diff options
author | Eddie Hung <eddie@fpgeh.com> | 2020-01-02 15:57:35 -0800 |
---|---|---|
committer | Eddie Hung <eddie@fpgeh.com> | 2020-01-02 15:57:35 -0800 |
commit | c28bea0382c07ea63709c33be4318d5012b9d281 (patch) | |
tree | e1d88f4b3cbf6df4df7d4035bd1b65290ae3d6cc /backends | |
parent | 5f970863023881caaa3a64120a0f767386d35d62 (diff) | |
parent | 6e866030c286d70f6ccff805e58b1fdd9a1a322b (diff) | |
download | yosys-c28bea0382c07ea63709c33be4318d5012b9d281.tar.gz yosys-c28bea0382c07ea63709c33be4318d5012b9d281.tar.bz2 yosys-c28bea0382c07ea63709c33be4318d5012b9d281.zip |
Merge remote-tracking branch 'origin/xaig_dff' into eddie/abc9_refactor
Diffstat (limited to 'backends')
-rw-r--r-- | backends/aiger/xaiger.cc | 273 |
1 files changed, 128 insertions, 145 deletions
diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 830c86787..42a26cbf9 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -78,11 +78,11 @@ struct XAigerWriter Module *module; SigMap sigmap; - pool<SigBit> input_bits, output_bits; + pool<SigBit> input_bits, output_bits, external_bits; dict<SigBit, SigBit> not_map, alias_map; dict<SigBit, pair<SigBit, SigBit>> and_map; vector<SigBit> ci_bits, co_bits; - dict<SigBit, std::pair<int,int>> ff_bits; + dict<SigBit, Cell*> ff_bits; dict<SigBit, float> arrival_times; vector<pair<int, int>> aig_gates; @@ -93,6 +93,7 @@ struct XAigerWriter dict<SigBit, int> ordered_outputs; vector<Cell*> box_list; + dict<IdString, std::vector<IdString>> box_ports; int mkgate(int a0, int a1) { @@ -140,7 +141,6 @@ struct XAigerWriter { pool<SigBit> undriven_bits; pool<SigBit> unused_bits; - pool<SigBit> inout_bits; // promote public wires for (auto wire : module->wires()) @@ -157,7 +157,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); @@ -171,9 +176,6 @@ struct XAigerWriter continue; } - undriven_bits.insert(bit); - unused_bits.insert(bit); - if (wire->port_input) input_bits.insert(bit); @@ -182,9 +184,19 @@ struct XAigerWriter alias_map[wirebit] = bit; 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 @@ -192,7 +204,6 @@ struct XAigerWriter dict<SigBit, pool<IdString>> bit_drivers, bit_users; TopoSort<IdString, RTLIL::sort_by_id_str> toposort; bool abc9_box_seen = false; - std::vector<Cell*> flop_boxes; for (auto cell : module->selected_cells()) { if (cell->type == "$_NOT_") @@ -224,25 +235,44 @@ 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_pair(0, 2))); + auto r YS_ATTRIBUTE(unused) = ff_bits.insert(std::make_pair(D, cell)); log_assert(r.second); continue; } 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"); + 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"); @@ -255,27 +285,13 @@ 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 (inst_module->attributes.count("\\abc9_flop")) - flop_boxes.push_back(cell); - continue; - } + if (abc9_box) { + abc9_box_seen = true; + toposort.node(cell->name); + continue; + } } bool cell_known = inst_module || cell->known(); @@ -298,76 +314,12 @@ struct XAigerWriter output_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)); } if (abc9_box_seen) { - dict<IdString, std::pair<IdString,int>> 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()) { - const SigSpec &rhs = conn.second; - if (!rhs.is_bit()) - continue; - if (!ff_bits.count(rhs)) - 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(); - } - d = rhs; - 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()); - rhs.first = 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; - else if (it->second[0] == State::S0) - rhs.second = 0; - else { - log_assert(it->second[0] == State::Sx); - rhs.second = 0; - } - cell->attributes.erase(it); - - auto arrival = r.first->second.second; - if (arrival) - arrival_times[d] = arrival; - } - for (auto &it : bit_users) if (bit_drivers.count(it.first)) for (auto driver_cell : bit_drivers.at(it.first)) @@ -396,18 +348,49 @@ 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 */); + 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) { + 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 (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()) { + 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) { @@ -422,7 +405,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; @@ -453,21 +436,20 @@ 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); } } } - // Connect <cell>.$abc9_currQ (inserted by abc9_map.v) as an input to the flop box + // Connect <cell>.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); @@ -496,46 +478,36 @@ struct XAigerWriter unused_bits.erase(sigmap(bit)); for (auto bit : unused_bits) undriven_bits.erase(bit); - if (!undriven_bits.empty()) { - 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); - } - log_warning("Treating a total of %d undriven bits in %s like $anyseq.\n", GetSize(undriven_bits), log_id(module)); - } - 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(); + // Make all undriven bits a primary input + for (auto bit : undriven_bits) { + input_bits.insert(bit); + undriven_bits.erase(bit); + } 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); 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 Cell *cell = i.second; + const SigBit &q = sigmap(cell->getPort("\\Q")); 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<SigBit, int> 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) { @@ -543,15 +515,17 @@ 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)); } 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)); } } @@ -653,9 +627,7 @@ struct XAigerWriter RTLIL::Module* box_module = module->design->module(derived_name); int box_inputs = 0, box_outputs = 0; - // NB: Assume box_module->ports are sorted alphabetically - // (as RTLIL::Module::fixup_ports() would do) - for (const auto &port_name : box_module->ports) { + for (auto port_name : box_ports.at(cell->type)) { RTLIL::Wire *w = box_module->wire(port_name); log_assert(w); if (w->port_input) @@ -664,8 +636,7 @@ struct XAigerWriter box_outputs += GetSize(w); } - // For flops only, create an extra 1-bit input that drives a new wire - // called "<cell>.$abc9_currQ" that is used below + // For flops only, create an extra 1-bit input for abc9_ff.Q if (box_module->get_bool_attribute("\\abc9_flop")) box_inputs++; @@ -685,13 +656,25 @@ 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 &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 = i.second.second; - write_s_buffer(init); - write_i_buffer(arrival_times.at(bit, 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); } |