Merge branch 'master' of https://github.com/cliffordwolf/yosys
[yosys.git] / passes / cmds / select.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/register.h"
21 #include "kernel/celltypes.h"
22 #include "kernel/log.h"
23 #include <string.h>
24 #include <fnmatch.h>
25
26 using RTLIL::id2cstr;
27
28 static std::vector<RTLIL::Selection> work_stack;
29
30 static bool match_ids(RTLIL::IdString id, std::string pattern)
31 {
32 if (id == pattern)
33 return true;
34 if (id.size() > 0 && id[0] == '\\' && id.substr(1) == pattern)
35 return true;
36 if (!fnmatch(pattern.c_str(), id.c_str(), 0))
37 return true;
38 if (id.size() > 0 && id[0] == '\\' && !fnmatch(pattern.c_str(), id.substr(1).c_str(), 0))
39 return true;
40 if (id.size() > 0 && id[0] == '$' && pattern.size() > 0 && pattern[0] == '$') {
41 const char *p = id.c_str();
42 const char *q = strrchr(p, '$');
43 if (pattern == q)
44 return true;
45 }
46 return false;
47 }
48
49 static bool match_attr_val(const RTLIL::Const &value, std::string pattern)
50 {
51 if ((value.flags & RTLIL::CONST_FLAG_STRING) == 0)
52 return false;
53 if (!fnmatch(pattern.c_str(), value.decode_string().c_str(), FNM_NOESCAPE))
54 return true;
55 return false;
56 }
57
58 static bool match_attr(const std::map<RTLIL::IdString, RTLIL::Const> &attributes, std::string name_pat, std::string value_pat, bool use_value_pat)
59 {
60 if (name_pat.find('*') != std::string::npos || name_pat.find('?') != std::string::npos || name_pat.find('[') != std::string::npos) {
61 for (auto &it : attributes) {
62 if (!fnmatch(name_pat.c_str(), it.first.c_str(), FNM_NOESCAPE) && (!use_value_pat || match_attr_val(it.second, value_pat)))
63 return true;
64 if (it.first.size() > 0 && it.first[0] == '\\' && !fnmatch(name_pat.c_str(), it.first.substr(1).c_str(), FNM_NOESCAPE) && (!use_value_pat || match_attr_val(it.second, value_pat)))
65 return true;
66 }
67 } else {
68 if (name_pat.size() > 0 && (name_pat[0] == '\\' || name_pat[0] == '$') && attributes.count(name_pat) && (!use_value_pat || match_attr_val(attributes.at(name_pat), value_pat)))
69 return true;
70 if (attributes.count("\\" + name_pat) && (!use_value_pat || match_attr_val(attributes.at("\\" + name_pat), value_pat)))
71 return true;
72 }
73 return false;
74 }
75
76 static void select_op_neg(RTLIL::Design *design, RTLIL::Selection &lhs)
77 {
78 if (lhs.full_selection) {
79 lhs.full_selection = false;
80 lhs.selected_modules.clear();
81 lhs.selected_members.clear();
82 return;
83 }
84
85 if (lhs.selected_modules.size() == 0 && lhs.selected_members.size() == 0) {
86 lhs.full_selection = true;
87 return;
88 }
89
90 RTLIL::Selection new_sel(false);
91
92 for (auto &mod_it : design->modules)
93 {
94 if (lhs.selected_whole_module(mod_it.first))
95 continue;
96 if (!lhs.selected_module(mod_it.first)) {
97 new_sel.selected_modules.insert(mod_it.first);
98 continue;
99 }
100
101 RTLIL::Module *mod = mod_it.second;
102 for (auto &it : mod->wires)
103 if (!lhs.selected_member(mod_it.first, it.first))
104 new_sel.selected_members[mod->name].insert(it.first);
105 for (auto &it : mod->memories)
106 if (!lhs.selected_member(mod_it.first, it.first))
107 new_sel.selected_members[mod->name].insert(it.first);
108 for (auto &it : mod->cells)
109 if (!lhs.selected_member(mod_it.first, it.first))
110 new_sel.selected_members[mod->name].insert(it.first);
111 for (auto &it : mod->processes)
112 if (!lhs.selected_member(mod_it.first, it.first))
113 new_sel.selected_members[mod->name].insert(it.first);
114 }
115
116 lhs.selected_modules.swap(new_sel.selected_modules);
117 lhs.selected_members.swap(new_sel.selected_members);
118 }
119
120 static void select_op_union(RTLIL::Design*, RTLIL::Selection &lhs, const RTLIL::Selection &rhs)
121 {
122 if (rhs.full_selection) {
123 lhs.full_selection = true;
124 lhs.selected_modules.clear();
125 lhs.selected_members.clear();
126 return;
127 }
128
129 if (lhs.full_selection)
130 return;
131
132 for (auto &it : rhs.selected_members)
133 for (auto &it2 : it.second)
134 lhs.selected_members[it.first].insert(it2);
135
136 for (auto &it : rhs.selected_modules) {
137 lhs.selected_modules.insert(it);
138 lhs.selected_members.erase(it);
139 }
140 }
141
142 static void select_op_diff(RTLIL::Design *design, RTLIL::Selection &lhs, const RTLIL::Selection &rhs)
143 {
144 if (rhs.full_selection) {
145 lhs.full_selection = false;
146 lhs.selected_modules.clear();
147 lhs.selected_members.clear();
148 return;
149 }
150
151 if (lhs.full_selection) {
152 if (!rhs.full_selection && rhs.selected_modules.size() == 0 && rhs.selected_members.size() == 0)
153 return;
154 lhs.full_selection = false;
155 for (auto &it : design->modules)
156 lhs.selected_modules.insert(it.first);
157 }
158
159 for (auto &it : rhs.selected_modules) {
160 lhs.selected_modules.erase(it);
161 lhs.selected_members.erase(it);
162 }
163
164 for (auto &it : rhs.selected_members)
165 {
166 if (design->modules.count(it.first) == 0)
167 continue;
168
169 RTLIL::Module *mod = design->modules[it.first];
170
171 if (lhs.selected_modules.count(mod->name) > 0)
172 {
173 for (auto &it : mod->wires)
174 lhs.selected_members[mod->name].insert(it.first);
175 for (auto &it : mod->memories)
176 lhs.selected_members[mod->name].insert(it.first);
177 for (auto &it : mod->cells)
178 lhs.selected_members[mod->name].insert(it.first);
179 for (auto &it : mod->processes)
180 lhs.selected_members[mod->name].insert(it.first);
181 lhs.selected_modules.erase(mod->name);
182 }
183
184 if (lhs.selected_members.count(mod->name) == 0)
185 continue;
186
187 for (auto &it2 : it.second)
188 lhs.selected_members[mod->name].erase(it2);
189 }
190 }
191
192 static void select_op_intersect(RTLIL::Design *design, RTLIL::Selection &lhs, const RTLIL::Selection &rhs)
193 {
194 if (rhs.full_selection)
195 return;
196
197 if (lhs.full_selection) {
198 lhs.full_selection = false;
199 for (auto &it : design->modules)
200 lhs.selected_modules.insert(it.first);
201 }
202
203 std::vector<RTLIL::IdString> del_list;
204
205 for (auto &it : lhs.selected_modules)
206 if (rhs.selected_modules.count(it) == 0) {
207 if (rhs.selected_members.count(it) > 0)
208 for (auto &it2 : rhs.selected_members.at(it))
209 lhs.selected_members[it].insert(it2);
210 del_list.push_back(it);
211 }
212 for (auto &it : del_list)
213 lhs.selected_modules.erase(it);
214
215 del_list.clear();
216 for (auto &it : lhs.selected_members) {
217 if (rhs.selected_modules.count(it.first) > 0)
218 continue;
219 if (rhs.selected_members.count(it.first) == 0) {
220 del_list.push_back(it.first);
221 continue;
222 }
223 std::vector<RTLIL::IdString> del_list2;
224 for (auto &it2 : it.second)
225 if (rhs.selected_members.at(it.first).count(it2) == 0)
226 del_list2.push_back(it2);
227 for (auto &it2 : del_list2)
228 it.second.erase(it2);
229 if (it.second.size() == 0)
230 del_list.push_back(it.first);
231 }
232 for (auto &it : del_list)
233 lhs.selected_members.erase(it);
234 }
235
236 namespace {
237 struct expand_rule_t {
238 char mode;
239 std::set<RTLIL::IdString> cell_types, port_names;
240 };
241 }
242
243 static int parse_comma_list(std::set<RTLIL::IdString> &tokens, std::string str, size_t pos, std::string stopchar)
244 {
245 stopchar += ',';
246 while (1) {
247 size_t endpos = str.find_first_of(stopchar, pos);
248 if (endpos == std::string::npos)
249 endpos = str.size();
250 if (endpos != pos)
251 tokens.insert(RTLIL::escape_id(str.substr(pos, endpos-pos)));
252 pos = endpos;
253 if (pos == str.size() || str[pos] != ',')
254 return pos;
255 pos++;
256 }
257 }
258
259 static int select_op_expand(RTLIL::Design *design, RTLIL::Selection &lhs, std::vector<expand_rule_t> &rules, std::set<RTLIL::IdString> &limits, int max_objects, char mode, CellTypes &ct)
260 {
261 int sel_objects = 0;
262 bool is_input, is_output;
263 for (auto &mod_it : design->modules)
264 {
265 if (lhs.selected_whole_module(mod_it.first) || !lhs.selected_module(mod_it.first))
266 continue;
267
268 RTLIL::Module *mod = mod_it.second;
269 std::set<RTLIL::Wire*> selected_wires;
270
271 for (auto &it : mod->wires)
272 if (lhs.selected_member(mod_it.first, it.first) && limits.count(it.first) == 0)
273 selected_wires.insert(it.second);
274
275 for (auto &conn : mod->connections)
276 {
277 std::vector<RTLIL::SigBit> conn_lhs = conn.first.to_sigbit_vector();
278 std::vector<RTLIL::SigBit> conn_rhs = conn.second.to_sigbit_vector();
279
280 for (size_t i = 0; i < conn_lhs.size(); i++) {
281 if (conn_lhs[i].wire == NULL || conn_rhs[i].wire == NULL)
282 continue;
283 if (mode != 'i' && selected_wires.count(conn_rhs[i].wire) && lhs.selected_members[mod->name].count(conn_lhs[i].wire->name) == 0)
284 lhs.selected_members[mod->name].insert(conn_lhs[i].wire->name), sel_objects++, max_objects--;
285 if (mode != 'o' && selected_wires.count(conn_lhs[i].wire) && lhs.selected_members[mod->name].count(conn_rhs[i].wire->name) == 0)
286 lhs.selected_members[mod->name].insert(conn_rhs[i].wire->name), sel_objects++, max_objects--;
287 }
288 }
289
290 for (auto &cell : mod->cells)
291 for (auto &conn : cell.second->connections)
292 {
293 char last_mode = '-';
294 for (auto &rule : rules) {
295 last_mode = rule.mode;
296 if (rule.cell_types.size() > 0 && rule.cell_types.count(cell.second->type) == 0)
297 continue;
298 if (rule.port_names.size() > 0 && rule.port_names.count(conn.first) == 0)
299 continue;
300 if (rule.mode == '+')
301 goto include_match;
302 else
303 goto exclude_match;
304 }
305 if (last_mode == '+')
306 goto exclude_match;
307 include_match:
308 is_input = mode == 'x' || ct.cell_input(cell.second->type, conn.first);
309 is_output = mode == 'x' || ct.cell_output(cell.second->type, conn.first);
310 for (auto &chunk : conn.second.chunks)
311 if (chunk.wire != NULL) {
312 if (max_objects != 0 && selected_wires.count(chunk.wire) > 0 && lhs.selected_members[mod->name].count(cell.first) == 0)
313 if (mode == 'x' || (mode == 'i' && is_output) || (mode == 'o' && is_input))
314 lhs.selected_members[mod->name].insert(cell.first), sel_objects++, max_objects--;
315 if (max_objects != 0 && lhs.selected_members[mod->name].count(cell.first) > 0 && limits.count(cell.first) == 0 && lhs.selected_members[mod->name].count(chunk.wire->name) == 0)
316 if (mode == 'x' || (mode == 'i' && is_input) || (mode == 'o' && is_output))
317 lhs.selected_members[mod->name].insert(chunk.wire->name), sel_objects++, max_objects--;
318 }
319 exclude_match:;
320 }
321 }
322
323 return sel_objects;
324 }
325
326 static void select_op_expand(RTLIL::Design *design, std::string arg, char mode)
327 {
328 int pos = mode == 'x' ? 2 : 3, levels = 1, rem_objects = -1;
329 std::vector<expand_rule_t> rules;
330 std::set<RTLIL::IdString> limits;
331
332 CellTypes ct;
333
334 if (mode != 'x')
335 ct.setup(design);
336
337 if (pos < int(arg.size()) && arg[pos] == '*') {
338 levels = 1000000;
339 pos++;
340 } else
341 if (pos < int(arg.size()) && '0' <= arg[pos] && arg[pos] <= '9') {
342 size_t endpos = arg.find_first_not_of("0123456789", pos);
343 if (endpos == std::string::npos)
344 endpos = arg.size();
345 levels = atoi(arg.substr(pos, endpos-pos).c_str());
346 pos = endpos;
347 }
348
349 if (pos < int(arg.size()) && arg[pos] == '.') {
350 size_t endpos = arg.find_first_not_of("0123456789", ++pos);
351 if (endpos == std::string::npos)
352 endpos = arg.size();
353 if (int(endpos) > pos)
354 rem_objects = atoi(arg.substr(pos, endpos-pos).c_str());
355 pos = endpos;
356 }
357
358 while (pos < int(arg.size())) {
359 if (arg[pos] != ':' || pos+1 == int(arg.size()))
360 log_cmd_error("Syntax error in expand operator '%s'.\n", arg.c_str());
361 pos++;
362 if (arg[pos] == '+' || arg[pos] == '-') {
363 expand_rule_t rule;
364 rule.mode = arg[pos++];
365 pos = parse_comma_list(rule.cell_types, arg, pos, "[:");
366 if (pos < int(arg.size()) && arg[pos] == '[') {
367 pos = parse_comma_list(rule.port_names, arg, pos+1, "]:");
368 if (pos < int(arg.size()) && arg[pos] == ']')
369 pos++;
370 }
371 rules.push_back(rule);
372 } else {
373 size_t endpos = arg.find(':', pos);
374 if (endpos == std::string::npos)
375 endpos = arg.size();
376 if (int(endpos) > pos) {
377 std::string str = arg.substr(pos, endpos-pos);
378 if (str[0] == '@') {
379 str = RTLIL::escape_id(str.substr(1));
380 if (design->selection_vars.count(str) > 0) {
381 for (auto i1 : design->selection_vars.at(str).selected_members)
382 for (auto i2 : i1.second)
383 limits.insert(i2);
384 }
385 } else
386 limits.insert(RTLIL::escape_id(str));
387 }
388 pos = endpos;
389 }
390 }
391
392 #if 0
393 log("expand by %d levels (max. %d objects):\n", levels, rem_objects);
394 for (auto &rule : rules) {
395 log(" rule (%c):\n", rule.mode);
396 if (rule.cell_types.size() > 0) {
397 log(" cell types:");
398 for (auto &it : rule.cell_types)
399 log(" %s", it.c_str());
400 log("\n");
401 }
402 if (rule.port_names.size() > 0) {
403 log(" port names:");
404 for (auto &it : rule.port_names)
405 log(" %s", it.c_str());
406 log("\n");
407 }
408 }
409 if (limits.size() > 0) {
410 log(" limits:");
411 for (auto &it : limits)
412 log(" %s", it.c_str());
413 log("\n");
414 }
415 #endif
416
417 while (levels-- > 0 && rem_objects != 0) {
418 int num_objects = select_op_expand(design, work_stack.back(), rules, limits, rem_objects, mode, ct);
419 if (num_objects == 0)
420 break;
421 rem_objects -= num_objects;
422 }
423
424 if (rem_objects == 0)
425 log("Warning: reached configured limit at `%s'.\n", arg.c_str());
426 }
427
428 static void select_filter_active_mod(RTLIL::Design *design, RTLIL::Selection &sel)
429 {
430 if (design->selected_active_module.empty())
431 return;
432
433 if (sel.full_selection) {
434 sel.full_selection = false;
435 sel.selected_modules.clear();
436 sel.selected_members.clear();
437 sel.selected_modules.insert(design->selected_active_module);
438 return;
439 }
440
441 std::vector<std::string> del_list;
442 for (auto mod_name : sel.selected_modules)
443 if (mod_name != design->selected_active_module)
444 del_list.push_back(mod_name);
445 for (auto &it : sel.selected_members)
446 if (it.first != design->selected_active_module)
447 del_list.push_back(it.first);
448 for (auto mod_name : del_list) {
449 sel.selected_modules.erase(mod_name);
450 sel.selected_members.erase(mod_name);
451 }
452 }
453
454 static void select_stmt(RTLIL::Design *design, std::string arg)
455 {
456 std::string arg_mod, arg_memb;
457
458 if (arg.size() == 0)
459 return;
460
461 if (arg[0] == '%') {
462 if (arg == "%") {
463 if (design->selection_stack.size() > 0)
464 work_stack.push_back(design->selection_stack.back());
465 } else
466 if (arg == "%%") {
467 while (work_stack.size() > 1) {
468 select_op_union(design, work_stack.front(), work_stack.back());
469 work_stack.pop_back();
470 }
471 } else
472 if (arg == "%n") {
473 if (work_stack.size() < 1)
474 log_cmd_error("Must have at least one element on the stack for operator %%n.\n");
475 select_op_neg(design, work_stack[work_stack.size()-1]);
476 } else
477 if (arg == "%u") {
478 if (work_stack.size() < 2)
479 log_cmd_error("Must have at least two elements on the stack for operator %%u.\n");
480 select_op_union(design, work_stack[work_stack.size()-2], work_stack[work_stack.size()-1]);
481 work_stack.pop_back();
482 } else
483 if (arg == "%d") {
484 if (work_stack.size() < 2)
485 log_cmd_error("Must have at least two elements on the stack for operator %%d.\n");
486 select_op_diff(design, work_stack[work_stack.size()-2], work_stack[work_stack.size()-1]);
487 work_stack.pop_back();
488 } else
489 if (arg == "%i") {
490 if (work_stack.size() < 2)
491 log_cmd_error("Must have at least two elements on the stack for operator %%i.\n");
492 select_op_intersect(design, work_stack[work_stack.size()-2], work_stack[work_stack.size()-1]);
493 work_stack.pop_back();
494 } else
495 if (arg == "%x" || (arg.size() > 2 && arg.substr(0, 2) == "%x" && (arg[2] == ':' || arg[2] == '*' || arg[2] == '.' || ('0' <= arg[2] && arg[2] <= '9')))) {
496 if (work_stack.size() < 1)
497 log_cmd_error("Must have at least one element on the stack for operator %%x.\n");
498 select_op_expand(design, arg, 'x');
499 } else
500 if (arg == "%ci" || (arg.size() > 3 && arg.substr(0, 3) == "%ci" && (arg[3] == ':' || arg[3] == '*' || arg[3] == '.' || ('0' <= arg[3] && arg[3] <= '9')))) {
501 if (work_stack.size() < 1)
502 log_cmd_error("Must have at least one element on the stack for operator %%ci.\n");
503 select_op_expand(design, arg, 'i');
504 } else
505 if (arg == "%co" || (arg.size() > 3 && arg.substr(0, 3) == "%co" && (arg[3] == ':' || arg[3] == '*' || arg[3] == '.' || ('0' <= arg[3] && arg[3] <= '9')))) {
506 if (work_stack.size() < 1)
507 log_cmd_error("Must have at least one element on the stack for operator %%co.\n");
508 select_op_expand(design, arg, 'o');
509 } else
510 log_cmd_error("Unknown selection operator '%s'.\n", arg.c_str());
511 if (work_stack.size() >= 1)
512 select_filter_active_mod(design, work_stack.back());
513 return;
514 }
515
516 if (arg[0] == '@') {
517 std::string set_name = RTLIL::escape_id(arg.substr(1));
518 if (design->selection_vars.count(set_name) > 0)
519 work_stack.push_back(design->selection_vars[set_name]);
520 else
521 work_stack.push_back(RTLIL::Selection(false));
522 select_filter_active_mod(design, work_stack.back());
523 return;
524 }
525
526 if (!design->selected_active_module.empty()) {
527 arg_mod = design->selected_active_module;
528 arg_memb = arg;
529 } else {
530 size_t pos = arg.find('/');
531 if (pos == std::string::npos) {
532 if (arg.find(':') == std::string::npos)
533 arg_mod = arg;
534 else
535 arg_mod = "*", arg_memb = arg;
536 } else {
537 arg_mod = arg.substr(0, pos);
538 arg_memb = arg.substr(pos+1);
539 }
540 }
541
542 work_stack.push_back(RTLIL::Selection());
543 RTLIL::Selection &sel = work_stack.back();
544
545 if (arg == "*" && arg_mod == "*") {
546 select_filter_active_mod(design, work_stack.back());
547 return;
548 }
549
550 sel.full_selection = false;
551 for (auto &mod_it : design->modules)
552 {
553 if (!match_ids(mod_it.first, arg_mod))
554 continue;
555
556 if (arg_memb == "") {
557 sel.selected_modules.insert(mod_it.first);
558 continue;
559 }
560
561 RTLIL::Module *mod = mod_it.second;
562 if (arg_memb.substr(0, 2) == "w:") {
563 for (auto &it : mod->wires)
564 if (match_ids(it.first, arg_memb.substr(2)))
565 sel.selected_members[mod->name].insert(it.first);
566 } else
567 if (arg_memb.substr(0, 2) == "m:") {
568 for (auto &it : mod->memories)
569 if (match_ids(it.first, arg_memb.substr(2)))
570 sel.selected_members[mod->name].insert(it.first);
571 } else
572 if (arg_memb.substr(0, 2) == "c:") {
573 for (auto &it : mod->cells)
574 if (match_ids(it.first, arg_memb.substr(2)))
575 sel.selected_members[mod->name].insert(it.first);
576 } else
577 if (arg_memb.substr(0, 2) == "t:") {
578 for (auto &it : mod->cells)
579 if (match_ids(it.second->type, arg_memb.substr(2)))
580 sel.selected_members[mod->name].insert(it.first);
581 } else
582 if (arg_memb.substr(0, 2) == "p:") {
583 for (auto &it : mod->processes)
584 if (match_ids(it.first, arg_memb.substr(2)))
585 sel.selected_members[mod->name].insert(it.first);
586 } else
587 if (arg_memb.substr(0, 2) == "a:") {
588 bool use_value_pat = false;
589 std::string name_pat = arg_memb.substr(2);
590 std::string value_pat;
591 if (name_pat.find('=') != std::string::npos) {
592 value_pat = name_pat.substr(name_pat.find('=')+1);
593 name_pat = name_pat.substr(0, name_pat.find('='));
594 use_value_pat = true;
595 }
596 for (auto &it : mod->wires)
597 if (match_attr(it.second->attributes, name_pat, value_pat, use_value_pat))
598 sel.selected_members[mod->name].insert(it.first);
599 for (auto &it : mod->memories)
600 if (match_attr(it.second->attributes, name_pat, value_pat, use_value_pat))
601 sel.selected_members[mod->name].insert(it.first);
602 for (auto &it : mod->cells)
603 if (match_attr(it.second->attributes, name_pat, value_pat, use_value_pat))
604 sel.selected_members[mod->name].insert(it.first);
605 for (auto &it : mod->processes)
606 if (match_attr(it.second->attributes, name_pat, value_pat, use_value_pat))
607 sel.selected_members[mod->name].insert(it.first);
608 } else {
609 if (arg_memb.substr(0, 2) == "n:")
610 arg_memb = arg_memb.substr(2);
611 for (auto &it : mod->wires)
612 if (match_ids(it.first, arg_memb))
613 sel.selected_members[mod->name].insert(it.first);
614 for (auto &it : mod->memories)
615 if (match_ids(it.first, arg_memb))
616 sel.selected_members[mod->name].insert(it.first);
617 for (auto &it : mod->cells)
618 if (match_ids(it.first, arg_memb))
619 sel.selected_members[mod->name].insert(it.first);
620 for (auto &it : mod->processes)
621 if (match_ids(it.first, arg_memb))
622 sel.selected_members[mod->name].insert(it.first);
623 }
624 }
625
626 select_filter_active_mod(design, work_stack.back());
627 }
628
629 // used in kernel/register.cc and maybe other locations, extern decl. in register.h
630 void handle_extra_select_args(Pass *pass, std::vector<std::string> args, size_t argidx, size_t args_size, RTLIL::Design *design)
631 {
632 work_stack.clear();
633 for (; argidx < args_size; argidx++) {
634 if (args[argidx].substr(0, 1) == "-") {
635 if (pass != NULL)
636 pass->cmd_error(args, argidx, "Unexpected option in selection arguments.");
637 else
638 log_cmd_error("Unexpected option in selection arguments.");
639 }
640 select_stmt(design, args[argidx]);
641 }
642 while (work_stack.size() > 1) {
643 select_op_union(design, work_stack.front(), work_stack.back());
644 work_stack.pop_back();
645 }
646 if (work_stack.size() > 0)
647 design->selection_stack.push_back(work_stack.back());
648 else
649 design->selection_stack.push_back(RTLIL::Selection(false));
650 }
651
652 struct SelectPass : public Pass {
653 SelectPass() : Pass("select", "modify and view the list of selected objects") { }
654 virtual void help()
655 {
656 // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
657 log("\n");
658 log(" select [ -add | -del | -set <name> ] <selection>\n");
659 log(" select [ -assert-none | -assert-any ] <selection>\n");
660 log(" select [ -list | -write <filename> | -count | -clear ]\n");
661 log(" select -module <modname>\n");
662 log("\n");
663 log("Most commands use the list of currently selected objects to determine which part\n");
664 log("of the design to operate on. This command can be used to modify and view this\n");
665 log("list of selected objects.\n");
666 log("\n");
667 log("Note that many commands support an optional [selection] argument that can be\n");
668 log("used to override the global selection for the command. The syntax of this\n");
669 log("optional argument is identical to the syntax of the <selection> argument\n");
670 log("described here.\n");
671 log("\n");
672 log(" -add, -del\n");
673 log(" add or remove the given objects to the current selection.\n");
674 log(" without this options the current selection is replaced.\n");
675 log("\n");
676 log(" -set <name>\n");
677 log(" do not modify the current selection. instead save the new selection\n");
678 log(" under the given name (see @<name> below).\n");
679 log("\n");
680 log(" -assert-none\n");
681 log(" asserts that the given selection is empty. i.e. produce an error if\n");
682 log(" any object matching the selection is found.\n");
683 log("\n");
684 log(" -assert-any\n");
685 log(" asserts that the given selection is non-empty. i.e. produce an error\n");
686 log(" if no object matching the selection is found.\n");
687 log("\n");
688 log(" -list\n");
689 log(" list all objects in the current selection\n");
690 log("\n");
691 log(" -write <filename>\n");
692 log(" like -list but write the output to the specified file\n");
693 log("\n");
694 log(" -count\n");
695 log(" count all objects in the current selection\n");
696 log("\n");
697 log(" -clear\n");
698 log(" clear the current selection. this effectively selects the\n");
699 log(" whole design.\n");
700 log("\n");
701 log(" -module <modname>\n");
702 log(" limit the current scope to the specified module.\n");
703 log(" the difference between this and simply selecting the module\n");
704 log(" is that all object names are interpreted relative to this\n");
705 log(" module after this command until the selection is cleared again.\n");
706 log("\n");
707 log("When this command is called without an argument, the current selection\n");
708 log("is displayed in a compact form (i.e. only the module name when a whole module\n");
709 log("is selected).\n");
710 log("\n");
711 log("The <selection> argument itself is a series of commands for a simple stack\n");
712 log("machine. Each element on the stack represents a set of selected objects.\n");
713 log("After this commands have been executed, the union of all remaining sets\n");
714 log("on the stack is computed and used as selection for the command.\n");
715 log("\n");
716 log("Pushing (selecting) object when not in -module mode:\n");
717 log("\n");
718 log(" <mod_pattern>\n");
719 log(" select the specified module(s)\n");
720 log("\n");
721 log(" <mod_pattern>/<obj_pattern>\n");
722 log(" select the specified object(s) from the module(s)\n");
723 log("\n");
724 log("Pushing (selecting) object when in -module mode:\n");
725 log("\n");
726 log(" <obj_pattern>\n");
727 log(" select the specified object(s) from the current module\n");
728 log("\n");
729 log("A <mod_pattern> can be a module name or wildcard expression (*, ?, [..])\n");
730 log("matching module names.\n");
731 log("\n");
732 log("An <obj_pattern> can be an object name, wildcard expression, or one of\n");
733 log("the following:\n");
734 log("\n");
735 log(" w:<pattern>\n");
736 log(" all wires with a name matching the given wildcard pattern\n");
737 log("\n");
738 log(" m:<pattern>\n");
739 log(" all memories with a name matching the given pattern\n");
740 log("\n");
741 log(" c:<pattern>\n");
742 log(" all cells with a name matching the given pattern\n");
743 log("\n");
744 log(" t:<pattern>\n");
745 log(" all cells with a type matching the given pattern\n");
746 log("\n");
747 log(" p:<pattern>\n");
748 log(" all processes with a name matching the given pattern\n");
749 log("\n");
750 log(" a:<pattern>\n");
751 log(" all objects with an attribute name matching the given pattern\n");
752 log("\n");
753 log(" a:<pattern>=<pattern>\n");
754 log(" all objects with a matching attribute name-value-pair\n");
755 log("\n");
756 log(" n:<pattern>\n");
757 log(" all objects with a name matching the given pattern\n");
758 log(" (i.e. 'n:' is optional as it is the default matching rule)\n");
759 log("\n");
760 log(" @<name>\n");
761 log(" push the selection saved prior with 'select -set <name> ...'\n");
762 log("\n");
763 log("The following actions can be performed on the top sets on the stack:\n");
764 log("\n");
765 log(" %%\n");
766 log(" push a copy of the current selection to the stack\n");
767 log("\n");
768 log(" %%%%\n");
769 log(" replace the stack with a union of all elements on it\n");
770 log("\n");
771 log(" %%n\n");
772 log(" replace top set with its invert\n");
773 log("\n");
774 log(" %%u\n");
775 log(" replace the two top sets on the stack with their union\n");
776 log("\n");
777 log(" %%i\n");
778 log(" replace the two top sets on the stack with their intersection\n");
779 log("\n");
780 log(" %%d\n");
781 log(" pop the top set from the stack and subtract it from the new top\n");
782 log("\n");
783 log(" %%x[<num1>|*][.<num2>][:<rule>[:<rule>..]]\n");
784 log(" expand top set <num1> num times according to the specified rules.\n");
785 log(" (i.e. select all cells connected to selected wires and select all\n");
786 log(" wires connected to selected cells) The rules specify which cell\n");
787 log(" ports to use for this. the syntax for a rule is a '-' for exclusion\n");
788 log(" and a '+' for inclusion, followed by an optional comma seperated\n");
789 log(" list of cell types followed by an optional comma separated list of\n");
790 log(" cell ports in square brackets. a rule can also be just a cell or wire\n");
791 log(" name that limits the expansion (is included but does not go beyond).\n");
792 log(" select at most <num2> objects. a warning message is printed when this\n");
793 log(" limit is reached. When '*' is used instead of <num1> then the process\n");
794 log(" is repeated until no further object are selected.\n");
795 log("\n");
796 log(" %%ci[<num1>|*][.<num2>][:<rule>[:<rule>..]]\n");
797 log(" %%co[<num1>|*][.<num2>][:<rule>[:<rule>..]]\n");
798 log(" simmilar to %%x, but only select input (%%ci) or output cones (%%co)\n");
799 log("\n");
800 log("Example: the following command selects all wires that are connected to a\n");
801 log("'GATE' input of a 'SWITCH' cell:\n");
802 log("\n");
803 log(" select */t:SWITCH %%x:+[GATE] */t:SWITCH %%d\n");
804 log("\n");
805 }
806 virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
807 {
808 bool add_mode = false;
809 bool del_mode = false;
810 bool clear_mode = false;
811 bool list_mode = false;
812 bool count_mode = false;
813 bool got_module = false;
814 bool assert_none = false;
815 bool assert_any = false;
816 std::string write_file;
817 std::string set_name;
818
819 work_stack.clear();
820
821 size_t argidx;
822 for (argidx = 1; argidx < args.size(); argidx++)
823 {
824 std::string arg = args[argidx];
825 if (arg == "-add") {
826 add_mode = true;
827 continue;
828 }
829 if (arg == "-del") {
830 del_mode = true;
831 continue;
832 }
833 if (arg == "-assert-none") {
834 assert_none = true;
835 continue;
836 }
837 if (arg == "-assert-any") {
838 assert_any = true;
839 continue;
840 }
841 if (arg == "-clear") {
842 clear_mode = true;
843 continue;
844 }
845 if (arg == "-list") {
846 list_mode = true;
847 continue;
848 }
849 if (arg == "-write" && argidx+1 < args.size()) {
850 write_file = args[++argidx];
851 continue;
852 }
853 if (arg == "-count") {
854 count_mode = true;
855 continue;
856 }
857 if (arg == "-module" && argidx+1 < args.size()) {
858 RTLIL::IdString mod_name = RTLIL::escape_id(args[++argidx]);
859 if (design->modules.count(mod_name) == 0)
860 log_cmd_error("No such module: %s\n", id2cstr(mod_name));
861 design->selected_active_module = mod_name;
862 got_module = true;
863 continue;
864 }
865 if (arg == "-set" && argidx+1 < args.size()) {
866 set_name = RTLIL::escape_id(args[++argidx]);
867 continue;
868 }
869 if (arg.size() > 0 && arg[0] == '-')
870 log_cmd_error("Unkown option %s.\n", arg.c_str());
871 select_stmt(design, arg);
872 }
873
874 if (clear_mode && args.size() != 2)
875 log_cmd_error("Option -clear can not be combined with any other options.\n");
876
877 if (add_mode + del_mode + assert_none + assert_any > 1)
878 log_cmd_error("Options -add, -del, -assert-none or -assert-any can not be combined.\n");
879
880 if ((list_mode || !write_file.empty() || count_mode) && (add_mode || del_mode || assert_none || assert_any))
881 log_cmd_error("Options -list, -write and -count can not be combined with -add, -del, -assert-none or -assert-any.\n");
882
883 if (!set_name.empty() && (list_mode || !write_file.empty() || count_mode || add_mode || del_mode || assert_none || assert_any))
884 log_cmd_error("Option -set can not be combined with -list, -write, -count, -add, -del, -assert-none or -assert-any.\n");
885
886 if (work_stack.size() == 0 && got_module) {
887 RTLIL::Selection sel;
888 select_filter_active_mod(design, sel);
889 work_stack.push_back(sel);
890 }
891
892 while (work_stack.size() > 1) {
893 select_op_union(design, work_stack.front(), work_stack.back());
894 work_stack.pop_back();
895 }
896
897 assert(design->selection_stack.size() > 0);
898
899 if (clear_mode)
900 {
901 design->selection_stack.back() = RTLIL::Selection(true);
902 design->selected_active_module = std::string();
903 return;
904 }
905
906 if (list_mode || count_mode || !write_file.empty())
907 {
908 #define LOG_OBJECT(...) do { if (list_mode) log(__VA_ARGS__); if (f != NULL) fprintf(f, __VA_ARGS__); total_count++; } while (0)
909 int total_count = 0;
910 FILE *f = NULL;
911 if (!write_file.empty()) {
912 f = fopen(write_file.c_str(), "w");
913 if (f == NULL)
914 log_error("Can't open '%s' for writing: %s\n", write_file.c_str(), strerror(errno));
915 }
916 RTLIL::Selection *sel = &design->selection_stack.back();
917 if (work_stack.size() > 0)
918 sel = &work_stack.back();
919 sel->optimize(design);
920 for (auto mod_it : design->modules)
921 {
922 if (sel->selected_whole_module(mod_it.first) && list_mode)
923 log("%s\n", id2cstr(mod_it.first));
924 if (sel->selected_module(mod_it.first)) {
925 for (auto &it : mod_it.second->wires)
926 if (sel->selected_member(mod_it.first, it.first))
927 LOG_OBJECT("%s/%s\n", id2cstr(mod_it.first), id2cstr(it.first));
928 for (auto &it : mod_it.second->memories)
929 if (sel->selected_member(mod_it.first, it.first))
930 LOG_OBJECT("%s/%s\n", id2cstr(mod_it.first), id2cstr(it.first));
931 for (auto &it : mod_it.second->cells)
932 if (sel->selected_member(mod_it.first, it.first))
933 LOG_OBJECT("%s/%s\n", id2cstr(mod_it.first), id2cstr(it.first));
934 for (auto &it : mod_it.second->processes)
935 if (sel->selected_member(mod_it.first, it.first))
936 LOG_OBJECT("%s/%s\n", id2cstr(mod_it.first), id2cstr(it.first));
937 }
938 }
939 if (count_mode)
940 log("%d objects.\n", total_count);
941 if (f != NULL)
942 fclose(f);
943 #undef LOG_OBJECT
944 return;
945 }
946
947 if (add_mode)
948 {
949 if (work_stack.size() == 0)
950 log_cmd_error("Nothing to add to selection.\n");
951 select_op_union(design, design->selection_stack.back(), work_stack.back());
952 design->selection_stack.back().optimize(design);
953 return;
954 }
955
956 if (del_mode)
957 {
958 if (work_stack.size() == 0)
959 log_cmd_error("Nothing to delete from selection.\n");
960 select_op_diff(design, design->selection_stack.back(), work_stack.back());
961 design->selection_stack.back().optimize(design);
962 return;
963 }
964
965 if (assert_none)
966 {
967 if (work_stack.size() == 0)
968 log_cmd_error("No selection to check.\n");
969 if (!work_stack.back().empty())
970 log_error("Assertation failed: selection is not empty.\n");
971 return;
972 }
973
974 if (assert_any)
975 {
976 if (work_stack.size() == 0)
977 log_cmd_error("No selection to check.\n");
978 if (work_stack.back().empty())
979 log_error("Assertation failed: selection is empty.\n");
980 return;
981 }
982
983 if (!set_name.empty())
984 {
985 if (work_stack.size() == 0)
986 design->selection_vars.erase(set_name);
987 else
988 design->selection_vars[set_name] = work_stack.back();
989 return;
990 }
991
992 if (work_stack.size() == 0) {
993 RTLIL::Selection &sel = design->selection_stack.back();
994 if (sel.full_selection)
995 log("*\n");
996 for (auto &it : sel.selected_modules)
997 log("%s\n", id2cstr(it));
998 for (auto &it : sel.selected_members)
999 for (auto &it2 : it.second)
1000 log("%s/%s\n", id2cstr(it.first), id2cstr(it2));
1001 return;
1002 }
1003
1004 design->selection_stack.back() = work_stack.back();
1005 design->selection_stack.back().optimize(design);
1006 }
1007 } SelectPass;
1008
1009 struct CdPass : public Pass {
1010 CdPass() : Pass("cd", "a shortcut for 'select -module <name>'") { }
1011 virtual void help()
1012 {
1013 // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
1014 log("\n");
1015 log(" cd <modname>\n");
1016 log("\n");
1017 log("This is just a shortcut for 'select -module <modname>'.\n");
1018 log("\n");
1019 log("\n");
1020 log(" cd <cellname>\n");
1021 log("\n");
1022 log("When no module with the specified name is found, but there is a cell\n");
1023 log("with the specified name in the current module, then this is equivialent\n");
1024 log("to 'cd <celltype>'.\n");
1025 log("\n");
1026 log(" cd ..\n");
1027 log("\n");
1028 log("This is just a shortcut for 'select -clear'.\n");
1029 log("\n");
1030 }
1031 virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
1032 {
1033 if (args.size() != 2)
1034 log_cmd_error("Invalid number of arguments.\n");
1035
1036 if (args[1] == "..") {
1037 design->selection_stack.back() = RTLIL::Selection(true);
1038 design->selected_active_module = std::string();
1039 return;
1040 }
1041
1042 std::string modname = RTLIL::escape_id(args[1]);
1043
1044 if (design->modules.count(modname) == 0 && !design->selected_active_module.empty()) {
1045 RTLIL::Module *module = NULL;
1046 if (design->modules.count(design->selected_active_module) > 0)
1047 module = design->modules.at(design->selected_active_module);
1048 if (module != NULL && module->cells.count(modname) > 0)
1049 modname = module->cells.at(modname)->type;
1050 }
1051
1052 if (design->modules.count(modname) > 0) {
1053 design->selected_active_module = modname;
1054 design->selection_stack.back() = RTLIL::Selection();
1055 select_filter_active_mod(design, design->selection_stack.back());
1056 design->selection_stack.back().optimize(design);
1057 return;
1058 }
1059
1060 log_cmd_error("No such module `%s' found!\n", RTLIL::id2cstr(modname));
1061 }
1062 } CdPass;
1063
1064 template<typename T>
1065 static int log_matches(const char *title, std::string pattern, T list)
1066 {
1067 std::vector<std::string> matches;
1068
1069 for (auto &it : list)
1070 if (pattern.empty() || match_ids(it.first, pattern))
1071 matches.push_back(it.first);
1072
1073 if (matches.empty())
1074 return 0;
1075
1076 log("\n%d %s:\n", int(matches.size()), title);
1077 for (auto &id : matches)
1078 log(" %s\n", RTLIL::id2cstr(id));
1079 return matches.size();
1080 }
1081
1082 struct LsPass : public Pass {
1083 LsPass() : Pass("ls", "list modules or objects in modules") { }
1084 virtual void help()
1085 {
1086 // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
1087 log("\n");
1088 log(" ls [pattern]\n");
1089 log("\n");
1090 log("When no active module is selected, this prints a list of all modules.\n");
1091 log("\n");
1092 log("When an active module is selected, this prints a list of objects in the module.\n");
1093 log("\n");
1094 log("If a pattern is given, the objects matching the pattern are printed\n");
1095 log("\n");
1096 log("Note that this command does not use the selection mechanism and always operates\n");
1097 log("on the whole design or whole active module. Use 'select -list' to show a list\n");
1098 log("of currently selected objects.\n");
1099 log("\n");
1100 }
1101 virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
1102 {
1103 std::string pattern;
1104 int counter = 0;
1105
1106 if (args.size() != 1 && args.size() != 2)
1107 log_cmd_error("Invalid number of arguments.\n");
1108 if (args.size() == 2)
1109 pattern = args.at(1);
1110
1111 if (design->selected_active_module.empty())
1112 {
1113 counter += log_matches("modules", pattern, design->modules);
1114 }
1115 else
1116 if (design->modules.count(design->selected_active_module) > 0)
1117 {
1118 RTLIL::Module *module = design->modules.at(design->selected_active_module);
1119 counter += log_matches("wires", pattern, module->wires);
1120 counter += log_matches("memories", pattern, module->memories);
1121 counter += log_matches("cells", pattern, module->cells);
1122 counter += log_matches("processes", pattern, module->processes);
1123 }
1124
1125 // log("\nfound %d item%s.\n", counter, counter == 1 ? "" : "s");
1126 }
1127 } LsPass;
1128