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"
22 #include "passes/techmap/simplemap.h"
27 PRIVATE_NAMESPACE_BEGIN
29 static SigBit
get_bit_or_zero(const SigSpec
&sig
)
31 if (GetSize(sig
) == 0)
36 static void run_ice40_opts(Module
*module
)
38 pool
<SigBit
> optimized_co
;
39 vector
<Cell
*> sb_lut_cells
;
40 SigMap
sigmap(module
);
42 for (auto cell
: module
->selected_cells())
44 if (cell
->type
== "\\SB_LUT4")
46 sb_lut_cells
.push_back(cell
);
50 if (cell
->type
== "\\SB_CARRY")
52 SigSpec non_const_inputs
, replacement_output
;
53 int count_zeros
= 0, count_ones
= 0;
56 get_bit_or_zero(cell
->getPort("\\I0")),
57 get_bit_or_zero(cell
->getPort("\\I1")),
58 get_bit_or_zero(cell
->getPort("\\CI"))
60 for (int i
= 0; i
< 3; i
++)
61 if (inbit
[i
].wire
== nullptr) {
62 if (inbit
[i
] == State::S1
)
67 non_const_inputs
.append(inbit
[i
]);
70 replacement_output
= State::S0
;
71 else if (count_ones
>= 2)
72 replacement_output
= State::S1
;
73 else if (GetSize(non_const_inputs
) == 1)
74 replacement_output
= non_const_inputs
;
76 if (GetSize(replacement_output
)) {
77 optimized_co
.insert(sigmap(cell
->getPort("\\CO")[0]));
78 module
->connect(cell
->getPort("\\CO")[0], replacement_output
);
79 module
->design
->scratchpad_set_bool("opt.did_something", true);
80 log("Optimized away SB_CARRY cell %s.%s: CO=%s\n",
81 log_id(module
), log_id(cell
), log_signal(replacement_output
));
88 for (auto cell
: sb_lut_cells
)
92 inbits
.append(get_bit_or_zero(cell
->getPort("\\I0")));
93 inbits
.append(get_bit_or_zero(cell
->getPort("\\I1")));
94 inbits
.append(get_bit_or_zero(cell
->getPort("\\I2")));
95 inbits
.append(get_bit_or_zero(cell
->getPort("\\I3")));
98 if (optimized_co
.count(inbits
[0])) goto remap_lut
;
99 if (optimized_co
.count(inbits
[1])) goto remap_lut
;
100 if (optimized_co
.count(inbits
[2])) goto remap_lut
;
101 if (optimized_co
.count(inbits
[3])) goto remap_lut
;
103 if (!sigmap(inbits
).is_fully_const())
107 module
->design
->scratchpad_set_bool("opt.did_something", true);
108 log("Mapping SB_LUT4 cell %s.%s back to logic.\n", log_id(module
), log_id(cell
));
111 cell
->setParam("\\WIDTH", 4);
112 cell
->setParam("\\LUT", cell
->getParam("\\LUT_INIT"));
113 cell
->unsetParam("\\LUT_INIT");
115 cell
->setPort("\\A", SigSpec({
116 get_bit_or_zero(cell
->getPort("\\I3")),
117 get_bit_or_zero(cell
->getPort("\\I2")),
118 get_bit_or_zero(cell
->getPort("\\I1")),
119 get_bit_or_zero(cell
->getPort("\\I0"))
121 cell
->setPort("\\Y", cell
->getPort("\\O")[0]);
122 cell
->unsetPort("\\I0");
123 cell
->unsetPort("\\I1");
124 cell
->unsetPort("\\I2");
125 cell
->unsetPort("\\I3");
126 cell
->unsetPort("\\O");
129 simplemap_lut(module
, cell
);
130 module
->remove(cell
);
134 struct Ice40OptPass
: public Pass
{
135 Ice40OptPass() : Pass("ice40_opt", "iCE40: perform simple optimizations") { }
136 void help() YS_OVERRIDE
138 // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
140 log(" ice40_opt [options] [selection]\n");
142 log("This command executes the following script:\n");
145 log(" <ice40 specific optimizations>\n");
146 log(" opt_expr -mux_undef -undriven [-full]\n");
150 log(" while <changed design>\n");
153 void execute(std::vector
<std::string
> args
, RTLIL::Design
*design
) YS_OVERRIDE
155 string opt_expr_args
= "-mux_undef -undriven";
157 log_header(design
, "Executing ICE40_OPT pass (performing simple optimizations).\n");
161 for (argidx
= 1; argidx
< args
.size(); argidx
++) {
162 if (args
[argidx
] == "-full") {
163 opt_expr_args
+= " -full";
168 extra_args(args
, argidx
, design
);
172 design
->scratchpad_unset("opt.did_something");
174 log_header(design
, "Running ICE40 specific optimizations.\n");
175 for (auto module
: design
->selected_modules())
176 run_ice40_opts(module
);
178 Pass::call(design
, "opt_expr " + opt_expr_args
);
179 Pass::call(design
, "opt_merge");
180 Pass::call(design
, "opt_rmdff");
181 Pass::call(design
, "opt_clean");
183 if (design
->scratchpad_get_bool("opt.did_something") == false)
186 log_header(design
, "Rerunning OPT passes. (Removed registers in this run.)\n");
193 log_header(design
, "Finished OPT passes. (There is nothing left to do.)\n");
198 PRIVATE_NAMESPACE_END