pattern ice40_dsp state clock state clock_pol clock_vld state sigA sigB sigY sigS state addAB muxAB match mul select mul->type.in($mul) select GetSize(mul->getPort(\A)) + GetSize(mul->getPort(\B)) > 10 select GetSize(mul->getPort(\Y)) > 10 endmatch match ffA select ffA->type.in($dff) // select nusers(port(ffA, \Q)) == 2 index port(ffA, \Q) === port(mul, \A) optional endmatch code sigA clock clock_pol clock_vld sigA = port(mul, \A); if (ffA) { sigA = 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) optional endmatch code sigB clock clock_pol clock_vld sigB = port(mul, \B); if (ffB) { sigB = 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)) reject; clock = c; clock_pol = cp; clock_vld = true; } endcode match ffY select ffY->type.in($dff) select nusers(port(ffY, \D)) == 2 index port(ffY, \D) === port(mul, \Y) optional endmatch code sigY clock clock_pol clock_vld sigY = port(mul, \Y); if (ffY) { sigY = 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)) reject; clock = c; clock_pol = cp; clock_vld = true; } 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 clock_vld 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)) reject; clock = c; clock_pol = cp; clock_vld = true; } accept; endcode