verlog: allow shadowing module ports within generate blocks
authorZachary Snow <zach@zachjs.com>
Sun, 7 Feb 2021 04:54:17 +0000 (23:54 -0500)
committerZachary Snow <zach@zachjs.com>
Sun, 7 Feb 2021 16:48:39 +0000 (11:48 -0500)
This is a somewhat obscure edge case I encountered while working on test
cases for earlier changes. Declarations in generate blocks should not be
checked against the list of ports. This change also adds a check
forbidding declarations within generate blocks being tagged as inputs or
outputs.

frontends/verilog/verilog_parser.y
tests/simple/genblk_port_shadow.v [new file with mode: 0644]
tests/verilog/genblk_port_decl.ys [new file with mode: 0644]

index fb5846f7b58eb84d117096ea19acae015b8bc7db..0aae253533adcffbd2ef20ccf4941b8b8103b9e9 100644 (file)
@@ -1784,7 +1784,13 @@ wire_name:
                        }
                        rewriteAsMemoryNode(node, $2);
                }
-               if (current_function_or_task == NULL) {
+               if (current_function_or_task) {
+                       if (node->is_input || node->is_output)
+                               node->port_id = current_function_or_task_port_id++;
+               } else if (ast_stack.back()->type == AST_GENBLOCK) {
+                       if (node->is_input || node->is_output)
+                               frontend_verilog_yyerror("Cannot declare module port `%s' within a generate block.", $1->c_str());
+               } else {
                        if (do_not_require_port_stubs && (node->is_input || node->is_output) && port_stubs.count(*$1) == 0) {
                                port_stubs[*$1] = ++port_counter;
                        }
@@ -1799,9 +1805,6 @@ wire_name:
                                if (node->is_input || node->is_output)
                                        frontend_verilog_yyerror("Module port `%s' is not declared in module header.", $1->c_str());
                        }
-               } else {
-                       if (node->is_input || node->is_output)
-                               node->port_id = current_function_or_task_port_id++;
                }
                //FIXME: for some reason, TOK_ID has a location which always points to one column *after* the real last column...
                SET_AST_NODE_LOC(node, @1, @1);
diff --git a/tests/simple/genblk_port_shadow.v b/tests/simple/genblk_port_shadow.v
new file mode 100644 (file)
index 0000000..a04631a
--- /dev/null
@@ -0,0 +1,10 @@
+module top(x);
+       generate
+               if (1) begin : blk
+                       wire x;
+                       assign x = 0;
+               end
+       endgenerate
+       output wire x;
+       assign x = blk.x;
+endmodule
diff --git a/tests/verilog/genblk_port_decl.ys b/tests/verilog/genblk_port_decl.ys
new file mode 100644 (file)
index 0000000..589d3d2
--- /dev/null
@@ -0,0 +1,12 @@
+logger -expect error "Cannot declare module port `\\x' within a generate block\." 1
+read_verilog <<EOT
+module top(x);
+    generate
+        if (1) begin : blk
+            output wire x;
+            assign x = 1;
+        end
+    endgenerate
+    output wire x;
+endmodule
+EOT