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 split_portname_pair(std::string
&port1
, std::string
&port2
)
28 size_t pos
= port1
.find_first_of(':');
29 if (pos
!= std::string::npos
) {
30 port2
= port1
.substr(pos
+1);
31 port1
= port1
.substr(0, pos
);
35 std::vector
<std::string
> split(std::string text
, const char *delim
)
37 std::vector
<std::string
> list
;
38 char *p
= strdup(text
.c_str());
39 char *t
= strtok(p
, delim
);
42 t
= strtok(NULL
, delim
);
48 struct ClkbufmapPass
: public Pass
{
49 ClkbufmapPass() : Pass("clkbufmap", "insert global buffers on clock networks") { }
50 void help() YS_OVERRIDE
53 log(" clkbufmap [options] [selection]\n");
55 log("Inserts global buffers between nets connected to clock inputs and their\n");
58 log(" -buf <celltype> <portname_out>:<portname_in>\n");
59 log(" Specifies the cell type to use for the global buffers\n");
60 log(" and its port names. The first port will be connected to\n");
61 log(" the clock network sinks, and the second will be connected\n");
62 log(" to the actual clock source. This option is required.\n");
64 log(" -inpad <celltype> <portname_out>:<portname_in>\n");
65 log(" If specified, a PAD cell of the given type is inserted on\n");
66 log(" clock nets that are also top module's inputs (in addition\n");
67 log(" to the global buffer).\n");
71 void module_queue(Design
*design
, Module
*module
, std::vector
<Module
*> &modules_sorted
, pool
<Module
*> &modules_processed
) {
72 if (modules_processed
.count(module
))
74 for (auto cell
: module
->cells()) {
75 Module
*submodule
= design
->module(cell
->type
);
78 module_queue(design
, submodule
, modules_sorted
, modules_processed
);
80 modules_sorted
.push_back(module
);
81 modules_processed
.insert(module
);
84 void execute(std::vector
<std::string
> args
, RTLIL::Design
*design
) YS_OVERRIDE
86 log_header(design
, "Executing CLKBUFMAP pass (inserting global clock buffers).\n");
88 std::string buf_celltype
, buf_portname
, buf_portname2
;
89 std::string inpad_celltype
, inpad_portname
, inpad_portname2
;
92 for (argidx
= 1; argidx
< args
.size(); argidx
++)
94 std::string arg
= args
[argidx
];
95 if (arg
== "-buf" && argidx
+2 < args
.size()) {
96 buf_celltype
= args
[++argidx
];
97 buf_portname
= args
[++argidx
];
98 split_portname_pair(buf_portname
, buf_portname2
);
101 if (arg
== "-inpad" && argidx
+2 < args
.size()) {
102 inpad_celltype
= args
[++argidx
];
103 inpad_portname
= args
[++argidx
];
104 split_portname_pair(inpad_portname
, inpad_portname2
);
109 extra_args(args
, argidx
, design
);
111 if (buf_celltype
.empty())
112 log_error("The -buf option is required.");
114 // Cell type, port name, bit index.
115 pool
<pair
<IdString
, pair
<IdString
, int>>> sink_ports
;
116 pool
<pair
<IdString
, pair
<IdString
, int>>> buf_ports
;
118 // Process submodules before module using them.
119 std::vector
<Module
*> modules_sorted
;
120 pool
<Module
*> modules_processed
;
121 for (auto module
: design
->selected_modules())
122 module_queue(design
, module
, modules_sorted
, modules_processed
);
124 for (auto module
: modules_sorted
)
126 if (module
->get_blackbox_attribute()) {
127 auto it
= module
->attributes
.find("\\clkbuf_driver");
128 if (it
!= module
->attributes
.end()) {
129 auto value
= it
->second
.decode_string();
130 for (auto name
: split(value
, ",")) {
131 auto wire
= module
->wire(RTLIL::escape_id(name
));
133 log_error("Module %s does not have port %s.\n", log_id(module
), log_id(name
));
134 for (int i
= 0; i
< GetSize(wire
); i
++)
135 buf_ports
.insert(make_pair(module
->name
, make_pair(RTLIL::escape_id(name
), i
)));
138 it
= module
->attributes
.find("\\clkbuf_sink");
139 if (it
!= module
->attributes
.end()) {
140 auto value
= it
->second
.decode_string();
141 for (auto name
: split(value
, ",")) {
142 auto wire
= module
->wire(RTLIL::escape_id(name
));
144 log_error("Module %s does not have port %s.\n", log_id(module
), log_id(name
));
145 for (int i
= 0; i
< GetSize(wire
); i
++)
146 sink_ports
.insert(make_pair(module
->name
, make_pair(RTLIL::escape_id(name
), i
)));
151 pool
<SigBit
> sink_wire_bits
;
152 pool
<SigBit
> buf_wire_bits
;
153 pool
<SigBit
> driven_wire_bits
;
154 SigMap
sigmap(module
);
155 // bit -> (buffer, buffer's input)
156 dict
<SigBit
, pair
<Cell
*, Wire
*>> buffered_bits
;
158 // First, collect nets that could use a clock buffer.
159 for (auto cell
: module
->cells())
160 for (auto port
: cell
->connections())
161 for (int i
= 0; i
< port
.second
.size(); i
++)
162 if (sink_ports
.count(make_pair(cell
->type
, make_pair(port
.first
, i
))))
163 sink_wire_bits
.insert(sigmap(port
.second
[i
]));
165 // Second, collect ones that already have a clock buffer.
166 for (auto cell
: module
->cells())
167 for (auto port
: cell
->connections())
168 for (int i
= 0; i
< port
.second
.size(); i
++)
169 if (buf_ports
.count(make_pair(cell
->type
, make_pair(port
.first
, i
))))
170 buf_wire_bits
.insert(sigmap(port
.second
[i
]));
172 // Collect all driven bits.
173 for (auto cell
: module
->cells())
174 for (auto port
: cell
->connections())
175 if (cell
->output(port
.first
))
176 for (int i
= 0; i
< port
.second
.size(); i
++)
177 driven_wire_bits
.insert(port
.second
[i
]);
180 std::vector
<pair
<Wire
*, Wire
*>> input_queue
;
181 for (auto wire
: module
->selected_wires())
183 // Should not happen.
184 if (wire
->port_input
&& wire
->port_output
)
186 if (wire
->get_bool_attribute("\\clkbuf_inhibit"))
189 pool
<int> input_bits
;
191 for (int i
= 0; i
< GetSize(wire
); i
++)
193 SigBit
wire_bit(wire
, i
);
194 SigBit mapped_wire_bit
= sigmap(wire_bit
);
195 if (buf_wire_bits
.count(mapped_wire_bit
)) {
196 // Already buffered downstream. If this is an output, mark it.
197 if (wire
->port_output
)
198 buf_ports
.insert(make_pair(module
->name
, make_pair(wire
->name
, i
)));
199 } else if (!sink_wire_bits
.count(mapped_wire_bit
)) {
201 } else if (driven_wire_bits
.count(wire_bit
) || (wire
->port_input
&& module
->get_bool_attribute("\\top"))) {
202 // Clock network not yet buffered, driven by one of
203 // our cells or a top-level input -- buffer it.
205 log("Inserting %s on %s.%s[%d].\n", buf_celltype
.c_str(), log_id(module
), log_id(wire
), i
);
206 RTLIL::Cell
*cell
= module
->addCell(NEW_ID
, RTLIL::escape_id(buf_celltype
));
207 Wire
*iwire
= module
->addWire(NEW_ID
);
208 cell
->setPort(RTLIL::escape_id(buf_portname
), mapped_wire_bit
);
209 cell
->setPort(RTLIL::escape_id(buf_portname2
), iwire
);
210 if (wire
->port_input
&& !inpad_celltype
.empty() && module
->get_bool_attribute("\\top")) {
211 log("Inserting %s on %s.%s[%d].\n", inpad_celltype
.c_str(), log_id(module
), log_id(wire
), i
);
212 RTLIL::Cell
*cell2
= module
->addCell(NEW_ID
, RTLIL::escape_id(inpad_celltype
));
213 cell2
->setPort(RTLIL::escape_id(inpad_portname
), iwire
);
214 iwire
= module
->addWire(NEW_ID
);
215 cell2
->setPort(RTLIL::escape_id(inpad_portname2
), iwire
);
217 buffered_bits
[mapped_wire_bit
] = make_pair(cell
, iwire
);
219 if (wire
->port_input
) {
220 input_bits
.insert(i
);
222 } else if (wire
->port_input
) {
223 // A clock input in a submodule -- mark it, let higher level
225 if (wire
->port_input
)
226 sink_ports
.insert(make_pair(module
->name
, make_pair(wire
->name
, i
)));
229 if (!input_bits
.empty()) {
230 // This is an input port and some buffers were inserted -- we need
231 // to create a new input wire and transfer attributes.
232 Wire
*new_wire
= module
->addWire(NEW_ID
, wire
);
234 for (int i
= 0; i
< wire
->width
; i
++) {
235 SigBit
wire_bit(wire
, i
);
236 SigBit mapped_wire_bit
= sigmap(wire_bit
);
237 auto it
= buffered_bits
.find(mapped_wire_bit
);
238 if (it
!= buffered_bits
.end()) {
240 module
->connect(it
->second
.second
, SigSpec(new_wire
, i
));
242 module
->connect(SigSpec(wire
, i
), SigSpec(new_wire
, i
));
245 input_queue
.push_back(make_pair(wire
, new_wire
));
249 // Mark any newly-buffered output ports as such.
250 for (auto wire
: module
->selected_wires()) {
251 if (wire
->port_input
|| !wire
->port_output
)
253 for (int i
= 0; i
< GetSize(wire
); i
++)
255 SigBit
wire_bit(wire
, i
);
256 SigBit mapped_wire_bit
= sigmap(wire_bit
);
257 if (buffered_bits
.count(mapped_wire_bit
))
258 buf_ports
.insert(make_pair(module
->name
, make_pair(wire
->name
, i
)));
262 // Reconnect the drivers to buffer inputs.
263 for (auto cell
: module
->cells())
264 for (auto port
: cell
->connections()) {
265 if (!cell
->output(port
.first
))
267 SigSpec sig
= port
.second
;
269 for (auto &bit
: sig
) {
270 const auto it
= buffered_bits
.find(sigmap(bit
));
271 if (it
== buffered_bits
.end())
273 // Avoid substituting buffer's own output pin.
274 if (cell
== it
->second
.first
)
276 bit
= it
->second
.second
;
280 cell
->setPort(port
.first
, sig
);
283 // This has to be done last, to avoid upsetting sigmap before the port reconnections.
284 for (auto &it
: input_queue
) {
285 Wire
*wire
= it
.first
;
286 Wire
*new_wire
= it
.second
;
287 module
->swap_names(new_wire
, wire
);
288 wire
->attributes
.clear();
290 wire
->port_input
= false;
291 wire
->port_output
= false;
294 module
->fixup_ports();
299 PRIVATE_NAMESPACE_END