Add HOLD/RST support for SB_MAC16
authorEddie Hung <eddie@fpgeh.com>
Thu, 19 Sep 2019 21:02:55 +0000 (14:02 -0700)
committerEddie Hung <eddie@fpgeh.com>
Thu, 19 Sep 2019 21:02:55 +0000 (14:02 -0700)
passes/pmgen/ice40_dsp.cc
passes/pmgen/ice40_dsp.pmg

index 7592593a6b8637a71f0672493f2fc2b213f5fbcd..f3cc83699b8102f2db468d00ce535fd3ba06bc36 100644 (file)
@@ -33,13 +33,13 @@ void create_ice40_dsp(ice40_dsp_pm &pm)
        log("\n");
        log("ffA:    %s %s %s\n", log_id(st.ffA, "--"), log_id(st.ffAcemux, "--"), log_id(st.ffArstmux, "--"));
        log("ffB:    %s %s %s\n", log_id(st.ffB, "--"), log_id(st.ffBcemux, "--"), log_id(st.ffBrstmux, "--"));
-       log("ffCD:   %s %s %s\n", log_id(st.ffCD, "--"), log_id(st.ffCDcemux, "--"), log_id(st.ffCDrstmux, "--"));
+       log("ffCD:   %s %s\n", log_id(st.ffCD, "--"), log_id(st.ffCDcemux, "--"));
        log("mul:    %s\n", log_id(st.mul, "--"));
-       log("ffFJKG: %s n/a %s\n", log_id(st.ffFJKG, "--"), log_id(st.ffFJKGrstmux, "--"));
-       log("ffH:    %s n/a %s\n", log_id(st.ffH, "--"), log_id(st.ffHrstmux, "--"));
+       log("ffFJKG: %s\n", log_id(st.ffFJKG, "--"));
+       log("ffH:    %s\n", log_id(st.ffH, "--"));
        log("add:    %s\n", log_id(st.add, "--"));
        log("mux:    %s\n", log_id(st.mux, "--"));
-       log("ffO:    %s\n", log_id(st.ffO, "--"));
+       log("ffO:    %s %s %s\n", log_id(st.ffO, "--"), log_id(st.ffOcemux, "--"), log_id(st.ffOrstmux, "--"));
 #endif
 
        log("Checking %s.%s for iCE40 DSP inference.\n", log_id(pm.module), log_id(st.mul));
@@ -98,13 +98,35 @@ void create_ice40_dsp(ice40_dsp_pm &pm)
        cell->setParam("\\C_REG", st.ffCD ? State::S1 : State::S0);
        cell->setParam("\\D_REG", st.ffCD ? State::S1 : State::S0);
 
-       cell->setPort("\\AHOLD", State::S0);
-       cell->setPort("\\BHOLD", State::S0);
-       cell->setPort("\\CHOLD", State::S0);
-       cell->setPort("\\DHOLD", State::S0);
-
-       cell->setPort("\\IRSTTOP", State::S0);
-       cell->setPort("\\IRSTBOT", State::S0);
+       SigSpec AHOLD, BHOLD, CDHOLD;
+       if (st.ffAcemux)
+               AHOLD = st.ffAcepol ? pm.module->Not(NEW_ID, st.ffAcemux->getPort("\\S")) : st.ffAcemux->getPort("\\S");
+       else
+               AHOLD = State::S0;
+       if (st.ffBcemux)
+               BHOLD = st.ffBcepol ? pm.module->Not(NEW_ID, st.ffBcemux->getPort("\\S")) : st.ffBcemux->getPort("\\S");
+       else
+               BHOLD = State::S0;
+       if (st.ffCDcemux)
+               CDHOLD = st.ffCDcepol ? pm.module->Not(NEW_ID, st.ffCDcemux->getPort("\\S")) : st.ffCDcemux->getPort("\\S");
+       else
+               CDHOLD = State::S0;
+       cell->setPort("\\AHOLD", AHOLD);
+       cell->setPort("\\BHOLD", BHOLD);
+       cell->setPort("\\CHOLD", CDHOLD);
+       cell->setPort("\\DHOLD", CDHOLD);
+
+       SigSpec IRSTTOP, IRSTBOT;
+       if (st.ffArstmux)
+               IRSTTOP = st.ffArstpol ? st.ffArstmux->getPort("\\S") : pm.module->Not(NEW_ID, st.ffArstmux->getPort("\\S"));
+       else
+               IRSTTOP = State::S0;
+       if (st.ffBrstmux)
+               IRSTBOT = st.ffBrstpol ? st.ffBrstmux->getPort("\\S") : pm.module->Not(NEW_ID, st.ffBrstmux->getPort("\\S"));
+       else
+               IRSTBOT = State::S0;
+       cell->setPort("\\IRSTTOP", IRSTTOP);
+       cell->setPort("\\IRSTBOT", IRSTBOT);
 
        if (st.clock != SigBit())
        {
@@ -187,11 +209,21 @@ void create_ice40_dsp(ice40_dsp_pm &pm)
                cell->setPort("\\ADDSUBBOT", State::S0);
        }
 
