Add support for A1 and B1 registers
authorEddie Hung <eddie@fpgeh.com>
Thu, 12 Sep 2019 00:16:46 +0000 (17:16 -0700)
committerEddie Hung <eddie@fpgeh.com>
Thu, 12 Sep 2019 00:16:46 +0000 (17:16 -0700)
passes/pmgen/xilinx_dsp.cc
passes/pmgen/xilinx_dsp.pmg

index 52ffa54653a33dc67b52472a1b4e43a0f7cdcfea..ae8cd64da50e3e9d2c993c3db81def3a464455c1 100644 (file)
@@ -259,7 +259,9 @@ void pack_xilinx_dsp(dict<SigBit, Cell*> &bit_to_driver, xilinx_dsp_pm &pm)
        log("preAdd:     %s\n", log_id(st.preAdd, "--"));
        log("ffAD:       %s %s %s\n", log_id(st.ffAD, "--"), log_id(st.ffADcemux, "--"), log_id(st.ffADrstmux, "--"));
        log("ffA2:       %s %s %s\n", log_id(st.ffA2, "--"), log_id(st.ffA2cemux, "--"), log_id(st.ffA2rstmux, "--"));
+       log("ffA1:       %s %s %s\n", log_id(st.ffA1, "--"), log_id(st.ffA1cemux, "--"), log_id(st.ffA1rstmux, "--"));
        log("ffB2:       %s %s %s\n", log_id(st.ffB2, "--"), log_id(st.ffB2cemux, "--"), log_id(st.ffB2rstmux, "--"));
+       log("ffB1:       %s %s %s\n", log_id(st.ffB1, "--"), log_id(st.ffB1cemux, "--"), log_id(st.ffB1rstmux, "--"));
        log("ffC:        %s %s %s\n", log_id(st.ffC, "--"), log_id(st.ffCcemux, "--"), log_id(st.ffCrstmux, "--"));
        log("ffD:        %s %s %s\n", log_id(st.ffD, "--"), log_id(st.ffDcemux, "--"), log_id(st.ffDrstmux, "--"));
        log("dsp:        %s\n", log_id(st.dsp, "--"));
@@ -338,12 +340,14 @@ void pack_xilinx_dsp(dict<SigBit, Cell*> &bit_to_driver, xilinx_dsp_pm &pm)
                        if (rstmux) {
                                SigSpec Y = rstmux->getPort("\\Y");
                                SigSpec AB = rstmux->getPort(rstpol ? "\\A" : "\\B");
-                               SigSpec S = rstmux->getPort("\\S");
                                if (!A.empty())
                                        A.replace(Y, AB);
-                               cell->setPort(rstport, rstpol ? S : pm.module->Not(NEW_ID, S));
+                               if (rstport != IdString()) {
+                                       SigSpec S = rstmux->getPort("\\S");
+                                       cell->setPort(rstport, rstpol ? S : pm.module->Not(NEW_ID, S));
+                               }
                        }
