From e7dc2de14b62af99c4884d2047ca68e25b3aba91 Mon Sep 17 00:00:00 2001 From: Wilson Snyder Date: Sat, 4 Jun 2022 12:43:18 -0400 Subject: [PATCH] Fix BLKANDNBLK on $readmem/$writemem (#3379). --- Changes | 1 + src/V3Delayed.cpp | 9 ++++++ test_regress/t/t_sys_readmem_assoc.v | 41 +++++++++++++++++++--------- 3 files changed, 38 insertions(+), 13 deletions(-) diff --git a/Changes b/Changes index 53560e563..4908e3d91 100644 --- a/Changes +++ b/Changes @@ -26,6 +26,7 @@ Verilator 4.223 devel * Define VM_TRACE_VCD when tracing in VCD format. [Geza Lore, Shunyao CAD] * Add assert when VerilatedContext is mis-deleted (#3121). [Rupert Swarbrick] * Fix hang with large case statement optimization (#3405). [Mike Urbach] +* Fix BLKANDNBLK on $readmem/$writemem (#3379). [Alex Solomatnikov] * Fix 'with' operator with type casting (#3387). [xiak95] * Fix incorrect conditional merging (#3409). [Raynard Qiao] * Fix passing VL_TRACE_FST_WRITER_THREAD in CMake build. [Geza Lore, Shunyao CAD] diff --git a/src/V3Delayed.cpp b/src/V3Delayed.cpp index 57fe02833..668fff8a4 100644 --- a/src/V3Delayed.cpp +++ b/src/V3Delayed.cpp @@ -94,6 +94,7 @@ private: bool m_inDly = false; // True in delayed assignments bool m_inLoop = false; // True in for loops bool m_inInitial = false; // True in initial blocks + bool m_ignoreBlkAndNBlk = false; // Suppress delayed assignment BLKANDNBLK using VarMap = std::map, AstVar*>; VarMap m_modVarMap; // Table of new var names created under module VDouble0 m_statSharedSet; // Statistic tracking @@ -105,6 +106,7 @@ private: void markVarUsage(AstNodeVarRef* nodep, bool blocking) { // Ignore if warning is disabled on this reference (used by V3Force). if (nodep->fileline()->warnIsOff(V3ErrorCode::BLKANDNBLK)) return; + if (m_ignoreBlkAndNBlk) return; if (blocking) nodep->user5(true); AstVarScope* const vscp = nodep->varScopep(); // UINFO(4, " MVU " << blocking << " " << nodep << endl); @@ -485,6 +487,13 @@ private: } } + virtual void visit(AstNodeReadWriteMem* nodep) override { + VL_RESTORER(m_ignoreBlkAndNBlk); + m_ignoreBlkAndNBlk = true; // $readmem/$writemem often used in mem models + // so we will suppress BLKANDNBLK warnings + iterateChildren(nodep); + } + virtual void visit(AstNodeFor* nodep) override { // LCOV_EXCL_LINE nodep->v3fatalSrc( "For statements should have been converted to while statements in V3Begin"); diff --git a/test_regress/t/t_sys_readmem_assoc.v b/test_regress/t/t_sys_readmem_assoc.v index 9d0654c2e..7d2487f31 100644 --- a/test_regress/t/t_sys_readmem_assoc.v +++ b/test_regress/t/t_sys_readmem_assoc.v @@ -6,22 +6,37 @@ `define STRINGIFY(x) `"x`" -module t; +module t(/*AUTOARG*/ + // Inputs + clk + ); + + input clk; + int cyc; reg [5:0] assoc_c[int]; reg [95:0] assoc_w[int]; - initial begin - assoc_c[300] = 10; // See if clearing must happen first - $readmemb("t/t_sys_readmem_b.mem", assoc_c); - $display("assoc_c=%p", assoc_c); - $writememh({`STRINGIFY(`TEST_OBJ_DIR),"/t_sys_writemem_c_b.mem"}, assoc_c); - - $readmemb("t/t_sys_readmem_b.mem", assoc_w); - // Not conditional with TEST_VERBOSE as found bug with wide display - $display("assoc_w=%p", assoc_w); - $writememh({`STRINGIFY(`TEST_OBJ_DIR),"/t_sys_writemem_w_h.mem"}, assoc_w); - $write("*-* All Finished *-*\n"); - $finish; + always_ff @ (posedge clk) begin + cyc <= cyc + 1; + if (cyc == 1) begin + assoc_c[300] <= 10; // See if clearing must happen first + // Also checks no BLKANDNBLK due to readmem/writemem + end + else if (cyc == 2) begin + $readmemb("t/t_sys_readmem_b.mem", assoc_c); + $display("assoc_c=%p", assoc_c); + $writememh({`STRINGIFY(`TEST_OBJ_DIR),"/t_sys_writemem_c_b.mem"}, assoc_c); + end + else if (cyc == 3) begin + $readmemb("t/t_sys_readmem_b.mem", assoc_w); + // Not conditional with TEST_VERBOSE as found bug with wide display + $display("assoc_w=%p", assoc_w); + $writememh({`STRINGIFY(`TEST_OBJ_DIR),"/t_sys_writemem_w_h.mem"}, assoc_w); + end + else if (cyc == 4) begin + $write("*-* All Finished *-*\n"); + $finish; + end end endmodule