aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEddie Hung <eddie@fpgeh.com>2020-01-13 19:21:11 -0800
committerEddie Hung <eddie@fpgeh.com>2020-01-13 19:21:11 -0800
commita6d4ea74634826741f09793c36d596f2fa239f62 (patch)
tree37e4bdc7f77b77c60d69516f9aa150c2c4c0579d
parent9ec948f3965eef214bee3af778b67fdd6ee86929 (diff)
downloadyosys-a6d4ea74634826741f09793c36d596f2fa239f62.tar.gz
yosys-a6d4ea74634826741f09793c36d596f2fa239f62.tar.bz2
yosys-a6d4ea74634826741f09793c36d596f2fa239f62.zip
abc9: respect (* keep *) on cells
-rw-r--r--backends/aiger/xaiger.cc130
-rw-r--r--passes/techmap/abc9_ops.cc2
-rw-r--r--tests/techmap/abc9.ys15
3 files changed, 86 insertions, 61 deletions
diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc
index 2a0f5c7e4..ed0e48e01 100644
--- a/backends/aiger/xaiger.cc
+++ b/backends/aiger/xaiger.cc
@@ -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;
diff --git a/passes/techmap/abc9_ops.cc b/passes/techmap/abc9_ops.cc
index cc22fd474..9cc58c99d 100644
--- a/passes/techmap/abc9_ops.cc
+++ b/passes/techmap/abc9_ops.cc
@@ -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"))
diff --git a/tests/techmap/abc9.ys b/tests/techmap/abc9.ys
index 46b6f08d2..d5a63e1cb 100644
--- a/tests/techmap/abc9.ys
+++ b/tests/techmap/abc9.ys
@@ -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_