add struct field test
This commit is contained in:
parent
6de7966115
commit
bb2ea625cf
|
|
@ -0,0 +1,18 @@
|
|||
#!/usr/bin/env python3
|
||||
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify it
|
||||
# under the terms of either the GNU Lesser General Public License Version 3
|
||||
# or the Perl Artistic License Version 2.0.
|
||||
# SPDX-FileCopyrightText: 2026 Wilson Snyder
|
||||
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
||||
|
||||
import vltest_bootstrap
|
||||
|
||||
test.scenarios('simulator')
|
||||
|
||||
test.compile(verilator_flags2=['--binary'])
|
||||
|
||||
test.execute()
|
||||
|
||||
test.passes()
|
||||
|
|
@ -0,0 +1,65 @@
|
|||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// Struct localparam field access via a class-scope Dot used in a cell
|
||||
// parameter pin (e.g. `CFG::cfg.jt.cam_type`), where CFG is a typedef
|
||||
// alias of a parameterized class. V3LinkDot defers the `CFG::cfg` Dot
|
||||
// until post-V3Param; when the cell is deparameterized, resolveDotToTypedef
|
||||
// folds the class localparam to a Const and must then walk up the outer
|
||||
// `.field[.field...]` Dot chain, accumulating the packed-struct bit offset,
|
||||
// and replace the topmost Dot with a Sel(const, lsb, width) matching
|
||||
// V3Width::memberSelStruct. Without this, the struct-field select on the
|
||||
// deferred class localparam cannot be constified for the cell pin.
|
||||
//
|
||||
// This file ONLY is placed under the Creative Commons Public Domain.
|
||||
// SPDX-FileCopyrightText: 2026 Wilson Snyder
|
||||
// SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
// verilog_format: off
|
||||
`define stop $stop
|
||||
`define checkh(gotv,expv) do if ((gotv) !== (expv)) begin $write("%%Error: %s:%0d: got='h%x exp='h%x\n", `__FILE__,`__LINE__, (gotv), (expv)); `stop; end while(0)
|
||||
// verilog_format: on
|
||||
|
||||
typedef struct packed {
|
||||
logic [7:0] cam_type;
|
||||
logic [7:0] depth;
|
||||
} inner_t;
|
||||
|
||||
typedef struct packed {
|
||||
inner_t jt;
|
||||
logic [7:0] tag;
|
||||
} cfg_t;
|
||||
|
||||
class C #(parameter int W = 1);
|
||||
// Struct localparam whose fields derive from the class parameter.
|
||||
localparam cfg_t cfg = '{jt: '{cam_type: W[7:0], depth: W[7:0] + 8'd1},
|
||||
tag: W[7:0] + 8'd2};
|
||||
endclass
|
||||
|
||||
module Sub #(parameter int WIDTH = 0) ();
|
||||
endmodule
|
||||
|
||||
// Parameterized wrapper so the class specialization is deferred until
|
||||
// V3Param processes the cell instance.
|
||||
module Mid #(parameter int W = 8) ();
|
||||
typedef C#(W) CFG;
|
||||
// (1) single-level struct field access -> one loop iteration
|
||||
Sub #(int'(CFG::cfg.tag)) u_tag ();
|
||||
// (2) nested struct field access -> two loop iterations, lsb accumulation
|
||||
Sub #(int'(CFG::cfg.jt.cam_type)) u_cam ();
|
||||
Sub #(int'(CFG::cfg.jt.depth)) u_depth ();
|
||||
endmodule
|
||||
|
||||
module t;
|
||||
Mid #(.W(8)) u ();
|
||||
|
||||
initial begin
|
||||
// cfg.tag = W + 2 = 10 (offset above the 16-bit jt struct)
|
||||
`checkh(u.u_tag.WIDTH, 32'd10);
|
||||
// cfg.jt.cam_type = W = 8 (nested, lsb 0)
|
||||
`checkh(u.u_cam.WIDTH, 32'd8);
|
||||
// cfg.jt.depth = W + 1 = 9 (nested, lsb 8)
|
||||
`checkh(u.u_depth.WIDTH, 32'd9);
|
||||
$write("*-* All Finished *-*\n");
|
||||
$finish;
|
||||
end
|
||||
endmodule
|
||||
Loading…
Reference in New Issue