verilator icon indicating copy to clipboard operation
verilator copied to clipboard

Fix compile error on bitstream with inline typecast

Open kaddkaka opened this issue 2 months ago • 6 comments

module foo;
   initial begin
      automatic reg [2:0] foo0 [1:0] = '{0, 0};
      $display("foo0 %p -> %b", foo0, |type(logic [$bits(foo0)-1:0])'({>>{foo0}}));
      $finish();
   end
endmodule

Saving above code into foo.sv running verilator --lint-only foo.sv --debug causes this error output:

export VERILATOR_ROOT='/usr/local/share/verilator'
Starting Verilator 5.040 2025-08-30 rev v5.040
- Verilator.cpp:657:  Option --verilate: Start Verilation

[...]

- V3Dead.cpp:567:     deadifyDTypes:
- V3Ast.cpp:1378:     Dumping obj_dir/Vverilator_bug_macro_or_reduce_033_deadDtypes.tree
%Error: Internal Error: foo.sv:4:72: ../V3Broken.cpp:173: Broken link in node->dtypep() to 0x55555702dd40
-node: STREAMR 0x5555570274a0 <e1134> {e4cu} @dt=0x55555702dd40@(G/w6)
    4 |       $display("foo0 %p -> %b", foo0, |type(logic [$bits(foo0)-1:0])'({>>{foo0}}));
      |                                                                        ^~
                        ... See the manual at https://verilator.org/verilator_doc.html?v=5.040 for more assistance.
- V3Ast.cpp:1378:     Dumping obj_dir/Vverilator_bug_macro_or_reduce_990_final.tree
- V3StatsReport.cpp:233:statsReport:
%Error: Internal Error: Aborting since under --debug
%Error: export VERILATOR_ROOT=/usr/local/share/verilator
%Error: ulimit -s unlimited 2>/dev/null; exec setarch --addr-no-randomize /usr/local/bin/verilator_bin_dbg --lint-only foo.sv --debug
%Error: Command Failed ulimit -s unlimited 2>/dev/null; exec setarch --addr-no-randomize /usr/local/bin/verilator_bin_dbg --lint-only foo.sv --debug

Tested on Ubuntu and verilator v5.040. (It passes on v5.012)

In contrast, linting this code with --debug is no problem:

module foo;
   wire [5:0] bar;

   initial begin
      automatic reg [2:0] foo0 [1:0] = '{0, 0};
      $display("foo0 %p -> %b", foo0, |type(bar)'({>>{foo0}}));
      $finish();
   end
endmodule

kaddkaka avatar Oct 20 '25 19:10 kaddkaka

I noticed this when similar code crashed with

%Error: Verilator internal fault, sorry. Suggest trying --debug --gdbbt
%Error: Command Failed ulimit -s unlimited 2>/dev/null; exec /usr/local/bin/verilator_bin --lint-only /home/david/tmp/verilator_bug_macro_or_reduce.sv

or when trying to add --debug to try and figure out why the below code example, which usually takes 0.005 s to lint, sometimes takes up to 24 seconds(!) to lint. (something like every ~4th time)

module foo;
   initial begin
      automatic reg [2:0] foo0 [1:0] = '{0, 0};
      automatic reg [2:0] foo1 [1:0] = '{0, 1};
      automatic reg [2:0] foo2 [1:0] = '{0, 2};
      automatic reg [2:0] foo3 [1:0] = '{0, 3};
      automatic reg [2:0] foo4 [1:0] = '{1, 0};
      automatic reg [2:0] foo5 [1:0] = '{2, 0};
      automatic reg [2:0] foo6 [1:0] = '{3, 0};

      $display("foo0 %p -> %b", foo0, |type(logic [$bits(foo0)-1:0])'({>>{foo0}}));
      $display("foo1 %p -> %b", foo1, |type(logic [$bits(foo1)-1:0])'({>>{foo1}}));
      $display("foo2 %p -> %b", foo2, |type(logic [$bits(foo2)-1:0])'({>>{foo2}}));
      $display("foo3 %p -> %b", foo3, |type(logic [$bits(foo3)-1:0])'({>>{foo3}}));
      $display("foo4 %p -> %b", foo4, |type(logic [$bits(foo4)-1:0])'({>>{foo4}}));
      $display("foo5 %p -> %b", foo5, |type(logic [$bits(foo5)-1:0])'({>>{foo5}}));
      $display("foo6 %p -> %b", foo6, |type(logic [$bits(foo6)-1:0])'({>>{foo6}}));
      $finish();
   end

   `define OR_REDUCE(s) |type(logic [$bits(s)-1:0])'({>>{s}})

   let or_reduce_let(s) = |type(logic [$bits(s)-1:0])'({>>{s}});

   initial begin
      automatic reg [2:0] bar0 [1:0] = '{0, 0};
      automatic reg [2:0] bar1 [1:0] = '{0, 1};
      automatic reg [2:0] bar2 [1:0] = '{0, 2};
      automatic reg [2:0] bar3 [1:0] = '{0, 3};
      automatic reg [2:0] bar4 [1:0] = '{1, 0};
      automatic reg [2:0] bar5 [1:0] = '{2, 0};
      automatic reg [2:0] bar6 [1:0] = '{3, 0};

      $display("bar0 %p -> %b", bar0, `OR_REDUCE(bar0));
      $display("bar1 %p -> %b", bar1, or_reduce_let(bar1));
      $display("bar2 %p -> %b", bar2, `OR_REDUCE(bar2));
      $display("bar3 %p -> %b", bar3, `OR_REDUCE(bar3));
      $display("bar4 %p -> %b", bar4, `OR_REDUCE(bar4));
      $display("bar5 %p -> %b", bar5, `OR_REDUCE(bar5));
      $display("bar6 %p -> %b", bar6, `OR_REDUCE(bar6));
      $finish();
   end
endmodule

kaddkaka avatar Oct 20 '25 19:10 kaddkaka

If the time is random then sounds there's at least two bugs here:

  1. The functional problem of the bitstream

  2. Why the behavior is non-determistic. We shouldn't depend in any performance or output way on address layout in any algorithms but seems from this we are. Comment out aslr_off in bin/verilator, then use --debug to make a obj_dir of both the slow and fast version. Hopefully you will then see a difference in the tree files (you can use verilator_difftree) that suggests the problem, if not gdb through to see where the time is.

Could you continue to debug into this and see if you can identify the problems?

wsnyder avatar Oct 20 '25 23:10 wsnyder

If you update to master you can now use --aslr --debug to force use of ASLR even when under debug.

wsnyder avatar Oct 20 '25 23:10 wsnyder

Interesting enough adding an unused wire to the first crashing example avoids the crash iff the range of that wire is exactly [5:0]:

module foo;
   wire [5:0] x;
   initial begin
      automatic reg [2:0] foo0 [1:0] = '{0, 0};
      $display("foo0 %p -> %b", foo0, |type(logic [$bits(foo0)-1:0])'({>>{foo0}}));
      $finish();
   end
endmodule

kaddkaka avatar Oct 22 '25 21:10 kaddkaka

When trying to lint the long example on my personal laptop I got this on 5.040:

$ verilator --lint-only bar.sv
%Error: Verilator threw signal 9. Suggest trying --debug --gdbbt
%Error: Command Failed ulimit -s unlimited 2>/dev/null; exec /usr/local/bin/verilator_bin --lint-only bar.sv

and on master (5.041) I get the "internal fault" no matter if I run with --aslr or not

kaddkaka avatar Oct 22 '25 21:10 kaddkaka

The crash is fixed, however the specific streaming fails now at GCC compile time due to other issues, see test_regress/t/t_stream_type.py. Perhaps you'd be willing to look at a pull to fix this?

wsnyder avatar Oct 25 '25 00:10 wsnyder