From f6b5e47e40b4a2bda6e5d928480ea218a6a911c2 Mon Sep 17 00:00:00 2001 From: David Shah Date: Thu, 19 Sep 2019 20:43:13 +0100 Subject: sv: Switch parser to glr, prep for typedef Signed-off-by: David Shah --- frontends/ast/ast.cc | 3 +++ frontends/ast/ast.h | 7 ++++-- frontends/ast/genrtlil.cc | 1 + frontends/ast/simplify.cc | 51 ++++++++++++++++++++++++++++++++++---- frontends/verilog/verilog_parser.y | 38 +++++++++++++++++++++++++--- 5 files changed, 89 insertions(+), 11 deletions(-) (limited to 'frontends') diff --git a/frontends/ast/ast.cc b/frontends/ast/ast.cc index 21279cbfa..937dad9be 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 93fee913e..fcc661b4c 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 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..b94662bcd 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 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,44 @@ 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); + while(children[0]->simplify(const_fold, at_zero, in_lvalue, stage, width_hint, sign_hint, in_param)) {}; + log_assert(!children[0]->is_custom_type); + } + + // resolve types of wires and parameters + if (type == AST_WIRE || type == AST_LOCALPARAM || type == AST_PARAMETER) { + 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", 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", children[0]->str.c_str()); + log_assert(resolved_type->children.size() == 1); + AstNode *templ = resolved_type->children[0]; + delete_children(); // type reference no longer needed + + 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; + for (auto template_child : templ->children) + children.push_back(template_child->clone()); + } + log_assert(!is_custom_type); + } + // resolve constant prefixes if (type == AST_PREFIX) { if (children[0]->type != AST_CONSTANT) { @@ -1194,7 +1234,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 +1246,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, std::vector 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]; @@ -2945,6 +2985,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); } diff --git a/frontends/verilog/verilog_parser.y b/frontends/verilog/verilog_parser.y index 4afd72b73..eb091bea6 100644 --- a/frontends/verilog/verilog_parser.y +++ b/frontends/verilog/verilog_parser.y @@ -112,6 +112,8 @@ struct specify_rise_fall { %define api.prefix {frontend_verilog_yy} +%glr-parser + /* The union is defined in the header, so we need to provide all the * includes it requires */ @@ -180,7 +182,7 @@ struct specify_rise_fall { %right UNARY_OPS %define parse.error verbose -%define parse.lac full +// %define parse.lac full %nonassoc FAKE_THEN %nonassoc TOK_ELSE @@ -206,6 +208,7 @@ design: task_func_decl design | param_decl design | localparam_decl design | + typedef_decl design | package design | interface design | /* empty */; @@ -426,6 +429,7 @@ package_body: package_body package_body_stmt |; package_body_stmt: + typedef_decl | localparam_decl; interface: @@ -452,7 +456,7 @@ interface_body: interface_body interface_body_stmt |; interface_body_stmt: - param_decl | localparam_decl | defparam_decl | wire_decl | always_stmt | assign_stmt | + param_decl | localparam_decl | typedef_decl | defparam_decl | wire_decl | always_stmt | assign_stmt | modport_stmt; non_opt_delay: @@ -529,6 +533,11 @@ wire_type_token: } | TOK_CONST { current_wire_const = true; + } | + hierarchical_id { + astbuf3->is_custom_type = true; + astbuf3->children.push_back(new AstNode(AST_WIRETYPE)); + astbuf3->children.back()->str = *$1; }; non_opt_range: @@ -591,7 +600,7 @@ module_body: /* empty */; module_body_stmt: - task_func_decl | specify_block |param_decl | localparam_decl | defparam_decl | specparam_declaration | wire_decl | assign_stmt | cell_stmt | + task_func_decl | specify_block |param_decl | localparam_decl | typedef_decl | defparam_decl | specparam_declaration | wire_decl | assign_stmt | cell_stmt | always_stmt | TOK_GENERATE module_gen_body TOK_ENDGENERATE | defattr | assert_property | checker_decl | ignored_specify_block; checker_decl: @@ -1377,6 +1386,27 @@ assign_expr: ast_stack.back()->children.push_back(new AstNode(AST_ASSIGN, $1, $3)); }; +typedef_decl: + TOK_TYPEDEF wire_type range TOK_ID ';' { + astbuf1 = $2; + astbuf2 = $3; + if (astbuf1->range_left >= 0 && astbuf1->range_right >= 0) { + if (astbuf2) { + frontend_verilog_yyerror("integer/genvar types cannot have packed dimensions."); + } else { + astbuf2 = new AstNode(AST_RANGE); + astbuf2->children.push_back(AstNode::mkconst_int(astbuf1->range_left, true)); + astbuf2->children.push_back(AstNode::mkconst_int(astbuf1->range_right, true)); + } + } + if (astbuf2 && astbuf2->children.size() != 2) + frontend_verilog_yyerror("wire/reg/logic packed dimension must be of the form: [:], [+:], or [-:]"); + if (astbuf2) + astbuf1->children.push_back(astbuf2); + ast_stack.back()->children.push_back(new AstNode(AST_TYPEDEF, astbuf1)); + ast_stack.back()->children.back()->str = *$4; + }; + cell_stmt: attr TOK_ID { astbuf1 = new AstNode(AST_CELL); @@ -1823,7 +1853,7 @@ simple_behavioral_stmt: // this production creates the obligatory if-else shift/reduce conflict behavioral_stmt: - defattr | assert | wire_decl | param_decl | localparam_decl | + defattr | assert | wire_decl | param_decl | localparam_decl | typedef_decl | non_opt_delay behavioral_stmt | simple_behavioral_stmt ';' | ';' | hierarchical_id attr { -- cgit v1.2.3 From c9629516120930aedaf52d72fec5d7fabe51d496 Mon Sep 17 00:00:00 2001 From: David Shah Date: Thu, 19 Sep 2019 21:07:20 +0100 Subject: sv: Fix typedef parameters Signed-off-by: David Shah --- frontends/ast/simplify.cc | 33 +++++++++++++++++++++++++++++++-- frontends/verilog/verilog_parser.y | 21 +++++++++++++++++---- 2 files changed, 48 insertions(+), 6 deletions(-) (limited to 'frontends') diff --git a/frontends/ast/simplify.cc b/frontends/ast/simplify.cc index b94662bcd..9abd2916d 100644 --- a/frontends/ast/simplify.cc +++ b/frontends/ast/simplify.cc @@ -790,8 +790,8 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, log_assert(!children[0]->is_custom_type); } - // resolve types of wires and parameters - if (type == AST_WIRE || type == AST_LOCALPARAM || type == AST_PARAMETER) { + // resolve types of wires + if (type == AST_WIRE) { if (is_custom_type) { log_assert(children.size() == 1); log_assert(children[0]->type == AST_WIRETYPE); @@ -820,6 +820,35 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, 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", 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", children[1]->str.c_str()); + log_assert(resolved_type->children.size() == 1); + AstNode *templ = resolved_type->children[0]; + delete children[1]; + children.pop_back(); + + 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()); + } + log_assert(!is_custom_type); + } + // resolve constant prefixes if (type == AST_PREFIX) { if (children[0]->type != AST_CONSTANT) { diff --git a/frontends/verilog/verilog_parser.y b/frontends/verilog/verilog_parser.y index eb091bea6..8cc084fe0 100644 --- a/frontends/verilog/verilog_parser.y +++ b/frontends/verilog/verilog_parser.y @@ -327,13 +327,13 @@ single_module_para: astbuf1 = new AstNode(AST_PARAMETER); astbuf1->children.push_back(AstNode::mkconst_int(0, true)); append_attr(astbuf1, $1); - } param_signed param_integer param_range single_param_decl | + } int_param_type single_param_decl | attr TOK_LOCALPARAM { if (astbuf1) delete astbuf1; astbuf1 = new AstNode(AST_LOCALPARAM); astbuf1->children.push_back(AstNode::mkconst_int(0, true)); append_attr(astbuf1, $1); - } param_signed param_integer param_range single_param_decl | + } int_param_type single_param_decl | single_param_decl; module_args_opt: @@ -1158,12 +1158,25 @@ param_range: } }; +custom_param_type: + hierarchical_id { + astbuf1->is_custom_type = true; + astbuf1->children.push_back(new AstNode(AST_WIRETYPE)); + astbuf1->children.back()->str = *$1; + }; + +param_type: + param_signed param_integer param_real param_range | custom_param_type; + +int_param_type: + param_signed param_integer param_range | custom_param_type; + param_decl: attr TOK_PARAMETER { astbuf1 = new AstNode(AST_PARAMETER); astbuf1->children.push_back(AstNode::mkconst_int(0, true)); append_attr(astbuf1, $1); - } param_signed param_integer param_real param_range param_decl_list ';' { + } param_type param_decl_list ';' { delete astbuf1; }; @@ -1172,7 +1185,7 @@ localparam_decl: astbuf1 = new AstNode(AST_LOCALPARAM); astbuf1->children.push_back(AstNode::mkconst_int(0, true)); append_attr(astbuf1, $1); - } param_signed param_integer param_real param_range param_decl_list ';' { + } param_type param_decl_list ';' { delete astbuf1; }; -- cgit v1.2.3 From e70e4afb60a41da6d9f6200b20f36f61c6b993b2 Mon Sep 17 00:00:00 2001 From: David Shah Date: Thu, 19 Sep 2019 21:21:21 +0100 Subject: sv: Fix typedefs in packages Signed-off-by: David Shah --- frontends/ast/simplify.cc | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) (limited to 'frontends') diff --git a/frontends/ast/simplify.cc b/frontends/ast/simplify.cc index 9abd2916d..44e32b29c 100644 --- a/frontends/ast/simplify.cc +++ b/frontends/ast/simplify.cc @@ -796,14 +796,17 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, 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", children[0]->str.c_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", children[0]->str.c_str()); + 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]; delete_children(); // type reference no longer needed + // Ensure typedef itself is fully simplified + while(templ->simplify(const_fold, at_zero, in_lvalue, stage, width_hint, sign_hint, in_param)) {}; + is_reg = templ->is_reg; is_logic = templ->is_logic; is_signed = templ->is_signed; @@ -826,15 +829,18 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, 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", children[1]->str.c_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", children[1]->str.c_str()); + 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)) {}; + is_signed = templ->is_signed; is_string = templ->is_string; is_custom_type = templ->is_custom_type; -- cgit v1.2.3 From 30d23260309ef392a0e69fe5294c38b71ad0692e Mon Sep 17 00:00:00 2001 From: David Shah Date: Fri, 20 Sep 2019 11:39:15 +0100 Subject: sv: Add support for memory typedefs Signed-off-by: David Shah --- frontends/ast/simplify.cc | 17 +++++++++++++++-- frontends/verilog/verilog_parser.y | 20 +++++++++++++++++++- 2 files changed, 34 insertions(+), 3 deletions(-) (limited to 'frontends') diff --git a/frontends/ast/simplify.cc b/frontends/ast/simplify.cc index 44e32b29c..a6ac04037 100644 --- a/frontends/ast/simplify.cc +++ b/frontends/ast/simplify.cc @@ -785,8 +785,10 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, // resolve typedefs if (type == AST_TYPEDEF) { log_assert(children.size() == 1); - log_assert(children[0]->type == AST_WIRE); - while(children[0]->simplify(const_fold, at_zero, in_lvalue, stage, width_hint, sign_hint, in_param)) {}; + 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); } @@ -807,6 +809,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, // Ensure typedef itself is fully simplified while(templ->simplify(const_fold, at_zero, in_lvalue, stage, width_hint, sign_hint, in_param)) {}; + type = templ->type; is_reg = templ->is_reg; is_logic = templ->is_logic; is_signed = templ->is_signed; @@ -819,6 +822,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, 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); } @@ -841,6 +845,8 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, // 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; @@ -851,6 +857,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, 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); } @@ -3074,6 +3081,9 @@ void AstNode::mem2reg_as_needed_pass1(dict> &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 @@ -3231,6 +3241,9 @@ bool AstNode::mem2reg_as_needed_pass2(pool &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); diff --git a/frontends/verilog/verilog_parser.y b/frontends/verilog/verilog_parser.y index 8cc084fe0..ba44d7f3d 100644 --- a/frontends/verilog/verilog_parser.y +++ b/frontends/verilog/verilog_parser.y @@ -1400,7 +1400,7 @@ assign_expr: }; typedef_decl: - TOK_TYPEDEF wire_type range TOK_ID ';' { + TOK_TYPEDEF wire_type range TOK_ID range_or_multirange ';' { astbuf1 = $2; astbuf2 = $3; if (astbuf1->range_left >= 0 && astbuf1->range_right >= 0) { @@ -1416,6 +1416,24 @@ typedef_decl: frontend_verilog_yyerror("wire/reg/logic packed dimension must be of the form: [:], [+:], or [-:]"); if (astbuf2) astbuf1->children.push_back(astbuf2); + + if ($5 != NULL) { + if (!astbuf2) { + AstNode *rng = new AstNode(AST_RANGE); + rng->children.push_back(AstNode::mkconst_int(0, true)); + rng->children.push_back(AstNode::mkconst_int(0, true)); + astbuf1->children.push_back(rng); + } + astbuf1->type = AST_MEMORY; + auto *rangeNode = $5; + if (rangeNode->type == AST_RANGE && rangeNode->children.size() == 1) { + // SV array size [n], rewrite as [n-1:0] + rangeNode->children[0] = new AstNode(AST_SUB, rangeNode->children[0], AstNode::mkconst_int(1, true)); + rangeNode->children.push_back(AstNode::mkconst_int(0, false)); + } + astbuf1->children.push_back(rangeNode); + } + ast_stack.back()->children.push_back(new AstNode(AST_TYPEDEF, astbuf1)); ast_stack.back()->children.back()->str = *$4; }; -- cgit v1.2.3 From af25585170f87506bcc7dbe5afe0fec868290d5b Mon Sep 17 00:00:00 2001 From: David Shah Date: Fri, 20 Sep 2019 11:46:37 +0100 Subject: sv: Add support for memories of a typedef Signed-off-by: David Shah --- frontends/ast/simplify.cc | 26 ++++++++++++++++++++------ 1 file changed, 20 insertions(+), 6 deletions(-) (limited to 'frontends') diff --git a/frontends/ast/simplify.cc b/frontends/ast/simplify.cc index a6ac04037..aaf1188b4 100644 --- a/frontends/ast/simplify.cc +++ b/frontends/ast/simplify.cc @@ -793,9 +793,9 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, } // resolve types of wires - if (type == AST_WIRE) { + if (type == AST_WIRE || type == AST_MEMORY) { if (is_custom_type) { - log_assert(children.size() == 1); + 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()); @@ -804,12 +804,15 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, 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]; - delete_children(); // type reference no longer needed + // 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)) {}; - type = templ->type; + if (type == AST_WIRE) + type = templ->type; is_reg = templ->is_reg; is_logic = templ->is_logic; is_signed = templ->is_signed; @@ -820,8 +823,19 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, 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()); + + // 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); -- cgit v1.2.3 From 497faf4ec0c078093ecef547965ae9d0fd153edb Mon Sep 17 00:00:00 2001 From: David Shah Date: Fri, 20 Sep 2019 11:59:33 +0100 Subject: sv: Add %expect Signed-off-by: David Shah --- frontends/verilog/verilog_parser.y | 1 + 1 file changed, 1 insertion(+) (limited to 'frontends') diff --git a/frontends/verilog/verilog_parser.y b/frontends/verilog/verilog_parser.y index ba44d7f3d..e0a654b76 100644 --- a/frontends/verilog/verilog_parser.y +++ b/frontends/verilog/verilog_parser.y @@ -113,6 +113,7 @@ struct specify_rise_fall { %define api.prefix {frontend_verilog_yy} %glr-parser +%expect 22 /* The union is defined in the header, so we need to provide all the * includes it requires -- cgit v1.2.3 From c0bb47beca2fb78670ab14515047a88a677cc608 Mon Sep 17 00:00:00 2001 From: David Shah Date: Fri, 20 Sep 2019 12:11:17 +0100 Subject: sv: Fix memories of typedefs Signed-off-by: David Shah --- frontends/verilog/verilog_parser.y | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'frontends') diff --git a/frontends/verilog/verilog_parser.y b/frontends/verilog/verilog_parser.y index e0a654b76..516fa4138 100644 --- a/frontends/verilog/verilog_parser.y +++ b/frontends/verilog/verilog_parser.y @@ -1350,7 +1350,7 @@ wire_name: if ($2 != NULL) { if (node->is_input || node->is_output) frontend_verilog_yyerror("input/output/inout ports cannot have unpacked dimensions."); - if (!astbuf2) { + if (!astbuf2 && !node->is_custom_type) { AstNode *rng = new AstNode(AST_RANGE); rng->children.push_back(AstNode::mkconst_int(0, true)); rng->children.push_back(AstNode::mkconst_int(0, true)); -- cgit v1.2.3 From 8cc1bee33c04690d729d1a8b8622be05d65f7911 Mon Sep 17 00:00:00 2001 From: David Shah Date: Fri, 20 Sep 2019 16:12:09 +0100 Subject: sv: Disambiguate interface ports Signed-off-by: David Shah --- frontends/verilog/verilog_parser.y | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) (limited to 'frontends') diff --git a/frontends/verilog/verilog_parser.y b/frontends/verilog/verilog_parser.y index 516fa4138..0024d4778 100644 --- a/frontends/verilog/verilog_parser.y +++ b/frontends/verilog/verilog_parser.y @@ -113,7 +113,8 @@ struct specify_rise_fall { %define api.prefix {frontend_verilog_yy} %glr-parser -%expect 22 +%expect 21 +%expect-rr 2 /* The union is defined in the header, so we need to provide all the * includes it requires @@ -157,7 +158,7 @@ struct specify_rise_fall { %token TOK_INCREMENT TOK_DECREMENT TOK_UNIQUE TOK_PRIORITY %type range range_or_multirange non_opt_range non_opt_multirange range_or_signed_int -%type wire_type expr basic_expr concat_list rvalue lvalue lvalue_concat_list +%type wire_type wire_type_io expr basic_expr concat_list rvalue lvalue lvalue_concat_list %type opt_label opt_sva_label tok_prim_wrapper hierarchical_id %type opt_signed opt_property unique_case_attr %type attr case_attr @@ -395,7 +396,7 @@ module_arg: ast_stack.back()->children.push_back(astbuf2); delete astbuf1; // really only needed if multiple instances of same type. } module_arg_opt_assignment | - attr wire_type range TOK_ID { + attr wire_type_io range TOK_ID { AstNode *node = $2; node->str = *$4; node->port_id = ++port_counter; @@ -479,6 +480,15 @@ wire_type: $$ = astbuf3; }; +wire_type_io: + { + astbuf3 = new AstNode(AST_WIRE); + current_wire_rand = false; + current_wire_const = false; + } io_wire_type_token_list delay { + $$ = astbuf3; + }; + wire_type_token_list: wire_type_token | wire_type_token_list wire_type_token | wire_type_token_io ; @@ -541,6 +551,12 @@ wire_type_token: astbuf3->children.back()->str = *$1; }; +wire_type_token_list_without_io: + wire_type_token | wire_type_token_list wire_type_token; + +io_wire_type_token_list: + wire_type_token_io | wire_type_token_io wire_type_token_list_without_io; + non_opt_range: '[' expr ':' expr ']' { $$ = new AstNode(AST_RANGE); -- cgit v1.2.3 From 5501d9090aaf2d508b2f082f8453effe7fce08df Mon Sep 17 00:00:00 2001 From: David Shah Date: Fri, 20 Sep 2019 18:40:23 +0100 Subject: sv: Fix typedefs in blocks Signed-off-by: David Shah --- frontends/ast/simplify.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'frontends') diff --git a/frontends/ast/simplify.cc b/frontends/ast/simplify.cc index aaf1188b4..0ebc183b2 100644 --- a/frontends/ast/simplify.cc +++ b/frontends/ast/simplify.cc @@ -3002,7 +3002,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 backup_name_map; @@ -3010,7 +3010,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; -- cgit v1.2.3 From e46e8753c84ee83f871d5ce116ce4c08dd49a031 Mon Sep 17 00:00:00 2001 From: David Shah Date: Thu, 3 Oct 2019 09:55:43 +0100 Subject: frontends/ast: code style Signed-off-by: David Shah --- frontends/ast/simplify.cc | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'frontends') diff --git a/frontends/ast/simplify.cc b/frontends/ast/simplify.cc index 0ebc183b2..44fd32cdc 100644 --- a/frontends/ast/simplify.cc +++ b/frontends/ast/simplify.cc @@ -786,9 +786,8 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, 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)) { + 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); } -- cgit v1.2.3