Merge pull request #1637 from YosysHQ/mwk/fix-1634
[yosys.git] / passes / pmgen / ice40_dsp.pmg
index 19ee9054b813f38a2d16454119eb8af73cb93d37..9d649cb98a2b0b3950a389fa0305b2a771af3867 100644 (file)
@@ -1,6 +1,5 @@
 pattern ice40_dsp
 
-udata <std::function<SigSpec(const SigSpec&)>> unextend
 state <SigBit> clock
 state <bool> clock_pol cd_signed o_lo
 state <SigSpec> sigA sigB sigCD sigH sigO
@@ -28,7 +27,7 @@ match mul
 endmatch
 
 code sigA sigB sigH
-       unextend = [](const SigSpec &sig) {
+       auto unextend = [](const SigSpec &sig) {
                int i;
                for (i = GetSize(sig)-1; i > 0; i--)
                        if (sig[i] != sig[i-1])
@@ -57,11 +56,16 @@ code sigA sigB sigH
                        break;
                sigH.append(O[i]);
        }
+       // This sigM could have no users if downstream sinks (e.g. $add) is
+       //   narrower than $mul result, for example
+       if (i == 0)
+               reject;
+
        log_assert(nusers(O.extract_end(i)) <= 1);
 endcode
 
 code argQ ffA ffAholdmux ffArstmux ffAholdpol ffArstpol sigA clock clock_pol
-       if (mul->type != \SB_MAC16 || !param(mul, \A_REG).as_bool()) {
+       if (mul->type != \SB_MAC16 || !param(mul, \A_REG, State::S0).as_bool()) {
                argQ = sigA;
                subpattern(in_dffe);
                if (dff) {
@@ -82,7 +86,7 @@ code argQ ffA ffAholdmux ffArstmux ffAholdpol ffArstpol sigA clock clock_pol
 endcode
 
 code argQ ffB ffBholdmux ffBrstmux ffBholdpol ffBrstpol sigB clock clock_pol
-       if (mul->type != \SB_MAC16 || !param(mul, \B_REG).as_bool()) {
+       if (mul->type != \SB_MAC16 || !param(mul, \B_REG, State::S0).as_bool()) {
                argQ = sigB;
                subpattern(in_dffe);
                if (dff) {
@@ -105,7 +109,7 @@ endcode
 code argD ffFJKG sigH clock clock_pol
        if (nusers(sigH) == 2 &&
                        (mul->type != \SB_MAC16 ||
-                        (!param(mul, \TOP_8x8_MULT_REG).as_bool() && !param(mul, \BOT_8x8_MULT_REG).as_bool() && !param(mul, \PIPELINE_16x16_MULT_REG1).as_bool() && !param(mul, \PIPELINE_16x16_MULT_REG1).as_bool()))) {
+                        (!param(mul, \TOP_8x8_MULT_REG, State::S0).as_bool() && !param(mul, \BOT_8x8_MULT_REG, State::S0).as_bool() && !param(mul, \PIPELINE_16x16_MULT_REG1, State::S0).as_bool() && !param(mul, \PIPELINE_16x16_MULT_REG1, State::S0).as_bool()))) {
                argD = sigH;
                subpattern(out_dffe);
                if (dff) {
@@ -144,7 +148,7 @@ endcode
 
 code argD ffH sigH sigO clock clock_pol
        if (ffFJKG && nusers(sigH) == 2 &&
-                       (mul->type != \SB_MAC16 || !param(mul, \PIPELINE_16x16_MULT_REG2).as_bool())) {
+                       (mul->type != \SB_MAC16 || !param(mul, \PIPELINE_16x16_MULT_REG2, State::S0).as_bool())) {
                argD = sigH;
                subpattern(out_dffe);
                if (dff) {
@@ -175,7 +179,7 @@ reject_ffH:         ;
 endcode
 
 match add
-       if mul->type != \SB_MAC16 || (param(mul, \TOPOUTPUT_SELECT).as_int() == 3 && param(mul, \BOTOUTPUT_SELECT).as_int() == 3)
+       if mul->type != \SB_MAC16 || (param(mul, \TOPOUTPUT_SELECT, State::S0).as_int() == 3 && param(mul, \BOTOUTPUT_SELECT, State::S0).as_int() == 3)
 
        select add->type.in($add)
        choice <IdString> AB {\A, \B}
@@ -201,7 +205,7 @@ code sigCD sigO cd_signed
                if ((actual_acc_width > actual_mul_width) && (natural_mul_width > actual_mul_width))
                        reject;
                // If accumulator, check adder width and signedness
-               if (sigCD == sigH && (actual_acc_width != actual_mul_width) && (param(mul, \A_SIGNED).as_bool() != param(add, \A_SIGNED).as_bool()))
+               if (sigCD == sigH && (actual_acc_width != actual_mul_width) && (param(mul, \A_SIGNED, State::S0).as_bool() != param(add, \A_SIGNED).as_bool()))
                        reject;
 
                sigO = port(add, \Y);
@@ -225,9 +229,9 @@ 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
-                       ((mul->parameters.at(\TOPOUTPUT_SELECT, 0).as_int() != 1 && mul->parameters.at(\BOTOUTPUT_SELECT, 0).as_int() != 1) &&
+                       ((param(mul, \TOPOUTPUT_SELECT, 0).as_int() != 1 && param(mul, \BOTOUTPUT_SELECT, 0).as_int() != 1) &&
                         // Ensure that OLOADTOP/OLOADBOT is unused or zero
-                        (mul->connections_.at(\OLOADTOP, State::S0).is_fully_zero() && mul->connections_.at(\OLOADBOT, State::S0).is_fully_zero()))) {
+                        (port(mul, \OLOADTOP, State::S0).is_fully_zero() && port(mul, \OLOADBOT, State::S0).is_fully_zero()))) {
 
                dff = nullptr;
 
@@ -276,7 +280,7 @@ endcode
 
 code argQ ffCD ffCDholdmux ffCDholdpol ffCDrstpol sigCD clock clock_pol
        if (!sigCD.empty() && sigCD != sigO &&
-                       (mul->type != \SB_MAC16 || (!param(mul, \C_REG).as_bool() && !param(mul, \D_REG).as_bool()))) {
+                       (mul->type != \SB_MAC16 || (!param(mul, \C_REG, State::S0).as_bool() && !param(mul, \D_REG, State::S0).as_bool()))) {
                argQ = sigCD;
                subpattern(in_dffe);
                if (dff) {
@@ -329,11 +333,16 @@ arg argD argQ clock clock_pol
 
 code
        dff = nullptr;
+       if (argQ.empty())
+               reject;
        for (auto c : argQ.chunks()) {
                if (!c.wire)
                        reject;
                if (c.wire->get_bool_attribute(\keep))
                        reject;
+               Const init = c.wire->attributes.at(\init, State::Sx);
+               if (!init.is_fully_undef() && !init.is_fully_zero())
+                       reject;
        }
 endcode