mirror of
				https://github.com/YosysHQ/yosys
				synced 2025-10-31 03:32:29 +00:00 
			
		
		
		
	abc9: fix SCC issues (#2694)
* xilinx: add SCC test for DSP48E1 * xilinx: Gate DSP48E1 being a whitebox behind ALLOW_WHITEBOX_DSP48E1 Have a test that checks it works through ABC9 when enabled * abc9 to break SCCs using $__ABC9_SCC_BREAKER module * Add test * abc9_ops: remove refs to (* abc9_keep *) on wires * abc9_ops: do not bypass cells in an SCC * Add myself to CODEOWNERS for abc9* * Fix compile * abc9_ops: run -prep_hier before scc * Fix tests * Remove bug reference pending fix * abc9: fix for -prep_hier -dff * xaiger: restore PI handling * abc9_ops: -prep_xaiger sigmap * abc9_ops: -mark_scc -> -break_scc * abc9: eliminate hard-coded abc9.box from tests Also tidy up * Address review
This commit is contained in:
		
							parent
							
								
									687f381b69
								
							
						
					
					
						commit
						55dc5a4e4f
					
				
					 9 changed files with 94 additions and 45 deletions
				
			
		|  | @ -544,18 +544,31 @@ void prep_dff_unmap(RTLIL::Design *design) | |||
| 	} | ||||
| } | ||||
| 
 | ||||
