forked from github/verilator
194 lines
7.6 KiB
C++
194 lines
7.6 KiB
C++
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
|
//=============================================================================
|
|
//
|
|
// Code available from: https://verilator.org
|
|
//
|
|
// Copyright 2001-2023 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 <iostream>
|
|
#include <sstream>
|
|
#include <string>
|
|
|
|
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(&m_cases[i], "comment", "Coverage Case", "i", cvtToNumStr(i));
|
|
/// }
|
|
|
|
#define VL_COVER_INSERT(covcontextp, countp, ...) \
|
|
do { \
|
|
covcontextp->_inserti(countp); \
|
|
covcontextp->_insertf(__FILE__, __LINE__); \
|
|
covcontextp->_insertp("hier", name(), __VA_ARGS__); \
|
|
} while (false)
|
|
|
|
//=============================================================================
|
|
// Convert VL_COVER_INSERT value arguments to strings, is \internal
|
|
|
|
template <class T>
|
|
std::string vlCovCvtToStr(const T& t) VL_PURE {
|
|
std::ostringstream os;
|
|
os << t;
|
|
return os.str();
|
|
}
|
|
|
|
//=============================================================================
|
|
// 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
|
|
static const char* defaultFilename() VL_PURE { return "coverage.dat"; }
|
|
/// 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(const char* filenamep = defaultFilename()) 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<VerilatedCovImp*>(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 const char* defaultFilename() VL_PURE { return VerilatedCovContext::defaultFilename(); }
|
|
/// Write all coverage data to a file for the current thread
|
|
static void write(const char* filenamep = defaultFilename()) VL_MT_SAFE {
|
|
threadCovp()->write(filenamep);
|
|
}
|
|
/// 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
|