synth_ice40: Use opt_dff.
authorMarcelina Kościelnicka <mwk@0x04.net>
Wed, 22 Jul 2020 11:34:11 +0000 (13:34 +0200)
committerMarcelina Kościelnicka <mwk@0x04.net>
Thu, 30 Jul 2020 20:26:20 +0000 (22:26 +0200)
The main part is converting ice40_dsp to recognize the new FF types
created in opt_dff instead of trying to recognize the mux patterns on
its own.

The fsm call has been moved upwards because the passes cannot deal with
$dffe/$sdff*, and other optimizations don't help it much anyway.

passes/pmgen/ice40_dsp.cc
passes/pmgen/ice40_dsp.pmg
techlibs/ice40/Makefile.inc
techlibs/ice40/ice40_ffssr.cc [deleted file]
techlibs/ice40/ice40_opt.cc
techlibs/ice40/synth_ice40.cc
tests/arch/ice40/fsm.ys

index fff04074bba129899af5d94fead30f839bcd2246..c46f5d58ff2dd58b0be0b03d5e24df0645bc81da 100644 (file)
@@ -31,15 +31,15 @@ void create_ice40_dsp(ice40_dsp_pm &pm)
 
        log("Checking %s.%s for iCE40 DSP inference.\n", log_id(pm.module), log_id(st.mul));
 
-       log_debug("ffA:    %s %s %s\n", log_id(st.ffA, "--"), log_id(st.ffAholdmux, "--"), log_id(st.ffArstmux, "--"));
-       log_debug("ffB:    %s %s %s\n", log_id(st.ffB, "--"), log_id(st.ffBholdmux, "--"), log_id(st.ffBrstmux, "--"));
-       log_debug("ffCD:   %s %s\n", log_id(st.ffCD, "--"), log_id(st.ffCDholdmux, "--"));
+       log_debug("ffA:    %s\n", log_id(st.ffA, "--"));
+       log_debug("ffB:    %s\n", log_id(st.ffB, "--"));
+       log_debug("ffCD:   %s\n", log_id(st.ffCD, "--"));
        log_debug("mul:    %s\n", log_id(st.mul, "--"));
        log_debug("ffFJKG: %s\n", log_id(st.ffFJKG, "--"));
        log_debug("ffH:    %s\n", log_id(st.ffH, "--"));
        log_debug("add:    %s\n", log_id(st.add, "--"));
        log_debug("mux:    %s\n", log_id(st.mux, "--"));
-       log_debug("ffO:    %s %s %s\n", log_id(st.ffO, "--"), log_id(st.ffOholdmux, "--"), log_id(st.ffOrstmux, "--"));
+       log_debug("ffO:    %s\n", log_id(st.ffO, "--"));
        log_debug("\n");
 
        if (GetSize(st.sigA) > 16) {
@@ -97,16 +97,16 @@ void create_ice40_dsp(ice40_dsp_pm &pm)
        cell->setParam(ID(D_REG), st.ffCD ? State::S1 : State::S0);
 
        SigSpec AHOLD, BHOLD, CDHOLD;
-       if (st.ffAholdmux)
-               AHOLD = st.ffAholdpol ? st.ffAholdmux->getPort(ID::S) : pm.module->Not(NEW_ID, st.ffAholdmux->getPort(ID::S));
+       if (st.ffA && st.ffA->hasPort(ID::EN))
+               AHOLD = st.ffA->getParam(ID::EN_POLARITY).as_bool() ? pm.module->Not(NEW_ID, st.ffA->getPort(ID::EN)) : st.ffA->getPort(ID::EN);
        else
                AHOLD = State::S0;
-       if (st.ffBholdmux)
-               BHOLD = st.ffBholdpol ? st.ffBholdmux->getPort(ID::S) : pm.module->Not(NEW_ID, st.ffBholdmux->getPort(ID::S));
+       if (st.ffB && st.ffB->hasPort(ID::EN))
+               BHOLD = st.ffB->getParam(ID::EN_POLARITY).as_bool() ? pm.module->Not(NEW_ID, st.ffB->getPort(ID::EN)) : st.ffB->getPort(ID::EN);
        else
                BHOLD = State::S0;
-       if (st.ffCDholdmux)
-               CDHOLD = st.ffCDholdpol ? st.ffCDholdmux->getPort(ID::S) : pm.module->Not(NEW_ID, st.ffCDholdmux->getPort(ID::S));
+       if (st.ffCD && st.ffCD->hasPort(ID::EN))
+               CDHOLD = st.ffCD->getParam(ID::EN_POLARITY).as_bool() ? pm.module->Not(NEW_ID, st.ffCD->getPort(ID::EN)) : st.ffCD->getPort(ID::EN);
        else
                CDHOLD = State::S0;
        cell->setPort(ID(AHOLD), AHOLD);
@@ -115,12 +115,12 @@ void create_ice40_dsp(ice40_dsp_pm &pm)
        cell->setPort(ID(DHOLD), CDHOLD);
 
        SigSpec IRSTTOP, IRSTBOT;
-       if (st.ffArstmux)
-               IRSTTOP = st.ffArstpol ? st.ffArstmux->getPort(ID::S) : pm.module->Not(NEW_ID, st.ffArstmux->getPort(ID::S));
+       if (st.ffA && st.ffA->hasPort(ID::ARST))
+               IRSTTOP = st.ffA->getParam(ID::ARST_POLARITY).as_bool() ? st.ffA->getPort(ID::ARST) : pm.module->Not(NEW_ID, st.ffA->getPort(ID::ARST));
        else
                IRSTTOP = State::S0;
-       if (st.ffBrstmux)
-               IRSTBOT = st.ffBrstpol ? st.ffBrstmux->getPort(ID::S) : pm.module->Not(NEW_ID, st.ffBrstmux->getPort(ID::S));
+       if (st.ffB && st.ffB->hasPort(ID::ARST))
+               IRSTBOT = st.ffB->getParam(ID::ARST_POLARITY).as_bool() ? st.ffB->getPort(ID::ARST) : pm.module->Not(NEW_ID, st.ffB->getPort(ID::ARST));
        else
                IRSTBOT = State::S0;
        cell->setPort(ID(IRSTTOP), IRSTTOP);
@@ -207,16 +207,16 @@ void create_ice40_dsp(ice40_dsp_pm &pm)
        }
 
        SigSpec OHOLD;
