sv: support tasks and functions within packages
authorZachary Snow <zach@zachjs.com>
Thu, 27 May 2021 20:47:02 +0000 (16:47 -0400)
committerZachary Snow <zachary.j.snow@gmail.com>
Tue, 1 Jun 2021 17:17:41 +0000 (13:17 -0400)
frontends/ast/ast.cc
frontends/ast/simplify.cc
frontends/verilog/verilog_parser.y
tests/verilog/package_task_func.sv [new file with mode: 0644]
tests/verilog/package_task_func.ys [new file with mode: 0644]

index 7e5cc94110464bb1851223e4fcc799f2937f0ea9..7e53713e3e52c0f95ab841d0168fc6713697b9fe 100644 (file)
@@ -1196,6 +1196,25 @@ static void process_module(RTLIL::Design *design, AstNode *ast, bool defer, AstN
        design->add(current_module);
 }
 
+// renames identifiers in tasks and functions within a package
+static void rename_in_package_stmts(AstNode *pkg)
+{
+       std::unordered_set<std::string> idents;
+       for (AstNode *item : pkg->children)
+               idents.insert(item->str);
+       std::function<void(AstNode*)> rename =
+               [&rename, &idents, pkg](AstNode *node) {
+                       for (AstNode *child : node->children) {
+                               if (idents.count(child->str))
+                                       child->str = pkg->str + "::" + child->str.substr(1);
+                               rename(child);
+                       }
+       };
+       for (AstNode *item : pkg->children)
+               if (item->type == AST_FUNCTION || item->type == AST_TASK)
+                       rename(item);
+}
+
 // create AstModule instances for all modules in the AST tree and add them to 'design'
 void AST::process(RTLIL::Design *design, AstNode *ast, bool dump_ast1, bool dump_ast2, bool no_dump_ptr, bool dump_vlog1, bool dump_vlog2, bool dump_rtlil,
                bool nolatches, bool nomeminit, bool nomem2reg, bool mem2reg, bool noblackbox, bool lib, bool nowb, bool noopt, bool icells, bool pwires, bool nooverwrite, bool overwrite, bool defer, bool autowire)
@@ -1284,6 +1303,7 @@ void AST::process(RTLIL::Design *design, AstNode *ast, bool dump_ast1, bool dump
                else if (child->type == AST_PACKAGE) {
                        // process enum/other declarations
                        child->simplify(true, false, false, 1, -1, false, false);
+                       rename_in_package_stmts(child);
                        design->verilog_packages.push_back(child->clone());
                        current_scope.clear();
                }
index 305f67da82d01e0fa8e13e2207df8344cc274fe9..517647afbf0e808b7836b2d6bd6d135ed106ed45 100644 (file)
@@ -875,7 +875,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
                for (size_t i = 0; i < children.size(); i++) {
                        AstNode *node = children[i];
                        // these nodes appear at the top level in a package and can define names
-                       if (node->type == AST_PARAMETER || node->type == AST_LOCALPARAM || node->type == AST_TYPEDEF) {
+                       if (node->type == AST_PARAMETER || node->type == AST_LOCALPARAM || node->type == AST_TYPEDEF || node->type == AST_FUNCTION || node->type == AST_TASK) {
                                current_scope[node->str] = node;
                        }
                        if (node->type == AST_ENUM) {
index c2b43f45b9e75db44a9c670422c61a24b38ff402..93ddbec9187a25ce069f03e377eb983d52047b1c 100644 (file)
@@ -593,7 +593,7 @@ package_body:
        package_body package_body_stmt | %empty;
 
 package_body_stmt:
-       typedef_decl | localparam_decl | param_decl;
+       typedef_decl | localparam_decl | param_decl | task_func_decl;
 
 interface:
        TOK_INTERFACE {
diff --git a/tests/verilog/package_task_func.sv b/tests/verilog/package_task_func.sv
new file mode 100644 (file)
index 0000000..2df7a52
--- /dev/null
@@ -0,0 +1,30 @@
+package P;
+    localparam Y = 2;
+    localparam X = Y + 1;
+    task t;
+        output integer x;
+        x = Y;
+    endtask
+    function automatic integer f;
+        input integer i;
+        f = i * X;
+    endfunction
+    function automatic integer g;
+        input integer i;
+        g = i == 0 ? 1 : Y * g(i - 1);
+    endfunction
+    localparam Z = g(4);
+endpackage
+
+module top;
+    integer a;
+    initial P::t(a);
+    integer b = P::f(3);
+    integer c = P::g(3);
+    integer d = P::Z;
+
+    assert property (a == 2);
+    assert property (b == 9);
+    assert property (c == 8);
+    assert property (d == 16);
+endmodule
diff --git a/tests/verilog/package_task_func.ys b/tests/verilog/package_task_func.ys
new file mode 100644 (file)
index 0000000..c94cc2a
--- /dev/null
@@ -0,0 +1,4 @@
+read_verilog -sv package_task_func.sv
+proc
+opt -full
+sat -verify -seq 1 -prove-asserts -show-all