mirror of
				https://github.com/YosysHQ/yosys
				synced 2025-10-31 03:32:29 +00:00 
			
		
		
		
	Merge remote-tracking branch 'origin/eddie/abc9_refactor' into eddie/abc9_required
This commit is contained in:
		
						commit
						f9aae90e7a
					
				
					 11 changed files with 198 additions and 156 deletions
				
			
		
							
								
								
									
										4
									
								
								Makefile
									
										
									
									
									
								
							
							
						
						
									
										4
									
								
								Makefile
									
										
									
									
									
								
							|  | @ -115,7 +115,7 @@ LDFLAGS += -rdynamic | |||
| LDLIBS += -lrt | ||||
| endif | ||||
| 
 | ||||
| YOSYS_VER := 0.9+932 | ||||
| YOSYS_VER := 0.9+1706 | ||||
| GIT_REV := $(shell cd $(YOSYS_SRC) && git rev-parse --short HEAD 2> /dev/null || echo UNKNOWN) | ||||
| OBJS = kernel/version_$(GIT_REV).o | ||||
| 
 | ||||
|  | @ -128,7 +128,7 @@ bumpversion: | |||
| # is just a symlink to your actual ABC working directory, as 'make mrproper'
 | ||||
| # will remove the 'abc' directory and you do not want to accidentally
 | ||||
| # delete your work on ABC..
 | ||||
| ABCREV = 144c5be | ||||
| ABCREV = 71f2b40 | ||||
| ABCPULL = 1 | ||||
| ABCURL ?= https://github.com/berkeley-abc/abc | ||||
| ABCMKARGS = CC="$(CXX)" CXX="$(CXX)" ABC_USE_LIBSTDCXX=1 | ||||
|  |  | |||
|  | @ -93,7 +93,6 @@ struct XAigerWriter | |||
| 	dict<SigBit, int> ordered_outputs; | ||||
| 
 | ||||
| 	vector<Cell*> box_list; | ||||
| 	dict<IdString, std::vector<IdString>> box_ports; | ||||
| 
 | ||||
| 	int mkgate(int a0, int a1) | ||||
| 	{ | ||||
|  | @ -296,6 +295,7 @@ struct XAigerWriter | |||
| 			//log_warning("Unsupported cell type: %s (%s)\n", log_id(cell->type), log_id(cell));
 | ||||
| 		} | ||||
| 
 | ||||