-       if (st.ffOholdmux)
-               OHOLD = st.ffOholdpol ? st.ffOholdmux->getPort(ID::S) : pm.module->Not(NEW_ID, st.ffOholdmux->getPort(ID::S));
+       if (st.ffO && st.ffO->hasPort(ID::EN))
+               OHOLD = st.ffO->getParam(ID::EN_POLARITY).as_bool() ? pm.module->Not(NEW_ID, st.ffO->getPort(ID::EN)) : st.ffO->getPort(ID::EN);
        else
                OHOLD = State::S0;
        cell->setPort(ID(OHOLDTOP), OHOLD);
        cell->setPort(ID(OHOLDBOT), OHOLD);
 
        SigSpec ORST;
-       if (st.ffOrstmux)
-               ORST = st.ffOrstpol ? st.ffOrstmux->getPort(ID::S) : pm.module->Not(NEW_ID, st.ffOrstmux->getPort(ID::S));
+       if (st.ffO && st.ffO->hasPort(ID::ARST))
+               ORST = st.ffO->getParam(ID::ARST_POLARITY).as_bool() ? st.ffO->getPort(ID::ARST) : pm.module->Not(NEW_ID, st.ffO->getPort(ID::ARST));
        else
                ORST = State::S0;
        cell->setPort(ID(ORSTTOP), ORST);
@@ -228,6 +228,8 @@ void create_ice40_dsp(ice40_dsp_pm &pm)
                        acc_reset = st.mux->getPort(ID::S);
                else
                        acc_reset = pm.module->Not(NEW_ID, st.mux->getPort(ID::S));
+       } else if (st.ffO && st.ffO->hasPort(ID::SRST)) {
+               acc_reset = st.ffO->getParam(ID::SRST_POLARITY).as_bool() ? st.ffO->getPort(ID::SRST) : pm.module->Not(NEW_ID, st.ffO->getPort(ID::SRST));
        }
        cell->setPort(ID(OLOADTOP), acc_reset);
        cell->setPort(ID(OLOADBOT), acc_reset);
index 2456a49dc74dbe3c2bdfb437b61ff8cc0f9eadd3..7a01cbd51e299b6d2b72e406b1c0eaa9f46249a4 100644 (file)
@@ -6,20 +6,16 @@ state <SigSpec> sigA sigB sigCD sigH sigO
 state <Cell*> add mux
 state <IdString> addAB muxAB
 
-state <bool> ffAholdpol ffBholdpol ffCDholdpol ffOholdpol
-state <bool> ffArstpol ffBrstpol ffCDrstpol ffOrstpol
-
-state <Cell*> ffA ffAholdmux ffArstmux ffB ffBholdmux ffBrstmux ffCD ffCDholdmux
-state <Cell*> ffFJKG ffH ffO ffOholdmux ffOrstmux
+state <Cell*> ffA ffB ffCD
+state <Cell*> ffFJKG ffH ffO
 
 // subpattern
