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_latch
= cell_type
.find("LATCH") != string::npos
;
30 bool cell_type_i
= cell_type
.find('I') != string::npos
;
31 bool cell_type_r
= cell_type
.find('R') != string::npos
;
32 bool cell_type_s
= cell_type
.find('S') != string::npos
;
36 Const initval
= cell
->getParam("\\INIT");
37 if (GetSize(initval
) >= 1) {
38 if (initval
.bits
[0] == State::S0
)
39 initval
.bits
[0] = State::S1
;
40 else if (initval
.bits
[0] == State::S1
)
41 initval
.bits
[0] = State::S0
;
42 cell
->setParam("\\INIT", initval
);
45 if (cell_type_r
&& cell_type_s
)
47 Const srmode
= cell
->getParam("\\SRMODE");
48 if (GetSize(srmode
) >= 1) {
49 if (srmode
.bits
[0] == State::S0
)
50 srmode
.bits
[0] = State::S1
;
51 else if (srmode
.bits
[0] == State::S1
)
52 srmode
.bits
[0] = State::S0
;
53 cell
->setParam("\\SRMODE", srmode
);
59 cell
->setPort("\\nSET", cell
->getPort("\\nRST"));
60 cell
->unsetPort("\\nRST");
65 cell
->setPort("\\nRST", cell
->getPort("\\nSET"));
66 cell
->unsetPort("\\nSET");
74 cell
->setPort("\\Q", cell
->getPort("\\nQ"));
75 cell
->unsetPort("\\nQ");
78 cell
->setPort("\\nQ", cell
->getPort("\\Q"));
79 cell
->unsetPort("\\Q");
84 cell
->type
= stringf("\\GP_DLATCH%s%s%s", cell_type_s
? "S" : "", cell_type_r
? "R" : "", cell_type_i
? "I" : "");
86 cell
->type
= stringf("\\GP_DFF%s%s%s", cell_type_s
? "S" : "", cell_type_r
? "R" : "", cell_type_i
? "I" : "");
88 log("Merged %s inverter into cell %s.%s: %s -> %s\n", invert_input
? "input" : "output",
89 log_id(cell
->module
), log_id(cell
), cell_type
.c_str()+1, log_id(cell
->type
));
92 struct Greenpak4DffInvPass
: public Pass
{
93 Greenpak4DffInvPass() : Pass("greenpak4_dffinv", "merge greenpak4 inverters and DFF/latches") { }
94 void help() YS_OVERRIDE
97 log(" greenpak4_dffinv [options] [selection]\n");
99 log("Merge GP_INV cells with GP_DFF* and GP_DLATCH* cells.\n");
102 void execute(std::vector
<std::string
> args
, RTLIL::Design
*design
) YS_OVERRIDE
104 log_header(design
, "Executing GREENPAK4_DFFINV pass (merge input/output inverters into FF/latch cells).\n");
107 for (argidx
= 1; argidx
< args
.size(); argidx
++)
109 // if (args[argidx] == "-singleton") {
110 // singleton_mode = true;
115 extra_args(args
, argidx
, design
);
117 pool
<IdString
> gp_dff_types
;
118 gp_dff_types
.insert("\\GP_DFF");
119 gp_dff_types
.insert("\\GP_DFFI");
120 gp_dff_types
.insert("\\GP_DFFR");
121 gp_dff_types
.insert("\\GP_DFFRI");
122 gp_dff_types
.insert("\\GP_DFFS");
123 gp_dff_types
.insert("\\GP_DFFSI");
124 gp_dff_types
.insert("\\GP_DFFSR");
125 gp_dff_types
.insert("\\GP_DFFSRI");
127 gp_dff_types
.insert("\\GP_DLATCH");
128 gp_dff_types
.insert("\\GP_DLATCHI");
129 gp_dff_types
.insert("\\GP_DLATCHR");
130 gp_dff_types
.insert("\\GP_DLATCHRI");
131 gp_dff_types
.insert("\\GP_DLATCHS");
132 gp_dff_types
.insert("\\GP_DLATCHSI");
133 gp_dff_types
.insert("\\GP_DLATCHSR");
134 gp_dff_types
.insert("\\GP_DLATCHSRI");
136 for (auto module
: design
->selected_modules())
138 SigMap
sigmap(module
);
139 dict
<SigBit
, int> sig_use_cnt
;
140 dict
<SigBit
, SigBit
> inv_in2out
, inv_out2in
;
141 dict
<SigBit
, Cell
*> inv_in2cell
;
142 pool
<Cell
*> dff_cells
;
144 for (auto wire
: module
->wires())
146 if (!wire
->port_output
)
149 for (auto bit
: sigmap(wire
))
153 for (auto cell
: module
->cells())
154 for (auto &conn
: cell
->connections())
155 if (cell
->input(conn
.first
) || !cell
->known())
156 for (auto bit
: sigmap(conn
.second
))
159 for (auto cell
: module
->selected_cells())
161 if (gp_dff_types
.count(cell
->type
)) {
162 dff_cells
.insert(cell
);
166 if (cell
->type
== "\\GP_INV") {
167 SigBit in_bit
= sigmap(cell
->getPort("\\IN"));
168 SigBit out_bit
= sigmap(cell
->getPort("\\OUT"));
169 inv_in2out
[in_bit
] = out_bit
;
170 inv_out2in
[out_bit
] = in_bit
;
171 inv_in2cell
[in_bit
] = cell
;
176 for (auto cell
: dff_cells
)
178 SigBit d_bit
= sigmap(cell
->getPort("\\D"));
179 SigBit q_bit
= sigmap(cell
->hasPort("\\Q") ? cell
->getPort("\\Q") : cell
->getPort("\\nQ"));
181 while (inv_out2in
.count(d_bit
))
183 sig_use_cnt
[d_bit
]--;
184 invert_gp_dff(cell
, true);
185 d_bit
= inv_out2in
.at(d_bit
);
186 cell
->setPort("\\D", d_bit
);
187 sig_use_cnt
[d_bit
]++;
190 while (inv_in2out
.count(q_bit
) && sig_use_cnt
[q_bit
] == 1)
192 SigBit new_q_bit
= inv_in2out
.at(q_bit
);
193 module
->remove(inv_in2cell
.at(q_bit
));
194 sig_use_cnt
.erase(q_bit
);
195 inv_in2out
.erase(q_bit
);
196 inv_out2in
.erase(new_q_bit
);
197 inv_in2cell
.erase(q_bit
);
199 invert_gp_dff(cell
, false);
200 if (cell
->hasPort("\\Q"))
201 cell
->setPort("\\Q", new_q_bit
);
203 cell
->setPort("\\nQ", new_q_bit
);
208 } Greenpak4DffInvPass
;
210 PRIVATE_NAMESPACE_END