Internals: Detab and fix spacing style issues in some include files. No functional change.

This commit is contained in:
Wilson Snyder 2019-05-07 23:00:52 -04:00
parent f818ddc71c
commit b23fc06388
14 changed files with 839 additions and 842 deletions

View File

@ -1712,7 +1712,7 @@ This is an example similar to the above, but using SystemC.
#include "Vour.h" #include "Vour.h"
int sc_main(int argc, char **argv) { int sc_main(int argc, char **argv) {
Verilated::commandArgs(argc, 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; Vour* top;
top = new Vour("top"); top = new Vour("top");
top->clk(clk); 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 synthesis which analyzes interconnection per-bit, but is circular to
simulation which analyzes per-bus: 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 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. "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: 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, and change all receiving logic to instead receive "xout". Alternatively,
change it to 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". 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: 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 Ignoring this warning will only suppress the lint check, it will simulate
correctly. 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 that widths inside concatenates and replicates must be sized, and should be
fixed in the code. 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: An example where this is technically legal (though still bad form) is:
parameter PAR = 1; 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 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 parameter definition ("parameter [31:0]"), or add the width to the

View File

@ -50,10 +50,10 @@ public: // But only local to this file
// CONSTRUCTORS // CONSTRUCTORS
// Derived classes should call zero() in their constructor // Derived classes should call zero() in their constructor
VerilatedCovImpItem() { VerilatedCovImpItem() {
for (int i=0; i<MAX_KEYS; ++i) { for (int i=0; i<MAX_KEYS; ++i) {
m_keys[i]=KEY_UNDEF; m_keys[i] = KEY_UNDEF;
m_vals[i]=0; m_vals[i] = 0;
} }
} }
virtual ~VerilatedCovImpItem() {} virtual ~VerilatedCovImpItem() {}
virtual vluint64_t count() const = 0; virtual vluint64_t count() const = 0;
@ -96,7 +96,7 @@ private:
private: private:
// MEMBERS // 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 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 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 ItemList m_items VL_GUARDED_BY(m_mutex); ///< List of all items
@ -107,294 +107,294 @@ private:
// CONSTRUCTORS // CONSTRUCTORS
VerilatedCovImp() { VerilatedCovImp() {
m_insertp = NULL; m_insertp = NULL;
m_insertFilenamep = NULL; m_insertFilenamep = NULL;
m_insertLineno = 0; m_insertLineno = 0;
} }
VL_UNCOPYABLE(VerilatedCovImp); VL_UNCOPYABLE(VerilatedCovImp);
public: public:
~VerilatedCovImp() { clearGuts(); } ~VerilatedCovImp() { clearGuts(); }
static VerilatedCovImp& imp() VL_MT_SAFE { static VerilatedCovImp& imp() VL_MT_SAFE {
static VerilatedCovImp s_singleton; static VerilatedCovImp s_singleton;
return s_singleton; return s_singleton;
} }
private: private:
// PRIVATE METHODS // PRIVATE METHODS
int valueIndex(const std::string& value) VL_REQUIRES(m_mutex) { int valueIndex(const std::string& value) VL_REQUIRES(m_mutex) {
static int nextIndex = KEY_UNDEF+1; static int nextIndex = KEY_UNDEF+1;
ValueIndexMap::iterator iter = m_valueIndexes.find(value); ValueIndexMap::iterator iter = m_valueIndexes.find(value);
if (iter != m_valueIndexes.end()) return iter->second; if (iter != m_valueIndexes.end()) return iter->second;
nextIndex++; assert(nextIndex>0); nextIndex++; assert(nextIndex>0);
m_valueIndexes.insert(std::make_pair(value, nextIndex)); m_valueIndexes.insert(std::make_pair(value, nextIndex));
m_indexValues.insert(std::make_pair(nextIndex, value)); m_indexValues.insert(std::make_pair(nextIndex, value));
return nextIndex; return nextIndex;
} }
static std::string dequote(const std::string& text) VL_PURE { static std::string dequote(const std::string& text) VL_PURE {
// Quote any special characters // Quote any special characters
std::string rtn; std::string rtn;
for (const char* pos = text.c_str(); *pos; ++pos) { for (const char* pos = text.c_str(); *pos; ++pos) {
if (!isprint(*pos) || *pos=='%' || *pos=='"') { if (!isprint(*pos) || *pos=='%' || *pos=='"') {
char hex[10]; sprintf(hex,"%%%02X",pos[0]); char hex[10]; sprintf(hex, "%%%02X", pos[0]);
rtn += hex; rtn += hex;
} else { } else {
rtn += *pos; rtn += *pos;
} }
} }
return rtn; return rtn;
} }
static bool legalKey(const std::string& key) VL_PURE { static bool legalKey(const std::string& key) VL_PURE {
// Because we compress long keys to a single letter, and // Because we compress long keys to a single letter, and
// don't want applications to either get confused if they use // don't want applications to either get confused if they use
// a letter differently, nor want them to rely on our compression... // a letter differently, nor want them to rely on our compression...
// (Considered using numeric keys, but will remain back compatible.) // (Considered using numeric keys, but will remain back compatible.)
if (key.length()<2) return false; if (key.length()<2) return false;
if (key.length()==2 && isdigit(key[1])) return false; if (key.length()==2 && isdigit(key[1])) return false;
return true; return true;
} }
static std::string keyValueFormatter(const std::string& key, const std::string& value) VL_PURE { static std::string keyValueFormatter(const std::string& key, const std::string& value) VL_PURE {
std::string name; std::string name;
if (key.length()==1 && isalpha(key[0])) { if (key.length()==1 && isalpha(key[0])) {
name += std::string("\001")+key; name += std::string("\001")+key;
} else { } else {
name += std::string("\001")+dequote(key); name += std::string("\001")+dequote(key);
} }
name += std::string("\002")+dequote(value); name += std::string("\002")+dequote(value);
return name; return name;
} }
static std::string combineHier(const std::string& old, const std::string& add) VL_PURE { 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.x) => foo.*.x
// (foo.a.x, foo.b.y) => foo.* // (foo.a.x, foo.b.y) => foo.*
// (foo.a.x, foo.b) => foo.* // (foo.a.x, foo.b) => foo.*
if (old == add) return add; if (old == add) return add;
if (old.empty()) return add; if (old.empty()) return add;
if (add.empty()) return old; if (add.empty()) return old;
const char* a = old.c_str(); const char* a = old.c_str();
const char* b = add.c_str(); const char* b = add.c_str();
// Scan forward to first mismatch // Scan forward to first mismatch
const char* apre = a; const char* apre = a;
const char* bpre = b; const char* bpre = b;
while (*apre == *bpre) { apre++; bpre++; } while (*apre == *bpre) { apre++; bpre++; }
// We used to backup and split on only .'s but it seems better to be verbose // We used to backup and split on only .'s but it seems better to be verbose
// and not assume . is the separator // and not assume . is the separator
std::string prefix = std::string(a,apre-a); std::string prefix = std::string(a, apre-a);
// Scan backward to last mismatch // Scan backward to last mismatch
const char* apost = a+strlen(a)-1; const char* apost = a+strlen(a)-1;
const char* bpost = b+strlen(b)-1; const char* bpost = b+strlen(b)-1;
while (*apost == *bpost while (*apost == *bpost
&& apost>apre && bpost>bpre) { apost--; bpost--; } && apost>apre && bpost>bpre) { apost--; bpost--; }
// Forward to . so we have a whole word // Forward to . so we have a whole word
std::string suffix = *bpost ? std::string(bpost+1) : ""; 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; //cout << "\nch pre="<<prefix<<" s="<<suffix<<"\nch a="<<old<<"\nch b="<<add<<"\nch o="<<out<<endl;
return out; return out;
} }
bool itemMatchesString(VerilatedCovImpItem* itemp, const std::string& match) VL_REQUIRES(m_mutex) { bool itemMatchesString(VerilatedCovImpItem* itemp, const std::string& match) VL_REQUIRES(m_mutex) {
for (int i=0; i<MAX_KEYS; ++i) { for (int i=0; i<MAX_KEYS; ++i) {
if (itemp->m_keys[i] != KEY_UNDEF) { if (itemp->m_keys[i] != KEY_UNDEF) {
// We don't compare keys, only values // We don't compare keys, only values
std::string val = m_indexValues[itemp->m_vals[i]]; std::string val = m_indexValues[itemp->m_vals[i]];
if (std::string::npos != val.find(match)) { // Found if (std::string::npos != val.find(match)) { // Found
return true; return true;
} }
} }
} }
return false; return false;
} }
static void selftest() VL_MT_SAFE { static void selftest() VL_MT_SAFE {
// Little selftest // 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.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.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.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("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("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.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("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"); 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) { void clearGuts() VL_REQUIRES(m_mutex) {
for (ItemList::const_iterator it=m_items.begin(); it!=m_items.end(); ++it) { for (ItemList::const_iterator it=m_items.begin(); it!=m_items.end(); ++it) {
VerilatedCovImpItem* itemp = *(it); VerilatedCovImpItem* itemp = *(it);
delete itemp; delete itemp;
} }
m_items.clear(); m_items.clear();
m_indexValues.clear(); m_indexValues.clear();
m_valueIndexes.clear(); m_valueIndexes.clear();
} }
public: public:
// PUBLIC METHODS // PUBLIC METHODS
void clear() VL_EXCLUDES(m_mutex) { void clear() VL_EXCLUDES(m_mutex) {
Verilated::quiesce(); Verilated::quiesce();
VerilatedLockGuard lock(m_mutex); VerilatedLockGuard lock(m_mutex);
clearGuts(); clearGuts();
} }
void clearNonMatch(const char* matchp) VL_EXCLUDES(m_mutex) { void clearNonMatch(const char* matchp) VL_EXCLUDES(m_mutex) {
Verilated::quiesce(); Verilated::quiesce();
VerilatedLockGuard lock(m_mutex); VerilatedLockGuard lock(m_mutex);
if (matchp && matchp[0]) { if (matchp && matchp[0]) {
ItemList newlist; ItemList newlist;
for (ItemList::iterator it=m_items.begin(); it!=m_items.end(); ++it) { for (ItemList::iterator it=m_items.begin(); it!=m_items.end(); ++it) {
VerilatedCovImpItem* itemp = *(it); VerilatedCovImpItem* itemp = *(it);
if (!itemMatchesString(itemp, matchp)) { if (!itemMatchesString(itemp, matchp)) {
delete itemp; delete itemp;
} else { } else {
newlist.push_back(itemp); newlist.push_back(itemp);
} }
} }
m_items = newlist; m_items = newlist;
} }
} }
void zero() VL_EXCLUDES(m_mutex) { void zero() VL_EXCLUDES(m_mutex) {
Verilated::quiesce(); Verilated::quiesce();
VerilatedLockGuard lock(m_mutex); VerilatedLockGuard lock(m_mutex);
for (ItemList::const_iterator it=m_items.begin(); it!=m_items.end(); ++it) { for (ItemList::const_iterator it=m_items.begin(); it!=m_items.end(); ++it) {
(*it)->zero(); (*it)->zero();
} }
} }
// We assume there's always call to i/f/p in that order // We assume there's always call to i/f/p in that order
void inserti(VerilatedCovImpItem* itemp) VL_EXCLUDES(m_mutex) { void inserti(VerilatedCovImpItem* itemp) VL_EXCLUDES(m_mutex) {
VerilatedLockGuard lock(m_mutex); VerilatedLockGuard lock(m_mutex);
assert(!m_insertp); assert(!m_insertp);
m_insertp = itemp; m_insertp = itemp;
} }
void insertf(const char* filenamep, int lineno) VL_EXCLUDES(m_mutex) { void insertf(const char* filenamep, int lineno) VL_EXCLUDES(m_mutex) {
VerilatedLockGuard lock(m_mutex); VerilatedLockGuard lock(m_mutex);
m_insertFilenamep = filenamep; m_insertFilenamep = filenamep;
m_insertLineno = lineno; m_insertLineno = lineno;
} }
void insertp(const char* ckeyps[MAX_KEYS], void insertp(const char* ckeyps[MAX_KEYS],
const char* valps[MAX_KEYS]) VL_EXCLUDES(m_mutex) { const char* valps[MAX_KEYS]) VL_EXCLUDES(m_mutex) {
VerilatedLockGuard lock(m_mutex); VerilatedLockGuard lock(m_mutex);
assert(m_insertp); assert(m_insertp);
// First two key/vals are filename // First two key/vals are filename
ckeyps[0]="filename"; valps[0]=m_insertFilenamep; ckeyps[0]="filename"; valps[0]=m_insertFilenamep;
std::string linestr = vlCovCvtToStr(m_insertLineno); std::string linestr = vlCovCvtToStr(m_insertLineno);
ckeyps[1]="lineno"; valps[1]=linestr.c_str(); ckeyps[1]="lineno"; valps[1]=linestr.c_str();
// Default page if not specified // Default page if not specified
const char* fnstartp = m_insertFilenamep; const char* fnstartp = m_insertFilenamep;
while (const char* foundp = strchr(fnstartp,'/')) fnstartp=foundp+1; while (const char* foundp = strchr(fnstartp,'/')) fnstartp = foundp+1;
const char* fnendp = fnstartp; const char* fnendp = fnstartp;
while (*fnendp && *fnendp!='.') fnendp++; while (*fnendp && *fnendp!='.') fnendp++;
std::string page_default = "sp_user/"+std::string(fnstartp,fnendp-fnstartp); std::string page_default = "sp_user/"+std::string(fnstartp, fnendp-fnstartp);
ckeyps[2]="page"; valps[2]=page_default.c_str(); ckeyps[2]="page"; valps[2]=page_default.c_str();
// Keys -> strings // Keys -> strings
std::string keys[MAX_KEYS]; std::string keys[MAX_KEYS];
for (int i=0; i<MAX_KEYS; ++i) { for (int i=0; i<MAX_KEYS; ++i) {
if (ckeyps[i] && ckeyps[i][0]) { if (ckeyps[i] && ckeyps[i][0]) {
keys[i] = ckeyps[i]; keys[i] = ckeyps[i];
} }
} }
// Ignore empty keys // Ignore empty keys
for (int i=0; i<MAX_KEYS; ++i) { for (int i=0; i<MAX_KEYS; ++i) {
if (!keys[i].empty()) { if (!keys[i].empty()) {
for (int j=i+1; j<MAX_KEYS; ++j) { for (int j=i+1; j<MAX_KEYS; ++j) {
if (keys[i] == keys[j]) { // Duplicate key. Keep the last one if (keys[i] == keys[j]) { // Duplicate key. Keep the last one
keys[i] = ""; keys[i] = "";
break; break;
} }
} }
} }
} }
// Insert the values // Insert the values
int addKeynum=0; int addKeynum = 0;
for (int i=0; i<MAX_KEYS; ++i) { for (int i=0; i<MAX_KEYS; ++i) {
const std::string key = keys[i]; const std::string key = keys[i];
if (!keys[i].empty()) { if (!keys[i].empty()) {
const std::string val = valps[i]; const std::string val = valps[i];
//cout<<" "<<__FUNCTION__<<" "<<key<<" = "<<val<<endl; //cout<<" "<<__FUNCTION__<<" "<<key<<" = "<<val<<endl;
m_insertp->m_keys[addKeynum] = valueIndex(key); m_insertp->m_keys[addKeynum] = valueIndex(key);
m_insertp->m_vals[addKeynum] = valueIndex(val); m_insertp->m_vals[addKeynum] = valueIndex(val);
addKeynum++; addKeynum++;
if (!legalKey(key)) { if (!legalKey(key)) {
std::string msg = "%Error: Coverage keys of one character, or letter+digit are illegal: "+key; std::string msg = "%Error: Coverage keys of one character, or letter+digit are illegal: "+key;
VL_FATAL_MT("",0,"",msg.c_str()); VL_FATAL_MT("", 0, "", msg.c_str());
} }
} }
} }
m_items.push_back(m_insertp); m_items.push_back(m_insertp);
// Prepare for next // Prepare for next
m_insertp = NULL; m_insertp = NULL;
} }
void write(const char* filename) VL_EXCLUDES(m_mutex) { void write(const char* filename) VL_EXCLUDES(m_mutex) {
Verilated::quiesce(); Verilated::quiesce();
VerilatedLockGuard lock(m_mutex); VerilatedLockGuard lock(m_mutex);
#ifndef VM_COVERAGE #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 #endif
selftest(); selftest();
std::ofstream os(filename); std::ofstream os(filename);
if (os.fail()) { if (os.fail()) {
std::string msg = std::string("%Error: Can't write '")+filename+"'"; std::string msg = std::string("%Error: Can't write '")+filename+"'";
VL_FATAL_MT("",0,"",msg.c_str()); VL_FATAL_MT("", 0, "", msg.c_str());
return; return;
} }
os << "# SystemC::Coverage-3\n"; os << "# SystemC::Coverage-3\n";
// Build list of events; totalize if collapsing hierarchy // Build list of events; totalize if collapsing hierarchy
typedef std::map<std::string,std::pair<std::string,vluint64_t> > EventMap; typedef std::map<std::string,std::pair<std::string,vluint64_t> > EventMap;
EventMap eventCounts; EventMap eventCounts;
for (ItemList::iterator it=m_items.begin(); it!=m_items.end(); ++it) { for (ItemList::iterator it=m_items.begin(); it!=m_items.end(); ++it) {
VerilatedCovImpItem* itemp = *(it); VerilatedCovImpItem* itemp = *(it);
std::string name; std::string name;
std::string hier; std::string hier;
bool per_instance = false; bool per_instance = false;
for (int i=0; i<MAX_KEYS; ++i) { for (int i=0; i<MAX_KEYS; ++i) {
if (itemp->m_keys[i] != KEY_UNDEF) { if (itemp->m_keys[i] != KEY_UNDEF) {
std::string key = VerilatedCovKey::shortKey(m_indexValues[itemp->m_keys[i]]); std::string key = VerilatedCovKey::shortKey(m_indexValues[itemp->m_keys[i]]);
std::string val = m_indexValues[itemp->m_vals[i]]; std::string val = m_indexValues[itemp->m_vals[i]];
if (key == VL_CIK_PER_INSTANCE) { if (key == VL_CIK_PER_INSTANCE) {
if (val != "0") per_instance = true; if (val != "0") per_instance = true;
} }
if (key == VL_CIK_HIER) { if (key == VL_CIK_HIER) {
hier = val; hier = val;
} else { } else {
// Print it // Print it
name += keyValueFormatter(key,val); name += keyValueFormatter(key, val);
} }
} }
} }
if (per_instance) { // Not collapsing hierarchies if (per_instance) { // Not collapsing hierarchies
name += keyValueFormatter(VL_CIK_HIER,hier); name += keyValueFormatter(VL_CIK_HIER, hier);
hier = ""; hier = "";
} }
// Group versus point labels don't matter here, downstream // Group versus point labels don't matter here, downstream
// deals with it. Seems bad for sizing though and doesn't // deals with it. Seems bad for sizing though and doesn't
// allow easy addition of new group codes (would be // allow easy addition of new group codes (would be
// inefficient) // inefficient)
// Find or insert the named event // Find or insert the named event
EventMap::iterator cit = eventCounts.find(name); EventMap::iterator cit = eventCounts.find(name);
if (cit != eventCounts.end()) { if (cit != eventCounts.end()) {
const std::string& oldhier = cit->second.first; const std::string& oldhier = cit->second.first;
cit->second.second += itemp->count(); cit->second.second += itemp->count();
cit->second.first = combineHier(oldhier, hier); cit->second.first = combineHier(oldhier, hier);
} else { } else {
eventCounts.insert(std::make_pair(name, make_pair(hier,itemp->count()))); eventCounts.insert(std::make_pair(name, make_pair(hier, itemp->count())));
} }
} }
// Output body // Output body
for (EventMap::const_iterator it=eventCounts.begin(); it!=eventCounts.end(); ++it) { for (EventMap::const_iterator it=eventCounts.begin(); it!=eventCounts.end(); ++it) {
os<<"C '"<<std::dec; os<<"C '"<<std::dec;
os<<it->first; os<<it->first;
if (!it->second.first.empty()) os<<keyValueFormatter(VL_CIK_HIER,it->second.first); if (!it->second.first.empty()) os<<keyValueFormatter(VL_CIK_HIER, it->second.first);
os<<"' "<<it->second.second; os<<"' "<<it->second.second;
os<<std::endl; os<<std::endl;
} }
} }
}; };
@ -420,7 +420,7 @@ void VerilatedCov::_inserti(vluint64_t* itemp) VL_MT_SAFE {
VerilatedCovImp::imp().inserti(new VerilatedCoverItemSpec<vluint64_t>(itemp)); VerilatedCovImp::imp().inserti(new VerilatedCoverItemSpec<vluint64_t>(itemp));
} }
void VerilatedCov::_insertf(const char* filename, int lineno) VL_MT_SAFE { 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 #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!) // 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 { 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), _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(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(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), 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 { 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), _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), 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)); N(20),N(21),N(22),N(23),N(24),N(25),N(26),N(27),N(28),N(29));
} }
// Backward compatibility for Verilator // Backward compatibility for Verilator
void VerilatedCov::_insertp(A(0), A(1), K(2),int val2, K(3),int val3, 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 val2str = vlCovCvtToStr(val2);
std::string val3str = vlCovCvtToStr(val3); std::string val3str = vlCovCvtToStr(val3);
_insertp(C(0),C(1), _insertp(C(0),C(1),
key2,val2str.c_str(), key3,val3str.c_str(), key4, val4.c_str(), key2,val2str.c_str(), key3,val3str.c_str(), key4, val4.c_str(),
C(5),C(6),N(7),N(8),N(9), 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(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(20),N(21),N(22),N(23),N(24),N(25),N(26),N(27),N(28),N(29));
} }
#undef A #undef A
#undef C #undef C

View File

@ -44,31 +44,31 @@
/// The value may be a string, or another type which will be auto-converted to a string. /// The value may be a string, or another type which will be auto-converted to a string.
/// ///
/// Some typical keys: /// Some typical keys:
/// filename File the recording occurs in. Defaults to __FILE__ /// filename File the recording occurs in. Defaults to __FILE__
/// lineno Line number the recording occurs in. Defaults to __LINE__ /// lineno Line number the recording occurs in. Defaults to __LINE__
/// column Column number (or occurrence# for dup file/lines). Defaults to undef. /// column Column number (or occurrence# for dup file/lines). Defaults to undef.
/// hier Hierarchical name. Defaults to name() /// hier Hierarchical name. Defaults to name()
/// type Type of coverage. Defaults to "user" /// type Type of coverage. Defaults to "user"
/// Other types are 'block', 'fsm', 'toggle'. /// Other types are 'block', 'fsm', 'toggle'.
/// comment Description of the coverage event. Should be set by the user. /// comment Description of the coverage event. Should be set by the user.
/// Comments for type==block: 'if', 'else', 'elsif', 'case' /// Comments for type==block: 'if', 'else', 'elsif', 'case'
/// thresh Threshold to consider fully covered. /// thresh Threshold to consider fully covered.
/// If unspecified, downstream tools will determine it. /// If unspecified, downstream tools will determine it.
/// ///
/// Examples: /// Examples:
/// ///
/// vluint32_t m_cases[10]; /// vluint32_t m_cases[10];
/// constructor { /// constructor {
/// for (int i=0; i<10; ++i) { m_cases[i]=0; } /// 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...) \ #define VL_COVER_INSERT(countp,args...) \
VL_IF_COVER(VerilatedCov::_inserti(countp); \ VL_IF_COVER(VerilatedCov::_inserti(countp); \
VerilatedCov::_insertf(__FILE__,__LINE__); \ VerilatedCov::_insertf(__FILE__,__LINE__); \
VerilatedCov::_insertp("hier", name(), args)) VerilatedCov::_insertp("hier", name(), args))
//============================================================================= //=============================================================================
/// Convert VL_COVER_INSERT value arguments to strings /// Convert VL_COVER_INSERT value arguments to strings

View File

@ -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); const vluint8_t* __restrict dp = static_cast<const vluint8_t* __restrict>(datap);
vluint8_t miss = 0; vluint8_t miss = 0;
while (size--) { while (size--) {
miss |= (*dp++ ^ *m_cp++); miss |= (*dp++ ^ *m_cp++);
} }
return (miss!=0); return (miss!=0);
} }
VerilatedDeserialize& VerilatedDeserialize::readAssert(const void* __restrict datap, size_t size) VL_MT_UNSAFE_ONE { VerilatedDeserialize& VerilatedDeserialize::readAssert(const void* __restrict datap, size_t size) VL_MT_UNSAFE_ONE {
if (VL_UNLIKELY(readDiffers(datap,size))) { if (VL_UNLIKELY(readDiffers(datap, size))) {
std::string fn = filename(); std::string fn = filename();
std::string msg = std::string("Can't deserialize save-restore file as was made from different model"); 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()); VL_FATAL_MT(fn.c_str(), 0, "", msg.c_str());
close(); close();
} }
return *this; // For function chaining return *this; // For function chaining
} }
@ -84,10 +84,10 @@ void VerilatedSerialize::header() VL_MT_UNSAFE_ONE {
void VerilatedDeserialize::header() VL_MT_UNSAFE_ONE { void VerilatedDeserialize::header() VL_MT_UNSAFE_ONE {
VerilatedDeserialize& os = *this; // So can cut and paste standard >> code below VerilatedDeserialize& os = *this; // So can cut and paste standard >> code below
if (VL_UNLIKELY(os.readDiffers(VLTSAVE_HEADER_STR, strlen(VLTSAVE_HEADER_STR)))) { if (VL_UNLIKELY(os.readDiffers(VLTSAVE_HEADER_STR, strlen(VLTSAVE_HEADER_STR)))) {
std::string fn = filename(); std::string fn = filename();
std::string msg = std::string("Can't deserialize; file has wrong header signature"); std::string msg = std::string("Can't deserialize; file has wrong header signature");
VL_FATAL_MT(fn.c_str(), 0, "", msg.c_str()); VL_FATAL_MT(fn.c_str(), 0, "", msg.c_str());
close(); close();
} }
os.read(Verilated::serializedPtr(), Verilated::serializedSize()); os.read(Verilated::serializedPtr(), Verilated::serializedSize());
} }
@ -101,10 +101,10 @@ void VerilatedSerialize::trailer() VL_MT_UNSAFE_ONE {
void VerilatedDeserialize::trailer() VL_MT_UNSAFE_ONE { void VerilatedDeserialize::trailer() VL_MT_UNSAFE_ONE {
VerilatedDeserialize& os = *this; // So can cut and paste standard >> code below VerilatedDeserialize& os = *this; // So can cut and paste standard >> code below
if (VL_UNLIKELY(os.readDiffers(VLTSAVE_TRAILER_STR, strlen(VLTSAVE_TRAILER_STR)))) { if (VL_UNLIKELY(os.readDiffers(VLTSAVE_TRAILER_STR, strlen(VLTSAVE_TRAILER_STR)))) {
std::string fn = filename(); std::string fn = filename();
std::string msg = std::string("Can't deserialize; file has wrong end-of-file signature"); 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()); VL_FATAL_MT(fn.c_str(), 0, "", msg.c_str());
close(); close();
} }
} }
@ -116,19 +116,19 @@ void VerilatedDeserialize::trailer() VL_MT_UNSAFE_ONE {
void VerilatedSave::open(const char* filenamep) VL_MT_UNSAFE_ONE { void VerilatedSave::open(const char* filenamep) VL_MT_UNSAFE_ONE {
m_assertOne.check(); m_assertOne.check();
if (isOpen()) return; 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]=='|') { if (filenamep[0]=='|') {
assert(0); // Not supported yet. assert(0); // Not supported yet.
} else { } else {
// cppcheck-suppress duplicateExpression // cppcheck-suppress duplicateExpression
m_fd = ::open(filenamep, O_CREAT|O_WRONLY|O_TRUNC|O_LARGEFILE|O_NONBLOCK|O_CLOEXEC m_fd = ::open(filenamep, O_CREAT|O_WRONLY|O_TRUNC|O_LARGEFILE|O_NONBLOCK|O_CLOEXEC
, 0666); , 0666);
if (m_fd<0) { if (m_fd<0) {
// User code can check isOpen() // User code can check isOpen()
m_isOpen = false; m_isOpen = false;
return; return;
} }
} }
m_isOpen = true; m_isOpen = true;
m_filename = filenamep; 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 { void VerilatedRestore::open(const char* filenamep) VL_MT_UNSAFE_ONE {
m_assertOne.check(); m_assertOne.check();
if (isOpen()) return; 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]=='|') { if (filenamep[0]=='|') {
assert(0); // Not supported yet. assert(0); // Not supported yet.
} else { } else {
// cppcheck-suppress duplicateExpression // cppcheck-suppress duplicateExpression
m_fd = ::open(filenamep, O_CREAT|O_RDONLY|O_LARGEFILE|O_CLOEXEC m_fd = ::open(filenamep, O_CREAT|O_RDONLY|O_LARGEFILE|O_CLOEXEC
, 0666); , 0666);
if (m_fd<0) { if (m_fd<0) {
// User code can check isOpen() // User code can check isOpen()
m_isOpen = false; m_isOpen = false;
return; return;
} }
} }
m_isOpen = true; m_isOpen = true;
m_filename = filenamep; m_filename = filenamep;
@ -184,21 +184,21 @@ void VerilatedSave::flush() VL_MT_UNSAFE_ONE {
if (VL_UNLIKELY(!isOpen())) return; if (VL_UNLIKELY(!isOpen())) return;
vluint8_t* wp = m_bufp; vluint8_t* wp = m_bufp;
while (1) { while (1) {
ssize_t remaining = (m_cp - wp); ssize_t remaining = (m_cp - wp);
if (remaining==0) break; if (remaining==0) break;
errno = 0; errno = 0;
ssize_t got = ::write(m_fd, wp, remaining); ssize_t got = ::write(m_fd, wp, remaining);
if (got>0) { if (got>0) {
wp += got; wp += got;
} else if (got < 0) { } else if (got < 0) {
if (errno != EAGAIN && errno != EINTR) { if (errno != EAGAIN && errno != EINTR) {
// write failed, presume error (perhaps out of disk space) // write failed, presume error (perhaps out of disk space)
std::string msg = std::string(__FUNCTION__)+": "+strerror(errno); std::string msg = std::string(__FUNCTION__)+": "+strerror(errno);
VL_FATAL_MT("",0,"",msg.c_str()); VL_FATAL_MT("", 0, "", msg.c_str());
close(); close();
break; break;
} }
} }
} }
m_cp = m_bufp; // Reset buffer m_cp = m_bufp; // Reset buffer
} }
@ -213,30 +213,28 @@ void VerilatedRestore::fill() VL_MT_UNSAFE_ONE {
m_cp = m_bufp; // Reset buffer m_cp = m_bufp; // Reset buffer
// Read into buffer starting at m_endp // Read into buffer starting at m_endp
while (1) { while (1) {
ssize_t remaining = (m_bufp+bufferSize() - m_endp); ssize_t remaining = (m_bufp+bufferSize() - m_endp);
if (remaining==0) break; if (remaining==0) break;
errno = 0; errno = 0;
ssize_t got = ::read(m_fd, m_endp, remaining); ssize_t got = ::read(m_fd, m_endp, remaining);
if (got>0) { if (got>0) {
m_endp += got; m_endp += got;
} else if (got < 0) { } else if (got < 0) {
if (errno != EAGAIN && errno != EINTR) { if (errno != EAGAIN && errno != EINTR) {
// write failed, presume error (perhaps out of disk space) // write failed, presume error (perhaps out of disk space)
std::string msg = std::string(__FUNCTION__)+": "+strerror(errno); std::string msg = std::string(__FUNCTION__)+": "+strerror(errno);
VL_FATAL_MT("",0,"",msg.c_str()); VL_FATAL_MT("", 0, "", msg.c_str());
close(); close();
break; break;
} }
} else { // got==0, EOF } else { // got==0, EOF
// Fill buffer from here to end with NULLs so reader's don't // Fill buffer from here to end with NULLs so reader's don't
// need to check eof each character. // need to check eof each character.
while (m_endp < m_bufp+bufferSize()) *m_endp++ = '\0'; while (m_endp < m_bufp+bufferSize()) *m_endp++ = '\0';
break; break;
} }
} }
} }
//============================================================================= //=============================================================================
// Serialization of types // Serialization of types

