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 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_error("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
)));
89 initbit_to_wire
[bit
] = SigBit(wire
, i
);
93 pool
<IdString
> sb_dff_types
= {
94 "\\SB_DFF", "\\SB_DFFE", "\\SB_DFFSR", "\\SB_DFFR", "\\SB_DFFSS", "\\SB_DFFS", "\\SB_DFFESR",
95 "\\SB_DFFER", "\\SB_DFFESS", "\\SB_DFFES", "\\SB_DFFN", "\\SB_DFFNE", "\\SB_DFFNSR", "\\SB_DFFNR",
96 "\\SB_DFFNSS", "\\SB_DFFNS", "\\SB_DFFNESR", "\\SB_DFFNER", "\\SB_DFFNESS", "\\SB_DFFNES"
99 for (auto cell
: module
->selected_cells())
101 if (!sb_dff_types
.count(cell
->type
))
104 SigBit sig_d
= sigmap(cell
->getPort("\\D"));
105 SigBit sig_q
= sigmap(cell
->getPort("\\Q"));
107 if (!initbits
.count(sig_q
))
110 State val
= initbits
.at(sig_q
);
111 handled_initbits
.insert(sig_q
);
113 log("FF init value for cell %s (%s): %s = %c\n", log_id(cell
), log_id(cell
->type
),
114 log_signal(sig_q
), val
!= State::S0
? '1' : '0');
116 if (val
== State::S0
)
119 string type_str
= cell
->type
.str();
121 if (type_str
.back() == 'S') {
122 type_str
.back() = 'R';
123 cell
->type
= type_str
;
124 cell
->setPort("\\R", cell
->getPort("\\S"));
125 cell
->unsetPort("\\S");
127 if (type_str
.back() == 'R') {
128 type_str
.back() = 'S';
129 cell
->type
= type_str
;
130 cell
->setPort("\\S", cell
->getPort("\\R"));
131 cell
->unsetPort("\\R");
134 Wire
*new_sig_d
= module
->addWire(NEW_ID
);
135 Wire
*new_sig_q
= module
->addWire(NEW_ID
);
137 module
->addNotGate(NEW_ID
, sig_d
, new_sig_d
);
138 module
->addNotGate(NEW_ID
, new_sig_q
, sig_q
);
140 cell
->setPort("\\D", new_sig_d
);
141 cell
->setPort("\\Q", new_sig_q
);
144 for (auto wire
: init_wires
)
146 if (wire
->attributes
.count("\\init") == 0)
149 SigSpec wirebits
= sigmap(wire
);
150 Const
&initval
= wire
->attributes
.at("\\init");
151 bool remove_attribute
= true;
153 for (int i
= 0; i
< GetSize(wirebits
) && i
< GetSize(initval
); i
++) {
154 if (handled_initbits
.count(wirebits
[i
]))
155 initval
[i
] = State::Sx
;
156 else if (initval
[i
] != State::Sx
)
157 remove_attribute
= false;
160 if (remove_attribute
)
161 wire
->attributes
.erase("\\init");
167 PRIVATE_NAMESPACE_END