-
Notifications
You must be signed in to change notification settings - Fork 685
Description
Consider the following code test.v
, which contains a signal with an extremely large bit-width (exceeding the range representable by a 32-bit int
):
`timescale 1ns/1ps
module top (out0);
output wire [32'hFFFF_FFFF:1] out0;
assign out0 = 1;
initial begin
#10;
$display("out0: %b", out0);
$finish;
end
endmodule
When running the following commands:
verilator --binary -Wno-lint --timing test.v
./obj_dir/Vtest
The code compiles successfully (the excessively large bit-width seems to bypass Verilator’s width checks, such as Width of bit range is huge; vector of over 1 billion bits:
or Value too wide for 32-bits expected in this context 36'haffffffff
), and treats out0
as a 3-bit signal. The output is:
out0: 001
So it appears that somewhere in the code, a conversion from uint32_t
to int
occurs, which causes 32'hffff_ffff
to be interpreted as -1
.
I further looked into the source code and found the following problematic line:
Line 949 in f74c67d
const int width = nodep->elementsConst(); |
Here, the width
value should ideally be of type uint32_t
.
After further investigation, it turns out that the cause is the following functions, which return int
instead:
verilator/src/V3AstNodeOther.h
Lines 2698 to 2710 in f74c67d
inline int leftConst() const VL_MT_STABLE; | |
inline int rightConst() const VL_MT_STABLE; | |
int hiConst() const VL_MT_STABLE { | |
const int l = leftConst(); | |
const int r = rightConst(); | |
return l > r ? l : r; | |
} | |
int loConst() const VL_MT_STABLE { | |
const int l = leftConst(); | |
const int r = rightConst(); | |
return l > r ? r : l; | |
} | |
int elementsConst() const VL_MT_STABLE { return hiConst() - loConst() + 1; } |
A straightforward fix would be to change the return type of these functions to uint32_t
. However, I’m not sure how extensive the impact would be on the rest of the codebase. If it's safe and has no side effects, I’d be happy to submit a PR to fix this.