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