2 * yosys -- Yosys Open SYnthesis Suite
4 * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
5 * Copyright (C) 2018-19 David Shah <david@symbioticeda.com>
7 * Permission to use, copy, modify, and/or distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
21 #include "kernel/yosys.h"
22 #include "kernel/sigtools.h"
25 PRIVATE_NAMESPACE_BEGIN
27 struct Ecp5FfinitPass
: public Pass
{
28 Ecp5FfinitPass() : Pass("ecp5_ffinit", "ECP5: handle FF init values") { }
29 void help() YS_OVERRIDE
31 // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
33 log(" ecp5_ffinit [options] [selection]\n");
35 log("Remove init values for FF output signals when equal to reset value.\n");
36 log("If reset is not used, set the reset value to the init value, otherwise\n");
37 log("unmap out the reset (if not an async reset).\n");
39 void execute(std::vector
<std::string
> args
, RTLIL::Design
*design
) YS_OVERRIDE
41 log_header(design
, "Executing ECP5_FFINIT pass (implement FF init values).\n");
44 for (argidx
= 1; argidx
< args
.size(); argidx
++)
46 // if (args[argidx] == "-singleton") {
47 // singleton_mode = true;
52 extra_args(args
, argidx
, design
);
54 for (auto module
: design
->selected_modules())
56 log("Handling FF init values in %s.\n", log_id(module
));
58 SigMap
sigmap(module
);
59 pool
<Wire
*> init_wires
;
60 dict
<SigBit
, State
> initbits
;
61 dict
<SigBit
, SigBit
> initbit_to_wire
;
62 pool
<SigBit
> handled_initbits
;
64 for (auto wire
: module
->selected_wires())
66 if (wire
->attributes
.count("\\init") == 0)
69 SigSpec wirebits
= sigmap(wire
);
70 Const initval
= wire
->attributes
.at("\\init");
71 init_wires
.insert(wire
);
73 for (int i
= 0; i
< GetSize(wirebits
) && i
< GetSize(initval
); i
++)
75 SigBit bit
= wirebits
[i
];
76 State val
= initval
[i
];
78 if (val
!= State::S0
&& val
!= State::S1
)
81 if (initbits
.count(bit
)) {
82 if (initbits
.at(bit
) != val
) {
83 log_warning("Conflicting init values for signal %s (%s = %s, %s = %s).\n",
84 log_signal(bit
), log_signal(SigBit(wire
, i
)), log_signal(val
),
85 log_signal(initbit_to_wire
[bit
]), log_signal(initbits
.at(bit
)));
86 initbits
.at(bit
) = State::Sx
;
92 initbit_to_wire
[bit
] = SigBit(wire
, i
);
95 for (auto cell
: module
->selected_cells())
97 if (cell
->type
!= "\\TRELLIS_FF")
99 SigSpec sig_d
= cell
->getPort("\\DI");
100 SigSpec sig_q
= cell
->getPort("\\Q");
101 SigSpec sig_lsr
= cell
->getPort("\\LSR");
103 if (GetSize(sig_d
) < 1 || GetSize(sig_q
) < 1)
106 SigBit bit_d
= sigmap(sig_d
[0]);
107 SigBit bit_q
= sigmap(sig_q
[0]);
109 std::string regset
= "RESET";
110 if (cell
->hasParam("\\REGSET"))
111 regset
= cell
->getParam("\\REGSET").decode_string();
114 resetState
= State::S1
;
115 else if (regset
== "RESET")
116 resetState
= State::S0
;
118 log_error("FF cell %s has illegal REGSET value %s.\n",
119 log_id(cell
), regset
.c_str());
121 if (!initbits
.count(bit_q
))
124 State val
= initbits
.at(bit_q
);
126 if (val
== State::Sx
)
129 log("FF init value for cell %s (%s): %s = %c\n", log_id(cell
), log_id(cell
->type
),
130 log_signal(bit_q
), val
!= State::S0
? '1' : '0');
131 // Initval is the same as the reset state. Matches hardware, nowt more to do
132 if (val
== resetState
) {
133 handled_initbits
.insert(bit_q
);
137 if (GetSize(sig_lsr
) >= 1 && sig_lsr
[0] != State::S0
) {
138 std::string srmode
= "LSR_OVER_CE";
139 if (cell
->hasParam("\\SRMODE"))
140 srmode
= cell
->getParam("\\SRMODE").decode_string();
141 if (srmode
== "ASYNC") {
142 log("Async reset value %c for FF cell %s inconsistent with init value %c.\n",
143 resetState
!= State::S0
? '1' : '0', log_id(cell
), val
!= State::S0
? '1' : '0');
145 SigBit bit_lsr
= sigmap(sig_lsr
[0]);
146 Wire
*new_bit_d
= module
->addWire(NEW_ID
);
147 if (resetState
== State::S0
) {
148 module
->addAndnotGate(NEW_ID
, bit_d
, bit_lsr
, new_bit_d
);
150 module
->addOrGate(NEW_ID
, bit_d
, bit_lsr
, new_bit_d
);
153 cell
->setPort("\\DI", new_bit_d
);
154 cell
->setPort("\\LSR", State::S0
);
156 if(cell
->hasPort("\\CE")) {
157 std::string cemux
= "CE";
158 if (cell
->hasParam("\\CEMUX"))
159 cemux
= cell
->getParam("\\CEMUX").decode_string();
160 SigSpec sig_ce
= cell
->getPort("\\CE");
161 if (GetSize(sig_ce
) >= 1) {
162 SigBit bit_ce
= sigmap(sig_ce
[0]);
163 Wire
*new_bit_ce
= module
->addWire(NEW_ID
);
165 module
->addAndnotGate(NEW_ID
, bit_ce
, bit_lsr
, new_bit_ce
);
167 module
->addOrGate(NEW_ID
, bit_ce
, bit_lsr
, new_bit_ce
);
168 cell
->setPort("\\CE", new_bit_ce
);
171 cell
->setParam("\\REGSET", val
!= State::S0
? Const("SET") : Const("RESET"));
172 handled_initbits
.insert(bit_q
);
175 cell
->setParam("\\REGSET", val
!= State::S0
? Const("SET") : Const("RESET"));
176 handled_initbits
.insert(bit_q
);
180 for (auto wire
: init_wires
)
182 if (wire
->attributes
.count("\\init") == 0)
185 SigSpec wirebits
= sigmap(wire
);
186 Const
&initval
= wire
->attributes
.at("\\init");
187 bool remove_attribute
= true;
189 for (int i
= 0; i
< GetSize(wirebits
) && i
< GetSize(initval
); i
++) {
190 if (handled_initbits
.count(wirebits
[i
]))
191 initval
[i
] = State::Sx
;
192 else if (initval
[i
] != State::Sx
)
193 remove_attribute
= false;
196 if (remove_attribute
)
197 wire
->attributes
.erase("\\init");
203 PRIVATE_NAMESPACE_END