+state <bool> argSdff
 state <SigSpec> argQ argD
-state <bool> ffholdpol ffrstpol
-state <int> ffoffset
 udata <SigSpec> dffD dffQ
 udata <SigBit> dffclock
-udata <Cell*> dff dffholdmux dffrstmux
-udata <bool> dffholdpol dffrstpol dffclock_pol
+udata <Cell*> dff
+udata <bool> dffclock_pol
 
 match mul
        select mul->type.in($mul, \SB_MAC16)
@@ -64,7 +60,7 @@ code sigA sigB sigH
        log_assert(nusers(O.extract_end(i)) <= 1);
 endcode
 
-code argQ ffA ffAholdmux ffArstmux ffAholdpol ffArstpol sigA clock clock_pol
+code argQ ffA sigA clock clock_pol
        if (mul->type != \SB_MAC16 || !param(mul, \A_REG).as_bool()) {
                argQ = sigA;
                subpattern(in_dffe);
@@ -72,20 +68,12 @@ code argQ ffA ffAholdmux ffArstmux ffAholdpol ffArstpol sigA clock clock_pol
                        ffA = dff;
                        clock = dffclock;
                        clock_pol = dffclock_pol;
-                       if (dffrstmux) {
-                               ffArstmux = dffrstmux;
-                               ffArstpol = dffrstpol;
-                       }
-                       if (dffholdmux) {
-                               ffAholdmux = dffholdmux;
-                               ffAholdpol = dffholdpol;
-                       }
                        sigA = dffD;
                }
        }
 endcode
 
-code argQ ffB ffBholdmux ffBrstmux ffBholdpol ffBrstpol sigB clock clock_pol
+code argQ ffB sigB clock clock_pol
        if (mul->type != \SB_MAC16 || !param(mul, \B_REG).as_bool()) {
                argQ = sigB;
                subpattern(in_dffe);
@@ -93,47 +81,44 @@ code argQ ffB ffBholdmux ffBrstmux ffBholdpol ffBrstpol sigB clock clock_pol
                        ffB = dff;
                        clock = dffclock;
                        clock_pol = dffclock_pol;
-                       if (dffrstmux) {
-                               ffBrstmux = dffrstmux;
-                               ffBrstpol = dffrstpol;
-                       }
-                       if (dffholdmux) {
-                               ffBholdmux = dffholdmux;
-                               ffBholdpol = dffholdpol;
-                       }
                        sigB = dffD;
                }
        }
 endcode
 
