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") { }
28 void help() YS_OVERRIDE
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 void execute(std::vector
<std::string
> args
, RTLIL::Design
*design
) YS_OVERRIDE
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 dict
<SigBit
, SigBit
> initbit_to_wire
;
61 pool
<SigBit
> handled_initbits
;
63 for (auto wire
: module
->selected_wires())
65 if (wire
->attributes
.count("\\init") == 0)
68 SigSpec wirebits
= sigmap(wire
);
69 Const initval
= wire
->attributes
.at("\\init");
70 init_wires
.insert(wire
);
72 for (int i
= 0; i
< GetSize(wirebits
) && i
< GetSize(initval
); i
++)
74 SigBit bit
= wirebits
[i
];
75 State val
= initval
[i
];
77 if (val
!= State::S0
&& val
!= State::S1
)
80 if (initbits
.count(bit
)) {
81 if (initbits
.at(bit
) != val
) {
82 log_warning("Conflicting init values for signal %s (%s = %s, %s = %s).\n",
83 log_signal(bit
), log_signal(SigBit(wire
, i
)), log_signal(val
),
84 log_signal(initbit_to_wire
[bit
]), log_signal(initbits
.at(bit
)));
85 initbits
.at(bit
) = State::Sx
;
91 initbit_to_wire
[bit
] = SigBit(wire
, i
);
95 pool
<IdString
> sb_dff_types
= {
96 "\\SB_DFF", "\\SB_DFFE", "\\SB_DFFSR", "\\SB_DFFR", "\\SB_DFFSS", "\\SB_DFFS", "\\SB_DFFESR",
97 "\\SB_DFFER", "\\SB_DFFESS", "\\SB_DFFES", "\\SB_DFFN", "\\SB_DFFNE", "\\SB_DFFNSR", "\\SB_DFFNR",
98 "\\SB_DFFNSS", "\\SB_DFFNS", "\\SB_DFFNESR", "\\SB_DFFNER", "\\SB_DFFNESS", "\\SB_DFFNES"
101 for (auto cell
: module
->selected_cells())
103 if (!sb_dff_types
.count(cell
->type
))
106 SigSpec sig_d
= cell
->getPort("\\D");
107 SigSpec sig_q
= cell
->getPort("\\Q");
109 if (GetSize(sig_d
) < 1 || GetSize(sig_q
) < 1)
112 SigBit bit_d
= sigmap(sig_d
[0]);
113 SigBit bit_q
= sigmap(sig_q
[0]);
115 if (!initbits
.count(bit_q
))
118 State val
= initbits
.at(bit_q
);
120 if (val
== State::Sx
)
123 handled_initbits
.insert(bit_q
);
125 log("FF init value for cell %s (%s): %s = %c\n", log_id(cell
), log_id(cell
->type
),
126 log_signal(bit_q
), val
!= State::S0
? '1' : '0');
128 if (val
== State::S0
)
131 string type_str
= cell
->type
.str();
133 if (type_str
.back() == 'S') {
134 type_str
.back() = 'R';
135 cell
->type
= type_str
;
136 cell
->setPort("\\R", cell
->getPort("\\S"));
137 cell
->unsetPort("\\S");
139 if (type_str
.back() == 'R') {
140 type_str
.back() = 'S';
141 cell
->type
= type_str
;
142 cell
->setPort("\\S", cell
->getPort("\\R"));
143 cell
->unsetPort("\\R");
146 Wire
*new_bit_d
= module
->addWire(NEW_ID
);
147 Wire
*new_bit_q
= module
->addWire(NEW_ID
);
149 module
->addNotGate(NEW_ID
, bit_d
, new_bit_d
);
150 module
->addNotGate(NEW_ID
, new_bit_q
, bit_q
);
152 cell
->setPort("\\D", new_bit_d
);
153 cell
->setPort("\\Q", new_bit_q
);
156 for (auto wire
: init_wires
)
158 if (wire
->attributes
.count("\\init") == 0)
161 SigSpec wirebits
= sigmap(wire
);
162 Const
&initval
= wire
->attributes
.at("\\init");
163 bool remove_attribute
= true;
165 for (int i
= 0; i
< GetSize(wirebits
) && i
< GetSize(initval
); i
++) {
166 if (handled_initbits
.count(wirebits
[i
]))
167 initval
[i
] = State::Sx
;
168 else if (initval
[i
] != State::Sx
)
169 remove_attribute
= false;
172 if (remove_attribute
)
173 wire
->attributes
.erase("\\init");
179 PRIVATE_NAMESPACE_END