mirror of
https://github.com/YosysHQ/yosys
synced 2025-06-06 22:23:23 +00:00
Preserve topo ordering from -prep_holes to write_xaiger
This commit is contained in:
parent
bb70915fb8
commit
559f3379e8
3 changed files with 80 additions and 165 deletions
|
@ -78,7 +78,7 @@ struct XAigerWriter
|
||||||
Module *module;
|
Module *module;
|
||||||
SigMap sigmap;
|
SigMap sigmap;
|
||||||
|
|
||||||
pool<SigBit> input_bits, output_bits, external_bits;
|
pool<SigBit> input_bits, output_bits;
|
||||||
dict<SigBit, SigBit> not_map, alias_map;
|
dict<SigBit, SigBit> not_map, alias_map;
|
||||||
dict<SigBit, pair<SigBit, SigBit>> and_map;
|
dict<SigBit, pair<SigBit, SigBit>> and_map;
|
||||||
vector<SigBit> ci_bits, co_bits;
|
vector<SigBit> ci_bits, co_bits;
|
||||||
|
@ -199,12 +199,6 @@ struct XAigerWriter
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Speed up toposort -- ultimately we care about
|
|
||||||
// box ordering, but not individual AIG cells
|
|
||||||
dict<SigBit, pool<IdString>> bit_drivers, bit_users;
|
|
||||||
TopoSort<IdString, RTLIL::sort_by_id_str> toposort;
|
|
||||||
bool abc9_box_seen = false;
|
|
||||||
|
|
||||||
for (auto cell : module->selected_cells()) {
|
for (auto cell : module->selected_cells()) {
|
||||||
if (cell->type == "$_NOT_")
|
if (cell->type == "$_NOT_")
|
||||||
{
|
{
|
||||||
|
@ -213,9 +207,6 @@ struct XAigerWriter
|
||||||
unused_bits.erase(A);
|
unused_bits.erase(A);
|
||||||
undriven_bits.erase(Y);
|
undriven_bits.erase(Y);
|
||||||
not_map[Y] = A;
|
not_map[Y] = A;
|
||||||
toposort.node(cell->name);
|
|
||||||
bit_users[A].insert(cell->name);
|
|
||||||
bit_drivers[Y].insert(cell->name);
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -228,10 +219,6 @@ struct XAigerWriter
|
||||||
unused_bits.erase(B);
|
unused_bits.erase(B);
|
||||||
undriven_bits.erase(Y);
|
undriven_bits.erase(Y);
|
||||||
and_map[Y] = make_pair(A, B);
|
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);
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -257,22 +244,17 @@ struct XAigerWriter
|
||||||
if (abc9_box && cell->get_bool_attribute("\\abc9_keep"))
|
if (abc9_box && cell->get_bool_attribute("\\abc9_keep"))
|
||||||
abc9_box = false;
|
abc9_box = false;
|
||||||
|
|
||||||
|
if (abc9_box) {
|
||||||
|
int abc9_box_order = cell->attributes.at("\\abc9_box_order").as_int();
|
||||||
|
if (GetSize(box_list) <= abc9_box_order)
|
||||||
|
box_list.resize(abc9_box_order+1);
|
||||||
|
box_list[abc9_box_order] = cell;
|
||||||
|
if (!abc9_flop)
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
for (const auto &conn : cell->connections()) {
|
for (const auto &conn : cell->connections()) {
|
||||||
auto port_wire = inst_module->wire(conn.first);
|
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) {
|
if (port_wire->port_output) {
|
||||||
int arrival = 0;
|
int arrival = 0;
|
||||||
auto it = port_wire->attributes.find("\\abc9_arrival");
|
auto it = port_wire->attributes.find("\\abc9_arrival");
|
||||||
|
@ -286,12 +268,6 @@ struct XAigerWriter
|
||||||
arrival_times[bit] = arrival;
|
arrival_times[bit] = arrival;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (abc9_box) {
|
|
||||||
abc9_box_seen = true;
|
|
||||||
toposort.node(cell->name);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool cell_known = inst_module || cell->known();
|
bool cell_known = inst_module || cell->known();
|
||||||
|
@ -319,138 +295,56 @@ struct XAigerWriter
|
||||||
//log_warning("Unsupported cell type: %s (%s)\n", log_id(cell->type), log_id(cell));
|
//log_warning("Unsupported cell type: %s (%s)\n", log_id(cell->type), log_id(cell));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (abc9_box_seen) {
|
for (auto cell : box_list) {
|
||||||
for (auto &it : bit_users)
|
log_assert(cell);
|
||||||
if (bit_drivers.count(it.first))
|
|
||||||
for (auto driver_cell : bit_drivers.at(it.first))
|
|
||||||
for (auto user_cell : it.second)
|
|
||||||
toposort.edge(driver_cell, user_cell);
|
|
||||||
|
|
||||||
#if 0
|
RTLIL::Module* box_module = module->design->module(cell->type);
|
||||||
toposort.analyze_loops = true;
|
log_assert(box_module);
|
||||||
#endif
|
log_assert(box_module->attributes.count("\\abc9_box_id"));
|
||||||
bool no_loops YS_ATTRIBUTE(unused) = toposort.sort();
|
|
||||||
#if 0
|
|
||||||
unsigned i = 0;
|
|
||||||
for (auto &it : toposort.loops) {
|
|
||||||
log(" loop %d\n", i++);
|
|
||||||
for (auto cell_name : it) {
|
|
||||||
auto cell = module->cell(cell_name);
|
|
||||||
log_assert(cell);
|
|
||||||
log("\t%s (%s @ %s)\n", log_id(cell), log_id(cell->type), cell->get_src_attribute().c_str());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
log_assert(no_loops);
|
|
||||||
|
|
||||||
for (auto cell_name : toposort.sorted) {
|
auto r = box_ports.insert(cell->type);
|
||||||
RTLIL::Cell *cell = module->cell(cell_name);
|
if (r.second) {
|
||||||
log_assert(cell);
|
// Make carry in the last PI, and carry out the last PO
|
||||||
|
// since ABC requires it this way
|
||||||
RTLIL::Module* box_module = module->design->module(cell->type);
|
IdString carry_in, carry_out;
|
||||||
if (!box_module || !box_module->attributes.count("\\abc9_box_id"))
|
for (const auto &port_name : box_module->ports) {
|
||||||
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
|
|
||||||
for (auto port_name : r.first->second) {
|
|
||||||
auto w = box_module->wire(port_name);
|
auto w = box_module->wire(port_name);
|
||||||
log_assert(w);
|
log_assert(w);
|
||||||
auto it = cell->connections_.find(port_name);
|
if (w->get_bool_attribute("\\abc9_carry")) {
|
||||||
if (w->port_input) {
|
if (w->port_input) {
|
||||||
RTLIL::SigSpec rhs;
|
if (carry_in != IdString())
|
||||||
if (it != cell->connections_.end()) {
|
log_error("Module '%s' contains more than one 'abc9_carry' input port.\n", log_id(box_module));
|
||||||
if (GetSize(it->second) < GetSize(w))
|
carry_in = port_name;
|
||||||
it->second.append(RTLIL::SigSpec(State::S0, GetSize(w)-GetSize(it->second)));
|
|
||||||
rhs = it->second;
|
|
||||||
}
|
}
|
||||||
else {
|
if (w->port_output) {
|
||||||
rhs = RTLIL::SigSpec(State::S0, GetSize(w));
|
if (carry_out != IdString())
|
||||||
cell->setPort(port_name, rhs);
|
log_error("Module '%s' contains more than one 'abc9_carry' output port.\n", log_id(box_module));
|
||||||
}
|
carry_out = port_name;
|
||||||
|
|
||||||
for (auto b : rhs) {
|
|
||||||
SigBit I = sigmap(b);
|
|
||||||
if (b == RTLIL::Sx)
|
|
||||||
b = State::S0;
|
|
||||||
else if (I != b) {
|
|
||||||
if (I == RTLIL::Sx)
|
|
||||||
alias_map[b] = State::S0;
|
|
||||||
else
|
|
||||||
alias_map[b] = I;
|
|
||||||
}
|
|
||||||
co_bits.emplace_back(b);
|
|
||||||
unused_bits.erase(I);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (w->port_output) {
|
|
||||||
RTLIL::SigSpec rhs;
|
|
||||||
auto it = cell->connections_.find(w->name);
|
|
||||||
if (it != cell->connections_.end()) {
|
|
||||||
if (GetSize(it->second) < GetSize(w))
|
|
||||||
it->second.append(module->addWire(NEW_ID, GetSize(w)-GetSize(it->second)));
|
|
||||||
rhs = it->second;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
Wire *wire = module->addWire(NEW_ID, GetSize(w));
|
|
||||||
if (blackbox)
|
|
||||||
wire->set_bool_attribute(ID(abc9_padding));
|
|
||||||
rhs = wire;
|
|
||||||
cell->setPort(port_name, rhs);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (const auto &b : rhs.bits()) {
|
|
||||||
SigBit O = sigmap(b);
|
|
||||||
if (O != b)
|
|
||||||
alias_map[O] = b;
|
|
||||||
ci_bits.emplace_back(b);
|
|
||||||
undriven_bits.erase(O);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
r.first->second.push_back(port_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Connect <cell>.abc9_ff.Q (inserted by abc9_map.v) as the last input to the flop box
|
if (carry_in != IdString() && carry_out == IdString())
|
||||||
if (box_module->get_bool_attribute("\\abc9_flop")) {
|
log_error("Module '%s' contains an 'abc9_carry' input port but no output port.\n", log_id(box_module));
|
||||||
SigSpec rhs = module->wire(stringf("%s.abc9_ff.Q", cell->name.c_str()));
|
if (carry_in == IdString() && carry_out != IdString())
|
||||||
if (rhs.empty())
|
log_error("Module '%s' contains an 'abc9_carry' output port but no input port.\n", log_id(box_module));
|
||||||
log_error("'%s.abc9_ff.Q' is not a wire present in module '%s'.\n", log_id(cell), log_id(module));
|
if (carry_in != IdString()) {
|
||||||
|
r.first->second.push_back(carry_in);
|
||||||
|
r.first->second.push_back(carry_out);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool blackbox = box_module->get_blackbox_attribute(true /* ignore_wb */);
|
||||||
|
|
||||||
|
// 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
|
||||||
|
for (auto port_name : r.first->second) {
|
||||||
|
auto w = box_module->wire(port_name);
|
||||||
|
log_assert(w);
|
||||||
|
auto rhs = cell->getPort(port_name);
|
||||||
|
if (w->port_input)
|
||||||
for (auto b : rhs) {
|
for (auto b : rhs) {
|
||||||
SigBit I = sigmap(b);
|
SigBit I = sigmap(b);
|
||||||
if (b == RTLIL::Sx)
|
if (b == RTLIL::Sx)
|
||||||
|
@ -464,12 +358,36 @@ struct XAigerWriter
|
||||||
co_bits.emplace_back(b);
|
co_bits.emplace_back(b);
|
||||||
unused_bits.erase(I);
|
unused_bits.erase(I);
|
||||||
}
|
}
|
||||||
}
|
if (w->port_output)
|
||||||
|
for (const auto &b : rhs.bits()) {
|
||||||
box_list.emplace_back(cell);
|
SigBit O = sigmap(b);
|
||||||
|
if (O != b)
|
||||||
|
alias_map[O] = b;
|
||||||
|
ci_bits.emplace_back(b);
|
||||||
|
undriven_bits.erase(O);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Free memory from toposort, bit_drivers, bit_users
|
// 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_ff.Q", cell->name.c_str()));
|
||||||
|
if (rhs.empty())
|
||||||
|
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);
|
||||||
|
if (b == RTLIL::Sx)
|
||||||
|
b = State::S0;
|
||||||
|
else if (I != b) {
|
||||||
|
if (I == RTLIL::Sx)
|
||||||
|
alias_map[b] = State::S0;
|
||||||
|
else
|
||||||
|
alias_map[b] = I;
|
||||||
|
}
|
||||||
|
co_bits.emplace_back(b);
|
||||||
|
unused_bits.erase(I);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto bit : input_bits)
|
for (auto bit : input_bits)
|
||||||
|
|
|
@ -187,17 +187,13 @@ struct Abc9Pass : public ScriptPass
|
||||||
{
|
{
|
||||||
run("scc -set_attr abc9_scc_id {}");
|
run("scc -set_attr abc9_scc_id {}");
|
||||||
run("abc9_ops -break_scc"/*" -prep_holes"*/);
|
run("abc9_ops -break_scc"/*" -prep_holes"*/);
|
||||||
// run("select -set abc9_holes A:abc9_holes");
|
|
||||||
// run("dump @abc9_holes");
|
|
||||||
// run("flatten -wb @abc9_holes");
|
// run("flatten -wb @abc9_holes");
|
||||||
// run("techmap @abc9_holes");
|
// run("techmap @abc9_holes");
|
||||||
run("aigmap");
|
run("aigmap");
|
||||||
|
run("abc9_ops -prep_holes");
|
||||||
if (dff_mode)
|
if (dff_mode)
|
||||||
run("abc9_ops -prep_dff");
|
run("abc9_ops -prep_dff");
|
||||||
// run("opt -purge @abc9_holes");
|
// run("opt -purge @abc9_holes");
|
||||||
|
|
||||||
run("abc9_ops -prep_holes");
|
|
||||||
|
|
||||||
run("select -set abc9_holes A:abc9_holes");
|
run("select -set abc9_holes A:abc9_holes");
|
||||||
run("wbflip @abc9_holes");
|
run("wbflip @abc9_holes");
|
||||||
|
|
||||||
|
|
|
@ -322,6 +322,7 @@ void prep_holes(RTLIL::Module *module)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cell->attributes["\\abc9_box_order"] = box_list.size();
|
||||||
box_list.emplace_back(cell);
|
box_list.emplace_back(cell);
|
||||||
}
|
}
|
||||||
log_assert(!box_list.empty());
|
log_assert(!box_list.empty());
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue