Merge pull request #3290 from mpasternacki/bugfix/freebsd-build
[yosys.git] / kernel / ffmerge.cc
1 /*
2 * yosys -- Yosys Open SYnthesis Suite
3 *
4 * Copyright (C) 2021 Marcelina Koƛcielnicka <mwk@0x04.net>
5 *
6 * Permission to use, copy, modify, and/or distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 *
18 */
19
20 #include "kernel/ffmerge.h"
21
22 USING_YOSYS_NAMESPACE
23
24 bool FfMergeHelper::is_output_unused(RTLIL::SigSpec sig) {
25 for (auto bit : (*sigmap)(sig))
26 if (sigbit_users_count[bit] != 0)
27 return false;
28 return true;
29 }
30
31 bool FfMergeHelper::find_output_ff(RTLIL::SigSpec sig, FfData &ff, pool<std::pair<Cell *, int>> &bits) {
32 ff = FfData(module, initvals, NEW_ID);
33 sigmap->apply(sig);
34
35 bool found = false;
36
37 for (auto bit : sig)
38 {
39 if (bit.wire == NULL || sigbit_users_count[bit] == 0) {
40 ff.width++;
41 ff.sig_q.append(bit);
42 ff.sig_d.append(bit);
43 ff.sig_clr.append(State::Sx);
44 ff.sig_set.append(State::Sx);
45 ff.val_init.bits.push_back(State::Sx);
46 ff.val_srst.bits.push_back(State::Sx);
47 ff.val_arst.bits.push_back(State::Sx);
48 continue;
49 }
50
51 if (sigbit_users_count[bit] != 1)
52 return false;
53
54 auto &sinks = dff_sink[bit];
55 if (sinks.size() != 1)
56 return false;
57
58 Cell *cell;
59 int idx;
60 std::tie(cell, idx) = *sinks.begin();
61 bits.insert(std::make_pair(cell, idx));
62
63 FfData cur_ff(initvals, cell);
64
65 // Reject latches and $ff.
66 if (!cur_ff.has_clk)
67 return false;
68
69 log_assert((*sigmap)(cur_ff.sig_d[idx]) == bit);
70
71 if (!found) {
72 ff.sig_clk = cur_ff.sig_clk;
73 ff.sig_ce = cur_ff.sig_ce;
74 ff.sig_aload = cur_ff.sig_aload;
75 ff.sig_srst = cur_ff.sig_srst;
76 ff.sig_arst = cur_ff.sig_arst;
77 ff.has_clk = cur_ff.has_clk;
78 ff.has_ce = cur_ff.has_ce;
79 ff.has_aload = cur_ff.has_aload;
80 ff.has_srst = cur_ff.has_srst;
81 ff.has_arst = cur_ff.has_arst;
82 ff.has_sr = cur_ff.has_sr;
83 ff.ce_over_srst = cur_ff.ce_over_srst;
84 ff.pol_clk = cur_ff.pol_clk;
85 ff.pol_ce = cur_ff.pol_ce;
86 ff.pol_aload = cur_ff.pol_aload;
87 ff.pol_arst = cur_ff.pol_arst;
88 ff.pol_srst = cur_ff.pol_srst;
89 ff.pol_clr = cur_ff.pol_clr;
90 ff.pol_set = cur_ff.pol_set;
91 } else {
92 if (ff.has_clk != cur_ff.has_clk)
93 return false;
94 if (ff.has_ce != cur_ff.has_ce)
95 return false;
96 if (ff.has_aload != cur_ff.has_aload)
97 return false;
98 if (ff.has_srst != cur_ff.has_srst)
99 return false;
100 if (ff.has_arst != cur_ff.has_arst)
101 return false;
102 if (ff.has_sr != cur_ff.has_sr)
103 return false;
104 if (ff.has_clk) {
105 if (ff.sig_clk != cur_ff.sig_clk)
106 return false;
107 if (ff.pol_clk != cur_ff.pol_clk)
108 return false;
109 }
110 if (ff.has_ce) {
111 if (ff.sig_ce != cur_ff.sig_ce)
112 return false;
113 if (ff.pol_ce != cur_ff.pol_ce)
114 return false;
115 }
116 if (ff.has_aload) {
117 if (ff.sig_aload != cur_ff.sig_aload)
118 return false;
119 if (ff.pol_aload != cur_ff.pol_aload)
120 return false;
121 }
122 if (ff.has_srst) {
123 if (ff.sig_srst != cur_ff.sig_srst)
124 return false;
125 if (ff.pol_srst != cur_ff.pol_srst)
126 return false;
127 if (ff.has_ce && ff.ce_over_srst != cur_ff.ce_over_srst)
128 return false;
129 }
130 if (ff.has_arst) {
131 if (ff.sig_arst != cur_ff.sig_arst)
132 return false;
133 if (ff.pol_arst != cur_ff.pol_arst)
134 return false;
135 }
136 if (ff.has_sr) {
137 if (ff.pol_clr != cur_ff.pol_clr)
138 return false;
139 if (ff.pol_set != cur_ff.pol_set)
140 return false;
141 }
142 }
143
144 ff.width++;
145 ff.sig_d.append(cur_ff.sig_d[idx]);
146 ff.sig_ad.append(ff.has_aload ? cur_ff.sig_ad[idx] : State::Sx);
147 ff.sig_q.append(cur_ff.sig_q[idx]);
148 ff.sig_clr.append(ff.has_sr ? cur_ff.sig_clr[idx] : State::S0);
149 ff.sig_set.append(ff.has_sr ? cur_ff.sig_set[idx] : State::S0);
150 ff.val_arst.bits.push_back(ff.has_arst ? cur_ff.val_arst[idx] : State::Sx);
151 ff.val_srst.bits.push_back(ff.has_srst ? cur_ff.val_srst[idx] : State::Sx);
152 ff.val_init.bits.push_back(cur_ff.val_init[idx]);
153 found = true;
154 }
155
156 return found;
157 }
158
159 bool FfMergeHelper::find_input_ff(RTLIL::SigSpec sig, FfData &ff, pool<std::pair<Cell *, int>> &bits) {
160 ff = FfData(module, initvals, NEW_ID);
161 sigmap->apply(sig);
162
163 bool found = false;
164
165 pool<int> const_bits;
166
167 for (auto bit : sig)
168 {
169 if (bit.wire == NULL) {
170 const_bits.insert(ff.width);
171 ff.width++;
172 ff.sig_q.append(bit);
173 ff.sig_d.append(bit);
174 // These two will be fixed up later.
175 ff.sig_clr.append(State::Sx);
176 ff.sig_set.append(State::Sx);
177 ff.val_init.bits.push_back(bit.data);
178 ff.val_srst.bits.push_back(bit.data);
179 ff.val_arst.bits.push_back(bit.data);
180 continue;
181 }
182
183 if (!dff_driver.count(bit))
184 return false;
185
186 Cell *cell;
187 int idx;
188 std::tie(cell, idx) = dff_driver[bit];
189 bits.insert(std::make_pair(cell, idx));
190
191 FfData cur_ff(initvals, cell);
192
193 log_assert((*sigmap)(cur_ff.sig_q[idx]) == bit);
194
195 if (!found) {
196 ff.sig_clk = cur_ff.sig_clk;
197 ff.sig_ce = cur_ff.sig_ce;
198 ff.sig_aload = cur_ff.sig_aload;
199 ff.sig_srst = cur_ff.sig_srst;
200 ff.sig_arst = cur_ff.sig_arst;
201 ff.has_clk = cur_ff.has_clk;
202 ff.has_gclk = cur_ff.has_gclk;
203 ff.has_ce = cur_ff.has_ce;
204 ff.has_aload = cur_ff.has_aload;
205 ff.has_srst = cur_ff.has_srst;
206 ff.has_arst = cur_ff.has_arst;
207 ff.has_sr = cur_ff.has_sr;
208 ff.ce_over_srst = cur_ff.ce_over_srst;
209 ff.pol_clk = cur_ff.pol_clk;
210 ff.pol_ce = cur_ff.pol_ce;
211 ff.pol_aload = cur_ff.pol_aload;
212 ff.pol_arst = cur_ff.pol_arst;
213 ff.pol_srst = cur_ff.pol_srst;
214 ff.pol_clr = cur_ff.pol_clr;
215 ff.pol_set = cur_ff.pol_set;
216 } else {
217 if (ff.has_gclk != cur_ff.has_gclk)
218 return false;
219 if (ff.has_clk != cur_ff.has_clk)
220 return false;
221 if (ff.has_ce != cur_ff.has_ce)
222 return false;
223 if (ff.has_aload != cur_ff.has_aload)
224 return false;
225 if (ff.has_srst != cur_ff.has_srst)
226 return false;
227 if (ff.has_arst != cur_ff.has_arst)
228 return false;
229 if (ff.has_sr != cur_ff.has_sr)
230 return false;
231 if (ff.has_clk) {
232 if (ff.sig_clk != cur_ff.sig_clk)
233 return false;
234 if (ff.pol_clk != cur_ff.pol_clk)
235 return false;
236 }
237 if (ff.has_ce) {
238 if (ff.sig_ce != cur_ff.sig_ce)
239 return false;
240 if (ff.pol_ce != cur_ff.pol_ce)
241 return false;
242 }
243 if (ff.has_aload) {
244 if (ff.sig_aload != cur_ff.sig_aload)
245 return false;
246 if (ff.pol_aload != cur_ff.pol_aload)
247 return false;
248 }
249 if (ff.has_srst) {
250 if (ff.sig_srst != cur_ff.sig_srst)
251 return false;
252 if (ff.pol_srst != cur_ff.pol_srst)
253 return false;
254 if (ff.has_ce && ff.ce_over_srst != cur_ff.ce_over_srst)
255 return false;
256 }
257 if (ff.has_arst) {
258 if (ff.sig_arst != cur_ff.sig_arst)
259 return false;
260 if (ff.pol_arst != cur_ff.pol_arst)
261 return false;
262 }
263 if (ff.has_sr) {
264 if (ff.pol_clr != cur_ff.pol_clr)
265 return false;
266 if (ff.pol_set != cur_ff.pol_set)
267 return false;
268 }
269 }
270
271 ff.width++;
272 ff.sig_d.append((ff.has_clk || ff.has_gclk) ? cur_ff.sig_d[idx] : State::Sx);
273 ff.sig_ad.append(ff.has_aload ? cur_ff.sig_ad[idx] : State::Sx);
274 ff.sig_q.append(cur_ff.sig_q[idx]);
275 ff.sig_clr.append(ff.has_sr ? cur_ff.sig_clr[idx] : State::S0);
276 ff.sig_set.append(ff.has_sr ? cur_ff.sig_set[idx] : State::S0);
277 ff.val_arst.bits.push_back(ff.has_arst ? cur_ff.val_arst[idx] : State::Sx);
278 ff.val_srst.bits.push_back(ff.has_srst ? cur_ff.val_srst[idx] : State::Sx);
279 ff.val_init.bits.push_back(cur_ff.val_init[idx]);
280 found = true;
281 }
282
283 if (found && ff.has_sr) {
284 for (auto i: const_bits) {
285 if (ff.sig_d[i] == State::S0) {
286 ff.sig_set[i] = ff.pol_set ? State::S0 : State::S1;
287 } else if (ff.sig_d[i] == State::S1) {
288 ff.sig_clr[i] = ff.pol_clr ? State::S0 : State::S1;
289 }
290 }
291 }
292
293 return found;
294 }
295
296
297 void FfMergeHelper::remove_output_ff(const pool<std::pair<Cell *, int>> &bits) {
298 for (auto &it : bits) {
299 Cell *cell = it.first;
300 int idx = it.second;
301 SigSpec q = cell->getPort(ID::Q);
302 initvals->remove_init(q[idx]);
303 dff_driver.erase((*sigmap)(q[idx]));
304 q[idx] = module->addWire(stringf("$ffmerge_disconnected$%d", autoidx++));
305 cell->setPort(ID::Q, q);
306 }
307 }
308
309 void FfMergeHelper::mark_input_ff(const pool<std::pair<Cell *, int>> &bits) {
310 for (auto &it : bits) {
311 Cell *cell = it.first;
312 int idx = it.second;
313 if (cell->hasPort(ID::D)) {
314 SigSpec d = cell->getPort(ID::D);
315 // The user count was already at least 1
316 // (for the D port). Bump it as it is now connected
317 // to the merged-to cell as well. This suffices for
318 // it to not be considered for output merging.
319 sigbit_users_count[d[idx]]++;
320 }
321 }
322 }
323
324 void FfMergeHelper::set(FfInitVals *initvals_, RTLIL::Module *module_)
325 {
326 clear();
327 initvals = initvals_;
328 sigmap = initvals->sigmap;
329 module = module_;
330
331 for (auto wire : module->wires()) {
332 if (wire->port_output)
333 for (auto bit : (*sigmap)(wire))
334 sigbit_users_count[bit]++;
335 }
336
337 for (auto cell : module->cells()) {
338 if (RTLIL::builtin_ff_cell_types().count(cell->type)) {
339 if (cell->hasPort(ID::D)) {
340 SigSpec d = (*sigmap)(cell->getPort(ID::D));
341 for (int i = 0; i < GetSize(d); i++)
342 dff_sink[d[i]].insert(std::make_pair(cell, i));
343 }
344 SigSpec q = (*sigmap)(cell->getPort(ID::Q));
345 for (int i = 0; i < GetSize(q); i++)
346 dff_driver[q[i]] = std::make_pair(cell, i);
347 }
348 for (auto &conn : cell->connections())
349 if (!cell->known() || cell->input(conn.first))
350 for (auto bit : (*sigmap)(conn.second))
351 sigbit_users_count[bit]++;
352 }
353 }
354
355 void FfMergeHelper::clear() {
356 dff_driver.clear();
357 dff_sink.clear();
358 sigbit_users_count.clear();
359 }