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 Ice40FfssrPass
: public Pass
{
27 Ice40FfssrPass() : Pass("ice40_ffssr", "iCE40: merge synchronous set/reset into FF cells") { }
28 void help() YS_OVERRIDE
31 log(" ice40_ffssr [options] [selection]\n");
33 log("Merge synchronous set/reset $_MUX_ cells into iCE40 FFs.\n");
36 void execute(std::vector
<std::string
> args
, RTLIL::Design
*design
) YS_OVERRIDE
38 log_header(design
, "Executing ICE40_FFSSR pass (merge synchronous set/reset into FF cells).\n");
41 for (argidx
= 1; argidx
< args
.size(); argidx
++)
43 // if (args[argidx] == "-singleton") {
44 // singleton_mode = true;
49 extra_args(args
, argidx
, design
);
51 pool
<IdString
> sb_dff_types
;
52 sb_dff_types
.insert("\\SB_DFF");
53 sb_dff_types
.insert("\\SB_DFFE");
54 sb_dff_types
.insert("\\SB_DFFN");
55 sb_dff_types
.insert("\\SB_DFFNE");
57 for (auto module
: design
->selected_modules())
59 log("Merging set/reset $_MUX_ cells into SB_FFs in %s.\n", log_id(module
));
61 SigMap
sigmap(module
);
62 dict
<SigBit
, Cell
*> sr_muxes
;
63 vector
<Cell
*> ff_cells
;
65 for (auto cell
: module
->selected_cells())
67 if (sb_dff_types
.count(cell
->type
)) {
68 ff_cells
.push_back(cell
);
72 if (cell
->type
!= "$_MUX_")
75 SigBit bit_a
= sigmap(cell
->getPort("\\A"));
76 SigBit bit_b
= sigmap(cell
->getPort("\\B"));
78 if (bit_a
.wire
== nullptr || bit_b
.wire
== nullptr)
79 sr_muxes
[sigmap(cell
->getPort("\\Y"))] = cell
;
82 for (auto cell
: ff_cells
)
84 if (cell
->get_bool_attribute("\\dont_touch"))
87 SigSpec sig_d
= cell
->getPort("\\D");
89 if (GetSize(sig_d
) < 1)
92 SigBit bit_d
= sigmap(sig_d
[0]);
94 if (sr_muxes
.count(bit_d
) == 0)
97 Cell
*mux_cell
= sr_muxes
.at(bit_d
);
98 SigBit bit_a
= sigmap(mux_cell
->getPort("\\A"));
99 SigBit bit_b
= sigmap(mux_cell
->getPort("\\B"));
100 SigBit bit_s
= sigmap(mux_cell
->getPort("\\S"));
102 log(" Merging %s (A=%s, B=%s, S=%s) into %s (%s).\n", log_id(mux_cell
),
103 log_signal(bit_a
), log_signal(bit_b
), log_signal(bit_s
), log_id(cell
), log_id(cell
->type
));
105 SigBit sr_val
, sr_sig
;
106 if (bit_a
.wire
== nullptr) {
109 sr_sig
= module
->NotGate(NEW_ID
, bit_s
);
111 log_assert(bit_b
.wire
== nullptr);
117 if (sr_val
== State::S1
) {
118 cell
->type
= cell
->type
.str() + "SS";
119 cell
->setPort("\\S", sr_sig
);
120 cell
->setPort("\\D", bit_d
);
122 cell
->type
= cell
->type
.str() + "SR";
123 cell
->setPort("\\R", sr_sig
);
124 cell
->setPort("\\D", bit_d
);
131 PRIVATE_NAMESPACE_END