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");
38 void execute(std::vector
<std::string
> args
, RTLIL::Design
*design
) YS_OVERRIDE
40 log_header(design
, "Executing dff2dffs pass (merge synchronous set/reset into FF cells).\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 pool
<IdString
> dff_types
;
54 dff_types
.insert(ID($_DFF_N_
));
55 dff_types
.insert(ID($_DFF_P_
));
57 for (auto module
: design
->selected_modules())
59 log("Merging set/reset $_MUX_ cells into DFFs 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 (dff_types
.count(cell
->type
)) {
68 ff_cells
.push_back(cell
);
72 if (cell
->type
!= ID($_MUX_
))
75 SigBit bit_a
= sigmap(cell
->getPort(ID(\\A
)));
76 SigBit bit_b
= sigmap(cell
->getPort(ID(\\B
)));
78 if (bit_a
.wire
== nullptr || bit_b
.wire
== nullptr)
79 sr_muxes
[sigmap(cell
->getPort(ID(\\Y
)))] = cell
;
82 for (auto cell
: ff_cells
)
84 SigSpec sig_d
= cell
->getPort(ID(\\D
));
86 if (GetSize(sig_d
) < 1)
89 SigBit bit_d
= sigmap(sig_d
[0]);
91 if (sr_muxes
.count(bit_d
) == 0)
94 Cell
*mux_cell
= sr_muxes
.at(bit_d
);
95 SigBit bit_a
= sigmap(mux_cell
->getPort(ID(\\A
)));
96 SigBit bit_b
= sigmap(mux_cell
->getPort(ID(\\B
)));
97 SigBit bit_s
= sigmap(mux_cell
->getPort(ID(\\S
)));
99 log(" Merging %s (A=%s, B=%s, S=%s) into %s (%s).\n", log_id(mux_cell
),
100 log_signal(bit_a
), log_signal(bit_b
), log_signal(bit_s
), log_id(cell
), log_id(cell
->type
));
102 SigBit sr_val
, sr_sig
;
105 if (bit_a
.wire
== nullptr) {
110 log_assert(bit_b
.wire
== nullptr);
116 if (sr_val
== State::S1
) {
117 if (cell
->type
== ID($_DFF_N_
)) {
118 if (invert_sr
) cell
->type
= ID($__DFFS_NN1_
);
119 else cell
->type
= ID($__DFFS_NP1_
);
121 log_assert(cell
->type
== ID($_DFF_P_
));
122 if (invert_sr
) cell
->type
= ID($__DFFS_PN1_
);
123 else cell
->type
= ID($__DFFS_PP1_
);
126 if (cell
->type
== ID($_DFF_N_
)) {
127 if (invert_sr
) cell
->type
= ID($__DFFS_NN0_
);
128 else cell
->type
= ID($__DFFS_NP0_
);
130 log_assert(cell
->type
== ID($_DFF_P_
));
131 if (invert_sr
) cell
->type
= ID($__DFFS_PN0_
);
132 else cell
->type
= ID($__DFFS_PP0_
);
135 cell
->setPort(ID(\\R
), sr_sig
);
136 cell
->setPort(ID(\\D
), bit_d
);
142 PRIVATE_NAMESPACE_END