diff options
author | Eddie Hung <eddie@fpgeh.com> | 2019-08-09 15:19:33 -0700 |
---|---|---|
committer | Eddie Hung <eddie@fpgeh.com> | 2019-08-09 15:19:33 -0700 |
commit | 0b5b56c1ecab78d126bbab13598c184f5e28cccc (patch) | |
tree | 2f40882c2140253ca83a48a3eca75fda7df51f71 /passes | |
parent | a002eba14a9895c7330a2741a49de02faf1af06f (diff) | |
download | yosys-0b5b56c1ecab78d126bbab13598c184f5e28cccc.tar.gz yosys-0b5b56c1ecab78d126bbab13598c184f5e28cccc.tar.bz2 yosys-0b5b56c1ecab78d126bbab13598c184f5e28cccc.zip |
Pack partial-product adder DSP48E1 packing
Diffstat (limited to 'passes')
-rw-r--r-- | passes/pmgen/xilinx_dsp.cc | 22 | ||||
-rw-r--r-- | passes/pmgen/xilinx_dsp.pmg | 67 |
2 files changed, 79 insertions, 10 deletions
diff --git a/passes/pmgen/xilinx_dsp.cc b/passes/pmgen/xilinx_dsp.cc index 389f0cb56..cd88f9449 100644 --- a/passes/pmgen/xilinx_dsp.cc +++ b/passes/pmgen/xilinx_dsp.cc @@ -37,16 +37,26 @@ void pack_xilinx_dsp(xilinx_dsp_pm &pm) log("ffA: %s\n", log_id(st.ffA, "--")); log("ffB: %s\n", log_id(st.ffB, "--")); log("dsp: %s\n", log_id(st.dsp, "--")); + log("addAB: %s\n", log_id(st.addAB, "--")); log("ffP: %s\n", log_id(st.ffP, "--")); //log("muxP: %s\n", log_id(st.muxP, "--")); log("sigPused: %s\n", log_signal(st.sigPused)); - log_module(pm.module); #endif - log("Analysing %s.%s for Xilinx DSP register packing.\n", log_id(pm.module), log_id(st.dsp)); + log("Analysing %s.%s for Xilinx DSP packing.\n", log_id(pm.module), log_id(st.dsp)); Cell *cell = st.dsp; - log_assert(cell); + SigSpec P = st.sigP; + + if (st.addAB) { + log(" adder %s (%s)\n", log_id(st.addAB), log_id(st.addAB->type)); + cell->setPort("\\C", st.sigC.extend_u0(48, true)); + SigSpec &opmode = cell->connections_.at("\\OPMODE"); + opmode[6] = State::S0; + opmode[5] = State::S1; + opmode[4] = State::S1; + pm.autoremove(st.addAB); + } if (st.clock != SigBit()) { @@ -79,7 +89,6 @@ void pack_xilinx_dsp(xilinx_dsp_pm &pm) else log_abort(); } if (st.ffP) { - SigSpec P = cell->getPort("\\P"); SigSpec D; //if (st.muxP) // D = st.muxP->getPort("\\B"); @@ -87,7 +96,6 @@ void pack_xilinx_dsp(xilinx_dsp_pm &pm) D = st.ffP->getPort("\\D"); SigSpec Q = st.ffP->getPort("\\Q"); P.replace(pm.sigmap(D), Q); - cell->setPort("\\P", P); cell->setParam("\\PREG", State::S1); if (st.ffP->type == "$dff") cell->setPort("\\CEP", State::S1); @@ -112,6 +120,10 @@ void pack_xilinx_dsp(xilinx_dsp_pm &pm) log("\n"); } + if (GetSize(P) < 48) + P.append(pm.module->addWire(NEW_ID, 48-GetSize(P))); + cell->setPort("\\P", P); + pm.blacklist(cell); } diff --git a/passes/pmgen/xilinx_dsp.pmg b/passes/pmgen/xilinx_dsp.pmg index f95de9410..4f5fae8df 100644 --- a/passes/pmgen/xilinx_dsp.pmg +++ b/passes/pmgen/xilinx_dsp.pmg @@ -1,7 +1,8 @@ pattern xilinx_dsp state <SigBit> clock -state <SigSpec> sigPused +state <SigSpec> sigC sigP sigPused +state <Cell*> addAB match dsp select dsp->type.in(\DSP48E1) @@ -43,13 +44,69 @@ code clock } endcode +code sigP + sigP = port(dsp, \P); +endcode + +match addA + select addA->type.in($add) + select param(addA, \A_SIGNED).as_bool() && param(addA, \B_SIGNED).as_bool() + select nusers(port(addA, \A)) == 2 + //index <SigSpec> port(addA, \A) === sigP.extract(0, param(addA, \A_WIDTH).as_int()) + filter GetSize(sigP) >= param(addA, \A_WIDTH).as_int() + filter port(addA, \A) == sigP.extract(0, param(addA, \A_WIDTH).as_int()) + optional +endmatch + +match addB + if !addA + select addB->type.in($add, $sub) + select param(addB, \A_SIGNED).as_bool() && param(addB, \B_SIGNED).as_bool() + select nusers(port(addB, \B)) == 2 + //index <SigSpec> port(addB, \B) === sigP.extract(0, param(addB, \B_WIDTH).as_int()) + filter GetSize(sigP) >= param(addB, \B_WIDTH).as_int() + filter port(addB, \B) == sigP.extract(0, param(addB, \B_WIDTH).as_int()) + optional +endmatch + +code addAB sigC sigP + bool C_SIGNED = false; + if (addA) { + addAB = addA; + sigC = port(addAB, \B); + C_SIGNED = param(addAB, \B_SIGNED).as_bool(); + } + if (addB) { + addAB = addB; + sigC = port(addAB, \A); + C_SIGNED = param(addAB, \B_SIGNED).as_bool(); + } + if (addAB) { + // Ensure that adder is not used + SigSpec opmodeZ = port(dsp, \OPMODE).extract(4,3); + if (!opmodeZ.is_fully_zero()) + reject; + + int natural_mul_width = GetSize(port(dsp, \A)) + GetSize(port(dsp, \B)); + int actual_mul_width = GetSize(sigP); + int actual_acc_width = GetSize(sigC); + + if ((actual_acc_width > actual_mul_width) && (natural_mul_width > actual_mul_width)) + reject; + //if ((actual_acc_width != actual_mul_width) && (param(dsp, \A_SIGNED).as_bool() != param(addAB, \A_SIGNED).as_bool())) + // reject; + + sigP = port(addAB, \Y); + sigC.extend_u0(32, C_SIGNED); + } +endcode + // Extract the bits of P that actually have a consumer // (as opposed to being a dummy) code sigPused - SigSpec P = port(dsp, \P); - for (int i = 0; i < GetSize(P); i++) - if (P[i].wire && nusers(P[i]) > 1) - sigPused.append(P[i]); + for (int i = 0; i < GetSize(sigP); i++) + if (sigP[i].wire && nusers(sigP[i]) > 1) + sigPused.append(sigP[i]); endcode match ffP |