pattern ice40_dsp state clock state clock_pol state sigA sigB sigY sigS state sigYused state addAB muxAB match mul select mul->type.in($mul, $__MUL16X16) select GetSize(mul->getPort(\A)) + GetSize(mul->getPort(\B)) > 10 select GetSize(mul->getPort(\Y)) > 10 endmatch match ffA select ffA->type.in($dff) 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 sigA = port(mul, \A); if (ffA) { sigA.replace(port(ffA, \Q), port(ffA, \D)); clock = port(ffA, \CLK).as_bit(); clock_pol = param(ffA, \CLK_POLARITY).as_bool(); } endcode match ffB select ffB->type.in($dff) 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 sigB = port(mul, \B); if (ffB) { 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 != SigBit() && (c != clock || cp != clock_pol)) reject; clock = c; clock_pol = cp; } 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 filter param(ffY, \WIDTH).as_int() >= GetSize(sigYused) filter includes(port(ffY, \D).to_sigbit_set(), sigYused.to_sigbit_set()) optional endmatch code clock clock_pol sigY if (ffY) { 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 != SigBit() && (c != clock || cp != clock_pol)) reject; clock = c; clock_pol = cp; } endcode match addA select addA->type.in($add) select nusers(port(addA, \A)) == 2 index port(addA, \A) === sigY optional endmatch match addB if !addA select addB->type.in($add, $sub) select nusers(port(addB, \B)) == 2 index port(addB, \B) === sigY optional endmatch code addAB sigS if (addA) { addAB = addA; sigS = port(addA, \B); } if (addB) { addAB = addB; sigS = port(addB, \A); } if (addAB) { int natural_mul_width = GetSize(sigA) + GetSize(sigB); int actual_mul_width = GetSize(sigY); int actual_acc_width = GetSize(sigS); if ((actual_acc_width > actual_mul_width) && (natural_mul_width > actual_mul_width)) reject; if ((actual_acc_width != actual_mul_width) && (param(mul, \A_SIGNED).as_bool() != param(addAB, \A_SIGNED).as_bool())) reject; } endcode match muxA if addAB select muxA->type.in($mux) select nusers(port(muxA, \A)) == 2 index port(muxA, \A) === port(addAB, \Y) optional endmatch match muxB if addAB if !muxA select muxB->type.in($mux) select nusers(port(muxB, \B)) == 2 index port(muxB, \B) === port(addAB, \Y) optional endmatch code muxAB muxAB = addAB; if (muxA) muxAB = muxA; if (muxB) muxAB = muxB; endcode match ffS if muxAB select ffS->type.in($dff) select nusers(port(ffS, \D)) == 2 index port(ffS, \D) === port(muxAB, \Y) index port(ffS, \Q) === sigS endmatch code clock clock_pol if (ffS) { SigBit c = port(ffS, \CLK).as_bit(); bool cp = param(ffS, \CLK_POLARITY).as_bool(); if (clock != SigBit() && (c != clock || cp != clock_pol)) reject; clock = c; clock_pol = cp; } endcode