diff --git a/Changes b/Changes index b6cdd4b08..22c55a30a 100644 --- a/Changes +++ b/Changes @@ -46,6 +46,7 @@ Verilator 5.007 devel * Fix class field linking when a super classes is a param (#3949). [Ryszard Rozak, Antmicro Ltd] * Fix CMake bad C identifiers (#3948) (#3951). [Zixi Li] * Fix build on HP PA architecture. (#3954) [John David Anglin] +* Fix packed array structure replication. Verilator 5.006 2023-01-22 diff --git a/src/V3Slice.cpp b/src/V3Slice.cpp index 8bee2d842..17ad58852 100644 --- a/src/V3Slice.cpp +++ b/src/V3Slice.cpp @@ -58,6 +58,7 @@ class SliceVisitor final : public VNVisitor { // STATE AstNode* m_assignp = nullptr; // Assignment we are under bool m_assignError = false; // True if the current assign already has an error + bool m_okInitArray = false; // Allow InitArray children // METHODS AstNodeExpr* cloneAndSel(AstNode* nodep, int elements, int offset) { @@ -163,8 +164,14 @@ class SliceVisitor final : public VNVisitor { } } + void visit(AstConsPackUOrStruct* nodep) override { + VL_RESTORER(m_okInitArray); + m_okInitArray = true; + iterateChildren(nodep); + } void visit(AstInitArray* nodep) override { - UASSERT_OBJ(!m_assignp, nodep, "Array initialization should have been removed earlier"); + UASSERT_OBJ(!m_assignp || m_okInitArray, nodep, + "Array initialization should have been removed earlier"); } void expandBiOp(AstNodeBiop* nodep) { diff --git a/src/V3Unknown.cpp b/src/V3Unknown.cpp index 258c98506..2f0eabfb0 100644 --- a/src/V3Unknown.cpp +++ b/src/V3Unknown.cpp @@ -439,7 +439,7 @@ private: } else if (VN_IS(basefromp, Const)) { // If it's a PARAMETER[bit], then basefromp may be a constant instead of a varrefp } else { - nodep->v3fatalSrc("No VarRef or Const under ArraySel"); + // Normally one of above, but might have MEMBERSEL or otherwise } // Find range of dtype we are selecting from int declElements = -1; diff --git a/test_regress/t/t_struct_pat.v b/test_regress/t/t_struct_pat.v index be82f6556..931113fc0 100644 --- a/test_regress/t/t_struct_pat.v +++ b/test_regress/t/t_struct_pat.v @@ -21,6 +21,19 @@ module t(/*AUTOARG*/); sabcu_t abcu; sabcp_t abcp; + typedef struct { + int a; + int b4[4]; + } sab4u_t; + + typedef struct packed { + int a; + bit [3:0][31:0] b4; + } sab4p_t; + + sab4u_t ab4u[2][3]; + sab4p_t ab4p[2][3]; + initial begin abcp = '{1, 2, 3}; abcu = '{1, 2, 3}; @@ -31,6 +44,15 @@ module t(/*AUTOARG*/); if (abcu.b !== 2) $stop; if (abcu.c !== 3) $stop; + abcp = '{3{40}}; + abcu = '{3{40}}; + if (abcp.a !== 40) $stop; + if (abcp.b !== 40) $stop; + if (abcp.c !== 40) $stop; + if (abcu.a !== 40) $stop; + if (abcu.b !== 40) $stop; + if (abcu.c !== 40) $stop; + abcp = '{default:4, int:5}; abcu = '{default:4, int:5}; if (abcp.a !== 5) $stop; @@ -49,6 +71,31 @@ module t(/*AUTOARG*/); if (abcu.b !== 8) $stop; if (abcu.c !== 7) $stop; + ab4p = '{2{'{3{'{10, '{2{20, 30}}}}}}}; + ab4u = '{2{'{3{'{10, '{2{20, 30}}}}}}}; + $display("%p", ab4p); + if (ab4p[0][0].a !== 10) $stop; + if (ab4p[0][0].b4[0] !== 30) $stop; + if (ab4p[0][0].b4[1] !== 20) $stop; + if (ab4p[0][0].b4[2] !== 30) $stop; + if (ab4p[0][0].b4[3] !== 20) $stop; + if (ab4p[1][2].a !== 10) $stop; + if (ab4p[1][2].b4[0] !== 30) $stop; + if (ab4p[1][2].b4[1] !== 20) $stop; + if (ab4p[1][2].b4[2] !== 30) $stop; + if (ab4p[1][2].b4[3] !== 20) $stop; + $display("%p", ab4u); + if (ab4u[0][0].a !== 10) $stop; + if (ab4u[0][0].b4[0] !== 20) $stop; + if (ab4u[0][0].b4[1] !== 30) $stop; + if (ab4u[0][0].b4[2] !== 20) $stop; + if (ab4u[0][0].b4[3] !== 30) $stop; + if (ab4u[1][2].a !== 10) $stop; + if (ab4u[1][2].b4[0] !== 20) $stop; + if (ab4u[1][2].b4[1] !== 30) $stop; + if (ab4u[1][2].b4[2] !== 20) $stop; + if (ab4u[1][2].b4[3] !== 30) $stop; + $write("*-* All Finished *-*\n"); $finish; end