Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

abc9: Experiment with importing structural choices #4283

Draft
wants to merge 7 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions frontends/aiger/aigerparse.cc
Original file line number Diff line number Diff line change
Expand Up @@ -505,6 +505,26 @@ void AigerReader::parse_xaiger()
boxes.emplace_back(cell);
}
}
else if (c == 'q') {
f.ignore(sizeof(uint32_t));
uint32_t pairNum = parse_xaiger_literal(f);

std::vector<Cell *> nodes;
nodes.resize(1000); // TODO: where can we get a reliable bound? `I` doesn't work
for (unsigned i = 0; i < pairNum; i++) {
uint32_t reprID = parse_xaiger_literal(f);
uint32_t siblingID = parse_xaiger_literal(f);
log_assert(nodes.size() > reprID && reprID > siblingID);
Cell *node = nodes[siblingID];
if (!node) {
node = nodes[siblingID] = module->addCell(stringf("$equivclass%u", siblingID), ID($__choice));
node->set_bool_attribute(ID::keep, true);
node->setPort(ID::A, module->wire(stringf("$aiger%d$%d", aiger_autoidx, siblingID)));
}
node->connections_.at(ID::A).append(module->wire(stringf("$aiger%d$%d", aiger_autoidx, reprID)));
nodes[reprID] = node;
}
}
else if (c == 'a' || c == 'i' || c == 'o' || c == 's') {
uint32_t dataSize = parse_xaiger_literal(f);
f.ignore(dataSize);
Expand Down
35 changes: 24 additions & 11 deletions passes/techmap/abc9.cc
Original file line number Diff line number Diff line change
Expand Up @@ -151,10 +151,14 @@ struct Abc9Pass : public ScriptPass
log(" generate netlist using luts. Use the specified costs for luts with 1,\n");
log(" 2, 3, .. inputs.\n");
log("\n");
log(" -lutlib\n");
log(" generate netlist using luts. Use the modules that are loaded into the\n");
log(" current design and have the (* abc9_lut *) attribute for the library of\n");
log(" the available lut primitives.\n");
log("\n");
log(" -maxlut <width>\n");
log(" when auto-generating the lut library, discard all luts equal to or\n");
log(" greater than this size (applicable when neither -lut nor -luts is\n");
log(" specified).\n");
log(" when sourcing the lut library from the current design (option -lutlib),\n");
log(" discard all lut primitives with greater than the specified width.\n");
log("\n");
log(" -dff\n");
log(" also pass $_DFF_[NP]_ cells through to ABC. modules with many clock\n");
Expand Down Expand Up @@ -186,7 +190,7 @@ struct Abc9Pass : public ScriptPass

std::stringstream exe_cmd;
bool dff_mode, cleanup;
bool lut_mode;
bool lutlib_mode, lut_mode;
int maxlut;
std::string box_file;

Expand All @@ -196,6 +200,7 @@ struct Abc9Pass : public ScriptPass
exe_cmd << "abc9_exe";
dff_mode = false;
cleanup = true;
lutlib_mode = false;
lut_mode = false;
maxlut = 0;
box_file = "";
Expand Down Expand Up @@ -232,6 +237,10 @@ struct Abc9Pass : public ScriptPass
exe_cmd << " " << arg;
continue;
}
if (arg == "-lutlib") {
lutlib_mode = true;
continue;
}
if (arg == "-dff") {
dff_mode = true;
exe_cmd << " " << arg;
Expand Down Expand Up @@ -261,8 +270,11 @@ struct Abc9Pass : public ScriptPass
}
extra_args(args, argidx, design);

if (maxlut && lut_mode)
log_cmd_error("abc9 '-maxlut' option only applicable without '-lut' nor '-luts'.\n");
if (maxlut && !lutlib_mode)
log_cmd_error("abc9 '-maxlut' option only applicable in conjunction with '-lutlib'.\n");

if (lut_mode && lutlib_mode)
log_cmd_error("abc9 '-lutlib' option is in conflict with '-lut' or '-luts'.\n");

