mirror of
https://github.com/verilator/verilator.git
synced 2025-04-05 04:02:37 +00:00
Internals: Detab and fix spacing style issues in some include files. No functional change.
This commit is contained in:
parent
f818ddc71c
commit
b23fc06388
@ -1712,7 +1712,7 @@ This is an example similar to the above, but using SystemC.
|
||||
#include "Vour.h"
|
||||
int sc_main(int argc, char **argv) {
|
||||
Verilated::commandArgs(argc, argv);
|
||||
sc_clock clk ("clk",10, 0.5, 3, true);
|
||||
sc_clock clk ("clk", 10, 0.5, 3, true);
|
||||
Vour* top;
|
||||
top = new Vour("top");
|
||||
top->clk(clk);
|
||||
@ -3894,7 +3894,7 @@ Often UNOPTFLAT is caused by logic that isn't truly circular as viewed by
|
||||
synthesis which analyzes interconnection per-bit, but is circular to
|
||||
simulation which analyzes per-bus:
|
||||
|
||||
wire [2:0] x = {x[1:0],shift_in};
|
||||
wire [2:0] x = {x[1:0], shift_in};
|
||||
|
||||
This statement needs to be evaluated multiple times, as a change in
|
||||
"shift_in" requires "x" to be computed 3 times before it becomes stable.
|
||||
@ -3903,12 +3903,12 @@ causes the warning.
|
||||
|
||||
For significantly better performance, split this into 2 separate signals:
|
||||
|
||||
wire [2:0] xout = {x[1:0],shift_in};
|
||||
wire [2:0] xout = {x[1:0], shift_in};
|
||||
|
||||
and change all receiving logic to instead receive "xout". Alternatively,
|
||||
change it to
|
||||
|
||||
wire [2:0] x = {xin[1:0],shift_in};
|
||||
wire [2:0] x = {xin[1:0], shift_in};
|
||||
|
||||
and change all driving logic to instead drive "xin".
|
||||
|
||||
@ -4024,7 +4024,7 @@ Concatenate leading zeros when doing arithmetic. In the statement
|
||||
|
||||
The best fix, which clarifies intent and will also make all tools happy is:
|
||||
|
||||
wire [5:0] plus_one = from[5:0] + 6'd1 + {5'd0,carry[0]};
|
||||
wire [5:0] plus_one = from[5:0] + 6'd1 + {5'd0, carry[0]};
|
||||
|
||||
Ignoring this warning will only suppress the lint check, it will simulate
|
||||
correctly.
|
||||
@ -4036,12 +4036,12 @@ has an indeterminate width. In most cases this violates the Verilog rule
|
||||
that widths inside concatenates and replicates must be sized, and should be
|
||||
fixed in the code.
|
||||
|
||||
wire [63:0] concat = {1,2};
|
||||
wire [63:0] concat = {1, 2};
|
||||
|
||||
An example where this is technically legal (though still bad form) is:
|
||||
|
||||
parameter PAR = 1;
|
||||
wire [63:0] concat = {PAR,PAR};
|
||||
wire [63:0] concat = {PAR, PAR};
|
||||
|
||||
The correct fix is to either size the 1 ("32'h1"), or add the width to the
|
||||
parameter definition ("parameter [31:0]"), or add the width to the
|
||||
|
@ -50,10 +50,10 @@ public: // But only local to this file
|
||||
// CONSTRUCTORS
|
||||
// Derived classes should call zero() in their constructor
|
||||
VerilatedCovImpItem() {
|
||||
for (int i=0; i<MAX_KEYS; ++i) {
|
||||
m_keys[i]=KEY_UNDEF;
|
||||
m_vals[i]=0;
|
||||
}
|
||||
for (int i=0; i<MAX_KEYS; ++i) {
|
||||
m_keys[i] = KEY_UNDEF;
|
||||
m_vals[i] = 0;
|
||||
}
|
||||
}
|
||||
virtual ~VerilatedCovImpItem() {}
|
||||
virtual vluint64_t count() const = 0;
|
||||
@ -96,7 +96,7 @@ private:
|
||||
|
||||
private:
|
||||
// MEMBERS
|
||||
VerilatedMutex m_mutex; ///< Protects all members, when VL_THREADED. Wrapper deals with setting it.
|
||||
VerilatedMutex m_mutex; ///< Protects all members, when VL_THREADED. Wrapper deals with setting it.
|
||||
ValueIndexMap m_valueIndexes VL_GUARDED_BY(m_mutex); ///< For each key/value a unique arbitrary index value
|
||||
IndexValueMap m_indexValues VL_GUARDED_BY(m_mutex); ///< For each key/value a unique arbitrary index value
|
||||
ItemList m_items VL_GUARDED_BY(m_mutex); ///< List of all items
|
||||
@ -107,294 +107,294 @@ private:
|
||||
|
||||
// CONSTRUCTORS
|
||||
VerilatedCovImp() {
|
||||
m_insertp = NULL;
|
||||
m_insertFilenamep = NULL;
|
||||
m_insertLineno = 0;
|
||||
m_insertp = NULL;
|
||||
m_insertFilenamep = NULL;
|
||||
m_insertLineno = 0;
|
||||
}
|
||||
VL_UNCOPYABLE(VerilatedCovImp);
|
||||
public:
|
||||
~VerilatedCovImp() { clearGuts(); }
|
||||
static VerilatedCovImp& imp() VL_MT_SAFE {
|
||||
static VerilatedCovImp s_singleton;
|
||||
return s_singleton;
|
||||
static VerilatedCovImp s_singleton;
|
||||
return s_singleton;
|
||||
}
|
||||
|
||||
private:
|
||||
// PRIVATE METHODS
|
||||
int valueIndex(const std::string& value) VL_REQUIRES(m_mutex) {
|
||||
static int nextIndex = KEY_UNDEF+1;
|
||||
ValueIndexMap::iterator iter = m_valueIndexes.find(value);
|
||||
if (iter != m_valueIndexes.end()) return iter->second;
|
||||
nextIndex++; assert(nextIndex>0);
|
||||
m_valueIndexes.insert(std::make_pair(value, nextIndex));
|
||||
m_indexValues.insert(std::make_pair(nextIndex, value));
|
||||
return nextIndex;
|
||||
static int nextIndex = KEY_UNDEF+1;
|
||||
ValueIndexMap::iterator iter = m_valueIndexes.find(value);
|
||||
if (iter != m_valueIndexes.end()) return iter->second;
|
||||
nextIndex++; assert(nextIndex>0);
|
||||
m_valueIndexes.insert(std::make_pair(value, nextIndex));
|
||||
m_indexValues.insert(std::make_pair(nextIndex, value));
|
||||
return nextIndex;
|
||||
}
|
||||
static std::string dequote(const std::string& text) VL_PURE {
|
||||
// Quote any special characters
|
||||
std::string rtn;
|
||||
for (const char* pos = text.c_str(); *pos; ++pos) {
|
||||
if (!isprint(*pos) || *pos=='%' || *pos=='"') {
|
||||
char hex[10]; sprintf(hex,"%%%02X",pos[0]);
|
||||
rtn += hex;
|
||||
} else {
|
||||
rtn += *pos;
|
||||
}
|
||||
}
|
||||
return rtn;
|
||||
// Quote any special characters
|
||||
std::string rtn;
|
||||
for (const char* pos = text.c_str(); *pos; ++pos) {
|
||||
if (!isprint(*pos) || *pos=='%' || *pos=='"') {
|
||||
char hex[10]; sprintf(hex, "%%%02X", pos[0]);
|
||||
rtn += hex;
|
||||
} else {
|
||||
rtn += *pos;
|
||||
}
|
||||
}
|
||||
return rtn;
|
||||
}
|
||||
static bool legalKey(const std::string& key) VL_PURE {
|
||||
// Because we compress long keys to a single letter, and
|
||||
// don't want applications to either get confused if they use
|
||||
// a letter differently, nor want them to rely on our compression...
|
||||
// (Considered using numeric keys, but will remain back compatible.)
|
||||
if (key.length()<2) return false;
|
||||
if (key.length()==2 && isdigit(key[1])) return false;
|
||||
return true;
|
||||
// Because we compress long keys to a single letter, and
|
||||
// don't want applications to either get confused if they use
|
||||
// a letter differently, nor want them to rely on our compression...
|
||||
// (Considered using numeric keys, but will remain back compatible.)
|
||||
if (key.length()<2) return false;
|
||||
if (key.length()==2 && isdigit(key[1])) return false;
|
||||
return true;
|
||||
}
|
||||
static std::string keyValueFormatter(const std::string& key, const std::string& value) VL_PURE {
|
||||
std::string name;
|
||||
if (key.length()==1 && isalpha(key[0])) {
|
||||
name += std::string("\001")+key;
|
||||
} else {
|
||||
name += std::string("\001")+dequote(key);
|
||||
}
|
||||
name += std::string("\002")+dequote(value);
|
||||
return name;
|
||||
std::string name;
|
||||
if (key.length()==1 && isalpha(key[0])) {
|
||||
name += std::string("\001")+key;
|
||||
} else {
|
||||
name += std::string("\001")+dequote(key);
|
||||
}
|
||||
name += std::string("\002")+dequote(value);
|
||||
return name;
|
||||
}
|
||||
static std::string combineHier(const std::string& old, const std::string& add) VL_PURE {
|
||||
// (foo.a.x, foo.b.x) => foo.*.x
|
||||
// (foo.a.x, foo.b.y) => foo.*
|
||||
// (foo.a.x, foo.b) => foo.*
|
||||
if (old == add) return add;
|
||||
// (foo.a.x, foo.b.x) => foo.*.x
|
||||
// (foo.a.x, foo.b.y) => foo.*
|
||||
// (foo.a.x, foo.b) => foo.*
|
||||
if (old == add) return add;
|
||||
if (old.empty()) return add;
|
||||
if (add.empty()) return old;
|
||||
|
||||
const char* a = old.c_str();
|
||||
const char* b = add.c_str();
|
||||
const char* a = old.c_str();
|
||||
const char* b = add.c_str();
|
||||
|
||||
// Scan forward to first mismatch
|
||||
const char* apre = a;
|
||||
const char* bpre = b;
|
||||
while (*apre == *bpre) { apre++; bpre++; }
|
||||
// Scan forward to first mismatch
|
||||
const char* apre = a;
|
||||
const char* bpre = b;
|
||||
while (*apre == *bpre) { apre++; bpre++; }
|
||||
|
||||
// We used to backup and split on only .'s but it seems better to be verbose
|
||||
// and not assume . is the separator
|
||||
std::string prefix = std::string(a,apre-a);
|
||||
// We used to backup and split on only .'s but it seems better to be verbose
|
||||
// and not assume . is the separator
|
||||
std::string prefix = std::string(a, apre-a);
|
||||
|
||||
// Scan backward to last mismatch
|
||||
const char* apost = a+strlen(a)-1;
|
||||
const char* bpost = b+strlen(b)-1;
|
||||
while (*apost == *bpost
|
||||
&& apost>apre && bpost>bpre) { apost--; bpost--; }
|
||||
// Scan backward to last mismatch
|
||||
const char* apost = a+strlen(a)-1;
|
||||
const char* bpost = b+strlen(b)-1;
|
||||
while (*apost == *bpost
|
||||
&& apost>apre && bpost>bpre) { apost--; bpost--; }
|
||||
|
||||
// Forward to . so we have a whole word
|
||||
std::string suffix = *bpost ? std::string(bpost+1) : "";
|
||||
// Forward to . so we have a whole word
|
||||
std::string suffix = *bpost ? std::string(bpost+1) : "";
|
||||
|
||||
std::string out = prefix+"*"+suffix;
|
||||
std::string out = prefix+"*"+suffix;
|
||||
|
||||
//cout << "\nch pre="<<prefix<<" s="<<suffix<<"\nch a="<<old<<"\nch b="<<add<<"\nch o="<<out<<endl;
|
||||
return out;
|
||||
//cout << "\nch pre="<<prefix<<" s="<<suffix<<"\nch a="<<old<<"\nch b="<<add<<"\nch o="<<out<<endl;
|
||||
return out;
|
||||
}
|
||||
bool itemMatchesString(VerilatedCovImpItem* itemp, const std::string& match) VL_REQUIRES(m_mutex) {
|
||||
for (int i=0; i<MAX_KEYS; ++i) {
|
||||
if (itemp->m_keys[i] != KEY_UNDEF) {
|
||||
// We don't compare keys, only values
|
||||
std::string val = m_indexValues[itemp->m_vals[i]];
|
||||
if (std::string::npos != val.find(match)) { // Found
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
for (int i=0; i<MAX_KEYS; ++i) {
|
||||
if (itemp->m_keys[i] != KEY_UNDEF) {
|
||||
// We don't compare keys, only values
|
||||
std::string val = m_indexValues[itemp->m_vals[i]];
|
||||
if (std::string::npos != val.find(match)) { // Found
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
static void selftest() VL_MT_SAFE {
|
||||
// Little selftest
|
||||
if (combineHier ("a.b.c","a.b.c") !="a.b.c") VL_FATAL_MT(__FILE__,__LINE__,"","%Error: selftest\n");
|
||||
if (combineHier ("a.b.c","a.b") !="a.b*") VL_FATAL_MT(__FILE__,__LINE__,"","%Error: selftest\n");
|
||||
if (combineHier ("a.x.c","a.y.c") !="a.*.c") VL_FATAL_MT(__FILE__,__LINE__,"","%Error: selftest\n");
|
||||
if (combineHier ("a.z.z.z.c","a.b.c") !="a.*.c") VL_FATAL_MT(__FILE__,__LINE__,"","%Error: selftest\n");
|
||||
if (combineHier ("z","a") !="*") VL_FATAL_MT(__FILE__,__LINE__,"","%Error: selftest\n");
|
||||
if (combineHier ("q.a","q.b") !="q.*") VL_FATAL_MT(__FILE__,__LINE__,"","%Error: selftest\n");
|
||||
if (combineHier ("q.za","q.zb") !="q.z*") VL_FATAL_MT(__FILE__,__LINE__,"","%Error: selftest\n");
|
||||
if (combineHier ("1.2.3.a","9.8.7.a") !="*.a") VL_FATAL_MT(__FILE__,__LINE__,"","%Error: selftest\n");
|
||||
// Little selftest
|
||||
if (combineHier("a.b.c","a.b.c") !="a.b.c") VL_FATAL_MT(__FILE__,__LINE__,"","%Error: selftest\n");
|
||||
if (combineHier("a.b.c","a.b") !="a.b*") VL_FATAL_MT(__FILE__,__LINE__,"","%Error: selftest\n");
|
||||
if (combineHier("a.x.c","a.y.c") !="a.*.c") VL_FATAL_MT(__FILE__,__LINE__,"","%Error: selftest\n");
|
||||
if (combineHier("a.z.z.z.c","a.b.c") !="a.*.c") VL_FATAL_MT(__FILE__,__LINE__,"","%Error: selftest\n");
|
||||
if (combineHier("z","a") !="*") VL_FATAL_MT(__FILE__,__LINE__,"","%Error: selftest\n");
|
||||
if (combineHier("q.a","q.b") !="q.*") VL_FATAL_MT(__FILE__,__LINE__,"","%Error: selftest\n");
|
||||
if (combineHier("q.za","q.zb") !="q.z*") VL_FATAL_MT(__FILE__,__LINE__,"","%Error: selftest\n");
|
||||
if (combineHier("1.2.3.a","9.8.7.a") !="*.a") VL_FATAL_MT(__FILE__,__LINE__,"","%Error: selftest\n");
|
||||
}
|
||||
void clearGuts() VL_REQUIRES(m_mutex) {
|
||||
for (ItemList::const_iterator it=m_items.begin(); it!=m_items.end(); ++it) {
|
||||
VerilatedCovImpItem* itemp = *(it);
|
||||
delete itemp;
|
||||
}
|
||||
m_items.clear();
|
||||
m_indexValues.clear();
|
||||
m_valueIndexes.clear();
|
||||
for (ItemList::const_iterator it=m_items.begin(); it!=m_items.end(); ++it) {
|
||||
VerilatedCovImpItem* itemp = *(it);
|
||||
delete itemp;
|
||||
}
|
||||
m_items.clear();
|
||||
m_indexValues.clear();
|
||||
m_valueIndexes.clear();
|
||||
}
|
||||
|
||||
public:
|
||||
// PUBLIC METHODS
|
||||
void clear() VL_EXCLUDES(m_mutex) {
|
||||
Verilated::quiesce();
|
||||
VerilatedLockGuard lock(m_mutex);
|
||||
clearGuts();
|
||||
Verilated::quiesce();
|
||||
VerilatedLockGuard lock(m_mutex);
|
||||
clearGuts();
|
||||
}
|
||||
void clearNonMatch(const char* matchp) VL_EXCLUDES(m_mutex) {
|
||||
Verilated::quiesce();
|
||||
VerilatedLockGuard lock(m_mutex);
|
||||
if (matchp && matchp[0]) {
|
||||
ItemList newlist;
|
||||
for (ItemList::iterator it=m_items.begin(); it!=m_items.end(); ++it) {
|
||||
VerilatedCovImpItem* itemp = *(it);
|
||||
if (!itemMatchesString(itemp, matchp)) {
|
||||
delete itemp;
|
||||
} else {
|
||||
newlist.push_back(itemp);
|
||||
}
|
||||
}
|
||||
m_items = newlist;
|
||||
}
|
||||
Verilated::quiesce();
|
||||
VerilatedLockGuard lock(m_mutex);
|
||||
if (matchp && matchp[0]) {
|
||||
ItemList newlist;
|
||||
for (ItemList::iterator it=m_items.begin(); it!=m_items.end(); ++it) {
|
||||
VerilatedCovImpItem* itemp = *(it);
|
||||
if (!itemMatchesString(itemp, matchp)) {
|
||||
delete itemp;
|
||||
} else {
|
||||
newlist.push_back(itemp);
|
||||
}
|
||||
}
|
||||
m_items = newlist;
|
||||
}
|
||||
}
|
||||
void zero() VL_EXCLUDES(m_mutex) {
|
||||
Verilated::quiesce();
|
||||
VerilatedLockGuard lock(m_mutex);
|
||||
for (ItemList::const_iterator it=m_items.begin(); it!=m_items.end(); ++it) {
|
||||
(*it)->zero();
|
||||
}
|
||||
Verilated::quiesce();
|
||||
VerilatedLockGuard lock(m_mutex);
|
||||
for (ItemList::const_iterator it=m_items.begin(); it!=m_items.end(); ++it) {
|
||||
(*it)->zero();
|
||||
}
|
||||
}
|
||||
|
||||
// We assume there's always call to i/f/p in that order
|
||||
void inserti(VerilatedCovImpItem* itemp) VL_EXCLUDES(m_mutex) {
|
||||
VerilatedLockGuard lock(m_mutex);
|
||||
assert(!m_insertp);
|
||||
m_insertp = itemp;
|
||||
VerilatedLockGuard lock(m_mutex);
|
||||
assert(!m_insertp);
|
||||
m_insertp = itemp;
|
||||
}
|
||||
void insertf(const char* filenamep, int lineno) VL_EXCLUDES(m_mutex) {
|
||||
VerilatedLockGuard lock(m_mutex);
|
||||
m_insertFilenamep = filenamep;
|
||||
m_insertLineno = lineno;
|
||||
VerilatedLockGuard lock(m_mutex);
|
||||
m_insertFilenamep = filenamep;
|
||||
m_insertLineno = lineno;
|
||||
}
|
||||
void insertp(const char* ckeyps[MAX_KEYS],
|
||||
const char* valps[MAX_KEYS]) VL_EXCLUDES(m_mutex) {
|
||||
VerilatedLockGuard lock(m_mutex);
|
||||
assert(m_insertp);
|
||||
// First two key/vals are filename
|
||||
ckeyps[0]="filename"; valps[0]=m_insertFilenamep;
|
||||
std::string linestr = vlCovCvtToStr(m_insertLineno);
|
||||
ckeyps[1]="lineno"; valps[1]=linestr.c_str();
|
||||
// Default page if not specified
|
||||
const char* fnstartp = m_insertFilenamep;
|
||||
while (const char* foundp = strchr(fnstartp,'/')) fnstartp=foundp+1;
|
||||
const char* fnendp = fnstartp;
|
||||
while (*fnendp && *fnendp!='.') fnendp++;
|
||||
std::string page_default = "sp_user/"+std::string(fnstartp,fnendp-fnstartp);
|
||||
ckeyps[2]="page"; valps[2]=page_default.c_str();
|
||||
VerilatedLockGuard lock(m_mutex);
|
||||
assert(m_insertp);
|
||||
// First two key/vals are filename
|
||||
ckeyps[0]="filename"; valps[0]=m_insertFilenamep;
|
||||
std::string linestr = vlCovCvtToStr(m_insertLineno);
|
||||
ckeyps[1]="lineno"; valps[1]=linestr.c_str();
|
||||
// Default page if not specified
|
||||
const char* fnstartp = m_insertFilenamep;
|
||||
while (const char* foundp = strchr(fnstartp,'/')) fnstartp = foundp+1;
|
||||
const char* fnendp = fnstartp;
|
||||
while (*fnendp && *fnendp!='.') fnendp++;
|
||||
std::string page_default = "sp_user/"+std::string(fnstartp, fnendp-fnstartp);
|
||||
ckeyps[2]="page"; valps[2]=page_default.c_str();
|
||||
|
||||
// Keys -> strings
|
||||
std::string keys[MAX_KEYS];
|
||||
for (int i=0; i<MAX_KEYS; ++i) {
|
||||
if (ckeyps[i] && ckeyps[i][0]) {
|
||||
keys[i] = ckeyps[i];
|
||||
}
|
||||
}
|
||||
// Ignore empty keys
|
||||
for (int i=0; i<MAX_KEYS; ++i) {
|
||||
// Keys -> strings
|
||||
std::string keys[MAX_KEYS];
|
||||
for (int i=0; i<MAX_KEYS; ++i) {
|
||||
if (ckeyps[i] && ckeyps[i][0]) {
|
||||
keys[i] = ckeyps[i];
|
||||
}
|
||||
}
|
||||
// Ignore empty keys
|
||||
for (int i=0; i<MAX_KEYS; ++i) {
|
||||
if (!keys[i].empty()) {
|
||||
for (int j=i+1; j<MAX_KEYS; ++j) {
|
||||
if (keys[i] == keys[j]) { // Duplicate key. Keep the last one
|
||||
keys[i] = "";
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// Insert the values
|
||||
int addKeynum=0;
|
||||
for (int i=0; i<MAX_KEYS; ++i) {
|
||||
const std::string key = keys[i];
|
||||
for (int j=i+1; j<MAX_KEYS; ++j) {
|
||||
if (keys[i] == keys[j]) { // Duplicate key. Keep the last one
|
||||
keys[i] = "";
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// Insert the values
|
||||
int addKeynum = 0;
|
||||
for (int i=0; i<MAX_KEYS; ++i) {
|
||||
const std::string key = keys[i];
|
||||
if (!keys[i].empty()) {
|
||||
const std::string val = valps[i];
|
||||
//cout<<" "<<__FUNCTION__<<" "<<key<<" = "<<val<<endl;
|
||||
m_insertp->m_keys[addKeynum] = valueIndex(key);
|
||||
m_insertp->m_vals[addKeynum] = valueIndex(val);
|
||||
addKeynum++;
|
||||
if (!legalKey(key)) {
|
||||
std::string msg = "%Error: Coverage keys of one character, or letter+digit are illegal: "+key;
|
||||
VL_FATAL_MT("",0,"",msg.c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
m_items.push_back(m_insertp);
|
||||
// Prepare for next
|
||||
m_insertp = NULL;
|
||||
const std::string val = valps[i];
|
||||
//cout<<" "<<__FUNCTION__<<" "<<key<<" = "<<val<<endl;
|
||||
m_insertp->m_keys[addKeynum] = valueIndex(key);
|
||||
m_insertp->m_vals[addKeynum] = valueIndex(val);
|
||||
addKeynum++;
|
||||
if (!legalKey(key)) {
|
||||
std::string msg = "%Error: Coverage keys of one character, or letter+digit are illegal: "+key;
|
||||
VL_FATAL_MT("", 0, "", msg.c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
m_items.push_back(m_insertp);
|
||||
// Prepare for next
|
||||
m_insertp = NULL;
|
||||
}
|
||||
|
||||
void write(const char* filename) VL_EXCLUDES(m_mutex) {
|
||||
Verilated::quiesce();
|
||||
VerilatedLockGuard lock(m_mutex);
|
||||
Verilated::quiesce();
|
||||
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\n");
|
||||
#endif
|
||||
selftest();
|
||||
selftest();
|
||||
|
||||
std::ofstream os(filename);
|
||||
if (os.fail()) {
|
||||
std::string msg = std::string("%Error: Can't write '")+filename+"'";
|
||||
VL_FATAL_MT("",0,"",msg.c_str());
|
||||
return;
|
||||
}
|
||||
os << "# SystemC::Coverage-3\n";
|
||||
if (os.fail()) {
|
||||
std::string msg = std::string("%Error: Can't write '")+filename+"'";
|
||||
VL_FATAL_MT("", 0, "", msg.c_str());
|
||||
return;
|
||||
}
|
||||
os << "# SystemC::Coverage-3\n";
|
||||
|
||||
// Build list of events; totalize if collapsing hierarchy
|
||||
typedef std::map<std::string,std::pair<std::string,vluint64_t> > EventMap;
|
||||
EventMap eventCounts;
|
||||
for (ItemList::iterator it=m_items.begin(); it!=m_items.end(); ++it) {
|
||||
VerilatedCovImpItem* itemp = *(it);
|
||||
std::string name;
|
||||
std::string hier;
|
||||
bool per_instance = false;
|
||||
// Build list of events; totalize if collapsing hierarchy
|
||||
typedef std::map<std::string,std::pair<std::string,vluint64_t> > EventMap;
|
||||
EventMap eventCounts;
|
||||
for (ItemList::iterator it=m_items.begin(); it!=m_items.end(); ++it) {
|
||||
VerilatedCovImpItem* itemp = *(it);
|
||||
std::string name;
|
||||
std::string hier;
|
||||
bool per_instance = false;
|
||||
|
||||
for (int i=0; i<MAX_KEYS; ++i) {
|
||||
if (itemp->m_keys[i] != KEY_UNDEF) {
|
||||
std::string key = VerilatedCovKey::shortKey(m_indexValues[itemp->m_keys[i]]);
|
||||
std::string val = m_indexValues[itemp->m_vals[i]];
|
||||
if (key == VL_CIK_PER_INSTANCE) {
|
||||
if (val != "0") per_instance = true;
|
||||
}
|
||||
if (key == VL_CIK_HIER) {
|
||||
hier = val;
|
||||
} else {
|
||||
// Print it
|
||||
name += keyValueFormatter(key,val);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (per_instance) { // Not collapsing hierarchies
|
||||
name += keyValueFormatter(VL_CIK_HIER,hier);
|
||||
hier = "";
|
||||
}
|
||||
for (int i=0; i<MAX_KEYS; ++i) {
|
||||
if (itemp->m_keys[i] != KEY_UNDEF) {
|
||||
std::string key = VerilatedCovKey::shortKey(m_indexValues[itemp->m_keys[i]]);
|
||||
std::string val = m_indexValues[itemp->m_vals[i]];
|
||||
if (key == VL_CIK_PER_INSTANCE) {
|
||||
if (val != "0") per_instance = true;
|
||||
}
|
||||
if (key == VL_CIK_HIER) {
|
||||
hier = val;
|
||||
} else {
|
||||
// Print it
|
||||
name += keyValueFormatter(key, val);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (per_instance) { // Not collapsing hierarchies
|
||||
name += keyValueFormatter(VL_CIK_HIER, hier);
|
||||
hier = "";
|
||||
}
|
||||
|
||||
// Group versus point labels don't matter here, downstream
|
||||
// deals with it. Seems bad for sizing though and doesn't
|
||||
// allow easy addition of new group codes (would be
|
||||
// inefficient)
|
||||
// Group versus point labels don't matter here, downstream
|
||||
// deals with it. Seems bad for sizing though and doesn't
|
||||
// allow easy addition of new group codes (would be
|
||||
// inefficient)
|
||||
|
||||
// Find or insert the named event
|
||||
EventMap::iterator cit = eventCounts.find(name);
|
||||
if (cit != eventCounts.end()) {
|
||||
const std::string& oldhier = cit->second.first;
|
||||
cit->second.second += itemp->count();
|
||||
cit->second.first = combineHier(oldhier, hier);
|
||||
} else {
|
||||
eventCounts.insert(std::make_pair(name, make_pair(hier,itemp->count())));
|
||||
}
|
||||
}
|
||||
// Find or insert the named event
|
||||
EventMap::iterator cit = eventCounts.find(name);
|
||||
if (cit != eventCounts.end()) {
|
||||
const std::string& oldhier = cit->second.first;
|
||||
cit->second.second += itemp->count();
|
||||
cit->second.first = combineHier(oldhier, hier);
|
||||
} else {
|
||||
eventCounts.insert(std::make_pair(name, make_pair(hier, itemp->count())));
|
||||
}
|
||||
}
|
||||
|
||||
// Output body
|
||||
for (EventMap::const_iterator it=eventCounts.begin(); it!=eventCounts.end(); ++it) {
|
||||
os<<"C '"<<std::dec;
|
||||
os<<it->first;
|
||||
if (!it->second.first.empty()) os<<keyValueFormatter(VL_CIK_HIER,it->second.first);
|
||||
os<<"' "<<it->second.second;
|
||||
os<<std::endl;
|
||||
}
|
||||
// Output body
|
||||
for (EventMap::const_iterator it=eventCounts.begin(); it!=eventCounts.end(); ++it) {
|
||||
os<<"C '"<<std::dec;
|
||||
os<<it->first;
|
||||
if (!it->second.first.empty()) os<<keyValueFormatter(VL_CIK_HIER, it->second.first);
|
||||
os<<"' "<<it->second.second;
|
||||
os<<std::endl;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@ -420,7 +420,7 @@ void VerilatedCov::_inserti(vluint64_t* itemp) VL_MT_SAFE {
|
||||
VerilatedCovImp::imp().inserti(new VerilatedCoverItemSpec<vluint64_t>(itemp));
|
||||
}
|
||||
void VerilatedCov::_insertf(const char* filename, int lineno) VL_MT_SAFE {
|
||||
VerilatedCovImp::imp().insertf(filename,lineno);
|
||||
VerilatedCovImp::imp().insertf(filename, lineno);
|
||||
}
|
||||
|
||||
#define K(n) const char* key ## n
|
||||
@ -446,14 +446,14 @@ void VerilatedCov::_insertp(A(0),A(1),A(2),A(3),A(4),A(5),A(6),A(7),A(8),A(9),
|
||||
// And versions with fewer arguments (oh for a language with named parameters!)
|
||||
void VerilatedCov::_insertp(A(0),A(1),A(2),A(3),A(4),A(5),A(6),A(7),A(8),A(9)) VL_MT_SAFE {
|
||||
_insertp(C(0),C(1),C(2),C(3),C(4),C(5),C(6),C(7),C(8),C(9),
|
||||
N(10),N(11),N(12),N(13),N(14),N(15),N(16),N(17),N(18),N(19),
|
||||
N(20),N(21),N(22),N(23),N(24),N(25),N(26),N(27),N(28),N(29));
|
||||
N(10),N(11),N(12),N(13),N(14),N(15),N(16),N(17),N(18),N(19),
|
||||
N(20),N(21),N(22),N(23),N(24),N(25),N(26),N(27),N(28),N(29));
|
||||
}
|
||||
void VerilatedCov::_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)) VL_MT_SAFE {
|
||||
_insertp(C(0),C(1),C(2),C(3),C(4),C(5),C(6),C(7),C(8),C(9),
|
||||
C(10),C(11),C(12),C(13),C(14),C(15),C(16),C(17),C(18),C(19),
|
||||
N(20),N(21),N(22),N(23),N(24),N(25),N(26),N(27),N(28),N(29));
|
||||
C(10),C(11),C(12),C(13),C(14),C(15),C(16),C(17),C(18),C(19),
|
||||
N(20),N(21),N(22),N(23),N(24),N(25),N(26),N(27),N(28),N(29));
|
||||
}
|
||||
// Backward compatibility for Verilator
|
||||
void VerilatedCov::_insertp(A(0), A(1), K(2),int val2, K(3),int val3,
|
||||
@ -461,10 +461,10 @@ void VerilatedCov::_insertp(A(0), A(1), K(2),int val2, K(3),int val3,
|
||||
std::string val2str = vlCovCvtToStr(val2);
|
||||
std::string val3str = vlCovCvtToStr(val3);
|
||||
_insertp(C(0),C(1),
|
||||
key2,val2str.c_str(), key3,val3str.c_str(), key4, val4.c_str(),
|
||||
C(5),C(6),N(7),N(8),N(9),
|
||||
N(10),N(11),N(12),N(13),N(14),N(15),N(16),N(17),N(18),N(19),
|
||||
N(20),N(21),N(22),N(23),N(24),N(25),N(26),N(27),N(28),N(29));
|
||||
key2,val2str.c_str(), key3,val3str.c_str(), key4, val4.c_str(),
|
||||
C(5),C(6),N(7),N(8),N(9),
|
||||
N(10),N(11),N(12),N(13),N(14),N(15),N(16),N(17),N(18),N(19),
|
||||
N(20),N(21),N(22),N(23),N(24),N(25),N(26),N(27),N(28),N(29));
|
||||
}
|
||||
#undef A
|
||||
#undef C
|
||||
|
@ -44,31 +44,31 @@
|
||||
/// 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.
|
||||
/// 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.
|
||||
///
|
||||
/// Examples:
|
||||
///
|
||||
/// vluint32_t m_cases[10];
|
||||
/// constructor {
|
||||
/// for (int i=0; i<10; ++i) { m_cases[i]=0; }
|
||||
/// vluint32_t m_cases[10];
|
||||
/// constructor {
|
||||
/// for (int i=0; i<10; ++i) { m_cases[i]=0; }
|
||||
/// }
|
||||
/// for (int i=0; i<10; ++i) {
|
||||
/// VL_COVER_INSERT(&m_cases[i], "comment", "Coverage Case", "i", cvtToNumStr(i));
|
||||
/// }
|
||||
/// for (int i=0; i<10; ++i) {
|
||||
/// VL_COVER_INSERT(&m_cases[i], "comment", "Coverage Case", "i", cvtToNumStr(i));
|
||||
/// }
|
||||
|
||||
#define VL_COVER_INSERT(countp,args...) \
|
||||
VL_IF_COVER(VerilatedCov::_inserti(countp); \
|
||||
VerilatedCov::_insertf(__FILE__,__LINE__); \
|
||||
VerilatedCov::_insertp("hier", name(), args))
|
||||
VL_IF_COVER(VerilatedCov::_inserti(countp); \
|
||||
VerilatedCov::_insertf(__FILE__,__LINE__); \
|
||||
VerilatedCov::_insertp("hier", name(), args))
|
||||
|
||||
//=============================================================================
|
||||
/// Convert VL_COVER_INSERT value arguments to strings
|
||||
|
@ -56,17 +56,17 @@ bool VerilatedDeserialize::readDiffers(const void* __restrict datap, size_t size
|
||||
const vluint8_t* __restrict dp = static_cast<const vluint8_t* __restrict>(datap);
|
||||
vluint8_t miss = 0;
|
||||
while (size--) {
|
||||
miss |= (*dp++ ^ *m_cp++);
|
||||
miss |= (*dp++ ^ *m_cp++);
|
||||
}
|
||||
return (miss!=0);
|
||||
}
|
||||
|
||||
VerilatedDeserialize& VerilatedDeserialize::readAssert(const void* __restrict datap, size_t size) VL_MT_UNSAFE_ONE {
|
||||
if (VL_UNLIKELY(readDiffers(datap,size))) {
|
||||
std::string fn = filename();
|
||||
std::string msg = std::string("Can't deserialize save-restore file as was made from different model");
|
||||
VL_FATAL_MT(fn.c_str(), 0, "", msg.c_str());
|
||||
close();
|
||||
if (VL_UNLIKELY(readDiffers(datap, size))) {
|
||||
std::string fn = filename();
|
||||
std::string msg = std::string("Can't deserialize save-restore file as was made from different model");
|
||||
VL_FATAL_MT(fn.c_str(), 0, "", msg.c_str());
|
||||
close();
|
||||
}
|
||||
return *this; // For function chaining
|
||||
}
|
||||
@ -84,10 +84,10 @@ void VerilatedSerialize::header() VL_MT_UNSAFE_ONE {
|
||||
void VerilatedDeserialize::header() VL_MT_UNSAFE_ONE {
|
||||
VerilatedDeserialize& os = *this; // So can cut and paste standard >> code below
|
||||
if (VL_UNLIKELY(os.readDiffers(VLTSAVE_HEADER_STR, strlen(VLTSAVE_HEADER_STR)))) {
|
||||
std::string fn = filename();
|
||||
std::string msg = std::string("Can't deserialize; file has wrong header signature");
|
||||
VL_FATAL_MT(fn.c_str(), 0, "", msg.c_str());
|
||||
close();
|
||||
std::string fn = filename();
|
||||
std::string msg = std::string("Can't deserialize; file has wrong header signature");
|
||||
VL_FATAL_MT(fn.c_str(), 0, "", msg.c_str());
|
||||
close();
|
||||
}
|
||||
os.read(Verilated::serializedPtr(), Verilated::serializedSize());
|
||||
}
|
||||
@ -101,10 +101,10 @@ void VerilatedSerialize::trailer() VL_MT_UNSAFE_ONE {
|
||||
void VerilatedDeserialize::trailer() VL_MT_UNSAFE_ONE {
|
||||
VerilatedDeserialize& os = *this; // So can cut and paste standard >> code below
|
||||
if (VL_UNLIKELY(os.readDiffers(VLTSAVE_TRAILER_STR, strlen(VLTSAVE_TRAILER_STR)))) {
|
||||
std::string fn = filename();
|
||||
std::string msg = std::string("Can't deserialize; file has wrong end-of-file signature");
|
||||
VL_FATAL_MT(fn.c_str(), 0, "", msg.c_str());
|
||||
close();
|
||||
std::string fn = filename();
|
||||
std::string msg = std::string("Can't deserialize; file has wrong end-of-file signature");
|
||||
VL_FATAL_MT(fn.c_str(), 0, "", msg.c_str());
|
||||
close();
|
||||
}
|
||||
}
|
||||
|
||||
@ -116,19 +116,19 @@ void VerilatedDeserialize::trailer() VL_MT_UNSAFE_ONE {
|
||||
void VerilatedSave::open(const char* filenamep) VL_MT_UNSAFE_ONE {
|
||||
m_assertOne.check();
|
||||
if (isOpen()) return;
|
||||
VL_DEBUG_IF(VL_DBG_MSGF("- save: opening save file %s\n",filenamep););
|
||||
VL_DEBUG_IF(VL_DBG_MSGF("- save: opening save file %s\n", filenamep););
|
||||
|
||||
if (filenamep[0]=='|') {
|
||||
assert(0); // Not supported yet.
|
||||
} else {
|
||||
// cppcheck-suppress duplicateExpression
|
||||
// cppcheck-suppress duplicateExpression
|
||||
m_fd = ::open(filenamep, O_CREAT|O_WRONLY|O_TRUNC|O_LARGEFILE|O_NONBLOCK|O_CLOEXEC
|
||||
, 0666);
|
||||
if (m_fd<0) {
|
||||
// User code can check isOpen()
|
||||
m_isOpen = false;
|
||||
return;
|
||||
}
|
||||
if (m_fd<0) {
|
||||
// User code can check isOpen()
|
||||
m_isOpen = false;
|
||||
return;
|
||||
}
|
||||
}
|
||||
m_isOpen = true;
|
||||
m_filename = filenamep;
|
||||
@ -139,19 +139,19 @@ void VerilatedSave::open(const char* filenamep) VL_MT_UNSAFE_ONE {
|
||||
void VerilatedRestore::open(const char* filenamep) VL_MT_UNSAFE_ONE {
|
||||
m_assertOne.check();
|
||||
if (isOpen()) return;
|
||||
VL_DEBUG_IF(VL_DBG_MSGF("- restore: opening restore file %s\n",filenamep););
|
||||
VL_DEBUG_IF(VL_DBG_MSGF("- restore: opening restore file %s\n", filenamep););
|
||||
|
||||
if (filenamep[0]=='|') {
|
||||
assert(0); // Not supported yet.
|
||||
} else {
|
||||
// cppcheck-suppress duplicateExpression
|
||||
// cppcheck-suppress duplicateExpression
|
||||
m_fd = ::open(filenamep, O_CREAT|O_RDONLY|O_LARGEFILE|O_CLOEXEC
|
||||
, 0666);
|
||||
if (m_fd<0) {
|
||||
// User code can check isOpen()
|
||||
m_isOpen = false;
|
||||
return;
|
||||
}
|
||||
if (m_fd<0) {
|
||||
// User code can check isOpen()
|
||||
m_isOpen = false;
|
||||
return;
|
||||
}
|
||||
}
|
||||
m_isOpen = true;
|
||||
m_filename = filenamep;
|
||||
@ -184,21 +184,21 @@ void VerilatedSave::flush() VL_MT_UNSAFE_ONE {
|
||||
if (VL_UNLIKELY(!isOpen())) return;
|
||||
vluint8_t* wp = m_bufp;
|
||||
while (1) {
|
||||
ssize_t remaining = (m_cp - wp);
|
||||
if (remaining==0) break;
|
||||
errno = 0;
|
||||
ssize_t remaining = (m_cp - wp);
|
||||
if (remaining==0) break;
|
||||
errno = 0;
|
||||
ssize_t got = ::write(m_fd, wp, remaining);
|
||||
if (got>0) {
|
||||
wp += got;
|
||||
} else if (got < 0) {
|
||||
if (errno != EAGAIN && errno != EINTR) {
|
||||
// write failed, presume error (perhaps out of disk space)
|
||||
std::string msg = std::string(__FUNCTION__)+": "+strerror(errno);
|
||||
VL_FATAL_MT("",0,"",msg.c_str());
|
||||
close();
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (got>0) {
|
||||
wp += got;
|
||||
} else if (got < 0) {
|
||||
if (errno != EAGAIN && errno != EINTR) {
|
||||
// write failed, presume error (perhaps out of disk space)
|
||||
std::string msg = std::string(__FUNCTION__)+": "+strerror(errno);
|
||||
VL_FATAL_MT("", 0, "", msg.c_str());
|
||||
close();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
m_cp = m_bufp; // Reset buffer
|
||||
}
|
||||
@ -213,30 +213,28 @@ void VerilatedRestore::fill() VL_MT_UNSAFE_ONE {
|
||||
m_cp = m_bufp; // Reset buffer
|
||||
// Read into buffer starting at m_endp
|
||||
while (1) {
|
||||
ssize_t remaining = (m_bufp+bufferSize() - m_endp);
|
||||
if (remaining==0) break;
|
||||
errno = 0;
|
||||
ssize_t remaining = (m_bufp+bufferSize() - m_endp);
|
||||
if (remaining==0) break;
|
||||
errno = 0;
|
||||
ssize_t got = ::read(m_fd, m_endp, remaining);
|
||||
if (got>0) {
|
||||
m_endp += got;
|
||||
} else if (got < 0) {
|
||||
if (errno != EAGAIN && errno != EINTR) {
|
||||
// write failed, presume error (perhaps out of disk space)
|
||||
std::string msg = std::string(__FUNCTION__)+": "+strerror(errno);
|
||||
VL_FATAL_MT("",0,"",msg.c_str());
|
||||
close();
|
||||
break;
|
||||
if (got>0) {
|
||||
m_endp += got;
|
||||
} else if (got < 0) {
|
||||
if (errno != EAGAIN && errno != EINTR) {
|
||||
// write failed, presume error (perhaps out of disk space)
|
||||
std::string msg = std::string(__FUNCTION__)+": "+strerror(errno);
|
||||
VL_FATAL_MT("", 0, "", msg.c_str());
|
||||
close();
|
||||
break;
|
||||
}
|
||||
} else { // got==0, EOF
|
||||
// Fill buffer from here to end with NULLs so reader's don't
|
||||
// need to check eof each character.
|
||||
while (m_endp < m_bufp+bufferSize()) *m_endp++ = '\0';
|
||||
break;
|
||||
}
|
||||
while (m_endp < m_bufp+bufferSize()) *m_endp++ = '\0';
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
// Serialization of types
|
||||
|
||||
|
||||
|
@ -34,10 +34,10 @@ class VerilatedSerialize {
|
||||
protected:
|
||||
// MEMBERS
|
||||
// For speed, keep m_cp as the first member of this structure
|
||||
vluint8_t* m_cp; ///< Current pointer into m_bufp buffer
|
||||
vluint8_t* m_bufp; ///< Output buffer
|
||||
bool m_isOpen; ///< True indicates open file/stream
|
||||
std::string m_filename; ///< Filename, for error messages
|
||||
vluint8_t* m_cp; ///< Current pointer into m_bufp buffer
|
||||
vluint8_t* m_bufp; ///< Output buffer
|
||||
bool m_isOpen; ///< True indicates open file/stream
|
||||
std::string m_filename; ///< Filename, for error messages
|
||||
VerilatedAssertOneThread m_assertOne; ///< Assert only called from single thread
|
||||
|
||||
inline static size_t bufferSize() { return 256*1024; } // See below for slack calculation
|
||||
@ -50,13 +50,13 @@ protected:
|
||||
VL_UNCOPYABLE(VerilatedSerialize);
|
||||
public:
|
||||
VerilatedSerialize() {
|
||||
m_isOpen = false;
|
||||
m_bufp = new vluint8_t [bufferSize()];
|
||||
m_cp = m_bufp;
|
||||
m_isOpen = false;
|
||||
m_bufp = new vluint8_t [bufferSize()];
|
||||
m_cp = m_bufp;
|
||||
}
|
||||
virtual ~VerilatedSerialize() {
|
||||
close();
|
||||
if (m_bufp) { delete m_bufp; m_bufp=NULL; }
|
||||
close();
|
||||
if (m_bufp) { delete m_bufp; m_bufp=NULL; }
|
||||
}
|
||||
// METHODS
|
||||
bool isOpen() const { return m_isOpen; }
|
||||
@ -64,24 +64,24 @@ public:
|
||||
virtual void close() VL_MT_UNSAFE_ONE { flush(); }
|
||||
virtual void flush() VL_MT_UNSAFE_ONE {}
|
||||
inline VerilatedSerialize& write(const void* __restrict datap, size_t size) VL_MT_UNSAFE_ONE {
|
||||
const vluint8_t* __restrict dp = (const vluint8_t* __restrict)datap;
|
||||
while (size) {
|
||||
bufferCheck();
|
||||
size_t blk = size; if (blk>bufferInsertSize()) blk = bufferInsertSize();
|
||||
const vluint8_t* __restrict maxp = dp + blk;
|
||||
while (dp < maxp) *m_cp++ = *dp++;
|
||||
size -= blk;
|
||||
}
|
||||
return *this; // For function chaining
|
||||
const vluint8_t* __restrict dp = (const vluint8_t* __restrict)datap;
|
||||
while (size) {
|
||||
bufferCheck();
|
||||
size_t blk = size; if (blk>bufferInsertSize()) blk = bufferInsertSize();
|
||||
const vluint8_t* __restrict maxp = dp + blk;
|
||||
while (dp < maxp) *m_cp++ = *dp++;
|
||||
size -= blk;
|
||||
}
|
||||
return *this; // For function chaining
|
||||
}
|
||||
private:
|
||||
VerilatedSerialize& bufferCheck() VL_MT_UNSAFE_ONE {
|
||||
// Flush the write buffer if there's not enough space left for new information
|
||||
// We only call this once per vector, so we need enough slop for a very wide "b###" line
|
||||
if (VL_UNLIKELY(m_cp > (m_bufp+(bufferSize()-bufferInsertSize())))) {
|
||||
flush();
|
||||
}
|
||||
return *this; // For function chaining
|
||||
// Flush the write buffer if there's not enough space left for new information
|
||||
// We only call this once per vector, so we need enough slop for a very wide "b###" line
|
||||
if (VL_UNLIKELY(m_cp > (m_bufp+(bufferSize()-bufferInsertSize())))) {
|
||||
flush();
|
||||
}
|
||||
return *this; // For function chaining
|
||||
}
|
||||
};
|
||||
|
||||
@ -93,12 +93,12 @@ class VerilatedDeserialize {
|
||||
protected:
|
||||
// MEMBERS
|
||||
// For speed, keep m_cp as the first member of this structure
|
||||
vluint8_t* m_cp; ///< Current pointer into m_bufp buffer
|
||||
vluint8_t* m_bufp; ///< Output buffer
|
||||
vluint8_t* m_endp; ///< Last valid byte in m_bufp buffer
|
||||
bool m_isOpen; ///< True indicates open file/stream
|
||||
std::string m_filename; ///< Filename, for error messages
|
||||
VerilatedAssertOneThread m_assertOne; ///< Assert only called from single thread
|
||||
vluint8_t* m_cp; ///< Current pointer into m_bufp buffer
|
||||
vluint8_t* m_bufp; ///< Output buffer
|
||||
vluint8_t* m_endp; ///< Last valid byte in m_bufp buffer
|
||||
bool m_isOpen; ///< True indicates open file/stream
|
||||
std::string m_filename; ///< Filename, for error messages
|
||||
VerilatedAssertOneThread m_assertOne; ///< Assert only called from single thread
|
||||
|
||||
inline static size_t bufferSize() { return 256*1024; } // See below for slack calculation
|
||||
inline static size_t bufferInsertSize() { return 16*1024; }
|
||||
@ -111,14 +111,14 @@ protected:
|
||||
VL_UNCOPYABLE(VerilatedDeserialize);
|
||||
public:
|
||||
VerilatedDeserialize() {
|
||||
m_isOpen = false;
|
||||
m_bufp = new vluint8_t [bufferSize()];
|
||||
m_cp = m_bufp;
|
||||
m_endp = NULL;
|
||||
m_isOpen = false;
|
||||
m_bufp = new vluint8_t [bufferSize()];
|
||||
m_cp = m_bufp;
|
||||
m_endp = NULL;
|
||||
}
|
||||
virtual ~VerilatedDeserialize() {
|
||||
close();
|
||||
if (m_bufp) { delete m_bufp; m_bufp=NULL; }
|
||||
close();
|
||||
if (m_bufp) { delete m_bufp; m_bufp=NULL; }
|
||||
}
|
||||
// METHODS
|
||||
bool isOpen() const { return m_isOpen; }
|
||||
@ -126,15 +126,15 @@ public:
|
||||
virtual void close() VL_MT_UNSAFE_ONE { flush(); }
|
||||
virtual void flush() VL_MT_UNSAFE_ONE {}
|
||||
inline VerilatedDeserialize& read(void* __restrict datap, size_t size) VL_MT_UNSAFE_ONE {
|
||||
vluint8_t* __restrict dp = (vluint8_t* __restrict)datap;
|
||||
while (size) {
|
||||
bufferCheck();
|
||||
size_t blk = size; if (blk>bufferInsertSize()) blk = bufferInsertSize();
|
||||
const vluint8_t* __restrict maxp = dp + blk;
|
||||
while (dp < maxp) *dp++ = *m_cp++;
|
||||
size -= blk;
|
||||
}
|
||||
return *this; // For function chaining
|
||||
vluint8_t* __restrict dp = (vluint8_t* __restrict)datap;
|
||||
while (size) {
|
||||
bufferCheck();
|
||||
size_t blk = size; if (blk>bufferInsertSize()) blk = bufferInsertSize();
|
||||
const vluint8_t* __restrict maxp = dp + blk;
|
||||
while (dp < maxp) *dp++ = *m_cp++;
|
||||
size -= blk;
|
||||
}
|
||||
return *this; // For function chaining
|
||||
}
|
||||
// Read a datum and compare with expected value
|
||||
VerilatedDeserialize& readAssert(const void* __restrict datap, size_t size) VL_MT_UNSAFE_ONE;
|
||||
@ -143,12 +143,12 @@ public:
|
||||
private:
|
||||
bool readDiffers(const void* __restrict datap, size_t size) VL_MT_UNSAFE_ONE;
|
||||
VerilatedDeserialize& bufferCheck() VL_MT_UNSAFE_ONE {
|
||||
// Flush the write buffer if there's not enough space left for new information
|
||||
// We only call this once per vector, so we need enough slop for a very wide "b###" line
|
||||
if (VL_UNLIKELY((m_cp+bufferInsertSize()) > m_endp)) {
|
||||
fill();
|
||||
}
|
||||
return *this; // For function chaining
|
||||
// Flush the write buffer if there's not enough space left for new information
|
||||
// We only call this once per vector, so we need enough slop for a very wide "b###" line
|
||||
if (VL_UNLIKELY((m_cp+bufferInsertSize()) > m_endp)) {
|
||||
fill();
|
||||
}
|
||||
return *this; // For function chaining
|
||||
}
|
||||
};
|
||||
|
||||
@ -158,7 +158,7 @@ private:
|
||||
|
||||
class VerilatedSave : public VerilatedSerialize {
|
||||
private:
|
||||
int m_fd; ///< File descriptor we're writing to
|
||||
int m_fd; ///< File descriptor we're writing to
|
||||
|
||||
public:
|
||||
// CONSTRUCTORS
|
||||
@ -177,7 +177,7 @@ public:
|
||||
|
||||
class VerilatedRestore : public VerilatedDeserialize {
|
||||
private:
|
||||
int m_fd; ///< File descriptor we're writing to
|
||||
int m_fd; ///< File descriptor we're writing to
|
||||
|
||||
public:
|
||||
// CONSTRUCTORS
|
||||
@ -237,12 +237,12 @@ inline VerilatedDeserialize& operator>>(VerilatedDeserialize& os, float& rhs) {
|
||||
return os.read(&rhs, sizeof(rhs));
|
||||
}
|
||||
inline VerilatedSerialize& operator<<(VerilatedSerialize& os, std::string& rhs) {
|
||||
vluint32_t len=rhs.length();
|
||||
vluint32_t len = rhs.length();
|
||||
os<<len;
|
||||
return os.write(rhs.data(), len);
|
||||
}
|
||||
inline VerilatedDeserialize& operator>>(VerilatedDeserialize& os, std::string& rhs) {
|
||||
vluint32_t len=0;
|
||||
vluint32_t len = 0;
|
||||
os>>len;
|
||||
rhs.resize(len);
|
||||
return os.read((void*)rhs.data(), len);
|
||||
|
@ -16,11 +16,11 @@
|
||||
/// \file
|
||||
/// \brief Verilator: Common include for OS portability (verilated & verilator)
|
||||
///
|
||||
/// This header is used by both the Verilator source code (run on the
|
||||
/// build and host system), and the Verilated output (run on the target
|
||||
/// system). Code needed by only the host system goes into
|
||||
/// config_build.h.in, code needed by Verilated code only goes into
|
||||
/// verilated.h, and code needed by both goes here (verilatedos.h).
|
||||
/// This header is used by both the Verilator source code (run on the
|
||||
/// build and host system), and the Verilated output (run on the target
|
||||
/// system). Code needed by only the host system goes into
|
||||
/// config_build.h.in, code needed by Verilated code only goes into
|
||||
/// verilated.h, and code needed by both goes here (verilatedos.h).
|
||||
///
|
||||
/// Code available from: http://www.veripool.org/verilator
|
||||
///
|
||||
@ -54,8 +54,8 @@
|
||||
# define VL_EXCLUDES(x) __attribute__ ((locks_excluded(x)))
|
||||
# define VL_SCOPED_CAPABILITY __attribute__ ((scoped_lockable))
|
||||
# endif
|
||||
# define VL_LIKELY(x) __builtin_expect(!!(x), 1)
|
||||
# define VL_UNLIKELY(x) __builtin_expect(!!(x), 0)
|
||||
# define VL_LIKELY(x) __builtin_expect(!!(x), 1)
|
||||
# define VL_UNLIKELY(x) __builtin_expect(!!(x), 0)
|
||||
# define VL_UNREACHABLE __builtin_unreachable();
|
||||
# define VL_PREFETCH_RD(p) __builtin_prefetch((p),0)
|
||||
# define VL_PREFETCH_RW(p) __builtin_prefetch((p),1)
|
||||
@ -65,51 +65,51 @@
|
||||
|
||||
// Defaults for unsupported compiler features
|
||||
#ifndef VL_ATTR_ALIGNED
|
||||
# define VL_ATTR_ALIGNED(alignment) ///< Align structure to specified byte alignment
|
||||
# define VL_ATTR_ALIGNED(alignment) ///< Align structure to specified byte alignment
|
||||
#endif
|
||||
#ifndef VL_ATTR_ALWINLINE
|
||||
# define VL_ATTR_ALWINLINE ///< Inline, even when not optimizing
|
||||
# define VL_ATTR_ALWINLINE ///< Inline, even when not optimizing
|
||||
#endif
|
||||
#ifndef VL_ATTR_NORETURN
|
||||
# define VL_ATTR_NORETURN ///< Function does not ever return
|
||||
# define VL_ATTR_NORETURN ///< Function does not ever return
|
||||
#endif
|
||||
#ifndef VL_ATTR_PRINTF
|
||||
# define VL_ATTR_PRINTF(fmtArgNum) ///< Function with printf format checking
|
||||
# define VL_ATTR_PRINTF(fmtArgNum) ///< Function with printf format checking
|
||||
#endif
|
||||
#ifndef VL_ATTR_PURE
|
||||
# define VL_ATTR_PURE ///< Function is pure (and thus also VL_MT_SAFE)
|
||||
# define VL_ATTR_PURE ///< Function is pure (and thus also VL_MT_SAFE)
|
||||
#endif
|
||||
#ifndef VL_ATTR_UNUSED
|
||||
# define VL_ATTR_UNUSED ///< Function that may be never used
|
||||
# define VL_ATTR_UNUSED ///< Function that may be never used
|
||||
#endif
|
||||
#ifndef VL_FUNC
|
||||
# define VL_FUNC "__func__" ///< Name of current function for error macros
|
||||
# define VL_FUNC "__func__" ///< Name of current function for error macros
|
||||
#endif
|
||||
#ifndef VL_CAPABILITY
|
||||
# define VL_ACQUIRE(...) ///< Function requires a capability/lock (-fthread-safety)
|
||||
# define VL_ACQUIRE_SHARED(...) ///< Function aquires a shared capability/lock (-fthread-safety)
|
||||
# define VL_RELEASE(...) ///< Function releases a capability/lock (-fthread-safety)
|
||||
# define VL_RELEASE_SHARED(...) ///< Function releases a shared capability/lock (-fthread-safety)
|
||||
# define VL_TRY_ACQUIRE(...) ///< Function returns bool if aquired a capability (-fthread-safety)
|
||||
# define VL_TRY_ACQUIRE_SHARED(...) ///< Function returns bool if aquired a shared capability (-fthread-safety)
|
||||
# define VL_REQUIRES(x) ///< Function requires a capability inbound (-fthread-safety)
|
||||
# define VL_EXCLUDES(x) ///< Function requires not having a capability inbound (-fthread-safety)
|
||||
# define VL_CAPABILITY(x) ///< Name of capability/lock (-fthread-safety)
|
||||
# define VL_GUARDED_BY(x) ///< Name of mutex protecting this variable (-fthread-safety)
|
||||
# define VL_SCOPED_CAPABILITY ///< Scoped threaded capability/lock (-fthread-safety)
|
||||
# define VL_ACQUIRE(...) ///< Function requires a capability/lock (-fthread-safety)
|
||||
# define VL_ACQUIRE_SHARED(...) ///< Function aquires a shared capability/lock (-fthread-safety)
|
||||
# define VL_RELEASE(...) ///< Function releases a capability/lock (-fthread-safety)
|
||||
# define VL_RELEASE_SHARED(...) ///< Function releases a shared capability/lock (-fthread-safety)
|
||||
# define VL_TRY_ACQUIRE(...) ///< Function returns bool if aquired a capability (-fthread-safety)
|
||||
# define VL_TRY_ACQUIRE_SHARED(...) ///< Function returns bool if aquired a shared capability (-fthread-safety)
|
||||
# define VL_REQUIRES(x) ///< Function requires a capability inbound (-fthread-safety)
|
||||
# define VL_EXCLUDES(x) ///< Function requires not having a capability inbound (-fthread-safety)
|
||||
# define VL_CAPABILITY(x) ///< Name of capability/lock (-fthread-safety)
|
||||
# define VL_GUARDED_BY(x) ///< Name of mutex protecting this variable (-fthread-safety)
|
||||
# define VL_SCOPED_CAPABILITY ///< Scoped threaded capability/lock (-fthread-safety)
|
||||
#endif
|
||||
#ifndef VL_LIKELY
|
||||
# define VL_LIKELY(x) (!!(x)) ///< Boolean expression more often true than false
|
||||
# define VL_UNLIKELY(x) (!!(x)) ///< Boolean expression more often false than true
|
||||
# define VL_LIKELY(x) (!!(x)) ///< Boolean expression more often true than false
|
||||
# define VL_UNLIKELY(x) (!!(x)) ///< Boolean expression more often false than true
|
||||
#endif
|
||||
#ifndef VL_UNREACHABLE
|
||||
# define VL_UNREACHABLE ///< Point that may never be reached
|
||||
# define VL_UNREACHABLE ///< Point that may never be reached
|
||||
#endif
|
||||
#ifndef VL_PREFETCH_RD
|
||||
# define VL_PREFETCH_RD(p) ///< Prefetch data with read intent
|
||||
# define VL_PREFETCH_RD(p) ///< Prefetch data with read intent
|
||||
#endif
|
||||
#ifndef VL_PREFETCH_RW
|
||||
# define VL_PREFETCH_RW(p) ///< Prefetch data with read/write intent
|
||||
# define VL_PREFETCH_RW(p) ///< Prefetch data with read/write intent
|
||||
#endif
|
||||
|
||||
#ifdef VL_THREADED
|
||||
@ -120,12 +120,12 @@
|
||||
# else
|
||||
# error "Unsupported compiler for VL_THREADED: No thread-local declarator"
|
||||
# endif
|
||||
# define VL_THREAD_LOCAL thread_local ///< Use new C++ static local thread
|
||||
# define VL_THREAD_LOCAL thread_local ///< Use new C++ static local thread
|
||||
#else
|
||||
# define VL_THREAD_LOCAL ///< Use new C++ static local thread
|
||||
# define VL_THREAD_LOCAL ///< Use new C++ static local thread
|
||||
#endif
|
||||
#define VL_THREAD ///< Deprecated
|
||||
#define VL_STATIC_OR_THREAD static ///< Deprecated
|
||||
#define VL_THREAD ///< Deprecated
|
||||
#define VL_STATIC_OR_THREAD static ///< Deprecated
|
||||
|
||||
#define VL_PURE ///< Comment tag that Function is pure (and thus also VL_MT_SAFE)
|
||||
#define VL_MT_SAFE ///< Comment tag that function is threadsafe when VL_THREADED
|
||||
@ -134,18 +134,18 @@
|
||||
#define VL_MT_UNSAFE_ONE ///< Comment tag that function is not threadsafe when VL_THREADED, protected to make sure single-caller
|
||||
|
||||
#ifdef _MSC_VER
|
||||
# define VL_ULL(c) (c##ui64) ///< Add appropriate suffix to 64-bit constant
|
||||
# define VL_ULL(c) (c##ui64) ///< Add appropriate suffix to 64-bit constant
|
||||
#else
|
||||
# define VL_ULL(c) (c##ULL) ///< Add appropriate suffix to 64-bit constant
|
||||
# define VL_ULL(c) (c##ULL) ///< Add appropriate suffix to 64-bit constant
|
||||
#endif
|
||||
|
||||
// This is not necessarily the same as #UL, depending on what the IData typedef is.
|
||||
#define VL_UL(c) (static_cast<IData>(c##UL)) ///< Add appropriate suffix to 32-bit constant
|
||||
#define VL_UL(c) (static_cast<IData>(c##UL)) ///< Add appropriate suffix to 32-bit constant
|
||||
|
||||
#if defined(VL_CPPCHECK) || defined(__clang_analyzer__)
|
||||
# define VL_DANGLING(v)
|
||||
#else
|
||||
# define VL_DANGLING(v) do { (v) = NULL; } while(0) ///< After e.g. delete, set variable to NULL to indicate must not use later
|
||||
# define VL_DANGLING(v) do { (v) = NULL; } while(0) ///< After e.g. delete, set variable to NULL to indicate must not use later
|
||||
#endif
|
||||
|
||||
//=========================================================================
|
||||
@ -176,7 +176,7 @@
|
||||
// Optimization
|
||||
|
||||
#ifndef VL_INLINE_OPT
|
||||
# define VL_INLINE_OPT ///< "inline" if compiling all objects in single compiler run
|
||||
# define VL_INLINE_OPT ///< "inline" if compiling all objects in single compiler run
|
||||
#endif
|
||||
|
||||
//=========================================================================
|
||||
@ -203,37 +203,37 @@
|
||||
# include <stdint.h>
|
||||
# include <sys/types.h> // __WORDSIZE
|
||||
# include <unistd.h> // ssize_t
|
||||
typedef unsigned char uint8_t; ///< 8-bit unsigned type (backward compatibility)
|
||||
typedef unsigned short int uint16_t; ///< 16-bit unsigned type (backward compatibility)
|
||||
typedef unsigned char vluint8_t; ///< 8-bit unsigned type
|
||||
typedef unsigned short int vluint16_t; ///< 16-bit unsigned type
|
||||
typedef unsigned char uint8_t; ///< 8-bit unsigned type (backward compatibility)
|
||||
typedef unsigned short int uint16_t; ///< 16-bit unsigned type (backward compatibility)
|
||||
typedef unsigned char vluint8_t; ///< 8-bit unsigned type
|
||||
typedef unsigned short int vluint16_t; ///< 16-bit unsigned type
|
||||
# if defined(__uint32_t_defined) || defined(___int32_t_defined) // Newer Cygwin uint32_t in stdint.h as an unsigned int
|
||||
typedef int32_t vlsint32_t; ///< 32-bit signed type
|
||||
typedef uint32_t vluint32_t; ///< 32-bit unsigned type
|
||||
# else // Older Cygwin has long==uint32_t
|
||||
typedef unsigned long uint32_t; ///< 32-bit unsigned type (backward compatibility)
|
||||
typedef long vlsint32_t; ///< 32-bit signed type
|
||||
typedef unsigned long vluint32_t; ///< 32-bit unsigned type
|
||||
typedef unsigned long uint32_t; ///< 32-bit unsigned type (backward compatibility)
|
||||
typedef long vlsint32_t; ///< 32-bit signed type
|
||||
typedef unsigned long vluint32_t; ///< 32-bit unsigned type
|
||||
# endif
|
||||
# if defined(__WORDSIZE) && (__WORDSIZE == 64)
|
||||
typedef long vlsint64_t; ///< 64-bit signed type
|
||||
typedef unsigned long vluint64_t; ///< 64-bit unsigned type
|
||||
typedef long vlsint64_t; ///< 64-bit signed type
|
||||
typedef unsigned long vluint64_t; ///< 64-bit unsigned type
|
||||
# else
|
||||
typedef long long vlsint64_t; ///< 64-bit signed type
|
||||
typedef unsigned long long vluint64_t; ///< 64-bit unsigned type
|
||||
typedef long long vlsint64_t; ///< 64-bit signed type
|
||||
typedef unsigned long long vluint64_t; ///< 64-bit unsigned type
|
||||
# endif
|
||||
|
||||
#elif defined(_WIN32) && defined(_MSC_VER)
|
||||
|
||||
typedef unsigned __int8 uint8_t; ///< 8-bit unsigned type (backward compatibility)
|
||||
typedef unsigned __int16 uint16_t; ///< 16-bit unsigned type (backward compatibility)
|
||||
typedef unsigned __int32 uint32_t; ///< 32-bit unsigned type (backward compatibility)
|
||||
typedef unsigned __int8 vluint8_t; ///< 8-bit unsigned type
|
||||
typedef unsigned __int16 vluint16_t; ///< 16-bit unsigned type
|
||||
typedef signed __int32 vlsint32_t; ///< 32-bit signed type
|
||||
typedef unsigned __int32 vluint32_t; ///< 32-bit unsigned type
|
||||
typedef signed __int64 vlsint64_t; ///< 64-bit signed type
|
||||
typedef unsigned __int64 vluint64_t; ///< 64-bit unsigned type
|
||||
typedef unsigned __int8 uint8_t; ///< 8-bit unsigned type (backward compatibility)
|
||||
typedef unsigned __int16 uint16_t; ///< 16-bit unsigned type (backward compatibility)
|
||||
typedef unsigned __int32 uint32_t; ///< 32-bit unsigned type (backward compatibility)
|
||||
typedef unsigned __int8 vluint8_t; ///< 8-bit unsigned type
|
||||
typedef unsigned __int16 vluint16_t; ///< 16-bit unsigned type
|
||||
typedef signed __int32 vlsint32_t; ///< 32-bit signed type
|
||||
typedef unsigned __int32 vluint32_t; ///< 32-bit unsigned type
|
||||
typedef signed __int64 vlsint64_t; ///< 64-bit signed type
|
||||
typedef unsigned __int64 vluint64_t; ///< 64-bit unsigned type
|
||||
|
||||
# ifndef _SSIZE_T_DEFINED
|
||||
# ifdef _WIN64
|
||||
@ -249,16 +249,16 @@ typedef signed __int32 ssize_t; ///< signed size_t; returned fro
|
||||
# include <stdint.h> // Linux and most flavors
|
||||
# include <sys/types.h> // __WORDSIZE
|
||||
# include <unistd.h> // ssize_t
|
||||
typedef uint8_t vluint8_t; ///< 32-bit unsigned type
|
||||
typedef uint16_t vluint16_t; ///< 32-bit unsigned type
|
||||
typedef int vlsint32_t; ///< 32-bit signed type
|
||||
typedef uint32_t vluint32_t; ///< 32-bit signed type
|
||||
typedef uint8_t vluint8_t; ///< 32-bit unsigned type
|
||||
typedef uint16_t vluint16_t; ///< 32-bit unsigned type
|
||||
typedef int vlsint32_t; ///< 32-bit signed type
|
||||
typedef uint32_t vluint32_t; ///< 32-bit signed type
|
||||
# if defined(__WORDSIZE) && (__WORDSIZE == 64)
|
||||
typedef long vlsint64_t; ///< 64-bit signed type
|
||||
typedef unsigned long vluint64_t; ///< 64-bit unsigned type
|
||||
typedef long vlsint64_t; ///< 64-bit signed type
|
||||
typedef unsigned long vluint64_t; ///< 64-bit unsigned type
|
||||
# else
|
||||
typedef long long vlsint64_t; ///< 64-bit signed type
|
||||
typedef unsigned long long vluint64_t; ///< 64-bit unsigned type
|
||||
typedef long long vlsint64_t; ///< 64-bit signed type
|
||||
typedef unsigned long long vluint64_t; ///< 64-bit unsigned type
|
||||
# endif
|
||||
#endif
|
||||
|
||||
@ -305,11 +305,11 @@ typedef unsigned long long vluint64_t; ///< 64-bit unsigned type
|
||||
//=========================================================================
|
||||
// Integer size macros
|
||||
|
||||
#define VL_BYTESIZE 8 ///< Bits in a byte
|
||||
#define VL_SHORTSIZE 16 ///< Bits in a short
|
||||
#define VL_WORDSIZE 32 ///< Bits in a word
|
||||
#define VL_QUADSIZE 64 ///< Bits in a quadword
|
||||
#define VL_WORDSIZE_LOG2 5 ///< log2(VL_WORDSIZE)
|
||||
#define VL_BYTESIZE 8 ///< Bits in a byte
|
||||
#define VL_SHORTSIZE 16 ///< Bits in a short
|
||||
#define VL_WORDSIZE 32 ///< Bits in a word
|
||||
#define VL_QUADSIZE 64 ///< Bits in a quadword
|
||||
#define VL_WORDSIZE_LOG2 5 ///< log2(VL_WORDSIZE)
|
||||
|
||||
/// Bytes this number of bits needs (1 bit=1 byte)
|
||||
#define VL_BYTES_I(nbits) (((nbits)+(VL_BYTESIZE-1))/VL_BYTESIZE)
|
||||
@ -327,21 +327,21 @@ typedef unsigned long long vluint64_t; ///< 64-bit unsigned type
|
||||
//=========================================================================
|
||||
// Verilated function size macros
|
||||
|
||||
#define VL_MULS_MAX_WORDS 16 ///< Max size in words of MULS operation
|
||||
#define VL_TO_STRING_MAX_WORDS 64 ///< Max size in words of String conversion operation
|
||||
#define VL_MULS_MAX_WORDS 16 ///< Max size in words of MULS operation
|
||||
#define VL_TO_STRING_MAX_WORDS 64 ///< Max size in words of String conversion operation
|
||||
|
||||
//=========================================================================
|
||||
// Base macros
|
||||
|
||||
#define VL_SIZEBITS_I (VL_WORDSIZE-1) ///< Bit mask for bits in a word
|
||||
#define VL_SIZEBITS_Q (VL_QUADSIZE-1) ///< Bit mask for bits in a quad
|
||||
#define VL_SIZEBITS_I (VL_WORDSIZE-1) ///< Bit mask for bits in a word
|
||||
#define VL_SIZEBITS_Q (VL_QUADSIZE-1) ///< Bit mask for bits in a quad
|
||||
|
||||
/// Mask for words with 1's where relevant bits are (0=all bits)
|
||||
#define VL_MASK_I(nbits) (((nbits) & VL_SIZEBITS_I) \
|
||||
? ((1U << ((nbits) & VL_SIZEBITS_I) )-1) : ~0)
|
||||
? ((1U << ((nbits) & VL_SIZEBITS_I) )-1) : ~0)
|
||||
/// Mask for quads with 1's where relevant bits are (0=all bits)
|
||||
#define VL_MASK_Q(nbits) (((nbits) & VL_SIZEBITS_Q) \
|
||||
? ((VL_ULL(1) << ((nbits) & VL_SIZEBITS_Q) )-VL_ULL(1)) : VL_ULL(~0))
|
||||
? ((VL_ULL(1) << ((nbits) & VL_SIZEBITS_Q) )-VL_ULL(1)) : VL_ULL(~0))
|
||||
#define VL_BITWORD_I(bit) ((bit)/VL_WORDSIZE) ///< Word number for a wide quantity
|
||||
#define VL_BITBIT_I(bit) ((bit)&VL_SIZEBITS_I) ///< Bit number for a bit in a long
|
||||
#define VL_BITBIT_Q(bit) ((bit)&VL_SIZEBITS_Q) ///< Bit number for a bit in a quad
|
||||
|
116
src/VlcBucket.h
116
src/VlcBucket.h
@ -32,35 +32,35 @@
|
||||
class VlcBuckets {
|
||||
private:
|
||||
// MEMBERS
|
||||
vluint64_t* m_datap; ///< Pointer to first bucket (dynamically allocated)
|
||||
vluint64_t m_dataSize; ///< Current entries in m_datap
|
||||
vluint64_t m_bucketsCovered; ///< Num buckets with sufficient coverage
|
||||
vluint64_t* m_datap; ///< Pointer to first bucket (dynamically allocated)
|
||||
vluint64_t m_dataSize; ///< Current entries in m_datap
|
||||
vluint64_t m_bucketsCovered; ///< Num buckets with sufficient coverage
|
||||
|
||||
private:
|
||||
static inline vluint64_t covBit(vluint64_t point) { return 1ULL<<(point & 63); }
|
||||
inline vluint64_t allocSize() const { return sizeof(vluint64_t) * m_dataSize / 64; }
|
||||
void allocate(vluint64_t point) {
|
||||
vluint64_t oldsize = m_dataSize;
|
||||
if (m_dataSize<point) m_dataSize=(point+64) & ~63ULL; // Keep power of two
|
||||
m_dataSize *= 2;
|
||||
vluint64_t oldsize = m_dataSize;
|
||||
if (m_dataSize<point) m_dataSize=(point+64) & ~63ULL; // Keep power of two
|
||||
m_dataSize *= 2;
|
||||
//UINFO(9, "Realloc "<<allocSize()<<" for "<<point<<" "<<cvtToHex(m_datap)<<endl);
|
||||
vluint64_t* newp = (vluint64_t*)realloc(m_datap, allocSize());
|
||||
if (!newp) { free(m_datap); v3fatal("Out of memory increasing buckets"); }
|
||||
m_datap = newp;
|
||||
for (vluint64_t i=oldsize; i<m_dataSize; i+=64) m_datap[i/64] = 0;
|
||||
vluint64_t* newp = (vluint64_t*)realloc(m_datap, allocSize());
|
||||
if (!newp) { free(m_datap); v3fatal("Out of memory increasing buckets"); }
|
||||
m_datap = newp;
|
||||
for (vluint64_t i=oldsize; i<m_dataSize; i+=64) m_datap[i/64] = 0;
|
||||
}
|
||||
|
||||
public:
|
||||
// CONSTRUCTORS
|
||||
VlcBuckets() {
|
||||
m_dataSize = 0;
|
||||
m_datap = NULL;
|
||||
m_bucketsCovered = 0;
|
||||
allocate(1024);
|
||||
m_dataSize = 0;
|
||||
m_datap = NULL;
|
||||
m_bucketsCovered = 0;
|
||||
allocate(1024);
|
||||
}
|
||||
~VlcBuckets() {
|
||||
m_dataSize = 0;
|
||||
free(m_datap); m_datap=NULL;
|
||||
m_dataSize = 0;
|
||||
free(m_datap); m_datap=NULL;
|
||||
}
|
||||
|
||||
// ACCESSORS
|
||||
@ -69,66 +69,66 @@ public:
|
||||
|
||||
// METHODS
|
||||
void addData(vluint64_t point, vluint64_t hits) {
|
||||
if (hits >= sufficient()) {
|
||||
//UINFO(9," addData "<<point<<" "<<hits<<" size="<<m_dataSize<<endl);
|
||||
if (point >= m_dataSize) allocate(point);
|
||||
m_datap[point/64] |= covBit(point);
|
||||
m_bucketsCovered++;
|
||||
}
|
||||
if (hits >= sufficient()) {
|
||||
//UINFO(9," addData "<<point<<" "<<hits<<" size="<<m_dataSize<<endl);
|
||||
if (point >= m_dataSize) allocate(point);
|
||||
m_datap[point/64] |= covBit(point);
|
||||
m_bucketsCovered++;
|
||||
}
|
||||
}
|
||||
void clearHits(vluint64_t point) const {
|
||||
if (point >= m_dataSize) {
|
||||
return;
|
||||
} else {
|
||||
m_datap[point/64] &= ~covBit(point);
|
||||
}
|
||||
if (point >= m_dataSize) {
|
||||
return;
|
||||
} else {
|
||||
m_datap[point/64] &= ~covBit(point);
|
||||
}
|
||||
}
|
||||
bool exists(vluint64_t point) const {
|
||||
if (point >= m_dataSize) {
|
||||
return false;
|
||||
} else {
|
||||
return (m_datap[point/64] & covBit(point)) ? 1:0;
|
||||
}
|
||||
if (point >= m_dataSize) {
|
||||
return false;
|
||||
} else {
|
||||
return (m_datap[point/64] & covBit(point)) ? 1:0;
|
||||
}
|
||||
}
|
||||
vluint64_t hits(vluint64_t point) const {
|
||||
if (point >= m_dataSize) {
|
||||
return 0;
|
||||
} else {
|
||||
return (m_datap[point/64] & covBit(point)) ? 1:0;
|
||||
}
|
||||
if (point >= m_dataSize) {
|
||||
return 0;
|
||||
} else {
|
||||
return (m_datap[point/64] & covBit(point)) ? 1:0;
|
||||
}
|
||||
}
|
||||
vluint64_t popCount() const {
|
||||
vluint64_t pop = 0;
|
||||
for (vluint64_t i=0; i<m_dataSize; i++) {
|
||||
if (hits(i)) pop++;
|
||||
}
|
||||
return pop;
|
||||
vluint64_t pop = 0;
|
||||
for (vluint64_t i=0; i<m_dataSize; i++) {
|
||||
if (hits(i)) pop++;
|
||||
}
|
||||
return pop;
|
||||
}
|
||||
vluint64_t dataPopCount(const VlcBuckets& remaining) {
|
||||
vluint64_t pop = 0;
|
||||
for (vluint64_t i=0; i<m_dataSize; i++) {
|
||||
if (hits(i) && remaining.hits(i)) pop++;
|
||||
}
|
||||
return pop;
|
||||
vluint64_t pop = 0;
|
||||
for (vluint64_t i=0; i<m_dataSize; i++) {
|
||||
if (hits(i) && remaining.hits(i)) pop++;
|
||||
}
|
||||
return pop;
|
||||
}
|
||||
void orData(const VlcBuckets& ordata) {
|
||||
for (vluint64_t i=0; i<m_dataSize; i++) {
|
||||
if (hits(i) && ordata.hits(i)) {
|
||||
clearHits(i);
|
||||
}
|
||||
}
|
||||
for (vluint64_t i=0; i<m_dataSize; i++) {
|
||||
if (hits(i) && ordata.hits(i)) {
|
||||
clearHits(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void dump() const {
|
||||
cout<<"# ";
|
||||
for (vluint64_t i=0; i<m_dataSize; i++) {
|
||||
if (hits(i)) cout<<","<<i;
|
||||
}
|
||||
cout<<endl;
|
||||
cout<<"# ";
|
||||
for (vluint64_t i=0; i<m_dataSize; i++) {
|
||||
if (hits(i)) cout<<","<<i;
|
||||
}
|
||||
cout<<endl;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
//######################################################################
|
||||
|
||||
#endif // guard
|
||||
#endif // guard
|
||||
|
135
src/VlcMain.cpp
135
src/VlcMain.cpp
@ -43,7 +43,7 @@
|
||||
|
||||
void VlcOptions::addReadFile(const string& filename) {
|
||||
if (m_readFiles.find(filename) == m_readFiles.end()) {
|
||||
m_readFiles.insert(filename);
|
||||
m_readFiles.insert(filename);
|
||||
}
|
||||
}
|
||||
|
||||
@ -59,9 +59,9 @@ bool VlcOptions::onoff(const char* sw, const char* arg, bool& flag) {
|
||||
// if sw=="-noarg", then return true (found it), and flag=false
|
||||
// else return false
|
||||
if (arg[0]!='-') v3fatalSrc("OnOff switches must have leading dash.");
|
||||
if (0==strcmp(sw,arg)) { flag=true; return true; }
|
||||
else if (0==strncmp(sw,"-no",3) && (0==strcmp(sw+3,arg+1))) { flag=false; return true; }
|
||||
else if (0==strncmp(sw,"-no-",4) && (0==strcmp(sw+4,arg+1))) { flag=false; return true; }
|
||||
if (0==strcmp(sw,arg)) { flag = true; return true; }
|
||||
else if (0==strncmp(sw,"-no",3) && (0==strcmp(sw+3,arg+1))) { flag = false; return true; }
|
||||
else if (0==strncmp(sw,"-no-",4) && (0==strcmp(sw+4,arg+1))) { flag = false; return true; }
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -71,58 +71,58 @@ void VlcOptions::parseOptsList(int argc, char** argv) {
|
||||
// May be called recursively when there are -f files.
|
||||
#define shift { ++i; }
|
||||
for (int i=0; i<argc; ) {
|
||||
UINFO(9, " Option: "<<argv[i]<<endl);
|
||||
if (argv[i][0]=='-') {
|
||||
const char *sw = argv[i];
|
||||
bool flag = true;
|
||||
// Allow gnu -- switches
|
||||
if (sw[0]=='-' && sw[1]=='-') ++sw;
|
||||
if (0) {}
|
||||
// Single switches
|
||||
else if ( onoff (sw, "-annotate-all", flag/*ref*/) ) { m_annotateAll = flag; }
|
||||
else if ( onoff (sw, "-rank", flag/*ref*/) ) { m_rank = flag; }
|
||||
else if ( onoff (sw, "-unlink", flag/*ref*/) ) { m_unlink = flag; }
|
||||
// Parameterized switches
|
||||
UINFO(9, " Option: "<<argv[i]<<endl);
|
||||
if (argv[i][0]=='-') {
|
||||
const char *sw = argv[i];
|
||||
bool flag = true;
|
||||
// Allow gnu -- switches
|
||||
if (sw[0]=='-' && sw[1]=='-') ++sw;
|
||||
if (0) {}
|
||||
// Single switches
|
||||
else if ( onoff (sw, "-annotate-all", flag/*ref*/) ) { m_annotateAll = flag; }
|
||||
else if ( onoff (sw, "-rank", flag/*ref*/) ) { m_rank = flag; }
|
||||
else if ( onoff (sw, "-unlink", flag/*ref*/) ) { m_unlink = flag; }
|
||||
// Parameterized switches
|
||||
else if ( !strcmp (sw, "-annotate-min") && (i+1)<argc ) {
|
||||
shift;
|
||||
m_annotateMin = atoi(argv[i]);
|
||||
}
|
||||
else if ( !strcmp (sw, "-annotate") && (i+1)<argc ) {
|
||||
shift;
|
||||
m_annotateOut = argv[i];
|
||||
}
|
||||
else if ( !strcmp (sw, "-debug") ) {
|
||||
V3Error::debugDefault(3);
|
||||
}
|
||||
else if ( !strcmp (sw, "-debugi") && (i+1)<argc ) {
|
||||
shift;
|
||||
V3Error::debugDefault(atoi(argv[i]));
|
||||
}
|
||||
else if ( !strcmp (sw, "-V") ) {
|
||||
showVersion(true);
|
||||
exit(0);
|
||||
}
|
||||
else if ( !strcmp (sw, "-version") ) {
|
||||
showVersion(false);
|
||||
exit(0);
|
||||
}
|
||||
else if ( !strcmp (sw, "-write") && (i+1)<argc ) {
|
||||
shift;
|
||||
m_writeFile = argv[i];
|
||||
}
|
||||
else {
|
||||
else if ( !strcmp (sw, "-annotate") && (i+1)<argc ) {
|
||||
shift;
|
||||
m_annotateOut = argv[i];
|
||||
}
|
||||
else if ( !strcmp (sw, "-debug") ) {
|
||||
V3Error::debugDefault(3);
|
||||
}
|
||||
else if ( !strcmp (sw, "-debugi") && (i+1)<argc ) {
|
||||
shift;
|
||||
V3Error::debugDefault(atoi(argv[i]));
|
||||
}
|
||||
else if ( !strcmp (sw, "-V") ) {
|
||||
showVersion(true);
|
||||
exit(0);
|
||||
}
|
||||
else if ( !strcmp (sw, "-version") ) {
|
||||
showVersion(false);
|
||||
exit(0);
|
||||
}
|
||||
else if ( !strcmp (sw, "-write") && (i+1)<argc ) {
|
||||
shift;
|
||||
m_writeFile = argv[i];
|
||||
}
|
||||
else {
|
||||
v3fatal("Invalid option: "<<argv[i]);
|
||||
}
|
||||
shift;
|
||||
} // - options
|
||||
else if (1) {
|
||||
addReadFile(argv[i]);
|
||||
shift;
|
||||
}
|
||||
else {
|
||||
}
|
||||
shift;
|
||||
} // - options
|
||||
else if (1) {
|
||||
addReadFile(argv[i]);
|
||||
shift;
|
||||
}
|
||||
else {
|
||||
v3fatal("Invalid argument: "<<argv[i]);
|
||||
shift;
|
||||
}
|
||||
shift;
|
||||
}
|
||||
}
|
||||
#undef shift
|
||||
}
|
||||
@ -154,20 +154,20 @@ int main(int argc, char** argv, char** env) {
|
||||
top.opt.parseOptsList(argc-1, argv+1);
|
||||
|
||||
if (top.opt.readFiles().empty()) {
|
||||
top.opt.addReadFile("vlt_coverage.dat");
|
||||
top.opt.addReadFile("vlt_coverage.dat");
|
||||
}
|
||||
|
||||
{
|
||||
const VlStringSet& readFiles = top.opt.readFiles();
|
||||
for (VlStringSet::iterator it = readFiles.begin(); it != readFiles.end(); ++it) {
|
||||
string filename = *it;
|
||||
top.readCoverage(filename);
|
||||
}
|
||||
const VlStringSet& readFiles = top.opt.readFiles();
|
||||
for (VlStringSet::iterator it = readFiles.begin(); it != readFiles.end(); ++it) {
|
||||
string filename = *it;
|
||||
top.readCoverage(filename);
|
||||
}
|
||||
}
|
||||
|
||||
if (debug() >= 9) {
|
||||
top.tests().dump(true);
|
||||
top.points().dump();
|
||||
top.tests().dump(true);
|
||||
top.points().dump();
|
||||
}
|
||||
|
||||
V3Error::abortIfWarnings();
|
||||
@ -176,19 +176,19 @@ int main(int argc, char** argv, char** env) {
|
||||
}
|
||||
|
||||
if (top.opt.rank()) {
|
||||
top.rank();
|
||||
top.tests().dump(false);
|
||||
top.rank();
|
||||
top.tests().dump(false);
|
||||
}
|
||||
|
||||
if (!top.opt.writeFile().empty()) {
|
||||
top.writeCoverage(top.opt.writeFile());
|
||||
V3Error::abortIfWarnings();
|
||||
top.writeCoverage(top.opt.writeFile());
|
||||
V3Error::abortIfWarnings();
|
||||
if (top.opt.unlink()) {
|
||||
const VlStringSet& readFiles = top.opt.readFiles();
|
||||
for (VlStringSet::iterator it = readFiles.begin(); it != readFiles.end(); ++it) {
|
||||
string filename = *it;
|
||||
unlink(filename.c_str());
|
||||
}
|
||||
const VlStringSet& readFiles = top.opt.readFiles();
|
||||
for (VlStringSet::iterator it = readFiles.begin(); it != readFiles.end(); ++it) {
|
||||
string filename = *it;
|
||||
unlink(filename.c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -201,4 +201,3 @@ int main(int argc, char** argv, char** env) {
|
||||
// Local Variables:
|
||||
// compile-command: "v4make bin/verilator_coverage --debugi 9 test_regress/t/t_vlcov_data_*.dat"
|
||||
// End:
|
||||
|
||||
|
@ -38,13 +38,13 @@ typedef std::set<string> VlStringSet;
|
||||
|
||||
class VlcOptions {
|
||||
// MEMBERS (general options)
|
||||
string m_annotateOut; // main switch: --annotate I<output_directory>
|
||||
bool m_annotateAll; // main switch: --annotate-all
|
||||
int m_annotateMin; // main switch: --annotate-min I<count>
|
||||
VlStringSet m_readFiles; // main switch: --read
|
||||
bool m_rank; // main switch: --rank
|
||||
bool m_unlink; // main switch: --unlink
|
||||
string m_writeFile; // main switch: --write
|
||||
string m_annotateOut; // main switch: --annotate I<output_directory>
|
||||
bool m_annotateAll; // main switch: --annotate-all
|
||||
int m_annotateMin; // main switch: --annotate-min I<count>
|
||||
VlStringSet m_readFiles; // main switch: --read
|
||||
bool m_rank; // main switch: --rank
|
||||
bool m_unlink; // main switch: --unlink
|
||||
string m_writeFile; // main switch: --write
|
||||
|
||||
private:
|
||||
// METHODS
|
||||
@ -54,10 +54,10 @@ private:
|
||||
public:
|
||||
// CONSTRUCTORS
|
||||
VlcOptions() {
|
||||
m_annotateAll = false;
|
||||
m_annotateMin = 10;
|
||||
m_rank = false;
|
||||
m_unlink = false;
|
||||
m_annotateAll = false;
|
||||
m_annotateMin = 10;
|
||||
m_rank = false;
|
||||
m_unlink = false;
|
||||
}
|
||||
~VlcOptions() {}
|
||||
void setDebugMode(int level);
|
||||
@ -81,4 +81,4 @@ public:
|
||||
|
||||
//######################################################################
|
||||
|
||||
#endif // guard
|
||||
#endif // guard
|
||||
|
@ -36,18 +36,18 @@
|
||||
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
|
||||
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;
|
||||
m_name = name;
|
||||
m_pointNum = pointNum;
|
||||
m_testsCovering = 0;
|
||||
m_count = 0;
|
||||
}
|
||||
~VlcPoint() {}
|
||||
// ACCESSORS
|
||||
@ -66,31 +66,31 @@ public:
|
||||
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 "";
|
||||
// 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;
|
||||
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;
|
||||
<<", \""<<name()<<"\""<<endl;
|
||||
}
|
||||
};
|
||||
|
||||
@ -115,40 +115,40 @@ public:
|
||||
public:
|
||||
// CONSTRUCTORS
|
||||
VlcPoints() {
|
||||
m_numPoints = 0;
|
||||
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();
|
||||
}
|
||||
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];
|
||||
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;
|
||||
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
|
||||
#endif // guard
|
||||
|
@ -33,18 +33,18 @@
|
||||
class VlcSourceCount {
|
||||
private:
|
||||
// MEMBERS
|
||||
int m_lineno; ///< Line number
|
||||
int m_column; ///< Column number
|
||||
vluint64_t m_count; ///< Count
|
||||
bool m_ok; ///< Coverage is above threshold
|
||||
int m_lineno; ///< Line number
|
||||
int m_column; ///< Column number
|
||||
vluint64_t m_count; ///< Count
|
||||
bool m_ok; ///< Coverage is above threshold
|
||||
|
||||
public:
|
||||
// CONSTRUCTORS
|
||||
VlcSourceCount(int lineno, int column) {
|
||||
m_lineno = lineno;
|
||||
m_column = column;
|
||||
m_count = 0;
|
||||
m_ok = false;
|
||||
m_lineno = lineno;
|
||||
m_column = column;
|
||||
m_count = 0;
|
||||
m_ok = false;
|
||||
}
|
||||
~VlcSourceCount() {}
|
||||
|
||||
@ -56,8 +56,8 @@ public:
|
||||
|
||||
// METHODS
|
||||
void incCount(vluint64_t count, bool ok) {
|
||||
m_count += count;
|
||||
if (ok) m_ok = true;
|
||||
m_count += count;
|
||||
if (ok) m_ok = true;
|
||||
}
|
||||
};
|
||||
|
||||
@ -72,15 +72,15 @@ public:
|
||||
|
||||
private:
|
||||
// MEMBERS
|
||||
string m_name; //< Name of the source file
|
||||
bool m_needed; //< Need to annotate; has low coverage
|
||||
LinenoMap m_lines; //< Map of each annotated line
|
||||
string m_name; //< Name of the source file
|
||||
bool m_needed; //< Need to annotate; has low coverage
|
||||
LinenoMap m_lines; //< Map of each annotated line
|
||||
|
||||
public:
|
||||
// CONSTRUCTORS
|
||||
explicit VlcSource(const string& name) {
|
||||
m_name = name;
|
||||
m_needed = false;
|
||||
m_name = name;
|
||||
m_needed = false;
|
||||
}
|
||||
~VlcSource() {}
|
||||
|
||||
@ -92,17 +92,17 @@ public:
|
||||
|
||||
// METHODS
|
||||
void incCount(int lineno, int column, vluint64_t count, bool ok) {
|
||||
LinenoMap::iterator lit = m_lines.find(lineno);
|
||||
if (lit == m_lines.end()) {
|
||||
lit = m_lines.insert(make_pair(lineno,ColumnMap())).first;
|
||||
}
|
||||
ColumnMap& cmap = lit->second;
|
||||
ColumnMap::iterator cit = cmap.find(column);
|
||||
if (cit == cmap.end()) {
|
||||
cit = cmap.insert(make_pair(column,VlcSourceCount(lineno, column))).first;
|
||||
}
|
||||
VlcSourceCount& sc = cit->second;
|
||||
sc.incCount(count,ok);
|
||||
LinenoMap::iterator lit = m_lines.find(lineno);
|
||||
if (lit == m_lines.end()) {
|
||||
lit = m_lines.insert(make_pair(lineno, ColumnMap())).first;
|
||||
}
|
||||
ColumnMap& cmap = lit->second;
|
||||
ColumnMap::iterator cit = cmap.find(column);
|
||||
if (cit == cmap.end()) {
|
||||
cit = cmap.insert(make_pair(column, VlcSourceCount(lineno, column))).first;
|
||||
}
|
||||
VlcSourceCount& sc = cit->second;
|
||||
sc.incCount(count, ok);
|
||||
}
|
||||
};
|
||||
|
||||
@ -115,7 +115,7 @@ public:
|
||||
typedef std::map<string,VlcSource> NameMap;
|
||||
private:
|
||||
// MEMBERS
|
||||
NameMap m_sources; //< List of all sources
|
||||
NameMap m_sources; //< List of all sources
|
||||
|
||||
public:
|
||||
// ITERATORS
|
||||
@ -130,17 +130,17 @@ public:
|
||||
|
||||
// METHODS
|
||||
VlcSource& findNewSource(const string& name) {
|
||||
NameMap::iterator iter = m_sources.find(name);
|
||||
if (iter != m_sources.end()) {
|
||||
return iter->second;
|
||||
}
|
||||
else {
|
||||
iter = m_sources.insert(make_pair(name, VlcSource(name))).first;
|
||||
return iter->second;
|
||||
}
|
||||
NameMap::iterator iter = m_sources.find(name);
|
||||
if (iter != m_sources.end()) {
|
||||
return iter->second;
|
||||
}
|
||||
else {
|
||||
iter = m_sources.insert(make_pair(name, VlcSource(name))).first;
|
||||
return iter->second;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
//######################################################################
|
||||
|
||||
#endif // Guard
|
||||
#endif // Guard
|
||||
|
@ -36,23 +36,23 @@
|
||||
class VlcTest {
|
||||
private:
|
||||
// MEMBERS
|
||||
string m_name; //< Name of the test
|
||||
double m_computrons; //< Runtime for the test
|
||||
vluint64_t m_testrun; //< Test run number, for database use
|
||||
vluint64_t m_rank; //< Execution rank suggestion
|
||||
vluint64_t m_rankPoints; //< Ranked additional points
|
||||
vluint64_t m_user; //< User data for algorithms (not persisted in .dat file)
|
||||
VlcBuckets m_buckets; //< Coverage data for each coverage point
|
||||
string m_name; //< Name of the test
|
||||
double m_computrons; //< Runtime for the test
|
||||
vluint64_t m_testrun; //< Test run number, for database use
|
||||
vluint64_t m_rank; //< Execution rank suggestion
|
||||
vluint64_t m_rankPoints; //< Ranked additional points
|
||||
vluint64_t m_user; //< User data for algorithms (not persisted in .dat file)
|
||||
VlcBuckets m_buckets; //< Coverage data for each coverage point
|
||||
|
||||
public:
|
||||
// CONSTRUCTORS
|
||||
VlcTest(const string& name, vluint64_t testrun, double comp) {
|
||||
m_name = name;
|
||||
m_computrons = comp;
|
||||
m_testrun = testrun;
|
||||
m_rank = 0;
|
||||
m_rankPoints = 0;
|
||||
m_user = 0;
|
||||
m_name = name;
|
||||
m_computrons = comp;
|
||||
m_testrun = testrun;
|
||||
m_rank = 0;
|
||||
m_rankPoints = 0;
|
||||
m_user = 0;
|
||||
}
|
||||
~VlcTest() {}
|
||||
|
||||
@ -71,20 +71,20 @@ public:
|
||||
|
||||
// METHODS
|
||||
static void dumpHeader() {
|
||||
cout<<"Tests:\n";
|
||||
//cout<<" Testrun, Computrons,"; // Currently not loaded
|
||||
cout<<" Covered, Rank, RankPts, Filename"<<endl;
|
||||
cout<<"Tests:\n";
|
||||
//cout<<" Testrun, Computrons,"; // Currently not loaded
|
||||
cout<<" Covered, Rank, RankPts, Filename"<<endl;
|
||||
}
|
||||
void dump(bool bucketsToo) {
|
||||
if (testrun() || computrons()!=0.0) {
|
||||
if (testrun() || computrons()!=0.0) {
|
||||
cout<<" "<<std::setw(8)<<std::setfill('0')<<testrun()
|
||||
<<", "<<std::setw(7)<<std::setfill(' ')<<computrons()<<",";
|
||||
}
|
||||
}
|
||||
cout<<" "<<std::setw(7)<<std::setfill(' ')<<bucketsCovered()
|
||||
<<", "<<std::setw(7)<<std::setfill(' ')<<rank()
|
||||
<<", "<<std::setw(7)<<std::setfill(' ')<<rankPoints()
|
||||
<<", \""<<name()<<"\""<<endl;
|
||||
if (bucketsToo) m_buckets.dump();
|
||||
<<", \""<<name()<<"\""<<endl;
|
||||
if (bucketsToo) m_buckets.dump();
|
||||
}
|
||||
};
|
||||
|
||||
@ -97,7 +97,7 @@ public:
|
||||
typedef std::vector<VlcTest*> ByName;
|
||||
private:
|
||||
// MEMBERS
|
||||
ByName m_tests; //< List of all tests
|
||||
ByName m_tests; //< List of all tests
|
||||
|
||||
public:
|
||||
// ITERATORS
|
||||
@ -109,31 +109,31 @@ public:
|
||||
// CONSTRUCTORS
|
||||
VlcTests() {}
|
||||
~VlcTests() {
|
||||
for (VlcTests::ByName::iterator it=begin(); it!=end(); ++it) {
|
||||
delete *it; *it=NULL;
|
||||
}
|
||||
for (VlcTests::ByName::iterator it=begin(); it!=end(); ++it) {
|
||||
delete *it; *it=NULL;
|
||||
}
|
||||
}
|
||||
|
||||
// METHODS
|
||||
void dump(bool bucketsToo) {
|
||||
UINFO(2,"dumpTests...\n");
|
||||
VlcTest::dumpHeader();
|
||||
for (VlcTests::ByName::iterator it=begin(); it!=end(); ++it) {
|
||||
(*it)->dump(bucketsToo);
|
||||
}
|
||||
UINFO(2,"dumpTests...\n");
|
||||
VlcTest::dumpHeader();
|
||||
for (VlcTests::ByName::iterator it=begin(); it!=end(); ++it) {
|
||||
(*it)->dump(bucketsToo);
|
||||
}
|
||||
}
|
||||
VlcTest* newTest(const string& name, vluint64_t testrun, double comp) {
|
||||
VlcTest* testp = new VlcTest(name, testrun, comp);
|
||||
m_tests.push_back(testp);
|
||||
return testp;
|
||||
VlcTest* testp = new VlcTest(name, testrun, comp);
|
||||
m_tests.push_back(testp);
|
||||
return testp;
|
||||
}
|
||||
void clearUser() {
|
||||
for (ByName::iterator it = m_tests.begin(); it != m_tests.end(); ++it) {
|
||||
(*it)->user(0);
|
||||
}
|
||||
for (ByName::iterator it = m_tests.begin(); it != m_tests.end(); ++it) {
|
||||
(*it)->user(0);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
//######################################################################
|
||||
|
||||
#endif // Guard
|
||||
#endif // Guard
|
||||
|
244
src/VlcTop.cpp
244
src/VlcTop.cpp
@ -34,8 +34,8 @@ void VlcTop::readCoverage(const string& filename, bool nonfatal) {
|
||||
|
||||
std::ifstream is(filename.c_str());
|
||||
if (!is) {
|
||||
if (!nonfatal) v3fatal("Can't read "<<filename);
|
||||
return;
|
||||
if (!nonfatal) v3fatal("Can't read "<<filename);
|
||||
return;
|
||||
}
|
||||
|
||||
// Testrun and computrons argument unsupported as yet
|
||||
@ -45,23 +45,23 @@ void VlcTop::readCoverage(const string& filename, bool nonfatal) {
|
||||
string line = V3Os::getline(is);
|
||||
//UINFO(9," got "<<line<<endl);
|
||||
if (line[0] == 'C') {
|
||||
string::size_type secspace=3;
|
||||
for (; secspace<line.length(); secspace++) {
|
||||
if (line[secspace]=='\'' && line[secspace+1]==' ') break;
|
||||
}
|
||||
string point = line.substr(3,secspace-3);
|
||||
vluint64_t hits = atoll(line.c_str()+secspace+1);
|
||||
//UINFO(9," point '"<<point<<"'"<<" "<<hits<<endl);
|
||||
string::size_type secspace = 3;
|
||||
for (; secspace<line.length(); secspace++) {
|
||||
if (line[secspace]=='\'' && line[secspace+1]==' ') break;
|
||||
}
|
||||
string point = line.substr(3, secspace-3);
|
||||
vluint64_t hits = atoll(line.c_str()+secspace+1);
|
||||
//UINFO(9," point '"<<point<<"'"<<" "<<hits<<endl);
|
||||
|
||||
vluint64_t pointnum = points().findAddPoint(point, hits);
|
||||
if (pointnum) {} // Prevent unused
|
||||
if (opt.rank()) { // Only if ranking - uses a lot of memory
|
||||
if (hits >= VlcBuckets::sufficient()) {
|
||||
points().pointNumber(pointnum).testsCoveringInc();
|
||||
testp->buckets().addData(pointnum, hits);
|
||||
}
|
||||
}
|
||||
}
|
||||
vluint64_t pointnum = points().findAddPoint(point, hits);
|
||||
if (pointnum) {} // Prevent unused
|
||||
if (opt.rank()) { // Only if ranking - uses a lot of memory
|
||||
if (hits >= VlcBuckets::sufficient()) {
|
||||
points().pointNumber(pointnum).testsCoveringInc();
|
||||
testp->buckets().addData(pointnum, hits);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -70,14 +70,14 @@ void VlcTop::writeCoverage(const string& filename) {
|
||||
|
||||
std::ofstream os(filename.c_str());
|
||||
if (!os) {
|
||||
v3fatal("Can't write "<<filename);
|
||||
return;
|
||||
v3fatal("Can't write "<<filename);
|
||||
return;
|
||||
}
|
||||
|
||||
os << "# SystemC::Coverage-3" << endl;
|
||||
for (VlcPoints::ByName::iterator it=m_points.begin(); it!=m_points.end(); ++it) {
|
||||
const VlcPoint& point = m_points.pointNumber(it->second);
|
||||
os <<"C '"<<point.name()<<"' " << point.count()<<endl;
|
||||
const VlcPoint& point = m_points.pointNumber(it->second);
|
||||
os <<"C '"<<point.name()<<"' " << point.count()<<endl;
|
||||
}
|
||||
}
|
||||
|
||||
@ -85,32 +85,32 @@ void VlcTop::writeCoverage(const string& filename) {
|
||||
|
||||
struct CmpComputrons {
|
||||
inline bool operator() (const VlcTest* lhsp, const VlcTest* rhsp) const {
|
||||
if (lhsp->computrons() != rhsp->computrons()) {
|
||||
return lhsp->computrons() < rhsp->computrons();
|
||||
}
|
||||
return lhsp->bucketsCovered() > rhsp->bucketsCovered();
|
||||
if (lhsp->computrons() != rhsp->computrons()) {
|
||||
return lhsp->computrons() < rhsp->computrons();
|
||||
}
|
||||
return lhsp->bucketsCovered() > rhsp->bucketsCovered();
|
||||
}
|
||||
};
|
||||
|
||||
void VlcTop::rank() {
|
||||
UINFO(2,"rank...\n");
|
||||
vluint64_t nextrank=1;
|
||||
vluint64_t nextrank = 1;
|
||||
|
||||
// Sort by computrons, so fast tests get selected first
|
||||
std::vector<VlcTest*> bytime;
|
||||
for (VlcTests::ByName::iterator it=m_tests.begin(); it!=m_tests.end(); ++it) {
|
||||
VlcTest* testp = *it;
|
||||
if (testp->bucketsCovered()) { // else no points, so can't help us
|
||||
bytime.push_back(*it);
|
||||
}
|
||||
VlcTest* testp = *it;
|
||||
if (testp->bucketsCovered()) { // else no points, so can't help us
|
||||
bytime.push_back(*it);
|
||||
}
|
||||
}
|
||||
sort(bytime.begin(), bytime.end(), CmpComputrons()); // Sort the vector
|
||||
sort(bytime.begin(), bytime.end(), CmpComputrons()); // Sort the vector
|
||||
|
||||
VlcBuckets remaining;
|
||||
for (VlcPoints::ByName::iterator it=m_points.begin(); it!=m_points.end(); ++it) {
|
||||
VlcPoint* pointp = &points().pointNumber(it->second);
|
||||
// If any tests hit this point, then we'll need to cover it.
|
||||
if (pointp->testsCovering()) { remaining.addData(pointp->pointNum(), 1); }
|
||||
VlcPoint* pointp = &points().pointNumber(it->second);
|
||||
// If any tests hit this point, then we'll need to cover it.
|
||||
if (pointp->testsCovering()) { remaining.addData(pointp->pointNum(), 1); }
|
||||
}
|
||||
|
||||
// Additional Greedy algorithm
|
||||
@ -118,26 +118,26 @@ void VlcTop::rank() {
|
||||
// then hierarchically solve a small subset of tests, and take resulting
|
||||
// solution and move up to larger subset of tests. (Aka quick sort.)
|
||||
while (1) {
|
||||
if (debug()) { UINFO(9,"Left on iter"<<nextrank<<": "); remaining.dump(); }
|
||||
VlcTest* bestTestp = NULL;
|
||||
vluint64_t bestRemain = 0;
|
||||
if (debug()) { UINFO(9,"Left on iter"<<nextrank<<": "); remaining.dump(); }
|
||||
VlcTest* bestTestp = NULL;
|
||||
vluint64_t bestRemain = 0;
|
||||
for (std::vector<VlcTest*>::iterator it=bytime.begin(); it!=bytime.end(); ++it) {
|
||||
VlcTest* testp = *it;
|
||||
if (!testp->rank()) {
|
||||
vluint64_t remain = testp->buckets().dataPopCount(remaining);
|
||||
if (remain > bestRemain) {
|
||||
bestTestp = testp;
|
||||
bestRemain = remain;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (VlcTest* testp = bestTestp) {
|
||||
testp->rank(nextrank++);
|
||||
testp->rankPoints(bestRemain);
|
||||
remaining.orData(bestTestp->buckets());
|
||||
} else {
|
||||
break; // No test covering more stuff found
|
||||
}
|
||||
VlcTest* testp = *it;
|
||||
if (!testp->rank()) {
|
||||
vluint64_t remain = testp->buckets().dataPopCount(remaining);
|
||||
if (remain > bestRemain) {
|
||||
bestTestp = testp;
|
||||
bestRemain = remain;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (VlcTest* testp = bestTestp) {
|
||||
testp->rank(nextrank++);
|
||||
testp->rankPoints(bestRemain);
|
||||
remaining.orData(bestTestp->buckets());
|
||||
} else {
|
||||
break; // No test covering more stuff found
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -146,18 +146,18 @@ void VlcTop::rank() {
|
||||
void VlcTop::annotateCalc() {
|
||||
// Calculate per-line information into filedata structure
|
||||
for (VlcPoints::ByName::iterator it=m_points.begin(); it!=m_points.end(); ++it) {
|
||||
const VlcPoint& point = m_points.pointNumber(it->second);
|
||||
string filename = point.filename();
|
||||
int lineno = point.lineno();
|
||||
const VlcPoint& point = m_points.pointNumber(it->second);
|
||||
string filename = point.filename();
|
||||
int lineno = point.lineno();
|
||||
if (!filename.empty() && lineno!=0) {
|
||||
int column = point.column();
|
||||
VlcSource& source = sources().findNewSource(filename);
|
||||
string threshStr = point.thresh();
|
||||
int column = point.column();
|
||||
VlcSource& source = sources().findNewSource(filename);
|
||||
string threshStr = point.thresh();
|
||||
unsigned thresh = (!threshStr.empty()) ? atoi(threshStr.c_str()) : opt.annotateMin();
|
||||
bool ok = (point.count() >= thresh);
|
||||
UINFO(9, "AnnoCalc count "<<filename<<" "<<lineno<<" "<<point.count()<<endl);
|
||||
source.incCount(lineno, column, point.count(), ok);
|
||||
}
|
||||
bool ok = (point.count() >= thresh);
|
||||
UINFO(9, "AnnoCalc count "<<filename<<" "<<lineno<<" "<<point.count()<<endl);
|
||||
source.incCount(lineno, column, point.count(), ok);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -167,23 +167,23 @@ void VlcTop::annotateCalcNeeded() {
|
||||
int totCases = 0;
|
||||
int totOk = 0;
|
||||
for (VlcSources::NameMap::iterator sit=m_sources.begin(); sit!=m_sources.end(); ++sit) {
|
||||
VlcSource& source = sit->second;
|
||||
//UINFO(1,"Source "<<source.name()<<endl);
|
||||
if (opt.annotateAll()) source.needed(true);
|
||||
VlcSource::LinenoMap& lines = source.lines();
|
||||
for (VlcSource::LinenoMap::iterator lit=lines.begin(); lit!=lines.end(); ++lit) {
|
||||
VlcSource::ColumnMap& cmap = lit->second;
|
||||
for (VlcSource::ColumnMap::iterator cit=cmap.begin(); cit!=cmap.end(); ++cit) {
|
||||
VlcSourceCount& col = cit->second;
|
||||
//UINFO(0,"Source "<<source.name()<<" lineno="<<col.lineno()<<" col="<<col.column()<<endl);
|
||||
++totCases;
|
||||
if (col.ok()) {
|
||||
++totOk;
|
||||
} else {
|
||||
source.needed(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
VlcSource& source = sit->second;
|
||||
//UINFO(1,"Source "<<source.name()<<endl);
|
||||
if (opt.annotateAll()) source.needed(true);
|
||||
VlcSource::LinenoMap& lines = source.lines();
|
||||
for (VlcSource::LinenoMap::iterator lit=lines.begin(); lit!=lines.end(); ++lit) {
|
||||
VlcSource::ColumnMap& cmap = lit->second;
|
||||
for (VlcSource::ColumnMap::iterator cit=cmap.begin(); cit!=cmap.end(); ++cit) {
|
||||
VlcSourceCount& col = cit->second;
|
||||
//UINFO(0,"Source "<<source.name()<<" lineno="<<col.lineno()<<" col="<<col.column()<<endl);
|
||||
++totCases;
|
||||
if (col.ok()) {
|
||||
++totOk;
|
||||
} else {
|
||||
source.needed(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
float pct = totCases ? (100*totOk / totCases) : 0;
|
||||
cout<<"Total coverage ("<<totOk<<"/"<<totCases<<") "
|
||||
@ -195,60 +195,61 @@ void VlcTop::annotateOutputFiles(const string& dirname) {
|
||||
// Create if uncreated, ignore errors
|
||||
V3Os::createDir(dirname);
|
||||
for (VlcSources::NameMap::iterator sit=m_sources.begin(); sit!=m_sources.end(); ++sit) {
|
||||
VlcSource& source = sit->second;
|
||||
if (!source.needed()) continue;
|
||||
string filename = source.name();
|
||||
string outfilename = dirname+"/"+V3Os::filenameNonDir(filename);
|
||||
VlcSource& source = sit->second;
|
||||
if (!source.needed()) continue;
|
||||
string filename = source.name();
|
||||
string outfilename = dirname+"/"+V3Os::filenameNonDir(filename);
|
||||
|
||||
UINFO(1,"annotateOutputFile "<<filename<<" -> "<<outfilename<<endl);
|
||||
UINFO(1,"annotateOutputFile "<<filename<<" -> "<<outfilename<<endl);
|
||||
|
||||
std::ifstream is(filename.c_str());
|
||||
if (!is) {
|
||||
v3error("Can't read "<<filename);
|
||||
return;
|
||||
}
|
||||
if (!is) {
|
||||
v3error("Can't read "<<filename);
|
||||
return;
|
||||
}
|
||||
|
||||
std::ofstream os(outfilename.c_str());
|
||||
if (!os) {
|
||||
v3fatal("Can't write "<<outfilename);
|
||||
return;
|
||||
}
|
||||
if (!os) {
|
||||
v3fatal("Can't write "<<outfilename);
|
||||
return;
|
||||
}
|
||||
|
||||
os << "\t// verilator_coverage annotation"<<endl;
|
||||
os << "\t// verilator_coverage annotation"<<endl;
|
||||
|
||||
int lineno = 0;
|
||||
while (!is.eof()) {
|
||||
int lineno = 0;
|
||||
while (!is.eof()) {
|
||||
lineno++;
|
||||
string line = V3Os::getline(is);
|
||||
|
||||
bool first = true;
|
||||
bool first = true;
|
||||
|
||||
VlcSource::LinenoMap& lines = source.lines();
|
||||
VlcSource::LinenoMap::iterator lit=lines.find(lineno);
|
||||
if (lit != lines.end()) {
|
||||
VlcSource::ColumnMap& cmap = lit->second;
|
||||
for (VlcSource::ColumnMap::iterator cit=cmap.begin(); cit!=cmap.end(); ++cit) {
|
||||
VlcSourceCount& col = cit->second;
|
||||
//UINFO(0,"Source "<<source.name()<<" lineno="<<col.lineno()<<" col="<<col.column()<<endl);
|
||||
os<<(col.ok()?" ":"%")
|
||||
VlcSource::LinenoMap& lines = source.lines();
|
||||
VlcSource::LinenoMap::iterator lit=lines.find(lineno);
|
||||
if (lit != lines.end()) {
|
||||
VlcSource::ColumnMap& cmap = lit->second;
|
||||
for (VlcSource::ColumnMap::iterator cit=cmap.begin(); cit!=cmap.end(); ++cit) {
|
||||
VlcSourceCount& col = cit->second;
|
||||
//UINFO(0,"Source "<<source.name()<<" lineno="<<col.lineno()<<" col="<<col.column()<<endl);
|
||||
os<<(col.ok()?" ":"%")
|
||||
<<std::setfill('0')<<std::setw(6)<<col.count()
|
||||
<<"\t"<<line<<endl;
|
||||
if (first) {
|
||||
first = false;
|
||||
// Multiple columns on same line; print line just once
|
||||
<<"\t"<<line<<endl;
|
||||
if (first) {
|
||||
first = false;
|
||||
// Multiple columns on same line; print line just once
|
||||
string indent;
|
||||
for (string::const_iterator pos=line.begin(); pos!=line.end() && isspace(*pos); ++pos) {
|
||||
indent += *pos;
|
||||
}
|
||||
line = indent + "verilator_coverage: (next point on previous line)\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
for (string::const_iterator pos=line.begin();
|
||||
pos!=line.end() && isspace(*pos); ++pos) {
|
||||
indent += *pos;
|
||||
}
|
||||
line = indent + "verilator_coverage: (next point on previous line)\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (first) {
|
||||
os<<"\t"<<line<<endl;
|
||||
}
|
||||
}
|
||||
if (first) {
|
||||
os<<"\t"<<line<<endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -258,4 +259,3 @@ void VlcTop::annotate(const string& dirname) {
|
||||
annotateCalcNeeded();
|
||||
annotateOutputFiles(dirname);
|
||||
}
|
||||
|
||||
|
@ -1420,16 +1420,16 @@ sub _make_top_v {
|
||||
# Test
|
||||
print $fh "\n";
|
||||
print $fh " initial begin\n";
|
||||
print $fh " fastclk=0;\n" if $self->{inputs}{fastclk};
|
||||
print $fh " clk=0;\n" if $self->{inputs}{clk};
|
||||
print $fh " fastclk = 0;\n" if $self->{inputs}{fastclk};
|
||||
print $fh " clk = 0;\n" if $self->{inputs}{clk};
|
||||
print $fh " #10;\n";
|
||||
print $fh " fastclk=1;\n" if $self->{inputs}{fastclk};
|
||||
print $fh " clk=1;\n" if $self->{inputs}{clk};
|
||||
print $fh " fastclk = 1;\n" if $self->{inputs}{fastclk};
|
||||
print $fh " clk = 1;\n" if $self->{inputs}{clk};
|
||||
print $fh " while (\$time < $self->{sim_time}) begin\n";
|
||||
for (my $i=0; $i<5; $i++) {
|
||||
print $fh " #1;\n";
|
||||
print $fh " fastclk=!fastclk;\n" if $self->{inputs}{fastclk};
|
||||
print $fh " clk=!clk;\n" if $i==4 && $self->{inputs}{clk};
|
||||
print $fh " fastclk = !fastclk;\n" if $self->{inputs}{fastclk};
|
||||
print $fh " clk = !clk;\n" if $i==4 && $self->{inputs}{clk};
|
||||
}
|
||||
print $fh " end\n";
|
||||
print $fh " end\n";
|
||||
@ -1657,7 +1657,7 @@ sub vcd_identical {
|
||||
# Also provides backup if vcddiff not installed
|
||||
my $h1 = $self->_vcd_read($fn1);
|
||||
my $h2 = $self->_vcd_read($fn2);
|
||||
$Data::Dumper::Sortkeys=1;
|
||||
$Data::Dumper::Sortkeys = 1;
|
||||
my $a = Dumper($h1);
|
||||
my $b = Dumper($h2);
|
||||
if ($a ne $b) {
|
||||
|
Loading…
Reference in New Issue
Block a user