Support CEA
authorEddie Hung <eddie@fpgeh.com>
Thu, 5 Sep 2019 17:07:26 +0000 (10:07 -0700)
committerEddie Hung <eddie@fpgeh.com>
Thu, 5 Sep 2019 17:07:26 +0000 (10:07 -0700)
passes/pmgen/xilinx_dsp.cc
passes/pmgen/xilinx_dsp.pmg

index c742ef84d5aebebcf313592e1f8e3af7a7f359dc..2f36a5bdecbfd76349df57e49f8d2a1f4c2ba281 100644 (file)
@@ -32,6 +32,7 @@ void pack_xilinx_dsp(dict<SigBit, Cell*> &bit_to_driver, xilinx_dsp_pm &pm)
 #if 1
        log("\n");
        log("ffA:        %s\n", log_id(st.ffA, "--"));
+       log("ffAmux:     %s\n", log_id(st.ffAmux, "--"));
        log("ffB:        %s\n", log_id(st.ffB, "--"));
        log("dsp:        %s\n", log_id(st.dsp, "--"));
        log("ffM:        %s\n", log_id(st.ffM, "--"));
@@ -78,15 +79,19 @@ void pack_xilinx_dsp(dict<SigBit, Cell*> &bit_to_driver, xilinx_dsp_pm &pm)
                if (st.ffA) {
                        SigSpec A = cell->getPort("\\A");
                        SigSpec D = st.ffA->getPort("\\D");
-                       SigSpec Q = st.ffA->getPort("\\Q");
+                       SigSpec Q = pm.sigmap(st.ffA->getPort("\\Q"));
                        A.replace(Q, D);
-                       cell->setPort("\\A", A);
+
                        cell->setParam("\\AREG", 1);
-                       if (st.ffA->type == "$dff")
+                       if (st.ffAmux) {
+                               SigSpec Y = st.ffAmux->getPort("\\Y");
+                               SigSpec AB = st.ffAmux->getPort(st.ffAmuxAB == "\\A" ? "\\B" : "\\A");
+                               A.replace(Y, AB);
+                               cell->setPort("\\CEA2", st.ffAmux->getPort("\\S"));
+                       }
+                       else
                                cell->setPort("\\CEA2", State::S1);
-                       //else if (st.ffA->type == "$dffe")
-                       //      cell->setPort("\\CEA2", st.ffA->getPort("\\EN"));
-                       else log_abort();
+                       cell->setPort("\\A", A);
                }
                if (st.ffB) {
                        SigSpec B = cell->getPort("\\B");
index d37792b29455b206d6927b47640c02c1d7044f3d..339ac646c5b1da8699f3cf29bc722b475e79328a 100644 (file)
@@ -1,8 +1,8 @@
 pattern xilinx_dsp
 
 state <SigBit> clock
-state <SigSpec> sigA sigB sigC sigM sigP sigPused
-state <IdString> ffMmuxAB postAddAB postAddMuxAB
+state <SigSpec> sigA sigffAmux sigB sigC sigM sigP sigPused
+state <IdString> ffAmuxAB ffMmuxAB postAddAB postAddMuxAB
 
 match dsp
        select dsp->type.in(\DSP48E1)
@@ -14,11 +14,17 @@ code sigA sigB
        for (i = GetSize(sigA)-1; i > 0; i--)
                if (sigA[i] != sigA[i-1])
                        break;
+       // Do not remove non-const sign bit
+       if (sigA[i].wire)
+               ++i;
        sigA.remove(i, GetSize(sigA)-i);
        sigB = port(dsp, \B);
        for (i = GetSize(sigB)-1; i > 0; i--)
                if (sigB[i] != sigB[i-1])
                        break;
+       // Do not remove non-const sign bit
+       if (sigB[i].wire)
+               ++i;
        sigB.remove(i, GetSize(sigB)-i);
 endcode
 
@@ -43,20 +49,34 @@ match ffA
        select param(ffA, \CLK_POLARITY).as_bool()
        filter GetSize(port(ffA, \Q)) >= GetSize(sigA)
        slice offset GetSize(port(ffA, \Q))
+       filter offset+GetSize(sigA) <= GetSize(port(ffA, \Q)) && nusers(port(ffA, \Q).extract(offset, GetSize(sigA))) <= 3
        filter offset+GetSize(sigA) <= GetSize(port(ffA, \Q)) && port(ffA, \Q).extract(offset, GetSize(sigA)) == sigA
        optional
 endmatch
 
-code clock
+code sigA sigffAmux clock
        if (ffA) {
                for (auto b : port(ffA, \Q))
                        if (b.wire->get_bool_attribute(\keep))
                                reject;
 
                clock = port(ffA, \CLK).as_bit();
+
+               if (nusers(sigA) == 3)
+                       sigffAmux = sigA;
+               sigA.replace(port(ffA, \Q), port(ffA, \D));
        }
 endcode
 
+match ffAmux
+       if sigffAmux != SigSpec()
+       select ffAmux->type.in($mux)
+       choice <IdString> AB {\A, \B}
+       index <SigSpec> port(ffAmux, \Y) === sigA
+       index <SigSpec> port(ffAmux, AB) === sigffAmux
+       set ffAmuxAB AB
+endmatch
+
 match ffB
        if param(dsp, \BREG).as_int() == 0
        select ffB->type.in($dff)