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 
FfData(FfInitVals * initvals,Cell * cell_)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 
slice(const std::vector<int> & bits)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 
add_dummy_ce()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 
add_dummy_srst()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 
add_dummy_arst()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 
add_dummy_aload()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 
add_dummy_sr()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 
add_dummy_clk()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 
arst_to_aload()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 
arst_to_sr()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 
aload_to_sr()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 
convert_ce_over_srst(bool val)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 
unmap_ce()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 
unmap_srst()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 
emit()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 
remove()654 void FfData::remove() {
655 	if (cell) {
656 		remove_init();
657 		module->remove(cell);
658 		cell = nullptr;
659 	}
660 }
661 
662 namespace {
invert(State s)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 
flip_bits(const pool<int> & bits)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 }
756