sv: Fix typedef parameters
authorDavid Shah <dave@ds0.me>
Thu, 19 Sep 2019 20:07:20 +0000 (21:07 +0100)
committerDavid Shah <dave@ds0.me>
Thu, 3 Oct 2019 08:54:14 +0000 (09:54 +0100)
Signed-off-by: David Shah <dave@ds0.me>
frontends/ast/simplify.cc
frontends/verilog/verilog_parser.y
tests/svtypes/typedef1.sv [deleted file]
tests/svtypes/typedef_param.sv [new file with mode: 0644]
tests/svtypes/typedef_simple.sv [new file with mode: 0644]

index b94662bcd3e811f40224225cff6e0917e0e63554..9abd2916d4669a755e484286373664f815f6bb07 100644 (file)
@@ -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) {
index eb091bea6cb2b7566d51b30c4de133bec97e6562..8cc084fe08d43c3bbcc391f0908b1a434332f9cc 100644 (file)
@@ -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;
        };
 
diff --git a/tests/svtypes/typedef1.sv b/tests/svtypes/typedef1.sv
deleted file mode 100644 (file)
index 9e5d023..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-`define STRINGIFY(x) `"x`"
-`define STATIC_ASSERT(x) if(!(x)) $error({"assert failed: ", `STRINGIFY(x)})
-
-module top;
-
-       typedef logic [1:0] uint2_t;
-       typedef logic signed [3:0] int4_t;
-       typedef logic signed [7:0] int8_t;
-       typedef int8_t char_t;
-
-       (* keep *) uint2_t int2 = 2'b10;
-       (* keep *) int4_t int4 = -1;
-       (* keep *) int8_t int8 = int4;
-       (* keep *) char_t ch = int8;
-
-
-       always @* assert(int2 == 2'b10);
-       always @* assert(int4 == 4'b1111);
-       always @* assert(int8 == 8'b11111111);
-       always @* assert(ch   == 8'b11111111);
-
-endmodule
\ No newline at end of file
diff --git a/tests/svtypes/typedef_param.sv b/tests/svtypes/typedef_param.sv
new file mode 100644 (file)
index 0000000..13a522f
--- /dev/null
@@ -0,0 +1,22 @@
+`define STRINGIFY(x) `"x`"
+`define STATIC_ASSERT(x) if(!(x)) $error({"assert failed: ", `STRINGIFY(x)})
+
+module top;
+
+       typedef logic [1:0] uint2_t;
+       typedef logic signed [3:0] int4_t;
+       typedef logic signed [7:0] int8_t;
+       typedef int8_t char_t;
+
+       parameter uint2_t int2 = 2'b10;
+       localparam int4_t int4 = -1;
+       localparam int8_t int8 = int4;
+       localparam char_t ch = int8;
+
+
+       `STATIC_ASSERT(int2 == 2'b10);
+       `STATIC_ASSERT(int4 == 4'b1111);
+       `STATIC_ASSERT(int8 == 8'b11111111);
+       `STATIC_ASSERT(ch   == 8'b11111111);
+
+endmodule
\ No newline at end of file
diff --git a/tests/svtypes/typedef_simple.sv b/tests/svtypes/typedef_simple.sv
new file mode 100644 (file)
index 0000000..0cf2c07
--- /dev/null
@@ -0,0 +1,19 @@
+module top;
+
+       typedef logic [1:0] uint2_t;
+       typedef logic signed [3:0] int4_t;
+       typedef logic signed [7:0] int8_t;
+       typedef int8_t char_t;
+
+       (* keep *) uint2_t int2 = 2'b10;
+       (* keep *) int4_t int4 = -1;
+       (* keep *) int8_t int8 = int4;
+       (* keep *) char_t ch = int8;
+
+
+       always @* assert(int2 == 2'b10);
+       always @* assert(int4 == 4'b1111);
+       always @* assert(int8 == 8'b11111111);
+       always @* assert(ch   == 8'b11111111);
+
+endmodule
\ No newline at end of file