From 9ad11ea2cc25f764bcd4e27dfc12c0f8041cb48a Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 19 Jul 2019 10:57:32 -0700 Subject: [PATCH] Fine tune ice40_dsp.pmg, add support for packing subsets of registers --- passes/pmgen/ice40_dsp.cc | 7 +++-- passes/pmgen/ice40_dsp.pmg | 53 ++++++++++++++++++++++--------------- passes/pmgen/xilinx_dsp.cc | 2 +- passes/pmgen/xilinx_dsp.pmg | 20 +++++++------- 4 files changed, 47 insertions(+), 35 deletions(-) diff --git a/passes/pmgen/ice40_dsp.cc b/passes/pmgen/ice40_dsp.cc index 963a7d7a1..f6a701540 100644 --- a/passes/pmgen/ice40_dsp.cc +++ b/passes/pmgen/ice40_dsp.cc @@ -23,13 +23,16 @@ USING_YOSYS_NAMESPACE PRIVATE_NAMESPACE_BEGIN +template bool includes(const T &lhs, const T &rhs) { + return std::includes(lhs.begin(), lhs.end(), rhs.begin(), rhs.end()); +} #include "passes/pmgen/ice40_dsp_pm.h" void create_ice40_dsp(ice40_dsp_pm &pm) { auto &st = pm.st_ice40_dsp; -#if 0 +#if 1 log("\n"); log("ffA: %s\n", log_id(st.ffA, "--")); log("ffB: %s\n", log_id(st.ffB, "--")); @@ -100,7 +103,7 @@ void create_ice40_dsp(ice40_dsp_pm &pm) cell->setPort("\\IRSTTOP", State::S0); cell->setPort("\\IRSTBOT", State::S0); - if (st.clock_vld) + if (st.clock != SigBit()) { cell->setPort("\\CLK", st.clock); cell->setPort("\\CE", State::S1); diff --git a/passes/pmgen/ice40_dsp.pmg b/passes/pmgen/ice40_dsp.pmg index f2b7f2169..471b8b519 100644 --- a/passes/pmgen/ice40_dsp.pmg +++ b/passes/pmgen/ice40_dsp.pmg @@ -1,8 +1,9 @@ pattern ice40_dsp state clock -state clock_pol clock_vld +state clock_pol state sigA sigB sigY sigS +state sigYused state addAB muxAB match mul @@ -13,68 +14,77 @@ endmatch match ffA select ffA->type.in($dff) - // select nusers(port(ffA, \Q)) == 2 - index port(ffA, \Q) === port(mul, \A) + filter !port(mul, \A).remove_const().empty() + filter includes(port(ffA, \Q).to_sigbit_set(), port(mul, \A).remove_const().to_sigbit_set()) optional endmatch -code sigA clock clock_pol clock_vld +code sigA clock clock_pol sigA = port(mul, \A); if (ffA) { - sigA = port(ffA, \D); + sigA.replace(port(ffA, \Q), port(ffA, \D)); clock = port(ffA, \CLK).as_bit(); clock_pol = param(ffA, \CLK_POLARITY).as_bool(); - clock_vld = true; } endcode match ffB select ffB->type.in($dff) - // select nusers(port(ffB, \Q)) == 2 - index port(ffB, \Q) === port(mul, \B) + filter !port(mul, \B).remove_const().empty() + filter includes(port(ffB, \Q).to_sigbit_set(), port(mul, \B).remove_const().to_sigbit_set()) optional endmatch -code sigB clock clock_pol clock_vld +code sigB clock clock_pol sigB = port(mul, \B); if (ffB) { - sigB = port(ffB, \D); + sigB.replace(port(ffB, \Q), port(ffB, \D)); + SigBit c = port(ffB, \CLK).as_bit(); bool cp = param(ffB, \CLK_POLARITY).as_bool(); - if (clock_vld && (c != clock || cp != clock_pol)) + if (clock != SigBit() && (c != clock || cp != clock_pol)) reject; clock = c; clock_pol = cp; - clock_vld = true; } endcode +// Extract the bits of Y that actually have a consumer +// (as opposed to being a sign extension) +code sigY sigYused + sigY = port(mul, \Y); + int i; + for (i = GetSize(sigY); i > 0; i--) + if (nusers(sigY[i-1]) > 1) + break; + sigYused = sigY.extract(0, i).remove_const(); +endcode + match ffY select ffY->type.in($dff) select nusers(port(ffY, \D)) == 2 - index port(ffY, \D) === port(mul, \Y) + filter param(ffY, \WIDTH).as_int() >= GetSize(sigYused) + filter includes(port(ffY, \D).to_sigbit_set(), sigYused.to_sigbit_set()) optional endmatch -code sigY clock clock_pol clock_vld - sigY = port(mul, \Y); - +code clock clock_pol sigY if (ffY) { - sigY = port(ffY, \Q); + sigY.replace(port(ffY, \D), port(ffY, \Q)); + SigBit c = port(ffY, \CLK).as_bit(); bool cp = param(ffY, \CLK_POLARITY).as_bool(); - if (clock_vld && (c != clock || cp != clock_pol)) + if (clock != SigBit() && (c != clock || cp != clock_pol)) reject; clock = c; clock_pol = cp; - clock_vld = true; } endcode @@ -147,16 +157,15 @@ match ffS index port(ffS, \Q) === sigS endmatch -code clock clock_pol clock_vld +code clock clock_pol if (ffS) { SigBit c = port(ffS, \CLK).as_bit(); bool cp = param(ffS, \CLK_POLARITY).as_bool(); - if (clock_vld && (c != clock || cp != clock_pol)) + if (clock != SigBit() && (c != clock || cp != clock_pol)) reject; clock = c; clock_pol = cp; - clock_vld = true; } endcode diff --git a/passes/pmgen/xilinx_dsp.cc b/passes/pmgen/xilinx_dsp.cc index c71ac5ef8..d87d63670 100644 --- a/passes/pmgen/xilinx_dsp.cc +++ b/passes/pmgen/xilinx_dsp.cc @@ -39,7 +39,7 @@ void pack_xilinx_dsp(xilinx_dsp_pm &pm) log("dsp: %s\n", log_id(st.dsp, "--")); log("ffP: %s\n", log_id(st.ffP, "--")); log("muxP: %s\n", log_id(st.muxP, "--")); - log("P_used: %s\n", log_signal(st.P_used)); + log("sigPused: %s\n", log_signal(st.sigPused)); log_module(pm.module); #endif diff --git a/passes/pmgen/xilinx_dsp.pmg b/passes/pmgen/xilinx_dsp.pmg index 7a175123e..a97ab4dd5 100644 --- a/passes/pmgen/xilinx_dsp.pmg +++ b/passes/pmgen/xilinx_dsp.pmg @@ -1,7 +1,7 @@ pattern xilinx_dsp state clock -state P_used +state sigPused match dsp select dsp->type.in(\DSP48E1) @@ -43,23 +43,23 @@ endcode // Extract the bits of P that actually have a consumer // (as opposed to being a sign extension) -code P_used +code sigPused SigSpec P = port(dsp, \P); int i; for (i = GetSize(P); i > 0; i--) if (nusers(P[i-1]) > 1) break; - P_used = P.extract(0, i).remove_const(); + sigPused = P.extract(0, i).remove_const(); endcode match ffP - if !P_used.empty() + if !sigPused.empty() select ffP->type.in($dff, $dffe) select nusers(port(ffP, \D)) == 2 // DSP48E1 does not support clock inversion select param(ffP, \CLK_POLARITY).as_bool() - filter param(ffP, \WIDTH).as_int() >= GetSize(P_used) - filter includes(port(ffP, \D).to_sigbit_set(), P_used.to_sigbit_set()) + filter param(ffP, \WIDTH).as_int() >= GetSize(sigPused) + filter includes(port(ffP, \D).to_sigbit_set(), sigPused.to_sigbit_set()) optional endmatch @@ -68,12 +68,12 @@ endmatch // since that would lose information helpful for // efficient wide-mux inference match muxP - if !P_used.empty() && !ffP + 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(P_used) - filter includes(port(muxP, \B).to_sigbit_set(), P_used.to_sigbit_set()) + filter param(muxP, \WIDTH).as_int() >= GetSize(sigPused) + filter includes(port(muxP, \B).to_sigbit_set(), sigPused.to_sigbit_set()) optional endmatch @@ -83,7 +83,7 @@ match ffY 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(P_used) + filter param(ffY, \WIDTH).as_int() >= GetSize(sigPused) filter includes(port(ffY, \D).to_sigbit_set(), port(muxP, \Y).to_sigbit_set()) endmatch -- 2.30.2