AigMaker refactoring
authorClifford Wolf <clifford@clifford.at>
Wed, 10 Jun 2015 21:00:12 +0000 (23:00 +0200)
committerClifford Wolf <clifford@clifford.at>
Wed, 10 Jun 2015 21:00:12 +0000 (23:00 +0200)
backends/json/json.cc
kernel/cellaigs.cc
kernel/cellaigs.h
passes/techmap/aigmap.cc

index 42bec277678a8fdde327ea3e02acd159595e83a3..52b97ef0bde938f71d3c2c369c5050202420c977 100644 (file)
@@ -225,7 +225,7 @@ struct JsonWriter
                                                f << stringf("\"%sport\", \"%s\", %d", node.inverter ? "n" : "",
                                                                log_id(node.portname), node.portbit);
                                        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
                                                f << stringf("\"%s\", %d, %d", node.inverter ? "nand" : "and", node.left_parent, node.right_parent);
                                        for (auto &op : node.outports)
index 1d9612e81fd79270d8ffb468ea2a91b40b358522..48727c14582d9b541888089d731014576e948b3a 100644 (file)
 
 YOSYS_NAMESPACE_BEGIN
 
+AigNode::AigNode()
+{
+       portbit = -1;
+       inverter = false;
+       left_parent = -1;
+       right_parent = -1;
+}
+
 bool AigNode::operator==(const AigNode &other) const
 {
        if (portname != other.portname) return false;
@@ -66,13 +74,13 @@ struct AigMaker
                the_false_node = -1;
        }
 
-       int bool_node(bool value)
+       int node2index(const AigNode &node)
        {
-               AigNode node;
-               node.portbit = -1;
-               node.inverter = !value;
-               node.left_parent = -1;
-               node.right_parent = -1;
+               if (node.left_parent > node.right_parent) {
+                       AigNode n(node);
+                       std::swap(n.left_parent, n.right_parent);
+                       return node2index(n);
+               }
 
                if (!aig_indices.count(node)) {
                        aig_indices.expect(node, GetSize(aig->nodes));
@@ -82,6 +90,13 @@ struct AigMaker
                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)
        {
                if (portbit >= GetSize(cell->getPort(portname))) {
@@ -94,15 +109,7 @@ struct AigMaker
                node.portname = portname;
                node.portbit = portbit;
                node.inverter = inverter;
-               node.left_parent = -1;
-               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);
+               return node2index(node);
        }
 
        int not_inport(IdString portname, int portbit = 0)
@@ -110,28 +117,86 @@ struct AigMaker
                return inport(portname, portbit, true);
        }
 
-       int and_gate(int left_parent, int right_parent, bool inverter = false)
+       int not_gate(int A)
+       {
+               AigNode node(aig_indices[A]);
+               node.outports.clear();
+               node.inverter = !node.inverter;
+               return node2index(node);
+       }
+
+       int and_gate(int A, int B, bool inverter = false)
        {
-               if (left_parent > right_parent)
-                       std::swap(left_parent, right_parent);
+               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.portbit = -1;
                node.inverter = inverter;
-               node.left_parent = left_parent;
-               node.right_parent = right_parent;
+               node.left_parent = A;
+               node.right_parent = B;
+               return node2index(node);
+       }
 
-               if (!aig_indices.count(node)) {
-                       aig_indices.expect(node, GetSize(aig->nodes));
-                       aig->nodes.push_back(node);
-               }
+       int nand_gate(int A, int B)
+       {
+               return and_gate(A, B, true);
+       }
 
-               return aig_indices.at(node);
+       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 nand_gate(int left_parent, int right_parent)
+       int xor_gate(int A, int B)
        {
-               return and_gate(left_parent, right_parent, true);
+               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)
@@ -153,78 +218,62 @@ Aig::Aig(Cell *cell)
        for (auto p : cell->parameters)
                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 B = mk.inport("\\B", i);
-                       int Y = mk.and_gate(A, B, cell->type == "$_NAND_");
-                       mk.outport(Y, "\\Y", i);
-               }
-               return;
-       }
-
-       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_");
+                       int Y = mk.not_gate(A);
                        mk.outport(Y, "\\Y", i);
                }
-               return;
+               goto optimize;
        }
 
-       if (cell->type.in("$xor", "$xnor", "$_XOR_", "$_XNOR_"))
+       if (cell->type.in("$and", "$_AND_", "$_NAND_", "$or", "$_OR_", "$_NOR_", "$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_"));
+                       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);
                }
-               return;
+               goto optimize;
        }
 
        if (cell->type.in("$mux", "$_MUX_"))
        {
                int S = mk.inport("\\S");
-               int NS = mk.not_inport("\\S");
                for (int i = 0; i < GetSize(cell->getPort("\\Y")); i++) {
                        int A = mk.inport("\\A", i);
                        int B = mk.inport("\\B", i);
-                       int NOT_SB = mk.nand_gate(S, B);
-                       int NOT_NSA = mk.nand_gate(NS, A);
-                       int Y = mk.nand_gate(NOT_SB, NOT_NSA);
+                       int Y = mk.mux_gate(A, B, S);
                        mk.outport(Y, "\\Y", i);
                }
-               return;
+               goto optimize;
        }
 
        if (cell->type == "$_AOI3_")
        {
                int A = mk.inport("\\A");
                int B = mk.inport("\\B");
-               int NC = mk.not_inport("\\C");
-               int NOT_AB = mk.nand_gate(A, B);
-               int Y = mk.and_gate(NOT_AB, NC);
+               int C = mk.inport("\\C");
+               int Y = mk.nor_gate(mk.and_gate(A, B), C);
                mk.outport(Y, "\\Y");
-               return;
+               goto optimize;
        }
 
        if (cell->type == "$_OAI3_")
        {
-               int NA = mk.not_inport("\\A");
-               int NB = mk.not_inport("\\B");
+               int A = mk.inport("\\A");
+               int B = mk.inport("\\B");
                int C = mk.inport("\\C");
-               int NOT_NAB = mk.nand_gate(NA, NB);
-               int Y = mk.nand_gate(NOT_NAB, C);
+               int Y = mk.nand_gate(mk.or_gate(A, B), C);
                mk.outport(Y, "\\Y");
-               return;
+               goto optimize;
        }
 
        if (cell->type == "$_AOI4_")
@@ -233,27 +282,52 @@ Aig::Aig(Cell *cell)
                int B = mk.inport("\\B");
                int C = mk.inport("\\C");
                int D = mk.inport("\\D");
-               int NOT_AB = mk.nand_gate(A, B);
-               int NOT_CD = mk.nand_gate(C, D);
-               int Y = mk.and_gate(NOT_AB, NOT_CD);
+               int Y = mk.nor_gate(mk.and_gate(A, B), mk.and_gate(C, D));
                mk.outport(Y, "\\Y");
-               return;
+               goto optimize;
        }
 
        if (cell->type == "$_OAI4_")
        {
-               int NA = mk.not_inport("\\A");
-               int NB = mk.not_inport("\\B");
-               int NC = mk.not_inport("\\C");
-               int ND = mk.not_inport("\\D");
-               int NOT_NAB = mk.nand_gate(NA, NB);
-               int NOT_NCD = mk.nand_gate(NC, ND);
-               int Y = mk.nand_gate(NOT_NAB, NOT_NCD);
+               int A = mk.inport("\\A");
+               int B = mk.inport("\\B");
+               int C = mk.inport("\\C");
+               int D = mk.inport("\\D");
+               int Y = mk.nand_gate(mk.nor_gate(A, B), mk.nor_gate(C, D));
                mk.outport(Y, "\\Y");
-               return;
+               goto optimize;
        }
 
        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
index efe9d83c1e2952eacb8b6ac2c8c786c31a8fbf8c..f548f4667833340243bad9c98d5dd3a2b500ce9a 100644 (file)
@@ -32,6 +32,7 @@ struct AigNode
        int left_parent, right_parent;
        vector<pair<IdString, int>> outports;
 
+       AigNode();
        bool operator==(const AigNode &other) const;
        unsigned int hash() const;
 };
index 9f552e3e568fc0c24a151c181e7aa62f82b82646..5253b0f8a37585b88e7812e2d260be4bd9f549f1 100644 (file)
@@ -89,7 +89,7 @@ struct AigmapPass : public Pass {
                                        if (node.portbit >= 0) {
                                                bit = cell->getPort(node.portname)[node.portbit];
                                        } 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;
                                        } else {
                                                SigBit A = sigs.at(node.left_parent);