-                       else
+                       else if (rstport != IdString())
                                cell->setPort(rstport, State::S0);
                        if (cemux) {
                                SigSpec Y = cemux->getPort("\\Y");
@@ -368,16 +372,26 @@ void pack_xilinx_dsp(dict<SigBit, Cell*> &bit_to_driver, xilinx_dsp_pm &pm)
                };
 
                if (st.ffA2) {
-                       SigSpec &A2 = cell->connections_.at("\\A");
-                       f(A2, st.ffA2, st.ffA2cemux, st.ffA2cepol, "\\CEA2", st.ffA2rstmux, st.ffArstpol, "\\RSTA");
-                       pm.add_siguser(A2, cell);
-                       cell->setParam("\\AREG", 1);
+                       SigSpec &A = cell->connections_.at("\\A");
+                       f(A, st.ffA2, st.ffA2cemux, st.ffA2cepol, "\\CEA2", st.ffA2rstmux, st.ffArstpol, "\\RSTA");
+                       pm.add_siguser(A, cell);
+                       if (st.ffA1) {
+                               f(A, st.ffA1, st.ffA1cemux, st.ffA1cepol, "\\CEA1", st.ffA1rstmux, st.ffArstpol, IdString());
+                               cell->setParam("\\AREG", 2);
+                       }
+                       else
+                               cell->setParam("\\AREG", 1);
                }
                if (st.ffB2) {
-                       SigSpec &B2 = cell->connections_.at("\\B");
-                       f(B2, st.ffB2, st.ffB2cemux, st.ffB2cepol, "\\CEB2", st.ffB2rstmux, st.ffBrstpol, "\\RSTB");
-                       pm.add_siguser(B2, cell);
-                       cell->setParam("\\BREG", 1);
+                       SigSpec &B = cell->connections_.at("\\B");
+                       f(B, st.ffB2, st.ffB2cemux, st.ffB2cepol, "\\CEB2", st.ffB2rstmux, st.ffBrstpol, "\\RSTB");
+                       pm.add_siguser(B, cell);
+                       if (st.ffB1) {
+                               f(B, st.ffB1, st.ffB1cemux, st.ffB1cepol, "\\CEB1", st.ffB1rstmux, st.ffBrstpol, IdString());
+                               cell->setParam("\\BREG", 2);
+                       }
+                       else
+                               cell->setParam("\\BREG", 1);
                }
                if (st.ffC) {
                        SigSpec &C = cell->connections_.at("\\C");
@@ -406,14 +420,20 @@ void pack_xilinx_dsp(dict<SigBit, Cell*> &bit_to_driver, xilinx_dsp_pm &pm)
 
                log("  clock: %s (%s)", log_signal(st.clock), "posedge");
 
-               if (st.ffA2)
+               if (st.ffA2) {
                        log(" ffA2:%s", log_id(st.ffA2));
+                       if (st.ffA1)
+                               log(" ffA1:%s", log_id(st.ffA1));
+               }
 
                if (st.ffAD)
                        log(" ffAD:%s", log_id(st.ffAD));
 
-               if (st.ffB2)
+               if (st.ffB2) {
                        log(" ffB2:%s", log_id(st.ffB2));
+                       if (st.ffB1)
+                               log(" ffB1:%s", log_id(st.ffB1));
+               }
 
                if (st.ffC)
                        log(" ffC:%s", log_id(st.ffC));
@@ -449,17 +469,18 @@ struct XilinxDspPass : public Pass {
                log("\n");
                log("    xilinx_dsp [options] [selection]\n");
                log("\n");
-               log("Pack input registers (A, B, C, D, AD; with optional enable/reset), pipeline\n");
-               log("registers (M; with optional enable/reset), output registers (P; with optional\n");
-               log("enable/reset), pre-adder and/or post-adder into Xilinx DSP resources.\n");
+               log("Pack input registers (A2, A1, B2, B1, C, D, AD; with optional enable/reset),\n");
+               log("pipeline registers (M; with optional enable/reset), output registers (P; with\n");
+               log("optional enable/reset), pre-adder and/or post-adder into Xilinx DSP resources.\n");
                log("\n");
                log("Multiply-accumulate operations using the post-adder with feedback on the 'C'\n");
                log("input will be folded into the DSP. In this scenario only, the 'C' input can be\n");
                log("used to override the existing accumulation result with a new value.\n");
                log("\n");
-               log("Use of the dedicated 'PCOUT' -> 'PCIN' path is detected for 'P' -> 'C' connections\n");
-               log("where 'P' is right-shifted by 18-bits and used as an input to the post-adder (a\n");
-               log("pattern common for summing partial products to implement wide multiplies).\n");
+               log("Use of the dedicated 'PCOUT' -> 'PCIN' cascade path is detected for 'P' -> 'C'\n");
+               log("connections (optionally, where 'P' is right-shifted by 18-bits and used as an\n");
+               log("input to the post-adder -- a pattern common for summing partial products to\n");
+               log("implement wide multipliers).\n");
                log("\n");
                log("\n");
                log("Experimental feature: addition/subtractions less than 12 or 24 bits with the\n");
index 8c7477efad88f4e3ff988f660e9b73ff2c7058e0..fa845b5936b4fc0f0eff550e0d5510f7449272ad 100644 (file)
@@ -104,9 +104,9 @@ code sigA sigD
        }
 endcode
 
-code argQ ffAD ffADcemux ffADrstmux ffADcepol ffADrstpol sigA clock ffA2 ffA2cemux ffA2rstmux ffA2cepol ffArstpol
+code argQ ffAD ffADcemux ffADrstmux ffADcepol ffADrstpol sigA clock ffA2 ffA2cemux ffA2rstmux ffA2cepol ffArstpol ffA1 ffA1cemux ffA1rstmux ffA1cepol
        // Only search for ffA2 if there was a pre-adder
-       //   (otherwise ffA2 would have been matched as ffA2)
+       //   (otherwise ffA2 would have been matched as ffAD)
        if (preAdd) {
                if (param(dsp, \AREG).as_int() == 0) {
                        argQ = sigA;
@@ -114,11 +114,13 @@ code argQ ffAD ffADcemux ffADrstmux ffADcepol ffADrstpol sigA clock ffA2 ffA2cem
                        if (dff) {
                                ffA2 = dff;
                                clock = dffclock;
+                               if (dffrstmux) {
+                                       ffA2cepol = dffcepol;
+                                       ffArstpol = dffrstpol;
+                               }
                                if (dffcemux) {
                                        ffA2cemux = dffcemux;
                                        ffA2rstmux = dffrstmux;
-                                       ffA2cepol = dffcepol;
-                                       ffArstpol = dffrstpol;
                                }
                                sigA = dffD;
                        }
@@ -134,9 +136,37 @@ code argQ ffAD ffADcemux ffADrstmux ffADcepol ffADrstpol sigA clock ffA2 ffA2cem
                ffA2cepol = ffADcepol;
                ffArstpol = ffADrstpol;
        }
+
+       // Now attempt to match A1
+       if (ffA2) {
+               argQ = sigA;
+               subpattern(in_dffe);
+               if (dff) {
+                       if ((ffA2rstmux != nullptr) ^ (dffrstmux != nullptr))
+                               goto ffA1_end;
+                       if (dffrstmux) {
+                               if (ffArstpol != dffrstpol)
+                                       goto ffA1_end;
+                               if (port(ffA2rstmux, \S) != port(dffrstmux, \S))
+                                       goto ffA1_end;
+                               ffA1rstmux = dffrstmux;
+                       }
+
+                       ffA1 = dff;
+                       clock = dffclock;
+
+                       if (dffcemux) {
+                               ffA1cemux = dffcemux;
+                               ffA1cepol = dffcepol;
+                       }
+                       sigA = dffD;
+
+ffA1_end:              ;
+               }
+       }
 endcode
 
-code argQ ffB2 ffB2cemux ffB2rstmux ffB2cepol ffBrstpol sigB clock
+code argQ ffB2 ffB2cemux ffB2rstmux ffB2cepol ffBrstpol sigB clock ffB1 ffB1cemux ffB1rstmux ffB1cepol
        if (param(dsp, \BREG).as_int() == 0) {
                argQ = sigB;
                subpattern(in_dffe);
@@ -150,6 +180,35 @@ code argQ ffB2 ffB2cemux ffB2rstmux ffB2cepol ffBrstpol sigB clock
                                ffBrstpol = dffrstpol;
                        }
                        sigB = dffD;
+
+                       // Now attempt to match B1
+                       if (ffB2) {
+                               argQ = sigB;
+                               subpattern(in_dffe);
+                               if (dff) {
+                                       if ((ffB2rstmux != nullptr) ^ (dffrstmux != nullptr))
+                                               goto ffB1_end;
+                                       if (dffrstmux) {
+                                               if (ffBrstpol != dffrstpol)
+                                                       goto ffB1_end;
+                                               if (port(ffB2rstmux, \S) != port(dffrstmux, \S))
+                                                       goto ffB1_end;
+                                               ffB1rstmux = dffrstmux;
+                                       }
+
+                                       ffB1 = dff;
+                                       clock = dffclock;
+
+                                       if (dffcemux) {
+                                               ffB1cemux = dffcemux;
+                                               ffB1cepol = dffcepol;
+                                       }
+                                       sigB = dffD;
+
+ffB1_end:                              ;
+                               }
+                       }
+
                }
        }
 endcode
@@ -387,6 +446,7 @@ code argD
        if (ffcemux) {
                dffcemux = ffcemux;
                dffcepol = ffcepol;
+               argD = port(ffcemux, ffcepol ? \B : \A);
                dffD.replace(port(ffcemux, \Y), argD);
        }
        else