if (check_label("map")) {
if (help_mode)
- run("abc9_ops -prep_hier -prep_bypass [-prep_dff -dff]", "(option if -dff)");
+ run("abc9_ops -prep_hier [-dff]", "(option if -dff)");
else
- run(stringf("abc9_ops -prep_hier -prep_bypass %s", dff_mode ? "-prep_dff -dff" : ""));
+ run(stringf("abc9_ops -prep_hier %s", dff_mode ? "-dff" : ""));
+ run("scc -specify -set_attr abc9_scc_id {}");
+ if (help_mode)
+ run("abc9_ops -prep_bypass [-prep_dff]", "(option if -dff)");
+ else
+ run(stringf("abc9_ops -prep_bypass %s", dff_mode ? "-prep_dff" : ""));
if (dff_mode) {
run("design -copy-to $abc9_map @$abc9_flops", "(only if -dff)");
run("select -unset $abc9_flops", " (only if -dff)");
run("design -stash $abc9_map");
run("design -load $abc9");
run("design -delete $abc9");
+ // Insert bypass modules (and perform +/abc9_map.v transformations), except for those cells part of a SCC
if (help_mode)
run("techmap -wb -max_iter 1 -map %$abc9_map -map +/abc9_map.v [-D DFF]", "(option if -dff)");
else
- run(stringf("techmap -wb -max_iter 1 -map %%$abc9_map -map +/abc9_map.v %s", dff_mode ? "-D DFF" : ""));
+ run(stringf("techmap -wb -max_iter 1 -map %%$abc9_map -map +/abc9_map.v %s a:abc9_scc_id %%n", dff_mode ? "-D DFF" : ""));
run("design -delete $abc9_map");
}
if (check_label("pre")) {
run("read_verilog -icells -lib -specify +/abc9_model.v");
- run("scc -specify -set_attr abc9_scc_id {}");
if (help_mode)
- run("abc9_ops -mark_scc -prep_delays -prep_xaiger [-dff]", "(option for -dff)");
+ run("abc9_ops -break_scc -prep_delays -prep_xaiger [-dff]", "(option for -dff)");
else
- run("abc9_ops -mark_scc -prep_delays -prep_xaiger" + std::string(dff_mode ? " -dff" : ""));
+ run("abc9_ops -break_scc -prep_delays -prep_xaiger" + std::string(dff_mode ? " -dff" : ""));
if (help_mode)
run("abc9_ops -prep_lut <maxlut>", "(skip if -lut or -luts)");
else if (!lut_mode)
}
}
-void mark_scc(RTLIL::Module *module)
+void break_scc(RTLIL::Module *module)
{
// For every unique SCC found, (arbitrarily) find the first
- // cell in the component, and replace its output connections
- // with a new wire driven by the old connection but with a
- // special (* abc9_keep *) attribute set (which is used by
- // write_xaiger to break this wire into PI and POs)
+ // cell in the component, and interrupt all its output connections
+ // with the $__ABC9_SCC_BREAKER cell
+
+ // Do not break SCCs which have a cell instantiating an abc9_bypass-able
+ // module (but which wouldn't have been bypassed)
+ auto design = module->design;
+ pool<RTLIL::Cell*> scc_cells;
pool<RTLIL::Const> ids_seen;
for (auto cell : module->cells()) {
auto it = cell->attributes.find(ID::abc9_scc_id);
if (it == cell->attributes.end())
continue;
+ scc_cells.insert(cell);
+ auto inst_module = design->module(cell->type);
+ if (inst_module && inst_module->has_attribute(ID::abc9_bypass))
+ ids_seen.insert(it->second);
+ }
+
+ SigSpec I, O;
+ for (auto cell : scc_cells) {
+ auto it = cell->attributes.find(ID::abc9_scc_id);
+ log_assert(it != cell->attributes.end());
auto id = it->second;
auto r = ids_seen.insert(id);
cell->attributes.erase(it);
if (c.second.is_fully_const()) continue;
if (cell->output(c.first)) {
Wire *w = module->addWire(NEW_ID, GetSize(c.second));
- w->set_bool_attribute(ID::abc9_keep);
- module->connect(w, c.second);
+ I.append(w);
+ O.append(c.second);
c.second = w;
}
}
}
+
+ if (!I.empty())
+ {
+ auto cell = module->addCell(NEW_ID, ID($__ABC9_SCC_BREAKER));
+ log_assert(GetSize(I) == GetSize(O));
+ cell->setParam(ID::WIDTH, GetSize(I));
+ cell->setPort(ID::I, std::move(I));
+ cell->setPort(ID::O, std::move(O));
+ }
}
void prep_delays(RTLIL::Design *design, bool dff_mode)
bit_users[bit].insert(cell->name);
if (cell->output(conn.first) && !abc9_flop)
- for (const auto &chunk : conn.second.chunks())
- if (!chunk.wire->get_bool_attribute(ID::abc9_keep))
- for (auto b : sigmap(SigSpec(chunk)))
- bit_drivers[b].insert(cell->name);
+ for (auto bit : sigmap(conn.second))
+ bit_drivers[bit].insert(cell->name);
}
toposort.node(cell->name);
}
RTLIL::Wire *mapped_wire = mapped_mod->wire(port);
RTLIL::Wire *wire = module->wire(port);
log_assert(wire);
- wire->attributes.erase(ID::abc9_keep);
RTLIL::Wire *remap_wire = module->wire(remap_name(port));
RTLIL::SigSpec signal(wire, remap_wire->start_offset-wire->start_offset, GetSize(remap_wire));
log(" insert `$__ABC9_DELAY' blackbox cells into the design to account for\n");
log(" certain required times.\n");
log("\n");
- log(" -mark_scc\n");
+ log(" -break_scc\n");
log(" for an arbitrarily chosen cell in each unique SCC of each selected module\n");
- log(" (tagged with an (* abc9_scc_id = <int> *) attribute), temporarily mark all\n");
- log(" wires driven by this cell's outputs with a (* keep *) attribute in order\n");
- log(" to break the SCC. this temporary attribute will be removed on -reintegrate.\n");
+ log(" (tagged with an (* abc9_scc_id = <int> *) attribute) interrupt all wires\n");
+ log(" driven by this cell's outputs with a temporary $__ABC9_SCC_BREAKER cell\n");
+ log(" to break the SCC.\n");
log("\n");
log(" -prep_xaiger\n");
log(" prepare the design for XAIGER output. this includes computing the\n");
bool check_mode = false;
bool prep_delays_mode = false;
- bool mark_scc_mode = false;
+ bool break_scc_mode = false;
bool prep_hier_mode = false;
bool prep_bypass_mode = false;
bool prep_dff_mode = false, prep_dff_submod_mode = false, prep_dff_unmap_mode = false;
valid = true;
continue;
}
- if (arg == "-mark_scc") {
- mark_scc_mode = true;
+ if (arg == "-break_scc") {
+ break_scc_mode = true;
valid = true;
continue;
}
extra_args(args, argidx, design);
if (!valid)
- log_cmd_error("At least one of -check, -mark_scc, -prep_{delays,xaiger,dff[123],lut,box}, -write_{lut,box}, -reintegrate must be specified.\n");
+ log_cmd_error("At least one of -check, -break_scc, -prep_{delays,xaiger,dff[123],lut,box}, -write_{lut,box}, -reintegrate must be specified.\n");
if (dff_mode && !check_mode && !prep_hier_mode && !prep_delays_mode && !prep_xaiger_mode && !reintegrate_mode)
log_cmd_error("'-dff' option is only relevant for -prep_{hier,delay,xaiger} or -reintegrate.\n");
write_lut(mod, write_lut_dst);
if (!write_box_dst.empty())
write_box(mod, write_box_dst);
- if (mark_scc_mode)
- mark_scc(mod);
+ if (break_scc_mode)
+ break_scc(mod);
if (prep_xaiger_mode)
prep_xaiger(mod, dff_mode);
if (reintegrate_mode)