mirror of
https://github.com/verilator/verilator.git
synced 2025-01-22 14:24:18 +00:00
155 lines
5.1 KiB
C++
155 lines
5.1 KiB
C++
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
||
//*************************************************************************
|
||
// DESCRIPTION: verilator_coverage: Coverage points
|
||
//
|
||
// Code available from: http://www.veripool.org/verilator
|
||
//
|
||
//*************************************************************************
|
||
//
|
||
// Copyright 2003-2019 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.
|
||
//
|
||
// Verilator is distributed in the hope that it will be useful,
|
||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
// GNU General Public License for more details.
|
||
//
|
||
//*************************************************************************
|
||
|
||
#ifndef _VLCPOINT_H_
|
||
#define _VLCPOINT_H_ 1
|
||
|
||
#include "config_build.h"
|
||
#include "verilatedos.h"
|
||
|
||
#include "verilated_cov_key.h"
|
||
|
||
#include <vector>
|
||
#include <iomanip>
|
||
#include VL_INCLUDE_UNORDERED_MAP
|
||
|
||
//********************************************************************
|
||
// VlcPoint - A coverage point (across all tests)
|
||
|
||
class VlcPoint {
|
||
private:
|
||
// MEMBERS
|
||
string m_name; //< Name of the point
|
||
vluint64_t m_pointNum; //< Point number
|
||
vluint64_t m_testsCovering; //< Number tests with non-zero coverage of this point
|
||
vluint64_t m_count; //< Count of hits across all tests
|
||
|
||
public:
|
||
// CONSTRUCTORS
|
||
VlcPoint(const string& name, int pointNum) {
|
||
m_name = name;
|
||
m_pointNum = pointNum;
|
||
m_testsCovering = 0;
|
||
m_count = 0;
|
||
}
|
||
~VlcPoint() {}
|
||
// ACCESSORS
|
||
const string& name() const { return m_name; }
|
||
vluint64_t pointNum() const { return m_pointNum; }
|
||
vluint64_t testsCovering() const { return m_testsCovering; }
|
||
void countInc(vluint64_t inc) { m_count += inc; }
|
||
vluint64_t count() const { return m_count; }
|
||
void testsCoveringInc() { m_testsCovering++; }
|
||
// KEY ACCESSORS
|
||
string filename() const { return keyExtract(VL_CIK_FILENAME); }
|
||
string comment() const { return keyExtract(VL_CIK_COMMENT); }
|
||
string type() const { return keyExtract(VL_CIK_TYPE); }
|
||
string thresh() const { return keyExtract(VL_CIK_THRESH); } // string as maybe ""
|
||
int lineno() const { return atoi(keyExtract(VL_CIK_LINENO).c_str()); }
|
||
int column() const { return atoi(keyExtract(VL_CIK_COLUMN).c_str()); }
|
||
// METHODS
|
||
string keyExtract(const char* shortKey) const {
|
||
// Hot function
|
||
size_t shortLen = strlen(shortKey);
|
||
const string namestr = name();
|
||
for (const char* cp = namestr.c_str(); *cp; ++cp) {
|
||
if (*cp == '\001') {
|
||
if (0==strncmp(cp+1, shortKey, shortLen)
|
||
&& cp[shortLen+1] == '\002') {
|
||
cp += shortLen+2; // Skip \001+short+\002
|
||
const char* ep = cp;
|
||
while (*ep && *ep != '\001') ++ep;
|
||
return string(cp, ep-cp);
|
||
}
|
||
}
|
||
}
|
||
return "";
|
||
}
|
||
static void dumpHeader() {
|
||
cout<<"Points:\n";
|
||
cout<<" Num, TestsCover, Count, Name"<<endl;
|
||
}
|
||
void dump() const {
|
||
cout<<" "<<std::setw(8)<<std::setfill('0')<<pointNum()
|
||
<<", "<<std::setw(7)<<std::setfill(' ')<<testsCovering()
|
||
<<", "<<std::setw(7)<<std::setfill(' ')<<count()
|
||
<<", \""<<name()<<"\""<<endl;
|
||
}
|
||
};
|
||
|
||
//********************************************************************
|
||
// VlcPoints - Container of all points
|
||
|
||
class VlcPoints {
|
||
private:
|
||
// MEMBERS
|
||
typedef std::map<string,vluint64_t> NameMap; // Sorted by name (ordered)
|
||
NameMap m_nameMap; //< Name to point-number
|
||
std::vector<VlcPoint> m_points; //< List of all points
|
||
vluint64_t m_numPoints; //< Total unique points
|
||
|
||
public:
|
||
// ITERATORS
|
||
typedef NameMap ByName;
|
||
typedef ByName::iterator iterator;
|
||
ByName::iterator begin() { return m_nameMap.begin(); }
|
||
ByName::iterator end() { return m_nameMap.end(); }
|
||
|
||
public:
|
||
// CONSTRUCTORS
|
||
VlcPoints() {
|
||
m_numPoints = 0;
|
||
}
|
||
~VlcPoints() {}
|
||
|
||
// METHODS
|
||
void dump() {
|
||
UINFO(2,"dumpPoints...\n");
|
||
VlcPoint::dumpHeader();
|
||
for (VlcPoints::ByName::iterator it=begin(); it!=end(); ++it) {
|
||
const VlcPoint& point = pointNumber(it->second);
|
||
point.dump();
|
||
}
|
||
}
|
||
VlcPoint& pointNumber(vluint64_t num) {
|
||
return m_points[num];
|
||
}
|
||
vluint64_t findAddPoint(const string& name, vluint64_t count) {
|
||
vluint64_t pointnum;
|
||
NameMap::iterator iter = m_nameMap.find(name);
|
||
if (iter != m_nameMap.end()) {
|
||
pointnum = iter->second;
|
||
m_points[pointnum].countInc(count);
|
||
}
|
||
else {
|
||
pointnum = m_numPoints++;
|
||
VlcPoint point (name, pointnum);
|
||
point.countInc(count);
|
||
m_points.push_back(point);
|
||
m_nameMap.insert(make_pair(point.name(), point.pointNum()));
|
||
}
|
||
return pointnum;
|
||
}
|
||
};
|
||
|
||
//######################################################################
|
||
|
||
#endif // guard
|