diff options
author | Clifford Wolf <clifford@clifford.at> | 2013-03-05 12:53:40 +0100 |
---|---|---|
committer | Clifford Wolf <clifford@clifford.at> | 2013-03-05 12:53:40 +0100 |
commit | 334fd03e1ccdc7e6330672318679a225b257e553 (patch) | |
tree | f9d9aa1be9f161808fb64fd48e7a2fb91d782588 | |
parent | efbb89de1a02806c0d6aa05eef5e80ea683f27ac (diff) | |
download | yosys-334fd03e1ccdc7e6330672318679a225b257e553.tar.gz yosys-334fd03e1ccdc7e6330672318679a225b257e553.tar.bz2 yosys-334fd03e1ccdc7e6330672318679a225b257e553.zip |
Implemented much better #x select operator
-rw-r--r-- | kernel/select.cc | 101 | ||||
-rw-r--r-- | passes/extract/extract.cc | 6 |
2 files changed, 91 insertions, 16 deletions
diff --git a/kernel/select.cc b/kernel/select.cc index 225c7e806..3a3c3013f 100644 --- a/kernel/select.cc +++ b/kernel/select.cc @@ -220,7 +220,30 @@ static void select_op_intersect(RTLIL::Design *design, RTLIL::Selection &lhs, co lhs.selected_members.erase(it); } -static void select_op_expand(RTLIL::Design *design, RTLIL::Selection &lhs) +namespace { + struct expand_rule_t { + char mode; + std::set<RTLIL::IdString> cell_types, port_names; + }; +} + +static int parse_comma_list(std::set<RTLIL::IdString> &tokens, std::string str, size_t pos, std::string stopchar) +{ + stopchar += ','; + while (1) { + size_t endpos = str.find_first_of(stopchar, pos); + if (endpos == std::string::npos) + endpos = str.size(); + if (endpos != pos) + tokens.insert(RTLIL::escape_id(str.substr(pos, endpos-pos))); + pos = endpos; + if (pos == str.size() || str[pos] != ',') + return pos; + pos++; + } +} + +static void select_op_expand(RTLIL::Design *design, RTLIL::Selection &lhs, std::vector<expand_rule_t> &rules) { for (auto &mod_it : design->modules) { @@ -236,13 +259,31 @@ static void select_op_expand(RTLIL::Design *design, RTLIL::Selection &lhs) for (auto &cell : mod->cells) for (auto &conn : cell.second->connections) - for (auto &chunk : conn.second.chunks) - if (chunk.wire != NULL) { - if (selected_wires.count(chunk.wire) > 0) - lhs.selected_members[mod->name].insert(cell.first); - if (lhs.selected_members[mod->name].count(cell.first) > 0) - lhs.selected_members[mod->name].insert(chunk.wire->name); + { + char last_mode = '-'; + for (auto &rule : rules) { + last_mode = rule.mode; + if (rule.cell_types.size() > 0 && rule.cell_types.count(cell.second->type)) + continue; + if (rule.port_names.size() > 0 && rule.port_names.count(cell.first)) + continue; + if (rule.mode == '+') + goto include_match; + else + goto exclude_match; } + if (last_mode == '+') + goto exclude_match; + include_match: + for (auto &chunk : conn.second.chunks) + if (chunk.wire != NULL) { + if (selected_wires.count(chunk.wire) > 0) + lhs.selected_members[mod->name].insert(cell.first); + if (lhs.selected_members[mod->name].count(cell.first) > 0) + lhs.selected_members[mod->name].insert(chunk.wire->name); + } + exclude_match:; + } } } @@ -307,14 +348,38 @@ 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 == "#x" || arg.substr(0, 3) == "#x:") { + if (arg == "#x" || (arg.size() > 2 && arg.substr(0, 2) == "#x" && (arg[2] == ':' || ('0' <= arg[2] && arg[2] <= '9')))) { if (work_stack.size() < 1) log_cmd_error("Must have at least one element on stack for operator #x.\n"); - int levels = 1; + size_t pos = 2, levels = 1; + std::vector<expand_rule_t> rules; + if (pos < arg.size() && '0' <= arg[pos] && arg[pos] <= '9') { + size_t endpos = arg.find_first_not_of("0123456789", pos); + if (endpos == std::string::npos) + endpos = arg.size(); + levels = atoi(arg.substr(pos, endpos-pos).c_str()); + } + while (pos < arg.size()) { + if (arg[pos] != ':' || pos+1 == arg.size()) + goto syntax_error_x; + pos++; + if (arg[pos] == '+' || arg[pos] == '-') { + expand_rule_t rule; + rule.mode = arg[pos++]; + pos = parse_comma_list(rule.cell_types, arg, pos, "[:"); + if (pos < arg.size() && arg[pos] == '[') { + pos = parse_comma_list(rule.port_names, arg, pos, "]:"); + if (pos < arg.size() && arg[pos] == ']') + pos++; + } + } else + syntax_error_x: + log_cmd_error("Syntax error in expand operator '%s'.\n", arg.c_str()); + } if (arg.size() > 3) levels = std::max(atoi(arg.substr(3).c_str()), 1); while (levels-- > 0) - select_op_expand(design, work_stack.back()); + select_op_expand(design, work_stack.back(), rules); } else log_cmd_error("Unknown selection operator '%s'.\n", arg.c_str()); select_filter_active_mod(design, work_stack.back()); @@ -560,9 +625,19 @@ struct SelectPass : public Pass { log(" #d\n"); log(" pop the top set from the stack and subtract it from the new top\n"); log("\n"); - log(" #x:<num>\n"); - log(" expand top set by <num> levels (i.e. select all cells connected\n"); - log(" to selected wires and select all wires connected to selected cells)\n"); + log(" #x[<num>][:<rule>[:<rule>..]]\n"); + log(" expand top set <num> num times accorind to the specified rules.\n"); + log(" (i.e. select all cells connected to selected wires and select all\n"); + log(" wires connected to selected cells) The rules specify which cell\n"); + log(" ports to use for this. the syntax for a rule is a '-' for exclusion\n"); + log(" and a '+' for inclusion, followed by an optional comma seperated\n"); + log(" list of cell types followed by an optional comma seperated list of\n"); + log(" cell ports in square brackets.\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"); + log(" select */t:SWITCH #x:+[GATE] */t:SWITCH #d\n"); log("\n"); } virtual void execute(std::vector<std::string> args, RTLIL::Design *design) diff --git a/passes/extract/extract.cc b/passes/extract/extract.cc index 669108612..62d09523e 100644 --- a/passes/extract/extract.cc +++ b/passes/extract/extract.cc @@ -121,6 +121,9 @@ namespace if (max_fanout > 0 && sig_use_count[std::pair<RTLIL::Wire*, int>(chunk.wire, chunk.offset)] > max_fanout) continue; + if (sel && !sel->selected(mod, chunk.wire)) + continue; + if (sig_bit_ref.count(chunk) == 0) { bit_ref_t &bit_ref = sig_bit_ref[chunk]; bit_ref.cell = cell->name; @@ -308,9 +311,6 @@ struct ExtractPass : public Pass { log("integer value. Then this value is used to determine the order in which the pass\n"); log("tries to map the modules to the design (ascending, default value is 0).\n"); log("\n"); - log("This pass operates on whole modules or selected cells from modules. Other\n"); - log("selected entities (wires, etc.) are ignored.\n"); - log("\n"); log("See 'help techmap' for a pass that does the opposite thing.\n"); log("\n"); } |