| 		dict<IdString, std::vector<IdString>> box_ports; | ||||
| 		for (auto cell : box_list) { | ||||
| 			log_assert(cell); | ||||
| 
 | ||||
|  | @ -405,7 +405,8 @@ struct XAigerWriter | |||
| 		if (holes_mode) { | ||||
| 			struct sort_by_port_id { | ||||
| 				bool operator()(const RTLIL::SigBit& a, const RTLIL::SigBit& b) const { | ||||
| 					return a.wire->port_id < b.wire->port_id; | ||||
| 					return a.wire->port_id < b.wire->port_id || | ||||
| 					    (a.wire->port_id == b.wire->port_id && a.offset < b.offset); | ||||
| 				} | ||||
| 			}; | ||||
| 			input_bits.sort(sort_by_port_id()); | ||||
|  | @ -545,7 +546,7 @@ struct XAigerWriter | |||
| 			RTLIL::Module *holes_module = module->design->module(stringf("%s$holes", module->name.c_str())); | ||||
| 			log_assert(holes_module); | ||||
| 
 | ||||
| 			dict<IdString, Cell*> cell_cache; | ||||
| 			dict<IdString, std::tuple<int,int,int>> cell_cache; | ||||
| 
 | ||||
| 			int box_count = 0; | ||||
| 			for (auto cell : box_list) { | ||||
|  | @ -554,24 +555,32 @@ struct XAigerWriter | |||
| 				RTLIL::Module* box_module = module->design->module(cell->type); | ||||
| 				log_assert(box_module); | ||||
| 
 | ||||
| 				int box_inputs = 0, box_outputs = 0; | ||||
| 				for (auto port_name : box_module->ports) { | ||||
| 					RTLIL::Wire *w = box_module->wire(port_name); | ||||
| 					log_assert(w); | ||||
| 					if (w->port_input) | ||||
| 						box_inputs += GetSize(w); | ||||
| 					if (w->port_output) | ||||
| 						box_outputs += GetSize(w); | ||||
| 				auto r = cell_cache.insert(cell->type); | ||||
| 				auto &v = r.first->second; | ||||
| 				if (r.second) { | ||||
| 					int box_inputs = 0, box_outputs = 0; | ||||
| 					for (auto port_name : box_module->ports) { | ||||
| 						RTLIL::Wire *w = box_module->wire(port_name); | ||||
| 						log_assert(w); | ||||
| 						if (w->port_input) | ||||
| 							box_inputs += GetSize(w); | ||||
| 						if (w->port_output) | ||||
| 							box_outputs += GetSize(w); | ||||
| 					} | ||||
| 
 | ||||
| 					// For flops only, create an extra 1-bit input that drives a new wire
 | ||||
| 					//   called "<cell>.abc9_ff.Q" that is used below
 | ||||
| 					if (box_module->get_bool_attribute("\\abc9_flop")) | ||||
| 					    box_inputs++; | ||||
| 
 | ||||
| 					std::get<0>(v) = box_inputs; | ||||
| 					std::get<1>(v) = box_outputs; | ||||
| 					std::get<2>(v) = box_module->attributes.at("\\abc9_box_id").as_int(); | ||||
| 				} | ||||
| 
 | ||||
| 				// For flops only, create an extra 1-bit input that drives a new wire
 | ||||
| 				//   called "<cell>.abc9_ff.Q" that is used below
 | ||||
| 				if (box_module->get_bool_attribute("\\abc9_flop")) | ||||
| 					box_inputs++; | ||||
| 
 | ||||
| 				write_h_buffer(box_inputs); | ||||
| 				write_h_buffer(box_outputs); | ||||
| 				write_h_buffer(box_module->attributes.at("\\abc9_box_id").as_int()); | ||||
| 				write_h_buffer(std::get<0>(v)); | ||||
| 				write_h_buffer(std::get<1>(v)); | ||||
| 				write_h_buffer(std::get<2>(v)); | ||||
| 				write_h_buffer(box_count++); | ||||
| 			} | ||||
| 
 | ||||
|  |  | |||
|  | @ -114,20 +114,35 @@ void Pass::run_register() | |||
| 
 | ||||
| void Pass::init_register() | ||||
| { | ||||
| 	vector<Pass*> added_passes; | ||||
| 	while (first_queued_pass) { | ||||
| 		added_passes.push_back(first_queued_pass); | ||||
| 		first_queued_pass->run_register(); | ||||
| 		first_queued_pass = first_queued_pass->next_queued_pass; | ||||
| 	} | ||||
| 	for (auto added_pass : added_passes) | ||||
| 		added_pass->on_register(); | ||||
| } | ||||
| 
 | ||||
| void Pass::done_register() | ||||
| { | ||||
| 	for (auto &it : pass_register) | ||||
| 		it.second->on_shutdown(); | ||||
| 
 | ||||
| 	frontend_register.clear(); | ||||
| 	pass_register.clear(); | ||||
| 	backend_register.clear(); | ||||
| 	log_assert(first_queued_pass == NULL); | ||||
| } | ||||
| 
 | ||||
| void Pass::on_register() | ||||
| { | ||||
| } | ||||
| 
 | ||||
| void Pass::on_shutdown() | ||||
| { | ||||
| } | ||||
| 
 | ||||
| Pass::~Pass() | ||||
| { | ||||
| } | ||||
|  |  | |||
|  | @ -62,6 +62,9 @@ struct Pass | |||
| 	virtual void run_register(); | ||||
| 	static void init_register(); | ||||
| 	static void done_register(); | ||||
| 
 | ||||
| 	virtual void on_register(); | ||||
| 	virtual void on_shutdown(); | ||||
| }; | ||||
| 
 | ||||
| struct ScriptPass : Pass | ||||
|  |  | |||
|  | @ -544,6 +544,8 @@ void yosys_shutdown() | |||
| 	already_shutdown = true; | ||||
| 	log_pop(); | ||||
| 
 | ||||
| 	Pass::done_register(); | ||||
| 
 | ||||
| 	delete yosys_design; | ||||
| 	yosys_design = NULL; | ||||
| 
 | ||||
|  | @ -553,7 +555,6 @@ void yosys_shutdown() | |||
| 	log_errfile = NULL; | ||||
| 	log_files.clear(); | ||||
| 
 | ||||
| 	Pass::done_register(); | ||||
| 	yosys_celltypes.clear(); | ||||
| 
 | ||||
| #ifdef YOSYS_ENABLE_TCL | ||||
|  |  | |||
|  | @ -26,9 +26,6 @@ | |||
| USING_YOSYS_NAMESPACE | ||||
| PRIVATE_NAMESPACE_BEGIN | ||||
| 
 | ||||
| #define XC7_WIRE_DELAY 300 // Number with which ABC will map a 6-input gate
 | ||||
|                            // to one LUT6 (instead of a LUT5 + LUT2)
 | ||||
| 
 | ||||
| struct Abc9Pass : public ScriptPass | ||||
| { | ||||
| 	Abc9Pass() : ScriptPass("abc9", "use ABC9 for technology mapping") { } | ||||
|  | @ -39,8 +36,9 @@ struct Abc9Pass : public ScriptPass | |||
| 		log("\n"); | ||||
| 		log("    abc9 [options] [selection]\n"); | ||||
| 		log("\n"); | ||||
| 		log("This pass uses the ABC tool [1] for technology mapping of yosys's internal gate\n"); | ||||
| 		log("library to a target architecture. Only fully-selected modules are supported.\n"); | ||||
| 		log("This script pass performs a sequence of commands to facilitate the use of the ABC\n"); | ||||
| 		log("tool [1] for technology mapping of the current design to a target FPGA\n"); | ||||
| 		log("architecture. Only fully-selected modules are supported.\n"); | ||||
| 		log("\n"); | ||||
| 		log("    -exe <command>\n"); | ||||
| #ifdef ABCEXTERNAL | ||||
|  | @ -59,21 +57,13 @@ struct Abc9Pass : public ScriptPass | |||
| 		log("        replaced with blanks before the string is passed to ABC.\n"); | ||||
| 		log("\n"); | ||||
| 		log("        if no -script parameter is given, the following scripts are used:\n"); | ||||
| 		log("\n"); | ||||
| 		log("        for -lut/-luts (only one LUT size):\n"); | ||||
| 		// FIXME
 | ||||
| 		//log("%s\n", fold_abc9_cmd(ABC_COMMAND_LUT /*"; lutpack {S}"*/).c_str());
 | ||||
| 		log("\n"); | ||||
| 		log("        for -lut/-luts (different LUT sizes):\n"); | ||||
| 		// FIXME
 | ||||
| 		//FIXME:
 | ||||
| 		//log("%s\n", fold_abc9_cmd(ABC_COMMAND_LUT).c_str());
 | ||||
| 		log("\n"); | ||||
| 		log("    -fast\n"); | ||||
| 		log("        use different default scripts that are slightly faster (at the cost\n"); | ||||
| 		log("        of output quality):\n"); | ||||
| 		log("\n"); | ||||
| 		log("        for -lut/-luts:\n"); | ||||
| 		// FIXME
 | ||||
| 		//FIXME:
 | ||||
| 		//log("%s\n", fold_abc9_cmd(ABC_FAST_COMMAND_LUT).c_str());
 | ||||
| 		log("\n"); | ||||
| 		log("    -D <picoseconds>\n"); | ||||
|  | @ -200,10 +190,10 @@ struct Abc9Pass : public ScriptPass | |||
| 			run("select -set abc9_holes A:abc9_holes"); | ||||
| 			run("flatten -wb @abc9_holes"); | ||||
| 			run("techmap @abc9_holes"); | ||||
| 			run("aigmap"); | ||||
| 			if (dff_mode || help_mode) | ||||
| 				run("abc9_ops -prep_dff", "(only if -dff)"); | ||||
| 			run("opt -purge @abc9_holes"); | ||||
| 			run("aigmap"); | ||||
| 			run("wbflip @abc9_holes"); | ||||
| 		} | ||||
| 
 | ||||
|  |  | |||
|  | @ -284,10 +284,12 @@ struct Abc9ExePass : public Pass { | |||
| 	{ | ||||
| 		//   |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
 | ||||
| 		log("\n"); | ||||
| 		log("    abc9_exe [options] [selection]\n"); | ||||
| 		log("    abc9_exe [options]\n"); | ||||
| 		log("\n"); | ||||
| 		log("This pass uses the ABC tool [1] for technology mapping of yosys's internal gate\n"); | ||||
| 		log("library to a target architecture.\n"); | ||||
| 		log(" \n"); | ||||
| 		log("This pass uses the ABC tool [1] for technology mapping of the top module\n"); | ||||
| 		log("(according to the (* top *) attribute or if only one module is currently selected)\n"); | ||||
| 		log("to a target FPGA architecture.\n"); | ||||
| 		log("\n"); | ||||
| 		log("    -exe <command>\n"); | ||||
| #ifdef ABCEXTERNAL | ||||
|  | @ -306,18 +308,11 @@ struct Abc9ExePass : public Pass { | |||
| 		log("        replaced with blanks before the string is passed to ABC.\n"); | ||||
| 		log("\n"); | ||||
| 		log("        if no -script parameter is given, the following scripts are used:\n"); | ||||
| 		log("\n"); | ||||
| 		log("        for -lut/-luts (only one LUT size):\n"); | ||||
| 		log("%s\n", fold_abc9_cmd(ABC_COMMAND_LUT /*"; lutpack {S}"*/).c_str()); | ||||
| 		log("\n"); | ||||
| 		log("        for -lut/-luts (different LUT sizes):\n"); | ||||
| 		log("%s\n", fold_abc9_cmd(ABC_COMMAND_LUT).c_str()); | ||||
| 		log("\n"); | ||||
| 		log("    -fast\n"); | ||||
| 		log("        use different default scripts that are slightly faster (at the cost\n"); | ||||
| 		log("        of output quality):\n"); | ||||
| 		log("\n"); | ||||
| 		log("        for -lut/-luts:\n"); | ||||
| 		log("%s\n", fold_abc9_cmd(ABC_FAST_COMMAND_LUT).c_str()); | ||||
| 		log("\n"); | ||||
| 		log("    -D <picoseconds>\n"); | ||||
|  |  | |||
|  | @ -98,7 +98,7 @@ void break_scc(RTLIL::Module *module) | |||
| 	//   its output ports into a new PO, and drive its previous
 | ||||
| 	//   sinks with a new PI
 | ||||
| 	pool<RTLIL::Const> ids_seen; | ||||
| 	for (auto cell : module->selected_cells()) { | ||||
| 	for (auto cell : module->cells()) { | ||||
| 		auto it = cell->attributes.find(ID(abc9_scc_id)); | ||||
| 		if (it == cell->attributes.end()) | ||||
| 			continue; | ||||
|  | @ -174,7 +174,7 @@ void prep_dff(RTLIL::Module *module) | |||
| 	typedef SigSpec clkdomain_t; | ||||
| 	dict<clkdomain_t, int> clk_to_mergeability; | ||||
| 
 | ||||
| 	for (auto cell : module->selected_cells()) { | ||||
| 	for (auto cell : module->cells()) { | ||||
| 		if (cell->type != "$__ABC9_FF_") | ||||
| 			continue; | ||||
| 
 | ||||
|  | @ -202,14 +202,16 @@ void prep_dff(RTLIL::Module *module) | |||
| 
 | ||||
| 	RTLIL::Module *holes_module = design->module(stringf("%s$holes", module->name.c_str())); | ||||
| 	if (holes_module) { | ||||
| 		dict<SigSig, SigSig> replace; | ||||
| 		SigMap sigmap(holes_module); | ||||
| 
 | ||||
| 		dict<SigSpec, SigSpec> replace; | ||||
| 		for (auto it = holes_module->cells_.begin(); it != holes_module->cells_.end(); ) { | ||||
| 			auto cell = it->second; | ||||
| 			if (cell->type.in("$_DFF_N_", "$_DFF_NN0_", "$_DFF_NN1_", "$_DFF_NP0_", "$_DFF_NP1_", | ||||
| 						"$_DFF_P_", "$_DFF_PN0_", "$_DFF_PN1", "$_DFF_PP0_", "$_DFF_PP1_")) { | ||||
| 				SigBit D = cell->getPort("\\D"); | ||||
| 				SigBit Q = cell->getPort("\\Q"); | ||||
| 				// Remove the DFF cell from what needs to be a combinatorial box
 | ||||
| 				// Remove the $_DFF_* cell from what needs to be a combinatorial box
 | ||||
| 				it = holes_module->cells_.erase(it); | ||||
| 				Wire *port; | ||||
| 				if (GetSize(Q.wire) == 1) | ||||
|  | @ -217,10 +219,10 @@ void prep_dff(RTLIL::Module *module) | |||
| 				else | ||||
| 					port = holes_module->wire(stringf("$abc%s[%d]", Q.wire->name.c_str(), Q.offset)); | ||||
| 				log_assert(port); | ||||
| 				// Prepare to replace "assign <port> = DFF.Q;" with "assign <port> = DFF.D;"
 | ||||
| 				//   in order to extract the combinatorial control logic that feeds the box
 | ||||
| 				// Prepare to replace "assign <port> = $_DFF_*.Q;" with "assign <port> = $_DFF_*.D;"
 | ||||
| 				//   in order to extract just the combinatorial control logic that feeds the box
 | ||||
| 				//   (i.e. clock enable, synchronous reset, etc.)
 | ||||
| 				replace.insert(std::make_pair(SigSig(port,Q), SigSig(port,D))); | ||||
| 				replace.insert(std::make_pair(Q,D)); | ||||
| 				// Since `flatten` above would have created wires named "<cell>.Q",
 | ||||
| 				//   extract the pre-techmap cell name
 | ||||
| 				auto pos = Q.wire->name.str().rfind("."); | ||||
|  | @ -228,7 +230,7 @@ void prep_dff(RTLIL::Module *module) | |||
| 				IdString driver = Q.wire->name.substr(0, pos); | ||||
| 				// And drive the signal that was previously driven by "DFF.Q" (typically
 | ||||
| 				//   used to implement clock-enable functionality) with the "<cell>.$abc9_currQ"
 | ||||
| 				//   wire (which itself is driven an input port) we inserted above
 | ||||
| 				//   wire (which itself is driven an by input port) we inserted above
 | ||||
| 				Wire *currQ = holes_module->wire(stringf("%s.abc9_ff.Q", driver.c_str())); | ||||
| 				log_assert(currQ); | ||||
| 				holes_module->connect(Q, currQ); | ||||
|  | @ -237,11 +239,8 @@ void prep_dff(RTLIL::Module *module) | |||
| 				++it; | ||||
| 		} | ||||
| 
 | ||||
| 		for (auto &conn : holes_module->connections_) { | ||||
| 			auto it = replace.find(conn); | ||||
| 			if (it != replace.end()) | ||||
| 				conn = it->second; | ||||
| 		} | ||||
| 		for (auto &conn : holes_module->connections_) | ||||
| 			conn.second = replace.at(sigmap(conn.second), conn.second); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
|  | @ -256,7 +255,7 @@ void prep_holes(RTLIL::Module *module, bool dff) | |||
| 	TopoSort<IdString, RTLIL::sort_by_id_str> toposort; | ||||
| 	bool abc9_box_seen = false; | ||||
| 
 | ||||
| 	for (auto cell : module->selected_cells()) { | ||||
| 	for (auto cell : module->cells()) { | ||||
| 		if (cell->type == "$__ABC9_FF_") | ||||
| 			continue; | ||||
| 
 | ||||
|  | @ -294,21 +293,23 @@ void prep_holes(RTLIL::Module *module, bool dff) | |||
| 			for (auto user_cell : it.second) | ||||
| 				toposort.edge(driver_cell, user_cell); | ||||
| 
 | ||||
| #if 0 | ||||
| 	toposort.analyze_loops = true; | ||||
| #endif | ||||
| 	if (ys_debug(1)) | ||||
| 		toposort.analyze_loops = true; | ||||
| 
 | ||||
| 	bool no_loops YS_ATTRIBUTE(unused) = toposort.sort(); | ||||
| #if 0 | ||||
| 	unsigned i = 0; | ||||
| 	for (auto &it : toposort.loops) { | ||||
| 		log("  loop %d\n", i++); | ||||
| 		for (auto cell_name : it) { | ||||
| 			auto cell = module->cell(cell_name); | ||||
| 			log_assert(cell); | ||||
| 			log("\t%s (%s @ %s)\n", log_id(cell), log_id(cell->type), cell->get_src_attribute().c_str()); | ||||
| 
 | ||||
| 	if (ys_debug(1)) { | ||||
| 		unsigned i = 0; | ||||
| 		for (auto &it : toposort.loops) { | ||||
| 			log("  loop %d\n", i++); | ||||
| 			for (auto cell_name : it) { | ||||
| 				auto cell = module->cell(cell_name); | ||||
| 				log_assert(cell); | ||||
| 				log("\t%s (%s @ %s)\n", log_id(cell), log_id(cell->type), cell->get_src_attribute().c_str()); | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| #endif | ||||
| 
 | ||||
| 	log_assert(no_loops); | ||||
| 
 | ||||
| 	vector<Cell*> box_list; | ||||
|  | @ -377,100 +378,97 @@ void prep_holes(RTLIL::Module *module, bool dff) | |||
| 		log_assert(orig_box_module); | ||||
| 		IdString derived_name = orig_box_module->derive(design, cell->parameters); | ||||
| 		RTLIL::Module* box_module = design->module(derived_name); | ||||
| 		cell->type = derived_name; | ||||
| 		cell->parameters.clear(); | ||||
| 		//cell->type = derived_name;
 | ||||
| 		//cell->parameters.clear();
 | ||||
| 
 | ||||
| 		int box_inputs = 0; | ||||
| 		auto r = cell_cache.insert(std::make_pair(derived_name, nullptr)); | ||||
| 		Cell *holes_cell = r.first->second; | ||||
| 		if (r.second && box_module->get_bool_attribute("\\whitebox")) { | ||||
| 			holes_cell = holes_module->addCell(cell->name, cell->type); | ||||
| 			holes_cell->parameters = cell->parameters; | ||||
| 			r.first->second = holes_cell; | ||||
| 
 | ||||
| 			if (box_module->has_processes()) | ||||
| 				Pass::call_on_module(design, box_module, "proc"); | ||||
| 		} | ||||
| 
 | ||||
| 		auto r2 = box_ports.insert(cell->type); | ||||
| 		if (r2.second) { | ||||
| 			// Make carry in the last PI, and carry out the last PO
 | ||||
| 			//   since ABC requires it this way
 | ||||
| 			IdString carry_in, carry_out; | ||||
| 			for (const auto &port_name : box_module->ports) { | ||||
| 				auto w = box_module->wire(port_name); | ||||
| 				log_assert(w); | ||||
| 				if (w->get_bool_attribute("\\abc9_carry")) { | ||||
| 					if (w->port_input) | ||||
| 						carry_in = port_name; | ||||
| 					if (w->port_output) | ||||
| 						carry_out = port_name; | ||||
| 		auto r = cell_cache.insert(derived_name); | ||||
| 		auto &holes_cell = r.first->second; | ||||
| 		if (r.second) { | ||||
| 			auto r2 = box_ports.insert(cell->type); | ||||
| 			if (r2.second) { | ||||
| 				// Make carry in the last PI, and carry out the last PO
 | ||||
| 				//   since ABC requires it this way
 | ||||
| 				IdString carry_in, carry_out; | ||||
| 				for (const auto &port_name : box_module->ports) { | ||||
| 					auto w = box_module->wire(port_name); | ||||
| 					log_assert(w); | ||||
| 					if (w->get_bool_attribute("\\abc9_carry")) { | ||||
| 						if (w->port_input) | ||||
| 							carry_in = port_name; | ||||
| 						if (w->port_output) | ||||
| 							carry_out = port_name; | ||||
| 					} | ||||
| 					else | ||||
| 						r2.first->second.push_back(port_name); | ||||
| 				} | ||||
| 
 | ||||
| 				if (carry_in != IdString()) { | ||||
| 					r2.first->second.push_back(carry_in); | ||||
| 					r2.first->second.push_back(carry_out); | ||||
| 				} | ||||
| 				else | ||||
| 					r2.first->second.push_back(port_name); | ||||
| 			} | ||||
| 
 | ||||
| 			if (carry_in != IdString()) { | ||||
| 				r2.first->second.push_back(carry_in); | ||||
| 				r2.first->second.push_back(carry_out); | ||||
| 			} | ||||
| 		} | ||||
| 			if (box_module->get_bool_attribute("\\whitebox")) { | ||||
| 				holes_cell = holes_module->addCell(cell->name, derived_name); | ||||
| 
 | ||||
| 		for (const auto &port_name : box_ports.at(cell->type)) { | ||||
| 			RTLIL::Wire *w = box_module->wire(port_name); | ||||
| 			log_assert(w); | ||||
| 			RTLIL::Wire *holes_wire; | ||||
| 			RTLIL::SigSpec port_sig; | ||||
| 			if (w->port_input) | ||||
| 				for (int i = 0; i < GetSize(w); i++) { | ||||
| 				if (box_module->has_processes()) | ||||
| 					Pass::call_on_module(design, box_module, "proc"); | ||||
| 
 | ||||
| 				int box_inputs = 0; | ||||
| 				for (auto port_name : box_ports.at(cell->type)) { | ||||
| 					RTLIL::Wire *w = box_module->wire(port_name); | ||||
| 					log_assert(w); | ||||
| 					log_assert(!w->port_input || !w->port_output); | ||||
| 					auto &conn = holes_cell->connections_[port_name]; | ||||
| 					if (w->port_input) { | ||||
| 						for (int i = 0; i < GetSize(w); i++) { | ||||
| 							box_inputs++; | ||||
| 							RTLIL::Wire *holes_wire = holes_module->wire(stringf("\\i%d", box_inputs)); | ||||
| 							if (!holes_wire) { | ||||
| 								holes_wire = holes_module->addWire(stringf("\\i%d", box_inputs)); | ||||
| 								holes_wire->port_input = true; | ||||
| 								holes_wire->port_id = port_id++; | ||||
| 								holes_module->ports.push_back(holes_wire->name); | ||||
| 							} | ||||
| 							conn.append(holes_wire); | ||||
| 						} | ||||
| 					} | ||||
| 					else if (w->port_output) | ||||
| 						conn = holes_module->addWire(stringf("%s.%s", derived_name.c_str(), log_id(port_name)), GetSize(w)); | ||||
| 				} | ||||
| 
 | ||||
| 				// For flops only, create an extra 1-bit input that drives a new wire
 | ||||
| 				//   called "<cell>.abc9_ff.Q" that is used below
 | ||||
| 				if (box_module->get_bool_attribute("\\abc9_flop")) { | ||||
| 					box_inputs++; | ||||
| 					holes_wire = holes_module->wire(stringf("\\i%d", box_inputs)); | ||||
| 					Wire *holes_wire = holes_module->wire(stringf("\\i%d", box_inputs)); | ||||
| 					if (!holes_wire) { | ||||
| 						holes_wire = holes_module->addWire(stringf("\\i%d", box_inputs)); | ||||
| 						holes_wire->port_input = true; | ||||
| 						holes_wire->port_id = port_id++; | ||||
| 						holes_module->ports.push_back(holes_wire->name); | ||||
| 					} | ||||
| 					if (holes_cell) | ||||
| 						port_sig.append(holes_wire); | ||||
| 					Wire *Q = holes_module->addWire(stringf("%s.abc9_ff.Q", cell->name.c_str())); | ||||
| 					holes_module->connect(Q, holes_wire); | ||||
| 				} | ||||
| 			if (w->port_output) | ||||
| 				for (int i = 0; i < GetSize(w); i++) { | ||||
| 					if (GetSize(w) == 1) | ||||
| 						holes_wire = holes_module->addWire(stringf("$abc%s.%s", cell->name.c_str(), log_id(w->name))); | ||||
| 					else | ||||
| 						holes_wire = holes_module->addWire(stringf("$abc%s.%s[%d]", cell->name.c_str(), log_id(w->name), i)); | ||||
| 					holes_wire->port_output = true; | ||||
| 					holes_wire->port_id = port_id++; | ||||
| 					holes_module->ports.push_back(holes_wire->name); | ||||
| 					if (holes_cell) | ||||
| 						port_sig.append(holes_wire); | ||||
| 					else | ||||
| 						holes_module->connect(holes_wire, State::S0); | ||||
| 				} | ||||
| 			if (!port_sig.empty()) { | ||||
| 				if (r.second) | ||||
| 					holes_cell->setPort(w->name, port_sig); | ||||
| 				else | ||||
| 					holes_module->connect(holes_cell->getPort(w->name), port_sig); | ||||
| 			} | ||||
| 			else // box_module is a blackbox
 | ||||
| 				log_assert(holes_cell == nullptr); | ||||
| 		} | ||||
| 
 | ||||
| 		// For flops only, create an extra 1-bit input that drives a new wire
 | ||||
| 		//   called "<cell>.$abc9_currQ" that is used below
 | ||||
| 		if (box_module->get_bool_attribute("\\abc9_flop")) { | ||||
| 			log_assert(holes_cell); | ||||
| 
 | ||||
| 			box_inputs++; | ||||
| 			Wire *holes_wire = holes_module->wire(stringf("\\i%d", box_inputs)); | ||||
| 			if (!holes_wire) { | ||||
| 				holes_wire = holes_module->addWire(stringf("\\i%d", box_inputs)); | ||||
| 				holes_wire->port_input = true; | ||||
| 				holes_wire->port_id = port_id++; | ||||
| 				holes_module->ports.push_back(holes_wire->name); | ||||
| 			} | ||||
| 			Wire *w = holes_module->addWire(stringf("%s.abc9_ff.Q", cell->name.c_str())); | ||||
| 			holes_module->connect(w, holes_wire); | ||||
| 		for (auto port_name : box_ports.at(cell->type)) { | ||||
| 			RTLIL::Wire *w = box_module->wire(port_name); | ||||
| 			log_assert(w); | ||||
| 			if (!w->port_output) | ||||
| 				continue; | ||||
| 			Wire *holes_wire = holes_module->addWire(stringf("$abc%s.%s", cell->name.c_str(), log_id(port_name)), GetSize(w)); | ||||
| 			holes_wire->port_output = true; | ||||
| 			holes_wire->port_id = port_id++; | ||||
| 			holes_module->ports.push_back(holes_wire->name); | ||||
| 			if (holes_cell) // whitebox
 | ||||
| 				holes_module->connect(holes_wire, holes_cell->getPort(port_name)); | ||||
| 			else // blackbox
 | ||||
| 				holes_module->connect(holes_wire, Const(State::S0, GetSize(w))); | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | @ -1059,7 +1057,11 @@ struct Abc9OpsPass : public Pass { | |||
| 		} | ||||
| 		extra_args(args, argidx, design); | ||||
| 
 | ||||
| 		// TODO: Check at least one mode given
 | ||||
| 		if (!(check_mode || break_scc_mode || unbreak_scc_mode || prep_times_mode || prep_holes_mode || prep_dff_mode || !write_box_src.empty() || reintegrate_mode)) | ||||
| 			log_cmd_error("At least one of -check, -{,un}break_scc, -prep_{times,holes,dff}, -write_box, -reintegrate must be specified.\n"); | ||||
| 
 | ||||
| 		if (dff_mode && !prep_holes_mode) | ||||
| 			log_cmd_error("'-dff' option is only relevant for -prep_holes.\n"); | ||||
| 
 | ||||
| 		if (check_mode) | ||||
| 			check(design); | ||||
|  | @ -1075,6 +1077,9 @@ struct Abc9OpsPass : public Pass { | |||
| 				continue; | ||||
| 			} | ||||
| 
 | ||||
| 			if (!design->selected_whole_module(mod)) | ||||
| 				log_error("Can't handle partially selected module %s!\n", log_id(mod)); | ||||
| 
 | ||||
| 			if (break_scc_mode) | ||||
| 				break_scc(mod); | ||||
| 			if (unbreak_scc_mode) | ||||
|  |  | |||
|  | @ -323,9 +323,9 @@ struct SynthEcp5Pass : public ScriptPass | |||
| 			if (abc9) { | ||||
| 				run("read_verilog -icells -lib +/ecp5/abc9_model.v"); | ||||
| 				if (nowidelut) | ||||
| 					run("abc9 -lut +/ecp5/abc9_5g_nowide.lut -box +/ecp5/abc9_5g.box -W 200 -nomfs"); | ||||
| 					run("abc9 -lut +/ecp5/abc9_5g_nowide.lut -box +/ecp5/abc9_5g.box -W 200"); | ||||
| 				else | ||||
| 					run("abc9 -lut +/ecp5/abc9_5g.lut -box +/ecp5/abc9_5g.box -W 200 -nomfs"); | ||||
| 					run("abc9 -lut +/ecp5/abc9_5g.lut -box +/ecp5/abc9_5g.box -W 200"); | ||||
| 				run("techmap -map +/ecp5/abc9_unmap.v"); | ||||
| 			} else { | ||||
| 				if (nowidelut) | ||||
|  |  | |||
|  | @ -556,7 +556,6 @@ struct SynthXilinxPass : public ScriptPass | |||
| 				run("read_verilog -icells -lib +/xilinx/abc9_model.v"); | ||||
| 				std::string abc9_opts = " -box +/xilinx/abc9_xc7.box"; | ||||
| 				abc9_opts += stringf(" -W %d", XC7_WIRE_DELAY); | ||||
| 				abc9_opts += " -nomfs"; | ||||
| 				if (nowidelut) | ||||
| 					abc9_opts += " -lut +/xilinx/abc9_xc7_nowide.lut"; | ||||
| 				else | ||||
|  |  | |||
							
								
								
									
										25
									
								
								tests/arch/ecp5/bug1459.ys
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								tests/arch/ecp5/bug1459.ys
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,25 @@ | |||
| read_verilog <<EOT | ||||
| module register_file( | ||||
|     input wire clk, | ||||
|     input wire write_enable, | ||||
|     input wire [63:0] write_data, | ||||
|     input wire [4:0] write_reg, | ||||
|     input wire [4:0] read1_reg, | ||||
|     output reg [63:0] read1_data, | ||||
|     ); | ||||
| 
 | ||||
|     reg [63:0] registers[0:31]; | ||||
| 
 | ||||
|     always @(posedge clk) begin | ||||
|       if (write_enable == 1'b1) begin | ||||
|         registers[write_reg] <= write_data; | ||||
|       end | ||||
|     end | ||||
| 
 | ||||
|     always @(all) begin | ||||
|       read1_data <= registers[read1_reg]; | ||||
|     end | ||||
| endmodule | ||||
| EOT | ||||
| 
 | ||||
| synth_ecp5 -abc9 | ||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue