diff options
Diffstat (limited to 'passes/cmds/select.cc')
-rw-r--r-- | passes/cmds/select.cc | 194 |
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 |