| void mark_scc(RTLIL::Module *module) | ||||
| void break_scc(RTLIL::Module *module) | ||||
| { | ||||
| 	// For every unique SCC found, (arbitrarily) find the first
 | ||||
| 	//   cell in the component, and replace its output connections
 | ||||
| 	//   with a new wire driven by the old connection but with a
 | ||||
| 	//   special (* abc9_keep *) attribute set (which is used by
 | ||||
| 	//   write_xaiger to break this wire into PI and POs)
 | ||||
| 	//   cell in the component, and interrupt all its output connections
 | ||||
| 	//   with the $__ABC9_SCC_BREAKER cell
 | ||||
| 
 | ||||
| 	// Do not break SCCs which have a cell instantiating an abc9_bypass-able
 | ||||
| 	// module (but which wouldn't have been bypassed)
 | ||||
| 	auto design = module->design; | ||||
| 	pool<RTLIL::Cell*> scc_cells; | ||||
| 	pool<RTLIL::Const> ids_seen; | ||||
| 	for (auto cell : module->cells()) { | ||||
| 		auto it = cell->attributes.find(ID::abc9_scc_id); | ||||
| 		if (it == cell->attributes.end()) | ||||
| 			continue; | ||||
| 		scc_cells.insert(cell); | ||||
| 		auto inst_module = design->module(cell->type); | ||||
| 		if (inst_module && inst_module->has_attribute(ID::abc9_bypass)) | ||||
| 			ids_seen.insert(it->second); | ||||
| 	} | ||||
| 
 | ||||
| 	SigSpec I, O; | ||||
| 	for (auto cell : scc_cells) { | ||||
| 		auto it = cell->attributes.find(ID::abc9_scc_id); | ||||
| 		log_assert(it != cell->attributes.end()); | ||||
| 		auto id = it->second; | ||||
| 		auto r = ids_seen.insert(id); | ||||
| 		cell->attributes.erase(it); | ||||
|  | @ -565,12 +578,21 @@ void mark_scc(RTLIL::Module *module) | |||
| 			if (c.second.is_fully_const()) continue; | ||||
| 			if (cell->output(c.first)) { | ||||
| 				Wire *w = module->addWire(NEW_ID, GetSize(c.second)); | ||||
| 				w->set_bool_attribute(ID::abc9_keep); | ||||
| 				module->connect(w, c.second); | ||||
| 				I.append(w); | ||||
| 				O.append(c.second); | ||||
| 				c.second = w; | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	if (!I.empty()) | ||||
| 	{ | ||||
| 		auto cell = module->addCell(NEW_ID, ID($__ABC9_SCC_BREAKER)); | ||||
| 		log_assert(GetSize(I) == GetSize(O)); | ||||
| 		cell->setParam(ID::WIDTH, GetSize(I)); | ||||
| 		cell->setPort(ID::I, std::move(I)); | ||||
| 		cell->setPort(ID::O, std::move(O)); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| void prep_delays(RTLIL::Design *design, bool dff_mode) | ||||
|  | @ -721,10 +743,8 @@ void prep_xaiger(RTLIL::Module *module, bool dff) | |||
| 					bit_users[bit].insert(cell->name); | ||||
| 
 | ||||
| 			if (cell->output(conn.first) && !abc9_flop) | ||||
| 				for (const auto &chunk : conn.second.chunks()) | ||||
| 				    if (!chunk.wire->get_bool_attribute(ID::abc9_keep)) | ||||
| 					    for (auto b : sigmap(SigSpec(chunk))) | ||||
| 						    bit_drivers[b].insert(cell->name); | ||||
| 				for (auto bit : sigmap(conn.second)) | ||||
| 					bit_drivers[bit].insert(cell->name); | ||||
| 		} | ||||
| 		toposort.node(cell->name); | ||||
| 	} | ||||
|  | @ -1424,7 +1444,6 @@ void reintegrate(RTLIL::Module *module, bool dff_mode) | |||
| 		RTLIL::Wire *mapped_wire = mapped_mod->wire(port); | ||||
| 		RTLIL::Wire *wire = module->wire(port); | ||||
| 		log_assert(wire); | ||||
| 		wire->attributes.erase(ID::abc9_keep); | ||||
| 
 | ||||
| 		RTLIL::Wire *remap_wire = module->wire(remap_name(port)); | ||||
| 		RTLIL::SigSpec signal(wire, remap_wire->start_offset-wire->start_offset, GetSize(remap_wire)); | ||||
|  | @ -1587,11 +1606,11 @@ struct Abc9OpsPass : public Pass { | |||
| 		log("        insert `$__ABC9_DELAY' blackbox cells into the design to account for\n"); | ||||
| 		log("        certain required times.\n"); | ||||
| 		log("\n"); | ||||
| 		log("    -mark_scc\n"); | ||||
| 		log("    -break_scc\n"); | ||||
| 		log("        for an arbitrarily chosen cell in each unique SCC of each selected module\n"); | ||||
| 		log("        (tagged with an (* abc9_scc_id = <int> *) attribute), temporarily mark all\n"); | ||||
| 		log("        wires driven by this cell's outputs with a (* keep *) attribute in order\n"); | ||||
| 		log("        to break the SCC. this temporary attribute will be removed on -reintegrate.\n"); | ||||
| 		log("        (tagged with an (* abc9_scc_id = <int> *) attribute) interrupt all wires\n"); | ||||
| 		log("        driven by this cell's outputs with a temporary $__ABC9_SCC_BREAKER cell\n"); | ||||
| 		log("        to break the SCC.\n"); | ||||
| 		log("\n"); | ||||
| 		log("    -prep_xaiger\n"); | ||||
| 		log("        prepare the design for XAIGER output. this includes computing the\n"); | ||||
|  | @ -1628,7 +1647,7 @@ struct Abc9OpsPass : public Pass { | |||
| 
 | ||||
| 		bool check_mode = false; | ||||
| 		bool prep_delays_mode = false; | ||||
| 		bool mark_scc_mode = false; | ||||
| 		bool break_scc_mode = false; | ||||
| 		bool prep_hier_mode = false; | ||||
| 		bool prep_bypass_mode = false; | ||||
| 		bool prep_dff_mode = false, prep_dff_submod_mode = false, prep_dff_unmap_mode = false; | ||||
|  | @ -1650,8 +1669,8 @@ struct Abc9OpsPass : public Pass { | |||
| 				valid = true; | ||||
| 				continue; | ||||
| 			} | ||||
| 			if (arg == "-mark_scc") { | ||||
| 				mark_scc_mode = true; | ||||
| 			if (arg == "-break_scc") { | ||||
| 				break_scc_mode = true; | ||||
| 				valid = true; | ||||
| 				continue; | ||||
| 			} | ||||
|  | @ -1727,7 +1746,7 @@ struct Abc9OpsPass : public Pass { | |||
| 		extra_args(args, argidx, design); | ||||
| 
 | ||||
| 		if (!valid) | ||||
| 			log_cmd_error("At least one of -check, -mark_scc, -prep_{delays,xaiger,dff[123],lut,box}, -write_{lut,box}, -reintegrate must be specified.\n"); | ||||
| 			log_cmd_error("At least one of -check, -break_scc, -prep_{delays,xaiger,dff[123],lut,box}, -write_{lut,box}, -reintegrate must be specified.\n"); | ||||
| 
 | ||||
| 		if (dff_mode && !check_mode && !prep_hier_mode && !prep_delays_mode && !prep_xaiger_mode && !reintegrate_mode) | ||||
| 			log_cmd_error("'-dff' option is only relevant for -prep_{hier,delay,xaiger} or -reintegrate.\n"); | ||||
|  | @ -1764,8 +1783,8 @@ struct Abc9OpsPass : public Pass { | |||
| 				write_lut(mod, write_lut_dst); | ||||
| 			if (!write_box_dst.empty()) | ||||
| 				write_box(mod, write_box_dst); | ||||
| 			if (mark_scc_mode) | ||||
| 				mark_scc(mod); | ||||
| 			if (break_scc_mode) | ||||
| 				break_scc(mod); | ||||
| 			if (prep_xaiger_mode) | ||||
| 				prep_xaiger(mod, dff_mode); | ||||
| 			if (reintegrate_mode) | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue