diff options
Diffstat (limited to 'passes')
| -rw-r--r-- | passes/opt/opt_lut.cc | 6 | ||||
| -rw-r--r-- | passes/pmgen/Makefile.inc | 10 | ||||
| -rw-r--r-- | passes/pmgen/ice40_wrapcarry.cc | 90 | ||||
| -rw-r--r-- | passes/pmgen/ice40_wrapcarry.pmg | 11 | ||||
| -rw-r--r-- | passes/proc/proc_prune.cc | 16 | ||||
| -rw-r--r-- | passes/techmap/abc.cc | 69 | ||||
| -rw-r--r-- | passes/techmap/abc9.cc | 37 | 
7 files changed, 205 insertions, 34 deletions
| diff --git a/passes/opt/opt_lut.cc b/passes/opt/opt_lut.cc index 587ef878a..4c199ba72 100644 --- a/passes/opt/opt_lut.cc +++ b/passes/opt/opt_lut.cc @@ -101,6 +101,12 @@ struct OptLutWorker  		{  			if (cell->type == "$lut")  			{ +				if (cell->has_keep_attr()) +					continue; +				SigBit lut_output = cell->getPort("\\Y"); +				if (lut_output.wire->get_bool_attribute("\\keep")) +					continue; +  				int lut_width = cell->getParam("\\WIDTH").as_int();  				SigSpec lut_input = cell->getPort("\\A");  				int lut_arity = 0; diff --git a/passes/pmgen/Makefile.inc b/passes/pmgen/Makefile.inc index 7911132db..c03606152 100644 --- a/passes/pmgen/Makefile.inc +++ b/passes/pmgen/Makefile.inc @@ -1,4 +1,5 @@  OBJS += passes/pmgen/ice40_dsp.o +OBJS += passes/pmgen/ice40_wrapcarry.o  OBJS += passes/pmgen/peepopt.o  # -------------------------------------- @@ -12,6 +13,15 @@ passes/pmgen/ice40_dsp_pm.h: passes/pmgen/pmgen.py passes/pmgen/ice40_dsp.pmg  # -------------------------------------- +passes/pmgen/ice40_wrapcarry.o: passes/pmgen/ice40_wrapcarry_pm.h +EXTRA_OBJS += passes/pmgen/ice40_wrapcarry_pm.h +.SECONDARY: passes/pmgen/ice40_wrapcarry_pm.h + +passes/pmgen/ice40_wrapcarry_pm.h: passes/pmgen/pmgen.py passes/pmgen/ice40_wrapcarry.pmg +	$(P) mkdir -p passes/pmgen && python3 $< -o $@ -p ice40_wrapcarry $(filter-out $<,$^) + +# -------------------------------------- +  passes/pmgen/peepopt.o: passes/pmgen/peepopt_pm.h  EXTRA_OBJS += passes/pmgen/peepopt_pm.h  .SECONDARY: passes/pmgen/peepopt_pm.h diff --git a/passes/pmgen/ice40_wrapcarry.cc b/passes/pmgen/ice40_wrapcarry.cc new file mode 100644 index 000000000..69ef3cd82 --- /dev/null +++ b/passes/pmgen/ice40_wrapcarry.cc @@ -0,0 +1,90 @@ +/* + *  yosys -- Yosys Open SYnthesis Suite + * + *  Copyright (C) 2012  Clifford Wolf <clifford@clifford.at> + * + *  Permission to use, copy, modify, and/or distribute this software for any + *  purpose with or without fee is hereby granted, provided that the above + *  copyright notice and this permission notice appear in all copies. + * + *  THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + *  WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + *  MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + *  ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + *  WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + *  ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + *  OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ + +#include "kernel/yosys.h" +#include "kernel/sigtools.h" + +USING_YOSYS_NAMESPACE +PRIVATE_NAMESPACE_BEGIN + +#include "passes/pmgen/ice40_wrapcarry_pm.h" + +void create_ice40_wrapcarry(ice40_wrapcarry_pm &pm) +{ +	auto &st = pm.st_ice40_wrapcarry; + +#if 0 +	log("\n"); +	log("carry: %s\n", log_id(st.carry, "--")); +	log("lut:   %s\n", log_id(st.lut, "--")); +#endif + +	log("  replacing SB_LUT + SB_CARRY with $__ICE40_CARRY_WRAPPER cell.\n"); + +	Cell *cell = pm.module->addCell(NEW_ID, "$__ICE40_CARRY_WRAPPER"); +	pm.module->swap_names(cell, st.carry); + +	cell->setPort("\\A", st.carry->getPort("\\I0")); +	cell->setPort("\\B", st.carry->getPort("\\I1")); +	cell->setPort("\\CI", st.carry->getPort("\\CI")); +	cell->setPort("\\CO", st.carry->getPort("\\CO")); + +	cell->setPort("\\I0", st.lut->getPort("\\I0")); +	cell->setPort("\\I3", st.lut->getPort("\\I3")); +	cell->setPort("\\O", st.lut->getPort("\\O")); +	cell->setParam("\\LUT", st.lut->getParam("\\LUT_INIT")); + +	pm.autoremove(st.carry); +	pm.autoremove(st.lut); +} + +struct Ice40WrapCarryPass : public Pass { +	Ice40WrapCarryPass() : Pass("ice40_wrapcarry", "iCE40: wrap carries") { } +	void help() YS_OVERRIDE +	{ +		//   |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| +		log("\n"); +		log("    ice40_wrapcarry [selection]\n"); +		log("\n"); +		log("Wrap manually instantiated SB_CARRY cells, along with their associated SB_LUTs,\n"); +		log("into an internal $__ICE40_CARRY_WRAPPER cell for preservation across technology\n"); +		log("mapping."); +		log("\n"); +	} +	void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE +	{ +		log_header(design, "Executing ICE40_WRAPCARRY pass (wrap carries).\n"); + +		size_t argidx; +		for (argidx = 1; argidx < args.size(); argidx++) +		{ +			// if (args[argidx] == "-singleton") { +			// 	singleton_mode = true; +			// 	continue; +			// } +			break; +		} +		extra_args(args, argidx, design); + +		for (auto module : design->selected_modules()) +			ice40_wrapcarry_pm(module, module->selected_cells()).run_ice40_wrapcarry(create_ice40_wrapcarry); +	} +} Ice40WrapCarryPass; + +PRIVATE_NAMESPACE_END diff --git a/passes/pmgen/ice40_wrapcarry.pmg b/passes/pmgen/ice40_wrapcarry.pmg new file mode 100644 index 000000000..9e64c7467 --- /dev/null +++ b/passes/pmgen/ice40_wrapcarry.pmg @@ -0,0 +1,11 @@ +pattern ice40_wrapcarry + +match carry +	select carry->type.in(\SB_CARRY) +endmatch + +match lut +	select lut->type.in(\SB_LUT4) +	index <SigSpec> port(lut, \I1) === port(carry, \I0) +	index <SigSpec> port(lut, \I2) === port(carry, \I1) +endmatch diff --git a/passes/proc/proc_prune.cc b/passes/proc/proc_prune.cc index b47ee79c2..d4aee9df0 100644 --- a/passes/proc/proc_prune.cc +++ b/passes/proc/proc_prune.cc @@ -65,8 +65,7 @@ struct PruneWorker  			pool<RTLIL::SigBit> sw_assigned = do_switch((*it), assigned, affected);  			assigned.insert(sw_assigned.begin(), sw_assigned.end());  		} -		pool<RTLIL::SigSig> remove; -		for (auto it = cs->actions.rbegin(); it != cs->actions.rend(); ++it) { +		for (auto it = cs->actions.rbegin(); it != cs->actions.rend(); ) {  			RTLIL::SigSpec lhs = sigmap(it->first);  			bool redundant = true;  			for (auto &bit : lhs) { @@ -75,9 +74,10 @@ struct PruneWorker  					break;  				}  			} +			bool remove = false;  			if (redundant) {  				removed_count++; -				remove.insert(*it); +				remove = true;  			} else {  				if (root) {  					bool promotable = true; @@ -99,7 +99,7 @@ struct PruneWorker  						}  						promoted_count++;  						module->connect(conn); -						remove.insert(*it); +						remove = true;  					}  				}  				for (auto &bit : lhs) @@ -109,11 +109,9 @@ struct PruneWorker  					if (bit.wire)  						affected.insert(bit);  			} -		} -		for (auto it = cs->actions.begin(); it != cs->actions.end(); ) { -			if (remove[*it]) { -				it = cs->actions.erase(it); -			} else it++; +			if (remove) +				cs->actions.erase((it++).base() - 1); +			else it++;  		}  		return assigned;  	} diff --git a/passes/techmap/abc.cc b/passes/techmap/abc.cc index 9db8aafa7..9f963a8bf 100644 --- a/passes/techmap/abc.cc +++ b/passes/techmap/abc.cc @@ -941,33 +941,33 @@ void abc_module(RTLIL::Design *design, RTLIL::Module *current_module, std::strin  		fprintf(f, "GATE ONE     1 Y=CONST1;\n");  		fprintf(f, "GATE BUF    %d Y=A;                  PIN * NONINV  1 999 1 0 1 0\n", cell_cost.at("$_BUF_"));  		fprintf(f, "GATE NOT    %d Y=!A;                 PIN * INV     1 999 1 0 1 0\n", cell_cost.at("$_NOT_")); -		if (enabled_gates.empty() || enabled_gates.count("AND")) +		if (enabled_gates.count("AND"))  			fprintf(f, "GATE AND    %d Y=A*B;                PIN * NONINV  1 999 1 0 1 0\n", cell_cost.at("$_AND_")); -		if (enabled_gates.empty() || enabled_gates.count("NAND")) +		if (enabled_gates.count("NAND"))  			fprintf(f, "GATE NAND   %d Y=!(A*B);             PIN * INV     1 999 1 0 1 0\n", cell_cost.at("$_NAND_")); -		if (enabled_gates.empty() || enabled_gates.count("OR")) +		if (enabled_gates.count("OR"))  			fprintf(f, "GATE OR     %d Y=A+B;                PIN * NONINV  1 999 1 0 1 0\n", cell_cost.at("$_OR_")); -		if (enabled_gates.empty() || enabled_gates.count("NOR")) +		if (enabled_gates.count("NOR"))  			fprintf(f, "GATE NOR    %d Y=!(A+B);             PIN * INV     1 999 1 0 1 0\n", cell_cost.at("$_NOR_")); -		if (enabled_gates.empty() || enabled_gates.count("XOR")) +		if (enabled_gates.count("XOR"))  			fprintf(f, "GATE XOR    %d Y=(A*!B)+(!A*B);      PIN * UNKNOWN 1 999 1 0 1 0\n", cell_cost.at("$_XOR_")); -		if (enabled_gates.empty() || enabled_gates.count("XNOR")) +		if (enabled_gates.count("XNOR"))  			fprintf(f, "GATE XNOR   %d Y=(A*B)+(!A*!B);      PIN * UNKNOWN 1 999 1 0 1 0\n", cell_cost.at("$_XNOR_")); -		if (enabled_gates.empty() || enabled_gates.count("ANDNOT")) +		if (enabled_gates.count("ANDNOT"))  			fprintf(f, "GATE ANDNOT %d Y=A*!B;               PIN * UNKNOWN 1 999 1 0 1 0\n", cell_cost.at("$_ANDNOT_")); -		if (enabled_gates.empty() || enabled_gates.count("ORNOT")) +		if (enabled_gates.count("ORNOT"))  			fprintf(f, "GATE ORNOT  %d Y=A+!B;               PIN * UNKNOWN 1 999 1 0 1 0\n", cell_cost.at("$_ORNOT_")); -		if (enabled_gates.empty() || enabled_gates.count("AOI3")) +		if (enabled_gates.count("AOI3"))  			fprintf(f, "GATE AOI3   %d Y=!((A*B)+C);         PIN * INV     1 999 1 0 1 0\n", cell_cost.at("$_AOI3_")); -		if (enabled_gates.empty() || enabled_gates.count("OAI3")) +		if (enabled_gates.count("OAI3"))  			fprintf(f, "GATE OAI3   %d Y=!((A+B)*C);         PIN * INV     1 999 1 0 1 0\n", cell_cost.at("$_OAI3_")); -		if (enabled_gates.empty() || enabled_gates.count("AOI4")) +		if (enabled_gates.count("AOI4"))  			fprintf(f, "GATE AOI4   %d Y=!((A*B)+(C*D));     PIN * INV     1 999 1 0 1 0\n", cell_cost.at("$_AOI4_")); -		if (enabled_gates.empty() || enabled_gates.count("OAI4")) +		if (enabled_gates.count("OAI4"))  			fprintf(f, "GATE OAI4   %d Y=!((A+B)*(C+D));     PIN * INV     1 999 1 0 1 0\n", cell_cost.at("$_OAI4_")); -		if (enabled_gates.empty() || enabled_gates.count("MUX")) +		if (enabled_gates.count("MUX"))  			fprintf(f, "GATE MUX    %d Y=(A*B)+(S*B)+(!S*A); PIN * UNKNOWN 1 999 1 0 1 0\n", cell_cost.at("$_MUX_")); -		if (enabled_gates.empty() || enabled_gates.count("NMUX")) +		if (enabled_gates.count("NMUX"))  			fprintf(f, "GATE NMUX   %d Y=!((A*B)+(S*B)+(!S*A)); PIN * UNKNOWN 1 999 1 0 1 0\n", cell_cost.at("$_NMUX_"));  		if (map_mux4)  			fprintf(f, "GATE MUX4   %d Y=(!S*!T*A)+(S*!T*B)+(!S*T*C)+(S*T*D); PIN * UNKNOWN 1 999 1 0 1 0\n", 2*cell_cost.at("$_MUX_")); @@ -1411,7 +1411,9 @@ struct AbcPass : public Pass {  		// log("\n");  		log("    -g type1,type2,...\n");  		log("        Map to the specified list of gate types. Supported gates types are:\n"); -		log("        AND, NAND, OR, NOR, XOR, XNOR, ANDNOT, ORNOT, MUX, AOI3, OAI3, AOI4, OAI4.\n"); +		//   |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| +		log("           AND, NAND, OR, NOR, XOR, XNOR, ANDNOT, ORNOT, MUX,\n"); +		log("           NMUX, AOI3, OAI3, AOI4, OAI4.\n");  		log("        (The NOT gate is always added to this list automatically.)\n");  		log("\n");  		log("        The following aliases can be used to reference common sets of gate types:\n"); @@ -1423,9 +1425,13 @@ struct AbcPass : public Pass {  		log("          gates:  AND NAND OR NOR XOR XNOR ANDNOT ORNOT\n");  		log("          aig:    AND NAND OR NOR ANDNOT ORNOT\n");  		log("\n"); +		log("        The alias 'all' represent the full set of all gate types.\n"); +		log("\n");  		log("        Prefix a gate type with a '-' to remove it from the list. For example\n");  		log("        the arguments 'AND,OR,XOR' and 'simple,-MUX' are equivalent.\n");  		log("\n"); +		log("        The default is 'all,-NMUX,-AOI3,-OAI3,-AOI4,-OAI4'.\n"); +		log("\n");  		log("    -dff\n");  		log("        also pass $_DFF_?_ and $_DFFE_??_ cells through ABC. modules with many\n");  		log("        clock domains are automatically partitioned in clock domains and each\n"); @@ -1701,6 +1707,22 @@ struct AbcPass : public Pass {  						gate_list.push_back("ORNOT");  						goto ok_alias;  					} +					if (g == "all") { +						gate_list.push_back("AND"); +						gate_list.push_back("NAND"); +						gate_list.push_back("OR"); +						gate_list.push_back("NOR"); +						gate_list.push_back("XOR"); +						gate_list.push_back("XNOR"); +						gate_list.push_back("ANDNOT"); +						gate_list.push_back("ORNOT"); +						gate_list.push_back("AOI3"); +						gate_list.push_back("OAI3"); +						gate_list.push_back("AOI4"); +						gate_list.push_back("OAI4"); +						gate_list.push_back("MUX"); +						gate_list.push_back("NMUX"); +					}  					cmd_error(args, argidx, stringf("Unsupported gate type: %s", g.c_str()));  				ok_gate:  					gate_list.push_back(g); @@ -1752,6 +1774,23 @@ struct AbcPass : public Pass {  		if (!constr_file.empty() && liberty_file.empty())  			log_cmd_error("Got -constr but no -liberty!\n"); +		if (enabled_gates.empty()) { +			enabled_gates.insert("AND"); +			enabled_gates.insert("NAND"); +			enabled_gates.insert("OR"); +			enabled_gates.insert("NOR"); +			enabled_gates.insert("XOR"); +			enabled_gates.insert("XNOR"); +			enabled_gates.insert("ANDNOT"); +			enabled_gates.insert("ORNOT"); +			// enabled_gates.insert("AOI3"); +			// enabled_gates.insert("OAI3"); +			// enabled_gates.insert("AOI4"); +			// enabled_gates.insert("OAI4"); +			enabled_gates.insert("MUX"); +			// enabled_gates.insert("NMUX"); +		} +  		for (auto mod : design->selected_modules())  		{  			if (mod->processes.size() > 0) { diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc index 31c1d6f80..7418ed4a3 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -82,7 +82,7 @@ void handle_loops(RTLIL::Design *design)  {  	Pass::call(design, "scc -set_attr abc_scc_id {}"); -        dict<IdString, vector<IdString>> abc_scc_break; +	dict<IdString, vector<IdString>> abc_scc_break;  	// For every unique SCC found, (arbitrarily) find the first  	// cell in the component, and select (and mark) all its output @@ -290,7 +290,7 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri  		bool cleanup, vector<int> lut_costs, bool dff_mode, std::string clk_str,  		bool /*keepff*/, std::string delay_target, std::string /*lutin_shared*/, bool fast_mode,  		bool show_tempdir, std::string box_file, std::string lut_file, -		std::string wire_delay) +		std::string wire_delay, const dict<int,IdString> &box_lookup)  {  	module = current_module;  	map_autoidx = autoidx++; @@ -429,10 +429,10 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri  		RTLIL::Selection& sel = design->selection_stack.back();  		sel.select(module); -		Pass::call(design, "aigmap"); -  		handle_loops(design); +		Pass::call(design, "aigmap"); +  		//log("Extracted %d gates and %d wires to a netlist network with %d inputs and %d outputs.\n",  		//		count_gates, GetSize(signal_list), count_input, count_output); @@ -476,7 +476,6 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri  		}  		module->fixup_ports(); -  		log_header(design, "Executing ABC9.\n");  		if (!lut_costs.empty()) { @@ -520,8 +519,9 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri  		buffer = stringf("%s/%s", tempdir_name.c_str(), "input.sym");  		log_assert(!design->module("$__abc9__")); +  		AigerReader reader(design, ifs, "$__abc9__", "" /* clk_name */, buffer.c_str() /* map_filename */, true /* wideports */); -		reader.parse_xaiger(); +		reader.parse_xaiger(box_lookup);  		ifs.close();  #if 0 @@ -646,6 +646,7 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri  			}  			else {  				existing_cell = module->cell(c->name); +				log_assert(existing_cell);  				cell = module->addCell(remap_name(c->name), c->type);  				module->swap_names(cell, existing_cell);  			} @@ -1081,6 +1082,21 @@ struct Abc9Pass : public Pass {  		}  		extra_args(args, argidx, design); +		dict<int,IdString> box_lookup; +		for (auto m : design->modules()) { +			auto it = m->attributes.find("\\abc_box_id"); +			if (it == m->attributes.end()) +				continue; +			if (m->name.begins_with("$paramod")) +				continue; +			auto id = it->second.as_int(); +			auto r = box_lookup.insert(std::make_pair(id, m->name)); +			if (!r.second) +				log_error("Module '%s' has the same abc_box_id = %d value as '%s'.\n", +						log_id(m), id, log_id(r.first->second)); +			log_assert(r.second); +		} +  		for (auto mod : design->selected_modules())  		{  			if (mod->attributes.count("\\abc_box_id")) @@ -1096,7 +1112,7 @@ struct Abc9Pass : public Pass {  			if (!dff_mode || !clk_str.empty()) {  				abc9_module(design, mod, script_file, exe_file, cleanup, lut_costs, dff_mode, clk_str, keepff,  						delay_target, lutin_shared, fast_mode, show_tempdir, -						box_file, lut_file, wire_delay); +						box_file, lut_file, wire_delay, box_lookup);  				continue;  			} @@ -1242,15 +1258,16 @@ struct Abc9Pass : public Pass {  				en_sig = assign_map(std::get<3>(it.first));  				abc9_module(design, mod, script_file, exe_file, cleanup, lut_costs, !clk_sig.empty(), "$",  						keepff, delay_target, lutin_shared, fast_mode, show_tempdir, -						box_file, lut_file, wire_delay); +						box_file, lut_file, wire_delay, box_lookup);  				assign_map.set(mod);  			}  		} -		Pass::call(design, "clean"); -  		assign_map.clear(); +		// The "clean" pass also contains a design->check() call +		Pass::call(design, "clean"); +  		log_pop();  	}  } Abc9Pass; | 
