mirror of
				https://github.com/YosysHQ/yosys
				synced 2025-10-31 19:52:31 +00:00 
			
		
		
		
	Merge pull request #1251 from YosysHQ/clifford/nmux
Add $_NMUX_, add "abc -g cmos", add proper cmos cell costs
This commit is contained in:
		
						commit
						a4b59de5d4
					
				
					 19 changed files with 174 additions and 42 deletions
				
			
		|  | @ -15,6 +15,7 @@ Yosys 0.9 .. Yosys 0.9-dev | |||
|     - Added "script -scriptwire | ||||
|     - "synth_xilinx" to now infer wide multiplexers (-widemux <min> to enable) | ||||
|     - Added automatic gzip decompression for frontends | ||||
|     - Added $_NMUX_ cell type | ||||
| 
 | ||||
| Yosys 0.8 .. Yosys 0.8-dev | ||||
| -------------------------- | ||||
|  |  | |||
|  | @ -327,6 +327,13 @@ struct BlifDumper | |||
| 				goto internal_cell; | ||||
| 			} | ||||
| 
 | ||||
| 			if (!config->icells_mode && cell->type == "$_NMUX_") { | ||||
| 				f << stringf(".names %s %s %s %s\n0-0 1\n-01 1\n", | ||||
| 						cstr(cell->getPort("\\A")), cstr(cell->getPort("\\B")), | ||||
| 						cstr(cell->getPort("\\S")), cstr(cell->getPort("\\Y"))); | ||||
| 				goto internal_cell; | ||||
| 			} | ||||
| 
 | ||||
| 			if (!config->icells_mode && cell->type == "$_FF_") { | ||||
| 				f << stringf(".latch %s %s%s\n", cstr(cell->getPort("\\D")), cstr(cell->getPort("\\Q")), | ||||
| 						cstr_init(cell->getPort("\\Q"))); | ||||
|  |  | |||
|  | @ -496,7 +496,7 @@ struct BtorWorker | |||
| 			goto okay; | ||||
| 		} | ||||
| 
 | ||||
| 		if (cell->type.in("$mux", "$_MUX_")) | ||||
| 		if (cell->type.in("$mux", "$_MUX_", "$_NMUX_")) | ||||
| 		{ | ||||
| 			SigSpec sig_a = sigmap(cell->getPort("\\A")); | ||||
| 			SigSpec sig_b = sigmap(cell->getPort("\\B")); | ||||
|  | @ -511,6 +511,12 @@ struct BtorWorker | |||
| 			int nid = next_nid++; | ||||
| 			btorf("%d ite %d %d %d %d\n", nid, sid, nid_s, nid_b, nid_a); | ||||
| 
 | ||||
| 			if (cell->type == "$_NMUX_") { | ||||
| 				int tmp = nid; | ||||
| 				nid = next_nid++; | ||||
| 				btorf("%d not %d %d\n", nid, sid, tmp); | ||||
| 			} | ||||
| 
 | ||||
| 			add_nid_sig(nid, sig_y); | ||||
| 			goto okay; | ||||
| 		} | ||||
|  |  | |||
|  | @ -472,7 +472,7 @@ struct SimplecWorker | |||
| 			return; | ||||
| 		} | ||||
| 
 | ||||
