Fine tune ice40_dsp.pmg, add support for packing subsets of registers
authorEddie Hung <eddie@fpgeh.com>
Fri, 19 Jul 2019 17:57:32 +0000 (10:57 -0700)
committerEddie Hung <eddie@fpgeh.com>
Fri, 19 Jul 2019 17:57:32 +0000 (10:57 -0700)
passes/pmgen/ice40_dsp.cc
passes/pmgen/ice40_dsp.pmg
passes/pmgen/xilinx_dsp.cc
passes/pmgen/xilinx_dsp.pmg

index 963a7d7a1b33e9fc96eb3df7b1d2ca01a8658031..f6a701540a7a0b6a8399886ec1be4b2847ccfd43 100644 (file)
 USING_YOSYS_NAMESPACE
 PRIVATE_NAMESPACE_BEGIN
 
+template<class T> bool includes(const T &lhs, const T &rhs) {
+       return std::includes(lhs.begin(), lhs.end(), rhs.begin(), rhs.end());
+}
 #include "passes/pmgen/ice40_dsp_pm.h"
 
 void create_ice40_dsp(ice40_dsp_pm &pm)
 {
        auto &st = pm.st_ice40_dsp;
 
-#if 0
+#if 1
        log("\n");
        log("ffA:   %s\n", log_id(st.ffA, "--"));
        log("ffB:   %s\n", log_id(st.ffB, "--"));
@@ -100,7 +103,7 @@ void create_ice40_dsp(ice40_dsp_pm &pm)
        cell->setPort("\\IRSTTOP", State::S0);
        cell->setPort("\\IRSTBOT", State::S0);
 
-       if (st.clock_vld)
+       if (st.clock != SigBit())
        {
                cell->setPort("\\CLK", st.clock);
                cell->setPort("\\CE", State::S1);
index f2b7f2169874723f51394a9a24a8e101a46166b6..471b8b51978825a92e01d27001c43a8689e0f302 100644 (file)
@@ -1,8 +1,9 @@
 pattern ice40_dsp
 
 state <SigBit> clock
-state <bool> clock_pol clock_vld
+state <bool> clock_pol
 state <SigSpec> sigA sigB sigY sigS
+state <SigSpec> sigYused
 state <Cell*> addAB muxAB
 
 match mul
@@ -13,68 +14,77 @@ endmatch
 
 match ffA
        select ffA->type.in($dff)
-       // select nusers(port(ffA, \Q)) == 2
-       index <SigSpec> port(ffA, \Q) === port(mul, \A)
+       filter !port(mul, \A).remove_const().empty()
+       filter includes(port(ffA, \Q).to_sigbit_set(), port(mul, \A).remove_const().to_sigbit_set())
        optional
 endmatch
 
-code sigA clock clock_pol clock_vld
+code sigA clock clock_pol
        sigA = port(mul, \A);
 
        if (ffA) {
-               sigA = port(ffA, \D);
+               sigA.replace(port(ffA, \Q), port(ffA, \D));
 
                clock = port(ffA, \CLK).as_bit();
                clock_pol = param(ffA, \CLK_POLARITY).as_bool();
-               clock_vld = true;
        }
 endcode
 
 match ffB
        select ffB->type.in($dff)
-       // select nusers(port(ffB, \Q)) == 2
-       index <SigSpec> port(ffB, \Q) === port(mul, \B)
+       filter !port(mul, \B).remove_const().empty()
+       filter includes(port(ffB, \Q).to_sigbit_set(), port(mul, \B).remove_const().to_sigbit_set())
        optional
 endmatch
 
-code sigB clock clock_pol clock_vld
+code sigB clock clock_pol
        sigB = port(mul, \B);
 
        if (ffB) {
-               sigB = port(ffB, \D);
+               sigB.replace(port(ffB, \Q), port(ffB, \D));
+               
                SigBit c = port(ffB, \CLK).as_bit();
                bool cp = param(ffB, \CLK_POLARITY).as_bool();
 
-               if (clock_vld && (c != clock || cp != clock_pol))
+               if (clock != SigBit() && (c != clock || cp != clock_pol))
                        reject;
 
                clock = c;
                clock_pol = cp;
-               clock_vld = true;
        }
 endcode
 
+// Extract the bits of Y that actually have a consumer
+// (as opposed to being a sign extension)
+code sigY sigYused
+       sigY = port(mul, \Y);
+       int i;
+       for (i = GetSize(sigY); i > 0; i--)
+               if (nusers(sigY[i-1]) > 1)
+                       break;
+       sigYused = sigY.extract(0, i).remove_const();
+endcode
+
 match ffY
        select ffY->type.in($dff)
        select nusers(port(ffY, \D)) == 2
-       index <SigSpec> port(ffY, \D) === port(mul, \Y)
+       filter param(ffY, \WIDTH).as_int() >= GetSize(sigYused)
+       filter includes(port(ffY, \D).to_sigbit_set(), sigYused.to_sigbit_set())
        optional
 endmatch
 
-code sigY clock clock_pol clock_vld
-       sigY = port(mul, \Y);
-
+code clock clock_pol sigY
        if (ffY) {
-               sigY = port(ffY, \Q);
+               sigY.replace(port(ffY, \D), port(ffY, \Q));
+
                SigBit c = port(ffY, \CLK).as_bit();
                bool cp = param(ffY, \CLK_POLARITY).as_bool();
 
-               if (clock_vld && (c != clock || cp != clock_pol))
+               if (clock != SigBit() && (c != clock || cp != clock_pol))
                        reject;
 
                clock = c;
                clock_pol = cp;
-               clock_vld = true;
        }
 endcode
 
@@ -147,16 +157,15 @@ match ffS
        index <SigSpec> port(ffS, \Q) === sigS
 endmatch
 
-code clock clock_pol clock_vld
+code clock clock_pol
        if (ffS) {
                SigBit c = port(ffS, \CLK).as_bit();
                bool cp = param(ffS, \CLK_POLARITY).as_bool();
 
-               if (clock_vld && (c != clock || cp != clock_pol))
+               if (clock != SigBit() && (c != clock || cp != clock_pol))
                        reject;
 
                clock = c;
                clock_pol = cp;
-               clock_vld = true;
        }
 endcode
index c71ac5ef81a5711d31c423c60916131297d17c0f..d87d6367055775c7d3d1b0ad38bfbb132dff03b4 100644 (file)
@@ -39,7 +39,7 @@ void pack_xilinx_dsp(xilinx_dsp_pm &pm)
        log("dsp:   %s\n", log_id(st.dsp, "--"));
        log("ffP:   %s\n", log_id(st.ffP, "--"));
        log("muxP:  %s\n", log_id(st.muxP, "--"));
-       log("P_used: %s\n", log_signal(st.P_used));
+       log("sigPused: %s\n", log_signal(st.sigPused));
        log_module(pm.module);
 #endif
 
index 7a175123ea3486a99ed86f6530757523e59b479d..a97ab4dd570c8428fa92842f2fe33c5394a2ebd1 100644 (file)
@@ -1,7 +1,7 @@
 pattern xilinx_dsp
 
 state <SigBit> clock
-state <SigSpec> P_used
+state <SigSpec> sigPused
 
 match dsp
        select dsp->type.in(\DSP48E1)
@@ -43,23 +43,23 @@ endcode
 
 // Extract the bits of P that actually have a consumer
 // (as opposed to being a sign extension)
-code P_used
+code sigPused
        SigSpec P = port(dsp, \P);
        int i;
        for (i = GetSize(P); i > 0; i--)
                if (nusers(P[i-1]) > 1)
                        break;
-       P_used = P.extract(0, i).remove_const();
+       sigPused = P.extract(0, i).remove_const();
 endcode
 
 match ffP
-       if !P_used.empty()
+       if !sigPused.empty()
        select ffP->type.in($dff, $dffe)
        select nusers(port(ffP, \D)) == 2
        // DSP48E1 does not support clock inversion
        select param(ffP, \CLK_POLARITY).as_bool()
-       filter param(ffP, \WIDTH).as_int() >= GetSize(P_used)
-       filter includes(port(ffP, \D).to_sigbit_set(), P_used.to_sigbit_set())
+       filter param(ffP, \WIDTH).as_int() >= GetSize(sigPused)
+       filter includes(port(ffP, \D).to_sigbit_set(), sigPused.to_sigbit_set())
        optional
 endmatch
 
@@ -68,12 +68,12 @@ endmatch
 //   since that would lose information helpful for
 //   efficient wide-mux inference
 match muxP
-       if !P_used.empty() && !ffP
+       if !sigPused.empty() && !ffP
        select muxP->type.in($mux)
        select nusers(port(muxP, \B)) == 2
        select port(muxP, \A).is_fully_undef()
-       filter param(muxP, \WIDTH).as_int() >= GetSize(P_used)
-       filter includes(port(muxP, \B).to_sigbit_set(), P_used.to_sigbit_set())
+       filter param(muxP, \WIDTH).as_int() >= GetSize(sigPused)
+       filter includes(port(muxP, \B).to_sigbit_set(), sigPused.to_sigbit_set())
        optional
 endmatch
 
@@ -83,7 +83,7 @@ match ffY
        select nusers(port(ffY, \D)) == 2
        // DSP48E1 does not support clock inversion
        select param(ffY, \CLK_POLARITY).as_bool()
-       filter param(ffY, \WIDTH).as_int() >= GetSize(P_used)
+       filter param(ffY, \WIDTH).as_int() >= GetSize(sigPused)
        filter includes(port(ffY, \D).to_sigbit_set(), port(muxP, \Y).to_sigbit_set())
 endmatch