d8a628448ffcabd0166300489cb021b4e6b986cd
[yosys.git] / passes / hierarchy / hierarchy.cc
1 /*
2 * yosys -- Yosys Open SYnthesis Suite
3 *
4 * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
5 * Copyright (C) 2018 Ruben Undheim <ruben.undheim@gmail.com>
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 "frontends/verific/verific.h"
23 #include <stdlib.h>
24 #include <stdio.h>
25 #include <set>
26
27 #ifndef _WIN32
28 # include <unistd.h>
29 #endif
30
31
32 USING_YOSYS_NAMESPACE
33 PRIVATE_NAMESPACE_BEGIN
34
35 struct generate_port_decl_t {
36 bool input, output;
37 string portname;
38 int index;
39 };
40
41 void generate(RTLIL::Design *design, const std::vector<std::string> &celltypes, const std::vector<generate_port_decl_t> &portdecls)
42 {
43 std::set<RTLIL::IdString> found_celltypes;
44
45 for (auto i1 : design->modules_)
46 for (auto i2 : i1.second->cells_)
47 {
48 RTLIL::Cell *cell = i2.second;
49 if (design->has(cell->type))
50 continue;
51 if (cell->type.begins_with("$__"))
52 continue;
53 for (auto &pattern : celltypes)
54 if (patmatch(pattern.c_str(), RTLIL::unescape_id(cell->type).c_str()))
55 found_celltypes.insert(cell->type);
56 }
57
58 for (auto &celltype : found_celltypes)
59 {
60 std::set<RTLIL::IdString> portnames;
61 std::set<RTLIL::IdString> parameters;
62 std::map<RTLIL::IdString, int> portwidths;
63 log("Generate module for cell type %s:\n", celltype.c_str());
64
65 for (auto i1 : design->modules_)
66 for (auto i2 : i1.second->cells_)
67 if (i2.second->type == celltype) {
68 for (auto &conn : i2.second->connections()) {
69 if (conn.first[0] != '$')
70 portnames.insert(conn.first);
71 portwidths[conn.first] = max(portwidths[conn.first], conn.second.size());
72 }
73 for (auto &para : i2.second->parameters)
74 parameters.insert(para.first);
75 }
76
77 for (auto &decl : portdecls)
78 if (decl.index > 0)
79 portnames.insert(decl.portname);
80
81 std::set<int> indices;
82 for (int i = 0; i < int(portnames.size()); i++)
83 indices.insert(i+1);
84
85 std::vector<generate_port_decl_t> ports(portnames.size());
86
87 for (auto &decl : portdecls)
88 if (decl.index > 0) {
89 portwidths[decl.portname] = max(portwidths[decl.portname], 1);
90 portwidths[decl.portname] = max(portwidths[decl.portname], portwidths[stringf("$%d", decl.index)]);
91 log(" port %d: %s [%d:0] %s\n", decl.index, decl.input ? decl.output ? "inout" : "input" : "output", portwidths[decl.portname]-1, RTLIL::id2cstr(decl.portname));
92 if (indices.count(decl.index) > ports.size())
93 log_error("Port index (%d) exceeds number of found ports (%d).\n", decl.index, int(ports.size()));
94 if (indices.count(decl.index) == 0)
95 log_error("Conflict on port index %d.\n", decl.index);
96 indices.erase(decl.index);
97 portnames.erase(decl.portname);
98 ports[decl.index-1] = decl;
99 }
100
101 while (portnames.size() > 0) {
102 RTLIL::IdString portname = *portnames.begin();
103 for (auto &decl : portdecls)
104 if (decl.index == 0 && patmatch(decl.portname.c_str(), RTLIL::unescape_id(portname).c_str())) {
105 generate_port_decl_t d = decl;
106 d.portname = portname.str();
107 d.index = *indices.begin();
108 log_assert(!indices.empty());
109 indices.erase(d.index);
110 ports[d.index-1] = d;
111 portwidths[d.portname] = max(portwidths[d.portname], 1);
112 log(" port %d: %s [%d:0] %s\n", d.index, d.input ? d.output ? "inout" : "input" : "output", portwidths[d.portname]-1, RTLIL::id2cstr(d.portname));
113 goto found_matching_decl;
114 }
115 log_error("Can't match port %s.\n", RTLIL::id2cstr(portname));
116 found_matching_decl:;
117 portnames.erase(portname);
118 }
119
120 log_assert(indices.empty());
121
122 RTLIL::Module *mod = new RTLIL::Module;
123 mod->name = celltype;
124 mod->attributes["\\blackbox"] = RTLIL::Const(1);
125 design->add(mod);
126
127 for (auto &decl : ports) {
128 RTLIL::Wire *wire = mod->addWire(decl.portname, portwidths.at(decl.portname));
129 wire->port_id = decl.index;
130 wire->port_input = decl.input;
131 wire->port_output = decl.output;
132 }
133
134 mod->fixup_ports();
135
136 for (auto &para : parameters)
137 log(" ignoring parameter %s.\n", RTLIL::id2cstr(para));
138
139 log(" module %s created.\n", RTLIL::id2cstr(mod->name));
140 }
141 }
142
143 // Return the "basic" type for an array item.
144 std::string basic_cell_type(const std::string celltype, int pos[3] = nullptr) {
145 std::string basicType = celltype;
146 if (celltype.compare(0, strlen("$array:"), "$array:") == 0) {
147 int pos_idx = celltype.find_first_of(':');
148 int pos_num = celltype.find_first_of(':', pos_idx + 1);
149 int pos_type = celltype.find_first_of(':', pos_num + 1);
150 basicType = celltype.substr(pos_type + 1);
151 if (pos != nullptr) {
152 pos[0] = pos_idx;
153 pos[1] = pos_num;
154 pos[2] = pos_type;
155 }
156 }
157 return basicType;
158 }
159
160 bool expand_module(RTLIL::Design *design, RTLIL::Module *module, bool flag_check, bool flag_simcheck, std::vector<std::string> &libdirs)
161 {
162 bool did_something = false;
163 std::map<RTLIL::Cell*, std::pair<int, int>> array_cells;
164 std::string filename;
165
166 bool has_interface_ports = false;
167
168 // If any of the ports are actually interface ports, we will always need to
169 // reprocess the module:
170 if(!module->get_bool_attribute("\\interfaces_replaced_in_module")) {
171 for (auto &wire : module->wires_) {
172 if ((wire.second->port_input || wire.second->port_output) && wire.second->get_bool_attribute("\\is_interface"))
173 has_interface_ports = true;
174 }
175 }
176
177 // Always keep track of all derived interfaces available in the current module in 'interfaces_in_module':
178 dict<RTLIL::IdString, RTLIL::Module*> interfaces_in_module;
179 for (auto &cell_it : module->cells_)
180 {
181 RTLIL::Cell *cell = cell_it.second;
182 if(cell->get_bool_attribute("\\is_interface")) {
183 RTLIL::Module *intf_module = design->modules_[cell->type];
184 interfaces_in_module[cell->name] = intf_module;
185 }
186 }
187
188 for (auto &cell_it : module->cells_)
189 {
190 RTLIL::Cell *cell = cell_it.second;
191 bool has_interfaces_not_found = false;
192
193 std::vector<RTLIL::IdString> connections_to_remove;
194 std::vector<RTLIL::IdString> connections_to_add_name;
195 std::vector<RTLIL::SigSpec> connections_to_add_signal;
196
197 if (cell->type.begins_with("$array:")) {
198 int pos[3];
199 basic_cell_type(cell->type.str(), pos);
200 int pos_idx = pos[0];
201 int pos_num = pos[1];
202 int pos_type = pos[2];
203 int idx = atoi(cell->type.substr(pos_idx + 1, pos_num).c_str());
204 int num = atoi(cell->type.substr(pos_num + 1, pos_type).c_str());
205 array_cells[cell] = std::pair<int, int>(idx, num);
206 cell->type = cell->type.substr(pos_type + 1);
207 }
208 dict<RTLIL::IdString, RTLIL::Module*> interfaces_to_add_to_submodule;
209 dict<RTLIL::IdString, RTLIL::IdString> modports_used_in_submodule;
210
211 if (design->modules_.count(cell->type) == 0)
212 {
213 if (design->modules_.count("$abstract" + cell->type.str()))
214 {
215 cell->type = design->modules_.at("$abstract" + cell->type.str())->derive(design, cell->parameters);
216 cell->parameters.clear();
217 did_something = true;
218 continue;
219 }
220
221 if (cell->type[0] == '$')
222 continue;
223
224 for (auto &dir : libdirs)
225 {
226 static const vector<pair<string, string>> extensions_list =
227 {
228 {".v", "verilog"},
229 {".sv", "verilog -sv"},
230 {".il", "ilang"}
231 };
232
233 for (auto &ext : extensions_list)
234 {
235 filename = dir + "/" + RTLIL::unescape_id(cell->type) + ext.first;
236 if (check_file_exists(filename)) {
237 Frontend::frontend_call(design, NULL, filename, ext.second);
238 goto loaded_module;
239 }
240 }
241 }
242
243 if ((flag_check || flag_simcheck) && cell->type[0] != '$')
244 log_error("Module `%s' referenced in module `%s' in cell `%s' is not part of the design.\n",
245 cell->type.c_str(), module->name.c_str(), cell->name.c_str());
246 continue;
247
248 loaded_module:
249 if (design->modules_.count(cell->type) == 0)
250 log_error("File `%s' from libdir does not declare module `%s'.\n", filename.c_str(), cell->type.c_str());
251 did_something = true;
252 } else {
253
254 RTLIL::Module *mod = design->module(cell->type);
255
256 // Go over all connections and see if any of them are SV interfaces. If they are, then add the replacements to
257 // some lists, so that the ports for sub-modules can be replaced further down:
258 for (auto &conn : cell->connections()) {
259 if(mod->wires_.count(conn.first) != 0 && mod->wire(conn.first)->get_bool_attribute("\\is_interface")) { // Check if the connection is present as an interface in the sub-module's port list
260 //const pool<string> &interface_type_pool = mod->wire(conn.first)->get_strpool_attribute("\\interface_type");
261 //for (auto &d : interface_type_pool) { // TODO: Compare interface type to type in parent module (not crucially important, but good for robustness)
262 //}
263
264 // Find if the sub-module has set a modport for the current interface connection:
265 const pool<string> &interface_modport_pool = mod->wire(conn.first)->get_strpool_attribute("\\interface_modport");
266 std::string interface_modport = "";
267 for (auto &d : interface_modport_pool) {
268 interface_modport = "\\" + d;
269 }
270 if(conn.second.bits().size() == 1 && conn.second.bits()[0].wire->get_bool_attribute("\\is_interface")) { // Check if the connected wire is a potential interface in the parent module
271 std::string interface_name_str = conn.second.bits()[0].wire->name.str();
272 interface_name_str.replace(0,23,""); // Strip the prefix '$dummywireforinterface' from the dummy wire to get the name
273 interface_name_str = "\\" + interface_name_str;
274 RTLIL::IdString interface_name = interface_name_str;
275 bool not_found_interface = false;
276 if(module->get_bool_attribute("\\interfaces_replaced_in_module")) { // If 'interfaces' in the cell have not be been handled yet, there is no need to derive the sub-module either
277 // Check if the interface instance is present in module:
278 // Interface instances may either have the plain name or the name appended with '_inst_from_top_dummy'.
279 // Check for both of them here
280 int nexactmatch = interfaces_in_module.count(interface_name) > 0;
281 std::string interface_name_str2 = interface_name_str + "_inst_from_top_dummy";
282 RTLIL::IdString interface_name2 = interface_name_str2;
283 int nmatch2 = interfaces_in_module.count(interface_name2) > 0;
284 if (nexactmatch > 0 || nmatch2 > 0) {
285 if (nexactmatch != 0) // Choose the one with the plain name if it exists
286 interface_name2 = interface_name;
287 RTLIL::Module *mod_replace_ports = interfaces_in_module.at(interface_name2);
288 for (auto &mod_wire : mod_replace_ports->wires_) { // Go over all wires in interface, and add replacements to lists.
289 std::string signal_name1 = conn.first.str() + "." + log_id(mod_wire.first);
290 std::string signal_name2 = interface_name.str() + "." + log_id(mod_wire.first);
291 connections_to_add_name.push_back(RTLIL::IdString(signal_name1));
292 if(module->wires_.count(signal_name2) == 0) {
293 log_error("Could not find signal '%s' in '%s'\n", signal_name2.c_str(), log_id(module->name));
294 }
295 else {
296 RTLIL::Wire *wire_in_parent = module->wire(signal_name2);
297 connections_to_add_signal.push_back(wire_in_parent);
298 }
299 }
300 connections_to_remove.push_back(conn.first);
301 interfaces_to_add_to_submodule[conn.first] = interfaces_in_module.at(interface_name2);
302
303 // Add modports to a dict which will be passed to AstModule::derive
304 if (interface_modport != "") {
305 modports_used_in_submodule[conn.first] = interface_modport;
306 }
307 }
308 else not_found_interface = true;
309 }
310 else not_found_interface = true;
311 // If the interface instance has not already been derived in the module, we cannot complete at this stage. Set "has_interfaces_not_found"
312 // which will delay the expansion of this cell:
313 if (not_found_interface) {
314 // If we have already gone over all cells in this module, and the interface has still not been found - flag it as an error:
315 if(!(module->get_bool_attribute("\\cells_not_processed"))) {
316 log_warning("Could not find interface instance for `%s' in `%s'\n", log_id(interface_name), log_id(module));
317 }
318 else {
319 // Only set has_interfaces_not_found if it would be possible to find them, since otherwiser we will end up in an infinite loop:
320 has_interfaces_not_found = true;
321 }
322 }
323 }
324 }
325 }
326 //
327
328 if (flag_check || flag_simcheck)
329 {
330 for (auto &conn : cell->connections()) {
331 if (conn.first[0] == '$' && '0' <= conn.first[1] && conn.first[1] <= '9') {
332 int id = atoi(conn.first.c_str()+1);
333 if (id <= 0 || id > GetSize(mod->ports))
334 log_error("Module `%s' referenced in module `%s' in cell `%s' has only %d ports, requested port %d.\n",
335 log_id(cell->type), log_id(module), log_id(cell), GetSize(mod->ports), id);
336 } else if (mod->wire(conn.first) == nullptr || mod->wire(conn.first)->port_id == 0)
337 log_error("Module `%s' referenced in module `%s' in cell `%s' does not have a port named '%s'.\n",
338 log_id(cell->type), log_id(module), log_id(cell), log_id(conn.first));
339 }
340 for (auto &param : cell->parameters)
341 if (mod->avail_parameters.count(param.first) == 0 && param.first[0] != '$' && strchr(param.first.c_str(), '.') == NULL)
342 log_error("Module `%s' referenced in module `%s' in cell `%s' does not have a parameter named '%s'.\n",
343 log_id(cell->type), log_id(module), log_id(cell), log_id(param.first));
344
345 }
346 }
347 RTLIL::Module *mod = design->modules_[cell->type];
348
349 if (design->modules_.at(cell->type)->get_blackbox_attribute()) {
350 if (flag_simcheck)
351 log_error("Module `%s' referenced in module `%s' in cell `%s' is a blackbox/whitebox module.\n",
352 cell->type.c_str(), module->name.c_str(), cell->name.c_str());
353 continue;
354 }
355
356 // If interface instances not yet found, skip cell for now, and say we did something, so that we will return back here:
357 if(has_interfaces_not_found) {
358 did_something = true; // waiting for interfaces to be handled
359 continue;
360 }
361
362 // Do the actual replacements of the SV interface port connection with the individual signal connections:
363 for(unsigned int i=0;i<connections_to_add_name.size();i++) {
364 cell->connections_[connections_to_add_name[i]] = connections_to_add_signal[i];
365 }
366 // Remove the connection for the interface itself:
367 for(unsigned int i=0;i<connections_to_remove.size();i++) {
368 cell->connections_.erase(connections_to_remove[i]);
369 }
370
371 // If there are no overridden parameters AND not interfaces, then we can use the existing module instance as the type
372 // for the cell:
373 if (cell->parameters.size() == 0 && (interfaces_to_add_to_submodule.size() == 0 || !(cell->get_bool_attribute("\\module_not_derived")))) {
374 // If the cell being processed is an the interface instance itself, go down to "handle_interface_instance:",
375 // so that the signals of the interface are added to the parent module.
376 if (mod->get_bool_attribute("\\is_interface")) {
377 goto handle_interface_instance;
378 }
379 continue;
380 }
381
382 cell->type = mod->derive(design, cell->parameters, interfaces_to_add_to_submodule, modports_used_in_submodule);
383 cell->parameters.clear();
384 did_something = true;
385
386 handle_interface_instance:
387
388 // We add all the signals of the interface explicitly to the parent module. This is always needed when we encounter
389 // an interface instance:
390 if (mod->get_bool_attribute("\\is_interface") && cell->get_bool_attribute("\\module_not_derived")) {
391 cell->set_bool_attribute("\\is_interface");
392 RTLIL::Module *derived_module = design->modules_[cell->type];
393 interfaces_in_module[cell->name] = derived_module;
394 did_something = true;
395 }
396 // We clear 'module_not_derived' such that we will not rederive the cell again (needed when there are interfaces connected to the cell)
397 cell->attributes.erase("\\module_not_derived");
398 }
399 // Clear the attribute 'cells_not_processed' such that it can be known that we
400 // have been through all cells at least once, and that we can know whether
401 // to flag an error because of interface instances not found:
402 module->attributes.erase("\\cells_not_processed");
403
404
405 // If any interface instances or interface ports were found in the module, we need to rederive it completely:
406 if ((interfaces_in_module.size() > 0 || has_interface_ports) && !module->get_bool_attribute("\\interfaces_replaced_in_module")) {
407 module->reprocess_module(design, interfaces_in_module);
408 return did_something;
409 }
410
411
412 for (auto &it : array_cells)
413 {
414 RTLIL::Cell *cell = it.first;
415 int idx = it.second.first, num = it.second.second;
416
417 if (design->modules_.count(cell->type) == 0)
418 log_error("Array cell `%s.%s' of unknown type `%s'.\n", RTLIL::id2cstr(module->name), RTLIL::id2cstr(cell->name), RTLIL::id2cstr(cell->type));
419
420 RTLIL::Module *mod = design->modules_[cell->type];
421
422 for (auto &conn : cell->connections_) {
423 int conn_size = conn.second.size();
424 RTLIL::IdString portname = conn.first;
425 if (portname.begins_with("$")) {
426 int port_id = atoi(portname.substr(1).c_str());
427 for (auto &wire_it : mod->wires_)
428 if (wire_it.second->port_id == port_id) {
429 portname = wire_it.first;
430 break;
431 }
432 }
433 if (mod->wires_.count(portname) == 0)
434 log_error("Array cell `%s.%s' connects to unknown port `%s'.\n", RTLIL::id2cstr(module->name), RTLIL::id2cstr(cell->name), RTLIL::id2cstr(conn.first));
435 int port_size = mod->wires_.at(portname)->width;
436 if (conn_size == port_size || conn_size == 0)
437 continue;
438 if (conn_size != port_size*num)
439 log_error("Array cell `%s.%s' has invalid port vs. signal size for port `%s'.\n", RTLIL::id2cstr(module->name), RTLIL::id2cstr(cell->name), RTLIL::id2cstr(conn.first));
440 conn.second = conn.second.extract(port_size*idx, port_size);
441 }
442 }
443
444 return did_something;
445 }
446
447 void hierarchy_worker(RTLIL::Design *design, std::set<RTLIL::Module*, IdString::compare_ptr_by_name<Module>> &used, RTLIL::Module *mod, int indent)
448 {
449 if (used.count(mod) > 0)
450 return;
451
452 if (indent == 0)
453 log("Top module: %s\n", mod->name.c_str());
454 else if (!mod->get_blackbox_attribute())
455 log("Used module: %*s%s\n", indent, "", mod->name.c_str());
456 used.insert(mod);
457
458 for (auto cell : mod->cells()) {
459 std::string celltype = cell->type.str();
460 if (celltype.compare(0, strlen("$array:"), "$array:") == 0)
461 celltype = basic_cell_type(celltype);
462 if (design->module(celltype))
463 hierarchy_worker(design, used, design->module(celltype), indent+4);
464 }
465 }
466
467 void hierarchy_clean(RTLIL::Design *design, RTLIL::Module *top, bool purge_lib)
468 {
469 std::set<RTLIL::Module*, IdString::compare_ptr_by_name<Module>> used;
470 hierarchy_worker(design, used, top, 0);
471
472 std::vector<RTLIL::Module*> del_modules;
473 for (auto &it : design->modules_)
474 if (used.count(it.second) == 0)
475 del_modules.push_back(it.second);
476 else {
477 // Now all interface ports must have been exploded, and it is hence
478 // safe to delete all of the remaining dummy interface ports:
479 pool<RTLIL::Wire*> del_wires;
480 for(auto &wire : it.second->wires_) {
481 if ((wire.second->port_input || wire.second->port_output) && wire.second->get_bool_attribute("\\is_interface")) {
482 del_wires.insert(wire.second);
483 }
484 }
485 if (del_wires.size() > 0) {
486 it.second->remove(del_wires);
487 it.second->fixup_ports();
488 }
489 }
490
491 int del_counter = 0;
492 for (auto mod : del_modules) {
493 if (!purge_lib && mod->get_blackbox_attribute())
494 continue;
495 log("Removing unused module `%s'.\n", mod->name.c_str());
496 design->modules_.erase(mod->name);
497 del_counter++;
498 delete mod;
499 }
500
501 log("Removed %d unused modules.\n", del_counter);
502 }
503
504 bool set_keep_assert(std::map<RTLIL::Module*, bool> &cache, RTLIL::Module *mod)
505 {
506 if (cache.count(mod) == 0)
507 for (auto c : mod->cells()) {
508 RTLIL::Module *m = mod->design->module(c->type);
509 if ((m != nullptr && set_keep_assert(cache, m)) || c->type.in("$assert", "$assume", "$live", "$fair", "$cover"))
510 return cache[mod] = true;
511 }
512 return cache[mod];
513 }
514
515 int find_top_mod_score(Design *design, Module *module, dict<Module*, int> &db)
516 {
517 if (db.count(module) == 0) {
518 int score = 0;
519 db[module] = 0;
520 for (auto cell : module->cells()) {
521 std::string celltype = cell->type.str();
522 // Is this an array instance
523 if (celltype.compare(0, strlen("$array:"), "$array:") == 0)
524 celltype = basic_cell_type(celltype);
525 // Is this cell a module instance?
526 auto instModule = design->module(celltype);
527 // If there is no instance for this, issue a warning.
528 if (instModule != nullptr) {
529 score = max(score, find_top_mod_score(design, instModule, db) + 1);
530 }
531 }
532 db[module] = score;
533 }
534 return db.at(module);
535 }
536
537 RTLIL::Module *check_if_top_has_changed(Design *design, Module *top_mod)
538 {
539 if(top_mod != NULL && top_mod->get_bool_attribute("\\initial_top"))
540 return top_mod;
541 else {
542 for (auto mod : design->modules()) {
543 if (mod->get_bool_attribute("\\top")) {
544 return mod;
545 }
546 }
547 }
548 return NULL;
549 }
550
551 struct HierarchyPass : public Pass {
552 HierarchyPass() : Pass("hierarchy", "check, expand and clean up design hierarchy") { }
553 void help() YS_OVERRIDE
554 {
555 // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
556 log("\n");
557 log(" hierarchy [-check] [-top <module>]\n");
558 log(" hierarchy -generate <cell-types> <port-decls>\n");
559 log("\n");
560 log("In parametric designs, a module might exists in several variations with\n");
561 log("different parameter values. This pass looks at all modules in the current\n");
562 log("design an re-runs the language frontends for the parametric modules as\n");
563 log("needed. It also resolves assignments to wired logic data types (wand/wor),\n");
564 log("resolves positional module parameters, unroll array instances, and more.\n");
565 log("\n");
566 log(" -check\n");
567 log(" also check the design hierarchy. this generates an error when\n");
568 log(" an unknown module is used as cell type.\n");
569 log("\n");
570 log(" -simcheck\n");
571 log(" like -check, but also throw an error if blackbox modules are\n");
572 log(" instantiated, and throw an error if the design has no top module.\n");
573 log("\n");
574 log(" -purge_lib\n");
575 log(" by default the hierarchy command will not remove library (blackbox)\n");
576 log(" modules. use this option to also remove unused blackbox modules.\n");
577 log("\n");
578 log(" -libdir <directory>\n");
579 log(" search for files named <module_name>.v in the specified directory\n");
580 log(" for unknown modules and automatically run read_verilog for each\n");
581 log(" unknown module.\n");
582 log("\n");
583 log(" -keep_positionals\n");
584 log(" per default this pass also converts positional arguments in cells\n");
585 log(" to arguments using port names. This option disables this behavior.\n");
586 log("\n");
587 log(" -keep_portwidths\n");
588 log(" per default this pass adjusts the port width on cells that are\n");
589 log(" module instances when the width does not match the module port. This\n");
590 log(" option disables this behavior.\n");
591 log("\n");
592 log(" -nodefaults\n");
593 log(" do not resolve input port default values\n");
594 log("\n");
595 log(" -nokeep_asserts\n");
596 log(" per default this pass sets the \"keep\" attribute on all modules\n");
597 log(" that directly or indirectly contain one or more formal properties.\n");
598 log(" This option disables this behavior.\n");
599 log("\n");
600 log(" -top <module>\n");
601 log(" use the specified top module to build the design hierarchy. Modules\n");
602 log(" outside this tree (unused modules) are removed.\n");
603 log("\n");
604 log(" when the -top option is used, the 'top' attribute will be set on the\n");
605 log(" specified top module. otherwise a module with the 'top' attribute set\n");
606 log(" will implicitly be used as top module, if such a module exists.\n");
607 log("\n");
608 log(" -auto-top\n");
609 log(" automatically determine the top of the design hierarchy and mark it.\n");
610 log("\n");
611 log(" -chparam name value \n");
612 log(" elaborate the top module using this parameter value. Modules on which\n");
613 log(" this parameter does not exist may cause a warning message to be output.\n");
614 log(" This option can be specified multiple times to override multiple\n");
615 log(" parameters. String values must be passed in double quotes (\").\n");
616 log("\n");
617 log("In -generate mode this pass generates blackbox modules for the given cell\n");
618 log("types (wildcards supported). For this the design is searched for cells that\n");
619 log("match the given types and then the given port declarations are used to\n");
620 log("determine the direction of the ports. The syntax for a port declaration is:\n");
621 log("\n");
622 log(" {i|o|io}[@<num>]:<portname>\n");
623 log("\n");
624 log("Input ports are specified with the 'i' prefix, output ports with the 'o'\n");
625 log("prefix and inout ports with the 'io' prefix. The optional <num> specifies\n");
626 log("the position of the port in the parameter list (needed when instantiated\n");
627 log("using positional arguments). When <num> is not specified, the <portname> can\n");
628 log("also contain wildcard characters.\n");
629 log("\n");
630 log("This pass ignores the current selection and always operates on all modules\n");
631 log("in the current design.\n");
632 log("\n");
633 }
634 void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
635 {
636 log_header(design, "Executing HIERARCHY pass (managing design hierarchy).\n");
637
638 bool flag_check = false;
639 bool flag_simcheck = false;
640 bool purge_lib = false;
641 RTLIL::Module *top_mod = NULL;
642 std::string load_top_mod;
643 std::vector<std::string> libdirs;
644
645 bool auto_top_mode = false;
646 bool generate_mode = false;
647 bool keep_positionals = false;
648 bool keep_portwidths = false;
649 bool nodefaults = false;
650 bool nokeep_asserts = false;
651 std::vector<std::string> generate_cells;
652 std::vector<generate_port_decl_t> generate_ports;
653 std::map<std::string, std::string> parameters;
654
655 size_t argidx;
656 for (argidx = 1; argidx < args.size(); argidx++)
657 {
658 if (args[argidx] == "-generate" && !flag_check && !flag_simcheck && !top_mod) {
659 generate_mode = true;
660 log("Entering generate mode.\n");
661 while (++argidx < args.size()) {
662 const char *p = args[argidx].c_str();
663 generate_port_decl_t decl;
664 if (p[0] == 'i' && p[1] == 'o')
665 decl.input = true, decl.output = true, p += 2;
666 else if (*p == 'i')
667 decl.input = true, decl.output = false, p++;
668 else if (*p == 'o')
669 decl.input = false, decl.output = true, p++;
670 else
671 goto is_celltype;
672 if (*p == '@') {
673 char *endptr;
674 decl.index = strtol(++p, &endptr, 10);
675 if (decl.index < 1)
676 goto is_celltype;
677 p = endptr;
678 } else
679 decl.index = 0;
680 if (*(p++) != ':')
681 goto is_celltype;
682 if (*p == 0)
683 goto is_celltype;
684 decl.portname = p;
685 log("Port declaration: %s", decl.input ? decl.output ? "inout" : "input" : "output");
686 if (decl.index >= 1)
687 log(" [at position %d]", decl.index);
688 log(" %s\n", decl.portname.c_str());
689 generate_ports.push_back(decl);
690 continue;
691 is_celltype:
692 log("Celltype: %s\n", args[argidx].c_str());
693 generate_cells.push_back(RTLIL::unescape_id(args[argidx]));
694 }
695 continue;
696 }
697 if (args[argidx] == "-check") {
698 flag_check = true;
699 continue;
700 }
701 if (args[argidx] == "-simcheck") {
702 flag_simcheck = true;
703 continue;
704 }
705 if (args[argidx] == "-purge_lib") {
706 purge_lib = true;
707 continue;
708 }
709 if (args[argidx] == "-keep_positionals") {
710 keep_positionals = true;
711 continue;
712 }
713 if (args[argidx] == "-keep_portwidths") {
714 keep_portwidths = true;
715 continue;
716 }
717 if (args[argidx] == "-nodefaults") {
718 nodefaults = true;
719 continue;
720 }
721 if (args[argidx] == "-nokeep_asserts") {
722 nokeep_asserts = true;
723 continue;
724 }
725 if (args[argidx] == "-libdir" && argidx+1 < args.size()) {
726 libdirs.push_back(args[++argidx]);
727 continue;
728 }
729 if (args[argidx] == "-top") {
730 if (++argidx >= args.size())
731 log_cmd_error("Option -top requires an additional argument!\n");
732 load_top_mod = args[argidx];
733 continue;
734 }
735 if (args[argidx] == "-auto-top") {
736 auto_top_mode = true;
737 continue;
738 }
739 if (args[argidx] == "-chparam" && argidx+2 < args.size()) {
740 const std::string &key = args[++argidx];
741 const std::string &value = args[++argidx];
742 auto r = parameters.emplace(key, value);
743 if (!r.second) {
744 log_warning("-chparam %s already specified: overwriting.\n", key.c_str());
745 r.first->second = value;
746 }
747 continue;
748 }
749 break;
750 }
751 extra_args(args, argidx, design, false);
752
753 if (!load_top_mod.empty())
754 {
755 IdString top_name = RTLIL::escape_id(load_top_mod);
756 IdString abstract_id = "$abstract" + RTLIL::escape_id(load_top_mod);
757 top_mod = design->module(top_name);
758
759 dict<RTLIL::IdString, RTLIL::Const> top_parameters;
760 for (auto &para : parameters) {
761 SigSpec sig_value;
762 if (!RTLIL::SigSpec::parse(sig_value, NULL, para.second))
763 log_cmd_error("Can't decode value '%s'!\n", para.second.c_str());
764 top_parameters[RTLIL::escape_id(para.first)] = sig_value.as_const();
765 }
766
767 if (top_mod == nullptr && design->module(abstract_id))
768 top_mod = design->module(design->module(abstract_id)->derive(design, top_parameters));
769 else if (top_mod != nullptr && !top_parameters.empty())
770 top_mod = design->module(top_mod->derive(design, top_parameters));
771
772 if (top_mod != nullptr && top_mod->name != top_name) {
773 Module *m = top_mod->clone();
774 m->name = top_name;
775 Module *old_mod = design->module(top_name);
776 if (old_mod)
777 design->remove(old_mod);
778 design->add(m);
779 top_mod = m;
780 }
781 }
782
783 if (top_mod == nullptr && !load_top_mod.empty()) {
784 #ifdef YOSYS_ENABLE_VERIFIC
785 if (verific_import_pending) {
786 verific_import(design, parameters, load_top_mod);
787 top_mod = design->module(RTLIL::escape_id(load_top_mod));
788 }
789 #endif
790 if (top_mod == NULL)
791 log_cmd_error("Module `%s' not found!\n", load_top_mod.c_str());
792 } else {
793 #ifdef YOSYS_ENABLE_VERIFIC
794 if (verific_import_pending)
795 verific_import(design, parameters);
796 #endif
797 }
798
799 if (generate_mode) {
800 generate(design, generate_cells, generate_ports);
801 return;
802 }
803
804 log_push();
805
806 if (top_mod == nullptr)
807 for (auto &mod_it : design->modules_)
808 if (mod_it.second->get_bool_attribute("\\top"))
809 top_mod = mod_it.second;
810
811 if (top_mod != nullptr && top_mod->name.begins_with("$abstract")) {
812 IdString top_name = top_mod->name.substr(strlen("$abstract"));
813
814 dict<RTLIL::IdString, RTLIL::Const> top_parameters;
815 for (auto &para : parameters) {
816 SigSpec sig_value;
817 if (!RTLIL::SigSpec::parse(sig_value, NULL, para.second))
818 log_cmd_error("Can't decode value '%s'!\n", para.second.c_str());
819 top_parameters[RTLIL::escape_id(para.first)] = sig_value.as_const();
820 }
821
822 top_mod = design->module(top_mod->derive(design, top_parameters));
823
824 if (top_mod != nullptr && top_mod->name != top_name) {
825 Module *m = top_mod->clone();
826 m->name = top_name;
827 Module *old_mod = design->module(top_name);
828 if (old_mod)
829 design->remove(old_mod);
830 design->add(m);
831 top_mod = m;
832 }
833 }
834
835 if (top_mod == nullptr && auto_top_mode) {
836 log_header(design, "Finding top of design hierarchy..\n");
837 dict<Module*, int> db;
838 for (Module *mod : design->selected_modules()) {
839 int score = find_top_mod_score(design, mod, db);
840 log("root of %3d design levels: %-20s\n", score, log_id(mod));
841 if (!top_mod || score > db[top_mod])
842 top_mod = mod;
843 }
844 if (top_mod != nullptr)
845 log("Automatically selected %s as design top module.\n", log_id(top_mod));
846 }
847
848 if (flag_simcheck && top_mod == nullptr)
849 log_error("Design has no top module.\n");
850
851 if (top_mod != NULL) {
852 for (auto &mod_it : design->modules_)
853 if (mod_it.second == top_mod)
854 mod_it.second->attributes["\\initial_top"] = RTLIL::Const(1);
855 else
856 mod_it.second->attributes.erase("\\initial_top");
857 }
858
859 bool did_something = true;
860 while (did_something)
861 {
862 did_something = false;
863
864 std::set<RTLIL::Module*, IdString::compare_ptr_by_name<Module>> used_modules;
865 if (top_mod != NULL) {
866 log_header(design, "Analyzing design hierarchy..\n");
867 hierarchy_worker(design, used_modules, top_mod, 0);
868 } else {
869 for (auto mod : design->modules())
870 used_modules.insert(mod);
871 }
872
873 for (auto module : used_modules) {
874 if (expand_module(design, module, flag_check, flag_simcheck, libdirs))
875 did_something = true;
876 }
877
878
879 // The top module might have changed if interface instances have been detected in it:
880 RTLIL::Module *tmp_top_mod = check_if_top_has_changed(design, top_mod);
881 if (tmp_top_mod != NULL) {
882 if (tmp_top_mod != top_mod){
883 top_mod = tmp_top_mod;
884 did_something = true;
885 }
886 }
887
888 // Delete modules marked as 'to_delete':
889 std::vector<RTLIL::Module *> modules_to_delete;
890 for(auto &mod_it : design->modules_) {
891 if (mod_it.second->get_bool_attribute("\\to_delete")) {
892 modules_to_delete.push_back(mod_it.second);
893 }
894 }
895 for(size_t i=0; i<modules_to_delete.size(); i++) {
896 design->remove(modules_to_delete[i]);
897 }
898 }
899
900
901 if (top_mod != NULL) {
902 log_header(design, "Analyzing design hierarchy..\n");
903 hierarchy_clean(design, top_mod, purge_lib);
904 }
905
906 if (top_mod != NULL) {
907 for (auto &mod_it : design->modules_) {
908 if (mod_it.second == top_mod)
909 mod_it.second->attributes["\\top"] = RTLIL::Const(1);
910 else
911 mod_it.second->attributes.erase("\\top");
912 mod_it.second->attributes.erase("\\initial_top");
913 }
914 }
915
916 if (!nokeep_asserts) {
917 std::map<RTLIL::Module*, bool> cache;
918 for (auto mod : design->modules())
919 if (set_keep_assert(cache, mod)) {
920 log("Module %s directly or indirectly contains formal properties -> setting \"keep\" attribute.\n", log_id(mod));
921 mod->set_bool_attribute("\\keep");
922 }
923 }
924
925 if (!keep_positionals)
926 {
927 std::set<RTLIL::Module*> pos_mods;
928 std::map<std::pair<RTLIL::Module*,int>, RTLIL::IdString> pos_map;
929 std::vector<std::pair<RTLIL::Module*,RTLIL::Cell*>> pos_work;
930
931 for (auto &mod_it : design->modules_)
932 for (auto &cell_it : mod_it.second->cells_) {
933 RTLIL::Cell *cell = cell_it.second;
934 if (design->modules_.count(cell->type) == 0)
935 continue;
936 for (auto &conn : cell->connections())
937 if (conn.first[0] == '$' && '0' <= conn.first[1] && conn.first[1] <= '9') {
938 pos_mods.insert(design->modules_.at(cell->type));
939 pos_work.push_back(std::pair<RTLIL::Module*,RTLIL::Cell*>(mod_it.second, cell));
940 break;
941 }
942 }
943
944 for (auto module : pos_mods)
945 for (auto &wire_it : module->wires_) {
946 RTLIL::Wire *wire = wire_it.second;
947 if (wire->port_id > 0)
948 pos_map[std::pair<RTLIL::Module*,int>(module, wire->port_id)] = wire->name;
949 }
950
951 for (auto &work : pos_work) {
952 RTLIL::Module *module = work.first;
953 RTLIL::Cell *cell = work.second;
954 log("Mapping positional arguments of cell %s.%s (%s).\n",
955 RTLIL::id2cstr(module->name), RTLIL::id2cstr(cell->name), RTLIL::id2cstr(cell->type));
956 dict<RTLIL::IdString, RTLIL::SigSpec> new_connections;
957 for (auto &conn : cell->connections())
958 if (conn.first[0] == '$' && '0' <= conn.first[1] && conn.first[1] <= '9') {
959 int id = atoi(conn.first.c_str()+1);
960 std::pair<RTLIL::Module*,int> key(design->modules_.at(cell->type), id);
961 if (pos_map.count(key) == 0) {
962 log(" Failed to map positional argument %d of cell %s.%s (%s).\n",
963 id, RTLIL::id2cstr(module->name), RTLIL::id2cstr(cell->name), RTLIL::id2cstr(cell->type));
964 new_connections[conn.first] = conn.second;
965 } else
966 new_connections[pos_map.at(key)] = conn.second;
967 } else
968 new_connections[conn.first] = conn.second;
969 cell->connections_ = new_connections;
970 }
971 }
972
973 if (!nodefaults)
974 {
975 dict<IdString, dict<IdString, Const>> defaults_db;
976
977 for (auto module : design->modules())
978 for (auto wire : module->wires())
979 if (wire->port_input && wire->attributes.count("\\defaultvalue"))
980 defaults_db[module->name][wire->name] = wire->attributes.at("\\defaultvalue");
981
982 for (auto module : design->modules())
983 for (auto cell : module->cells())
984 {
985 if (defaults_db.count(cell->type) == 0)
986 continue;
987
988 if (keep_positionals) {
989 bool found_positionals = false;
990 for (auto &conn : cell->connections())
991 if (conn.first[0] == '$' && '0' <= conn.first[1] && conn.first[1] <= '9')
992 found_positionals = true;
993 if (found_positionals)
994 continue;
995 }
996
997 for (auto &it : defaults_db.at(cell->type))
998 if (!cell->hasPort(it.first))
999 cell->setPort(it.first, it.second);
1000 }
1001 }
1002
1003 std::set<Module*> blackbox_derivatives;
1004 std::vector<Module*> design_modules = design->modules();
1005
1006 for (auto module : design_modules)
1007 {
1008 pool<Wire*> wand_wor_index;
1009 dict<Wire*, SigSpec> wand_map, wor_map;
1010 vector<SigSig> new_connections;
1011
1012 for (auto wire : module->wires())
1013 {
1014 if (wire->get_bool_attribute("\\wand")) {
1015 wand_map[wire] = SigSpec();
1016 wand_wor_index.insert(wire);
1017 }
1018 if (wire->get_bool_attribute("\\wor")) {
1019 wor_map[wire] = SigSpec();
1020 wand_wor_index.insert(wire);
1021 }
1022 }
1023
1024 for (auto &conn : module->connections())
1025 {
1026 SigSig new_conn;
1027 int cursor = 0;
1028
1029 for (auto c : conn.first.chunks())
1030 {
1031 Wire *w = c.wire;
1032 SigSpec rhs = conn.second.extract(cursor, GetSize(c));
1033
1034 if (wand_wor_index.count(w) == 0) {
1035 new_conn.first.append(c);
1036 new_conn.second.append(rhs);
1037 } else {
1038 if (wand_map.count(w)) {
1039 SigSpec sig = SigSpec(State::S1, GetSize(w));
1040 sig.replace(c.offset, rhs);
1041 wand_map.at(w).append(sig);
1042 } else {
1043 SigSpec sig = SigSpec(State::S0, GetSize(w));
1044 sig.replace(c.offset, rhs);
1045 wor_map.at(w).append(sig);
1046 }
1047 }
1048 cursor += GetSize(c);
1049 }
1050 new_connections.push_back(new_conn);
1051 }
1052 module->new_connections(new_connections);
1053
1054 for (auto cell : module->cells())
1055 {
1056 if (!cell->known())
1057 continue;
1058
1059 for (auto &conn : cell->connections())
1060 {
1061 if (!cell->output(conn.first))
1062 continue;
1063
1064 SigSpec new_sig;
1065 bool update_port = false;
1066
1067 for (auto c : conn.second.chunks())
1068 {
1069 Wire *w = c.wire;
1070
1071 if (wand_wor_index.count(w) == 0) {
1072 new_sig.append(c);
1073 continue;
1074 }
1075
1076 Wire *t = module->addWire(NEW_ID, GetSize(c));
1077 new_sig.append(t);
1078 update_port = true;
1079
1080 if (wand_map.count(w)) {
1081 SigSpec sig = SigSpec(State::S1, GetSize(w));
1082 sig.replace(c.offset, t);
1083 wand_map.at(w).append(sig);
1084 } else {
1085 SigSpec sig = SigSpec(State::S0, GetSize(w));
1086 sig.replace(c.offset, t);
1087 wor_map.at(w).append(sig);
1088 }
1089 }
1090
1091 if (update_port)
1092 cell->setPort(conn.first, new_sig);
1093 }
1094 }
1095
1096 for (auto w : wand_wor_index)
1097 {
1098 bool wand = wand_map.count(w);
1099 SigSpec sigs = wand ? wand_map.at(w) : wor_map.at(w);
1100
1101 if (GetSize(sigs) == 0)
1102 continue;
1103
1104 if (GetSize(w) == 1) {
1105 if (wand)
1106 module->addReduceAnd(NEW_ID, sigs, w);
1107 else
1108 module->addReduceOr(NEW_ID, sigs, w);
1109 continue;
1110 }
1111
1112 SigSpec s = sigs.extract(0, GetSize(w));
1113 for (int i = GetSize(w); i < GetSize(sigs); i += GetSize(w)) {
1114 if (wand)
1115 s = module->And(NEW_ID, s, sigs.extract(i, GetSize(w)));
1116 else
1117 s = module->Or(NEW_ID, s, sigs.extract(i, GetSize(w)));
1118 }
1119 module->connect(w, s);
1120 }
1121
1122 for (auto cell : module->cells())
1123 {
1124 Module *m = design->module(cell->type);
1125
1126 if (m == nullptr)
1127 continue;
1128
1129 if (m->get_blackbox_attribute() && !cell->parameters.empty() && m->get_bool_attribute("\\dynports")) {
1130 IdString new_m_name = m->derive(design, cell->parameters, true);
1131 if (new_m_name.empty())
1132 continue;
1133 if (new_m_name != m->name) {
1134 m = design->module(new_m_name);
1135 blackbox_derivatives.insert(m);
1136 }
1137 }
1138
1139 for (auto &conn : cell->connections())
1140 {
1141 Wire *w = m->wire(conn.first);
1142
1143 if (w == nullptr || w->port_id == 0)
1144 continue;
1145
1146 if (GetSize(conn.second) == 0)
1147 continue;
1148
1149 SigSpec sig = conn.second;
1150
1151 if (!keep_portwidths && GetSize(w) != GetSize(conn.second))
1152 {
1153 if (GetSize(w) < GetSize(conn.second))
1154 {
1155 int n = GetSize(conn.second) - GetSize(w);
1156 if (!w->port_input && w->port_output)
1157 module->connect(sig.extract(GetSize(w), n), Const(0, n));
1158 sig.remove(GetSize(w), n);
1159 }
1160 else
1161 {
1162 int n = GetSize(w) - GetSize(conn.second);
1163 if (w->port_input && !w->port_output)
1164 sig.append(Const(0, n));
1165 else
1166 sig.append(module->addWire(NEW_ID, n));
1167 }
1168
1169 if (!conn.second.is_fully_const() || !w->port_input || w->port_output)
1170 log_warning("Resizing cell port %s.%s.%s from %d bits to %d bits.\n", log_id(module), log_id(cell),
1171 log_id(conn.first), GetSize(conn.second), GetSize(sig));
1172 cell->setPort(conn.first, sig);
1173 }
1174
1175 if (w->port_output && !w->port_input && sig.has_const())
1176 log_error("Output port %s.%s.%s (%s) is connected to constants: %s\n",
1177 log_id(module), log_id(cell), log_id(conn.first), log_id(cell->type), log_signal(sig));
1178 }
1179 }
1180 }
1181
1182 for (auto module : blackbox_derivatives)
1183 design->remove(module);
1184
1185 log_pop();
1186 }
1187 } HierarchyPass;
1188
1189 PRIVATE_NAMESPACE_END