mirror of
				https://github.com/YosysHQ/yosys
				synced 2025-10-31 03:32:29 +00:00 
			
		
		
		
	AigMaker refactoring
This commit is contained in:
		
							parent
							
								
									e534881794
								
							
						
					
					
						commit
						1ae360cf72
					
				
					 4 changed files with 165 additions and 90 deletions
				
			
		|  | @ -225,7 +225,7 @@ struct JsonWriter | ||||||
| 						f << stringf("\"%sport\", \"%s\", %d", node.inverter ? "n" : "", | 						f << stringf("\"%sport\", \"%s\", %d", node.inverter ? "n" : "", | ||||||
| 								log_id(node.portname), node.portbit); | 								log_id(node.portname), node.portbit); | ||||||
| 					else if (node.left_parent < 0 && node.right_parent < 0) | 					else if (node.left_parent < 0 && node.right_parent < 0) | ||||||
| 						f << stringf("\"%s\"", node.inverter ? "false" : "true"); | 						f << stringf("\"%s\"", node.inverter ? "true" : "false"); | ||||||
| 					else | 					else | ||||||
| 						f << stringf("\"%s\", %d, %d", node.inverter ? "nand" : "and", node.left_parent, node.right_parent); | 						f << stringf("\"%s\", %d, %d", node.inverter ? "nand" : "and", node.left_parent, node.right_parent); | ||||||
| 					for (auto &op : node.outports) | 					for (auto &op : node.outports) | ||||||
|  |  | ||||||
|  | @ -21,6 +21,14 @@ | ||||||
| 
 | 
 | ||||||
| YOSYS_NAMESPACE_BEGIN | YOSYS_NAMESPACE_BEGIN | ||||||
| 
 | 
 | ||||||