View File

@ -34,10 +34,10 @@ class VerilatedSerialize {
protected: protected:
// MEMBERS // MEMBERS
// For speed, keep m_cp as the first member of this structure // 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_cp; ///< Current pointer into m_bufp buffer
vluint8_t* m_bufp; ///< Output buffer vluint8_t* m_bufp; ///< Output buffer
bool m_isOpen; ///< True indicates open file/stream bool m_isOpen; ///< True indicates open file/stream
std::string m_filename; ///< Filename, for error messages std::string m_filename; ///< Filename, for error messages
VerilatedAssertOneThread m_assertOne; ///< Assert only called from single thread 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 bufferSize() { return 256*1024; } // See below for slack calculation
@ -50,13 +50,13 @@ protected:
VL_UNCOPYABLE(VerilatedSerialize); VL_UNCOPYABLE(VerilatedSerialize);
public: public:
VerilatedSerialize() { VerilatedSerialize() {
m_isOpen = false; m_isOpen = false;
m_bufp = new vluint8_t [bufferSize()]; m_bufp = new vluint8_t [bufferSize()];
m_cp = m_bufp; m_cp = m_bufp;
} }
virtual ~VerilatedSerialize() { virtual ~VerilatedSerialize() {
close(); close();
if (m_bufp) { delete m_bufp; m_bufp=NULL; } if (m_bufp) { delete m_bufp; m_bufp=NULL; }
} }
// METHODS // METHODS
bool isOpen() const { return m_isOpen; } bool isOpen() const { return m_isOpen; }
@ -64,24 +64,24 @@ public:
virtual void close() VL_MT_UNSAFE_ONE { flush(); } virtual void close() VL_MT_UNSAFE_ONE { flush(); }
virtual void flush() VL_MT_UNSAFE_ONE {} virtual void flush() VL_MT_UNSAFE_ONE {}
inline VerilatedSerialize& write(const void* __restrict datap, size_t size) 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; const vluint8_t* __restrict dp = (const vluint8_t* __restrict)datap;
while (size) { while (size) {
bufferCheck(); bufferCheck();
size_t blk = size; if (blk>bufferInsertSize()) blk = bufferInsertSize(); size_t blk = size; if (blk>bufferInsertSize()) blk = bufferInsertSize();
const vluint8_t* __restrict maxp = dp + blk; const vluint8_t* __restrict maxp = dp + blk;
while (dp < maxp) *m_cp++ = *dp++; while (dp < maxp) *m_cp++ = *dp++;
size -= blk; size -= blk;
} }
return *this; // For function chaining return *this; // For function chaining
} }
private: private:
VerilatedSerialize& bufferCheck() VL_MT_UNSAFE_ONE { VerilatedSerialize& bufferCheck() VL_MT_UNSAFE_ONE {
// Flush the write buffer if there's not enough space left for new information // 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 // 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())))) { if (VL_UNLIKELY(m_cp > (m_bufp+(bufferSize()-bufferInsertSize())))) {
flush(); flush();
} }
return *this; // For function chaining return *this; // For function chaining
} }
}; };
@ -93,12 +93,12 @@ class VerilatedDeserialize {
protected: protected:
// MEMBERS // MEMBERS
// For speed, keep m_cp as the first member of this structure // 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_cp; ///< Current pointer into m_bufp buffer
vluint8_t* m_bufp; ///< Output buffer vluint8_t* m_bufp; ///< Output buffer
vluint8_t* m_endp; ///< Last valid byte in m_bufp buffer vluint8_t* m_endp; ///< Last valid byte in m_bufp buffer
bool m_isOpen; ///< True indicates open file/stream bool m_isOpen; ///< True indicates open file/stream
std::string m_filename; ///< Filename, for error messages std::string m_filename; ///< Filename, for error messages
VerilatedAssertOneThread m_assertOne; ///< Assert only called from single thread 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 bufferSize() { return 256*1024; } // See below for slack calculation
inline static size_t bufferInsertSize() { return 16*1024; } inline static size_t bufferInsertSize() { return 16*1024; }
@ -111,14 +111,14 @@ protected:
VL_UNCOPYABLE(VerilatedDeserialize); VL_UNCOPYABLE(VerilatedDeserialize);
public: public:
VerilatedDeserialize() { VerilatedDeserialize() {
m_isOpen = false; m_isOpen = false;
m_bufp = new vluint8_t [bufferSize()]; m_bufp = new vluint8_t [bufferSize()];
m_cp = m_bufp; m_cp = m_bufp;
m_endp = NULL; m_endp = NULL;
} }
virtual ~VerilatedDeserialize() { virtual ~VerilatedDeserialize() {
close(); close();
if (m_bufp) { delete m_bufp; m_bufp=NULL; } if (m_bufp) { delete m_bufp; m_bufp=NULL; }
} }
// METHODS // METHODS
bool isOpen() const { return m_isOpen; } bool isOpen() const { return m_isOpen; }
@ -126,15 +126,15 @@ public:
virtual void close() VL_MT_UNSAFE_ONE { flush(); } virtual void close() VL_MT_UNSAFE_ONE { flush(); }
virtual void flush() VL_MT_UNSAFE_ONE {} virtual void flush() VL_MT_UNSAFE_ONE {}
inline VerilatedDeserialize& read(void* __restrict datap, size_t size) 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; vluint8_t* __restrict dp = (vluint8_t* __restrict)datap;
while (size) { while (size) {
bufferCheck(); bufferCheck();
size_t blk = size; if (blk>bufferInsertSize()) blk = bufferInsertSize(); size_t blk = size; if (blk>bufferInsertSize()) blk = bufferInsertSize();
const vluint8_t* __restrict maxp = dp + blk; const vluint8_t* __restrict maxp = dp + blk;
while (dp < maxp) *dp++ = *m_cp++; while (dp < maxp) *dp++ = *m_cp++;
size -= blk; size -= blk;
} }
return *this; // For function chaining return *this; // For function chaining
} }
// Read a datum and compare with expected value // Read a datum and compare with expected value
VerilatedDeserialize& readAssert(const void* __restrict datap, size_t size) VL_MT_UNSAFE_ONE; VerilatedDeserialize& readAssert(const void* __restrict datap, size_t size) VL_MT_UNSAFE_ONE;
@ -143,12 +143,12 @@ public:
private: private:
bool readDiffers(const void* __restrict datap, size_t size) VL_MT_UNSAFE_ONE; bool readDiffers(const void* __restrict datap, size_t size) VL_MT_UNSAFE_ONE;
VerilatedDeserialize& bufferCheck() VL_MT_UNSAFE_ONE { VerilatedDeserialize& bufferCheck() VL_MT_UNSAFE_ONE {
// Flush the write buffer if there's not enough space left for new information // 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 // 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)) { if (VL_UNLIKELY((m_cp+bufferInsertSize()) > m_endp)) {
fill(); fill();
} }
return *this; // For function chaining return *this; // For function chaining
} }
}; };
@ -158,7 +158,7 @@ private:
class VerilatedSave : public VerilatedSerialize { class VerilatedSave : public VerilatedSerialize {
private: private:
int m_fd; ///< File descriptor we're writing to int m_fd; ///< File descriptor we're writing to
public: public:
// CONSTRUCTORS // CONSTRUCTORS
@ -177,7 +177,7 @@ public:
class VerilatedRestore : public VerilatedDeserialize { class VerilatedRestore : public VerilatedDeserialize {
private: private:
int m_fd; ///< File descriptor we're writing to int m_fd; ///< File descriptor we're writing to
public: public:
// CONSTRUCTORS // CONSTRUCTORS
@ -237,12 +237,12 @@ inline VerilatedDeserialize& operator>>(VerilatedDeserialize& os, float& rhs) {
return os.read(&rhs, sizeof(rhs)); return os.read(&rhs, sizeof(rhs));
} }
inline VerilatedSerialize& operator<<(VerilatedSerialize& os, std::string& rhs) { inline VerilatedSerialize& operator<<(VerilatedSerialize& os, std::string& rhs) {
vluint32_t len=rhs.length(); vluint32_t len = rhs.length();
os<<len; os<<len;
return os.write(rhs.data(), len); return os.write(rhs.data(), len);
} }
inline VerilatedDeserialize& operator>>(VerilatedDeserialize& os, std::string& rhs) { inline VerilatedDeserialize& operator>>(VerilatedDeserialize& os, std::string& rhs) {
vluint32_t len=0; vluint32_t len = 0;
os>>len; os>>len;
rhs.resize(len); rhs.resize(len);
return os.read((void*)rhs.data(), len); return os.read((void*)rhs.data(), len);

View File

@ -16,11 +16,11 @@
/// \file /// \file
/// \brief Verilator: Common include for OS portability (verilated & verilator) /// \brief Verilator: Common include for OS portability (verilated & verilator)
/// ///
/// This header is used by both the Verilator source code (run on the /// 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 /// build and host system), and the Verilated output (run on the target
/// system). Code needed by only the host system goes into /// system). Code needed by only the host system goes into
/// config_build.h.in, code needed by Verilated code only 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). /// verilated.h, and code needed by both goes here (verilatedos.h).
/// ///
/// Code available from: http://www.veripool.org/verilator /// Code available from: http://www.veripool.org/verilator
/// ///
@ -54,8 +54,8 @@
# define VL_EXCLUDES(x) __attribute__ ((locks_excluded(x))) # define VL_EXCLUDES(x) __attribute__ ((locks_excluded(x)))
# define VL_SCOPED_CAPABILITY __attribute__ ((scoped_lockable)) # define VL_SCOPED_CAPABILITY __attribute__ ((scoped_lockable))
# endif # endif
# define VL_LIKELY(x) __builtin_expect(!!(x), 1) # define VL_LIKELY(x) __builtin_expect(!!(x), 1)
# define VL_UNLIKELY(x) __builtin_expect(!!(x), 0) # define VL_UNLIKELY(x) __builtin_expect(!!(x), 0)
# define VL_UNREACHABLE __builtin_unreachable(); # define VL_UNREACHABLE __builtin_unreachable();
# define VL_PREFETCH_RD(p) __builtin_prefetch((p),0) # define VL_PREFETCH_RD(p) __builtin_prefetch((p),0)
# define VL_PREFETCH_RW(p) __builtin_prefetch((p),1) # define VL_PREFETCH_RW(p) __builtin_prefetch((p),1)
@ -65,51 +65,51 @@
// Defaults for unsupported compiler features // Defaults for unsupported compiler features
#ifndef VL_ATTR_ALIGNED #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 #endif
#ifndef VL_ATTR_ALWINLINE #ifndef VL_ATTR_ALWINLINE
# define VL_ATTR_ALWINLINE ///< Inline, even when not optimizing # define VL_ATTR_ALWINLINE ///< Inline, even when not optimizing
#endif #endif
#ifndef VL_ATTR_NORETURN #ifndef VL_ATTR_NORETURN
# define VL_ATTR_NORETURN ///< Function does not ever return # define VL_ATTR_NORETURN ///< Function does not ever return
#endif #endif
#ifndef VL_ATTR_PRINTF #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 #endif
#ifndef VL_ATTR_PURE #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 #endif
#ifndef VL_ATTR_UNUSED #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 #endif
#ifndef VL_FUNC #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 #endif
#ifndef VL_CAPABILITY #ifndef VL_CAPABILITY
# define VL_ACQUIRE(...) ///< Function requires a 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_ACQUIRE_SHARED(...) ///< Function aquires a shared capability/lock (-fthread-safety)
# define VL_RELEASE(...) ///< Function releases a 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_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(...) ///< 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_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_REQUIRES(x) ///< Function requires a capability inbound (-fthread-safety)
# define VL_EXCLUDES(x) ///< Function requires not having 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_CAPABILITY(x) ///< Name of capability/lock (-fthread-safety)
# define VL_GUARDED_BY(x) ///< Name of mutex protecting this variable (-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_SCOPED_CAPABILITY ///< Scoped threaded capability/lock (-fthread-safety)
#endif #endif
#ifndef VL_LIKELY #ifndef VL_LIKELY
# define VL_LIKELY(x) (!!(x)) ///< Boolean expression more often true than false # 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_UNLIKELY(x) (!!(x)) ///< Boolean expression more often false than true
#endif #endif
#ifndef VL_UNREACHABLE #ifndef VL_UNREACHABLE
# define VL_UNREACHABLE ///< Point that may never be reached # define VL_UNREACHABLE ///< Point that may never be reached
#endif #endif
#ifndef VL_PREFETCH_RD #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 #endif
#ifndef VL_PREFETCH_RW #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 #endif
#ifdef VL_THREADED #ifdef VL_THREADED
@ -120,12 +120,12 @@
# else # else
# error "Unsupported compiler for VL_THREADED: No thread-local declarator" # error "Unsupported compiler for VL_THREADED: No thread-local declarator"
# endif # 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 #else
# define VL_THREAD_LOCAL ///< Use new C++ static local thread # define VL_THREAD_LOCAL ///< Use new C++ static local thread
#endif #endif
#define VL_THREAD ///< Deprecated #define VL_THREAD ///< Deprecated
#define VL_STATIC_OR_THREAD static ///< 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_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 #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 #define VL_MT_UNSAFE_ONE ///< Comment tag that function is not threadsafe when VL_THREADED, protected to make sure single-caller
#ifdef _MSC_VER #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 #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 #endif
// This is not necessarily the same as #UL, depending on what the IData typedef is. // 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__) #if defined(VL_CPPCHECK) || defined(__clang_analyzer__)
# define VL_DANGLING(v) # define VL_DANGLING(v)
#else #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 #endif
//========================================================================= //=========================================================================
@ -176,7 +176,7 @@
// Optimization // Optimization
#ifndef VL_INLINE_OPT #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 #endif
//========================================================================= //=========================================================================
@ -203,37 +203,37 @@
# include <stdint.h> # include <stdint.h>
# include <sys/types.h> // __WORDSIZE # include <sys/types.h> // __WORDSIZE
# include <unistd.h> // ssize_t # include <unistd.h> // ssize_t
typedef unsigned char uint8_t; ///< 8-bit unsigned type (backward compatibility) 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 short int uint16_t; ///< 16-bit unsigned type (backward compatibility)
typedef unsigned char vluint8_t; ///< 8-bit unsigned type typedef unsigned char vluint8_t; ///< 8-bit unsigned type
typedef unsigned short int vluint16_t; ///< 16-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 # 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 int32_t vlsint32_t; ///< 32-bit signed type
typedef uint32_t vluint32_t; ///< 32-bit unsigned type typedef uint32_t vluint32_t; ///< 32-bit unsigned type
# else // Older Cygwin has long==uint32_t # else // Older Cygwin has long==uint32_t
typedef unsigned long uint32_t; ///< 32-bit unsigned type (backward compatibility) typedef unsigned long uint32_t; ///< 32-bit unsigned type (backward compatibility)
typedef long vlsint32_t; ///< 32-bit signed type typedef long vlsint32_t; ///< 32-bit signed type
typedef unsigned long vluint32_t; ///< 32-bit unsigned type typedef unsigned long vluint32_t; ///< 32-bit unsigned type
# endif # endif
# if defined(__WORDSIZE) && (__WORDSIZE == 64) # if defined(__WORDSIZE) && (__WORDSIZE == 64)
typedef long vlsint64_t; ///< 64-bit signed type typedef long vlsint64_t; ///< 64-bit signed type
typedef unsigned long vluint64_t; ///< 64-bit unsigned type typedef unsigned long vluint64_t; ///< 64-bit unsigned type
# else # else
typedef long long vlsint64_t; ///< 64-bit signed type typedef long long vlsint64_t; ///< 64-bit signed type
typedef unsigned long long vluint64_t; ///< 64-bit unsigned type typedef unsigned long long vluint64_t; ///< 64-bit unsigned type
# endif # endif
#elif defined(_WIN32) && defined(_MSC_VER) #elif defined(_WIN32) && defined(_MSC_VER)
typedef unsigned __int8 uint8_t; ///< 8-bit unsigned type (backward compatibility) typedef unsigned __int8 uint8_t; ///< 8-bit unsigned type (backward compatibility)
typedef unsigned __int16 uint16_t; ///< 16-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 __int32 uint32_t; ///< 32-bit unsigned type (backward compatibility)
typedef unsigned __int8 vluint8_t; ///< 8-bit unsigned type typedef unsigned __int8 vluint8_t; ///< 8-bit unsigned type
typedef unsigned __int16 vluint16_t; ///< 16-bit unsigned type typedef unsigned __int16 vluint16_t; ///< 16-bit unsigned type
typedef signed __int32 vlsint32_t; ///< 32-bit signed type typedef signed __int32 vlsint32_t; ///< 32-bit signed type
typedef unsigned __int32 vluint32_t; ///< 32-bit unsigned type typedef unsigned __int32 vluint32_t; ///< 32-bit unsigned type
typedef signed __int64 vlsint64_t; ///< 64-bit signed type typedef signed __int64 vlsint64_t; ///< 64-bit signed type
typedef unsigned __int64 vluint64_t; ///< 64-bit unsigned type typedef unsigned __int64 vluint64_t; ///< 64-bit unsigned type
# ifndef _SSIZE_T_DEFINED # ifndef _SSIZE_T_DEFINED
# ifdef _WIN64 # ifdef _WIN64
@ -249,16 +249,16 @@ typedef signed __int32 ssize_t; ///< signed size_t; returned fro
# include <stdint.h> // Linux and most flavors # include <stdint.h> // Linux and most flavors
# include <sys/types.h> // __WORDSIZE # include <sys/types.h> // __WORDSIZE
# include <unistd.h> // ssize_t # include <unistd.h> // ssize_t
typedef uint8_t vluint8_t; ///< 32-bit unsigned type typedef uint8_t vluint8_t; ///< 32-bit unsigned type
typedef uint16_t vluint16_t; ///< 32-bit unsigned type typedef uint16_t vluint16_t; ///< 32-bit unsigned type
typedef int vlsint32_t; ///< 32-bit signed type typedef int vlsint32_t; ///< 32-bit signed type
typedef uint32_t vluint32_t; ///< 32-bit signed type typedef uint32_t vluint32_t; ///< 32-bit signed type
# if defined(__WORDSIZE) && (__WORDSIZE == 64) # if defined(__WORDSIZE) && (__WORDSIZE == 64)
typedef long vlsint64_t; ///< 64-bit signed type typedef long vlsint64_t; ///< 64-bit signed type
typedef unsigned long vluint64_t; ///< 64-bit unsigned type typedef unsigned long vluint64_t; ///< 64-bit unsigned type
# else # else
typedef long long vlsint64_t; ///< 64-bit signed type typedef long long vlsint64_t; ///< 64-bit signed type
typedef unsigned long long vluint64_t; ///< 64-bit unsigned type typedef unsigned long long vluint64_t; ///< 64-bit unsigned type
# endif # endif
#endif #endif
@ -305,11 +305,11 @@ typedef unsigned long long vluint64_t; ///< 64-bit unsigned type
//========================================================================= //=========================================================================
// Integer size macros // Integer size macros
#define VL_BYTESIZE 8 ///< Bits in a byte #define VL_BYTESIZE 8 ///< Bits in a byte
#define VL_SHORTSIZE 16 ///< Bits in a short #define VL_SHORTSIZE 16 ///< Bits in a short
#define VL_WORDSIZE 32 ///< Bits in a word #define VL_WORDSIZE 32 ///< Bits in a word
#define VL_QUADSIZE 64 ///< Bits in a quadword #define VL_QUADSIZE 64 ///< Bits in a quadword
#define VL_WORDSIZE_LOG2 5 ///< log2(VL_WORDSIZE) #define VL_WORDSIZE_LOG2 5 ///< log2(VL_WORDSIZE)
/// Bytes this number of bits needs (1 bit=1 byte) /// Bytes this number of bits needs (1 bit=1 byte)
#define VL_BYTES_I(nbits) (((nbits)+(VL_BYTESIZE-1))/VL_BYTESIZE) #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 // Verilated function size macros
#define VL_MULS_MAX_WORDS 16 ///< Max size in words of MULS 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 #define VL_TO_STRING_MAX_WORDS 64 ///< Max size in words of String conversion operation
//========================================================================= //=========================================================================
// Base macros // Base macros
#define VL_SIZEBITS_I (VL_WORDSIZE-1) ///< Bit mask for bits in a word #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_Q (VL_QUADSIZE-1) ///< Bit mask for bits in a quad
/// Mask for words with 1's where relevant bits are (0=all bits) /// Mask for words with 1's where relevant bits are (0=all bits)
#define VL_MASK_I(nbits) (((nbits) & VL_SIZEBITS_I) \ #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) /// Mask for quads with 1's where relevant bits are (0=all bits)
#define VL_MASK_Q(nbits) (((nbits) & VL_SIZEBITS_Q) \ #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_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_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 #define VL_BITBIT_Q(bit) ((bit)&VL_SIZEBITS_Q) ///< Bit number for a bit in a quad

View File

@ -32,35 +32,35 @@
class VlcBuckets { class VlcBuckets {
private: private:
// MEMBERS // MEMBERS
vluint64_t* m_datap; ///< Pointer to first bucket (dynamically allocated) vluint64_t* m_datap; ///< Pointer to first bucket (dynamically allocated)
vluint64_t m_dataSize; ///< Current entries in m_datap vluint64_t m_dataSize; ///< Current entries in m_datap
vluint64_t m_bucketsCovered; ///< Num buckets with sufficient coverage vluint64_t m_bucketsCovered; ///< Num buckets with sufficient coverage
private: private:
static inline vluint64_t covBit(vluint64_t point) { return 1ULL<<(point & 63); } static inline vluint64_t covBit(vluint64_t point) { return 1ULL<<(point & 63); }
inline vluint64_t allocSize() const { return sizeof(vluint64_t) * m_dataSize / 64; } inline vluint64_t allocSize() const { return sizeof(vluint64_t) * m_dataSize / 64; }
void allocate(vluint64_t point) { void allocate(vluint64_t point) {
vluint64_t oldsize = m_dataSize; vluint64_t oldsize = m_dataSize;
if (m_dataSize<point) m_dataSize=(point+64) & ~63ULL; // Keep power of two if (m_dataSize<point) m_dataSize=(point+64) & ~63ULL; // Keep power of two
m_dataSize *= 2; m_dataSize *= 2;
//UINFO(9, "Realloc "<<allocSize()<<" for "<<point<<" "<<cvtToHex(m_datap)<<endl); //UINFO(9, "Realloc "<<allocSize()<<" for "<<point<<" "<<cvtToHex(m_datap)<<endl);
vluint64_t* newp = (vluint64_t*)realloc(m_datap, allocSize()); vluint64_t* newp = (vluint64_t*)realloc(m_datap, allocSize());
if (!newp) { free(m_datap); v3fatal("Out of memory increasing buckets"); } if (!newp) { free(m_datap); v3fatal("Out of memory increasing buckets"); }
m_datap = newp; m_datap = newp;
for (vluint64_t i=oldsize; i<m_dataSize; i+=64) m_datap[i/64] = 0; for (vluint64_t i=oldsize; i<m_dataSize; i+=64) m_datap[i/64] = 0;
} }
public: public:
// CONSTRUCTORS // CONSTRUCTORS
VlcBuckets() { VlcBuckets() {
m_dataSize = 0; m_dataSize = 0;
m_datap = NULL; m_datap = NULL;
m_bucketsCovered = 0; m_bucketsCovered = 0;
allocate(1024); allocate(1024);
} }
~VlcBuckets() { ~VlcBuckets() {
m_dataSize = 0; m_dataSize = 0;
free(m_datap); m_datap=NULL; free(m_datap); m_datap=NULL;
} }
// ACCESSORS // ACCESSORS
@ -69,66 +69,66 @@ public:
// METHODS // METHODS
void addData(vluint64_t point, vluint64_t hits) { void addData(vluint64_t point, vluint64_t hits) {
if (hits >= sufficient()) { if (hits >= sufficient()) {
//UINFO(9," addData "<<point<<" "<<hits<<" size="<<m_dataSize<<endl); //UINFO(9," addData "<<point<<" "<<hits<<" size="<<m_dataSize<<endl);
if (point >= m_dataSize) allocate(point); if (point >= m_dataSize) allocate(point);
m_datap[point/64] |= covBit(point); m_datap[point/64] |= covBit(point);
m_bucketsCovered++; m_bucketsCovered++;
} }
} }
void clearHits(vluint64_t point) const { void clearHits(vluint64_t point) const {
if (point >= m_dataSize) { if (point >= m_dataSize) {
return; return;
} else { } else {
m_datap[point/64] &= ~covBit(point); m_datap[point/64] &= ~covBit(point);
} }
} }
bool exists(vluint64_t point) const { bool exists(vluint64_t point) const {
if (point >= m_dataSize) { if (point >= m_dataSize) {
return false; return false;
} else { } else {
return (m_datap[point/64] & covBit(point)) ? 1:0; return (m_datap[point/64] & covBit(point)) ? 1:0;
} }
} }
vluint64_t hits(vluint64_t point) const { vluint64_t hits(vluint64_t point) const {
if (point >= m_dataSize) { if (point >= m_dataSize) {
return 0; return 0;
} else { } else {
return (m_datap[point/64] & covBit(point)) ? 1:0; return (m_datap[point/64] & covBit(point)) ? 1:0;
} }
} }
vluint64_t popCount() const { vluint64_t popCount() const {
vluint64_t pop = 0; vluint64_t pop = 0;
for (vluint64_t i=0; i<m_dataSize; i++) { for (vluint64_t i=0; i<m_dataSize; i++) {
if (hits(i)) pop++; if (hits(i)) pop++;
} }
return pop; return pop;
} }
vluint64_t dataPopCount(const VlcBuckets& remaining) { vluint64_t dataPopCount(const VlcBuckets& remaining) {
vluint64_t pop = 0; vluint64_t pop = 0;
for (vluint64_t i=0; i<m_dataSize; i++) { for (vluint64_t i=0; i<m_dataSize; i++) {
if (hits(i) && remaining.hits(i)) pop++; if (hits(i) && remaining.hits(i)) pop++;
} }
return pop; return pop;
} }
void orData(const VlcBuckets& ordata) { void orData(const VlcBuckets& ordata) {
for (vluint64_t i=0; i<m_dataSize; i++) { for (vluint64_t i=0; i<m_dataSize; i++) {
if (hits(i) && ordata.hits(i)) { if (hits(i) && ordata.hits(i)) {
clearHits(i); clearHits(i);
} }
} }
} }
void dump() const { void dump() const {
cout<<"# "; cout<<"# ";
for (vluint64_t i=0; i<m_dataSize; i++) { for (vluint64_t i=0; i<m_dataSize; i++) {
if (hits(i)) cout<<","<<i; if (hits(i)) cout<<","<<i;
} }
cout<<endl; cout<<endl;
} }
}; };
//###################################################################### //######################################################################
#endif // guard #endif // guard

View File

@ -43,7 +43,7 @@
void VlcOptions::addReadFile(const string& filename) { void VlcOptions::addReadFile(const string& filename) {
if (m_readFiles.find(filename) == m_readFiles.end()) { 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 // if sw=="-noarg", then return true (found it), and flag=false
// else return false // else return false
if (arg[0]!='-') v3fatalSrc("OnOff switches must have leading dash."); if (arg[0]!='-') v3fatalSrc("OnOff switches must have leading dash.");
if (0==strcmp(sw,arg)) { flag=true; 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",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; } else if (0==strncmp(sw,"-no-",4) && (0==strcmp(sw+4,arg+1))) { flag = false; return true; }
return false; return false;
} }
@ -71,58 +71,58 @@ void VlcOptions::parseOptsList(int argc, char** argv) {
// May be called recursively when there are -f files. // May be called recursively when there are -f files.
#define shift { ++i; } #define shift { ++i; }
for (int i=0; i<argc; ) { for (int i=0; i<argc; ) {
UINFO(9, " Option: "<<argv[i]<<endl); UINFO(9, " Option: "<<argv[i]<<endl);
if (argv[i][0]=='-') { if (argv[i][0]=='-') {
const char *sw = argv[i]; const char *sw = argv[i];
bool flag = true; bool flag = true;
// Allow gnu -- switches // Allow gnu -- switches
if (sw[0]=='-' && sw[1]=='-') ++sw; if (sw[0]=='-' && sw[1]=='-') ++sw;
if (0) {} if (0) {}
// Single switches // Single switches
else if ( onoff (sw, "-annotate-all", flag/*ref*/) ) { m_annotateAll = flag; } 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, "-rank", flag/*ref*/) ) { m_rank = flag; }
else if ( onoff (sw, "-unlink", flag/*ref*/) ) { m_unlink = flag; } else if ( onoff (sw, "-unlink", flag/*ref*/) ) { m_unlink = flag; }
// Parameterized switches // Parameterized switches
else if ( !strcmp (sw, "-annotate-min") && (i+1)<argc ) { else if ( !strcmp (sw, "-annotate-min") && (i+1)<argc ) {
shift; shift;
m_annotateMin = atoi(argv[i]); m_annotateMin = atoi(argv[i]);
} }
else if ( !strcmp (sw, "-annotate") && (i+1)<argc ) { else if ( !strcmp (sw, "-annotate") && (i+1)<argc ) {
shift; shift;
m_annotateOut = argv[i]; m_annotateOut = argv[i];
} }
else if ( !strcmp (sw, "-debug") ) { else if ( !strcmp (sw, "-debug") ) {
V3Error::debugDefault(3); V3Error::debugDefault(3);
} }
else if ( !strcmp (sw, "-debugi") && (i+1)<argc ) { else if ( !strcmp (sw, "-debugi") && (i+1)<argc ) {
shift; shift;
V3Error::debugDefault(atoi(argv[i])); V3Error::debugDefault(atoi(argv[i]));
} }
else if ( !strcmp (sw, "-V") ) { else if ( !strcmp (sw, "-V") ) {
showVersion(true); showVersion(true);
exit(0); exit(0);
} }
else if ( !strcmp (sw, "-version") ) { else if ( !strcmp (sw, "-version") ) {
showVersion(false); showVersion(false);
exit(0); exit(0);
} }
else if ( !strcmp (sw, "-write") && (i+1)<argc ) { else if ( !strcmp (sw, "-write") && (i+1)<argc ) {
shift; shift;
m_writeFile = argv[i]; m_writeFile = argv[i];
} }
else { else {
v3fatal("Invalid option: "<<argv[i]); v3fatal("Invalid option: "<<argv[i]);
} }
shift; shift;
} // - options } // - options
else if (1) { else if (1) {
addReadFile(argv[i]); addReadFile(argv[i]);
shift; shift;
} }
else { else {
v3fatal("Invalid argument: "<<argv[i]); v3fatal("Invalid argument: "<<argv[i]);
shift; shift;
} }
} }
#undef shift #undef shift
} }
@ -154,20 +154,20 @@ int main(int argc, char** argv, char** env) {
top.opt.parseOptsList(argc-1, argv+1); top.opt.parseOptsList(argc-1, argv+1);
if (top.opt.readFiles().empty()) { if (top.opt.readFiles().empty()) {
top.opt.addReadFile("vlt_coverage.dat"); top.opt.addReadFile("vlt_coverage.dat");
} }
{ {
const VlStringSet& readFiles = top.opt.readFiles(); const VlStringSet& readFiles = top.opt.readFiles();
for (VlStringSet::iterator it = readFiles.begin(); it != readFiles.end(); ++it) { for (VlStringSet::iterator it = readFiles.begin(); it != readFiles.end(); ++it) {
string filename = *it; string filename = *it;
top.readCoverage(filename); top.readCoverage(filename);
} }
} }
if (debug() >= 9) { if (debug() >= 9) {
top.tests().dump(true); top.tests().dump(true);
top.points().dump(); top.points().dump();
} }
V3Error::abortIfWarnings(); V3Error::abortIfWarnings();
@ -176,19 +176,19 @@ int main(int argc, char** argv, char** env) {
} }
if (top.opt.rank()) { if (top.opt.rank()) {
top.rank(); top.rank();
top.tests().dump(false); top.tests().dump(false);
} }
if (!top.opt.writeFile().empty()) { if (!top.opt.writeFile().empty()) {
top.writeCoverage(top.opt.writeFile()); top.writeCoverage(top.opt.writeFile());
V3Error::abortIfWarnings(); V3Error::abortIfWarnings();
if (top.opt.unlink()) { if (top.opt.unlink()) {
const VlStringSet& readFiles = top.opt.readFiles(); const VlStringSet& readFiles = top.opt.readFiles();
for (VlStringSet::iterator it = readFiles.begin(); it != readFiles.end(); ++it) { for (VlStringSet::iterator it = readFiles.begin(); it != readFiles.end(); ++it) {
string filename = *it; string filename = *it;
unlink(filename.c_str()); unlink(filename.c_str());
} }
} }
} }
@ -201,4 +201,3 @@ int main(int argc, char** argv, char** env) {
// Local Variables: // Local Variables:
// compile-command: "v4make bin/verilator_coverage --debugi 9 test_regress/t/t_vlcov_data_*.dat" // compile-command: "v4make bin/verilator_coverage --debugi 9 test_regress/t/t_vlcov_data_*.dat"
// End: // End:

View File

@ -38,13 +38,13 @@ typedef std::set<string> VlStringSet;
class VlcOptions { class VlcOptions {
// MEMBERS (general options) // MEMBERS (general options)
string m_annotateOut; // main switch: --annotate I<output_directory> string m_annotateOut; // main switch: --annotate I<output_directory>
bool m_annotateAll; // main switch: --annotate-all bool m_annotateAll; // main switch: --annotate-all
int m_annotateMin; // main switch: --annotate-min I<count> int m_annotateMin; // main switch: --annotate-min I<count>
VlStringSet m_readFiles; // main switch: --read VlStringSet m_readFiles; // main switch: --read
bool m_rank; // main switch: --rank bool m_rank; // main switch: --rank
bool m_unlink; // main switch: --unlink bool m_unlink; // main switch: --unlink
string m_writeFile; // main switch: --write string m_writeFile; // main switch: --write
private: private:
// METHODS // METHODS
@ -54,10 +54,10 @@ private:
public: public:
// CONSTRUCTORS // CONSTRUCTORS
VlcOptions() { VlcOptions() {
m_annotateAll = false; m_annotateAll = false;
m_annotateMin = 10; m_annotateMin = 10;
m_rank = false; m_rank = false;
m_unlink = false; m_unlink = false;
} }
~VlcOptions() {} ~VlcOptions() {}
void setDebugMode(int level); void setDebugMode(int level);
@ -81,4 +81,4 @@ public:
//###################################################################### //######################################################################
#endif // guard #endif // guard

View File

@ -36,18 +36,18 @@
class VlcPoint { class VlcPoint {
private: private:
// MEMBERS // MEMBERS
string m_name; //< Name of the point string m_name; //< Name of the point
vluint64_t m_pointNum; //< Point number vluint64_t m_pointNum; //< Point number
vluint64_t m_testsCovering;//< Number tests with non-zero coverage of this point vluint64_t m_testsCovering; //< Number tests with non-zero coverage of this point
vluint64_t m_count; //< Count of hits across all tests vluint64_t m_count; //< Count of hits across all tests
public: public:
// CONSTRUCTORS // CONSTRUCTORS
VlcPoint(const string& name, int pointNum) { VlcPoint(const string& name, int pointNum) {
m_name = name; m_name = name;
m_pointNum = pointNum; m_pointNum = pointNum;
m_testsCovering = 0; m_testsCovering = 0;
m_count = 0; m_count = 0;
} }
~VlcPoint() {} ~VlcPoint() {}
// ACCESSORS // ACCESSORS
@ -66,31 +66,31 @@ public:
int column() const { return atoi(keyExtract(VL_CIK_COLUMN).c_str()); } int column() const { return atoi(keyExtract(VL_CIK_COLUMN).c_str()); }
// METHODS // METHODS
string keyExtract(const char* shortKey) const { string keyExtract(const char* shortKey) const {
// Hot function // Hot function
size_t shortLen = strlen(shortKey); size_t shortLen = strlen(shortKey);
const string namestr = name(); const string namestr = name();
for (const char* cp = namestr.c_str(); *cp; ++cp) { for (const char* cp = namestr.c_str(); *cp; ++cp) {
if (*cp == '\001') { if (*cp == '\001') {
if (0==strncmp(cp+1, shortKey, shortLen) if (0==strncmp(cp+1, shortKey, shortLen)
&& cp[shortLen+1] == '\002') { && cp[shortLen+1] == '\002') {
cp += shortLen+2; // Skip \001+short+\002 cp += shortLen+2; // Skip \001+short+\002
const char* ep = cp; const char* ep = cp;
while (*ep && *ep != '\001') ++ep; while (*ep && *ep != '\001') ++ep;
return string(cp, ep-cp); return string(cp, ep-cp);
} }
} }
} }
return ""; return "";
} }
static void dumpHeader() { static void dumpHeader() {
cout<<"Points:\n"; cout<<"Points:\n";
cout<<" Num, TestsCover, Count, Name"<<endl; cout<<" Num, TestsCover, Count, Name"<<endl;
} }
void dump() const { void dump() const {
cout<<" "<<std::setw(8)<<std::setfill('0')<<pointNum() cout<<" "<<std::setw(8)<<std::setfill('0')<<pointNum()
<<", "<<std::setw(7)<<std::setfill(' ')<<testsCovering() <<", "<<std::setw(7)<<std::setfill(' ')<<testsCovering()
<<", "<<std::setw(7)<<std::setfill(' ')<<count() <<", "<<std::setw(7)<<std::setfill(' ')<<count()
<<", \""<<name()<<"\""<<endl; <<", \""<<name()<<"\""<<endl;
} }
}; };
@ -115,40 +115,40 @@ public:
public: public:
// CONSTRUCTORS // CONSTRUCTORS
VlcPoints() { VlcPoints() {
m_numPoints = 0; m_numPoints = 0;
} }
~VlcPoints() {} ~VlcPoints() {}
// METHODS // METHODS
void dump() { void dump() {
UINFO(2,"dumpPoints...\n"); UINFO(2,"dumpPoints...\n");
VlcPoint::dumpHeader(); VlcPoint::dumpHeader();
for (VlcPoints::ByName::iterator it=begin(); it!=end(); ++it) { for (VlcPoints::ByName::iterator it=begin(); it!=end(); ++it) {
const VlcPoint& point = pointNumber(it->second); const VlcPoint& point = pointNumber(it->second);
point.dump(); point.dump();
} }
} }
VlcPoint& pointNumber(vluint64_t num) { VlcPoint& pointNumber(vluint64_t num) {
return m_points[num]; return m_points[num];
} }
vluint64_t findAddPoint(const string& name, vluint64_t count) { vluint64_t findAddPoint(const string& name, vluint64_t count) {
vluint64_t pointnum; vluint64_t pointnum;
NameMap::iterator iter = m_nameMap.find(name); NameMap::iterator iter = m_nameMap.find(name);
if (iter != m_nameMap.end()) { if (iter != m_nameMap.end()) {
pointnum = iter->second; pointnum = iter->second;
m_points[pointnum].countInc(count); m_points[pointnum].countInc(count);
} }
else { else {
pointnum = m_numPoints++; pointnum = m_numPoints++;
VlcPoint point (name, pointnum); VlcPoint point (name, pointnum);
point.countInc(count); point.countInc(count);
m_points.push_back(point); m_points.push_back(point);
m_nameMap.insert(make_pair(point.name(), point.pointNum())); m_nameMap.insert(make_pair(point.name(), point.pointNum()));
} }
return pointnum; return pointnum;
} }
}; };
//###################################################################### //######################################################################
#endif // guard #endif // guard

View File

@ -33,18 +33,18 @@
class VlcSourceCount { class VlcSourceCount {
private: private:
// MEMBERS // MEMBERS
int m_lineno; ///< Line number int m_lineno; ///< Line number
int m_column; ///< Column number int m_column; ///< Column number
vluint64_t m_count; ///< Count vluint64_t m_count; ///< Count
bool m_ok; ///< Coverage is above threshold bool m_ok; ///< Coverage is above threshold
public: public:
// CONSTRUCTORS // CONSTRUCTORS
VlcSourceCount(int lineno, int column) { VlcSourceCount(int lineno, int column) {
m_lineno = lineno; m_lineno = lineno;
m_column = column; m_column = column;
m_count = 0; m_count = 0;
m_ok = false; m_ok = false;
} }
~VlcSourceCount() {} ~VlcSourceCount() {}
@ -56,8 +56,8 @@ public:
// METHODS // METHODS
void incCount(vluint64_t count, bool ok) { void incCount(vluint64_t count, bool ok) {
m_count += count; m_count += count;
if (ok) m_ok = true; if (ok) m_ok = true;
} }
}; };
@ -72,15 +72,15 @@ public:
private: private:
// MEMBERS // MEMBERS
string m_name; //< Name of the source file string m_name; //< Name of the source file
bool m_needed; //< Need to annotate; has low coverage bool m_needed; //< Need to annotate; has low coverage
LinenoMap m_lines; //< Map of each annotated line LinenoMap m_lines; //< Map of each annotated line
public: public:
// CONSTRUCTORS // CONSTRUCTORS
explicit VlcSource(const string& name) { explicit VlcSource(const string& name) {
m_name = name; m_name = name;
m_needed = false; m_needed = false;
} }
~VlcSource() {} ~VlcSource() {}
@ -92,17 +92,17 @@ public:
// METHODS // METHODS
void incCount(int lineno, int column, vluint64_t count, bool ok) { void incCount(int lineno, int column, vluint64_t count, bool ok) {
LinenoMap::iterator lit = m_lines.find(lineno); LinenoMap::iterator lit = m_lines.find(lineno);
if (lit == m_lines.end()) { if (lit == m_lines.end()) {
lit = m_lines.insert(make_pair(lineno,ColumnMap())).first; lit = m_lines.insert(make_pair(lineno, ColumnMap())).first;
} }
ColumnMap& cmap = lit->second; ColumnMap& cmap = lit->second;
ColumnMap::iterator cit = cmap.find(column); ColumnMap::iterator cit = cmap.find(column);
if (cit == cmap.end()) { if (cit == cmap.end()) {
cit = cmap.insert(make_pair(column,VlcSourceCount(lineno, column))).first; cit = cmap.insert(make_pair(column, VlcSourceCount(lineno, column))).first;
} }
VlcSourceCount& sc = cit->second; VlcSourceCount& sc = cit->second;
sc.incCount(count,ok); sc.incCount(count, ok);
} }
}; };
@ -115,7 +115,7 @@ public:
typedef std::map<string,VlcSource> NameMap; typedef std::map<string,VlcSource> NameMap;
private: private:
// MEMBERS // MEMBERS
NameMap m_sources; //< List of all sources NameMap m_sources; //< List of all sources
public: public:
// ITERATORS // ITERATORS
@ -130,17 +130,17 @@ public:
// METHODS // METHODS
VlcSource& findNewSource(const string& name) { VlcSource& findNewSource(const string& name) {
NameMap::iterator iter = m_sources.find(name); NameMap::iterator iter = m_sources.find(name);
if (iter != m_sources.end()) { if (iter != m_sources.end()) {
return iter->second; return iter->second;
} }
else { else {
iter = m_sources.insert(make_pair(name, VlcSource(name))).first; iter = m_sources.insert(make_pair(name, VlcSource(name))).first;
return iter->second; return iter->second;
} }
} }
}; };
//###################################################################### //######################################################################
#endif // Guard #endif // Guard

View File

@ -36,23 +36,23 @@
class VlcTest { class VlcTest {
private: private:
// MEMBERS // MEMBERS
string m_name; //< Name of the test string m_name; //< Name of the test
double m_computrons; //< Runtime for the test double m_computrons; //< Runtime for the test
vluint64_t m_testrun; //< Test run number, for database use vluint64_t m_testrun; //< Test run number, for database use
vluint64_t m_rank; //< Execution rank suggestion vluint64_t m_rank; //< Execution rank suggestion
vluint64_t m_rankPoints; //< Ranked additional points vluint64_t m_rankPoints; //< Ranked additional points
vluint64_t m_user; //< User data for algorithms (not persisted in .dat file) vluint64_t m_user; //< User data for algorithms (not persisted in .dat file)
VlcBuckets m_buckets; //< Coverage data for each coverage point VlcBuckets m_buckets; //< Coverage data for each coverage point
public: public:
// CONSTRUCTORS // CONSTRUCTORS
VlcTest(const string& name, vluint64_t testrun, double comp) { VlcTest(const string& name, vluint64_t testrun, double comp) {
m_name = name; m_name = name;
m_computrons = comp; m_computrons = comp;
m_testrun = testrun; m_testrun = testrun;
m_rank = 0; m_rank = 0;
m_rankPoints = 0; m_rankPoints = 0;
m_user = 0; m_user = 0;
} }
~VlcTest() {} ~VlcTest() {}
@ -71,20 +71,20 @@ public:
// METHODS // METHODS
static void dumpHeader() { static void dumpHeader() {
cout<<"Tests:\n"; cout<<"Tests:\n";
//cout<<" Testrun, Computrons,"; // Currently not loaded //cout<<" Testrun, Computrons,"; // Currently not loaded
cout<<" Covered, Rank, RankPts, Filename"<<endl; cout<<" Covered, Rank, RankPts, Filename"<<endl;
} }
void dump(bool bucketsToo) { void dump(bool bucketsToo) {
if (testrun() || computrons()!=0.0) { if (testrun() || computrons()!=0.0) {
cout<<" "<<std::setw(8)<<std::setfill('0')<<testrun() cout<<" "<<std::setw(8)<<std::setfill('0')<<testrun()
<<", "<<std::setw(7)<<std::setfill(' ')<<computrons()<<","; <<", "<<std::setw(7)<<std::setfill(' ')<<computrons()<<",";
} }
cout<<" "<<std::setw(7)<<std::setfill(' ')<<bucketsCovered() cout<<" "<<std::setw(7)<<std::setfill(' ')<<bucketsCovered()
<<", "<<std::setw(7)<<std::setfill(' ')<<rank() <<", "<<std::setw(7)<<std::setfill(' ')<<rank()
<<", "<<std::setw(7)<<std::setfill(' ')<<rankPoints() <<", "<<std::setw(7)<<std::setfill(' ')<<rankPoints()
<<", \""<<name()<<"\""<<endl; <<", \""<<name()<<"\""<<endl;
if (bucketsToo) m_buckets.dump(); if (bucketsToo) m_buckets.dump();
} }
}; };
@ -97,7 +97,7 @@ public:
typedef std::vector<VlcTest*> ByName; typedef std::vector<VlcTest*> ByName;
private: private:
// MEMBERS // MEMBERS
ByName m_tests; //< List of all tests ByName m_tests; //< List of all tests
public: public:
// ITERATORS // ITERATORS
@ -109,31 +109,31 @@ public:
// CONSTRUCTORS // CONSTRUCTORS
VlcTests() {} VlcTests() {}
~VlcTests() { ~VlcTests() {
for (VlcTests::ByName::iterator it=begin(); it!=end(); ++it) { for (VlcTests::ByName::iterator it=begin(); it!=end(); ++it) {
delete *it; *it=NULL; delete *it; *it=NULL;
} }
} }
// METHODS // METHODS
void dump(bool bucketsToo) { void dump(bool bucketsToo) {
UINFO(2,"dumpTests...\n"); UINFO(2,"dumpTests...\n");
VlcTest::dumpHeader(); VlcTest::dumpHeader();
for (VlcTests::ByName::iterator it=begin(); it!=end(); ++it) { for (VlcTests::ByName::iterator it=begin(); it!=end(); ++it) {
(*it)->dump(bucketsToo); (*it)->dump(bucketsToo);
} }
} }
VlcTest* newTest(const string& name, vluint64_t testrun, double comp) { VlcTest* newTest(const string& name, vluint64_t testrun, double comp) {
VlcTest* testp = new VlcTest(name, testrun, comp); VlcTest* testp = new VlcTest(name, testrun, comp);
m_tests.push_back(testp); m_tests.push_back(testp);
return testp; return testp;
} }
void clearUser() { void clearUser() {
for (ByName::iterator it = m_tests.begin(); it != m_tests.end(); ++it) { for (ByName::iterator it = m_tests.begin(); it != m_tests.end(); ++it) {
(*it)->user(0); (*it)->user(0);
} }
} }
}; };
//###################################################################### //######################################################################
#endif // Guard #endif // Guard

