Simplify and fix for MACs
[yosys.git] / passes / pmgen / ice40_dsp.pmg
1 pattern ice40_dsp
2
3 state <SigBit> clock
4 state <bool> clock_pol sigCD_signed
5 state <SigSpec> sigA sigB sigCD sigH sigO
6 state <Cell*> addAB muxAB
7
8 match mul
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
12 endmatch
13
14 match ffA
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())
18 optional
19 endmatch
20
21 code sigA clock clock_pol
22 sigA = port(mul, \A);
23
24 if (ffA) {
25 clock = port(ffA, \CLK).as_bit();
26 clock_pol = param(ffA, \CLK_POLARITY).as_bool();
27
28 sigA.replace(port(ffA, \Q), port(ffA, \D));
29 }
30 endcode
31
32 match ffB
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())
36 optional
37 endmatch
38
39 code sigB clock clock_pol
40 sigB = port(mul, \B);
41
42 if (ffB) {
43 SigBit c = port(ffB, \CLK).as_bit();
44 bool cp = param(ffB, \CLK_POLARITY).as_bool();
45
46 if (clock != SigBit() && (c != clock || cp != clock_pol))
47 reject;
48
49 clock = c;
50 clock_pol = cp;
51
52 sigB.replace(port(ffB, \Q), port(ffB, \D));
53 }
54 endcode
55
56 match ffH
57 select ffH->type.in($dff)
58 select nusers(port(ffH, \D)) == 2
59 index <SigSpec> port(ffH, \D) === port(mul, \Y)
60 optional
61 endmatch
62
63 code sigH sigO clock clock_pol
64 sigH = port(mul, \Y);
65 sigO = sigH;
66
67 if (ffH) {
68 sigH = port(ffH, \Q);
69 sigO = sigH;
70
71 SigBit c = port(ffH, \CLK).as_bit();
72 bool cp = param(ffH, \CLK_POLARITY).as_bool();
73
74 if (clock != SigBit() && (c != clock || cp != clock_pol))
75 reject;
76
77 clock = c;
78 clock_pol = cp;
79 }
80 endcode
81
82 match addA
83 select addA->type.in($add)
84 select nusers(port(addA, \A)) == 2
85 index <SigSpec> port(addA, \A) === sigH
86 optional
87 endmatch
88
89 match addB
90 if !addA
91 select addB->type.in($add, $sub)
92 select nusers(port(addB, \B)) == 2
93 index <SigSpec> port(addB, \B) === sigH
94 optional
95 endmatch
96
97 code addAB sigCD sigCD_signed sigO
98 if (addA) {
99 addAB = addA;
100 sigCD = port(addAB, \B);
101 sigCD_signed = param(addAB, \B_SIGNED).as_bool();
102 }
103 if (addB) {
104 addAB = addB;
105 sigCD = port(addAB, \A);
106 sigCD_signed = param(addAB, \A_SIGNED).as_bool();
107 }
108 if (addAB) {
109 int natural_mul_width = GetSize(sigA) + GetSize(sigB);
110 int actual_mul_width = GetSize(sigH);
111 int actual_acc_width = GetSize(sigO);
112
113 if ((actual_acc_width > actual_mul_width) && (natural_mul_width > actual_mul_width))
114 reject;
115 if ((actual_acc_width != actual_mul_width) && (param(mul, \A_SIGNED).as_bool() != param(addAB, \A_SIGNED).as_bool()))
116 reject;
117
118 sigO = port(addAB, \Y);
119 }
120 endcode
121
122 match muxA
123 select muxA->type.in($mux)
124 select nusers(port(muxA, \A)) == 2
125 index <SigSpec> port(muxA, \A) === sigO
126 optional
127 endmatch
128
129 match muxB
130 if !muxA
131 select muxB->type.in($mux)
132 select nusers(port(muxB, \B)) == 2
133 index <SigSpec> port(muxB, \B) === sigO
134 optional
135 endmatch
136
137 code muxAB
138 if (muxA)
139 muxAB = muxA;
140 else if (muxB)
141 muxAB = muxB;
142 endcode
143
144 match ffO_lo
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())
148 optional
149 endmatch
150
151 match ffO_hi
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())
155 optional
156 endmatch
157
158 code clock clock_pol sigO sigCD sigCD_signed
159 if (ffO_lo || ffO_hi) {
160 if (ffO_lo) {
161 SigBit c = port(ffO_lo, \CLK).as_bit();
162 bool cp = param(ffO_lo, \CLK_POLARITY).as_bool();
163
164 if (clock != SigBit() && (c != clock || cp != clock_pol))
165 reject;
166
167 clock = c;
168 clock_pol = cp;
169
170 if (port(ffO_lo, \Q) != sigO.extract(0,16))
171 sigO.replace(port(ffO_lo, \D), port(ffO_lo, \Q));
172 }
173
174 if (ffO_hi) {
175 SigBit c = port(ffO_hi, \CLK).as_bit();
176 bool cp = param(ffO_hi, \CLK_POLARITY).as_bool();
177
178 if (clock != SigBit() && (c != clock || cp != clock_pol))
179 reject;
180
181 clock = c;
182 clock_pol = cp;
183
184 if (port(ffO_hi, \Q) != sigO.extract(16,16))
185 sigO.replace(port(ffO_hi, \D), port(ffO_hi, \Q));
186 }
187
188 // Loading value into output register is not
189 // supported unless using accumulator
190 if (muxAB && sigCD != sigO) {
191 if (muxAB != addAB)
192 reject;
193
194 if (muxA)
195 sigCD = port(muxAB, \B);
196 else if (muxB)
197 sigCD = port(muxAB, \A);
198 else log_abort();
199 sigCD_signed = addAB && param(addAB, \A_SIGNED).as_bool() && param(addAB, \B_SIGNED).as_bool();
200 }
201 }
202 endcode