Improved scope resolution of local regs in Verilog+AST frontend
authorClifford Wolf <clifford@clifford.at>
Tue, 5 Aug 2014 10:15:53 +0000 (12:15 +0200)
committerClifford Wolf <clifford@clifford.at>
Tue, 5 Aug 2014 10:15:53 +0000 (12:15 +0200)
frontends/ast/ast.h
frontends/ast/simplify.cc
frontends/verilog/parser.y
tests/simple/scopes.v [new file with mode: 0644]

index 83798edf0831f85eca8e7eb722d467bc6786c195..00b044bc4fbe574d16792317e9857617c2953f74 100644 (file)
@@ -200,7 +200,7 @@ namespace AST
                // it also sets the id2ast pointers so that identifier lookups are fast in genRTLIL()
                bool simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, int width_hint, bool sign_hint, bool in_param);
                void expand_genblock(std::string index_var, std::string prefix, std::map<std::string, std::string> &name_map);
-               void replace_ids(std::map<std::string, std::string> &rules);
+               void replace_ids(const std::string &prefix, const std::map<std::string, std::string> &rules);
                void mem2reg_as_needed_pass1(std::map<AstNode*, std::set<std::string>> &mem2reg_places,
                                std::map<AstNode*, uint32_t> &mem2reg_flags, std::map<AstNode*, uint32_t> &proc_flags, uint32_t &status_flags);
                void mem2reg_as_needed_pass2(std::set<AstNode*> &mem2reg_set, AstNode *mod, AstNode *block);
index 20edc1739bcae5499e37451820b7621d6b2ffdb9..29d00be96e9c8c7e73661a80a069096e798bd5d2 100644 (file)
@@ -794,6 +794,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
                        if (children[i]->type == AST_WIRE) {
                                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];
                        } else
                                new_children.push_back(children[i]);
 
@@ -1492,7 +1493,7 @@ skip_dynamic_range_lvalue_expansion:;
                        if (child->type != AST_WIRE)
                        {
                                AstNode *stmt = child->clone();
-                               stmt->replace_ids(replace_rules);
+                               stmt->replace_ids(prefix, replace_rules);
 
                                for (auto it = current_block->children.begin(); it != current_block->children.end(); it++) {
                                        if (*it != current_block_child)
@@ -1855,12 +1856,30 @@ void AstNode::expand_genblock(std::string index_var, std::string prefix, std::ma
 }
 
 // rename stuff (used when tasks of functions are instanciated)
-void AstNode::replace_ids(std::map<std::string, std::string> &rules)
+void AstNode::replace_ids(const std::string &prefix, const std::map<std::string, std::string> &rules)
 {
-       if (type == AST_IDENTIFIER && rules.count(str) > 0)
-               str = rules[str];
-       for (auto child : children)
-               child->replace_ids(rules);
+       if (type == AST_BLOCK)
+       {
+               std::map<std::string, std::string> new_rules = rules;
+               std::string new_prefix = prefix + str;
+
+               for (auto child : children)
+                       if (child->type == AST_WIRE) {
+                               new_rules[child->str] = new_prefix + child->str;
+                               child->str = new_prefix + child->str;
+                       }
+
+               for (auto child : children)
+                       if (child->type != AST_WIRE)
+                               child->replace_ids(new_prefix, new_rules);
+       }
+       else
+       {
+               if (type == AST_IDENTIFIER && rules.count(str) > 0)
+                       str = rules.at(str);
+               for (auto child : children)
+                       child->replace_ids(prefix, rules);
+       }
 }
 
 // helper function for mem2reg_as_needed_pass1
index 1e0168a5f2e06686a5841b2ea31aeedc15cda0e9..26e2ddc347919bbd3012b0604b9f95eb0a057d6e 100644 (file)
@@ -599,12 +599,11 @@ wire_name:
                                if (node->is_input || node->is_output)
                                        frontend_verilog_yyerror("Module port `%s' is not declared in module header.", $1->c_str());
                        }
-                       ast_stack.back()->children.push_back(node);
                } else {
                        if (node->is_input || node->is_output)
                                node->port_id = current_function_or_task_port_id++;
-                       current_function_or_task->children.push_back(node);
                }
+               ast_stack.back()->children.push_back(node);
                delete $1;
        };
 
diff --git a/tests/simple/scopes.v b/tests/simple/scopes.v
new file mode 100644 (file)
index 0000000..eecc1a0
--- /dev/null
@@ -0,0 +1,63 @@
+module scopes_test_01(input [3:0] k, output reg [15:0] x, y);
+       function [15:0] func_01;
+               input [15:0] x, y;
+               begin
+                       func_01 = x + y;
+                       begin:blk
+                               reg [15:0] x;
+                               x = y;
+                               func_01 = func_01 ^ x;
+                       end
+                       func_01 = func_01 ^ x;
+               end
+       endfunction
+
+       function [15:0] func_02;
+               input [15:0] x, y;
+               begin
+                       func_02 = x - y;
+                       begin:blk
+                               reg [15:0] func_02;
+                               func_02 = 0;
+                       end
+               end
+       endfunction
+
+       task task_01;
+               input [3:0] a;
+               reg [15:0] y;
+               begin
+                       y = a * 23;
+                       x = x + y;
+               end
+       endtask
+
+       task task_02;
+               input [3:0] a;
+               begin:foo
+                       reg [15:0] x, z;
+                       x = y;
+                       begin:bar
+                               reg [15:0] x;
+                               x = 77 + a;
+                               z = -x;
+                       end
+                       y = x ^ z;
+               end
+       endtask
+
+       always @* begin
+               x = func_01(11, 22);
+               y = func_02(33, 44);
+               task_01(k);
+               task_02(k);
+               begin:foo
+                       reg [15:0] y;
+                       y = x;
+                       y = y + k;
+                       x = y;
+               end
+               x = func_01(y, x);
+               y = func_02(y, x);
+       end
+endmodule