// -*- mode: C++; c-file-style: "cc-mode" -*- //============================================================================= // // Code available from: https://verilator.org // // Copyright 2001-2024 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 // //============================================================================= /// /// \file /// \brief Verilated coverage analysis support header /// /// This must be included in user wrapper code that wants to save coverage /// data. /// /// It declares the VerilatedCovContext::write() which writes the collected /// coverage information. /// //============================================================================= #ifndef VERILATOR_VERILATED_COV_H_ #define VERILATOR_VERILATED_COV_H_ #include "verilatedos.h" #include "verilated.h" #include #include #include class VerilatedCovImp; //============================================================================= /// Insert an item for coverage analysis. /// The first argument is a pointer to the count to be dumped. /// The remaining arguments occur in pairs: A string key, and a value. /// The value may be a string, or another type which will be auto-converted to a string. /// /// Some typical keys: /// /// filename File the recording occurs in. Defaults to __FILE__. /// lineno Line number the recording occurs in. Defaults to __LINE__ /// column Column number (or occurrence# for dup file/lines). Defaults to undef. /// hier Hierarchical name. Defaults to name() /// type Type of coverage. Defaults to "user" /// Other types are 'block', 'fsm', 'toggle'. /// comment Description of the coverage event. Should be set by the user. /// Comments for type==block: 'if', 'else', 'elsif', 'case' /// thresh Threshold to consider fully covered. /// If unspecified, downstream tools will determine it. /// per_instance If non-zero don't combine all hierarchies into one count /// /// Example: /// /// uint32_t m_cases[10]; // Storage for coverage data /// constructor() { /// // Initialize /// for (int i = 0; i < 10; ++i) m_cases[i] = 0; /// // Insert /// for (int i = 0; i < 10; ++i) /// VL_COVER_INSERT(covp, name(), &m_cases[i], "comment", "Coverage Case", /// "i", cvtToNumStr(i)); /// } #define VL_COVER_INSERT(covcontextp, name, countp, ...) \ do { \ auto const ccontextp = covcontextp; \ ccontextp->_inserti(countp); \ ccontextp->_insertf(__FILE__, __LINE__); \ ccontextp->_insertp("hier", name, __VA_ARGS__); \ } while (false) //============================================================================= // VerilatedCov /// Per-VerilatedContext coverage data class. /// All public methods in this class are thread safe. /// /// This structure is accessed and constructed on first access via /// VerilatedContext::coveragep() class VerilatedCovContext VL_NOT_FINAL : public VerilatedVirtualBase { VL_UNCOPYABLE(VerilatedCovContext); public: // METHODS /// Return default filename, may override with +verilator+coverage+file std::string defaultFilename() VL_MT_SAFE; /// Make all data per_instance, overriding point's per_instance void forcePerInstance(bool flag) VL_MT_SAFE; /// Write all coverage data to a file void write() VL_MT_SAFE { write(defaultFilename()); } void write(const std::string& filename) VL_MT_SAFE; /// Clear coverage points (and call delete on all items) void clear() VL_MT_SAFE; /// Clear items not matching the provided string void clearNonMatch(const char* matchp) VL_MT_SAFE; /// Zero coverage points void zero() VL_MT_SAFE; // METHODS - public but Internal use only // Insert a coverage item // We accept from 1-30 key/value pairs, all as strings. // Call _insert1, followed by _insert2 and _insert3 // Do not call directly; use VL_COVER_INSERT or higher level macros instead // _insert1: Remember item pointer with count. (Not const, as may add zeroing function) void _inserti(uint32_t* itemp) VL_MT_SAFE; void _inserti(uint64_t* itemp) VL_MT_SAFE; // _insert2: Set default filename and line number void _insertf(const char* filename, int lineno) VL_MT_SAFE; // _insert3: Set parameters // We could have just the maximum argument version, but this compiles // much slower (nearly 2x) than having smaller versions also. However // there's not much more gain in having a version for each number of args. #ifndef DOXYGEN #define K(n) const char* key##n #define A(n) const char *key##n, const char *valp##n // Argument list #define D(n) const char *key##n = nullptr, const char *valp##n = nullptr // Argument list void _insertp(D(0), D(1), D(2), D(3), D(4), D(5), D(6), D(7), D(8), D(9)) VL_MT_SAFE; void _insertp(A(0), A(1), A(2), A(3), A(4), A(5), A(6), A(7), A(8), A(9), A(10), D(11), D(12), D(13), D(14), D(15), D(16), D(17), D(18), D(19)) VL_MT_SAFE; void _insertp(A(0), A(1), A(2), A(3), A(4), A(5), A(6), A(7), A(8), A(9), A(10), A(11), A(12), A(13), A(14), A(15), A(16), A(17), A(18), A(19), A(20), D(21), D(22), D(23), D(24), D(25), D(26), D(27), D(28), D(29)) VL_MT_SAFE; // Backward compatibility for Verilator void _insertp(A(0), A(1), K(2), int val2, K(3), int val3, K(4), const std::string& val4, A(5), A(6), A(7)) VL_MT_SAFE; #undef K #undef A #undef D #endif // DOXYGEN protected: friend class VerilatedCovImp; // CONSTRUCTORS // Internal: Only made as part of VerilatedCovImp VerilatedCovContext() = default; ~VerilatedCovContext() override = default; // METHODS // Internal: access to implementation class VerilatedCovImp* impp() VL_MT_SAFE { return reinterpret_cast(this); } }; //============================================================================= // VerilatedCov /// Coverage global class. /// /// Global class that accesses via current thread's context's /// VerilatedCovContext. This class is provided only for /// backward-compatibility, use VerilatedContext::coveragep() instead. #ifndef VL_NO_LEGACY class VerilatedCov final { VL_UNCOPYABLE(VerilatedCov); public: // METHODS /// Return default filename for the current thread static std::string defaultFilename() VL_MT_SAFE { return threadCovp()->defaultFilename(); } /// Write all coverage data to a file for the current thread static void write() VL_MT_SAFE { write(defaultFilename()); } static void write(const std::string& filename) VL_MT_SAFE { threadCovp()->write(filename); } /// Clear coverage points (and call delete on all items) for the current thread static void clear() VL_MT_SAFE { threadCovp()->clear(); } /// Clear items not matching the provided string for the current thread static void clearNonMatch(const char* matchp) VL_MT_SAFE { threadCovp()->clearNonMatch(matchp); } /// Zero coverage points for the current thread static void zero() VL_MT_SAFE { threadCovp()->zero(); } private: // Current thread's coverage structure static VerilatedCovContext* threadCovp() VL_MT_SAFE; }; #endif // VL_NO_LEGACY #endif // Guard