2 * yosys -- Yosys Open SYnthesis Suite
4 * Copyright (C) 2020 Marcelina Kościelnicka <mwk@0x04.net>
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.
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.
23 #include "kernel/yosys.h"
24 #include "kernel/ffinit.h"
28 // Describes a flip-flop or a latch.
30 // If has_gclk, this is a formal verification FF with implicit global clock:
31 // Q is simply previous cycle's D.
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):
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
40 // - sig_set is per-bit async set, and sets the corresponding bit to 1
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
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
57 // Since the yosys FF cell library isn't fully generic, not all combinations
58 // of the features above can be supported:
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
64 // The valid feature combinations are thus:
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]
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]
82 // The sync data input, present if has_clk or has_gclk.
84 // The async data input, present if has_aload.
86 // The sync clock, present if has_clk.
88 // The clock enable, present if has_ce.
90 // The async load enable, present if has_aload.
92 // The async reset, preset if has_arst.
94 // The sync reset, preset if has_srst.
96 // The async clear (per-lane), present if has_sr.
98 // The async set (per-lane), present if has_sr.
100 // True if this is a clocked (edge-sensitive) flip-flop.
102 // True if this is a $ff, exclusive with every other has_*.
104 // True if this FF has a clock enable. Depends on has_clk.
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.
109 // True if this FF has sync set/reset. Depends on has_clk, exclusive
110 // with has_arst, has_sr, has_aload.
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.
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
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.
123 // True if this FF is a fine cell, false if it is a coarse cell.
124 // If true, width must be 1.
126 // Polarities, corresponding to sig_*. True means active-high, false
135 // The value loaded by sig_arst.
137 // The value loaded by sig_srst.
139 // The initial value at power-up.
141 // The FF data width in bits.
143 dict
<IdString
, Const
> attributes
;
145 FfData(FfInitVals
*initvals
= nullptr, Cell
*cell
= nullptr) : initvals(initvals
) {
154 ce_over_srst
= false;
167 sig_q
= cell
->getPort(ID::Q
);
168 width
= GetSize(sig_q
);
169 attributes
= cell
->attributes
;
172 val_init
= (*initvals
)(sig_q
);
174 std::string type_str
= cell
->type
.str();
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
)) {
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
))) {
184 sig_aload
= cell
->getPort(ID::EN
);
185 pol_aload
= cell
->getParam(ID::EN_POLARITY
).as_bool();
186 sig_ad
= cell
->getPort(ID::D
);
189 sig_clk
= cell
->getPort(ID::CLK
);
190 pol_clk
= cell
->getParam(ID::CLK_POLARITY
).as_bool();
191 sig_d
= cell
->getPort(ID::D
);
193 if (cell
->type
.in(ID($dffe
), ID($dffsre
), ID($adffe
), ID($sdffe
), ID($sdffce
))) {
195 sig_ce
= cell
->getPort(ID::EN
);
196 pol_ce
= cell
->getParam(ID::EN_POLARITY
).as_bool();
198 if (cell
->type
.in(ID($dffsr
), ID($dffsre
), ID($dlatchsr
), ID($sr
))) {
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();
205 if (cell
->type
.in(ID($adff
), ID($adffe
), ID($adlatch
))) {
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
);
211 if (cell
->type
.in(ID($sdff
), ID($sdffe
), ID($sdffce
))) {
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
);
218 } else if (cell
->type
== ID($_FF_
)) {
221 sig_d
= cell
->getPort(ID::D
);
222 } else if (type_str
.substr(0, 5) == "$_SR_") {
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) {
231 sig_d
= cell
->getPort(ID::D
);
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) {
237 sig_d
= cell
->getPort(ID::D
);
239 pol_clk
= type_str
[7] == 'P';
240 sig_clk
= cell
->getPort(ID::C
);
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) {
246 sig_d
= cell
->getPort(ID::D
);
248 pol_clk
= type_str
[6] == 'P';
249 sig_clk
= cell
->getPort(ID::C
);
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) {
256 sig_d
= cell
->getPort(ID::D
);
258 pol_clk
= type_str
[7] == 'P';
259 sig_clk
= cell
->getPort(ID::C
);
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
;
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) {
269 sig_d
= cell
->getPort(ID::D
);
271 pol_clk
= type_str
[8] == 'P';
272 sig_clk
= cell
->getPort(ID::C
);
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) {
280 sig_d
= cell
->getPort(ID::D
);
282 pol_clk
= type_str
[9] == 'P';
283 sig_clk
= cell
->getPort(ID::C
);
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
);
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) {
294 sig_d
= cell
->getPort(ID::D
);
296 pol_clk
= type_str
[7] == 'P';
297 sig_clk
= cell
->getPort(ID::C
);
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) {
304 sig_d
= cell
->getPort(ID::D
);
306 pol_clk
= type_str
[8] == 'P';
307 sig_clk
= cell
->getPort(ID::C
);
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
;
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) {
317 sig_d
= cell
->getPort(ID::D
);
319 pol_clk
= type_str
[9] == 'P';
320 sig_clk
= cell
->getPort(ID::C
);
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
;
326 pol_ce
= type_str
[12] == 'P';
327 sig_ce
= cell
->getPort(ID::E
);
329 } else if (type_str
.substr(0, 9) == "$_DLATCH_" && type_str
.size() == 11) {
332 sig_ad
= cell
->getPort(ID::D
);
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) {
339 sig_ad
= cell
->getPort(ID::D
);
341 pol_aload
= type_str
[9] == 'P';
342 sig_aload
= cell
->getPort(ID::E
);
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) {
350 sig_ad
= cell
->getPort(ID::D
);
352 pol_aload
= type_str
[11] == 'P';
353 sig_aload
= cell
->getPort(ID::E
);
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
);
362 if (has_aload
&& !has_clk
&& !has_sr
&& !has_arst
&& sig_ad
.is_fully_const()) {
363 // Plain D latches with const D treated specially.
366 sig_arst
= sig_aload
;
367 pol_arst
= pol_aload
;
368 val_arst
= sig_ad
.as_const();
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
;
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
;
383 res
.has_aload
= has_aload
;
384 res
.has_arst
= has_arst
;
385 res
.has_srst
= has_srst
;
387 res
.ce_over_srst
= ce_over_srst
;
388 res
.is_fine
= is_fine
;
389 res
.pol_clk
= pol_clk
;
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
;
398 res
.sig_q
.append(sig_q
[i
]);
399 if (has_clk
|| has_gclk
)
400 res
.sig_d
.append(sig_d
[i
]);
402 res
.sig_ad
.append(sig_ad
[i
]);
404 res
.sig_clr
.append(sig_clr
[i
]);
405 res
.sig_set
.append(sig_set
[i
]);
408 res
.val_arst
.bits
.push_back(val_arst
[i
]);
410 res
.val_srst
.bits
.push_back(val_srst
[i
]);
412 res
.val_init
.bits
.push_back(val_init
[i
]);
414 res
.width
= GetSize(res
.sig_q
);
418 void unmap_ce(Module
*module
) {
422 if (has_srst
&& ce_over_srst
)
427 sig_d
= module
->Mux(NEW_ID
, sig_q
, sig_d
, sig_ce
);
429 sig_d
= module
->Mux(NEW_ID
, sig_d
, sig_q
, sig_ce
);
432 sig_d
= module
->MuxGate(NEW_ID
, sig_q
, sig_d
, sig_ce
);
434 sig_d
= module
->MuxGate(NEW_ID
, sig_d
, sig_q
, sig_ce
);
439 void unmap_srst(Module
*module
) {
442 if (has_ce
&& !ce_over_srst
)
447 sig_d
= module
->Mux(NEW_ID
, sig_d
, val_srst
, sig_srst
);
449 sig_d
= module
->Mux(NEW_ID
, val_srst
, sig_d
, sig_srst
);
452 sig_d
= module
->MuxGate(NEW_ID
, sig_d
, val_srst
[0], sig_srst
);
454 sig_d
= module
->MuxGate(NEW_ID
, val_srst
[0], sig_d
, sig_srst
);
459 void unmap_ce_srst(Module
*module
) {
464 Cell
*emit(Module
*module
, IdString name
) {
467 if (!has_aload
&& !has_clk
&& !has_gclk
&& !has_sr
) {
469 // Convert this case to a D latch.
473 sig_aload
= sig_arst
;
474 pol_aload
= pol_arst
;
476 // No control inputs left. Turn into a const driver.
478 initvals
->remove_init(sig_q
);
479 module
->connect(sig_q
, val_init
);
484 initvals
->set_init(sig_q
, val_init
);
488 log_assert(!has_clk
);
490 log_assert(!has_aload
);
491 log_assert(!has_arst
);
492 log_assert(!has_srst
);
494 cell
= module
->addFf(name
, sig_d
, sig_q
);
495 } else if (!has_aload
&& !has_clk
) {
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
);
501 cell
= module
->addDlatchsr(name
, sig_aload
, sig_set
, sig_clr
, sig_ad
, sig_q
, pol_aload
, pol_set
, pol_clr
);
503 cell
= module
->addAdlatch(name
, sig_aload
, sig_arst
, sig_ad
, sig_q
, val_arst
, pol_aload
, pol_arst
);
505 cell
= module
->addDlatch(name
, sig_aload
, sig_ad
, sig_q
, pol_aload
);
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
);
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
) {
514 cell
= module
->addAdffe(name
, sig_clk
, sig_ce
, sig_arst
, sig_d
, sig_q
, val_arst
, pol_clk
, pol_ce
, pol_arst
);
516 cell
= module
->addAdff(name
, sig_clk
, sig_arst
, sig_d
, sig_q
, val_arst
, pol_clk
, pol_arst
);
517 } else if (has_srst
) {
520 cell
= module
->addSdffce(name
, sig_clk
, sig_ce
, sig_srst
, sig_d
, sig_q
, val_srst
, pol_clk
, pol_ce
, pol_srst
);
522 cell
= module
->addSdffe(name
, sig_clk
, sig_ce
, sig_srst
, sig_d
, sig_q
, val_srst
, pol_clk
, pol_ce
, pol_srst
);
524 cell
= module
->addSdff(name
, sig_clk
, sig_srst
, sig_d
, sig_q
, val_srst
, pol_clk
, pol_srst
);
527 cell
= module
->addDffe(name
, sig_clk
, sig_ce
, sig_d
, sig_q
, pol_clk
, pol_ce
);
529 cell
= module
->addDff(name
, sig_clk
, sig_d
, sig_q
, pol_clk
);
534 log_assert(!has_clk
);
536 log_assert(!has_aload
);
537 log_assert(!has_arst
);
538 log_assert(!has_srst
);
540 cell
= module
->addFfGate(name
, sig_d
, sig_q
);
541 } else if (!has_aload
&& !has_clk
) {
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
);
547 cell
= module
->addDlatchsrGate(name
, sig_aload
, sig_set
, sig_clr
, sig_ad
, sig_q
, pol_aload
, pol_set
, pol_clr
);
549 cell
= module
->addAdlatchGate(name
, sig_aload
, sig_arst
, sig_ad
, sig_q
, val_arst
.as_bool(), pol_aload
, pol_arst
);
551 cell
= module
->addDlatchGate(name
, sig_aload
, sig_ad
, sig_q
, pol_aload
);
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
);
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
) {
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
);
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
) {
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
);
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
);
570 cell
= module
->addSdffGate(name
, sig_clk
, sig_srst
, sig_d
, sig_q
, val_srst
.as_bool(), pol_clk
, pol_srst
);
573 cell
= module
->addDffeGate(name
, sig_clk
, sig_ce
, sig_d
, sig_q
, pol_clk
, pol_ce
);
575 cell
= module
->addDffGate(name
, sig_clk
, sig_d
, sig_q
, pol_clk
);
579 cell
->attributes
= attributes
;