pattern xilinx_dsp state clock state P_WIDTH match dsp select dsp->type.in(\DSP48E1) endmatch match ffA select ffA->type.in($dff, $dffe) select param(ffA, \CLK_POLARITY).as_bool() // select nusers(port(ffA, \Q)) == 2 index > port(ffA, \Q).to_sigbit_pool() === port(dsp, \A).remove_const().to_sigbit_pool() // DSP48E1 does not support clock inversion optional endmatch code clock if (ffA) clock = port(ffA, \CLK).as_bit(); endcode match ffB select ffB->type.in($dff, $dffe) select param(ffB, \CLK_POLARITY).as_bool() // select nusers(port(ffB, \Q)) == 2 index > port(ffB, \Q).to_sigbit_pool() === port(dsp, \B).remove_const().to_sigbit_pool() optional endmatch code clock if (ffB) { SigBit c = port(ffB, \CLK).as_bit(); if (clock != SigBit() && c != clock) reject; clock = c; } endcode code P_WIDTH SigSpec P = port(dsp, \P); int i; for (i = GetSize(P); i > 0; i--) if (nusers(P[i-1]) > 1) break; P_WIDTH = i; endcode match ffP select ffP->type.in($dff, $dffe) select nusers(port(ffP, \D)) == 2 filter param(ffP, \WIDTH).as_int() == P_WIDTH filter port(ffP, \D) == port(dsp, \P).extract(0, P_WIDTH) index param(ffP, \CLK_POLARITY) === State::S1 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 !ffP select muxP->type.in($mux) select port(muxP, \A).is_fully_undef() filter param(muxP, \WIDTH).as_int() == P_WIDTH filter port(muxP, \B) == port(dsp, \P).extract(0, P_WIDTH) select nusers(port(muxP, \B)) == 2 optional endmatch match ffY if muxP select ffY->type.in($dff, $dffe) select nusers(port(ffY, \D)) == 2 index port(ffY, \D) === port(muxP, \Y) endmatch code ffP clock if (ffY) ffP = ffY; if (ffP) { SigBit c = port(ffP, \CLK).as_bit(); if (clock != SigBit() && c != clock) reject; clock = c; } endcode