Support unpacked struct in localparam (#6053 partial) (#6708)

This commit is contained in:
Jonathan Drolet 2025-11-27 14:17:18 -05:00 committed by GitHub
parent 2c5ff3f63f
commit f2e05bc0b7
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 109 additions and 0 deletions

View File

@ -2931,6 +2931,31 @@ class ConstVisitor final : public VNVisitor {
replaceWithSimulation(nodep);
}
void visit(AstStructSel* nodep) override {
iterateChildren(nodep);
if (VN_IS(nodep->fromp(), ConsPackUOrStruct)) {
const AstConsPackUOrStruct* const consp = VN_AS(nodep->fromp(), ConsPackUOrStruct);
for (AstConsPackMember* memberp = consp->membersp(); memberp;
memberp = VN_AS(memberp->nextp(), ConsPackMember)) {
if (memberp->dtypep() && memberp->dtypep()->name() == nodep->name()) {
AstNode* const valuep = memberp->rhsp();
if (VN_IS(valuep, Const)) {
const V3Number& num = VN_AS(valuep, Const)->num();
VL_DO_DANGLING(replaceNum(nodep, num), nodep);
} else {
AstNode* const newp = valuep->cloneTree(false);
nodep->replaceWith(newp);
VL_DO_DANGLING(pushDeletep(nodep), nodep);
}
break;
}
}
}
}
void visit(AstCAwait* nodep) override {
m_hasJumpDelay = true;
iterateChildren(nodep);
@ -2976,6 +3001,11 @@ class ConstVisitor final : public VNVisitor {
nodep->replaceWithKeepDType(newp);
VL_DO_DANGLING(pushDeletep(nodep), nodep);
did = true;
} else if (m_params && VN_IS(valuep, ConsPackUOrStruct)) {
AstNode* const newp = valuep->cloneTree(false);
nodep->replaceWithKeepDType(newp);
VL_DO_DANGLING(pushDeletep(nodep), nodep);
did = true;
} else if (nodep->varp()->isParam() && VN_IS(valuep, Unbounded)) {
AstNode* const newp = valuep->cloneTree(false);
nodep->replaceWithKeepDType(newp);
@ -3654,6 +3684,8 @@ class ConstVisitor final : public VNVisitor {
}
void visit(AstInitArray* nodep) override { iterateChildren(nodep); }
void visit(AstConsPackUOrStruct* nodep) override { iterateChildren(nodep); }
void visit(AstConsPackMember* nodep) override { iterateChildren(nodep); }
void visit(AstInitItem* nodep) override { iterateChildren(nodep); }
void visit(AstUnbounded* nodep) override { iterateChildren(nodep); }
// These are converted by V3Param. Don't constify as we don't want the

View File

@ -0,0 +1,18 @@
#!/usr/bin/env python3
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# Copyright 2025 by Wilson Snyder. 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-License-Identifier: LGPL-3.0-only OR Artistic-2.0
import vltest_bootstrap
test.scenarios("simulator")
test.compile()
test.execute()
test.passes()

View File

@ -0,0 +1,59 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed into the Public Domain, for any use,
// without warranty, 2025 by Jonathan Drolet.
// SPDX-License-Identifier: CC0-1.0
// verilog_format: off
`define stop $stop
`define checkd(gotv, expv) do if ((gotv) !== (expv)) begin $write("%%Error: %s:%0d: got=%0d exp=%0d\n", `__FILE__,`__LINE__, (gotv), (expv)); `stop; end while(0);
// verilog_format: on
module t;
typedef struct {
int a;
int b;
int c;
} subsubstruct_t;
typedef struct {
int a;
int b;
subsubstruct_t subsub;
int c;
} substruct_t;
typedef substruct_t substruct_t_t;
typedef struct {
int a;
int b;
substruct_t_t sub;
int c;
} struct_t;
// Constant value unpacked struct support is limited at the moment.
// Only localparams are supported, returning constant unpacked structure
// from function or passing unpacked structure as parameters is not
// (yet) supported
localparam struct_t MY_STRUCT = '{a: 10, b: 5, c: 20, sub: '{a: 100, b: 200, c: 150, subsub: '{default: 10}}};
// Make standalone localparam to ensure MY_STRUCT is const
localparam int C = MY_STRUCT.c;
localparam int S_A = MY_STRUCT.sub.a;
localparam int SS_B = MY_STRUCT.sub.subsub.b;
initial begin
`checkd(MY_STRUCT.a, 10);
`checkd(MY_STRUCT.b, 5);
`checkd(MY_STRUCT.c, 20);
`checkd(MY_STRUCT.sub.c, 150);
`checkd(C, 20);
`checkd(S_A, 100);
`checkd(SS_B, 10);
$write("*-* All Finished *-*\n");
$finish;
end
endmodule