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 &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 &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 clock state > sigAset sigBset state sigC sigM sigMused sigP sigPused -state addAB +state 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 port(muxA, \A) === sigP + index port(muxA, \Y) === sigC + optional +endmatch + +match muxB + if addAB + select muxB->type.in($mux) + select nusers(port(muxB, \Y)) == 2 + index port(muxB, \B) === sigP + index 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