From 2f04beeeb5114058ce762d0393859d517a9a35eb Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 13 Aug 2019 17:11:35 -0700 Subject: [PATCH] Perform C -> PCIN optimisation after pattern matcher --- passes/pmgen/xilinx_dsp.cc | 67 +++++++++++++++++++++++++++++++------ passes/pmgen/xilinx_dsp.pmg | 24 ++++++++----- 2 files changed, 72 insertions(+), 19 deletions(-) diff --git a/passes/pmgen/xilinx_dsp.cc b/passes/pmgen/xilinx_dsp.cc index 31c0d48c5..e7b72e312 100644 --- a/passes/pmgen/xilinx_dsp.cc +++ b/passes/pmgen/xilinx_dsp.cc @@ -23,22 +23,23 @@ USING_YOSYS_NAMESPACE PRIVATE_NAMESPACE_BEGIN -template bool includes(const T &lhs, const T &rhs) { +template inline bool includes(const T &lhs, const T &rhs) { return std::includes(lhs.begin(), lhs.end(), rhs.begin(), rhs.end()); } +#include #include "passes/pmgen/xilinx_dsp_pm.h" -void pack_xilinx_dsp(xilinx_dsp_pm &pm) +void pack_xilinx_dsp(dict &bit_to_driver, xilinx_dsp_pm &pm) { auto &st = pm.st_xilinx_dsp; #if 1 log("\n"); - 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("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)); #endif @@ -46,11 +47,17 @@ void pack_xilinx_dsp(xilinx_dsp_pm &pm) log("Analysing %s.%s for Xilinx DSP packing.\n", log_id(pm.module), log_id(st.dsp)); Cell *cell = st.dsp; + bit_to_driver.insert(std::make_pair(cell->getPort("\\P")[17], cell)); SigSpec P = st.sigP; if (st.addAB) { + log_assert(st.addAB->getParam("\\A_SIGNED").as_bool()); + log_assert(st.addAB->getParam("\\B_SIGNED").as_bool()); log(" adder %s (%s)\n", log_id(st.addAB), log_id(st.addAB->type)); - cell->setPort("\\C", st.sigC.extend_u0(48, true)); + + SigSpec C = st.sigC; + C.extend_u0(48, true); + cell->setPort("\\C", C); SigSpec &opmode = cell->connections_.at("\\OPMODE"); opmode[6] = State::S0; opmode[5] = State::S1; @@ -153,8 +160,48 @@ struct XilinxDspPass : public Pass { } extra_args(args, argidx, design); - for (auto module : design->selected_modules()) - xilinx_dsp_pm(module, module->selected_cells()).run_xilinx_dsp(pack_xilinx_dsp); + for (auto module : design->selected_modules()) { + xilinx_dsp_pm pm(module, module->selected_cells()); + dict bit_to_driver; + auto f = [&bit_to_driver](xilinx_dsp_pm &pm){ pack_xilinx_dsp(bit_to_driver, pm); }; + pm.run_xilinx_dsp(f); + + // Look for ability to convert C input from another DSP into PCIN + // NB: Needs to be done after pattern matcher has folded all + // $add cells into the DSP + for (auto cell : module->cells()) { + if (cell->type != "\\DSP48E1") + continue; + SigSpec &opmode = cell->connections_.at("\\OPMODE"); + if (opmode.extract(4,3) != Const::from_string("011")) + continue; + SigSpec C = pm.sigmap(cell->getPort("\\C")); + if (C.has_const()) + continue; + auto it = bit_to_driver.find(C[0]); + if (it == bit_to_driver.end()) + continue; + auto driver = it->second; + + // Unextend C + int i; + for (i = GetSize(C)-1; i > 0; i--) + if (C[i] != C[i-1]) + break; + if (i > 48-17) + continue; + if (driver->getPort("\\P").extract(17, i) == C.extract(0, i)) { + cell->setPort("\\C", Const(0, 48)); + Wire *cascade = module->addWire(NEW_ID, 48); + driver->setPort("\\PCOUT", cascade); + cell->setPort("\\PCIN", cascade); + opmode[6] = State::S1; + opmode[5] = State::S0; + opmode[4] = State::S1; + bit_to_driver.erase(it); + } + } + } } } XilinxDspPass; diff --git a/passes/pmgen/xilinx_dsp.pmg b/passes/pmgen/xilinx_dsp.pmg index 5dee36a11..1a3dcdcbb 100644 --- a/passes/pmgen/xilinx_dsp.pmg +++ b/passes/pmgen/xilinx_dsp.pmg @@ -1,6 +1,7 @@ pattern xilinx_dsp state clock +state > sigAset sigBset state sigC sigP sigPused state addAB @@ -8,13 +9,22 @@ match dsp select dsp->type.in(\DSP48E1) endmatch +code sigAset sigBset + SigSpec A = port(dsp, \A); + A.remove_const(); + sigAset = A.to_sigbit_set(); + SigSpec B = port(dsp, \B); + B.remove_const(); + sigBset = B.to_sigbit_set(); +endcode + match ffA if param(dsp, \AREG).as_int() == 0 - if !port(dsp, \A).remove_const().empty() + if !sigAset.empty() select ffA->type.in($dff) // DSP48E1 does not support clock inversion select param(ffA, \CLK_POLARITY).as_bool() - filter includes(port(ffA, \Q).to_sigbit_set(), port(dsp, \A).remove_const().to_sigbit_set()) + filter includes(port(ffA, \Q).to_sigbit_set(), sigAset) optional endmatch @@ -25,11 +35,11 @@ endcode match ffB if param(dsp, \BREG).as_int() == 0 - if !port(dsp, \B).remove_const().empty() + if !sigBset.empty() select ffB->type.in($dff) // DSP48E1 does not support clock inversion select param(ffB, \CLK_POLARITY).as_bool() - filter includes(port(ffB, \Q).to_sigbit_set(), port(dsp, \B).remove_const().to_sigbit_set()) + filter includes(port(ffB, \Q).to_sigbit_set(), sigBset) optional endmatch @@ -65,21 +75,18 @@ match addB index nusers(port(addB, \B)) === 2 //index port(addB, \B) === sigP.extract(0, param(addB, \B_WIDTH).as_int()) filter param(addB, \B_WIDTH).as_int() <= GetSize(sigP) - filter port(addB, \B) == sigP.extract(0, 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 @@ -97,7 +104,6 @@ code addAB sigC sigP // reject; sigP = port(addAB, \Y); - sigC.extend_u0(32, C_SIGNED); } endcode -- 2.30.2