mirror of https://github.com/YosysHQ/yosys.git
AigMaker refactoring
This commit is contained in:
parent
e534881794
commit
1ae360cf72
|
@ -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…
Reference in New Issue