|  | AigNode::AigNode() | ||||||
|  | { | ||||||
|  | 	portbit = -1; | ||||||
|  | 	inverter = false; | ||||||
|  | 	left_parent = -1; | ||||||
|  | 	right_parent = -1; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| bool AigNode::operator==(const AigNode &other) const | bool AigNode::operator==(const AigNode &other) const | ||||||
| { | { | ||||||
| 	if (portname != other.portname) return false; | 	if (portname != other.portname) return false; | ||||||
|  | @ -66,13 +74,13 @@ struct AigMaker | ||||||
| 		the_false_node = -1; | 		the_false_node = -1; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	int bool_node(bool value) | 	int node2index(const AigNode &node) | ||||||
| 	{ | 	{ | ||||||
| 		AigNode node; | 		if (node.left_parent > node.right_parent) { | ||||||
| 		node.portbit = -1; | 			AigNode n(node); | ||||||
| 		node.inverter = !value; | 			std::swap(n.left_parent, n.right_parent); | ||||||
| 		node.left_parent = -1; | 			return node2index(n); | ||||||
| 		node.right_parent = -1; | 		} | ||||||
| 
 | 
 | ||||||
| 		if (!aig_indices.count(node)) { | 		if (!aig_indices.count(node)) { | ||||||
| 			aig_indices.expect(node, GetSize(aig->nodes)); | 			aig_indices.expect(node, GetSize(aig->nodes)); | ||||||
|  | @ -82,6 +90,13 @@ struct AigMaker | ||||||
| 		return aig_indices.at(node); | 		return aig_indices.at(node); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	int bool_node(bool value) | ||||||
|  | 	{ | ||||||
|  | 		AigNode node; | ||||||
|  | 		node.inverter = value; | ||||||
|  | 		return node2index(node); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
| 	int inport(IdString portname, int portbit = 0, bool inverter = false) | 	int inport(IdString portname, int portbit = 0, bool inverter = false) | ||||||
| 	{ | 	{ | ||||||
| 		if (portbit >= GetSize(cell->getPort(portname))) { | 		if (portbit >= GetSize(cell->getPort(portname))) { | ||||||
|  | @ -94,15 +109,7 @@ struct AigMaker | ||||||
| 		node.portname = portname; | 		node.portname = portname; | ||||||
| 		node.portbit = portbit; | 		node.portbit = portbit; | ||||||
| 		node.inverter = inverter; | 		node.inverter = inverter; | ||||||
| 		node.left_parent = -1; | 		return node2index(node); | ||||||
| 		node.right_parent = -1; |  | ||||||
| 
 |  | ||||||
| 		if (!aig_indices.count(node)) { |  | ||||||
| 			aig_indices.expect(node, GetSize(aig->nodes)); |  | ||||||
| 			aig->nodes.push_back(node); |  | ||||||
| 		} |  | ||||||
| 
 |  | ||||||
| 		return aig_indices.at(node); |  | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	int not_inport(IdString portname, int portbit = 0) | 	int not_inport(IdString portname, int portbit = 0) | ||||||
|  | @ -110,28 +117,86 @@ struct AigMaker | ||||||
| 		return inport(portname, portbit, true); | 		return inport(portname, portbit, true); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	int and_gate(int left_parent, int right_parent, bool inverter = false) | 	int not_gate(int A) | ||||||
| 	{ | 	{ | ||||||
| 		if (left_parent > right_parent) | 		AigNode node(aig_indices[A]); | ||||||
| 			std::swap(left_parent, right_parent); | 		node.outports.clear(); | ||||||
| 
 | 		node.inverter = !node.inverter; | ||||||
| 		AigNode node; | 		return node2index(node); | ||||||
| 		node.portbit = -1; |  | ||||||
| 		node.inverter = inverter; |  | ||||||
| 		node.left_parent = left_parent; |  | ||||||
| 		node.right_parent = right_parent; |  | ||||||
| 
 |  | ||||||
| 		if (!aig_indices.count(node)) { |  | ||||||
| 			aig_indices.expect(node, GetSize(aig->nodes)); |  | ||||||
| 			aig->nodes.push_back(node); |  | ||||||
| 		} |  | ||||||
| 
 |  | ||||||
| 		return aig_indices.at(node); |  | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	int nand_gate(int left_parent, int right_parent) | 	int and_gate(int A, int B, bool inverter = false) | ||||||
| 	{ | 	{ | ||||||
| 		return and_gate(left_parent, right_parent, true); | 		if (A == B) | ||||||
|  | 			return A; | ||||||
|  | 
 | ||||||
|  | 		const AigNode &nA = aig_indices[A]; | ||||||
|  | 		const AigNode &nB = aig_indices[B]; | ||||||
|  | 
 | ||||||
|  | 		AigNode nB_inv(nB); | ||||||
|  | 		nB_inv.inverter = !nB_inv.inverter; | ||||||
|  | 
 | ||||||
|  | 		if (nA == nB_inv) | ||||||
|  | 			return bool_node(inverter); | ||||||
|  | 
 | ||||||
|  | 		bool nA_bool = nA.portbit < 0 && nA.left_parent < 0 && nA.right_parent < 0; | ||||||
|  | 		bool nB_bool = nB.portbit < 0 && nB.left_parent < 0 && nB.right_parent < 0; | ||||||
|  | 
 | ||||||
|  | 		if (nA_bool && nB_bool) { | ||||||
|  | 			bool bA = nA.inverter; | ||||||
|  | 			bool bB = nB.inverter; | ||||||
|  | 			return bool_node(inverter != (bA && bB)); | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		if (nA_bool) { | ||||||
|  | 			bool bA = nA.inverter; | ||||||
|  | 			if (inverter) | ||||||
|  | 				return bA ? not_gate(B) : bool_node(true); | ||||||
|  | 			return bA ? B : bool_node(false); | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		if (nB_bool) { | ||||||
|  | 			bool bB = nB.inverter; | ||||||
|  | 			if (inverter) | ||||||
|  | 				return bB ? not_gate(A) : bool_node(true); | ||||||
|  | 			return bB ? A : bool_node(false); | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		AigNode node; | ||||||
|  | 		node.inverter = inverter; | ||||||
|  | 		node.left_parent = A; | ||||||
|  | 		node.right_parent = B; | ||||||
|  | 		return node2index(node); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	int nand_gate(int A, int B) | ||||||
|  | 	{ | ||||||
|  | 		return and_gate(A, B, true); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	int or_gate(int A, int B) | ||||||
|  | 	{ | ||||||
|  | 		return nand_gate(not_gate(A), not_gate(B)); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	int nor_gate(int A, int B) | ||||||
|  | 	{ | ||||||
|  | 		return and_gate(not_gate(A), not_gate(B)); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	int xor_gate(int A, int B) | ||||||
|  | 	{ | ||||||
|  | 		return nor_gate(and_gate(A, B), nor_gate(A, B)); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	int xnor_gate(int A, int B) | ||||||
|  | 	{ | ||||||
|  | 		return or_gate(and_gate(A, B), nor_gate(A, B)); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	int mux_gate(int A, int B, int S) | ||||||
|  | 	{ | ||||||
|  | 		return or_gate(and_gate(A, not_gate(S)), and_gate(B, S)); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	void outport(int node, IdString portname, int portbit = 0) | 	void outport(int node, IdString portname, int portbit = 0) | ||||||
|  | @ -153,78 +218,62 @@ Aig::Aig(Cell *cell) | ||||||
| 	for (auto p : cell->parameters) | 	for (auto p : cell->parameters) | ||||||
| 		name += stringf(":%d", p.second.as_int()); | 		name += stringf(":%d", p.second.as_int()); | ||||||
| 
 | 
 | ||||||
| 	if (cell->type.in("$and", "$_AND_", "$_NAND_")) | 	if (cell->type.in("$not", "$_NOT_")) | ||||||
|  | 	{ | ||||||
|  | 		for (int i = 0; i < GetSize(cell->getPort("\\Y")); i++) { | ||||||
|  | 			int A = mk.inport("\\A", i); | ||||||
|  | 			int Y = mk.not_gate(A); | ||||||
|  | 			mk.outport(Y, "\\Y", i); | ||||||
|  | 		} | ||||||
|  | 		goto optimize; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if (cell->type.in("$and", "$_AND_", "$_NAND_", "$or", "$_OR_", "$_NOR_", "$xor", "$xnor", "$_XOR_", "$_XNOR_")) | ||||||
| 	{ | 	{ | ||||||
| 		for (int i = 0; i < GetSize(cell->getPort("\\Y")); i++) { | 		for (int i = 0; i < GetSize(cell->getPort("\\Y")); i++) { | ||||||
| 			int A = mk.inport("\\A", i); | 			int A = mk.inport("\\A", i); | ||||||
| 			int B = mk.inport("\\B", i); | 			int B = mk.inport("\\B", i); | ||||||
| 			int Y = mk.and_gate(A, B, cell->type == "$_NAND_"); | 			int Y = cell->type.in("$and", "$_AND_")   ? mk.and_gate(A, B) : | ||||||
|  | 			        cell->type.in("$_NAND_")          ? mk.nand_gate(A, B) : | ||||||
|  | 			        cell->type.in("$or", "$_OR_")     ? mk.or_gate(A, B) : | ||||||
|  | 			        cell->type.in("$_NOR_")           ? mk.nor_gate(A, B) : | ||||||
|  | 			        cell->type.in("$xor", "$_XOR_")   ? mk.xor_gate(A, B) : | ||||||
|  | 			        cell->type.in("$xnor", "$_XNOR_") ? mk.xnor_gate(A, B) : -1; | ||||||
| 			mk.outport(Y, "\\Y", i); | 			mk.outport(Y, "\\Y", i); | ||||||
| 		} | 		} | ||||||
| 		return; | 		goto optimize; | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	if (cell->type.in("$or", "$_OR_", "$_NOR_")) |  | ||||||
| 	{ |  | ||||||
| 		for (int i = 0; i < GetSize(cell->getPort("\\Y")); i++) { |  | ||||||
| 			int A = mk.not_inport("\\A", i); |  | ||||||
| 			int B = mk.not_inport("\\B", i); |  | ||||||
| 			int Y = mk.and_gate(A, B, cell->type != "$_NOR_"); |  | ||||||
| 			mk.outport(Y, "\\Y", i); |  | ||||||
| 		} |  | ||||||
| 		return; |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	if (cell->type.in("$xor", "$xnor", "$_XOR_", "$_XNOR_")) |  | ||||||
| 	{ |  | ||||||
| 		for (int i = 0; i < GetSize(cell->getPort("\\Y")); i++) { |  | ||||||
| 			int A = mk.inport("\\A", i); |  | ||||||
| 			int B = mk.inport("\\B", i); |  | ||||||
| 			int NA = mk.not_inport("\\A", i); |  | ||||||
| 			int NB = mk.not_inport("\\B", i); |  | ||||||
| 			int NOT_AB = mk.nand_gate(A, B); |  | ||||||
| 			int NOT_NAB = mk.nand_gate(NA, NB); |  | ||||||
| 			int Y = mk.and_gate(NOT_AB, NOT_NAB, !cell->type.in("$xor", "$_XOR_")); |  | ||||||
| 			mk.outport(Y, "\\Y", i); |  | ||||||
| 		} |  | ||||||
| 		return; |  | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	if (cell->type.in("$mux", "$_MUX_")) | 	if (cell->type.in("$mux", "$_MUX_")) | ||||||
| 	{ | 	{ | ||||||
| 		int S = mk.inport("\\S"); | 		int S = mk.inport("\\S"); | ||||||
| 		int NS = mk.not_inport("\\S"); |  | ||||||
| 		for (int i = 0; i < GetSize(cell->getPort("\\Y")); i++) { | 		for (int i = 0; i < GetSize(cell->getPort("\\Y")); i++) { | ||||||
| 			int A = mk.inport("\\A", i); | 			int A = mk.inport("\\A", i); | ||||||
| 			int B = mk.inport("\\B", i); | 			int B = mk.inport("\\B", i); | ||||||
| 			int NOT_SB = mk.nand_gate(S, B); | 			int Y = mk.mux_gate(A, B, S); | ||||||
| 			int NOT_NSA = mk.nand_gate(NS, A); |  | ||||||
| 			int Y = mk.nand_gate(NOT_SB, NOT_NSA); |  | ||||||
| 			mk.outport(Y, "\\Y", i); | 			mk.outport(Y, "\\Y", i); | ||||||
| 		} | 		} | ||||||
| 		return; | 		goto optimize; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	if (cell->type == "$_AOI3_") | 	if (cell->type == "$_AOI3_") | ||||||
| 	{ | 	{ | ||||||
| 		int A = mk.inport("\\A"); | 		int A = mk.inport("\\A"); | ||||||
| 		int B = mk.inport("\\B"); | 		int B = mk.inport("\\B"); | ||||||
| 		int NC = mk.not_inport("\\C"); | 		int C = mk.inport("\\C"); | ||||||
| 		int NOT_AB = mk.nand_gate(A, B); | 		int Y = mk.nor_gate(mk.and_gate(A, B), C); | ||||||
| 		int Y = mk.and_gate(NOT_AB, NC); |  | ||||||
| 		mk.outport(Y, "\\Y"); | 		mk.outport(Y, "\\Y"); | ||||||
| 		return; | 		goto optimize; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	if (cell->type == "$_OAI3_") | 	if (cell->type == "$_OAI3_") | ||||||
| 	{ | 	{ | ||||||
| 		int NA = mk.not_inport("\\A"); | 		int A = mk.inport("\\A"); | ||||||
| 		int NB = mk.not_inport("\\B"); | 		int B = mk.inport("\\B"); | ||||||
| 		int C = mk.inport("\\C"); | 		int C = mk.inport("\\C"); | ||||||
| 		int NOT_NAB = mk.nand_gate(NA, NB); | 		int Y = mk.nand_gate(mk.or_gate(A, B), C); | ||||||
| 		int Y = mk.nand_gate(NOT_NAB, C); |  | ||||||
| 		mk.outport(Y, "\\Y"); | 		mk.outport(Y, "\\Y"); | ||||||
| 		return; | 		goto optimize; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	if (cell->type == "$_AOI4_") | 	if (cell->type == "$_AOI4_") | ||||||
|  | @ -233,27 +282,52 @@ Aig::Aig(Cell *cell) | ||||||
| 		int B = mk.inport("\\B"); | 		int B = mk.inport("\\B"); | ||||||
| 		int C = mk.inport("\\C"); | 		int C = mk.inport("\\C"); | ||||||
| 		int D = mk.inport("\\D"); | 		int D = mk.inport("\\D"); | ||||||
| 		int NOT_AB = mk.nand_gate(A, B); | 		int Y = mk.nor_gate(mk.and_gate(A, B), mk.and_gate(C, D)); | ||||||
| 		int NOT_CD = mk.nand_gate(C, D); |  | ||||||
| 		int Y = mk.and_gate(NOT_AB, NOT_CD); |  | ||||||
| 		mk.outport(Y, "\\Y"); | 		mk.outport(Y, "\\Y"); | ||||||
| 		return; | 		goto optimize; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	if (cell->type == "$_OAI4_") | 	if (cell->type == "$_OAI4_") | ||||||
| 	{ | 	{ | ||||||
| 		int NA = mk.not_inport("\\A"); | 		int A = mk.inport("\\A"); | ||||||
| 		int NB = mk.not_inport("\\B"); | 		int B = mk.inport("\\B"); | ||||||
| 		int NC = mk.not_inport("\\C"); | 		int C = mk.inport("\\C"); | ||||||
| 		int ND = mk.not_inport("\\D"); | 		int D = mk.inport("\\D"); | ||||||
| 		int NOT_NAB = mk.nand_gate(NA, NB); | 		int Y = mk.nand_gate(mk.nor_gate(A, B), mk.nor_gate(C, D)); | ||||||
| 		int NOT_NCD = mk.nand_gate(NC, ND); |  | ||||||
| 		int Y = mk.nand_gate(NOT_NAB, NOT_NCD); |  | ||||||
| 		mk.outport(Y, "\\Y"); | 		mk.outport(Y, "\\Y"); | ||||||
| 		return; | 		goto optimize; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	name.clear(); | 	name.clear(); | ||||||
|  | 	return; | ||||||
|  | 
 | ||||||
|  | optimize:; | ||||||
|  | 	pool<int> used_old_ids; | ||||||
|  | 	vector<AigNode> new_nodes; | ||||||
|  | 	dict<int, int> old_to_new_ids; | ||||||
|  | 	old_to_new_ids[-1] = -1; | ||||||
|  | 
 | ||||||
|  | 	for (int i = GetSize(nodes)-1; i >= 0; i--) { | ||||||
|  | 		if (!nodes[i].outports.empty()) | ||||||
|  | 			used_old_ids.insert(i); | ||||||
|  | 		if (!used_old_ids.count(i)) | ||||||
|  | 			continue; | ||||||
|  | 		if (nodes[i].left_parent >= 0) | ||||||
|  | 			used_old_ids.insert(nodes[i].left_parent); | ||||||
|  | 		if (nodes[i].right_parent >= 0) | ||||||
|  | 			used_old_ids.insert(nodes[i].right_parent); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	for (int i = 0; i < GetSize(nodes); i++) { | ||||||
|  | 		if (!used_old_ids.count(i)) | ||||||
|  | 			continue; | ||||||
|  | 		nodes[i].left_parent = old_to_new_ids.at(nodes[i].left_parent); | ||||||
|  | 		nodes[i].right_parent = old_to_new_ids.at(nodes[i].right_parent); | ||||||
|  | 		old_to_new_ids[i] = GetSize(new_nodes); | ||||||
|  | 		new_nodes.push_back(nodes[i]); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	new_nodes.swap(nodes); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| YOSYS_NAMESPACE_END | YOSYS_NAMESPACE_END | ||||||
|  |  | ||||||
|  | @ -32,6 +32,7 @@ struct AigNode | ||||||
| 	int left_parent, right_parent; | 	int left_parent, right_parent; | ||||||
| 	vector<pair<IdString, int>> outports; | 	vector<pair<IdString, int>> outports; | ||||||
| 
 | 
 | ||||||
|  | 	AigNode(); | ||||||
| 	bool operator==(const AigNode &other) const; | 	bool operator==(const AigNode &other) const; | ||||||
| 	unsigned int hash() const; | 	unsigned int hash() const; | ||||||
| }; | }; | ||||||
|  |  | ||||||
|  | @ -89,7 +89,7 @@ struct AigmapPass : public Pass { | ||||||
| 					if (node.portbit >= 0) { | 					if (node.portbit >= 0) { | ||||||
| 						bit = cell->getPort(node.portname)[node.portbit]; | 						bit = cell->getPort(node.portname)[node.portbit]; | ||||||
| 					} else if (node.left_parent < 0 && node.right_parent < 0) { | 					} else if (node.left_parent < 0 && node.right_parent < 0) { | ||||||
| 						bit = node.inverter ? State::S0 : State::S1; | 						bit = node.inverter ? State::S1 : State::S0; | ||||||
| 						goto skip_inverter; | 						goto skip_inverter; | ||||||
| 					} else { | 					} else { | ||||||
| 						SigBit A = sigs.at(node.left_parent); | 						SigBit A = sigs.at(node.left_parent); | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue