Pack hi and lo registers separately
[yosys.git] / passes / pmgen / ice40_dsp.pmg
1 pattern ice40_dsp
2
3 state <SigBit> clock
4 state <bool> clock_pol sigO_signed
5 state <SigSpec> sigA sigB 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 sigO sigO_signed
98 if (addA) {
99 addAB = addA;
100 sigO_signed = param(addAB, \B_SIGNED).as_bool();
101 }
102 if (addB) {
103 addAB = addB;
104 sigO_signed = param(addAB, \A_SIGNED).as_bool();
105 }
106 if (addAB) {
107 int natural_mul_width = GetSize(sigA) + GetSize(sigB);
108 int actual_mul_width = GetSize(sigH);
109 int actual_acc_width = GetSize(sigO);
110
111 if ((actual_acc_width > actual_mul_width) && (natural_mul_width > actual_mul_width))
112 reject;
113 if ((actual_acc_width != actual_mul_width) && (param(mul, \A_SIGNED).as_bool() != param(addAB, \A_SIGNED).as_bool()))
114 reject;
115
116 sigO = port(addAB, \Y);
117 }
118 endcode
119
120 match muxA
121 if addAB
122 select muxA->type.in($mux)
123 select nusers(port(muxA, \A)) == 2
124 index <SigSpec> port(muxA, \A) === port(addAB, \Y)
125 optional
126 endmatch
127
128 match muxB
129 if addAB
130 if !muxA
131 select muxB->type.in($mux)
132 select nusers(port(muxB, \B)) == 2
133 index <SigSpec> port(muxB, \B) === port(addAB, \Y)
134 optional
135 endmatch
136
137 code muxAB sigO
138 muxAB = addAB;
139 if (muxA)
140 muxAB = muxA;
141 if (muxB)
142 muxAB = muxB;
143 if (muxA || muxB)
144 sigO = port(muxAB, \Y);
145 endcode
146
147 match ffO_lo
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())
151 optional
152 endmatch
153
154 match ffO_hi
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())
158 optional
159 endmatch
160
161 code clock clock_pol sigO
162 if (ffO_lo || ffO_hi) {
163 if (ffO_lo) {
164 SigBit c = port(ffO_lo, \CLK).as_bit();
165 bool cp = param(ffO_lo, \CLK_POLARITY).as_bool();
166
167 if (clock != SigBit() && (c != clock || cp != clock_pol))
168 reject;
169
170 clock = c;
171 clock_pol = cp;
172
173 if (port(ffO_lo, \Q) != sigO.extract(0,16))
174 sigO.replace(port(ffO_lo, \D), port(ffO_lo, \Q));
175 }
176
177 if (ffO_hi) {
178 SigBit c = port(ffO_hi, \CLK).as_bit();
179 bool cp = param(ffO_hi, \CLK_POLARITY).as_bool();
180
181 if (clock != SigBit() && (c != clock || cp != clock_pol))
182 reject;
183
184 clock = c;
185 clock_pol = cp;
186
187 if (port(ffO_hi, \Q) != sigO.extract(16,16))
188 sigO.replace(port(ffO_hi, \D), port(ffO_hi, \Q));
189 }
190 }
191 endcode