Refactoring before renaming tests
Signed-off-by: Matthew Ballance <matt.ballance@gmail.com>
This commit is contained in:
parent
43bfd85dc0
commit
c749ff09b4
|
|
@ -1,300 +0,0 @@
|
|||
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
||||
//=============================================================================
|
||||
//
|
||||
// Code available from: https://verilator.org
|
||||
//
|
||||
// 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-FileCopyrightText: 2026-2026 by Wilson Snyder
|
||||
// SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
||||
//
|
||||
//=============================================================================
|
||||
///
|
||||
/// \file
|
||||
/// \brief Verilated functional coverage support header
|
||||
///
|
||||
/// This file provides runtime support for SystemVerilog functional coverage
|
||||
/// constructs (covergroups, coverpoints, bins, cross coverage).
|
||||
///
|
||||
//=============================================================================
|
||||
|
||||
#ifndef VERILATOR_VERILATED_FUNCCOV_H_
|
||||
#define VERILATOR_VERILATED_FUNCCOV_H_
|
||||
|
||||
#include "verilatedos.h"
|
||||
|
||||
#include "verilated.h"
|
||||
#include "verilated_cov.h"
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
//=============================================================================
|
||||
// VerilatedCoverBin - Represents a single bin in a coverpoint
|
||||
|
||||
class VerilatedCoverBin VL_NOT_FINAL {
|
||||
private:
|
||||
std::string m_name; // Bin name
|
||||
std::string m_rangeStr; // String representation of range (e.g., "0:15")
|
||||
uint32_t m_count = 0; // Hit count
|
||||
uint32_t* m_countp = nullptr; // Pointer to counter (for coverage registration)
|
||||
|
||||
public:
|
||||
VerilatedCoverBin(const std::string& name, const std::string& rangeStr)
|
||||
: m_name{name}
|
||||
, m_rangeStr{rangeStr}
|
||||
, m_countp{&m_count} {}
|
||||
|
||||
virtual ~VerilatedCoverBin() = default;
|
||||
|
||||
// Accessors
|
||||
const std::string& name() const { return m_name; }
|
||||
const std::string& rangeStr() const { return m_rangeStr; }
|
||||
uint32_t count() const { return m_count; }
|
||||
uint32_t* countp() { return m_countp; }
|
||||
|
||||
// Increment hit count
|
||||
void hit() { ++m_count; }
|
||||
|
||||
// Check if value matches this bin (to be overridden by specific bin types)
|
||||
virtual bool matches(uint64_t value) const { return false; }
|
||||
};
|
||||
|
||||
//=============================================================================
|
||||
// VerilatedCoverRangeBin - Bin that matches a value range
|
||||
|
||||
class VerilatedCoverRangeBin final : public VerilatedCoverBin {
|
||||
private:
|
||||
uint64_t m_min;
|
||||
uint64_t m_max;
|
||||
|
||||
public:
|
||||
VerilatedCoverRangeBin(const std::string& name, uint64_t min, uint64_t max)
|
||||
: VerilatedCoverBin(name, std::to_string(min) + ":" + std::to_string(max))
|
||||
, m_min{min}
|
||||
, m_max{max} {}
|
||||
|
||||
bool matches(uint64_t value) const override { return value >= m_min && value <= m_max; }
|
||||
};
|
||||
|
||||
//=============================================================================
|
||||
// VerilatedCoverpoint - Represents a coverage point
|
||||
|
||||
class VerilatedCoverpoint VL_NOT_FINAL {
|
||||
private:
|
||||
std::string m_name; // Coverpoint name
|
||||
std::vector<VerilatedCoverBin*> m_bins; // Bins in this coverpoint
|
||||
bool m_enabled = true; // Coverage collection enabled
|
||||
|
||||
public:
|
||||
explicit VerilatedCoverpoint(const std::string& name)
|
||||
: m_name{name} {}
|
||||
|
||||
~VerilatedCoverpoint() {
|
||||
for (auto* bin : m_bins) delete bin;
|
||||
}
|
||||
|
||||
// Accessors
|
||||
const std::string& name() const { return m_name; }
|
||||
const std::vector<VerilatedCoverBin*>& bins() const { return m_bins; }
|
||||
bool enabled() const { return m_enabled; }
|
||||
void enabled(bool flag) { m_enabled = flag; }
|
||||
|
||||
// Add a bin to this coverpoint
|
||||
void addBin(VerilatedCoverBin* binp) { m_bins.push_back(binp); }
|
||||
|
||||
// Sample a value and update bin counts
|
||||
void sample(uint64_t value) {
|
||||
if (!m_enabled) return;
|
||||
for (auto* bin : m_bins) {
|
||||
if (bin->matches(value)) { bin->hit(); }
|
||||
}
|
||||
}
|
||||
|
||||
// Compute coverage percentage
|
||||
double getCoverage(uint32_t atLeast = 1) const {
|
||||
if (m_bins.empty()) return 100.0;
|
||||
int coveredBins = 0;
|
||||
for (const auto* bin : m_bins) {
|
||||
if (bin->count() >= atLeast) ++coveredBins;
|
||||
}
|
||||
return (100.0 * coveredBins) / m_bins.size();
|
||||
}
|
||||
|
||||
// Register bins with coverage infrastructure
|
||||
void registerCoverage(VerilatedCovContext* contextp, const std::string& hier,
|
||||
const std::string& cgName) {
|
||||
for (auto* bin : m_bins) {
|
||||
const std::string fullName = cgName + "." + m_name;
|
||||
const std::string& binName = bin->name();
|
||||
const std::string& binRange = bin->rangeStr();
|
||||
VL_COVER_INSERT(contextp, hier.c_str(), bin->countp(), "type", "coverpoint", "name",
|
||||
fullName.c_str(), "bin", binName.c_str(), "range", binRange.c_str());
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
//=============================================================================
|
||||
// VerilatedCoverCross - Represents cross coverage between coverpoints
|
||||
|
||||
class VerilatedCoverCross VL_NOT_FINAL {
|
||||
private:
|
||||
std::string m_name; // Cross name
|
||||
std::vector<VerilatedCoverpoint*> m_coverpoints; // Coverpoints being crossed
|
||||
std::map<std::string, uint32_t> m_crossBins; // Sparse storage: "<bin1,bin2>" -> count
|
||||
bool m_enabled = true;
|
||||
|
||||
public:
|
||||
explicit VerilatedCoverCross(const std::string& name)
|
||||
: m_name{name} {}
|
||||
|
||||
// Accessors
|
||||
const std::string& name() const { return m_name; }
|
||||
bool enabled() const { return m_enabled; }
|
||||
void enabled(bool flag) { m_enabled = flag; }
|
||||
|
||||
// Add a coverpoint to cross
|
||||
void addCoverpoint(VerilatedCoverpoint* cpp) { m_coverpoints.push_back(cpp); }
|
||||
|
||||
// Sample cross product (to be called after coverpoints are sampled)
|
||||
void sample(const std::vector<uint64_t>& values) {
|
||||
if (!m_enabled || values.size() != m_coverpoints.size()) return;
|
||||
|
||||
// Build cross bin key from matched bins
|
||||
std::string key = "<";
|
||||
bool first = true;
|
||||
for (size_t i = 0; i < values.size(); ++i) {
|
||||
// Find which bin matched for this coverpoint
|
||||
for (const auto* bin : m_coverpoints[i]->bins()) {
|
||||
if (bin->matches(values[i])) {
|
||||
if (!first) key += ",";
|
||||
key += bin->name();
|
||||
first = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
key += ">";
|
||||
|
||||
// Increment cross bin count
|
||||
m_crossBins[key]++;
|
||||
}
|
||||
|
||||
// Compute coverage percentage
|
||||
double getCoverage(uint32_t atLeast = 1) const {
|
||||
if (m_crossBins.empty()) return 100.0;
|
||||
int coveredBins = 0;
|
||||
for (const auto& pair : m_crossBins) {
|
||||
if (pair.second >= atLeast) ++coveredBins;
|
||||
}
|
||||
// Total possible bins is product of coverpoint bin counts
|
||||
size_t totalBins = 1;
|
||||
for (const auto* cp : m_coverpoints) { totalBins *= cp->bins().size(); }
|
||||
return (100.0 * coveredBins) / totalBins;
|
||||
}
|
||||
|
||||
// Register cross bins with coverage infrastructure
|
||||
void registerCoverage(VerilatedCovContext* contextp, const std::string& hier,
|
||||
const std::string& cgName) {
|
||||
// Cross bins are registered dynamically as they're hit
|
||||
// For now, we'll register them all upfront (can be optimized later)
|
||||
std::string fullName = cgName + "." + m_name;
|
||||
for (const auto& pair : m_crossBins) {
|
||||
// Note: We need a persistent counter, so we use the map value's address
|
||||
// This is safe because std::map doesn't reallocate on insert
|
||||
const std::string& binName = pair.first;
|
||||
VL_COVER_INSERT(contextp, hier.c_str(), const_cast<uint32_t*>(&pair.second), "type",
|
||||
"cross", "name", fullName.c_str(), "bin", binName.c_str());
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
//=============================================================================
|
||||
// VerilatedCovergroup - Represents a covergroup instance
|
||||
|
||||
class VerilatedCovergroup VL_NOT_FINAL {
|
||||
private:
|
||||
std::string m_name; // Covergroup type name
|
||||
std::string m_instName; // Instance name
|
||||
std::vector<VerilatedCoverpoint*> m_coverpoints;
|
||||
std::vector<VerilatedCoverCross*> m_crosses;
|
||||
bool m_enabled = true;
|
||||
|
||||
// Coverage options
|
||||
uint32_t m_weight = 1;
|
||||
uint32_t m_goal = 100;
|
||||
uint32_t m_atLeast = 1;
|
||||
std::string m_comment;
|
||||
|
||||
public:
|
||||
explicit VerilatedCovergroup(const std::string& name)
|
||||
: m_name{name}
|
||||
, m_instName{name} {}
|
||||
|
||||
~VerilatedCovergroup() {
|
||||
for (auto* cp : m_coverpoints) delete cp;
|
||||
for (auto* cross : m_crosses) delete cross;
|
||||
}
|
||||
|
||||
// Accessors
|
||||
const std::string& name() const { return m_name; }
|
||||
const std::string& instName() const { return m_instName; }
|
||||
void instName(const std::string& name) { m_instName = name; }
|
||||
bool enabled() const { return m_enabled; }
|
||||
|
||||
// Options
|
||||
void weight(uint32_t w) { m_weight = w; }
|
||||
void goal(uint32_t g) { m_goal = g; }
|
||||
void atLeast(uint32_t a) { m_atLeast = a; }
|
||||
void comment(const std::string& c) { m_comment = c; }
|
||||
|
||||
// Add components
|
||||
void addCoverpoint(VerilatedCoverpoint* cpp) { m_coverpoints.push_back(cpp); }
|
||||
void addCross(VerilatedCoverCross* cross) { m_crosses.push_back(cross); }
|
||||
|
||||
// Predefined methods per IEEE 1800-2023 Section 19.9
|
||||
void sample() {
|
||||
if (!m_enabled) return;
|
||||
// Sampling is done by generated code calling coverpoint sample() methods
|
||||
}
|
||||
|
||||
void start() { m_enabled = true; }
|
||||
void stop() { m_enabled = false; }
|
||||
|
||||
void set_inst_name(const std::string& name) { m_instName = name; }
|
||||
|
||||
// Get type coverage (0-100)
|
||||
double get_coverage() const {
|
||||
if (m_coverpoints.empty()) return 100.0;
|
||||
double totalCov = 0.0;
|
||||
uint32_t totalWeight = 0;
|
||||
for (const auto* cp : m_coverpoints) {
|
||||
totalCov += cp->getCoverage(m_atLeast) * m_weight;
|
||||
totalWeight += m_weight;
|
||||
}
|
||||
for (const auto* cross : m_crosses) {
|
||||
totalCov += cross->getCoverage(m_atLeast) * m_weight;
|
||||
totalWeight += m_weight;
|
||||
}
|
||||
return totalWeight > 0 ? totalCov / totalWeight : 100.0;
|
||||
}
|
||||
|
||||
// Get instance coverage (same as type coverage for now)
|
||||
double get_inst_coverage() const { return get_coverage(); }
|
||||
|
||||
// Register all coverage points with coverage infrastructure
|
||||
void registerCoverage(VerilatedCovContext* contextp, const std::string& hier) {
|
||||
// Register covergroup metadata
|
||||
// (Will be extended when we add metadata output)
|
||||
|
||||
// Register all coverpoints
|
||||
for (auto* cp : m_coverpoints) { cp->registerCoverage(contextp, hier, m_name); }
|
||||
|
||||
// Register all crosses
|
||||
for (auto* cross : m_crosses) { cross->registerCoverage(contextp, hier, m_name); }
|
||||
}
|
||||
};
|
||||
|
||||
#endif // guard
|
||||
|
|
@ -70,8 +70,7 @@ set(HEADERS
|
|||
V3Control.h
|
||||
V3Coverage.h
|
||||
V3CoverageJoin.h
|
||||
V3CoverageFunctional.h
|
||||
V3AstNodeFuncCov.h
|
||||
V3Covergroup.h
|
||||
V3Dead.h
|
||||
V3DebugBisect.h
|
||||
V3Delayed.h
|
||||
|
|
@ -239,8 +238,7 @@ set(COMMON_SOURCES
|
|||
V3Const__gen.cpp
|
||||
V3Coverage.cpp
|
||||
V3CoverageJoin.cpp
|
||||
V3CoverageFunctional.cpp
|
||||
V3AstNodeFuncCov.cpp
|
||||
V3Covergroup.cpp
|
||||
V3Dead.cpp
|
||||
V3Delayed.cpp
|
||||
V3Depth.cpp
|
||||
|
|
@ -405,7 +403,7 @@ add_custom_command(
|
|||
ARGS
|
||||
${ASTGEN} -I "${srcdir}" --astdef V3AstNodeDType.h --astdef
|
||||
V3AstNodeExpr.h --astdef V3AstNodeOther.h --astdef V3AstNodeStmt.h
|
||||
--astdef V3AstNodeFuncCov.h --dfgdef V3DfgVertices.h --classes
|
||||
--dfgdef V3DfgVertices.h --classes
|
||||
)
|
||||
list(
|
||||
APPEND GENERATED_FILES
|
||||
|
|
@ -517,7 +515,7 @@ foreach(astgen_name ${ASTGENERATED_NAMES})
|
|||
ARGS
|
||||
${ASTGEN} -I "${srcdir}" --astdef V3AstNodeDType.h --astdef
|
||||
V3AstNodeExpr.h --astdef V3AstNodeOther.h --astdef V3AstNodeStmt.h
|
||||
--astdef V3AstNodeFuncCov.h --dfgdef V3DfgVertices.h
|
||||
--dfgdef V3DfgVertices.h
|
||||
${astgen_name}.cpp
|
||||
)
|
||||
list(APPEND GENERATED_FILES ${astgen_name}__gen.cpp)
|
||||
|
|
|
|||
|
|
@ -207,7 +207,6 @@ RAW_OBJS = \
|
|||
|
||||
RAW_OBJS_PCH_ASTMT = \
|
||||
V3Ast.o \
|
||||
V3AstNodeFuncCov.o \
|
||||
V3AstNodes.o \
|
||||
V3Broken.o \
|
||||
V3Control.o \
|
||||
|
|
@ -250,7 +249,7 @@ RAW_OBJS_PCH_ASTNOMT = \
|
|||
V3Combine.o \
|
||||
V3Common.o \
|
||||
V3Coverage.o \
|
||||
V3CoverageFunctional.o \
|
||||
V3Covergroup.o \
|
||||
V3CoverageJoin.o \
|
||||
V3Dead.o \
|
||||
V3Delayed.o \
|
||||
|
|
@ -362,7 +361,6 @@ NON_STANDALONE_HEADERS = \
|
|||
V3AstInlines.h \
|
||||
V3AstNodeDType.h \
|
||||
V3AstNodeExpr.h \
|
||||
V3AstNodeFuncCov.h \
|
||||
V3AstNodeOther.h \
|
||||
V3AstNodeStmt.h \
|
||||
V3DebugBisect.h \
|
||||
|
|
@ -373,7 +371,6 @@ NON_STANDALONE_HEADERS = \
|
|||
AST_DEFS := \
|
||||
V3AstNodeDType.h \
|
||||
V3AstNodeExpr.h \
|
||||
V3AstNodeFuncCov.h \
|
||||
V3AstNodeOther.h \
|
||||
V3AstNodeStmt.h \
|
||||
|
||||
|
|
|
|||
|
|
@ -634,7 +634,7 @@ class CovergroupSamplingVisitor final : public VNVisitor {
|
|||
|
||||
// Helper to get the clocking event from a covergroup class
|
||||
AstSenTree* getCovergroupEvent(AstClass* classp) {
|
||||
// The AstCovergroup (holding the SenTree) was left in membersp by V3CoverageFunctional
|
||||
// The AstCovergroup (holding the SenTree) was left in membersp by V3Covergroup
|
||||
for (AstNode* memberp = classp->membersp(); memberp; memberp = memberp->nextp()) {
|
||||
if (AstCovergroup* const cgp = VN_CAST(memberp, Covergroup)) {
|
||||
if (cgp->eventp()) return cgp->eventp();
|
||||
|
|
|
|||
|
|
@ -1583,7 +1583,6 @@ AstNode* VNVisitor::iterateSubtreeReturnEdits(AstNode* nodep) {
|
|||
#include "V3AstNodeOther.h"
|
||||
#include "V3AstNodeExpr.h"
|
||||
#include "V3AstNodeStmt.h"
|
||||
#include "V3AstNodeFuncCov.h"
|
||||
// clang-format on
|
||||
|
||||
// Inline function definitions need to go last
|
||||
|
|
|
|||
|
|
@ -1,155 +0,0 @@
|
|||
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
||||
//*************************************************************************
|
||||
// DESCRIPTION: Verilator: AstNode implementation for functional coverage nodes
|
||||
//
|
||||
// Code available from: https://verilator.org
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// 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-FileCopyrightText: 2026-2026 by Wilson Snyder
|
||||
// SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
||||
//
|
||||
//*************************************************************************
|
||||
|
||||
#include "V3PchAstMT.h"
|
||||
|
||||
#include "V3AstNodeFuncCov.h"
|
||||
|
||||
//######################################################################
|
||||
// Dump methods
|
||||
|
||||
void AstCovergroup::dump(std::ostream& str) const {
|
||||
this->AstNode::dump(str);
|
||||
str << " " << m_name;
|
||||
if (m_isClass) str << " [class]";
|
||||
}
|
||||
|
||||
void AstCovergroup::dumpJson(std::ostream& str) const {
|
||||
this->AstNode::dumpJson(str);
|
||||
str << ", \"name\": " << VString::quotePercent(name());
|
||||
if (m_isClass) str << ", \"isClass\": true";
|
||||
}
|
||||
|
||||
void AstCoverpoint::dump(std::ostream& str) const { this->AstNodeFuncCovItem::dump(str); }
|
||||
|
||||
void AstCoverpoint::dumpJson(std::ostream& str) const { this->AstNodeFuncCovItem::dumpJson(str); }
|
||||
|
||||
void AstCoverBin::dump(std::ostream& str) const {
|
||||
this->AstNode::dump(str);
|
||||
str << " " << m_name << " ";
|
||||
switch (m_type) {
|
||||
case VCoverBinsType::USER: str << "user"; break;
|
||||
case VCoverBinsType::ARRAY: str << "array"; break;
|
||||
case VCoverBinsType::AUTO: str << "auto"; break;
|
||||
case VCoverBinsType::BINS_IGNORE: str << "ignore"; break;
|
||||
case VCoverBinsType::BINS_ILLEGAL: str << "illegal"; break;
|
||||
case VCoverBinsType::DEFAULT: str << "default"; break;
|
||||
case VCoverBinsType::BINS_WILDCARD: str << "wildcard"; break;
|
||||
case VCoverBinsType::TRANSITION: str << "transition"; break;
|
||||
}
|
||||
if (m_isArray) str << "[]";
|
||||
}
|
||||
|
||||
void AstCoverBin::dumpJson(std::ostream& str) const {
|
||||
this->AstNode::dumpJson(str);
|
||||
str << ", \"name\": " << VString::quotePercent(m_name);
|
||||
str << ", \"binsType\": ";
|
||||
switch (m_type) {
|
||||
case VCoverBinsType::USER: str << "\"user\""; break;
|
||||
case VCoverBinsType::ARRAY: str << "\"array\""; break;
|
||||
case VCoverBinsType::AUTO: str << "\"auto\""; break;
|
||||
case VCoverBinsType::BINS_IGNORE: str << "\"ignore\""; break;
|
||||
case VCoverBinsType::BINS_ILLEGAL: str << "\"illegal\""; break;
|
||||
case VCoverBinsType::DEFAULT: str << "\"default\""; break;
|
||||
case VCoverBinsType::BINS_WILDCARD: str << "\"wildcard\""; break;
|
||||
case VCoverBinsType::TRANSITION: str << "\"transition\""; break;
|
||||
}
|
||||
if (m_isArray) str << ", \"isArray\": true";
|
||||
}
|
||||
|
||||
void AstCoverTransItem::dump(std::ostream& str) const {
|
||||
this->AstNode::dump(str);
|
||||
switch (m_repType) {
|
||||
case VTransRepType::NONE: break;
|
||||
case VTransRepType::CONSEC: str << " [*]"; break;
|
||||
case VTransRepType::GOTO: str << " [->]"; break;
|
||||
case VTransRepType::NONCONS: str << " [=]"; break;
|
||||
}
|
||||
}
|
||||
|
||||
void AstCoverTransItem::dumpJson(std::ostream& str) const {
|
||||
this->AstNode::dumpJson(str);
|
||||
if (m_repType != VTransRepType::NONE) {
|
||||
str << ", \"repType\": ";
|
||||
switch (m_repType) {
|
||||
case VTransRepType::NONE: break;
|
||||
case VTransRepType::CONSEC: str << "\"consec\""; break;
|
||||
case VTransRepType::GOTO: str << "\"goto\""; break;
|
||||
case VTransRepType::NONCONS: str << "\"noncons\""; break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AstCoverTransSet::dump(std::ostream& str) const {
|
||||
this->AstNode::dump(str);
|
||||
str << " trans_set";
|
||||
}
|
||||
|
||||
void AstCoverTransSet::dumpJson(std::ostream& str) const { this->AstNode::dumpJson(str); }
|
||||
|
||||
void AstCoverCross::dump(std::ostream& str) const { this->AstNodeFuncCovItem::dump(str); }
|
||||
|
||||
void AstCoverCross::dumpJson(std::ostream& str) const { this->AstNodeFuncCovItem::dumpJson(str); }
|
||||
|
||||
void AstCoverCrossBins::dump(std::ostream& str) const {
|
||||
this->AstNode::dump(str);
|
||||
str << " " << m_name;
|
||||
}
|
||||
|
||||
void AstCoverCrossBins::dumpJson(std::ostream& str) const {
|
||||
this->AstNode::dumpJson(str);
|
||||
str << ", \"name\": " << VString::quotePercent(m_name);
|
||||
}
|
||||
|
||||
void AstCoverOption::dump(std::ostream& str) const {
|
||||
this->AstNode::dump(str);
|
||||
str << " ";
|
||||
switch (m_type) {
|
||||
case VCoverOptionType::WEIGHT: str << "weight"; break;
|
||||
case VCoverOptionType::GOAL: str << "goal"; break;
|
||||
case VCoverOptionType::AT_LEAST: str << "at_least"; break;
|
||||
case VCoverOptionType::AUTO_BIN_MAX: str << "auto_bin_max"; break;
|
||||
case VCoverOptionType::PER_INSTANCE: str << "per_instance"; break;
|
||||
case VCoverOptionType::COMMENT: str << "comment"; break;
|
||||
}
|
||||
}
|
||||
|
||||
void AstCoverOption::dumpJson(std::ostream& str) const {
|
||||
this->AstNode::dumpJson(str);
|
||||
str << ", \"optionType\": ";
|
||||
switch (m_type) {
|
||||
case VCoverOptionType::WEIGHT: str << "\"weight\""; break;
|
||||
case VCoverOptionType::GOAL: str << "\"goal\""; break;
|
||||
case VCoverOptionType::AT_LEAST: str << "\"at_least\""; break;
|
||||
case VCoverOptionType::AUTO_BIN_MAX: str << "\"auto_bin_max\""; break;
|
||||
case VCoverOptionType::PER_INSTANCE: str << "\"per_instance\""; break;
|
||||
case VCoverOptionType::COMMENT: str << "\"comment\""; break;
|
||||
}
|
||||
}
|
||||
|
||||
void AstCoverpointRef::dump(std::ostream& str) const {
|
||||
this->AstNode::dump(str);
|
||||
str << " " << m_name;
|
||||
}
|
||||
|
||||
void AstCoverpointRef::dumpJson(std::ostream& str) const {
|
||||
this->AstNode::dumpJson(str);
|
||||
str << ", \"name\": " << VString::quotePercent(m_name);
|
||||
}
|
||||
|
||||
void AstCoverSelectExpr::dump(std::ostream& str) const { this->AstNode::dump(str); }
|
||||
|
||||
void AstCoverSelectExpr::dumpJson(std::ostream& str) const { this->AstNode::dumpJson(str); }
|
||||
|
|
@ -1,289 +0,0 @@
|
|||
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
||||
//*************************************************************************
|
||||
// DESCRIPTION: Verilator: AstNode sub-types for functional coverage
|
||||
//
|
||||
// Code available from: https://verilator.org
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// 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-FileCopyrightText: 2026-2026 by Wilson Snyder
|
||||
// SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// This file contains AST nodes for SystemVerilog functional coverage
|
||||
// (IEEE 1800-2023 Section 19)
|
||||
//
|
||||
//*************************************************************************
|
||||
|
||||
#ifndef VERILATOR_V3ASTNODEFUNCCOV_H_
|
||||
#define VERILATOR_V3ASTNODEFUNCCOV_H_
|
||||
|
||||
#ifndef VERILATOR_V3AST_H_
|
||||
#error "Use V3Ast.h as the include"
|
||||
#include "V3Ast.h"
|
||||
#define VL_NOT_FINAL
|
||||
#endif
|
||||
|
||||
//######################################################################
|
||||
// Enumerations
|
||||
|
||||
enum class VCoverBinsType : uint8_t {
|
||||
USER,
|
||||
ARRAY,
|
||||
AUTO,
|
||||
BINS_IGNORE, // Renamed to avoid Windows macro conflict
|
||||
BINS_ILLEGAL, // Renamed to avoid Windows macro conflict
|
||||
DEFAULT,
|
||||
BINS_WILDCARD, // Renamed to avoid Windows macro conflict
|
||||
TRANSITION
|
||||
};
|
||||
|
||||
enum class VCoverOptionType : uint8_t {
|
||||
WEIGHT,
|
||||
GOAL,
|
||||
AT_LEAST,
|
||||
AUTO_BIN_MAX,
|
||||
PER_INSTANCE,
|
||||
COMMENT
|
||||
};
|
||||
|
||||
enum class VTransRepType : uint8_t {
|
||||
NONE, // No repetition
|
||||
CONSEC, // Consecutive repetition [*]
|
||||
GOTO, // Goto repetition [->]
|
||||
NONCONS // Nonconsecutive repetition [=]
|
||||
};
|
||||
|
||||
//######################################################################
|
||||
// Base classes
|
||||
|
||||
class AstNodeFuncCovItem VL_NOT_FINAL : public AstNode {
|
||||
protected:
|
||||
string m_name;
|
||||
|
||||
public:
|
||||
AstNodeFuncCovItem(VNType t, FileLine* fl, const string& name)
|
||||
: AstNode{t, fl}
|
||||
, m_name{name} {}
|
||||
ASTGEN_MEMBERS_AstNodeFuncCovItem;
|
||||
string name() const override VL_MT_STABLE { return m_name; }
|
||||
void name(const string& flag) override { m_name = flag; }
|
||||
bool maybePointedTo() const override { return true; }
|
||||
};
|
||||
|
||||
//######################################################################
|
||||
// Concrete nodes - ORDER MATTERS FOR ASTGEN!
|
||||
// Must be in order: CoverBin, CoverCrossBins, CoverOption, CoverSelectExpr,
|
||||
// CoverTransItem, CoverTransSet, Covergroup, CoverpointRef, CoverCross,
|
||||
// Coverpoint
|
||||
|
||||
// Forward declarations for types used in constructors
|
||||
class AstCoverTransSet;
|
||||
class AstCoverSelectExpr;
|
||||
|
||||
class AstCoverBin final : public AstNode {
|
||||
// @astgen op1 := rangesp : List[AstNode]
|
||||
// @astgen op2 := iffp : Optional[AstNodeExpr]
|
||||
// @astgen op3 := arraySizep : Optional[AstNodeExpr]
|
||||
// @astgen op4 := transp : List[AstCoverTransSet]
|
||||
string m_name;
|
||||
VCoverBinsType m_type;
|
||||
bool m_isArray = false;
|
||||
|
||||
public:
|
||||
AstCoverBin(FileLine* fl, const string& name, AstNode* rangesp, bool isIgnore, bool isIllegal,
|
||||
bool isWildcard = false)
|
||||
: ASTGEN_SUPER_CoverBin(fl)
|
||||
, m_name{name}
|
||||
, m_type{isWildcard ? VCoverBinsType::BINS_WILDCARD
|
||||
: (isIllegal ? VCoverBinsType::BINS_ILLEGAL
|
||||
: (isIgnore ? VCoverBinsType::BINS_IGNORE
|
||||
: VCoverBinsType::USER))} {
|
||||
if (rangesp) addRangesp(rangesp);
|
||||
}
|
||||
// Constructor for automatic bins
|
||||
AstCoverBin(FileLine* fl, const string& name, AstNodeExpr* arraySizep)
|
||||
: ASTGEN_SUPER_CoverBin(fl)
|
||||
, m_name{name}
|
||||
, m_type{VCoverBinsType::AUTO}
|
||||
, m_isArray{true} {
|
||||
this->arraySizep(arraySizep);
|
||||
}
|
||||
// Constructor for default bins (catch-all)
|
||||
AstCoverBin(FileLine* fl, const string& name, VCoverBinsType type)
|
||||
: ASTGEN_SUPER_CoverBin(fl)
|
||||
, m_name{name}
|
||||
, m_type{type} {
|
||||
// DEFAULT bins have no ranges - they catch everything not in other bins
|
||||
}
|
||||
// Constructor for transition bins
|
||||
AstCoverBin(FileLine* fl, const string& name, AstCoverTransSet* transp, bool isIgnore,
|
||||
bool isIllegal, bool isArrayBin = false)
|
||||
: ASTGEN_SUPER_CoverBin(fl)
|
||||
, m_name{name}
|
||||
, m_type{isIllegal ? VCoverBinsType::BINS_ILLEGAL
|
||||
: (isIgnore ? VCoverBinsType::BINS_IGNORE : VCoverBinsType::TRANSITION)}
|
||||
, m_isArray{isArrayBin} {
|
||||
if (transp) addTransp(transp);
|
||||
}
|
||||
ASTGEN_MEMBERS_AstCoverBin;
|
||||
void dump(std::ostream& str) const override;
|
||||
void dumpJson(std::ostream& str) const override;
|
||||
string name() const override VL_MT_STABLE { return m_name; }
|
||||
VCoverBinsType binsType() const { return m_type; }
|
||||
bool isArray() const { return m_isArray; }
|
||||
void isArray(bool flag) { m_isArray = flag; }
|
||||
};
|
||||
|
||||
class AstCoverCrossBins final : public AstNode {
|
||||
// @astgen op1 := selectp : Optional[AstCoverSelectExpr]
|
||||
string m_name;
|
||||
|
||||
public:
|
||||
AstCoverCrossBins(FileLine* fl, const string& name, AstCoverSelectExpr* selectp)
|
||||
: ASTGEN_SUPER_CoverCrossBins(fl)
|
||||
, m_name{name} {
|
||||
this->selectp(selectp);
|
||||
}
|
||||
ASTGEN_MEMBERS_AstCoverCrossBins;
|
||||
void dump(std::ostream& str) const override;
|
||||
void dumpJson(std::ostream& str) const override;
|
||||
string name() const override VL_MT_STABLE { return m_name; }
|
||||
};
|
||||
|
||||
class AstCoverOption final : public AstNode {
|
||||
// @astgen op1 := valuep : AstNodeExpr
|
||||
VCoverOptionType m_type;
|
||||
|
||||
public:
|
||||
AstCoverOption(FileLine* fl, VCoverOptionType type, AstNodeExpr* valuep)
|
||||
: ASTGEN_SUPER_CoverOption(fl)
|
||||
, m_type{type} {
|
||||
this->valuep(valuep);
|
||||
}
|
||||
ASTGEN_MEMBERS_AstCoverOption;
|
||||
void dump(std::ostream& str) const override;
|
||||
void dumpJson(std::ostream& str) const override;
|
||||
VCoverOptionType optionType() const { return m_type; }
|
||||
};
|
||||
|
||||
class AstCoverSelectExpr final : public AstNode {
|
||||
// @astgen op1 := exprp : AstNodeExpr
|
||||
public:
|
||||
AstCoverSelectExpr(FileLine* fl, AstNodeExpr* exprp)
|
||||
: ASTGEN_SUPER_CoverSelectExpr(fl) {
|
||||
this->exprp(exprp);
|
||||
}
|
||||
ASTGEN_MEMBERS_AstCoverSelectExpr;
|
||||
void dump(std::ostream& str) const override;
|
||||
void dumpJson(std::ostream& str) const override;
|
||||
};
|
||||
|
||||
// Represents a single transition item: value or value[*N] or value[->N] or value[=N]
|
||||
class AstCoverTransItem final : public AstNode {
|
||||
// @astgen op1 := valuesp : List[AstNode] // Range list (values or ranges)
|
||||
// @astgen op2 := repMinp : Optional[AstNodeExpr] // Repetition min count (for [*], [->], [=])
|
||||
// @astgen op3 := repMaxp : Optional[AstNodeExpr] // Repetition max count (for ranges)
|
||||
VTransRepType m_repType;
|
||||
|
||||
public:
|
||||
AstCoverTransItem(FileLine* fl, AstNode* valuesp, VTransRepType repType = VTransRepType::NONE)
|
||||
: ASTGEN_SUPER_CoverTransItem(fl)
|
||||
, m_repType{repType} {
|
||||
if (valuesp) addValuesp(valuesp);
|
||||
}
|
||||
ASTGEN_MEMBERS_AstCoverTransItem;
|
||||
void dump(std::ostream& str) const override;
|
||||
void dumpJson(std::ostream& str) const override;
|
||||
VTransRepType repType() const { return m_repType; }
|
||||
};
|
||||
|
||||
// Represents a transition set: value1 => value2 => value3
|
||||
class AstCoverTransSet final : public AstNode {
|
||||
// @astgen op1 := itemsp : List[AstCoverTransItem]
|
||||
public:
|
||||
AstCoverTransSet(FileLine* fl, AstCoverTransItem* itemsp)
|
||||
: ASTGEN_SUPER_CoverTransSet(fl) {
|
||||
if (itemsp) addItemsp(itemsp);
|
||||
}
|
||||
ASTGEN_MEMBERS_AstCoverTransSet;
|
||||
void dump(std::ostream& str) const override;
|
||||
void dumpJson(std::ostream& str) const override;
|
||||
};
|
||||
|
||||
class AstCovergroup final : public AstNode {
|
||||
// @astgen op1 := argsp : List[AstVar]
|
||||
// @astgen op2 := membersp : List[AstNode]
|
||||
// @astgen op3 := eventp : Optional[AstSenTree]
|
||||
string m_name;
|
||||
bool m_isClass = false;
|
||||
|
||||
public:
|
||||
AstCovergroup(FileLine* fl, const string& name, AstNode* membersp, AstSenTree* eventp)
|
||||
: ASTGEN_SUPER_Covergroup(fl)
|
||||
, m_name{name} {
|
||||
if (membersp) addMembersp(membersp);
|
||||
this->eventp(eventp);
|
||||
}
|
||||
ASTGEN_MEMBERS_AstCovergroup;
|
||||
void dump(std::ostream& str) const override;
|
||||
void dumpJson(std::ostream& str) const override;
|
||||
string name() const override VL_MT_STABLE { return m_name; }
|
||||
void name(const string& name) override { m_name = name; }
|
||||
bool isClass() const { return m_isClass; }
|
||||
void isClass(bool flag) { m_isClass = flag; }
|
||||
bool maybePointedTo() const override { return true; }
|
||||
};
|
||||
|
||||
class AstCoverpointRef final : public AstNode {
|
||||
// @astgen ptr := m_coverpointp : Optional[AstCoverpoint]
|
||||
string m_name;
|
||||
|
||||
public:
|
||||
AstCoverpointRef(FileLine* fl, const string& name)
|
||||
: ASTGEN_SUPER_CoverpointRef(fl)
|
||||
, m_name{name} {}
|
||||
ASTGEN_MEMBERS_AstCoverpointRef;
|
||||
void dump(std::ostream& str) const override;
|
||||
void dumpJson(std::ostream& str) const override;
|
||||
string name() const override VL_MT_STABLE { return m_name; }
|
||||
AstCoverpoint* coverpointp() const { return m_coverpointp; }
|
||||
void coverpointp(AstCoverpoint* nodep) { m_coverpointp = nodep; }
|
||||
};
|
||||
|
||||
class AstCoverCross final : public AstNodeFuncCovItem {
|
||||
// @astgen op1 := itemsp : List[AstCoverpointRef]
|
||||
// @astgen op2 := binsp : List[AstCoverCrossBins]
|
||||
// @astgen op3 := optionsp : List[AstCoverOption]
|
||||
public:
|
||||
AstCoverCross(FileLine* fl, const string& name, AstCoverpointRef* itemsp)
|
||||
: ASTGEN_SUPER_CoverCross(fl, name) {
|
||||
if (itemsp) addItemsp(itemsp);
|
||||
}
|
||||
ASTGEN_MEMBERS_AstCoverCross;
|
||||
void dump(std::ostream& str) const override;
|
||||
void dumpJson(std::ostream& str) const override;
|
||||
};
|
||||
|
||||
class AstCoverpoint final : public AstNodeFuncCovItem {
|
||||
// @astgen op1 := exprp : AstNodeExpr
|
||||
// @astgen op2 := binsp : List[AstCoverBin]
|
||||
// @astgen op3 := iffp : Optional[AstNodeExpr]
|
||||
// @astgen op4 := optionsp : List[AstCoverOption]
|
||||
public:
|
||||
AstCoverpoint(FileLine* fl, const string& name, AstNodeExpr* exprp)
|
||||
: ASTGEN_SUPER_Coverpoint(fl, name) {
|
||||
this->exprp(exprp);
|
||||
}
|
||||
ASTGEN_MEMBERS_AstCoverpoint;
|
||||
void dump(std::ostream& str) const override;
|
||||
void dumpJson(std::ostream& str) const override;
|
||||
};
|
||||
|
||||
//######################################################################
|
||||
|
||||
#endif // Guard
|
||||
|
|
@ -253,6 +253,20 @@ public:
|
|||
string name() const override VL_MT_STABLE { return m_name; }
|
||||
bool sameNode(const AstNode* /*samep*/) const override { return true; }
|
||||
};
|
||||
class AstNodeFuncCovItem VL_NOT_FINAL : public AstNode {
|
||||
// Base class for functional coverage items (coverpoints, crosses)
|
||||
protected:
|
||||
string m_name;
|
||||
|
||||
public:
|
||||
AstNodeFuncCovItem(VNType t, FileLine* fl, const string& name)
|
||||
: AstNode{t, fl}
|
||||
, m_name{name} {}
|
||||
ASTGEN_MEMBERS_AstNodeFuncCovItem;
|
||||
string name() const override VL_MT_STABLE { return m_name; }
|
||||
void name(const string& flag) override { m_name = flag; }
|
||||
bool maybePointedTo() const override { return true; }
|
||||
};
|
||||
class AstNodeGen VL_NOT_FINAL : public AstNode {
|
||||
// Generate construct
|
||||
public:
|
||||
|
|
@ -1024,6 +1038,198 @@ public:
|
|||
bool isPredictOptimizable() const override { return false; }
|
||||
bool sameNode(const AstNode* /*samep*/) const override { return true; }
|
||||
};
|
||||
|
||||
// Forward declarations for types used in constructors below
|
||||
class AstCoverTransSet;
|
||||
class AstCoverSelectExpr;
|
||||
|
||||
enum class VCoverBinsType : uint8_t {
|
||||
USER,
|
||||
ARRAY,
|
||||
AUTO,
|
||||
BINS_IGNORE, // Renamed to avoid Windows macro conflict
|
||||
BINS_ILLEGAL, // Renamed to avoid Windows macro conflict
|
||||
DEFAULT,
|
||||
BINS_WILDCARD, // Renamed to avoid Windows macro conflict
|
||||
TRANSITION
|
||||
};
|
||||
|
||||
enum class VCoverOptionType : uint8_t {
|
||||
WEIGHT,
|
||||
GOAL,
|
||||
AT_LEAST,
|
||||
AUTO_BIN_MAX,
|
||||
PER_INSTANCE,
|
||||
COMMENT
|
||||
};
|
||||
|
||||
enum class VTransRepType : uint8_t {
|
||||
NONE, // No repetition
|
||||
CONSEC, // Consecutive repetition [*]
|
||||
GOTO, // Goto repetition [->]
|
||||
NONCONS // Nonconsecutive repetition [=]
|
||||
};
|
||||
|
||||
class AstCoverBin final : public AstNode {
|
||||
// @astgen op1 := rangesp : List[AstNode]
|
||||
// @astgen op2 := iffp : Optional[AstNodeExpr]
|
||||
// @astgen op3 := arraySizep : Optional[AstNodeExpr]
|
||||
// @astgen op4 := transp : List[AstCoverTransSet]
|
||||
string m_name;
|
||||
VCoverBinsType m_type;
|
||||
bool m_isArray = false;
|
||||
|
||||
public:
|
||||
AstCoverBin(FileLine* fl, const string& name, AstNode* rangesp, bool isIgnore, bool isIllegal,
|
||||
bool isWildcard = false)
|
||||
: ASTGEN_SUPER_CoverBin(fl)
|
||||
, m_name{name}
|
||||
, m_type{isWildcard ? VCoverBinsType::BINS_WILDCARD
|
||||
: (isIllegal ? VCoverBinsType::BINS_ILLEGAL
|
||||
: (isIgnore ? VCoverBinsType::BINS_IGNORE
|
||||
: VCoverBinsType::USER))} {
|
||||
if (rangesp) addRangesp(rangesp);
|
||||
}
|
||||
// Constructor for automatic bins
|
||||
AstCoverBin(FileLine* fl, const string& name, AstNodeExpr* arraySizep)
|
||||
: ASTGEN_SUPER_CoverBin(fl)
|
||||
, m_name{name}
|
||||
, m_type{VCoverBinsType::AUTO}
|
||||
, m_isArray{true} {
|
||||
this->arraySizep(arraySizep);
|
||||
}
|
||||
// Constructor for default bins (catch-all)
|
||||
AstCoverBin(FileLine* fl, const string& name, VCoverBinsType type)
|
||||
: ASTGEN_SUPER_CoverBin(fl)
|
||||
, m_name{name}
|
||||
, m_type{type} {}
|
||||
// Constructor for transition bins
|
||||
AstCoverBin(FileLine* fl, const string& name, AstCoverTransSet* transp, bool isIgnore,
|
||||
bool isIllegal, bool isArrayBin = false)
|
||||
: ASTGEN_SUPER_CoverBin(fl)
|
||||
, m_name{name}
|
||||
, m_type{isIllegal ? VCoverBinsType::BINS_ILLEGAL
|
||||
: (isIgnore ? VCoverBinsType::BINS_IGNORE : VCoverBinsType::TRANSITION)}
|
||||
, m_isArray{isArrayBin} {
|
||||
if (transp) addTransp(transp);
|
||||
}
|
||||
ASTGEN_MEMBERS_AstCoverBin;
|
||||
void dump(std::ostream& str) const override;
|
||||
void dumpJson(std::ostream& str) const override;
|
||||
string name() const override VL_MT_STABLE { return m_name; }
|
||||
VCoverBinsType binsType() const { return m_type; }
|
||||
bool isArray() const { return m_isArray; }
|
||||
void isArray(bool flag) { m_isArray = flag; }
|
||||
};
|
||||
class AstCoverCrossBins final : public AstNode {
|
||||
// @astgen op1 := selectp : Optional[AstCoverSelectExpr]
|
||||
string m_name;
|
||||
|
||||
public:
|
||||
AstCoverCrossBins(FileLine* fl, const string& name, AstCoverSelectExpr* selectp)
|
||||
: ASTGEN_SUPER_CoverCrossBins(fl)
|
||||
, m_name{name} {
|
||||
this->selectp(selectp);
|
||||
}
|
||||
ASTGEN_MEMBERS_AstCoverCrossBins;
|
||||
void dump(std::ostream& str) const override;
|
||||
void dumpJson(std::ostream& str) const override;
|
||||
string name() const override VL_MT_STABLE { return m_name; }
|
||||
};
|
||||
class AstCoverOption final : public AstNode {
|
||||
// @astgen op1 := valuep : AstNodeExpr
|
||||
VCoverOptionType m_type;
|
||||
|
||||
public:
|
||||
AstCoverOption(FileLine* fl, VCoverOptionType type, AstNodeExpr* valuep)
|
||||
: ASTGEN_SUPER_CoverOption(fl)
|
||||
, m_type{type} {
|
||||
this->valuep(valuep);
|
||||
}
|
||||
ASTGEN_MEMBERS_AstCoverOption;
|
||||
void dump(std::ostream& str) const override;
|
||||
void dumpJson(std::ostream& str) const override;
|
||||
VCoverOptionType optionType() const { return m_type; }
|
||||
};
|
||||
class AstCoverSelectExpr final : public AstNode {
|
||||
// @astgen op1 := exprp : AstNodeExpr
|
||||
public:
|
||||
AstCoverSelectExpr(FileLine* fl, AstNodeExpr* exprp)
|
||||
: ASTGEN_SUPER_CoverSelectExpr(fl) {
|
||||
this->exprp(exprp);
|
||||
}
|
||||
ASTGEN_MEMBERS_AstCoverSelectExpr;
|
||||
void dump(std::ostream& str) const override;
|
||||
void dumpJson(std::ostream& str) const override;
|
||||
};
|
||||
class AstCoverTransItem final : public AstNode {
|
||||
// Represents a single transition item: value or value[*N] or value[->N] or value[=N]
|
||||
// @astgen op1 := valuesp : List[AstNode]
|
||||
// @astgen op2 := repMinp : Optional[AstNodeExpr]
|
||||
// @astgen op3 := repMaxp : Optional[AstNodeExpr]
|
||||
VTransRepType m_repType;
|
||||
|
||||
public:
|
||||
AstCoverTransItem(FileLine* fl, AstNode* valuesp, VTransRepType repType = VTransRepType::NONE)
|
||||
: ASTGEN_SUPER_CoverTransItem(fl)
|
||||
, m_repType{repType} {
|
||||
if (valuesp) addValuesp(valuesp);
|
||||
}
|
||||
ASTGEN_MEMBERS_AstCoverTransItem;
|
||||
void dump(std::ostream& str) const override;
|
||||
void dumpJson(std::ostream& str) const override;
|
||||
VTransRepType repType() const { return m_repType; }
|
||||
};
|
||||
class AstCoverTransSet final : public AstNode {
|
||||
// Represents a transition set: value1 => value2 => value3
|
||||
// @astgen op1 := itemsp : List[AstCoverTransItem]
|
||||
public:
|
||||
AstCoverTransSet(FileLine* fl, AstCoverTransItem* itemsp)
|
||||
: ASTGEN_SUPER_CoverTransSet(fl) {
|
||||
if (itemsp) addItemsp(itemsp);
|
||||
}
|
||||
ASTGEN_MEMBERS_AstCoverTransSet;
|
||||
void dump(std::ostream& str) const override;
|
||||
void dumpJson(std::ostream& str) const override;
|
||||
};
|
||||
class AstCovergroup final : public AstNode {
|
||||
// @astgen op1 := argsp : List[AstVar]
|
||||
// @astgen op2 := membersp : List[AstNode]
|
||||
// @astgen op3 := eventp : Optional[AstSenTree]
|
||||
string m_name;
|
||||
bool m_isClass = false;
|
||||
|
||||
public:
|
||||
AstCovergroup(FileLine* fl, const string& name, AstNode* membersp, AstSenTree* eventp)
|
||||
: ASTGEN_SUPER_Covergroup(fl)
|
||||
, m_name{name} {
|
||||
if (membersp) addMembersp(membersp);
|
||||
this->eventp(eventp);
|
||||
}
|
||||
ASTGEN_MEMBERS_AstCovergroup;
|
||||
void dump(std::ostream& str) const override;
|
||||
void dumpJson(std::ostream& str) const override;
|
||||
string name() const override VL_MT_STABLE { return m_name; }
|
||||
void name(const string& name) override { m_name = name; }
|
||||
bool isClass() const { return m_isClass; }
|
||||
void isClass(bool flag) { m_isClass = flag; }
|
||||
bool maybePointedTo() const override { return true; }
|
||||
};
|
||||
class AstCoverpointRef final : public AstNode {
|
||||
// @astgen ptr := m_coverpointp : Optional[AstCoverpoint]
|
||||
string m_name;
|
||||
|
||||
public:
|
||||
AstCoverpointRef(FileLine* fl, const string& name)
|
||||
: ASTGEN_SUPER_CoverpointRef(fl)
|
||||
, m_name{name} {}
|
||||
ASTGEN_MEMBERS_AstCoverpointRef;
|
||||
void dump(std::ostream& str) const override;
|
||||
void dumpJson(std::ostream& str) const override;
|
||||
string name() const override VL_MT_STABLE { return m_name; }
|
||||
AstCoverpoint* coverpointp() const { return m_coverpointp; }
|
||||
void coverpointp(AstCoverpoint* nodep) { m_coverpointp = nodep; }
|
||||
};
|
||||
class AstDefParam final : public AstNode {
|
||||
// A defparam assignment
|
||||
// Parents: MODULE
|
||||
|
|
@ -2539,6 +2745,33 @@ public:
|
|||
void dump(std::ostream& str = std::cout) const override;
|
||||
void dumpJson(std::ostream& str = std::cout) const override;
|
||||
};
|
||||
class AstCoverCross final : public AstNodeFuncCovItem {
|
||||
// @astgen op1 := itemsp : List[AstCoverpointRef]
|
||||
// @astgen op2 := binsp : List[AstCoverCrossBins]
|
||||
// @astgen op3 := optionsp : List[AstCoverOption]
|
||||
public:
|
||||
AstCoverCross(FileLine* fl, const string& name, AstCoverpointRef* itemsp)
|
||||
: ASTGEN_SUPER_CoverCross(fl, name) {
|
||||
if (itemsp) addItemsp(itemsp);
|
||||
}
|
||||
ASTGEN_MEMBERS_AstCoverCross;
|
||||
void dump(std::ostream& str) const override;
|
||||
void dumpJson(std::ostream& str) const override;
|
||||
};
|
||||
class AstCoverpoint final : public AstNodeFuncCovItem {
|
||||
// @astgen op1 := exprp : AstNodeExpr
|
||||
// @astgen op2 := binsp : List[AstCoverBin]
|
||||
// @astgen op3 := iffp : Optional[AstNodeExpr]
|
||||
// @astgen op4 := optionsp : List[AstCoverOption]
|
||||
public:
|
||||
AstCoverpoint(FileLine* fl, const string& name, AstNodeExpr* exprp)
|
||||
: ASTGEN_SUPER_Coverpoint(fl, name) {
|
||||
this->exprp(exprp);
|
||||
}
|
||||
ASTGEN_MEMBERS_AstCoverpoint;
|
||||
void dump(std::ostream& str) const override;
|
||||
void dumpJson(std::ostream& str) const override;
|
||||
};
|
||||
|
||||
// === AstNodeGen ===
|
||||
class AstGenBlock final : public AstNodeGen {
|
||||
|
|
@ -2964,4 +3197,5 @@ public:
|
|||
bool sameNode(const AstNode* /*samep*/) const override { return true; }
|
||||
};
|
||||
|
||||
|
||||
#endif // Guard
|
||||
|
|
|
|||
|
|
@ -3259,7 +3259,6 @@ void AstCoverToggleDecl::dumpJson(std::ostream& str) const {
|
|||
std::to_string(range().left()) + ":" + std::to_string(range().right()));
|
||||
}
|
||||
}
|
||||
// NOTE: AstCoverBin and AstCoverpoint dump methods removed - moved to V3AstNodeFuncCov.cpp
|
||||
void AstCoverInc::dump(std::ostream& str) const {
|
||||
this->AstNodeStmt::dump(str);
|
||||
str << " -> ";
|
||||
|
|
@ -3496,3 +3495,139 @@ const char* AstNot::widthMismatch() const VL_MT_STABLE {
|
|||
BROKEN_RTN(lhsp()->widthMin() != widthMin());
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
//######################################################################
|
||||
// Functional coverage dump methods
|
||||
|
||||
void AstCovergroup::dump(std::ostream& str) const {
|
||||
this->AstNode::dump(str);
|
||||
str << " " << m_name;
|
||||
if (m_isClass) str << " [class]";
|
||||
}
|
||||
|
||||
void AstCovergroup::dumpJson(std::ostream& str) const {
|
||||
this->AstNode::dumpJson(str);
|
||||
str << ", \"name\": " << VString::quotePercent(name());
|
||||
if (m_isClass) str << ", \"isClass\": true";
|
||||
}
|
||||
|
||||
void AstCoverpoint::dump(std::ostream& str) const { this->AstNodeFuncCovItem::dump(str); }
|
||||
|
||||
void AstCoverpoint::dumpJson(std::ostream& str) const { this->AstNodeFuncCovItem::dumpJson(str); }
|
||||
|
||||
void AstCoverBin::dump(std::ostream& str) const {
|
||||
this->AstNode::dump(str);
|
||||
str << " " << m_name << " ";
|
||||
switch (m_type) {
|
||||
case VCoverBinsType::USER: str << "user"; break;
|
||||
case VCoverBinsType::ARRAY: str << "array"; break;
|
||||
case VCoverBinsType::AUTO: str << "auto"; break;
|
||||
case VCoverBinsType::BINS_IGNORE: str << "ignore"; break;
|
||||
case VCoverBinsType::BINS_ILLEGAL: str << "illegal"; break;
|
||||
case VCoverBinsType::DEFAULT: str << "default"; break;
|
||||
case VCoverBinsType::BINS_WILDCARD: str << "wildcard"; break;
|
||||
case VCoverBinsType::TRANSITION: str << "transition"; break;
|
||||
}
|
||||
if (m_isArray) str << "[]";
|
||||
}
|
||||
|
||||
void AstCoverBin::dumpJson(std::ostream& str) const {
|
||||
this->AstNode::dumpJson(str);
|
||||
str << ", \"name\": " << VString::quotePercent(m_name);
|
||||
str << ", \"binsType\": ";
|
||||
switch (m_type) {
|
||||
case VCoverBinsType::USER: str << "\"user\""; break;
|
||||
case VCoverBinsType::ARRAY: str << "\"array\""; break;
|
||||
case VCoverBinsType::AUTO: str << "\"auto\""; break;
|
||||
case VCoverBinsType::BINS_IGNORE: str << "\"ignore\""; break;
|
||||
case VCoverBinsType::BINS_ILLEGAL: str << "\"illegal\""; break;
|
||||
case VCoverBinsType::DEFAULT: str << "\"default\""; break;
|
||||
case VCoverBinsType::BINS_WILDCARD: str << "\"wildcard\""; break;
|
||||
case VCoverBinsType::TRANSITION: str << "\"transition\""; break;
|
||||
}
|
||||
if (m_isArray) str << ", \"isArray\": true";
|
||||
}
|
||||
|
||||
void AstCoverTransItem::dump(std::ostream& str) const {
|
||||
this->AstNode::dump(str);
|
||||
switch (m_repType) {
|
||||
case VTransRepType::NONE: break;
|
||||
case VTransRepType::CONSEC: str << " [*]"; break;
|
||||
case VTransRepType::GOTO: str << " [->]"; break;
|
||||
case VTransRepType::NONCONS: str << " [=]"; break;
|
||||
}
|
||||
}
|
||||
|
||||
void AstCoverTransItem::dumpJson(std::ostream& str) const {
|
||||
this->AstNode::dumpJson(str);
|
||||
if (m_repType != VTransRepType::NONE) {
|
||||
str << ", \"repType\": ";
|
||||
switch (m_repType) {
|
||||
case VTransRepType::NONE: break;
|
||||
case VTransRepType::CONSEC: str << "\"consec\""; break;
|
||||
case VTransRepType::GOTO: str << "\"goto\""; break;
|
||||
case VTransRepType::NONCONS: str << "\"noncons\""; break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AstCoverTransSet::dump(std::ostream& str) const {
|
||||
this->AstNode::dump(str);
|
||||
str << " trans_set";
|
||||
}
|
||||
|
||||
void AstCoverTransSet::dumpJson(std::ostream& str) const { this->AstNode::dumpJson(str); }
|
||||
|
||||
void AstCoverCross::dump(std::ostream& str) const { this->AstNodeFuncCovItem::dump(str); }
|
||||
|
||||
void AstCoverCross::dumpJson(std::ostream& str) const { this->AstNodeFuncCovItem::dumpJson(str); }
|
||||
|
||||
void AstCoverCrossBins::dump(std::ostream& str) const {
|
||||
this->AstNode::dump(str);
|
||||
str << " " << m_name;
|
||||
}
|
||||
|
||||
void AstCoverCrossBins::dumpJson(std::ostream& str) const {
|
||||
this->AstNode::dumpJson(str);
|
||||
str << ", \"name\": " << VString::quotePercent(m_name);
|
||||
}
|
||||
|
||||
void AstCoverOption::dump(std::ostream& str) const {
|
||||
this->AstNode::dump(str);
|
||||
str << " ";
|
||||
switch (m_type) {
|
||||
case VCoverOptionType::WEIGHT: str << "weight"; break;
|
||||
case VCoverOptionType::GOAL: str << "goal"; break;
|
||||
case VCoverOptionType::AT_LEAST: str << "at_least"; break;
|
||||
case VCoverOptionType::AUTO_BIN_MAX: str << "auto_bin_max"; break;
|
||||
case VCoverOptionType::PER_INSTANCE: str << "per_instance"; break;
|
||||
case VCoverOptionType::COMMENT: str << "comment"; break;
|
||||
}
|
||||
}
|
||||
|
||||
void AstCoverOption::dumpJson(std::ostream& str) const {
|
||||
this->AstNode::dumpJson(str);
|
||||
str << ", \"optionType\": ";
|
||||
switch (m_type) {
|
||||
case VCoverOptionType::WEIGHT: str << "\"weight\""; break;
|
||||
case VCoverOptionType::GOAL: str << "\"goal\""; break;
|
||||
case VCoverOptionType::AT_LEAST: str << "\"at_least\""; break;
|
||||
case VCoverOptionType::AUTO_BIN_MAX: str << "\"auto_bin_max\""; break;
|
||||
case VCoverOptionType::PER_INSTANCE: str << "\"per_instance\""; break;
|
||||
case VCoverOptionType::COMMENT: str << "\"comment\""; break;
|
||||
}
|
||||
}
|
||||
|
||||
void AstCoverpointRef::dump(std::ostream& str) const {
|
||||
this->AstNode::dump(str);
|
||||
str << " " << m_name;
|
||||
}
|
||||
|
||||
void AstCoverpointRef::dumpJson(std::ostream& str) const {
|
||||
this->AstNode::dumpJson(str);
|
||||
str << ", \"name\": " << VString::quotePercent(m_name);
|
||||
}
|
||||
|
||||
void AstCoverSelectExpr::dump(std::ostream& str) const { this->AstNode::dump(str); }
|
||||
|
||||
void AstCoverSelectExpr::dumpJson(std::ostream& str) const { this->AstNode::dumpJson(str); }
|
||||
|
|
|
|||
|
|
@ -797,6 +797,7 @@ class CoverageVisitor final : public VNVisitor {
|
|||
pair.first->second = varp;
|
||||
if (m_ftaskp) {
|
||||
varp->funcLocal(true);
|
||||
varp->lifetime(VLifetime::AUTOMATIC_EXPLICIT);
|
||||
m_ftaskp->stmtsp()->addHereThisAsNext(varp);
|
||||
} else {
|
||||
m_modp->stmtsp()->addHereThisAsNext(varp);
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@
|
|||
|
||||
#include "V3PchAstNoMT.h" // VL_MT_DISABLED_CODE_UNIT
|
||||
|
||||
#include "V3CoverageFunctional.h"
|
||||
#include "V3Covergroup.h"
|
||||
|
||||
VL_DEFINE_DEBUG_FUNCTIONS;
|
||||
|
||||
|
|
@ -1886,7 +1886,7 @@ public:
|
|||
//######################################################################
|
||||
// Functional coverage class functions
|
||||
|
||||
void V3CoverageFunctional::coverageFunctional(AstNetlist* nodep) {
|
||||
void V3Covergroup::covergroup(AstNetlist* nodep) {
|
||||
UINFO(4, __FUNCTION__ << ": " << endl);
|
||||
{ FunctionalCoverageVisitor{nodep}; } // Destruct before checking
|
||||
V3Global::dumpCheckGlobalTree("coveragefunc", 0, dumpTreeEitherLevel() >= 3);
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
||||
//*************************************************************************
|
||||
// DESCRIPTION: Verilator: Functional coverage implementation
|
||||
// DESCRIPTION: Verilator: Covergroup implementation
|
||||
//
|
||||
// Code available from: https://verilator.org
|
||||
//
|
||||
|
|
@ -14,17 +14,17 @@
|
|||
//
|
||||
//*************************************************************************
|
||||
|
||||
#ifndef VERILATOR_V3COVERAGEFUNCTIONAL_H_
|
||||
#define VERILATOR_V3COVERAGEFUNCTIONAL_H_
|
||||
#ifndef VERILATOR_V3COVERGROUP_H_
|
||||
#define VERILATOR_V3COVERGROUP_H_
|
||||
|
||||
#include "V3Ast.h"
|
||||
#include "V3Error.h"
|
||||
|
||||
//============================================================================
|
||||
|
||||
class V3CoverageFunctional final {
|
||||
class V3Covergroup final {
|
||||
public:
|
||||
static void coverageFunctional(AstNetlist* nodep);
|
||||
static void covergroup(AstNetlist* nodep);
|
||||
};
|
||||
|
||||
#endif // Guard
|
||||
|
|
@ -227,12 +227,6 @@ class EmitVBaseVisitorConst VL_NOT_FINAL : public VNVisitorConst {
|
|||
iterateAndNextConstNull(nodep->rhsp());
|
||||
if (!m_suppressSemi) puts(";\n");
|
||||
}
|
||||
void visit(AstAssignDly* nodep) override {
|
||||
iterateAndNextConstNull(nodep->lhsp());
|
||||
putfs(nodep, " <= ");
|
||||
iterateAndNextConstNull(nodep->rhsp());
|
||||
puts(";\n");
|
||||
}
|
||||
void visit(AstAlias* nodep) override {
|
||||
putbs("alias ");
|
||||
iterateConst(nodep->itemsp());
|
||||
|
|
|
|||
|
|
@ -309,6 +309,7 @@ class LinkIncVisitor final : public VNVisitor {
|
|||
AstVar* const varp = new AstVar{
|
||||
fl, VVarType::BLOCKTEMP, name, VFlagChildDType{},
|
||||
new AstRefDType{fl, AstRefDType::FlagTypeOfExpr{}, readp->cloneTree(true)}};
|
||||
varp->lifetime(VLifetime::AUTOMATIC_EXPLICIT);
|
||||
if (m_ftaskp) varp->funcLocal(true);
|
||||
|
||||
// Declare the variable
|
||||
|
|
|
|||
|
|
@ -37,7 +37,7 @@
|
|||
#include "V3Const.h"
|
||||
#include "V3Control.h"
|
||||
#include "V3Coverage.h"
|
||||
#include "V3CoverageFunctional.h"
|
||||
#include "V3Covergroup.h"
|
||||
#include "V3CoverageJoin.h"
|
||||
#include "V3Dead.h"
|
||||
#include "V3Delayed.h"
|
||||
|
|
@ -239,7 +239,7 @@ static void process() {
|
|||
|
||||
// Functional coverage code generation
|
||||
// Generate code for covergroups/coverpoints
|
||||
V3CoverageFunctional::coverageFunctional(v3Global.rootp());
|
||||
V3Covergroup::covergroup(v3Global.rootp());
|
||||
|
||||
// Resolve randsequence if they are used by the design
|
||||
if (v3Global.useRandSequence()) V3RandSequence::randSequenceNetlist(v3Global.rootp());
|
||||
|
|
|
|||
|
|
@ -1,18 +0,0 @@
|
|||
#!/usr/bin/env python3
|
||||
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||
#
|
||||
# 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-FileCopyrightText: 2026 Wilson Snyder
|
||||
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
||||
|
||||
import vltest_bootstrap
|
||||
|
||||
test.scenarios('vlt')
|
||||
|
||||
test.compile(verilator_flags2=["--exe", "t/t_funccov_basic_main.cpp"], make_main=False)
|
||||
|
||||
test.execute()
|
||||
|
||||
test.passes()
|
||||
|
|
@ -1,25 +0,0 @@
|
|||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// This file ONLY is placed under the Creative Commons Public Domain
|
||||
// SPDX-FileCopyrightText: 2026 Matthew Ballance
|
||||
// SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
// Test basic functional coverage infrastructure
|
||||
|
||||
module t;
|
||||
/* verilator lint_off UNSIGNED */
|
||||
int addr;
|
||||
int cmd;
|
||||
|
||||
// For now, this is just a placeholder until parser support is added
|
||||
// We'll test the runtime infrastructure directly from C++
|
||||
|
||||
initial begin
|
||||
addr = 10;
|
||||
cmd = 1;
|
||||
$display("Test placeholder for functional coverage");
|
||||
$write("*-* All Finished *-*\n");
|
||||
$finish;
|
||||
end
|
||||
|
||||
endmodule
|
||||
|
|
@ -1,112 +0,0 @@
|
|||
// DESCRIPTION: Verilator: Verilog Test main for functional coverage
|
||||
//
|
||||
// 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-FileCopyrightText: 2026 Matthew Ballance
|
||||
// SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
||||
|
||||
#include "verilated.h"
|
||||
#include "verilated_funccov.h"
|
||||
#include VM_PREFIX_INCLUDE
|
||||
|
||||
#include <iostream>
|
||||
#include <memory>
|
||||
|
||||
// Test the functional coverage runtime infrastructure
|
||||
void testFuncCovInfrastructure() {
|
||||
std::cout << "Testing functional coverage infrastructure..." << std::endl;
|
||||
|
||||
// Create a covergroup
|
||||
VerilatedCovergroup cg("test_cg");
|
||||
|
||||
// Create a coverpoint with automatic bins
|
||||
auto* cp_addr = new VerilatedCoverpoint{"cp_addr"};
|
||||
cp_addr->addBin(new VerilatedCoverRangeBin{"low", 0, 127});
|
||||
cp_addr->addBin(new VerilatedCoverRangeBin{"high", 128, 255});
|
||||
cg.addCoverpoint(cp_addr);
|
||||
|
||||
// Create another coverpoint
|
||||
auto* cp_cmd = new VerilatedCoverpoint{"cp_cmd"};
|
||||
cp_cmd->addBin(new VerilatedCoverRangeBin{"read", 0, 0});
|
||||
cp_cmd->addBin(new VerilatedCoverRangeBin{"write", 1, 1});
|
||||
cg.addCoverpoint(cp_cmd);
|
||||
|
||||
// Create a cross coverage
|
||||
auto* cross = new VerilatedCoverCross{"cross_cmd_addr"};
|
||||
cross->addCoverpoint(cp_addr);
|
||||
cross->addCoverpoint(cp_cmd);
|
||||
cg.addCross(cross);
|
||||
|
||||
// Sample some values
|
||||
std::cout << "Sampling values..." << std::endl;
|
||||
cp_addr->sample(10); // low bin
|
||||
cp_cmd->sample(0); // read bin
|
||||
cross->sample({10, 0});
|
||||
|
||||
cp_addr->sample(200); // high bin
|
||||
cp_cmd->sample(1); // write bin
|
||||
cross->sample({200, 1});
|
||||
|
||||
cp_addr->sample(50); // low bin again
|
||||
cp_cmd->sample(0); // read bin again
|
||||
cross->sample({50, 0});
|
||||
|
||||
// Check coverage
|
||||
double addr_cov = cp_addr->getCoverage();
|
||||
double cmd_cov = cp_cmd->getCoverage();
|
||||
double cross_cov = cross->getCoverage();
|
||||
double cg_cov = cg.get_coverage();
|
||||
|
||||
std::cout << "cp_addr coverage: " << addr_cov << "%" << std::endl;
|
||||
std::cout << "cp_cmd coverage: " << cmd_cov << "%" << std::endl;
|
||||
std::cout << "cross coverage: " << cross_cov << "%" << std::endl;
|
||||
std::cout << "Covergroup coverage: " << cg_cov << "%" << std::endl;
|
||||
|
||||
// Verify results
|
||||
if (addr_cov != 100.0) {
|
||||
std::cerr << "ERROR: Expected addr coverage 100%, got " << addr_cov << std::endl;
|
||||
exit(1);
|
||||
}
|
||||
if (cmd_cov != 100.0) {
|
||||
std::cerr << "ERROR: Expected cmd coverage 100%, got " << cmd_cov << std::endl;
|
||||
exit(1);
|
||||
}
|
||||
// Cross coverage should be 50% (2 out of 4 possible cross products covered)
|
||||
if (cross_cov < 49.9 || cross_cov > 50.1) {
|
||||
std::cerr << "ERROR: Expected cross coverage ~50%, got " << cross_cov << std::endl;
|
||||
exit(1);
|
||||
}
|
||||
// Overall covergroup coverage is weighted average of all components
|
||||
// (100 + 100 + 50) / 3 = 83.33%
|
||||
if (cg_cov < 83.0 || cg_cov > 84.0) {
|
||||
std::cerr << "ERROR: Expected covergroup coverage ~83.33%, got " << cg_cov << std::endl;
|
||||
exit(1);
|
||||
}
|
||||
|
||||
std::cout << "Functional coverage infrastructure test PASSED" << std::endl;
|
||||
}
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
// Standard Verilator setup
|
||||
const std::unique_ptr<VerilatedContext> contextp{new VerilatedContext};
|
||||
contextp->commandArgs(argc, argv);
|
||||
|
||||
const std::unique_ptr<VM_PREFIX> topp{new VM_PREFIX{contextp.get()}};
|
||||
|
||||
// Test functional coverage infrastructure
|
||||
testFuncCovInfrastructure();
|
||||
|
||||
// Run the Verilog simulation briefly
|
||||
contextp->timeInc(1);
|
||||
topp->eval();
|
||||
|
||||
// Check for finish
|
||||
if (!contextp->gotFinish()) {
|
||||
VL_PRINTF("%%Error: main.cpp didn't finish\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
std::cout << "*-* All Finished *-*" << std::endl;
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -44,8 +44,7 @@ for dfile in test.glob_some(test.obj_dir + "/*.d"):
|
|||
hit[filename] = True
|
||||
|
||||
for filename in sorted(hit.keys()):
|
||||
if (not hit[filename] and filename != "verilated_funccov.h"
|
||||
and not re.search(r'_sc', filename) and not re.search(r'_fst', filename)
|
||||
if (not hit[filename] and not re.search(r'_sc', filename) and not re.search(r'_fst', filename)
|
||||
and not re.search(r'_saif', filename) and not re.search(r'_thread', filename)
|
||||
and (not re.search(r'_timing', filename) or test.have_coroutines)):
|
||||
test.error("Include file not covered by t_verilated_all test: ", filename)
|
||||
|
|
|
|||
Loading…
Reference in New Issue