From fdb19a5b3a10572b1b84a26306ec5e83a4eff613 Mon Sep 17 00:00:00 2001 From: Kamil Rakoczy Date: Tue, 16 Nov 2021 10:59:54 +0100 Subject: [PATCH] Support parameters using struct as a wiretype (#3050) Signed-off-by: Kamil Rakoczy --- frontends/ast/simplify.cc | 30 ++++++++++++++++----- tests/various/param_struct.ys | 51 +++++++++++++++++++++++++++++++++++ 2 files changed, 74 insertions(+), 7 deletions(-) create mode 100644 tests/various/param_struct.ys diff --git a/frontends/ast/simplify.cc b/frontends/ast/simplify.cc index 64d0fe475..777f46bd7 100644 --- a/frontends/ast/simplify.cc +++ b/frontends/ast/simplify.cc @@ -1613,6 +1613,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, if (template_node->type == AST_STRUCT || template_node->type == AST_UNION) { // replace with wire representing the packed structure newNode = make_packed_struct(template_node, str); + newNode->attributes[ID::wiretype] = mkconst_str(resolved_type_node->str); // add original input/output attribute to resolved wire newNode->is_input = this->is_input; newNode->is_output = this->is_output; @@ -1661,18 +1662,33 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, 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, location.first_line, "Unknown identifier `%s' used as type name\n", children[1]->str.c_str()); - AstNode *resolved_type_node = current_scope.at(children[1]->str); + auto type_name = children[1]->str; + if (!current_scope.count(type_name)) { + log_file_error(filename, location.first_line, "Unknown identifier `%s' used as type name\n", type_name.c_str()); + } + AstNode *resolved_type_node = current_scope.at(type_name); if (resolved_type_node->type != AST_TYPEDEF) - log_file_error(filename, location.first_line, "`%s' does not name a type\n", children[1]->str.c_str()); + log_file_error(filename, location.first_line, "`%s' does not name a type\n", type_name.c_str()); log_assert(resolved_type_node->children.size() == 1); AstNode *template_node = resolved_type_node->children[0]; - delete children[1]; - children.pop_back(); // Ensure typedef itself is fully simplified - while(template_node->simplify(const_fold, at_zero, in_lvalue, stage, width_hint, sign_hint, in_param)) {}; + while (template_node->simplify(const_fold, at_zero, in_lvalue, stage, width_hint, sign_hint, in_param)) {}; + + if (template_node->type == AST_STRUCT || template_node->type == AST_UNION) { + // replace with wire representing the packed structure + newNode = make_packed_struct(template_node, str); + newNode->attributes[ID::wiretype] = mkconst_str(resolved_type_node->str); + newNode->type = type; + current_scope[str] = this; + // copy param value, it needs to be 1st value + delete children[1]; + children.pop_back(); + newNode->children.insert(newNode->children.begin(), children[0]->clone()); + goto apply_newNode; + } + delete children[1]; + children.pop_back(); if (template_node->type == AST_MEMORY) log_file_error(filename, location.first_line, "unpacked array type `%s' cannot be used for a parameter\n", children[1]->str.c_str()); diff --git a/tests/various/param_struct.ys b/tests/various/param_struct.ys new file mode 100644 index 000000000..6d7a7c6ad --- /dev/null +++ b/tests/various/param_struct.ys @@ -0,0 +1,51 @@ +read_verilog -sv << EOF +package p; +typedef struct packed { + logic a; + logic b; +} struct_t; + +typedef struct packed { + struct_t g; + logic [2:0] h; +} nested_struct_t; + +typedef union packed { + logic [4:0] x; +} nested_union_t; + +parameter struct_t c = {1'b1, 1'b0}; +parameter nested_struct_t x = {{1'b1, 1'b0}, 1'b1, 1'b1, 1'b1}; +endpackage + +module dut (); +parameter p::struct_t d = p::c; +parameter p::nested_struct_t i = p::x; + +parameter p::nested_union_t u = {5'b11001}; + +localparam e = d.a; +localparam f = d.b; + +localparam j = i.g.a; +localparam k = i.g.b; +localparam l = i.h; +localparam m = i.g; + +localparam o = u.x; + +always_comb begin + assert(d == 2'b10); + assert(e == 1'b1); + assert(f == 1'b0); + assert(j == 1'b1); + assert(k == 1'b0); + assert(l == 3'b111); +// TODO: support access to whole sub-structs and unions +// assert(m == 2'b10); + assert(u == 5'b11001); +end +endmodule +EOF +hierarchy; proc; opt +sat -verify -seq 1 -tempinduct -prove-asserts -show-all -- 2.30.2