diff options
author | Clifford Wolf <clifford@clifford.at> | 2019-10-14 05:24:31 +0200 |
---|---|---|
committer | Clifford Wolf <clifford@clifford.at> | 2019-10-14 05:24:31 +0200 |
commit | e84cedfae4211244da45ef51a84213874579117e (patch) | |
tree | fb0a14f4c06675a7d3dbb5a1f22d386402e22d0b /frontends/ast | |
parent | 3c6a566d865e3d70f8793225a6d211ce3d6246a1 (diff) | |
parent | e46e8753c84ee83f871d5ce116ce4c08dd49a031 (diff) | |
download | yosys-e84cedfae4211244da45ef51a84213874579117e.tar.gz yosys-e84cedfae4211244da45ef51a84213874579117e.tar.bz2 yosys-e84cedfae4211244da45ef51a84213874579117e.zip |
Use "(id)" instead of "id" for types as temporary hack
Signed-off-by: Clifford Wolf <clifford@clifford.at>
Diffstat (limited to 'frontends/ast')
-rw-r--r-- | frontends/ast/ast.cc | 3 | ||||
-rw-r--r-- | frontends/ast/ast.h | 7 | ||||
-rw-r--r-- | frontends/ast/genrtlil.cc | 1 | ||||
-rw-r--r-- | frontends/ast/simplify.cc | 116 |
4 files changed, 118 insertions, 9 deletions
diff --git a/frontends/ast/ast.cc b/frontends/ast/ast.cc index 37a69d8bf..5bbea0faf 100644 --- a/frontends/ast/ast.cc +++ b/frontends/ast/ast.cc @@ -164,6 +164,8 @@ std::string AST::type2str(AstNodeType type) X(AST_MODPORT) X(AST_MODPORTMEMBER) X(AST_PACKAGE) + X(AST_WIRETYPE) + X(AST_TYPEDEF) #undef X default: log_abort(); @@ -206,6 +208,7 @@ AstNode::AstNode(AstNodeType type, AstNode *child1, AstNode *child2, AstNode *ch was_checked = false; range_valid = false; range_swapped = false; + is_custom_type = false; port_id = 0; range_left = -1; range_right = 0; diff --git a/frontends/ast/ast.h b/frontends/ast/ast.h index 0ec249ab9..918d178c7 100644 --- a/frontends/ast/ast.h +++ b/frontends/ast/ast.h @@ -148,7 +148,10 @@ namespace AST AST_INTERFACEPORTTYPE, AST_MODPORT, AST_MODPORTMEMBER, - AST_PACKAGE + AST_PACKAGE, + + AST_WIRETYPE, + AST_TYPEDEF }; // convert an node type to a string (e.g. for debug output) @@ -174,7 +177,7 @@ namespace AST // node content - most of it is unused in most node types std::string str; std::vector<RTLIL::State> bits; - bool is_input, is_output, is_reg, is_logic, is_signed, is_string, is_wand, is_wor, range_valid, range_swapped, was_checked, is_unsized; + bool is_input, is_output, is_reg, is_logic, is_signed, is_string, is_wand, is_wor, range_valid, range_swapped, was_checked, is_unsized, is_custom_type; int port_id, range_left, range_right; uint32_t integer; double realvalue; diff --git a/frontends/ast/genrtlil.cc b/frontends/ast/genrtlil.cc index 407a34472..94f5c0a04 100644 --- a/frontends/ast/genrtlil.cc +++ b/frontends/ast/genrtlil.cc @@ -863,6 +863,7 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) case AST_PACKAGE: case AST_MODPORT: case AST_MODPORTMEMBER: + case AST_TYPEDEF: break; case AST_INTERFACEPORT: { // If a port in a module with unknown type is found, mark it with the attribute 'is_interface' diff --git a/frontends/ast/simplify.cc b/frontends/ast/simplify.cc index b1ee22f42..44fd32cdc 100644 --- a/frontends/ast/simplify.cc +++ b/frontends/ast/simplify.cc @@ -318,7 +318,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, } // activate const folding if this is anything that must be evaluated statically (ranges, parameters, attributes, etc.) - if (type == AST_WIRE || type == AST_PARAMETER || type == AST_LOCALPARAM || type == AST_DEFPARAM || type == AST_PARASET || type == AST_RANGE || type == AST_PREFIX) + if (type == AST_WIRE || type == AST_PARAMETER || type == AST_LOCALPARAM || type == AST_DEFPARAM || type == AST_PARASET || type == AST_RANGE || type == AST_PREFIX || type == AST_TYPEDEF) const_fold = true; if (type == AST_IDENTIFIER && current_scope.count(str) > 0 && (current_scope[str]->type == AST_PARAMETER || current_scope[str]->type == AST_LOCALPARAM)) const_fold = true; @@ -336,6 +336,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, std::map<std::string, AstNode*> this_wire_scope; for (size_t i = 0; i < children.size(); i++) { AstNode *node = children[i]; + if (node->type == AST_WIRE) { if (node->children.size() == 1 && node->children[0]->type == AST_RANGE) { for (auto c : node->children[0]->children) { @@ -405,14 +406,15 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, this_wire_scope[node->str] = node; } if (node->type == AST_PARAMETER || node->type == AST_LOCALPARAM || node->type == AST_WIRE || node->type == AST_AUTOWIRE || node->type == AST_GENVAR || - node->type == AST_MEMORY || node->type == AST_FUNCTION || node->type == AST_TASK || node->type == AST_DPI_FUNCTION || node->type == AST_CELL) { + node->type == AST_MEMORY || node->type == AST_FUNCTION || node->type == AST_TASK || node->type == AST_DPI_FUNCTION || node->type == AST_CELL || + node->type == AST_TYPEDEF) { backup_scope[node->str] = current_scope[node->str]; current_scope[node->str] = node; } } for (size_t i = 0; i < children.size(); i++) { AstNode *node = children[i]; - if (node->type == AST_PARAMETER || node->type == AST_LOCALPARAM || node->type == AST_WIRE || node->type == AST_AUTOWIRE || node->type == AST_MEMORY) + if (node->type == AST_PARAMETER || node->type == AST_LOCALPARAM || node->type == AST_WIRE || node->type == AST_AUTOWIRE || node->type == AST_MEMORY || node->type == AST_TYPEDEF) while (node->simplify(true, false, false, 1, -1, false, node->type == AST_PARAMETER || node->type == AST_LOCALPARAM)) did_something = true; } @@ -780,6 +782,99 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, delete_children(); } + // resolve typedefs + if (type == AST_TYPEDEF) { + log_assert(children.size() == 1); + log_assert(children[0]->type == AST_WIRE || children[0]->type == AST_MEMORY); + while(children[0]->simplify(const_fold, at_zero, in_lvalue, stage, width_hint, sign_hint, in_param)) + did_something = true; + log_assert(!children[0]->is_custom_type); + } + + // resolve types of wires + if (type == AST_WIRE || type == AST_MEMORY) { + if (is_custom_type) { + log_assert(children.size() >= 1); + log_assert(children[0]->type == AST_WIRETYPE); + if (!current_scope.count(children[0]->str)) + log_file_error(filename, linenum, "Unknown identifier `%s' used as type name\n", children[0]->str.c_str()); + AstNode *resolved_type = current_scope.at(children[0]->str); + if (resolved_type->type != AST_TYPEDEF) + log_file_error(filename, linenum, "`%s' does not name a type\n", children[0]->str.c_str()); + log_assert(resolved_type->children.size() == 1); + AstNode *templ = resolved_type->children[0]; + // Remove type reference + delete children[0]; + children.erase(children.begin()); + + // Ensure typedef itself is fully simplified + while(templ->simplify(const_fold, at_zero, in_lvalue, stage, width_hint, sign_hint, in_param)) {}; + + if (type == AST_WIRE) + type = templ->type; + is_reg = templ->is_reg; + is_logic = templ->is_logic; + is_signed = templ->is_signed; + is_string = templ->is_string; + is_custom_type = templ->is_custom_type; + + range_valid = templ->range_valid; + range_swapped = templ->range_swapped; + range_left = templ->range_left; + range_right = templ->range_right; + + // Insert clones children from template at beginning + for (int i = 0; i < GetSize(templ->children); i++) + children.insert(children.begin() + i, templ->children[i]->clone()); + + if (type == AST_MEMORY && GetSize(children) == 1) { + // Single-bit memories must have [0:0] range + AstNode *rng = new AstNode(AST_RANGE); + rng->children.push_back(AstNode::mkconst_int(0, true)); + rng->children.push_back(AstNode::mkconst_int(0, true)); + children.insert(children.begin(), rng); + } + + did_something = true; + } + log_assert(!is_custom_type); + } + + // resolve types of parameters + if (type == AST_LOCALPARAM || type == AST_PARAMETER) { + if (is_custom_type) { + log_assert(children.size() == 2); + log_assert(children[1]->type == AST_WIRETYPE); + if (!current_scope.count(children[1]->str)) + log_file_error(filename, linenum, "Unknown identifier `%s' used as type name\n", children[1]->str.c_str()); + AstNode *resolved_type = current_scope.at(children[1]->str); + if (resolved_type->type != AST_TYPEDEF) + log_file_error(filename, linenum, "`%s' does not name a type\n", children[1]->str.c_str()); + log_assert(resolved_type->children.size() == 1); + AstNode *templ = resolved_type->children[0]; + delete children[1]; + children.pop_back(); + + // Ensure typedef itself is fully simplified + while(templ->simplify(const_fold, at_zero, in_lvalue, stage, width_hint, sign_hint, in_param)) {}; + + if (templ->type == AST_MEMORY) + log_file_error(filename, linenum, "unpacked array type `%s' cannot be used for a parameter\n", children[1]->str.c_str()); + is_signed = templ->is_signed; + is_string = templ->is_string; + is_custom_type = templ->is_custom_type; + + range_valid = templ->range_valid; + range_swapped = templ->range_swapped; + range_left = templ->range_left; + range_right = templ->range_right; + for (auto template_child : templ->children) + children.push_back(template_child->clone()); + did_something = true; + } + log_assert(!is_custom_type); + } + // resolve constant prefixes if (type == AST_PREFIX) { if (children[0]->type != AST_CONSTANT) { @@ -1194,7 +1289,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, if (type == AST_BLOCK && str.empty()) { for (size_t i = 0; i < children.size(); i++) - if (children[i]->type == AST_WIRE || children[i]->type == AST_MEMORY || children[i]->type == AST_PARAMETER || children[i]->type == AST_LOCALPARAM) + if (children[i]->type == AST_WIRE || children[i]->type == AST_MEMORY || children[i]->type == AST_PARAMETER || children[i]->type == AST_LOCALPARAM || children[i]->type == AST_TYPEDEF) log_file_error(children[i]->filename, children[i]->linenum, "Local declaration in unnamed block is an unsupported SystemVerilog feature!\n"); } @@ -1206,7 +1301,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, std::vector<AstNode*> new_children; for (size_t i = 0; i < children.size(); i++) - if (children[i]->type == AST_WIRE || children[i]->type == AST_MEMORY || children[i]->type == AST_PARAMETER || children[i]->type == AST_LOCALPARAM) { + if (children[i]->type == AST_WIRE || children[i]->type == AST_MEMORY || children[i]->type == AST_PARAMETER || children[i]->type == AST_LOCALPARAM || children[i]->type == AST_TYPEDEF) { children[i]->simplify(false, false, false, stage, -1, false, false); current_ast_mod->children.push_back(children[i]); current_scope[children[i]->str] = children[i]; @@ -2906,7 +3001,7 @@ void AstNode::expand_genblock(std::string index_var, std::string prefix, std::ma } } - if ((type == AST_IDENTIFIER || type == AST_FCALL || type == AST_TCALL) && name_map.count(str) > 0) + if ((type == AST_IDENTIFIER || type == AST_FCALL || type == AST_TCALL || type == AST_WIRETYPE) && name_map.count(str) > 0) str = name_map[str]; std::map<std::string, std::string> backup_name_map; @@ -2914,7 +3009,7 @@ void AstNode::expand_genblock(std::string index_var, std::string prefix, std::ma for (size_t i = 0; i < children.size(); i++) { AstNode *child = children[i]; if (child->type == AST_WIRE || child->type == AST_MEMORY || child->type == AST_PARAMETER || child->type == AST_LOCALPARAM || - child->type == AST_FUNCTION || child->type == AST_TASK || child->type == AST_CELL) { + child->type == AST_FUNCTION || child->type == AST_TASK || child->type == AST_CELL || child->type == AST_TYPEDEF) { if (backup_name_map.size() == 0) backup_name_map = name_map; std::string new_name = prefix[0] == '\\' ? prefix.substr(1) : prefix; @@ -2945,6 +3040,7 @@ void AstNode::expand_genblock(std::string index_var, std::string prefix, std::ma child->expand_genblock(index_var, prefix, name_map); } + if (backup_name_map.size() > 0) name_map.swap(backup_name_map); } @@ -2998,6 +3094,9 @@ void AstNode::mem2reg_as_needed_pass1(dict<AstNode*, pool<std::string>> &mem2reg uint32_t children_flags = 0; int lhs_children_counter = 0; + if (type == AST_TYPEDEF) + return; // don't touch content of typedefs + if (type == AST_ASSIGN || type == AST_ASSIGN_LE || type == AST_ASSIGN_EQ) { // mark all memories that are used in a complex expression on the left side of an assignment @@ -3155,6 +3254,9 @@ bool AstNode::mem2reg_as_needed_pass2(pool<AstNode*> &mem2reg_set, AstNode *mod, if (type == AST_FUNCTION || type == AST_TASK) return false; + if (type == AST_TYPEDEF) + return false; + if (type == AST_MEMINIT && id2ast && mem2reg_set.count(id2ast)) { log_assert(children[0]->type == AST_CONSTANT); |