Improve pattern matcher to match subsets of $dffe? cells
authorEddie Hung <eddie@fpgeh.com>
Thu, 18 Jul 2019 21:08:18 +0000 (14:08 -0700)
committerEddie Hung <eddie@fpgeh.com>
Thu, 18 Jul 2019 21:08:18 +0000 (14:08 -0700)
passes/pmgen/xilinx_dsp.cc
passes/pmgen/xilinx_dsp.pmg

index b583988c4e50e833954da1130b2a2d242d3a82cf..897bc1aaabe44d1ed8a606ac4cff74ef87754651 100644 (file)
@@ -39,7 +39,8 @@ 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_WIDTH:  %d\n", st.P_WIDTH);
+       log("P_used: %s\n", log_signal(st.P_used));
+       log_module(pm.module);
 #endif
 
        log("Analysing %s.%s for Xilinx DSP register packing.\n", log_id(pm.module), log_id(st.dsp));
@@ -79,8 +80,13 @@ void pack_xilinx_dsp(xilinx_dsp_pm &pm)
                }
                if (st.ffP) {
                        SigSpec P = cell->getPort("\\P");
+                       SigSpec D;
+                       if (st.muxP)
+                               D = st.muxP->getPort("\\B");
+                       else
+                               D = st.ffP->getPort("\\D");
                        SigSpec Q = st.ffP->getPort("\\Q");
-                       P.replace(Q, P.extract(0, GetSize(Q)));
+                       P.replace(D, Q);
                        cell->setPort("\\P", Q);
                        cell->setParam("\\PREG", State::S1);
                        if (st.ffP->type == "$dff")
index fe907b2985c82b2a1f3114dec1439fd9c6376abe..c2bec4c5462c3592f16bb70daa79781cd89c5f2a 100644 (file)
@@ -1,7 +1,7 @@
 pattern xilinx_dsp
 
 state <SigBit> clock
-state <int> P_WIDTH
+state <SigSpec> P_used
 
 match dsp
        select dsp->type.in(\DSP48E1)
@@ -39,22 +39,25 @@ code clock
        }
 endcode
 
-code P_WIDTH
+// Extract the bits of P that actually have a consumer
+// (as opposed to being a sign extension)
+code P_used
        SigSpec P = port(dsp, \P);
        int i;
        for (i = GetSize(P); i > 0; i--)
                if (nusers(P[i-1]) > 1)
                        break;
-       P_WIDTH = i;
+       P_used = P.extract(0, i).remove_const();
 endcode
 
 match ffP
+       if !P_used.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() == P_WIDTH
-       filter port(ffP, \D) == port(dsp, \P).extract(0, P_WIDTH)
+       filter param(ffP, \WIDTH).as_int() >= GetSize(P_used)
+       filter includes(port(ffP, \D).to_sigbit_set(), P_used.to_sigbit_set())
        optional
 endmatch
 
@@ -63,12 +66,12 @@ endmatch
 //   since that would lose information helpful for
 //   efficient wide-mux inference
 match muxP
-       if !ffP
+       if !P_used.empty() && !ffP
        select muxP->type.in($mux)
-       select port(muxP, \A).is_fully_undef()
-       filter param(muxP, \WIDTH).as_int() == P_WIDTH
-       filter port(muxP, \B) == port(dsp, \P).extract(0, P_WIDTH)
        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())
        optional
 endmatch
 
@@ -78,7 +81,8 @@ match ffY
        select nusers(port(ffY, \D)) == 2
        // DSP48E1 does not support clock inversion
        select param(ffY, \CLK_POLARITY).as_bool()
-       index <SigSpec> port(ffY, \D) === port(muxP, \Y)
+       filter param(ffY, \WIDTH).as_int() >= GetSize(P_used)
+       filter includes(port(ffY, \D).to_sigbit_set(), port(muxP, \Y).to_sigbit_set())
 endmatch
 
 code ffP clock