2 * yosys -- Yosys Open SYnthesis Suite
4 * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
5 * Copyright (C) 2018 David Shah <dave@ds0.me>
7 * Permission to use, copy, modify, and/or distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
21 #include "kernel/yosys.h"
22 #include "kernel/sigtools.h"
25 PRIVATE_NAMESPACE_BEGIN
27 struct Dff2dffsPass
: public Pass
{
28 Dff2dffsPass() : Pass("dff2dffs", "process sync set/reset with SR over CE priority") { }
29 void help() YS_OVERRIDE
32 log(" dff2dffs [options] [selection]\n");
34 log("Merge synchronous set/reset $_MUX_ cells to create $__DFFS_[NP][NP][01], to be run before\n");
35 log("dff2dffe for SR over CE priority.\n");
37 log(" -match-init\n");
38 log(" Disallow merging synchronous set/reset that has polarity opposite of the\n");
39 log(" output wire's init attribute (if any).\n");
42 void execute(std::vector
<std::string
> args
, RTLIL::Design
*design
) YS_OVERRIDE
44 log_header(design
, "Executing dff2dffs pass (merge synchronous set/reset into FF cells).\n");
46 bool match_init
= false;
48 for (argidx
= 1; argidx
< args
.size(); argidx
++)
50 // if (args[argidx] == "-singleton") {
51 // singleton_mode = true;
54 if (args
[argidx
] == "-match-init") {
60 extra_args(args
, argidx
, design
);
62 pool
<IdString
> dff_types
;
63 dff_types
.insert(ID($_DFF_N_
));
64 dff_types
.insert(ID($_DFF_P_
));
66 for (auto module
: design
->selected_modules())
68 log("Merging set/reset $_MUX_ cells into DFFs in %s.\n", log_id(module
));
70 SigMap
sigmap(module
);
71 dict
<SigBit
, Cell
*> sr_muxes
;
72 vector
<Cell
*> ff_cells
;
74 for (auto cell
: module
->selected_cells())
76 if (dff_types
.count(cell
->type
)) {
77 ff_cells
.push_back(cell
);
81 if (cell
->type
!= ID($_MUX_
))
84 SigBit bit_a
= sigmap(cell
->getPort(ID::A
));
85 SigBit bit_b
= sigmap(cell
->getPort(ID::B
));
87 if (bit_a
.wire
== nullptr || bit_b
.wire
== nullptr)
88 sr_muxes
[sigmap(cell
->getPort(ID::Y
))] = cell
;
91 for (auto cell
: ff_cells
)
93 SigSpec sig_d
= cell
->getPort(ID(D
));
95 if (GetSize(sig_d
) < 1)
98 SigBit bit_d
= sigmap(sig_d
[0]);
100 if (sr_muxes
.count(bit_d
) == 0)
103 Cell
*mux_cell
= sr_muxes
.at(bit_d
);
104 SigBit bit_a
= sigmap(mux_cell
->getPort(ID::A
));
105 SigBit bit_b
= sigmap(mux_cell
->getPort(ID::B
));
106 SigBit bit_s
= sigmap(mux_cell
->getPort(ID(S
)));
108 SigBit sr_val
, sr_sig
;
111 if (bit_a
.wire
== nullptr) {
116 log_assert(bit_b
.wire
== nullptr);
123 SigBit bit_q
= cell
->getPort(ID(Q
));
125 auto it
= bit_q
.wire
->attributes
.find(ID(init
));
126 if (it
!= bit_q
.wire
->attributes
.end()) {
127 auto init_val
= it
->second
[bit_q
.offset
];
128 if (init_val
== State::S1
&& sr_val
!= State::S1
)
130 if (init_val
== State::S0
&& sr_val
!= State::S0
)
136 log(" Merging %s (A=%s, B=%s, S=%s) into %s (%s).\n", log_id(mux_cell
),
137 log_signal(bit_a
), log_signal(bit_b
), log_signal(bit_s
), log_id(cell
), log_id(cell
->type
));
139 if (sr_val
== State::S1
) {
140 if (cell
->type
== ID($_DFF_N_
)) {
141 if (invert_sr
) cell
->type
= ID($__DFFS_NN1_
);
142 else cell
->type
= ID($__DFFS_NP1_
);
144 log_assert(cell
->type
== ID($_DFF_P_
));
145 if (invert_sr
) cell
->type
= ID($__DFFS_PN1_
);
146 else cell
->type
= ID($__DFFS_PP1_
);
149 if (cell
->type
== ID($_DFF_N_
)) {
150 if (invert_sr
) cell
->type
= ID($__DFFS_NN0_
);
151 else cell
->type
= ID($__DFFS_NP0_
);
153 log_assert(cell
->type
== ID($_DFF_P_
));
154 if (invert_sr
) cell
->type
= ID($__DFFS_PN0_
);
155 else cell
->type
= ID($__DFFS_PP0_
);
158 cell
->setPort(ID(R
), sr_sig
);
159 cell
->setPort(ID(D
), bit_d
);
165 PRIVATE_NAMESPACE_END