c43482bd242e2c127114f68627a9f9292901600a
[yosys.git] / kernel / ff.cc
1 /*
2 * yosys -- Yosys Open SYnthesis Suite
3 *
4 * Copyright (C) 2020 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/ff.h"
21
22 USING_YOSYS_NAMESPACE
23
24 FfData::FfData(FfInitVals *initvals, Cell *cell_) : FfData(cell_->module, initvals, cell_->name)
25 {
26 cell = cell_;
27 sig_q = cell->getPort(ID::Q);
28 width = GetSize(sig_q);
29 attributes = cell->attributes;
30
31 if (initvals)
32 val_init = (*initvals)(sig_q);
33
34 std::string type_str = cell->type.str();
35
36 if (cell->type.in(ID($ff), ID($dff), ID($dffe), ID($dffsr), ID($dffsre), ID($adff), ID($adffe), ID($aldff), ID($aldffe), ID($sdff), ID($sdffe), ID($sdffce), ID($dlatch), ID($adlatch), ID($dlatchsr), ID($sr))) {
37 if (cell->type == ID($ff)) {
38 has_gclk = true;
39 sig_d = cell->getPort(ID::D);
40 } else if (cell->type == ID($sr)) {
41 // No data input at all.
42 } else if (cell->type.in(ID($dlatch), ID($adlatch), ID($dlatchsr))) {
43 has_aload = true;
44 sig_aload = cell->getPort(ID::EN);
45 pol_aload = cell->getParam(ID::EN_POLARITY).as_bool();
46 sig_ad = cell->getPort(ID::D);
47 } else {
48 has_clk = true;
49 sig_clk = cell->getPort(ID::CLK);
50 pol_clk = cell->getParam(ID::CLK_POLARITY).as_bool();
51 sig_d = cell->getPort(ID::D);
52 }
53 if (cell->type.in(ID($dffe), ID($dffsre), ID($adffe), ID($aldffe), ID($sdffe), ID($sdffce))) {
54 has_ce = true;
55 sig_ce = cell->getPort(ID::EN);
56 pol_ce = cell->getParam(ID::EN_POLARITY).as_bool();
57 }
58 if (cell->type.in(ID($dffsr), ID($dffsre), ID($dlatchsr), ID($sr))) {
59 has_sr = true;
60 sig_clr = cell->getPort(ID::CLR);
61 sig_set = cell->getPort(ID::SET);
62 pol_clr = cell->getParam(ID::CLR_POLARITY).as_bool();
63 pol_set = cell->getParam(ID::SET_POLARITY).as_bool();
64 }
65 if (cell->type.in(ID($aldff), ID($aldffe))) {
66 has_aload = true;
67 sig_aload = cell->getPort(ID::ALOAD);
68 pol_aload = cell->getParam(ID::ALOAD_POLARITY).as_bool();
69 sig_ad = cell->getPort(ID::AD);
70 }
71 if (cell->type.in(ID($adff), ID($adffe), ID($adlatch))) {
72 has_arst = true;
73 sig_arst = cell->getPort(ID::ARST);
74 pol_arst = cell->getParam(ID::ARST_POLARITY).as_bool();
75 val_arst = cell->getParam(ID::ARST_VALUE);
76 }
77 if (cell->type.in(ID($sdff), ID($sdffe), ID($sdffce))) {
78 has_srst = true;
79 sig_srst = cell->getPort(ID::SRST);
80 pol_srst = cell->getParam(ID::SRST_POLARITY).as_bool();
81 val_srst = cell->getParam(ID::SRST_VALUE);
82 ce_over_srst = cell->type == ID($sdffce);
83 }
84 } else if (cell->type == ID($_FF_)) {
85 is_fine = true;
86 has_gclk = true;
87 sig_d = cell->getPort(ID::D);
88 } else if (type_str.substr(0, 5) == "$_SR_") {
89 is_fine = true;
90 has_sr = true;
91 pol_set = type_str[5] == 'P';
92 pol_clr = type_str[6] == 'P';
93 sig_set = cell->getPort(ID::S);
94 sig_clr = cell->getPort(ID::R);
95 } else if (type_str.substr(0, 6) == "$_DFF_" && type_str.size() == 8) {
96 is_fine = true;
97 sig_d = cell->getPort(ID::D);
98 has_clk = true;
99 pol_clk = type_str[6] == 'P';
100 sig_clk = cell->getPort(ID::C);
101 } else if (type_str.substr(0, 7) == "$_DFFE_" && type_str.size() == 10) {
102 is_fine = true;
103 sig_d = cell->getPort(ID::D);
104 has_clk = true;
105 pol_clk = type_str[7] == 'P';
106 sig_clk = cell->getPort(ID::C);
107 has_ce = true;
108 pol_ce = type_str[8] == 'P';
109 sig_ce = cell->getPort(ID::E);
110 } else if (type_str.substr(0, 6) == "$_DFF_" && type_str.size() == 10) {
111 is_fine = true;
112 sig_d = cell->getPort(ID::D);
113 has_clk = true;
114 pol_clk = type_str[6] == 'P';
115 sig_clk = cell->getPort(ID::C);
116 has_arst = true;
117 pol_arst = type_str[7] == 'P';
118 sig_arst = cell->getPort(ID::R);
119 val_arst = type_str[8] == '1' ? State::S1 : State::S0;
120 } else if (type_str.substr(0, 7) == "$_DFFE_" && type_str.size() == 12) {
121 is_fine = true;
122 sig_d = cell->getPort(ID::D);
123 has_clk = true;
124 pol_clk = type_str[7] == 'P';
125 sig_clk = cell->getPort(ID::C);
126 has_arst = true;
127 pol_arst = type_str[8] == 'P';
128 sig_arst = cell->getPort(ID::R);
129 val_arst = type_str[9] == '1' ? State::S1 : State::S0;
130 has_ce = true;
131 pol_ce = type_str[10] == 'P';
132 sig_ce = cell->getPort(ID::E);
133 } else if (type_str.substr(0, 8) == "$_ALDFF_" && type_str.size() == 11) {
134 is_fine = true;
135 sig_d = cell->getPort(ID::D);
136 has_clk = true;
137 pol_clk = type_str[8] == 'P';
138 sig_clk = cell->getPort(ID::C);
139 has_aload = true;
140 pol_aload = type_str[9] == 'P';
141 sig_aload = cell->getPort(ID::L);
142 sig_ad = cell->getPort(ID::AD);
143 } else if (type_str.substr(0, 9) == "$_ALDFFE_" && type_str.size() == 13) {
144 is_fine = true;
145 sig_d = cell->getPort(ID::D);
146 has_clk = true;
147 pol_clk = type_str[9] == 'P';
148 sig_clk = cell->getPort(ID::C);
149 has_aload = true;
150 pol_aload = type_str[10] == 'P';
151 sig_aload = cell->getPort(ID::L);
152 sig_ad = cell->getPort(ID::AD);
153 has_ce = true;
154 pol_ce = type_str[11] == 'P';
155 sig_ce = cell->getPort(ID::E);
156 } else if (type_str.substr(0, 8) == "$_DFFSR_" && type_str.size() == 12) {
157 is_fine = true;
158 sig_d = cell->getPort(ID::D);
159 has_clk = true;
160 pol_clk = type_str[8] == 'P';
161 sig_clk = cell->getPort(ID::C);
162 has_sr = true;
163 pol_set = type_str[9] == 'P';
164 pol_clr = type_str[10] == 'P';
165 sig_set = cell->getPort(ID::S);
166 sig_clr = cell->getPort(ID::R);
167 } else if (type_str.substr(0, 9) == "$_DFFSRE_" && type_str.size() == 14) {
168 is_fine = true;
169 sig_d = cell->getPort(ID::D);
170 has_clk = true;
171 pol_clk = type_str[9] == 'P';
172 sig_clk = cell->getPort(ID::C);
173 has_sr = true;
174 pol_set = type_str[10] == 'P';
175 pol_clr = type_str[11] == 'P';
176 sig_set = cell->getPort(ID::S);
177 sig_clr = cell->getPort(ID::R);
178 has_ce = true;
179 pol_ce = type_str[12] == 'P';
180 sig_ce = cell->getPort(ID::E);
181 } else if (type_str.substr(0, 7) == "$_SDFF_" && type_str.size() == 11) {
182 is_fine = true;
183 sig_d = cell->getPort(ID::D);
184 has_clk = true;
185 pol_clk = type_str[7] == 'P';
186 sig_clk = cell->getPort(ID::C);
187 has_srst = true;
188 pol_srst = type_str[8] == 'P';
189 sig_srst = cell->getPort(ID::R);
190 val_srst = type_str[9] == '1' ? State::S1 : State::S0;
191 } else if (type_str.substr(0, 8) == "$_SDFFE_" && type_str.size() == 13) {
192 is_fine = true;
193 sig_d = cell->getPort(ID::D);
194 has_clk = true;
195 pol_clk = type_str[8] == 'P';
196 sig_clk = cell->getPort(ID::C);
197 has_srst = true;
198 pol_srst = type_str[9] == 'P';
199 sig_srst = cell->getPort(ID::R);
200 val_srst = type_str[10] == '1' ? State::S1 : State::S0;
201 has_ce = true;
202 pol_ce = type_str[11] == 'P';
203 sig_ce = cell->getPort(ID::E);
204 } else if (type_str.substr(0, 9) == "$_SDFFCE_" && type_str.size() == 14) {
205 is_fine = true;
206 sig_d = cell->getPort(ID::D);
207 has_clk = true;
208 pol_clk = type_str[9] == 'P';
209 sig_clk = cell->getPort(ID::C);
210 has_srst = true;
211 pol_srst = type_str[10] == 'P';
212 sig_srst = cell->getPort(ID::R);
213 val_srst = type_str[11] == '1' ? State::S1 : State::S0;
214 has_ce = true;
215 pol_ce = type_str[12] == 'P';
216 sig_ce = cell->getPort(ID::E);
217 ce_over_srst = true;
218 } else if (type_str.substr(0, 9) == "$_DLATCH_" && type_str.size() == 11) {
219 is_fine = true;
220 has_aload = true;
221 sig_ad = cell->getPort(ID::D);
222 has_aload = true;
223 pol_aload = type_str[9] == 'P';
224 sig_aload = cell->getPort(ID::E);
225 } else if (type_str.substr(0, 9) == "$_DLATCH_" && type_str.size() == 13) {
226 is_fine = true;
227 has_aload = true;
228 sig_ad = cell->getPort(ID::D);
229 has_aload = true;
230 pol_aload = type_str[9] == 'P';
231 sig_aload = cell->getPort(ID::E);
232 has_arst = true;
233 pol_arst = type_str[10] == 'P';
234 sig_arst = cell->getPort(ID::R);
235 val_arst = type_str[11] == '1' ? State::S1 : State::S0;
236 } else if (type_str.substr(0, 11) == "$_DLATCHSR_" && type_str.size() == 15) {
237 is_fine = true;
238 has_aload = true;
239 sig_ad = cell->getPort(ID::D);
240 has_aload = true;
241 pol_aload = type_str[11] == 'P';
242 sig_aload = cell->getPort(ID::E);
243 has_sr = true;
244 pol_set = type_str[12] == 'P';
245 pol_clr = type_str[13] == 'P';
246 sig_set = cell->getPort(ID::S);
247 sig_clr = cell->getPort(ID::R);
248 } else {
249 log_assert(0);
250 }
251 if (has_aload && !has_clk && !has_sr && !has_arst && sig_ad.is_fully_const()) {
252 // Plain D latches with const D treated specially.
253 has_aload = false;
254 has_arst = true;
255 sig_arst = sig_aload;
256 pol_arst = pol_aload;
257 val_arst = sig_ad.as_const();
258 }
259 }
260
261 FfData FfData::slice(const std::vector<int> &bits) {
262 FfData res(module, initvals, NEW_ID);
263 res.sig_clk = sig_clk;
264 res.sig_ce = sig_ce;
265 res.sig_aload = sig_aload;
266 res.sig_arst = sig_arst;
267 res.sig_srst = sig_srst;
268 res.has_clk = has_clk;
269 res.has_gclk = has_gclk;
270 res.has_ce = has_ce;
271 res.has_aload = has_aload;
272 res.has_arst = has_arst;
273 res.has_srst = has_srst;
274 res.has_sr = has_sr;
275 res.ce_over_srst = ce_over_srst;
276 res.is_fine = is_fine;
277 res.pol_clk = pol_clk;
278 res.pol_ce = pol_ce;
279 res.pol_aload = pol_aload;
280 res.pol_arst = pol_arst;
281 res.pol_srst = pol_srst;
282 res.pol_clr = pol_clr;
283 res.pol_set = pol_set;
284 res.attributes = attributes;
285 for (int i : bits) {
286 res.sig_q.append(sig_q[i]);
287 if (has_clk || has_gclk)
288 res.sig_d.append(sig_d[i]);
289 if (has_aload)
290 res.sig_ad.append(sig_ad[i]);
291 if (has_sr) {
292 res.sig_clr.append(sig_clr[i]);
293 res.sig_set.append(sig_set[i]);
294 }
295 if (has_arst)
296 res.val_arst.bits.push_back(val_arst[i]);
297 if (has_srst)
298 res.val_srst.bits.push_back(val_srst[i]);
299 if (initvals)
300 res.val_init.bits.push_back(val_init[i]);
301 }
302 res.width = GetSize(res.sig_q);
303 return res;
304 }
305
306 void FfData::add_dummy_ce() {
307 if (has_ce)
308 return;
309 has_ce = true;
310 pol_ce = true;
311 sig_ce = State::S1;
312 ce_over_srst = false;
313 }
314
315 void FfData::add_dummy_srst() {
316 if (has_srst)
317 return;
318 has_srst = true;
319 pol_srst = true;
320 sig_srst = State::S0;
321 val_srst = Const(State::Sx, width);
322 ce_over_srst = false;
323 }
324
325 void FfData::add_dummy_arst() {
326 if (has_arst)
327 return;
328 has_arst = true;
329 pol_arst = true;
330 sig_arst = State::S0;
331 val_arst = Const(State::Sx, width);
332 }
333
334 void FfData::add_dummy_aload() {
335 if (has_aload)
336 return;
337 has_aload = true;
338 pol_aload = true;
339 sig_aload = State::S0;
340 sig_ad = Const(State::Sx, width);
341 }
342
343 void FfData::add_dummy_sr() {
344 if (has_sr)
345 return;
346 has_sr = true;
347 pol_clr = true;
348 pol_set = true;
349 sig_clr = Const(State::S0, width);
350 sig_set = Const(State::S0, width);
351 }
352
353 void FfData::add_dummy_clk() {
354 if (has_clk)
355 return;
356 has_clk = true;
357 pol_clk = true;
358 sig_clk = State::S0;
359 sig_d = Const(State::Sx, width);
360 }
361
362 void FfData::arst_to_aload() {
363 log_assert(has_arst);
364 log_assert(!has_aload);
365 pol_aload = pol_arst;
366 sig_aload = sig_arst;
367 sig_ad = val_arst;
368 has_aload = true;
369 has_arst = false;
370 }
371
372 void FfData::arst_to_sr() {
373 log_assert(has_arst);
374 log_assert(!has_sr);
375 pol_clr = pol_arst;
376 pol_set = pol_arst;
377 sig_clr = Const(pol_arst ? State::S0 : State::S1, width);
378 sig_set = Const(pol_arst ? State::S0 : State::S1, width);
379 has_sr = true;
380 has_arst = false;
381 for (int i = 0; i < width; i++) {
382 if (val_arst[i] == State::S1)
383 sig_set[i] = sig_arst;
384 else
385 sig_clr[i] = sig_arst;
386 }
387 }
388
389 void FfData::aload_to_sr() {
390 log_assert(has_aload);
391 log_assert(!has_sr);
392 has_sr = true;
393 has_aload = false;
394 if (!is_fine) {
395 pol_clr = false;
396 pol_set = true;
397 if (pol_aload) {
398 sig_clr = module->Mux(NEW_ID, Const(State::S1, width), sig_ad, sig_aload);
399 sig_set = module->Mux(NEW_ID, Const(State::S0, width), sig_ad, sig_aload);
400 } else {
401 sig_clr = module->Mux(NEW_ID, sig_ad, Const(State::S1, width), sig_aload);
402 sig_set = module->Mux(NEW_ID, sig_ad, Const(State::S0, width), sig_aload);
403 }
404 } else {
405 pol_clr = pol_aload;
406 pol_set = pol_aload;
407 if (pol_aload) {
408 sig_clr = module->AndnotGate(NEW_ID, sig_aload, sig_ad);
409 sig_set = module->AndGate(NEW_ID, sig_aload, sig_ad);
410 } else {
411 sig_clr = module->OrGate(NEW_ID, sig_aload, sig_ad);
412 sig_set = module->OrnotGate(NEW_ID, sig_aload, sig_ad);
413 }
414 }
415 }
416
417 void FfData::convert_ce_over_srst(bool val) {
418 if (!has_ce || !has_srst || ce_over_srst == val)
419 return;
420 if (val) {
421 // sdffe to sdffce
422 if (!is_fine) {
423 if (pol_ce) {
424 if (pol_srst) {
425 sig_ce = module->Or(NEW_ID, sig_ce, sig_srst);
426 } else {
427 SigSpec tmp = module->Not(NEW_ID, sig_srst);
428 sig_ce = module->Or(NEW_ID, sig_ce, tmp);
429 }
430 } else {
431 if (pol_srst) {
432 SigSpec tmp = module->Not(NEW_ID, sig_srst);
433 sig_ce = module->And(NEW_ID, sig_ce, tmp);
434 } else {
435 sig_ce = module->And(NEW_ID, sig_ce, sig_srst);
436 }
437 }
438 } else {
439 if (pol_ce) {
440 if (pol_srst) {
441 sig_ce = module->OrGate(NEW_ID, sig_ce, sig_srst);
442 } else {
443 sig_ce = module->OrnotGate(NEW_ID, sig_ce, sig_srst);
444 }
445 } else {
446 if (pol_srst) {
447 sig_ce = module->AndnotGate(NEW_ID, sig_ce, sig_srst);
448 } else {
449 sig_ce = module->AndGate(NEW_ID, sig_ce, sig_srst);
450 }
451 }
452 }
453 } else {
454 // sdffce to sdffe
455 if (!is_fine) {
456 if (pol_srst) {
457 if (pol_ce) {
458 sig_srst = cell->module->And(NEW_ID, sig_srst, sig_ce);
459 } else {
460 SigSpec tmp = module->Not(NEW_ID, sig_ce);
461 sig_srst = cell->module->And(NEW_ID, sig_srst, tmp);
462 }
463 } else {
464 if (pol_ce) {
465 SigSpec tmp = module->Not(NEW_ID, sig_ce);
466 sig_srst = cell->module->Or(NEW_ID, sig_srst, tmp);
467 } else {
468 sig_srst = cell->module->Or(NEW_ID, sig_srst, sig_ce);
469 }
470 }
471 } else {
472 if (pol_srst) {
473 if (pol_ce) {
474 sig_srst = cell->module->AndGate(NEW_ID, sig_srst, sig_ce);
475 } else {
476 sig_srst = cell->module->AndnotGate(NEW_ID, sig_srst, sig_ce);
477 }
478 } else {
479 if (pol_ce) {
480 sig_srst = cell->module->OrnotGate(NEW_ID, sig_srst, sig_ce);
481 } else {
482 sig_srst = cell->module->OrGate(NEW_ID, sig_srst, sig_ce);
483 }
484 }
485 }
486 }
487 ce_over_srst = val;
488 }
489
490 void FfData::unmap_ce() {
491 if (!has_ce)
492 return;
493 log_assert(has_clk);
494 if (has_srst && ce_over_srst)
495 unmap_srst();
496
497 if (!is_fine) {
498 if (pol_ce)
499 sig_d = module->Mux(NEW_ID, sig_q, sig_d, sig_ce);
500 else
501 sig_d = module->Mux(NEW_ID, sig_d, sig_q, sig_ce);
502 } else {
503 if (pol_ce)
504 sig_d = module->MuxGate(NEW_ID, sig_q, sig_d, sig_ce);
505 else
506 sig_d = module->MuxGate(NEW_ID, sig_d, sig_q, sig_ce);
507 }
508 has_ce = false;
509 }
510
511 void FfData::unmap_srst() {
512 if (!has_srst)
513 return;
514 if (has_ce && !ce_over_srst)
515 unmap_ce();
516
517 if (!is_fine) {
518 if (pol_srst)
519 sig_d = module->Mux(NEW_ID, sig_d, val_srst, sig_srst);
520 else
521 sig_d = module->Mux(NEW_ID, val_srst, sig_d, sig_srst);
522 } else {
523 if (pol_srst)
524 sig_d = module->MuxGate(NEW_ID, sig_d, val_srst[0], sig_srst);
525 else
526 sig_d = module->MuxGate(NEW_ID, val_srst[0], sig_d, sig_srst);
527 }
528 has_srst = false;
529 }
530
531 Cell *FfData::emit() {
532 remove();
533 if (!width)
534 return nullptr;
535 if (!has_aload && !has_clk && !has_gclk && !has_sr) {
536 if (has_arst) {
537 // Convert this case to a D latch.
538 arst_to_aload();
539 } else {
540 // No control inputs left. Turn into a const driver.
541 module->connect(sig_q, val_init);
542 return nullptr;
543 }
544 }
545 if (initvals)
546 initvals->set_init(sig_q, val_init);
547 if (!is_fine) {
548 if (has_gclk) {
549 log_assert(!has_clk);
550 log_assert(!has_ce);
551 log_assert(!has_aload);
552 log_assert(!has_arst);
553 log_assert(!has_srst);
554 log_assert(!has_sr);
555 cell = module->addFf(name, sig_d, sig_q);
556 } else if (!has_aload && !has_clk) {
557 log_assert(has_sr);
558 cell = module->addSr(name, sig_set, sig_clr, sig_q, pol_set, pol_clr);
559 } else if (!has_clk) {
560 log_assert(!has_srst);
561 if (has_sr)
562 cell = module->addDlatchsr(name, sig_aload, sig_set, sig_clr, sig_ad, sig_q, pol_aload, pol_set, pol_clr);
563 else if (has_arst)
564 cell = module->addAdlatch(name, sig_aload, sig_arst, sig_ad, sig_q, val_arst, pol_aload, pol_arst);
565 else
566 cell = module->addDlatch(name, sig_aload, sig_ad, sig_q, pol_aload);
567 } else {
568 if (has_sr) {
569 if (has_ce)
570 cell = module->addDffsre(name, sig_clk, sig_ce, sig_set, sig_clr, sig_d, sig_q, pol_clk, pol_ce, pol_set, pol_clr);
571 else
572 cell = module->addDffsr(name, sig_clk, sig_set, sig_clr, sig_d, sig_q, pol_clk, pol_set, pol_clr);
573 } else if (has_arst) {
574 if (has_ce)
575 cell = module->addAdffe(name, sig_clk, sig_ce, sig_arst, sig_d, sig_q, val_arst, pol_clk, pol_ce, pol_arst);
576 else
577 cell = module->addAdff(name, sig_clk, sig_arst, sig_d, sig_q, val_arst, pol_clk, pol_arst);
578 } else if (has_aload) {
579 if (has_ce)
580 cell = module->addAldffe(name, sig_clk, sig_ce, sig_aload, sig_d, sig_q, sig_ad, pol_clk, pol_ce, pol_aload);
581 else
582 cell = module->addAldff(name, sig_clk, sig_aload, sig_d, sig_q, sig_ad, pol_clk, pol_aload);
583 } else if (has_srst) {
584 if (has_ce)
585 if (ce_over_srst)
586 cell = module->addSdffce(name, sig_clk, sig_ce, sig_srst, sig_d, sig_q, val_srst, pol_clk, pol_ce, pol_srst);
587 else
588 cell = module->addSdffe(name, sig_clk, sig_ce, sig_srst, sig_d, sig_q, val_srst, pol_clk, pol_ce, pol_srst);
589 else
590 cell = module->addSdff(name, sig_clk, sig_srst, sig_d, sig_q, val_srst, pol_clk, pol_srst);
591 } else {
592 if (has_ce)
593 cell = module->addDffe(name, sig_clk, sig_ce, sig_d, sig_q, pol_clk, pol_ce);
594 else
595 cell = module->addDff(name, sig_clk, sig_d, sig_q, pol_clk);
596 }
597 }
598 } else {
599 if (has_gclk) {
600 log_assert(!has_clk);
601 log_assert(!has_ce);
602 log_assert(!has_aload);
603 log_assert(!has_arst);
604 log_assert(!has_srst);
605 log_assert(!has_sr);
606 cell = module->addFfGate(name, sig_d, sig_q);
607 } else if (!has_aload && !has_clk) {
608 log_assert(has_sr);
609 cell = module->addSrGate(name, sig_set, sig_clr, sig_q, pol_set, pol_clr);
610 } else if (!has_clk) {
611 log_assert(!has_srst);
612 if (has_sr)
613 cell = module->addDlatchsrGate(name, sig_aload, sig_set, sig_clr, sig_ad, sig_q, pol_aload, pol_set, pol_clr);
614 else if (has_arst)
615 cell = module->addAdlatchGate(name, sig_aload, sig_arst, sig_ad, sig_q, val_arst.as_bool(), pol_aload, pol_arst);
616 else
617 cell = module->addDlatchGate(name, sig_aload, sig_ad, sig_q, pol_aload);
618 } else {
619 if (has_sr) {
620 if (has_ce)
621 cell = module->addDffsreGate(name, sig_clk, sig_ce, sig_set, sig_clr, sig_d, sig_q, pol_clk, pol_ce, pol_set, pol_clr);
622 else
623 cell = module->addDffsrGate(name, sig_clk, sig_set, sig_clr, sig_d, sig_q, pol_clk, pol_set, pol_clr);
624 } else if (has_arst) {
625 if (has_ce)
626 cell = module->addAdffeGate(name, sig_clk, sig_ce, sig_arst, sig_d, sig_q, val_arst.as_bool(), pol_clk, pol_ce, pol_arst);
627 else
628 cell = module->addAdffGate(name, sig_clk, sig_arst, sig_d, sig_q, val_arst.as_bool(), pol_clk, pol_arst);
629 } else if (has_aload) {
630 if (has_ce)
631 cell = module->addAldffeGate(name, sig_clk, sig_ce, sig_aload, sig_d, sig_q, sig_ad, pol_clk, pol_ce, pol_aload);
632 else
633 cell = module->addAldffGate(name, sig_clk, sig_aload, sig_d, sig_q, sig_ad, pol_clk, pol_aload);
634 } else if (has_srst) {
635 if (has_ce)
636 if (ce_over_srst)
637 cell = module->addSdffceGate(name, sig_clk, sig_ce, sig_srst, sig_d, sig_q, val_srst.as_bool(), pol_clk, pol_ce, pol_srst);
638 else
639 cell = module->addSdffeGate(name, sig_clk, sig_ce, sig_srst, sig_d, sig_q, val_srst.as_bool(), pol_clk, pol_ce, pol_srst);
640 else
641 cell = module->addSdffGate(name, sig_clk, sig_srst, sig_d, sig_q, val_srst.as_bool(), pol_clk, pol_srst);
642 } else {
643 if (has_ce)
644 cell = module->addDffeGate(name, sig_clk, sig_ce, sig_d, sig_q, pol_clk, pol_ce);
645 else
646 cell = module->addDffGate(name, sig_clk, sig_d, sig_q, pol_clk);
647 }
648 }
649 }
650 cell->attributes = attributes;
651 return cell;
652 }
653
654 void FfData::remove() {
655 if (cell) {
656 remove_init();
657 module->remove(cell);
658 cell = nullptr;
659 }
660 }
661
662 namespace {
663 State invert(State s) {
664 switch (s) {
665 case State::S0: return State::S1;
666 case State::S1: return State::S0;
667 default: return s;
668 }
669 }
670 }
671
672 void FfData::flip_bits(const pool<int> &bits) {
673 if (!bits.size())
674 return;
675
676 remove_init();
677
678 Wire *new_q = module->addWire(NEW_ID, width);
679
680 for (auto bit: bits) {
681 if (has_arst)
682 val_arst[bit] = invert(val_arst[bit]);
683 if (has_srst)
684 val_srst[bit] = invert(val_srst[bit]);
685 val_init[bit] = invert(val_init[bit]);
686 }
687
688 if (has_sr && cell) {
689 log_warning("Flipping D/Q/init and inserting priority fixup to legalize %s.%s [%s].\n", log_id(module->name), log_id(cell->name), log_id(cell->type));
690 }
691
692 if (is_fine) {
693 if (has_sr) {
694 bool new_pol_clr = pol_set;
695 SigSpec new_sig_clr;
696 if (pol_set) {
697 if (pol_clr) {
698 new_sig_clr = module->AndnotGate(NEW_ID, sig_set, sig_clr);
699 } else {
700 new_sig_clr = module->AndGate(NEW_ID, sig_set, sig_clr);
701 }
702 } else {
703 if (pol_clr) {
704 new_sig_clr = module->OrGate(NEW_ID, sig_set, sig_clr);
705 } else {
706 new_sig_clr = module->OrnotGate(NEW_ID, sig_set, sig_clr);
707 }
708 }
709 pol_set = pol_clr;
710 sig_set = sig_clr;
711 pol_clr = new_pol_clr;
712 sig_clr = new_sig_clr;
713 }
714 if (has_clk || has_gclk)
715 sig_d = module->NotGate(NEW_ID, sig_d);
716 if (has_aload)
717 sig_ad = module->NotGate(NEW_ID, sig_ad);
718 module->addNotGate(NEW_ID, new_q, sig_q);
719 }
720 else
721 {
722 if (has_sr) {
723 SigSpec not_clr;
724 if (!pol_clr) {
725 not_clr = sig_clr;
726 sig_clr = module->Not(NEW_ID, sig_clr);
727 pol_clr = true;
728 } else {
729 not_clr = module->Not(NEW_ID, sig_clr);
730 }
731 if (!pol_set) {
732 sig_set = module->Not(NEW_ID, sig_set);
733 pol_set = true;
734 }
735
736 SigSpec masked_set = module->And(NEW_ID, sig_set, not_clr);
737 for (auto bit: bits) {
738 sig_set[bit] = sig_clr[bit];
739 sig_clr[bit] = masked_set[bit];
740 }
741 }
742
743 Const mask = Const(State::S0, width);
744 for (auto bit: bits)
745 mask.bits[bit] = State::S1;
746
747 if (has_clk || has_gclk)
748 sig_d = module->Xor(NEW_ID, sig_d, mask);
749 if (has_aload)
750 sig_ad = module->Xor(NEW_ID, sig_ad, mask);
751 module->addXor(NEW_ID, new_q, mask, sig_q);
752 }
753
754 sig_q = new_q;
755 }