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"
58 dict
<IdString
, Const
> attributes
;
60 FfData(FfInitVals
*initvals
= nullptr, Cell
*cell
= nullptr) : initvals(initvals
) {
81 sig_q
= cell
->getPort(ID::Q
);
82 width
= GetSize(sig_q
);
83 attributes
= cell
->attributes
;
86 val_init
= (*initvals
)(sig_q
);
88 std::string type_str
= cell
->type
.str();
90 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
))) {
91 if (cell
->type
== ID($sr
)) {
94 sig_d
= cell
->getPort(ID::D
);
96 if (!cell
->type
.in(ID($ff
), ID($dlatch
), ID($adlatch
), ID($dlatchsr
), ID($sr
))) {
98 sig_clk
= cell
->getPort(ID::CLK
);
99 pol_clk
= cell
->getParam(ID::CLK_POLARITY
).as_bool();
101 if (cell
->type
.in(ID($dffe
), ID($dffsre
), ID($adffe
), ID($sdffe
), ID($sdffce
), ID($dlatch
), ID($adlatch
), ID($dlatchsr
))) {
103 sig_en
= cell
->getPort(ID::EN
);
104 pol_en
= cell
->getParam(ID::EN_POLARITY
).as_bool();
106 if (cell
->type
.in(ID($dffsr
), ID($dffsre
), ID($dlatchsr
), ID($sr
))) {
108 sig_clr
= cell
->getPort(ID::CLR
);
109 sig_set
= cell
->getPort(ID::SET
);
110 pol_clr
= cell
->getParam(ID::CLR_POLARITY
).as_bool();
111 pol_set
= cell
->getParam(ID::SET_POLARITY
).as_bool();
113 if (cell
->type
.in(ID($adff
), ID($adffe
), ID($adlatch
))) {
115 sig_arst
= cell
->getPort(ID::ARST
);
116 pol_arst
= cell
->getParam(ID::ARST_POLARITY
).as_bool();
117 val_arst
= cell
->getParam(ID::ARST_VALUE
);
119 if (cell
->type
.in(ID($sdff
), ID($sdffe
), ID($sdffce
))) {
121 sig_srst
= cell
->getPort(ID::SRST
);
122 pol_srst
= cell
->getParam(ID::SRST_POLARITY
).as_bool();
123 val_srst
= cell
->getParam(ID::SRST_VALUE
);
124 ce_over_srst
= cell
->type
== ID($sdffce
);
126 } else if (cell
->type
== ID($_FF_
)) {
128 sig_d
= cell
->getPort(ID::D
);
129 } else if (type_str
.substr(0, 5) == "$_SR_") {
133 pol_set
= type_str
[5] == 'P';
134 pol_clr
= type_str
[6] == 'P';
135 sig_set
= cell
->getPort(ID::S
);
136 sig_clr
= cell
->getPort(ID::R
);
137 } else if (type_str
.substr(0, 6) == "$_DFF_" && type_str
.size() == 8) {
139 sig_d
= cell
->getPort(ID::D
);
141 pol_clk
= type_str
[6] == 'P';
142 sig_clk
= cell
->getPort(ID::C
);
143 } else if (type_str
.substr(0, 7) == "$_DFFE_" && type_str
.size() == 10) {
145 sig_d
= cell
->getPort(ID::D
);
147 pol_clk
= type_str
[7] == 'P';
148 sig_clk
= cell
->getPort(ID::C
);
150 pol_en
= type_str
[8] == 'P';
151 sig_en
= cell
->getPort(ID::E
);
152 } else if (type_str
.substr(0, 6) == "$_DFF_" && type_str
.size() == 10) {
154 sig_d
= cell
->getPort(ID::D
);
156 pol_clk
= type_str
[6] == 'P';
157 sig_clk
= cell
->getPort(ID::C
);
159 pol_arst
= type_str
[7] == 'P';
160 sig_arst
= cell
->getPort(ID::R
);
161 val_arst
= type_str
[8] == '1' ? State::S1
: State::S0
;
162 } else if (type_str
.substr(0, 7) == "$_DFFE_" && type_str
.size() == 12) {
164 sig_d
= cell
->getPort(ID::D
);
166 pol_clk
= type_str
[7] == 'P';
167 sig_clk
= cell
->getPort(ID::C
);
169 pol_arst
= type_str
[8] == 'P';
170 sig_arst
= cell
->getPort(ID::R
);
171 val_arst
= type_str
[9] == '1' ? State::S1
: State::S0
;
173 pol_en
= type_str
[10] == 'P';
174 sig_en
= cell
->getPort(ID::E
);
175 } else if (type_str
.substr(0, 8) == "$_DFFSR_" && type_str
.size() == 12) {
177 sig_d
= cell
->getPort(ID::D
);
179 pol_clk
= type_str
[8] == 'P';
180 sig_clk
= cell
->getPort(ID::C
);
182 pol_set
= type_str
[9] == 'P';
183 pol_clr
= type_str
[10] == 'P';
184 sig_set
= cell
->getPort(ID::S
);
185 sig_clr
= cell
->getPort(ID::R
);
186 } else if (type_str
.substr(0, 9) == "$_DFFSRE_" && type_str
.size() == 14) {
188 sig_d
= cell
->getPort(ID::D
);
190 pol_clk
= type_str
[9] == 'P';
191 sig_clk
= cell
->getPort(ID::C
);
193 pol_set
= type_str
[10] == 'P';
194 pol_clr
= type_str
[11] == 'P';
195 sig_set
= cell
->getPort(ID::S
);
196 sig_clr
= cell
->getPort(ID::R
);
198 pol_en
= type_str
[12] == 'P';
199 sig_en
= cell
->getPort(ID::E
);
200 } else if (type_str
.substr(0, 7) == "$_SDFF_" && type_str
.size() == 11) {
202 sig_d
= cell
->getPort(ID::D
);
204 pol_clk
= type_str
[7] == 'P';
205 sig_clk
= cell
->getPort(ID::C
);
207 pol_srst
= type_str
[8] == 'P';
208 sig_srst
= cell
->getPort(ID::R
);
209 val_srst
= type_str
[9] == '1' ? State::S1
: State::S0
;
210 } else if (type_str
.substr(0, 8) == "$_SDFFE_" && type_str
.size() == 13) {
212 sig_d
= cell
->getPort(ID::D
);
214 pol_clk
= type_str
[8] == 'P';
215 sig_clk
= cell
->getPort(ID::C
);
217 pol_srst
= type_str
[9] == 'P';
218 sig_srst
= cell
->getPort(ID::R
);
219 val_srst
= type_str
[10] == '1' ? State::S1
: State::S0
;
221 pol_en
= type_str
[11] == 'P';
222 sig_en
= cell
->getPort(ID::E
);
223 } else if (type_str
.substr(0, 9) == "$_SDFFCE_" && type_str
.size() == 14) {
225 sig_d
= cell
->getPort(ID::D
);
227 pol_clk
= type_str
[9] == 'P';
228 sig_clk
= cell
->getPort(ID::C
);
230 pol_srst
= type_str
[10] == 'P';
231 sig_srst
= cell
->getPort(ID::R
);
232 val_srst
= type_str
[11] == '1' ? State::S1
: State::S0
;
234 pol_en
= type_str
[12] == 'P';
235 sig_en
= cell
->getPort(ID::E
);
237 } else if (type_str
.substr(0, 9) == "$_DLATCH_" && type_str
.size() == 11) {
239 sig_d
= cell
->getPort(ID::D
);
241 pol_en
= type_str
[9] == 'P';
242 sig_en
= cell
->getPort(ID::E
);
243 } else if (type_str
.substr(0, 9) == "$_DLATCH_" && type_str
.size() == 13) {
245 sig_d
= cell
->getPort(ID::D
);
247 pol_en
= type_str
[9] == 'P';
248 sig_en
= cell
->getPort(ID::E
);
250 pol_arst
= type_str
[10] == 'P';
251 sig_arst
= cell
->getPort(ID::R
);
252 val_arst
= type_str
[11] == '1' ? State::S1
: State::S0
;
253 } else if (type_str
.substr(0, 11) == "$_DLATCHSR_" && type_str
.size() == 15) {
255 sig_d
= cell
->getPort(ID::D
);
257 pol_en
= type_str
[11] == 'P';
258 sig_en
= cell
->getPort(ID::E
);
260 pol_set
= type_str
[12] == 'P';
261 pol_clr
= type_str
[13] == 'P';
262 sig_set
= cell
->getPort(ID::S
);
263 sig_clr
= cell
->getPort(ID::R
);
267 if (has_d
&& sig_d
.is_fully_const()) {
269 val_d
= sig_d
.as_const();
270 if (has_en
&& !has_clk
&& !has_sr
&& !has_arst
) {
271 // Plain D latches with const D treated specially.
272 has_en
= has_d
= false;
281 // Returns a FF identical to this one, but only keeping bit indices from the argument.
282 FfData
slice(const std::vector
<int> &bits
) {
283 FfData
res(initvals
);
284 res
.sig_clk
= sig_clk
;
286 res
.sig_arst
= sig_arst
;
287 res
.sig_srst
= sig_srst
;
289 res
.has_clk
= has_clk
;
291 res
.has_arst
= has_arst
;
292 res
.has_srst
= has_srst
;
294 res
.ce_over_srst
= ce_over_srst
;
295 res
.is_fine
= is_fine
;
296 res
.pol_clk
= pol_clk
;
298 res
.pol_arst
= pol_arst
;
299 res
.pol_srst
= pol_srst
;
300 res
.pol_clr
= pol_clr
;
301 res
.pol_set
= pol_set
;
302 res
.attributes
= attributes
;
304 res
.sig_q
.append(sig_q
[i
]);
306 res
.sig_d
.append(sig_d
[i
]);
308 res
.sig_clr
.append(sig_clr
[i
]);
309 res
.sig_set
.append(sig_set
[i
]);
312 res
.val_arst
.bits
.push_back(val_arst
[i
]);
314 res
.val_srst
.bits
.push_back(val_srst
[i
]);
315 res
.val_init
.bits
.push_back(val_init
[i
]);
317 res
.width
= GetSize(res
.sig_q
);
318 // Slicing bits out may cause D to become const.
319 if (has_d
&& res
.sig_d
.is_fully_const()) {
320 res
.d_is_const
= true;
321 res
.val_d
= res
.sig_d
.as_const();
326 void unmap_ce(Module
*module
) {
330 if (has_srst
&& ce_over_srst
)
335 sig_d
= module
->Mux(NEW_ID
, sig_q
, sig_d
, sig_en
);
337 sig_d
= module
->Mux(NEW_ID
, sig_d
, sig_q
, sig_en
);
340 sig_d
= module
->MuxGate(NEW_ID
, sig_q
, sig_d
, sig_en
);
342 sig_d
= module
->MuxGate(NEW_ID
, sig_d
, sig_q
, sig_en
);
347 void unmap_srst(Module
*module
) {
350 if (has_en
&& !ce_over_srst
)
355 sig_d
= module
->Mux(NEW_ID
, sig_d
, val_srst
, sig_srst
);
357 sig_d
= module
->Mux(NEW_ID
, val_srst
, sig_d
, sig_srst
);
360 sig_d
= module
->MuxGate(NEW_ID
, sig_d
, val_srst
[0], sig_srst
);
362 sig_d
= module
->MuxGate(NEW_ID
, val_srst
[0], sig_d
, sig_srst
);
367 void unmap_ce_srst(Module
*module
) {
372 Cell
*emit(Module
*module
, IdString name
) {
375 if (!has_d
&& !has_sr
) {
377 // Convert this case to a D latch.
378 has_d
= has_en
= true;
384 // No control inputs left. Turn into a const driver.
385 initvals
->remove_init(sig_q
);
386 module
->connect(sig_q
, val_init
);
390 initvals
->set_init(sig_q
, val_init
);
395 cell
= module
->addSr(name
, sig_set
, sig_clr
, sig_q
, pol_set
, pol_clr
);
396 } else if (!has_clk
&& !has_en
) {
397 log_assert(!has_arst
);
398 log_assert(!has_srst
);
400 cell
= module
->addFf(name
, sig_d
, sig_q
);
401 } else if (!has_clk
) {
402 log_assert(!has_srst
);
404 cell
= module
->addDlatchsr(name
, sig_en
, sig_set
, sig_clr
, sig_d
, sig_q
, pol_en
, pol_set
, pol_clr
);
406 cell
= module
->addAdlatch(name
, sig_en
, sig_arst
, sig_d
, sig_q
, val_arst
, pol_en
, pol_arst
);
408 cell
= module
->addDlatch(name
, sig_en
, sig_d
, sig_q
, pol_en
);
412 cell
= module
->addDffsre(name
, sig_clk
, sig_en
, sig_set
, sig_clr
, sig_d
, sig_q
, pol_clk
, pol_en
, pol_set
, pol_clr
);
414 cell
= module
->addDffsr(name
, sig_clk
, sig_set
, sig_clr
, sig_d
, sig_q
, pol_clk
, pol_set
, pol_clr
);
415 } else if (has_arst
) {
417 cell
= module
->addAdffe(name
, sig_clk
, sig_en
, sig_arst
, sig_d
, sig_q
, val_arst
, pol_clk
, pol_en
, pol_arst
);
419 cell
= module
->addAdff(name
, sig_clk
, sig_arst
, sig_d
, sig_q
, val_arst
, pol_clk
, pol_arst
);
420 } else if (has_srst
) {
423 cell
= module
->addSdffce(name
, sig_clk
, sig_en
, sig_srst
, sig_d
, sig_q
, val_srst
, pol_clk
, pol_en
, pol_srst
);
425 cell
= module
->addSdffe(name
, sig_clk
, sig_en
, sig_srst
, sig_d
, sig_q
, val_srst
, pol_clk
, pol_en
, pol_srst
);
427 cell
= module
->addSdff(name
, sig_clk
, sig_srst
, sig_d
, sig_q
, val_srst
, pol_clk
, pol_srst
);
430 cell
= module
->addDffe(name
, sig_clk
, sig_en
, sig_d
, sig_q
, pol_clk
, pol_en
);
432 cell
= module
->addDff(name
, sig_clk
, sig_d
, sig_q
, pol_clk
);
438 cell
= module
->addSrGate(name
, sig_set
, sig_clr
, sig_q
, pol_set
, pol_clr
);
439 } else if (!has_clk
&& !has_en
) {
440 log_assert(!has_arst
);
441 log_assert(!has_srst
);
443 cell
= module
->addFfGate(name
, sig_d
, sig_q
);
444 } else if (!has_clk
) {
445 log_assert(!has_srst
);
447 cell
= module
->addDlatchsrGate(name
, sig_en
, sig_set
, sig_clr
, sig_d
, sig_q
, pol_en
, pol_set
, pol_clr
);
449 cell
= module
->addAdlatchGate(name
, sig_en
, sig_arst
, sig_d
, sig_q
, val_arst
.as_bool(), pol_en
, pol_arst
);
451 cell
= module
->addDlatchGate(name
, sig_en
, sig_d
, sig_q
, pol_en
);
455 cell
= module
->addDffsreGate(name
, sig_clk
, sig_en
, sig_set
, sig_clr
, sig_d
, sig_q
, pol_clk
, pol_en
, pol_set
, pol_clr
);
457 cell
= module
->addDffsrGate(name
, sig_clk
, sig_set
, sig_clr
, sig_d
, sig_q
, pol_clk
, pol_set
, pol_clr
);
458 } else if (has_arst
) {
460 cell
= module
->addAdffeGate(name
, sig_clk
, sig_en
, sig_arst
, sig_d
, sig_q
, val_arst
.as_bool(), pol_clk
, pol_en
, pol_arst
);
462 cell
= module
->addAdffGate(name
, sig_clk
, sig_arst
, sig_d
, sig_q
, val_arst
.as_bool(), pol_clk
, pol_arst
);
463 } else if (has_srst
) {
466 cell
= module
->addSdffceGate(name
, sig_clk
, sig_en
, sig_srst
, sig_d
, sig_q
, val_srst
.as_bool(), pol_clk
, pol_en
, pol_srst
);
468 cell
= module
->addSdffeGate(name
, sig_clk
, sig_en
, sig_srst
, sig_d
, sig_q
, val_srst
.as_bool(), pol_clk
, pol_en
, pol_srst
);
470 cell
= module
->addSdffGate(name
, sig_clk
, sig_srst
, sig_d
, sig_q
, val_srst
.as_bool(), pol_clk
, pol_srst
);
473 cell
= module
->addDffeGate(name
, sig_clk
, sig_en
, sig_d
, sig_q
, pol_clk
, pol_en
);
475 cell
= module
->addDffGate(name
, sig_clk
, sig_d
, sig_q
, pol_clk
);
479 cell
->attributes
= attributes
;