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(ID::init
) == 0)
68 SigSpec wirebits
= sigmap(wire
);
69 Const initval
= wire
->attributes
.at(ID::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 ID(SB_DFF
), ID(SB_DFFE
), ID(SB_DFFSR
), ID(SB_DFFR
), ID(SB_DFFSS
), ID(SB_DFFS
), ID(SB_DFFESR
),
97 ID(SB_DFFER
), ID(SB_DFFESS
), ID(SB_DFFES
), ID(SB_DFFN
), ID(SB_DFFNE
), ID(SB_DFFNSR
), ID(SB_DFFNR
),
98 ID(SB_DFFNSS
), ID(SB_DFFNS
), ID(SB_DFFNESR
), ID(SB_DFFNER
), ID(SB_DFFNESS
), ID(SB_DFFNES
)
101 for (auto cell
: module
->selected_cells())
103 if (!sb_dff_types
.count(cell
->type
))
106 SigSpec sig_d
= cell
->getPort(ID::D
);
107 SigSpec sig_q
= cell
->getPort(ID::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(ID::R
, cell
->getPort(ID::S
));
137 cell
->unsetPort(ID::S
);
139 if (type_str
.back() == 'R') {
140 type_str
.back() = 'S';
141 cell
->type
= type_str
;
142 cell
->setPort(ID::S
, cell
->getPort(ID::R
));
143 cell
->unsetPort(ID::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(ID::D
, new_bit_d
);
153 cell
->setPort(ID::Q
, new_bit_q
);
156 for (auto wire
: init_wires
)
158 if (wire
->attributes
.count(ID::init
) == 0)
161 SigSpec wirebits
= sigmap(wire
);
162 Const
&initval
= wire
->attributes
.at(ID::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(ID::init
);
179 PRIVATE_NAMESPACE_END