From 697cf1eb807ce48b69946a13769c647c82869efb Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Thu, 14 Mar 2013 15:57:47 +0100 Subject: Added #ci and #co selection operators --- kernel/celltypes.h | 20 ++++-- kernel/select.cc | 206 +++++++++++++++++++++++++++++++---------------------- 2 files changed, 136 insertions(+), 90 deletions(-) (limited to 'kernel') diff --git a/kernel/celltypes.h b/kernel/celltypes.h index d6a12525..6273e926 100644 --- a/kernel/celltypes.h +++ b/kernel/celltypes.h @@ -29,6 +29,21 @@ struct CellTypes std::set cell_types; std::vector designs; + void setup(const RTLIL::Design *design = NULL) + { + if (design) + setup_design(design); + setup_internals(); + setup_internals_mem(); + setup_stdcells(); + setup_stdcells_mem(); + } + + void setup_design(const RTLIL::Design *design) + { + designs.push_back(design); + } + void setup_internals() { cell_types.insert("$not"); @@ -101,11 +116,6 @@ struct CellTypes cell_types.insert("$_DFF_PP1_"); } - void setup_design(const RTLIL::Design *design) - { - designs.push_back(design); - } - void clear() { cell_types.clear(); diff --git a/kernel/select.cc b/kernel/select.cc index 79281d0c..650774c0 100644 --- a/kernel/select.cc +++ b/kernel/select.cc @@ -18,6 +18,7 @@ */ #include "kernel/register.h" +#include "kernel/celltypes.h" #include "kernel/log.h" #include #include @@ -243,9 +244,10 @@ static int parse_comma_list(std::set &tokens, std::string str, } } -static int select_op_expand(RTLIL::Design *design, RTLIL::Selection &lhs, std::vector &rules, std::set &limits, int max_objects) +static int select_op_expand(RTLIL::Design *design, RTLIL::Selection &lhs, std::vector &rules, std::set &limits, int max_objects, char mode, CellTypes &ct) { int sel_objects = 0; + bool is_input, is_output; for (auto &mod_it : design->modules) { if (lhs.selected_whole_module(mod_it.first) || !lhs.selected_module(mod_it.first)) @@ -276,12 +278,16 @@ static int select_op_expand(RTLIL::Design *design, RTLIL::Selection &lhs, std::v if (last_mode == '+') goto exclude_match; include_match: + is_input = mode == 'x' || ct.cell_input(cell.second->type, conn.first); + is_output = mode == 'x' || ct.cell_output(cell.second->type, conn.first); for (auto &chunk : conn.second.chunks) if (chunk.wire != NULL) { if (max_objects != 0 && selected_wires.count(chunk.wire) > 0 && lhs.selected_members[mod->name].count(cell.first) == 0) - lhs.selected_members[mod->name].insert(cell.first), sel_objects++, max_objects--; + if (mode == 'x' || (mode == 'i' && is_output) || (mode == 'o' && is_input)) + lhs.selected_members[mod->name].insert(cell.first), sel_objects++, max_objects--; 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) - lhs.selected_members[mod->name].insert(chunk.wire->name), sel_objects++, max_objects--; + if (mode == 'x' || (mode == 'i' && is_input) || (mode == 'o' && is_output)) + lhs.selected_members[mod->name].insert(chunk.wire->name), sel_objects++, max_objects--; } exclude_match:; } @@ -290,6 +296,98 @@ 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) +{ + int pos = mode == 'x' ? 2 : 3, levels = 1, rem_objects = -1; + std::vector rules; + std::set limits; + + CellTypes ct; + + if (mode != 'x') + ct.setup(design); + + if (pos < int(arg.size()) && arg[pos] == '*') { + levels = 1000000; + pos++; + } else + if (pos < int(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()); + pos = endpos; + } + + if (pos < int(arg.size()) && arg[pos] == '.') { + size_t endpos = arg.find_first_not_of("0123456789", ++pos); + if (endpos == std::string::npos) + endpos = arg.size(); + if (int(endpos) > pos) + rem_objects = atoi(arg.substr(pos, endpos-pos).c_str()); + pos = endpos; + } + + while (pos < int(arg.size())) { + if (arg[pos] != ':' || pos+1 == int(arg.size())) + log_cmd_error("Syntax error in expand operator '%s'.\n", arg.c_str()); + 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 < int(arg.size()) && arg[pos] == '[') { + pos = parse_comma_list(rule.port_names, arg, pos+1, "]:"); + if (pos < int(arg.size()) && arg[pos] == ']') + pos++; + } + rules.push_back(rule); + } else { + size_t endpos = arg.find(':', pos); + if (endpos == std::string::npos) + endpos = arg.size(); + if (int(endpos) > pos) + limits.insert(RTLIL::escape_id(arg.substr(pos, endpos-pos))); + pos = endpos; + } + } + +#if 0 + log("expand by %d levels (max. %d objects):\n", levels, rem_objects); + for (auto &rule : rules) { + log(" rule (%c):\n", rule.mode); + if (rule.cell_types.size() > 0) { + log(" cell types:"); + for (auto &it : rule.cell_types) + log(" %s", it.c_str()); + log("\n"); + } + if (rule.port_names.size() > 0) { + log(" port names:"); + for (auto &it : rule.port_names) + log(" %s", it.c_str()); + log("\n"); + } + } + if (limits.size() > 0) { + log(" limits:"); + for (auto &it : limits) + log(" %s", it.c_str()); + log("\n"); + } +#endif + + while (levels-- > 0 && rem_objects != 0) { + int num_objects = select_op_expand(design, work_stack.back(), rules, limits, rem_objects, mode, ct); + if (num_objects == 0) + break; + rem_objects -= num_objects; + } + + if (rem_objects == 0) + log("Warning: reached configured limit at `%s'.\n", arg.c_str()); +} + static void select_filter_active_mod(RTLIL::Design *design, RTLIL::Selection &sel) { if (design->selected_active_module.empty()) @@ -336,107 +434,41 @@ static void select_stmt(RTLIL::Design *design, std::string arg) } else if (arg == "#n") { if (work_stack.size() < 1) - log_cmd_error("Must have at least one element on stack for operator #n.\n"); + log_cmd_error("Must have at least one element on the stack for operator #n.\n"); select_op_neg(design, work_stack[work_stack.size()-1]); } else if (arg == "#u") { if (work_stack.size() < 2) - log_cmd_error("Must have at least two elements on stack for operator #u.\n"); + log_cmd_error("Must have at least two elements on the stack for operator #u.\n"); select_op_union(design, work_stack[work_stack.size()-2], work_stack[work_stack.size()-1]); work_stack.pop_back(); } else if (arg == "#d") { if (work_stack.size() < 2) - log_cmd_error("Must have at least two elements on stack for operator #d.\n"); + log_cmd_error("Must have at least two elements on the stack for operator #d.\n"); select_op_diff(design, work_stack[work_stack.size()-2], work_stack[work_stack.size()-1]); work_stack.pop_back(); } else if (arg == "#i") { if (work_stack.size() < 2) - log_cmd_error("Must have at least two elements on stack for operator #i.\n"); + log_cmd_error("Must have at least two elements on the stack for operator #i.\n"); 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.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 stack for operator #x.\n"); - int pos = 2, levels = 1, rem_objects = -1; - std::vector rules; - std::set limits; - if (pos < int(arg.size()) && arg[pos] == '*') { - levels = 1000000; - pos++; - } else - if (pos < int(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()); - pos = endpos; - } - if (pos < int(arg.size()) && arg[pos] == '.') { - size_t endpos = arg.find_first_not_of("0123456789", ++pos); - if (endpos == std::string::npos) - endpos = arg.size(); - if (int(endpos) > pos) - rem_objects = atoi(arg.substr(pos, endpos-pos).c_str()); - pos = endpos; - } - while (pos < int(arg.size())) { - if (arg[pos] != ':' || pos+1 == int(arg.size())) - log_cmd_error("Syntax error in expand operator '%s'.\n", arg.c_str()); - 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 < int(arg.size()) && arg[pos] == '[') { - pos = parse_comma_list(rule.port_names, arg, pos+1, "]:"); - if (pos < int(arg.size()) && arg[pos] == ']') - pos++; - } - rules.push_back(rule); - } else { - size_t endpos = arg.find(':', pos); - if (endpos == std::string::npos) - endpos = arg.size(); - if (int(endpos) > pos) - limits.insert(RTLIL::escape_id(arg.substr(pos, endpos-pos))); - pos = endpos; - } - } - #if 0 - log("expand by %d levels (max. %d objects):\n", levels, rem_objects); - for (auto &rule : rules) { - log(" rule (%c):\n", rule.mode); - if (rule.cell_types.size() > 0) { - log(" cell types:"); - for (auto &it : rule.cell_types) - log(" %s", it.c_str()); - log("\n"); - } - if (rule.port_names.size() > 0) { - log(" port names:"); - for (auto &it : rule.port_names) - log(" %s", it.c_str()); - log("\n"); - } - } - if (limits.size() > 0) { - log(" limits:"); - for (auto &it : limits) - log(" %s", it.c_str()); - log("\n"); - } - #endif - while (levels-- > 0 && rem_objects != 0) { - int num_objects = select_op_expand(design, work_stack.back(), rules, limits, rem_objects); - if (num_objects == 0) - break; - rem_objects -= num_objects; - } - if (rem_objects == 0) - log("Warning: reached configured limit at `%s'.\n", arg.c_str()); + log_cmd_error("Must have at least one element on the stack for operator #x.\n"); + select_op_expand(design, arg, 'x'); + } 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'); + } 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'); } else log_cmd_error("Unknown selection operator '%s'.\n", arg.c_str()); select_filter_active_mod(design, work_stack.back()); @@ -704,6 +736,10 @@ struct SelectPass : public Pass { log(" limit is reached. When '*' is used instead of then the process\n"); log(" is repeated until no further object are selected.\n"); log("\n"); + log(" #ci[|*][.][:[:..]]\n"); + log(" #co[|*][.][:[:..]]\n"); + log(" simmilar to #x, but only select input (#ci) or output cones (#co)\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"); -- cgit v1.2.3