Add support for load value into DSP48E1.P
authorEddie Hung <eddie@fpgeh.com>
Tue, 3 Sep 2019 22:53:10 +0000 (15:53 -0700)
committerEddie Hung <eddie@fpgeh.com>
Tue, 3 Sep 2019 22:53:10 +0000 (15:53 -0700)
passes/pmgen/xilinx_dsp.cc
passes/pmgen/xilinx_dsp.pmg

index 1732a2d6ac74dadba04d67797873980ed9e730c6..b3d302071ef367250e34dbf2f6a93b4c96f4d979 100644 (file)
@@ -40,6 +40,7 @@ void pack_xilinx_dsp(dict<SigBit, Cell*> &bit_to_driver, xilinx_dsp_pm &pm)
        log("dsp:     %s\n", log_id(st.dsp, "--"));
        log("ffM:     %s\n", log_id(st.ffM, "--"));
        log("addAB:   %s\n", log_id(st.addAB, "--"));
+       log("muxAB:   %s\n", log_id(st.muxAB, "--"));
        log("ffP:     %s\n", log_id(st.ffP, "--"));
        //log("muxP:  %s\n", log_id(st.muxP, "--"));
        log("sigPused: %s\n", log_signal(st.sigPused));
@@ -58,7 +59,11 @@ void pack_xilinx_dsp(dict<SigBit, Cell*> &bit_to_driver, xilinx_dsp_pm &pm)
                log("  adder %s (%s)\n", log_id(st.addAB), log_id(st.addAB->type));
 
                SigSpec &opmode = cell->connections_.at("\\OPMODE");
-               if (st.ffP && C == P) {
+               if (st.ffP && st.muxAB) {
+                       opmode[4] = st.muxAB->getPort("\\S");
+                       pm.autoremove(st.muxAB);
+               }
+               else if (st.ffP && C == P) {
                        C = SigSpec();
                        opmode[4] = State::S0;
                }
index 132b09b2b20fc2dc3f3fbc90ba383a24fcdb5dce..fdc3fa5e77ddf055016ca9a0075918c20bb69d48 100644 (file)
@@ -3,7 +3,7 @@ pattern xilinx_dsp
 state <SigBit> clock
 state <std::set<SigBit>> sigAset sigBset
 state <SigSpec> sigC sigM sigMused sigP sigPused
-state <Cell*> addAB
+state <Cell*> addAB muxAB
 
 match dsp
        select dsp->type.in(\DSP48E1)
@@ -172,34 +172,7 @@ match ffP
        optional
 endmatch
 
-//// $mux cell left behind by dff2dffe
-////   would prefer not to run 'opt_expr -mux_undef'
-////   since that would lose information helpful for
-////   efficient wide-mux inference
-//match muxP
-//     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(sigPused)
-//     filter includes(port(muxP, \B).to_sigbit_set(), sigPused.to_sigbit_set())
-//     optional
-//endmatch
-//
-//match ffY
-//     if muxP
-//     select ffY->type.in($dff, $dffe)
-//     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(sigPused)
-//     filter includes(port(ffY, \D).to_sigbit_set(), port(muxP, \Y).to_sigbit_set())
-//endmatch
-
-code ffP clock
-//     if (ffY)
-//             ffP = ffY;
-
+code ffP sigP clock
        if (ffP) {
                for (auto b : port(ffP, \Q))
                        if (b.wire->get_bool_attribute(\keep))
@@ -211,7 +184,46 @@ code ffP clock
                        reject;
 
                clock = c;
+
+               sigP = port(ffP, \Q);
+       }
+endcode
+
+match muxA
+       if addAB
+       select muxA->type.in($mux)
+       select nusers(port(muxA, \Y)) == 2
+       index <SigSpec> port(muxA, \A) === sigP
+       index <SigSpec> port(muxA, \Y) === sigC
+       optional
+endmatch
+
+match muxB
+       if addAB
+       select muxB->type.in($mux)
+       select nusers(port(muxB, \Y)) == 2
+       index <SigSpec> port(muxB, \B) === sigP
+       index <SigSpec> port(muxB, \Y) === sigC
+       optional
+endmatch
+
+code sigC muxAB
+       if (muxA) {
+               muxAB = muxA;
+               sigC = port(muxAB, \B);
+       }
+       if (muxB) {
+               muxAB = muxB;
+               sigC = port(muxAB, \A);
        }
+       if (muxAB) {
+               // Ensure that adder is not used
+               SigSpec opmodeZ = port(dsp, \OPMODE).extract(4,3);
+               if (!opmodeZ.is_fully_zero())
+                       reject;
+       }
+endcode
 
+code
        accept;
 endcode