Fix typo
[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 if sigCD.empty()
124 select muxA->type.in($mux)
125 select nusers(port(muxA, \A)) == 2
126 index <SigSpec> port(muxA, \A) === sigO
127 optional
128 endmatch
129
130 match muxB
131 if sigCD.empty()
132 if !muxA
133 select muxB->type.in($mux)
134 select nusers(port(muxB, \B)) == 2
135 index <SigSpec> port(muxB, \B) === sigO
136 optional
137 endmatch
138
139 code muxAB sigCD sigCD_signed sigO
140 muxAB = addAB;
141 if (muxA) {
142 muxAB = muxA;
143 sigCD = port(muxAB, \B);
144 }
145 if (muxB) {
146 muxAB = muxB;
147 sigCD = port(muxAB, \A);
148 }
149 if (muxA || muxB) {
150 sigO = port(muxAB, \Y);
151 sigCD_signed = addAB && param(addAB, \A_SIGNED).as_bool() && param(addAB, \B_SIGNED).as_bool();
152 }
153 endcode
154
155 match ffO_lo
156 select ffO_lo->type.in($dff)
157 filter nusers(sigO.extract(0,16)) == 2
158 filter includes(port(ffO_lo, \D).to_sigbit_set(), sigO.extract(0,16).to_sigbit_set())
159 optional
160 endmatch
161
162 match ffO_hi
163 select ffO_hi->type.in($dff)
164 filter nusers(sigO.extract(16,16)) == 2
165 filter includes(port(ffO_hi, \D).to_sigbit_set(), sigO.extract(16,16).to_sigbit_set())
166 optional
167 endmatch
168
169 code clock clock_pol sigO
170 if (ffO_lo || ffO_hi) {
171 if (ffO_lo) {
172 SigBit c = port(ffO_lo, \CLK).as_bit();
173 bool cp = param(ffO_lo, \CLK_POLARITY).as_bool();
174
175 if (clock != SigBit() && (c != clock || cp != clock_pol))
176 reject;
177
178 clock = c;
179 clock_pol = cp;
180
181 if (port(ffO_lo, \Q) != sigO.extract(0,16))
182 sigO.replace(port(ffO_lo, \D), port(ffO_lo, \Q));
183 }
184
185 if (ffO_hi) {
186 SigBit c = port(ffO_hi, \CLK).as_bit();
187 bool cp = param(ffO_hi, \CLK_POLARITY).as_bool();
188
189 if (clock != SigBit() && (c != clock || cp != clock_pol))
190 reject;
191
192 clock = c;
193 clock_pol = cp;
194
195 if (port(ffO_hi, \Q) != sigO.extract(16,16))
196 sigO.replace(port(ffO_hi, \D), port(ffO_hi, \Q));
197 }
198 }
199 endcode