aboutsummaryrefslogtreecommitdiffstats
path: root/passes/cmds/select.cc
diff options
context:
space:
mode:
Diffstat (limited to 'passes/cmds/select.cc')
-rw-r--r--passes/cmds/select.cc194
1 files changed, 164 insertions, 30 deletions
diff --git a/passes/cmds/select.cc b/passes/cmds/select.cc
index 247765f0d..d2e1a2e2b 100644
--- a/passes/cmds/select.cc
+++ b/passes/cmds/select.cc
@@ -2,11 +2,11 @@
* yosys -- Yosys Open SYnthesis Suite
*
* Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
- *
+ *
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
- *
+ *
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
@@ -180,6 +180,47 @@ static void select_op_neg(RTLIL::Design *design, RTLIL::Selection &lhs)
lhs.selected_members.swap(new_sel.selected_members);
}
+static int my_xorshift32_rng() {
+ static uint32_t x32 = 314159265;
+ x32 ^= x32 << 13;
+ x32 ^= x32 >> 17;
+ x32 ^= x32 << 5;
+ return x32 & 0x0fffffff;
+}
+
+static void select_op_random(RTLIL::Design *design, RTLIL::Selection &lhs, int count)
+{
+ vector<pair<IdString, IdString>> objects;
+
+ for (auto mod : design->modules())
+ {
+ if (!lhs.selected_module(mod->name))
+ continue;
+
+ for (auto cell : mod->cells()) {
+ if (lhs.selected_member(mod->name, cell->name))
+ objects.push_back(make_pair(mod->name, cell->name));
+ }
+
+ for (auto wire : mod->wires()) {
+ if (lhs.selected_member(mod->name, wire->name))
+ objects.push_back(make_pair(mod->name, wire->name));
+ }
+ }
+
+ lhs = RTLIL::Selection(false);
+
+ while (!objects.empty() && count-- > 0)
+ {
+ int idx = my_xorshift32_rng() % GetSize(objects);
+ lhs.selected_members[objects[idx].first].insert(objects[idx].second);
+ objects[idx] = objects.back();
+ objects.pop_back();
+ }
+
+ lhs.optimize(design);
+}
+
static void select_op_submod(RTLIL::Design *design, RTLIL::Selection &lhs)
{
for (auto &mod_it : design->modules_)
@@ -196,6 +237,27 @@ static void select_op_submod(RTLIL::Design *design, RTLIL::Selection &lhs)
}
}
+static void select_op_cells_to_modules(RTLIL::Design *design, RTLIL::Selection &lhs)
+{
+ RTLIL::Selection new_sel(false);
+ for (auto &mod_it : design->modules_)
+ if (lhs.selected_module(mod_it.first))
+ for (auto &cell_it : mod_it.second->cells_)
+ if (lhs.selected_member(mod_it.first, cell_it.first) && design->modules_.count(cell_it.second->type))
+ new_sel.selected_modules.insert(cell_it.second->type);
+ lhs = new_sel;
+}
+
+static void select_op_module_to_cells(RTLIL::Design *design, RTLIL::Selection &lhs)
+{
+ RTLIL::Selection new_sel(false);
+ for (auto &mod_it : design->modules_)
+ for (auto &cell_it : mod_it.second->cells_)
+ if (design->modules_.count(cell_it.second->type) && lhs.selected_whole_module(cell_it.second->type))
+ new_sel.selected_members[mod_it.first].insert(cell_it.first);
+ lhs = new_sel;
+}
+
static void select_op_fullmod(RTLIL::Design *design, RTLIL::Selection &lhs)
{
lhs.optimize(design);
@@ -365,7 +427,7 @@ static int parse_comma_list(std::set<RTLIL::IdString> &tokens, std::string str,
}
}
-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)
+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, bool eval_only)
{
int sel_objects = 0;
bool is_input, is_output;
@@ -401,6 +463,8 @@ static int select_op_expand(RTLIL::Design *design, RTLIL::Selection &lhs, std::v
for (auto &conn : cell.second->connections())
{
char last_mode = '-';
+ if (eval_only && !yosys_celltypes.cell_evaluable(cell.second->type))
+ goto exclude_match;
for (auto &rule : rules) {
last_mode = rule.mode;
if (rule.cell_types.size() > 0 && rule.cell_types.count(cell.second->type) == 0)
@@ -433,9 +497,10 @@ static int select_op_expand(RTLIL::Design *design, RTLIL::Selection &lhs, std::v
return sel_objects;
}
-static void select_op_expand(RTLIL::Design *design, std::string arg, char mode)
+static void select_op_expand(RTLIL::Design *design, std::string arg, char mode, bool eval_only)
{
- int pos = mode == 'x' ? 2 : 3, levels = 1, rem_objects = -1;
+ int pos = (mode == 'x' ? 2 : 3) + (eval_only ? 1 : 0);
+ int levels = 1, rem_objects = -1;
std::vector<expand_rule_t> rules;
std::set<RTLIL::IdString> limits;
@@ -526,7 +591,7 @@ static void select_op_expand(RTLIL::Design *design, std::string arg, char mode)
#endif
while (levels-- > 0 && rem_objects != 0) {
- int num_objects = select_op_expand(design, work_stack.back(), rules, limits, rem_objects, mode, ct);
+ int num_objects = select_op_expand(design, work_stack.back(), rules, limits, rem_objects, mode, ct, eval_only);
if (num_objects == 0)
break;
rem_objects -= num_objects;
@@ -540,7 +605,7 @@ static void select_filter_active_mod(RTLIL::Design *design, RTLIL::Selection &se
{
if (design->selected_active_module.empty())
return;
-
+
if (sel.full_selection) {
sel.full_selection = false;
sel.selected_modules.clear();
@@ -610,11 +675,27 @@ static void select_stmt(RTLIL::Design *design, std::string arg)
select_op_intersect(design, work_stack[work_stack.size()-2], work_stack[work_stack.size()-1]);
work_stack.pop_back();
} else
+ if (arg.size() >= 2 && arg[0] == '%' && arg[1] == 'R') {
+ if (work_stack.size() < 1)
+ log_cmd_error("Must have at least one element on the stack for operator %%R.\n");
+ int count = arg.size() > 2 ? atoi(arg.c_str() + 2) : 1;
+ select_op_random(design, work_stack[work_stack.size()-1], count);
+ } else
if (arg == "%s") {
if (work_stack.size() < 1)
log_cmd_error("Must have at least one element on the stack for operator %%s.\n");
select_op_submod(design, work_stack[work_stack.size()-1]);
} else
+ if (arg == "%M") {
+ if (work_stack.size() < 1)
+ log_cmd_error("Must have at least one element on the stack for operator %%M.\n");
+ select_op_cells_to_modules(design, work_stack[work_stack.size()-1]);
+ } else
+ if (arg == "%C") {
+ if (work_stack.size() < 1)
+ log_cmd_error("Must have at least one element on the stack for operator %%M.\n");
+ select_op_module_to_cells(design, work_stack[work_stack.size()-1]);
+ } else
if (arg == "%c") {
if (work_stack.size() < 1)
log_cmd_error("Must have at least one element on the stack for operator %%c.\n");
@@ -633,17 +714,32 @@ static void select_stmt(RTLIL::Design *design, std::string arg)
if (arg == "%x" || (arg.size() > 2 && arg.substr(0, 2) == "%x" && (arg[2] == ':' || arg[2] == '*' || arg[2] == '.' || ('0' <= arg[2] && arg[2] <= '9')))) {
if (work_stack.size() < 1)
log_cmd_error("Must have at least one element on the stack for operator %%x.\n");
- select_op_expand(design, arg, 'x');
+ select_op_expand(design, arg, 'x', false);
} else
if (arg == "%ci" || (arg.size() > 3 && arg.substr(0, 3) == "%ci" && (arg[3] == ':' || arg[3] == '*' || arg[3] == '.' || ('0' <= arg[3] && arg[3] <= '9')))) {
if (work_stack.size() < 1)
log_cmd_error("Must have at least one element on the stack for operator %%ci.\n");
- select_op_expand(design, arg, 'i');
+ select_op_expand(design, arg, 'i', false);
} else
if (arg == "%co" || (arg.size() > 3 && arg.substr(0, 3) == "%co" && (arg[3] == ':' || arg[3] == '*' || arg[3] == '.' || ('0' <= arg[3] && arg[3] <= '9')))) {
if (work_stack.size() < 1)
log_cmd_error("Must have at least one element on the stack for operator %%co.\n");
- select_op_expand(design, arg, 'o');
+ select_op_expand(design, arg, 'o', false);
+ } else
+ if (arg == "%xe" || (arg.size() > 3 && arg.substr(0, 3) == "%xe" && (arg[3] == ':' || arg[3] == '*' || arg[3] == '.' || ('0' <= arg[3] && arg[3] <= '9')))) {
+ if (work_stack.size() < 1)
+ log_cmd_error("Must have at least one element on the stack for operator %%xe.\n");
+ select_op_expand(design, arg, 'x', true);
+ } else
+ if (arg == "%cie" || (arg.size() > 4 && arg.substr(0, 4) == "%cie" && (arg[4] == ':' || arg[4] == '*' || arg[4] == '.' || ('0' <= arg[4] && arg[4] <= '9')))) {
+ if (work_stack.size() < 1)
+ log_cmd_error("Must have at least one element on the stack for operator %%cie.\n");
+ select_op_expand(design, arg, 'i', true);
+ } else
+ if (arg == "%coe" || (arg.size() > 4 && arg.substr(0, 4) == "%coe" && (arg[4] == ':' || arg[4] == '*' || arg[4] == '.' || ('0' <= arg[4] && arg[4] <= '9')))) {
+ if (work_stack.size() < 1)
+ log_cmd_error("Must have at least one element on the stack for operator %%coe.\n");
+ select_op_expand(design, arg, 'o', true);
} else
log_cmd_error("Unknown selection operator '%s'.\n", arg.c_str());
if (work_stack.size() >= 1)
@@ -684,7 +780,7 @@ static void select_stmt(RTLIL::Design *design, std::string arg)
select_filter_active_mod(design, work_stack.back());
return;
}
-
+
sel.full_selection = false;
for (auto &mod_it : design->modules_)
{
@@ -856,7 +952,7 @@ struct SelectPass : public Pass {
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
log(" select [ -add | -del | -set <name> ] {-read <filename> | <selection>}\n");
- log(" select [ -assert-none | -assert-any ] {-read <filename> | <selection>}\n");
+ log(" select [ <assert_option> ] {-read <filename> | <selection>}\n");
log(" select [ -list | -write <filename> | -count | -clear ]\n");
log(" select -module <modname>\n");
log("\n");
@@ -892,6 +988,14 @@ struct SelectPass : public Pass {
log(" do not modify the current selection. instead assert that the given\n");
log(" selection contains exactly N objects.\n");
log("\n");
+ log(" -assert-max N\n");
+ log(" do not modify the current selection. instead assert that the given\n");
+ log(" selection contains less than or exactly N objects.\n");
+ log("\n");
+ log(" -assert-min N\n");
+ log(" do not modify the current selection. instead assert that the given\n");
+ log(" selection contains at least N objects.\n");
+ log("\n");
log(" -list\n");
log(" list all objects in the current selection\n");
log("\n");
@@ -1012,7 +1116,7 @@ struct SelectPass : public Pass {
log(" like %%d but swap the roles of two top sets on the stack\n");
log("\n");
log(" %%c\n");
- log(" create a copy of the top set rom the stack and push it\n");
+ log(" create a copy of the top set from the stack and push it\n");
log("\n");
log(" %%x[<num1>|*][.<num2>][:<rule>[:<rule>..]]\n");
log(" expand top set <num1> num times according to the specified rules.\n");
@@ -1029,19 +1133,31 @@ struct SelectPass : public Pass {
log("\n");
log(" %%ci[<num1>|*][.<num2>][:<rule>[:<rule>..]]\n");
log(" %%co[<num1>|*][.<num2>][:<rule>[:<rule>..]]\n");
- log(" simmilar to %%x, but only select input (%%ci) or output cones (%%co)\n");
+ log(" similar to %%x, but only select input (%%ci) or output cones (%%co)\n");
+ log("\n");
+ log(" %%xe[...] %%cie[...] %%coe\n");
+ log(" like %%x, %%ci, and %%co but only consider combinatorial cells\n");
log("\n");
log(" %%a\n");
log(" expand top set by selecting all wires that are (at least in part)\n");
log(" aliases for selected wires.\n");
log("\n");
log(" %%s\n");
- log(" expand top set by adding all modules of instantiated cells in selected\n");
+ log(" expand top set by adding all modules that implement cells in selected\n");
log(" modules\n");
log("\n");
log(" %%m\n");
log(" expand top set by selecting all modules that contain selected objects\n");
log("\n");
+ log(" %%M\n");
+ log(" select modules that implement selected cells\n");
+ log("\n");
+ log(" %%C\n");
+ log(" select cells that implement selected modules\n");
+ log("\n");
+ log(" %%R[<num>]\n");
+ log(" select <num> random objects from top selection (default 1)\n");
+ log("\n");
log("Example: the following command selects all wires that are connected to a\n");
log("'GATE' input of a 'SWITCH' cell:\n");
log("\n");
@@ -1060,6 +1176,8 @@ struct SelectPass : public Pass {
bool assert_none = false;
bool assert_any = false;
int assert_count = -1;
+ int assert_max = -1;
+ int assert_min = -1;
std::string write_file, read_file;
std::string set_name, sel_str;
@@ -1089,6 +1207,14 @@ struct SelectPass : public Pass {
assert_count = atoi(args[++argidx].c_str());
continue;
}
+ if (arg == "-assert-max" && argidx+1 < args.size()) {
+ assert_max = atoi(args[++argidx].c_str());
+ continue;
+ }
+ if (arg == "-assert-min" && argidx+1 < args.size()) {
+ assert_min = atoi(args[++argidx].c_str());
+ continue;
+ }
if (arg == "-clear") {
clear_mode = true;
continue;
@@ -1165,14 +1291,14 @@ struct SelectPass : public Pass {
if (none_mode && args.size() != 2)
log_cmd_error("Option -none can not be combined with any other options.\n");
- if (add_mode + del_mode + assert_none + assert_any + (assert_count >= 0) > 1)
- log_cmd_error("Options -add, -del, -assert-none, -assert-any or -assert-count can not be combined.\n");
+ if (add_mode + del_mode + assert_none + assert_any + (assert_count >= 0) + (assert_max >= 0) + (assert_min >= 0) > 1)
+ log_cmd_error("Options -add, -del, -assert-none, -assert-any, assert-count, -assert-max or -assert-min can not be combined.\n");
- if ((list_mode || !write_file.empty() || count_mode) && (add_mode || del_mode || assert_none || assert_any || assert_count >= 0))
- log_cmd_error("Options -list, -write and -count can not be combined with -add, -del, -assert-none, -assert-any or -assert-count.\n");
+ if ((list_mode || !write_file.empty() || count_mode) && (add_mode || del_mode || assert_none || assert_any || assert_count >= 0 || assert_max >= 0 || assert_min >= 0))
+ log_cmd_error("Options -list, -write and -count can not be combined with -add, -del, -assert-none, -assert-any, assert-count, -assert-max, or -assert-min.\n");
- if (!set_name.empty() && (list_mode || !write_file.empty() || count_mode || add_mode || del_mode || assert_none || assert_any || assert_count >= 0))
- log_cmd_error("Option -set can not be combined with -list, -write, -count, -add, -del, -assert-none, -assert-any or -assert-count.\n");
+ if (!set_name.empty() && (list_mode || !write_file.empty() || count_mode || add_mode || del_mode || assert_none || assert_any || assert_count >= 0 || assert_max >= 0 || assert_min >= 0))
+ log_cmd_error("Option -set can not be combined with -list, -write, -count, -add, -del, -assert-none, -assert-any, -assert-count, -assert-max, or -assert-min.\n");
if (work_stack.size() == 0 && got_module) {
RTLIL::Selection sel;
@@ -1261,8 +1387,9 @@ struct SelectPass : public Pass {
{
if (work_stack.size() == 0)
log_cmd_error("No selection to check.\n");
+ work_stack.back().optimize(design);
if (!work_stack.back().empty())
- log_error("Assertation failed: selection is not empty:%s\n", sel_str.c_str());
+ log_error("Assertion failed: selection is not empty:%s\n", sel_str.c_str());
return;
}
@@ -1270,12 +1397,13 @@ struct SelectPass : public Pass {
{
if (work_stack.size() == 0)
log_cmd_error("No selection to check.\n");
+ work_stack.back().optimize(design);
if (work_stack.back().empty())
- log_error("Assertation failed: selection is empty:%s\n", sel_str.c_str());
+ log_error("Assertion failed: selection is empty:%s\n", sel_str.c_str());
return;
}
- if (assert_count >= 0)
+ if (assert_count >= 0 || assert_max >= 0 || assert_min >= 0)
{
int total_count = 0;
if (work_stack.size() == 0)
@@ -1297,9 +1425,15 @@ struct SelectPass : public Pass {
if (sel->selected_member(mod_it.first, it.first))
total_count++;
}
- if (assert_count != total_count)
- log_error("Assertation failed: selection contains %d elements instead of the asserted %d:%s\n",
+ if (assert_count >= 0 && assert_count != total_count)
+ log_error("Assertion failed: selection contains %d elements instead of the asserted %d:%s\n",
total_count, assert_count, sel_str.c_str());
+ if (assert_max >= 0 && assert_max < total_count)
+ log_error("Assertion failed: selection contains %d elements, more than the maximum number %d:%s\n",
+ total_count, assert_max, sel_str.c_str());
+ if (assert_min >= 0 && assert_min > total_count)
+ log_error("Assertion failed: selection contains %d elements, less than the minimum number %d:%s\n",
+ total_count, assert_min, sel_str.c_str());
return;
}
@@ -1328,7 +1462,7 @@ struct SelectPass : public Pass {
design->selection_stack.back().optimize(design);
}
} SelectPass;
-
+
struct CdPass : public Pass {
CdPass() : Pass("cd", "a shortcut for 'select -module <name>'") { }
virtual void help()
@@ -1343,7 +1477,7 @@ struct CdPass : public Pass {
log(" cd <cellname>\n");
log("\n");
log("When no module with the specified name is found, but there is a cell\n");
- log("with the specified name in the current module, then this is equivialent\n");
+ log("with the specified name in the current module, then this is equivalent\n");
log("to 'cd <celltype>'.\n");
log("\n");
log(" cd ..\n");
@@ -1400,7 +1534,7 @@ static void log_matches(const char *title, Module *module, T list)
log(" %s\n", RTLIL::id2cstr(id));
}
}
-
+
struct LsPass : public Pass {
LsPass() : Pass("ls", "list modules or objects in modules") { }
virtual void help()
@@ -1444,5 +1578,5 @@ struct LsPass : public Pass {
}
}
} LsPass;
-
+
PRIVATE_NAMESPACE_END