-       cell->setPort("\\ORSTTOP", State::S0);
-       cell->setPort("\\ORSTBOT", State::S0);
+       SigSpec OHOLD;
+       if (st.ffOcemux)
+               OHOLD = st.ffOcemux ? pm.module->Not(NEW_ID, st.ffOcemux->getPort("\\S")) : st.ffOcemux->getPort("\\S");
+       else
+               OHOLD = State::S0;
+       cell->setPort("\\OHOLDTOP", OHOLD);
+       cell->setPort("\\OHOLDBOT", OHOLD);
 
-       cell->setPort("\\OHOLDTOP", State::S0);
-       cell->setPort("\\OHOLDBOT", State::S0);
+       SigSpec ORST;
+       if (st.ffOrstmux)
+               ORST = st.ffOrstmux ? st.ffOrstmux->getPort("\\S") : pm.module->Not(NEW_ID, st.ffOrstmux->getPort("\\S"));
+       else
+               ORST = State::S0;
+       cell->setPort("\\ORSTTOP", ORST);
+       cell->setPort("\\ORSTBOT", ORST);
 
        SigSpec acc_reset = State::S0;
        if (st.mux) {
@@ -200,7 +232,6 @@ void create_ice40_dsp(ice40_dsp_pm &pm)
                else
                        acc_reset = pm.module->Not(NEW_ID, st.mux->getPort("\\S"));
        }
-
        cell->setPort("\\OLOADTOP", acc_reset);
        cell->setPort("\\OLOADBOT", acc_reset);
 
index 532995da70a49820ae36fdfa66c86203e387ef53..01e344767be317ea54479e22989d92c22d217daf 100644 (file)
@@ -9,8 +9,8 @@ state <IdString> addAB muxAB
 state <bool> ffAcepol ffBcepol ffCDcepol ffOcepol
 state <bool> ffArstpol ffBrstpol ffCDrstpol ffOrstpol
 
-state <Cell*> ffA ffAcemux ffArstmux ffB ffBcemux ffBrstmux ffCD ffCDcemux ffCDrstmux
-state <Cell*> ffFJKG ffFJKGrstmux ffH ffHrstmux ffO ffOcemux ffOrstmux
+state <Cell*> ffA ffAcemux ffArstmux ffB ffBcemux ffBrstmux ffCD ffCDcemux
+state <Cell*> ffFJKG ffH ffO ffOcemux ffOrstmux
 
 // subpattern
 state <SigSpec> argQ argD
@@ -105,75 +105,79 @@ code argQ ffB ffBcemux ffBrstmux ffBcepol ffBrstpol sigB clock clock_pol
        }
 endcode
 
-code argD ffFJKG ffFJKGrstmux sigH sigO clock clock_pol
+code argD ffFJKG sigH sigO 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;
                subpattern(out_dffe);
                if (dff) {
-                       ffFJKG = dff;
-                       clock = dffclock;
-                       clock_pol = dffclock_pol;
-                       if (dffrstmux)
-                               ffFJKGrstmux = dffrstmux;
                        // F/J/K/G do not have a CE-like (hold) input
                        if (dffcemux)
-                               reject;
+                               goto reject_ffFJKG;
 
                        // Reset signal of F/J (IRSTTOP) and K/G (IRSTBOT)
                        //   shared with A and B
-                       if ((ffArstmux != NULL) != (ffFJKGrstmux != NULL))
-                               reject;
-                       if ((ffBrstmux != NULL) != (ffFJKGrstmux != NULL))
-                               reject;
+                       if ((ffArstmux != NULL) != (dffrstmux != NULL))
+                               goto reject_ffFJKG;
+                       if ((ffBrstmux != NULL) != (dffrstmux != NULL))
+                               goto reject_ffFJKG;
                        if (ffArstmux) {
-                               if (port(ffArstmux, \S) != port(ffFJKGrstmux, \S))
-                                       reject;
+                               if (port(ffArstmux, \S) != port(dffrstmux, \S))
+                                       goto reject_ffFJKG;
                                if (ffArstpol != dffrstpol)
-                                       reject;
+                                       goto reject_ffFJKG;
                        }
                        if (ffBrstmux) {
-                               if (port(ffBrstmux, \S) != port(ffFJKGrstmux, \S))
-                                       reject;
+                               if (port(ffBrstmux, \S) != port(dffrstmux, \S))
+                                       goto reject_ffFJKG;
                                if (ffBrstpol != dffrstpol)
-                                       reject;
+                                       goto reject_ffFJKG;
                        }
 
+                       ffFJKG = dff;
+                       clock = dffclock;
+                       clock_pol = dffclock_pol;
                        sigH = dffQ;
                }
        }
+
+       if (0) {
+reject_ffFJKG: ;
+       }
 endcode
 
