fix struct member accesses within field select bounds (#330)

This commit is contained in:
Ethan Sifferman 2026-08-17 21:05:12 -07:00 committed by GitHub
parent 1a89e8b986
commit 493a88f930
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 58 additions and 3 deletions

View File

@ -6,6 +6,11 @@
* Added support for `bufif0`, `bufif1`, `notif0`, `notif1`, `cmos`, `rcmos`,
`nmos`, `pmos`, `rnmos`, and `rpmos`.
### Bug Fixes
* Fixed conversion of struct field accesses when the struct's field widths
depend on a member of a struct-typed parameter
### Other Enhancements
* `always_comb` blocks with sensitivities inherited from called functions or

View File

@ -385,10 +385,12 @@ convertSubExpr scopes (Dot e x) =
where
(subExprType, e') = convertSubExpr scopes e
(isHier, fieldType, bounds, dims) = lookupFieldInfo scopes subExprType e' x
base = fst bounds
len = rangeSize bounds
-- the offset and size are derived from the struct layout, whose field
-- widths may contain member accesses that must themselves be lowered
(_, base) = convertSubExpr scopes $ fst bounds
(_, len) = convertSubExpr scopes $ rangeSize bounds
undotted = if null dims || rangeSize (head dims) == RawNum 1
then Bit e' (fst bounds)
then Bit e' base
else Range e' IndexedMinus (base, len)
-- retain signedness of fields which would otherwise be lost via the
-- resulting bit or range selection

View File

@ -0,0 +1,26 @@
package P;
typedef struct packed { int unsigned a; int unsigned b; } cfg_t;
localparam cfg_t cfg = '{a: 8, b: 4};
typedef enum logic [1:0] { S_A, S_B } enum_e;
endpackage
class C #(parameter P::cfg_t cfg = P::cfg);
typedef logic [$clog2(cfg.a) - 1:0] x_t;
typedef logic [cfg.b - 1:0] y_t;
typedef struct packed { P::enum_e e; x_t x; y_t y; } s_t;
endclass
module child #(
parameter P::cfg_t cfg = P::cfg,
parameter type s_t = C#(cfg)::s_t,
localparam type x_t = C#(cfg)::x_t
) (
input s_t ins,
output x_t out
);
always_comb
unique case (ins.e)
P::S_A: out = ins.x;
default: out = '0;
endcase
endmodule

View File

@ -0,0 +1,11 @@
module child(
input wire [8:0] inp,
output reg [2:0] out
);
always @* begin
case (inp[8:7])
2'd0: out = inp[6:4];
default: out = 3'd0;
endcase
end
endmodule

View File

@ -0,0 +1,11 @@
module top;
reg [8:0] inp;
wire [2:0] out;
child c(inp, out);
initial begin
$monitor("%2d %b %b", $time, inp, out);
inp = 9'b00_101_0000; #1;
inp = 9'b00_010_1111; #1;
inp = 9'b01_111_0000; #1;
end
endmodule