mirror of
https://github.com/YosysHQ/yosys
synced 2025-04-23 09:05:32 +00:00
Merge remote-tracking branch 'origin/eddie/abc9_refactor' into eddie/abc9_required
This commit is contained in:
commit
915e7dde73
22 changed files with 789 additions and 389 deletions
|
@ -56,7 +56,7 @@ int autoname_worker(Module *module)
|
|||
for (auto &conn : cell->connections()) {
|
||||
string suffix = stringf("_%s", log_id(conn.first));
|
||||
for (auto bit : conn.second)
|
||||
if (bit.wire != nullptr && bit.wire->name[0] == '$') {
|
||||
if (bit.wire != nullptr && bit.wire->name[0] == '$' && !bit.wire->port_id) {
|
||||
IdString new_name(cell->name.str() + suffix);
|
||||
int score = wire_score.at(bit.wire);
|
||||
if (cell->output(conn.first)) score = 0;
|
||||
|
|
|
@ -70,8 +70,10 @@ struct ScratchpadPass : public Pass {
|
|||
{
|
||||
if (args[argidx] == "-get" && argidx+1 < args.size()) {
|
||||
string identifier = args[++argidx];
|
||||
if (design->scratchpad.count(identifier)){
|
||||
if (design->scratchpad.count(identifier)) {
|
||||
log("%s\n", design->scratchpad_get_string(identifier).c_str());
|
||||
} else if (RTLIL::constpad.count(identifier)) {
|
||||
log("%s\n", RTLIL::constpad.at(identifier).c_str());
|
||||
} else {
|
||||
log("\"%s\" not set\n", identifier.c_str());
|
||||
}
|
||||
|
@ -79,6 +81,8 @@ struct ScratchpadPass : public Pass {
|
|||
}
|
||||
if (args[argidx] == "-set" && argidx+2 < args.size()) {
|
||||
string identifier = args[++argidx];
|
||||
if (RTLIL::constpad.count(identifier))
|
||||
log_error("scratchpad entry \"%s\" is a global constant\n", identifier.c_str());
|
||||
string value = args[++argidx];
|
||||
if (value.front() == '\"' && value.back() == '\"') value = value.substr(1, value.size() - 2);
|
||||
design->scratchpad_set_string(identifier, value);
|
||||
|
@ -92,8 +96,15 @@ struct ScratchpadPass : public Pass {
|
|||
if (args[argidx] == "-copy" && argidx+2 < args.size()) {
|
||||
string identifier_from = args[++argidx];
|
||||
string identifier_to = args[++argidx];
|
||||
if (design->scratchpad.count(identifier_from) == 0) log_error("\"%s\" not set\n", identifier_from.c_str());
|
||||
string value = design->scratchpad_get_string(identifier_from);
|
||||
string value;
|
||||
if (design->scratchpad.count(identifier_from))
|
||||
value = design->scratchpad_get_string(identifier_from);
|
||||
else if (RTLIL::constpad.count(identifier_from))
|
||||
value = RTLIL::constpad.at(identifier_from);
|
||||
else
|
||||
log_error("\"%s\" not set\n", identifier_from.c_str());
|
||||
if (RTLIL::constpad.count(identifier_to))
|
||||
log_error("scratchpad entry \"%s\" is a global constant\n", identifier_to.c_str());
|
||||
design->scratchpad_set_string(identifier_to, value);
|
||||
continue;
|
||||
}
|
||||
|
@ -102,10 +113,10 @@ struct ScratchpadPass : public Pass {
|
|||
string expected = args[++argidx];
|
||||
if (expected.front() == '\"' && expected.back() == '\"') expected = expected.substr(1, expected.size() - 2);
|
||||
if (design->scratchpad.count(identifier) == 0)
|
||||
log_error("Assertion failed: scratchpad entry '%s' is not defined\n", identifier.c_str());
|
||||
log_error("scratchpad entry '%s' is not defined\n", identifier.c_str());
|
||||
string value = design->scratchpad_get_string(identifier);
|
||||
if (value != expected) {
|
||||
log_error("Assertion failed: scratchpad entry '%s' is set to '%s' instead of the asserted '%s'\n",
|
||||
log_error("scratchpad entry '%s' is set to '%s' instead of the asserted '%s'\n",
|
||||
identifier.c_str(), value.c_str(), expected.c_str());
|
||||
}
|
||||
continue;
|
||||
|
@ -113,13 +124,13 @@ struct ScratchpadPass : public Pass {
|
|||
if (args[argidx] == "-assert-set" && argidx+1 < args.size()) {
|
||||
string identifier = args[++argidx];
|
||||
if (design->scratchpad.count(identifier) == 0)
|
||||
log_error("Assertion failed: scratchpad entry '%s' is not defined\n", identifier.c_str());
|
||||
log_error("scratchpad entry '%s' is not defined\n", identifier.c_str());
|
||||
continue;
|
||||
}
|
||||
if (args[argidx] == "-assert-unset" && argidx+1 < args.size()) {
|
||||
string identifier = args[++argidx];
|
||||
if (design->scratchpad.count(identifier) > 0)
|
||||
log_error("Assertion failed: scratchpad entry '%s' is defined\n", identifier.c_str());
|
||||
log_error("scratchpad entry '%s' is defined\n", identifier.c_str());
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
|
|
|
@ -18,18 +18,69 @@
|
|||
*
|
||||
*/
|
||||
|
||||
// [[CITE]] ABC
|
||||
// Berkeley Logic Synthesis and Verification Group, ABC: A System for Sequential Synthesis and Verification
|
||||
// http://www.eecs.berkeley.edu/~alanmi/abc/
|
||||
|
||||
#include "kernel/register.h"
|
||||
#include "kernel/celltypes.h"
|
||||
#include "kernel/rtlil.h"
|
||||
#include "kernel/log.h"
|
||||
|
||||
// abc9_exe.cc
|
||||
std::string fold_abc9_cmd(std::string str);
|
||||
|
||||
USING_YOSYS_NAMESPACE
|
||||
PRIVATE_NAMESPACE_BEGIN
|
||||
|
||||
struct Abc9Pass : public ScriptPass
|
||||
{
|
||||
Abc9Pass() : ScriptPass("abc9", "use ABC9 for technology mapping") { }
|
||||
|
||||
void on_register() YS_OVERRIDE
|
||||
{
|
||||
RTLIL::constpad["abc9.script.default"] = "+&scorr; &sweep; &dc2; &dch -f; &ps; &if {C} {W} {D} {R} -v; &mfs";
|
||||
RTLIL::constpad["abc9.script.default.area"] = "+&scorr; &sweep; &dc2; &dch -f; &ps; &if {C} {W} {D} {R} -a -v; &mfs";
|
||||
RTLIL::constpad["abc9.script.default.fast"] = "+&if {C} {W} {D} {R} -v";
|
||||
// Based on ABC's &flow
|
||||
RTLIL::constpad["abc9.script.flow"] = "+&scorr; &sweep;" \
|
||||
"&dch -C 500;" \
|
||||
/* Round 1 */ \
|
||||
/* Map 1 */ "&unmap; &if {C} {W} {D} {R} -v; &save; &load; &mfs;" \
|
||||
"&st; &dsdb;" \
|
||||
/* Map 2 */ "&unmap; &if {C} {W} {D} {R} -v; &save; &load; &mfs;" \
|
||||
"&st; &syn2 -m -R 10; &dsdb;" \
|
||||
"&blut -a -K 6;" \
|
||||
/* Map 3 */ "&unmap; &if {C} {W} {D} {R} -v; &save; &load; &mfs;" \
|
||||
/* Round 2 */ \
|
||||
"&st; &sopb;" \
|
||||
/* Map 1 */ "&unmap; &if {C} {W} {D} {R} -v; &save; &load; &mfs;" \
|
||||
"&st; &dsdb;" \
|
||||
/* Map 2 */ "&unmap; &if {C} {W} {D} {R} -v; &save; &load; &mfs;" \
|
||||
"&st; &syn2 -m -R 10; &dsdb;" \
|
||||
"&blut -a -K 6;" \
|
||||
/* Map 3 */ "&unmap; &if {C} {W} {D} {R} -v; &save; &load; &mfs;" \
|
||||
/* Round 3 */ \
|
||||
/* Map 1 */ "&unmap; &if {C} {W} {D} {R} -v; &save; &load; &mfs;" \
|
||||
"&st; &dsdb;" \
|
||||
/* Map 2 */ "&unmap; &if {C} {W} {D} {R} -v; &save; &load; &mfs;" \
|
||||
"&st; &syn2 -m -R 10; &dsdb;" \
|
||||
"&blut -a -K 6;" \
|
||||
/* Map 3 */ "&unmap; &if {C} {W} {D} {R} -v; &save; &load; &mfs;";
|
||||
// Based on ABC's &flow2
|
||||
RTLIL::constpad["abc9.script.flow2"] = "+&scorr; &sweep;" \
|
||||
/* Comm1 */ "&synch2 -K 6 -C 500; &if -m {C} {W} {D} {R} -v; &mfs "/*"-W 4 -M 500 -C 7000"*/"; &save;"\
|
||||
/* Comm2 */ "&dch -C 500; &if -m {C} {W} {D} {R} -v; &mfs "/*"-W 4 -M 500 -C 7000"*/"; &save;"\
|
||||
"&load; &st; &sopb -R 10 -C 4; " \
|
||||
/* Comm3 */ "&synch2 -K 6 -C 500; &if -m "/*"-E 5"*/" {C} {W} {D} {R} -v; &mfs "/*"-W 4 -M 500 -C 7000"*/"; &save;"\
|
||||
/* Comm2 */ "&dch -C 500; &if -m {C} {W} {D} {R} -v; &mfs "/*"-W 4 -M 500 -C 7000"*/"; &save; "\
|
||||
"&load";
|
||||
// Based on ABC's &flow3
|
||||
RTLIL::constpad["abc9.script.flow3"] = "+&scorr; &sweep;" \
|
||||
"&if {C} {W} {D}; &save; &st; &syn2; &if {C} {W} {D} {R} -v; &save; &load;"\
|
||||
"&st; &if {C} -g -K 6; &dch -f; &if {C} {W} {D} {R} -v; &save; &load;"\
|
||||
"&st; &if {C} -g -K 6; &synch2; &if {C} {W} {D} {R} -v; &save; &load;"\
|
||||
"&mfs";
|
||||
}
|
||||
void help() YS_OVERRIDE
|
||||
{
|
||||
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
|
||||
|
@ -40,6 +91,11 @@ struct Abc9Pass : public ScriptPass
|
|||
log("tool [1] for technology mapping of the current design to a target FPGA\n");
|
||||
log("architecture. Only fully-selected modules are supported.\n");
|
||||
log("\n");
|
||||
log(" -run <from_label>:<to_label>\n");
|
||||
log(" only run the commands between the labels (see below). an empty\n");
|
||||
log(" from label is synonymous to 'begin', and empty to label is\n");
|
||||
log(" synonymous to the end of the command list.\n");
|
||||
log("\n");
|
||||
log(" -exe <command>\n");
|
||||
#ifdef ABCEXTERNAL
|
||||
log(" use the specified command instead of \"" ABCEXTERNAL "\" to execute ABC.\n");
|
||||
|
@ -57,14 +113,12 @@ struct Abc9Pass : public ScriptPass
|
|||
log(" replaced with blanks before the string is passed to ABC.\n");
|
||||
log("\n");
|
||||
log(" if no -script parameter is given, the following scripts are used:\n");
|
||||
//FIXME:
|
||||
//log("%s\n", fold_abc9_cmd(ABC_COMMAND_LUT).c_str());
|
||||
log("%s\n", fold_abc9_cmd(RTLIL::constpad.at("abc9.script.default").substr(1,std::string::npos)).c_str());
|
||||
log("\n");
|
||||
log(" -fast\n");
|
||||
log(" use different default scripts that are slightly faster (at the cost\n");
|
||||
log(" of output quality):\n");
|
||||
//FIXME:
|
||||
//log("%s\n", fold_abc9_cmd(ABC_FAST_COMMAND_LUT).c_str());
|
||||
log("%s\n", fold_abc9_cmd(RTLIL::constpad.at("abc9.script.default.fast").substr(1,std::string::npos)).c_str());
|
||||
log("\n");
|
||||
log(" -D <picoseconds>\n");
|
||||
log(" set delay target. the string {D} in the default scripts above is\n");
|
||||
|
@ -104,7 +158,7 @@ struct Abc9Pass : public ScriptPass
|
|||
log(" command output is identical across runs.\n");
|
||||
log("\n");
|
||||
log(" -box <file>\n");
|
||||
log(" pass this file with box library to ABC. Use with -lut.\n");
|
||||
log(" pass this file with box library to ABC.\n");
|
||||
log("\n");
|
||||
log("Note that this is a logic optimization pass within Yosys that is calling ABC\n");
|
||||
log("internally. This is not going to \"run ABC on your design\". It will instead run\n");
|
||||
|
@ -141,6 +195,11 @@ struct Abc9Pass : public ScriptPass
|
|||
dff_mode = design->scratchpad_get_bool("abc9.dff", dff_mode);
|
||||
cleanup = !design->scratchpad_get_bool("abc9.nocleanup", !cleanup);
|
||||
|
||||
if (design->scratchpad_get_bool("abc9.debug")) {
|
||||
cleanup = false;
|
||||
exe_cmd << " -showtmp";
|
||||
}
|
||||
|
||||
size_t argidx;
|
||||
for (argidx = 1; argidx < args.size(); argidx++) {
|
||||
std::string arg = args[argidx];
|
||||
|
@ -152,13 +211,13 @@ struct Abc9Pass : public ScriptPass
|
|||
continue;
|
||||
}
|
||||
if (arg == "-fast" || /* arg == "-dff" || */
|
||||
/* arg == "-nocleanup" || */ arg == "-showtmp" ||
|
||||
arg == "-nomfs") {
|
||||
/* arg == "-nocleanup" || */ arg == "-showtmp") {
|
||||
exe_cmd << " " << arg;
|
||||
continue;
|
||||
}
|
||||
if (arg == "-dff") {
|
||||
dff_mode = true;
|
||||
exe_cmd << " " << arg;
|
||||
continue;
|
||||
}
|
||||
if (arg == "-nocleanup") {
|
||||
|
@ -169,6 +228,14 @@ struct Abc9Pass : public ScriptPass
|
|||
box_file = args[++argidx];
|
||||
continue;
|
||||
}
|
||||
if (arg == "-run" && argidx+1 < args.size()) {
|
||||
size_t pos = args[argidx+1].find(':');
|
||||
if (pos == std::string::npos)
|
||||
break;
|
||||
run_from = args[++argidx].substr(0, pos);
|
||||
run_to = args[argidx].substr(pos+1);
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
extra_args(args, argidx, design);
|
||||
|
@ -184,9 +251,9 @@ struct Abc9Pass : public ScriptPass
|
|||
run("abc9_ops -check");
|
||||
run("scc -set_attr abc9_scc_id {}");
|
||||
if (help_mode)
|
||||
run("abc9_ops -break_scc -prep_times -prep_holes [-dff]", "(option for -dff)");
|
||||
run("abc9_ops -mark_scc -prep_times -prep_xaiger [-dff]", "(option for -dff)");
|
||||
else
|
||||
run("abc9_ops -break_scc -prep_times -prep_holes" + std::string(dff_mode ? " -dff" : ""), "(option for -dff)");
|
||||
run("abc9_ops -mark_scc -prep_times -prep_xaiger" + std::string(dff_mode ? " -dff" : ""), "(option for -dff)");
|
||||
run("select -set abc9_holes A:abc9_holes");
|
||||
run("flatten -wb @abc9_holes");
|
||||
run("techmap @abc9_holes");
|
||||
|
@ -200,7 +267,7 @@ struct Abc9Pass : public ScriptPass
|
|||
if (check_label("map")) {
|
||||
if (help_mode) {
|
||||
run("foreach module in selection");
|
||||
run(" abc9_ops -write_box [(-box value)|(null)] <abc-temp-dir>/input.box");
|
||||
run(" abc9_ops -write_box [(-box <path>)|(null)] <abc-temp-dir>/input.box");
|
||||
run(" write_xaiger -map <abc-temp-dir>/input.sym <abc-temp-dir>/input.xaig");
|
||||
run(" abc9_exe [options] -cwd <abc-temp-dir> -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");
|
||||
|
@ -234,14 +301,16 @@ struct Abc9Pass : public ScriptPass
|
|||
run(stringf("write_xaiger -map %s/input.sym %s/input.xaig", tempdir_name.c_str(), tempdir_name.c_str()));
|
||||
|
||||
int num_outputs = active_design->scratchpad_get_int("write_xaiger.num_outputs");
|
||||
log("Extracted %d AND gates and %d wires to a netlist network with %d inputs and %d outputs.\n",
|
||||
|
||||
log("Extracted %d AND gates and %d wires from module `%s' to a netlist network with %d inputs and %d outputs.\n",
|
||||
active_design->scratchpad_get_int("write_xaiger.num_ands"),
|
||||
active_design->scratchpad_get_int("write_xaiger.num_wires"),
|
||||
log_id(mod),
|
||||
active_design->scratchpad_get_int("write_xaiger.num_inputs"),
|
||||
num_outputs);
|
||||
if (num_outputs) {
|
||||
run(stringf("%s -cwd %s -box %s/input.box", exe_cmd.str().c_str(), tempdir_name.c_str(), tempdir_name.c_str()));
|
||||
run(stringf("read_aiger -xaiger -wideports -module_name %s$abc9 -map %s/input.sym %s/output.aig", log_id(mod->name), tempdir_name.c_str(), tempdir_name.c_str()));
|
||||
run(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("abc9_ops -reintegrate");
|
||||
}
|
||||
else
|
||||
|
@ -258,9 +327,6 @@ struct Abc9Pass : public ScriptPass
|
|||
active_design->selection_stack.pop_back();
|
||||
}
|
||||
}
|
||||
|
||||
if (check_label("post"))
|
||||
run("abc9_ops -unbreak_scc");
|
||||
}
|
||||
} Abc9Pass;
|
||||
|
||||
|
|
|
@ -22,20 +22,6 @@
|
|||
// Berkeley Logic Synthesis and Verification Group, ABC: A System for Sequential Synthesis and Verification
|
||||
// http://www.eecs.berkeley.edu/~alanmi/abc/
|
||||
|
||||
#if 0
|
||||
// Based on &flow3 - better QoR but more experimental
|
||||
#define ABC_COMMAND_LUT "&st; &ps -l; &sweep -v; &scorr; " \
|
||||
"&st; &if {W}; &save; &st; &syn2; &if {W} -v; &save; &load; "\
|
||||
"&st; &if -g -K 6; &dch -f; &if {W} -v; &save; &load; "\
|
||||
"&st; &if -g -K 6; &synch2; &if {W} -v; &save; &load; "\
|
||||
"&mfs; &ps -l"
|
||||
#else
|
||||
#define ABC_COMMAND_LUT "&st; &scorr; &sweep; &dc2; &st; &dch -f; &ps; &if {W} {D} -v; &mfs; &ps -l"
|
||||
#endif
|
||||
|
||||
|
||||
#define ABC_FAST_COMMAND_LUT "&st; &if {W} {D}"
|
||||
|
||||
#include "kernel/register.h"
|
||||
#include "kernel/log.h"
|
||||
|
||||
|
@ -48,6 +34,25 @@
|
|||
extern "C" int Abc_RealMain(int argc, char *argv[]);
|
||||
#endif
|
||||
|
||||
std::string fold_abc9_cmd(std::string str)
|
||||
{
|
||||
std::string token, new_str = " ";
|
||||
int char_counter = 10;
|
||||
|
||||
for (size_t i = 0; i <= str.size(); i++) {
|
||||
if (i < str.size())
|
||||
token += str[i];
|
||||
if (i == str.size() || str[i] == ';') {
|
||||
if (char_counter + token.size() > 75)
|
||||
new_str += "\n ", char_counter = 14;
|
||||
new_str += token, char_counter += token.size();
|
||||
token.clear();
|
||||
}
|
||||
}
|
||||
|
||||
return new_str;
|
||||
}
|
||||
|
||||
USING_YOSYS_NAMESPACE
|
||||
PRIVATE_NAMESPACE_BEGIN
|
||||
|
||||
|
@ -73,25 +78,6 @@ std::string add_echos_to_abc9_cmd(std::string str)
|
|||
return new_str;
|
||||
}
|
||||
|
||||
std::string fold_abc9_cmd(std::string str)
|
||||
{
|
||||
std::string token, new_str = " ";
|
||||
int char_counter = 10;
|
||||
|
||||
for (size_t i = 0; i <= str.size(); i++) {
|
||||
if (i < str.size())
|
||||
token += str[i];
|
||||
if (i == str.size() || str[i] == ';') {
|
||||
if (char_counter + token.size() > 75)
|
||||
new_str += "\n ", char_counter = 14;
|
||||
new_str += token, char_counter += token.size();
|
||||
token.clear();
|
||||
}
|
||||
}
|
||||
|
||||
return new_str;
|
||||
}
|
||||
|
||||
std::string replace_tempdir(std::string text, std::string tempdir_name, bool show_tempdir)
|
||||
{
|
||||
if (show_tempdir)
|
||||
|
@ -177,25 +163,21 @@ struct abc9_output_filter
|
|||
};
|
||||
|
||||
void abc9_module(RTLIL::Design *design, std::string script_file, std::string exe_file,
|
||||
vector<int> lut_costs, std::string delay_target, std::string /*lutin_shared*/, bool fast_mode,
|
||||
vector<int> lut_costs, bool dff_mode, std::string delay_target, std::string /*lutin_shared*/, bool fast_mode,
|
||||
bool show_tempdir, std::string box_file, std::string lut_file,
|
||||
std::string wire_delay, bool nomfs, std::string tempdir_name
|
||||
std::string wire_delay, std::string tempdir_name
|
||||
)
|
||||
{
|
||||
//FIXME:
|
||||
//log_header(design, "Extracting gate netlist of module `%s' to `%s/input.xaig'..\n",
|
||||
// module->name.c_str(), replace_tempdir(tempdir_name, tempdir_name, show_tempdir).c_str());
|
||||
|
||||
std::string abc9_script;
|
||||
|
||||
if (!lut_costs.empty())
|
||||
abc9_script += stringf("read_lut %s/lutdefs.txt; ", tempdir_name.c_str());
|
||||
else
|
||||
if (!lut_file.empty())
|
||||
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());
|
||||
abc9_script += stringf("&read %s/input.xaig; &ps; ", tempdir_name.c_str());
|
||||
|
||||
|
@ -211,7 +193,8 @@ void abc9_module(RTLIL::Design *design, std::string script_file, std::string exe
|
|||
} else
|
||||
abc9_script += stringf("source %s", script_file.c_str());
|
||||
} else if (!lut_costs.empty() || !lut_file.empty()) {
|
||||
abc9_script += fast_mode ? ABC_FAST_COMMAND_LUT : ABC_COMMAND_LUT;
|
||||
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();
|
||||
|
||||
|
@ -224,11 +207,26 @@ void abc9_module(RTLIL::Design *design, std::string script_file, std::string exe
|
|||
for (size_t pos = abc9_script.find("{W}"); pos != std::string::npos; pos = abc9_script.find("{W}", pos))
|
||||
abc9_script = abc9_script.substr(0, pos) + wire_delay + abc9_script.substr(pos+3);
|
||||
|
||||
if (nomfs)
|
||||
for (size_t pos = abc9_script.find("&mfs"); pos != std::string::npos; pos = abc9_script.find("&mfs", pos))
|
||||
abc9_script = abc9_script.erase(pos, strlen("&mfs"));
|
||||
std::string C;
|
||||
if (design->scratchpad.count("abc9.if.C"))
|
||||
C = "-C " + design->scratchpad_get_string("abc9.if.C");
|
||||
for (size_t pos = abc9_script.find("{C}"); pos != std::string::npos; pos = abc9_script.find("{C}", pos))
|
||||
abc9_script = abc9_script.substr(0, pos) + C + abc9_script.substr(pos+3);
|
||||
|
||||
abc9_script += stringf("; &write -n %s/output.aig", tempdir_name.c_str());
|
||||
std::string R;
|
||||
if (design->scratchpad.count("abc9.if.R"))
|
||||
R = "-R " + design->scratchpad_get_string("abc9.if.R");
|
||||
for (size_t pos = abc9_script.find("{R}"); pos != std::string::npos; pos = abc9_script.find("{R}", pos))
|
||||
abc9_script = abc9_script.substr(0, pos) + R + abc9_script.substr(pos+3);
|
||||
|
||||
abc9_script += stringf("; &ps -l; &write -n %s/output.aig;", tempdir_name.c_str());
|
||||
if (design->scratchpad_get_bool("abc9.verify")) {
|
||||
if (dff_mode)
|
||||
abc9_script += "verify -s;";
|
||||
else
|
||||
abc9_script += "verify;";
|
||||
}
|
||||
abc9_script += "time";
|
||||
abc9_script = add_echos_to_abc9_cmd(abc9_script);
|
||||
|
||||
for (size_t i = 0; i+1 < abc9_script.size(); i++)
|
||||
|
@ -308,12 +306,12 @@ struct Abc9ExePass : public Pass {
|
|||
log(" replaced with blanks before the string is passed to ABC.\n");
|
||||
log("\n");
|
||||
log(" if no -script parameter is given, the following scripts are used:\n");
|
||||
log("%s\n", fold_abc9_cmd(ABC_COMMAND_LUT).c_str());
|
||||
log("%s\n", fold_abc9_cmd(RTLIL::constpad.at("abc9.script.default").substr(1,std::string::npos)).c_str());
|
||||
log("\n");
|
||||
log(" -fast\n");
|
||||
log(" use different default scripts that are slightly faster (at the cost\n");
|
||||
log(" of output quality):\n");
|
||||
log("%s\n", fold_abc9_cmd(ABC_FAST_COMMAND_LUT).c_str());
|
||||
log("%s\n", fold_abc9_cmd(RTLIL::constpad.at("abc9.script.default.fast").substr(1,std::string::npos)).c_str());
|
||||
log("\n");
|
||||
log(" -D <picoseconds>\n");
|
||||
log(" set delay target. the string {D} in the default scripts above is\n");
|
||||
|
@ -374,9 +372,8 @@ struct Abc9ExePass : public Pass {
|
|||
std::string script_file, clk_str, box_file, lut_file;
|
||||
std::string delay_target, lutin_shared = "-S 1", wire_delay;
|
||||
std::string tempdir_name;
|
||||
bool fast_mode = false;
|
||||
bool fast_mode = false, dff_mode = false;
|
||||
bool show_tempdir = false;
|
||||
bool nomfs = false;
|
||||
vector<int> lut_costs;
|
||||
|
||||
#if 0
|
||||
|
@ -400,12 +397,12 @@ struct Abc9ExePass : public Pass {
|
|||
lut_arg = design->scratchpad_get_string("abc9.lut", lut_arg);
|
||||
luts_arg = design->scratchpad_get_string("abc9.luts", luts_arg);
|
||||
fast_mode = design->scratchpad_get_bool("abc9.fast", fast_mode);
|
||||
dff_mode = design->scratchpad_get_bool("abc9.dff", dff_mode);
|
||||
show_tempdir = design->scratchpad_get_bool("abc9.showtmp", show_tempdir);
|
||||
box_file = design->scratchpad_get_string("abc9.box", box_file);
|
||||
if (design->scratchpad.count("abc9.W")) {
|
||||
wire_delay = "-W " + design->scratchpad_get_string("abc9.W");
|
||||
}
|
||||
nomfs = design->scratchpad_get_bool("abc9.nomfs", nomfs);
|
||||
|
||||
size_t argidx;
|
||||
char pwd [PATH_MAX];
|
||||
|
@ -443,6 +440,10 @@ struct Abc9ExePass : public Pass {
|
|||
fast_mode = true;
|
||||
continue;
|
||||
}
|
||||
if (arg == "-dff") {
|
||||
dff_mode = true;
|
||||
continue;
|
||||
}
|
||||
if (arg == "-showtmp") {
|
||||
show_tempdir = true;
|
||||
continue;
|
||||
|
@ -455,10 +456,6 @@ struct Abc9ExePass : public Pass {
|
|||
wire_delay = "-W " + args[++argidx];
|
||||
continue;
|
||||
}
|
||||
if (arg == "-nomfs") {
|
||||
nomfs = true;
|
||||
continue;
|
||||
}
|
||||
if (arg == "-cwd" && argidx+1 < args.size()) {
|
||||
tempdir_name = args[++argidx];
|
||||
continue;
|
||||
|
@ -525,9 +522,9 @@ struct Abc9ExePass : public Pass {
|
|||
log_cmd_error("abc9_exe '-cwd' option is mandatory.\n");
|
||||
|
||||
|
||||
abc9_module(design, script_file, exe_file, lut_costs,
|
||||
abc9_module(design, script_file, exe_file, lut_costs, dff_mode,
|
||||
delay_target, lutin_shared, fast_mode, show_tempdir,
|
||||
box_file, lut_file, wire_delay, nomfs, tempdir_name);
|
||||
box_file, lut_file, wire_delay, tempdir_name);
|
||||
}
|
||||
} Abc9ExePass;
|
||||
|
||||
|
|
|
@ -91,7 +91,7 @@ void check(RTLIL::Design *design)
|
|||
}
|
||||
}
|
||||
|
||||
void break_scc(RTLIL::Module *module)
|
||||
void mark_scc(RTLIL::Module *module)
|
||||
{
|
||||
// For every unique SCC found, (arbitrarily) find the first
|
||||
// cell in the component, and convert all wires driven by
|
||||
|
@ -102,7 +102,8 @@ void break_scc(RTLIL::Module *module)
|
|||
auto it = cell->attributes.find(ID(abc9_scc_id));
|
||||
if (it == cell->attributes.end())
|
||||
continue;
|
||||
auto r = ids_seen.insert(it->second);
|
||||
auto id = it->second;
|
||||
auto r = ids_seen.insert(id);
|
||||
cell->attributes.erase(it);
|
||||
if (!r.second)
|
||||
continue;
|
||||
|
@ -111,30 +112,8 @@ void break_scc(RTLIL::Module *module)
|
|||
if (cell->output(c.first)) {
|
||||
SigBit b = c.second.as_bit();
|
||||
Wire *w = b.wire;
|
||||
if (w->port_input) {
|
||||
// In this case, hopefully the loop break has been already created
|
||||
// Get the non-prefixed wire
|
||||
Wire *wo = module->wire(stringf("%s.abco", b.wire->name.c_str()));
|
||||
log_assert(wo != nullptr);
|
||||
log_assert(wo->port_output);
|
||||
log_assert(b.offset < GetSize(wo));
|
||||
c.second = RTLIL::SigBit(wo, b.offset);
|
||||
}
|
||||
else {
|
||||
// Create a new output/input loop break
|
||||
w->port_input = true;
|
||||
w = module->wire(stringf("%s.abco", w->name.c_str()));
|
||||
if (!w) {
|
||||
w = module->addWire(stringf("%s.abco", b.wire->name.c_str()), GetSize(b.wire));
|
||||
w->port_output = true;
|
||||
}
|
||||
else {
|
||||
log_assert(w->port_input);
|
||||
log_assert(b.offset < GetSize(w));
|
||||
}
|
||||
w->set_bool_attribute(ID(abc9_scc_break));
|
||||
c.second = RTLIL::SigBit(w, b.offset);
|
||||
}
|
||||
w->set_bool_attribute(ID::keep);
|
||||
w->attributes[ID(abc9_scc_id)] = id.as_int();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -142,28 +121,6 @@ void break_scc(RTLIL::Module *module)
|
|||
module->fixup_ports();
|
||||
}
|
||||
|
||||
void unbreak_scc(RTLIL::Module *module)
|
||||
{
|
||||
// Now 'unexpose' those wires by undoing
|
||||
// the expose operation -- remove them from PO/PI
|
||||
// and re-connecting them back together
|
||||
for (auto wire : module->wires()) {
|
||||
auto it = wire->attributes.find(ID(abc9_scc_break));
|
||||
if (it != wire->attributes.end()) {
|
||||
wire->attributes.erase(it);
|
||||
log_assert(wire->port_output);
|
||||
wire->port_output = false;
|
||||
std::string name = wire->name.str();
|
||||
RTLIL::Wire *i_wire = module->wire(name.substr(0, GetSize(name) - 5));
|
||||
log_assert(i_wire);
|
||||
log_assert(i_wire->port_input);
|
||||
i_wire->port_input = false;
|
||||
module->connect(i_wire, wire);
|
||||
}
|
||||
}
|
||||
module->fixup_ports();
|
||||
}
|
||||
|
||||
void prep_dff(RTLIL::Module *module)
|
||||
{
|
||||
auto design = module->design;
|
||||
|
@ -244,7 +201,7 @@ void prep_dff(RTLIL::Module *module)
|
|||
}
|
||||
}
|
||||
|
||||
void prep_holes(RTLIL::Module *module, bool dff)
|
||||
void prep_xaiger(RTLIL::Module *module, bool dff)
|
||||
{
|
||||
auto design = module->design;
|
||||
log_assert(design);
|
||||
|
@ -253,7 +210,7 @@ void prep_holes(RTLIL::Module *module, bool dff)
|
|||
|
||||
dict<SigBit, pool<IdString>> bit_drivers, bit_users;
|
||||
TopoSort<IdString, RTLIL::sort_by_id_str> toposort;
|
||||
bool abc9_box_seen = false;
|
||||
dict<IdString, std::vector<IdString>> box_ports;
|
||||
|
||||
for (auto cell : module->cells()) {
|
||||
if (cell->type == "$__ABC9_FF_")
|
||||
|
@ -266,7 +223,40 @@ void prep_holes(RTLIL::Module *module, bool dff)
|
|||
abc9_flop = inst_module->get_bool_attribute("\\abc9_flop");
|
||||
if (abc9_flop && !dff)
|
||||
continue;
|
||||
abc9_box_seen = abc9_box;
|
||||
|
||||
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 : inst_module->ports) {
|
||||
auto w = inst_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(inst_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(inst_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(inst_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(inst_module));
|
||||
if (carry_in != IdString()) {
|
||||
r.first->second.push_back(carry_in);
|
||||
r.first->second.push_back(carry_out);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (!yosys_celltypes.cell_known(cell->type))
|
||||
continue;
|
||||
|
@ -284,7 +274,7 @@ void prep_holes(RTLIL::Module *module, bool dff)
|
|||
toposort.node(cell->name);
|
||||
}
|
||||
|
||||
if (!abc9_box_seen)
|
||||
if (box_ports.empty())
|
||||
return;
|
||||
|
||||
for (auto &it : bit_users)
|
||||
|
@ -312,7 +302,13 @@ void prep_holes(RTLIL::Module *module, bool dff)
|
|||
|
||||
log_assert(no_loops);
|
||||
|
||||
vector<Cell*> box_list;
|
||||
RTLIL::Module *holes_module = design->addModule(stringf("%s$holes", module->name.c_str()));
|
||||
log_assert(holes_module);
|
||||
holes_module->set_bool_attribute("\\abc9_holes");
|
||||
|
||||
dict<IdString, Cell*> cell_cache;
|
||||
|
||||
int port_id = 1, box_count = 0;
|
||||
for (auto cell_name : toposort.sorted) {
|
||||
RTLIL::Cell *cell = module->cell(cell_name);
|
||||
log_assert(cell);
|
||||
|
@ -321,92 +317,16 @@ void prep_holes(RTLIL::Module *module, bool dff)
|
|||
if (!box_module || !box_module->attributes.count("\\abc9_box_id"))
|
||||
continue;
|
||||
|
||||
bool blackbox = box_module->get_blackbox_attribute(true /* ignore_wb */);
|
||||
cell->attributes["\\abc9_box_seq"] = box_count++;
|
||||
|
||||
// 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 (const auto &port_name : box_module->ports) {
|
||||
RTLIL::Wire* w = box_module->wire(port_name);
|
||||
log_assert(w);
|
||||
auto it = cell->connections_.find(port_name);
|
||||
if (w->port_input) {
|
||||
RTLIL::SigSpec rhs;
|
||||
if (it != cell->connections_.end()) {
|
||||
if (GetSize(it->second) < GetSize(w))
|
||||
it->second.append(RTLIL::SigSpec(State::S0, GetSize(w)-GetSize(it->second)));
|
||||
rhs = it->second;
|
||||
}
|
||||
else {
|
||||
rhs = RTLIL::SigSpec(State::S0, GetSize(w));
|
||||
cell->setPort(port_name, rhs);
|
||||
}
|
||||
}
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
cell->attributes["\\abc9_box_seq"] = box_list.size();
|
||||
//log_debug("%s.%s is box %d\n", log_id(module), log_id(cell), box_list.size());
|
||||
box_list.emplace_back(cell);
|
||||
}
|
||||
log_assert(!box_list.empty());
|
||||
|
||||
RTLIL::Module *holes_module = design->addModule(stringf("%s$holes", module->name.c_str()));
|
||||
log_assert(holes_module);
|
||||
holes_module->set_bool_attribute("\\abc9_holes");
|
||||
|
||||
dict<IdString, Cell*> cell_cache;
|
||||
dict<IdString, std::vector<IdString>> box_ports;
|
||||
|
||||
int port_id = 1;
|
||||
for (auto cell : box_list) {
|
||||
RTLIL::Module* orig_box_module = design->module(cell->type);
|
||||
log_assert(orig_box_module);
|
||||
IdString derived_name = orig_box_module->derive(design, cell->parameters);
|
||||
RTLIL::Module* box_module = design->module(derived_name);
|
||||
//cell->type = derived_name;
|
||||
//cell->parameters.clear();
|
||||
IdString derived_name = box_module->derive(design, cell->parameters);
|
||||
box_module = design->module(derived_name);
|
||||
|
||||
auto r = cell_cache.insert(derived_name);
|
||||
auto &holes_cell = r.first->second;
|
||||
if (r.second) {
|
||||
auto r2 = box_ports.insert(cell->type);
|
||||
if (r2.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)
|
||||
carry_in = port_name;
|
||||
if (w->port_output)
|
||||
carry_out = port_name;
|
||||
}
|
||||
else
|
||||
r2.first->second.push_back(port_name);
|
||||
}
|
||||
|
||||
if (carry_in != IdString()) {
|
||||
r2.first->second.push_back(carry_in);
|
||||
r2.first->second.push_back(carry_out);
|
||||
}
|
||||
}
|
||||
if (box_module->has_processes())
|
||||
Pass::call_on_module(design, box_module, "proc");
|
||||
|
||||
if (box_module->get_bool_attribute("\\whitebox")) {
|
||||
holes_cell = holes_module->addCell(cell->name, derived_name);
|
||||
|
@ -655,6 +575,8 @@ void reintegrate(RTLIL::Module *module)
|
|||
pool<IdString> delay_boxes;
|
||||
std::vector<Cell*> boxes;
|
||||
for (auto cell : module->cells().to_vector()) {
|
||||
if (cell->has_keep_attr())
|
||||
continue;
|
||||
if (cell->type.in(ID($_AND_), ID($_NOT_), ID($__ABC9_FF_)))
|
||||
module->remove(cell);
|
||||
else if (cell->type.begins_with("$paramod$__ABC9_DELAY\\DELAY=")) {
|
||||
|
@ -680,7 +602,9 @@ void reintegrate(RTLIL::Module *module)
|
|||
RTLIL::SigBit a_bit = mapped_cell->getPort(ID::A);
|
||||
RTLIL::SigBit y_bit = mapped_cell->getPort(ID::Y);
|
||||
bit_users[a_bit].insert(mapped_cell->name);
|
||||
bit_drivers[y_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);
|
||||
|
||||
if (!a_bit.wire) {
|
||||
mapped_cell->setPort(ID::Y, module->addWire(NEW_ID));
|
||||
|
@ -698,16 +622,16 @@ void reintegrate(RTLIL::Module *module)
|
|||
// (TODO: Optimise by not cloning unless will increase depth)
|
||||
RTLIL::IdString driver_name;
|
||||
if (GetSize(a_bit.wire) == 1)
|
||||
driver_name = stringf("%s$lut", a_bit.wire->name.c_str());
|
||||
driver_name = stringf("$lut%s", a_bit.wire->name.c_str());
|
||||
else
|
||||
driver_name = stringf("%s[%d]$lut", a_bit.wire->name.c_str(), a_bit.offset);
|
||||
driver_name = stringf("$lut%s[%d]", a_bit.wire->name.c_str(), a_bit.offset);
|
||||
driver_lut = mapped_mod->cell(driver_name);
|
||||
}
|
||||
|
||||
if (!driver_lut) {
|
||||
// If a driver couldn't be found (could be from PI or box CI)
|
||||
// then implement using a LUT
|
||||
RTLIL::Cell *cell = module->addLut(remap_name(stringf("%s$lut", mapped_cell->name.c_str())),
|
||||
RTLIL::Cell *cell = module->addLut(remap_name(stringf("$lut%s", mapped_cell->name.c_str())),
|
||||
RTLIL::SigBit(module->wires_.at(remap_name(a_bit.wire->name)), a_bit.offset),
|
||||
RTLIL::SigBit(module->wires_.at(remap_name(y_bit.wire->name)), y_bit.offset),
|
||||
RTLIL::Const::from_string("01"));
|
||||
|
@ -745,7 +669,9 @@ void reintegrate(RTLIL::Module *module)
|
|||
}
|
||||
if (cell->output(mapped_conn.first))
|
||||
for (auto i : mapped_conn.second)
|
||||
bit_drivers[i].insert(mapped_cell->name);
|
||||
// Ignore inouts for topo ordering
|
||||
if (i.wire && !(i.wire->port_input && i.wire->port_output))
|
||||
bit_drivers[i].insert(mapped_cell->name);
|
||||
}
|
||||
}
|
||||
else if (delay_boxes.count(mapped_cell->name)) {
|
||||
|
@ -788,7 +714,9 @@ void reintegrate(RTLIL::Module *module)
|
|||
for (const auto &i : inputs)
|
||||
bit_users[i].insert(mapped_cell->name);
|
||||
for (const auto &i : outputs)
|
||||
bit_drivers[i].insert(mapped_cell->name);
|
||||
// Ignore inouts for topo ordering
|
||||
if (i.wire && !(i.wire->port_input && i.wire->port_output))
|
||||
bit_drivers[i].insert(mapped_cell->name);
|
||||
}
|
||||
|
||||
auto r2 = box_ports.insert(cell->type);
|
||||
|
@ -886,21 +814,25 @@ void reintegrate(RTLIL::Module *module)
|
|||
|
||||
// Stitch in mapped_mod's inputs/outputs into module
|
||||
for (auto port : mapped_mod->ports) {
|
||||
RTLIL::Wire *w = mapped_mod->wire(port);
|
||||
RTLIL::Wire *mapped_wire = mapped_mod->wire(port);
|
||||
RTLIL::Wire *wire = module->wire(port);
|
||||
log_assert(wire);
|
||||
if (wire->attributes.erase(ID(abc9_scc_id))) {
|
||||
auto r YS_ATTRIBUTE(unused) = wire->attributes.erase(ID::keep);
|
||||
log_assert(r);
|
||||
}
|
||||
RTLIL::Wire *remap_wire = module->wire(remap_name(port));
|
||||
RTLIL::SigSpec signal(wire, 0, GetSize(remap_wire));
|
||||
log_assert(GetSize(signal) >= GetSize(remap_wire));
|
||||
|
||||
RTLIL::SigSig conn;
|
||||
if (w->port_output) {
|
||||
if (mapped_wire->port_output) {
|
||||
conn.first = signal;
|
||||
conn.second = remap_wire;
|
||||
out_wires++;
|
||||
module->connect(conn);
|
||||
}
|
||||
else if (w->port_input) {
|
||||
else if (mapped_wire->port_input) {
|
||||
conn.first = remap_wire;
|
||||
conn.second = signal;
|
||||
in_wires++;
|
||||
|
@ -996,6 +928,35 @@ struct Abc9OpsPass : public Pass {
|
|||
log("\n");
|
||||
log(" abc9_ops [options] [selection]\n");
|
||||
log("\n");
|
||||
log("This pass contains a set of supporting operations for use during ABC technology\n");
|
||||
log("mapping, and is expected to be called in conjunction with other operations from\n");
|
||||
log("the `abc9' script pass. Only fully-selected modules are supported.\n");
|
||||
log("\n");
|
||||
log(" -mark_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("\n");
|
||||
log(" -prep_xaiger\n");
|
||||
log(" prepare the design for XAIGER output. this includes computing the\n");
|
||||
log(" topological ordering of ABC9 boxes, as well as preparing the\n");
|
||||
log(" '<module-name>$holes' module that contains the logic behaviour of ABC9\n");
|
||||
log(" whiteboxes.\n");
|
||||
log("\n");
|
||||
log(" -dff\n");
|
||||
log(" consider flop cells (those instantiating modules marked with (* abc9_flop *)\n");
|
||||
log(" during -prep_xaiger.\n");
|
||||
log("\n");
|
||||
log(" -prep_dff\n");
|
||||
log(" compute the clock domain and initial value of each flop in the design.\n");
|
||||
log(" process the '$holes' module to support clock-enable functionality.\n");
|
||||
log("\n");
|
||||
log(" -reintegrate\n");
|
||||
log(" for each selected module, re-intergrate the module '<module-name>$abc9'\n");
|
||||
log(" by first recovering ABC9 boxes, and then stitching in the remaining primary\n");
|
||||
log(" inputs and outputs.\n");
|
||||
log("\n");
|
||||
}
|
||||
void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
|
||||
{
|
||||
|
@ -1003,13 +964,12 @@ struct Abc9OpsPass : public Pass {
|
|||
|
||||
bool check_mode = false;
|
||||
bool prep_times_mode = false;
|
||||
bool break_scc_mode = false;
|
||||
bool unbreak_scc_mode = false;
|
||||
bool prep_holes_mode = false;
|
||||
bool mark_scc_mode = false;
|
||||
bool prep_dff_mode = false;
|
||||
std::string write_box_src, write_box_dst;
|
||||
bool prep_xaiger_mode = false;
|
||||
bool reintegrate_mode = false;
|
||||
bool dff_mode = false;
|
||||
std::string write_box_src, write_box_dst;
|
||||
|
||||
size_t argidx;
|
||||
for (argidx = 1; argidx < args.size(); argidx++) {
|
||||
|
@ -1018,20 +978,16 @@ struct Abc9OpsPass : public Pass {
|
|||
check_mode = true;
|
||||
continue;
|
||||
}
|
||||
if (arg == "-break_scc") {
|
||||
break_scc_mode = true;
|
||||
continue;
|
||||
}
|
||||
if (arg == "-unbreak_scc") {
|
||||
unbreak_scc_mode = true;
|
||||
if (arg == "-mark_scc") {
|
||||
mark_scc_mode = true;
|
||||
continue;
|
||||
}
|
||||
if (arg == "-prep_dff") {
|
||||
prep_dff_mode = true;
|
||||
continue;
|
||||
}
|
||||
if (arg == "-prep_holes") {
|
||||
prep_holes_mode = true;
|
||||
if (arg == "-prep_xaiger") {
|
||||
prep_xaiger_mode = true;
|
||||
continue;
|
||||
}
|
||||
if (arg == "-prep_times") {
|
||||
|
@ -1057,11 +1013,11 @@ struct Abc9OpsPass : public Pass {
|
|||
}
|
||||
extra_args(args, argidx, design);
|
||||
|
||||
if (!(check_mode || break_scc_mode || unbreak_scc_mode || prep_times_mode || prep_holes_mode || prep_dff_mode || !write_box_src.empty() || reintegrate_mode))
|
||||
log_cmd_error("At least one of -check, -{,un}break_scc, -prep_{times,holes,dff}, -write_box, -reintegrate must be specified.\n");
|
||||
if (!(check_mode || mark_scc_mode || prep_times_mode || prep_xaiger_mode || prep_dff_mode || !write_box_src.empty() || reintegrate_mode))
|
||||
log_cmd_error("At least one of -check, -mark_scc, -prep_{times,xaiger,dff}, -write_box, -reintegrate must be specified.\n");
|
||||
|
||||
if (dff_mode && !prep_holes_mode)
|
||||
log_cmd_error("'-dff' option is only relevant for -prep_holes.\n");
|
||||
if (dff_mode && !prep_xaiger_mode)
|
||||
log_cmd_error("'-dff' option is only relevant for -prep_xaiger.\n");
|
||||
|
||||
if (check_mode)
|
||||
check(design);
|
||||
|
@ -1080,16 +1036,14 @@ struct Abc9OpsPass : public Pass {
|
|||
if (!design->selected_whole_module(mod))
|
||||
log_error("Can't handle partially selected module %s!\n", log_id(mod));
|
||||
|
||||
if (break_scc_mode)
|
||||
break_scc(mod);
|
||||
if (unbreak_scc_mode)
|
||||
unbreak_scc(mod);
|
||||
if (prep_holes_mode)
|
||||
prep_holes(mod, dff_mode);
|
||||
if (prep_dff_mode)
|
||||
prep_dff(mod);
|
||||
if (!write_box_src.empty())
|
||||
write_box(mod, write_box_src, write_box_dst);
|
||||
if (mark_scc_mode)
|
||||
mark_scc(mod);
|
||||
if (prep_dff_mode)
|
||||
prep_dff(mod);
|
||||
if (prep_xaiger_mode)
|
||||
prep_xaiger(mod, dff_mode);
|
||||
if (reintegrate_mode)
|
||||
reintegrate(mod);
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue