4 state <bool> clock_pol sigCD_signed
5 state <SigSpec> sigA sigB sigCD 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 sigCD sigCD_signed sigO
100 sigCD = port(addAB, \B);
101 sigCD_signed = param(addAB, \B_SIGNED).as_bool();
105 sigCD = port(addAB, \A);
106 sigCD_signed = param(addAB, \A_SIGNED).as_bool();
109 int natural_mul_width = GetSize(sigA) + GetSize(sigB);
110 int actual_mul_width = GetSize(sigH);
111 int actual_acc_width = GetSize(sigO);
113 if ((actual_acc_width > actual_mul_width) && (natural_mul_width > actual_mul_width))
115 if ((actual_acc_width != actual_mul_width) && (param(mul, \A_SIGNED).as_bool() != param(addAB, \A_SIGNED).as_bool()))
118 sigO = port(addAB, \Y);
123 select muxA->type.in($mux)
124 select nusers(port(muxA, \A)) == 2
125 index <SigSpec> port(muxA, \A) === sigO
131 select muxB->type.in($mux)
132 select nusers(port(muxB, \B)) == 2
133 index <SigSpec> port(muxB, \B) === sigO
145 select ffO_lo->type.in($dff)
146 filter nusers(sigO.extract(0,16)) == 2
147 filter includes(port(ffO_lo, \D).to_sigbit_set(), sigO.extract(0,16).to_sigbit_set())
152 select ffO_hi->type.in($dff)
153 filter nusers(sigO.extract(16,16)) == 2
154 filter includes(port(ffO_hi, \D).to_sigbit_set(), sigO.extract(16,16).to_sigbit_set())
158 code clock clock_pol sigO sigCD sigCD_signed
159 if (ffO_lo || ffO_hi) {
161 SigBit c = port(ffO_lo, \CLK).as_bit();
162 bool cp = param(ffO_lo, \CLK_POLARITY).as_bool();
164 if (clock != SigBit() && (c != clock || cp != clock_pol))
170 if (port(ffO_lo, \Q) != sigO.extract(0,16))
171 sigO.replace(port(ffO_lo, \D), port(ffO_lo, \Q));
175 SigBit c = port(ffO_hi, \CLK).as_bit();
176 bool cp = param(ffO_hi, \CLK_POLARITY).as_bool();
178 if (clock != SigBit() && (c != clock || cp != clock_pol))
184 if (port(ffO_hi, \Q) != sigO.extract(16,16))
185 sigO.replace(port(ffO_hi, \D), port(ffO_hi, \Q));
188 // Loading value into output register is not
189 // supported unless using accumulator
194 sigCD = port(muxAB, \B);
196 sigCD = port(muxAB, \A);
198 sigCD_signed = addAB && param(addAB, \A_SIGNED).as_bool() && param(addAB, \B_SIGNED).as_bool();