aboutsummaryrefslogtreecommitdiffstats
path: root/passes
diff options
context:
space:
mode:
Diffstat (limited to 'passes')
-rw-r--r--passes/cmds/autoname.cc2
-rw-r--r--passes/cmds/scc.cc51
-rw-r--r--passes/cmds/scratchpad.cc25
-rw-r--r--passes/pmgen/ice40_dsp.cc8
-rw-r--r--passes/pmgen/ice40_dsp.pmg21
-rw-r--r--passes/pmgen/xilinx_dsp.pmg16
-rw-r--r--passes/techmap/abc.cc399
-rw-r--r--passes/techmap/abc9.cc760
-rw-r--r--passes/techmap/iopadmap.cc3
9 files changed, 577 insertions, 708 deletions
diff --git a/passes/cmds/autoname.cc b/passes/cmds/autoname.cc
index 4614a8153..50632201e 100644
--- a/passes/cmds/autoname.cc
+++ b/passes/cmds/autoname.cc
@@ -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;
diff --git a/passes/cmds/scc.cc b/passes/cmds/scc.cc
index 99f4fbae8..ad0554bae 100644
--- a/passes/cmds/scc.cc
+++ b/passes/cmds/scc.cc
@@ -301,42 +301,41 @@ struct SccPass : public Pass {
RTLIL::Selection newSelection(false);
int scc_counter = 0;
- for (auto &mod_it : design->modules_)
- if (design->selected(mod_it.second))
- {
- SccWorker worker(design, mod_it.second, nofeedbackMode, allCellTypes, maxDepth);
+ for (auto mod : design->selected_modules())
+ {
+ SccWorker worker(design, mod, nofeedbackMode, allCellTypes, maxDepth);
- if (!setAttr.empty())
+ if (!setAttr.empty())
+ {
+ for (const auto &cells : worker.sccList)
{
- for (const auto &cells : worker.sccList)
+ for (auto attr : setAttr)
{
- for (auto attr : setAttr)
- {
- IdString attr_name(RTLIL::escape_id(attr.first));
- string attr_valstr = attr.second;
- string index = stringf("%d", scc_counter);
-
- for (size_t pos = 0; (pos = attr_valstr.find("{}", pos)) != string::npos; pos += index.size())
- attr_valstr.replace(pos, 2, index);
+ IdString attr_name(RTLIL::escape_id(attr.first));
+ string attr_valstr = attr.second;
+ string index = stringf("%d", scc_counter);
- Const attr_value(attr_valstr);
+ for (size_t pos = 0; (pos = attr_valstr.find("{}", pos)) != string::npos; pos += index.size())
+ attr_valstr.replace(pos, 2, index);
- for (auto cell : cells)
- cell->attributes[attr_name] = attr_value;
- }
+ Const attr_value(attr_valstr);
- scc_counter++;
+ for (auto cell : cells)
+ cell->attributes[attr_name] = attr_value;
}
- }
- else
- {
- scc_counter += GetSize(worker.sccList);
- }
- if (selectMode)
- worker.select(newSelection);
+ scc_counter++;
+ }
+ }
+ else
+ {
+ scc_counter += GetSize(worker.sccList);
}
+ if (selectMode)
+ worker.select(newSelection);
+ }
+
if (expect >= 0) {
if (scc_counter == expect)
log("Found and expected %d SCCs.\n", scc_counter);
diff --git a/passes/cmds/scratchpad.cc b/passes/cmds/scratchpad.cc
index 7ec55b78e..34ec0863a 100644
--- a/passes/cmds/scratchpad.cc
+++ b/passes/cmds/scratchpad.cc
@@ -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;
diff --git a/passes/pmgen/ice40_dsp.cc b/passes/pmgen/ice40_dsp.cc
index f60e67158..c364cd91a 100644
--- a/passes/pmgen/ice40_dsp.cc
+++ b/passes/pmgen/ice40_dsp.cc
@@ -73,11 +73,11 @@ void create_ice40_dsp(ice40_dsp_pm &pm)
// SB_MAC16 Input Interface
SigSpec A = st.sigA;
- A.extend_u0(16, st.mul->getParam(ID(A_SIGNED)).as_bool());
+ A.extend_u0(16, st.mul->parameters.at(ID(A_SIGNED), State::S0).as_bool());
log_assert(GetSize(A) == 16);
SigSpec B = st.sigB;
- B.extend_u0(16, st.mul->getParam(ID(B_SIGNED)).as_bool());
+ B.extend_u0(16, st.mul->parameters.at(ID(B_SIGNED), State::S0).as_bool());
log_assert(GetSize(B) == 16);
SigSpec CD = st.sigCD;
@@ -248,8 +248,8 @@ void create_ice40_dsp(ice40_dsp_pm &pm)
cell->setParam(ID(BOTADDSUB_CARRYSELECT), Const(0, 2));
cell->setParam(ID(MODE_8x8), State::S0);
- cell->setParam(ID(A_SIGNED), st.mul->getParam(ID(A_SIGNED)).as_bool());
- cell->setParam(ID(B_SIGNED), st.mul->getParam(ID(B_SIGNED)).as_bool());
+ cell->setParam(ID(A_SIGNED), st.mul->parameters.at(ID(A_SIGNED), State::S0).as_bool());
+ cell->setParam(ID(B_SIGNED), st.mul->parameters.at(ID(B_SIGNED), State::S0).as_bool());
if (st.ffO) {
if (st.o_lo)
diff --git a/passes/pmgen/ice40_dsp.pmg b/passes/pmgen/ice40_dsp.pmg
index 6b6d2b56f..9d649cb98 100644
--- a/passes/pmgen/ice40_dsp.pmg
+++ b/passes/pmgen/ice40_dsp.pmg
@@ -56,11 +56,16 @@ code sigA sigB sigH
break;
sigH.append(O[i]);
}
+ // This sigM could have no users if downstream sinks (e.g. $add) is
+ // narrower than $mul result, for example
+ if (i == 0)
+ reject;
+
log_assert(nusers(O.extract_end(i)) <= 1);
endcode
code argQ ffA ffAholdmux ffArstmux ffAholdpol ffArstpol sigA clock clock_pol
- if (mul->type != \SB_MAC16 || !param(mul, \A_REG).as_bool()) {
+ if (mul->type != \SB_MAC16 || !param(mul, \A_REG, State::S0).as_bool()) {
argQ = sigA;
subpattern(in_dffe);
if (dff) {
@@ -81,7 +86,7 @@ code argQ ffA ffAholdmux ffArstmux ffAholdpol ffArstpol sigA clock clock_pol
endcode
code argQ ffB ffBholdmux ffBrstmux ffBholdpol ffBrstpol sigB clock clock_pol
- if (mul->type != \SB_MAC16 || !param(mul, \B_REG).as_bool()) {
+ if (mul->type != \SB_MAC16 || !param(mul, \B_REG, State::S0).as_bool()) {
argQ = sigB;
subpattern(in_dffe);
if (dff) {
@@ -104,7 +109,7 @@ endcode
code argD ffFJKG sigH clock clock_pol
if (nusers(sigH) == 2 &&
(mul->type != \SB_MAC16 ||
- (!param(mul, \TOP_8x8_MULT_REG).as_bool() && !param(mul, \BOT_8x8_MULT_REG).as_bool() && !param(mul, \PIPELINE_16x16_MULT_REG1).as_bool() && !param(mul, \PIPELINE_16x16_MULT_REG1).as_bool()))) {
+ (!param(mul, \TOP_8x8_MULT_REG, State::S0).as_bool() && !param(mul, \BOT_8x8_MULT_REG, State::S0).as_bool() && !param(mul, \PIPELINE_16x16_MULT_REG1, State::S0).as_bool() && !param(mul, \PIPELINE_16x16_MULT_REG1, State::S0).as_bool()))) {
argD = sigH;
subpattern(out_dffe);
if (dff) {
@@ -143,7 +148,7 @@ endcode
code argD ffH sigH sigO clock clock_pol
if (ffFJKG && nusers(sigH) == 2 &&
- (mul->type != \SB_MAC16 || !param(mul, \PIPELINE_16x16_MULT_REG2).as_bool())) {
+ (mul->type != \SB_MAC16 || !param(mul, \PIPELINE_16x16_MULT_REG2, State::S0).as_bool())) {
argD = sigH;
subpattern(out_dffe);
if (dff) {
@@ -174,7 +179,7 @@ reject_ffH: ;
endcode
match add
- if mul->type != \SB_MAC16 || (param(mul, \TOPOUTPUT_SELECT).as_int() == 3 && param(mul, \BOTOUTPUT_SELECT).as_int() == 3)
+ if mul->type != \SB_MAC16 || (param(mul, \TOPOUTPUT_SELECT, State::S0).as_int() == 3 && param(mul, \BOTOUTPUT_SELECT, State::S0).as_int() == 3)
select add->type.in($add)
choice <IdString> AB {\A, \B}
@@ -200,7 +205,7 @@ code sigCD sigO cd_signed
if ((actual_acc_width > actual_mul_width) && (natural_mul_width > actual_mul_width))
reject;
// If accumulator, check adder width and signedness
- if (sigCD == sigH && (actual_acc_width != actual_mul_width) && (param(mul, \A_SIGNED).as_bool() != param(add, \A_SIGNED).as_bool()))
+ if (sigCD == sigH && (actual_acc_width != actual_mul_width) && (param(mul, \A_SIGNED, State::S0).as_bool() != param(add, \A_SIGNED).as_bool()))
reject;
sigO = port(add, \Y);
@@ -275,7 +280,7 @@ endcode
code argQ ffCD ffCDholdmux ffCDholdpol ffCDrstpol sigCD clock clock_pol
if (!sigCD.empty() && sigCD != sigO &&
- (mul->type != \SB_MAC16 || (!param(mul, \C_REG).as_bool() && !param(mul, \D_REG).as_bool()))) {
+ (mul->type != \SB_MAC16 || (!param(mul, \C_REG, State::S0).as_bool() && !param(mul, \D_REG, State::S0).as_bool()))) {
argQ = sigCD;
subpattern(in_dffe);
if (dff) {
@@ -328,6 +333,8 @@ arg argD argQ clock clock_pol
code
dff = nullptr;
+ if (argQ.empty())
+ reject;
for (auto c : argQ.chunks()) {
if (!c.wire)
reject;
diff --git a/passes/pmgen/xilinx_dsp.pmg b/passes/pmgen/xilinx_dsp.pmg
index 5d3b9c2eb..af47ab111 100644
--- a/passes/pmgen/xilinx_dsp.pmg
+++ b/passes/pmgen/xilinx_dsp.pmg
@@ -120,7 +120,7 @@ endcode
// reset functionality, using a subpattern discussed above)
// If matched, treat 'A' input as input of ADREG
code argQ ffAD ffADcemux ffADrstmux ffADcepol ffADrstpol sigA clock
- if (param(dsp, \ADREG).as_int() == 0) {
+ if (param(dsp, \ADREG, 1).as_int() == 0) {
argQ = sigA;
subpattern(in_dffe);
if (dff) {
@@ -176,7 +176,7 @@ code argQ ffAD ffADcemux ffADrstmux ffADcepol ffADrstpol sigA clock ffA2 ffA2cem
// Only search for ffA2 if there was a pre-adder
// (otherwise ffA2 would have been matched as ffAD)
if (preAdd) {
- if (param(dsp, \AREG).as_int() == 0) {
+ if (param(dsp, \AREG, 1).as_int() == 0) {
argQ = sigA;
subpattern(in_dffe);
if (dff) {
@@ -237,7 +237,7 @@ endcode
// (5) Match 'B' input for B2REG
// If B2REG, then match 'B' input for B1REG
code argQ ffB2 ffB2cemux ffB2rstmux ffB2cepol ffBrstpol sigB clock ffB1 ffB1cemux ffB1rstmux ffB1cepol
- if (param(dsp, \BREG).as_int() == 0) {
+ if (param(dsp, \BREG, 1).as_int() == 0) {
argQ = sigB;
subpattern(in_dffe);
if (dff) {
@@ -287,7 +287,7 @@ endcode
// (6) Match 'D' input for DREG
code argQ ffD ffDcemux ffDrstmux ffDcepol ffDrstpol sigD clock
- if (param(dsp, \DREG).as_int() == 0) {
+ if (param(dsp, \DREG, 1).as_int() == 0) {
argQ = sigD;
subpattern(in_dffe);
if (dff) {
@@ -308,7 +308,7 @@ endcode
// (7) Match 'P' output that exclusively drives an MREG
code argD ffM ffMcemux ffMrstmux ffMcepol ffMrstpol sigM sigP clock
- if (param(dsp, \MREG).as_int() == 0 && nusers(sigM) == 2) {
+ if (param(dsp, \MREG, 1).as_int() == 0 && nusers(sigM) == 2) {
argD = sigM;
subpattern(out_dffe);
if (dff) {
@@ -335,7 +335,7 @@ endcode
// recognised in xilinx_dsp.cc).
match postAdd
// Ensure that Z mux is not already used
- if port(dsp, \OPMODE, SigSpec()).extract(4,3).is_fully_zero()
+ if port(dsp, \OPMODE, SigSpec(0, 7)).extract(4,3).is_fully_zero()
select postAdd->type.in($add)
select GetSize(port(postAdd, \Y)) <= 48
@@ -363,7 +363,7 @@ endcode
// (9) Match 'P' output that exclusively drives a PREG
code argD ffP ffPcemux ffPrstmux ffPcepol ffPrstpol sigP clock
- if (param(dsp, \PREG).as_int() == 0) {
+ if (param(dsp, \PREG, 1).as_int() == 0) {
int users = 2;
// If ffMcemux and no postAdd new-value net must have three users: ffMcemux, ffM and ffPcemux
if (ffMcemux && !postAdd) users++;
@@ -460,7 +460,7 @@ arg argD argQ clock
code
dff = nullptr;
- if (GetSize(argQ) == 0)
+ if (argQ.empty())
reject;
for (const auto &c : argQ.chunks()) {
// Abandon matches when 'Q' is a constant
diff --git a/passes/techmap/abc.cc b/passes/techmap/abc.cc
index b29480e26..581652a41 100644
--- a/passes/techmap/abc.cc
+++ b/passes/techmap/abc.cc
@@ -29,17 +29,17 @@
// Kahn, Arthur B. (1962), "Topological sorting of large networks", Communications of the ACM 5 (11): 558-562, doi:10.1145/368996.369025
// http://en.wikipedia.org/wiki/Topological_sorting
-#define ABC_COMMAND_LIB "strash; ifraig; scorr; dc2; dretime; retime {D}; strash; &get -n; &dch -f; &nf {D}; &put"
-#define ABC_COMMAND_CTR "strash; ifraig; scorr; dc2; dretime; retime {D}; strash; &get -n; &dch -f; &nf {D}; &put; buffer; upsize {D}; dnsize {D}; stime -p"
-#define ABC_COMMAND_LUT "strash; ifraig; scorr; dc2; dretime; retime {D}; strash; dch -f; if; mfs2"
-#define ABC_COMMAND_SOP "strash; ifraig; scorr; dc2; dretime; retime {D}; strash; dch -f; cover {I} {P}"
-#define ABC_COMMAND_DFL "strash; ifraig; scorr; dc2; dretime; retime {D}; strash; &get -n; &dch -f; &nf {D}; &put"
-
-#define ABC_FAST_COMMAND_LIB "strash; dretime; retime {D}; map {D}"
-#define ABC_FAST_COMMAND_CTR "strash; dretime; retime {D}; map {D}; buffer; upsize {D}; dnsize {D}; stime -p"
-#define ABC_FAST_COMMAND_LUT "strash; dretime; retime {D}; if"
-#define ABC_FAST_COMMAND_SOP "strash; dretime; retime {D}; cover -I {I} -P {P}"
-#define ABC_FAST_COMMAND_DFL "strash; dretime; retime {D}; map"
+#define ABC_COMMAND_LIB "strash; ifraig; scorr; dc2; dretime; strash; &get -n; &dch -f; &nf {D}; &put"
+#define ABC_COMMAND_CTR "strash; ifraig; scorr; dc2; dretime; strash; &get -n; &dch -f; &nf {D}; &put; buffer; upsize {D}; dnsize {D}; stime -p"
+#define ABC_COMMAND_LUT "strash; ifraig; scorr; dc2; dretime; strash; dch -f; if; mfs2"
+#define ABC_COMMAND_SOP "strash; ifraig; scorr; dc2; dretime; strash; dch -f; cover {I} {P}"
+#define ABC_COMMAND_DFL "strash; ifraig; scorr; dc2; dretime; strash; &get -n; &dch -f; &nf {D}; &put"
+
+#define ABC_FAST_COMMAND_LIB "strash; dretime; map {D}"
+#define ABC_FAST_COMMAND_CTR "strash; dretime; map {D}; buffer; upsize {D}; dnsize {D}; stime -p"
+#define ABC_FAST_COMMAND_LUT "strash; dretime; if"
+#define ABC_FAST_COMMAND_SOP "strash; dretime; cover -I {I} -P {P}"
+#define ABC_FAST_COMMAND_DFL "strash; dretime; map"
#include "kernel/register.h"
#include "kernel/sigtools.h"
@@ -747,6 +747,10 @@ void abc_module(RTLIL::Design *design, RTLIL::Module *current_module, std::strin
else
abc_script += fast_mode ? ABC_FAST_COMMAND_DFL : ABC_COMMAND_DFL;
+ if (script_file.empty() && !delay_target.empty())
+ for (size_t pos = abc_script.find("dretime;"); pos != std::string::npos; pos = abc_script.find("dretime;", pos+1))
+ abc_script = abc_script.substr(0, pos) + "dretime; retime -o {D};" + abc_script.substr(pos+8);
+
for (size_t pos = abc_script.find("{D}"); pos != std::string::npos; pos = abc_script.find("{D}", pos))
abc_script = abc_script.substr(0, pos) + delay_target + abc_script.substr(pos+3);
@@ -1510,7 +1514,47 @@ struct AbcPass : public Pass {
#endif
#endif
- size_t argidx;
+ // get arguments from scratchpad first, then override by command arguments
+ std::string lut_arg, luts_arg, g_arg;
+ exe_file = design->scratchpad_get_string("abc.exe", exe_file /* inherit default value if not set */);
+ script_file = design->scratchpad_get_string("abc.script", script_file);
+ liberty_file = design->scratchpad_get_string("abc.liberty", liberty_file);
+ constr_file = design->scratchpad_get_string("abc.constr", constr_file);
+ if (design->scratchpad.count("abc.D")) {
+ delay_target = "-D " + design->scratchpad_get_string("abc.D");
+ }
+ if (design->scratchpad.count("abc.I")) {
+ sop_inputs = "-I " + design->scratchpad_get_string("abc.I");
+ }
+ if (design->scratchpad.count("abc.P")) {
+ sop_products = "-P " + design->scratchpad_get_string("abc.P");
+ }
+ if (design->scratchpad.count("abc.S")) {
+ lutin_shared = "-S " + design->scratchpad_get_string("abc.S");
+ }
+ lut_arg = design->scratchpad_get_string("abc.lut", lut_arg);
+ luts_arg = design->scratchpad_get_string("abc.luts", luts_arg);
+ sop_mode = design->scratchpad_get_bool("abc.sop", sop_mode);
+ map_mux4 = design->scratchpad_get_bool("abc.mux4", map_mux4);
+ map_mux8 = design->scratchpad_get_bool("abc.mux8", map_mux8);
+ map_mux16 = design->scratchpad_get_bool("abc.mux16", map_mux16);
+ abc_dress = design->scratchpad_get_bool("abc.dress", abc_dress);
+ g_arg = design->scratchpad_get_string("abc.g", g_arg);
+
+ fast_mode = design->scratchpad_get_bool("abc.fast", fast_mode);
+ dff_mode = design->scratchpad_get_bool("abc.dff", dff_mode);
+ if (design->scratchpad.count("abc.clk")) {
+ clk_str = design->scratchpad_get_string("abc.clk");
+ dff_mode = true;
+ }
+ keepff = design->scratchpad_get_bool("abc.keepff", keepff);
+ cleanup = !design->scratchpad_get_bool("abc.nocleanup", !cleanup);
+ keepff = design->scratchpad_get_bool("abc.keepff", keepff);
+ show_tempdir = design->scratchpad_get_bool("abc.showtmp", show_tempdir);
+ markgroups = design->scratchpad_get_bool("abc.markgroups", markgroups);
+
+ size_t argidx, g_argidx;
+ bool g_arg_from_cmd = false;
char pwd [PATH_MAX];
if (!getcwd(pwd, sizeof(pwd))) {
log_cmd_error("getcwd failed: %s\n", strerror(errno));
@@ -1524,23 +1568,14 @@ struct AbcPass : public Pass {
}
if (arg == "-script" && argidx+1 < args.size()) {
script_file = args[++argidx];
- rewrite_filename(script_file);
- if (!script_file.empty() && !is_absolute_path(script_file) && script_file[0] != '+')
- script_file = std::string(pwd) + "/" + script_file;
continue;
}
if (arg == "-liberty" && argidx+1 < args.size()) {
liberty_file = args[++argidx];
- rewrite_filename(liberty_file);
- if (!liberty_file.empty() && !is_absolute_path(liberty_file))
- liberty_file = std::string(pwd) + "/" + liberty_file;
continue;
}
if (arg == "-constr" && argidx+1 < args.size()) {
- rewrite_filename(constr_file);
constr_file = args[++argidx];
- if (!constr_file.empty() && !is_absolute_path(constr_file))
- constr_file = std::string(pwd) + "/" + constr_file;
continue;
}
if (arg == "-D" && argidx+1 < args.size()) {
@@ -1560,37 +1595,11 @@ struct AbcPass : public Pass {
continue;
}
if (arg == "-lut" && argidx+1 < args.size()) {
- string arg = args[++argidx];
- size_t pos = arg.find_first_of(':');
- int lut_mode = 0, lut_mode2 = 0;
- if (pos != string::npos) {
- lut_mode = atoi(arg.substr(0, pos).c_str());
- lut_mode2 = atoi(arg.substr(pos+1).c_str());
- } else {
- lut_mode = atoi(arg.c_str());
- lut_mode2 = lut_mode;
- }
- lut_costs.clear();
- for (int i = 0; i < lut_mode; i++)
- lut_costs.push_back(1);
- for (int i = lut_mode; i < lut_mode2; i++)
- lut_costs.push_back(2 << (i - lut_mode));
+ lut_arg = args[++argidx];
continue;
}
if (arg == "-luts" && argidx+1 < args.size()) {
- lut_costs.clear();
- for (auto &tok : split_tokens(args[++argidx], ",")) {
- auto parts = split_tokens(tok, ":");
- if (GetSize(parts) == 0 && !lut_costs.empty())
- lut_costs.push_back(lut_costs.back());
- else if (GetSize(parts) == 1)
- lut_costs.push_back(atoi(parts.at(0).c_str()));
- else if (GetSize(parts) == 2)
- while (GetSize(lut_costs) < std::atoi(parts.at(0).c_str()))
- lut_costs.push_back(atoi(parts.at(1).c_str()));
- else
- log_cmd_error("Invalid -luts syntax.\n");
- }
+ luts_arg = args[++argidx];
continue;
}
if (arg == "-sop") {
@@ -1614,123 +1623,11 @@ struct AbcPass : public Pass {
continue;
}
if (arg == "-g" && argidx+1 < args.size()) {
- for (auto g : split_tokens(args[++argidx], ",")) {
- vector<string> gate_list;
- bool remove_gates = false;
- if (GetSize(g) > 0 && g[0] == '-') {
- remove_gates = true;
- g = g.substr(1);
- }
- if (g == "AND") goto ok_gate;
- if (g == "NAND") goto ok_gate;
- if (g == "OR") goto ok_gate;
- if (g == "NOR") goto ok_gate;
- if (g == "XOR") goto ok_gate;
- if (g == "XNOR") goto ok_gate;
- if (g == "ANDNOT") goto ok_gate;
- if (g == "ORNOT") goto ok_gate;
- if (g == "MUX") goto ok_gate;
- if (g == "NMUX") goto ok_gate;
- if (g == "AOI3") goto ok_gate;
- if (g == "OAI3") goto ok_gate;
- if (g == "AOI4") goto ok_gate;
- if (g == "OAI4") goto ok_gate;
- if (g == "simple") {
- gate_list.push_back("AND");
- gate_list.push_back("OR");
- gate_list.push_back("XOR");
- gate_list.push_back("MUX");
- goto ok_alias;
- }
- if (g == "cmos2") {
- if (!remove_gates)
- cmos_cost = true;
- gate_list.push_back("NAND");
- gate_list.push_back("NOR");
- goto ok_alias;
- }
- if (g == "cmos3") {
- if (!remove_gates)
- cmos_cost = true;
- gate_list.push_back("NAND");
- gate_list.push_back("NOR");
- gate_list.push_back("AOI3");
- gate_list.push_back("OAI3");
- goto ok_alias;
- }
- if (g == "cmos4") {
- if (!remove_gates)
- cmos_cost = true;
- gate_list.push_back("NAND");
- gate_list.push_back("NOR");
- gate_list.push_back("AOI3");
- gate_list.push_back("OAI3");
- gate_list.push_back("AOI4");
- gate_list.push_back("OAI4");
- goto ok_alias;
- }
- if (g == "cmos") {
- if (!remove_gates)
- cmos_cost = true;
- gate_list.push_back("NAND");
- gate_list.push_back("NOR");
- gate_list.push_back("AOI3");
- gate_list.push_back("OAI3");
- gate_list.push_back("AOI4");
- gate_list.push_back("OAI4");
- gate_list.push_back("NMUX");
- gate_list.push_back("MUX");
- gate_list.push_back("XOR");
- gate_list.push_back("XNOR");
- goto ok_alias;
- }
- if (g == "gates") {
- gate_list.push_back("AND");
- gate_list.push_back("NAND");
- gate_list.push_back("OR");
- gate_list.push_back("NOR");
- gate_list.push_back("XOR");
- gate_list.push_back("XNOR");
- gate_list.push_back("ANDNOT");
- gate_list.push_back("ORNOT");
- goto ok_alias;
- }
- if (g == "aig") {
- gate_list.push_back("AND");
- gate_list.push_back("NAND");
- gate_list.push_back("OR");
- gate_list.push_back("NOR");
- gate_list.push_back("ANDNOT");
- gate_list.push_back("ORNOT");
- goto ok_alias;
- }
- if (g == "all") {
- gate_list.push_back("AND");
- gate_list.push_back("NAND");
- gate_list.push_back("OR");
- gate_list.push_back("NOR");
- gate_list.push_back("XOR");
- gate_list.push_back("XNOR");
- gate_list.push_back("ANDNOT");
- gate_list.push_back("ORNOT");
- gate_list.push_back("AOI3");
- gate_list.push_back("OAI3");
- gate_list.push_back("AOI4");
- gate_list.push_back("OAI4");
- gate_list.push_back("MUX");
- gate_list.push_back("NMUX");
- }
- cmd_error(args, argidx, stringf("Unsupported gate type: %s", g.c_str()));
- ok_gate:
- gate_list.push_back(g);
- ok_alias:
- for (auto gate : gate_list) {
- if (remove_gates)
- enabled_gates.erase(gate);
- else
- enabled_gates.insert(gate);
- }
- }
+ if (g_arg_from_cmd)
+ log_cmd_error("Can only use -g once. Please combine.");
+ g_arg = args[++argidx];
+ g_argidx = argidx;
+ g_arg_from_cmd = true;
continue;
}
if (arg == "-fast") {
@@ -1766,8 +1663,176 @@ struct AbcPass : public Pass {
}
extra_args(args, argidx, design);
+ rewrite_filename(script_file);
+ if (!script_file.empty() && !is_absolute_path(script_file) && script_file[0] != '+')
+ script_file = std::string(pwd) + "/" + script_file;
+ rewrite_filename(liberty_file);
+ if (!liberty_file.empty() && !is_absolute_path(liberty_file))
+ liberty_file = std::string(pwd) + "/" + liberty_file;
+ rewrite_filename(constr_file);
+ if (!constr_file.empty() && !is_absolute_path(constr_file))
+ constr_file = std::string(pwd) + "/" + constr_file;
+
+ // handle -lut argument
+ if (!lut_arg.empty()) {
+ size_t pos = lut_arg.find_first_of(':');
+ int lut_mode = 0, lut_mode2 = 0;
+ if (pos != string::npos) {
+ lut_mode = atoi(lut_arg.substr(0, pos).c_str());
+ lut_mode2 = atoi(lut_arg.substr(pos+1).c_str());
+ } else {
+ lut_mode = atoi(lut_arg.c_str());
+ lut_mode2 = lut_mode;
+ }
+ lut_costs.clear();
+ for (int i = 0; i < lut_mode; i++)
+ lut_costs.push_back(1);
+ for (int i = lut_mode; i < lut_mode2; i++)
+ lut_costs.push_back(2 << (i - lut_mode));
+ }
+ //handle -luts argument
+ if (!luts_arg.empty()){
+ lut_costs.clear();
+ for (auto &tok : split_tokens(luts_arg, ",")) {
+ auto parts = split_tokens(tok, ":");
+ if (GetSize(parts) == 0 && !lut_costs.empty())
+ lut_costs.push_back(lut_costs.back());
+ else if (GetSize(parts) == 1)
+ lut_costs.push_back(atoi(parts.at(0).c_str()));
+ else if (GetSize(parts) == 2)
+ while (GetSize(lut_costs) < std::atoi(parts.at(0).c_str()))
+ lut_costs.push_back(atoi(parts.at(1).c_str()));
+ else
+ log_cmd_error("Invalid -luts syntax.\n");
+ }
+ }
+
+ // handle -g argument
+ if (!g_arg.empty()){
+ for (auto g : split_tokens(g_arg, ",")) {
+ vector<string> gate_list;
+ bool remove_gates = false;
+ if (GetSize(g) > 0 && g[0] == '-') {
+ remove_gates = true;
+ g = g.substr(1);
+ }
+ if (g == "AND") goto ok_gate;
+ if (g == "NAND") goto ok_gate;
+ if (g == "OR") goto ok_gate;
+ if (g == "NOR") goto ok_gate;
+ if (g == "XOR") goto ok_gate;
+ if (g == "XNOR") goto ok_gate;
+ if (g == "ANDNOT") goto ok_gate;
+ if (g == "ORNOT") goto ok_gate;
+ if (g == "MUX") goto ok_gate;
+ if (g == "NMUX") goto ok_gate;
+ if (g == "AOI3") goto ok_gate;
+ if (g == "OAI3") goto ok_gate;
+ if (g == "AOI4") goto ok_gate;
+ if (g == "OAI4") goto ok_gate;
+ if (g == "simple") {
+ gate_list.push_back("AND");
+ gate_list.push_back("OR");
+ gate_list.push_back("XOR");
+ gate_list.push_back("MUX");
+ goto ok_alias;
+ }
+ if (g == "cmos2") {
+ if (!remove_gates)
+ cmos_cost = true;
+ gate_list.push_back("NAND");
+ gate_list.push_back("NOR");
+ goto ok_alias;
+ }
+ if (g == "cmos3") {
+ if (!remove_gates)
+ cmos_cost = true;
+ gate_list.push_back("NAND");
+ gate_list.push_back("NOR");
+ gate_list.push_back("AOI3");
+ gate_list.push_back("OAI3");
+ goto ok_alias;
+ }
+ if (g == "cmos4") {
+ if (!remove_gates)
+ cmos_cost = true;
+ gate_list.push_back("NAND");
+ gate_list.push_back("NOR");
+ gate_list.push_back("AOI3");
+ gate_list.push_back("OAI3");
+ gate_list.push_back("AOI4");
+ gate_list.push_back("OAI4");
+ goto ok_alias;
+ }
+ if (g == "cmos") {
+ if (!remove_gates)
+ cmos_cost = true;
+ gate_list.push_back("NAND");
+ gate_list.push_back("NOR");
+ gate_list.push_back("AOI3");
+ gate_list.push_back("OAI3");
+ gate_list.push_back("AOI4");
+ gate_list.push_back("OAI4");
+ gate_list.push_back("NMUX");
+ gate_list.push_back("MUX");
+ gate_list.push_back("XOR");
+ gate_list.push_back("XNOR");
+ goto ok_alias;
+ }
+ if (g == "gates") {
+ gate_list.push_back("AND");
+ gate_list.push_back("NAND");
+ gate_list.push_back("OR");
+ gate_list.push_back("NOR");
+ gate_list.push_back("XOR");
+ gate_list.push_back("XNOR");
+ gate_list.push_back("ANDNOT");
+ gate_list.push_back("ORNOT");
+ goto ok_alias;
+ }
+ if (g == "aig") {
+ gate_list.push_back("AND");
+ gate_list.push_back("NAND");
+ gate_list.push_back("OR");
+ gate_list.push_back("NOR");
+ gate_list.push_back("ANDNOT");
+ gate_list.push_back("ORNOT");
+ goto ok_alias;
+ }
+ if (g == "all") {
+ gate_list.push_back("AND");
+ gate_list.push_back("NAND");
+ gate_list.push_back("OR");
+ gate_list.push_back("NOR");
+ gate_list.push_back("XOR");
+ gate_list.push_back("XNOR");
+ gate_list.push_back("ANDNOT");
+ gate_list.push_back("ORNOT");
+ gate_list.push_back("AOI3");
+ gate_list.push_back("OAI3");
+ gate_list.push_back("AOI4");
+ gate_list.push_back("OAI4");
+ gate_list.push_back("MUX");
+ gate_list.push_back("NMUX");
+ }
+ if (g_arg_from_cmd)
+ cmd_error(args, g_argidx, stringf("Unsupported gate type: %s", g.c_str()));
+ else
+ log_cmd_error("Unsupported gate type: %s", g.c_str());
+ ok_gate:
+ gate_list.push_back(g);
+ ok_alias:
+ for (auto gate : gate_list) {
+ if (remove_gates)
+ enabled_gates.erase(gate);
+ else
+ enabled_gates.insert(gate);
+ }
+ }
+ }
+
if (!lut_costs.empty() && !liberty_file.empty())
- log_cmd_error("Got -lut and -liberty! This two options are exclusive.\n");
+ log_cmd_error("Got -lut and -liberty! These two options are exclusive.\n");
if (!constr_file.empty() && liberty_file.empty())
log_cmd_error("Got -constr but no -liberty!\n");
diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc
index d03e5da8e..1f6cdaa22 100644
--- a/passes/techmap/abc9.cc
+++ b/passes/techmap/abc9.cc
@@ -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/sigtools.h"
#include "kernel/celltypes.h"
@@ -63,22 +49,16 @@ extern "C" int Abc_RealMain(int argc, char *argv[]);
USING_YOSYS_NAMESPACE
PRIVATE_NAMESPACE_BEGIN
-bool markgroups;
int map_autoidx;
-SigMap assign_map;
-RTLIL::Module *module;
-
-bool clk_polarity, en_polarity;
-RTLIL::SigSpec clk_sig, en_sig;
inline std::string remap_name(RTLIL::IdString abc9_name)
{
return stringf("$abc$%d$%s", map_autoidx, abc9_name.c_str()+1);
}
-void handle_loops(RTLIL::Design *design)
+void handle_loops(RTLIL::Design *design, RTLIL::Module *module)
{
- Pass::call(design, "scc -set_attr abc9_scc_id {}");
+ Pass::call(design, "scc -set_attr abc9_scc_id {} % w:*");
// For every unique SCC found, (arbitrarily) find the first
// cell in the component, and select (and mark) all its output
@@ -253,49 +233,14 @@ struct abc9_output_filter
}
};
-void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::string script_file, std::string exe_file,
- bool cleanup, vector<int> lut_costs, bool dff_mode, std::string clk_str,
- bool /*keepff*/, std::string delay_target, std::string /*lutin_shared*/, bool fast_mode,
+void abc9_module(RTLIL::Design *design, RTLIL::Module *module, std::string script_file, std::string exe_file,
+ bool cleanup, 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, const dict<int,IdString> &box_lookup, bool nomfs
+ std::string wire_delay
)
{
- module = current_module;
map_autoidx = autoidx++;
- if (clk_str != "$")
- {
- clk_polarity = true;
- clk_sig = RTLIL::SigSpec();
-
- en_polarity = true;
- en_sig = RTLIL::SigSpec();
- }
-
- if (!clk_str.empty() && clk_str != "$")
- {
- if (clk_str.find(',') != std::string::npos) {
- int pos = clk_str.find(',');
- std::string en_str = clk_str.substr(pos+1);
- clk_str = clk_str.substr(0, pos);
- if (en_str[0] == '!') {
- en_polarity = false;
- en_str = en_str.substr(1);
- }
- if (module->wires_.count(RTLIL::escape_id(en_str)) != 0)
- en_sig = assign_map(RTLIL::SigSpec(module->wires_.at(RTLIL::escape_id(en_str)), 0));
- }
- if (clk_str[0] == '!') {
- clk_polarity = false;
- clk_str = clk_str.substr(1);
- }
- if (module->wires_.count(RTLIL::escape_id(clk_str)) != 0)
- clk_sig = assign_map(RTLIL::SigSpec(module->wires_.at(RTLIL::escape_id(clk_str)), 0));
- }
-
- if (dff_mode && clk_sig.empty())
- log_cmd_error("Clock domain %s not found.\n", clk_str.c_str());
-
std::string tempdir_name = "/tmp/yosys-abc-XXXXXX";
if (!cleanup)
tempdir_name[0] = tempdir_name[4] = '_';
@@ -308,13 +253,13 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri
if (!lut_costs.empty()) {
abc9_script += stringf("read_lut %s/lutdefs.txt; ", tempdir_name.c_str());
if (!box_file.empty())
- abc9_script += stringf("read_box -v %s; ", box_file.c_str());
+ abc9_script += stringf("read_box %s; ", box_file.c_str());
}
else
if (!lut_file.empty()) {
abc9_script += stringf("read_lut %s; ", lut_file.c_str());
if (!box_file.empty())
- abc9_script += stringf("read_box -v %s; ", box_file.c_str());
+ abc9_script += stringf("read_box %s; ", box_file.c_str());
}
else
log_abort();
@@ -333,20 +278,11 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri
} else
abc9_script += stringf("source %s", script_file.c_str());
} else if (!lut_costs.empty() || !lut_file.empty()) {
- //bool all_luts_cost_same = true;
- //for (int this_cost : lut_costs)
- // if (this_cost != lut_costs.front())
- // all_luts_cost_same = false;
- abc9_script += fast_mode ? ABC_FAST_COMMAND_LUT : ABC_COMMAND_LUT;
- //if (all_luts_cost_same && !fast_mode)
- // abc9_script += "; lutpack {S}";
+ 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();
- //if (script_file.empty() && !delay_target.empty())
- // for (size_t pos = abc9_script.find("dretime;"); pos != std::string::npos; pos = abc9_script.find("dretime;", pos+1))
- // abc9_script = abc9_script.substr(0, pos) + "dretime; retime -o {D};" + abc9_script.substr(pos+8);
-
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);
@@ -356,11 +292,26 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri
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"));
-
- abc9_script += stringf("; &write %s/output.aig", tempdir_name.c_str());
+ 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);
+
+ 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++)
@@ -371,45 +322,22 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri
fprintf(f, "%s\n", abc9_script.c_str());
fclose(f);
- if (dff_mode || !clk_str.empty())
- {
- if (clk_sig.size() == 0)
- log("No%s clock domain found. Not extracting any FF cells.\n", clk_str.empty() ? "" : " matching");
- else {
- log("Found%s %s clock domain: %s", clk_str.empty() ? "" : " matching", clk_polarity ? "posedge" : "negedge", log_signal(clk_sig));
- if (en_sig.size() != 0)
- log(", enabled by %s%s", en_polarity ? "" : "!", log_signal(en_sig));
- log("\n");
- }
- }
-
- bool count_output = false;
- for (auto port_name : module->ports) {
- RTLIL::Wire *port_wire = module->wire(port_name);
- log_assert(port_wire);
- if (port_wire->port_output) {
- count_output = true;
- break;
- }
- }
-
log_push();
- if (count_output)
- {
- design->selection_stack.emplace_back(false);
- RTLIL::Selection& sel = design->selection_stack.back();
- sel.select(module);
-
- handle_loops(design);
+ handle_loops(design, module);
- Pass::call(design, "aigmap");
+ Pass::call(design, "aigmap -select");
- //log("Extracted %d gates and %d wires to a netlist network with %d inputs and %d outputs.\n",
- // count_gates, GetSize(signal_list), count_input, count_output);
+ Pass::call(design, stringf("write_xaiger -map %s/input.sym %s/input.xaig", tempdir_name.c_str(), tempdir_name.c_str()));
- Pass::call(design, stringf("write_xaiger -map %s/input.sym %s/input.xaig", tempdir_name.c_str(), tempdir_name.c_str()));
+ int count_outputs = 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",
+ design->scratchpad_get_int("write_xaiger.num_ands"),
+ design->scratchpad_get_int("write_xaiger.num_wires"),
+ design->scratchpad_get_int("write_xaiger.num_inputs"),
+ count_outputs);
+ if (count_outputs > 0) {
std::string buffer;
std::ifstream ifs;
#if 0
@@ -424,12 +352,10 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri
reader.parse_xaiger();
}
ifs.close();
- Pass::call(design, stringf("write_verilog -noexpr -norename"));
+ Pass::call_on_module(design, design->module(ID($__abc9__)), stringf("write_verilog -noexpr -norename -selected"));
design->remove(design->module(ID($__abc9__)));
#endif
- design->selection_stack.pop_back();
-
log_header(design, "Executing ABC9.\n");
if (!lut_costs.empty()) {
@@ -475,11 +401,11 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri
log_assert(!design->module(ID($__abc9__)));
AigerReader reader(design, ifs, ID($__abc9__), "" /* clk_name */, buffer.c_str() /* map_filename */, true /* wideports */);
- reader.parse_xaiger(box_lookup);
+ reader.parse_xaiger();
ifs.close();
#if 0
- Pass::call(design, stringf("write_verilog -noexpr -norename"));
+ Pass::call_on_module(design, design->module(ID($__abc9__)), stringf("write_verilog -noexpr -norename -selected"));
#endif
log_header(design, "Re-integrating ABC9 results.\n");
@@ -487,43 +413,30 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri
if (mapped_mod == NULL)
log_error("ABC output file does not contain a module `$__abc9__'.\n");
- pool<RTLIL::SigBit> output_bits;
- for (auto &it : mapped_mod->wires_) {
- RTLIL::Wire *w = it.second;
- RTLIL::Wire *remap_wire = module->addWire(remap_name(w->name), GetSize(w));
- if (markgroups) remap_wire->attributes[ID(abcgroup)] = map_autoidx;
- if (w->port_output) {
- RTLIL::Wire *wire = module->wire(w->name);
- log_assert(wire);
- for (int i = 0; i < GetSize(w); i++)
- output_bits.insert({wire, i});
- }
- }
-
- for (auto &it : module->connections_) {
- auto &signal = it.first;
- auto bits = signal.bits();
- for (auto &b : bits)
- if (output_bits.count(b))
- b = module->addWire(NEW_ID);
- signal = std::move(bits);
- }
+ for (auto w : mapped_mod->wires())
+ module->addWire(remap_name(w->name), GetSize(w));
dict<IdString, bool> abc9_box;
vector<RTLIL::Cell*> boxes;
- for (const auto &it : module->cells_) {
- auto cell = it.second;
- if (cell->type.in(ID($_AND_), ID($_NOT_))) {
+ for (auto cell : module->cells().to_vector()) {
+ if (cell->type.in(ID($_AND_), ID($_NOT_), ID($__ABC9_FF_))) {
module->remove(cell);
continue;
}
+ RTLIL::Module* box_module = design->module(cell->type);
auto jt = abc9_box.find(cell->type);
- if (jt == abc9_box.end()) {
- RTLIL::Module* box_module = design->module(cell->type);
+ if (jt == abc9_box.end())
jt = abc9_box.insert(std::make_pair(cell->type, box_module && box_module->attributes.count(ID(abc9_box_id)))).first;
+ if (jt->second) {
+ if (box_module->get_bool_attribute("\\abc9_flop")) {
+ if (dff_mode)
+ boxes.emplace_back(cell);
+ else
+ box_module->set_bool_attribute("\\abc9_keep", false);
+ }
+ else
+ boxes.emplace_back(cell);
}
- if (jt->second)
- boxes.emplace_back(cell);
}
dict<SigBit, pool<IdString>> bit_drivers, bit_users;
@@ -532,19 +445,19 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri
dict<SigBit, std::vector<RTLIL::Cell*>> bit2sinks;
std::map<IdString, int> cell_stats;
- for (auto c : mapped_mod->cells())
+ for (auto mapped_cell : mapped_mod->cells())
{
- toposort.node(c->name);
+ toposort.node(mapped_cell->name);
RTLIL::Cell *cell = nullptr;
- if (c->type == ID($_NOT_)) {
- RTLIL::SigBit a_bit = c->getPort(ID::A);
- RTLIL::SigBit y_bit = c->getPort(ID::Y);
- bit_users[a_bit].insert(c->name);
- bit_drivers[y_bit].insert(c->name);
+ if (mapped_cell->type == ID($_NOT_)) {
+ 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);
if (!a_bit.wire) {
- c->setPort(ID::Y, module->addWire(NEW_ID));
+ mapped_cell->setPort(ID::Y, module->addWire(NEW_ID));
RTLIL::Wire *wire = module->wire(remap_name(y_bit.wire->name));
log_assert(wire);
module->connect(RTLIL::SigBit(wire, y_bit.offset), State::S1);
@@ -559,16 +472,16 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri
// (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
- cell = module->addLut(remap_name(stringf("%s$lut", c->name.c_str())),
+ 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"));
@@ -576,44 +489,46 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri
cell_stats[ID($lut)]++;
}
else
- not2drivers[c] = driver_lut;
+ not2drivers[mapped_cell] = driver_lut;
continue;
}
else
log_abort();
- if (cell && markgroups) cell->attributes[ID(abcgroup)] = map_autoidx;
continue;
}
- cell_stats[c->type]++;
+ cell_stats[mapped_cell->type]++;
RTLIL::Cell *existing_cell = nullptr;
- if (c->type == ID($lut)) {
- if (GetSize(c->getPort(ID::A)) == 1 && c->getParam(ID(LUT)) == RTLIL::Const::from_string("01")) {
- SigSpec my_a = module->wires_.at(remap_name(c->getPort(ID::A).as_wire()->name));
- SigSpec my_y = module->wires_.at(remap_name(c->getPort(ID::Y).as_wire()->name));
+ if (mapped_cell->type.in(ID($lut), ID($__ABC9_FF_))) {
+ if (mapped_cell->type == ID($lut) &&
+ GetSize(mapped_cell->getPort(ID::A)) == 1 &&
+ mapped_cell->getParam(ID(LUT)) == RTLIL::Const::from_string("01")) {
+ SigSpec my_a = module->wires_.at(remap_name(mapped_cell->getPort(ID::A).as_wire()->name));
+ SigSpec my_y = module->wires_.at(remap_name(mapped_cell->getPort(ID::Y).as_wire()->name));
module->connect(my_y, my_a);
- if (markgroups) c->attributes[ID(abcgroup)] = map_autoidx;
log_abort();
continue;
}
- cell = module->addCell(remap_name(c->name), c->type);
+ cell = module->addCell(remap_name(mapped_cell->name), mapped_cell->type);
}
else {
- existing_cell = module->cell(c->name);
+ existing_cell = module->cell(mapped_cell->name);
log_assert(existing_cell);
- cell = module->addCell(remap_name(c->name), c->type);
+ cell = module->addCell(remap_name(mapped_cell->name), mapped_cell->type);
}
- if (markgroups) cell->attributes[ID(abcgroup)] = map_autoidx;
if (existing_cell) {
cell->parameters = existing_cell->parameters;
cell->attributes = existing_cell->attributes;
}
else {
- cell->parameters = c->parameters;
- cell->attributes = c->attributes;
+ cell->parameters = mapped_cell->parameters;
+ cell->attributes = mapped_cell->attributes;
}
- for (auto &conn : c->connections()) {
+
+ RTLIL::Module* box_module = design->module(mapped_cell->type);
+ auto abc9_flop = box_module && box_module->get_bool_attribute("\\abc9_flop");
+ for (auto &conn : mapped_cell->connections()) {
RTLIL::SigSpec newsig;
for (auto c : conn.second.chunks()) {
if (c.width == 0)
@@ -625,15 +540,17 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri
}
cell->setPort(conn.first, newsig);
- if (cell->input(conn.first)) {
- for (auto i : newsig)
- bit2sinks[i].push_back(cell);
- for (auto i : conn.second)
- bit_users[i].insert(c->name);
+ if (!abc9_flop) {
+ if (cell->input(conn.first)) {
+ for (auto i : newsig)
+ bit2sinks[i].push_back(cell);
+ for (auto i : conn.second)
+ bit_users[i].insert(mapped_cell->name);
+ }
+ if (cell->output(conn.first))
+ for (auto i : conn.second)
+ bit_drivers[i].insert(mapped_cell->name);
}
- if (cell->output(conn.first))
- for (auto i : conn.second)
- bit_drivers[i].insert(c->name);
}
}
@@ -814,6 +731,51 @@ clone_lut:
struct Abc9Pass : public Pass {
Abc9Pass() : Pass("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---|
@@ -821,7 +783,7 @@ struct Abc9Pass : public Pass {
log(" abc9 [options] [selection]\n");
log("\n");
log("This pass uses the ABC tool [1] for technology mapping of yosys's internal gate\n");
- log("library to a target architecture.\n");
+ log("library to a target architecture. Only fully-selected modules are supported.\n");
log("\n");
log(" -exe <command>\n");
#ifdef ABCEXTERNAL
@@ -841,25 +803,20 @@ struct Abc9Pass : public Pass {
log("\n");
log(" if no -script parameter is given, the following scripts are used:\n");
log("\n");
- log(" for -lut/-luts (only one LUT size):\n");
- log("%s\n", fold_abc9_cmd(ABC_COMMAND_LUT /*"; lutpack {S}"*/).c_str());
- log("\n");
- log(" for -lut/-luts (different LUT sizes):\n");
- log("%s\n", fold_abc9_cmd(ABC_COMMAND_LUT).c_str());
+ log(" for -lut/-luts:\n");
+ 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("\n");
log(" for -lut/-luts:\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");
log(" replaced by this option when used, and an empty string otherwise\n");
log(" (indicating best possible delay).\n");
-// log(" This also replaces 'dretime' with 'dretime; retime -o {D}' in the\n");
-// log(" default scripts above.\n");
log("\n");
// log(" -S <num>\n");
// log(" maximum number of LUT inputs shared.\n");
@@ -881,19 +838,10 @@ struct Abc9Pass : public Pass {
log(" generate netlist using luts. Use the specified costs for luts with 1,\n");
log(" 2, 3, .. inputs.\n");
log("\n");
-// log(" -dff\n");
-// log(" also pass $_DFF_?_ and $_DFFE_??_ cells through ABC. modules with many\n");
-// log(" clock domains are automatically partitioned in clock domains and each\n");
-// log(" domain is passed through ABC independently.\n");
-// log("\n");
-// log(" -clk [!]<clock-signal-name>[,[!]<enable-signal-name>]\n");
-// log(" use only the specified clock domain. this is like -dff, but only FF\n");
-// log(" cells that belong to the specified clock domain are used.\n");
-// log("\n");
-// log(" -keepff\n");
-// log(" set the \"keep\" attribute on flip-flop output wires. (and thus preserve\n");
-// log(" them, for example for equivalence checking.)\n");
-// log("\n");
+ log(" -dff\n");
+ log(" also pass $_ABC9_FF_ cells through to ABC. modules with many clock\n");
+ log(" domains are marked as such and automatically partitioned by ABC.\n");
+ log("\n");
log(" -nocleanup\n");
log(" when this option is used, the temporary files created by this pass\n");
log(" are not removed. this is useful for debugging.\n");
@@ -902,11 +850,6 @@ struct Abc9Pass : public Pass {
log(" print the temp dir name in log. usually this is suppressed so that the\n");
log(" command output is identical across runs.\n");
log("\n");
- log(" -markgroups\n");
- log(" set a 'abcgroup' attribute on all objects created by ABC. The value of\n");
- log(" this attribute is a unique integer for each ABC process started. This\n");
- log(" is useful for debugging the partitioning of clock domains.\n");
- log("\n");
log(" -box <file>\n");
log(" pass this file with box library to ABC. Use with -lut.\n");
log("\n");
@@ -914,8 +857,8 @@ struct Abc9Pass : public Pass {
log("internally. This is not going to \"run ABC on your design\". It will instead run\n");
log("ABC on logic snippets extracted from your design. You will not get any useful\n");
log("output when passing an ABC script that writes a file. Instead write your full\n");
- log("design as BLIF file with write_blif and then load that into ABC externally if\n");
- log("you want to use ABC to convert your design into another format.\n");
+ log("design as an XAIGER file with `write_xaiger' and then load that into ABC\n");
+ log("externally if you want to use ABC to convert your design into another format.\n");
log("\n");
log("[1] http://www.eecs.berkeley.edu/~alanmi/abc/\n");
log("\n");
@@ -925,8 +868,6 @@ struct Abc9Pass : public Pass {
log_header(design, "Executing ABC9 pass (technology mapping using ABC9).\n");
log_push();
- assign_map.clear();
-
#ifdef ABCEXTERNAL
std::string exe_file = ABCEXTERNAL;
#else
@@ -934,11 +875,9 @@ struct Abc9Pass : public Pass {
#endif
std::string script_file, clk_str, box_file, lut_file;
std::string delay_target, lutin_shared = "-S 1", wire_delay;
- bool fast_mode = false, dff_mode = false, keepff = false, cleanup = true;
+ bool fast_mode = false, dff_mode = false, cleanup = true;
bool show_tempdir = false;
- bool nomfs = false;
vector<int> lut_costs;
- markgroups = false;
#if 0
cleanup = false;
@@ -952,6 +891,29 @@ struct Abc9Pass : public Pass {
#endif
#endif
+ // get arguments from scratchpad first, then override by command arguments
+ std::string lut_arg, luts_arg;
+ exe_file = design->scratchpad_get_string("abc9.exe", exe_file /* inherit default value if not set */);
+ script_file = design->scratchpad_get_string("abc9.script", script_file);
+ if (design->scratchpad.count("abc9.D")) {
+ delay_target = "-D " + design->scratchpad_get_string("abc9.D");
+ }
+ 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);
+ cleanup = !design->scratchpad_get_bool("abc9.nocleanup", !cleanup);
+ 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");
+ }
+
+ if (design->scratchpad_get_bool("abc9.debug")) {
+ cleanup = false;
+ show_tempdir = true;
+ }
+
size_t argidx;
char pwd [PATH_MAX];
if (!getcwd(pwd, sizeof(pwd))) {
@@ -966,9 +928,6 @@ struct Abc9Pass : public Pass {
}
if (arg == "-script" && argidx+1 < args.size()) {
script_file = args[++argidx];
- rewrite_filename(script_file);
- if (!script_file.empty() && !is_absolute_path(script_file) && script_file[0] != '+')
- script_file = std::string(pwd) + "/" + script_file;
continue;
}
if (arg == "-D" && argidx+1 < args.size()) {
@@ -980,64 +939,21 @@ struct Abc9Pass : public Pass {
// continue;
//}
if (arg == "-lut" && argidx+1 < args.size()) {
- string arg = args[++argidx];
- if (arg.find_first_not_of("0123456789:") == std::string::npos) {
- size_t pos = arg.find_first_of(':');
- int lut_mode = 0, lut_mode2 = 0;
- if (pos != string::npos) {
- lut_mode = atoi(arg.substr(0, pos).c_str());
- lut_mode2 = atoi(arg.substr(pos+1).c_str());
- } else {
- lut_mode = atoi(arg.c_str());
- lut_mode2 = lut_mode;
- }
- lut_costs.clear();
- for (int i = 0; i < lut_mode; i++)
- lut_costs.push_back(1);
- for (int i = lut_mode; i < lut_mode2; i++)
- lut_costs.push_back(2 << (i - lut_mode));
- }
- else {
- lut_file = arg;
- rewrite_filename(lut_file);
- if (!lut_file.empty() && !is_absolute_path(lut_file) && lut_file[0] != '+')
- lut_file = std::string(pwd) + "/" + lut_file;
- }
+ lut_arg = args[++argidx];
continue;
}
if (arg == "-luts" && argidx+1 < args.size()) {
- lut_costs.clear();
- for (auto &tok : split_tokens(args[++argidx], ",")) {
- auto parts = split_tokens(tok, ":");
- if (GetSize(parts) == 0 && !lut_costs.empty())
- lut_costs.push_back(lut_costs.back());
- else if (GetSize(parts) == 1)
- lut_costs.push_back(atoi(parts.at(0).c_str()));
- else if (GetSize(parts) == 2)
- while (GetSize(lut_costs) < atoi(parts.at(0).c_str()))
- lut_costs.push_back(atoi(parts.at(1).c_str()));
- else
- log_cmd_error("Invalid -luts syntax.\n");
- }
+ luts_arg = args[++argidx];
continue;
}
if (arg == "-fast") {
fast_mode = true;
continue;
}
- //if (arg == "-dff") {
- // dff_mode = true;
- // continue;
- //}
- //if (arg == "-clk" && argidx+1 < args.size()) {
- // clk_str = args[++argidx];
- // dff_mode = true;
- // continue;
- //}
- //if (arg == "-keepff") {
- // keepff = true;
- // continue;
- //}
+ if (arg == "-dff") {
+ dff_mode = true;
+ continue;
+ }
if (arg == "-nocleanup") {
cleanup = false;
continue;
@@ -1046,10 +962,6 @@ struct Abc9Pass : public Pass {
show_tempdir = true;
continue;
}
- if (arg == "-markgroups") {
- markgroups = true;
- continue;
- }
if (arg == "-box" && argidx+1 < args.size()) {
box_file = args[++argidx];
continue;
@@ -1058,14 +970,56 @@ struct Abc9Pass : public Pass {
wire_delay = "-W " + args[++argidx];
continue;
}
- if (arg == "-nomfs") {
- nomfs = true;
- continue;
- }
break;
}
extra_args(args, argidx, design);
+ rewrite_filename(script_file);
+ if (!script_file.empty() && !is_absolute_path(script_file) && script_file[0] != '+')
+ script_file = std::string(pwd) + "/" + script_file;
+
+ // handle -lut / -luts args
+ if (!lut_arg.empty()) {
+ string arg = lut_arg;
+ if (arg.find_first_not_of("0123456789:") == std::string::npos) {
+ size_t pos = arg.find_first_of(':');
+ int lut_mode = 0, lut_mode2 = 0;
+ if (pos != string::npos) {
+ lut_mode = atoi(arg.substr(0, pos).c_str());
+ lut_mode2 = atoi(arg.substr(pos+1).c_str());
+ } else {
+ lut_mode = atoi(arg.c_str());
+ lut_mode2 = lut_mode;
+ }
+ lut_costs.clear();
+ for (int i = 0; i < lut_mode; i++)
+ lut_costs.push_back(1);
+ for (int i = lut_mode; i < lut_mode2; i++)
+ lut_costs.push_back(2 << (i - lut_mode));
+ }
+ else {
+ lut_file = arg;
+ rewrite_filename(lut_file);
+ if (!lut_file.empty() && !is_absolute_path(lut_file) && lut_file[0] != '+')
+ lut_file = std::string(pwd) + "/" + lut_file;
+ }
+ }
+ if (!luts_arg.empty()) {
+ lut_costs.clear();
+ for (auto &tok : split_tokens(luts_arg, ",")) {
+ auto parts = split_tokens(tok, ":");
+ if (GetSize(parts) == 0 && !lut_costs.empty())
+ lut_costs.push_back(lut_costs.back());
+ else if (GetSize(parts) == 1)
+ lut_costs.push_back(atoi(parts.at(0).c_str()));
+ else if (GetSize(parts) == 2)
+ while (GetSize(lut_costs) < atoi(parts.at(0).c_str()))
+ lut_costs.push_back(atoi(parts.at(1).c_str()));
+ else
+ log_cmd_error("Invalid -luts syntax.\n");
+ }
+ }
+
// ABC expects a box file for XAIG
if (box_file.empty())
box_file = "+/dummy.box";
@@ -1074,235 +1028,65 @@ struct Abc9Pass : public Pass {
if (!box_file.empty() && !is_absolute_path(box_file) && box_file[0] != '+')
box_file = std::string(pwd) + "/" + box_file;
- dict<int,IdString> box_lookup;
- for (auto m : design->modules()) {
- auto it = m->attributes.find(ID(abc9_box_id));
- if (it == m->attributes.end())
- continue;
- if (m->name.begins_with("$paramod"))
- continue;
- auto id = it->second.as_int();
- auto r = box_lookup.insert(std::make_pair(id, m->name));
- if (!r.second)
- log_error("Module '%s' has the same abc9_box_id = %d value as '%s'.\n",
- log_id(m), id, log_id(r.first->second));
- log_assert(r.second);
-
- RTLIL::Wire *carry_in = nullptr, *carry_out = nullptr;
- for (auto p : m->ports) {
- auto w = m->wire(p);
- log_assert(w);
- if (w->attributes.count(ID(abc9_carry))) {
- if (w->port_input) {
- if (carry_in)
- log_error("Module '%s' contains more than one 'abc9_carry' input port.\n", log_id(m));
- carry_in = w;
- }
- else if (w->port_output) {
- if (carry_out)
- log_error("Module '%s' contains more than one 'abc9_carry' input port.\n", log_id(m));
- carry_out = w;
- }
- }
- }
- if (carry_in || carry_out) {
- if (carry_in && !carry_out)
- log_error("Module '%s' contains an 'abc9_carry' input port but no output port.\n", log_id(m));
- if (!carry_in && carry_out)
- log_error("Module '%s' contains an 'abc9_carry' output port but no input port.\n", log_id(m));
- // Make carry_in the last PI, and carry_out the last PO
- // since ABC requires it this way
- auto &ports = m->ports;
- for (auto it = ports.begin(); it != ports.end(); ) {
- RTLIL::Wire* w = m->wire(*it);
- log_assert(w);
- if (w == carry_in || w == carry_out) {
- it = ports.erase(it);
- continue;
- }
- if (w->port_id > carry_in->port_id)
- --w->port_id;
- if (w->port_id > carry_out->port_id)
- --w->port_id;
- log_assert(w->port_input || w->port_output);
- log_assert(ports[w->port_id-1] == w->name);
- ++it;
- }
- ports.push_back(carry_in->name);
- carry_in->port_id = ports.size();
- ports.push_back(carry_out->name);
- carry_out->port_id = ports.size();
- }
- }
-
- for (auto mod : design->selected_modules())
+ SigMap assign_map;
+ CellTypes ct(design);
+ for (auto module : design->selected_modules())
{
- if (mod->attributes.count(ID(abc9_box_id)))
- continue;
-
- if (mod->processes.size() > 0) {
- log("Skipping module %s as it contains processes.\n", log_id(mod));
- continue;
- }
-
- assign_map.set(mod);
-
- if (!dff_mode || !clk_str.empty()) {
- abc9_module(design, mod, script_file, exe_file, cleanup, lut_costs, dff_mode, clk_str, keepff,
- delay_target, lutin_shared, fast_mode, show_tempdir,
- box_file, lut_file, wire_delay, box_lookup, nomfs);
+ if (module->processes.size() > 0) {
+ log("Skipping module %s as it contains processes.\n", log_id(module));
continue;
}
+ log_assert(!module->attributes.count(ID(abc9_box_id)));
- CellTypes ct(design);
-
- std::vector<RTLIL::Cell*> all_cells = mod->selected_cells();
- std::set<RTLIL::Cell*> unassigned_cells(all_cells.begin(), all_cells.end());
-
- std::set<RTLIL::Cell*> expand_queue, next_expand_queue;
- std::set<RTLIL::Cell*> expand_queue_up, next_expand_queue_up;
- std::set<RTLIL::Cell*> expand_queue_down, next_expand_queue_down;
-
- typedef tuple<bool, RTLIL::SigSpec, bool, RTLIL::SigSpec> clkdomain_t;
- std::map<clkdomain_t, std::vector<RTLIL::Cell*>> assigned_cells;
- std::map<RTLIL::Cell*, clkdomain_t> assigned_cells_reverse;
-
- std::map<RTLIL::Cell*, std::set<RTLIL::SigBit>> cell_to_bit, cell_to_bit_up, cell_to_bit_down;
- std::map<RTLIL::SigBit, std::set<RTLIL::Cell*>> bit_to_cell, bit_to_cell_up, bit_to_cell_down;
-
- for (auto cell : all_cells)
- {
- clkdomain_t key;
-
- for (auto &conn : cell->connections())
- for (auto bit : conn.second) {
- bit = assign_map(bit);
- if (bit.wire != nullptr) {
- cell_to_bit[cell].insert(bit);
- bit_to_cell[bit].insert(cell);
- if (ct.cell_input(cell->type, conn.first)) {
- cell_to_bit_up[cell].insert(bit);
- bit_to_cell_down[bit].insert(cell);
- }
- if (ct.cell_output(cell->type, conn.first)) {
- cell_to_bit_down[cell].insert(bit);
- bit_to_cell_up[bit].insert(cell);
- }
- }
- }
-
- if (cell->type.in(ID($_DFF_N_), ID($_DFF_P_)))
- {
- key = clkdomain_t(cell->type == ID($_DFF_P_), assign_map(cell->getPort(ID(C))), true, RTLIL::SigSpec());
- }
- else
- if (cell->type.in(ID($_DFFE_NN_), ID($_DFFE_NP_), ID($_DFFE_PN_), ID($_DFFE_PP_)))
- {
- bool this_clk_pol = cell->type.in(ID($_DFFE_PN_), ID($_DFFE_PP_));
- bool this_en_pol = cell->type.in(ID($_DFFE_NP_), ID($_DFFE_PP_));
- key = clkdomain_t(this_clk_pol, assign_map(cell->getPort(ID(C))), this_en_pol, assign_map(cell->getPort(ID(E))));
- }
- else
- continue;
-
- unassigned_cells.erase(cell);
- expand_queue.insert(cell);
- expand_queue_up.insert(cell);
- expand_queue_down.insert(cell);
+ if (!design->selected_whole_module(module))
+ log_error("Can't handle partially selected module %s!\n", log_id(module));
- assigned_cells[key].push_back(cell);
- assigned_cells_reverse[cell] = key;
- }
+ assign_map.set(module);
- while (!expand_queue_up.empty() || !expand_queue_down.empty())
- {
- if (!expand_queue_up.empty())
- {
- RTLIL::Cell *cell = *expand_queue_up.begin();
- clkdomain_t key = assigned_cells_reverse.at(cell);
- expand_queue_up.erase(cell);
-
- for (auto bit : cell_to_bit_up[cell])
- for (auto c : bit_to_cell_up[bit])
- if (unassigned_cells.count(c)) {
- unassigned_cells.erase(c);
- next_expand_queue_up.insert(c);
- assigned_cells[key].push_back(c);
- assigned_cells_reverse[c] = key;
- expand_queue.insert(c);
- }
- }
+ typedef SigSpec clkdomain_t;
+ dict<clkdomain_t, int> clk_to_mergeability;
- if (!expand_queue_down.empty())
- {
- RTLIL::Cell *cell = *expand_queue_down.begin();
- clkdomain_t key = assigned_cells_reverse.at(cell);
- expand_queue_down.erase(cell);
-
- for (auto bit : cell_to_bit_down[cell])
- for (auto c : bit_to_cell_down[bit])
- if (unassigned_cells.count(c)) {
- unassigned_cells.erase(c);
- next_expand_queue_up.insert(c);
- assigned_cells[key].push_back(c);
- assigned_cells_reverse[c] = key;
- expand_queue.insert(c);
- }
- }
+ if (dff_mode)
+ for (auto cell : module->cells()) {
+ if (cell->type != "$__ABC9_FF_")
+ continue;
- if (expand_queue_up.empty() && expand_queue_down.empty()) {
- expand_queue_up.swap(next_expand_queue_up);
- expand_queue_down.swap(next_expand_queue_down);
+ Wire *abc9_clock_wire = module->wire(stringf("%s.clock", cell->name.c_str()));
+ if (abc9_clock_wire == NULL)
+ log_error("'%s.clock' is not a wire present in module '%s'.\n", cell->name.c_str(), log_id(module));
+ SigSpec abc9_clock = assign_map(abc9_clock_wire);
+
+ clkdomain_t key(abc9_clock);
+
+ auto r = clk_to_mergeability.insert(std::make_pair(abc9_clock, clk_to_mergeability.size() + 1));
+ auto r2 YS_ATTRIBUTE(unused) = cell->attributes.insert(std::make_pair(ID(abc9_mergeability), r.first->second));
+ log_assert(r2.second);
+
+ Wire *abc9_init_wire = module->wire(stringf("%s.init", cell->name.c_str()));
+ if (abc9_init_wire == NULL)
+ log_error("'%s.init' is not a wire present in module '%s'.\n", cell->name.c_str(), log_id(module));
+ log_assert(GetSize(abc9_init_wire) == 1);
+ SigSpec abc9_init = assign_map(abc9_init_wire);
+ if (!abc9_init.is_fully_const())
+ log_error("'%s.init' is not a constant wire present in module '%s'.\n", cell->name.c_str(), log_id(module));
+ r2 = cell->attributes.insert(std::make_pair(ID(abc9_init), abc9_init.as_const()));
+ log_assert(r2.second);
}
- }
-
- while (!expand_queue.empty())
- {
- RTLIL::Cell *cell = *expand_queue.begin();
- clkdomain_t key = assigned_cells_reverse.at(cell);
- expand_queue.erase(cell);
-
- for (auto bit : cell_to_bit.at(cell)) {
- for (auto c : bit_to_cell[bit])
- if (unassigned_cells.count(c)) {
- unassigned_cells.erase(c);
- next_expand_queue.insert(c);
- assigned_cells[key].push_back(c);
- assigned_cells_reverse[c] = key;
- }
- bit_to_cell[bit].clear();
+ else
+ for (auto cell : module->cells()) {
+ auto inst_module = design->module(cell->type);
+ if (!inst_module || !inst_module->get_bool_attribute("\\abc9_flop"))
+ continue;
+ cell->set_bool_attribute("\\abc9_keep");
}
- if (expand_queue.empty())
- expand_queue.swap(next_expand_queue);
- }
-
- clkdomain_t key(true, RTLIL::SigSpec(), true, RTLIL::SigSpec());
- for (auto cell : unassigned_cells) {
- assigned_cells[key].push_back(cell);
- assigned_cells_reverse[cell] = key;
- }
-
- log_header(design, "Summary of detected clock domains:\n");
- for (auto &it : assigned_cells)
- log(" %d cells in clk=%s%s, en=%s%s\n", GetSize(it.second),
- std::get<0>(it.first) ? "" : "!", log_signal(std::get<1>(it.first)),
- std::get<2>(it.first) ? "" : "!", log_signal(std::get<3>(it.first)));
-
- for (auto &it : assigned_cells) {
- clk_polarity = std::get<0>(it.first);
- clk_sig = assign_map(std::get<1>(it.first));
- en_polarity = std::get<2>(it.first);
- en_sig = assign_map(std::get<3>(it.first));
- abc9_module(design, mod, script_file, exe_file, cleanup, lut_costs, !clk_sig.empty(), "$",
- keepff, delay_target, lutin_shared, fast_mode, show_tempdir,
- box_file, lut_file, wire_delay, box_lookup, nomfs);
- assign_map.set(mod);
- }
+ design->selected_active_module = module->name.str();
+ abc9_module(design, module, script_file, exe_file, cleanup, lut_costs, dff_mode,
+ delay_target, lutin_shared, fast_mode, show_tempdir,
+ box_file, lut_file, wire_delay);
+ design->selected_active_module.clear();
}
- assign_map.clear();
-
log_pop();
}
} Abc9Pass;
diff --git a/passes/techmap/iopadmap.cc b/passes/techmap/iopadmap.cc
index 47da98b06..531ac2b99 100644
--- a/passes/techmap/iopadmap.cc
+++ b/passes/techmap/iopadmap.cc
@@ -234,6 +234,9 @@ struct IopadmapPass : public Pass {
SigBit wire_bit(wire, i);
Cell *tbuf_cell = nullptr;
+ if (skip_wire_bits.count(wire_bit))
+ continue;
+
if (tbuf_bits.count(wire_bit))
tbuf_cell = tbuf_bits.at(wire_bit);