ff63958e6d0e20b23625ef9e52463cc9df26846e
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 void invert_gp_dff(Cell
*cell
, bool invert_input
)
28 string cell_type
= cell
->type
.str();
29 bool cell_type_i
= cell_type
.find('I') != string::npos
;
30 bool cell_type_r
= cell_type
.find('R') != string::npos
;
31 bool cell_type_s
= cell_type
.find('S') != string::npos
;
35 Const initval
= cell
->getParam("\\INIT");
36 if (GetSize(initval
) >= 1) {
37 if (initval
.bits
[0] == State::S0
)
38 initval
.bits
[0] = State::S1
;
39 else if (initval
.bits
[0] == State::S1
)
40 initval
.bits
[0] = State::S0
;
41 cell
->setParam("\\INIT", initval
);
44 if (cell_type_r
&& cell_type_s
)
46 Const srmode
= cell
->getParam("\\SRMODE");
47 if (GetSize(srmode
) >= 1) {
48 if (srmode
.bits
[0] == State::S0
)
49 srmode
.bits
[0] = State::S1
;
50 else if (srmode
.bits
[0] == State::S1
)
51 srmode
.bits
[0] = State::S0
;
52 cell
->setParam("\\SRMODE", srmode
);
58 cell
->setPort("\\nSET", cell
->getPort("\\nRST"));
59 cell
->unsetPort("\\nRST");
64 cell
->setPort("\\nRST", cell
->getPort("\\nSET"));
65 cell
->unsetPort("\\nSET");
73 cell
->setPort("\\Q", cell
->getPort("\\nQ"));
74 cell
->unsetPort("\\nQ");
77 cell
->setPort("\\nQ", cell
->getPort("\\Q"));
78 cell
->unsetPort("\\Q");
82 cell
->type
= stringf("\\GP_DFF%s%s%s", cell_type_s
? "S" : "", cell_type_r
? "R" : "", cell_type_i
? "I" : "");
84 log("Merged %s inverter into cell %s.%s: %s -> %s\n", invert_input
? "input" : "output",
85 log_id(cell
->module
), log_id(cell
), cell_type
.c_str()+1, log_id(cell
->type
));
88 struct Greenpak4DffInvPass
: public Pass
{
89 Greenpak4DffInvPass() : Pass("greenpak4_dffinv", "merge greenpak4 inverters and DFFs") { }
93 log(" greenpak4_dffinv [options] [selection]\n");
95 log("Merge GP_INV cells with GP_DFF* cells.\n");
98 virtual void execute(std::vector
<std::string
> args
, RTLIL::Design
*design
)
100 log_header(design
, "Executing GREENPAK4_DFFINV pass (merge synchronous set/reset into FF cells).\n");
103 for (argidx
= 1; argidx
< args
.size(); argidx
++)
105 // if (args[argidx] == "-singleton") {
106 // singleton_mode = true;
111 extra_args(args
, argidx
, design
);
113 pool
<IdString
> gp_dff_types
;
114 gp_dff_types
.insert("\\GP_DFF");
115 gp_dff_types
.insert("\\GP_DFFI");
116 gp_dff_types
.insert("\\GP_DFFR");
117 gp_dff_types
.insert("\\GP_DFFRI");
118 gp_dff_types
.insert("\\GP_DFFS");
119 gp_dff_types
.insert("\\GP_DFFSI");
120 gp_dff_types
.insert("\\GP_DFFSR");
121 gp_dff_types
.insert("\\GP_DFFSRI");
123 for (auto module
: design
->selected_modules())
125 SigMap
sigmap(module
);
126 dict
<SigBit
, int> sig_use_cnt
;
127 dict
<SigBit
, SigBit
> inv_in2out
, inv_out2in
;
128 dict
<SigBit
, Cell
*> inv_in2cell
;
129 pool
<Cell
*> dff_cells
;
131 for (auto wire
: module
->wires())
133 if (!wire
->port_output
)
136 for (auto bit
: sigmap(wire
))
140 for (auto cell
: module
->cells())
141 for (auto &conn
: cell
->connections())
142 if (cell
->input(conn
.first
) || !cell
->known())
143 for (auto bit
: sigmap(conn
.second
))
146 for (auto cell
: module
->selected_cells())
148 if (gp_dff_types
.count(cell
->type
)) {
149 dff_cells
.insert(cell
);
153 if (cell
->type
== "\\GP_INV") {
154 SigBit in_bit
= sigmap(cell
->getPort("\\IN"));
155 SigBit out_bit
= sigmap(cell
->getPort("\\OUT"));
156 inv_in2out
[in_bit
] = out_bit
;
157 inv_out2in
[out_bit
] = in_bit
;
158 inv_in2cell
[in_bit
] = cell
;
163 for (auto cell
: dff_cells
)
165 SigBit d_bit
= sigmap(cell
->getPort("\\D"));
166 SigBit q_bit
= sigmap(cell
->hasPort("\\Q") ? cell
->getPort("\\Q") : cell
->getPort("\\nQ"));
168 while (inv_out2in
.count(d_bit
))
170 sig_use_cnt
[d_bit
]--;
171 invert_gp_dff(cell
, true);
172 d_bit
= inv_out2in
.at(d_bit
);
173 cell
->setPort("\\D", d_bit
);
174 sig_use_cnt
[d_bit
]++;
177 while (inv_in2out
.count(q_bit
) && sig_use_cnt
[q_bit
] == 1)
179 SigBit new_q_bit
= inv_in2out
.at(q_bit
);
180 module
->remove(inv_in2cell
.at(q_bit
));
181 sig_use_cnt
.erase(q_bit
);
182 inv_in2out
.erase(q_bit
);
183 inv_out2in
.erase(new_q_bit
);
184 inv_in2cell
.erase(q_bit
);
186 invert_gp_dff(cell
, false);
187 if (cell
->hasPort("\\Q"))
188 cell
->setPort("\\Q", new_q_bit
);
190 cell
->setPort("\\nQ", new_q_bit
);
195 } Greenpak4DffInvPass
;
197 PRIVATE_NAMESPACE_END