-code argD ffFJKG sigH clock clock_pol
+code argD argSdff 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()))) {
                argD = sigH;
+               argSdff = false;
                subpattern(out_dffe);
                if (dff) {
                        // F/J/K/G do not have a CE-like (hold) input
-                       if (dffholdmux)
+                       if (dff->hasPort(\EN))
                                goto reject_ffFJKG;
 
                        // Reset signal of F/J (IRSTTOP) and K/G (IRSTBOT)
                        //   shared with A and B
-                       if ((ffArstmux != NULL) != (dffrstmux != NULL))
-                               goto reject_ffFJKG;
-                       if ((ffBrstmux != NULL) != (dffrstmux != NULL))
-                               goto reject_ffFJKG;
-                       if (ffArstmux) {
-                               if (port(ffArstmux, \S) != port(dffrstmux, \S))
-                                       goto reject_ffFJKG;
-                               if (ffArstpol != dffrstpol)
+                       if (ffA) {
+                               if (ffA->hasPort(\ARST) != dff->hasPort(\ARST))
                                        goto reject_ffFJKG;
+                               if (ffA->hasPort(\ARST)) {
+                                       if (port(ffA, \ARST) != port(dff, \ARST))
+                                               goto reject_ffFJKG;
+                                       if (param(ffA, \ARST_POLARITY) != param(dff, \ARST_POLARITY))
+                                               goto reject_ffFJKG;
+                               }
                        }
-                       if (ffBrstmux) {
-                               if (port(ffBrstmux, \S) != port(dffrstmux, \S))
-                                       goto reject_ffFJKG;
-                               if (ffBrstpol != dffrstpol)
+                       if (ffB) {
+                               if (ffB->hasPort(\ARST) != dff->hasPort(\ARST))
                                        goto reject_ffFJKG;
+                               if (ffB->hasPort(\ARST)) {
+                                       if (port(ffB, \ARST) != port(dff, \ARST))
+                                               goto reject_ffFJKG;
+                                       if (param(ffB, \ARST_POLARITY) != param(dff, \ARST_POLARITY))
+                                               goto reject_ffFJKG;
+                               }
                        }
 
                        ffFJKG = dff;
@@ -146,23 +131,24 @@ reject_ffFJKG:            ;
        }
 endcode
 
-code argD ffH sigH sigO clock clock_pol
+code argD argSdff ffH sigH sigO clock clock_pol
        if (ffFJKG && nusers(sigH) == 2 &&
                        (mul->type != \SB_MAC16 || !param(mul, \PIPELINE_16x16_MULT_REG2).as_bool())) {
                argD = sigH;
+               argSdff = false;
                subpattern(out_dffe);
                if (dff) {
                        // H does not have a CE-like (hold) input
-                       if (dffholdmux)
+                       if (dff->hasPort(\EN))
                                goto reject_ffH;
 
                        // Reset signal of H (IRSTBOT) shared with B
-                       if ((ffBrstmux != NULL) != (dffrstmux != NULL))
+                       if (ffB->hasPort(\ARST) != dff->hasPort(\ARST))
                                goto reject_ffH;
-                       if (ffBrstmux) {
-                               if (port(ffBrstmux, \S) != port(dffrstmux, \S))
+                       if (ffB->hasPort(\ARST)) {
+                               if (port(ffB, \ARST) != port(dff, \ARST))
                                        goto reject_ffH;
-                               if (ffBrstpol != dffrstpol)
+                               if (param(ffB, \ARST_POLARITY) != param(dff, \ARST_POLARITY))
                                        goto reject_ffH;
                        }
 
@@ -226,7 +212,7 @@ code sigO
                sigO = port(mux, \Y);
 endcode
 
-code argD ffO ffOholdmux ffOrstmux ffOholdpol ffOrstpol sigO sigCD clock clock_pol cd_signed o_lo
+code argD argSdff ffO 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).as_int() != 1 && param(mul, \BOTOUTPUT_SELECT).as_int() != 1) &&
@@ -238,6 +224,7 @@ code argD ffO ffOholdmux ffOrstmux ffOholdpol ffOrstpol sigO sigCD clock clock_p
                // First try entire sigO
                if (nusers(sigO) == 2) {
                        argD = sigO;
+                       argSdff = !mux;
                        subpattern(out_dffe);
                }
 
@@ -245,6 +232,7 @@ code argD ffO ffOholdmux ffOrstmux ffOholdpol ffOrstpol sigO sigCD clock clock_p
                if (!dff && GetSize(sigO) > 16) {
                        argD = sigO.extract(0, 16);
                        if (nusers(argD) == 2) {
+                               argSdff = !mux;
                                subpattern(out_dffe);
                                o_lo = dff;
                        }
@@ -254,14 +242,6 @@ code argD ffO ffOholdmux ffOrstmux ffOholdpol ffOrstpol sigO sigCD clock clock_p
                        ffO = dff;
                        clock = dffclock;
                        clock_pol = dffclock_pol;
-                       if (dffrstmux) {
-                               ffOrstmux = dffrstmux;
-                               ffOrstpol = dffrstpol;
-                       }
-                       if (dffholdmux) {
-                               ffOholdmux = dffholdmux;
-                               ffOholdpol = dffholdpol;
-                       }
 
                        sigO.replace(sigO.extract(0, GetSize(dffQ)), dffQ);
                }
@@ -273,39 +253,44 @@ code argD ffO ffOholdmux ffOrstmux ffOholdpol ffOrstpol sigO sigCD clock clock_p
                                reject;
                        sigCD = port(mux, muxAB == \B ? \A : \B);
 
+                       cd_signed = add && param(add, \A_SIGNED).as_bool() && param(add, \B_SIGNED).as_bool();
+               } else if (dff && dff->hasPort(\SRST)) {
+                       if (sigCD != sigO)
+                               reject;
+                       sigCD = param(dff, \SRST_VALUE);
+
                        cd_signed = add && param(add, \A_SIGNED).as_bool() && param(add, \B_SIGNED).as_bool();
                }
        }
 endcode
 
-code argQ ffCD ffCDholdmux ffCDholdpol ffCDrstpol sigCD clock clock_pol
+code argQ ffCD 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()))) {
                argQ = sigCD;
                subpattern(in_dffe);
                if (dff) {
-                       if (dffholdmux) {
-                               ffCDholdmux = dffholdmux;
-                               ffCDholdpol = dffholdpol;
-                       }
-
                        // Reset signal of C (IRSTTOP) and D (IRSTBOT)
                        //   shared with A and B
-                       if ((ffArstmux != NULL) != (dffrstmux != NULL))
-                               goto reject_ffCD;
-                       if ((ffBrstmux != NULL) != (dffrstmux != NULL))
-                               goto reject_ffCD;
-                       if (ffArstmux) {
-                               if (port(ffArstmux, \S) != port(dffrstmux, \S))
-                                       goto reject_ffCD;
-                               if (ffArstpol != dffrstpol)
+                       if (ffA) {
+                               if (ffA->hasPort(\ARST) != dff->hasPort(\ARST))
                                        goto reject_ffCD;
+                               if (ffA->hasPort(\ARST)) {
+                                       if (port(ffA, \ARST) != port(dff, \ARST))
+                                               goto reject_ffCD;
+                                       if (param(ffA, \ARST_POLARITY) != param(dff, \ARST_POLARITY))
+                                               goto reject_ffCD;
+                               }
                        }
-                       if (ffBrstmux) {
-                               if (port(ffBrstmux, \S) != port(dffrstmux, \S))
-                                       goto reject_ffCD;
-                               if (ffBrstpol != dffrstpol)
+                       if (ffB) {
+                               if (ffB->hasPort(\ARST) != dff->hasPort(\ARST))
                                        goto reject_ffCD;
+                               if (ffB->hasPort(\ARST)) {
+                                       if (port(ffB, \ARST) != port(dff, \ARST))
+                                               goto reject_ffCD;
+                                       if (param(ffB, \ARST_POLARITY) != param(dff, \ARST_POLARITY))
+                                               goto reject_ffCD;
+                               }
                        }
 
                        ffCD = dff;
@@ -347,7 +332,7 @@ code
 endcode
 
 match ff
-       select ff->type.in($dff)
+       select ff->type.in($dff, $dffe)
        // DSP48E1 does not support clock inversion
        select param(ff, \CLK_POLARITY).as_bool()
 
@@ -357,8 +342,6 @@ match ff
        // Check that the rest of argQ is present
        filter GetSize(port(ff, \Q)) >= offset + GetSize(argQ)
        filter port(ff, \Q).extract(offset, GetSize(argQ)) == argQ
-
-       set ffoffset offset
 endmatch
 
 code argQ argD
@@ -378,72 +361,13 @@ code argQ argD
        argD = port(ff, \D);
        argQ = Q;
        dffD.replace(argQ, argD);
-       // Only search for ffrstmux if dffD only
-       //   has two (ff, ffrstmux) users
-       if (nusers(dffD) > 2)
-               argD = SigSpec();
 }
 endcode
 
-match ffrstmux
-       if false /* TODO: ice40 resets are actually async */
-
-       if !argD.empty()
-       select ffrstmux->type.in($mux)
-       index <SigSpec> port(ffrstmux, \Y) === argD
-
-       choice <IdString> BA {\B, \A}
-       // DSP48E1 only supports reset to zero
-       select port(ffrstmux, BA).is_fully_zero()
-
-       define <bool> pol (BA == \B)
-       set ffrstpol pol
-       semioptional
-endmatch
-
-code argD
-       if (ffrstmux) {
-               dffrstmux = ffrstmux;
-               dffrstpol = ffrstpol;
-               argD = port(ffrstmux, ffrstpol ? \A : \B);
-               dffD.replace(port(ffrstmux, \Y), argD);
-
-               // Only search for ffholdmux if argQ has at
-               //   least 3 users (ff, <upstream>, ffrstmux) and
-               //   dffD only has two (ff, ffrstmux)
-               if (!(nusers(argQ) >= 3 && nusers(dffD) == 2))
-                       argD = SigSpec();
-       }
-       else
-               dffrstmux = nullptr;
-endcode
-
-match ffholdmux
-       if !argD.empty()
-       select ffholdmux->type.in($mux)
-       index <SigSpec> port(ffholdmux, \Y) === argD
-       choice <IdString> BA {\B, \A}
-       index <SigSpec> port(ffholdmux, BA) === argQ
-       define <bool> pol (BA == \B)
-       set ffholdpol pol
-       semioptional
-endmatch
-
-code argD
-       if (ffholdmux) {
-               dffholdmux = ffholdmux;
-               dffholdpol = ffholdpol;
-               argD = port(ffholdmux, ffholdpol ? \A : \B);
-               dffD.replace(port(ffholdmux, \Y), argD);
-       }
-       else
-               dffholdmux = nullptr;
-endcode
-
 // #######################
 
 subpattern out_dffe
-arg argD argQ clock clock_pol
+arg argD argSdff argQ clock clock_pol
 
 code
        dff = nullptr;
@@ -452,101 +376,19 @@ code
                        reject;
 endcode
 
-match ffholdmux
-       select ffholdmux->type.in($mux)
-       // ffholdmux output must have two users: ffholdmux and ff.D
-       select nusers(port(ffholdmux, \Y)) == 2
-
-       choice <IdString> BA {\B, \A}
-       // keep-last-value net must have at least three users: ffholdmux, ff, downstream sink(s)
-       select nusers(port(ffholdmux, BA)) >= 3
-
-       slice offset GetSize(port(ffholdmux, \Y))
-       define <IdString> AB (BA == \B ? \A : \B)
-       index <SigBit> port(ffholdmux, AB)[offset] === argD[0]
-
-       // Check that the rest of argD is present
-       filter GetSize(port(ffholdmux, AB)) >= offset + GetSize(argD)
-       filter port(ffholdmux, AB).extract(offset, GetSize(argD)) == argD
-
-       set ffoffset offset
-       define <bool> pol (BA == \B)
-       set ffholdpol pol
-
-       semioptional
-endmatch
-
-code argD argQ
-       dffholdmux = ffholdmux;
-       if (ffholdmux) {
-               SigSpec AB = port(ffholdmux, ffholdpol ? \A : \B);
-               SigSpec Y = port(ffholdmux, \Y);
-               argQ = argD;
-               argD.replace(AB, Y);
-               argQ.replace(AB, port(ffholdmux, ffholdpol ? \B : \A));
-
-               dffholdmux = ffholdmux;
-               dffholdpol = ffholdpol;
-       }
-endcode
-
-match ffrstmux
-       if false /* TODO: ice40 resets are actually async */
-
-       select ffrstmux->type.in($mux)
-       // ffrstmux output must have two users: ffrstmux and ff.D
-       select nusers(port(ffrstmux, \Y)) == 2
-
-       choice <IdString> BA {\B, \A}
-       // DSP48E1 only supports reset to zero
-       select port(ffrstmux, BA).is_fully_zero()
-
-       slice offset GetSize(port(ffrstmux, \Y))
-       define <IdString> AB (BA == \B ? \A : \B)
-       index <SigBit> port(ffrstmux, AB)[offset] === argD[0]
-
-       // Check that offset is consistent
-       filter !ffholdmux || ffoffset == offset
-       // Check that the rest of argD is present
-       filter GetSize(port(ffrstmux, AB)) >= offset + GetSize(argD)
-       filter port(ffrstmux, AB).extract(offset, GetSize(argD)) == argD
-
-       set ffoffset offset
-       define <bool> pol (AB == \A)
-       set ffrstpol pol
-
-       semioptional
-endmatch
-
-code argD argQ
-       dffrstmux = ffrstmux;
-       if (ffrstmux) {
-               SigSpec AB = port(ffrstmux, ffrstpol ? \A : \B);
-               SigSpec Y = port(ffrstmux, \Y);
-               argD.replace(AB, Y);
-
-               dffrstmux = ffrstmux;
-               dffrstpol = ffrstpol;
-       }
-endcode
-
 match ff
-       select ff->type.in($dff)
+       select ff->type.in($dff, $dffe, $sdff, $sdffce)
        // SB_MAC16 does not support clock inversion
        select param(ff, \CLK_POLARITY).as_bool()
 
        slice offset GetSize(port(ff, \D))
        index <SigBit> port(ff, \D)[offset] === argD[0]
 
-       // Check that offset is consistent
-       filter (!ffholdmux && !ffrstmux) || ffoffset == offset
+       // Only allow sync reset if requested.
+       filter argSdff || ff->type.in($dff, $dffe)
        // Check that the rest of argD is present
        filter GetSize(port(ff, \D)) >= offset + GetSize(argD)
        filter port(ff, \D).extract(offset, GetSize(argD)) == argD
-       // Check that FF.Q is connected to CE-mux
-       filter !ffholdmux || port(ff, \Q).extract(offset, GetSize(argQ)) == argQ
-
-       set ffoffset offset
 endmatch
 
 code argQ
@@ -559,10 +401,8 @@ code argQ
                }
                SigSpec D = port(ff, \D);
                SigSpec Q = port(ff, \Q);
-               if (!ffholdmux) {
-                       argQ = argD;
-                       argQ.replace(D, Q);
-               }
+               argQ = argD;
+               argQ.replace(D, Q);
 
                for (auto c : argQ.chunks()) {
                        Const init = c.wire->attributes.at(\init, State::Sx);
@@ -575,7 +415,4 @@ code argQ
                dffclock = port(ff, \CLK);
                dffclock_pol = param(ff, \CLK_POLARITY).as_bool();
        }
-       // No enable/reset mux possible without flop
-       else if (dffholdmux || dffrstmux)
-               reject;
 endcode
index 4f4faf6d5a0373a08a124e6f944e807863c953f4..8ce3cb024573c5c253ef785254ab263aa7d11fb9 100644 (file)
@@ -1,7 +1,6 @@
 
 OBJS += techlibs/ice40/synth_ice40.o
 OBJS += techlibs/ice40/ice40_braminit.o
-OBJS += techlibs/ice40/ice40_ffssr.o
 OBJS += techlibs/ice40/ice40_opt.o
 
 GENFILES += techlibs/ice40/brams_init1.vh
diff --git a/techlibs/ice40/ice40_ffssr.cc b/techlibs/ice40/ice40_ffssr.cc
deleted file mode 100644 (file)
index 492029b..0000000
+++ /dev/null
@@ -1,131 +0,0 @@
-/*
- *  yosys -- Yosys Open SYnthesis Suite
- *
- *  Copyright (C) 2012  Clifford Wolf <clifford@clifford.at>
- *
- *  Permission to use, copy, modify, and/or distribute this software for any
- *  purpose with or without fee is hereby granted, provided that the above
- *  copyright notice and this permission notice appear in all copies.
- *
- *  THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- *  WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- *  MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- *  ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- *  WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- *  ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- *  OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- *
- */
-
-#include "kernel/yosys.h"
-#include "kernel/sigtools.h"
-
-USING_YOSYS_NAMESPACE
-PRIVATE_NAMESPACE_BEGIN
-
-struct Ice40FfssrPass : public Pass {
-       Ice40FfssrPass() : Pass("ice40_ffssr", "iCE40: merge synchronous set/reset into FF cells") { }
-       void help() override
-       {
-               log("\n");
-               log("    ice40_ffssr [options] [selection]\n");
-               log("\n");
-               log("Merge synchronous set/reset $_MUX_ cells into iCE40 FFs.\n");
-               log("\n");
-       }
-       void execute(std::vector<std::string> args, RTLIL::Design *design) override
-       {
-               log_header(design, "Executing ICE40_FFSSR pass (merge synchronous set/reset into FF cells).\n");
-
-               size_t argidx;
-               for (argidx = 1; argidx < args.size(); argidx++)
-               {
-                       // if (args[argidx] == "-singleton") {
-                       //      singleton_mode = true;
-                       //      continue;
-                       // }
-                       break;
-               }
-               extra_args(args, argidx, design);
-
-               pool<IdString> sb_dff_types;
-               sb_dff_types.insert(ID(SB_DFF));
-               sb_dff_types.insert(ID(SB_DFFE));
-               sb_dff_types.insert(ID(SB_DFFN));
-               sb_dff_types.insert(ID(SB_DFFNE));
-
-               for (auto module : design->selected_modules())
-               {
-                       log("Merging set/reset $_MUX_ cells into SB_FFs in %s.\n", log_id(module));
-
-                       SigMap sigmap(module);
-                       dict<SigBit, Cell*> sr_muxes;
-                       vector<Cell*> ff_cells;
-
-                       for (auto cell : module->selected_cells())
-                       {
-                               if (sb_dff_types.count(cell->type)) {
-                                       ff_cells.push_back(cell);
-                                       continue;
-                               }
-
-                               if (cell->type != ID($_MUX_))
-                                       continue;
-
-                               SigBit bit_a = sigmap(cell->getPort(ID::A));
-                               SigBit bit_b = sigmap(cell->getPort(ID::B));
-
-                               if (bit_a.wire == nullptr || bit_b.wire == nullptr)
-                                       sr_muxes[sigmap(cell->getPort(ID::Y))] = cell;
-                       }
-
-                       for (auto cell : ff_cells)
-                       {
-                               if (cell->get_bool_attribute(ID(dont_touch)))
-                                       continue;
-
-                               SigSpec sig_d = cell->getPort(ID::D);
-
-                               if (GetSize(sig_d) < 1)
-                                       continue;
-
-                               SigBit bit_d = sigmap(sig_d[0]);
-
-                               if (sr_muxes.count(bit_d) == 0)
-                                       continue;
-
-                               Cell *mux_cell = sr_muxes.at(bit_d);
-                               SigBit bit_a = sigmap(mux_cell->getPort(ID::A));
-                               SigBit bit_b = sigmap(mux_cell->getPort(ID::B));
-                               SigBit bit_s = sigmap(mux_cell->getPort(ID::S));
-
-                               log("  Merging %s (A=%s, B=%s, S=%s) into %s (%s).\n", log_id(mux_cell),
-                                               log_signal(bit_a), log_signal(bit_b), log_signal(bit_s), log_id(cell), log_id(cell->type));
-
-                               SigBit sr_val, sr_sig;
-                               if (bit_a.wire == nullptr) {
-                                       bit_d = bit_b;
-                                       sr_val = bit_a;
-                                       sr_sig = module->NotGate(NEW_ID, bit_s);
-                               } else {
-                                       log_assert(bit_b.wire == nullptr);
-                                       bit_d = bit_a;
-                                       sr_val = bit_b;
-                                       sr_sig = bit_s;
-                               }
-
-                               if (sr_val == State::S1) {
-                                       cell->type = cell->type.str() + "SS";
-                                       cell->setPort(ID::S, sr_sig);
-                                       cell->setPort(ID::D, bit_d);
-                               } else {
-                                       cell->type = cell->type.str() + "SR";
-                                       cell->setPort(ID::R, sr_sig);
-                                       cell->setPort(ID::D, bit_d);
-                               }
-                       }
-               }
-       }
-} Ice40FfssrPass;
-
-PRIVATE_NAMESPACE_END
index 1a70fa8c0f9ed361ce47c1a32691046fcff8f9bf..d2860790451b8166b4f7e505550a250478ef914e 100644 (file)
@@ -215,7 +215,7 @@ struct Ice40OptPass : public Pass {
                log("        <ice40 specific optimizations>\n");
                log("        opt_expr -mux_undef -undriven [-full]\n");
                log("        opt_merge\n");
-               log("        opt_rmdff\n");
+               log("        opt_dff\n");
                log("        opt_clean\n");
                log("    while <changed design>\n");
                log("\n");
@@ -247,7 +247,7 @@ struct Ice40OptPass : public Pass {
 
                        Pass::call(design, "opt_expr " + opt_expr_args);
                        Pass::call(design, "opt_merge");
-                       Pass::call(design, "opt_rmdff");
+                       Pass::call(design, "opt_dff");
                        Pass::call(design, "opt_clean");
 
                        if (design->scratchpad_get_bool("opt.did_something") == false)
index 4ddb6ca70aeca9b8a5a674f69ffb63063d66ce73..ae6d3539cd837dda6b76af70d0a334b221d60692 100644 (file)
@@ -293,6 +293,10 @@ struct SynthIce40Pass : public ScriptPass
                        run("opt_clean");
                        run("check");
                        run("opt");
+                       run("fsm");
+                       run("opt");
+                       run("opt_dff");
+                       run("opt");
                        run("wreduce");
                        run("peepopt");
                        run("opt_clean");
@@ -316,8 +320,6 @@ struct SynthIce40Pass : public ScriptPass
                        }
                        run("alumacc");
                        run("opt");
-                       run("fsm");
-                       run("opt -fast");
                        run("memory -nomap");
                        run("opt_clean");
                }
@@ -354,11 +356,6 @@ struct SynthIce40Pass : public ScriptPass
 
                if (check_label("map_ffs"))
                {
-                       if (!nodffe)
-                               run("dff2dffe -direct-match $_DFF_*");
-                       if (min_ce_use >= 0) {
-                               run("opt_merge");
-                       }
                        if (nodffe)
                                run(stringf("dfflegalize -cell $_DFF_?_ 0 -cell $_DFF_?P?_ 0 -cell $_SDFF_?P?_ 0 -cell $_DLATCH_?_ x"));
                        else
@@ -366,7 +363,6 @@ struct SynthIce40Pass : public ScriptPass
                        run("techmap -map +/ice40/ff_map.v");
                        run("opt_expr -mux_undef");
                        run("simplemap");
-                       run("ice40_ffssr");
                        run("ice40_opt -full");
                }
 
index 223ba070e9900501ef01763f9aae3531b03e31a9..e3b74620232a67c9ee933076a1ed48d19f2c15ac 100644 (file)
@@ -12,5 +12,5 @@ cd fsm # Constrain all select calls below inside the top module
 
 select -assert-count 4 t:SB_DFF
 select -assert-count 2 t:SB_DFFESR
-select -assert-count 15 t:SB_LUT4
+select -assert-max 15 t:SB_LUT4
 select -assert-none t:SB_DFFESR t:SB_DFF t:SB_LUT4 %% t:* %D