View File

@ -34,8 +34,8 @@ void VlcTop::readCoverage(const string& filename, bool nonfatal) {
std::ifstream is(filename.c_str()); std::ifstream is(filename.c_str());
if (!is) { if (!is) {
if (!nonfatal) v3fatal("Can't read "<<filename); if (!nonfatal) v3fatal("Can't read "<<filename);
return; return;
} }
// Testrun and computrons argument unsupported as yet // Testrun and computrons argument unsupported as yet
@ -45,23 +45,23 @@ void VlcTop::readCoverage(const string& filename, bool nonfatal) {
string line = V3Os::getline(is); string line = V3Os::getline(is);
//UINFO(9," got "<<line<<endl); //UINFO(9," got "<<line<<endl);
if (line[0] == 'C') { if (line[0] == 'C') {
string::size_type secspace=3; string::size_type secspace = 3;
for (; secspace<line.length(); secspace++) { for (; secspace<line.length(); secspace++) {
if (line[secspace]=='\'' && line[secspace+1]==' ') break; if (line[secspace]=='\'' && line[secspace+1]==' ') break;
} }
string point = line.substr(3,secspace-3); string point = line.substr(3, secspace-3);
vluint64_t hits = atoll(line.c_str()+secspace+1); vluint64_t hits = atoll(line.c_str()+secspace+1);
//UINFO(9," point '"<<point<<"'"<<" "<<hits<<endl); //UINFO(9," point '"<<point<<"'"<<" "<<hits<<endl);
vluint64_t pointnum = points().findAddPoint(point, hits); vluint64_t pointnum = points().findAddPoint(point, hits);
if (pointnum) {} // Prevent unused if (pointnum) {} // Prevent unused
if (opt.rank()) { // Only if ranking - uses a lot of memory if (opt.rank()) { // Only if ranking - uses a lot of memory
if (hits >= VlcBuckets::sufficient()) { if (hits >= VlcBuckets::sufficient()) {
points().pointNumber(pointnum).testsCoveringInc(); points().pointNumber(pointnum).testsCoveringInc();
testp->buckets().addData(pointnum, hits); testp->buckets().addData(pointnum, hits);
} }
} }
} }
} }
} }
@ -70,14 +70,14 @@ void VlcTop::writeCoverage(const string& filename) {
std::ofstream os(filename.c_str()); std::ofstream os(filename.c_str());
if (!os) { if (!os) {
v3fatal("Can't write "<<filename); v3fatal("Can't write "<<filename);
return; return;
} }
os << "# SystemC::Coverage-3" << endl; os << "# SystemC::Coverage-3" << endl;
for (VlcPoints::ByName::iterator it=m_points.begin(); it!=m_points.end(); ++it) { for (VlcPoints::ByName::iterator it=m_points.begin(); it!=m_points.end(); ++it) {
const VlcPoint& point = m_points.pointNumber(it->second); const VlcPoint& point = m_points.pointNumber(it->second);
os <<"C '"<<point.name()<<"' " << point.count()<<endl; os <<"C '"<<point.name()<<"' " << point.count()<<endl;
} }
} }
@ -85,32 +85,32 @@ void VlcTop::writeCoverage(const string& filename) {
struct CmpComputrons { struct CmpComputrons {
inline bool operator() (const VlcTest* lhsp, const VlcTest* rhsp) const { inline bool operator() (const VlcTest* lhsp, const VlcTest* rhsp) const {
if (lhsp->computrons() != rhsp->computrons()) { if (lhsp->computrons() != rhsp->computrons()) {
return lhsp->computrons() < rhsp->computrons(); return lhsp->computrons() < rhsp->computrons();
} }
return lhsp->bucketsCovered() > rhsp->bucketsCovered(); return lhsp->bucketsCovered() > rhsp->bucketsCovered();
} }
}; };
void VlcTop::rank() { void VlcTop::rank() {
UINFO(2,"rank...\n"); UINFO(2,"rank...\n");
vluint64_t nextrank=1; vluint64_t nextrank = 1;
// Sort by computrons, so fast tests get selected first // Sort by computrons, so fast tests get selected first
std::vector<VlcTest*> bytime; std::vector<VlcTest*> bytime;
for (VlcTests::ByName::iterator it=m_tests.begin(); it!=m_tests.end(); ++it) { for (VlcTests::ByName::iterator it=m_tests.begin(); it!=m_tests.end(); ++it) {
VlcTest* testp = *it; VlcTest* testp = *it;
if (testp->bucketsCovered()) { // else no points, so can't help us if (testp->bucketsCovered()) { // else no points, so can't help us
bytime.push_back(*it); bytime.push_back(*it);
} }
} }
sort(bytime.begin(), bytime.end(), CmpComputrons()); // Sort the vector sort(bytime.begin(), bytime.end(), CmpComputrons()); // Sort the vector
VlcBuckets remaining; VlcBuckets remaining;
for (VlcPoints::ByName::iterator it=m_points.begin(); it!=m_points.end(); ++it) { for (VlcPoints::ByName::iterator it=m_points.begin(); it!=m_points.end(); ++it) {
VlcPoint* pointp = &points().pointNumber(it->second); VlcPoint* pointp = &points().pointNumber(it->second);
// If any tests hit this point, then we'll need to cover it. // If any tests hit this point, then we'll need to cover it.
if (pointp->testsCovering()) { remaining.addData(pointp->pointNum(), 1); } if (pointp->testsCovering()) { remaining.addData(pointp->pointNum(), 1); }
} }
// Additional Greedy algorithm // Additional Greedy algorithm
@ -118,26 +118,26 @@ void VlcTop::rank() {
// then hierarchically solve a small subset of tests, and take resulting // then hierarchically solve a small subset of tests, and take resulting
// solution and move up to larger subset of tests. (Aka quick sort.) // solution and move up to larger subset of tests. (Aka quick sort.)
while (1) { while (1) {
if (debug()) { UINFO(9,"Left on iter"<<nextrank<<": "); remaining.dump(); } if (debug()) { UINFO(9,"Left on iter"<<nextrank<<": "); remaining.dump(); }
VlcTest* bestTestp = NULL; VlcTest* bestTestp = NULL;
vluint64_t bestRemain = 0; vluint64_t bestRemain = 0;
for (std::vector<VlcTest*>::iterator it=bytime.begin(); it!=bytime.end(); ++it) { for (std::vector<VlcTest*>::iterator it=bytime.begin(); it!=bytime.end(); ++it) {
VlcTest* testp = *it; VlcTest* testp = *it;
if (!testp->rank()) { if (!testp->rank()) {
vluint64_t remain = testp->buckets().dataPopCount(remaining); vluint64_t remain = testp->buckets().dataPopCount(remaining);
if (remain > bestRemain) { if (remain > bestRemain) {
bestTestp = testp; bestTestp = testp;
bestRemain = remain; bestRemain = remain;
} }
} }
} }
if (VlcTest* testp = bestTestp) { if (VlcTest* testp = bestTestp) {
testp->rank(nextrank++); testp->rank(nextrank++);
testp->rankPoints(bestRemain); testp->rankPoints(bestRemain);
remaining.orData(bestTestp->buckets()); remaining.orData(bestTestp->buckets());
} else { } else {
break; // No test covering more stuff found break; // No test covering more stuff found
} }
} }
} }
@ -146,18 +146,18 @@ void VlcTop::rank() {
void VlcTop::annotateCalc() { void VlcTop::annotateCalc() {
// Calculate per-line information into filedata structure // Calculate per-line information into filedata structure
for (VlcPoints::ByName::iterator it=m_points.begin(); it!=m_points.end(); ++it) { for (VlcPoints::ByName::iterator it=m_points.begin(); it!=m_points.end(); ++it) {
const VlcPoint& point = m_points.pointNumber(it->second); const VlcPoint& point = m_points.pointNumber(it->second);
string filename = point.filename(); string filename = point.filename();
int lineno = point.lineno(); int lineno = point.lineno();
if (!filename.empty() && lineno!=0) { if (!filename.empty() && lineno!=0) {
int column = point.column(); int column = point.column();
VlcSource& source = sources().findNewSource(filename); VlcSource& source = sources().findNewSource(filename);
string threshStr = point.thresh(); string threshStr = point.thresh();
unsigned thresh = (!threshStr.empty()) ? atoi(threshStr.c_str()) : opt.annotateMin(); unsigned thresh = (!threshStr.empty()) ? atoi(threshStr.c_str()) : opt.annotateMin();
bool ok = (point.count() >= thresh); bool ok = (point.count() >= thresh);
UINFO(9, "AnnoCalc count "<<filename<<" "<<lineno<<" "<<point.count()<<endl); UINFO(9, "AnnoCalc count "<<filename<<" "<<lineno<<" "<<point.count()<<endl);
source.incCount(lineno, column, point.count(), ok); source.incCount(lineno, column, point.count(), ok);
} }
} }
} }
@ -167,23 +167,23 @@ void VlcTop::annotateCalcNeeded() {
int totCases = 0; int totCases = 0;
int totOk = 0; int totOk = 0;
for (VlcSources::NameMap::iterator sit=m_sources.begin(); sit!=m_sources.end(); ++sit) { for (VlcSources::NameMap::iterator sit=m_sources.begin(); sit!=m_sources.end(); ++sit) {
VlcSource& source = sit->second; VlcSource& source = sit->second;
//UINFO(1,"Source "<<source.name()<<endl); //UINFO(1,"Source "<<source.name()<<endl);
if (opt.annotateAll()) source.needed(true); if (opt.annotateAll()) source.needed(true);
VlcSource::LinenoMap& lines = source.lines(); VlcSource::LinenoMap& lines = source.lines();
for (VlcSource::LinenoMap::iterator lit=lines.begin(); lit!=lines.end(); ++lit) { for (VlcSource::LinenoMap::iterator lit=lines.begin(); lit!=lines.end(); ++lit) {
VlcSource::ColumnMap& cmap = lit->second; VlcSource::ColumnMap& cmap = lit->second;
for (VlcSource::ColumnMap::iterator cit=cmap.begin(); cit!=cmap.end(); ++cit) { for (VlcSource::ColumnMap::iterator cit=cmap.begin(); cit!=cmap.end(); ++cit) {
VlcSourceCount& col = cit->second; VlcSourceCount& col = cit->second;
//UINFO(0,"Source "<<source.name()<<" lineno="<<col.lineno()<<" col="<<col.column()<<endl); //UINFO(0,"Source "<<source.name()<<" lineno="<<col.lineno()<<" col="<<col.column()<<endl);
++totCases; ++totCases;
if (col.ok()) { if (col.ok()) {
++totOk; ++totOk;
} else { } else {
source.needed(true); source.needed(true);
} }
} }
} }
} }
float pct = totCases ? (100*totOk / totCases) : 0; float pct = totCases ? (100*totOk / totCases) : 0;
cout<<"Total coverage ("<<totOk<<"/"<<totCases<<") " cout<<"Total coverage ("<<totOk<<"/"<<totCases<<") "
@ -195,60 +195,61 @@ void VlcTop::annotateOutputFiles(const string& dirname) {
// Create if uncreated, ignore errors // Create if uncreated, ignore errors
V3Os::createDir(dirname); V3Os::createDir(dirname);
for (VlcSources::NameMap::iterator sit=m_sources.begin(); sit!=m_sources.end(); ++sit) { for (VlcSources::NameMap::iterator sit=m_sources.begin(); sit!=m_sources.end(); ++sit) {
VlcSource& source = sit->second; VlcSource& source = sit->second;
if (!source.needed()) continue; if (!source.needed()) continue;
string filename = source.name(); string filename = source.name();
string outfilename = dirname+"/"+V3Os::filenameNonDir(filename); string outfilename = dirname+"/"+V3Os::filenameNonDir(filename);
UINFO(1,"annotateOutputFile "<<filename<<" -> "<<outfilename<<endl); UINFO(1,"annotateOutputFile "<<filename<<" -> "<<outfilename<<endl);
std::ifstream is(filename.c_str()); std::ifstream is(filename.c_str());
if (!is) { if (!is) {
v3error("Can't read "<<filename); v3error("Can't read "<<filename);
return; return;
} }
std::ofstream os(outfilename.c_str()); std::ofstream os(outfilename.c_str());
if (!os) { if (!os) {
v3fatal("Can't write "<<outfilename); v3fatal("Can't write "<<outfilename);
return; return;
} }
os << "\t// verilator_coverage annotation"<<endl; os << "\t// verilator_coverage annotation"<<endl;
int lineno = 0; int lineno = 0;
while (!is.eof()) { while (!is.eof()) {
lineno++; lineno++;
string line = V3Os::getline(is); string line = V3Os::getline(is);
bool first = true; bool first = true;
VlcSource::LinenoMap& lines = source.lines(); VlcSource::LinenoMap& lines = source.lines();
VlcSource::LinenoMap::iterator lit=lines.find(lineno); VlcSource::LinenoMap::iterator lit=lines.find(lineno);
if (lit != lines.end()) { if (lit != lines.end()) {
VlcSource::ColumnMap& cmap = lit->second; VlcSource::ColumnMap& cmap = lit->second;
for (VlcSource::ColumnMap::iterator cit=cmap.begin(); cit!=cmap.end(); ++cit) { for (VlcSource::ColumnMap::iterator cit=cmap.begin(); cit!=cmap.end(); ++cit) {
VlcSourceCount& col = cit->second; VlcSourceCount& col = cit->second;
//UINFO(0,"Source "<<source.name()<<" lineno="<<col.lineno()<<" col="<<col.column()<<endl); //UINFO(0,"Source "<<source.name()<<" lineno="<<col.lineno()<<" col="<<col.column()<<endl);
os<<(col.ok()?" ":"%") os<<(col.ok()?" ":"%")
<<std::setfill('0')<<std::setw(6)<<col.count() <<std::setfill('0')<<std::setw(6)<<col.count()
<<"\t"<<line<<endl; <<"\t"<<line<<endl;
if (first) { if (first) {
first = false; first = false;
// Multiple columns on same line; print line just once // Multiple columns on same line; print line just once
string indent; string indent;
for (string::const_iterator pos=line.begin(); pos!=line.end() && isspace(*pos); ++pos) { for (string::const_iterator pos=line.begin();
indent += *pos; pos!=line.end() && isspace(*pos); ++pos) {
} indent += *pos;
line = indent + "verilator_coverage: (next point on previous line)\n"; }
} line = indent + "verilator_coverage: (next point on previous line)\n";
} }
} }
}
if (first) { if (first) {
os<<"\t"<<line<<endl; os<<"\t"<<line<<endl;
} }
} }
} }
} }
@ -258,4 +259,3 @@ void VlcTop::annotate(const string& dirname) {
annotateCalcNeeded(); annotateCalcNeeded();
annotateOutputFiles(dirname); annotateOutputFiles(dirname);
} }

View File

@ -1420,16 +1420,16 @@ sub _make_top_v {
# Test # Test
print $fh "\n"; print $fh "\n";
print $fh " initial begin\n"; print $fh " initial begin\n";
print $fh " fastclk=0;\n" if $self->{inputs}{fastclk}; print $fh " fastclk = 0;\n" if $self->{inputs}{fastclk};
print $fh " clk=0;\n" if $self->{inputs}{clk}; print $fh " clk = 0;\n" if $self->{inputs}{clk};
print $fh " #10;\n"; print $fh " #10;\n";
print $fh " fastclk=1;\n" if $self->{inputs}{fastclk}; print $fh " fastclk = 1;\n" if $self->{inputs}{fastclk};
print $fh " clk=1;\n" if $self->{inputs}{clk}; print $fh " clk = 1;\n" if $self->{inputs}{clk};
print $fh " while (\$time < $self->{sim_time}) begin\n"; print $fh " while (\$time < $self->{sim_time}) begin\n";
for (my $i=0; $i<5; $i++) { for (my $i=0; $i<5; $i++) {
print $fh " #1;\n"; print $fh " #1;\n";
print $fh " fastclk=!fastclk;\n" if $self->{inputs}{fastclk}; print $fh " fastclk = !fastclk;\n" if $self->{inputs}{fastclk};
print $fh " clk=!clk;\n" if $i==4 && $self->{inputs}{clk}; print $fh " clk = !clk;\n" if $i==4 && $self->{inputs}{clk};
} }
print $fh " end\n"; print $fh " end\n";
print $fh " end\n"; print $fh " end\n";
@ -1657,7 +1657,7 @@ sub vcd_identical {
# Also provides backup if vcddiff not installed # Also provides backup if vcddiff not installed
my $h1 = $self->_vcd_read($fn1); my $h1 = $self->_vcd_read($fn1);
my $h2 = $self->_vcd_read($fn2); my $h2 = $self->_vcd_read($fn2);
$Data::Dumper::Sortkeys=1; $Data::Dumper::Sortkeys = 1;
my $a = Dumper($h1); my $a = Dumper($h1);
my $b = Dumper($h2); my $b = Dumper($h2);
if ($a ne $b) { if ($a ne $b) {