kernel/ff: Refactor FfData to enable FFs with async load.
[yosys.git] / kernel / ff.h
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 #ifndef FF_H
21 #define FF_H
22
23 #include "kernel/yosys.h"
24 #include "kernel/ffinit.h"
25
26 YOSYS_NAMESPACE_BEGIN
27
28 // Describes a flip-flop or a latch.
29 //
30 // If has_gclk, this is a formal verification FF with implicit global clock:
31 // Q is simply previous cycle's D.
32 //
33 // Otherwise, the FF/latch can have any number of features selected by has_*
34 // attributes that determine Q's value (in order of decreasing priority):
35 //
36 // - on start, register is initialized to val_init
37 // - if has_sr is present:
38 // - sig_clr is per-bit async clear, and sets the corresponding bit to 0
39 // if active
40 // - sig_set is per-bit async set, and sets the corresponding bit to 1
41 // if active
42 // - if has_arst is present:
43 // - sig_arst is whole-reg async reset, and sets the whole register to val_arst
44 // - if has_aload is present:
45 // - sig_aload is whole-reg async load (aka latch gate enable), and sets the whole
46 // register to sig_ad
47 // - if has_clk is present, and we're currently on a clock edge:
48 // - if has_ce is present and ce_over_srst is true:
49 // - ignore clock edge (don't change value) unless sig_ce is active
50 // - if has_srst is present:
51 // - sig_srst is whole-reg sync reset and sets the register to val_srst
52 // - if has_ce is present and ce_over_srst is false:
53 // - ignore clock edge (don't change value) unless sig_ce is active
54 // - set whole reg to sig_d
55 // - if nothing of the above applies, the reg value remains unchanged
56 //
57 // Since the yosys FF cell library isn't fully generic, not all combinations
58 // of the features above can be supported:
59 //
60 // - only one of has_srst, has_arst, has_sr can be used
61 // - if has_clk is used together with has_aload, then has_srst, has_arst,
62 // has_sr cannot be used
63 //
64 // The valid feature combinations are thus:
65 //
66 // - has_clk + optional has_ce [dff/dffe]
67 // - has_clk + optional has_ce + has_arst [adff/adffe]
68 // - has_clk + optional has_ce + has_aload [aldff/aldffe]
69 // - has_clk + optional has_ce + has_sr [dffsr/dffsre]
70 // - has_clk + optional has_ce + has_srst [sdff/sdffe/sdffce]
71 // - has_aload [dlatch]
72 // - has_aload + has_arst [adlatch]
73 // - has_aload + has_sr [dlatchsr]
74 // - has_sr [sr]
75 // - has_arst [does not correspond to a native cell, represented as dlatch with const D input]
76 // - empty set [not a cell — will be emitted as a simple direct connection]
77
78 struct FfData {
79 FfInitVals *initvals;
80 // The FF output.
81 SigSpec sig_q;
82 // The sync data input, present if has_clk or has_gclk.
83 SigSpec sig_d;
84 // The async data input, present if has_aload.
85 SigSpec sig_ad;
86 // The sync clock, present if has_clk.
87 SigSpec sig_clk;
88 // The clock enable, present if has_ce.
89 SigSpec sig_ce;
90 // The async load enable, present if has_aload.
91 SigSpec sig_aload;
92 // The async reset, preset if has_arst.
93 SigSpec sig_arst;
94 // The sync reset, preset if has_srst.
95 SigSpec sig_srst;
96 // The async clear (per-lane), present if has_sr.
97 SigSpec sig_clr;
98 // The async set (per-lane), present if has_sr.
99 SigSpec sig_set;
100 // True if this is a clocked (edge-sensitive) flip-flop.
101 bool has_clk;
102 // True if this is a $ff, exclusive with every other has_*.
103 bool has_gclk;
104 // True if this FF has a clock enable. Depends on has_clk.
105 bool has_ce;
106 // True if this FF has async load function — this includes D latches.
107 // If this and has_clk are both set, has_arst and has_sr cannot be set.
108 bool has_aload;
109 // True if this FF has sync set/reset. Depends on has_clk, exclusive
110 // with has_arst, has_sr, has_aload.
111 bool has_srst;
112 // True if this FF has async set/reset. Exclusive with has_srst,
113 // has_sr. If this and has_clk are both set, has_aload cannot be set.
114 bool has_arst;
115 // True if this FF has per-bit async set + clear. Exclusive with
116 // has_srst, has_arst. If this and has_clk are both set, has_aload
117 // cannot be set.
118 bool has_sr;
119 // If has_ce and has_srst are both set, determines their relative
120 // priorities: if true, inactive ce disables srst; if false, srst
121 // operates independent of ce.
122 bool ce_over_srst;
123 // True if this FF is a fine cell, false if it is a coarse cell.
124 // If true, width must be 1.
125 bool is_fine;
126 // Polarities, corresponding to sig_*. True means active-high, false
127 // means active-low.
128 bool pol_clk;
129 bool pol_ce;
130 bool pol_aload;
131 bool pol_arst;
132 bool pol_srst;
133 bool pol_clr;
134 bool pol_set;
135 // The value loaded by sig_arst.
136 Const val_arst;
137 // The value loaded by sig_srst.
138 Const val_srst;
139 // The initial value at power-up.
140 Const val_init;
141 // The FF data width in bits.
142 int width;
143 dict<IdString, Const> attributes;
144
145 FfData(FfInitVals *initvals = nullptr, Cell *cell = nullptr) : initvals(initvals) {
146 width = 0;
147 has_clk = false;
148 has_gclk = false;
149 has_ce = false;
150 has_aload = false;
151 has_srst = false;
152 has_arst = false;
153 has_sr = false;
154 ce_over_srst = false;
155 is_fine = false;
156 pol_clk = false;
157 pol_aload = false;
158 pol_ce = false;
159 pol_arst = false;
160 pol_srst = false;
161 pol_clr = false;
162 pol_set = false;
163
164 if (!cell)
165 return;
166
167 sig_q = cell->getPort(ID::Q);
168 width = GetSize(sig_q);
169 attributes = cell->attributes;
170
171 if (initvals)
172 val_init = (*initvals)(sig_q);
173
174 std::string type_str = cell->type.str();
175
176 if (cell->type.in(ID($ff), ID($dff), ID($dffe), ID($dffsr), ID($dffsre), ID($adff), ID($adffe), ID($sdff), ID($sdffe), ID($sdffce), ID($dlatch), ID($adlatch), ID($dlatchsr), ID($sr))) {
177 if (cell->type == ID($ff)) {
178 has_gclk = true;
179 sig_d = cell->getPort(ID::D);
180 } else if (cell->type == ID($sr)) {
181 // No data input at all.
182 } else if (cell->type.in(ID($dlatch), ID($adlatch), ID($dlatchsr))) {
183 has_aload = true;
184 sig_aload = cell->getPort(ID::EN);
185 pol_aload = cell->getParam(ID::EN_POLARITY).as_bool();
186 sig_ad = cell->getPort(ID::D);
187 } else {
188 has_clk = true;
189 sig_clk = cell->getPort(ID::CLK);
190 pol_clk = cell->getParam(ID::CLK_POLARITY).as_bool();
191 sig_d = cell->getPort(ID::D);
192 }
193 if (cell->type.in(ID($dffe), ID($dffsre), ID($adffe), ID($sdffe), ID($sdffce))) {
194 has_ce = true;
195 sig_ce = cell->getPort(ID::EN);
196 pol_ce = cell->getParam(ID::EN_POLARITY).as_bool();
197 }
198 if (cell->type.in(ID($dffsr), ID($dffsre), ID($dlatchsr), ID($sr))) {
199 has_sr = true;
200 sig_clr = cell->getPort(ID::CLR);
201 sig_set = cell->getPort(ID::SET);
202 pol_clr = cell->getParam(ID::CLR_POLARITY).as_bool();
203 pol_set = cell->getParam(ID::SET_POLARITY).as_bool();
204 }
205 if (cell->type.in(ID($adff), ID($adffe), ID($adlatch))) {
206 has_arst = true;
207 sig_arst = cell->getPort(ID::ARST);
208 pol_arst = cell->getParam(ID::ARST_POLARITY).as_bool();
209 val_arst = cell->getParam(ID::ARST_VALUE);
210 }
211 if (cell->type.in(ID($sdff), ID($sdffe), ID($sdffce))) {
212 has_srst = true;
213 sig_srst = cell->getPort(ID::SRST);
214 pol_srst = cell->getParam(ID::SRST_POLARITY).as_bool();
215 val_srst = cell->getParam(ID::SRST_VALUE);
216 ce_over_srst = cell->type == ID($sdffce);
217 }
218 } else if (cell->type == ID($_FF_)) {
219 is_fine = true;
220 has_gclk = true;
221 sig_d = cell->getPort(ID::D);
222 } else if (type_str.substr(0, 5) == "$_SR_") {
223 is_fine = true;
224 has_sr = true;
225 pol_set = type_str[5] == 'P';
226 pol_clr = type_str[6] == 'P';
227 sig_set = cell->getPort(ID::S);
228 sig_clr = cell->getPort(ID::R);
229 } else if (type_str.substr(0, 6) == "$_DFF_" && type_str.size() == 8) {
230 is_fine = true;
231 sig_d = cell->getPort(ID::D);
232 has_clk = true;
233 pol_clk = type_str[6] == 'P';
234 sig_clk = cell->getPort(ID::C);
235 } else if (type_str.substr(0, 7) == "$_DFFE_" && type_str.size() == 10) {
236 is_fine = true;
237 sig_d = cell->getPort(ID::D);
238 has_clk = true;
239 pol_clk = type_str[7] == 'P';
240 sig_clk = cell->getPort(ID::C);
241 has_ce = true;
242 pol_ce = type_str[8] == 'P';
243 sig_ce = cell->getPort(ID::E);
244 } else if (type_str.substr(0, 6) == "$_DFF_" && type_str.size() == 10) {
245 is_fine = true;
246 sig_d = cell->getPort(ID::D);
247 has_clk = true;
248 pol_clk = type_str[6] == 'P';
249 sig_clk = cell->getPort(ID::C);
250 has_arst = true;
251 pol_arst = type_str[7] == 'P';
252 sig_arst = cell->getPort(ID::R);
253 val_arst = type_str[8] == '1' ? State::S1 : State::S0;
254 } else if (type_str.substr(0, 7) == "$_DFFE_" && type_str.size() == 12) {
255 is_fine = true;
256 sig_d = cell->getPort(ID::D);
257 has_clk = true;
258 pol_clk = type_str[7] == 'P';
259 sig_clk = cell->getPort(ID::C);
260 has_arst = true;
261 pol_arst = type_str[8] == 'P';
262 sig_arst = cell->getPort(ID::R);
263 val_arst = type_str[9] == '1' ? State::S1 : State::S0;
264 has_ce = true;
265 pol_ce = type_str[10] == 'P';
266 sig_ce = cell->getPort(ID::E);
267 } else if (type_str.substr(0, 8) == "$_DFFSR_" && type_str.size() == 12) {
268 is_fine = true;
269 sig_d = cell->getPort(ID::D);
270 has_clk = true;
271 pol_clk = type_str[8] == 'P';
272 sig_clk = cell->getPort(ID::C);
273 has_sr = true;
274 pol_set = type_str[9] == 'P';
275 pol_clr = type_str[10] == 'P';
276 sig_set = cell->getPort(ID::S);
277 sig_clr = cell->getPort(ID::R);
278 } else if (type_str.substr(0, 9) == "$_DFFSRE_" && type_str.size() == 14) {
279 is_fine = true;
280 sig_d = cell->getPort(ID::D);
281 has_clk = true;
282 pol_clk = type_str[9] == 'P';
283 sig_clk = cell->getPort(ID::C);
284 has_sr = true;
285 pol_set = type_str[10] == 'P';
286 pol_clr = type_str[11] == 'P';
287 sig_set = cell->getPort(ID::S);
288 sig_clr = cell->getPort(ID::R);
289 has_ce = true;
290 pol_ce = type_str[12] == 'P';
291 sig_ce = cell->getPort(ID::E);
292 } else if (type_str.substr(0, 7) == "$_SDFF_" && type_str.size() == 11) {
293 is_fine = true;
294 sig_d = cell->getPort(ID::D);
295 has_clk = true;
296 pol_clk = type_str[7] == 'P';
297 sig_clk = cell->getPort(ID::C);
298 has_srst = true;
299 pol_srst = type_str[8] == 'P';
300 sig_srst = cell->getPort(ID::R);
301 val_srst = type_str[9] == '1' ? State::S1 : State::S0;
302 } else if (type_str.substr(0, 8) == "$_SDFFE_" && type_str.size() == 13) {
303 is_fine = true;
304 sig_d = cell->getPort(ID::D);
305 has_clk = true;
306 pol_clk = type_str[8] == 'P';
307 sig_clk = cell->getPort(ID::C);
308 has_srst = true;
309 pol_srst = type_str[9] == 'P';
310 sig_srst = cell->getPort(ID::R);
311 val_srst = type_str[10] == '1' ? State::S1 : State::S0;
312 has_ce = true;
313 pol_ce = type_str[11] == 'P';
314 sig_ce = cell->getPort(ID::E);
315 } else if (type_str.substr(0, 9) == "$_SDFFCE_" && type_str.size() == 14) {
316 is_fine = true;
317 sig_d = cell->getPort(ID::D);
318 has_clk = true;
319 pol_clk = type_str[9] == 'P';
320 sig_clk = cell->getPort(ID::C);
321 has_srst = true;
322 pol_srst = type_str[10] == 'P';
323 sig_srst = cell->getPort(ID::R);
324 val_srst = type_str[11] == '1' ? State::S1 : State::S0;
325 has_ce = true;
326 pol_ce = type_str[12] == 'P';
327 sig_ce = cell->getPort(ID::E);
328 ce_over_srst = true;
329 } else if (type_str.substr(0, 9) == "$_DLATCH_" && type_str.size() == 11) {
330 is_fine = true;
331 has_aload = true;
332 sig_ad = cell->getPort(ID::D);
333 has_aload = true;
334 pol_aload = type_str[9] == 'P';
335 sig_aload = cell->getPort(ID::E);
336 } else if (type_str.substr(0, 9) == "$_DLATCH_" && type_str.size() == 13) {
337 is_fine = true;
338 has_aload = true;
339 sig_ad = cell->getPort(ID::D);
340 has_aload = true;
341 pol_aload = type_str[9] == 'P';
342 sig_aload = cell->getPort(ID::E);
343 has_arst = true;
344 pol_arst = type_str[10] == 'P';
345 sig_arst = cell->getPort(ID::R);
346 val_arst = type_str[11] == '1' ? State::S1 : State::S0;
347 } else if (type_str.substr(0, 11) == "$_DLATCHSR_" && type_str.size() == 15) {
348 is_fine = true;
349 has_aload = true;
350 sig_ad = cell->getPort(ID::D);
351 has_aload = true;
352 pol_aload = type_str[11] == 'P';
353 sig_aload = cell->getPort(ID::E);
354 has_sr = true;
355 pol_set = type_str[12] == 'P';
356 pol_clr = type_str[13] == 'P';
357 sig_set = cell->getPort(ID::S);
358 sig_clr = cell->getPort(ID::R);
359 } else {
360 log_assert(0);
361 }
362 if (has_aload && !has_clk && !has_sr && !has_arst && sig_ad.is_fully_const()) {
363 // Plain D latches with const D treated specially.
364 has_aload = false;
365 has_arst = true;
366 sig_arst = sig_aload;
367 pol_arst = pol_aload;
368 val_arst = sig_ad.as_const();
369 }
370 }
371
372 // Returns a FF identical to this one, but only keeping bit indices from the argument.
373 FfData slice(const std::vector<int> &bits) {
374 FfData res(initvals);
375 res.sig_clk = sig_clk;
376 res.sig_ce = sig_ce;
377 res.sig_aload = sig_aload;
378 res.sig_arst = sig_arst;
379 res.sig_srst = sig_srst;
380 res.has_clk = has_clk;
381 res.has_gclk = has_gclk;
382 res.has_ce = has_ce;
383 res.has_aload = has_aload;
384 res.has_arst = has_arst;
385 res.has_srst = has_srst;
386 res.has_sr = has_sr;
387 res.ce_over_srst = ce_over_srst;
388 res.is_fine = is_fine;
389 res.pol_clk = pol_clk;
390 res.pol_ce = pol_ce;
391 res.pol_aload = pol_aload;
392 res.pol_arst = pol_arst;
393 res.pol_srst = pol_srst;
394 res.pol_clr = pol_clr;
395 res.pol_set = pol_set;
396 res.attributes = attributes;
397 for (int i : bits) {
398 res.sig_q.append(sig_q[i]);
399 if (has_clk || has_gclk)
400 res.sig_d.append(sig_d[i]);
401 if (has_aload)
402 res.sig_ad.append(sig_ad[i]);
403 if (has_sr) {
404 res.sig_clr.append(sig_clr[i]);
405 res.sig_set.append(sig_set[i]);
406 }
407 if (has_arst)
408 res.val_arst.bits.push_back(val_arst[i]);
409 if (has_srst)
410 res.val_srst.bits.push_back(val_srst[i]);
411 if (initvals)
412 res.val_init.bits.push_back(val_init[i]);
413 }
414 res.width = GetSize(res.sig_q);
415 return res;
416 }
417
418 void unmap_ce(Module *module) {
419 if (!has_ce)
420 return;
421 log_assert(has_clk);
422 if (has_srst && ce_over_srst)
423 unmap_srst(module);
424
425 if (!is_fine) {
426 if (pol_ce)
427 sig_d = module->Mux(NEW_ID, sig_q, sig_d, sig_ce);
428 else
429 sig_d = module->Mux(NEW_ID, sig_d, sig_q, sig_ce);
430 } else {
431 if (pol_ce)
432 sig_d = module->MuxGate(NEW_ID, sig_q, sig_d, sig_ce);
433 else
434 sig_d = module->MuxGate(NEW_ID, sig_d, sig_q, sig_ce);
435 }
436 has_ce = false;
437 }
438
439 void unmap_srst(Module *module) {
440 if (!has_srst)
441 return;
442 if (has_ce && !ce_over_srst)
443 unmap_ce(module);
444
445 if (!is_fine) {
446 if (pol_srst)
447 sig_d = module->Mux(NEW_ID, sig_d, val_srst, sig_srst);
448 else
449 sig_d = module->Mux(NEW_ID, val_srst, sig_d, sig_srst);
450 } else {
451 if (pol_srst)
452 sig_d = module->MuxGate(NEW_ID, sig_d, val_srst[0], sig_srst);
453 else
454 sig_d = module->MuxGate(NEW_ID, val_srst[0], sig_d, sig_srst);
455 }
456 has_srst = false;
457 }
458
459 void unmap_ce_srst(Module *module) {
460 unmap_ce(module);
461 unmap_srst(module);
462 }
463
464 Cell *emit(Module *module, IdString name) {
465 if (!width)
466 return nullptr;
467 if (!has_aload && !has_clk && !has_gclk && !has_sr) {
468 if (has_arst) {
469 // Convert this case to a D latch.
470 has_aload = true;
471 has_arst = false;
472 sig_ad = val_arst;
473 sig_aload = sig_arst;
474 pol_aload = pol_arst;
475 } else {
476 // No control inputs left. Turn into a const driver.
477 if (initvals)
478 initvals->remove_init(sig_q);
479 module->connect(sig_q, val_init);
480 return nullptr;
481 }
482 }
483 if (initvals)
484 initvals->set_init(sig_q, val_init);
485 Cell *cell;
486 if (!is_fine) {
487 if (has_gclk) {
488 log_assert(!has_clk);
489 log_assert(!has_ce);
490 log_assert(!has_aload);
491 log_assert(!has_arst);
492 log_assert(!has_srst);
493 log_assert(!has_sr);
494 cell = module->addFf(name, sig_d, sig_q);
495 } else if (!has_aload && !has_clk) {
496 log_assert(has_sr);
497 cell = module->addSr(name, sig_set, sig_clr, sig_q, pol_set, pol_clr);
498 } else if (!has_clk) {
499 log_assert(!has_srst);
500 if (has_sr)
501 cell = module->addDlatchsr(name, sig_aload, sig_set, sig_clr, sig_ad, sig_q, pol_aload, pol_set, pol_clr);
502 else if (has_arst)
503 cell = module->addAdlatch(name, sig_aload, sig_arst, sig_ad, sig_q, val_arst, pol_aload, pol_arst);
504 else
505 cell = module->addDlatch(name, sig_aload, sig_ad, sig_q, pol_aload);
506 } else {
507 if (has_sr) {
508 if (has_ce)
509 cell = module->addDffsre(name, sig_clk, sig_ce, sig_set, sig_clr, sig_d, sig_q, pol_clk, pol_ce, pol_set, pol_clr);
510 else
511 cell = module->addDffsr(name, sig_clk, sig_set, sig_clr, sig_d, sig_q, pol_clk, pol_set, pol_clr);
512 } else if (has_arst) {
513 if (has_ce)
514 cell = module->addAdffe(name, sig_clk, sig_ce, sig_arst, sig_d, sig_q, val_arst, pol_clk, pol_ce, pol_arst);
515 else
516 cell = module->addAdff(name, sig_clk, sig_arst, sig_d, sig_q, val_arst, pol_clk, pol_arst);
517 } else if (has_srst) {
518 if (has_ce)
519 if (ce_over_srst)
520 cell = module->addSdffce(name, sig_clk, sig_ce, sig_srst, sig_d, sig_q, val_srst, pol_clk, pol_ce, pol_srst);
521 else
522 cell = module->addSdffe(name, sig_clk, sig_ce, sig_srst, sig_d, sig_q, val_srst, pol_clk, pol_ce, pol_srst);
523 else
524 cell = module->addSdff(name, sig_clk, sig_srst, sig_d, sig_q, val_srst, pol_clk, pol_srst);
525 } else {
526 if (has_ce)
527 cell = module->addDffe(name, sig_clk, sig_ce, sig_d, sig_q, pol_clk, pol_ce);
528 else
529 cell = module->addDff(name, sig_clk, sig_d, sig_q, pol_clk);
530 }
531 }
532 } else {
533 if (has_gclk) {
534 log_assert(!has_clk);
535 log_assert(!has_ce);
536 log_assert(!has_aload);
537 log_assert(!has_arst);
538 log_assert(!has_srst);
539 log_assert(!has_sr);
540 cell = module->addFfGate(name, sig_d, sig_q);
541 } else if (!has_aload && !has_clk) {
542 log_assert(has_sr);
543 cell = module->addSrGate(name, sig_set, sig_clr, sig_q, pol_set, pol_clr);
544 } else if (!has_clk) {
545 log_assert(!has_srst);
546 if (has_sr)
547 cell = module->addDlatchsrGate(name, sig_aload, sig_set, sig_clr, sig_ad, sig_q, pol_aload, pol_set, pol_clr);
548 else if (has_arst)
549 cell = module->addAdlatchGate(name, sig_aload, sig_arst, sig_ad, sig_q, val_arst.as_bool(), pol_aload, pol_arst);
550 else
551 cell = module->addDlatchGate(name, sig_aload, sig_ad, sig_q, pol_aload);
552 } else {
553 if (has_sr) {
554 if (has_ce)
555 cell = module->addDffsreGate(name, sig_clk, sig_ce, sig_set, sig_clr, sig_d, sig_q, pol_clk, pol_ce, pol_set, pol_clr);
556 else
557 cell = module->addDffsrGate(name, sig_clk, sig_set, sig_clr, sig_d, sig_q, pol_clk, pol_set, pol_clr);
558 } else if (has_arst) {
559 if (has_ce)
560 cell = module->addAdffeGate(name, sig_clk, sig_ce, sig_arst, sig_d, sig_q, val_arst.as_bool(), pol_clk, pol_ce, pol_arst);
561 else
562 cell = module->addAdffGate(name, sig_clk, sig_arst, sig_d, sig_q, val_arst.as_bool(), pol_clk, pol_arst);
563 } else if (has_srst) {
564 if (has_ce)
565 if (ce_over_srst)
566 cell = module->addSdffceGate(name, sig_clk, sig_ce, sig_srst, sig_d, sig_q, val_srst.as_bool(), pol_clk, pol_ce, pol_srst);
567 else
568 cell = module->addSdffeGate(name, sig_clk, sig_ce, sig_srst, sig_d, sig_q, val_srst.as_bool(), pol_clk, pol_ce, pol_srst);
569 else
570 cell = module->addSdffGate(name, sig_clk, sig_srst, sig_d, sig_q, val_srst.as_bool(), pol_clk, pol_srst);
571 } else {
572 if (has_ce)
573 cell = module->addDffeGate(name, sig_clk, sig_ce, sig_d, sig_q, pol_clk, pol_ce);
574 else
575 cell = module->addDffGate(name, sig_clk, sig_d, sig_q, pol_clk);
576 }
577 }
578 }
579 cell->attributes = attributes;
580 return cell;
581 }
582 };
583
584 YOSYS_NAMESPACE_END
585
586 #endif