| 		if (cell->type == "$_MUX_") | ||||
| 		if (cell->type.in("$_MUX_", "$_NMUX_")) | ||||
| 		{ | ||||
| 			SigBit a = sigmaps.at(work->module)(cell->getPort("\\A")); | ||||
| 			SigBit b = sigmaps.at(work->module)(cell->getPort("\\B")); | ||||
|  | @ -484,7 +484,9 @@ struct SimplecWorker | |||
| 			string s_expr = s.wire ? util_get_bit(work->prefix + cid(s.wire->name), s.wire->width, s.offset) : s.data ? "1" : "0"; | ||||
| 
 | ||||
| 			// casts to bool are a workaround for CBMC bug (https://github.com/diffblue/cbmc/issues/933)
 | ||||
| 			string expr = stringf("%s ? (bool)%s : (bool)%s", s_expr.c_str(), b_expr.c_str(), a_expr.c_str()); | ||||
| 			string expr = stringf("%s ? %s(bool)%s : %s(bool)%s", s_expr.c_str(), | ||||
| 					cell->type == "$_NMUX_" ? "!" : "", b_expr.c_str(), | ||||
| 					cell->type == "$_NMUX_" ? "!" : "", a_expr.c_str()); | ||||
| 
 | ||||
| 			log_assert(y.wire); | ||||
| 			funct_declarations.push_back(util_set_bit(work->prefix + cid(y.wire->name), y.wire->width, y.offset, expr) + | ||||
|  |  | |||
|  | @ -510,6 +510,7 @@ struct Smt2Worker | |||
| 		if (cell->type == "$_ANDNOT_") return export_gate(cell, "(and A (not B))"); | ||||
| 		if (cell->type == "$_ORNOT_") return export_gate(cell, "(or A (not B))"); | ||||
| 		if (cell->type == "$_MUX_") return export_gate(cell, "(ite S B A)"); | ||||
| 		if (cell->type == "$_NMUX_") return export_gate(cell, "(not (ite S B A))"); | ||||
| 		if (cell->type == "$_AOI3_") return export_gate(cell, "(not (or (and A B) C))"); | ||||
| 		if (cell->type == "$_OAI3_") return export_gate(cell, "(not (and (or A B) C))"); | ||||
| 		if (cell->type == "$_AOI4_") return export_gate(cell, "(not (or (and A B) (and C D)))"); | ||||
|  |  | |||
|  | @ -537,6 +537,13 @@ struct SmvWorker | |||
| 				continue; | ||||
| 			} | ||||
| 
 | ||||
| 			if (cell->type == "$_NMUX_") | ||||
| 			{ | ||||
| 				definitions.push_back(stringf("%s := !(bool(%s) ? %s : %s);", lvalue(cell->getPort("\\Y")), | ||||
| 						rvalue(cell->getPort("\\S")), rvalue(cell->getPort("\\B")), rvalue(cell->getPort("\\A")))); | ||||
| 				continue; | ||||
| 			} | ||||
| 
 | ||||
| 			if (cell->type == "$_AOI3_") | ||||
| 			{ | ||||
| 				definitions.push_back(stringf("%s := !((%s & %s) | %s);", lvalue(cell->getPort("\\Y")), | ||||
|  |  | |||
|  | @ -558,6 +558,20 @@ bool dump_cell_expr(std::ostream &f, std::string indent, RTLIL::Cell *cell) | |||
| 		return true; | ||||
| 	} | ||||
| 
 | ||||
| 	if (cell->type == "$_NMUX_") { | ||||
| 		f << stringf("%s" "assign ", indent.c_str()); | ||||
| 		dump_sigspec(f, cell->getPort("\\Y")); | ||||
| 		f << stringf(" = !("); | ||||
| 		dump_cell_expr_port(f, cell, "S", false); | ||||
| 		f << stringf(" ? "); | ||||
| 		dump_attributes(f, "", cell->attributes, ' '); | ||||
| 		dump_cell_expr_port(f, cell, "B", false); | ||||
| 		f << stringf(" : "); | ||||
| 		dump_cell_expr_port(f, cell, "A", false); | ||||
| 		f << stringf(");\n"); | ||||
| 		return true; | ||||
| 	} | ||||
| 
 | ||||
| 	if (cell->type.in("$_AOI3_", "$_OAI3_")) { | ||||
| 		f << stringf("%s" "assign ", indent.c_str()); | ||||
| 		dump_sigspec(f, cell->getPort("\\Y")); | ||||
|  |  | |||
|  | @ -325,6 +325,8 @@ Aig::Aig(Cell *cell) | |||
| 			int A = mk.inport("\\A", i); | ||||
| 			int B = mk.inport("\\B", i); | ||||
| 			int Y = mk.mux_gate(A, B, S); | ||||
| 			if (cell->type == "$_NMUX_") | ||||
| 				Y = mk.not_gate(Y); | ||||
| 			mk.outport(Y, "\\Y", i); | ||||
| 		} | ||||
| 		goto optimize; | ||||
|  |  | |||
|  | @ -193,6 +193,7 @@ struct CellTypes | |||
| 		setup_type("$_ANDNOT_", {A, B}, {Y}, true); | ||||
| 		setup_type("$_ORNOT_", {A, B}, {Y}, true); | ||||
| 		setup_type("$_MUX_", {A, B, S}, {Y}, true); | ||||
| 		setup_type("$_NMUX_", {A, B, S}, {Y}, true); | ||||
| 		setup_type("$_MUX4_", {A, B, C, D, S, T}, {Y}, true); | ||||
| 		setup_type("$_MUX8_", {A, B, C, D, E, F, G, H, S, T, U}, {Y}, true); | ||||
| 		setup_type("$_MUX16_", {A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, S, T, U, V}, {Y}, true); | ||||
|  |  | |||
|  | @ -145,7 +145,7 @@ struct ConstEval | |||
| 		if (cell->hasPort("\\B")) | ||||
| 			sig_b = cell->getPort("\\B"); | ||||
| 
 | ||||
| 		if (cell->type == "$mux" || cell->type == "$pmux" || cell->type == "$_MUX_") | ||||
| 		if (cell->type.in("$mux", "$pmux", "$_MUX_", "$_NMUX_")) | ||||
| 		{ | ||||
| 			std::vector<RTLIL::SigSpec> y_candidates; | ||||
| 			int count_maybe_set_s_bits = 0; | ||||
|  | @ -175,7 +175,10 @@ struct ConstEval | |||
| 			for (auto &yc : y_candidates) { | ||||
| 				if (!eval(yc, undef, cell)) | ||||
| 					return false; | ||||
| 				y_values.push_back(yc.as_const()); | ||||
| 				if (cell->type == "$_NMUX_") | ||||
| 					y_values.push_back(RTLIL::const_not(yc.as_const(), Const(), false, false, GetSize(yc))); | ||||
| 				else | ||||
| 					y_values.push_back(yc.as_const()); | ||||
| 			} | ||||
| 
 | ||||
| 			if (y_values.size() > 1) | ||||
|  |  | |||
|  | @ -24,10 +24,10 @@ | |||
| 
 | ||||
| YOSYS_NAMESPACE_BEGIN | ||||
| 
 | ||||
| int get_cell_cost(RTLIL::Cell *cell, dict<RTLIL::IdString, int> *mod_cost_cache = nullptr); | ||||
| int get_cell_cost(RTLIL::Cell *cell, dict<RTLIL::IdString, int> *mod_cost_cache = nullptr, bool cmos_cost = false); | ||||
| 
 | ||||
| inline int get_cell_cost(RTLIL::IdString type, const dict<RTLIL::IdString, RTLIL::Const> ¶meters = dict<RTLIL::IdString, RTLIL::Const>(), | ||||
| 		RTLIL::Design *design = nullptr, dict<RTLIL::IdString, int> *mod_cost_cache = nullptr) | ||||
| 		RTLIL::Design *design = nullptr, dict<RTLIL::IdString, int> *mod_cost_cache = nullptr, bool cmos_cost = false) | ||||
| { | ||||
| 	static dict<RTLIL::IdString, int> gate_cost = { | ||||
| 		{ "$_BUF_",    1 }, | ||||
|  | @ -44,9 +44,33 @@ inline int get_cell_cost(RTLIL::IdString type, const dict<RTLIL::IdString, RTLIL | |||
| 		{ "$_OAI3_",   6 }, | ||||
| 		{ "$_AOI4_",   8 }, | ||||
| 		{ "$_OAI4_",   8 }, | ||||
| 		{ "$_MUX_",    4 } | ||||
| 		{ "$_MUX_",    4 }, | ||||
| 		{ "$_NMUX_",   4 } | ||||
| 	}; | ||||
| 
 | ||||
| 	// match costs in "stat -tech cmos"
 | ||||
| 	static dict<RTLIL::IdString, int> cmos_gate_cost = { | ||||
| 		{ "$_BUF_",     1 }, | ||||
| 		{ "$_NOT_",     2 }, | ||||
| 		{ "$_AND_",     6 }, | ||||
| 		{ "$_NAND_",    4 }, | ||||
| 		{ "$_OR_",      6 }, | ||||
| 		{ "$_NOR_",     4 }, | ||||
| 		{ "$_ANDNOT_",  6 }, | ||||
| 		{ "$_ORNOT_",   6 }, | ||||
| 		{ "$_XOR_",    12 }, | ||||
| 		{ "$_XNOR_",   12 }, | ||||
| 		{ "$_AOI3_",    6 }, | ||||
| 		{ "$_OAI3_",    6 }, | ||||
| 		{ "$_AOI4_",    8 }, | ||||
| 		{ "$_OAI4_",    8 }, | ||||
| 		{ "$_MUX_",    12 }, | ||||
| 		{ "$_NMUX_",   10 } | ||||
| 	}; | ||||
| 
 | ||||
| 	if (cmos_cost && cmos_gate_cost.count(type)) | ||||
| 		return cmos_gate_cost.at(type); | ||||
| 
 | ||||
| 	if (gate_cost.count(type)) | ||||
| 		return gate_cost.at(type); | ||||
| 
 | ||||
|  | @ -76,9 +100,9 @@ inline int get_cell_cost(RTLIL::IdString type, const dict<RTLIL::IdString, RTLIL | |||
| 	return 1; | ||||
| } | ||||
| 
 | ||||
| inline int get_cell_cost(RTLIL::Cell *cell, dict<RTLIL::IdString, int> *mod_cost_cache) | ||||
| inline int get_cell_cost(RTLIL::Cell *cell, dict<RTLIL::IdString, int> *mod_cost_cache, bool cmos_cost) | ||||
| { | ||||
| 	return get_cell_cost(cell->type, cell->parameters, cell->module->design, mod_cost_cache); | ||||
| 	return get_cell_cost(cell->type, cell->parameters, cell->module->design, mod_cost_cache, cmos_cost); | ||||
| } | ||||
| 
 | ||||
| YOSYS_NAMESPACE_END | ||||
|  |  | |||
|  | @ -1249,6 +1249,7 @@ namespace { | |||
| 			if (cell->type == "$_ANDNOT_") { check_gate("ABY"); return; } | ||||
| 			if (cell->type == "$_ORNOT_")  { check_gate("ABY"); return; } | ||||
| 			if (cell->type == "$_MUX_")    { check_gate("ABSY"); return; } | ||||
| 			if (cell->type == "$_NMUX_")   { check_gate("ABSY"); return; } | ||||
| 			if (cell->type == "$_AOI3_")   { check_gate("ABCY"); return; } | ||||
| 			if (cell->type == "$_OAI3_")   { check_gate("ABCY"); return; } | ||||
| 			if (cell->type == "$_AOI4_")   { check_gate("ABCDY"); return; } | ||||
|  | @ -1976,6 +1977,7 @@ DEF_METHOD_3(XnorGate,   "$_XNOR_",   A, B, Y) | |||
| DEF_METHOD_3(AndnotGate, "$_ANDNOT_", A, B, Y) | ||||
| DEF_METHOD_3(OrnotGate,  "$_ORNOT_",  A, B, Y) | ||||
| DEF_METHOD_4(MuxGate,    "$_MUX_",    A, B, S, Y) | ||||
| DEF_METHOD_4(NmuxGate,   "$_NMUX_",   A, B, S, Y) | ||||
| DEF_METHOD_4(Aoi3Gate,   "$_AOI3_",   A, B, C, Y) | ||||
| DEF_METHOD_4(Oai3Gate,   "$_OAI3_",   A, B, C, Y) | ||||
| DEF_METHOD_5(Aoi4Gate,   "$_AOI4_",   A, B, C, D, Y) | ||||
|  |  | |||
|  | @ -1154,6 +1154,7 @@ public: | |||
| 	RTLIL::Cell* addAndnotGate (RTLIL::IdString name, RTLIL::SigBit sig_a, RTLIL::SigBit sig_b, RTLIL::SigBit sig_y, const std::string &src = ""); | ||||
| 	RTLIL::Cell* addOrnotGate  (RTLIL::IdString name, RTLIL::SigBit sig_a, RTLIL::SigBit sig_b, RTLIL::SigBit sig_y, const std::string &src = ""); | ||||
| 	RTLIL::Cell* addMuxGate    (RTLIL::IdString name, RTLIL::SigBit sig_a, RTLIL::SigBit sig_b, RTLIL::SigBit sig_s, RTLIL::SigBit sig_y, const std::string &src = ""); | ||||
| 	RTLIL::Cell* addNmuxGate   (RTLIL::IdString name, RTLIL::SigBit sig_a, RTLIL::SigBit sig_b, RTLIL::SigBit sig_s, RTLIL::SigBit sig_y, const std::string &src = ""); | ||||
| 	RTLIL::Cell* addAoi3Gate   (RTLIL::IdString name, RTLIL::SigBit sig_a, RTLIL::SigBit sig_b, RTLIL::SigBit sig_c, RTLIL::SigBit sig_y, const std::string &src = ""); | ||||
| 	RTLIL::Cell* addOai3Gate   (RTLIL::IdString name, RTLIL::SigBit sig_a, RTLIL::SigBit sig_b, RTLIL::SigBit sig_c, RTLIL::SigBit sig_y, const std::string &src = ""); | ||||
| 	RTLIL::Cell* addAoi4Gate   (RTLIL::IdString name, RTLIL::SigBit sig_a, RTLIL::SigBit sig_b, RTLIL::SigBit sig_c, RTLIL::SigBit sig_d, RTLIL::SigBit sig_y, const std::string &src = ""); | ||||
|  | @ -1229,6 +1230,7 @@ public: | |||
| 	RTLIL::SigBit AndnotGate (RTLIL::IdString name, RTLIL::SigBit sig_a, RTLIL::SigBit sig_b, const std::string &src = ""); | ||||
| 	RTLIL::SigBit OrnotGate  (RTLIL::IdString name, RTLIL::SigBit sig_a, RTLIL::SigBit sig_b, const std::string &src = ""); | ||||
| 	RTLIL::SigBit MuxGate    (RTLIL::IdString name, RTLIL::SigBit sig_a, RTLIL::SigBit sig_b, RTLIL::SigBit sig_s, const std::string &src = ""); | ||||
| 	RTLIL::SigBit NmuxGate   (RTLIL::IdString name, RTLIL::SigBit sig_a, RTLIL::SigBit sig_b, RTLIL::SigBit sig_s, const std::string &src = ""); | ||||
| 	RTLIL::SigBit Aoi3Gate   (RTLIL::IdString name, RTLIL::SigBit sig_a, RTLIL::SigBit sig_b, RTLIL::SigBit sig_c, const std::string &src = ""); | ||||
| 	RTLIL::SigBit Oai3Gate   (RTLIL::IdString name, RTLIL::SigBit sig_a, RTLIL::SigBit sig_b, RTLIL::SigBit sig_c, const std::string &src = ""); | ||||
| 	RTLIL::SigBit Aoi4Gate   (RTLIL::IdString name, RTLIL::SigBit sig_a, RTLIL::SigBit sig_b, RTLIL::SigBit sig_c, RTLIL::SigBit sig_d, const std::string &src = ""); | ||||
|  |  | |||
|  | @ -475,7 +475,7 @@ struct SatGen | |||
| 			return true; | ||||
| 		} | ||||
| 
 | ||||
| 		if (cell->type == "$_MUX_" || cell->type == "$mux") | ||||
| 		if (cell->type == "$_MUX_" || cell->type == "$mux" || cell->type == "$_NMUX_") | ||||
| 		{ | ||||
| 			std::vector<int> a = importDefSigSpec(cell->getPort("\\A"), timestep); | ||||
| 			std::vector<int> b = importDefSigSpec(cell->getPort("\\B"), timestep); | ||||
|  | @ -483,7 +483,10 @@ struct SatGen | |||
| 			std::vector<int> y = importDefSigSpec(cell->getPort("\\Y"), timestep); | ||||
| 
 | ||||
| 			std::vector<int> yy = model_undef ? ez->vec_var(y.size()) : y; | ||||
| 			ez->assume(ez->vec_eq(ez->vec_ite(s.at(0), b, a), yy)); | ||||
| 			if (cell->type == "$_NMUX_") | ||||
| 				ez->assume(ez->vec_eq(ez->vec_not(ez->vec_ite(s.at(0), b, a)), yy)); | ||||
| 			else | ||||
| 				ez->assume(ez->vec_eq(ez->vec_ite(s.at(0), b, a), yy)); | ||||
| 
 | ||||
| 			if (model_undef) | ||||
| 			{ | ||||
|  |  | |||
|  | @ -494,6 +494,6 @@ Add information about {\tt \$\_DFFE\_??\_}, {\tt \$\_DFFSR\_???\_}, {\tt \$\_DLA | |||
| \end{fixme} | ||||
| 
 | ||||
| \begin{fixme} | ||||
| Add information about {\tt \$\_AOI3\_}, {\tt \$\_OAI3\_}, {\tt \$\_AOI4\_}, and {\tt \$\_OAI4\_} cells. | ||||
| Add information about {\tt \$\_AOI3\_}, {\tt \$\_OAI3\_}, {\tt \$\_AOI4\_}, {\tt \$\_OAI4\_}, and {\tt \$\_NMUX\_} cells. | ||||
| \end{fixme} | ||||
| 
 | ||||
|  |  | |||
|  | @ -241,6 +241,10 @@ struct statdata_t | |||
| 					tran_cnt += 6*cnum; | ||||
| 				else if (ctype.in("$_AOI4_", "$_OAI4_")) | ||||
| 					tran_cnt += 8*cnum; | ||||
| 				else if (ctype.in("$_NMUX_")) | ||||
| 					tran_cnt += 10*cnum; | ||||
| 				else if (ctype.in("$_MUX_", "$_XOR_", "$_XNOR_")) | ||||
| 					tran_cnt += 12*cnum; | ||||
| 				else if (ctype.in("$_DFF_P_", "$_DFF_N_")) | ||||
| 					tran_cnt += 16*cnum; | ||||
| 				else | ||||
|  |  | |||
|  | @ -82,6 +82,7 @@ enum class gate_type_t { | |||
| 	G_ANDNOT, | ||||
| 	G_ORNOT, | ||||
| 	G_MUX, | ||||
| 	G_NMUX, | ||||
| 	G_AOI3, | ||||
| 	G_OAI3, | ||||
| 	G_AOI4, | ||||
|  | @ -112,7 +113,7 @@ std::vector<gate_t> signal_list; | |||
| std::map<RTLIL::SigBit, int> signal_map; | ||||
| std::map<RTLIL::SigBit, RTLIL::State> signal_init; | ||||
| pool<std::string> enabled_gates; | ||||
| bool recover_init; | ||||
| bool recover_init, cmos_cost; | ||||
| 
 | ||||
| bool clk_polarity, en_polarity; | ||||
| RTLIL::SigSpec clk_sig, en_sig; | ||||
|  | @ -258,7 +259,7 @@ void extract_cell(RTLIL::Cell *cell, bool keepff) | |||
| 		return; | ||||
| 	} | ||||
| 
 | ||||
| 	if (cell->type == "$_MUX_") | ||||
| 	if (cell->type.in("$_MUX_", "$_NMUX_")) | ||||
| 	{ | ||||
| 		RTLIL::SigSpec sig_a = cell->getPort("\\A"); | ||||
| 		RTLIL::SigSpec sig_b = cell->getPort("\\B"); | ||||
|  | @ -274,7 +275,7 @@ void extract_cell(RTLIL::Cell *cell, bool keepff) | |||
| 		int mapped_b = map_signal(sig_b); | ||||
| 		int mapped_s = map_signal(sig_s); | ||||
| 
 | ||||
| 		map_signal(sig_y, G(MUX), mapped_a, mapped_b, mapped_s); | ||||
| 		map_signal(sig_y, cell->type == "$_MUX_" ? G(MUX) : G(NMUX), mapped_a, mapped_b, mapped_s); | ||||
| 
 | ||||
| 		module->remove(cell); | ||||
| 		return; | ||||
|  | @ -886,6 +887,10 @@ void abc_module(RTLIL::Design *design, RTLIL::Module *current_module, std::strin | |||
| 			fprintf(f, ".names ys__n%d ys__n%d ys__n%d ys__n%d\n", si.in1, si.in2, si.in3, si.id); | ||||
| 			fprintf(f, "1-0 1\n"); | ||||
| 			fprintf(f, "-11 1\n"); | ||||
| 		} else if (si.type == G(NMUX)) { | ||||
| 			fprintf(f, ".names ys__n%d ys__n%d ys__n%d ys__n%d\n", si.in1, si.in2, si.in3, si.id); | ||||
| 			fprintf(f, "0-0 1\n"); | ||||
| 			fprintf(f, "-01 1\n"); | ||||
| 		} else if (si.type == G(AOI3)) { | ||||
| 			fprintf(f, ".names ys__n%d ys__n%d ys__n%d ys__n%d\n", si.in1, si.in2, si.in3, si.id); | ||||
| 			fprintf(f, "-00 1\n"); | ||||
|  | @ -926,46 +931,52 @@ void abc_module(RTLIL::Design *design, RTLIL::Module *current_module, std::strin | |||
| 	{ | ||||
| 		log_header(design, "Executing ABC.\n"); | ||||
| 
 | ||||
| 		auto cell_cost = [](IdString cell_type) { | ||||
| 			return get_cell_cost(cell_type, dict<RTLIL::IdString, RTLIL::Const>(), nullptr, nullptr, cmos_cost); | ||||
| 		}; | ||||
| 
 | ||||
| 		buffer = stringf("%s/stdcells.genlib", tempdir_name.c_str()); | ||||
| 		f = fopen(buffer.c_str(), "wt"); | ||||
| 		if (f == NULL) | ||||
| 			log_error("Opening %s for writing failed: %s\n", buffer.c_str(), strerror(errno)); | ||||
| 		fprintf(f, "GATE ZERO    1 Y=CONST0;\n"); | ||||
| 		fprintf(f, "GATE ONE     1 Y=CONST1;\n"); | ||||
| 		fprintf(f, "GATE BUF    %d Y=A;                  PIN * NONINV  1 999 1 0 1 0\n", get_cell_cost("$_BUF_")); | ||||
| 		fprintf(f, "GATE NOT    %d Y=!A;                 PIN * INV     1 999 1 0 1 0\n", get_cell_cost("$_NOT_")); | ||||
| 		fprintf(f, "GATE BUF    %d Y=A;                  PIN * NONINV  1 999 1 0 1 0\n", cell_cost("$_BUF_")); | ||||
| 		fprintf(f, "GATE NOT    %d Y=!A;                 PIN * INV     1 999 1 0 1 0\n", cell_cost("$_NOT_")); | ||||
| 		if (enabled_gates.empty() || enabled_gates.count("AND")) | ||||
| 			fprintf(f, "GATE AND    %d Y=A*B;                PIN * NONINV  1 999 1 0 1 0\n", get_cell_cost("$_AND_")); | ||||
| 			fprintf(f, "GATE AND    %d Y=A*B;                PIN * NONINV  1 999 1 0 1 0\n", cell_cost("$_AND_")); | ||||
| 		if (enabled_gates.empty() || enabled_gates.count("NAND")) | ||||
| 			fprintf(f, "GATE NAND   %d Y=!(A*B);             PIN * INV     1 999 1 0 1 0\n", get_cell_cost("$_NAND_")); | ||||
| 			fprintf(f, "GATE NAND   %d Y=!(A*B);             PIN * INV     1 999 1 0 1 0\n", cell_cost("$_NAND_")); | ||||
| 		if (enabled_gates.empty() || enabled_gates.count("OR")) | ||||
| 			fprintf(f, "GATE OR     %d Y=A+B;                PIN * NONINV  1 999 1 0 1 0\n", get_cell_cost("$_OR_")); | ||||
| 			fprintf(f, "GATE OR     %d Y=A+B;                PIN * NONINV  1 999 1 0 1 0\n", cell_cost("$_OR_")); | ||||
| 		if (enabled_gates.empty() || enabled_gates.count("NOR")) | ||||
| 			fprintf(f, "GATE NOR    %d Y=!(A+B);             PIN * INV     1 999 1 0 1 0\n", get_cell_cost("$_NOR_")); | ||||
| 			fprintf(f, "GATE NOR    %d Y=!(A+B);             PIN * INV     1 999 1 0 1 0\n", cell_cost("$_NOR_")); | ||||
| 		if (enabled_gates.empty() || enabled_gates.count("XOR")) | ||||
| 			fprintf(f, "GATE XOR    %d Y=(A*!B)+(!A*B);      PIN * UNKNOWN 1 999 1 0 1 0\n", get_cell_cost("$_XOR_")); | ||||
| 			fprintf(f, "GATE XOR    %d Y=(A*!B)+(!A*B);      PIN * UNKNOWN 1 999 1 0 1 0\n", cell_cost("$_XOR_")); | ||||
| 		if (enabled_gates.empty() || enabled_gates.count("XNOR")) | ||||
| 			fprintf(f, "GATE XNOR   %d Y=(A*B)+(!A*!B);      PIN * UNKNOWN 1 999 1 0 1 0\n", get_cell_cost("$_XNOR_")); | ||||
| 			fprintf(f, "GATE XNOR   %d Y=(A*B)+(!A*!B);      PIN * UNKNOWN 1 999 1 0 1 0\n", cell_cost("$_XNOR_")); | ||||
| 		if (enabled_gates.empty() || enabled_gates.count("ANDNOT")) | ||||
| 			fprintf(f, "GATE ANDNOT %d Y=A*!B;               PIN * UNKNOWN 1 999 1 0 1 0\n", get_cell_cost("$_ANDNOT_")); | ||||
| 			fprintf(f, "GATE ANDNOT %d Y=A*!B;               PIN * UNKNOWN 1 999 1 0 1 0\n", cell_cost("$_ANDNOT_")); | ||||
| 		if (enabled_gates.empty() || enabled_gates.count("ORNOT")) | ||||
| 			fprintf(f, "GATE ORNOT  %d Y=A+!B;               PIN * UNKNOWN 1 999 1 0 1 0\n", get_cell_cost("$_ORNOT_")); | ||||
| 			fprintf(f, "GATE ORNOT  %d Y=A+!B;               PIN * UNKNOWN 1 999 1 0 1 0\n", cell_cost("$_ORNOT_")); | ||||
| 		if (enabled_gates.empty() || enabled_gates.count("AOI3")) | ||||
| 			fprintf(f, "GATE AOI3   %d Y=!((A*B)+C);         PIN * INV     1 999 1 0 1 0\n", get_cell_cost("$_AOI3_")); | ||||
| 			fprintf(f, "GATE AOI3   %d Y=!((A*B)+C);         PIN * INV     1 999 1 0 1 0\n", cell_cost("$_AOI3_")); | ||||
| 		if (enabled_gates.empty() || enabled_gates.count("OAI3")) | ||||
| 			fprintf(f, "GATE OAI3   %d Y=!((A+B)*C);         PIN * INV     1 999 1 0 1 0\n", get_cell_cost("$_OAI3_")); | ||||
| 			fprintf(f, "GATE OAI3   %d Y=!((A+B)*C);         PIN * INV     1 999 1 0 1 0\n", cell_cost("$_OAI3_")); | ||||
| 		if (enabled_gates.empty() || enabled_gates.count("AOI4")) | ||||
| 			fprintf(f, "GATE AOI4   %d Y=!((A*B)+(C*D));     PIN * INV     1 999 1 0 1 0\n", get_cell_cost("$_AOI4_")); | ||||
| 			fprintf(f, "GATE AOI4   %d Y=!((A*B)+(C*D));     PIN * INV     1 999 1 0 1 0\n", cell_cost("$_AOI4_")); | ||||
| 		if (enabled_gates.empty() || enabled_gates.count("OAI4")) | ||||
| 			fprintf(f, "GATE OAI4   %d Y=!((A+B)*(C+D));     PIN * INV     1 999 1 0 1 0\n", get_cell_cost("$_OAI4_")); | ||||
| 			fprintf(f, "GATE OAI4   %d Y=!((A+B)*(C+D));     PIN * INV     1 999 1 0 1 0\n", cell_cost("$_OAI4_")); | ||||
| 		if (enabled_gates.empty() || 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", get_cell_cost("$_MUX_")); | ||||
| 			fprintf(f, "GATE MUX    %d Y=(A*B)+(S*B)+(!S*A); PIN * UNKNOWN 1 999 1 0 1 0\n", cell_cost("$_MUX_")); | ||||
| 		if (enabled_gates.empty() || 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("$_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*get_cell_cost("$_MUX_")); | ||||
| 			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("$_MUX_")); | ||||
| 		if (map_mux8) | ||||
| 			fprintf(f, "GATE MUX8   %d Y=(!S*!T*!U*A)+(S*!T*!U*B)+(!S*T*!U*C)+(S*T*!U*D)+(!S*!T*U*E)+(S*!T*U*F)+(!S*T*U*G)+(S*T*U*H); PIN * UNKNOWN 1 999 1 0 1 0\n", 4*get_cell_cost("$_MUX_")); | ||||
| 			fprintf(f, "GATE MUX8   %d Y=(!S*!T*!U*A)+(S*!T*!U*B)+(!S*T*!U*C)+(S*T*!U*D)+(!S*!T*U*E)+(S*!T*U*F)+(!S*T*U*G)+(S*T*U*H); PIN * UNKNOWN 1 999 1 0 1 0\n", 4*cell_cost("$_MUX_")); | ||||
| 		if (map_mux16) | ||||
| 			fprintf(f, "GATE MUX16  %d Y=(!S*!T*!U*!V*A)+(S*!T*!U*!V*B)+(!S*T*!U*!V*C)+(S*T*!U*!V*D)+(!S*!T*U*!V*E)+(S*!T*U*!V*F)+(!S*T*U*!V*G)+(S*T*U*!V*H)+(!S*!T*!U*V*I)+(S*!T*!U*V*J)+(!S*T*!U*V*K)+(S*T*!U*V*L)+(!S*!T*U*V*M)+(S*!T*U*V*N)+(!S*T*U*V*O)+(S*T*U*V*P); PIN * UNKNOWN 1 999 1 0 1 0\n", 8*get_cell_cost("$_MUX_")); | ||||
| 			fprintf(f, "GATE MUX16  %d Y=(!S*!T*!U*!V*A)+(S*!T*!U*!V*B)+(!S*T*!U*!V*C)+(S*T*!U*!V*D)+(!S*!T*U*!V*E)+(S*!T*U*!V*F)+(!S*T*U*!V*G)+(S*T*U*!V*H)+(!S*!T*!U*V*I)+(S*!T*!U*V*J)+(!S*T*!U*V*K)+(S*T*!U*V*L)+(!S*!T*U*V*M)+(S*!T*U*V*N)+(!S*T*U*V*O)+(S*T*U*V*P); PIN * UNKNOWN 1 999 1 0 1 0\n", 8*cell_cost("$_MUX_")); | ||||
| 		fclose(f); | ||||
| 
 | ||||
| 		if (!lut_costs.empty()) { | ||||
|  | @ -1066,8 +1077,8 @@ void abc_module(RTLIL::Design *design, RTLIL::Module *current_module, std::strin | |||
| 					design->select(module, cell); | ||||
| 					continue; | ||||
| 				} | ||||
| 				if (c->type == "\\MUX") { | ||||
| 					RTLIL::Cell *cell = module->addCell(remap_name(c->name), "$_MUX_"); | ||||
| 				if (c->type == "\\MUX" || c->type == "\\NMUX") { | ||||
| 					RTLIL::Cell *cell = module->addCell(remap_name(c->name), "$_" + c->type.substr(1) + "_"); | ||||
| 					if (markgroups) cell->attributes["\\abcgroup"] = map_autoidx; | ||||
| 					cell->setPort("\\A", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\A").as_wire()->name)])); | ||||
| 					cell->setPort("\\B", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\B").as_wire()->name)])); | ||||
|  | @ -1407,11 +1418,12 @@ struct AbcPass : public Pass { | |||
| 		log("\n"); | ||||
| 		log("        The following aliases can be used to reference common sets of gate types:\n"); | ||||
| 		log("          simple: AND OR XOR MUX\n"); | ||||
| 		log("          cmos2: NAND NOR\n"); | ||||
| 		log("          cmos3: NAND NOR AOI3 OAI3\n"); | ||||
| 		log("          cmos4: NAND NOR AOI3 OAI3 AOI4 OAI4\n"); | ||||
| 		log("          gates: AND NAND OR NOR XOR XNOR ANDNOT ORNOT\n"); | ||||
| 		log("          aig: AND NAND OR NOR ANDNOT ORNOT\n"); | ||||
| 		log("          cmos2:  NAND NOR\n"); | ||||
| 		log("          cmos3:  NAND NOR AOI3 OAI3\n"); | ||||
| 		log("          cmos4:  NAND NOR AOI3 OAI3 AOI4 OAI4\n"); | ||||
| 		log("          cmos:   NAND NOR AOI3 OAI3 AOI4 OAI4 NMUX MUX XOR XNOR\n"); | ||||
| 		log("          gates:  AND NAND OR NOR XOR XNOR ANDNOT ORNOT\n"); | ||||
| 		log("          aig:    AND NAND OR NOR ANDNOT ORNOT\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"); | ||||
|  | @ -1489,6 +1501,7 @@ struct AbcPass : public Pass { | |||
| 		map_mux8 = false; | ||||
| 		map_mux16 = false; | ||||
| 		enabled_gates.clear(); | ||||
| 		cmos_cost = false; | ||||
| 
 | ||||
| #ifdef _WIN32 | ||||
| #ifndef ABCEXTERNAL | ||||
|  | @ -1629,11 +1642,15 @@ struct AbcPass : public Pass { | |||
| 						goto ok_alias; | ||||
| 					} | ||||
| 					if (g == "cmos2") { | ||||
| 						if (!remove_gates) | ||||
| 							cmos_cost = true; | ||||
| 						gate_list.push_back("NAND"); | ||||
| 						gate_list.push_back("NOR"); | ||||
| 						goto ok_alias; | ||||
| 					} | ||||
| 					if (g == "cmos3") { | ||||
| 						if (!remove_gates) | ||||
| 							cmos_cost = true; | ||||
| 						gate_list.push_back("NAND"); | ||||
| 						gate_list.push_back("NOR"); | ||||
| 						gate_list.push_back("AOI3"); | ||||
|  | @ -1641,6 +1658,8 @@ struct AbcPass : public Pass { | |||
| 						goto ok_alias; | ||||
| 					} | ||||
| 					if (g == "cmos4") { | ||||
| 						if (!remove_gates) | ||||
| 							cmos_cost = true; | ||||
| 						gate_list.push_back("NAND"); | ||||
| 						gate_list.push_back("NOR"); | ||||
| 						gate_list.push_back("AOI3"); | ||||
|  | @ -1649,6 +1668,21 @@ struct AbcPass : public Pass { | |||
| 						gate_list.push_back("OAI4"); | ||||
| 						goto ok_alias; | ||||
| 					} | ||||
| 					if (g == "cmos") { | ||||
| 						if (!remove_gates) | ||||
| 							cmos_cost = true; | ||||
| 						gate_list.push_back("NAND"); | ||||
| 						gate_list.push_back("NOR"); | ||||
| 						gate_list.push_back("AOI3"); | ||||
| 						gate_list.push_back("OAI3"); | ||||
| 						gate_list.push_back("AOI4"); | ||||
| 						gate_list.push_back("OAI4"); | ||||
| 						gate_list.push_back("NMUX"); | ||||
| 						gate_list.push_back("MUX"); | ||||
| 						gate_list.push_back("XOR"); | ||||
| 						gate_list.push_back("XNOR"); | ||||
| 						goto ok_alias; | ||||
| 					} | ||||
| 					if (g == "gates") { | ||||
| 						gate_list.push_back("AND"); | ||||
| 						gate_list.push_back("NAND"); | ||||
|  |  | |||
|  | @ -86,7 +86,7 @@ struct ExtractFaWorker | |||
| 		for (auto cell : module->selected_cells()) | ||||
| 		{ | ||||
| 			if (cell->type.in( "$_BUF_", "$_NOT_", "$_AND_", "$_NAND_", "$_OR_", "$_NOR_", | ||||
| 					"$_XOR_", "$_XNOR_", "$_ANDNOT_", "$_ORNOT_", "$_MUX_", | ||||
| 					"$_XOR_", "$_XNOR_", "$_ANDNOT_", "$_ORNOT_", "$_MUX_", "$_NMUX_", | ||||
| 					"$_AOI3_", "$_OAI3_", "$_AOI4_", "$_OAI4_")) | ||||
| 			{ | ||||
| 				SigBit y = sigmap(SigBit(cell->getPort("\\Y"))); | ||||
|  |  | |||
|  | @ -228,6 +228,25 @@ output Y; | |||
| assign Y = S ? B : A; | ||||
| endmodule | ||||
| 
 | ||||
| //  |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| | ||||
| //- | ||||
| //-     $_NMUX_ (A, B, S, Y) | ||||
| //- | ||||
| //- A 2-input inverting MUX gate. | ||||
| //- | ||||
| //- Truth table:    A B S | Y | ||||
| //-                -------+--- | ||||
| //-                 0 - 0 | 1 | ||||
| //-                 1 - 0 | 0 | ||||
| //-                 - 0 1 | 1 | ||||
| //-                 - 1 1 | 0 | ||||
| //- | ||||
| module \$_NMUX_ (A, B, S, Y); | ||||
| input A, B, S; | ||||
| output Y; | ||||
| assign Y = S ? !B : !A; | ||||
| endmodule | ||||
| 
 | ||||
| //  |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| | ||||
| //- | ||||
| //-     $_MUX4_ (A, B, C, D, S, T, Y) | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue