abc9: respect (* keep *) on cells
authorEddie Hung <eddie@fpgeh.com>
Tue, 14 Jan 2020 03:21:11 +0000 (19:21 -0800)
committerEddie Hung <eddie@fpgeh.com>
Tue, 14 Jan 2020 03:21:11 +0000 (19:21 -0800)
backends/aiger/xaiger.cc
passes/techmap/abc9_ops.cc
tests/techmap/abc9.ys

index 2a0f5c7e4efc3f518492de8dfe040b76ddafaf60..ed0e48e010339b1a2a80ab45a149563fdf4d72b6 100644 (file)
@@ -186,74 +186,76 @@ struct XAigerWriter
 
                dict<IdString,dict<IdString,int>> arrival_cache;
                for (auto cell : module->cells()) {
-                       if (cell->type == "$_NOT_")
-                       {
-                               SigBit A = sigmap(cell->getPort("\\A").as_bit());
-                               SigBit Y = sigmap(cell->getPort("\\Y").as_bit());
-                               unused_bits.erase(A);
-                               undriven_bits.erase(Y);
-                               not_map[Y] = A;
-                               continue;
-                       }
-
-                       if (cell->type == "$_AND_")
-                       {
-                               SigBit A = sigmap(cell->getPort("\\A").as_bit());
-                               SigBit B = sigmap(cell->getPort("\\B").as_bit());
-                               SigBit Y = sigmap(cell->getPort("\\Y").as_bit());
-                               unused_bits.erase(A);
-                               unused_bits.erase(B);
-                               undriven_bits.erase(Y);
-                               and_map[Y] = make_pair(A, B);
-                               continue;
-                       }
+                       RTLIL::Module* inst_module = module->design->module(cell->type);
+                       if (!cell->has_keep_attr()) {
+                               if (cell->type == "$_NOT_")
+                               {
+                                       SigBit A = sigmap(cell->getPort("\\A").as_bit());
+                                       SigBit Y = sigmap(cell->getPort("\\Y").as_bit());
+                                       unused_bits.erase(A);
+                                       undriven_bits.erase(Y);
+                                       not_map[Y] = A;
+                                       continue;
+                               }
 
-                       if (cell->type == "$__ABC9_FF_" &&
-                                       // The presence of an abc9_mergeability attribute indicates
-                                       //   that we do want to pass this flop to ABC
-                                       cell->attributes.count("\\abc9_mergeability"))
-                       {
-                               SigBit D = sigmap(cell->getPort("\\D").as_bit());
-                               SigBit Q = sigmap(cell->getPort("\\Q").as_bit());
-                               unused_bits.erase(D);
-                               undriven_bits.erase(Q);
-                               alias_map[Q] = D;
-                               auto r YS_ATTRIBUTE(unused) = ff_bits.insert(std::make_pair(D, cell));
-                               log_assert(r.second);
-                               continue;
-                       }
+                               if (cell->type == "$_AND_")
+                               {
+                                       SigBit A = sigmap(cell->getPort("\\A").as_bit());
+                                       SigBit B = sigmap(cell->getPort("\\B").as_bit());
+                                       SigBit Y = sigmap(cell->getPort("\\Y").as_bit());
+                                       unused_bits.erase(A);
+                                       unused_bits.erase(B);
+                                       undriven_bits.erase(Y);
+                                       and_map[Y] = make_pair(A, B);
+                                       continue;
+                               }
 
-                       RTLIL::Module* inst_module = module->design->module(cell->type);
-                       if (inst_module) {
-                               auto it = cell->attributes.find("\\abc9_box_seq");
-                               if (it != cell->attributes.end()) {
-                                       int abc9_box_seq = it->second.as_int();
-                                       if (GetSize(box_list) <= abc9_box_seq)
-                                               box_list.resize(abc9_box_seq+1);
-                                       box_list[abc9_box_seq] = cell;
-                                       // Only flop boxes may have arrival times
-                                       if (!inst_module->get_bool_attribute("\\abc9_flop"))
-                                               continue;
+                               if (cell->type == "$__ABC9_FF_" &&
+                                               // The presence of an abc9_mergeability attribute indicates
+                                               //   that we do want to pass this flop to ABC
+                                               cell->attributes.count("\\abc9_mergeability"))
+                               {
+                                       SigBit D = sigmap(cell->getPort("\\D").as_bit());
+                                       SigBit Q = sigmap(cell->getPort("\\Q").as_bit());
+                                       unused_bits.erase(D);
+                                       undriven_bits.erase(Q);
+                                       alias_map[Q] = D;
+                                       auto r YS_ATTRIBUTE(unused) = ff_bits.insert(std::make_pair(D, cell));
+                                       log_assert(r.second);
+                                       continue;
                                }
 
-                               auto &cell_arrivals = arrival_cache[cell->type];
-                               for (const auto &conn : cell->connections()) {
-                                       auto r = cell_arrivals.insert(conn.first);
-                                       auto &arrival = r.first->second;
-                                       if (r.second) {
-                                               auto port_wire = inst_module->wire(conn.first);
-                                               if (port_wire->port_output) {
-                                                       auto it = port_wire->attributes.find("\\abc9_arrival");
-                                                       if (it != port_wire->attributes.end()) {
-                                                               if (it->second.flags != 0)
-                                                                       log_error("Attribute 'abc9_arrival' on port '%s' of module '%s' is not an integer.\n", log_id(port_wire), log_id(cell->type));
-                                                               arrival = it->second.as_int();
+                               if (inst_module) {
+                                       auto it = cell->attributes.find("\\abc9_box_seq");
+                                       if (it != cell->attributes.end()) {
+                                               int abc9_box_seq = it->second.as_int();
+                                               if (GetSize(box_list) <= abc9_box_seq)
+                                                       box_list.resize(abc9_box_seq+1);
+                                               box_list[abc9_box_seq] = cell;
+                                               // Only flop boxes may have arrival times
+                                               if (!inst_module->get_bool_attribute("\\abc9_flop"))
+                                                       continue;
+                                       }
+
+                                       auto &cell_arrivals = arrival_cache[cell->type];
+                                       for (const auto &conn : cell->connections()) {
+                                               auto r = cell_arrivals.insert(conn.first);
+                                               auto &arrival = r.first->second;
+                                               if (r.second) {
+                                                       auto port_wire = inst_module->wire(conn.first);
+                                                       if (port_wire->port_output) {
+                                                               auto it = port_wire->attributes.find("\\abc9_arrival");
+                                                               if (it != port_wire->attributes.end()) {
+                                                                       if (it->second.flags != 0)
+                                                                               log_error("Attribute 'abc9_arrival' on port '%s' of module '%s' is not an integer.\n", log_id(port_wire), log_id(cell->type));
+                                                                       arrival = it->second.as_int();
+                                                               }
                                                        }
                                                }
+                                               if (arrival)
+                                                       for (auto bit : sigmap(conn.second))
+                                                               arrival_times[bit] = arrival;
                                        }
-                                       if (arrival)
-                                               for (auto bit : sigmap(conn.second))
-                                                       arrival_times[bit] = arrival;
                                }
                        }
 
@@ -270,6 +272,9 @@ struct XAigerWriter
                                        for (auto b : c.second) {
                                                Wire *w = b.wire;
                                                if (!w) continue;
+                                               // Do not add as PO if bit is already a PI
+                                               if (input_bits.count(b))
+                                                       continue;
                                                if (!w->port_output || !cell_known) {
                                                        SigBit I = sigmap(b);
                                                        if (I != b)
@@ -431,6 +436,9 @@ struct XAigerWriter
                for (const auto &bit : output_bits) {
                        ordered_outputs[bit] = aig_o++;
                        int aig;
+                       // For inout/keep bits only, the output bit
+                       //   should be driven by logic, not the PI,
+                       //   so temporarily swap that out
                        if (input_bits.count(bit)) {
                                auto it = aig_map.find(bit);
                                int input_aig = it->second;
index cc22fd474ab913aa2edb8700932214fe5182088f..9cc58c99d896c2e01078d9896f0f6c73b7fbe585 100644 (file)
@@ -489,6 +489,8 @@ void reintegrate(RTLIL::Module *module)
 
        std::vector<Cell*> boxes;
        for (auto cell : module->cells().to_vector()) {
+               if (cell->has_keep_attr())
+                       continue;
                if (cell->type.in(ID($_AND_), ID($_NOT_), ID($__ABC9_FF_)))
                        module->remove(cell);
                else if (cell->attributes.erase("\\abc9_box_seq"))
index 46b6f08d2e712a41c7e7f0d289d58932420e8548..d5a63e1cbd61c63e2f8073eb57362c64635a0001 100644 (file)
@@ -51,3 +51,18 @@ simplemap
 equiv_opt -assert abc9 -lut 4
 design -load postopt
 select -assert-count 2 t:$lut
+
+design -reset
+read_verilog -icells <<EOT
+module top(input a, b, output o);
+wire w;
+(* keep *) $_AND_ gate (.Y(w), .A(a), .B(b));
+assign o = ~w;
+endmodule
+EOT
+
+simplemap
+equiv_opt -assert abc9 -lut 4
+design -load postopt
+select -assert-count 1 t:$lut
+select -assert-count 1 t:$_AND_