aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--passes/pmgen/xilinx_dsp.cc7
-rw-r--r--passes/pmgen/xilinx_dsp.pmg70
2 files changed, 47 insertions, 30 deletions
diff --git a/passes/pmgen/xilinx_dsp.cc b/passes/pmgen/xilinx_dsp.cc
index 1732a2d6a..b3d302071 100644
--- a/passes/pmgen/xilinx_dsp.cc
+++ b/passes/pmgen/xilinx_dsp.cc
@@ -40,6 +40,7 @@ void pack_xilinx_dsp(dict<SigBit, Cell*> &bit_to_driver, xilinx_dsp_pm &pm)
log("dsp: %s\n", log_id(st.dsp, "--"));
log("ffM: %s\n", log_id(st.ffM, "--"));
log("addAB: %s\n", log_id(st.addAB, "--"));
+ log("muxAB: %s\n", log_id(st.muxAB, "--"));
log("ffP: %s\n", log_id(st.ffP, "--"));
//log("muxP: %s\n", log_id(st.muxP, "--"));
log("sigPused: %s\n", log_signal(st.sigPused));
@@ -58,7 +59,11 @@ void pack_xilinx_dsp(dict<SigBit, Cell*> &bit_to_driver, xilinx_dsp_pm &pm)
log(" adder %s (%s)\n", log_id(st.addAB), log_id(st.addAB->type));
SigSpec &opmode = cell->connections_.at("\\OPMODE");
- if (st.ffP && C == P) {
+ if (st.ffP && st.muxAB) {
+ opmode[4] = st.muxAB->getPort("\\S");
+ pm.autoremove(st.muxAB);
+ }
+ else if (st.ffP && C == P) {
C = SigSpec();
opmode[4] = State::S0;
}
diff --git a/passes/pmgen/xilinx_dsp.pmg b/passes/pmgen/xilinx_dsp.pmg
index 132b09b2b..fdc3fa5e7 100644
--- a/passes/pmgen/xilinx_dsp.pmg
+++ b/passes/pmgen/xilinx_dsp.pmg
@@ -3,7 +3,7 @@ pattern xilinx_dsp
state <SigBit> clock
state <std::set<SigBit>> sigAset sigBset
state <SigSpec> sigC sigM sigMused sigP sigPused
-state <Cell*> addAB
+state <Cell*> addAB muxAB
match dsp
select dsp->type.in(\DSP48E1)
@@ -172,34 +172,7 @@ match ffP
optional
endmatch
-//// $mux cell left behind by dff2dffe
-//// would prefer not to run 'opt_expr -mux_undef'
-//// since that would lose information helpful for
-//// efficient wide-mux inference
-//match muxP
-// 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(sigPused)
-// filter includes(port(muxP, \B).to_sigbit_set(), sigPused.to_sigbit_set())
-// optional
-//endmatch
-//
-//match ffY
-// if muxP
-// select ffY->type.in($dff, $dffe)
-// 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(sigPused)
-// filter includes(port(ffY, \D).to_sigbit_set(), port(muxP, \Y).to_sigbit_set())
-//endmatch
-
-code ffP clock
-// if (ffY)
-// ffP = ffY;
-
+code ffP sigP clock
if (ffP) {
for (auto b : port(ffP, \Q))
if (b.wire->get_bool_attribute(\keep))
@@ -211,7 +184,46 @@ code ffP clock
reject;
clock = c;
+
+ sigP = port(ffP, \Q);
+ }
+endcode
+
+match muxA
+ if addAB
+ select muxA->type.in($mux)
+ select nusers(port(muxA, \Y)) == 2
+ index <SigSpec> port(muxA, \A) === sigP
+ index <SigSpec> port(muxA, \Y) === sigC
+ optional
+endmatch
+
+match muxB
+ if addAB
+ select muxB->type.in($mux)
+ select nusers(port(muxB, \Y)) == 2
+ index <SigSpec> port(muxB, \B) === sigP
+ index <SigSpec> port(muxB, \Y) === sigC
+ optional
+endmatch
+
+code sigC muxAB
+ if (muxA) {
+ muxAB = muxA;
+ sigC = port(muxAB, \B);
+ }
+ if (muxB) {
+ muxAB = muxB;
+ sigC = port(muxAB, \A);
}
+ if (muxAB) {
+ // Ensure that adder is not used
+ SigSpec opmodeZ = port(dsp, \OPMODE).extract(4,3);
+ if (!opmodeZ.is_fully_zero())
+ reject;
+ }
+endcode
+code
accept;
endcode