2 * yosys -- Yosys Open SYnthesis Suite
4 * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
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.
20 #include "kernel/yosys.h"
21 #include "kernel/sigtools.h"
24 PRIVATE_NAMESPACE_BEGIN
26 struct Ice40FfinitPass
: public Pass
{
27 Ice40FfinitPass() : Pass("ice40_ffinit", "iCE40: handle FF init values") { }
30 // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
32 log(" ice40_ffinit [options] [selection]\n");
34 log("Remove zero init values for FF output signals. Add inverters to implement\n");
35 log("nonzero init values.\n");
38 virtual void execute(std::vector
<std::string
> args
, RTLIL::Design
*design
)
40 log_header(design
, "Executing ICE40_FFINIT pass (implement FF init values).\n");
43 for (argidx
= 1; argidx
< args
.size(); argidx
++)
45 // if (args[argidx] == "-singleton") {
46 // singleton_mode = true;
51 extra_args(args
, argidx
, design
);
53 for (auto module
: design
->selected_modules())
55 log("Handling FF init values in %s.\n", log_id(module
));
57 SigMap
sigmap(module
);
58 pool
<Wire
*> init_wires
;
59 dict
<SigBit
, State
> initbits
;
60 pool
<SigBit
> handled_initbits
;
62 for (auto wire
: module
->selected_wires())
64 if (wire
->attributes
.count("\\init") == 0)
67 SigSpec wirebits
= sigmap(wire
);
68 Const initval
= wire
->attributes
.at("\\init");
69 init_wires
.insert(wire
);
71 for (int i
= 0; i
< GetSize(wirebits
) && i
< GetSize(initval
); i
++)
73 SigBit bit
= wirebits
[i
];
74 State val
= initval
[i
];
76 if (val
!= State::S0
&& val
!= State::S1
)
79 if (initbits
.count(bit
)) {
80 if (initbits
.at(bit
) != val
)
81 log_error("Conflicting init values for signal %s.\n", log_signal(bit
));
89 pool
<IdString
> sb_dff_types
= {
90 "\\SB_DFF", "\\SB_DFFE", "\\SB_DFFSR", "\\SB_DFFR", "\\SB_DFFSS", "\\SB_DFFS", "\\SB_DFFESR",
91 "\\SB_DFFER", "\\SB_DFFESS", "\\SB_DFFES", "\\SB_DFFN", "\\SB_DFFNE", "\\SB_DFFNSR", "\\SB_DFFNR",
92 "\\SB_DFFNSS", "\\SB_DFFNS", "\\SB_DFFNESR", "\\SB_DFFNER", "\\SB_DFFNESS", "\\SB_DFFNES"
95 for (auto cell
: module
->selected_cells())
97 if (!sb_dff_types
.count(cell
->type
))
100 SigBit sig_d
= sigmap(cell
->getPort("\\D"));
101 SigBit sig_q
= sigmap(cell
->getPort("\\Q"));
103 if (!initbits
.count(sig_q
))
106 State val
= initbits
.at(sig_q
);
107 handled_initbits
.insert(sig_q
);
109 log("FF init value for cell %s (%s): %s = %c\n", log_id(cell
), log_id(cell
->type
),
110 log_signal(sig_q
), val
!= State::S0
? '1' : '0');
112 if (val
== State::S0
)
115 string type_str
= cell
->type
.str();
117 if (type_str
.back() == 'S') {
118 type_str
.back() = 'R';
119 cell
->type
= type_str
;
120 cell
->setPort("\\R", cell
->getPort("\\S"));
121 cell
->unsetPort("\\S");
123 if (type_str
.back() == 'R') {
124 type_str
.back() = 'S';
125 cell
->type
= type_str
;
126 cell
->setPort("\\S", cell
->getPort("\\R"));
127 cell
->unsetPort("\\R");
130 Wire
*new_sig_d
= module
->addWire(NEW_ID
);
131 Wire
*new_sig_q
= module
->addWire(NEW_ID
);
133 module
->addNotGate(NEW_ID
, sig_d
, new_sig_d
);
134 module
->addNotGate(NEW_ID
, new_sig_q
, sig_q
);
136 cell
->setPort("\\D", new_sig_d
);
137 cell
->setPort("\\Q", new_sig_q
);
140 for (auto wire
: init_wires
)
142 if (wire
->attributes
.count("\\init") == 0)
145 SigSpec wirebits
= sigmap(wire
);
146 Const
&initval
= wire
->attributes
.at("\\init");
147 bool remove_attribute
= true;
149 for (int i
= 0; i
< GetSize(wirebits
) && i
< GetSize(initval
); i
++) {
150 if (handled_initbits
.count(wirebits
[i
]))
151 initval
[i
] = State::Sx
;
152 else if (initval
[i
] != State::Sx
)
153 remove_attribute
= false;
156 if (remove_attribute
)
157 wire
->attributes
.erase("\\init");
163 PRIVATE_NAMESPACE_END