1 /*
2 * yosys -- Yosys Open SYnthesis Suite
3 *
4 * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.com>
5 * Copyright (C) 2019 Marcelina Kościelnicka <mwk@0x04.net>
6 *
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.
10 *
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.
18 *
19 */
20
21 #include "kernel/yosys.h"
22 #include "kernel/sigtools.h"
23
24 USING_YOSYS_NAMESPACE
25 PRIVATE_NAMESPACE_BEGIN
26
split_portname_pair(std::string & port1,std::string & port2)27 void split_portname_pair(std::string &port1, std::string &port2)
28 {
29 size_t pos = port1.find_first_of(':');
30 if (pos != std::string::npos) {
31 port2 = port1.substr(pos+1);
32 port1 = port1.substr(0, pos);
33 }
34 }
35
36 struct ClkbufmapPass : public Pass {
ClkbufmapPassClkbufmapPass37 ClkbufmapPass() : Pass("clkbufmap", "insert clock buffers on clock networks") { }
helpClkbufmapPass38 void help() override
39 {
40 // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
41 log("\n");
42 log(" clkbufmap [options] [selection]\n");
43 log("\n");
44 log("Inserts clock buffers between nets connected to clock inputs and their drivers.\n");
45 log("\n");
46 log("In the absence of any selection, all wires without the 'clkbuf_inhibit'\n");
47 log("attribute will be considered for clock buffer insertion.\n");
48 log("Alternatively, to consider all wires without the 'buffer_type' attribute set to\n");
49 log("'none' or 'bufr' one would specify:\n");
50 log(" 'w:* a:buffer_type=none a:buffer_type=bufr %%u %%d'\n");
51 log("as the selection.\n");
52 log("\n");
53 log(" -buf <celltype> <portname_out>:<portname_in>\n");
54 log(" Specifies the cell type to use for the clock buffers\n");
55 log(" and its port names. The first port will be connected to\n");
56 log(" the clock network sinks, and the second will be connected\n");
57 log(" to the actual clock source.\n");
58 log("\n");
59 log(" -inpad <celltype> <portname_out>:<portname_in>\n");
60 log(" If specified, a PAD cell of the given type is inserted on\n");
61 log(" clock nets that are also top module's inputs (in addition\n");
62 log(" to the clock buffer, if any).\n");
63 log("\n");
64 log("At least one of -buf or -inpad should be specified.\n");
65 }
66
module_queueClkbufmapPass67 void module_queue(Design *design, Module *module, std::vector<Module *> &modules_sorted, pool<Module *> &modules_processed) {
68 if (modules_processed.count(module))
69 return;
70 for (auto cell : module->cells()) {
71 Module *submodule = design->module(cell->type);
72 if (!submodule)
73 continue;
74 module_queue(design, submodule, modules_sorted, modules_processed);
75 }
76 modules_sorted.push_back(module);
77 modules_processed.insert(module);
78 }
79
executeClkbufmapPass80 void execute(std::vector<std::string> args, RTLIL::Design *design) override
81 {
82 log_header(design, "Executing CLKBUFMAP pass (inserting clock buffers).\n");
83
84 std::string buf_celltype, buf_portname, buf_portname2;
85 std::string inpad_celltype, inpad_portname, inpad_portname2;
86
87 size_t argidx;
88 for (argidx = 1; argidx < args.size(); argidx++)
89 {
90 std::string arg = args[argidx];
91 if (arg == "-buf" && argidx+2 < args.size()) {
92 buf_celltype = args[++argidx];
93 buf_portname = args[++argidx];
94 split_portname_pair(buf_portname, buf_portname2);
95 continue;
96 }
97 if (arg == "-inpad" && argidx+2 < args.size()) {
98 inpad_celltype = args[++argidx];
99 inpad_portname = args[++argidx];
100 split_portname_pair(inpad_portname, inpad_portname2);
101 continue;
102 }
103 break;
104 }
105
106 bool select = false;
107 if (argidx < args.size()) {
108 if (args[argidx].compare(0, 1, "-") != 0)
109 select = true;
110 extra_args(args, argidx, design);
111 }
112
113 if (buf_celltype.empty() && inpad_celltype.empty())
114 log_error("Either the -buf option or -inpad option is required.\n");
115
116 // Cell type, port name, bit index.
117 pool<pair<IdString, pair<IdString, int>>> sink_ports;
118 pool<pair<IdString, pair<IdString, int>>> buf_ports;
119 dict<pair<IdString, pair<IdString, int>>, pair<IdString, int>> inv_ports_out;
120 dict<pair<IdString, pair<IdString, int>>, pair<IdString, int>> inv_ports_in;
121
122 // If true, use both ther -buf and -inpad cell for input ports that are clocks.
123 bool buffer_inputs = true;
124
125 Module *inpad_mod = design->module(RTLIL::escape_id(inpad_celltype));
126 if (inpad_mod) {
127 Wire *buf_wire = inpad_mod->wire(RTLIL::escape_id(buf_portname));
128 if (buf_wire && buf_wire->get_bool_attribute(ID::clkbuf_driver))
129 buffer_inputs = false;
130 }
131
132 // Process submodules before module using them.
133 std::vector<Module *> modules_sorted;
134 pool<Module *> modules_processed;
135 for (auto module : design->selected_modules())
136 module_queue(design, module, modules_sorted, modules_processed);
137
138 for (auto module : modules_sorted)
139 {
140 if (module->get_blackbox_attribute()) {
141 for (auto port : module->ports) {
142 auto wire = module->wire(port);
143 if (wire->get_bool_attribute(ID::clkbuf_driver))
144 for (int i = 0; i < GetSize(wire); i++)
145 buf_ports.insert(make_pair(module->name, make_pair(wire->name, i)));
146 if (wire->get_bool_attribute(ID::clkbuf_sink))
147 for (int i = 0; i < GetSize(wire); i++)
148 sink_ports.insert(make_pair(module->name, make_pair(wire->name, i)));
149 auto it = wire->attributes.find(ID::clkbuf_inv);
150 if (it != wire->attributes.end()) {
151 IdString in_name = RTLIL::escape_id(it->second.decode_string());
152 for (int i = 0; i < GetSize(wire); i++) {
153 inv_ports_out[make_pair(module->name, make_pair(wire->name, i))] = make_pair(in_name, i);
154 inv_ports_in[make_pair(module->name, make_pair(in_name, i))] = make_pair(wire->name, i);
155 }
156 }
157 }
158 continue;
159 }
160 pool<SigBit> sink_wire_bits;
161 pool<SigBit> buf_wire_bits;
162 pool<SigBit> driven_wire_bits;
163 SigMap sigmap(module);
164 // bit -> (buffer, buffer's input)
165 dict<SigBit, pair<Cell *, Wire *>> buffered_bits;
166
167 // First, collect nets that could use a clock buffer.
168 for (auto cell : module->cells())
169 for (auto port : cell->connections())
170 for (int i = 0; i < port.second.size(); i++)
171 if (sink_ports.count(make_pair(cell->type, make_pair(port.first, i))))
172 sink_wire_bits.insert(sigmap(port.second[i]));
173
174 // Second, collect ones that already have a clock buffer.
175 for (auto cell : module->cells())
176 for (auto port : cell->connections())
177 for (int i = 0; i < port.second.size(); i++)
178 if (buf_ports.count(make_pair(cell->type, make_pair(port.first, i))))
179 buf_wire_bits.insert(sigmap(port.second[i]));
180
181 // Third, propagate tags through inverters.
182 bool retry = true;
183 while (retry) {
184 retry = false;
185 for (auto cell : module->cells())
186 for (auto port : cell->connections())
187 for (int i = 0; i < port.second.size(); i++) {
188 auto it = inv_ports_out.find(make_pair(cell->type, make_pair(port.first, i)));
189 auto bit = sigmap(port.second[i]);
190 // If output of an inverter is connected to a sink, mark it as buffered,
191 // and request a buffer on the inverter's input instead.
192 if (it != inv_ports_out.end() && !buf_wire_bits.count(bit) && sink_wire_bits.count(bit)) {
193 buf_wire_bits.insert(bit);
194 auto other_bit = sigmap(cell->getPort(it->second.first)[it->second.second]);
195 sink_wire_bits.insert(other_bit);
196 retry = true;
197 }
198 // If input of an inverter is marked as already-buffered,
199 // mark its output already-buffered as well.
200 auto it2 = inv_ports_in.find(make_pair(cell->type, make_pair(port.first, i)));
201 if (it2 != inv_ports_in.end() && buf_wire_bits.count(bit)) {
202 auto other_bit = sigmap(cell->getPort(it2->second.first)[it2->second.second]);
203 if (!buf_wire_bits.count(other_bit)) {
204 buf_wire_bits.insert(other_bit);
205 retry = true;
206 }
207 }
208
209 }
210 };
211
212 // Collect all driven bits.
213 for (auto cell : module->cells())
214 for (auto port : cell->connections())
215 if (cell->output(port.first))
216 for (int i = 0; i < port.second.size(); i++)
217 driven_wire_bits.insert(port.second[i]);
218
219 // Insert buffers.
220 std::vector<pair<Wire *, Wire *>> input_queue;
221 // Copy current wire list, as we will be adding new ones during iteration.
222 std::vector<Wire *> wires(module->wires());
223 for (auto wire : wires)
224 {
225 // Should not happen.
226 if (wire->port_input && wire->port_output)
227 continue;
228 bool process_wire = module->selected(wire);
229 if (!select && wire->get_bool_attribute(ID::clkbuf_inhibit))
230 process_wire = false;
231 if (!process_wire) {
232 // This wire is supposed to be bypassed, so make sure we don't buffer it in
233 // some buffer higher up in the hierarchy.
234 if (wire->port_output)
235 for (int i = 0; i < GetSize(wire); i++)
236 buf_ports.insert(make_pair(module->name, make_pair(wire->name, i)));
237 continue;
238 }
239
240 pool<int> input_bits;
241
242 for (int i = 0; i < GetSize(wire); i++)
243 {
244 SigBit wire_bit(wire, i);
245 SigBit mapped_wire_bit = sigmap(wire_bit);
246 if (buf_wire_bits.count(mapped_wire_bit)) {
247 // Already buffered downstream. If this is an output, mark it.
248 if (wire->port_output)
249 buf_ports.insert(make_pair(module->name, make_pair(wire->name, i)));
250 } else if (!sink_wire_bits.count(mapped_wire_bit)) {
251 // Nothing to do.
252 } else if (driven_wire_bits.count(wire_bit) || (wire->port_input && module->get_bool_attribute(ID::top))) {
253 // Clock network not yet buffered, driven by one of
254 // our cells or a top-level input -- buffer it.
255
256 Wire *iwire = nullptr;
257 RTLIL::Cell *cell = nullptr;
258 bool is_input = wire->port_input && !inpad_celltype.empty() && module->get_bool_attribute(ID::top);
259 if (!buf_celltype.empty() && (!is_input || buffer_inputs)) {
260 log("Inserting %s on %s.%s[%d].\n", buf_celltype.c_str(), log_id(module), log_id(wire), i);
261 cell = module->addCell(NEW_ID, RTLIL::escape_id(buf_celltype));
262 iwire = module->addWire(NEW_ID);
263 cell->setPort(RTLIL::escape_id(buf_portname), mapped_wire_bit);
264 cell->setPort(RTLIL::escape_id(buf_portname2), iwire);
265 }
266 if (is_input) {
267 log("Inserting %s on %s.%s[%d].\n", inpad_celltype.c_str(), log_id(module), log_id(wire), i);
268 RTLIL::Cell *cell2 = module->addCell(NEW_ID, RTLIL::escape_id(inpad_celltype));
269 if (iwire) {
270 cell2->setPort(RTLIL::escape_id(inpad_portname), iwire);
271 } else {
272 cell2->setPort(RTLIL::escape_id(inpad_portname), mapped_wire_bit);
273 cell = cell2;
274 }
275 iwire = module->addWire(NEW_ID);
276 cell2->setPort(RTLIL::escape_id(inpad_portname2), iwire);
277 }
278 if (iwire)
279 buffered_bits[mapped_wire_bit] = make_pair(cell, iwire);
280
281 if (wire->port_input) {
282 input_bits.insert(i);
283 }
284 } else if (wire->port_input) {
285 // A clock input in a submodule -- mark it, let higher level
286 // worry about it.
287 if (wire->port_input)
288 sink_ports.insert(make_pair(module->name, make_pair(wire->name, i)));
289 }
290 }
291 if (!input_bits.empty()) {
292 // This is an input port and some buffers were inserted -- we need
293 // to create a new input wire and transfer attributes.
294 Wire *new_wire = module->addWire(NEW_ID, wire);
295
296 for (int i = 0; i < wire->width; i++) {
297 SigBit wire_bit(wire, i);
298 SigBit mapped_wire_bit = sigmap(wire_bit);
299 auto it = buffered_bits.find(mapped_wire_bit);
300 if (it != buffered_bits.end()) {
301
302 module->connect(it->second.second, SigSpec(new_wire, i));
303 } else {
304 module->connect(SigSpec(wire, i), SigSpec(new_wire, i));
305 }
306 }
307 input_queue.push_back(make_pair(wire, new_wire));
308 }
309 }
310
311 // Mark any newly-buffered output ports as such.
312 for (auto wire : module->selected_wires()) {
313 if (wire->port_input || !wire->port_output)
314 continue;
315 for (int i = 0; i < GetSize(wire); i++)
316 {
317 SigBit wire_bit(wire, i);
318 SigBit mapped_wire_bit = sigmap(wire_bit);
319 if (buffered_bits.count(mapped_wire_bit))
320 buf_ports.insert(make_pair(module->name, make_pair(wire->name, i)));
321 }
322 }
323
324 // Reconnect the drivers to buffer inputs.
325 for (auto cell : module->cells())
326 for (auto port : cell->connections()) {
327 if (!cell->output(port.first))
328 continue;
329 SigSpec sig = port.second;
330 bool newsig = false;
331 for (auto &bit : sig) {
332 const auto it = buffered_bits.find(sigmap(bit));
333 if (it == buffered_bits.end())
334 continue;
335 // Avoid substituting buffer's own output pin.
336 if (cell == it->second.first)
337 continue;
338 bit = it->second.second;
339 newsig = true;
340 }
341 if (newsig)
342 cell->setPort(port.first, sig);
343 }
344
345 // This has to be done last, to avoid upsetting sigmap before the port reconnections.
346 for (auto &it : input_queue) {
347 Wire *wire = it.first;
348 Wire *new_wire = it.second;
349 module->swap_names(new_wire, wire);
350 wire->attributes.clear();
351 wire->port_id = 0;
352 wire->port_input = false;
353 wire->port_output = false;
354 }
355
356 module->fixup_ports();
357 }
358 }
359 } ClkbufmapPass;
360
361 PRIVATE_NAMESPACE_END
362