aboutsummaryrefslogtreecommitdiffstats
path: root/passes
diff options
context:
space:
mode:
Diffstat (limited to 'passes')
-rw-r--r--passes/cmds/bugpoint.cc18
-rw-r--r--passes/cmds/design.cc10
-rw-r--r--passes/cmds/select.cc35
-rw-r--r--passes/hierarchy/hierarchy.cc30
-rw-r--r--passes/pmgen/ice40_dsp.cc8
-rw-r--r--passes/pmgen/ice40_dsp.pmg18
-rw-r--r--passes/pmgen/xilinx_dsp.pmg18
-rw-r--r--passes/pmgen/xilinx_dsp_CREG.pmg4
-rw-r--r--passes/pmgen/xilinx_dsp_cascade.pmg24
-rw-r--r--passes/pmgen/xilinx_srl.cc4
-rw-r--r--passes/pmgen/xilinx_srl.pmg20
-rw-r--r--passes/sat/qbfsat.cc35
-rw-r--r--passes/sat/sim.cc6
-rw-r--r--passes/techmap/abc9_ops.cc49
14 files changed, 185 insertions, 94 deletions
diff --git a/passes/cmds/bugpoint.cc b/passes/cmds/bugpoint.cc
index ad6a07fa0..a75927393 100644
--- a/passes/cmds/bugpoint.cc
+++ b/passes/cmds/bugpoint.cc
@@ -133,6 +133,7 @@ struct BugpointPass : public Pass {
int index = 0;
if (modules)
{
+ Module *removed_module = nullptr;
for (auto module : design_copy->modules())
{
if (module->get_blackbox_attribute())
@@ -141,10 +142,14 @@ struct BugpointPass : public Pass {
if (index++ == seed)
{
log("Trying to remove module %s.\n", module->name.c_str());
- design_copy->remove(module);
- return design_copy;
+ removed_module = module;
+ break;
}
}
+ if (removed_module) {
+ design_copy->remove(removed_module);
+ return design_copy;
+ }
}
if (ports)
{
@@ -178,15 +183,20 @@ struct BugpointPass : public Pass {
if (mod->get_blackbox_attribute())
continue;
+ Cell *removed_cell = nullptr;
for (auto cell : mod->cells())
{
if (index++ == seed)
{
log("Trying to remove cell %s.%s.\n", mod->name.c_str(), cell->name.c_str());
- mod->remove(cell);
- return design_copy;
+ removed_cell = cell;
+ break;
}
}
+ if (removed_cell) {
+ mod->remove(removed_cell);
+ return design_copy;
+ }
}
}
if (connections)
diff --git a/passes/cmds/design.cc b/passes/cmds/design.cc
index cfe97067d..421defe0c 100644
--- a/passes/cmds/design.cc
+++ b/passes/cmds/design.cc
@@ -228,14 +228,20 @@ struct DesignPass : public Pass {
}
if (import_mode) {
+ std::vector<RTLIL::Module*> candidates;
for (auto module : copy_src_modules)
{
if (module->get_bool_attribute(ID::top)) {
- copy_src_modules.clear();
- copy_src_modules.push_back(module);
+ candidates.clear();
+ candidates.push_back(module);
break;
}
+ if (!module->get_blackbox_attribute())
+ candidates.push_back(module);
}
+
+ if (GetSize(candidates) == 1)
+ copy_src_modules = std::move(candidates);
}
}
diff --git a/passes/cmds/select.cc b/passes/cmds/select.cc
index c04ff438a..6e728c16f 100644
--- a/passes/cmds/select.cc
+++ b/passes/cmds/select.cc
@@ -630,8 +630,10 @@ static void select_stmt(RTLIL::Design *design, std::string arg, bool disable_emp
std::string arg_mod, arg_memb;
std::unordered_map<std::string, bool> arg_mod_found;
std::unordered_map<std::string, bool> arg_memb_found;
- auto isalpha = [](const char &x) { return ((x >= 'a' && x <= 'z') || (x >= 'A' && x <= 'Z')); };
- bool prefixed = GetSize(arg) >= 2 && isalpha(arg[0]) && arg[1] == ':';
+
+ auto isprefixed = [](const string &s) {
+ return GetSize(s) >= 2 && ((s[0] >= 'a' && s[0] <= 'z') || (s[0] >= 'A' && s[0] <= 'Z')) && s[1] == ':';
+ };
if (arg.size() == 0)
return;
@@ -759,31 +761,40 @@ static void select_stmt(RTLIL::Design *design, std::string arg, bool disable_emp
return;
}
+ bool select_blackboxes = false;
+ if (arg.substr(0, 1) == "=") {
+ arg = arg.substr(1);
+ select_blackboxes = true;
+ }
+
if (!design->selected_active_module.empty()) {
arg_mod = design->selected_active_module;
arg_memb = arg;
- if (!prefixed) arg_memb_found[arg_memb] = false;
+ if (!isprefixed(arg_memb))
+ arg_memb_found[arg_memb] = false;
} else
- if (prefixed && arg[0] >= 'a' && arg[0] <= 'z') {
+ if (isprefixed(arg) && arg[0] >= 'a' && arg[0] <= 'z') {
arg_mod = "*", arg_memb = arg;
} else {
size_t pos = arg.find('/');
if (pos == std::string::npos) {
arg_mod = arg;
- if (!prefixed) arg_mod_found[arg_mod] = false;
+ if (!isprefixed(arg_mod))
+ arg_mod_found[arg_mod] = false;
} else {
arg_mod = arg.substr(0, pos);
- if (!prefixed) arg_mod_found[arg_mod] = false;
+ if (!isprefixed(arg_mod))
+ arg_mod_found[arg_mod] = false;
arg_memb = arg.substr(pos+1);
- bool arg_memb_prefixed = GetSize(arg_memb) >= 2 && isalpha(arg_memb[0]) && arg_memb[1] == ':';
- if (!arg_memb_prefixed) arg_memb_found[arg_memb] = false;
+ if (!isprefixed(arg_memb))
+ arg_memb_found[arg_memb] = false;
}
}
work_stack.push_back(RTLIL::Selection());
RTLIL::Selection &sel = work_stack.back();
- if (arg == "*" && arg_mod == "*") {
+ if (arg == "*" && arg_mod == "*" && select_blackboxes) {
select_filter_active_mod(design, work_stack.back());
return;
}
@@ -791,6 +802,9 @@ static void select_stmt(RTLIL::Design *design, std::string arg, bool disable_emp
sel.full_selection = false;
for (auto mod : design->modules())
{
+ if (!select_blackboxes && mod->get_blackbox_attribute())
+ continue;
+
if (arg_mod.compare(0, 2, "A:") == 0) {
if (!match_attr(mod->attributes, arg_mod.substr(2)))
continue;
@@ -1104,6 +1118,9 @@ struct SelectPass : public Pass {
log(" <obj_pattern>\n");
log(" select the specified object(s) from the current module\n");
log("\n");
+ log("By default, patterns will not match black/white-box modules or their");
+ log("contents. To include such objects, prefix the pattern with '='.\n");
+ log("\n");
log("A <mod_pattern> can be a module name, wildcard expression (*, ?, [..])\n");
log("matching module names, or one of the following:\n");
log("\n");
diff --git a/passes/hierarchy/hierarchy.cc b/passes/hierarchy/hierarchy.cc
index 3880b19fe..95d74d1eb 100644
--- a/passes/hierarchy/hierarchy.cc
+++ b/passes/hierarchy/hierarchy.cc
@@ -334,10 +334,16 @@ bool expand_module(RTLIL::Design *design, RTLIL::Module *module, bool flag_check
log_error("Module `%s' referenced in module `%s' in cell `%s' does not have a port named '%s'.\n",
log_id(cell->type), log_id(module), log_id(cell), log_id(conn.first));
}
- for (auto &param : cell->parameters)
- if (mod->avail_parameters.count(param.first) == 0 && param.first[0] != '$' && strchr(param.first.c_str(), '.') == NULL)
+ for (auto &param : cell->parameters) {
+ if (param.first[0] == '$' && '0' <= param.first[1] && param.first[1] <= '9') {
+ int id = atoi(param.first.c_str()+1);
+ if (id <= 0 || id > GetSize(mod->avail_parameters))
+ log_error("Module `%s' referenced in module `%s' in cell `%s' has only %d parameters, requested parameter %d.\n",
+ log_id(cell->type), log_id(module), log_id(cell), GetSize(mod->avail_parameters), id);
+ } else if (mod->avail_parameters.count(param.first) == 0 && param.first[0] != '$' && strchr(param.first.c_str(), '.') == NULL)
log_error("Module `%s' referenced in module `%s' in cell `%s' does not have a parameter named '%s'.\n",
log_id(cell->type), log_id(module), log_id(cell), log_id(param.first));
+ }
}
}
@@ -939,7 +945,8 @@ struct HierarchyPass : public Pass {
for (auto mod : design->modules())
for (auto cell : mod->cells()) {
- if (design->module(cell->type) == nullptr)
+ RTLIL::Module *cell_mod = design->module(cell->type);
+ if (cell_mod == nullptr)
continue;
for (auto &conn : cell->connections())
if (conn.first[0] == '$' && '0' <= conn.first[1] && conn.first[1] <= '9') {
@@ -947,6 +954,23 @@ struct HierarchyPass : public Pass {
pos_work.push_back(std::pair<RTLIL::Module*,RTLIL::Cell*>(mod, cell));
break;
}
+
+ pool<std::pair<IdString, IdString>> params_rename;
+ for (const auto &p : cell->parameters) {
+ if (p.first[0] == '$' && '0' <= p.first[1] && p.first[1] <= '9') {
+ int id = atoi(p.first.c_str()+1);
+ if (id <= 0 || id > GetSize(cell_mod->avail_parameters)) {
+ log(" Failed to map positional parameter %d of cell %s.%s (%s).\n",
+ id, RTLIL::id2cstr(mod->name), RTLIL::id2cstr(cell->name), RTLIL::id2cstr(cell->type));
+ } else {
+ params_rename.insert(std::make_pair(p.first, cell_mod->avail_parameters[id - 1]));
+ }
+ }
+ }
+ for (const auto &p : params_rename) {
+ cell->setParam(p.second, cell->getParam(p.first));
+ cell->unsetParam(p.first);
+ }
}
for (auto module : pos_mods)
diff --git a/passes/pmgen/ice40_dsp.cc b/passes/pmgen/ice40_dsp.cc
index bfddfd0eb..f16cc4a0b 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->parameters.at(ID::A_SIGNED, State::S0).as_bool());
+ A.extend_u0(16, st.mul->getParam(ID::A_SIGNED).as_bool());
log_assert(GetSize(A) == 16);
SigSpec B = st.sigB;
- B.extend_u0(16, st.mul->parameters.at(ID::B_SIGNED, State::S0).as_bool());
+ B.extend_u0(16, st.mul->getParam(ID::B_SIGNED).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->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());
+ 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());
if (st.ffO) {
if (st.o_lo)
diff --git a/passes/pmgen/ice40_dsp.pmg b/passes/pmgen/ice40_dsp.pmg
index 9d649cb98..2456a49dc 100644
--- a/passes/pmgen/ice40_dsp.pmg
+++ b/passes/pmgen/ice40_dsp.pmg
@@ -65,7 +65,7 @@ code sigA sigB sigH
endcode
code argQ ffA ffAholdmux ffArstmux ffAholdpol ffArstpol sigA clock clock_pol
- if (mul->type != \SB_MAC16 || !param(mul, \A_REG, State::S0).as_bool()) {
+ if (mul->type != \SB_MAC16 || !param(mul, \A_REG).as_bool()) {
argQ = sigA;
subpattern(in_dffe);
if (dff) {
@@ -86,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, State::S0).as_bool()) {
+ if (mul->type != \SB_MAC16 || !param(mul, \B_REG).as_bool()) {
argQ = sigB;
subpattern(in_dffe);
if (dff) {
@@ -109,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, 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()))) {
+ (!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()))) {
argD = sigH;
subpattern(out_dffe);
if (dff) {
@@ -148,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, State::S0).as_bool())) {
+ (mul->type != \SB_MAC16 || !param(mul, \PIPELINE_16x16_MULT_REG2).as_bool())) {
argD = sigH;
subpattern(out_dffe);
if (dff) {
@@ -179,7 +179,7 @@ reject_ffH: ;
endcode
match add
- if mul->type != \SB_MAC16 || (param(mul, \TOPOUTPUT_SELECT, State::S0).as_int() == 3 && param(mul, \BOTOUTPUT_SELECT, State::S0).as_int() == 3)
+ if mul->type != \SB_MAC16 || (param(mul, \TOPOUTPUT_SELECT).as_int() == 3 && param(mul, \BOTOUTPUT_SELECT).as_int() == 3)
select add->type.in($add)
choice <IdString> AB {\A, \B}
@@ -205,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, State::S0).as_bool() != param(add, \A_SIGNED).as_bool()))
+ if (sigCD == sigH && (actual_acc_width != actual_mul_width) && (param(mul, \A_SIGNED).as_bool() != param(add, \A_SIGNED).as_bool()))
reject;
sigO = port(add, \Y);
@@ -229,7 +229,7 @@ endcode
code argD ffO ffOholdmux ffOrstmux ffOholdpol ffOrstpol sigO sigCD clock clock_pol cd_signed o_lo
if (mul->type != \SB_MAC16 ||
// Ensure that register is not already used
- ((param(mul, \TOPOUTPUT_SELECT, 0).as_int() != 1 && param(mul, \BOTOUTPUT_SELECT, 0).as_int() != 1) &&
+ ((param(mul, \TOPOUTPUT_SELECT).as_int() != 1 && param(mul, \BOTOUTPUT_SELECT).as_int() != 1) &&
// Ensure that OLOADTOP/OLOADBOT is unused or zero
(port(mul, \OLOADTOP, State::S0).is_fully_zero() && port(mul, \OLOADBOT, State::S0).is_fully_zero()))) {
@@ -280,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, State::S0).as_bool() && !param(mul, \D_REG, State::S0).as_bool()))) {
+ (mul->type != \SB_MAC16 || (!param(mul, \C_REG).as_bool() && !param(mul, \D_REG).as_bool()))) {
argQ = sigCD;
subpattern(in_dffe);
if (dff) {
@@ -532,7 +532,7 @@ endcode
match ff
select ff->type.in($dff)
- // DSP48E1 does not support clock inversion
+ // SB_MAC16 does not support clock inversion
select param(ff, \CLK_POLARITY).as_bool()
slice offset GetSize(port(ff, \D))
diff --git a/passes/pmgen/xilinx_dsp.pmg b/passes/pmgen/xilinx_dsp.pmg
index af47ab111..d40f073c9 100644
--- a/passes/pmgen/xilinx_dsp.pmg
+++ b/passes/pmgen/xilinx_dsp.pmg
@@ -95,7 +95,7 @@ code sigA sigB sigC sigD sigM clock
sigD = port(dsp, \D, SigSpec());
SigSpec P = port(dsp, \P);
- if (param(dsp, \USE_MULT, Const("MULTIPLY")).decode_string() == "MULTIPLY") {
+ if (param(dsp, \USE_MULT).decode_string() == "MULTIPLY") {
// Only care about those bits that are used
int i;
for (i = GetSize(P)-1; i >= 0; i--)
@@ -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, 1).as_int() == 0) {
+ if (param(dsp, \ADREG).as_int() == 0) {
argQ = sigA;
subpattern(in_dffe);
if (dff) {
@@ -144,7 +144,7 @@ endcode
match preAdd
if sigD.empty() || sigD.is_fully_zero()
// Ensure that preAdder not already used
- if param(dsp, \USE_DPORT, Const("FALSE")).decode_string() == "FALSE"
+ if param(dsp, \USE_DPORT).decode_string() == "FALSE"
if port(dsp, \INMODE, Const(0, 5)).is_fully_zero()
select preAdd->type.in($add)
@@ -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, 1).as_int() == 0) {
+ if (param(dsp, \AREG).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, 1).as_int() == 0) {
+ if (param(dsp, \BREG).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, 1).as_int() == 0) {
+ if (param(dsp, \DREG).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, 1).as_int() == 0 && nusers(sigM) == 2) {
+ if (param(dsp, \MREG).as_int() == 0 && nusers(sigM) == 2) {
argD = sigM;
subpattern(out_dffe);
if (dff) {
@@ -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, 1).as_int() == 0) {
+ if (param(dsp, \PREG).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++;
@@ -424,7 +424,7 @@ endcode
// to implement this function
match overflow
if ffP
- if param(dsp, \USE_PATTERN_DETECT, Const("NO_PATDET")).decode_string() == "NO_PATDET"
+ if param(dsp, \USE_PATTERN_DETECT).decode_string() == "NO_PATDET"
select overflow->type.in($ge)
select GetSize(port(overflow, \Y)) <= 48
select port(overflow, \B).is_fully_const()
diff --git a/passes/pmgen/xilinx_dsp_CREG.pmg b/passes/pmgen/xilinx_dsp_CREG.pmg
index b20e4f458..42d4d1b9b 100644
--- a/passes/pmgen/xilinx_dsp_CREG.pmg
+++ b/passes/pmgen/xilinx_dsp_CREG.pmg
@@ -42,7 +42,7 @@ udata <bool> dffcepol dffrstpol
// and (b) uses the 'C' port
match dsp
select dsp->type.in(\DSP48A, \DSP48A1, \DSP48E1)
- select param(dsp, \CREG, 1).as_int() == 0
+ select param(dsp, \CREG).as_int() == 0
select nusers(port(dsp, \C, SigSpec())) > 1
endmatch
@@ -61,7 +61,7 @@ code sigC sigP clock
SigSpec P = port(dsp, \P);
if (!dsp->type.in(\DSP48E1) ||
- param(dsp, \USE_MULT, Const("MULTIPLY")).decode_string() == "MULTIPLY") {
+ param(dsp, \USE_MULT).decode_string() == "MULTIPLY") {
// Only care about those bits that are used
int i;
for (i = GetSize(P)-1; i >= 0; i--)
diff --git a/passes/pmgen/xilinx_dsp_cascade.pmg b/passes/pmgen/xilinx_dsp_cascade.pmg
index b14a1ee0a..8babb88e6 100644
--- a/passes/pmgen/xilinx_dsp_cascade.pmg
+++ b/passes/pmgen/xilinx_dsp_cascade.pmg
@@ -188,7 +188,7 @@ arg next
// driven by the 'P' output of the previous DSP cell, and (c) has its
// 'PCIN' port unused
match nextP
- select !param(nextP, \CREG, State::S1).as_bool()
+ select !nextP->type.in(\DSP48E1) || !param(nextP, \CREG).as_bool()
select (nextP->type.in(\DSP48A, \DSP48A1) && port(nextP, \OPMODE, Const(0, 8)).extract(2,2) == Const::from_string("11")) || (nextP->type.in(\DSP48E1) && port(nextP, \OPMODE, Const(0, 7)).extract(4,3) == Const::from_string("011"))
select nusers(port(nextP, \C, SigSpec())) > 1
select nusers(port(nextP, \PCIN, SigSpec())) == 0
@@ -201,7 +201,7 @@ endmatch
match nextP_shift17
if !nextP
select nextP_shift17->type.in(\DSP48E1)
- select !param(nextP_shift17, \CREG, State::S1).as_bool()
+ select !param(nextP_shift17, \CREG).as_bool()
select port(nextP_shift17, \OPMODE, Const(0, 7)).extract(4,3) == Const::from_string("011")
select nusers(port(nextP_shift17, \C, SigSpec())) > 1
select nusers(port(nextP_shift17, \PCIN, SigSpec())) == 0
@@ -242,10 +242,10 @@ code argQ clock AREG
if (next && next->type.in(\DSP48E1)) {
Cell *prev = std::get<0>(chain.back());
- if (param(next, \A_INPUT, Const("DIRECT")).decode_string() == "DIRECT" &&
+ if (param(next, \A_INPUT).decode_string() == "DIRECT" &&
port(next, \ACIN, SigSpec()).is_fully_zero() &&
nusers(port(prev, \ACOUT, SigSpec())) <= 1) {
- if (param(prev, \AREG, 2) == 0) {
+ if (param(prev, \AREG) == 0) {
if (port(prev, \A) == port(next, \A))
AREG = 0;
}
@@ -259,9 +259,9 @@ code argQ clock AREG
if (dffrstmux && port(dffrstmux, \S) != port(prev, \RSTA, State::S0))
goto reject_AREG;
IdString CEA;
- if (param(prev, \AREG, 2) == 1)
+ if (param(prev, \AREG) == 1)
CEA = \CEA2;
- else if (param(prev, \AREG, 2) == 2)
+ else if (param(prev, \AREG) == 2)
CEA = \CEA1;
else log_abort();
if (!dffcemux && port(prev, CEA, State::S0) != State::S1)
@@ -282,11 +282,11 @@ code argQ clock BREG
BREG = -1;
if (next) {
Cell *prev = std::get<0>(chain.back());
- if (param(next, \B_INPUT, Const("DIRECT")).decode_string() == "DIRECT" &&
+ if ((next->type != \DSP48E1 || param(next, \B_INPUT).decode_string() == "DIRECT") &&
port(next, \BCIN, SigSpec()).is_fully_zero() &&
nusers(port(prev, \BCOUT, SigSpec())) <= 1) {
- if ((next->type.in(\DSP48A, \DSP48A1) && param(prev, \B0REG, 0) == 0 && param(prev, \B1REG, 1) == 0) ||
- (next->type.in(\DSP48E1) && param(prev, \BREG, 2) == 0)) {
+ if ((next->type.in(\DSP48A, \DSP48A1) && param(prev, \B0REG) == 0 && param(prev, \B1REG) == 0) ||
+ (next->type.in(\DSP48E1) && param(prev, \BREG) == 0)) {
if (port(prev, \B) == port(next, \B))
BREG = 0;
}
@@ -303,9 +303,9 @@ code argQ clock BREG
if (next->type.in(\DSP48A, \DSP48A1))
CEB = \CEB;
else if (next->type.in(\DSP48E1)) {
- if (param(prev, \BREG, 2) == 1)
+ if (param(prev, \BREG) == 1)
CEB = \CEB2;
- else if (param(prev, \BREG, 2) == 2)
+ else if (param(prev, \BREG) == 2)
CEB = \CEB1;
else log_abort();
}
@@ -315,7 +315,7 @@ code argQ clock BREG
if (dffcemux && port(dffcemux, \S) != port(prev, CEB, State::S0))
goto reject_BREG;
if (dffD == unextend(port(prev, \B))) {
- if (next->type.in(\DSP48A, \DSP48A1) && param(prev, \B0REG, 0) != 0)
+ if (next->type.in(\DSP48A, \DSP48A1) && param(prev, \B0REG) != 0)
goto reject_BREG;
BREG = 1;
}
diff --git a/passes/pmgen/xilinx_srl.cc b/passes/pmgen/xilinx_srl.cc
index 24b525b93..b99653fb3 100644
--- a/passes/pmgen/xilinx_srl.cc
+++ b/passes/pmgen/xilinx_srl.cc
@@ -48,7 +48,7 @@ void run_fixed(xilinx_srl_pm &pm)
initval.append(State::Sx);
}
else if (cell->type.in(ID(FDRE), ID(FDRE_1))) {
- if (cell->parameters.at(ID::INIT, State::S0).as_bool())
+ if (cell->getParam(ID::INIT).as_bool())
initval.append(State::S1);
else
initval.append(State::S0);
@@ -71,7 +71,7 @@ void run_fixed(xilinx_srl_pm &pm)
else if (first_cell->type.in(ID($_DFF_N_), ID($_DFFE_NN_), ID($_DFFE_NP_), ID(FDRE_1)))
c->setParam(ID(CLKPOL), 0);
else if (first_cell->type.in(ID(FDRE))) {
- if (!first_cell->parameters.at(ID(IS_C_INVERTED), State::S0).as_bool())
+ if (!first_cell->getParam(ID(IS_C_INVERTED)).as_bool())
c->setParam(ID(CLKPOL), 1);
else
c->setParam(ID(CLKPOL), 0);
diff --git a/passes/pmgen/xilinx_srl.pmg b/passes/pmgen/xilinx_srl.pmg
index 535b3dfdc..80f0a27c2 100644
--- a/passes/pmgen/xilinx_srl.pmg
+++ b/passes/pmgen/xilinx_srl.pmg
@@ -13,8 +13,8 @@ endcode
match first
select first->type.in($_DFF_N_, $_DFF_P_, $_DFFE_NN_, $_DFFE_NP_, $_DFFE_PN_, $_DFFE_PP_, \FDRE, \FDRE_1)
select !first->has_keep_attr()
- select !first->type.in(\FDRE) || !param(first, \IS_R_INVERTED, State::S0).as_bool()
- select !first->type.in(\FDRE) || !param(first, \IS_D_INVERTED, State::S0).as_bool()
+ select !first->type.in(\FDRE) || !param(first, \IS_R_INVERTED).as_bool()
+ select !first->type.in(\FDRE) || !param(first, \IS_D_INVERTED).as_bool()
select !first->type.in(\FDRE, \FDRE_1) || port(first, \R, State::S0).is_fully_zero()
filter !non_first_cells.count(first)
generate
@@ -84,8 +84,8 @@ arg en_port
match first
select first->type.in($_DFF_N_, $_DFF_P_, $_DFFE_NN_, $_DFFE_NP_, $_DFFE_PN_, $_DFFE_PP_, \FDRE, \FDRE_1)
select !first->has_keep_attr()
- select !first->type.in(\FDRE) || !param(first, \IS_R_INVERTED, State::S0).as_bool()
- select !first->type.in(\FDRE) || !param(first, \IS_D_INVERTED, State::S0).as_bool()
+ select !first->type.in(\FDRE) || !param(first, \IS_R_INVERTED).as_bool()
+ select !first->type.in(\FDRE) || !param(first, \IS_D_INVERTED).as_bool()
select !first->type.in(\FDRE, \FDRE_1) || port(first, \R, State::S0).is_fully_zero()
endmatch
@@ -111,9 +111,9 @@ match next
index <SigBit> port(next, \Q) === port(first, \D)
filter port(next, clk_port) == port(first, clk_port)
filter en_port == IdString() || port(next, en_port) == port(first, en_port)
- filter !first->type.in(\FDRE) || param(next, \IS_C_INVERTED, State::S0).as_bool() == param(first, \IS_C_INVERTED, State::S0).as_bool()
- filter !first->type.in(\FDRE) || param(next, \IS_D_INVERTED, State::S0).as_bool() == param(first, \IS_D_INVERTED, State::S0).as_bool()
- filter !first->type.in(\FDRE) || param(next, \IS_R_INVERTED, State::S0).as_bool() == param(first, \IS_R_INVERTED, State::S0).as_bool()
+ filter !first->type.in(\FDRE) || param(next, \IS_C_INVERTED).as_bool() == param(first, \IS_C_INVERTED).as_bool()
+ filter !first->type.in(\FDRE) || param(next, \IS_D_INVERTED).as_bool() == param(first, \IS_D_INVERTED).as_bool()
+ filter !first->type.in(\FDRE) || param(next, \IS_R_INVERTED).as_bool() == param(first, \IS_R_INVERTED).as_bool()
filter !first->type.in(\FDRE, \FDRE_1) || port(next, \R, State::S0).is_fully_zero()
endmatch
@@ -138,9 +138,9 @@ match next
index <SigBit> port(next, \Q) === port(chain.back(), \D)
filter port(next, clk_port) == port(first, clk_port)
filter en_port == IdString() || port(next, en_port) == port(first, en_port)
- filter !first->type.in(\FDRE) || param(next, \IS_C_INVERTED, State::S0).as_bool() == param(first, \IS_C_INVERTED, State::S0).as_bool()
- filter !first->type.in(\FDRE) || param(next, \IS_D_INVERTED, State::S0).as_bool() == param(first, \IS_D_INVERTED, State::S0).as_bool()
- filter !first->type.in(\FDRE) || param(next, \IS_R_INVERTED, State::S0).as_bool() == param(first, \IS_R_INVERTED, State::S0).as_bool()
+ filter !first->type.in(\FDRE) || param(next, \IS_C_INVERTED).as_bool() == param(first, \IS_C_INVERTED).as_bool()
+ filter !first->type.in(\FDRE) || param(next, \IS_D_INVERTED).as_bool() == param(first, \IS_D_INVERTED).as_bool()
+ filter !first->type.in(\FDRE) || param(next, \IS_R_INVERTED).as_bool() == param(first, \IS_R_INVERTED).as_bool()
filter !first->type.in(\FDRE, \FDRE_1) || port(next, \R, State::S0).is_fully_zero()
generate
Cell *cell = module->addCell(NEW_ID, chain.back()->type);
diff --git a/passes/sat/qbfsat.cc b/passes/sat/qbfsat.cc
index 981271770..d99ca1b53 100644
--- a/passes/sat/qbfsat.cc
+++ b/passes/sat/qbfsat.cc
@@ -49,15 +49,15 @@ struct QbfSolutionType {
};
struct QbfSolveOptions {
- bool specialize, specialize_from_file, write_solution, nocleanup, dump_final_smt2, assume_outputs;
+ bool specialize, specialize_from_file, write_solution, nocleanup, dump_final_smt2, assume_outputs, assume_neg;
bool sat, unsat, show_smtbmc;
std::string specialize_soln_file;
std::string write_soln_soln_file;
std::string dump_final_smt2_file;
size_t argidx;
QbfSolveOptions() : specialize(false), specialize_from_file(false), write_solution(false),
- nocleanup(false), dump_final_smt2(false), assume_outputs(false), sat(false), unsat(false),
- show_smtbmc(false), argidx(0) {};
+ nocleanup(false), dump_final_smt2(false), assume_outputs(false), assume_neg(false),
+ sat(false), unsat(false), show_smtbmc(false), argidx(0) {};
};
void recover_solution(QbfSolutionType &sol) {
@@ -98,11 +98,8 @@ dict<std::string, std::string> get_hole_loc_name_map(RTLIL::Module *module, cons
for (auto cell : module->cells()) {
std::string cell_src = cell->get_src_attribute();
auto pos = sol.hole_to_value.find(cell_src);
- if (pos != sol.hole_to_value.end()) {
-#ifndef NDEBUG
- log_assert(cell->type.in("$anyconst", "$anyseq"));
- log_assert(cell->getPort(ID::Y).is_wire());
-#endif
+ if (pos != sol.hole_to_value.end() && cell->type.in("$anyconst", "$anyseq")) {
+ log_assert(hole_loc_to_name.find(pos->first) == hole_loc_to_name.end());
hole_loc_to_name[pos->first] = cell->getPort(ID::Y).as_wire()->name.str();
}
}
@@ -242,7 +239,7 @@ void allconstify_inputs(RTLIL::Module *module, const pool<std::string> &input_wi
module->fixup_ports();
}
-void assume_miter_outputs(RTLIL::Module *module) {
+void assume_miter_outputs(RTLIL::Module *module, const QbfSolveOptions &opt) {
std::vector<RTLIL::Wire *> wires_to_assume;
for (auto w : module->wires())
if (w->port_output && w->width == 1)
@@ -257,7 +254,14 @@ void assume_miter_outputs(RTLIL::Module *module) {
log("\n");
}
- for(auto i = 0; wires_to_assume.size() > 1; ++i) {
+ if (opt.assume_neg) {
+ for (unsigned int i = 0; i < wires_to_assume.size(); ++i) {
+ RTLIL::SigSpec n_wire = module->LogicNot(wires_to_assume[i]->name.str() + "__n__qbfsat", wires_to_assume[i], false, wires_to_assume[i]->get_src_attribute());
+ wires_to_assume[i] = n_wire.as_wire();
+ }
+ }
+
+ for (auto i = 0; wires_to_assume.size() > 1; ++i) {
std::vector<RTLIL::Wire *> buf;
for (auto j = 0; j + 1 < GetSize(wires_to_assume); j += 2) {
std::stringstream strstr; strstr << i << "_" << j;
@@ -371,6 +375,10 @@ QbfSolveOptions parse_args(const std::vector<std::string> &args) {
opt.assume_outputs = true;
continue;
}
+ else if (args[opt.argidx] == "-assume-negative-polarity") {
+ opt.assume_neg = true;
+ continue;
+ }
else if (args[opt.argidx] == "-sat") {
opt.sat = true;
continue;
@@ -464,6 +472,11 @@ struct QbfSatPass : public Pass {
log(" -assume-outputs\n");
log(" Add an $assume cell for the conjunction of all one-bit module output wires.\n");
log("\n");
+ log(" -assume-negative-polarity\n");
+ log(" When adding $assume cells for one-bit module output wires, assume they are\n");
+ log(" negative polarity signals and should always be low, for example like the\n");
+ log(" miters created with the `miter` command.\n");
+ log("\n");
log(" -sat\n");
log(" Generate an error if the solver does not return \"sat\".\n");
log("\n");
@@ -512,7 +525,7 @@ struct QbfSatPass : public Pass {
pool<std::string> input_wires = validate_design_and_get_inputs(module, opt);
allconstify_inputs(module, input_wires);
if (opt.assume_outputs)
- assume_miter_outputs(module);
+ assume_miter_outputs(module, opt);
QbfSolutionType ret = qbf_solve(module, opt);
Pass::call(design, "design -pop");
diff --git a/passes/sat/sim.cc b/passes/sat/sim.cc
index 59bf5a712..03ca42cf3 100644
--- a/passes/sat/sim.cc
+++ b/passes/sat/sim.cc
@@ -128,8 +128,12 @@ struct SimInstance
for (auto &port : cell->connections()) {
if (cell->input(port.first))
- for (auto bit : sigmap(port.second))
+ for (auto bit : sigmap(port.second)) {
upd_cells[bit].insert(cell);
+ // Make sure cell inputs connected to constants are updated in the first cycle
+ if (bit.wire == nullptr)
+ dirty_bits.insert(bit);
+ }
}
if (cell->type.in(ID($dff))) {
diff --git a/passes/techmap/abc9_ops.cc b/passes/techmap/abc9_ops.cc
index 8ae1b51ff..78c902866 100644
--- a/passes/techmap/abc9_ops.cc
+++ b/passes/techmap/abc9_ops.cc
@@ -467,7 +467,12 @@ void prep_lut(RTLIL::Design *design, int maxlut)
{
TimingInfo timing;
- std::vector<std::tuple<int, IdString, int, std::vector<int>>> table;
+ struct t_lut {
+ IdString name;
+ int area;
+ std::vector<int> delays;
+ };
+ std::map<int,t_lut> table;
for (auto module : design->modules()) {
auto it = module->attributes.find(ID::abc9_lut);
if (it == module->attributes.end())
@@ -476,40 +481,52 @@ void prep_lut(RTLIL::Design *design, int maxlut)
auto &t = timing.setup_module(module);
TimingInfo::NameBit o;
- std::vector<int> specify;
+ std::vector<int> delays;
for (const auto &i : t.comb) {
auto &d = i.first.second;
if (o == TimingInfo::NameBit())
o = d;
else if (o != d)
- log_error("(* abc9_lut *) module '%s' with has more than one output.\n", log_id(module));
- specify.push_back(i.second);
+ log_error("Module '%s' with (* abc9_lut *) has more than one output.\n", log_id(module));
+ delays.push_back(i.second);
}
- if (maxlut && GetSize(specify) > maxlut)
+ if (GetSize(delays) == 0)
+ log_error("Module '%s' with (* abc9_lut *) has no specify entries.\n", log_id(module));
+ if (maxlut && GetSize(delays) > maxlut)
continue;
// ABC requires non-decreasing LUT input delays
- std::sort(specify.begin(), specify.end());
- table.emplace_back(GetSize(specify), module->name, it->second.as_int(), std::move(specify));
+ std::sort(delays.begin(), delays.end());
+
+ int K = GetSize(delays);
+ auto entry = t_lut{module->name, it->second.as_int(), std::move(delays)};
+ auto r = table.emplace(K, entry);
+ if (!r.second) {
+ if (r.first->second.area != entry.area)
+ log_error("Modules '%s' and '%s' have conflicting (* abc9_lut *) values.\n", log_id(module), log_id(r.first->second.name));
+ if (r.first->second.delays != entry.delays)
+ log_error("Modules '%s' and '%s' have conflicting specify entries.\n", log_id(module), log_id(r.first->second.name));
+ }
}
- // ABC requires ascending size
- std::sort(table.begin(), table.end());
+
+ if (table.empty())
+ log_error("Design does not contain any modules with (* abc9_lut *).\n");
std::stringstream ss;
- const auto &first = table.front();
+ const auto &front = *table.begin();
// If the first entry does not start from a 1-input LUT,
// (as ABC requires) crop the first entry to do so
- for (int i = 1; i < std::get<0>(first); i++) {
+ for (int i = 1; i < front.first; i++) {
ss << "# $__ABC9_LUT" << i << std::endl;
- ss << i << " " << std::get<2>(first);
+ ss << i << " " << front.second.area;
for (int j = 0; j < i; j++)
- ss << " " << std::get<3>(first)[j];
+ ss << " " << front.second.delays[j];
ss << std::endl;
}
for (const auto &i : table) {
- ss << "# " << log_id(std::get<1>(i)) << std::endl;
- ss << std::get<0>(i) << " " << std::get<2>(i);
- for (const auto &j : std::get<3>(i))
+ ss << "# " << log_id(i.second.name) << std::endl;
+ ss << i.first << " " << i.second.area;
+ for (const auto &j : i.second.delays)
ss << " " << j;
ss << std::endl;
}