From 7526151670fd3ffb22bc2096c276599b24fca889 Mon Sep 17 00:00:00 2001 From: Wilson Snyder Date: Tue, 21 Dec 2021 19:55:04 -0500 Subject: [PATCH] Fix bad ending address on $readmem (#3205). --- Changes | 1 + include/verilated.cpp | 30 ++++++++++++++++++++--- include/verilated_cov.cpp | 4 +-- include/verilated_funcs.h | 12 +++++++-- include/verilated_trace_imp.cpp | 2 +- include/verilated_types.h | 1 + test_regress/t/t_sys_readmem_bad_end.out | 4 +-- test_regress/t/t_sys_readmem_bad_end.pl | 1 - test_regress/t/t_sys_readmem_bad_end.v | 3 +++ test_regress/t/t_sys_readmem_bad_end2.mem | 13 ++++++++++ 10 files changed, 60 insertions(+), 11 deletions(-) create mode 100644 test_regress/t/t_sys_readmem_bad_end2.mem diff --git a/Changes b/Changes index 797a23983..ab37a6260 100644 --- a/Changes +++ b/Changes @@ -23,6 +23,7 @@ Verilator 4.217 devel * Support up to 64 bit enums for .next/.prev/.name (#3244). [Alexander Grobman] * Reduce .rodata footprint of trace initialization (#3250). [Geza Lore, Shunyao CAD] * Use C++11 standard types for MacOS portability (#3254). [Adrien Le Masle] +* Fix bad ending address on $readmem (#3205). [Julie Schwartz] * Fix MSWIN compile error (#2681). [Unai Martinez-Corral] * Fix break under foreach loop (#3230). * Fix VL_STREAML_FAST_QQI with 64 bit left-hand-side (#3232) (#3235) diff --git a/include/verilated.cpp b/include/verilated.cpp index ae76d93a1..bc1e05061 100644 --- a/include/verilated.cpp +++ b/include/verilated.cpp @@ -168,6 +168,19 @@ void vl_stop_maybe(const char* filename, int linenum, const char* hier, bool may } #endif +#ifndef VL_USER_WARN ///< Define this to override the vl_warn function +void vl_warn(const char* filename, int linenum, const char* hier, const char* msg) VL_MT_UNSAFE { + if (false && hier) {} + if (filename && filename[0]) { + // Not VL_PRINTF_MT, already on main thread + VL_PRINTF("%%Warning: %s:%d: %s\n", filename, linenum, msg); + } else { + VL_PRINTF("%%Warning: %s\n", msg); + } + Verilated::runFlushCallbacks(); +} +#endif + //=========================================================================== // Wrapper to call certain functions via messages when multithreaded @@ -201,6 +214,16 @@ void VL_FATAL_MT(const char* filename, int linenum, const char* hier, const char #endif } +void VL_WARN_MT(const char* filename, int linenum, const char* hier, const char* msg) VL_MT_SAFE { +#ifdef VL_THREADED + VerilatedThreadMsgQueue::post(VerilatedMsg{[=]() { // + vl_warn(filename, linenum, hier, msg); + }}); +#else + vl_warn(filename, linenum, hier, msg); +#endif +} + //=========================================================================== // Debug prints @@ -1876,6 +1899,7 @@ bool VlReadMem::get(QData& addrr, std::string& valuer) { ignore_to_eol = true; } else if (c == '@') { reading_addr = true; + m_anyAddr = true; m_addr = 0; } // Check for hex or binary digits as file format requests @@ -1902,9 +1926,9 @@ bool VlReadMem::get(QData& addrr, std::string& valuer) { lastc = c; } - if (VL_UNLIKELY(m_end != ~0ULL && m_addr <= m_end)) { - VL_FATAL_MT(m_filename.c_str(), m_linenum, "", - "$readmem file ended before specified final address (IEEE 2017 21.4)"); + if (VL_UNLIKELY(m_end != ~0ULL && m_addr <= m_end && !m_anyAddr)) { + VL_WARN_MT(m_filename.c_str(), m_linenum, "", + "$readmem file ended before specified final address (IEEE 2017 21.4)"); } return false; // EOF diff --git a/include/verilated_cov.cpp b/include/verilated_cov.cpp index d52ecc8f8..1bbba02f1 100644 --- a/include/verilated_cov.cpp +++ b/include/verilated_cov.cpp @@ -231,7 +231,7 @@ private: // Little selftest #define SELF_CHECK(got, exp) \ do { \ - if ((got) != (exp)) VL_FATAL_MT(__FILE__, __LINE__, "", "%Error: selftest\n"); \ + if ((got) != (exp)) VL_FATAL_MT(__FILE__, __LINE__, "", "%Error: selftest"); \ } while (0) SELF_CHECK(combineHier("a.b.c", "a.b.c"), "a.b.c"); SELF_CHECK(combineHier("a.b.c", "a.b"), "a.b*"); @@ -358,7 +358,7 @@ public: Verilated::quiesce(); const VerilatedLockGuard lock{m_mutex}; #ifndef VM_COVERAGE - VL_FATAL_MT("", 0, "", "%Error: Called VerilatedCov::write when VM_COVERAGE disabled\n"); + VL_FATAL_MT("", 0, "", "%Error: Called VerilatedCov::write when VM_COVERAGE disabled"); #endif selftest(); diff --git a/include/verilated_funcs.h b/include/verilated_funcs.h index 81a68dd99..19e48f6fb 100644 --- a/include/verilated_funcs.h +++ b/include/verilated_funcs.h @@ -43,12 +43,17 @@ extern void vl_finish(const char* filename, int linenum, const char* hier); /// Verilator internal code must call VL_FINISH_MT instead, which eventually calls this. extern void vl_stop(const char* filename, int linenum, const char* hier); -/// Routine to call for a couple of fatal messages +/// Routine to call for fatal messages /// User code may wish to replace this function, to do so, define VL_USER_FATAL. /// This code does not have to be thread safe. /// Verilator internal code must call VL_FINISH_MT instead, which eventually calls this. extern void vl_fatal(const char* filename, int linenum, const char* hier, const char* msg); +/// Routine to call for warning messages +/// User code may wish to replace this function, to do so, define VL_USER_WARN. +/// This code does not have to be thread safe. +extern void vl_warn(const char* filename, int linenum, const char* hier, const char* msg); + //========================================================================= // Extern functions -- Slow path @@ -57,9 +62,12 @@ extern void VL_FINISH_MT(const char* filename, int linenum, const char* hier) VL /// Multithread safe wrapper for calls to $stop extern void VL_STOP_MT(const char* filename, int linenum, const char* hier, bool maybe = true) VL_MT_SAFE; -/// Multithread safe wrapper to call for a couple of fatal messages +/// Multithread safe wrapper to call for fatal messages extern void VL_FATAL_MT(const char* filename, int linenum, const char* hier, const char* msg) VL_MT_SAFE; +/// Multithread safe wrapper to call for warning messages +extern void VL_WARN_MT(const char* filename, int linenum, const char* hier, + const char* msg) VL_MT_SAFE; // clang-format off /// Print a string, multithread safe. Eventually VL_PRINTF will get called. diff --git a/include/verilated_trace_imp.cpp b/include/verilated_trace_imp.cpp index 925e30580..6154ceb80 100644 --- a/include/verilated_trace_imp.cpp +++ b/include/verilated_trace_imp.cpp @@ -660,7 +660,7 @@ static inline void cvtQDataToStr(char* dstp, QData value) { void verilated_trace_imp_selftest() { #define SELF_CHECK(got, exp) \ do { \ - if ((got) != (exp)) VL_FATAL_MT(__FILE__, __LINE__, "", "%Error: selftest\n"); \ + if ((got) != (exp)) VL_FATAL_MT(__FILE__, __LINE__, "", "%Error: selftest"); \ } while (0) #define SELF_CHECK_TS(scale) \ diff --git a/include/verilated_types.h b/include/verilated_types.h index 13c57d3cc..bb065c9e4 100644 --- a/include/verilated_types.h +++ b/include/verilated_types.h @@ -86,6 +86,7 @@ class VlReadMem final { FILE* m_fp; // File handle for filename QData m_addr; // Next address to read int m_linenum; // Line number last read from file + bool m_anyAddr = false; // Had address directive in the file public: VlReadMem(bool hex, int bits, const std::string& filename, QData start, QData end); ~VlReadMem(); diff --git a/test_regress/t/t_sys_readmem_bad_end.out b/test_regress/t/t_sys_readmem_bad_end.out index 752129a5b..4c6aaf01f 100644 --- a/test_regress/t/t_sys_readmem_bad_end.out +++ b/test_regress/t/t_sys_readmem_bad_end.out @@ -1,2 +1,2 @@ -%Error: t/t_sys_readmem_bad_end.mem:12: $readmem file ended before specified final address (IEEE 2017 21.4) -Aborting... +%Warning: t/t_sys_readmem_bad_end.mem:12: $readmem file ended before specified final address (IEEE 2017 21.4) +*-* All Finished *-* diff --git a/test_regress/t/t_sys_readmem_bad_end.pl b/test_regress/t/t_sys_readmem_bad_end.pl index d89f1290d..56cc415df 100755 --- a/test_regress/t/t_sys_readmem_bad_end.pl +++ b/test_regress/t/t_sys_readmem_bad_end.pl @@ -14,7 +14,6 @@ compile( ); execute( - fails => $Self->{vlt_all}, expect_filename => $Self->{golden_filename}, ); diff --git a/test_regress/t/t_sys_readmem_bad_end.v b/test_regress/t/t_sys_readmem_bad_end.v index 7aee6a967..772e74f55 100644 --- a/test_regress/t/t_sys_readmem_bad_end.v +++ b/test_regress/t/t_sys_readmem_bad_end.v @@ -11,6 +11,9 @@ module t; integer i; initial begin + // No warning as has addresses + $readmemh("t/t_sys_readmem_bad_end2.mem", hex, 0, 15); + // Warning as wrong end address $readmemh("t/t_sys_readmem_bad_end.mem", hex, 0, 15); $write("*-* All Finished *-*\n"); $finish; diff --git a/test_regress/t/t_sys_readmem_bad_end2.mem b/test_regress/t/t_sys_readmem_bad_end2.mem new file mode 100644 index 000000000..d4d4bc48a --- /dev/null +++ b/test_regress/t/t_sys_readmem_bad_end2.mem @@ -0,0 +1,13 @@ +// DESCRIPTION: Verilator: Verilog Test data file +// +// Copyright 2006 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 + +10 +11 +@2 +01 +// Missing additional data