4 state <bool> clock_pol sigO_signed
5 state <SigSpec> sigA sigB sigH sigO
6 state <Cell*> addAB muxAB
9 select mul->type.in($mul, $__MUL16X16)
10 select GetSize(mul->getPort(\A)) + GetSize(mul->getPort(\B)) > 10
11 select GetSize(mul->getPort(\Y)) > 10
15 select ffA->type.in($dff)
16 filter !port(mul, \A).remove_const().empty()
17 filter includes(port(ffA, \Q).to_sigbit_set(), port(mul, \A).remove_const().to_sigbit_set())
21 code sigA clock clock_pol
25 clock = port(ffA, \CLK).as_bit();
26 clock_pol = param(ffA, \CLK_POLARITY).as_bool();
28 sigA.replace(port(ffA, \Q), port(ffA, \D));
33 select ffB->type.in($dff)
34 filter !port(mul, \B).remove_const().empty()
35 filter includes(port(ffB, \Q).to_sigbit_set(), port(mul, \B).remove_const().to_sigbit_set())
39 code sigB clock clock_pol
43 SigBit c = port(ffB, \CLK).as_bit();
44 bool cp = param(ffB, \CLK_POLARITY).as_bool();
46 if (clock != SigBit() && (c != clock || cp != clock_pol))
52 sigB.replace(port(ffB, \Q), port(ffB, \D));
57 select ffH->type.in($dff)
58 select nusers(port(ffH, \D)) == 2
59 index <SigSpec> port(ffH, \D) === port(mul, \Y)
63 code sigH sigO clock clock_pol
71 SigBit c = port(ffH, \CLK).as_bit();
72 bool cp = param(ffH, \CLK_POLARITY).as_bool();
74 if (clock != SigBit() && (c != clock || cp != clock_pol))
83 select addA->type.in($add)
84 select nusers(port(addA, \A)) == 2
85 index <SigSpec> port(addA, \A) === sigH
91 select addB->type.in($add, $sub)
92 select nusers(port(addB, \B)) == 2
93 index <SigSpec> port(addB, \B) === sigH
97 code addAB sigO sigO_signed
100 sigO_signed = param(addAB, \B_SIGNED).as_bool();
104 sigO_signed = param(addAB, \A_SIGNED).as_bool();
107 int natural_mul_width = GetSize(sigA) + GetSize(sigB);
108 int actual_mul_width = GetSize(sigH);
109 int actual_acc_width = GetSize(sigO);
111 if ((actual_acc_width > actual_mul_width) && (natural_mul_width > actual_mul_width))
113 if ((actual_acc_width != actual_mul_width) && (param(mul, \A_SIGNED).as_bool() != param(addAB, \A_SIGNED).as_bool()))
116 sigO = port(addAB, \Y);
122 select muxA->type.in($mux)
123 select nusers(port(muxA, \A)) == 2
124 index <SigSpec> port(muxA, \A) === port(addAB, \Y)
131 select muxB->type.in($mux)
132 select nusers(port(muxB, \B)) == 2
133 index <SigSpec> port(muxB, \B) === port(addAB, \Y)
144 sigO = port(muxAB, \Y);
148 select ffO_lo->type.in($dff)
149 filter nusers(sigO.extract(0,16)) == 2
150 filter includes(port(ffO_lo, \D).to_sigbit_set(), sigO.extract(0,16).to_sigbit_set())
155 select ffO_hi->type.in($dff)
156 filter nusers(sigO.extract(16,16)) == 2
157 filter includes(port(ffO_hi, \D).to_sigbit_set(), sigO.extract(16,16).to_sigbit_set())
161 code clock clock_pol sigO
162 if (ffO_lo || ffO_hi) {
164 SigBit c = port(ffO_lo, \CLK).as_bit();
165 bool cp = param(ffO_lo, \CLK_POLARITY).as_bool();
167 if (clock != SigBit() && (c != clock || cp != clock_pol))
173 if (port(ffO_lo, \Q) != sigO.extract(0,16))
174 sigO.replace(port(ffO_lo, \D), port(ffO_lo, \Q));
178 SigBit c = port(ffO_hi, \CLK).as_bit();
179 bool cp = param(ffO_hi, \CLK_POLARITY).as_bool();
181 if (clock != SigBit() && (c != clock || cp != clock_pol))
187 if (port(ffO_hi, \Q) != sigO.extract(16,16))
188 sigO.replace(port(ffO_hi, \D), port(ffO_hi, \Q));