Add clock buffer insertion pass, improve iopadmap.
[yosys.git] / passes / techmap / clkbufmap.cc
1 /*
2 * yosys -- Yosys Open SYnthesis Suite
3 *
4 * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
5 *
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.
9 *
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.
17 *
18 */
19
20 #include "kernel/yosys.h"
21 #include "kernel/sigtools.h"
22
23 USING_YOSYS_NAMESPACE
24 PRIVATE_NAMESPACE_BEGIN
25
26 void split_portname_pair(std::string &port1, std::string &port2)
27 {
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);
32 }
33 }
34
35 std::vector<std::string> split(std::string text, const char *delim)
36 {
37 std::vector<std::string> list;
38 char *p = strdup(text.c_str());
39 char *t = strtok(p, delim);
40 while (t != NULL) {
41 list.push_back(t);
42 t = strtok(NULL, delim);
43 }
44 free(p);
45 return list;
46 }
47
48 struct ClkbufmapPass : public Pass {
49 ClkbufmapPass() : Pass("clkbufmap", "insert global buffers on clock networks") { }
50 void help() YS_OVERRIDE
51 {
52 log("\n");
53 log(" clkbufmap [options] [selection]\n");
54 log("\n");
55 log("Inserts global buffers between nets connected to clock inputs and their\n");
56 log("drivers.\n");
57 log("\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");
63 log("\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");
68 log("\n");
69 }
70
71 void module_queue(Design *design, Module *module, std::vector<Module *> &modules_sorted, pool<Module *> &modules_processed) {
72 if (modules_processed.count(module))
73 return;
74 for (auto cell : module->cells()) {
75 Module *submodule = design->module(cell->type);
76 if (!submodule)
77 continue;
78 module_queue(design, submodule, modules_sorted, modules_processed);
79 }
80 modules_sorted.push_back(module);
81 modules_processed.insert(module);
82 }
83
84 void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
85 {
86 log_header(design, "Executing CLKBUFMAP pass (inserting global clock buffers).\n");
87
88 std::string buf_celltype, buf_portname, buf_portname2;
89 std::string inpad_celltype, inpad_portname, inpad_portname2;
90
91 size_t argidx;
92 for (argidx = 1; argidx < args.size(); argidx++)
93 {
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);
99 continue;
100 }
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);
105 continue;
106 }
107 break;
108 }
109 extra_args(args, argidx, design);
110
111 if (buf_celltype.empty())
112 log_error("The -buf option is required.");
113
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;
117
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);
123
124 for (auto module : modules_sorted)
125 {
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));
132 if (!wire)
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)));
136 }
137 }
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));
143 if (!wire)
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)));
147 }
148 }
149 continue;
150 }
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;
157
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]));
164
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]));
171
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]);
178
179 // Insert buffers.
180 std::vector<pair<Wire *, Wire *>> input_queue;
181 for (auto wire : module->selected_wires())
182 {
183 // Should not happen.
184 if (wire->port_input && wire->port_output)
185 continue;
186 if (wire->get_bool_attribute("\\clkbuf_inhibit"))
187 continue;
188
189 pool<int> input_bits;
190
191 for (int i = 0; i < GetSize(wire); i++)
192 {
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)) {
200 // Nothing to do.
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.
204
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);
216 }
217 buffered_bits[mapped_wire_bit] = make_pair(cell, iwire);
218
219 if (wire->port_input) {
220 input_bits.insert(i);
221 }
222 } else if (wire->port_input) {
223 // A clock input in a submodule -- mark it, let higher level
224 // worry about it.
225 if (wire->port_input)
226 sink_ports.insert(make_pair(module->name, make_pair(wire->name, i)));
227 }
228 }
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);
233
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()) {
239
240 module->connect(it->second.second, SigSpec(new_wire, i));
241 } else {
242 module->connect(SigSpec(wire, i), SigSpec(new_wire, i));
243 }
244 }
245 input_queue.push_back(make_pair(wire, new_wire));
246 }
247 }
248
249 // Mark any newly-buffered output ports as such.
250 for (auto wire : module->selected_wires()) {
251 if (wire->port_input || !wire->port_output)
252 continue;
253 for (int i = 0; i < GetSize(wire); i++)
254 {
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)));
259 }
260 }
261
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))
266 continue;
267 SigSpec sig = port.second;
268 bool newsig = false;
269 for (auto &bit : sig) {
270 const auto it = buffered_bits.find(sigmap(bit));
271 if (it == buffered_bits.end())
272 continue;
273 // Avoid substituting buffer's own output pin.
274 if (cell == it->second.first)
275 continue;
276 bit = it->second.second;
277 newsig = true;
278 }
279 if (newsig)
280 cell->setPort(port.first, sig);
281 }
282
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();
289 wire->port_id = 0;
290 wire->port_input = false;
291 wire->port_output = false;
292 }
293
294 module->fixup_ports();
295 }
296 }
297 } ClkbufmapPass;
298
299 PRIVATE_NAMESPACE_END