aboutsummaryrefslogtreecommitdiffstats
path: root/backends
diff options
context:
space:
mode:
authorEddie Hung <eddie@fpgeh.com>2020-01-02 15:57:35 -0800
committerEddie Hung <eddie@fpgeh.com>2020-01-02 15:57:35 -0800
commitc28bea0382c07ea63709c33be4318d5012b9d281 (patch)
treee1d88f4b3cbf6df4df7d4035bd1b65290ae3d6cc /backends
parent5f970863023881caaa3a64120a0f767386d35d62 (diff)
parent6e866030c286d70f6ccff805e58b1fdd9a1a322b (diff)
downloadyosys-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.cc273
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);
}