diff --git a/src/V3Delayed.cpp b/src/V3Delayed.cpp index 6feb4e4da..1f6758629 100644 --- a/src/V3Delayed.cpp +++ b/src/V3Delayed.cpp @@ -150,6 +150,7 @@ class DelayedVisitor final : public VNVisitor { const AstVarRef* m_firstNbaRefp = nullptr; // Active block 'm_firstNbaRefp' is under const AstActive* m_fistActivep = nullptr; + bool m_whole = false; // Used on LHS of NBA directly via VarRef bool m_partial = false; // Used on LHS of NBA under a Sel bool m_inLoop = false; // Used on LHS of NBA in a loop bool m_inSuspOrFork = false; // Used on LHS of NBA in suspendable process or fork @@ -414,6 +415,8 @@ class DelayedVisitor final : public VNVisitor { const AstNodeDType* const dtypep = vscp->dtypep()->skipRefp(); // Unpacked arrays if (const AstUnpackArrayDType* const uaDTypep = VN_CAST(dtypep, UnpackArrayDType)) { + // If whole array is target of NBA, use ShadowVar + if (vscpInfo.m_whole) return Scheme::ShadowVar; // Basic underlying type of elements, if any. const AstBasicDType* const basicp = uaDTypep->basicp(); // If used in a loop, we must have a dynamic commit queue. (Also works in suspendables) @@ -1255,6 +1258,7 @@ class DelayedVisitor final : public VNVisitor { m_vscps.emplace_back(vscp); } // Note usage context + vscpInfo.m_whole |= VN_IS(nodep->lhsp(), VarRef); vscpInfo.m_partial |= VN_IS(nodep->lhsp(), Sel); vscpInfo.m_inLoop |= m_inLoop; vscpInfo.m_inSuspOrFork |= m_inSuspendableOrFork; diff --git a/test_regress/t/t_nba_commit_queue.py b/test_regress/t/t_nba_commit_queue.py index 0b71cf8b2..63d6c69e3 100755 --- a/test_regress/t/t_nba_commit_queue.py +++ b/test_regress/t/t_nba_commit_queue.py @@ -17,5 +17,6 @@ test.execute() test.file_grep(test.stats, r'NBA, variables using ValueQueueWhole scheme\s+(\d+)', 6) test.file_grep(test.stats, r'NBA, variables using ValueQueuePartial scheme\s+(\d+)', 3) +test.file_grep(test.stats, r'NBA, variables using ShadowVar scheme\s+(\d+)', 3) test.passes() diff --git a/test_regress/t/t_nba_commit_queue.v b/test_regress/t/t_nba_commit_queue.v index ccda0713c..09ac4bcf3 100644 --- a/test_regress/t/t_nba_commit_queue.v +++ b/test_regress/t/t_nba_commit_queue.v @@ -297,4 +297,32 @@ module t(clk); for (int i = 0 ; i < 10; ++i) `checks(array9[i], "cuttlefish"); end + // Case 10: Packed narrow, but whole array also target of NBA directly + typedef logic [31:0] elem10_t; + typedef elem10_t array10_t[128]; + array10_t array10; + array10_t array10_init = '{default: 10}; + `at_posedge_clk_on_cycle(0) begin + for (int i = 0 ; i < 128; ++i) array10[i] = 0; + for (int i = 0 ; i < 128; ++i) `checkh(array10[i], 0); + end + `at_posedge_clk_on_cycle(1) begin + for (int i = 0 ; i < 128; ++i) `checkh(array10[i], 0); + array10 <= array10_init; + for (int i = 0 ; i < 128; ++i) `checkh(array10[i], 0); + end + `at_posedge_clk_on_cycle(2) begin + for (int i = 0 ; i < 128; ++i) `checkh(array10[i], 10); + for (int i = 64 ; i < 128; ++i) array10[i][4] <= 1'b1; + for (int i = 0 ; i < 128; ++i) `checkh(array10[i], 10); + end + `at_posedge_clk_on_cycle(3) begin + for (int i = 0 ; i < 128; ++i) `checkh(array10[i], i < 64 ? 10 : 26); + for (int i = 0 ; i < 128; ++i) array10[i] <= ~i; + for (int i = 0 ; i < 128; ++i) `checkh(array10[i], i < 64 ? 10 : 26); + end + `at_posedge_clk_on_cycle(4) begin + for (int i = 0 ; i < 128; ++i) `checkh(array10[i], ~i); + end + endmodule