From 436c96e2fba0d7f73adb0ebb2b69821fe1dfc58c Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 30 Dec 2019 23:29:14 -0800 Subject: Revert "Get rid of holes_mode" This reverts commit 7997e2a90fd37886241b7eb657408177ef7f6fa7. --- backends/aiger/xaiger.cc | 105 +++++++++++++++++++++++++++++++---------------- 1 file changed, 70 insertions(+), 35 deletions(-) (limited to 'backends/aiger') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 277017dfd..e7d767721 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -78,7 +78,7 @@ struct XAigerWriter Module *module; SigMap sigmap; - pool input_bits, output_bits; + pool input_bits, output_bits, external_bits; dict not_map, alias_map; dict> and_map; vector ci_bits, co_bits; @@ -136,7 +136,7 @@ struct XAigerWriter return a; } - XAigerWriter(Module *module) : module(module), sigmap(module) + XAigerWriter(Module *module, bool holes_mode=false) : module(module), sigmap(module) { pool undriven_bits; pool unused_bits; @@ -166,7 +166,9 @@ struct XAigerWriter if (bit.wire == nullptr) { if (wire->port_output) { aig_map[wirebit] = (bit == State::S1) ? 1 : 0; - output_bits.insert(wirebit); + if (holes_mode) + output_bits.insert(wirebit); + //external_bits.insert(wirebit); } continue; } @@ -180,7 +182,10 @@ struct XAigerWriter if (wire->port_output) { if (bit != wirebit) alias_map[wirebit] = bit; - output_bits.insert(wirebit); + if (holes_mode) + output_bits.insert(wirebit); + else + external_bits.insert(wirebit); } if (wire->port_input && wire->port_output) @@ -202,9 +207,11 @@ struct XAigerWriter unused_bits.erase(A); undriven_bits.erase(Y); not_map[Y] = A; - toposort.node(cell->name); - bit_users[A].insert(cell->name); - bit_drivers[Y].insert(cell->name); + if (!holes_mode) { + toposort.node(cell->name); + bit_users[A].insert(cell->name); + bit_drivers[Y].insert(cell->name); + } continue; } @@ -217,13 +224,17 @@ struct XAigerWriter unused_bits.erase(B); undriven_bits.erase(Y); and_map[Y] = make_pair(A, B); - toposort.node(cell->name); - bit_users[A].insert(cell->name); - bit_users[B].insert(cell->name); - bit_drivers[Y].insert(cell->name); + if (!holes_mode) { + toposort.node(cell->name); + bit_users[A].insert(cell->name); + bit_users[B].insert(cell->name); + bit_drivers[Y].insert(cell->name); + } continue; } + log_assert(!holes_mode); + if (cell->type == "$__ABC9_FF_") { SigBit D = sigmap(cell->getPort("\\D").as_bit()); @@ -287,7 +298,7 @@ struct XAigerWriter if (!is_input && !is_output) log_error("Connection '%s' on cell '%s' (type '%s') not recognised!\n", log_id(c.first), log_id(cell), log_id(cell->type)); - if (is_input) + if (is_input) { for (auto b : c.second) { Wire *w = b.wire; if (!w) continue; @@ -295,19 +306,13 @@ struct XAigerWriter SigBit I = sigmap(b); if (I != b) alias_map[b] = I; - output_bits.insert(b); + if (holes_mode) + output_bits.insert(b); + else + external_bits.insert(b); } } - - if (is_output) - for (auto b : c.second) { - Wire *w = b.wire; - if (!w) continue; - SigBit O = sigmap(b); - if (O != b) - alias_map[O] = b; - input_bits.insert(O); - } + } } //log_warning("Unsupported cell type: %s (%s)\n", log_id(cell->type), log_id(cell)); @@ -490,27 +495,57 @@ struct XAigerWriter // TODO: Free memory from toposort, bit_drivers, bit_users } + if (!holes_mode) + for (auto cell : module->cells()) + if (!module->selected(cell)) + for (auto &conn : cell->connections()) + if (cell->input(conn.first)) + for (auto wirebit : conn.second) + if (sigmap(wirebit).wire) + external_bits.insert(wirebit); + + // For all bits consumed outside of the selected cells, + // but driven from a selected cell, then add it as + // a primary output + for (auto wirebit : external_bits) { + SigBit bit = sigmap(wirebit); + if (!bit.wire) + continue; + if (!undriven_bits.count(bit)) { + if (bit != wirebit) + alias_map[wirebit] = bit; + output_bits.insert(wirebit); + } + } + for (auto bit : input_bits) - undriven_bits.erase(bit); + undriven_bits.erase(sigmap(bit)); for (auto bit : output_bits) unused_bits.erase(sigmap(bit)); for (auto bit : unused_bits) undriven_bits.erase(bit); - if (!undriven_bits.empty()) { + + // Make all undriven bits a primary input + if (!holes_mode) for (auto bit : undriven_bits) { - log_warning("Treating undriven bit %s.%s like $anyseq.\n", log_id(module), log_signal(bit)); input_bits.insert(bit); + undriven_bits.erase(bit); } - log_warning("Treating a total of %d undriven bits in %s like $anyseq.\n", GetSize(undriven_bits), log_id(module)); + + if (holes_mode) { + struct sort_by_port_id { + bool operator()(const RTLIL::SigBit& a, const RTLIL::SigBit& b) const { + return a.wire->port_id < b.wire->port_id; + } + }; + input_bits.sort(sort_by_port_id()); + output_bits.sort(sort_by_port_id()); + } + else { + input_bits.sort(); + output_bits.sort(); } - struct sort_by_port_id { - bool operator()(const RTLIL::SigBit& a, const RTLIL::SigBit& b) const { - return a.wire->port_id < b.wire->port_id; - } - }; - input_bits.sort(sort_by_port_id()); - output_bits.sort(sort_by_port_id()); not_map.sort(); and_map.sort(); @@ -842,7 +877,7 @@ struct XAigerWriter Pass::call(holes_design, "opt -purge"); std::stringstream a_buffer; - XAigerWriter writer(holes_module); + XAigerWriter writer(holes_module, true /* holes_mode */); writer.write_aiger(a_buffer, false /*ascii_mode*/); delete holes_design; -- cgit v1.2.3 From 3798fa3bead6b944ebdee892c9bf5231559766f1 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 31 Dec 2019 09:59:17 -0800 Subject: Retry getting rid of write_xaiger's holes_mode --- backends/aiger/xaiger.cc | 122 ++++++++++++++++------------------------------- 1 file changed, 41 insertions(+), 81 deletions(-) (limited to 'backends/aiger') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index e7d767721..40cf72548 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -136,11 +136,10 @@ struct XAigerWriter return a; } - XAigerWriter(Module *module, bool holes_mode=false) : module(module), sigmap(module) + XAigerWriter(Module *module) : module(module), sigmap(module) { pool undriven_bits; pool unused_bits; - pool inout_bits; // promote public wires for (auto wire : module->wires()) @@ -157,7 +156,12 @@ struct XAigerWriter if (wire->get_bool_attribute(ID::keep)) sigmap.add(wire); - for (auto wire : module->wires()) + // First, collect all the ports in port_id order + // since module->wires() could be sorted + // alphabetically + for (auto port : module->ports) { + auto wire = module->wire(port); + log_assert(wire); for (int i = 0; i < GetSize(wire); i++) { SigBit wirebit(wire, i); @@ -166,30 +170,32 @@ struct XAigerWriter if (bit.wire == nullptr) { if (wire->port_output) { aig_map[wirebit] = (bit == State::S1) ? 1 : 0; - if (holes_mode) - output_bits.insert(wirebit); - //external_bits.insert(wirebit); + output_bits.insert(wirebit); } continue; } - undriven_bits.insert(bit); - unused_bits.insert(bit); - if (wire->port_input) input_bits.insert(bit); if (wire->port_output) { if (bit != wirebit) alias_map[wirebit] = bit; - if (holes_mode) - output_bits.insert(wirebit); - else - external_bits.insert(wirebit); + output_bits.insert(wirebit); } + } + } + + for (auto wire : module->wires()) + for (int i = 0; i < GetSize(wire); i++) + { + SigBit wirebit(wire, i); + SigBit bit = sigmap(wirebit); - if (wire->port_input && wire->port_output) - inout_bits.insert(wirebit); + if (bit.wire) { + undriven_bits.insert(bit); + unused_bits.insert(bit); + } } // TODO: Speed up toposort -- ultimately we care about @@ -207,11 +213,9 @@ struct XAigerWriter unused_bits.erase(A); undriven_bits.erase(Y); not_map[Y] = A; - if (!holes_mode) { - toposort.node(cell->name); - bit_users[A].insert(cell->name); - bit_drivers[Y].insert(cell->name); - } + toposort.node(cell->name); + bit_users[A].insert(cell->name); + bit_drivers[Y].insert(cell->name); continue; } @@ -224,17 +228,13 @@ struct XAigerWriter unused_bits.erase(B); undriven_bits.erase(Y); and_map[Y] = make_pair(A, B); - if (!holes_mode) { - toposort.node(cell->name); - bit_users[A].insert(cell->name); - bit_users[B].insert(cell->name); - bit_drivers[Y].insert(cell->name); - } + toposort.node(cell->name); + bit_users[A].insert(cell->name); + bit_users[B].insert(cell->name); + bit_drivers[Y].insert(cell->name); continue; } - log_assert(!holes_mode); - if (cell->type == "$__ABC9_FF_") { SigBit D = sigmap(cell->getPort("\\D").as_bit()); @@ -298,7 +298,7 @@ struct XAigerWriter if (!is_input && !is_output) log_error("Connection '%s' on cell '%s' (type '%s') not recognised!\n", log_id(c.first), log_id(cell), log_id(cell->type)); - if (is_input) { + if (is_input) for (auto b : c.second) { Wire *w = b.wire; if (!w) continue; @@ -306,13 +306,9 @@ struct XAigerWriter SigBit I = sigmap(b); if (I != b) alias_map[b] = I; - if (holes_mode) - output_bits.insert(b); - else - external_bits.insert(b); + output_bits.insert(b); } } - } } //log_warning("Unsupported cell type: %s (%s)\n", log_id(cell->type), log_id(cell)); @@ -495,29 +491,6 @@ struct XAigerWriter // TODO: Free memory from toposort, bit_drivers, bit_users } - if (!holes_mode) - for (auto cell : module->cells()) - if (!module->selected(cell)) - for (auto &conn : cell->connections()) - if (cell->input(conn.first)) - for (auto wirebit : conn.second) - if (sigmap(wirebit).wire) - external_bits.insert(wirebit); - - // For all bits consumed outside of the selected cells, - // but driven from a selected cell, then add it as - // a primary output - for (auto wirebit : external_bits) { - SigBit bit = sigmap(wirebit); - if (!bit.wire) - continue; - if (!undriven_bits.count(bit)) { - if (bit != wirebit) - alias_map[wirebit] = bit; - output_bits.insert(wirebit); - } - } - for (auto bit : input_bits) undriven_bits.erase(sigmap(bit)); for (auto bit : output_bits) @@ -526,33 +499,18 @@ struct XAigerWriter undriven_bits.erase(bit); // Make all undriven bits a primary input - if (!holes_mode) - for (auto bit : undriven_bits) { - input_bits.insert(bit); - undriven_bits.erase(bit); - } - - if (holes_mode) { - struct sort_by_port_id { - bool operator()(const RTLIL::SigBit& a, const RTLIL::SigBit& b) const { - return a.wire->port_id < b.wire->port_id; - } - }; - input_bits.sort(sort_by_port_id()); - output_bits.sort(sort_by_port_id()); - } - else { - input_bits.sort(); - output_bits.sort(); + for (auto bit : undriven_bits) { + input_bits.insert(bit); + undriven_bits.erase(bit); } - not_map.sort(); - and_map.sort(); - aig_map[State::S0] = 0; aig_map[State::S1] = 1; - for (auto bit : input_bits) { + // pool<> iterates in LIFO order... + for (int i = input_bits.size()-1; i >= 0; i--) { + const auto &bit = *input_bits.element(i); + log_dump(bit, i); aig_m++, aig_i++; log_assert(!aig_map.count(bit)); aig_map[bit] = 2*aig_m; @@ -578,7 +536,9 @@ struct XAigerWriter aig_outputs.push_back(bit2aig(bit)); } - for (auto bit : output_bits) { + // pool<> iterates in LIFO order... + for (int i = output_bits.size()-1; i >= 0; i--) { + const auto &bit = *output_bits.element(i); ordered_outputs[bit] = aig_o++; aig_outputs.push_back(bit2aig(bit)); } @@ -877,7 +837,7 @@ struct XAigerWriter Pass::call(holes_design, "opt -purge"); std::stringstream a_buffer; - XAigerWriter writer(holes_module, true /* holes_mode */); + XAigerWriter writer(holes_module); writer.write_aiger(a_buffer, false /*ascii_mode*/); delete holes_design; -- cgit v1.2.3 From 134e70e8e7798dd1e841b8deac2165c9f334ba09 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 31 Dec 2019 10:21:11 -0800 Subject: write_xaiger: be more precise with ff_bits, remove ff_aig_map --- backends/aiger/xaiger.cc | 40 +++++++++++++++++++--------------------- 1 file changed, 19 insertions(+), 21 deletions(-) (limited to 'backends/aiger') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 40cf72548..650ceba7a 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -82,7 +82,7 @@ struct XAigerWriter dict not_map, alias_map; dict> and_map; vector ci_bits, co_bits; - dict> ff_bits; + dict> ff_bits; dict arrival_times; vector> aig_gates; @@ -242,7 +242,7 @@ struct XAigerWriter unused_bits.erase(D); undriven_bits.erase(Q); alias_map[Q] = D; - auto r = ff_bits.insert(std::make_pair(D, std::make_pair(0, 2))); + auto r = ff_bits.insert(std::make_pair(D, std::make_tuple(Q, 0, 2))); log_assert(r.second); continue; } @@ -348,25 +348,26 @@ struct XAigerWriter auto it = cell->attributes.find(ID(abc9_mergeability)); log_assert(it != cell->attributes.end()); - rhs.first = it->second.as_int(); + std::get<1>(rhs) = it->second.as_int(); cell->attributes.erase(it); it = cell->attributes.find(ID(abc9_init)); log_assert(it != cell->attributes.end()); log_assert(GetSize(it->second) == 1); if (it->second[0] == State::S1) - rhs.second = 1; + std::get<2>(rhs) = 1; else if (it->second[0] == State::S0) - rhs.second = 0; + std::get<2>(rhs) = 0; else { log_assert(it->second[0] == State::Sx); - rhs.second = 0; + std::get<2>(rhs) = 0; } cell->attributes.erase(it); + const SigBit &q = std::get<0>(rhs); auto arrival = r.first->second.second; if (arrival) - arrival_times[d] = arrival; + arrival_times[q] = arrival; } for (auto &it : bit_users) @@ -510,25 +511,22 @@ struct XAigerWriter // pool<> iterates in LIFO order... for (int i = input_bits.size()-1; i >= 0; i--) { const auto &bit = *input_bits.element(i); - log_dump(bit, i); aig_m++, aig_i++; log_assert(!aig_map.count(bit)); aig_map[bit] = 2*aig_m; } for (const auto &i : ff_bits) { - const SigBit &bit = i.first; + const SigBit &q = std::get<0>(i.second); aig_m++, aig_i++; - log_assert(!aig_map.count(bit)); - aig_map[bit] = 2*aig_m; + log_assert(!aig_map.count(q)); + aig_map[q] = 2*aig_m; } - dict ff_aig_map; for (auto &bit : ci_bits) { aig_m++, aig_i++; - auto r = aig_map.insert(std::make_pair(bit, 2*aig_m)); - if (!r.second) - ff_aig_map[bit] = 2*aig_m; + log_assert(!aig_map.count(bit)); + aig_map[bit] = 2*aig_m; } for (auto bit : co_bits) { @@ -544,9 +542,9 @@ struct XAigerWriter } for (auto &i : ff_bits) { - const SigBit &bit = i.first; + const SigBit &d = i.first; aig_o++; - aig_outputs.push_back(ff_aig_map.at(bit)); + aig_outputs.push_back(aig_map.at(d)); } } @@ -752,13 +750,13 @@ struct XAigerWriter write_s_buffer(ff_bits.size()); for (const auto &i : ff_bits) { - const SigBit &bit = i.first; - int mergeability = i.second.first; + const SigBit &q = std::get<0>(i.second); + int mergeability = std::get<1>(i.second); log_assert(mergeability > 0); write_r_buffer(mergeability); - int init = i.second.second; + int init = std::get<2>(i.second); write_s_buffer(init); - write_i_buffer(arrival_times.at(bit, 0)); + write_i_buffer(arrival_times.at(q, 0)); //write_o_buffer(0); } -- cgit v1.2.3 From cac7f5d82eb2760bcc248d15315b0d8460c92cb0 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 31 Dec 2019 16:12:40 -0800 Subject: Do not re-order carry chain ports, just precompute iteration order --- backends/aiger/xaiger.cc | 54 ++++++++++++++++++++++++++++-------------------- 1 file changed, 32 insertions(+), 22 deletions(-) (limited to 'backends/aiger') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 650ceba7a..3e40562b7 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -93,6 +93,7 @@ struct XAigerWriter dict ordered_outputs; vector box_list; + dict> box_ports; int mkgate(int a0, int a1) { @@ -404,12 +405,34 @@ struct XAigerWriter bool blackbox = box_module->get_blackbox_attribute(true /* ignore_wb */); + auto r = box_ports.insert(cell->type); + if (r.second) { + // Make carry in the last PI, and carry out the last PO + // since ABC requires it this way + IdString carry_in, carry_out; + for (const auto &port_name : box_module->ports) { + auto w = box_module->wire(port_name); + log_assert(w); + if (w->get_bool_attribute("\\abc9_carry")) { + if (w->port_input) + carry_in = port_name; + if (w->port_output) + carry_out = port_name; + } + else + r.first->second.push_back(port_name); + } + if (carry_in != IdString()) { + log_assert(carry_out != IdString()); + r.first->second.push_back(carry_in); + r.first->second.push_back(carry_out); + } + } + // Fully pad all unused input connections of this box cell with S0 // Fully pad all undriven output connections of this box cell with anonymous wires - // NB: Assume box_module->ports are sorted alphabetically - // (as RTLIL::Module::fixup_ports() would do) - for (const auto &port_name : box_module->ports) { - RTLIL::Wire* w = box_module->wire(port_name); + for (auto port_name : r.first->second) { + auto w = box_module->wire(port_name); log_assert(w); auto it = cell->connections_.find(port_name); if (w->port_input) { @@ -424,7 +447,7 @@ struct XAigerWriter cell->setPort(port_name, rhs); } - for (auto b : rhs.bits()) { + for (auto b : rhs) { SigBit I = sigmap(b); if (b == RTLIL::Sx) b = State::S0; @@ -455,11 +478,10 @@ struct XAigerWriter } for (const auto &b : rhs.bits()) { - ci_bits.emplace_back(b); SigBit O = sigmap(b); if (O != b) alias_map[O] = b; - input_bits.erase(O); + ci_bits.emplace_back(b); undriven_bits.erase(O); } } @@ -653,33 +675,21 @@ struct XAigerWriter if (box_module->has_processes()) Pass::call_on_module(module->design, box_module, "proc"); - int box_inputs = 0, box_outputs = 0; auto r = cell_cache.insert(std::make_pair(derived_name, nullptr)); Cell *holes_cell = r.first->second; if (r.second && box_module->get_bool_attribute("\\whitebox")) { holes_cell = holes_module->addCell(cell->name, cell->type); holes_cell->parameters = cell->parameters; r.first->second = holes_cell; - - // Since Module::derive() will create a new module, there - // is a chance that the ports will be alphabetically ordered - // again, which is a problem when carry-chains are involved. - // Inherit the port ordering from the original module here... - // (and set the port_id below, when iterating through those) - log_assert(GetSize(box_module->ports) == GetSize(orig_box_module->ports)); - box_module->ports = orig_box_module->ports; } - // NB: Assume box_module->ports are sorted alphabetically - // (as RTLIL::Module::fixup_ports() would do) - int box_port_id = 1; - for (const auto &port_name : box_module->ports) { + int box_inputs = 0, box_outputs = 0; + for (auto port_name : box_ports.at(cell->type)) { RTLIL::Wire *w = box_module->wire(port_name); log_assert(w); - if (r.second) - w->port_id = box_port_id++; RTLIL::Wire *holes_wire; RTLIL::SigSpec port_sig; + if (w->port_input) for (int i = 0; i < GetSize(w); i++) { box_inputs++; -- cgit v1.2.3 From 96db05aaefd970c819ba1f75b7246c5958527b8b Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 31 Dec 2019 17:06:03 -0800 Subject: parse_xaiger to not take box_lookup --- backends/aiger/xaiger.cc | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) (limited to 'backends/aiger') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 3e40562b7..be900f0e7 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -414,14 +414,25 @@ struct XAigerWriter auto w = box_module->wire(port_name); log_assert(w); if (w->get_bool_attribute("\\abc9_carry")) { - if (w->port_input) + if (w->port_input) { + if (carry_in != IdString()) + log_error("Module '%s' contains more than one 'abc9_carry' input port.\n", log_id(box_module)); carry_in = port_name; - if (w->port_output) + } + if (w->port_output) { + if (carry_out != IdString()) + log_error("Module '%s' contains more than one 'abc9_carry' output port.\n", log_id(box_module)); carry_out = port_name; + } } else r.first->second.push_back(port_name); } + + if (carry_in != IdString() && carry_out == IdString()) + log_error("Module '%s' contains an 'abc9_carry' input port but no output port.\n", log_id(box_module)); + if (carry_in == IdString() && carry_out != IdString()) + log_error("Module '%s' contains an 'abc9_carry' output port but no input port.\n", log_id(box_module)); if (carry_in != IdString()) { log_assert(carry_out != IdString()); r.first->second.push_back(carry_in); -- cgit v1.2.3 From ac808c5e2aa0fbcfb5b56160131fcc61ba13da05 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 31 Dec 2019 22:54:56 -0800 Subject: attributes.count() -> get_bool_attribute() --- backends/aiger/xaiger.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'backends/aiger') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index be900f0e7..77659b4d8 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -284,7 +284,7 @@ struct XAigerWriter toposort.node(cell->name); - if (inst_module->attributes.count("\\abc9_flop")) + if (inst_module->get_bool_attribute("\\abc9_flop")) flop_boxes.push_back(cell); continue; } -- cgit v1.2.3 From 11577b46fcfa6c9aef4c3ed83e508ab07bc722c7 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 1 Jan 2020 08:38:23 -0800 Subject: Get rid of (* abc9_keep *) in write_xaiger too --- backends/aiger/xaiger.cc | 33 ++++++++++++++++++--------------- 1 file changed, 18 insertions(+), 15 deletions(-) (limited to 'backends/aiger') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 77659b4d8..9c6152dff 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -250,7 +250,12 @@ struct XAigerWriter RTLIL::Module* inst_module = module->design->module(cell->type); if (inst_module) { - bool abc9_box = inst_module->attributes.count("\\abc9_box_id") && !cell->get_bool_attribute("\\abc9_keep"); + bool abc9_box = inst_module->attributes.count("\\abc9_box_id"); + bool abc9_flop = inst_module->get_bool_attribute("\\abc9_flop"); + // The lack of an abc9_mergeability attribute indicates that + // we do want to keep this flop, so do not treat it as a box + if (abc9_flop && !cell->attributes.count("\\abc9_mergeability")) + abc9_box = false; for (const auto &conn : cell->connections()) { auto port_wire = inst_module->wire(conn.first); @@ -279,15 +284,15 @@ struct XAigerWriter } } - if (abc9_box) { - abc9_box_seen = true; + if (abc9_box) { + abc9_box_seen = true; - toposort.node(cell->name); + toposort.node(cell->name); - if (inst_module->get_bool_attribute("\\abc9_flop")) - flop_boxes.push_back(cell); - continue; - } + if (abc9_flop) + flop_boxes.push_back(cell); + continue; + } } bool cell_known = inst_module || cell->known(); @@ -322,11 +327,12 @@ struct XAigerWriter SigBit d; if (r.second) { for (const auto &conn : cell->connections()) { - const SigSpec &rhs = conn.second; - if (!rhs.is_bit()) + if (!conn.second.is_bit()) continue; - if (!ff_bits.count(rhs)) + d = conn.second; + if (!ff_bits.count(d)) continue; + r.first->second.first = conn.first; Module *inst_module = module->design->module(cell->type); Wire *wire = inst_module->wire(conn.first); @@ -337,7 +343,6 @@ struct XAigerWriter log_error("Attribute 'abc9_arrival' on port '%s' of module '%s' is not an integer.\n", log_id(wire), log_id(cell->type)); r.first->second.second = jt->second.as_int(); } - d = rhs; log_assert(d == sigmap(d)); break; } @@ -399,8 +404,7 @@ struct XAigerWriter log_assert(cell); RTLIL::Module* box_module = module->design->module(cell->type); - if (!box_module || !box_module->attributes.count("\\abc9_box_id") - || cell->get_bool_attribute("\\abc9_keep")) + if (!box_module || !box_module->attributes.count("\\abc9_box_id")) continue; bool blackbox = box_module->get_blackbox_attribute(true /* ignore_wb */); @@ -434,7 +438,6 @@ struct XAigerWriter if (carry_in == IdString() && carry_out != IdString()) log_error("Module '%s' contains an 'abc9_carry' output port but no input port.\n", log_id(box_module)); if (carry_in != IdString()) { - log_assert(carry_out != IdString()); r.first->second.push_back(carry_in); r.first->second.push_back(carry_out); } -- cgit v1.2.3 From 8e507bd80785db9fa6723eada4214a5a06516cae Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 2 Jan 2020 12:36:54 -0800 Subject: abc9 -keepff -> -dff; refactor dff operations --- backends/aiger/xaiger.cc | 136 ++++++++++++++++------------------------------- 1 file changed, 47 insertions(+), 89 deletions(-) (limited to 'backends/aiger') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 9c6152dff..053f9d835 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -82,7 +82,7 @@ struct XAigerWriter dict not_map, alias_map; dict> and_map; vector ci_bits, co_bits; - dict> ff_bits; + dict ff_bits; dict arrival_times; vector> aig_gates; @@ -204,7 +204,6 @@ struct XAigerWriter dict> bit_drivers, bit_users; TopoSort toposort; bool abc9_box_seen = false; - std::vector flop_boxes; for (auto cell : module->selected_cells()) { if (cell->type == "$_NOT_") @@ -236,14 +235,17 @@ struct XAigerWriter continue; } - if (cell->type == "$__ABC9_FF_") + 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 = ff_bits.insert(std::make_pair(D, std::make_tuple(Q, 0, 2))); + auto r YS_ATTRIBUTE(unused) = ff_bits.insert(std::make_pair(D, cell)); log_assert(r.second); continue; } @@ -252,14 +254,25 @@ struct XAigerWriter if (inst_module) { bool abc9_box = inst_module->attributes.count("\\abc9_box_id"); bool abc9_flop = inst_module->get_bool_attribute("\\abc9_flop"); - // The lack of an abc9_mergeability attribute indicates that - // we do want to keep this flop, so do not treat it as a box - if (abc9_flop && !cell->attributes.count("\\abc9_mergeability")) + if (abc9_box && cell->get_bool_attribute("\\abc9_keep")) abc9_box = false; for (const auto &conn : cell->connections()) { auto port_wire = inst_module->wire(conn.first); + if (abc9_box) { + // Ignore inout for the sake of topographical ordering + if (port_wire->port_input && !port_wire->port_output) + for (auto bit : sigmap(conn.second)) + bit_users[bit].insert(cell->name); + if (port_wire->port_output) + for (auto bit : sigmap(conn.second)) + bit_drivers[bit].insert(cell->name); + + if (!abc9_flop) + continue; + } + if (port_wire->port_output) { int arrival = 0; auto it = port_wire->attributes.find("\\abc9_arrival"); @@ -272,25 +285,11 @@ struct XAigerWriter for (auto bit : sigmap(conn.second)) arrival_times[bit] = arrival; } - - if (abc9_box) { - // Ignore inout for the sake of topographical ordering - if (port_wire->port_input && !port_wire->port_output) - for (auto bit : sigmap(conn.second)) - bit_users[bit].insert(cell->name); - if (port_wire->port_output) - for (auto bit : sigmap(conn.second)) - bit_drivers[bit].insert(cell->name); - } } if (abc9_box) { abc9_box_seen = true; - toposort.node(cell->name); - - if (abc9_flop) - flop_boxes.push_back(cell); continue; } } @@ -321,61 +320,6 @@ struct XAigerWriter } if (abc9_box_seen) { - dict> flop_q; - for (auto cell : flop_boxes) { - auto r = flop_q.insert(std::make_pair(cell->type, std::make_pair(IdString(), 0))); - SigBit d; - if (r.second) { - for (const auto &conn : cell->connections()) { - if (!conn.second.is_bit()) - continue; - d = conn.second; - if (!ff_bits.count(d)) - continue; - - r.first->second.first = conn.first; - Module *inst_module = module->design->module(cell->type); - Wire *wire = inst_module->wire(conn.first); - log_assert(wire); - auto jt = wire->attributes.find("\\abc9_arrival"); - if (jt != wire->attributes.end()) { - if (jt->second.flags != 0) - log_error("Attribute 'abc9_arrival' on port '%s' of module '%s' is not an integer.\n", log_id(wire), log_id(cell->type)); - r.first->second.second = jt->second.as_int(); - } - log_assert(d == sigmap(d)); - break; - } - } - else - d = cell->getPort(r.first->second.first); - - auto &rhs = ff_bits.at(d); - - auto it = cell->attributes.find(ID(abc9_mergeability)); - log_assert(it != cell->attributes.end()); - std::get<1>(rhs) = it->second.as_int(); - cell->attributes.erase(it); - - it = cell->attributes.find(ID(abc9_init)); - log_assert(it != cell->attributes.end()); - log_assert(GetSize(it->second) == 1); - if (it->second[0] == State::S1) - std::get<2>(rhs) = 1; - else if (it->second[0] == State::S0) - std::get<2>(rhs) = 0; - else { - log_assert(it->second[0] == State::Sx); - std::get<2>(rhs) = 0; - } - cell->attributes.erase(it); - - const SigBit &q = std::get<0>(rhs); - auto arrival = r.first->second.second; - if (arrival) - arrival_times[q] = arrival; - } - for (auto &it : bit_users) if (bit_drivers.count(it.first)) for (auto driver_cell : bit_drivers.at(it.first)) @@ -501,11 +445,11 @@ struct XAigerWriter } } - // Connect .$abc9_currQ (inserted by abc9_map.v) as an input to the flop box + // Connect .abc9_ff.Q (inserted by abc9_map.v) as the last input to the flop box if (box_module->get_bool_attribute("\\abc9_flop")) { - SigSpec rhs = module->wire(stringf("%s.$abc9_currQ", cell->name.c_str())); + SigSpec rhs = module->wire(stringf("%s.abc9_ff.Q", cell->name.c_str())); if (rhs.empty()) - log_error("'%s.$abc9_currQ' is not a wire present in module '%s'.\n", log_id(cell), log_id(module)); + log_error("'%s.abc9_ff.Q' is not a wire present in module '%s'.\n", log_id(cell), log_id(module)); for (auto b : rhs) { SigBit I = sigmap(b); @@ -553,7 +497,8 @@ struct XAigerWriter } for (const auto &i : ff_bits) { - const SigBit &q = std::get<0>(i.second); + const Cell *cell = i.second; + const SigBit &q = sigmap(cell->getPort("\\Q")); aig_m++, aig_i++; log_assert(!aig_map.count(q)); aig_map[q] = 2*aig_m; @@ -742,7 +687,7 @@ struct XAigerWriter } // For flops only, create an extra 1-bit input that drives a new wire - // called ".$abc9_currQ" that is used below + // called ".abc9_ff.Q" that is used below if (box_module->get_bool_attribute("\\abc9_flop")) { log_assert(holes_cell); @@ -754,7 +699,8 @@ struct XAigerWriter holes_wire->port_id = port_id++; holes_module->ports.push_back(holes_wire->name); } - Wire *w = holes_module->addWire(stringf("%s.$abc9_currQ", cell->name.c_str())); + Wire *w = holes_module->addWire(stringf("%s.abc9_ff.Q", cell->name.c_str())); + log_assert(w); holes_module->connect(w, holes_wire); } @@ -774,13 +720,25 @@ struct XAigerWriter write_s_buffer(ff_bits.size()); for (const auto &i : ff_bits) { - const SigBit &q = std::get<0>(i.second); - int mergeability = std::get<1>(i.second); + const SigBit &d = i.first; + const Cell *cell = i.second; + + int mergeability = cell->attributes.at(ID(abc9_mergeability)).as_int(); log_assert(mergeability > 0); write_r_buffer(mergeability); - int init = std::get<2>(i.second); - write_s_buffer(init); - write_i_buffer(arrival_times.at(q, 0)); + + Const init = cell->attributes.at(ID(abc9_init)); + log_assert(GetSize(init) == 1); + if (init == State::S1) + write_s_buffer(1); + else if (init == State::S0) + write_s_buffer(0); + else { + log_assert(init == State::Sx); + write_s_buffer(0); + } + + write_i_buffer(arrival_times.at(d, 0)); //write_o_buffer(0); } @@ -833,9 +791,9 @@ struct XAigerWriter log_assert(pos != std::string::npos); IdString driver = Q.wire->name.substr(0, pos); // And drive the signal that was previously driven by "DFF.Q" (typically - // used to implement clock-enable functionality) with the ".$abc9_currQ" + // used to implement clock-enable functionality) with the ".abc9_ff.Q" // wire (which itself is driven an input port) we inserted above - Wire *currQ = holes_module->wire(stringf("%s.$abc9_currQ", driver.c_str())); + Wire *currQ = holes_module->wire(stringf("%s.abc9_ff.Q", driver.c_str())); log_assert(currQ); holes_module->connect(Q, currQ); continue; -- cgit v1.2.3