mirror of
				https://github.com/YosysHQ/yosys
				synced 2025-11-03 21:09:12 +00:00 
			
		
		
		
	Added additional gate types: $_NAND_ $_NOR_ $_XNOR_ $_AOI3_ $_OAI3_ $_AOI4_ $_OAI4_
This commit is contained in:
		
							parent
							
								
									56a30cf42c
								
							
						
					
					
						commit
						47c2637a96
					
				
					 8 changed files with 399 additions and 48 deletions
				
			
		| 
						 | 
				
			
			@ -381,21 +381,25 @@ bool dump_cell_expr(FILE *f, std::string indent, RTLIL::Cell *cell)
 | 
			
		|||
		return true;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (cell->type == "$_AND_" || cell->type == "$_OR_" || cell->type == "$_XOR_") {
 | 
			
		||||
	if (cell->type.in("$_AND_", "$_NAND_", "$_OR_", "$_NOR_", "$_XOR_", "$_XNOR_")) {
 | 
			
		||||
		fprintf(f, "%s" "assign ", indent.c_str());
 | 
			
		||||
		dump_sigspec(f, cell->getPort("\\Y"));
 | 
			
		||||
		fprintf(f, " = ");
 | 
			
		||||
		if (cell->type.in("$_NAND_", "$_NOR_", "$_XNOR_"))
 | 
			
		||||
			fprintf(f, "~(");
 | 
			
		||||
		dump_cell_expr_port(f, cell, "A", false);
 | 
			
		||||
		fprintf(f, " ");
 | 
			
		||||
		if (cell->type == "$_AND_")
 | 
			
		||||
		if (cell->type.in("$_AND_", "$_NAND_"))
 | 
			
		||||
			fprintf(f, "&");
 | 
			
		||||
		if (cell->type == "$_OR_")
 | 
			
		||||
		if (cell->type.in("$_OR_", "$_NOR_"))
 | 
			
		||||
			fprintf(f, "|");
 | 
			
		||||
		if (cell->type == "$_XOR_")
 | 
			
		||||
		if (cell->type.in("$_XOR_", "$_XNOR_"))
 | 
			
		||||
			fprintf(f, "^");
 | 
			
		||||
		dump_attributes(f, "", cell->attributes, ' ');
 | 
			
		||||
		fprintf(f, " ");
 | 
			
		||||
		dump_cell_expr_port(f, cell, "B", false);
 | 
			
		||||
		if (cell->type.in("$_NAND_", "$_NOR_", "$_XNOR_"))
 | 
			
		||||
			fprintf(f, ")");
 | 
			
		||||
		fprintf(f, ";\n");
 | 
			
		||||
		return true;
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			@ -414,6 +418,38 @@ bool dump_cell_expr(FILE *f, std::string indent, RTLIL::Cell *cell)
 | 
			
		|||
		return true;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (cell->type.in("$_AOI3_", "$_OAI3_")) {
 | 
			
		||||
		fprintf(f, "%s" "assign ", indent.c_str());
 | 
			
		||||
		dump_sigspec(f, cell->getPort("\\Y"));
 | 
			
		||||
		fprintf(f, " = (");
 | 
			
		||||
		dump_cell_expr_port(f, cell, "A", false);
 | 
			
		||||
		fprintf(f, cell->type == "$_AOI3_" ? " & " : " | ");
 | 
			
		||||
		dump_cell_expr_port(f, cell, "B", false);
 | 
			
		||||
		fprintf(f, cell->type == "$_AOI3_" ? ") |" : ") &");
 | 
			
		||||
		dump_attributes(f, "", cell->attributes, ' ');
 | 
			
		||||
		fprintf(f, " ");
 | 
			
		||||
		dump_cell_expr_port(f, cell, "C", false);
 | 
			
		||||
		fprintf(f, ";\n");
 | 
			
		||||
		return true;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (cell->type.in("$_AOI4_", "$_OAI4_")) {
 | 
			
		||||
		fprintf(f, "%s" "assign ", indent.c_str());
 | 
			
		||||
		dump_sigspec(f, cell->getPort("\\Y"));
 | 
			
		||||
		fprintf(f, " = (");
 | 
			
		||||
		dump_cell_expr_port(f, cell, "A", false);
 | 
			
		||||
		fprintf(f, cell->type == "$_AOI4_" ? " & " : " | ");
 | 
			
		||||
		dump_cell_expr_port(f, cell, "B", false);
 | 
			
		||||
		fprintf(f, cell->type == "$_AOI4_" ? ") |" : ") &");
 | 
			
		||||
		dump_attributes(f, "", cell->attributes, ' ');
 | 
			
		||||
		fprintf(f, " (");
 | 
			
		||||
		dump_cell_expr_port(f, cell, "C", false);
 | 
			
		||||
		fprintf(f, cell->type == "$_AOI4_" ? " & " : " | ");
 | 
			
		||||
		dump_cell_expr_port(f, cell, "D", false);
 | 
			
		||||
		fprintf(f, ");\n");
 | 
			
		||||
		return true;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (cell->type.substr(0, 6) == "$_DFF_")
 | 
			
		||||
	{
 | 
			
		||||
		std::string reg_name = cellname(cell);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -131,9 +131,16 @@ struct CellTypes
 | 
			
		|||
	{
 | 
			
		||||
		setup_type("$_NOT_", {"\\A"}, {"\\Y"}, true);
 | 
			
		||||
		setup_type("$_AND_", {"\\A", "\\B"}, {"\\Y"}, true);
 | 
			
		||||
		setup_type("$_NAND_", {"\\A", "\\B"}, {"\\Y"}, true);
 | 
			
		||||
		setup_type("$_OR_",  {"\\A", "\\B"}, {"\\Y"}, true);
 | 
			
		||||
		setup_type("$_NOR_",  {"\\A", "\\B"}, {"\\Y"}, true);
 | 
			
		||||
		setup_type("$_XOR_", {"\\A", "\\B"}, {"\\Y"}, true);
 | 
			
		||||
		setup_type("$_XNOR_", {"\\A", "\\B"}, {"\\Y"}, true);
 | 
			
		||||
		setup_type("$_MUX_", {"\\A", "\\B", "\\S"}, {"\\Y"}, true);
 | 
			
		||||
		setup_type("$_AOI3_", {"\\A", "\\B", "\\C"}, {"\\Y"}, true);
 | 
			
		||||
		setup_type("$_OAI3_", {"\\A", "\\B", "\\C"}, {"\\Y"}, true);
 | 
			
		||||
		setup_type("$_AOI4_", {"\\A", "\\B", "\\C", "\\D"}, {"\\Y"}, true);
 | 
			
		||||
		setup_type("$_OAI4_", {"\\A", "\\B", "\\C", "\\D"}, {"\\Y"}, true);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	void setup_stdcells_mem()
 | 
			
		||||
| 
						 | 
				
			
			@ -194,6 +201,14 @@ struct CellTypes
 | 
			
		|||
		return it != cell_types.end() && it->second.is_evaluable;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	static RTLIL::Const eval_not(RTLIL::Const v)
 | 
			
		||||
	{
 | 
			
		||||
		for (auto &bit : v.bits)
 | 
			
		||||
			if (bit == RTLIL::S0) bit = RTLIL::S1;
 | 
			
		||||
			else if (bit == RTLIL::S1) bit = RTLIL::S0;
 | 
			
		||||
		return v;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	static RTLIL::Const eval(RTLIL::IdString type, const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len)
 | 
			
		||||
	{
 | 
			
		||||
		if (type == "$sshr" && !signed1)
 | 
			
		||||
| 
						 | 
				
			
			@ -247,13 +262,19 @@ struct CellTypes
 | 
			
		|||
#undef HANDLE_CELL_TYPE
 | 
			
		||||
 | 
			
		||||
		if (type == "$_NOT_")
 | 
			
		||||
			return const_not(arg1, arg2, false, false, 1);
 | 
			
		||||
			return eval_not(arg1);
 | 
			
		||||
		if (type == "$_AND_")
 | 
			
		||||
			return const_and(arg1, arg2, false, false, 1);
 | 
			
		||||
		if (type == "$_NAND_")
 | 
			
		||||
			return eval_not(const_and(arg1, arg2, false, false, 1));
 | 
			
		||||
		if (type == "$_OR_")
 | 
			
		||||
			return const_or(arg1, arg2, false, false, 1);
 | 
			
		||||
		if (type == "$_NOR_")
 | 
			
		||||
			return eval_not(const_and(arg1, arg2, false, false, 1));
 | 
			
		||||
		if (type == "$_XOR_")
 | 
			
		||||
			return const_xor(arg1, arg2, false, false, 1);
 | 
			
		||||
		if (type == "$_XNOR_")
 | 
			
		||||
			return const_xnor(arg1, arg2, false, false, 1);
 | 
			
		||||
 | 
			
		||||
		log_abort();
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			@ -280,21 +301,37 @@ struct CellTypes
 | 
			
		|||
		return eval(cell->type, arg1, arg2, signed_a, signed_b, result_len);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	static RTLIL::Const eval(RTLIL::Cell *cell, const RTLIL::Const &arg1, const RTLIL::Const &arg2, const RTLIL::Const &sel)
 | 
			
		||||
	static RTLIL::Const eval(RTLIL::Cell *cell, const RTLIL::Const &arg1, const RTLIL::Const &arg2, const RTLIL::Const &arg3)
 | 
			
		||||
	{
 | 
			
		||||
		if (cell->type == "$mux" || cell->type == "$pmux" || cell->type == "$_MUX_") {
 | 
			
		||||
		if (cell->type.in("$mux", "$pmux", "$_MUX_")) {
 | 
			
		||||
			RTLIL::Const ret = arg1;
 | 
			
		||||
			for (size_t i = 0; i < sel.bits.size(); i++)
 | 
			
		||||
				if (sel.bits[i] == RTLIL::State::S1) {
 | 
			
		||||
			for (size_t i = 0; i < arg3.bits.size(); i++)
 | 
			
		||||
				if (arg3.bits[i] == RTLIL::State::S1) {
 | 
			
		||||
					std::vector<RTLIL::State> bits(arg2.bits.begin() + i*arg1.bits.size(), arg2.bits.begin() + (i+1)*arg1.bits.size());
 | 
			
		||||
					ret = RTLIL::Const(bits);
 | 
			
		||||
				}
 | 
			
		||||
			return ret;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		log_assert(sel.bits.size() == 0);
 | 
			
		||||
		if (cell->type == "$_AOI3_")
 | 
			
		||||
			return eval_not(const_or(const_and(arg1, arg2, false, false, 1), arg3, false, false, 1));
 | 
			
		||||
		if (cell->type == "$_OAI3_")
 | 
			
		||||
			return eval_not(const_and(const_or(arg1, arg2, false, false, 1), arg3, false, false, 1));
 | 
			
		||||
 | 
			
		||||
		log_assert(arg3.bits.size() == 0);
 | 
			
		||||
		return eval(cell, arg1, arg2);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	static RTLIL::Const eval(RTLIL::Cell *cell, const RTLIL::Const &arg1, const RTLIL::Const &arg2, const RTLIL::Const &arg3, const RTLIL::Const &arg4)
 | 
			
		||||
	{
 | 
			
		||||
		if (cell->type == "$_AOI4_")
 | 
			
		||||
			return eval_not(const_or(const_and(arg1, arg2, false, false, 1), const_and(arg3, arg4, false, false, 1), false, false, 1));
 | 
			
		||||
		if (cell->type == "$_OAI4_")
 | 
			
		||||
			return eval_not(const_and(const_or(arg1, arg2, false, false, 1), const_and(arg3, arg4, false, false, 1), false, false, 1));
 | 
			
		||||
 | 
			
		||||
		log_assert(arg4.bits.size() == 0);
 | 
			
		||||
		return eval(cell, arg1, arg2, arg3);
 | 
			
		||||
	}
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -156,11 +156,26 @@ struct ConstEval
 | 
			
		|||
		}
 | 
			
		||||
		else
 | 
			
		||||
		{
 | 
			
		||||
			RTLIL::SigSpec sig_c, sig_d;
 | 
			
		||||
 | 
			
		||||
			if (cell->type.in("$_AOI3_", "$_OAI3_", "$_AOI4_", "$_OAI4_")) {
 | 
			
		||||
				if (cell->hasPort("\\C"))
 | 
			
		||||
					sig_c = cell->getPort("\\C");
 | 
			
		||||
				if (cell->hasPort("\\D"))
 | 
			
		||||
					sig_d = cell->getPort("\\D");
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			if (sig_a.size() > 0 && !eval(sig_a, undef, cell))
 | 
			
		||||
				return false;
 | 
			
		||||
			if (sig_b.size() > 0 && !eval(sig_b, undef, cell))
 | 
			
		||||
				return false;
 | 
			
		||||
			set(sig_y, CellTypes::eval(cell, sig_a.as_const(), sig_b.as_const()));
 | 
			
		||||
			if (sig_c.size() > 0 && !eval(sig_c, undef, cell))
 | 
			
		||||
				return false;
 | 
			
		||||
			if (sig_d.size() > 0 && !eval(sig_d, undef, cell))
 | 
			
		||||
				return false;
 | 
			
		||||
 | 
			
		||||
			set(sig_y, CellTypes::eval(cell, sig_a.as_const(), sig_b.as_const(),
 | 
			
		||||
					sig_c.as_const(), sig_d.as_const()));
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		return true;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -758,11 +758,18 @@ namespace {
 | 
			
		|||
				return;
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			if (cell->type == "$_NOT_") { check_gate("AY"); return; }
 | 
			
		||||
			if (cell->type == "$_AND_") { check_gate("ABY"); return; }
 | 
			
		||||
			if (cell->type == "$_OR_")  { check_gate("ABY"); return; }
 | 
			
		||||
			if (cell->type == "$_XOR_") { check_gate("ABY"); return; }
 | 
			
		||||
			if (cell->type == "$_MUX_") { check_gate("ABSY"); return; }
 | 
			
		||||
			if (cell->type == "$_NOT_")  { check_gate("AY"); return; }
 | 
			
		||||
			if (cell->type == "$_AND_")  { check_gate("ABY"); return; }
 | 
			
		||||
			if (cell->type == "$_NAND_") { check_gate("ABY"); return; }
 | 
			
		||||
			if (cell->type == "$_OR_")   { check_gate("ABY"); return; }
 | 
			
		||||
			if (cell->type == "$_NOR_")  { check_gate("ABY"); return; }
 | 
			
		||||
			if (cell->type == "$_XOR_")  { check_gate("ABY"); return; }
 | 
			
		||||
			if (cell->type == "$_XNOR_") { check_gate("ABY"); return; }
 | 
			
		||||
			if (cell->type == "$_MUX_")  { 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; }
 | 
			
		||||
			if (cell->type == "$_OAI4_") { check_gate("ABCDY"); return; }
 | 
			
		||||
 | 
			
		||||
			if (cell->type == "$_SR_NN_") { check_gate("SRQ"); return; }
 | 
			
		||||
			if (cell->type == "$_SR_NP_") { check_gate("SRQ"); return; }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -175,6 +175,11 @@ struct SatGen
 | 
			
		|||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	void undefGating(int y, int yy, int undef)
 | 
			
		||||
	{
 | 
			
		||||
		ez->assume(ez->OR(undef, ez->IFF(y, yy)));
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	bool importCell(RTLIL::Cell *cell, int timestep = -1)
 | 
			
		||||
	{
 | 
			
		||||
		bool arith_undef_handled = false;
 | 
			
		||||
| 
						 | 
				
			
			@ -211,9 +216,8 @@ struct SatGen
 | 
			
		|||
			arith_undef_handled = true;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if (cell->type == "$_AND_" || cell->type == "$_OR_" || cell->type == "$_XOR_" ||
 | 
			
		||||
				cell->type == "$and" || cell->type == "$or" || cell->type == "$xor" || cell->type == "$xnor" ||
 | 
			
		||||
				cell->type == "$add" || cell->type == "$sub")
 | 
			
		||||
		if (cell->type.in("$_AND_", "$_NAND_", "$_OR_", "$_NOR_", "$_XOR_", "$_XNOR_",
 | 
			
		||||
				"$and", "$or", "$xor", "$xnor", "$add", "$sub"))
 | 
			
		||||
		{
 | 
			
		||||
			std::vector<int> a = importDefSigSpec(cell->getPort("\\A"), timestep);
 | 
			
		||||
			std::vector<int> b = importDefSigSpec(cell->getPort("\\B"), timestep);
 | 
			
		||||
| 
						 | 
				
			
			@ -224,11 +228,15 @@ struct SatGen
 | 
			
		|||
 | 
			
		||||
			if (cell->type == "$and" || cell->type == "$_AND_")
 | 
			
		||||
				ez->assume(ez->vec_eq(ez->vec_and(a, b), yy));
 | 
			
		||||
			if (cell->type == "$_NAND_")
 | 
			
		||||
				ez->assume(ez->vec_eq(ez->vec_not(ez->vec_and(a, b)), yy));
 | 
			
		||||
			if (cell->type == "$or" || cell->type == "$_OR_")
 | 
			
		||||
				ez->assume(ez->vec_eq(ez->vec_or(a, b), yy));
 | 
			
		||||
			if (cell->type == "$_NOR_")
 | 
			
		||||
				ez->assume(ez->vec_eq(ez->vec_not(ez->vec_or(a, b)), yy));
 | 
			
		||||
			if (cell->type == "$xor" || cell->type == "$_XOR_")
 | 
			
		||||
				ez->assume(ez->vec_eq(ez->vec_xor(a, b), yy));
 | 
			
		||||
			if (cell->type == "$xnor")
 | 
			
		||||
			if (cell->type == "$xnor" || cell->type == "$_XNOR_")
 | 
			
		||||
				ez->assume(ez->vec_eq(ez->vec_not(ez->vec_xor(a, b)), yy));
 | 
			
		||||
			if (cell->type == "$add")
 | 
			
		||||
				ez->assume(ez->vec_eq(ez->vec_add(a, b), yy));
 | 
			
		||||
| 
						 | 
				
			
			@ -242,19 +250,19 @@ struct SatGen
 | 
			
		|||
				std::vector<int> undef_y = importUndefSigSpec(cell->getPort("\\Y"), timestep);
 | 
			
		||||
				extendSignalWidth(undef_a, undef_b, undef_y, cell, false);
 | 
			
		||||
 | 
			
		||||
				if (cell->type == "$and" || cell->type == "$_AND_") {
 | 
			
		||||
				if (cell->type.in("$and", "$_AND_", "$_NAND_")) {
 | 
			
		||||
					std::vector<int> a0 = ez->vec_and(ez->vec_not(a), ez->vec_not(undef_a));
 | 
			
		||||
					std::vector<int> b0 = ez->vec_and(ez->vec_not(b), ez->vec_not(undef_b));
 | 
			
		||||
					std::vector<int> yX = ez->vec_and(ez->vec_or(undef_a, undef_b), ez->vec_not(ez->vec_or(a0, b0)));
 | 
			
		||||
					ez->assume(ez->vec_eq(yX, undef_y));
 | 
			
		||||
				}
 | 
			
		||||
				else if (cell->type == "$or" || cell->type == "$_OR_") {
 | 
			
		||||
				else if (cell->type.in("$or", "$_OR_", "$_NOR_")) {
 | 
			
		||||
					std::vector<int> a1 = ez->vec_and(a, ez->vec_not(undef_a));
 | 
			
		||||
					std::vector<int> b1 = ez->vec_and(b, ez->vec_not(undef_b));
 | 
			
		||||
					std::vector<int> yX = ez->vec_and(ez->vec_or(undef_a, undef_b), ez->vec_not(ez->vec_or(a1, b1)));
 | 
			
		||||
					ez->assume(ez->vec_eq(yX, undef_y));
 | 
			
		||||
				}
 | 
			
		||||
				else if (cell->type == "$xor" || cell->type == "$_XOR_" || cell->type == "$xnor") {
 | 
			
		||||
				else if (cell->type.in("$xor", "$xnor", "$_XOR_", "$_XNOR_")) {
 | 
			
		||||
					std::vector<int> yX = ez->vec_or(undef_a, undef_b);
 | 
			
		||||
					ez->assume(ez->vec_eq(yX, undef_y));
 | 
			
		||||
				}
 | 
			
		||||
| 
						 | 
				
			
			@ -271,6 +279,72 @@ struct SatGen
 | 
			
		|||
			return true;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if (cell->type.in("$_AOI3_", "$_OAI3_", "$_AOI4_", "$_OAI4_"))
 | 
			
		||||
		{
 | 
			
		||||
			bool aoi_mode = cell->type.in("$_AOI3_", "$_AOI4_");
 | 
			
		||||
			bool three_mode = cell->type.in("$_AOI3_", "$_OAI3_");
 | 
			
		||||
 | 
			
		||||
			int a = importDefSigSpec(cell->getPort("\\A"), timestep).at(0);
 | 
			
		||||
			int b = importDefSigSpec(cell->getPort("\\B"), timestep).at(0);
 | 
			
		||||
			int c = importDefSigSpec(cell->getPort("\\C"), timestep).at(0);
 | 
			
		||||
			int d = three_mode ? (aoi_mode ? ez->TRUE : ez->FALSE) : importDefSigSpec(cell->getPort("\\D"), timestep).at(0);
 | 
			
		||||
			int y = importDefSigSpec(cell->getPort("\\Y"), timestep).at(0);
 | 
			
		||||
			int yy = model_undef ? ez->literal() : y;
 | 
			
		||||
 | 
			
		||||
			if (cell->type.in("$_AOI3_", "$_AOI4_"))
 | 
			
		||||
				ez->assume(ez->IFF(ez->NOT(ez->OR(ez->AND(a, b), ez->AND(c, d))), yy));
 | 
			
		||||
			else
 | 
			
		||||
				ez->assume(ez->IFF(ez->NOT(ez->AND(ez->OR(a, b), ez->OR(c, d))), yy));
 | 
			
		||||
 | 
			
		||||
			if (model_undef)
 | 
			
		||||
			{
 | 
			
		||||
				int undef_a = importUndefSigSpec(cell->getPort("\\A"), timestep).at(0);
 | 
			
		||||
				int undef_b = importUndefSigSpec(cell->getPort("\\B"), timestep).at(0);
 | 
			
		||||
				int undef_c = importUndefSigSpec(cell->getPort("\\C"), timestep).at(0);
 | 
			
		||||
				int undef_d = three_mode ? ez->FALSE : importUndefSigSpec(cell->getPort("\\D"), timestep).at(0);
 | 
			
		||||
				int undef_y = importUndefSigSpec(cell->getPort("\\Y"), timestep).at(0);
 | 
			
		||||
 | 
			
		||||
				if (aoi_mode)
 | 
			
		||||
				{
 | 
			
		||||
					int a0 = ez->AND(ez->NOT(a), ez->NOT(undef_a));
 | 
			
		||||
					int b0 = ez->AND(ez->NOT(b), ez->NOT(undef_b));
 | 
			
		||||
					int c0 = ez->AND(ez->NOT(c), ez->NOT(undef_c));
 | 
			
		||||
					int d0 = ez->AND(ez->NOT(d), ez->NOT(undef_d));
 | 
			
		||||
 | 
			
		||||
					int ab = ez->AND(a, b), cd = ez->AND(c, d);
 | 
			
		||||
					int undef_ab = ez->AND(ez->OR(undef_a, undef_b), ez->NOT(ez->OR(a0, b0)));
 | 
			
		||||
					int undef_cd = ez->AND(ez->OR(undef_c, undef_d), ez->NOT(ez->OR(c0, d0)));
 | 
			
		||||
 | 
			
		||||
					int ab1 = ez->AND(ab, ez->NOT(undef_ab));
 | 
			
		||||
					int cd1 = ez->AND(cd, ez->NOT(undef_cd));
 | 
			
		||||
					int yX = ez->AND(ez->OR(undef_ab, undef_cd), ez->NOT(ez->OR(ab1, cd1)));
 | 
			
		||||
 | 
			
		||||
					ez->assume(ez->IFF(yX, undef_y));
 | 
			
		||||
				}
 | 
			
		||||
				else
 | 
			
		||||
				{
 | 
			
		||||
					int a1 = ez->AND(a, ez->NOT(undef_a));
 | 
			
		||||
					int b1 = ez->AND(b, ez->NOT(undef_b));
 | 
			
		||||
					int c1 = ez->AND(c, ez->NOT(undef_c));
 | 
			
		||||
					int d1 = ez->AND(d, ez->NOT(undef_d));
 | 
			
		||||
 | 
			
		||||
					int ab = ez->OR(a, b), cd = ez->OR(c, d);
 | 
			
		||||
					int undef_ab = ez->AND(ez->OR(undef_a, undef_b), ez->NOT(ez->OR(a1, b1)));
 | 
			
		||||
					int undef_cd = ez->AND(ez->OR(undef_c, undef_d), ez->NOT(ez->OR(c1, d1)));
 | 
			
		||||
 | 
			
		||||
					int ab0 = ez->AND(ez->NOT(ab), ez->NOT(undef_ab));
 | 
			
		||||
					int cd0 = ez->AND(ez->NOT(cd), ez->NOT(undef_cd));
 | 
			
		||||
					int yX = ez->AND(ez->OR(undef_ab, undef_cd), ez->NOT(ez->OR(ab0, cd0)));
 | 
			
		||||
 | 
			
		||||
					ez->assume(ez->IFF(yX, undef_y));
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				undefGating(y, yy, undef_y);
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			return true;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if (cell->type == "$_NOT_" || cell->type == "$not")
 | 
			
		||||
		{
 | 
			
		||||
			std::vector<int> a = importDefSigSpec(cell->getPort("\\A"), timestep);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -430,3 +430,7 @@ Add information about {\tt \$assert} cells.
 | 
			
		|||
Add information about {\tt \$slice} and {\tt \$concat} cells.
 | 
			
		||||
\end{fixme}
 | 
			
		||||
 | 
			
		||||
\begin{fixme}
 | 
			
		||||
Add information about {\tt \$\_NAND\_}, {\tt \$\_NOR\_}, {\tt \$\_XNOR\_}, {\tt \$\_AOI3\_}, {\tt \$\_OAI3\_}, {\tt \$\_AOI4\_}, and {\tt \$\_OAI4\_} cells.
 | 
			
		||||
\end{fixme}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -48,11 +48,30 @@
 | 
			
		|||
 | 
			
		||||
#include "blifparse.h"
 | 
			
		||||
 | 
			
		||||
enum class gate_type_t {
 | 
			
		||||
	G_NONE,
 | 
			
		||||
	G_FF,
 | 
			
		||||
	G_NOT,
 | 
			
		||||
	G_AND,
 | 
			
		||||
	G_NAND,
 | 
			
		||||
	G_OR,
 | 
			
		||||
	G_NOR,
 | 
			
		||||
	G_XOR,
 | 
			
		||||
	G_XNOR,
 | 
			
		||||
	G_MUX,
 | 
			
		||||
	G_AOI3,
 | 
			
		||||
	G_OAI3,
 | 
			
		||||
	G_AOI4,
 | 
			
		||||
	G_OAI4
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#define G(_name) gate_type_t::G_ ## _name
 | 
			
		||||
 | 
			
		||||
struct gate_t
 | 
			
		||||
{
 | 
			
		||||
	int id;
 | 
			
		||||
	char type;
 | 
			
		||||
	int in1, in2, in3;
 | 
			
		||||
	gate_type_t type;
 | 
			
		||||
	int in1, in2, in3, in4;
 | 
			
		||||
	bool is_port;
 | 
			
		||||
	RTLIL::SigBit bit;
 | 
			
		||||
};
 | 
			
		||||
| 
						 | 
				
			
			@ -66,17 +85,18 @@ static std::map<RTLIL::SigBit, int> signal_map;
 | 
			
		|||
static bool clk_polarity;
 | 
			
		||||
static RTLIL::SigSpec clk_sig;
 | 
			
		||||
 | 
			
		||||
static int map_signal(RTLIL::SigBit bit, char gate_type = -1, int in1 = -1, int in2 = -1, int in3 = -1)
 | 
			
		||||
static int map_signal(RTLIL::SigBit bit, gate_type_t gate_type = G(NONE), int in1 = -1, int in2 = -1, int in3 = -1, int in4 = -1)
 | 
			
		||||
{
 | 
			
		||||
	assign_map.apply(bit);
 | 
			
		||||
 | 
			
		||||
	if (signal_map.count(bit) == 0) {
 | 
			
		||||
		gate_t gate;
 | 
			
		||||
		gate.id = signal_list.size();
 | 
			
		||||
		gate.type = -1;
 | 
			
		||||
		gate.type = G(NONE);
 | 
			
		||||
		gate.in1 = -1;
 | 
			
		||||
		gate.in2 = -1;
 | 
			
		||||
		gate.in3 = -1;
 | 
			
		||||
		gate.in4 = -1;
 | 
			
		||||
		gate.is_port = false;
 | 
			
		||||
		gate.bit = bit;
 | 
			
		||||
		signal_list.push_back(gate);
 | 
			
		||||
| 
						 | 
				
			
			@ -85,7 +105,7 @@ static int map_signal(RTLIL::SigBit bit, char gate_type = -1, int in1 = -1, int
 | 
			
		|||
 | 
			
		||||
	gate_t &gate = signal_list[signal_map[bit]];
 | 
			
		||||
 | 
			
		||||
	if (gate_type >= 0)
 | 
			
		||||
	if (gate_type != G(NONE))
 | 
			
		||||
		gate.type = gate_type;
 | 
			
		||||
	if (in1 >= 0)
 | 
			
		||||
		gate.in1 = in1;
 | 
			
		||||
| 
						 | 
				
			
			@ -93,6 +113,8 @@ static int map_signal(RTLIL::SigBit bit, char gate_type = -1, int in1 = -1, int
 | 
			
		|||
		gate.in2 = in2;
 | 
			
		||||
	if (in3 >= 0)
 | 
			
		||||
		gate.in3 = in3;
 | 
			
		||||
	if (in4 >= 0)
 | 
			
		||||
		gate.in4 = in4;
 | 
			
		||||
 | 
			
		||||
	return gate.id;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -124,7 +146,7 @@ static void extract_cell(RTLIL::Cell *cell, bool keepff)
 | 
			
		|||
		assign_map.apply(sig_d);
 | 
			
		||||
		assign_map.apply(sig_q);
 | 
			
		||||
 | 
			
		||||
		map_signal(sig_q, 'f', map_signal(sig_d));
 | 
			
		||||
		map_signal(sig_q, G(FF), map_signal(sig_d));
 | 
			
		||||
 | 
			
		||||
		module->remove(cell);
 | 
			
		||||
		return;
 | 
			
		||||
| 
						 | 
				
			
			@ -138,13 +160,13 @@ static void extract_cell(RTLIL::Cell *cell, bool keepff)
 | 
			
		|||
		assign_map.apply(sig_a);
 | 
			
		||||
		assign_map.apply(sig_y);
 | 
			
		||||
 | 
			
		||||
		map_signal(sig_y, 'n', map_signal(sig_a));
 | 
			
		||||
		map_signal(sig_y, G(NOT), map_signal(sig_a));
 | 
			
		||||
 | 
			
		||||
		module->remove(cell);
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (cell->type == "$_AND_" || cell->type == "$_OR_" || cell->type == "$_XOR_")
 | 
			
		||||
	if (cell->type.in("$_AND_", "$_NAND_", "$_OR_", "$_NOR", "$_XOR_", "$_XNOR_"))
 | 
			
		||||
	{
 | 
			
		||||
		RTLIL::SigSpec sig_a = cell->getPort("\\A");
 | 
			
		||||
		RTLIL::SigSpec sig_b = cell->getPort("\\B");
 | 
			
		||||
| 
						 | 
				
			
			@ -158,11 +180,17 @@ static void extract_cell(RTLIL::Cell *cell, bool keepff)
 | 
			
		|||
		int mapped_b = map_signal(sig_b);
 | 
			
		||||
 | 
			
		||||
		if (cell->type == "$_AND_")
 | 
			
		||||
			map_signal(sig_y, 'a', mapped_a, mapped_b);
 | 
			
		||||
			map_signal(sig_y, G(AND), mapped_a, mapped_b);
 | 
			
		||||
		else if (cell->type == "$_NAND_")
 | 
			
		||||
			map_signal(sig_y, G(NAND), mapped_a, mapped_b);
 | 
			
		||||
		else if (cell->type == "$_OR_")
 | 
			
		||||
			map_signal(sig_y, 'o', mapped_a, mapped_b);
 | 
			
		||||
			map_signal(sig_y, G(OR), mapped_a, mapped_b);
 | 
			
		||||
		else if (cell->type == "$_NOR_")
 | 
			
		||||
			map_signal(sig_y, G(NOR), mapped_a, mapped_b);
 | 
			
		||||
		else if (cell->type == "$_XOR_")
 | 
			
		||||
			map_signal(sig_y, 'x', mapped_a, mapped_b);
 | 
			
		||||
			map_signal(sig_y, G(XOR), mapped_a, mapped_b);
 | 
			
		||||
		else if (cell->type == "$_XNOR_")
 | 
			
		||||
			map_signal(sig_y, G(XNOR), mapped_a, mapped_b);
 | 
			
		||||
		else
 | 
			
		||||
			log_abort();
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -186,7 +214,54 @@ static 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, 'm', mapped_a, mapped_b, mapped_s);
 | 
			
		||||
		map_signal(sig_y, G(MUX), mapped_a, mapped_b, mapped_s);
 | 
			
		||||
 | 
			
		||||
		module->remove(cell);
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (cell->type.in("$_AOI3_", "$_OAI3_"))
 | 
			
		||||
	{
 | 
			
		||||
		RTLIL::SigSpec sig_a = cell->getPort("\\A");
 | 
			
		||||
		RTLIL::SigSpec sig_b = cell->getPort("\\B");
 | 
			
		||||
		RTLIL::SigSpec sig_c = cell->getPort("\\C");
 | 
			
		||||
		RTLIL::SigSpec sig_y = cell->getPort("\\Y");
 | 
			
		||||
 | 
			
		||||
		assign_map.apply(sig_a);
 | 
			
		||||
		assign_map.apply(sig_b);
 | 
			
		||||
		assign_map.apply(sig_c);
 | 
			
		||||
		assign_map.apply(sig_y);
 | 
			
		||||
 | 
			
		||||
		int mapped_a = map_signal(sig_a);
 | 
			
		||||
		int mapped_b = map_signal(sig_b);
 | 
			
		||||
		int mapped_c = map_signal(sig_c);
 | 
			
		||||
 | 
			
		||||
		map_signal(sig_y, cell->type == "$_AOI3_" ? G(AOI3) : G(OAI3), mapped_a, mapped_b, mapped_c);
 | 
			
		||||
 | 
			
		||||
		module->remove(cell);
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (cell->type.in("$_AOI4_", "$_OAI4_"))
 | 
			
		||||
	{
 | 
			
		||||
		RTLIL::SigSpec sig_a = cell->getPort("\\A");
 | 
			
		||||
		RTLIL::SigSpec sig_b = cell->getPort("\\B");
 | 
			
		||||
		RTLIL::SigSpec sig_c = cell->getPort("\\C");
 | 
			
		||||
		RTLIL::SigSpec sig_d = cell->getPort("\\D");
 | 
			
		||||
		RTLIL::SigSpec sig_y = cell->getPort("\\Y");
 | 
			
		||||
 | 
			
		||||
		assign_map.apply(sig_a);
 | 
			
		||||
		assign_map.apply(sig_b);
 | 
			
		||||
		assign_map.apply(sig_c);
 | 
			
		||||
		assign_map.apply(sig_d);
 | 
			
		||||
		assign_map.apply(sig_y);
 | 
			
		||||
 | 
			
		||||
		int mapped_a = map_signal(sig_a);
 | 
			
		||||
		int mapped_b = map_signal(sig_b);
 | 
			
		||||
		int mapped_c = map_signal(sig_c);
 | 
			
		||||
		int mapped_d = map_signal(sig_d);
 | 
			
		||||
 | 
			
		||||
		map_signal(sig_y, cell->type == "$_AOI4_" ? G(AOI4) : G(OAI4), mapped_a, mapped_b, mapped_c, mapped_d);
 | 
			
		||||
 | 
			
		||||
		module->remove(cell);
 | 
			
		||||
		return;
 | 
			
		||||
| 
						 | 
				
			
			@ -244,7 +319,7 @@ static void handle_loops()
 | 
			
		|||
	// dot_f = fopen("test.dot", "w");
 | 
			
		||||
 | 
			
		||||
	for (auto &g : signal_list) {
 | 
			
		||||
		if (g.type == -1 || g.type == 'f') {
 | 
			
		||||
		if (g.type == G(NONE) || g.type == G(FF)) {
 | 
			
		||||
			workpool.insert(g.id);
 | 
			
		||||
		} else {
 | 
			
		||||
			if (g.in1 >= 0) {
 | 
			
		||||
| 
						 | 
				
			
			@ -259,6 +334,10 @@ static void handle_loops()
 | 
			
		|||
				edges[g.in3].insert(g.id);
 | 
			
		||||
				in_edges_count[g.id]++;
 | 
			
		||||
			}
 | 
			
		||||
			if (g.in4 >= 0 && g.in4 != g.in3 && g.in4 != g.in2 && g.in4 != g.in1) {
 | 
			
		||||
				edges[g.in4].insert(g.id);
 | 
			
		||||
				in_edges_count[g.id]++;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -341,6 +420,8 @@ static void handle_loops()
 | 
			
		|||
					signal_list[id2].in2 = id3;
 | 
			
		||||
				if (signal_list[id2].in3 == id1)
 | 
			
		||||
					signal_list[id2].in3 = id3;
 | 
			
		||||
				if (signal_list[id2].in4 == id1)
 | 
			
		||||
					signal_list[id2].in4 = id3;
 | 
			
		||||
			}
 | 
			
		||||
			edges[id1].swap(edges[id3]);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -521,7 +602,7 @@ static void abc_module(RTLIL::Design *design, RTLIL::Module *current_module, std
 | 
			
		|||
	int count_input = 0;
 | 
			
		||||
	fprintf(f, ".inputs");
 | 
			
		||||
	for (auto &si : signal_list) {
 | 
			
		||||
		if (!si.is_port || si.type >= 0)
 | 
			
		||||
		if (!si.is_port || si.type != G(NONE))
 | 
			
		||||
			continue;
 | 
			
		||||
		fprintf(f, " n%d", si.id);
 | 
			
		||||
		count_input++;
 | 
			
		||||
| 
						 | 
				
			
			@ -533,7 +614,7 @@ static void abc_module(RTLIL::Design *design, RTLIL::Module *current_module, std
 | 
			
		|||
	int count_output = 0;
 | 
			
		||||
	fprintf(f, ".outputs");
 | 
			
		||||
	for (auto &si : signal_list) {
 | 
			
		||||
		if (!si.is_port || si.type < 0)
 | 
			
		||||
		if (!si.is_port || si.type == G(NONE))
 | 
			
		||||
			continue;
 | 
			
		||||
		fprintf(f, " n%d", si.id);
 | 
			
		||||
		count_output++;
 | 
			
		||||
| 
						 | 
				
			
			@ -553,29 +634,58 @@ static void abc_module(RTLIL::Design *design, RTLIL::Module *current_module, std
 | 
			
		|||
 | 
			
		||||
	int count_gates = 0;
 | 
			
		||||
	for (auto &si : signal_list) {
 | 
			
		||||
		if (si.type == 'n') {
 | 
			
		||||
		if (si.type == G(NOT)) {
 | 
			
		||||
			fprintf(f, ".names n%d n%d\n", si.in1, si.id);
 | 
			
		||||
			fprintf(f, "0 1\n");
 | 
			
		||||
		} else if (si.type == 'a') {
 | 
			
		||||
		} else if (si.type == G(AND)) {
 | 
			
		||||
			fprintf(f, ".names n%d n%d n%d\n", si.in1, si.in2, si.id);
 | 
			
		||||
			fprintf(f, "11 1\n");
 | 
			
		||||
		} else if (si.type == 'o') {
 | 
			
		||||
		} else if (si.type == G(NAND)) {
 | 
			
		||||
			fprintf(f, ".names n%d n%d n%d\n", si.in1, si.in2, si.id);
 | 
			
		||||
			fprintf(f, "0- 1\n");
 | 
			
		||||
			fprintf(f, "-0 1\n");
 | 
			
		||||
		} else if (si.type == G(OR)) {
 | 
			
		||||
			fprintf(f, ".names n%d n%d n%d\n", si.in1, si.in2, si.id);
 | 
			
		||||
			fprintf(f, "-1 1\n");
 | 
			
		||||
			fprintf(f, "1- 1\n");
 | 
			
		||||
		} else if (si.type == 'x') {
 | 
			
		||||
		} else if (si.type == G(NOR)) {
 | 
			
		||||
			fprintf(f, ".names n%d n%d n%d\n", si.in1, si.in2, si.id);
 | 
			
		||||
			fprintf(f, "00 1\n");
 | 
			
		||||
		} else if (si.type == G(XOR)) {
 | 
			
		||||
			fprintf(f, ".names n%d n%d n%d\n", si.in1, si.in2, si.id);
 | 
			
		||||
			fprintf(f, "01 1\n");
 | 
			
		||||
			fprintf(f, "10 1\n");
 | 
			
		||||
		} else if (si.type == 'm') {
 | 
			
		||||
		} else if (si.type == G(XNOR)) {
 | 
			
		||||
			fprintf(f, ".names n%d n%d n%d\n", si.in1, si.in2, si.id);
 | 
			
		||||
			fprintf(f, "00 1\n");
 | 
			
		||||
			fprintf(f, "11 1\n");
 | 
			
		||||
		} else if (si.type == G(MUX)) {
 | 
			
		||||
			fprintf(f, ".names n%d n%d n%d 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 == 'f') {
 | 
			
		||||
		} else if (si.type == G(AOI3)) {
 | 
			
		||||
			fprintf(f, ".names n%d n%d n%d n%d\n", si.in1, si.in2, si.in3, si.id);
 | 
			
		||||
			fprintf(f, "-00 1\n");
 | 
			
		||||
			fprintf(f, "0-0 1\n");
 | 
			
		||||
		} else if (si.type == G(OAI3)) {
 | 
			
		||||
			fprintf(f, ".names n%d n%d n%d n%d\n", si.in1, si.in2, si.in3, si.id);
 | 
			
		||||
			fprintf(f, "00- 1\n");
 | 
			
		||||
			fprintf(f, "--0 1\n");
 | 
			
		||||
		} else if (si.type == G(AOI4)) {
 | 
			
		||||
			fprintf(f, ".names n%d n%d n%d n%d n%d\n", si.in1, si.in2, si.in3, si.in4, si.id);
 | 
			
		||||
			fprintf(f, "-0-0 1\n");
 | 
			
		||||
			fprintf(f, "-00- 1\n");
 | 
			
		||||
			fprintf(f, "0--0 1\n");
 | 
			
		||||
			fprintf(f, "0-0- 1\n");
 | 
			
		||||
		} else if (si.type == G(OAI4)) {
 | 
			
		||||
			fprintf(f, ".names n%d n%d n%d n%d n%d\n", si.in1, si.in2, si.in3, si.in4, si.id);
 | 
			
		||||
			fprintf(f, "00-- 1\n");
 | 
			
		||||
			fprintf(f, "--00 1\n");
 | 
			
		||||
		} else if (si.type == G(FF)) {
 | 
			
		||||
			fprintf(f, ".latch n%d n%d\n", si.in1, si.id);
 | 
			
		||||
		} else if (si.type >= 0)
 | 
			
		||||
		} else if (si.type != G(NONE))
 | 
			
		||||
			log_abort();
 | 
			
		||||
		if (si.type >= 0)
 | 
			
		||||
		if (si.type != G(NONE))
 | 
			
		||||
			count_gates++;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -599,9 +709,16 @@ static void abc_module(RTLIL::Design *design, RTLIL::Module *current_module, std
 | 
			
		|||
		fprintf(f, "GATE BUF  1 Y=A;                  PIN * NONINV  1 999 1 0 1 0\n");
 | 
			
		||||
		fprintf(f, "GATE INV  1 Y=!A;                 PIN * INV     1 999 1 0 1 0\n");
 | 
			
		||||
		fprintf(f, "GATE AND  1 Y=A*B;                PIN * NONINV  1 999 1 0 1 0\n");
 | 
			
		||||
		fprintf(f, "GATE NAND 1 Y=!(A*B);             PIN * INV     1 999 1 0 1 0\n");
 | 
			
		||||
		fprintf(f, "GATE OR   1 Y=A+B;                PIN * NONINV  1 999 1 0 1 0\n");
 | 
			
		||||
		fprintf(f, "GATE NOR  1 Y=!(A+B);             PIN * INV     1 999 1 0 1 0\n");
 | 
			
		||||
		fprintf(f, "GATE XOR  1 Y=(A*!B)+(!A*B);      PIN * UNKNOWN 1 999 1 0 1 0\n");
 | 
			
		||||
		fprintf(f, "GATE XNOR 1 Y=(A*B)+(!A*!B);      PIN * UNKNOWN 1 999 1 0 1 0\n");
 | 
			
		||||
		fprintf(f, "GATE MUX  1 Y=(A*B)+(S*B)+(!S*A); PIN * UNKNOWN 1 999 1 0 1 0\n");
 | 
			
		||||
		fprintf(f, "GATE AOI3 1 Y=!((A*B)+C);         PIN * INV     1 999 1 0 1 0\n");
 | 
			
		||||
		fprintf(f, "GATE OAI3 1 Y=!((A+B)*C);         PIN * INV     1 999 1 0 1 0\n");
 | 
			
		||||
		fprintf(f, "GATE AOI4 1 Y=!((A*B)+(C*D));     PIN * INV     1 999 1 0 1 0\n");
 | 
			
		||||
		fprintf(f, "GATE OAI4 1 Y=!((A+B)*(C+D));     PIN * INV     1 999 1 0 1 0\n");
 | 
			
		||||
		fclose(f);
 | 
			
		||||
		free(p);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -739,7 +856,7 @@ static void abc_module(RTLIL::Design *design, RTLIL::Module *current_module, std
 | 
			
		|||
					design->select(module, cell);
 | 
			
		||||
					continue;
 | 
			
		||||
				}
 | 
			
		||||
				if (c->type == "\\AND" || c->type == "\\OR" || c->type == "\\XOR") {
 | 
			
		||||
				if (c->type == "\\AND" || c->type == "\\OR" || c->type == "\\XOR" || c->type == "\\NAND" || c->type == "\\NOR" || c->type == "\\XNOR") {
 | 
			
		||||
					RTLIL::Cell *cell = module->addCell(remap_name(c->name), "$_" + c->type.substr(1) + "_");
 | 
			
		||||
					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)]));
 | 
			
		||||
| 
						 | 
				
			
			@ -756,6 +873,25 @@ static void abc_module(RTLIL::Design *design, RTLIL::Module *current_module, std
 | 
			
		|||
					design->select(module, cell);
 | 
			
		||||
					continue;
 | 
			
		||||
				}
 | 
			
		||||
				if (c->type == "\\AOI3" || c->type == "\\OAI3") {
 | 
			
		||||
					RTLIL::Cell *cell = module->addCell(remap_name(c->name), "$_" + c->type.substr(1) + "_");
 | 
			
		||||
					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)]));
 | 
			
		||||
					cell->setPort("\\C", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\C").as_wire()->name)]));
 | 
			
		||||
					cell->setPort("\\Y", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\Y").as_wire()->name)]));
 | 
			
		||||
					design->select(module, cell);
 | 
			
		||||
					continue;
 | 
			
		||||
				}
 | 
			
		||||
				if (c->type == "\\AOI4" || c->type == "\\OAI4") {
 | 
			
		||||
					RTLIL::Cell *cell = module->addCell(remap_name(c->name), "$_" + c->type.substr(1) + "_");
 | 
			
		||||
					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)]));
 | 
			
		||||
					cell->setPort("\\C", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\C").as_wire()->name)]));
 | 
			
		||||
					cell->setPort("\\D", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\D").as_wire()->name)]));
 | 
			
		||||
					cell->setPort("\\Y", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\Y").as_wire()->name)]));
 | 
			
		||||
					design->select(module, cell);
 | 
			
		||||
					continue;
 | 
			
		||||
				}
 | 
			
		||||
				if (c->type == "\\DFF") {
 | 
			
		||||
					log_assert(clk_sig.size() == 1);
 | 
			
		||||
					RTLIL::Cell *cell = module->addCell(remap_name(c->name), clk_polarity ? "$_DFF_P_" : "$_DFF_N_");
 | 
			
		||||
| 
						 | 
				
			
			@ -822,7 +958,7 @@ static void abc_module(RTLIL::Design *design, RTLIL::Module *current_module, std
 | 
			
		|||
				char buffer[100];
 | 
			
		||||
				snprintf(buffer, 100, "\\n%d", si.id);
 | 
			
		||||
				RTLIL::SigSig conn;
 | 
			
		||||
				if (si.type >= 0) {
 | 
			
		||||
				if (si.type != G(NONE)) {
 | 
			
		||||
					conn.first = si.bit;
 | 
			
		||||
					conn.second = RTLIL::SigSpec(module->wires_[remap_name(buffer)]);
 | 
			
		||||
					out_wires++;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -37,24 +37,66 @@ output Y;
 | 
			
		|||
assign Y = A & B;
 | 
			
		||||
endmodule
 | 
			
		||||
 | 
			
		||||
module  \$_NAND_ (A, B, Y);
 | 
			
		||||
input A, B;
 | 
			
		||||
output Y;
 | 
			
		||||
assign Y = ~(A & B);
 | 
			
		||||
endmodule
 | 
			
		||||
 | 
			
		||||
module  \$_OR_ (A, B, Y);
 | 
			
		||||
input A, B;
 | 
			
		||||
output Y;
 | 
			
		||||
assign Y = A | B;
 | 
			
		||||
endmodule
 | 
			
		||||
 | 
			
		||||
module  \$_NOR_ (A, B, Y);
 | 
			
		||||
input A, B;
 | 
			
		||||
output Y;
 | 
			
		||||
assign Y = ~(A | B);
 | 
			
		||||
endmodule
 | 
			
		||||
 | 
			
		||||
module  \$_XOR_ (A, B, Y);
 | 
			
		||||
input A, B;
 | 
			
		||||
output Y;
 | 
			
		||||
assign Y = A ^ B;
 | 
			
		||||
endmodule
 | 
			
		||||
 | 
			
		||||
module  \$_XNOR_ (A, B, Y);
 | 
			
		||||
input A, B;
 | 
			
		||||
output Y;
 | 
			
		||||
assign Y = ~(A ^ B);
 | 
			
		||||
endmodule
 | 
			
		||||
 | 
			
		||||
module \$_MUX_ (A, B, S, Y);
 | 
			
		||||
input A, B, S;
 | 
			
		||||
output Y;
 | 
			
		||||
assign Y = S ? B : A;
 | 
			
		||||
endmodule
 | 
			
		||||
 | 
			
		||||
module  \$_AOI3_ (A, B, C, Y);
 | 
			
		||||
input A, B, C;
 | 
			
		||||
output Y;
 | 
			
		||||
assign Y = ~((A & B) | C);
 | 
			
		||||
endmodule
 | 
			
		||||
 | 
			
		||||
module  \$_OAI3_ (A, B, C, Y);
 | 
			
		||||
input A, B, C;
 | 
			
		||||
output Y;
 | 
			
		||||
assign Y = ~((A | B) & C);
 | 
			
		||||
endmodule
 | 
			
		||||
 | 
			
		||||
module  \$_AOI4_ (A, B, C, D, Y);
 | 
			
		||||
input A, B, C, D;
 | 
			
		||||
output Y;
 | 
			
		||||
assign Y = ~((A & B) | (C & D));
 | 
			
		||||
endmodule
 | 
			
		||||
 | 
			
		||||
module  \$_OAI4_ (A, B, C, D, Y);
 | 
			
		||||
input A, B, C, D;
 | 
			
		||||
output Y;
 | 
			
		||||
assign Y = ~((A | B) & (C | D));
 | 
			
		||||
endmodule
 | 
			
		||||
 | 
			
		||||
module  \$_SR_NN_ (S, R, Q);
 | 
			
		||||
input S, R;
 | 
			
		||||
output reg Q;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue