Fix direct NBA to dynamically-sized variable (#6310)

This commit is contained in:
Artur Bieniek 2025-08-22 12:21:13 +02:00 committed by GitHub
parent 457fcc267b
commit b19215770b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 63 additions and 15 deletions

View File

@ -43,6 +43,8 @@ class WidthCommitVisitor final : public VNVisitor {
// STATE
AstNodeModule* m_modp = nullptr;
std::string m_contNba; // In continuous- or non-blocking assignment
bool m_dynsizedelem
= false; // Writing a dynamically-sized array element, not the array itself
VMemberMap m_memberMap; // Member names cached for fast lookup
bool m_underSel = false; // Whether is currently under AstMemberSel or AstSel
@ -138,7 +140,7 @@ private:
else if (varp->isClassMember() && !varp->lifetime().isStatic()
&& !VN_IS(varDtp, IfaceRefDType))
varType = "Class non-static";
else if (varDtp->isDynamicallySized())
else if (varDtp->isDynamicallySized() && m_dynsizedelem)
varType = "Dynamically-sized";
if (!varType.empty()) {
UINFO(1, " Related var dtype: " << varDtp);
@ -395,6 +397,20 @@ private:
// This check could go anywhere after V3Param
nodep->v3fatalSrc("Presels should have been removed before this point");
}
void visit(AstCMethodHard* nodep) override {
VL_RESTORER(m_dynsizedelem);
if (nodep->name() == "atWrite" || nodep->name() == "atWriteAppend"
|| nodep->name() == "at")
m_dynsizedelem = true;
iterateChildren(nodep);
editDType(nodep);
}
void visit(AstAssocSel* nodep) override {
VL_RESTORER(m_dynsizedelem);
m_dynsizedelem = true;
iterateChildren(nodep);
editDType(nodep);
}
void visit(AstSel* nodep) override {
{
VL_RESTORER(m_underSel);

View File

@ -1,26 +1,42 @@
%Error: t/t_assign_automatic_bad.v:31:10: Automatic lifetime variable not allowed in continuous assignment (IEEE 1800-2023 6.21): 'bad_auto3'
%Error: t/t_assign_automatic_bad.v:37:10: Automatic lifetime variable not allowed in continuous assignment (IEEE 1800-2023 6.21): 'bad_auto3'
: ... note: In instance 't'
31 | assign bad_auto3 = 2;
37 | assign bad_auto3 = 2;
| ^~~~~~~~~
... See the manual at https://verilator.org/verilator_doc.html?v=latest for more assistance.
%Error: t/t_assign_automatic_bad.v:32:10: Dynamically-sized variable not allowed in continuous assignment (IEEE 1800-2023 6.21): 'bad_dyn5'
%Error: t/t_assign_automatic_bad.v:38:10: Dynamically-sized variable not allowed in continuous assignment (IEEE 1800-2023 6.21): 'bad_dyn5'
: ... note: In instance 't'
32 | assign bad_dyn5 = empty_dyn;
38 | assign bad_dyn5[0] = empty_dyn;
| ^~~~~~~~
%Error: t/t_assign_automatic_bad.v:33:12: Automatic lifetime variable not allowed in continuous assignment (IEEE 1800-2023 6.21): 'm_bad1'
%Error: t/t_assign_automatic_bad.v:40:12: Automatic lifetime variable not allowed in continuous assignment (IEEE 1800-2023 6.21): 'm_bad1'
: ... note: In instance 't'
33 | assign c.m_bad1 = 2;
40 | assign c.m_bad1 = 2;
| ^~~~~~
%Error: t/t_assign_automatic_bad.v:43:5: Automatic lifetime variable not allowed in nonblocking assignment (IEEE 1800-2023 6.21): 'bad_auto4'
%Error: t/t_assign_automatic_bad.v:50:5: Automatic lifetime variable not allowed in nonblocking assignment (IEEE 1800-2023 6.21): 'bad_auto4'
: ... note: In instance 't'
43 | bad_auto4 <= 2;
50 | bad_auto4 <= 2;
| ^~~~~~~~~
%Error: t/t_assign_automatic_bad.v:44:5: Dynamically-sized variable not allowed in nonblocking assignment (IEEE 1800-2023 6.21): 'bad_dyn6'
%Error: t/t_assign_automatic_bad.v:51:5: Dynamically-sized variable not allowed in nonblocking assignment (IEEE 1800-2023 6.21): 'bad_dyn6'
: ... note: In instance 't'
44 | bad_dyn6 <= empty_dyn;
51 | bad_dyn6[0] <= 2;
| ^~~~~~~~
%Error: t/t_assign_automatic_bad.v:46:7: Automatic lifetime variable not allowed in nonblocking assignment (IEEE 1800-2023 6.21): 'm_bad2'
%Error: t/t_assign_automatic_bad.v:53:5: Dynamically-sized variable not allowed in nonblocking assignment (IEEE 1800-2023 6.21): 'bad_queue'
: ... note: In instance 't'
46 | c.m_bad2 <= 2;
53 | bad_queue[0] <= 2;
| ^~~~~~~~~
%Error: t/t_assign_automatic_bad.v:55:5: Dynamically-sized variable not allowed in nonblocking assignment (IEEE 1800-2023 6.21): 'bad_assoc'
: ... note: In instance 't'
55 | bad_assoc[0] <= 2;
| ^~~~~~~~~
%Error: t/t_assign_automatic_bad.v:58:7: Automatic lifetime variable not allowed in nonblocking assignment (IEEE 1800-2023 6.21): 'm_bad2'
: ... note: In instance 't'
58 | c.m_bad2 <= 2;
| ^~~~~~
%Error: t/t_assign_automatic_bad.v:60:10: Dynamically-sized variable not allowed in nonblocking assignment (IEEE 1800-2023 6.21): 's_dyn'
: ... note: In instance 't'
60 | Cls::s_dyn[0] <= 2;
| ^~~~~
%Error: t/t_assign_automatic_bad.v:62:26: Dynamically-sized variable not allowed in nonblocking assignment (IEEE 1800-2023 6.21): 's_dyn'
: ... note: In instance 't'
62 | clist[bad_dyn6[0]++].s_dyn[0] <= '1;
| ^~~~~
%Error: Exiting due to

View File

@ -13,6 +13,7 @@
class Cls;
static int s_ok1;
static int s_ok2;
static int s_dyn[];
int m_bad1;
int m_bad2;
endclass
@ -27,9 +28,15 @@ module t(clk);
int bad_dyn5[];
int bad_dyn6[];
int empty_dyn[];
int empty_queue[$];
int empty_assoc[int];
int bad_queue[$];
int bad_assoc[int];
Cls clist[1];
assign bad_auto3 = 2; // <--- Error: continuous automatic
assign bad_dyn5 = empty_dyn; // <--- Error: continuous dynarray
assign bad_dyn5[0] = empty_dyn; // <--- Error: continuous dynarray element
assign bad_dyn5 = empty_dyn; // <--- OK: continuous dynarray assignment, not to its element
assign c.m_bad1 = 2; // <--- Error: continuous class non-static
// Only one simulator fails on this, probably not legal
// assign Cls::s_ok1 = 2; // OK: continuous class static
@ -41,9 +48,18 @@ module t(clk);
always @(posedge clk) begin
bad_auto4 <= 2; // <--- Error: nonblocking automatic
bad_dyn6 <= empty_dyn; // <--- Error: nonblocking dynarray
bad_dyn6[0] <= 2; // <--- Error: nonblocking dynarray element
bad_dyn6 <= empty_dyn; // <--- OK: nonblocking dynarray assignment, not to its element
bad_queue[0] <= 2; // Error: nonblocking queue element assignment
bad_queue <= empty_queue; // OK: nonblocking assignment to queue itself, not to its element
bad_assoc[0] <= 2; // Error: nonblocking associative array element assignment
bad_assoc <= empty_assoc; // OK: nonblocking assignment to associative array itself, not to its element
Cls::s_ok2 <= 2; // OK: nonblocking class static
c.m_bad2 <= 2; // <--- Error: nonblocking class automatic
Cls::s_dyn <= 2; // OK: nonblocking class static dynarray assignment, not to its element
Cls::s_dyn[0] <= 2; // Error: nonblocking class static dynarray element
clist[bad_dyn6[0]++].s_dyn <= '1; // OK: direct nonblocking assignment to dynamically-sized array
clist[bad_dyn6[0]++].s_dyn[0] <= '1; // Error: nonblocking assigment to dynamically-sized array element
mt(ok_7);
$stop;
end