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 DffinitPass
: public Pass
{
27 DffinitPass() : Pass("dffinit", "set INIT param on FF cells") { }
28 void help() YS_OVERRIDE
30 // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
32 log(" dffinit [options] [selection]\n");
34 log("This pass sets an FF cell parameter to the the initial value of the net it\n");
35 log("drives. (This is primarily used in FPGA flows.)\n");
37 log(" -ff <cell_name> <output_port> <init_param>\n");
38 log(" operate on the specified cell type. this option can be used\n");
39 log(" multiple times.\n");
42 log(" use the string values \"high\" and \"low\" to represent a single-bit\n");
43 log(" initial value of 1 or 0. (multi-bit values are not supported in this\n");
46 log(" -strinit <string for high> <string for low> \n");
47 log(" use string values in the command line to represent a single-bit\n");
48 log(" initial value of 1 or 0. (multi-bit values are not supported in this\n");
52 log(" fail if the FF cell has already a defined initial value set in other\n");
53 log(" passes and the initial value of the net it drives is not equal to\n");
54 log(" the already defined initial value.\n");
57 void execute(std::vector
<std::string
> args
, RTLIL::Design
*design
) YS_OVERRIDE
59 log_header(design
, "Executing DFFINIT pass (set INIT param on FF cells).\n");
61 dict
<IdString
, dict
<IdString
, IdString
>> ff_types
;
62 bool highlow_mode
= false, noreinit
= false;
63 std::string high_string
, low_string
;
66 for (argidx
= 1; argidx
< args
.size(); argidx
++) {
67 if (args
[argidx
] == "-highlow") {
73 if (args
[argidx
] == "-strinit" && argidx
+2 < args
.size()) {
75 high_string
= args
[++argidx
];
76 low_string
= args
[++argidx
];
79 if (args
[argidx
] == "-ff" && argidx
+3 < args
.size()) {
80 IdString cell_name
= RTLIL::escape_id(args
[++argidx
]);
81 IdString output_port
= RTLIL::escape_id(args
[++argidx
]);
82 IdString init_param
= RTLIL::escape_id(args
[++argidx
]);
83 ff_types
[cell_name
][output_port
] = init_param
;
86 if (args
[argidx
] == "-noreinit") {
92 extra_args(args
, argidx
, design
);
94 for (auto module
: design
->selected_modules())
96 SigMap
sigmap(module
);
97 dict
<SigBit
, State
> init_bits
;
98 pool
<SigBit
> cleanup_bits
;
99 pool
<SigBit
> used_bits
;
101 for (auto wire
: module
->selected_wires()) {
102 if (wire
->attributes
.count("\\init")) {
103 Const value
= wire
->attributes
.at("\\init");
104 for (int i
= 0; i
< min(GetSize(value
), GetSize(wire
)); i
++)
105 if (value
[i
] != State::Sx
)
106 init_bits
[sigmap(SigBit(wire
, i
))] = value
[i
];
108 if (wire
->port_output
)
109 for (auto bit
: sigmap(wire
))
110 used_bits
.insert(bit
);
113 for (auto cell
: module
->selected_cells())
115 for (auto it
: cell
->connections())
116 if (!cell
->known() || cell
->input(it
.first
))
117 for (auto bit
: sigmap(it
.second
))
118 used_bits
.insert(bit
);
120 if (ff_types
.count(cell
->type
) == 0)
123 for (auto &it
: ff_types
[cell
->type
])
125 if (!cell
->hasPort(it
.first
))
128 SigSpec sig
= sigmap(cell
->getPort(it
.first
));
131 if (cell
->hasParam(it
.second
))
132 value
= cell
->getParam(it
.second
);
134 for (int i
= 0; i
< GetSize(sig
); i
++) {
135 if (init_bits
.count(sig
[i
]) == 0)
137 while (GetSize(value
.bits
) <= i
)
138 value
.bits
.push_back(State::S0
);
139 if (noreinit
&& value
.bits
[i
] != State::Sx
&& value
.bits
[i
] != init_bits
.at(sig
[i
]))
140 log_error("Trying to assign a different init value for %s.%s.%s which technically "
141 "have a conflicted init value.\n",
142 log_id(module
), log_id(cell
), log_id(it
.second
));
143 value
.bits
[i
] = init_bits
.at(sig
[i
]);
144 cleanup_bits
.insert(sig
[i
]);
147 if (highlow_mode
&& GetSize(value
) != 0) {
148 if (GetSize(value
) != 1)
149 log_error("Multi-bit init value for %s.%s.%s is incompatible with -highlow mode.\n",
150 log_id(module
), log_id(cell
), log_id(it
.second
));
151 if (value
[0] == State::S1
)
152 value
= Const(high_string
);
154 value
= Const(low_string
);
157 log("Setting %s.%s.%s (port=%s, net=%s) to %s.\n", log_id(module
), log_id(cell
), log_id(it
.second
),
158 log_id(it
.first
), log_signal(sig
), log_signal(value
));
159 cell
->setParam(it
.second
, value
);
163 for (auto wire
: module
->selected_wires())
164 if (wire
->attributes
.count("\\init")) {
165 Const
&value
= wire
->attributes
.at("\\init");
166 bool do_cleanup
= true;
167 for (int i
= 0; i
< min(GetSize(value
), GetSize(wire
)); i
++) {
168 SigBit bit
= sigmap(SigBit(wire
, i
));
169 if (cleanup_bits
.count(bit
) || !used_bits
.count(bit
))
170 value
[i
] = State::Sx
;
171 else if (value
[i
] != State::Sx
)
175 log("Removing init attribute from wire %s.%s.\n", log_id(module
), log_id(wire
));
176 wire
->attributes
.erase("\\init");
183 PRIVATE_NAMESPACE_END