log_assert(design);
if (design->selected_modules().empty()) {
Expand Down Expand Up @@ -359,7 +371,7 @@ struct Abc9Pass : public ScriptPass
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)
else if (lutlib_mode)
run(stringf("abc9_ops -prep_lut %d", maxlut));
if (help_mode)
run("abc9_ops -prep_box", "(skip if -box)");
Expand All @@ -386,7 +398,7 @@ struct Abc9Pass : public ScriptPass
run(" write_xaiger -map <abc-temp-dir>/input.sym [-dff] <abc-temp-dir>/input.xaig");
run(" abc9_exe [options] -cwd <abc-temp-dir> -lut [<abc-temp-dir>/input.lut] -box [<abc-temp-dir>/input.box]");
run(" read_aiger -xaiger -wideports -module_name <module-name>$abc9 -map <abc-temp-dir>/input.sym <abc-temp-dir>/output.aig");
run(" abc9_ops -reintegrate [-dff]");
run(" abc9_ops -reintegrate [-dff] [-lut]");
}
else {
auto selected_modules = active_design->selected_modules();
Expand All @@ -412,7 +424,7 @@ struct Abc9Pass : public ScriptPass
tempdir_name += proc_program_prefix() + "yosys-abc-XXXXXX";
tempdir_name = make_temp_dir(tempdir_name);

if (!lut_mode)
if (lutlib_mode)
run_nocheck(stringf("abc9_ops -write_lut %s/input.lut", tempdir_name.c_str()));
if (box_file.empty())
run_nocheck(stringf("abc9_ops -write_box %s/input.box", tempdir_name.c_str()));
Expand All @@ -429,15 +441,16 @@ struct Abc9Pass : public ScriptPass
if (num_outputs) {
std::string abc9_exe_cmd;
abc9_exe_cmd += stringf("%s -cwd %s", exe_cmd.str().c_str(), tempdir_name.c_str());
if (!lut_mode)
if (lutlib_mode)
abc9_exe_cmd += stringf(" -lut %s/input.lut", tempdir_name.c_str());
if (box_file.empty())
abc9_exe_cmd += stringf(" -box %s/input.box", tempdir_name.c_str());
else
abc9_exe_cmd += stringf(" -box %s", box_file.c_str());
run_nocheck(abc9_exe_cmd);
run_nocheck(stringf("read_aiger -xaiger -wideports -module_name %s$abc9 -map %s/input.sym %s/output.aig", log_id(mod), tempdir_name.c_str(), tempdir_name.c_str()));
run_nocheck(stringf("abc9_ops -reintegrate %s", dff_mode ? "-dff" : ""));
run_nocheck(stringf("abc9_ops -reintegrate%s%s", dff_mode ? " -dff" : "",
(lutlib_mode || lut_mode) ? " -lut" : ""));
}
else
log("Don't call ABC as there is nothing to map.\n");
Expand Down
7 changes: 3 additions & 4 deletions passes/techmap/abc9_exe.cc
Original file line number Diff line number Diff line change
Expand Up @@ -176,8 +176,6 @@ void abc9_module(RTLIL::Design *design, std::string script_file, std::string exe
abc9_script += stringf("read_lut %s/lutdefs.txt; ", tempdir_name.c_str());
else if (!lut_file.empty())
abc9_script += stringf("read_lut \"%s\"; ", lut_file.c_str());
else
log_abort();

log_assert(!box_file.empty());
abc9_script += stringf("read_box \"%s\"; ", box_file.c_str());
Expand All @@ -197,8 +195,9 @@ void abc9_module(RTLIL::Design *design, std::string script_file, std::string exe
} else if (!lut_costs.empty() || !lut_file.empty()) {
abc9_script += fast_mode ? RTLIL::constpad.at("abc9.script.default.fast").substr(1,std::string::npos)
: RTLIL::constpad.at("abc9.script.default").substr(1,std::string::npos);
} else
log_abort();
} else {
log_error("Without a target library, a script needs to be provided.\n");
}

for (size_t pos = abc9_script.find("{D}"); pos != std::string::npos; pos = abc9_script.find("{D}", pos))
abc9_script = abc9_script.substr(0, pos) + delay_target + abc9_script.substr(pos+3);
Expand Down
72 changes: 70 additions & 2 deletions passes/techmap/abc9_ops.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1137,7 +1137,7 @@ void write_box(RTLIL::Module *module, const std::string &dst) {
ofs.close();
}

void reintegrate(RTLIL::Module *module, bool dff_mode)
void reintegrate(RTLIL::Module *module, bool dff_mode, bool lut_mode)
{
auto design = module->design;
log_assert(design);
Expand Down Expand Up @@ -1248,6 +1248,69 @@ void reintegrate(RTLIL::Module *module, bool dff_mode)
// TODO: Speed up toposort -- we care about NOT ordering only
toposort.node(mapped_cell->name);

if (mapped_cell->type == ID($__choice)) {
RTLIL::SigSpec a = mapped_cell->getPort(ID::A);

for (auto bit : a)
bit_users[bit].insert(mapped_cell->name);

Cell *cell = module->addCell(remap_name(mapped_cell->name.c_str()),
mapped_cell->type);

for (auto &bit : a)
if (bit.wire) {
bit.wire = module->wires_.at(remap_name(bit.wire->name));
bit2sinks[bit].push_back(cell);
}

cell->set_bool_attribute(ID::keep, true);
cell->setPort(ID::A, a);
cell_stats[cell->type]++;
continue;
}

if (!lut_mode && mapped_cell->type.in(ID($_AND_), ID($_NOT_))) {
RTLIL::SigBit a_bit, b_bit, y_bit;
RTLIL::SigBit a_bit_remap, b_bit_remap, y_bit_remap;

a_bit = a_bit_remap = mapped_cell->getPort(ID::A);
y_bit = y_bit_remap = mapped_cell->getPort(ID::Y);
if (mapped_cell->type == ID($_AND_))
b_bit = b_bit_remap = mapped_cell->getPort(ID::B);

for (auto bit : {&a_bit_remap, &b_bit_remap, &y_bit_remap})
if (bit->wire)
bit->wire = module->wires_.at(remap_name(bit->wire->name));

// Catch the case of a complemented constant zero
if (mapped_cell->type == ID($_NOT_) && !a_bit.wire) {
module->connect(y_bit_remap, State::S1);
continue;
}

bit_users[a_bit].insert(mapped_cell->name);
if (mapped_cell->type == ID($_AND_))
bit_users[b_bit].insert(mapped_cell->name);

// Ignore inouts for topo ordering
if (y_bit.wire && !(y_bit.wire->port_input && y_bit.wire->port_output))
bit_drivers[y_bit].insert(mapped_cell->name);

Cell *cell = module->addCell(remap_name(stringf("$aig%s", mapped_cell->name.c_str())),
mapped_cell->type);
for (auto bit : {a_bit_remap, b_bit_remap})
if (bit.wire)
bit2sinks[bit].push_back(cell);

cell->setPort(ID::A, a_bit_remap);
cell->setPort(ID::Y, y_bit_remap);
if (cell->type == ID($_AND_))
cell->setPort(ID::B, b_bit_remap);

cell_stats[cell->type]++;
continue;
}

if (mapped_cell->type == ID($_NOT_)) {
RTLIL::SigBit a_bit = mapped_cell->getPort(ID::A);
RTLIL::SigBit y_bit = mapped_cell->getPort(ID::Y);
Expand Down Expand Up @@ -1667,6 +1730,7 @@ struct Abc9OpsPass : public Pass {
bool prep_box_mode = false;
bool reintegrate_mode = false;
bool dff_mode = false;
bool lut_mode = false;
std::string write_lut_dst;
int maxlut = 0;
std::string write_box_dst;
Expand Down Expand Up @@ -1752,6 +1816,10 @@ struct Abc9OpsPass : public Pass {
dff_mode = true;
continue;
}
if (arg == "-lut") {
lut_mode = true;
continue;
}
break;
}
extra_args(args, argidx, design);
Expand Down Expand Up @@ -1799,7 +1867,7 @@ struct Abc9OpsPass : public Pass {
if (prep_xaiger_mode)
prep_xaiger(mod, dff_mode);
if (reintegrate_mode)
reintegrate(mod, dff_mode);
reintegrate(mod, dff_mode, lut_mode);
}
}
} Abc9OpsPass;
Expand Down
2 changes: 1 addition & 1 deletion techlibs/ecp5/synth_ecp5.cc
Original file line number Diff line number Diff line change
Expand Up @@ -388,7 +388,7 @@ struct SynthEcp5Pass : public ScriptPass
abc9_opts += " -maxlut 4";
if (dff)
abc9_opts += " -dff";
run("abc9" + abc9_opts);
run("abc9 -lutlib" + abc9_opts);
} else {
std::string abc_args = " -dress";
if (nowidelut)
Expand Down
4 changes: 2 additions & 2 deletions techlibs/gowin/synth_gowin.cc
Original file line number Diff line number Diff line change
Expand Up @@ -278,12 +278,12 @@ struct SynthGowinPass : public ScriptPass
{
if (nowidelut && abc9) {
run("read_verilog -icells -lib -specify +/abc9_model.v");
run("abc9 -maxlut 4 -W 500");
run("abc9 -lutlib -maxlut 4 -W 500");
} else if (nowidelut && !abc9) {
run("abc -lut 4");
} else if (!nowidelut && abc9) {
run("read_verilog -icells -lib -specify +/abc9_model.v");
run("abc9 -maxlut 8 -W 500");
run("abc9 -lutlib -maxlut 8 -W 500");
} else if (!nowidelut && !abc9) {
run("abc -lut 4:8");
}
Expand Down
2 changes: 1 addition & 1 deletion techlibs/ice40/synth_ice40.cc
Original file line number Diff line number Diff line change
Expand Up @@ -424,7 +424,7 @@ struct SynthIce40Pass : public ScriptPass
}
if (dff)
abc9_opts += " -dff";
run("abc9 " + abc9_opts);
run("abc9 -lutlib" + abc9_opts);
}
else
run(stringf("abc -dress -lut 4 %s", dff ? "-dff" : ""), "(skip if -noabc)");
Expand Down
2 changes: 1 addition & 1 deletion techlibs/intel_alm/synth_intel_alm.cc
Original file line number Diff line number Diff line change
Expand Up @@ -289,7 +289,7 @@ struct SynthIntelALMPass : public ScriptPass {

if (check_label("map_luts")) {
run("techmap -map +/intel_alm/common/abc9_map.v");
run(stringf("abc9 %s -maxlut 6 -W 600", help_mode ? "[-dff]" : dff ? "-dff" : ""));
run(stringf("abc9 -lutlib %s -maxlut 6 -W 600", help_mode ? "[-dff]" : dff ? "-dff" : ""));
run("techmap -map +/intel_alm/common/abc9_unmap.v");
run("techmap -map +/intel_alm/common/alm_map.v");
run("opt -fast");
Expand Down
2 changes: 1 addition & 1 deletion techlibs/lattice/synth_lattice.cc
Original file line number Diff line number Diff line change
Expand Up @@ -454,7 +454,7 @@ struct SynthLatticePass : public ScriptPass
abc9_opts += " -maxlut 4";
if (dff)
abc9_opts += " -dff";
run("abc9" + abc9_opts);
run("abc9 -lutlib" + abc9_opts);
} else {
std::string abc_args = " -dress";
if (nowidelut)
Expand Down
2 changes: 1 addition & 1 deletion techlibs/nexus/synth_nexus.cc
Original file line number Diff line number Diff line change
Expand Up @@ -366,7 +366,7 @@ struct SynthNexusPass : public ScriptPass
abc9_opts += " -maxlut 4";
if (dff)
abc9_opts += " -dff";
run("abc9" + abc9_opts);
run("abc9 -lutlib" + abc9_opts);
} else {
std::string abc_args = " -dress";
if (nowidelut)
Expand Down
4 changes: 2 additions & 2 deletions techlibs/quicklogic/synth_quicklogic.cc
Original file line number Diff line number Diff line change
Expand Up @@ -304,7 +304,7 @@ struct SynthQuickLogicPass : public ScriptPass {
if (abc9) {
run("read_verilog -lib -specify -icells " + lib_path + family + "/abc9_model.v");
run("techmap -map " + lib_path + family + "/abc9_map.v");
run("abc9 -maxlut 4 -dff");
run("abc9 -lutlib -maxlut 4 -dff");
run("techmap -map " + lib_path + family + "/abc9_unmap.v");
} else {
run("abc -luts 1,2,2,4 -dress");
Expand All @@ -314,7 +314,7 @@ struct SynthQuickLogicPass : public ScriptPass {

if (check_label("map_luts", "(for qlf_k6n10f)") && (help_mode || family == "qlf_k6n10f")) {
if (abc9) {
run("abc9 -maxlut 6");
run("abc9 -lutlib -maxlut 6");
} else {
run("abc -lut 6 -dress");
}
Expand Down
2 changes: 1 addition & 1 deletion techlibs/xilinx/synth_xilinx.cc
Original file line number Diff line number Diff line change
Expand Up @@ -650,7 +650,7 @@ struct SynthXilinxPass : public ScriptPass
abc9_opts += stringf(" -maxlut %d", lut_size);
if (dff)
abc9_opts += " -dff";
run("abc9" + abc9_opts);
run("abc9 -lutlib" + abc9_opts);
}
else {
std::string abc_opts;
Expand Down
2 changes: 1 addition & 1 deletion tests/arch/xilinx/bug3670.ys
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
read_verilog bug3670.v
read_verilog -lib -specify +/xilinx/cells_sim.v
abc9
abc9 -lutlib
2 changes: 1 addition & 1 deletion tests/arch/xilinx/dsp_abc9.ys
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ DSP48E1 #(.AREG(1)) u2(.A(A), .B(B), .PCIN(casc), .P(P));
endmodule
EOT
synth_xilinx -run :prepare
abc9
abc9 -lutlib
clean
check
logger -expect-no-warnings
2 changes: 1 addition & 1 deletion tests/various/abc9.ys
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ module abc9_test037(input [1:0] i, output o);
LUT2 #(.mask(4'b0)) lut (.i(i), .o(o));
endmodule
EOT
abc9
abc9 -lutlib


design -reset
Expand Down
Loading