-code argD ffH ffHrstmux sigH sigO clock clock_pol
-       if (nusers(sigH) == 2 &&
+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())) {
                argD = sigH;
                subpattern(out_dffe);
                if (dff) {
-                       ffH = dff;
-                       clock = dffclock;
-                       clock_pol = dffclock_pol;
-                       if (dffrstmux)
-                               ffHrstmux = dffrstmux;
                        // H does not have a CE-like (hold) input
                        if (dffcemux)
-                               reject;
+                               goto reject_ffH;
 
                        // Reset signal of H (IRSTBOT) shared with B
-                       if ((ffBrstmux != NULL) != (ffHrstmux != NULL))
-                               reject;
+                       if ((ffBrstmux != NULL) != (dffrstmux != NULL))
+                               goto reject_ffH;
                        if (ffBrstmux) {
-                               if (port(ffBrstmux, \S) != port(ffHrstmux, \S))
-                                       reject;
+                               if (port(ffBrstmux, \S) != port(dffrstmux, \S))
+                                       goto reject_ffH;
                                if (ffBrstpol != dffrstpol)
-                                       reject;
+                                       goto reject_ffH;
                        }
 
+                       ffH = dff;
+                       clock = dffclock;
+                       clock_pol = dffclock_pol;
                        sigH = dffQ;
                }
        }
 
+       if (0) {
+reject_ffH: ;
+       }
+
        sigO = sigH;
 endcode
 
@@ -274,26 +278,46 @@ code argD ffO ffOcemux ffOrstmux ffOcepol ffOrstpol sigO sigCD clock clock_pol c
        }
 endcode
 
-code argQ ffCD ffCDcemux ffCDrstmux ffCDcepol ffCDrstpol sigCD clock clock_pol
+code argQ ffCD ffCDcemux ffCDcepol ffCDrstpol sigCD clock clock_pol
        if (!sigCD.empty() &&
                        (mul->type != \SB_MAC16 || (!param(mul, \C_REG).as_bool() && !param(mul, \D_REG).as_bool()))) {
                argQ = sigCD;
                subpattern(in_dffe);
                if (dff) {
-                       ffCD = dff;
-                       clock = dffclock;
-                       clock_pol = dffclock_pol;
-                       if (dffrstmux) {
-                               ffCDrstmux = dffrstmux;
-                               ffCDrstpol = dffrstpol;
-                       }
                        if (dffcemux) {
                                ffCDcemux = dffcemux;
                                ffCDcepol = dffcepol;
                        }
+
+                       // 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)
+                                       goto reject_ffCD;
+                       }
+                       if (ffBrstmux) {
+                               if (port(ffBrstmux, \S) != port(dffrstmux, \S))
+                                       goto reject_ffCD;
+                               if (ffBrstpol != dffrstpol)
+                                       goto reject_ffCD;
+                       }
+
+                       ffCD = dff;
+                       clock = dffclock;
+                       clock_pol = dffclock_pol;
                        sigCD = dffD;
                }
        }
+
+       if (0) {
+reject_ffCD: ;
+       }
 endcode
 
 code sigCD
@@ -418,6 +442,9 @@ arg argD argQ clock clock_pol
 
 code
        dff = nullptr;
+       for (auto c : argD.chunks())
+               if (c.wire->get_bool_attribute(\keep))
+                       reject;
 endcode
 
 match ffcemux
@@ -434,7 +461,7 @@ match ffcemux
        index <SigBit> port(ffcemux, BA)[offset] === argD[0]
 
        // Check that the rest of argD is present
-       filter GetSize(BA) >= offset + GetSize(argD)
+       filter GetSize(port(ffcemux, BA)) >= offset + GetSize(argD)
        filter port(ffcemux, BA).extract(offset, GetSize(argD)) == argD
 
        set ffoffset offset
@@ -448,12 +475,6 @@ code argD argQ
        dffcemux = ffcemux;
        if (ffcemux) {
                SigSpec BA = port(ffcemux, ffcepol ? \B : \A);
-               if (ffoffset + GetSize(argD) > GetSize(BA))
-                       reject;
-               for (int i = 1; i < GetSize(argD); i++)
-                       if (BA[ffoffset+i] != argD[i])
-                               reject;
-
                SigSpec Y = port(ffcemux, \Y);
                argQ = argD;
                argD.replace(BA, Y);
@@ -480,7 +501,7 @@ match ffrstmux
        // Check that offset is consistent
        filter !ffcemux || ffoffset == offset
        // Check that the rest of argD is present
-       filter GetSize(AB) >= offset + GetSize(argD)
+       filter GetSize(port(ffrstmux, AB)) >= offset + GetSize(argD)
        filter port(ffrstmux, AB).extract(offset, GetSize(argD)) == argD
 
        set ffoffset offset
@@ -519,8 +540,6 @@ match ff
        filter !ffcemux || port(ff, \Q).extract(offset, GetSize(argQ)) == argQ
 
        set ffoffset offset
-
-       semioptional
 endmatch
 
 code argQ
@@ -531,7 +550,6 @@ code argQ
                        if (param(ff, \CLK_POLARITY).as_bool() != clock_pol)
                                reject;
                }
-
                SigSpec D = port(ff, \D);
                SigSpec Q = port(ff, \Q);
                if (!ffcemux) {
@@ -540,8 +558,6 @@ code argQ
                }
 
                for (auto c : argQ.chunks()) {
-                       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;