diff options
Diffstat (limited to 'passes')
-rw-r--r-- | passes/cmds/select.cc | 35 | ||||
-rw-r--r-- | passes/pmgen/ice40_dsp.cc | 8 | ||||
-rw-r--r-- | passes/pmgen/ice40_dsp.pmg | 18 | ||||
-rw-r--r-- | passes/pmgen/xilinx_dsp.pmg | 18 | ||||
-rw-r--r-- | passes/pmgen/xilinx_dsp_CREG.pmg | 4 | ||||
-rw-r--r-- | passes/pmgen/xilinx_dsp_cascade.pmg | 24 | ||||
-rw-r--r-- | passes/pmgen/xilinx_srl.cc | 4 | ||||
-rw-r--r-- | passes/pmgen/xilinx_srl.pmg | 20 | ||||
-rw-r--r-- | passes/sat/qbfsat.cc | 35 | ||||
-rw-r--r-- | passes/techmap/abc9_exe.cc | 19 |
10 files changed, 115 insertions, 70 deletions
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/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/techmap/abc9_exe.cc b/passes/techmap/abc9_exe.cc index 18618ff91..bad91a224 100644 --- a/passes/techmap/abc9_exe.cc +++ b/passes/techmap/abc9_exe.cc @@ -219,6 +219,17 @@ void abc9_module(RTLIL::Design *design, std::string script_file, std::string exe 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); + if (design->scratchpad_get_bool("abc9.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")); + else { + auto s = stringf("&write -n %s/output.aig; ", tempdir_name.c_str()); + for (size_t pos = abc9_script.find("&mfs"); pos != std::string::npos; pos = abc9_script.find("&mfs", pos)) { + abc9_script = abc9_script.insert(pos, s); + pos += GetSize(s) + strlen("&mfs"); + } + } + abc9_script += stringf("; &ps -l; &write -n %s/output.aig", tempdir_name.c_str()); if (design->scratchpad_get_bool("abc9.verify")) { if (dff_mode) @@ -272,8 +283,12 @@ void abc9_module(RTLIL::Design *design, std::string script_file, std::string exe free(abc9_argv[2]); free(abc9_argv[3]); #endif - if (ret != 0) - log_error("ABC: execution of command \"%s\" failed: return code %d.\n", buffer.c_str(), ret); + if (ret != 0) { + if (check_file_exists(stringf("%s/output.aig", tempdir_name.c_str()))) + log_warning("ABC: execution of command \"%s\" failed: return code %d.\n", buffer.c_str(), ret); + else + log_error("ABC: execution of command \"%s\" failed: return code %d.\n", buffer.c_str(), ret); + } } struct Abc9ExePass : public Pass { |