sv: Add support for memories of a typedef
authorDavid Shah <dave@ds0.me>
Fri, 20 Sep 2019 10:46:37 +0000 (11:46 +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
tests/svtypes/typedef_memory_2.sv [new file with mode: 0644]

index a6ac0403770e525534133f52e63bd5d98157505a..aaf1188b422d8a1009df6cb4e2d51fd7ea92e201 100644 (file)
@@ -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);
diff --git a/tests/svtypes/typedef_memory_2.sv b/tests/svtypes/typedef_memory_2.sv
new file mode 100644 (file)
index 0000000..1e8abb1
--- /dev/null
@@ -0,0 +1,10 @@
+module top(input [3:0] addr, wdata, input clk, wen, output reg [3:0] rdata);
+       typedef logic [3:0] nibble;
+
+       nibble mem[0:15];
+
+       always @(posedge clk) begin
+               if (wen) mem[addr] <= wdata;
+               rdata <= mem[addr];
+       end
+endmodule
\ No newline at end of file