diff options
26 files changed, 291 insertions, 213 deletions
diff --git a/frontends/verific/verific.cc b/frontends/verific/verific.cc index 519151310..89606a5bd 100644 --- a/frontends/verific/verific.cc +++ b/frontends/verific/verific.cc @@ -1153,6 +1153,30 @@ void VerificImporter::import_netlist(RTLIL::Design *design, Netlist *nl, std::se for (auto net : anyseq_nets) module->connect(net_map_at(net), module->Anyseq(new_verific_id(net))); + char *id_name; + TypeRange *type_range; + FOREACH_MAP_ITEM(nl->GetTypeRangeTable(), mi, &id_name, &type_range) + { + if (!type_range) + continue; + if (!type_range->IsTypeEnum()) + continue; + auto wire = module->wire(RTLIL::escape_id(id_name)); + if (!wire) { + if (net->IsUserDeclared()) + log_warning("Unable to find imported net '%s'.\n", net->Name()); + continue; + } + wire->set_string_attribute(ID::wiretype, type_range->GetTypeName()); + + MapIter mj; + char *k, *v; + FOREACH_MAP_ITEM(type_range->GetEnumIdMap(), mj, &k, &v) { + IdString key = stringf("\\enum_value_%s", v); + wire->set_string_attribute(key, k); + } + } + pool<Instance*, hash_ptr_ops> sva_asserts; pool<Instance*, hash_ptr_ops> sva_assumes; pool<Instance*, hash_ptr_ops> sva_covers; diff --git a/kernel/constids.inc b/kernel/constids.inc index 68a5782fd..c5f672d09 100644 --- a/kernel/constids.inc +++ b/kernel/constids.inc @@ -199,6 +199,7 @@ X(wand) X(whitebox) X(WIDTH) X(wildcard_port_conns) +X(wiretype) X(wor) X(WORDS) X(WR_ADDR) diff --git a/kernel/rtlil.cc b/kernel/rtlil.cc index 2aefe30b1..196e301b6 100644 --- a/kernel/rtlil.cc +++ b/kernel/rtlil.cc @@ -2619,16 +2619,15 @@ void RTLIL::Cell::setParam(RTLIL::IdString paramname, RTLIL::Const value) const RTLIL::Const &RTLIL::Cell::getParam(RTLIL::IdString paramname) const { - static const RTLIL::Const empty; const auto &it = parameters.find(paramname); if (it != parameters.end()) return it->second; if (module && module->design) { RTLIL::Module *m = module->design->module(type); if (m) - return m->parameter_default_values.at(paramname, empty); + return m->parameter_default_values.at(paramname); } - return empty; + throw std::out_of_range("Cell::getParam()"); } void RTLIL::Cell::sort() 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 { diff --git a/techlibs/ecp5/ecp5_ffinit.cc b/techlibs/ecp5/ecp5_ffinit.cc index e85bee64e..ba72bd0c6 100644 --- a/techlibs/ecp5/ecp5_ffinit.cc +++ b/techlibs/ecp5/ecp5_ffinit.cc @@ -106,9 +106,7 @@ struct Ecp5FfinitPass : public Pass { SigBit bit_d = sigmap(sig_d[0]); SigBit bit_q = sigmap(sig_q[0]); - std::string regset = "RESET"; - if (cell->hasParam(ID(REGSET))) - regset = cell->getParam(ID(REGSET)).decode_string(); + std::string regset = cell->getParam(ID(REGSET)).decode_string(); State resetState; if (regset == "SET") resetState = State::S1; @@ -135,9 +133,7 @@ struct Ecp5FfinitPass : public Pass { } if (GetSize(sig_lsr) >= 1 && sig_lsr[0] != State::S0) { - std::string srmode = "LSR_OVER_CE"; - if (cell->hasParam(ID(SRMODE))) - srmode = cell->getParam(ID(SRMODE)).decode_string(); + std::string srmode = cell->getParam(ID(SRMODE)).decode_string(); if (srmode == "ASYNC") { log("Async reset value %c for FF cell %s inconsistent with init value %c.\n", resetState != State::S0 ? '1' : '0', log_id(cell), val != State::S0 ? '1' : '0'); @@ -154,9 +150,7 @@ struct Ecp5FfinitPass : public Pass { cell->setPort(ID(LSR), State::S0); if(cell->hasPort(ID(CE))) { - std::string cemux = "CE"; - if (cell->hasParam(ID(CEMUX))) - cemux = cell->getParam(ID(CEMUX)).decode_string(); + std::string cemux = cell->getParam(ID(CEMUX)).decode_string(); SigSpec sig_ce = cell->getPort(ID(CE)); if (GetSize(sig_ce) >= 1) { SigBit bit_ce = sigmap(sig_ce[0]); diff --git a/techlibs/ecp5/ecp5_gsr.cc b/techlibs/ecp5/ecp5_gsr.cc index d1503f71f..3d3f8e1c1 100644 --- a/techlibs/ecp5/ecp5_gsr.cc +++ b/techlibs/ecp5/ecp5_gsr.cc @@ -114,9 +114,9 @@ struct Ecp5GsrPass : public Pass { { if (cell->type != ID(TRELLIS_FF)) continue; - if (!cell->hasParam(ID(GSR)) || cell->getParam(ID(GSR)).decode_string() != "ENABLED") + if (cell->getParam(ID(GSR)).decode_string() != "ENABLED") continue; - if (!cell->hasParam(ID(SRMODE)) || cell->getParam(ID(SRMODE)).decode_string() != "ASYNC") + if (cell->getParam(ID(SRMODE)).decode_string() != "ASYNC") continue; SigSpec sig_lsr = cell->getPort(ID(LSR)); if (GetSize(sig_lsr) < 1) diff --git a/techlibs/intel_alm/Makefile.inc b/techlibs/intel_alm/Makefile.inc index 66204c8fc..bbf233aeb 100644 --- a/techlibs/intel_alm/Makefile.inc +++ b/techlibs/intel_alm/Makefile.inc @@ -15,9 +15,6 @@ $(foreach bramtype, $(bramtypes), $(eval $(call add_share_file,share/intel_alm/c $(eval $(call add_share_file,share/intel_alm/common,techlibs/intel_alm/common/lutram_mlab.txt)) $(eval $(call add_share_file,share/intel_alm/common,techlibs/intel_alm/common/lutram_mlab_map.v)) -families := cyclonev cyclone10gx - # Miscellaneous $(eval $(call add_share_file,share/intel_alm/common,techlibs/intel_alm/common/megafunction_bb.v)) $(eval $(call add_share_file,share/intel_alm/common,techlibs/intel_alm/common/quartus_rename.v)) -$(foreach family, $(families), $(eval $(call add_share_file,share/intel_alm/$(family),techlibs/intel_alm/$(family)/quartus_rename.v))) diff --git a/techlibs/intel_alm/common/quartus_rename.v b/techlibs/intel_alm/common/quartus_rename.v index d9961c174..ac0fe12aa 100644 --- a/techlibs/intel_alm/common/quartus_rename.v +++ b/techlibs/intel_alm/common/quartus_rename.v @@ -1,3 +1,10 @@ +`ifdef cyclonev +`define LCELL cyclonev_lcell_comb +`endif +`ifdef cyclone10gx +`define LCELL cyclone10gx_lcell_comb +`endif + module __MISTRAL_VCC(output Q); MISTRAL_ALUT2 #(.LUT(4'b1111)) _TECHMAP_REPLACE_ (.A(1'b1), .B(1'b1), .Q(Q)); @@ -17,3 +24,59 @@ module MISTRAL_FF(input DATAIN, CLK, ACLR, ENA, SCLR, SLOAD, SDATA, output reg Q dffeas #(.power_up("low"), .is_wysiwyg("true")) _TECHMAP_REPLACE_ (.d(DATAIN), .clk(CLK), .clrn(ACLR), .ena(ENA), .sclr(SCLR), .sload(SLOAD), .asdata(SDATA), .q(Q)); endmodule + + +module MISTRAL_ALUT6(input A, B, C, D, E, F, output Q); +parameter [63:0] LUT = 64'h0000_0000_0000_0000; + +`LCELL #(.lut_mask(LUT)) _TECHMAP_REPLACE_ (.dataa(A), .datab(B), .datac(C), .datad(D), .datae(E), .dataf(F), .combout(Q)); + +endmodule + + +module MISTRAL_ALUT5(input A, B, C, D, E, output Q); +parameter [31:0] LUT = 32'h0000_0000; + +`LCELL #(.lut_mask({2{LUT}})) _TECHMAP_REPLACE_ (.dataa(A), .datab(B), .datac(C), .datad(D), .datae(E), .combout(Q)); + +endmodule + + +module MISTRAL_ALUT4(input A, B, C, D, output Q); +parameter [15:0] LUT = 16'h0000; + +`LCELL #(.lut_mask({4{LUT}})) _TECHMAP_REPLACE_ (.dataa(A), .datab(B), .datac(C), .datad(D), .combout(Q)); + +endmodule + + +module MISTRAL_ALUT3(input A, B, C, output Q); +parameter [7:0] LUT = 8'h00; + +`LCELL #(.lut_mask({8{LUT}})) _TECHMAP_REPLACE_ (.dataa(A), .datab(B), .datac(C), .combout(Q)); + +endmodule + + +module MISTRAL_ALUT2(input A, B, output Q); +parameter [3:0] LUT = 4'h0; + +`LCELL #(.lut_mask({16{LUT}})) _TECHMAP_REPLACE_ (.dataa(A), .datab(B), .combout(Q)); + +endmodule + + +module MISTRAL_NOT(input A, output Q); + +NOT _TECHMAP_REPLACE_ (.IN(A), .OUT(Q)); + +endmodule + + +module MISTRAL_ALUT_ARITH(input A, B, C, D0, D1, CI, output SO, CO); +parameter LUT0 = 16'h0000; +parameter LUT1 = 16'h0000; + +`LCELL #(.lut_mask({16'h0, LUT1, 16'h0, LUT0})) _TECHMAP_REPLACE_ (.dataa(A), .datab(B), .datac(C), .datad(D0), .dataf(D1), .cin(CI), .sumout(SO), .cout(CO)); + +endmodule diff --git a/techlibs/intel_alm/cyclone10gx/quartus_rename.v b/techlibs/intel_alm/cyclone10gx/quartus_rename.v deleted file mode 100644 index 3fbc508ed..000000000 --- a/techlibs/intel_alm/cyclone10gx/quartus_rename.v +++ /dev/null @@ -1,54 +0,0 @@ -module MISTRAL_ALUT6(input A, B, C, D, E, F, output Q); -parameter LUT = 64'h0000_0000_0000_0000; - -cyclone10gx_lcell_comb #(.lut_mask(LUT)) _TECHMAP_REPLACE_ (.dataa(A), .datab(B), .datac(C), .datad(D), .datae(E), .dataf(F), .combout(Q)); - -endmodule - - -module MISTRAL_ALUT5(input A, B, C, D, E, output Q); -parameter LUT = 32'h0000_0000; - -cyclone10gx_lcell_comb #(.lut_mask({2{LUT}})) _TECHMAP_REPLACE_ (.dataa(A), .datab(B), .datac(C), .datad(D), .datae(E), .combout(Q)); - -endmodule - - -module MISTRAL_ALUT4(input A, B, C, D, output Q); -parameter LUT = 16'h0000; - -cyclone10gx_lcell_comb #(.lut_mask({4{LUT}})) _TECHMAP_REPLACE_ (.dataa(A), .datab(B), .datac(C), .datad(D), .combout(Q)); - -endmodule - - -module MISTRAL_ALUT3(input A, B, C, output Q); -parameter LUT = 8'h00; - -cyclone10gx_lcell_comb #(.lut_mask({8{LUT}})) _TECHMAP_REPLACE_ (.dataa(A), .datab(B), .datac(C), .combout(Q)); - -endmodule - - -module MISTRAL_ALUT2(input A, B, output Q); -parameter LUT = 4'h0; - -cyclone10gx_lcell_comb #(.lut_mask({16{LUT}})) _TECHMAP_REPLACE_ (.dataa(A), .datab(B), .combout(Q)); - -endmodule - - -module MISTRAL_NOT(input A, output Q); - -NOT _TECHMAP_REPLACE_ (.IN(A), .OUT(Q)); - -endmodule - - -module MISTRAL_ALUT_ARITH(input A, B, C, D0, D1, CI, output SO, CO); -parameter LUT0 = 16'h0000; -parameter LUT1 = 16'h0000; - -cyclone10gx_lcell_comb #(.lut_mask({16'h0, LUT1, 16'h0, LUT0})) _TECHMAP_REPLACE_ (.dataa(A), .datab(B), .datac(C), .datad(D0), .dataf(D1), .cin(CI), .sumout(SO), .cout(CO)); - -endmodule diff --git a/techlibs/intel_alm/cyclonev/quartus_rename.v b/techlibs/intel_alm/cyclonev/quartus_rename.v deleted file mode 100644 index 6eff375e1..000000000 --- a/techlibs/intel_alm/cyclonev/quartus_rename.v +++ /dev/null @@ -1,54 +0,0 @@ -module MISTRAL_ALUT6(input A, B, C, D, E, F, output Q); -parameter LUT = 64'h0000_0000_0000_0000; - -cyclonev_lcell_comb #(.lut_mask(LUT)) _TECHMAP_REPLACE_ (.dataa(A), .datab(B), .datac(C), .datad(D), .datae(E), .dataf(F), .combout(Q)); - -endmodule - - -module MISTRAL_ALUT5(input A, B, C, D, E, output Q); -parameter LUT = 32'h0000_0000; - -cyclonev_lcell_comb #(.lut_mask({2{LUT}})) _TECHMAP_REPLACE_ (.dataa(A), .datab(B), .datac(C), .datad(D), .datae(E), .combout(Q)); - -endmodule - - -module MISTRAL_ALUT4(input A, B, C, D, output Q); -parameter LUT = 16'h0000; - -cyclonev_lcell_comb #(.lut_mask({4{LUT}})) _TECHMAP_REPLACE_ (.dataa(A), .datab(B), .datac(C), .datad(D), .combout(Q)); - -endmodule - - -module MISTRAL_ALUT3(input A, B, C, output Q); -parameter LUT = 8'h00; - -cyclonev_lcell_comb #(.lut_mask({8{LUT}})) _TECHMAP_REPLACE_ (.dataa(A), .datab(B), .datac(C), .combout(Q)); - -endmodule - - -module MISTRAL_ALUT2(input A, B, output Q); -parameter LUT = 4'h0; - -cyclonev_lcell_comb #(.lut_mask({16{LUT}})) _TECHMAP_REPLACE_ (.dataa(A), .datab(B), .combout(Q)); - -endmodule - - -module MISTRAL_NOT(input A, output Q); - -NOT _TECHMAP_REPLACE_ (.IN(A), .OUT(Q)); - -endmodule - - -module MISTRAL_ALUT_ARITH(input A, B, C, D0, D1, CI, output SO, CO); -parameter LUT0 = 16'h0000; -parameter LUT1 = 16'h0000; - -cyclonev_lcell_comb #(.lut_mask({16'h0, LUT1, 16'h0, LUT0})) _TECHMAP_REPLACE_ (.dataa(A), .datab(B), .datac(C), .datad(D0), .dataf(D1), .cin(CI), .sumout(SO), .cout(CO)); - -endmodule diff --git a/techlibs/intel_alm/synth_intel_alm.cc b/techlibs/intel_alm/synth_intel_alm.cc index 47aa11500..200b0cdd1 100644 --- a/techlibs/intel_alm/synth_intel_alm.cc +++ b/techlibs/intel_alm/synth_intel_alm.cc @@ -200,6 +200,8 @@ struct SynthIntelALMPass : public ScriptPass { if (check_label("map_ffs")) { run("dff2dffe -direct-match $_DFF_*"); + // As mentioned in common/dff_sim.v, Intel flops power up to zero, + // so use `zinit` to add inverters where needed. run("zinit"); run("techmap -map +/techmap.v -map +/intel_alm/common/dff_map.v"); run("opt -full -undriven -mux_undef"); @@ -223,10 +225,17 @@ struct SynthIntelALMPass : public ScriptPass { if (check_label("quartus")) { if (quartus || help_mode) { + // Quartus ICEs if you have a wire which has `[]` in its name, + // which Yosys produces when building memories out of flops. + run("rename -hide w:*[* w:*]*"); + // VQM mode does not support 'x, so replace those with zero. run("setundef -zero"); + // VQM mode does not support multi-bit constant assignments + // (e.g. 2'b00 is an error), so as a workaround use references + // to constant driver cells, which Quartus accepts. run("hilomap -singleton -hicell __MISTRAL_VCC Q -locell __MISTRAL_GND Q"); - run("techmap -map +/intel_alm/common/quartus_rename.v"); - run(stringf("techmap -map +/intel_alm/%s/quartus_rename.v", family_opt.c_str())); + // Rename from Yosys-internal MISTRAL_* cells to Quartus cells. + run(stringf("techmap -D %s -map +/intel_alm/common/quartus_rename.v", family_opt.c_str())); } } diff --git a/techlibs/xilinx/xilinx_dffopt.cc b/techlibs/xilinx/xilinx_dffopt.cc index c608db883..c9d63c9f7 100644 --- a/techlibs/xilinx/xilinx_dffopt.cc +++ b/techlibs/xilinx/xilinx_dffopt.cc @@ -292,18 +292,21 @@ unmap: LutData final_lut; if (worthy_post_r) { final_lut = lut_d_post_r; - log(" Merging R LUT for %s/%s (%d -> %d)\n", log_id(cell), log_id(sig_Q.wire), GetSize(lut_d.second), GetSize(final_lut.second)); } else if (worthy_post_s) { final_lut = lut_d_post_s; - log(" Merging S LUT for %s/%s (%d -> %d)\n", log_id(cell), log_id(sig_Q.wire), GetSize(lut_d.second), GetSize(final_lut.second)); } else if (worthy_post_ce) { final_lut = lut_d_post_ce; - log(" Merging CE LUT for %s/%s (%d -> %d)\n", log_id(cell), log_id(sig_Q.wire), GetSize(lut_d.second), GetSize(final_lut.second)); } else { // Nothing to do here. continue; } + std::string ports; + if (worthy_post_r) ports += " + R"; + if (worthy_post_s) ports += " + S"; + if (worthy_post_ce) ports += " + CE"; + log(" Merging D%s LUTs for %s/%s (%d -> %d)\n", ports.c_str(), log_id(cell), log_id(sig_Q.wire), GetSize(lut_d.second), GetSize(final_lut.second)); + // Okay, we're doing it. Unmap ports. if (worthy_post_r) { cell->unsetParam(ID(IS_R_INVERTED)); diff --git a/tests/arch/ice40/ice40_dsp.ys b/tests/arch/ice40/ice40_dsp.ys index 250273859..b13e525fd 100644 --- a/tests/arch/ice40/ice40_dsp.ys +++ b/tests/arch/ice40/ice40_dsp.ys @@ -8,4 +8,5 @@ assign o4 = a * b; SB_MAC16 m3 (.A(a), .B(b), .O(o5)); endmodule EOT +read_verilog -lib +/ice40/cells_sim.v ice40_dsp diff --git a/tests/arch/intel_alm/quartus_ice.ys b/tests/arch/intel_alm/quartus_ice.ys new file mode 100644 index 000000000..4b9b54d10 --- /dev/null +++ b/tests/arch/intel_alm/quartus_ice.ys @@ -0,0 +1,12 @@ +read_verilog <<EOT +// Verilog has syntax for raw identifiers, where you start it with \ and end it with a space. +// This test crashes Quartus due to it parsing \a[10] as a wire slice and not a raw identifier. +module top(); + (* keep *) wire [31:0] \a[10] ; + (* keep *) wire b; + assign b = \a[10] [31]; +endmodule +EOT + +synth_intel_alm -family cyclonev -quartus +select -assert-none w:*[* w:*]* diff --git a/tests/arch/xilinx/xilinx_dffopt.ys b/tests/arch/xilinx/xilinx_dffopt.ys index dc036acfd..2c729832e 100644 --- a/tests/arch/xilinx/xilinx_dffopt.ys +++ b/tests/arch/xilinx/xilinx_dffopt.ys @@ -18,17 +18,17 @@ FDRE ff (.D(tmp[0]), .CE(tmp[1]), .R(tmp[2]), .Q(o[0])); endmodule EOT - +read_verilog -lib +/xilinx/cells_sim.v design -save t0 equiv_opt -blacklist xilinx_dffopt_blacklist.txt -assert -map +/xilinx/cells_sim.v xilinx_dffopt design -load postopt clean +cd t0 select -assert-count 1 t:FDRE select -assert-count 1 t:LUT6 -select -assert-count 3 t:LUT2 -select -assert-none t:FDRE t:LUT6 t:LUT2 %% t:* %D +select -assert-none t:FDRE t:LUT6 %% t:* %D design -load t0 @@ -36,9 +36,10 @@ equiv_opt -blacklist xilinx_dffopt_blacklist.txt -assert -map +/xilinx/cells_sim design -load postopt clean +cd t0 select -assert-count 1 t:FDRE select -assert-count 1 t:LUT4 -select -assert-count 3 t:LUT2 +select -assert-count 1 t:LUT2 select -assert-none t:FDRE t:LUT4 t:LUT2 %% t:* %D design -reset @@ -65,16 +66,17 @@ endmodule EOT +read_verilog -lib +/xilinx/cells_sim.v design -save t0 equiv_opt -blacklist xilinx_dffopt_blacklist.txt -assert -map +/xilinx/cells_sim.v xilinx_dffopt design -load postopt clean +cd t0 select -assert-count 1 t:FDSE select -assert-count 1 t:LUT6 -select -assert-count 3 t:LUT2 -select -assert-none t:FDSE t:LUT6 t:LUT2 %% t:* %D +select -assert-none t:FDSE t:LUT6 %% t:* %D design -load t0 @@ -82,9 +84,10 @@ equiv_opt -blacklist xilinx_dffopt_blacklist.txt -assert -map +/xilinx/cells_sim design -load postopt clean +cd t0 select -assert-count 1 t:FDSE select -assert-count 1 t:LUT4 -select -assert-count 3 t:LUT2 +select -assert-count 1 t:LUT2 select -assert-none t:FDSE t:LUT4 t:LUT2 %% t:* %D design -reset @@ -111,15 +114,17 @@ endmodule EOT +read_verilog -lib +/xilinx/cells_sim.v design -save t0 equiv_opt -async2sync -blacklist xilinx_dffopt_blacklist.txt -assert -map +/xilinx/cells_sim.v xilinx_dffopt design -load postopt clean +cd t0 select -assert-count 1 t:FDCE select -assert-count 1 t:LUT4 -select -assert-count 3 t:LUT2 +select -assert-count 1 t:LUT2 select -assert-none t:FDCE t:LUT4 t:LUT2 %% t:* %D design -reset @@ -145,16 +150,17 @@ endmodule EOT +read_verilog -lib +/xilinx/cells_sim.v design -save t0 equiv_opt -blacklist xilinx_dffopt_blacklist.txt -assert -map +/xilinx/cells_sim.v xilinx_dffopt design -load postopt clean +cd t0 select -assert-count 1 t:FDSE select -assert-count 1 t:LUT5 -select -assert-count 2 t:LUT2 -select -assert-none t:FDSE t:LUT5 t:LUT2 %% t:* %D +select -assert-none t:FDSE t:LUT5 %% t:* %D design -load t0 @@ -162,6 +168,7 @@ equiv_opt -blacklist xilinx_dffopt_blacklist.txt -assert -map +/xilinx/cells_sim design -load postopt clean +cd t0 select -assert-count 1 t:FDSE select -assert-count 2 t:LUT2 select -assert-none t:FDSE t:LUT2 %% t:* %D @@ -191,16 +198,17 @@ endmodule EOT +read_verilog -lib +/xilinx/cells_sim.v design -save t0 equiv_opt -blacklist xilinx_dffopt_blacklist.txt -assert -map +/xilinx/cells_sim.v xilinx_dffopt design -load postopt clean +cd t0 select -assert-count 1 t:FDRSE select -assert-count 1 t:LUT6 -select -assert-count 4 t:LUT2 -select -assert-none t:FDRSE t:LUT6 t:LUT2 %% t:* %D +select -assert-none t:FDRSE t:LUT6 %% t:* %D design -load t0 @@ -208,9 +216,10 @@ equiv_opt -blacklist xilinx_dffopt_blacklist.txt -assert -map +/xilinx/cells_sim design -load postopt clean +cd t0 select -assert-count 1 t:FDRSE select -assert-count 1 t:LUT4 -select -assert-count 4 t:LUT2 +select -assert-count 1 t:LUT2 select -assert-none t:FDRSE t:LUT4 t:LUT2 %% t:* %D design -reset diff --git a/tests/arch/xilinx/xilinx_dsp.ys b/tests/arch/xilinx/xilinx_dsp.ys index 3b9f52930..59d8296ab 100644 --- a/tests/arch/xilinx/xilinx_dsp.ys +++ b/tests/arch/xilinx/xilinx_dsp.ys @@ -8,4 +8,5 @@ assign o4 = a * b; DSP48E1 m3 (.A(a), .B(b), .P(o5)); endmodule EOT +read_verilog -lib +/xilinx/cells_sim.v xilinx_dsp diff --git a/tests/select/blackboxes.ys b/tests/select/blackboxes.ys new file mode 100644 index 000000000..9bfe92c6b --- /dev/null +++ b/tests/select/blackboxes.ys @@ -0,0 +1,28 @@ +read_verilog -specify <<EOT +module top(input a, b, output o); +assign o = a & b; +endmodule + +(* blackbox *) +module bb(input a, b, output o); +assign o = a | b; +specify + (a => o) = 1; +endspecify +endmodule + +(* whitebox *) +module wb(input a, b, output o); +assign o = a ^ b; +endmodule +EOT +clean + +select -assert-count 1 c:* +select -assert-none t:* t:$and %d +select -assert-count 3 w:* +select -assert-count 4 * + +select -assert-count 3 =c:* +select -assert-count 10 =w:* +select -assert-count 13 =* |