clang-format many files. No functional change.

Use nodist/clang_formatter to reformat files that are now clean.
This commit is contained in:
Wilson Snyder 2020-04-13 22:51:35 -04:00
parent dc5c259069
commit 5c966ec510
91 changed files with 4413 additions and 4023 deletions

View File

@ -1,150 +0,0 @@
clang-format is used to standardize the indentation of the internal C++
code.
For the most part clang-format changes provide good consistency, the two
main exceptions being the indentation of preprocessor directives, and
tables of statements.
Reformatting is generally performed only before other large changes are to
be made to a file. The following files are not yet clang-format clean:
clang-format -i include/verilated.h
clang-format -i include/verilated_dpi.h
clang-format -i include/verilated_imp.h
clang-format -i include/verilated_unordered_set_map.h
clang-format -i include/verilatedos.h
clang-format -i include/verilated.cpp
clang-format -i include/verilated_cov.cpp
clang-format -i include/verilated_dpi.cpp
clang-format -i include/verilated_vpi.cpp
clang-format -i src/V3Ast.h
clang-format -i src/V3AstNodes.h
clang-format -i src/V3EmitCBase.h
clang-format -i src/V3Error.h
clang-format -i src/V3File.h
clang-format -i src/V3FileLine.h
clang-format -i src/V3Global.h
clang-format -i src/V3Graph.h
clang-format -i src/V3GraphDfa.h
clang-format -i src/V3GraphStream.h
clang-format -i src/V3Hashed.h
clang-format -i src/V3LanguageWords.h
clang-format -i src/V3LinkDot.h
clang-format -i src/V3List.h
clang-format -i src/V3Number.h
clang-format -i src/V3Options.h
clang-format -i src/V3OrderGraph.h
clang-format -i src/V3Os.h
clang-format -i src/V3ParseImp.h
clang-format -i src/V3ParseSym.h
clang-format -i src/V3Partition.h
clang-format -i src/V3PartitionGraph.h
clang-format -i src/V3PreLex.h
clang-format -i src/V3PreProc.h
clang-format -i src/V3Scoreboard.h
clang-format -i src/V3SenTree.h
clang-format -i src/V3Simulate.h
clang-format -i src/V3Stats.h
clang-format -i src/V3String.h
clang-format -i src/V3SymTable.h
clang-format -i src/V3TSP.h
clang-format -i src/V3Task.h
clang-format -i src/V3WidthCommit.h
clang-format -i src/V3Active.cpp
clang-format -i src/V3ActiveTop.cpp
clang-format -i src/V3Assert.cpp
clang-format -i src/V3AssertPre.cpp
clang-format -i src/V3Ast.cpp
clang-format -i src/V3AstNodes.cpp
clang-format -i src/V3Begin.cpp
clang-format -i src/V3Branch.cpp
clang-format -i src/V3Broken.cpp
clang-format -i src/V3CCtors.cpp
clang-format -i src/V3Case.cpp
clang-format -i src/V3Cast.cpp
clang-format -i src/V3Cdc.cpp
clang-format -i src/V3Changed.cpp
clang-format -i src/V3Clean.cpp
clang-format -i src/V3Clock.cpp
clang-format -i src/V3Combine.cpp
clang-format -i src/V3Const.cpp
clang-format -i src/V3Coverage.cpp
clang-format -i src/V3CoverageJoin.cpp
clang-format -i src/V3Dead.cpp
clang-format -i src/V3Delayed.cpp
clang-format -i src/V3Depth.cpp
clang-format -i src/V3DepthBlock.cpp
clang-format -i src/V3EmitC.cpp
clang-format -i src/V3EmitCInlines.cpp
clang-format -i src/V3EmitCMake.cpp
clang-format -i src/V3EmitCSyms.cpp
clang-format -i src/V3EmitMk.cpp
clang-format -i src/V3EmitV.cpp
clang-format -i src/V3EmitXml.cpp
clang-format -i src/V3Error.cpp
clang-format -i src/V3Expand.cpp
clang-format -i src/V3File.cpp
clang-format -i src/V3FileLine.cpp
clang-format -i src/V3Gate.cpp
clang-format -i src/V3GenClk.cpp
clang-format -i src/V3Graph.cpp
clang-format -i src/V3GraphAcyc.cpp
clang-format -i src/V3GraphAlg.cpp
clang-format -i src/V3GraphDfa.cpp
clang-format -i src/V3GraphPathChecker.cpp
clang-format -i src/V3GraphTest.cpp
clang-format -i src/V3Hashed.cpp
clang-format -i src/V3Inline.cpp
clang-format -i src/V3Inst.cpp
clang-format -i src/V3InstrCount.cpp
clang-format -i src/V3Life.cpp
clang-format -i src/V3LifePost.cpp
clang-format -i src/V3LinkCells.cpp
clang-format -i src/V3LinkDot.cpp
clang-format -i src/V3LinkJump.cpp
clang-format -i src/V3LinkLValue.cpp
clang-format -i src/V3LinkLevel.cpp
clang-format -i src/V3LinkParse.cpp
clang-format -i src/V3LinkResolve.cpp
clang-format -i src/V3Localize.cpp
clang-format -i src/V3Name.cpp
clang-format -i src/V3Number.cpp
clang-format -i src/V3Number_test.cpp
clang-format -i src/V3Options.cpp
clang-format -i src/V3Order.cpp
clang-format -i src/V3Os.cpp
clang-format -i src/V3Param.cpp
clang-format -i src/V3ParseGrammar.cpp
clang-format -i src/V3ParseImp.cpp
clang-format -i src/V3ParseLex.cpp
clang-format -i src/V3Partition.cpp
clang-format -i src/V3PreProc.cpp
clang-format -i src/V3PreShell.cpp
clang-format -i src/V3Premit.cpp
clang-format -i src/V3ProtectLib.cpp
clang-format -i src/V3Reloop.cpp
clang-format -i src/V3Scope.cpp
clang-format -i src/V3Scoreboard.cpp
clang-format -i src/V3Slice.cpp
clang-format -i src/V3Split.cpp
clang-format -i src/V3SplitAs.cpp
clang-format -i src/V3SplitVar.cpp
clang-format -i src/V3Stats.cpp
clang-format -i src/V3StatsReport.cpp
clang-format -i src/V3String.cpp
clang-format -i src/V3Subst.cpp
clang-format -i src/V3TSP.cpp
clang-format -i src/V3Table.cpp
clang-format -i src/V3Task.cpp
clang-format -i src/V3Trace.cpp
clang-format -i src/V3TraceDecl.cpp
clang-format -i src/V3Tristate.cpp
clang-format -i src/V3Undriven.cpp
clang-format -i src/V3Unknown.cpp
clang-format -i src/V3Unroll.cpp
clang-format -i src/V3Width.cpp
clang-format -i src/V3WidthSel.cpp
clang-format -i src/Verilator.cpp

View File

@ -29,16 +29,16 @@ int sc_main(int argc, char* argv[]) {
Vtop* top = new Vtop("top");
// Initialize SC model
#if (SYSTEMC_VERSION>=20070314)
sc_start(1,SC_NS);
#if (SYSTEMC_VERSION >= 20070314)
sc_start(1, SC_NS);
#else
sc_start(1);
#endif
// Simulate until $finish
while (!Verilated::gotFinish()) {
#if (SYSTEMC_VERSION>=20070314)
sc_start(1,SC_NS);
#if (SYSTEMC_VERSION >= 20070314)
sc_start(1, SC_NS);
#else
sc_start(1);
#endif

View File

@ -17,9 +17,7 @@
#endif
vluint64_t main_time = 0;
double sc_time_stamp() {
return main_time;
}
double sc_time_stamp() { return main_time; }
int main(int argc, char** argv, char** env) {
if (0 && argc && argv && env) {}
@ -35,7 +33,7 @@ int main(int argc, char** argv, char** env) {
// When tracing, the contents of the secret module will not be seen
VerilatedVcdC* tfp = NULL;
const char* flag = Verilated::commandArgsPlusMatch("trace");
if (flag && 0==strcmp(flag, "+trace")) {
if (flag && 0 == strcmp(flag, "+trace")) {
Verilated::traceEverOn(true);
VL_PRINTF("Enabling waves into logs/vlt_dump.vcd...\n");
tfp = new VerilatedVcdC;
@ -62,11 +60,15 @@ int main(int argc, char** argv, char** env) {
// Close trace if opened
#if VM_TRACE
if (tfp) { tfp->close(); tfp = NULL; }
if (tfp) {
tfp->close();
tfp = NULL;
}
#endif
// Destroy model
delete top; top = NULL;
delete top;
top = NULL;
// Fin
exit(0);

View File

@ -83,9 +83,9 @@ int main(int argc, char** argv, char** env) {
// Read outputs
VL_PRINTF("[%" VL_PRI64 "d] clk=%x rstl=%x iquad=%" VL_PRI64 "x"
" -> oquad=%" VL_PRI64"x owide=%x_%08x_%08x\n",
main_time, top->clk, top->reset_l, top->in_quad,
top->out_quad, top->out_wide[2], top->out_wide[1], top->out_wide[0]);
" -> oquad=%" VL_PRI64 "x owide=%x_%08x_%08x\n",
main_time, top->clk, top->reset_l, top->in_quad, top->out_quad, top->out_wide[2],
top->out_wide[1], top->out_wide[0]);
}
// Final model cleanup
@ -98,7 +98,8 @@ int main(int argc, char** argv, char** env) {
#endif
// Destroy model
delete top; top = NULL;
delete top;
top = NULL;
// Fin
exit(0);

View File

@ -45,19 +45,19 @@ int sc_main(int argc, char* argv[]) {
ios::sync_with_stdio();
// Defaults time
#if (SYSTEMC_VERSION>20011000)
#if (SYSTEMC_VERSION > 20011000)
#else
sc_time dut(1.0, sc_ns);
sc_set_default_time_unit(dut);
#endif
// Define clocks
#if (SYSTEMC_VERSION>=20070314)
sc_clock clk ("clk", 10,SC_NS, 0.5, 3,SC_NS, true);
sc_clock fastclk ("fastclk", 2,SC_NS, 0.5, 2,SC_NS, true);
#if (SYSTEMC_VERSION >= 20070314)
sc_clock clk("clk", 10, SC_NS, 0.5, 3, SC_NS, true);
sc_clock fastclk("fastclk", 2, SC_NS, 0.5, 2, SC_NS, true);
#else
sc_clock clk ("clk", 10, 0.5, 3, true);
sc_clock fastclk ("fastclk", 2, 0.5, 2, true);
sc_clock clk("clk", 10, 0.5, 3, true);
sc_clock fastclk("fastclk", 2, 0.5, 2, true);
#endif
// Define interconnect
@ -72,15 +72,15 @@ int sc_main(int argc, char* argv[]) {
// Construct the Verilated model, from inside Vtop.h
Vtop* top = new Vtop("top");
// Attach signals to the model
top->clk (clk);
top->fastclk (fastclk);
top->reset_l (reset_l);
top->in_small (in_small);
top->in_quad (in_quad);
top->in_wide (in_wide);
top->out_small (out_small);
top->out_quad (out_quad);
top->out_wide (out_wide);
top->clk(clk);
top->fastclk(fastclk);
top->reset_l(reset_l);
top->in_small(in_small);
top->in_quad(in_quad);
top->in_wide(in_wide);
top->out_small(out_small);
top->out_quad(out_quad);
top->out_wide(out_wide);
#if VM_TRACE
// Before any evaluation, need to know to calculate those signals only used for tracing
@ -89,7 +89,7 @@ int sc_main(int argc, char* argv[]) {
// You must do one evaluation before enabling waves, in order to allow
// SystemC to interconnect everything for testing.
#if (SYSTEMC_VERSION>=20070314)
#if (SYSTEMC_VERSION >= 20070314)
sc_start(1, SC_NS);
#else
sc_start(1);
@ -100,7 +100,7 @@ int sc_main(int argc, char* argv[]) {
// and if at run time passed the +trace argument, turn on tracing
VerilatedVcdSc* tfp = NULL;
const char* flag = Verilated::commandArgsPlusMatch("trace");
if (flag && 0==strcmp(flag, "+trace")) {
if (flag && 0 == strcmp(flag, "+trace")) {
cout << "Enabling waves into logs/vlt_dump.vcd...\n";
tfp = new VerilatedVcdSc;
top->trace(tfp, 99); // Trace 99 levels of hierarchy
@ -118,15 +118,14 @@ int sc_main(int argc, char* argv[]) {
#endif
// Apply inputs
if (sc_time_stamp() > sc_time(1, SC_NS)
&& sc_time_stamp() < sc_time(10, SC_NS)) {
if (sc_time_stamp() > sc_time(1, SC_NS) && sc_time_stamp() < sc_time(10, SC_NS)) {
reset_l = !1; // Assert reset
} else {
reset_l = !0; // Deassert reset
}
// Simulate 1ns
#if (SYSTEMC_VERSION>=20070314)
#if (SYSTEMC_VERSION >= 20070314)
sc_start(1, SC_NS);
#else
sc_start(1);
@ -138,7 +137,10 @@ int sc_main(int argc, char* argv[]) {
// Close trace if opened
#if VM_TRACE
if (tfp) { tfp->close(); tfp = NULL; }
if (tfp) {
tfp->close();
tfp = NULL;
}
#endif
// Coverage analysis (since test passed)
@ -148,7 +150,8 @@ int sc_main(int argc, char* argv[]) {
#endif
// Destroy model
delete top; top = NULL;
delete top;
top = NULL;
// Fin
return 0;

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -16,9 +16,8 @@
///
//*************************************************************************
///**** Product and Version name
// Autoconf substitutes this with the strings from AC_INIT.
#define VERILATOR_PRODUCT "@PACKAGE_NAME@"
#define VERILATOR_VERSION "@PACKAGE_VERSION@"
#define VERILATOR_PRODUCT "@PACKAGE_NAME@"
#define VERILATOR_VERSION "@PACKAGE_VERSION@"

View File

@ -47,7 +47,7 @@ public: // But only local to this file
// CONSTRUCTORS
// Derived classes should call zero() in their constructor
VerilatedCovImpItem() {
for (int i=0; i<MAX_KEYS; ++i) {
for (int i = 0; i < MAX_KEYS; ++i) {
m_keys[i] = KEY_UNDEF;
m_vals[i] = 0;
}
@ -66,7 +66,7 @@ public: // But only local to this file
template <class T> class VerilatedCoverItemSpec : public VerilatedCovImpItem {
private:
// MEMBERS
T* m_countp; ///< Count value
T* m_countp; ///< Count value
public:
// METHODS
// cppcheck-suppress truncLongCastReturn
@ -74,7 +74,10 @@ public:
virtual void zero() const VL_OVERRIDE { *m_countp = 0; }
// CONSTRUCTORS
// cppcheck-suppress noExplicitConstructor
explicit VerilatedCoverItemSpec(T* countp) : m_countp(countp) { *m_countp = 0; }
explicit VerilatedCoverItemSpec(T* countp)
: m_countp(countp) {
*m_countp = 0;
}
virtual ~VerilatedCoverItemSpec() VL_OVERRIDE {}
};
@ -87,20 +90,20 @@ public:
class VerilatedCovImp : VerilatedCovImpBase {
private:
// TYPES
typedef std::map<std::string,int> ValueIndexMap;
typedef std::map<int,std::string> IndexValueMap;
typedef std::map<std::string, int> ValueIndexMap;
typedef std::map<int, std::string> IndexValueMap;
typedef std::deque<VerilatedCovImpItem*> ItemList;
private:
// MEMBERS
VerilatedMutex m_mutex; ///< Protects all members, when VL_THREADED. Wrapper deals with setting it.
ValueIndexMap m_valueIndexes VL_GUARDED_BY(m_mutex); ///< For each key/value a unique arbitrary index value
IndexValueMap m_indexValues VL_GUARDED_BY(m_mutex); ///< For each key/value a unique arbitrary index value
ItemList m_items VL_GUARDED_BY(m_mutex); ///< List of all items
VerilatedMutex m_mutex; ///< Protects all members
ValueIndexMap m_valueIndexes VL_GUARDED_BY(m_mutex); ///< Unique arbitrary value for values
IndexValueMap m_indexValues VL_GUARDED_BY(m_mutex); ///< Unique arbitrary value for keys
ItemList m_items VL_GUARDED_BY(m_mutex); ///< List of all items
VerilatedCovImpItem* m_insertp VL_GUARDED_BY(m_mutex); ///< Item about to insert
const char* m_insertFilenamep VL_GUARDED_BY(m_mutex); ///< Filename about to insert
int m_insertLineno VL_GUARDED_BY(m_mutex); ///< Line number about to insert
const char* m_insertFilenamep VL_GUARDED_BY(m_mutex); ///< Filename about to insert
int m_insertLineno VL_GUARDED_BY(m_mutex); ///< Line number about to insert
// CONSTRUCTORS
VerilatedCovImp() {
@ -109,6 +112,7 @@ private:
m_insertLineno = 0;
}
VL_UNCOPYABLE(VerilatedCovImp);
public:
~VerilatedCovImp() { clearGuts(); }
static VerilatedCovImp& imp() VL_MT_SAFE {
@ -119,10 +123,11 @@ public:
private:
// PRIVATE METHODS
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);
if (iter != m_valueIndexes.end()) return iter->second;
nextIndex++; assert(nextIndex>0);
nextIndex++;
assert(nextIndex > 0); // Didn't rollover
m_valueIndexes.insert(std::make_pair(value, nextIndex));
m_indexValues.insert(std::make_pair(nextIndex, value));
return nextIndex;
@ -131,8 +136,9 @@ private:
// Quote any special characters
std::string rtn;
for (const char* pos = text.c_str(); *pos; ++pos) {
if (!isprint(*pos) || *pos=='%' || *pos=='"') {
char hex[10]; sprintf(hex, "%%%02X", pos[0]);
if (!isprint(*pos) || *pos == '%' || *pos == '"') {
char hex[10];
sprintf(hex, "%%%02X", pos[0]);
rtn += hex;
} else {
rtn += *pos;
@ -145,18 +151,19 @@ private:
// don't want applications to either get confused if they use
// a letter differently, nor want them to rely on our compression...
// (Considered using numeric keys, but will remain back compatible.)
if (key.length()<2) return false;
if (key.length()==2 && isdigit(key[1])) return false;
if (key.length() < 2) return false;
if (key.length() == 2 && isdigit(key[1])) return false;
return true;
}
static std::string keyValueFormatter(const std::string& key, const std::string& value) VL_PURE {
static std::string keyValueFormatter(const std::string& key,
const std::string& value) VL_PURE {
std::string name;
if (key.length()==1 && isalpha(key[0])) {
name += std::string("\001")+key;
if (key.length() == 1 && isalpha(key[0])) {
name += std::string("\001") + key;
} 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;
}
static std::string combineHier(const std::string& old, const std::string& add) VL_PURE {
@ -173,28 +180,35 @@ private:
// Scan forward to first mismatch
const char* apre = a;
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
// 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
const char* apost = a+strlen(a)-1;
const char* bpost = b+strlen(b)-1;
while (*apost == *bpost
&& apost>apre && bpost>bpre) { apost--; bpost--; }
const char* apost = a + strlen(a) - 1;
const char* bpost = b + strlen(b) - 1;
while (*apost == *bpost && apost > apre && bpost > bpre) {
apost--;
bpost--;
}
// Forward to . so we have a whole word
std::string suffix = *bpost ? std::string(bpost+1) : "";
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
// <<"\ncho="<<out<<endl;
return out;
}
bool itemMatchesString(VerilatedCovImpItem* itemp, const std::string& match) VL_REQUIRES(m_mutex) {
for (int i=0; i<MAX_KEYS; ++i) {
bool itemMatchesString(VerilatedCovImpItem* itemp, const std::string& match)
VL_REQUIRES(m_mutex) {
for (int i = 0; i < MAX_KEYS; ++i) {
if (itemp->m_keys[i] != KEY_UNDEF) {
// We don't compare keys, only values
std::string val = m_indexValues[itemp->m_vals[i]];
@ -207,17 +221,23 @@ private:
}
static void selftest() VL_MT_SAFE {
// Little selftest
if (combineHier("a.b.c","a.b.c") !="a.b.c") VL_FATAL_MT(__FILE__,__LINE__,"","%Error: selftest\n");
if (combineHier("a.b.c","a.b") !="a.b*") VL_FATAL_MT(__FILE__,__LINE__,"","%Error: selftest\n");
if (combineHier("a.x.c","a.y.c") !="a.*.c") VL_FATAL_MT(__FILE__,__LINE__,"","%Error: selftest\n");
if (combineHier("a.z.z.z.c","a.b.c") !="a.*.c") VL_FATAL_MT(__FILE__,__LINE__,"","%Error: selftest\n");
if (combineHier("z","a") !="*") VL_FATAL_MT(__FILE__,__LINE__,"","%Error: selftest\n");
if (combineHier("q.a","q.b") !="q.*") VL_FATAL_MT(__FILE__,__LINE__,"","%Error: selftest\n");
if (combineHier("q.za","q.zb") !="q.z*") VL_FATAL_MT(__FILE__,__LINE__,"","%Error: selftest\n");
if (combineHier("1.2.3.a","9.8.7.a") !="*.a") VL_FATAL_MT(__FILE__,__LINE__,"","%Error: selftest\n");
#define VL_CST_CHECK(got, exp) \
do { \
if ((got) != (exp)) VL_FATAL_MT(__FILE__, __LINE__, "", "%Error: selftest\n"); \
} while (0)
VL_CST_CHECK(combineHier("a.b.c", "a.b.c"), "a.b.c");
VL_CST_CHECK(combineHier("a.b.c", "a.b"), "a.b*");
VL_CST_CHECK(combineHier("a.x.c", "a.y.c"), "a.*.c");
VL_CST_CHECK(combineHier("a.z.z.z.c", "a.b.c"), "a.*.c");
VL_CST_CHECK(combineHier("z", "a"), "*");
VL_CST_CHECK(combineHier("q.a", "q.b"), "q.*");
VL_CST_CHECK(combineHier("q.za", "q.zb"), "q.z*");
VL_CST_CHECK(combineHier("1.2.3.a", "9.8.7.a"), "*.a");
#undef VL_CST_CHECK
}
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);
VL_DO_DANGLING(delete itemp, itemp);
}
@ -238,7 +258,7 @@ public:
VerilatedLockGuard lock(m_mutex);
if (matchp && matchp[0]) {
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);
if (!itemMatchesString(itemp, matchp)) {
VL_DO_DANGLING(delete itemp, itemp);
@ -252,7 +272,7 @@ public:
void zero() VL_EXCLUDES(m_mutex) {
Verilated::quiesce();
VerilatedLockGuard lock(m_mutex);
for (ItemList::const_iterator it=m_items.begin(); it!=m_items.end(); ++it) {
for (ItemList::const_iterator it = m_items.begin(); it != m_items.end(); ++it) {
(*it)->zero();
}
}
@ -268,33 +288,33 @@ public:
m_insertFilenamep = filenamep;
m_insertLineno = lineno;
}
void insertp(const char* ckeyps[MAX_KEYS],
const char* valps[MAX_KEYS]) VL_EXCLUDES(m_mutex) {
void insertp(const char* ckeyps[MAX_KEYS], const char* valps[MAX_KEYS]) VL_EXCLUDES(m_mutex) {
VerilatedLockGuard lock(m_mutex);
assert(m_insertp);
// First two key/vals are filename
ckeyps[0]="filename"; valps[0]=m_insertFilenamep;
ckeyps[0] = "filename";
valps[0] = m_insertFilenamep;
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
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;
while (*fnendp && *fnendp!='.') fnendp++;
std::string page_default = "sp_user/"+std::string(fnstartp, fnendp-fnstartp);
ckeyps[2]="page"; valps[2]=page_default.c_str();
for (; *fnendp && *fnendp != '.'; fnendp++) {}
std::string page_default = "sp_user/" + std::string(fnstartp, fnendp - fnstartp);
ckeyps[2] = "page";
valps[2] = page_default.c_str();
// Keys -> strings
std::string keys[MAX_KEYS];
for (int i=0; i<MAX_KEYS; ++i) {
if (ckeyps[i] && ckeyps[i][0]) {
keys[i] = ckeyps[i];
}
for (int i = 0; i < MAX_KEYS; ++i) {
if (ckeyps[i] && ckeyps[i][0]) { keys[i] = ckeyps[i]; }
}
// Ignore empty keys
for (int i=0; i<MAX_KEYS; ++i) {
for (int i = 0; i < MAX_KEYS; ++i) {
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
keys[i] = "";
break;
@ -304,18 +324,18 @@ public:
}
// Insert the values
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];
if (!keys[i].empty()) {
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_vals[addKeynum] = valueIndex(val);
addKeynum++;
if (!legalKey(key)) {
std::string msg
= ("%Error: Coverage keys of one character, or letter+digit are illegal: "
+key);
+ key);
VL_FATAL_MT("", 0, "", msg.c_str());
}
}
@ -335,22 +355,22 @@ public:
std::ofstream os(filename);
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());
return;
}
os << "# SystemC::Coverage-3\n";
// Build list of events; totalize if collapsing hierarchy
typedef std::map<std::string,std::pair<std::string,vluint64_t> > EventMap;
typedef std::map<std::string, std::pair<std::string, vluint64_t> > EventMap;
EventMap eventCounts;
for (ItemList::iterator it=m_items.begin(); it!=m_items.end(); ++it) {
for (ItemList::iterator it = m_items.begin(); it != m_items.end(); ++it) {
VerilatedCovImpItem* itemp = *(it);
std::string name;
std::string hier;
bool per_instance = false;
for (int i=0; i<MAX_KEYS; ++i) {
for (int i = 0; i < MAX_KEYS; ++i) {
if (itemp->m_keys[i] != KEY_UNDEF) {
std::string key = VerilatedCovKey::shortKey(m_indexValues[itemp->m_keys[i]]);
std::string val = m_indexValues[itemp->m_vals[i]];
@ -380,19 +400,19 @@ public:
if (cit != eventCounts.end()) {
const std::string& oldhier = cit->second.first;
cit->second.second += itemp->count();
cit->second.first = combineHier(oldhier, hier);
cit->second.first = combineHier(oldhier, hier);
} else {
eventCounts.insert(std::make_pair(name, make_pair(hier, itemp->count())));
}
}
// Output body
for (EventMap::const_iterator it=eventCounts.begin(); it!=eventCounts.end(); ++it) {
os<<"C '"<<std::dec;
os<<it->first;
if (!it->second.first.empty()) os<<keyValueFormatter(VL_CIK_HIER, it->second.first);
os<<"' "<<it->second.second;
os<<std::endl;
for (EventMap::const_iterator it = eventCounts.begin(); it != eventCounts.end(); ++it) {
os << "C '" << std::dec;
os << it->first;
if (!it->second.first.empty()) os << keyValueFormatter(VL_CIK_HIER, it->second.first);
os << "' " << it->second.second;
os << std::endl;
}
}
};
@ -400,15 +420,11 @@ public:
//=============================================================================
// VerilatedCov
void VerilatedCov::clear() VL_MT_SAFE {
VerilatedCovImp::imp().clear();
}
void VerilatedCov::clear() VL_MT_SAFE { VerilatedCovImp::imp().clear(); }
void VerilatedCov::clearNonMatch(const char* matchp) VL_MT_SAFE {
VerilatedCovImp::imp().clearNonMatch(matchp);
}
void VerilatedCov::zero() VL_MT_SAFE {
VerilatedCovImp::imp().zero();
}
void VerilatedCov::zero() VL_MT_SAFE { VerilatedCovImp::imp().zero(); }
void VerilatedCov::write(const char* filenamep) VL_MT_SAFE {
VerilatedCovImp::imp().write(filenamep);
}
@ -422,48 +438,49 @@ void VerilatedCov::_insertf(const char* filename, int lineno) VL_MT_SAFE {
VerilatedCovImp::imp().insertf(filename, lineno);
}
#define K(n) const char* key ## n
#define A(n) const char* key ## n, const char* valp ## n // Argument list
#define C(n) key ## n, valp ## n // Calling argument list
#define N(n) "","" // Null argument list
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),
A(20),A(21),A(22),A(23),A(24),A(25),A(26),A(27),A(28),A(29)) VL_MT_SAFE {
#define K(n) const char* key##n
#define A(n) const char *key##n, const char *valp##n // Argument list
#define C(n) key##n, valp##n // Calling argument list
#define N(n) "", "" // Null argument list
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), A(20),
A(21), A(22), A(23), A(24), A(25), A(26), A(27), A(28),
A(29)) VL_MT_SAFE {
const char* keyps[VerilatedCovImpBase::MAX_KEYS]
= {NULL,NULL,NULL, // filename,lineno,page
key0,key1,key2,key3,key4,key5,key6,key7,key8,key9,
key10,key11,key12,key13,key14,key15,key16,key17,key18,key19,
key20,key21,key22,key23,key24,key25,key26,key27,key28,key29};
= {NULL, NULL, NULL, // filename,lineno,page
key0, key1, key2, key3, key4, key5, key6, key7, key8, key9,
key10, key11, key12, key13, key14, key15, key16, key17, key18, key19,
key20, key21, key22, key23, key24, key25, key26, key27, key28, key29};
const char* valps[VerilatedCovImpBase::MAX_KEYS]
= {NULL,NULL,NULL, // filename,lineno,page
valp0,valp1,valp2,valp3,valp4,valp5,valp6,valp7,valp8,valp9,
valp10,valp11,valp12,valp13,valp14,valp15,valp16,valp17,valp18,valp19,
valp20,valp21,valp22,valp23,valp24,valp25,valp26,valp27,valp28,valp29};
= {NULL, NULL, NULL, // filename,lineno,page
valp0, valp1, valp2, valp3, valp4, valp5, valp6, valp7, valp8, valp9,
valp10, valp11, valp12, valp13, valp14, valp15, valp16, valp17, valp18, valp19,
valp20, valp21, valp22, valp23, valp24, valp25, valp26, valp27, valp28, valp29};
VerilatedCovImp::imp().insertp(keyps, valps);
}
// And versions with fewer arguments (oh for a language with named parameters!)
void VerilatedCov::_insertp(A(0),A(1),A(2),A(3),A(4),A(5),A(6),A(7),A(8),A(9)) VL_MT_SAFE {
_insertp(C(0),C(1),C(2),C(3),C(4),C(5),C(6),C(7),C(8),C(9),
N(10),N(11),N(12),N(13),N(14),N(15),N(16),N(17),N(18),N(19),
N(20),N(21),N(22),N(23),N(24),N(25),N(26),N(27),N(28),N(29));
void VerilatedCov::_insertp(A(0), A(1), A(2), A(3), A(4), A(5), A(6), A(7), A(8),
A(9)) VL_MT_SAFE {
_insertp(C(0), C(1), C(2), C(3), C(4), C(5), C(6), C(7), C(8), C(9), N(10), N(11), N(12),
N(13), N(14), N(15), N(16), N(17), N(18), N(19), N(20), N(21), N(22), N(23), N(24),
N(25), N(26), N(27), N(28), N(29));
}
void VerilatedCov::_insertp(A(0),A(1),A(2),A(3),A(4),A(5),A(6),A(7),A(8),A(9),
A(10),A(11),A(12),A(13),A(14),A(15),A(16),A(17),A(18),A(19)) VL_MT_SAFE {
_insertp(C(0),C(1),C(2),C(3),C(4),C(5),C(6),C(7),C(8),C(9),
C(10),C(11),C(12),C(13),C(14),C(15),C(16),C(17),C(18),C(19),
N(20),N(21),N(22),N(23),N(24),N(25),N(26),N(27),N(28),N(29));
void VerilatedCov::_insertp(A(0), A(1), A(2), A(3), A(4), A(5), A(6), A(7), A(8), A(9), A(10),
A(11), A(12), A(13), A(14), A(15), A(16), A(17), A(18),
A(19)) VL_MT_SAFE {
_insertp(C(0), C(1), C(2), C(3), C(4), C(5), C(6), C(7), C(8), C(9), C(10), C(11), C(12),
C(13), C(14), C(15), C(16), C(17), C(18), C(19), N(20), N(21), N(22), N(23), N(24),
N(25), N(26), N(27), N(28), N(29));
}
// Backward compatibility for Verilator
void VerilatedCov::_insertp(A(0), A(1), K(2),int val2, K(3),int val3,
K(4),const std::string& val4, A(5),A(6)) VL_MT_SAFE {
void VerilatedCov::_insertp(A(0), A(1), K(2), int val2, K(3), int val3, K(4),
const std::string& val4, A(5), A(6)) VL_MT_SAFE {
std::string val2str = vlCovCvtToStr(val2);
std::string val3str = vlCovCvtToStr(val3);
_insertp(C(0),C(1),
key2,val2str.c_str(), key3,val3str.c_str(), key4, val4.c_str(),
C(5),C(6),N(7),N(8),N(9),
N(10),N(11),N(12),N(13),N(14),N(15),N(16),N(17),N(18),N(19),
N(20),N(21),N(22),N(23),N(24),N(25),N(26),N(27),N(28),N(29));
_insertp(C(0), C(1), key2, val2str.c_str(), key3, val3str.c_str(), key4, val4.c_str(), C(5),
C(6), N(7), N(8), N(9), N(10), N(11), N(12), N(13), N(14), N(15), N(16), N(17), N(18),
N(19), N(20), N(21), N(22), N(23), N(24), N(25), N(26), N(27), N(28), N(29));
}
#undef A
#undef C

View File

@ -28,17 +28,17 @@
//=============================================================================
/// Conditionally compile coverage code
// clang-format off
#ifdef VM_COVERAGE
# define VL_IF_COVER(stmts) \
do { \
stmts; \
} while (false)
do { stmts; } while (false)
#else
# define VL_IF_COVER(stmts) \
do { \
if (false) { stmts; } \
} while (false)
#endif
// clang-format on
//=============================================================================
/// Insert a item for coverage analysis.
@ -68,16 +68,17 @@
/// VL_COVER_INSERT(&m_cases[i], "comment", "Coverage Case", "i", cvtToNumStr(i));
/// }
#define VL_COVER_INSERT(countp,...) \
VL_IF_COVER(VerilatedCov::_inserti(countp); \
VerilatedCov::_insertf(__FILE__, __LINE__); \
#define VL_COVER_INSERT(countp, ...) \
VL_IF_COVER(VerilatedCov::_inserti(countp); VerilatedCov::_insertf(__FILE__, __LINE__); \
VerilatedCov::_insertp("hier", name(), __VA_ARGS__))
//=============================================================================
/// Convert VL_COVER_INSERT value arguments to strings
template< class T> std::string vlCovCvtToStr(const T& t) VL_PURE {
std::ostringstream os; os<<t; return os.str();
template <class T> std::string vlCovCvtToStr(const T& t) VL_PURE {
std::ostringstream os;
os << t;
return os.str();
}
//=============================================================================
@ -89,6 +90,7 @@ template< class T> std::string vlCovCvtToStr(const T& t) VL_PURE {
class VerilatedCov {
VL_UNCOPYABLE(VerilatedCov);
public:
// GLOBAL METHODS
/// Return default filename
@ -108,18 +110,18 @@ public:
// We could have just the maximum argument version, but this compiles
// much slower (nearly 2x) than having smaller versions also. However
// there's not much more gain in having a version for each number of args.
#define K(n) const char* key ## n
#define A(n) const char* key ## n, const char* valp ## n // Argument list
#define D(n) const char* key ## n = NULL, const char* valp ## n = NULL // Argument list
static void _insertp(D(0),D(1),D(2),D(3),D(4),D(5),D(6),D(7),D(8),D(9));
static void _insertp(A(0),A(1),A(2),A(3),A(4),A(5),A(6),A(7),A(8),A(9)
,A(10),D(11),D(12),D(13),D(14),D(15),D(16),D(17),D(18),D(19));
static void _insertp(A(0),A(1),A(2),A(3),A(4),A(5),A(6),A(7),A(8),A(9)
,A(10),A(11),A(12),A(13),A(14),A(15),A(16),A(17),A(18),A(19)
,A(20),D(21),D(22),D(23),D(24),D(25),D(26),D(27),D(28),D(29));
#define K(n) const char* key##n
#define A(n) const char *key##n, const char *valp##n // Argument list
#define D(n) const char *key##n = NULL, const char *valp##n = NULL // Argument list
static void _insertp(D(0), D(1), D(2), D(3), D(4), D(5), D(6), D(7), D(8), D(9));
static void _insertp(A(0), A(1), A(2), A(3), A(4), A(5), A(6), A(7), A(8), A(9), A(10), D(11),
D(12), D(13), D(14), D(15), D(16), D(17), D(18), D(19));
static void _insertp(A(0), A(1), A(2), A(3), A(4), A(5), A(6), A(7), A(8), A(9), A(10), A(11),
A(12), A(13), A(14), A(15), A(16), A(17), A(18), A(19), A(20), D(21),
D(22), D(23), D(24), D(25), D(26), D(27), D(28), D(29));
// Backward compatibility for Verilator
static void _insertp(A(0), A(1), K(2),int val2, K(3),int val3,
K(4),const std::string& val4, A(5),A(6));
static void _insertp(A(0), A(1), K(2), int val2, K(3), int val3, K(4), const std::string& val4,
A(5), A(6));
#undef K
#undef A

View File

@ -28,6 +28,7 @@
#define VLCOVGEN_ITEM(string_parsed_by_vlcovgen)
// clang-format off
VLCOVGEN_ITEM("name=>'col0_name', short=>'C0', group=>1, default=>undef, descr=>'The column title for the header line of this column'")
VLCOVGEN_ITEM("name=>'col1_name', short=>'C1', group=>1, default=>undef, ")
VLCOVGEN_ITEM("name=>'col2_name', short=>'C2', group=>1, default=>undef, ")
@ -59,6 +60,7 @@ VLCOVGEN_ITEM("name=>'row1', short=>'r1', group=>0, default=>undef, ")
VLCOVGEN_ITEM("name=>'row2', short=>'r2', group=>0, default=>undef, ")
VLCOVGEN_ITEM("name=>'row3', short=>'r3', group=>0, default=>undef, ")
VLCOVGEN_ITEM("name=>'weight', short=>'w', group=>0, default=>undef, descr=>'For totaling items, weight of this item'")
// clang-format on
// VLCOVGEN_CIK_AUTO_EDIT_BEGIN
#define VL_CIK_COL0 "c0"

View File

@ -40,88 +40,80 @@
// Not supported yet
#define _VL_SVDPI_UNIMP() \
VL_FATAL_MT(__FILE__, __LINE__, "", \
(std::string("%%Error: Unsupported DPI function: ")+VL_FUNC).c_str())
(std::string("%%Error: Unsupported DPI function: ") + VL_FUNC).c_str())
#define _VL_SVDPI_WARN(...) \
VL_PRINTF_MT(__VA_ARGS__)
#define _VL_SVDPI_WARN(...) VL_PRINTF_MT(__VA_ARGS__)
// Function requires a "context" in the import declaration
#define _VL_SVDPI_CONTEXT_WARN() \
_VL_SVDPI_WARN("%%Warning: DPI C Function called by Verilog DPI import with missing 'context' keyword.\n");
_VL_SVDPI_WARN("%%Warning: DPI C Function called by Verilog DPI import with missing " \
"'context' keyword.\n");
//======================================================================
//======================================================================
//======================================================================
// DPI ROUTINES
const char* svDpiVersion() {
return "1800-2005";
}
const char* svDpiVersion() { return "1800-2005"; }
//======================================================================
// Bit-select utility functions.
svBit svGetBitselBit(const svBitVecVal* sp, int bit) {
return VL_BITRSHIFT_W(sp,bit) & 1;
}
svBit svGetBitselBit(const svBitVecVal* sp, int bit) { return VL_BITRSHIFT_W(sp, bit) & 1; }
svLogic svGetBitselLogic(const svLogicVecVal* sp, int bit) {
// Not VL_BITRSHIFT_W as sp is a different structure type
// Verilator doesn't support X/Z so only aval
return (((sp[VL_BITWORD_I(bit)].aval >> VL_BITBIT_I(bit)) & 1)
| (((sp[VL_BITWORD_I(bit)].bval >> VL_BITBIT_I(bit)) & 1)<<1));
| (((sp[VL_BITWORD_I(bit)].bval >> VL_BITBIT_I(bit)) & 1) << 1));
}
void svPutBitselBit(svBitVecVal* dp, int bit, svBit s) {
VL_ASSIGNBIT_WI(32, bit, dp, s);
}
void svPutBitselBit(svBitVecVal* dp, int bit, svBit s) { VL_ASSIGNBIT_WI(32, bit, dp, s); }
void svPutBitselLogic(svLogicVecVal* dp, int bit, svLogic s) {
// Verilator doesn't support X/Z so only aval
dp[VL_BITWORD_I(bit)].aval
= ((dp[VL_BITWORD_I(bit)].aval & ~(VL_UL(1)<<VL_BITBIT_I(bit)))
| ((s&1)<<VL_BITBIT_I(bit)));
dp[VL_BITWORD_I(bit)].bval
= ((dp[VL_BITWORD_I(bit)].bval & ~(VL_UL(1)<<VL_BITBIT_I(bit)))
| ((s&2)>>1<<VL_BITBIT_I(bit)));
dp[VL_BITWORD_I(bit)].aval = ((dp[VL_BITWORD_I(bit)].aval & ~(VL_UL(1) << VL_BITBIT_I(bit)))
| ((s & 1) << VL_BITBIT_I(bit)));
dp[VL_BITWORD_I(bit)].bval = ((dp[VL_BITWORD_I(bit)].bval & ~(VL_UL(1) << VL_BITBIT_I(bit)))
| ((s & 2) >> 1 << VL_BITBIT_I(bit)));
}
void svGetPartselBit(svBitVecVal* dp, const svBitVecVal* sp, int lsb, int width) {
// See also VL_SEL_WWI
int msb = lsb+width-1;
int msb = lsb + width - 1;
int word_shift = VL_BITWORD_I(lsb);
if (VL_BITBIT_I(lsb)==0) {
if (VL_BITBIT_I(lsb) == 0) {
// Just a word extract
for (int i=0; i<VL_WORDS_I(width); ++i) dp[i] = sp[i+word_shift];
for (int i = 0; i < VL_WORDS_I(width); ++i) dp[i] = sp[i + word_shift];
} else {
int loffset = lsb & VL_SIZEBITS_I;
int nbitsfromlow = 32-loffset; // bits that end up in lword (know loffset!=0)
int nbitsfromlow = 32 - loffset; // bits that end up in lword (know loffset!=0)
// Middle words
int words = VL_WORDS_I(msb-lsb+1);
for (int i=0; i<words; ++i) {
dp[i] = sp[i+word_shift]>>loffset;
int upperword = i+word_shift+1;
int words = VL_WORDS_I(msb - lsb + 1);
for (int i = 0; i < words; ++i) {
dp[i] = sp[i + word_shift] >> loffset;
int upperword = i + word_shift + 1;
if (upperword <= static_cast<int>(VL_BITWORD_I(msb))) {
dp[i] |= sp[upperword] << nbitsfromlow;
}
}
}
// Clean result
dp[VL_WORDS_I(width)-1] &= VL_MASK_I(width);
dp[VL_WORDS_I(width) - 1] &= VL_MASK_I(width);
}
void svGetPartselLogic(svLogicVecVal* dp, const svLogicVecVal* sp, int lsb, int width) {
int msb = lsb+width-1;
int msb = lsb + width - 1;
int word_shift = VL_BITWORD_I(lsb);
if (VL_BITBIT_I(lsb)==0) {
if (VL_BITBIT_I(lsb) == 0) {
// Just a word extract
for (int i=0; i<VL_WORDS_I(width); ++i) dp[i] = sp[i+word_shift];
for (int i = 0; i < VL_WORDS_I(width); ++i) dp[i] = sp[i + word_shift];
} else {
int loffset = lsb & VL_SIZEBITS_I;
int nbitsfromlow = 32-loffset; // bits that end up in lword (know loffset!=0)
int nbitsfromlow = 32 - loffset; // bits that end up in lword (know loffset!=0)
// Middle words
int words = VL_WORDS_I(msb-lsb+1);
for (int i=0; i<words; ++i) {
dp[i].aval = sp[i+word_shift].aval >> loffset;
dp[i].bval = sp[i+word_shift].bval >> loffset;
int upperword = i+word_shift+1;
int words = VL_WORDS_I(msb - lsb + 1);
for (int i = 0; i < words; ++i) {
dp[i].aval = sp[i + word_shift].aval >> loffset;
dp[i].bval = sp[i + word_shift].bval >> loffset;
int upperword = i + word_shift + 1;
if (upperword <= static_cast<int>(VL_BITWORD_I(msb))) {
dp[i].aval |= sp[upperword].aval << nbitsfromlow;
dp[i].bval |= sp[upperword].bval << nbitsfromlow;
@ -129,58 +121,56 @@ void svGetPartselLogic(svLogicVecVal* dp, const svLogicVecVal* sp, int lsb, int
}
}
// Clean result
dp[VL_WORDS_I(width)-1].aval &= VL_MASK_I(width);
dp[VL_WORDS_I(width)-1].bval &= VL_MASK_I(width);
dp[VL_WORDS_I(width) - 1].aval &= VL_MASK_I(width);
dp[VL_WORDS_I(width) - 1].bval &= VL_MASK_I(width);
}
void svPutPartselBit(svBitVecVal* dp, const svBitVecVal s, int lbit, int width) {
// See also _VL_INSERT_WI
int hbit = lbit+width-1;
int hbit = lbit + width - 1;
int hoffset = VL_BITBIT_I(hbit);
int loffset = VL_BITBIT_I(lbit);
if (hoffset==VL_SIZEBITS_I && loffset==0) {
if (hoffset == VL_SIZEBITS_I && loffset == 0) {
// Fast and common case, word based insertion
dp[VL_BITWORD_I(lbit)] = s;
}
else {
} else {
int hword = VL_BITWORD_I(hbit);
int lword = VL_BITWORD_I(lbit);
if (hword==lword) { // know < 32 bits because above checks it
IData insmask = (VL_MASK_I(hoffset-loffset+1))<<loffset;
dp[lword] = (dp[lword] & ~insmask) | ((s<<loffset) & insmask);
if (hword == lword) { // know < 32 bits because above checks it
IData insmask = (VL_MASK_I(hoffset - loffset + 1)) << loffset;
dp[lword] = (dp[lword] & ~insmask) | ((s << loffset) & insmask);
} else {
IData hinsmask = (VL_MASK_I(hoffset-0+1))<<0;
IData linsmask = (VL_MASK_I(31-loffset+1))<<loffset;
int nbitsonright = 32-loffset; // bits that end up in lword
dp[lword] = (dp[lword] & ~linsmask) | ((s<<loffset) & linsmask);
dp[hword] = (dp[hword] & ~hinsmask) | ((s>>nbitsonright) & hinsmask);
IData hinsmask = (VL_MASK_I(hoffset - 0 + 1)) << 0;
IData linsmask = (VL_MASK_I(31 - loffset + 1)) << loffset;
int nbitsonright = 32 - loffset; // bits that end up in lword
dp[lword] = (dp[lword] & ~linsmask) | ((s << loffset) & linsmask);
dp[hword] = (dp[hword] & ~hinsmask) | ((s >> nbitsonright) & hinsmask);
}
}
}
// cppcheck-suppress passedByValue
void svPutPartselLogic(svLogicVecVal* dp, const svLogicVecVal s, int lbit, int width) {
int hbit = lbit+width-1;
int hbit = lbit + width - 1;
int hoffset = VL_BITBIT_I(hbit);
int loffset = VL_BITBIT_I(lbit);
if (hoffset==VL_SIZEBITS_I && loffset==0) {
if (hoffset == VL_SIZEBITS_I && loffset == 0) {
// Fast and common case, word based insertion
dp[VL_BITWORD_I(lbit)].aval = s.aval;
dp[VL_BITWORD_I(lbit)].bval = s.bval;
}
else {
} else {
int hword = VL_BITWORD_I(hbit);
int lword = VL_BITWORD_I(lbit);
if (hword==lword) { // know < 32 bits because above checks it
IData insmask = (VL_MASK_I(hoffset-loffset+1))<<loffset;
dp[lword].aval = (dp[lword].aval & ~insmask) | ((s.aval<<loffset) & insmask);
dp[lword].bval = (dp[lword].bval & ~insmask) | ((s.bval<<loffset) & insmask);
if (hword == lword) { // know < 32 bits because above checks it
IData insmask = (VL_MASK_I(hoffset - loffset + 1)) << loffset;
dp[lword].aval = (dp[lword].aval & ~insmask) | ((s.aval << loffset) & insmask);
dp[lword].bval = (dp[lword].bval & ~insmask) | ((s.bval << loffset) & insmask);
} else {
IData hinsmask = (VL_MASK_I(hoffset-0+1))<<0;
IData linsmask = (VL_MASK_I(31-loffset+1))<<loffset;
int nbitsonright = 32-loffset; // bits that end up in lword
dp[lword].aval = (dp[lword].aval & ~linsmask) | ((s.aval<<loffset) & linsmask);
dp[lword].bval = (dp[lword].bval & ~linsmask) | ((s.bval<<loffset) & linsmask);
dp[hword].aval = (dp[hword].aval & ~hinsmask) | ((s.aval>>nbitsonright) & hinsmask);
dp[hword].bval = (dp[hword].bval & ~hinsmask) | ((s.bval>>nbitsonright) & hinsmask);
IData hinsmask = (VL_MASK_I(hoffset - 0 + 1)) << 0;
IData linsmask = (VL_MASK_I(31 - loffset + 1)) << loffset;
int nbitsonright = 32 - loffset; // bits that end up in lword
dp[lword].aval = (dp[lword].aval & ~linsmask) | ((s.aval << loffset) & linsmask);
dp[lword].bval = (dp[lword].bval & ~linsmask) | ((s.bval << loffset) & linsmask);
dp[hword].aval = (dp[hword].aval & ~hinsmask) | ((s.aval >> nbitsonright) & hinsmask);
dp[hword].bval = (dp[hword].bval & ~hinsmask) | ((s.bval >> nbitsonright) & hinsmask);
}
}
}
@ -204,27 +194,14 @@ static inline const VerilatedDpiOpenVar* _vl_openhandle_varp(const svOpenArrayHa
//======================================================================
// Open array querying functions
int svLeft(const svOpenArrayHandle h, int d) {
return _vl_openhandle_varp(h)->left(d);
}
int svRight(const svOpenArrayHandle h, int d) {
return _vl_openhandle_varp(h)->right(d);
}
int svLow(const svOpenArrayHandle h, int d) {
return _vl_openhandle_varp(h)->low(d);
}
int svHigh(const svOpenArrayHandle h, int d) {
return _vl_openhandle_varp(h)->high(d);
}
int svIncrement(const svOpenArrayHandle h, int d) {
return _vl_openhandle_varp(h)->increment(d);
}
int svSize(const svOpenArrayHandle h, int d) {
return _vl_openhandle_varp(h)->elements(d);
}
int svDimensions(const svOpenArrayHandle h) {
return _vl_openhandle_varp(h)->udims();
}
int svLeft(const svOpenArrayHandle h, int d) { return _vl_openhandle_varp(h)->left(d); }
int svRight(const svOpenArrayHandle h, int d) { return _vl_openhandle_varp(h)->right(d); }
int svLow(const svOpenArrayHandle h, int d) { return _vl_openhandle_varp(h)->low(d); }
int svHigh(const svOpenArrayHandle h, int d) { return _vl_openhandle_varp(h)->high(d); }
int svIncrement(const svOpenArrayHandle h, int d) { return _vl_openhandle_varp(h)->increment(d); }
int svSize(const svOpenArrayHandle h, int d) { return _vl_openhandle_varp(h)->elements(d); }
int svDimensions(const svOpenArrayHandle h) { return _vl_openhandle_varp(h)->udims(); }
/// Return pointer to open array data, or NULL if not in IEEE standard C layout
void* svGetArrayPtr(const svOpenArrayHandle h) {
const VerilatedDpiOpenVar* varp = _vl_openhandle_varp(h);
@ -242,8 +219,8 @@ int svSizeOfArray(const svOpenArrayHandle h) {
//======================================================================
// Open array access internals
static void* _vl_sv_adjusted_datap(const VerilatedDpiOpenVar* varp,
int nargs, int indx1, int indx2, int indx3) {
static void* _vl_sv_adjusted_datap(const VerilatedDpiOpenVar* varp, int nargs, int indx1,
int indx2, int indx3) {
void* datap = varp->datap();
if (VL_UNLIKELY(nargs != varp->udims())) {
_VL_SVDPI_WARN("%%Warning: DPI svOpenArrayHandle function called on"
@ -251,26 +228,29 @@ static void* _vl_sv_adjusted_datap(const VerilatedDpiOpenVar* varp,
varp->udims(), nargs);
return NULL;
}
if (nargs>=1) {
if (nargs >= 1) {
datap = varp->datapAdjustIndex(datap, 1, indx1);
if (VL_UNLIKELY(!datap)) {
_VL_SVDPI_WARN("%%Warning: DPI svOpenArrayHandle function index 1 out of bounds; %d outside [%d:%d].\n",
_VL_SVDPI_WARN("%%Warning: DPI svOpenArrayHandle function index 1 "
"out of bounds; %d outside [%d:%d].\n",
indx1, varp->left(1), varp->right(1));
return NULL;
}
}
if (nargs>=2) {
if (nargs >= 2) {
datap = varp->datapAdjustIndex(datap, 2, indx2);
if (VL_UNLIKELY(!datap)) {
_VL_SVDPI_WARN("%%Warning: DPI svOpenArrayHandle function index 2 out of bounds; %d outside [%d:%d].\n",
_VL_SVDPI_WARN("%%Warning: DPI svOpenArrayHandle function index 2 "
"out of bounds; %d outside [%d:%d].\n",
indx2, varp->left(2), varp->right(2));
return NULL;
}
}
if (nargs>=3) {
if (nargs >= 3) {
datap = varp->datapAdjustIndex(datap, 3, indx3);
if (VL_UNLIKELY(!datap)) {
_VL_SVDPI_WARN("%%Warning: DPI svOpenArrayHandle function index 3 out of bounds; %d outside [%d:%d].\n",
_VL_SVDPI_WARN("%%Warning: DPI svOpenArrayHandle function index 3 "
"out of bounds; %d outside [%d:%d].\n",
indx1, varp->left(3), varp->right(3));
return NULL;
}
@ -280,7 +260,8 @@ static void* _vl_sv_adjusted_datap(const VerilatedDpiOpenVar* varp,
static int _vl_sv_adjusted_bit(const VerilatedDpiOpenVar* varp, int indx) {
if (VL_UNLIKELY(indx < varp->low(0) || indx > varp->high(0))) {
_VL_SVDPI_WARN("%%Warning: DPI svOpenArrayHandle function packed index out of bounds; %d outside [%d:%d].\n",
_VL_SVDPI_WARN("%%Warning: DPI svOpenArrayHandle function packed index out of bounds; %d "
"outside [%d:%d].\n",
indx, varp->left(0), varp->right(0));
return 0;
}
@ -288,8 +269,8 @@ static int _vl_sv_adjusted_bit(const VerilatedDpiOpenVar* varp, int indx) {
}
/// Return pointer to simulator open array element, or NULL if outside range
static void* _vl_svGetArrElemPtr(const svOpenArrayHandle h,
int nargs, int indx1, int indx2, int indx3) VL_MT_SAFE {
static void* _vl_svGetArrElemPtr(const svOpenArrayHandle h, int nargs, int indx1, int indx2,
int indx3) VL_MT_SAFE {
const VerilatedDpiOpenVar* varp = _vl_openhandle_varp(h);
if (VL_UNLIKELY(!varp->isDpiStdLayout())) return NULL;
void* datap = _vl_sv_adjusted_datap(varp, nargs, indx1, indx2, indx3);
@ -297,23 +278,25 @@ static void* _vl_svGetArrElemPtr(const svOpenArrayHandle h,
}
/// Copy to user bit array from simulator open array
static void _vl_svGetBitArrElemVecVal(svBitVecVal* d, const svOpenArrayHandle s,
int nargs, int indx1, int indx2, int indx3) VL_MT_SAFE {
static void _vl_svGetBitArrElemVecVal(svBitVecVal* d, const svOpenArrayHandle s, int nargs,
int indx1, int indx2, int indx3) VL_MT_SAFE {
const VerilatedDpiOpenVar* varp = _vl_openhandle_varp(s);
void* datap = _vl_sv_adjusted_datap(varp, nargs, indx1, indx2, indx3);
if (VL_UNLIKELY(!datap)) return;
switch (varp->vltype()) {
case VLVT_UINT8: d[0] = *(reinterpret_cast<CData*>(datap)); return;
case VLVT_UINT8: d[0] = *(reinterpret_cast<CData*>(datap)); return;
case VLVT_UINT16: d[0] = *(reinterpret_cast<SData*>(datap)); return;
case VLVT_UINT32: d[0] = *(reinterpret_cast<IData*>(datap)); return;
case VLVT_UINT64: {
WData lwp[2]; VL_SET_WQ(lwp, *(reinterpret_cast<QData*>(datap)));
d[0] = lwp[0]; d[1] = lwp[1];
WData lwp[2];
VL_SET_WQ(lwp, *(reinterpret_cast<QData*>(datap)));
d[0] = lwp[0];
d[1] = lwp[1];
break;
}
case VLVT_WDATA: {
WDataOutP wdatap = (reinterpret_cast<WDataOutP>(datap));
for (int i=0; i<VL_WORDS_I(varp->packed().elements()); ++i) d[i] = wdatap[i];
for (int i = 0; i < VL_WORDS_I(varp->packed().elements()); ++i) d[i] = wdatap[i];
return;
}
default:
@ -323,25 +306,38 @@ static void _vl_svGetBitArrElemVecVal(svBitVecVal* d, const svOpenArrayHandle s,
}
}
/// Copy to user logic array from simulator open array
static void _vl_svGetLogicArrElemVecVal(svLogicVecVal* d, const svOpenArrayHandle s,
int nargs, int indx1, int indx2, int indx3) VL_MT_SAFE {
static void _vl_svGetLogicArrElemVecVal(svLogicVecVal* d, const svOpenArrayHandle s, int nargs,
int indx1, int indx2, int indx3) VL_MT_SAFE {
const VerilatedDpiOpenVar* varp = _vl_openhandle_varp(s);
void* datap = _vl_sv_adjusted_datap(varp, nargs, indx1, indx2, indx3);
if (VL_UNLIKELY(!datap)) return;
switch (varp->vltype()) {
case VLVT_UINT8: d[0].aval = *(reinterpret_cast<CData*>(datap)); d[0].bval=0; return;
case VLVT_UINT16: d[0].aval = *(reinterpret_cast<SData*>(datap)); d[0].bval=0; return;
case VLVT_UINT32: d[0].aval = *(reinterpret_cast<IData*>(datap)); d[0].bval=0; return;
case VLVT_UINT8:
d[0].aval = *(reinterpret_cast<CData*>(datap));
d[0].bval = 0;
return;
case VLVT_UINT16:
d[0].aval = *(reinterpret_cast<SData*>(datap));
d[0].bval = 0;
return;
case VLVT_UINT32:
d[0].aval = *(reinterpret_cast<IData*>(datap));
d[0].bval = 0;
return;
case VLVT_UINT64: {
WData lwp[2]; VL_SET_WQ(lwp, *(reinterpret_cast<QData*>(datap)));
d[0].aval = lwp[0]; d[0].bval=0;
d[1].aval = lwp[1]; d[0].bval=0;
WData lwp[2];
VL_SET_WQ(lwp, *(reinterpret_cast<QData*>(datap)));
d[0].aval = lwp[0];
d[0].bval = 0;
d[1].aval = lwp[1];
d[0].bval = 0;
break;
}
case VLVT_WDATA: {
WDataOutP wdatap = (reinterpret_cast<WDataOutP>(datap));
for (int i=0; i<VL_WORDS_I(varp->packed().elements()); ++i) {
d[i].aval = wdatap[i]; d[i].bval = 0;
for (int i = 0; i < VL_WORDS_I(varp->packed().elements()); ++i) {
d[i].aval = wdatap[i];
d[i].bval = 0;
}
return;
}
@ -353,19 +349,19 @@ static void _vl_svGetLogicArrElemVecVal(svLogicVecVal* d, const svOpenArrayHandl
}
/// Copy to simulator open array from from user bit array
static void _vl_svPutBitArrElemVecVal(const svOpenArrayHandle d, const svBitVecVal* s,
int nargs, int indx1, int indx2, int indx3) VL_MT_SAFE {
static void _vl_svPutBitArrElemVecVal(const svOpenArrayHandle d, const svBitVecVal* s, int nargs,
int indx1, int indx2, int indx3) VL_MT_SAFE {
const VerilatedDpiOpenVar* varp = _vl_openhandle_varp(d);
void* datap = _vl_sv_adjusted_datap(varp, nargs, indx1, indx2, indx3);
if (VL_UNLIKELY(!datap)) return;
switch (varp->vltype()) {
case VLVT_UINT8: *(reinterpret_cast<CData*>(datap)) = s[0]; return;
case VLVT_UINT8: *(reinterpret_cast<CData*>(datap)) = s[0]; return;
case VLVT_UINT16: *(reinterpret_cast<SData*>(datap)) = s[0]; return;
case VLVT_UINT32: *(reinterpret_cast<IData*>(datap)) = s[0]; return;
case VLVT_UINT64: *(reinterpret_cast<QData*>(datap)) = _VL_SET_QII(s[1], s[0]); break;
case VLVT_WDATA: {
WDataOutP wdatap = (reinterpret_cast<WDataOutP>(datap));
for (int i=0; i<VL_WORDS_I(varp->packed().elements()); ++i) wdatap[i] = s[i];
for (int i = 0; i < VL_WORDS_I(varp->packed().elements()); ++i) wdatap[i] = s[i];
return;
}
default:
@ -381,80 +377,82 @@ static void _vl_svPutLogicArrElemVecVal(const svOpenArrayHandle d, const svLogic
void* datap = _vl_sv_adjusted_datap(varp, nargs, indx1, indx2, indx3);
if (VL_UNLIKELY(!datap)) return;
switch (varp->vltype()) {
case VLVT_UINT8: *(reinterpret_cast<CData*>(datap)) = s[0].aval; return;
case VLVT_UINT8: *(reinterpret_cast<CData*>(datap)) = s[0].aval; return;
case VLVT_UINT16: *(reinterpret_cast<SData*>(datap)) = s[0].aval; return;
case VLVT_UINT32: *(reinterpret_cast<IData*>(datap)) = s[0].aval; return;
case VLVT_UINT64: *(reinterpret_cast<QData*>(datap)) = _VL_SET_QII(s[1].aval, s[0].aval); break;
case VLVT_UINT64:
*(reinterpret_cast<QData*>(datap)) = _VL_SET_QII(s[1].aval, s[0].aval);
break;
case VLVT_WDATA: {
WDataOutP wdatap = (reinterpret_cast<WDataOutP>(datap));
for (int i=0; i<VL_WORDS_I(varp->packed().elements()); ++i) wdatap[i] = s[i].aval;
for (int i = 0; i < VL_WORDS_I(varp->packed().elements()); ++i) wdatap[i] = s[i].aval;
return;
}
default:
_VL_SVDPI_WARN("%%Warning: DPI svOpenArrayHandle function unsupported datatype (%d).\n", varp->vltype());
_VL_SVDPI_WARN("%%Warning: DPI svOpenArrayHandle function unsupported datatype (%d).\n",
varp->vltype());
return;
}
}
/// Return bit from simulator open array
static svBit _vl_svGetBitArrElem(const svOpenArrayHandle s,
int nargs, int indx1, int indx2, int indx3, int indx4) VL_MT_SAFE {
static svBit _vl_svGetBitArrElem(const svOpenArrayHandle s, int nargs, int indx1, int indx2,
int indx3, int indx4) VL_MT_SAFE {
// One extra index supported, as need bit number
const VerilatedDpiOpenVar* varp = _vl_openhandle_varp(s);
void* datap;
int lsb;
if (varp->packed().elements()) {
datap = _vl_sv_adjusted_datap(varp, nargs-1, indx1, indx2, indx3);
lsb = _vl_sv_adjusted_bit(varp, ((nargs==1) ? indx1
: (nargs==2) ? indx2
: (nargs==3) ? indx3
: indx4));
datap = _vl_sv_adjusted_datap(varp, nargs - 1, indx1, indx2, indx3);
lsb = _vl_sv_adjusted_bit(
varp, ((nargs == 1) ? indx1 : (nargs == 2) ? indx2 : (nargs == 3) ? indx3 : indx4));
} else {
datap = _vl_sv_adjusted_datap(varp, nargs, indx1, indx2, indx3);
lsb = 0;
}
if (VL_UNLIKELY(!datap)) return 0;
switch (varp->vltype()) {
case VLVT_UINT8: return (*(reinterpret_cast<CData*>(datap)) >> lsb) & 1;
case VLVT_UINT8: return (*(reinterpret_cast<CData*>(datap)) >> lsb) & 1;
case VLVT_UINT16: return (*(reinterpret_cast<SData*>(datap)) >> lsb) & 1;
case VLVT_UINT32: return (*(reinterpret_cast<IData*>(datap)) >> lsb) & 1;
case VLVT_UINT64: return (*(reinterpret_cast<QData*>(datap)) >> static_cast<QData>(lsb)) & VL_ULL(1);
case VLVT_UINT64:
return (*(reinterpret_cast<QData*>(datap)) >> static_cast<QData>(lsb)) & VL_ULL(1);
case VLVT_WDATA: {
WDataOutP wdatap = (reinterpret_cast<WDataOutP>(datap));
return VL_BITRSHIFT_W(wdatap, lsb) & 1;
}
default:
_VL_SVDPI_WARN("%%Warning: DPI svOpenArrayHandle function unsupported datatype (%d).\n", varp->vltype());
_VL_SVDPI_WARN("%%Warning: DPI svOpenArrayHandle function unsupported datatype (%d).\n",
varp->vltype());
return 0;
}
}
/// Update simulator open array from bit
static void _vl_svPutBitArrElem(const svOpenArrayHandle d, svBit value,
int nargs, int indx1, int indx2, int indx3, int indx4) VL_MT_SAFE {
static void _vl_svPutBitArrElem(const svOpenArrayHandle d, svBit value, int nargs, int indx1,
int indx2, int indx3, int indx4) VL_MT_SAFE {
// One extra index supported, as need bit number
value &= 1; // Make sure clean
const VerilatedDpiOpenVar* varp = _vl_openhandle_varp(d);
void* datap;
int lsb;
if (varp->packed().elements()) {
datap = _vl_sv_adjusted_datap(varp, nargs-1, indx1, indx2, indx3);
lsb = _vl_sv_adjusted_bit(varp, ((nargs==1) ? indx1
: (nargs==2) ? indx2
: (nargs==3) ? indx3
: indx4));
datap = _vl_sv_adjusted_datap(varp, nargs - 1, indx1, indx2, indx3);
lsb = _vl_sv_adjusted_bit(
varp, ((nargs == 1) ? indx1 : (nargs == 2) ? indx2 : (nargs == 3) ? indx3 : indx4));
} else {
datap = _vl_sv_adjusted_datap(varp, nargs, indx1, indx2, indx3);
lsb = 0;
}
if (VL_UNLIKELY(!datap)) return;
switch (varp->vltype()) {
case VLVT_UINT8: VL_ASSIGNBIT_II(-1, lsb, *(reinterpret_cast<CData*>(datap)), value); return;
case VLVT_UINT8: VL_ASSIGNBIT_II(-1, lsb, *(reinterpret_cast<CData*>(datap)), value); return;
case VLVT_UINT16: VL_ASSIGNBIT_II(-1, lsb, *(reinterpret_cast<SData*>(datap)), value); return;
case VLVT_UINT32: VL_ASSIGNBIT_II(-1, lsb, *(reinterpret_cast<IData*>(datap)), value); return;
case VLVT_UINT64: VL_ASSIGNBIT_QI(-1, lsb, *(reinterpret_cast<QData*>(datap)), value); return;
case VLVT_WDATA: VL_ASSIGNBIT_WI(-1, lsb, (reinterpret_cast<WDataOutP>(datap)), value); return;
case VLVT_WDATA: VL_ASSIGNBIT_WI(-1, lsb, (reinterpret_cast<WDataOutP>(datap)), value); return;
default:
_VL_SVDPI_WARN("%%Warning: DPI svOpenArrayHandle function unsupported datatype (%d).\n", varp->vltype());
_VL_SVDPI_WARN("%%Warning: DPI svOpenArrayHandle function unsupported datatype (%d).\n",
varp->vltype());
return;
}
}
@ -470,10 +468,17 @@ void* svGetArrElemPtr(const svOpenArrayHandle h, int indx1, ...) {
// va_arg is a macro, so need temporaries as used below
switch (varp->udims()) {
case 1: datap = _vl_svGetArrElemPtr(h, 1, indx1, 0, 0); break;
case 2: { int indx2=va_arg(ap,int);
datap = _vl_svGetArrElemPtr(h, 2, indx1, indx2, 0); break; }
case 3: { int indx2=va_arg(ap,int); int indx3=va_arg(ap,int);
datap = _vl_svGetArrElemPtr(h, 3, indx1, indx2, indx3); break; }
case 2: {
int indx2 = va_arg(ap, int);
datap = _vl_svGetArrElemPtr(h, 2, indx1, indx2, 0);
break;
}
case 3: {
int indx2 = va_arg(ap, int);
int indx3 = va_arg(ap, int);
datap = _vl_svGetArrElemPtr(h, 3, indx1, indx2, indx3);
break;
}
default: datap = _vl_svGetArrElemPtr(h, -1, 0, 0, 0); break; // Will error
}
va_end(ap);
@ -489,116 +494,134 @@ void* svGetArrElemPtr3(const svOpenArrayHandle h, int indx1, int indx2, int indx
return _vl_svGetArrElemPtr(h, 3, indx1, indx2, indx3);
}
void svPutBitArrElemVecVal(const svOpenArrayHandle d, const svBitVecVal* s,
int indx1, ...) {
void svPutBitArrElemVecVal(const svOpenArrayHandle d, const svBitVecVal* s, int indx1, ...) {
const VerilatedDpiOpenVar* varp = _vl_openhandle_varp(d);
va_list ap;
va_start(ap, indx1);
switch (varp->udims()) {
case 1: _vl_svPutBitArrElemVecVal(d, s, 1, indx1, 0, 0); break;
case 2: { int indx2=va_arg(ap,int);
_vl_svPutBitArrElemVecVal(d, s, 2, indx1, indx2, 0); break; }
case 3: { int indx2=va_arg(ap,int); int indx3=va_arg(ap,int);
_vl_svPutBitArrElemVecVal(d, s, 3, indx1, indx2, indx3); break; }
case 2: {
int indx2 = va_arg(ap, int);
_vl_svPutBitArrElemVecVal(d, s, 2, indx1, indx2, 0);
break;
}
case 3: {
int indx2 = va_arg(ap, int);
int indx3 = va_arg(ap, int);
_vl_svPutBitArrElemVecVal(d, s, 3, indx1, indx2, indx3);
break;
}
default: _vl_svPutBitArrElemVecVal(d, s, -1, 0, 0, 0); break; // Will error
}
va_end(ap);
}
void svPutBitArrElem1VecVal(const svOpenArrayHandle d, const svBitVecVal* s,
int indx1) {
void svPutBitArrElem1VecVal(const svOpenArrayHandle d, const svBitVecVal* s, int indx1) {
_vl_svPutBitArrElemVecVal(d, s, 1, indx1, 0, 0);
}
void svPutBitArrElem2VecVal(const svOpenArrayHandle d, const svBitVecVal* s,
int indx1, int indx2) {
void svPutBitArrElem2VecVal(const svOpenArrayHandle d, const svBitVecVal* s, int indx1,
int indx2) {
_vl_svPutBitArrElemVecVal(d, s, 2, indx1, indx2, 0);
}
void svPutBitArrElem3VecVal(const svOpenArrayHandle d, const svBitVecVal* s,
int indx1, int indx2, int indx3) {
void svPutBitArrElem3VecVal(const svOpenArrayHandle d, const svBitVecVal* s, int indx1, int indx2,
int indx3) {
_vl_svPutBitArrElemVecVal(d, s, 3, indx1, indx2, indx3);
}
void svPutLogicArrElemVecVal(const svOpenArrayHandle d, const svLogicVecVal* s,
int indx1, ...) {
void svPutLogicArrElemVecVal(const svOpenArrayHandle d, const svLogicVecVal* s, int indx1, ...) {
const VerilatedDpiOpenVar* varp = _vl_openhandle_varp(d);
va_list ap;
va_start(ap, indx1);
switch (varp->udims()) {
case 1: _vl_svPutLogicArrElemVecVal(d, s, 1, indx1, 0, 0); break;
case 2: { int indx2=va_arg(ap,int);
_vl_svPutLogicArrElemVecVal(d, s, 2, indx1, indx2, 0); break; }
case 3: { int indx2=va_arg(ap,int); int indx3=va_arg(ap,int);
_vl_svPutLogicArrElemVecVal(d, s, 3, indx1, indx2, indx3); break; }
case 2: {
int indx2 = va_arg(ap, int);
_vl_svPutLogicArrElemVecVal(d, s, 2, indx1, indx2, 0);
break;
}
case 3: {
int indx2 = va_arg(ap, int);
int indx3 = va_arg(ap, int);
_vl_svPutLogicArrElemVecVal(d, s, 3, indx1, indx2, indx3);
break;
}
default: _vl_svPutLogicArrElemVecVal(d, s, -1, 0, 0, 0); break; // Will error
}
va_end(ap);
}
void svPutLogicArrElem1VecVal(const svOpenArrayHandle d, const svLogicVecVal* s,
int indx1) {
void svPutLogicArrElem1VecVal(const svOpenArrayHandle d, const svLogicVecVal* s, int indx1) {
_vl_svPutLogicArrElemVecVal(d, s, 1, indx1, 0, 0);
}
void svPutLogicArrElem2VecVal(const svOpenArrayHandle d, const svLogicVecVal* s,
int indx1, int indx2) {
void svPutLogicArrElem2VecVal(const svOpenArrayHandle d, const svLogicVecVal* s, int indx1,
int indx2) {
_vl_svPutLogicArrElemVecVal(d, s, 2, indx1, indx2, 0);
}
void svPutLogicArrElem3VecVal(const svOpenArrayHandle d, const svLogicVecVal* s,
int indx1, int indx2, int indx3) {
void svPutLogicArrElem3VecVal(const svOpenArrayHandle d, const svLogicVecVal* s, int indx1,
int indx2, int indx3) {
_vl_svPutLogicArrElemVecVal(d, s, 3, indx1, indx2, indx3);
}
//======================================================================
// From simulator storage into user space
void svGetBitArrElemVecVal(svBitVecVal* d, const svOpenArrayHandle s,
int indx1, ...) {
void svGetBitArrElemVecVal(svBitVecVal* d, const svOpenArrayHandle s, int indx1, ...) {
const VerilatedDpiOpenVar* varp = _vl_openhandle_varp(s);
va_list ap;
va_start(ap, indx1);
switch (varp->udims()) {
case 1: _vl_svGetBitArrElemVecVal(d, s, 1, indx1, 0, 0); break;
case 2: { int indx2=va_arg(ap,int);
_vl_svGetBitArrElemVecVal(d, s, 2, indx1, indx2, 0); break; }
case 3: { int indx2=va_arg(ap,int); int indx3=va_arg(ap,int);
_vl_svGetBitArrElemVecVal(d, s, 3, indx1, indx2, indx3); break; }
case 2: {
int indx2 = va_arg(ap, int);
_vl_svGetBitArrElemVecVal(d, s, 2, indx1, indx2, 0);
break;
}
case 3: {
int indx2 = va_arg(ap, int);
int indx3 = va_arg(ap, int);
_vl_svGetBitArrElemVecVal(d, s, 3, indx1, indx2, indx3);
break;
}
default: _vl_svGetBitArrElemVecVal(d, s, -1, 0, 0, 0); break; // Will error
}
va_end(ap);
}
void svGetBitArrElem1VecVal(svBitVecVal* d, const svOpenArrayHandle s,
int indx1) {
void svGetBitArrElem1VecVal(svBitVecVal* d, const svOpenArrayHandle s, int indx1) {
_vl_svGetBitArrElemVecVal(d, s, 1, indx1, 0, 0);
}
void svGetBitArrElem2VecVal(svBitVecVal* d, const svOpenArrayHandle s,
int indx1, int indx2) {
void svGetBitArrElem2VecVal(svBitVecVal* d, const svOpenArrayHandle s, int indx1, int indx2) {
_vl_svGetBitArrElemVecVal(d, s, 2, indx1, indx2, 0);
}
void svGetBitArrElem3VecVal(svBitVecVal* d, const svOpenArrayHandle s,
int indx1, int indx2, int indx3) {
void svGetBitArrElem3VecVal(svBitVecVal* d, const svOpenArrayHandle s, int indx1, int indx2,
int indx3) {
_vl_svGetBitArrElemVecVal(d, s, 3, indx1, indx2, indx3);
}
void svGetLogicArrElemVecVal(svLogicVecVal* d, const svOpenArrayHandle s,
int indx1, ...) {
void svGetLogicArrElemVecVal(svLogicVecVal* d, const svOpenArrayHandle s, int indx1, ...) {
const VerilatedDpiOpenVar* varp = _vl_openhandle_varp(s);
va_list ap;
va_start(ap, indx1);
switch (varp->udims()) {
case 1: _vl_svGetLogicArrElemVecVal(d, s, 1, indx1, 0, 0); break;
case 2: { int indx2=va_arg(ap,int);
_vl_svGetLogicArrElemVecVal(d, s, 2, indx1, indx2, 0); break; }
case 3: { int indx2=va_arg(ap,int); int indx3=va_arg(ap,int);
_vl_svGetLogicArrElemVecVal(d, s, 3, indx1, indx2, indx3); break; }
case 2: {
int indx2 = va_arg(ap, int);
_vl_svGetLogicArrElemVecVal(d, s, 2, indx1, indx2, 0);
break;
}
case 3: {
int indx2 = va_arg(ap, int);
int indx3 = va_arg(ap, int);
_vl_svGetLogicArrElemVecVal(d, s, 3, indx1, indx2, indx3);
break;
}
default: _vl_svGetLogicArrElemVecVal(d, s, -1, 0, 0, 0); break; // Will error
}
va_end(ap);
}
void svGetLogicArrElem1VecVal(svLogicVecVal* d, const svOpenArrayHandle s,
int indx1) {
void svGetLogicArrElem1VecVal(svLogicVecVal* d, const svOpenArrayHandle s, int indx1) {
_vl_svGetLogicArrElemVecVal(d, s, 1, indx1, 0, 0);
}
void svGetLogicArrElem2VecVal(svLogicVecVal* d, const svOpenArrayHandle s,
int indx1, int indx2) {
void svGetLogicArrElem2VecVal(svLogicVecVal* d, const svOpenArrayHandle s, int indx1, int indx2) {
_vl_svGetLogicArrElemVecVal(d, s, 2, indx1, indx2, 0);
}
void svGetLogicArrElem3VecVal(svLogicVecVal* d, const svOpenArrayHandle s,
int indx1, int indx2, int indx3) {
void svGetLogicArrElem3VecVal(svLogicVecVal* d, const svOpenArrayHandle s, int indx1, int indx2,
int indx3) {
_vl_svGetLogicArrElemVecVal(d, s, 3, indx1, indx2, indx3);
}
@ -609,12 +632,24 @@ svBit svGetBitArrElem(const svOpenArrayHandle s, int indx1, ...) {
va_start(ap, indx1);
switch (varp->udims()) {
case 1: out = _vl_svGetBitArrElem(s, 1, indx1, 0, 0, 0); break;
case 2: { int indx2=va_arg(ap,int);
out = _vl_svGetBitArrElem(s, 2, indx1, indx2, 0, 0); break; }
case 3: { int indx2=va_arg(ap,int); int indx3=va_arg(ap,int);
out = _vl_svGetBitArrElem(s, 3, indx1, indx2, indx3, 0); break; }
case 4: { int indx2=va_arg(ap,int); int indx3=va_arg(ap,int); int indx4=va_arg(ap,int);
out = _vl_svGetBitArrElem(s, 4, indx1, indx2, indx3, indx4); break; }
case 2: {
int indx2 = va_arg(ap, int);
out = _vl_svGetBitArrElem(s, 2, indx1, indx2, 0, 0);
break;
}
case 3: {
int indx2 = va_arg(ap, int);
int indx3 = va_arg(ap, int);
out = _vl_svGetBitArrElem(s, 3, indx1, indx2, indx3, 0);
break;
}
case 4: {
int indx2 = va_arg(ap, int);
int indx3 = va_arg(ap, int);
int indx4 = va_arg(ap, int);
out = _vl_svGetBitArrElem(s, 4, indx1, indx2, indx3, indx4);
break;
}
default: out = _vl_svGetBitArrElem(s, -1, 0, 0, 0, 0); break; // Will error
}
va_end(ap);
@ -637,12 +672,24 @@ svLogic svGetLogicArrElem(const svOpenArrayHandle s, int indx1, ...) {
va_start(ap, indx1);
switch (varp->udims()) {
case 1: out = _vl_svGetBitArrElem(s, 1, indx1, 0, 0, 0); break;
case 2: { int indx2=va_arg(ap,int);
out = _vl_svGetBitArrElem(s, 2, indx1, indx2, 0, 0); break; }
case 3: { int indx2=va_arg(ap,int); int indx3=va_arg(ap,int);
out = _vl_svGetBitArrElem(s, 3, indx1, indx2, indx3, 0); break; }
case 4: { int indx2=va_arg(ap,int); int indx3=va_arg(ap,int); int indx4=va_arg(ap,int);
out = _vl_svGetBitArrElem(s, 4, indx1, indx2, indx3, indx4); break; }
case 2: {
int indx2 = va_arg(ap, int);
out = _vl_svGetBitArrElem(s, 2, indx1, indx2, 0, 0);
break;
}
case 3: {
int indx2 = va_arg(ap, int);
int indx3 = va_arg(ap, int);
out = _vl_svGetBitArrElem(s, 3, indx1, indx2, indx3, 0);
break;
}
case 4: {
int indx2 = va_arg(ap, int);
int indx3 = va_arg(ap, int);
int indx4 = va_arg(ap, int);
out = _vl_svGetBitArrElem(s, 4, indx1, indx2, indx3, indx4);
break;
}
default: out = _vl_svGetBitArrElem(s, -1, 0, 0, 0, 0); break; // Will error
}
va_end(ap);
@ -667,12 +714,24 @@ void svPutBitArrElem(const svOpenArrayHandle d, svBit value, int indx1, ...) {
va_start(ap, indx1);
switch (varp->udims()) {
case 1: _vl_svPutBitArrElem(d, value, 1, indx1, 0, 0, 0); break;
case 2: { int indx2=va_arg(ap,int);
_vl_svPutBitArrElem(d, value, 2, indx1, indx2, 0, 0); break; }
case 3: { int indx2=va_arg(ap,int); int indx3=va_arg(ap,int);
_vl_svPutBitArrElem(d, value, 3, indx1, indx2, indx3, 0); break; }
case 4: { int indx2=va_arg(ap,int); int indx3=va_arg(ap,int); int indx4=va_arg(ap,int);
_vl_svPutBitArrElem(d, value, 4, indx1, indx2, indx3, indx4); break; }
case 2: {
int indx2 = va_arg(ap, int);
_vl_svPutBitArrElem(d, value, 2, indx1, indx2, 0, 0);
break;
}
case 3: {
int indx2 = va_arg(ap, int);
int indx3 = va_arg(ap, int);
_vl_svPutBitArrElem(d, value, 3, indx1, indx2, indx3, 0);
break;
}
case 4: {
int indx2 = va_arg(ap, int);
int indx3 = va_arg(ap, int);
int indx4 = va_arg(ap, int);
_vl_svPutBitArrElem(d, value, 4, indx1, indx2, indx3, indx4);
break;
}
default: _vl_svPutBitArrElem(d, value, -1, 0, 0, 0, 0); break; // Will error
}
va_end(ap);
@ -693,12 +752,24 @@ void svPutLogicArrElem(const svOpenArrayHandle d, svLogic value, int indx1, ...)
va_start(ap, indx1);
switch (varp->udims()) {
case 1: _vl_svPutBitArrElem(d, value, 1, indx1, 0, 0, 0); break;
case 2: { int indx2=va_arg(ap,int);
_vl_svPutBitArrElem(d, value, 2, indx1, indx2, 0, 0); break; }
case 3: { int indx2=va_arg(ap,int); int indx3=va_arg(ap,int);
_vl_svPutBitArrElem(d, value, 3, indx1, indx2, indx3, 0); break; }
case 4: { int indx2=va_arg(ap,int); int indx3=va_arg(ap,int); int indx4=va_arg(ap,int);
_vl_svPutBitArrElem(d, value, 4, indx1, indx2, indx3, indx4); break; }
case 2: {
int indx2 = va_arg(ap, int);
_vl_svPutBitArrElem(d, value, 2, indx1, indx2, 0, 0);
break;
}
case 3: {
int indx2 = va_arg(ap, int);
int indx3 = va_arg(ap, int);
_vl_svPutBitArrElem(d, value, 3, indx1, indx2, indx3, 0);
break;
}
case 4: {
int indx2 = va_arg(ap, int);
int indx3 = va_arg(ap, int);
int indx4 = va_arg(ap, int);
_vl_svPutBitArrElem(d, value, 4, indx1, indx2, indx3, indx4);
break;
}
default: _vl_svPutBitArrElem(d, value, -1, 0, 0, 0, 0); break; // Will error
}
va_end(ap);
@ -707,13 +778,12 @@ void svPutLogicArrElem1(const svOpenArrayHandle d, svLogic value, int indx1) {
// Verilator doesn't support X/Z so can just call Bit version
svPutBitArrElem1(d, value, indx1);
}
void svPutLogicArrElem2(const svOpenArrayHandle d, svLogic value,
int indx1, int indx2) {
void svPutLogicArrElem2(const svOpenArrayHandle d, svLogic value, int indx1, int indx2) {
// Verilator doesn't support X/Z so can just call Bit version
svPutBitArrElem2(d, value, indx1, indx2);
}
void svPutLogicArrElem3(const svOpenArrayHandle d, svLogic value,
int indx1, int indx2, int indx3) {
void svPutLogicArrElem3(const svOpenArrayHandle d, svLogic value, int indx1, int indx2,
int indx3) {
// Verilator doesn't support X/Z so can just call Bit version
svPutBitArrElem3(d, value, indx1, indx2, indx3);
}
@ -722,7 +792,10 @@ void svPutLogicArrElem3(const svOpenArrayHandle d, svLogic value,
// Functions for working with DPI context
svScope svGetScope() {
if (VL_UNLIKELY(!Verilated::dpiInContext())) { _VL_SVDPI_CONTEXT_WARN(); return NULL; }
if (VL_UNLIKELY(!Verilated::dpiInContext())) {
_VL_SVDPI_CONTEXT_WARN();
return NULL;
}
// NOLINTNEXTLINE(google-readability-casting)
return (svScope)(Verilated::dpiScope());
}
@ -746,16 +819,19 @@ svScope svGetScopeFromName(const char* scopeName) {
}
int svPutUserData(const svScope scope, void* userKey, void* userData) {
VerilatedImp::userInsert(scope,userKey,userData);
VerilatedImp::userInsert(scope, userKey, userData);
return 0;
}
void* svGetUserData(const svScope scope, void* userKey) {
return VerilatedImp::userFind(scope,userKey);
return VerilatedImp::userFind(scope, userKey);
}
int svGetCallerInfo(const char** fileNamepp, int *lineNumberp) {
if (VL_UNLIKELY(!Verilated::dpiInContext())) { _VL_SVDPI_CONTEXT_WARN(); return false; }
int svGetCallerInfo(const char** fileNamepp, int* lineNumberp) {
if (VL_UNLIKELY(!Verilated::dpiInContext())) {
_VL_SVDPI_CONTEXT_WARN();
return false;
}
if (VL_LIKELY(fileNamepp)) *fileNamepp = Verilated::dpiFilenamep(); // thread local
if (VL_LIKELY(lineNumberp)) *lineNumberp = Verilated::dpiLineno(); // thread local
return true;

View File

@ -35,29 +35,21 @@
/// Convert svBitVecVal to Verilator internal data
static inline void VL_SET_W_SVBV(int obits, WDataOutP owp, const svBitVecVal* lwp) VL_MT_SAFE {
int words = VL_WORDS_I(obits);
for (int i = 0; i < words - 1; ++i) {
owp[i] = lwp[i];
}
for (int i = 0; i < words - 1; ++i) owp[i] = lwp[i];
owp[words - 1] = lwp[words - 1] & VL_MASK_I(obits);
}
static inline QData VL_SET_Q_SVBV(const svBitVecVal* lwp) VL_MT_SAFE {
return _VL_SET_QII(lwp[1], lwp[0]);
}
static inline IData VL_SET_I_SVBV(const svBitVecVal* lwp) VL_MT_SAFE {
return lwp[0];
}
static inline IData VL_SET_I_SVBV(const svBitVecVal* lwp) VL_MT_SAFE { return lwp[0]; }
/// Convert Verilator internal data to svBitVecVal
static inline void VL_SET_SVBV_W(int obits, svBitVecVal* owp, WDataInP lwp) VL_MT_SAFE {
int words = VL_WORDS_I(obits);
for (int i = 0; i < words - 1; ++i) {
owp[i] = lwp[i];
}
for (int i = 0; i < words - 1; ++i) owp[i] = lwp[i];
owp[words - 1] = lwp[words - 1] & VL_MASK_I(obits);
}
static inline void VL_SET_SVBV_I(int, svBitVecVal* owp, IData ld) VL_MT_SAFE {
owp[0] = ld;
}
static inline void VL_SET_SVBV_I(int, svBitVecVal* owp, IData ld) VL_MT_SAFE { owp[0] = ld; }
static inline void VL_SET_SVBV_Q(int, svBitVecVal* owp, QData ld) VL_MT_SAFE {
VL_SET_WQ(owp, ld);
}
@ -66,28 +58,20 @@ static inline void VL_SET_SVBV_Q(int, svBitVecVal* owp, QData ld) VL_MT_SAFE {
/// Note these functions ignore X/Z in svLogicVecVal
static inline void VL_SET_W_SVLV(int obits, WDataOutP owp, const svLogicVecVal* lwp) VL_MT_SAFE {
int words = VL_WORDS_I(obits);
for (int i = 0; i < words - 1; ++i) {
owp[i] = lwp[i].aval;
}
for (int i = 0; i < words - 1; ++i) owp[i] = lwp[i].aval;
owp[words - 1] = lwp[words - 1].aval & VL_MASK_I(obits);
}
static inline QData VL_SET_Q_SVLV(const svLogicVecVal* lwp) VL_MT_SAFE {
return _VL_SET_QII(lwp[1].aval, lwp[0].aval);
}
static inline IData VL_SET_I_SVLV(const svLogicVecVal* lwp) VL_MT_SAFE {
return lwp[0].aval;
}
static inline IData VL_SET_I_SVLV(const svLogicVecVal* lwp) VL_MT_SAFE { return lwp[0].aval; }
/// Convert Verilator internal data to svLogicVecVal
/// Note these functions never create X/Z in svLogicVecVal
static inline void VL_SET_SVLV_W(int obits, svLogicVecVal* owp, WDataInP lwp) VL_MT_SAFE {
int words = VL_WORDS_I(obits);
for (int i = 0; i < words; ++i) {
owp[i].bval = 0;
}
for (int i = 0; i < words - 1; ++i) {
owp[i].aval = lwp[i];
}
for (int i = 0; i < words; ++i) owp[i].bval = 0;
for (int i = 0; i < words - 1; ++i) owp[i].aval = lwp[i];
owp[words - 1].aval = lwp[words - 1] & VL_MASK_I(obits);
}
static inline void VL_SET_SVLV_I(int, svLogicVecVal* owp, IData ld) VL_MT_SAFE {

View File

@ -379,11 +379,13 @@ template <class T_Value> std::string VL_TO_STRING(const VlQueue<T_Value>& obj) {
// be protected by other means
//
// clang-format off
#if (defined(_MSC_VER) && _MSC_VER >= 1900) || (__cplusplus >= 201103L)
# define VlClassRef std::shared_ptr
#else
# define VlClassRef VlClassRef__SystemVerilog_class_support_requires_a_C11_or_newer_compiler
#endif
// clang-format on
template <class T> // T typically of type VlClassRef<x>
inline T VL_NULL_CHECK(T t, const char* filename, int linenum) {
@ -412,9 +414,7 @@ inline std::string VL_CONCATN_NNN(const std::string& lhs, const std::string& rhs
inline std::string VL_REPLICATEN_NNQ(int, int, int, const std::string& lhs, IData rep) VL_PURE {
std::string out;
out.reserve(lhs.length() * rep);
for (unsigned times = 0; times < rep; ++times) {
out += lhs;
}
for (unsigned times = 0; times < rep; ++times) out += lhs;
return out;
}
inline std::string VL_REPLICATEN_NNI(int obits, int lbits, int rbits, const std::string& lhs,

View File

@ -19,6 +19,7 @@
#ifndef _VERILATED_IMP_H_
#define _VERILATED_IMP_H_ 1 ///< Header Guard
// clang-format off
#if !defined(_VERILATED_CPP_) && !defined(_VERILATED_DPI_CPP_) && !defined(_VERILATED_VPI_CPP_)
# error "verilated_imp.h only to be included by verilated*.cpp internals"
#endif
@ -35,6 +36,7 @@
# include <functional>
# include <queue>
#endif
// clang-format on
class VerilatedScope;
@ -47,9 +49,11 @@ class VerilatedMsg {
public:
// TYPES
struct Cmp {
bool operator() (const VerilatedMsg& a, const VerilatedMsg& b) const {
return a.mtaskId() < b.mtaskId(); }
bool operator()(const VerilatedMsg& a, const VerilatedMsg& b) const {
return a.mtaskId() < b.mtaskId();
}
};
private:
// MEMBERS
vluint32_t m_mtaskId; ///< MTask that did enqueue
@ -86,6 +90,7 @@ public:
private:
VL_UNCOPYABLE(VerilatedEvalMsgQueue);
public:
// METHODS
//// Add message to queue (called by producer)
@ -122,6 +127,7 @@ public:
/// Each thread has a local queue to build up messages until the end of the eval() call
class VerilatedThreadMsgQueue {
std::queue<VerilatedMsg> m_queue;
public:
// CONSTRUCTORS
VerilatedThreadMsgQueue() {}
@ -129,6 +135,7 @@ public:
// The only call of this with a non-empty queue is a fatal error.
// So this does not flush the queue, as the destination queue is not known to this class.
}
private:
VL_UNCOPYABLE(VerilatedThreadMsgQueue);
// METHODS
@ -136,6 +143,7 @@ private:
static VL_THREAD_LOCAL VerilatedThreadMsgQueue t_s;
return t_s;
}
public:
/// Add message to queue, called by producer
static void post(const VerilatedMsg& msg) VL_MT_SAFE {
@ -176,28 +184,33 @@ class VerilatedImp {
// Nothing here is save-restored; users expected to re-register appropriately
VerilatedMutex m_argMutex; ///< Protect m_argVec, m_argVecLoaded
ArgVec m_argVec VL_GUARDED_BY(m_argMutex); ///< Argument list (NOT save-restored, may want different results)
bool m_argVecLoaded VL_GUARDED_BY(m_argMutex); ///< Ever loaded argument list
VerilatedMutex m_argMutex; ///< Protect m_argVec, m_argVecLoaded
/// Argument list (NOT save-restored, may want different results)
ArgVec m_argVec VL_GUARDED_BY(m_argMutex);
bool m_argVecLoaded VL_GUARDED_BY(m_argMutex); ///< Ever loaded argument list
VerilatedMutex m_userMapMutex; ///< Protect m_userMap
UserMap m_userMap VL_GUARDED_BY(m_userMapMutex); ///< Map of <(scope,userkey), userData>
VerilatedMutex m_userMapMutex; ///< Protect m_userMap
UserMap m_userMap VL_GUARDED_BY(m_userMapMutex); ///< Map of <(scope,userkey), userData>
VerilatedMutex m_nameMutex; ///< Protect m_nameMap
VerilatedScopeNameMap m_nameMap VL_GUARDED_BY(m_nameMutex); ///< Map of <scope_name, scope pointer>
VerilatedMutex m_nameMutex; ///< Protect m_nameMap
/// Map of <scope_name, scope pointer>
VerilatedScopeNameMap m_nameMap VL_GUARDED_BY(m_nameMutex);
VerilatedMutex m_hierMapMutex; ///< Protect m_hierMap
VerilatedHierarchyMap m_hierMap VL_GUARDED_BY(m_hierMapMutex); ///< Map the represents scope hierarchy
VerilatedMutex m_hierMapMutex; ///< Protect m_hierMap
/// Map the represents scope hierarchy
VerilatedHierarchyMap m_hierMap VL_GUARDED_BY(m_hierMapMutex);
// Slow - somewhat static:
VerilatedMutex m_exportMutex; ///< Protect m_nameMap
ExportNameMap m_exportMap VL_GUARDED_BY(m_exportMutex); ///< Map of <export_func_proto, func number>
int m_exportNext VL_GUARDED_BY(m_exportMutex); ///< Next export funcnum
VerilatedMutex m_exportMutex; ///< Protect m_nameMap
/// Map of <export_func_proto, func number>
ExportNameMap m_exportMap VL_GUARDED_BY(m_exportMutex);
int m_exportNext VL_GUARDED_BY(m_exportMutex); ///< Next export funcnum
// File I/O
VerilatedMutex m_fdMutex; ///< Protect m_fdps, m_fdFree
std::vector<FILE*> m_fdps VL_GUARDED_BY(m_fdMutex); ///< File descriptors
std::deque<IData> m_fdFree VL_GUARDED_BY(m_fdMutex); ///< List of free descriptors (SLOW - FOPEN/CLOSE only)
VerilatedMutex m_fdMutex; ///< Protect m_fdps, m_fdFree
std::vector<FILE*> m_fdps VL_GUARDED_BY(m_fdMutex); ///< File descriptors
/// List of free descriptors (SLOW - FOPEN/CLOSE only)
std::deque<IData> m_fdFree VL_GUARDED_BY(m_fdMutex);
public: // But only for verilated*.cpp
// CONSTRUCTORS
@ -210,8 +223,10 @@ public: // But only for verilated*.cpp
m_fdps[2] = stderr;
}
~VerilatedImp() {}
private:
VL_UNCOPYABLE(VerilatedImp);
public:
// METHODS - debug
static void internalsDump() VL_MT_SAFE;
@ -238,11 +253,12 @@ public:
}
return "";
}
private:
static void commandArgsAddGuts(int argc, const char** argv) VL_REQUIRES(s_s.m_argMutex);
static void commandArgVl(const std::string& arg);
static bool commandArgVlValue(const std::string& arg,
const std::string& prefix, std::string& valuer);
static bool commandArgVlValue(const std::string& arg, const std::string& prefix,
std::string& valuer);
public:
// METHODS - user scope tracking
@ -252,16 +268,19 @@ public:
static inline void userInsert(const void* scopep, void* userKey, void* userData) VL_MT_SAFE {
VerilatedLockGuard lock(s_s.m_userMapMutex);
UserMap::iterator it = s_s.m_userMap.find(std::make_pair(scopep, userKey));
if (it != s_s.m_userMap.end()) it->second = userData;
// When we support VL_THREADs, we need a lock around this insert, as it's runtime
else s_s.m_userMap.insert(it, std::make_pair(std::make_pair(scopep, userKey), userData));
if (it != s_s.m_userMap.end()) {
it->second = userData;
} else {
s_s.m_userMap.insert(it, std::make_pair(std::make_pair(scopep, userKey), userData));
}
}
static inline void* userFind(const void* scopep, void* userKey) VL_MT_SAFE {
VerilatedLockGuard lock(s_s.m_userMapMutex);
UserMap::const_iterator it=s_s.m_userMap.find(std::make_pair(scopep, userKey));
if (VL_LIKELY(it != s_s.m_userMap.end())) return it->second;
else return NULL;
UserMap::const_iterator it = s_s.m_userMap.find(std::make_pair(scopep, userKey));
if (VL_UNLIKELY(it == s_s.m_userMap.end())) return NULL;
return it->second;
}
private:
/// Symbol table destruction cleans up the entries for each scope.
static void userEraseScope(const VerilatedScope* scopep) VL_MT_SAFE {
@ -278,10 +297,13 @@ private:
static void userDump() VL_MT_SAFE {
VerilatedLockGuard lock(s_s.m_userMapMutex); // Avoid it changing in middle of dump
bool first = true;
for (UserMap::const_iterator it=s_s.m_userMap.begin(); it!=s_s.m_userMap.end(); ++it) {
if (first) { VL_PRINTF_MT(" userDump:\n"); first=false; }
VL_PRINTF_MT(" DPI_USER_DATA scope %p key %p: %p\n",
it->first.first, it->first.second, it->second);
for (UserMap::const_iterator it = s_s.m_userMap.begin(); it != s_s.m_userMap.end(); ++it) {
if (first) {
VL_PRINTF_MT(" userDump:\n");
first = false;
}
VL_PRINTF_MT(" DPI_USER_DATA scope %p key %p: %p\n", it->first.first,
it->first.second, it->second);
}
}
@ -298,9 +320,9 @@ public: // But only for verilated*.cpp
static inline const VerilatedScope* scopeFind(const char* namep) VL_MT_SAFE {
VerilatedLockGuard lock(s_s.m_nameMutex);
// If too slow, can assume this is only VL_MT_SAFE_POSINIT
VerilatedScopeNameMap::const_iterator it=s_s.m_nameMap.find(namep);
if (VL_LIKELY(it != s_s.m_nameMap.end())) return it->second;
else return NULL;
VerilatedScopeNameMap::const_iterator it = s_s.m_nameMap.find(namep);
if (VL_UNLIKELY(it == s_s.m_nameMap.end())) return NULL;
return it->second;
}
static void scopeErase(const VerilatedScope* scopep) VL_MT_SAFE {
// Slow ok - called once/scope at destruction
@ -360,8 +382,8 @@ public: // But only for verilated*.cpp
VerilatedLockGuard lock(s_s.m_exportMutex);
ExportNameMap::const_iterator it = s_s.m_exportMap.find(namep);
if (VL_LIKELY(it != s_s.m_exportMap.end())) return it->second;
std::string msg = (std::string("%Error: Testbench C called ")+namep
+" but no such DPI export function name exists in ANY model");
std::string msg = (std::string("%Error: Testbench C called ") + namep
+ " but no such DPI export function name exists in ANY model");
VL_FATAL_MT("unknown", 0, "", msg.c_str());
return -1;
}
@ -377,9 +399,12 @@ public: // But only for verilated*.cpp
static void exportsDump() VL_MT_SAFE {
VerilatedLockGuard lock(s_s.m_exportMutex);
bool first = true;
for (ExportNameMap::const_iterator it=s_s.m_exportMap.begin();
it!=s_s.m_exportMap.end(); ++it) {
if (first) { VL_PRINTF_MT(" exportDump:\n"); first=false; }
for (ExportNameMap::const_iterator it = s_s.m_exportMap.begin();
it != s_s.m_exportMap.end(); ++it) {
if (first) {
VL_PRINTF_MT(" exportDump:\n");
first = false;
}
VL_PRINTF_MT(" DPI_EXPORT_NAME %05d: %s\n", it->second, it->first);
}
}
@ -395,12 +420,15 @@ public: // But only for verilated*.cpp
if (s_s.m_fdFree.empty()) {
// Need to create more space in m_fdps and m_fdFree
size_t start = s_s.m_fdps.size();
s_s.m_fdps.resize(start*2);
for (size_t i=start; i<start*2; ++i) s_s.m_fdFree.push_back(static_cast<IData>(i));
s_s.m_fdps.resize(start * 2);
for (size_t i = start; i < start * 2; ++i) {
s_s.m_fdFree.push_back(static_cast<IData>(i));
}
}
IData idx = s_s.m_fdFree.back(); s_s.m_fdFree.pop_back();
IData idx = s_s.m_fdFree.back();
s_s.m_fdFree.pop_back();
s_s.m_fdps[idx] = fp;
return (idx | (1UL<<31)); // bit 31 indicates not MCD
return (idx | (1UL << 31)); // bit 31 indicates not MCD
}
static void fdDelete(IData fdi) VL_MT_SAFE {
IData idx = VL_MASK_I(31) & fdi;

View File

@ -23,6 +23,7 @@
#include <cerrno>
#include <fcntl.h>
// clang-format off
#if defined(_WIN32) && !defined(__MINGW32__) && !defined(__CYGWIN__)
# include <io.h>
#else
@ -38,6 +39,7 @@
#ifndef O_CLOEXEC
# define O_CLOEXEC 0
#endif
// clang-format on
// CONSTANTS
static const char* const VLTSAVE_HEADER_STR
@ -54,9 +56,7 @@ bool VerilatedDeserialize::readDiffers(const void* __restrict datap,
bufferCheck();
const vluint8_t* __restrict dp = static_cast<const vluint8_t* __restrict>(datap);
vluint8_t miss = 0;
while (size--) {
miss |= (*dp++ ^ *m_cp++);
}
while (size--) miss |= (*dp++ ^ *m_cp++);
return (miss != 0);
}
@ -232,9 +232,7 @@ void VerilatedRestore::fill() VL_MT_UNSAFE_ONE {
} else { // got==0, EOF
// Fill buffer from here to end with NULLs so reader's don't
// need to check eof each character.
while (m_endp < m_bufp + bufferSize()) {
*m_endp++ = '\0';
}
while (m_endp < m_bufp + bufferSize()) *m_endp++ = '\0';
break;
}
}

View File

@ -132,7 +132,7 @@ public:
size_t blk = size;
if (blk > bufferInsertSize()) blk = bufferInsertSize();
const vluint8_t* __restrict maxp = dp + blk;
for (; dp < maxp; *dp++ = *m_cp++);
for (; dp < maxp; *dp++ = *m_cp++) {}
size -= blk;
}
return *this; // For function chaining
@ -257,8 +257,8 @@ VerilatedSerialize& operator<<(VerilatedSerialize& os, VlAssocArray<T_Key, T_Val
os << rhs.atDefault();
vluint32_t len = rhs.size();
os << len;
for (typename VlAssocArray<T_Key, T_Value>::const_iterator it = rhs.begin();
it != rhs.end(); ++it) {
for (typename VlAssocArray<T_Key, T_Value>::const_iterator it = rhs.begin(); it != rhs.end();
++it) {
T_Key index = it->first; // Copy to get around const_iterator
T_Value value = it->second;
os << index << value;

View File

@ -41,8 +41,12 @@ class VerilatedRange {
protected:
friend class VerilatedVarProps;
friend class VerilatedScope;
VerilatedRange() : m_left(0), m_right(0) {}
VerilatedRange(int left, int right) : m_left(left), m_right(right) {}
VerilatedRange()
: m_left(0)
, m_right(0) {}
VerilatedRange(int left, int right)
: m_left(left)
, m_right(right) {}
void init(int left, int right) {
m_left = left;
m_right = right;
@ -78,63 +82,89 @@ class VerilatedVarProps {
// CONSTRUCTORS
protected:
friend class VerilatedScope;
VerilatedVarProps(VerilatedVarType vltype, VerilatedVarFlags vlflags,
int pdims, int udims)
: m_magic(MAGIC), m_vltype(vltype), m_vlflags(vlflags), m_pdims(pdims), m_udims(udims) {}
VerilatedVarProps(VerilatedVarType vltype, VerilatedVarFlags vlflags, int pdims, int udims)
: m_magic(MAGIC)
, m_vltype(vltype)
, m_vlflags(vlflags)
, m_pdims(pdims)
, m_udims(udims) {}
public:
class Unpacked {};
// Without packed
VerilatedVarProps(VerilatedVarType vltype, int vlflags)
: m_magic(MAGIC), m_vltype(vltype),
m_vlflags(VerilatedVarFlags(vlflags)), m_pdims(0), m_udims(0) {}
VerilatedVarProps(VerilatedVarType vltype, int vlflags,
Unpacked, int u0l, int u0r)
: m_magic(MAGIC), m_vltype(vltype),
m_vlflags(VerilatedVarFlags(vlflags)), m_pdims(0), m_udims(1) {
: m_magic(MAGIC)
, m_vltype(vltype)
, m_vlflags(VerilatedVarFlags(vlflags))
, m_pdims(0)
, m_udims(0) {}
VerilatedVarProps(VerilatedVarType vltype, int vlflags, Unpacked, int u0l, int u0r)
: m_magic(MAGIC)
, m_vltype(vltype)
, m_vlflags(VerilatedVarFlags(vlflags))
, m_pdims(0)
, m_udims(1) {
m_unpacked[0].init(u0l, u0r);
}
VerilatedVarProps(VerilatedVarType vltype, int vlflags,
Unpacked, int u0l, int u0r, int u1l, int u1r)
: m_magic(MAGIC), m_vltype(vltype),
m_vlflags(VerilatedVarFlags(vlflags)), m_pdims(0), m_udims(2) {
VerilatedVarProps(VerilatedVarType vltype, int vlflags, Unpacked, int u0l, int u0r, int u1l,
int u1r)
: m_magic(MAGIC)
, m_vltype(vltype)
, m_vlflags(VerilatedVarFlags(vlflags))
, m_pdims(0)
, m_udims(2) {
m_unpacked[0].init(u0l, u0r);
m_unpacked[1].init(u1l, u1r);
}
VerilatedVarProps(VerilatedVarType vltype, int vlflags,
Unpacked, int u0l, int u0r, int u1l, int u1r, int u2l, int u2r)
: m_magic(MAGIC), m_vltype(vltype),
m_vlflags(VerilatedVarFlags(vlflags)), m_pdims(0), m_udims(3) {
VerilatedVarProps(VerilatedVarType vltype, int vlflags, Unpacked, int u0l, int u0r, int u1l,
int u1r, int u2l, int u2r)
: m_magic(MAGIC)
, m_vltype(vltype)
, m_vlflags(VerilatedVarFlags(vlflags))
, m_pdims(0)
, m_udims(3) {
m_unpacked[0].init(u0l, u0r);
m_unpacked[1].init(u1l, u1r);
m_unpacked[2].init(u2l, u2r);
}
// With packed
class Packed {};
VerilatedVarProps(VerilatedVarType vltype, int vlflags,
Packed, int pl, int pr)
: m_magic(MAGIC), m_vltype(vltype),
m_vlflags(VerilatedVarFlags(vlflags)), m_pdims(1), m_udims(0), m_packed(pl,pr) {}
VerilatedVarProps(VerilatedVarType vltype, int vlflags,
Packed, int pl, int pr,
Unpacked, int u0l, int u0r)
: m_magic(MAGIC), m_vltype(vltype),
m_vlflags(VerilatedVarFlags(vlflags)), m_pdims(1), m_udims(1), m_packed(pl,pr) {
VerilatedVarProps(VerilatedVarType vltype, int vlflags, Packed, int pl, int pr)
: m_magic(MAGIC)
, m_vltype(vltype)
, m_vlflags(VerilatedVarFlags(vlflags))
, m_pdims(1)
, m_udims(0)
, m_packed(pl, pr) {}
VerilatedVarProps(VerilatedVarType vltype, int vlflags, Packed, int pl, int pr, Unpacked,
int u0l, int u0r)
: m_magic(MAGIC)
, m_vltype(vltype)
, m_vlflags(VerilatedVarFlags(vlflags))
, m_pdims(1)
, m_udims(1)
, m_packed(pl, pr) {
m_unpacked[0].init(u0l, u0r);
}
VerilatedVarProps(VerilatedVarType vltype, int vlflags,
Packed, int pl, int pr,
Unpacked, int u0l, int u0r, int u1l, int u1r)
: m_magic(MAGIC), m_vltype(vltype), m_vlflags(VerilatedVarFlags(vlflags)),
m_pdims(1), m_udims(2), m_packed(pl,pr) {
VerilatedVarProps(VerilatedVarType vltype, int vlflags, Packed, int pl, int pr, Unpacked,
int u0l, int u0r, int u1l, int u1r)
: m_magic(MAGIC)
, m_vltype(vltype)
, m_vlflags(VerilatedVarFlags(vlflags))
, m_pdims(1)
, m_udims(2)
, m_packed(pl, pr) {
m_unpacked[0].init(u0l, u0r);
m_unpacked[1].init(u1l, u1r);
}
VerilatedVarProps(VerilatedVarType vltype, int vlflags,
Packed, int pl, int pr,
Unpacked, int u0l, int u0r, int u1l, int u1r, int u2l, int u2r)
: m_magic(MAGIC), m_vltype(vltype),
m_vlflags(VerilatedVarFlags(vlflags)), m_pdims(1), m_udims(3), m_packed(pl,pr) {
VerilatedVarProps(VerilatedVarType vltype, int vlflags, Packed, int pl, int pr, Unpacked,
int u0l, int u0r, int u1l, int u1r, int u2l, int u2r)
: m_magic(MAGIC)
, m_vltype(vltype)
, m_vlflags(VerilatedVarFlags(vlflags))
, m_pdims(1)
, m_udims(3)
, m_packed(pl, pr) {
m_unpacked[0].init(u0l, u0r);
m_unpacked[1].init(u1l, u1r);
m_unpacked[2].init(u2l, u2r);

View File

@ -61,8 +61,7 @@ void VlWorkerThread::workerLoop() {
if (VL_LIKELY(!work.m_fnp)) dequeWork(&work);
// Do this here, not above, to avoid a race with the destructor.
if (VL_UNLIKELY(m_exiting.load(std::memory_order_acquire)))
break;
if (VL_UNLIKELY(m_exiting.load(std::memory_order_acquire))) break;
if (VL_LIKELY(work.m_fnp)) {
work.m_fnp(work.m_evenCycle, work.m_sym);
@ -128,8 +127,7 @@ void VlThreadPool::setupProfilingClientThread() {
void VlThreadPool::profileAppendAll(const VlProfileRec& rec) {
VerilatedLockGuard lk(m_mutex);
for (ProfileSet::iterator it = m_allProfiles.begin();
it != m_allProfiles.end(); ++it) {
for (ProfileSet::iterator it = m_allProfiles.begin(); it != m_allProfiles.end(); ++it) {
// Every thread's profile trace gets a copy of rec.
(*it)->emplace_back(rec);
}
@ -156,14 +154,14 @@ void VlThreadPool::profileDump(const char* filenamep, vluint64_t ticksElapsed) {
fprintf(fp, "VLPROF stat yields %" VL_PRI64 "u\n", VlMTaskVertex::yields());
vluint32_t thread_id = 0;
for (ProfileSet::const_iterator pit = m_allProfiles.begin();
pit != m_allProfiles.end(); ++pit) {
for (ProfileSet::const_iterator pit = m_allProfiles.begin(); pit != m_allProfiles.end();
++pit) {
++thread_id;
bool printing = false; // False while in warmup phase
for (ProfileTrace::const_iterator eit = (*pit)->begin(); eit != (*pit)->end(); ++eit) {
switch (eit->m_type) {
case VlProfileRec::TYPE_BARRIER:
case VlProfileRec::TYPE_BARRIER: //
printing = true;
break;
case VlProfileRec::TYPE_MTASK_RUN:

View File

@ -25,12 +25,15 @@
#include <condition_variable>
#include <set>
#include <vector>
// clang-format off
#if defined(__linux)
#include <sched.h> // For sched_getcpu()
# include <sched.h> // For sched_getcpu()
#endif
#if defined(__APPLE__)
# include <cpuid.h> // For __cpuid_count()
#endif
// clang-format on
// VlMTaskVertex and VlThreadpool will work with multiple symbol table types.
// Since the type is opaque to VlMTaskVertex and VlThreadPool, represent it
@ -115,10 +118,7 @@ public:
class VlProfileRec {
protected:
friend class VlThreadPool;
enum VlProfileE {
TYPE_MTASK_RUN,
TYPE_BARRIER
};
enum VlProfileE { TYPE_MTASK_RUN, TYPE_BARRIER };
VlProfileE m_type; // Record type
vluint32_t m_mtaskId; // Mtask we're logging
vluint32_t m_predictTime; // How long scheduler predicted would take
@ -173,9 +173,14 @@ private:
VlExecFnp m_fnp; // Function to execute
VlThrSymTab m_sym; // Symbol table to execute
bool m_evenCycle; // Even/odd for flag alternation
ExecRec() : m_fnp(NULL), m_sym(NULL), m_evenCycle(false) {}
ExecRec()
: m_fnp(NULL)
, m_sym(NULL)
, m_evenCycle(false) {}
ExecRec(VlExecFnp fnp, bool evenCycle, VlThrSymTab sym)
: m_fnp(fnp), m_sym(sym), m_evenCycle(evenCycle) {}
: m_fnp(fnp)
, m_sym(sym)
, m_evenCycle(evenCycle) {}
};
// MEMBERS
@ -208,7 +213,7 @@ public:
inline void dequeWork(ExecRec* workp) {
// Spin for a while, waiting for new data
for (int i = 0; i < VL_LOCK_SPINS; ++i) {
if (VL_LIKELY(m_ready_size.load(std::memory_order_relaxed))) {
if (VL_LIKELY(m_ready_size.load(std::memory_order_relaxed))) { //
break;
}
VL_CPU_RELAX();

View File

@ -41,13 +41,9 @@
#include <string>
// Abstract 'vl_hash' and 'vl_equal_to' templates.
template <typename T> struct vl_hash {
size_t operator()(const T& k) const;
};
template <typename T> struct vl_hash { size_t operator()(const T& k) const; };
template <typename T> struct vl_equal_to {
bool operator()(const T& a, const T& b) const;
};
template <typename T> struct vl_equal_to { bool operator()(const T& a, const T& b) const; };
// Specializations of 'vl_hash' and 'vl_equal_to'.
inline size_t vl_hash_bytes(const void* vbufp, size_t nbytes) {
@ -59,60 +55,50 @@ inline size_t vl_hash_bytes(const void* vbufp, size_t nbytes) {
return hash;
}
template <> inline size_t
vl_hash<unsigned int>::operator()(const unsigned int& k) const {
template <> inline size_t vl_hash<unsigned int>::operator()(const unsigned int& k) const {
return k;
}
template <> inline bool
vl_equal_to<unsigned int>::operator()(const unsigned int& a,
const unsigned int& b) const {
template <>
inline bool vl_equal_to<unsigned int>::operator()(const unsigned int& a,
const unsigned int& b) const {
return a == b;
}
template <> inline size_t
vl_hash<std::string>::operator()(const std::string& k) const {
template <> inline size_t vl_hash<std::string>::operator()(const std::string& k) const {
return vl_hash_bytes(k.data(), k.size());
}
template <> inline bool
vl_equal_to<std::string>::operator()(const std::string& a,
const std::string& b) const {
template <>
inline bool vl_equal_to<std::string>::operator()(const std::string& a,
const std::string& b) const {
// Don't scan the strings if the sizes are different.
if (a.size() != b.size()) {
return false;
}
if (a.size() != b.size()) return false;
return (0 == a.compare(b)); // Must scan.
}
template <typename T> struct vl_hash<T*> {
size_t operator()(T* kp) const {
return ((sizeof(size_t) == sizeof(kp))
? reinterpret_cast<size_t>(kp)
: vl_hash_bytes(&kp, sizeof(kp)));
return ((sizeof(size_t) == sizeof(kp)) ? reinterpret_cast<size_t>(kp)
: vl_hash_bytes(&kp, sizeof(kp)));
}
};
template <typename T> struct vl_equal_to<T*> {
bool operator()(T* ap, T* bp) const {
return ap == bp;
}
bool operator()(T* ap, T* bp) const { return ap == bp; }
};
//===================================================================
//
/// Functional clone of the std::unordered_set hash table.
template <class T_Key,
class T_Hash = vl_hash<T_Key>,
class T_Equal = vl_equal_to<T_Key> >
template <class T_Key, class T_Hash = vl_hash<T_Key>, class T_Equal = vl_equal_to<T_Key> >
class vl_unordered_set {
public:
// TYPES
typedef std::list<T_Key> Bucket;
enum RehashType { GROW, SHRINK };
template <class KK, class VV,
class HH, class EQ> friend class vl_unordered_map;
template <class KK, class VV, class HH, class EQ> friend class vl_unordered_map;
class iterator {
protected:
@ -123,29 +109,23 @@ public:
public:
// CONSTRUCTORS
iterator(size_t bucketIdx, typename Bucket::iterator bit,
const vl_unordered_set* setp)
: m_bucketIdx(bucketIdx), m_bit(bit), m_setp(setp) {}
iterator(size_t bucketIdx, typename Bucket::iterator bit, const vl_unordered_set* setp)
: m_bucketIdx(bucketIdx)
, m_bit(bit)
, m_setp(setp) {}
// METHODS
const T_Key& operator*() const {
return *m_bit;
}
const T_Key& operator*() const { return *m_bit; }
// This should really be 'const T_Key*' type for unordered_set,
// however this iterator is shared with unordered_map whose
// operator-> returns a non-const ValueType*, so keep this
// non-const to avoid having to define a whole separate iterator
// for unordered_map.
T_Key* operator->() const {
return &(*m_bit);
}
T_Key* operator->() const { return &(*m_bit); }
bool operator==(const iterator& other) const {
return ((m_bucketIdx == other.m_bucketIdx)
&& (m_bit == other.m_bit));
}
bool operator!=(const iterator& other) const {
return (!this->operator==(other));
return ((m_bucketIdx == other.m_bucketIdx) && (m_bit == other.m_bit));
}
bool operator!=(const iterator& other) const { return (!this->operator==(other)); }
void advanceUntilValid() {
while (true) {
if (m_bit != m_setp->m_bucketsp[m_bucketIdx].end()) {
@ -176,14 +156,14 @@ public:
private:
// MEMBERS
size_t m_numElements; // Number of entries present.
size_t m_log2Buckets; // Log-base-2 of the number of buckets.
mutable Bucket* m_bucketsp; // Hash table buckets. May be NULL;
size_t m_numElements; // Number of entries present.
size_t m_log2Buckets; // Log-base-2 of the number of buckets.
mutable Bucket* m_bucketsp; // Hash table buckets. May be NULL;
// // we'll allocate it on the fly when
// // the first entries are created.
Bucket m_emptyBucket; // A fake bucket, used to construct end().
T_Hash m_hash; // Hash function provider.
T_Equal m_equal; // Equal-to function provider.
Bucket m_emptyBucket; // A fake bucket, used to construct end().
T_Hash m_hash; // Hash function provider.
T_Equal m_equal; // Equal-to function provider.
public:
// CONSTRUCTORS
@ -202,26 +182,20 @@ public:
, m_equal() {
if (other.m_bucketsp) {
m_bucketsp = new Bucket[numBuckets()];
for (size_t i = 0; i < numBuckets(); i++) {
m_bucketsp[i] = other.m_bucketsp[i];
}
for (size_t i = 0; i < numBuckets(); i++) m_bucketsp[i] = other.m_bucketsp[i];
}
}
~vl_unordered_set() {
VL_DO_DANGLING(delete [] m_bucketsp, m_bucketsp);
}
~vl_unordered_set() { VL_DO_DANGLING(delete[] m_bucketsp, m_bucketsp); }
vl_unordered_set& operator=(const vl_unordered_set& other) {
if (this != &other) {
clear();
delete [] m_bucketsp;
delete[] m_bucketsp;
m_numElements = other.m_numElements;
m_log2Buckets = other.m_log2Buckets;
if (other.m_bucketsp) {
m_bucketsp = new Bucket[numBuckets()];
for (size_t i = 0; i < numBuckets(); i++) {
m_bucketsp[i] = other.m_bucketsp[i];
}
for (size_t i = 0; i < numBuckets(); i++) m_bucketsp[i] = other.m_bucketsp[i];
} else {
m_bucketsp = NULL;
}
@ -251,24 +225,21 @@ public:
return end();
}
const_iterator end() const {
return iterator(VL_ULL(0xFFFFFFFFFFFFFFFF),
const_cast<Bucket&>(m_emptyBucket).begin(), this);
return iterator(VL_ULL(0xFFFFFFFFFFFFFFFF), const_cast<Bucket&>(m_emptyBucket).begin(),
this);
}
bool empty() const { return m_numElements == 0; }
size_t size() const { return m_numElements; }
size_t count(const T_Key& key) const {
return (find(key) == end()) ? 0 : 1;
}
size_t count(const T_Key& key) const { return (find(key) == end()) ? 0 : 1; }
size_t hashToBucket(size_t hashVal) const {
return hashToBucket(hashVal, m_log2Buckets);
}
size_t hashToBucket(size_t hashVal) const { return hashToBucket(hashVal, m_log2Buckets); }
static size_t hashToBucket(size_t hashVal, unsigned log2Buckets) {
// Fibonacci hashing
// See https://probablydance.com/2018/06/16/fibonacci-hashing-the-optimization-that-the-world-forgot-or-a-better-alternative-to-integer-modulo/
// Fibonacci hashing, see
// https://probablydance.com/2018/06/16/fibonacci-hashing-the-optimization
// -that-the-world-forgot-or-a-better-alternative-to-integer-modulo/
//
// * The magic numbers below are UINT_MAX/phi where phi is the
// golden ratio number (1.618...) for either 64- or 32-bit
@ -278,11 +249,9 @@ public:
// function further. This permits the use of very fast client
// hash funcs (like just returning the int or pointer value as
// is!) and tolerates crappy client hash functions pretty well.
size_t mult = hashVal * ((sizeof(size_t) == 8)
? VL_ULL(11400714819323198485)
: 2654435769lu);
size_t result = (mult >> (((sizeof(size_t) == 8)
? 64 : 32) - log2Buckets));
size_t mult
= hashVal * ((sizeof(size_t) == 8) ? VL_ULL(11400714819323198485) : 2654435769lu);
size_t result = (mult >> (((sizeof(size_t) == 8) ? 64 : 32) - log2Buckets));
return result;
}
@ -292,19 +261,15 @@ public:
initBuckets();
Bucket* bucketp = &m_bucketsp[bucketIdxOut];
for (typename Bucket::iterator it = bucketp->begin();
it != bucketp->end(); ++it) {
if (m_equal.operator()(*it, key)) {
return iterator(bucketIdxOut, it, this);
}
for (typename Bucket::iterator it = bucketp->begin(); it != bucketp->end(); ++it) {
if (m_equal.operator()(*it, key)) return iterator(bucketIdxOut, it, this);
}
return end();
}
const_iterator find(const T_Key& key) const {
size_t bucketIdx;
return const_cast<vl_unordered_set*>(this)->find_internal(key,
bucketIdx);
return const_cast<vl_unordered_set*>(this)->find_internal(key, bucketIdx);
}
iterator find(const T_Key& key) {
@ -358,9 +323,7 @@ public:
// for the Scoreboard in V3Partition, which begins tracking
// a huge number of vertices and then tracks a successively
// smaller number over time.
if (needToRehash(SHRINK)) {
rehash(SHRINK);
}
if (needToRehash(SHRINK)) rehash(SHRINK);
return 1;
}
return 0;
@ -419,8 +382,7 @@ private:
size_t new_idx = hashToBucket(hash, new_log2Buckets);
// Avoid mallocing one list elem and freeing another;
// splice just moves it over.
new_bucketsp[new_idx].splice(new_bucketsp[new_idx].begin(),
m_bucketsp[i], bit);
new_bucketsp[new_idx].splice(new_bucketsp[new_idx].begin(), m_bucketsp[i], bit);
}
}
@ -433,9 +395,7 @@ private:
//===================================================================
//
/// Functional clone of the std::unordered_map hash table.
template <class T_Key,
class T_Value,
class T_Hash = vl_hash<T_Key>,
template <class T_Key, class T_Value, class T_Hash = vl_hash<T_Key>,
class T_Equal = vl_equal_to<T_Key> >
class vl_unordered_map {
private:
@ -445,6 +405,7 @@ private:
class KeyHash {
private:
T_Hash key_hash;
public:
KeyHash() {}
size_t operator()(const KeyValPair& kv_pair) const {
@ -455,6 +416,7 @@ private:
class KeyEqual {
private:
T_Equal key_eq;
public:
KeyEqual() {}
bool operator()(const KeyValPair& kv_a, const KeyValPair& kv_b) const {
@ -491,24 +453,19 @@ public:
size_t bucketIdxOut = m_set.hashToBucket(hash);
typename MapSet::Bucket* bucketp = m_set.getBucket(bucketIdxOut);
for (typename MapSet::Bucket::iterator it = bucketp->begin();
it != bucketp->end(); ++it) {
if (mapEq.operator()(it->first, k)) {
return iterator(bucketIdxOut, it, &m_set);
}
for (typename MapSet::Bucket::iterator it = bucketp->begin(); it != bucketp->end(); ++it) {
if (mapEq.operator()(it->first, k)) return iterator(bucketIdxOut, it, &m_set);
}
return end();
}
const_iterator find(const T_Key& k) const {
return const_cast<vl_unordered_map*>(this)->find(k);
}
std::pair<iterator, bool> insert(const KeyValPair& val) {
return m_set.insert(val);
}
std::pair<iterator, bool> insert(const KeyValPair& val) { return m_set.insert(val); }
iterator erase(iterator it) { return m_set.erase(it); }
size_t erase(const T_Key& k) {
iterator it = find(k);
if (it == end()) { return 0; }
if (it == end()) return 0;
m_set.erase(it);
return 1;
}
@ -517,9 +474,7 @@ public:
// std::unordered_map::operator[] relies on it too.
KeyValPair dummy = std::make_pair(k, T_Value());
iterator it = m_set.find(dummy);
if (it == m_set.end()) {
it = m_set.insert(dummy).first;
}
if (it == m_set.end()) it = m_set.insert(dummy).first;
// For the 'set', it's generally not safe to modify
// the value after deref. For the 'map' though, we know
// it's safe to modify the value field and we can allow it:

View File

@ -25,21 +25,22 @@
//======================================================================
//--------------------------------------------------
#if (SYSTEMC_VERSION>=20050714)
// SystemC 2.1.v1
#if (SYSTEMC_VERSION >= 20050714)
// SystemC 2.1.v1
// cppcheck-suppress unusedFunction
void VerilatedVcdSc::write_comment(const std::string &) {}
void VerilatedVcdSc::trace(const unsigned int &, const std::string &, const char**) {}
void VerilatedVcdSc::write_comment(const std::string&) {}
void VerilatedVcdSc::trace(const unsigned int&, const std::string&, const char**) {}
// clang-format off
# define DECL_TRACE_METHOD_A(tp) \
void VerilatedVcdSc::trace( const tp& object, const std::string& name ) {}
void VerilatedVcdSc::trace(const tp& object, const std::string& name) {}
# define DECL_TRACE_METHOD_B(tp) \
void VerilatedVcdSc::trace( const tp& object, const std::string& name, int width ) {}
void VerilatedVcdSc::trace(const tp& object, const std::string& name, int width) {}
#if (SYSTEMC_VERSION>=20171012)
# if (SYSTEMC_VERSION >= 20171012)
DECL_TRACE_METHOD_A( sc_event )
DECL_TRACE_METHOD_A( sc_time )
#endif
# endif
DECL_TRACE_METHOD_A( bool )
DECL_TRACE_METHOD_A( sc_dt::sc_bit )
@ -49,9 +50,9 @@ void VerilatedVcdSc::trace(const unsigned int &, const std::string &, const char
DECL_TRACE_METHOD_B( unsigned short )
DECL_TRACE_METHOD_B( unsigned int )
DECL_TRACE_METHOD_B( unsigned long )
#ifdef SYSTEMC_64BIT_PATCHES
# ifdef SYSTEMC_64BIT_PATCHES
DECL_TRACE_METHOD_B( unsigned long long)
#endif
# endif
DECL_TRACE_METHOD_B( char )
DECL_TRACE_METHOD_B( short )
DECL_TRACE_METHOD_B( int )
@ -73,19 +74,21 @@ void VerilatedVcdSc::trace(const unsigned int &, const std::string &, const char
DECL_TRACE_METHOD_A( sc_dt::sc_bv_base )
DECL_TRACE_METHOD_A( sc_dt::sc_lv_base )
// clang-format on
//--------------------------------------------------
#elif (SYSTEMC_VERSION>20011000)
// SystemC 2.0.1
#elif (SYSTEMC_VERSION > 20011000)
// SystemC 2.0.1
// cppcheck-suppress unusedFunction
void VerilatedVcdSc::write_comment(const sc_string &) {}
void VerilatedVcdSc::write_comment(const sc_string&) {}
void VerilatedVcdSc::trace(const unsigned int&, const sc_string&, const char**) {}
#define DECL_TRACE_METHOD_A(tp) \
void VerilatedVcdSc::trace( const tp& object, const sc_string& name ) {}
void VerilatedVcdSc::trace(const tp& object, const sc_string& name) {}
#define DECL_TRACE_METHOD_B(tp) \
void VerilatedVcdSc::trace( const tp& object, const sc_string& name, int width ) {}
void VerilatedVcdSc::trace(const tp& object, const sc_string& name, int width) {}
// clang-format off
DECL_TRACE_METHOD_A( bool )
DECL_TRACE_METHOD_A( sc_bit )
DECL_TRACE_METHOD_A( sc_logic )
@ -96,7 +99,7 @@ void VerilatedVcdSc::trace(const unsigned int&, const sc_string&, const char**)
#ifdef SYSTEMC_64BIT_PATCHES
DECL_TRACE_METHOD_B( unsigned long long)
#endif
#if (SYSTEMC_VERSION>20041000)
#if (SYSTEMC_VERSION > 20041000)
DECL_TRACE_METHOD_B( unsigned long long)
DECL_TRACE_METHOD_B( long long)
#endif
@ -116,19 +119,21 @@ void VerilatedVcdSc::trace(const unsigned int&, const sc_string&, const char**)
DECL_TRACE_METHOD_A( sc_fxnum_fast )
DECL_TRACE_METHOD_A( sc_bv_base )
DECL_TRACE_METHOD_A( sc_lv_base )
// clang-format on
//--------------------------------------------------
#else
// SystemC 1.2.1beta
// SystemC 1.2.1beta
// cppcheck-suppress unusedFunction
void VerilatedVcdSc::write_comment(const sc_string &) {}
void VerilatedVcdSc::write_comment(const sc_string&) {}
void VerilatedVcdSc::trace(const unsigned int&, const sc_string&, const char**) {}
#define DECL_TRACE_METHOD_A(tp) \
void VerilatedVcdSc::trace( const tp& object, const sc_string& name ) {}
void VerilatedVcdSc::trace(const tp& object, const sc_string& name) {}
#define DECL_TRACE_METHOD_B(tp) \
void VerilatedVcdSc::trace( const tp& object, const sc_string& name, int width ) {}
void VerilatedVcdSc::trace(const tp& object, const sc_string& name, int width) {}
// clang-format off
DECL_TRACE_METHOD_A( bool )
DECL_TRACE_METHOD_B( unsigned char )
DECL_TRACE_METHOD_B( short unsigned int )
@ -154,6 +159,7 @@ void VerilatedVcdSc::trace(const unsigned int&, const sc_string&, const char**)
DECL_TRACE_METHOD_A( sc_signal_resolved_vector )
DECL_TRACE_METHOD_A( sc_bv_ns::sc_bv_base )
DECL_TRACE_METHOD_A( sc_bv_ns::sc_lv_base )
// clang-format on
#endif
#undef DECL_TRACE_METHOD_A

View File

@ -31,44 +31,42 @@
/// This class is passed to the SystemC simulation kernel, just like a
/// documented SystemC trace format.
class VerilatedVcdSc
: sc_trace_file
, public VerilatedVcdC
{
class VerilatedVcdSc : sc_trace_file, public VerilatedVcdC {
// CONSTRUCTORS
VL_UNCOPYABLE(VerilatedVcdSc);
public:
VerilatedVcdSc() {
sc_get_curr_simcontext()->add_trace_file(this);
# if (SYSTEMC_VERSION>=20060505)
#if (SYSTEMC_VERSION >= 20060505)
// We want to avoid a depreciated warning, but still be back compatible.
// Turning off the message just for this still results in an
// annoying "to turn off" message.
sc_time t1sec(1,SC_SEC);
if (t1sec.to_default_time_units()!=0) {
sc_time tunits(1.0/t1sec.to_default_time_units(),SC_SEC);
sc_time t1sec(1, SC_SEC);
if (t1sec.to_default_time_units() != 0) {
sc_time tunits(1.0 / t1sec.to_default_time_units(), SC_SEC);
spTrace()->set_time_unit(tunits.to_string());
}
spTrace()->set_time_resolution(sc_get_time_resolution().to_string());
# elif (SYSTEMC_VERSION>20011000)
#elif (SYSTEMC_VERSION > 20011000)
// To confuse matters 2.1.beta returns a char* here, while 2.1.v1 returns a std::string
// we allow both flavors with overloaded set_time_* functions.
spTrace()->set_time_unit(sc_get_default_time_unit().to_string());
spTrace()->set_time_resolution(sc_get_time_resolution().to_string());
# endif
#endif
}
virtual ~VerilatedVcdSc() { close(); }
// METHODS
/// Called by SystemC simulate()
virtual void cycle(bool delta_cycle) {
# if (SYSTEMC_VERSION>20011000)
#if (SYSTEMC_VERSION > 20011000)
if (!delta_cycle) { this->dump(sc_time_stamp().to_double()); }
# else
#else
// VCD files must have integer timestamps, so we write all times in
// increments of time_resolution
if (!delta_cycle) { this->dump(sc_time_stamp().to_double()); }
# endif
#endif
}
private:
@ -78,26 +76,26 @@ private:
// Cadence Incisive has these as abstract functions so we must create them
virtual void set_time_unit(int exponent10_seconds) {} // deprecated
#endif
#if defined(NC_SYSTEMC) || (SYSTEMC_VERSION>=20111100)
#if defined(NC_SYSTEMC) || (SYSTEMC_VERSION >= 20111100)
virtual void set_time_unit(double v, sc_time_unit tu) {}
#endif
//--------------------------------------------------
# if (SYSTEMC_VERSION>=20050714)
#if (SYSTEMC_VERSION >= 20050714)
// SystemC 2.1.v1
# define DECL_TRACE_METHOD_A(tp) \
virtual void trace(const tp& object, const std::string& name);
// clang-format off
# define DECL_TRACE_METHOD_A(tp) virtual void trace(const tp& object, const std::string& name);
# define DECL_TRACE_METHOD_B(tp) \
virtual void trace(const tp& object, const std::string& name, int width);
virtual void write_comment(const std::string&);
virtual void trace(const unsigned int&, const std::string&, const char**);
#if (SYSTEMC_VERSION>=20171012)
// Formatting matches that of sc_trace.h
# if (SYSTEMC_VERSION >= 20171012)
DECL_TRACE_METHOD_A( sc_event )
DECL_TRACE_METHOD_A( sc_time )
#endif
# endif
DECL_TRACE_METHOD_A( bool )
DECL_TRACE_METHOD_A( sc_dt::sc_bit )
@ -107,9 +105,9 @@ private:
DECL_TRACE_METHOD_B( unsigned short )
DECL_TRACE_METHOD_B( unsigned int )
DECL_TRACE_METHOD_B( unsigned long )
#ifdef SYSTEMC_64BIT_PATCHES
# ifdef SYSTEMC_64BIT_PATCHES
DECL_TRACE_METHOD_B( unsigned long long)
#endif
# endif
DECL_TRACE_METHOD_B( char )
DECL_TRACE_METHOD_B( short )
DECL_TRACE_METHOD_B( int )
@ -131,12 +129,13 @@ private:
DECL_TRACE_METHOD_A( sc_dt::sc_bv_base )
DECL_TRACE_METHOD_A( sc_dt::sc_lv_base )
// clang-format on
//--------------------------------------------------
# elif (SYSTEMC_VERSION>20011000)
#elif (SYSTEMC_VERSION > 20011000)
// SystemC 2.0.1
# define DECL_TRACE_METHOD_A(tp) \
virtual void trace(const tp& object, const sc_string& name);
// clang-format off
# define DECL_TRACE_METHOD_A(tp) virtual void trace(const tp& object, const sc_string& name);
# define DECL_TRACE_METHOD_B(tp) \
virtual void trace(const tp& object, const sc_string& name, int width);
@ -152,13 +151,13 @@ private:
DECL_TRACE_METHOD_B( unsigned short )
DECL_TRACE_METHOD_B( unsigned int )
DECL_TRACE_METHOD_B( unsigned long )
#ifdef SYSTEMC_64BIT_PATCHES
# ifdef SYSTEMC_64BIT_PATCHES
DECL_TRACE_METHOD_B( unsigned long long)
#endif
#if (SYSTEMC_VERSION>20041000)
# endif
# if (SYSTEMC_VERSION > 20041000)
DECL_TRACE_METHOD_B( unsigned long long)
DECL_TRACE_METHOD_B( long long)
#endif
# endif
DECL_TRACE_METHOD_B( char )
DECL_TRACE_METHOD_B( short )
DECL_TRACE_METHOD_B( int )
@ -175,12 +174,13 @@ private:
DECL_TRACE_METHOD_A( sc_fxnum_fast )
DECL_TRACE_METHOD_A( sc_bv_base )
DECL_TRACE_METHOD_A( sc_lv_base )
// clang-format on
//--------------------------------------------------
# else
#else
// SystemC 1.2.1beta
# define DECL_TRACE_METHOD_A(tp) \
virtual void trace(const tp& object, const sc_string& name);
// clang-format off
# define DECL_TRACE_METHOD_A(tp) virtual void trace(const tp& object, const sc_string& name);
# define DECL_TRACE_METHOD_B(tp) \
virtual void trace(const tp& object, const sc_string& name, int width);
@ -213,9 +213,10 @@ private:
DECL_TRACE_METHOD_A( sc_bv_ns::sc_bv_base )
DECL_TRACE_METHOD_A( sc_bv_ns::sc_lv_base )
# endif
// clang-format on
# undef DECL_TRACE_METHOD_A
# undef DECL_TRACE_METHOD_B
#undef DECL_TRACE_METHOD_A
#undef DECL_TRACE_METHOD_B
};
#endif // Guard

File diff suppressed because it is too large Load Diff

View File

@ -25,95 +25,97 @@
#ifndef _VERILATEDOS_H_
#define _VERILATEDOS_H_ 1 ///< Header Guard
// Current clang-format versions botch #ifdef inclusion, so
// clang-format off
//=========================================================================
// Compiler pragma abstraction
#ifdef __GNUC__
# define VL_ATTR_ALIGNED(alignment) __attribute__ ((aligned (alignment)))
# define VL_ATTR_ALWINLINE __attribute__ ((always_inline))
# define VL_ATTR_COLD __attribute__ ((cold))
# define VL_ATTR_HOT __attribute__ ((hot))
# define VL_ATTR_NORETURN __attribute__ ((noreturn))
# define VL_ATTR_PRINTF(fmtArgNum) __attribute__ ((format (printf, (fmtArgNum), (fmtArgNum)+1)))
# define VL_ATTR_PURE __attribute__ ((pure))
# define VL_ATTR_UNUSED __attribute__ ((unused))
# define VL_FUNC __func__
# define VL_ATTR_ALIGNED(alignment) __attribute__((aligned(alignment)))
# define VL_ATTR_ALWINLINE __attribute__((always_inline))
# define VL_ATTR_COLD __attribute__((cold))
# define VL_ATTR_HOT __attribute__((hot))
# define VL_ATTR_NORETURN __attribute__((noreturn))
# define VL_ATTR_PRINTF(fmtArgNum) __attribute__((format(printf, (fmtArgNum), (fmtArgNum) + 1)))
# define VL_ATTR_PURE __attribute__((pure))
# define VL_ATTR_UNUSED __attribute__((unused))
# define VL_FUNC __func__
# if defined(__clang__) && defined(VL_THREADED)
# define VL_ACQUIRE(...) __attribute__ ((acquire_capability(__VA_ARGS__)))
# define VL_ACQUIRE_SHARED(...) __attribute__ ((acquire_shared_capability(__VA_ARGS__)))
# define VL_RELEASE(...) __attribute__ ((release_capability(__VA_ARGS__)))
# define VL_RELEASE_SHARED(...) __attribute__ ((release_shared_capability(__VA_ARGS__)))
# define VL_TRY_ACQUIRE(...) __attribute__ ((try_acquire_capability(__VA_ARGS__)))
# define VL_TRY_ACQUIRE_SHARED(...) __attribute__ ((try_acquire_shared_capability(__VA_ARGS__)))
# define VL_CAPABILITY(x) __attribute__ ((capability(x)))
# define VL_REQUIRES(x) __attribute__ ((requires_capability(x)))
# define VL_GUARDED_BY(x) __attribute__ ((guarded_by(x)))
# define VL_EXCLUDES(x) __attribute__ ((locks_excluded(x)))
# define VL_SCOPED_CAPABILITY __attribute__ ((scoped_lockable))
# define VL_ACQUIRE(...) __attribute__((acquire_capability(__VA_ARGS__)))
# define VL_ACQUIRE_SHARED(...) __attribute__((acquire_shared_capability(__VA_ARGS__)))
# define VL_RELEASE(...) __attribute__((release_capability(__VA_ARGS__)))
# define VL_RELEASE_SHARED(...) __attribute__((release_shared_capability(__VA_ARGS__)))
# define VL_TRY_ACQUIRE(...) __attribute__((try_acquire_capability(__VA_ARGS__)))
# define VL_TRY_ACQUIRE_SHARED(...) __attribute__((try_acquire_shared_capability(__VA_ARGS__)))
# define VL_CAPABILITY(x) __attribute__((capability(x)))
# define VL_REQUIRES(x) __attribute__((requires_capability(x)))
# define VL_GUARDED_BY(x) __attribute__((guarded_by(x)))
# define VL_EXCLUDES(x) __attribute__((locks_excluded(x)))
# define VL_SCOPED_CAPABILITY __attribute__((scoped_lockable))
# endif
# define VL_LIKELY(x) __builtin_expect(!!(x), 1)
# define VL_LIKELY(x) __builtin_expect(!!(x), 1)
# define VL_UNLIKELY(x) __builtin_expect(!!(x), 0)
# define VL_UNREACHABLE __builtin_unreachable();
# define VL_PREFETCH_RD(p) __builtin_prefetch((p),0)
# define VL_PREFETCH_RW(p) __builtin_prefetch((p),1)
# define VL_PREFETCH_RD(p) __builtin_prefetch((p), 0)
# define VL_PREFETCH_RW(p) __builtin_prefetch((p), 1)
#elif defined(_MSC_VER)
# define VL_FUNC __FUNCTION__
# define VL_FUNC __FUNCTION__
#endif
// Defaults for unsupported compiler features
#ifndef VL_ATTR_ALIGNED
# define VL_ATTR_ALIGNED(alignment) ///< Align structure to specified byte alignment
# define VL_ATTR_ALIGNED(alignment) ///< Align structure to specified byte alignment
#endif
#ifndef VL_ATTR_ALWINLINE
# define VL_ATTR_ALWINLINE ///< Inline, even when not optimizing
# define VL_ATTR_ALWINLINE ///< Inline, even when not optimizing
#endif
#ifndef VL_ATTR_COLD
# define VL_ATTR_COLD ///< Function is rarely executed
# define VL_ATTR_COLD ///< Function is rarely executed
#endif
#ifndef VL_ATTR_HOT
# define VL_ATTR_HOT ///< Function is highly executed
# define VL_ATTR_HOT ///< Function is highly executed
#endif
#ifndef VL_ATTR_NORETURN
# define VL_ATTR_NORETURN ///< Function does not ever return
# define VL_ATTR_NORETURN ///< Function does not ever return
#endif
#ifndef VL_ATTR_PRINTF
# define VL_ATTR_PRINTF(fmtArgNum) ///< Function with printf format checking
# define VL_ATTR_PRINTF(fmtArgNum) ///< Function with printf format checking
#endif
#ifndef VL_ATTR_PURE
# define VL_ATTR_PURE ///< Function is pure (and thus also VL_MT_SAFE)
# define VL_ATTR_PURE ///< Function is pure (and thus also VL_MT_SAFE)
#endif
#ifndef VL_ATTR_UNUSED
# define VL_ATTR_UNUSED ///< Function that may be never used
# define VL_ATTR_UNUSED ///< Function that may be never used
#endif
#ifndef VL_FUNC
# define VL_FUNC "__func__" ///< Name of current function for error macros
# define VL_FUNC "__func__" ///< Name of current function for error macros
#endif
#ifndef VL_CAPABILITY
# define VL_ACQUIRE(...) ///< Function requires a capability/lock (-fthread-safety)
# define VL_ACQUIRE_SHARED(...) ///< Function aquires a shared capability/lock (-fthread-safety)
# define VL_RELEASE(...) ///< Function releases a capability/lock (-fthread-safety)
# define VL_RELEASE_SHARED(...) ///< Function releases a shared capability/lock (-fthread-safety)
# define VL_TRY_ACQUIRE(...) ///< Function returns bool if aquired a capability (-fthread-safety)
# define VL_TRY_ACQUIRE_SHARED(...) ///< Function returns bool if aquired a shared capability (-fthread-safety)
# define VL_REQUIRES(x) ///< Function requires a capability inbound (-fthread-safety)
# define VL_EXCLUDES(x) ///< Function requires not having a capability inbound (-fthread-safety)
# define VL_CAPABILITY(x) ///< Name of capability/lock (-fthread-safety)
# define VL_GUARDED_BY(x) ///< Name of mutex protecting this variable (-fthread-safety)
# define VL_SCOPED_CAPABILITY ///< Scoped threaded capability/lock (-fthread-safety)
# define VL_ACQUIRE(...) ///< Function requires a capability/lock (-fthread-safety)
# define VL_ACQUIRE_SHARED(...) ///< Function aquires a shared capability/lock (-fthread-safety)
# define VL_RELEASE(...) ///< Function releases a capability/lock (-fthread-safety)
# define VL_RELEASE_SHARED(...) ///< Function releases a shared capability/lock (-fthread-safety)
# define VL_TRY_ACQUIRE(...) ///< Function returns bool if aquired a capability (-fthread-safety)
# define VL_TRY_ACQUIRE_SHARED(...) ///< Function returns bool if aquired shared (-fthread-safety)
# define VL_REQUIRES(x) ///< Function requires a capability inbound (-fthread-safety)
# define VL_EXCLUDES(x) ///< Function requires not having a capability inbound (-fthread-safety)
# define VL_CAPABILITY(x) ///< Name of capability/lock (-fthread-safety)
# define VL_GUARDED_BY(x) ///< Name of mutex protecting this variable (-fthread-safety)
# define VL_SCOPED_CAPABILITY ///< Scoped threaded capability/lock (-fthread-safety)
#endif
#ifndef VL_LIKELY
# define VL_LIKELY(x) (!!(x)) ///< Boolean expression more often true than false
# define VL_UNLIKELY(x) (!!(x)) ///< Boolean expression more often false than true
# define VL_LIKELY(x) (!!(x)) ///< Boolean expression more often true than false
# define VL_UNLIKELY(x) (!!(x)) ///< Boolean expression more often false than true
#endif
#define VL_UNCOVERABLE(x) VL_UNLIKELY(x) ///< Boolean expression never hit by users (no coverage)
# define VL_UNCOVERABLE(x) VL_UNLIKELY(x) ///< Boolean expression never hit by users (no coverage)
#ifndef VL_UNREACHABLE
# define VL_UNREACHABLE ///< Point that may never be reached
# define VL_UNREACHABLE ///< Point that may never be reached
#endif
#ifndef VL_PREFETCH_RD
# define VL_PREFETCH_RD(p) ///< Prefetch data with read intent
# define VL_PREFETCH_RD(p) ///< Prefetch data with read intent
#endif
#ifndef VL_PREFETCH_RW
# define VL_PREFETCH_RW(p) ///< Prefetch data with read/write intent
# define VL_PREFETCH_RW(p) ///< Prefetch data with read/write intent
#endif
#ifdef VL_THREADED
@ -121,31 +123,34 @@
# define VL_THREAD_LOCAL thread_local
# elif defined(__GNUC__)
# if (__cplusplus < 201103L) && !defined(VL_THREADED_NO_C11_WARNING)
# error "VL_THREADED/--threads support requires C++-11 or newer only; use newer compiler"
# error "VL_THREADED/--threads support requires C++-11 or newer only; use newer compiler"
# endif
# else
# error "Unsupported compiler for VL_THREADED: No thread-local declarator"
# endif
# define VL_THREAD_LOCAL thread_local ///< Use new C++ static local thread
# define VL_THREAD_LOCAL thread_local ///< Use new C++ static local thread
#else
# define VL_THREAD_LOCAL ///< Use new C++ static local thread
# define VL_THREAD_LOCAL ///< Use new C++ static local thread
#endif
#define VL_THREAD ///< Deprecated
#define VL_STATIC_OR_THREAD static ///< Deprecated
#define VL_THREAD ///< Deprecated
#define VL_STATIC_OR_THREAD static ///< Deprecated
#define VL_PURE ///< Comment tag that Function is pure (and thus also VL_MT_SAFE)
#define VL_MT_SAFE ///< Comment tag that function is threadsafe when VL_THREADED
#define VL_MT_SAFE_POSTINIT ///< Comment tag that function is threadsafe when VL_THREADED, only during normal operation (post-init)
#define VL_MT_SAFE_POSTINIT ///< Comment tag that function is threadsafe when VL_THREADED, only
///< during normal operation (post-init)
#define VL_MT_UNSAFE ///< Comment tag that function is not threadsafe when VL_THREADED
#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
# 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
// Was "(c##ui64)". C++11 has standardized on ULL, and MSVC now supports this.
// We propose to no longer require using this macro no sooner than June 2020.
// File an issue ASAP if this breaks anything.
#else
# define VL_ULL(c) (c##ULL) ///< Add appropriate suffix to 64-bit constant
# define VL_ULL(c) (c##ULL) ///< Add appropriate suffix to 64-bit constant
#endif
// This is not necessarily the same as #UL, depending on what the IData typedef is.
@ -249,47 +254,47 @@
# include <stdint.h>
# include <sys/types.h> // __WORDSIZE
# include <unistd.h> // ssize_t
typedef unsigned char uint8_t; ///< 8-bit unsigned type (backward compatibility)
typedef unsigned short int uint16_t; ///< 16-bit unsigned type (backward compatibility)
typedef char vlsint8_t; ///< 8-bit signed type
typedef unsigned char vluint8_t; ///< 8-bit unsigned type
typedef short int vlsint16_t; ///< 16-bit signed type
typedef unsigned short int vluint16_t; ///< 16-bit unsigned type
typedef unsigned char uint8_t; ///< 8-bit unsigned type (backward compatibility)
typedef unsigned short int uint16_t; ///< 16-bit unsigned type (backward compatibility)
typedef char vlsint8_t; ///< 8-bit signed type
typedef unsigned char vluint8_t; ///< 8-bit unsigned type
typedef short int vlsint16_t; ///< 16-bit signed type
typedef unsigned short int vluint16_t; ///< 16-bit unsigned type
# if defined(__uint32_t_defined) || defined(___int32_t_defined) // Newer Cygwin uint32_t in stdint.h as an unsigned int
typedef int32_t vlsint32_t; ///< 32-bit signed type
typedef uint32_t vluint32_t; ///< 32-bit unsigned type
typedef int32_t vlsint32_t; ///< 32-bit signed type
typedef uint32_t vluint32_t; ///< 32-bit unsigned type
# else // Older Cygwin has long==uint32_t
typedef unsigned long uint32_t; ///< 32-bit unsigned type (backward compatibility)
typedef long vlsint32_t; ///< 32-bit signed type
typedef unsigned long vluint32_t; ///< 32-bit unsigned type
typedef unsigned long uint32_t; ///< 32-bit unsigned type (backward compatibility)
typedef long vlsint32_t; ///< 32-bit signed type
typedef unsigned long vluint32_t; ///< 32-bit unsigned type
# endif
# if defined(__WORDSIZE) && (__WORDSIZE == 64)
typedef long vlsint64_t; ///< 64-bit signed type
typedef unsigned long vluint64_t; ///< 64-bit unsigned type
typedef long vlsint64_t; ///< 64-bit signed type
typedef unsigned long vluint64_t; ///< 64-bit unsigned type
# else
typedef long long vlsint64_t; ///< 64-bit signed type
typedef unsigned long long vluint64_t; ///< 64-bit unsigned type
typedef long long vlsint64_t; ///< 64-bit signed type
typedef unsigned long long vluint64_t; ///< 64-bit unsigned type
# endif
#elif defined(_WIN32) && defined(_MSC_VER)
typedef unsigned __int8 uint8_t; ///< 8-bit unsigned type (backward compatibility)
typedef unsigned __int16 uint16_t; ///< 16-bit unsigned type (backward compatibility)
typedef unsigned __int32 uint32_t; ///< 32-bit unsigned type (backward compatibility)
typedef signed __int8 vlsint8_t; ///< 8-bit signed type
typedef unsigned __int8 vluint8_t; ///< 8-bit unsigned type
typedef signed __int16 vlsint16_t; ///< 16-bit signed type
typedef unsigned __int16 vluint16_t; ///< 16-bit unsigned type
typedef signed __int32 vlsint32_t; ///< 32-bit signed type
typedef unsigned __int32 vluint32_t; ///< 32-bit unsigned type
typedef signed __int64 vlsint64_t; ///< 64-bit signed type
typedef unsigned __int64 vluint64_t; ///< 64-bit unsigned type
typedef unsigned __int8 uint8_t; ///< 8-bit unsigned type (backward compatibility)
typedef unsigned __int16 uint16_t; ///< 16-bit unsigned type (backward compatibility)
typedef unsigned __int32 uint32_t; ///< 32-bit unsigned type (backward compatibility)
typedef signed __int8 vlsint8_t; ///< 8-bit signed type
typedef unsigned __int8 vluint8_t; ///< 8-bit unsigned type
typedef signed __int16 vlsint16_t; ///< 16-bit signed type
typedef unsigned __int16 vluint16_t; ///< 16-bit unsigned type
typedef signed __int32 vlsint32_t; ///< 32-bit signed type
typedef unsigned __int32 vluint32_t; ///< 32-bit unsigned type
typedef signed __int64 vlsint64_t; ///< 64-bit signed type
typedef unsigned __int64 vluint64_t; ///< 64-bit unsigned type
# ifndef _SSIZE_T_DEFINED
# ifdef _WIN64
typedef signed __int64 ssize_t; ///< signed size_t; returned from read()
# ifdef _WIN64
typedef signed __int64 ssize_t; ///< signed size_t; returned from read()
# else
typedef signed __int32 ssize_t; ///< signed size_t; returned from read()
typedef signed __int32 ssize_t; ///< signed size_t; returned from read()
# endif
# endif
@ -299,18 +304,18 @@ typedef signed __int32 ssize_t; ///< signed size_t; returned fro
# include <stdint.h> // Linux and most flavors
# include <sys/types.h> // __WORDSIZE
# include <unistd.h> // ssize_t
typedef char vlsint8_t; ///< 8-bit signed type
typedef uint8_t vluint8_t; ///< 8-bit unsigned type
typedef short vlsint16_t; ///< 16-bit signed type
typedef uint16_t vluint16_t; ///< 16-bit unsigned type
typedef int vlsint32_t; ///< 32-bit signed type
typedef uint32_t vluint32_t; ///< 32-bit unsigned type
typedef char vlsint8_t; ///< 8-bit signed type
typedef uint8_t vluint8_t; ///< 8-bit unsigned type
typedef short vlsint16_t; ///< 16-bit signed type
typedef uint16_t vluint16_t; ///< 16-bit unsigned type
typedef int vlsint32_t; ///< 32-bit signed type
typedef uint32_t vluint32_t; ///< 32-bit unsigned type
# if defined(__WORDSIZE) && (__WORDSIZE == 64)
typedef long vlsint64_t; ///< 64-bit signed type
typedef unsigned long vluint64_t; ///< 64-bit unsigned type
typedef long vlsint64_t; ///< 64-bit signed type
typedef unsigned long vluint64_t; ///< 64-bit unsigned type
# else
typedef long long vlsint64_t; ///< 64-bit signed type
typedef unsigned long long vluint64_t; ///< 64-bit unsigned type
typedef long long vlsint64_t; ///< 64-bit signed type
typedef unsigned long long vluint64_t; ///< 64-bit unsigned type
# endif
#endif
@ -353,14 +358,14 @@ typedef unsigned long long vluint64_t; ///< 64-bit unsigned type
//=========================================================================
// Integer size macros
#define VL_BYTESIZE 8 ///< Bits in a CData / byte
#define VL_SHORTSIZE 16 ///< Bits in a SData / short
#define VL_IDATASIZE 32 ///< Bits in a IData / word
#define VL_WORDSIZE IDATASIZE ///< Legacy define
#define VL_QUADSIZE 64 ///< Bits in a QData / quadword
#define VL_EDATASIZE 32 ///< Bits in a EData (WData entry)
#define VL_EDATASIZE_LOG2 5 ///< log2(VL_EDATASIZE)
#define VL_CACHE_LINE_BYTES 64 ///< Bytes in a cache line (for alignment)
#define VL_BYTESIZE 8 ///< Bits in a CData / byte
#define VL_SHORTSIZE 16 ///< Bits in a SData / short
#define VL_IDATASIZE 32 ///< Bits in a IData / word
#define VL_WORDSIZE IDATASIZE ///< Legacy define
#define VL_QUADSIZE 64 ///< Bits in a QData / quadword
#define VL_EDATASIZE 32 ///< Bits in a EData (WData entry)
#define VL_EDATASIZE_LOG2 5 ///< log2(VL_EDATASIZE)
#define VL_CACHE_LINE_BYTES 64 ///< Bytes in a cache line (for alignment)
/// Bytes this number of bits needs (1 bit=1 byte)
#define VL_BYTES_I(nbits) (((nbits) + (VL_BYTESIZE - 1)) / VL_BYTESIZE)
@ -373,9 +378,9 @@ typedef unsigned long long vluint64_t; ///< 64-bit unsigned type
// Class definition helpers
// Used to declare a class as uncopyable; put after a private:
#define VL_UNCOPYABLE(Type) \
Type(const Type& other) VL_EQ_DELETE; \
Type& operator= (const Type&) VL_EQ_DELETE
#define VL_UNCOPYABLE(Type) \
Type(const Type& other) VL_EQ_DELETE; \
Type& operator=(const Type&) VL_EQ_DELETE
//=========================================================================
// Verilated function size macros
@ -391,11 +396,10 @@ typedef unsigned long long vluint64_t; ///< 64-bit unsigned type
#define VL_SIZEBITS_E (VL_EDATASIZE - 1) ///< Bit mask for bits in a quad
/// Mask for words with 1's where relevant bits are (0=all bits)
#define VL_MASK_I(nbits) (((nbits) & VL_SIZEBITS_I) \
? ((1U << ((nbits) & VL_SIZEBITS_I) )-1) : ~0)
#define VL_MASK_I(nbits) (((nbits) & VL_SIZEBITS_I) ? ((1U << ((nbits) & VL_SIZEBITS_I)) - 1) : ~0)
/// Mask for quads with 1's where relevant bits are (0=all bits)
#define VL_MASK_Q(nbits) (((nbits) & VL_SIZEBITS_Q) \
? ((VL_ULL(1) << ((nbits) & VL_SIZEBITS_Q) )-VL_ULL(1)) : VL_ULL(~0))
#define VL_MASK_Q(nbits) \
(((nbits) & VL_SIZEBITS_Q) ? ((VL_ULL(1) << ((nbits) & VL_SIZEBITS_Q)) - VL_ULL(1)) : VL_ULL(~0))
/// Mask for EData with 1's where relevant bits are (0=all bits)
#define VL_MASK_E(nbits) VL_MASK_I(nbits)
#define VL_EUL(n) VL_UL(n) ///< Make constant number EData sized
@ -411,8 +415,8 @@ typedef unsigned long long vluint64_t; ///< 64-bit unsigned type
// #defines, to avoid requiring math.h on all compile runs
#ifdef _MSC_VER
# define VL_TRUNC(n) (((n)<0) ? ceil((n)) : floor((n)))
# define VL_ROUND(n) (((n)<0) ? ceil((n)-0.5) : floor((n)+0.5))
# define VL_TRUNC(n) (((n) < 0) ? ceil((n)) : floor((n)))
# define VL_ROUND(n) (((n) < 0) ? ceil((n)-0.5) : floor((n) + 0.5))
#else
# define VL_TRUNC(n) trunc(n)
# define VL_ROUND(n) round(n)
@ -424,13 +428,14 @@ typedef unsigned long long vluint64_t; ///< 64-bit unsigned type
/// The vluint64_t argument is loaded with a high-performance counter for profiling
/// or 0x0 if not implemeted on this platform
#if defined(__i386__) || defined(__x86_64__)
# define VL_RDTSC(val) { \
vluint32_t hi, lo; \
asm volatile("rdtsc" : "=a" (lo), "=d" (hi)); \
(val) = ((vluint64_t)lo) | (((vluint64_t)hi)<<32); \
}
#define VL_RDTSC(val) \
{ \
vluint32_t hi, lo; \
asm volatile("rdtsc" : "=a"(lo), "=d"(hi)); \
(val) = ((vluint64_t)lo) | (((vluint64_t)hi) << 32); \
}
#elif defined(__aarch64__)
# define VL_RDTSC(val) asm volatile("mrs %[rt],PMCCNTR_EL0" : [rt] "=r" (val));
# define VL_RDTSC(val) asm volatile("mrs %[rt],PMCCNTR_EL0" : [rt] "=r"(val));
#else
// We just silently ignore unknown OSes, as only leads to missing statistics
# define VL_RDTSC(val) (val) = 0;
@ -468,6 +473,7 @@ typedef unsigned long long vluint64_t; ///< 64-bit unsigned type
#else
# define VL_STRCASECMP strcasecmp
#endif
// clang-format on
//=========================================================================
// Stringify macros

260
nodist/clang_formatter Executable file
View File

@ -0,0 +1,260 @@
#!/bin/bash
#
# clang-format is used to standardize the indentation of the internal C++
# code.
#
# For the most part clang-format changes provide good consistency, the two
# main exceptions being the indentation of preprocessor directives, and
# tables of statements. Reformatting is generally performed only before
# other large changes are to be made to a file.
#
# "##" files commented out below are not yet clang-format clean.
# "#" files commented out hit a clang-format limitation with ifdefs.
clang-format -i examples/make_hello_c/sim_main.cpp
clang-format -i examples/make_hello_sc/sc_main.cpp
#clang-format -i examples/make_protect_lib/sim_main.cpp
clang-format -i examples/make_tracing_c/sim_main.cpp
clang-format -i examples/make_tracing_sc/sc_main.cpp
clang-format -i include/verilated.cpp
clang-format -i include/verilated.h
clang-format -i include/verilated_config.h.in
clang-format -i include/verilated_cov.cpp
clang-format -i include/verilated_cov.h
clang-format -i include/verilated_cov_key.h
clang-format -i include/verilated_dpi.cpp
clang-format -i include/verilated_dpi.h
clang-format -i include/verilated_fst_c.cpp
clang-format -i include/verilated_fst_c.h
clang-format -i include/verilated_heavy.h
clang-format -i include/verilated_imp.h
clang-format -i include/verilated_save.cpp
clang-format -i include/verilated_save.h
clang-format -i include/verilated_sc.h
clang-format -i include/verilated_sym_props.h
clang-format -i include/verilated_syms.h
clang-format -i include/verilated_threads.cpp
clang-format -i include/verilated_threads.h
clang-format -i include/verilated_unordered_set_map.h
clang-format -i include/verilated_vcd_c.cpp
clang-format -i include/verilated_vcd_c.h
clang-format -i include/verilated_vcd_sc.cpp
clang-format -i include/verilated_vcd_sc.h
clang-format -i include/verilated_vpi.cpp
clang-format -i include/verilated_vpi.h
clang-format -i include/verilatedos.h
clang-format -i nodist/fuzzer/wrapper.cpp
clang-format -i src/V3Active.cpp
clang-format -i src/V3Active.h
clang-format -i src/V3ActiveTop.cpp
clang-format -i src/V3ActiveTop.h
clang-format -i src/V3Assert.cpp
clang-format -i src/V3Assert.h
clang-format -i src/V3AssertPre.cpp
clang-format -i src/V3AssertPre.h
##clang-format -i src/V3Ast.cpp
##clang-format -i src/V3Ast.h
clang-format -i src/V3AstConstOnly.h
##clang-format -i src/V3AstNodes.cpp
##clang-format -i src/V3AstNodes.h
##clang-format -i src/V3Begin.cpp
clang-format -i src/V3Begin.h
clang-format -i src/V3Branch.cpp
clang-format -i src/V3Branch.h
##clang-format -i src/V3Broken.cpp
clang-format -i src/V3Broken.h
##clang-format -i src/V3CCtors.cpp
clang-format -i src/V3CCtors.h
clang-format -i src/V3CUse.cpp
clang-format -i src/V3CUse.h
##clang-format -i src/V3Case.cpp
clang-format -i src/V3Case.h
##clang-format -i src/V3Cast.cpp
clang-format -i src/V3Cast.h
##clang-format -i src/V3Cdc.cpp
clang-format -i src/V3Cdc.h
##clang-format -i src/V3Changed.cpp
clang-format -i src/V3Changed.h
clang-format -i src/V3Class.cpp
clang-format -i src/V3Class.h
##clang-format -i src/V3Clean.cpp
clang-format -i src/V3Clean.h
##clang-format -i src/V3Clock.cpp
clang-format -i src/V3Clock.h
##clang-format -i src/V3Combine.cpp
clang-format -i src/V3Combine.h
clang-format -i src/V3Config.cpp
clang-format -i src/V3Config.h
##clang-format -i src/V3Const.cpp
clang-format -i src/V3Const.h
clang-format -i src/V3Coverage.cpp
clang-format -i src/V3Coverage.h
clang-format -i src/V3CoverageJoin.cpp
clang-format -i src/V3CoverageJoin.h
##clang-format -i src/V3Dead.cpp
clang-format -i src/V3Dead.h
##clang-format -i src/V3Delayed.cpp
clang-format -i src/V3Delayed.h
clang-format -i src/V3Depth.cpp
clang-format -i src/V3Depth.h
clang-format -i src/V3DepthBlock.cpp
clang-format -i src/V3DepthBlock.h
clang-format -i src/V3Descope.cpp
clang-format -i src/V3Descope.h
##clang-format -i src/V3EmitC.cpp
clang-format -i src/V3EmitC.h
##clang-format -i src/V3EmitCBase.h
clang-format -i src/V3EmitCInlines.cpp
##clang-format -i src/V3EmitCMake.cpp
clang-format -i src/V3EmitCMake.h
##clang-format -i src/V3EmitCSyms.cpp
##clang-format -i src/V3EmitMk.cpp
clang-format -i src/V3EmitMk.h
##clang-format -i src/V3EmitV.cpp
clang-format -i src/V3EmitV.h
##clang-format -i src/V3EmitXml.cpp
clang-format -i src/V3EmitXml.h
##clang-format -i src/V3Error.cpp
##clang-format -i src/V3Error.h
##clang-format -i src/V3Expand.cpp
clang-format -i src/V3Expand.h
##clang-format -i src/V3File.cpp
##clang-format -i src/V3File.h
##clang-format -i src/V3FileLine.cpp
##clang-format -i src/V3FileLine.h
##clang-format -i src/V3Gate.cpp
clang-format -i src/V3Gate.h
##clang-format -i src/V3GenClk.cpp
clang-format -i src/V3GenClk.h
clang-format -i src/V3Global.cpp
clang-format -i src/V3Global.h
##clang-format -i src/V3Graph.cpp
clang-format -i src/V3Graph.h
##clang-format -i src/V3GraphAcyc.cpp
##clang-format -i src/V3GraphAlg.cpp
clang-format -i src/V3GraphAlg.h
clang-format -i src/V3GraphDfa.cpp
clang-format -i src/V3GraphDfa.h
clang-format -i src/V3GraphPathChecker.cpp
clang-format -i src/V3GraphPathChecker.h
clang-format -i src/V3GraphStream.h
##clang-format -i src/V3GraphTest.cpp
##clang-format -i src/V3Hashed.cpp
clang-format -i src/V3Hashed.h
##clang-format -i src/V3Inline.cpp
clang-format -i src/V3Inline.h
##clang-format -i src/V3Inst.cpp
clang-format -i src/V3Inst.h
clang-format -i src/V3InstrCount.cpp
clang-format -i src/V3InstrCount.h
clang-format -i src/V3LangCode.h
clang-format -i src/V3LanguageWords.h
##clang-format -i src/V3Life.cpp
clang-format -i src/V3Life.h
##clang-format -i src/V3LifePost.cpp
clang-format -i src/V3LifePost.h
##clang-format -i src/V3LinkCells.cpp
clang-format -i src/V3LinkCells.h
##clang-format -i src/V3LinkDot.cpp
clang-format -i src/V3LinkDot.h
##clang-format -i src/V3LinkJump.cpp
clang-format -i src/V3LinkJump.h
clang-format -i src/V3LinkLValue.cpp
clang-format -i src/V3LinkLValue.h
##clang-format -i src/V3LinkLevel.cpp
clang-format -i src/V3LinkLevel.h
##clang-format -i src/V3LinkParse.cpp
clang-format -i src/V3LinkParse.h
##clang-format -i src/V3LinkResolve.cpp
clang-format -i src/V3LinkResolve.h
clang-format -i src/V3List.h
clang-format -i src/V3Localize.cpp
clang-format -i src/V3Localize.h
clang-format -i src/V3Name.cpp
clang-format -i src/V3Name.h
##clang-format -i src/V3Number.cpp
##clang-format -i src/V3Number.h
clang-format -i src/V3Number_test.cpp
##clang-format -i src/V3Options.cpp
##clang-format -i src/V3Options.h
##clang-format -i src/V3Order.cpp
clang-format -i src/V3Order.h
clang-format -i src/V3OrderGraph.h
##clang-format -i src/V3Os.cpp
clang-format -i src/V3Os.h
##clang-format -i src/V3Param.cpp
clang-format -i src/V3Param.h
clang-format -i src/V3Parse.h
##clang-format -i src/V3ParseGrammar.cpp
##clang-format -i src/V3ParseImp.cpp
##clang-format -i src/V3ParseImp.h
clang-format -i src/V3ParseLex.cpp
clang-format -i src/V3ParseSym.h
##clang-format -i src/V3Partition.cpp
clang-format -i src/V3Partition.h
clang-format -i src/V3PartitionGraph.h
clang-format -i src/V3PreLex.h
##clang-format -i src/V3PreProc.cpp
clang-format -i src/V3PreProc.h
clang-format -i src/V3PreShell.cpp
clang-format -i src/V3PreShell.h
##clang-format -i src/V3Premit.cpp
clang-format -i src/V3Premit.h
##clang-format -i src/V3ProtectLib.cpp
clang-format -i src/V3ProtectLib.h
clang-format -i src/V3Reloop.cpp
clang-format -i src/V3Reloop.h
##clang-format -i src/V3Scope.cpp
clang-format -i src/V3Scope.h
clang-format -i src/V3Scoreboard.cpp
clang-format -i src/V3Scoreboard.h
clang-format -i src/V3SenTree.h
##clang-format -i src/V3Simulate.h
##clang-format -i src/V3Slice.cpp
clang-format -i src/V3Slice.h
##clang-format -i src/V3Split.cpp
clang-format -i src/V3Split.h
##clang-format -i src/V3SplitAs.cpp
clang-format -i src/V3SplitAs.h
##clang-format -i src/V3SplitVar.cpp
clang-format -i src/V3SplitVar.h
clang-format -i src/V3Stats.cpp
clang-format -i src/V3Stats.h
clang-format -i src/V3StatsReport.cpp
clang-format -i src/V3String.cpp
clang-format -i src/V3String.h
##clang-format -i src/V3Subst.cpp
clang-format -i src/V3Subst.h
clang-format -i src/V3SymTable.h
##clang-format -i src/V3TSP.cpp
clang-format -i src/V3TSP.h
##clang-format -i src/V3Table.cpp
clang-format -i src/V3Table.h
##clang-format -i src/V3Task.cpp
clang-format -i src/V3Task.h
clang-format -i src/V3Trace.cpp
clang-format -i src/V3Trace.h
clang-format -i src/V3TraceDecl.cpp
clang-format -i src/V3TraceDecl.h
##clang-format -i src/V3Tristate.cpp
clang-format -i src/V3Tristate.h
##clang-format -i src/V3Undriven.cpp
clang-format -i src/V3Undriven.h
##clang-format -i src/V3Unknown.cpp
clang-format -i src/V3Unknown.h
##clang-format -i src/V3Unroll.cpp
clang-format -i src/V3Unroll.h
##clang-format -i src/V3Width.cpp
clang-format -i src/V3Width.h
clang-format -i src/V3WidthCommit.h
##clang-format -i src/V3WidthSel.cpp
##clang-format -i src/Verilator.cpp
clang-format -i src/VlcBucket.h
clang-format -i src/VlcMain.cpp
clang-format -i src/VlcOptions.h
clang-format -i src/VlcPoint.h
clang-format -i src/VlcSource.h
clang-format -i src/VlcTest.h
clang-format -i src/VlcTop.cpp
clang-format -i src/VlcTop.h
clang-format -i src/config_build.h.in

View File

@ -50,11 +50,11 @@ protected:
class ActiveNamer : public ActiveBaseVisitor {
private:
typedef std::map<string,AstActive*> ActiveNameMap;
typedef std::map<string, AstActive*> ActiveNameMap;
// STATE
AstScope* m_scopep; // Current scope to add statement to
AstActive* m_iActivep; // For current scope, the IActive we're building
AstActive* m_cActivep; // For current scope, the SActive(combo) we're building
AstScope* m_scopep; // Current scope to add statement to
AstActive* m_iActivep; // For current scope, the IActive we're building
AstActive* m_cActivep; // For current scope, the SActive(combo) we're building
SenTreeSet m_activeSens; // Sen lists for each active we've made
typedef vl_unordered_map<AstSenTree*, AstActive*> ActiveMap;
@ -89,8 +89,7 @@ public:
AstActive* getCActive(FileLine* fl) {
if (!m_cActivep) {
m_cActivep = new AstActive(
fl, "combo",
new AstSenTree(fl, new AstSenItem(fl, AstSenItem::Combo())));
fl, "combo", new AstSenTree(fl, new AstSenItem(fl, AstSenItem::Combo())));
m_cActivep->sensesStorep(m_cActivep->sensesp());
addActive(m_cActivep);
}
@ -99,8 +98,7 @@ public:
AstActive* getIActive(FileLine* fl) {
if (!m_iActivep) {
m_iActivep = new AstActive(
fl, "initial",
new AstSenTree(fl, new AstSenItem(fl, AstSenItem::Initial())));
fl, "initial", new AstSenTree(fl, new AstSenItem(fl, AstSenItem::Initial())));
m_iActivep->sensesStorep(m_iActivep->sensesp());
addActive(m_iActivep);
}
@ -122,7 +120,7 @@ public:
AstSenTree* newsenp = sensesp->cloneTree(false);
activep = new AstActive(fl, "sequent", newsenp);
activep->sensesStorep(activep->sensesp());
UINFO(8," New ACTIVE "<<activep<<endl);
UINFO(8, " New ACTIVE " << activep << endl);
// Form the sensitivity list
addActive(activep);
m_activeMap[newsenp] = activep;
@ -131,6 +129,7 @@ public:
}
return activep;
}
public:
// CONSTRUCTORS
ActiveNamer() {
@ -139,9 +138,7 @@ public:
m_cActivep = NULL;
}
virtual ~ActiveNamer() {}
void main(AstScope* nodep) {
iterate(nodep);
}
void main(AstScope* nodep) { iterate(nodep); }
};
//######################################################################
@ -150,27 +147,29 @@ public:
class ActiveDlyVisitor : public ActiveBaseVisitor {
public:
enum CheckType { CT_SEQ, CT_COMBO, CT_INITIAL, CT_LATCH };
private:
CheckType m_check; // Combo logic or other
AstNode* m_alwaysp; // Always we're under
AstNode* m_assignp; // In assign
CheckType m_check; // Combo logic or other
AstNode* m_alwaysp; // Always we're under
AstNode* m_assignp; // In assign
// VISITORS
virtual void visit(AstAssignDly* nodep) VL_OVERRIDE {
if (m_check != CT_SEQ) {
// Convert to a non-delayed assignment
UINFO(5," ASSIGNDLY "<<nodep<<endl);
UINFO(5, " ASSIGNDLY " << nodep << endl);
if (m_check == CT_INITIAL) {
nodep->v3warn(INITIALDLY, "Delayed assignments (<=) in initial or final block\n"
<<nodep->warnMore()<<"... Suggest blocking assignments (=)");
<< nodep->warnMore()
<< "... Suggest blocking assignments (=)");
} else if (m_check == CT_LATCH) {
// Suppress. Shouldn't matter that the interior of the latch races
} else {
nodep->v3warn(COMBDLY, "Delayed assignments (<=) in non-clocked"
" (non flop or latch) block\n"
<<nodep->warnMore()<<"... Suggest blocking assignments (=)");
" (non flop or latch) block\n"
<< nodep->warnMore()
<< "... Suggest blocking assignments (=)");
}
AstNode* newp = new AstAssign(nodep->fileline(),
nodep->lhsp()->unlinkFrBack(),
AstNode* newp = new AstAssign(nodep->fileline(), nodep->lhsp()->unlinkFrBack(),
nodep->rhsp()->unlinkFrBack());
nodep->replaceWith(newp);
VL_DO_DANGLING(nodep->deleteTree(), nodep);
@ -186,17 +185,18 @@ private:
}
virtual void visit(AstVarRef* nodep) VL_OVERRIDE {
AstVar* varp = nodep->varp();
if (m_check == CT_SEQ
&& m_assignp
&& !varp->isUsedLoopIdx() // Ignore loop indices
if (m_check == CT_SEQ && m_assignp && !varp->isUsedLoopIdx() // Ignore loop indices
&& !varp->isTemp()) {
// Allow turning off warnings on the always, or the variable also
if (!m_alwaysp->fileline()->warnIsOff(V3ErrorCode::BLKSEQ)
&& !m_assignp->fileline()->warnIsOff(V3ErrorCode::BLKSEQ)
&& !varp->fileline()->warnIsOff(V3ErrorCode::BLKSEQ)) {
m_assignp->v3warn(BLKSEQ, "Blocking assignments (=) in sequential (flop or latch) block\n"
<<m_assignp->warnMore()<<"... Suggest delayed assignments (<=)");
m_alwaysp->fileline()->modifyWarnOff(V3ErrorCode::BLKSEQ, true); // Complain just once for the entire always
m_assignp->v3warn(BLKSEQ,
"Blocking assignments (=) in sequential (flop or latch) block\n"
<< m_assignp->warnMore()
<< "... Suggest delayed assignments (<=)");
m_alwaysp->fileline()->modifyWarnOff(
V3ErrorCode::BLKSEQ, true); // Complain just once for the entire always
varp->fileline()->modifyWarnOff(V3ErrorCode::BLKSEQ, true);
}
}
@ -225,15 +225,15 @@ private:
// AstNode::user4() Used by V3Const::constify, called below
// STATE
ActiveNamer m_namer; // Tracking of active names
AstCFunc* m_scopeFinalp; // Final function for this scope
bool m_itemCombo; // Found a SenItem combo
bool m_itemSequent; // Found a SenItem sequential
ActiveNamer m_namer; // Tracking of active names
AstCFunc* m_scopeFinalp; // Final function for this scope
bool m_itemCombo; // Found a SenItem combo
bool m_itemSequent; // Found a SenItem sequential
// VISITORS
virtual void visit(AstScope* nodep) VL_OVERRIDE {
// Create required actives and add to scope
UINFO(4," SCOPE "<<nodep<<endl);
UINFO(4, " SCOPE " << nodep << endl);
// Clear last scope's names, and collect this scope's existing names
m_namer.main(nodep);
m_scopeFinalp = NULL;
@ -244,48 +244,47 @@ private:
}
virtual void visit(AstInitial* nodep) VL_OVERRIDE {
// Relink to IACTIVE, unless already under it
UINFO(4," INITIAL "<<nodep<<endl);
ActiveDlyVisitor dlyvisitor (nodep, ActiveDlyVisitor::CT_INITIAL);
UINFO(4, " INITIAL " << nodep << endl);
ActiveDlyVisitor dlyvisitor(nodep, ActiveDlyVisitor::CT_INITIAL);
AstActive* wantactivep = m_namer.getIActive(nodep->fileline());
nodep->unlinkFrBack();
wantactivep->addStmtsp(nodep);
}
virtual void visit(AstAssignAlias* nodep) VL_OVERRIDE {
// Relink to CACTIVE, unless already under it
UINFO(4," ASSIGNW "<<nodep<<endl);
UINFO(4, " ASSIGNW " << nodep << endl);
AstActive* wantactivep = m_namer.getCActive(nodep->fileline());
nodep->unlinkFrBack();
wantactivep->addStmtsp(nodep);
}
virtual void visit(AstAssignW* nodep) VL_OVERRIDE {
// Relink to CACTIVE, unless already under it
UINFO(4," ASSIGNW "<<nodep<<endl);
UINFO(4, " ASSIGNW " << nodep << endl);
AstActive* wantactivep = m_namer.getCActive(nodep->fileline());
nodep->unlinkFrBack();
wantactivep->addStmtsp(nodep);
}
virtual void visit(AstCoverToggle* nodep) VL_OVERRIDE {
// Relink to CACTIVE, unless already under it
UINFO(4," COVERTOGGLE "<<nodep<<endl);
UINFO(4, " COVERTOGGLE " << nodep << endl);
AstActive* wantactivep = m_namer.getCActive(nodep->fileline());
nodep->unlinkFrBack();
wantactivep->addStmtsp(nodep);
}
virtual void visit(AstFinal* nodep) VL_OVERRIDE {
// Relink to CFUNC for the final
UINFO(4," FINAL "<<nodep<<endl);
UINFO(4, " FINAL " << nodep << endl);
if (!nodep->bodysp()) { // Empty, Kill it.
VL_DO_DANGLING(nodep->unlinkFrBack()->deleteTree(), nodep);
return;
}
ActiveDlyVisitor dlyvisitor (nodep, ActiveDlyVisitor::CT_INITIAL);
ActiveDlyVisitor dlyvisitor(nodep, ActiveDlyVisitor::CT_INITIAL);
if (!m_scopeFinalp) {
m_scopeFinalp = new AstCFunc(
nodep->fileline(), "_final_"+m_namer.scopep()->nameDotless(),
m_namer.scopep());
nodep->fileline(), "_final_" + m_namer.scopep()->nameDotless(), m_namer.scopep());
m_scopeFinalp->argTypes(EmitCBaseVisitor::symClassVar());
m_scopeFinalp->addInitsp(
new AstCStmt(nodep->fileline(), EmitCBaseVisitor::symTopAssign()+"\n"));
new AstCStmt(nodep->fileline(), EmitCBaseVisitor::symTopAssign() + "\n"));
m_scopeFinalp->dontCombine(true);
m_scopeFinalp->formCallTree(true);
m_scopeFinalp->slow(true);
@ -300,9 +299,7 @@ private:
// METHODS
void visitAlways(AstNode* nodep, AstSenTree* oldsensesp, VAlwaysKwd kwd) {
// Move always to appropriate ACTIVE based on its sense list
if (oldsensesp
&& oldsensesp->sensesp()
&& VN_IS(oldsensesp->sensesp(), SenItem)
if (oldsensesp && oldsensesp->sensesp() && VN_IS(oldsensesp->sensesp(), SenItem)
&& VN_CAST(oldsensesp->sensesp(), SenItem)->isNever()) {
// Never executing. Kill it.
UASSERT_OBJ(!oldsensesp->sensesp()->nextp(), nodep,
@ -318,10 +315,11 @@ private:
bool combo = m_itemCombo;
bool sequent = m_itemSequent;
if (!combo && !sequent) combo=true; // If no list, Verilog 2000: always @ (*)
if (!combo && !sequent) combo = true; // If no list, Verilog 2000: always @ (*)
if (combo && sequent) {
if (!v3Global.opt.bboxUnsup()) {
nodep->v3error("Unsupported: Mixed edge (pos/negedge) and activity (no edge) sensitive activity list");
nodep->v3error("Unsupported: Mixed edge (pos/negedge) and activity "
"(no edge) sensitive activity list");
}
sequent = false;
}
@ -336,8 +334,9 @@ private:
// always (posedge RESET) { if (RESET).... } we know RESET is true.
// Summarize a long list of combo inputs as just "combo"
#ifndef __COVERITY__ // Else dead code on next line.
if (combo) oldsensesp->addSensesp
(new AstSenItem(nodep->fileline(), AstSenItem::Combo()));
if (combo) {
oldsensesp->addSensesp(new AstSenItem(nodep->fileline(), AstSenItem::Combo()));
}
#endif
wantactivep = m_namer.getActive(nodep->fileline(), oldsensesp);
}
@ -354,19 +353,18 @@ private:
// Warn and/or convert any delayed assignments
if (combo && !sequent) {
if (kwd == VAlwaysKwd::ALWAYS_LATCH) {
ActiveDlyVisitor dlyvisitor (nodep, ActiveDlyVisitor::CT_LATCH);
ActiveDlyVisitor dlyvisitor(nodep, ActiveDlyVisitor::CT_LATCH);
} else {
ActiveDlyVisitor dlyvisitor (nodep, ActiveDlyVisitor::CT_COMBO);
ActiveDlyVisitor dlyvisitor(nodep, ActiveDlyVisitor::CT_COMBO);
}
}
else if (!combo && sequent) {
ActiveDlyVisitor dlyvisitor (nodep, ActiveDlyVisitor::CT_SEQ);
} else if (!combo && sequent) {
ActiveDlyVisitor dlyvisitor(nodep, ActiveDlyVisitor::CT_SEQ);
}
}
virtual void visit(AstAlways* nodep) VL_OVERRIDE {
// Move always to appropriate ACTIVE based on its sense list
UINFO(4," ALW "<<nodep<<endl);
//if (debug()>=9) nodep->dumpTree(cout, " Alw: ");
UINFO(4, " ALW " << nodep << endl);
// if (debug()>=9) nodep->dumpTree(cout, " Alw: ");
if (!nodep->bodysp()) {
// Empty always. Kill it.
@ -377,15 +375,15 @@ private:
}
virtual void visit(AstAlwaysPublic* nodep) VL_OVERRIDE {
// Move always to appropriate ACTIVE based on its sense list
UINFO(4," ALWPub "<<nodep<<endl);
//if (debug()>=9) nodep->dumpTree(cout, " Alw: ");
UINFO(4, " ALWPub " << nodep << endl);
// if (debug()>=9) nodep->dumpTree(cout, " Alw: ");
visitAlways(nodep, nodep->sensesp(), VAlwaysKwd::ALWAYS);
}
virtual void visit(AstSenGate* nodep) VL_OVERRIDE {
AstSenItem* subitemp = nodep->sensesp();
UASSERT_OBJ(subitemp->edgeType() == VEdgeType::ET_ANYEDGE
|| subitemp->edgeType() == VEdgeType::ET_POSEDGE
|| subitemp->edgeType() == VEdgeType::ET_NEGEDGE,
|| subitemp->edgeType() == VEdgeType::ET_POSEDGE
|| subitemp->edgeType() == VEdgeType::ET_NEGEDGE,
nodep, "Strange activity type under SenGate");
iterateChildren(nodep);
}
@ -399,7 +397,7 @@ private:
// V3LinkResolve should have cleaned most of these up
if (!nodep->varrefp()->width1()) {
nodep->v3error("Unsupported: Non-single bit wide signal pos/negedge sensitivity: "
<<nodep->varrefp()->prettyNameQ());
<< nodep->varrefp()->prettyNameQ());
}
m_itemSequent = true;
nodep->varrefp()->varp()->usedClock(true);
@ -426,9 +424,7 @@ public:
// Active class functions
void V3Active::activeAll(AstNetlist* nodep) {
UINFO(2,__FUNCTION__<<": "<<endl);
{
ActiveVisitor visitor (nodep);
} // Destruct before checking
UINFO(2, __FUNCTION__ << ": " << endl);
{ ActiveVisitor visitor(nodep); } // Destruct before checking
V3Global::dumpCheckGlobalTree("active", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
}

View File

@ -42,11 +42,11 @@ private:
// AstNode::user() bool. True if processed
// Each call to V3Const::constify
// AstNode::user4() Used by V3Const::constify, called below
AstUser1InUse m_inuser1;
AstUser1InUse m_inuser1;
// STATE
AstTopScope* m_topscopep; // Top scope for adding sentrees under
SenTreeFinder m_finder; // Find global sentree's and add them
AstTopScope* m_topscopep; // Top scope for adding sentrees under
SenTreeFinder m_finder; // Find global sentree's and add them
// METHODS
VL_DEBUG_FUNC; // Declare debug()
@ -61,16 +61,16 @@ private:
virtual void visit(AstNodeModule* nodep) VL_OVERRIDE {
// Create required actives and add to module
// We can start ordering at a module, or a scope
UINFO(4," MOD "<<nodep<<endl);
UINFO(4, " MOD " << nodep << endl);
iterateChildren(nodep);
}
virtual void visit(AstActive* nodep) VL_OVERRIDE {
UINFO(4," ACTIVE "<<nodep<<endl);
V3Const::constifyExpensiveEdit(nodep); // Remove duplicate clocks and such; sensesp() may change!
UINFO(4, " ACTIVE " << nodep << endl);
// Remove duplicate clocks and such; sensesp() may change!
V3Const::constifyExpensiveEdit(nodep);
AstSenTree* sensesp = nodep->sensesp();
UASSERT_OBJ(sensesp, nodep, "NULL");
if (sensesp->sensesp()
&& VN_IS(sensesp->sensesp(), SenItem)
if (sensesp->sensesp() && VN_IS(sensesp->sensesp(), SenItem)
&& VN_CAST(sensesp->sensesp(), SenItem)->isNever()) {
// Never executing. Kill it.
UASSERT_OBJ(!sensesp->sensesp()->nextp(), nodep,
@ -80,10 +80,9 @@ private:
}
// Copy combo tree to settlement tree with duplicated statements
if (sensesp->hasCombo()) {
AstSenTree* newsentreep
= new AstSenTree(nodep->fileline(),
new AstSenItem(nodep->fileline(), AstSenItem::Settle()));
AstActive* newp = new AstActive(nodep->fileline(),"settle", newsentreep);
AstSenTree* newsentreep = new AstSenTree(
nodep->fileline(), new AstSenItem(nodep->fileline(), AstSenItem::Settle()));
AstActive* newp = new AstActive(nodep->fileline(), "settle", newsentreep);
newp->sensesStorep(newsentreep);
if (nodep->stmtsp()) newp->addStmtsp(nodep->stmtsp()->cloneTree(true));
nodep->addNextHere(newp);
@ -91,10 +90,10 @@ private:
// Move the SENTREE for each active up to the global level.
// This way we'll easily see what clock domains are identical
AstSenTree* wantp = m_finder.getSenTree(nodep->fileline(), sensesp);
UINFO(4," lookdone\n");
UINFO(4, " lookdone\n");
if (wantp != sensesp) {
// Move the active's contents to the other active
UINFO(4," merge active "<<sensesp<<" into "<<wantp<<endl);
UINFO(4, " merge active " << sensesp << " into " << wantp << endl);
if (nodep->sensesStorep()) {
UASSERT_OBJ(sensesp == nodep->sensesStorep(), nodep,
"sensesStore should have been deleted earlier if different");
@ -107,7 +106,7 @@ private:
nodep->sensesp(wantp);
}
// No need to do statements under it, they're already moved.
//iterateChildren(nodep);
// iterateChildren(nodep);
}
virtual void visit(AstInitial* nodep) VL_OVERRIDE { // LCOV_EXCL_LINE
nodep->v3fatalSrc("Node should have been under ACTIVE");
@ -145,9 +144,7 @@ public:
// Active class functions
void V3ActiveTop::activeTopAll(AstNetlist* nodep) {
UINFO(2,__FUNCTION__<<": "<<endl);
{
ActiveTopVisitor visitor (nodep);
} // Destruct before checking
UINFO(2, __FUNCTION__ << ": " << endl);
{ ActiveTopVisitor visitor(nodep); } // Destruct before checking
V3Global::dumpCheckGlobalTree("activetop", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
}

View File

@ -34,24 +34,22 @@ private:
// NODE STATE/TYPES
// Cleared on netlist
// AstNode::user() -> bool. True if processed
AstUser1InUse m_inuser1;
AstUser1InUse m_inuser1;
// STATE
AstNodeModule* m_modp; // Last module
AstBegin* m_beginp; // Last begin
unsigned m_modPastNum; // Module past numbering
VDouble0 m_statCover; // Statistic tracking
VDouble0 m_statAsNotImm; // Statistic tracking
VDouble0 m_statAsImm; // Statistic tracking
VDouble0 m_statAsFull; // Statistic tracking
AstNodeModule* m_modp; // Last module
AstBegin* m_beginp; // Last begin
unsigned m_modPastNum; // Module past numbering
VDouble0 m_statCover; // Statistic tracking
VDouble0 m_statAsNotImm; // Statistic tracking
VDouble0 m_statAsImm; // Statistic tracking
VDouble0 m_statAsFull; // Statistic tracking
// METHODS
string assertDisplayMessage(AstNode* nodep, const string& prefix, const string& message) {
return (string("[%0t] "+prefix+": ")+nodep->fileline()->filebasename()
+":"+cvtToStr(nodep->fileline()->lineno())
+": Assertion failed in %m"
+((message != "")?": ":"")+message
+"\n");
return (string("[%0t] " + prefix + ": ") + nodep->fileline()->filebasename() + ":"
+ cvtToStr(nodep->fileline()->lineno()) + ": Assertion failed in %m"
+ ((message != "") ? ": " : "") + message + "\n");
}
void replaceDisplay(AstDisplay* nodep, const string& prefix) {
nodep->displayType(AstDisplayType::DT_WRITE);
@ -77,8 +75,8 @@ private:
// If assertions are off, have constant propagation rip them out later
// This allows syntax errors and such to be detected normally.
(v3Global.opt.assertOn()
? static_cast<AstNode*>(new AstCMath(fl, "Verilated::assertOn()", 1))
: static_cast<AstNode*>(new AstConst(fl, AstConst::LogicFalse()))),
? static_cast<AstNode*>(new AstCMath(fl, "Verilated::assertOn()", 1))
: static_cast<AstNode*>(new AstConst(fl, AstConst::LogicFalse()))),
nodep, NULL);
newp->user1(true); // Don't assert/cover this if
return newp;
@ -86,8 +84,8 @@ private:
AstNode* newFireAssertUnchecked(AstNode* nodep, const string& message) {
// Like newFireAssert() but omits the asserts-on check
AstDisplay* dispp = new AstDisplay(nodep->fileline(),
AstDisplayType::DT_ERROR, message, NULL, NULL);
AstDisplay* dispp
= new AstDisplay(nodep->fileline(), AstDisplayType::DT_ERROR, message, NULL, NULL);
AstNode* bodysp = dispp;
replaceDisplay(dispp, "%%Error"); // Convert to standard DISPLAY format
bodysp->addNext(new AstStop(nodep->fileline(), true));
@ -129,7 +127,7 @@ private:
AstCoverInc* covincp = VN_CAST(snodep->coverincp(), CoverInc);
UASSERT_OBJ(covincp, snodep, "Missing AstCoverInc under assertion");
covincp->unlinkFrBackWithNext(); // next() might have AstAssign for trace
if (message!="") covincp->declp()->comment(message);
if (message != "") covincp->declp()->comment(message);
bodysp = covincp;
}
@ -137,8 +135,11 @@ private:
ifp = new AstIf(nodep->fileline(), propp, bodysp, NULL);
bodysp = ifp;
} else if (VN_IS(nodep, Assert)) {
if (nodep->immediate()) ++m_statAsImm;
else ++m_statAsNotImm;
if (nodep->immediate()) {
++m_statAsImm;
} else {
++m_statAsNotImm;
}
if (passsp) passsp = newIfAssertOn(passsp);
if (failsp) failsp = newIfAssertOn(failsp);
if (!failsp) failsp = newFireAssertUnchecked(nodep, "'assert' failed.");
@ -153,9 +154,10 @@ private:
AstNode* newp;
if (sentreep) {
newp = new AstAlways(nodep->fileline(),
VAlwaysKwd::ALWAYS, sentreep, bodysp);
} else { newp = bodysp; }
newp = new AstAlways(nodep->fileline(), VAlwaysKwd::ALWAYS, sentreep, bodysp);
} else {
newp = bodysp;
}
// Install it
if (selfDestruct) {
// Delete it after making the tree. This way we can tell the user
@ -186,7 +188,7 @@ private:
iterateAndNextNull(ifp->ifsp());
// If the last else is not an else if, recurse into that too.
if (ifp->elsesp() && !nextifp) {
if (ifp->elsesp() && !nextifp) { //
iterateAndNextNull(ifp->elsesp());
}
@ -199,14 +201,12 @@ private:
}
// Record if this ends with an 'else' that does not have an if
if (ifp->elsesp() && !nextifp) {
hasDefaultElse = true;
}
if (ifp->elsesp() && !nextifp) hasDefaultElse = true;
ifp = nextifp;
} while (ifp);
AstNode *newifp = nodep->cloneTree(false);
AstNode* newifp = nodep->cloneTree(false);
bool allow_none = nodep->unique0Pragma();
// Empty case means no property
@ -215,12 +215,11 @@ private:
// Note: if this ends with an 'else', then we don't need to validate that one of the
// predicates evaluates to true.
AstNode* ohot = ((allow_none || hasDefaultElse)
? static_cast<AstNode*>(new AstOneHot0(nodep->fileline(), propp))
: static_cast<AstNode*>(new AstOneHot(nodep->fileline(), propp)));
AstIf* checkifp = new AstIf(nodep->fileline(),
new AstLogNot(nodep->fileline(), ohot),
newFireAssert(nodep, "'unique if' statement violated"),
newifp);
? static_cast<AstNode*>(new AstOneHot0(nodep->fileline(), propp))
: static_cast<AstNode*>(new AstOneHot(nodep->fileline(), propp)));
AstIf* checkifp
= new AstIf(nodep->fileline(), new AstLogNot(nodep->fileline(), ohot),
newFireAssert(nodep, "'unique if' statement violated"), newifp);
checkifp->branchPred(VBranchPred::BP_UNLIKELY);
nodep->replaceWith(checkifp);
pushDeletep(nodep);
@ -234,16 +233,17 @@ private:
iterateChildren(nodep);
if (!nodep->user1SetOnce()) {
bool has_default = false;
for (AstCaseItem* itemp = nodep->itemsp();
itemp; itemp = VN_CAST(itemp->nextp(), CaseItem)) {
for (AstCaseItem* itemp = nodep->itemsp(); itemp;
itemp = VN_CAST(itemp->nextp(), CaseItem)) {
if (itemp->isDefault()) has_default = true;
}
if (nodep->fullPragma() || nodep->priorityPragma()) {
// Simply need to add a default if there isn't one already
++m_statAsFull;
if (!has_default) {
nodep->addItemsp(new AstCaseItem(nodep->fileline(), NULL/*DEFAULT*/,
newFireAssert(nodep, "synthesis full_case, but non-match found")));
nodep->addItemsp(new AstCaseItem(
nodep->fileline(), NULL /*DEFAULT*/,
newFireAssert(nodep, "synthesis full_case, but non-match found")));
}
}
if (nodep->parallelPragma() || nodep->uniquePragma() || nodep->unique0Pragma()) {
@ -271,8 +271,11 @@ private:
nodep->exprp()->cloneTree(false),
icondp->cloneTree(false));
}
if (propp) propp = new AstConcat(icondp->fileline(), onep, propp);
else propp = onep;
if (propp) {
propp = new AstConcat(icondp->fileline(), onep, propp);
} else {
propp = onep;
}
}
}
// Empty case means no property
@ -281,12 +284,13 @@ private:
bool allow_none = has_default || nodep->unique0Pragma();
AstNode* ohot
= (allow_none
? static_cast<AstNode*>(new AstOneHot0(nodep->fileline(), propp))
: static_cast<AstNode*>(new AstOneHot(nodep->fileline(), propp)));
AstIf* ifp = new AstIf(nodep->fileline(),
new AstLogNot(nodep->fileline(), ohot),
newFireAssert(nodep, "synthesis parallel_case, but multiple matches found"),
NULL);
? static_cast<AstNode*>(new AstOneHot0(nodep->fileline(), propp))
: static_cast<AstNode*>(new AstOneHot(nodep->fileline(), propp)));
AstIf* ifp = new AstIf(
nodep->fileline(), new AstLogNot(nodep->fileline(), ohot),
newFireAssert(nodep,
"synthesis parallel_case, but multiple matches found"),
NULL);
ifp->branchPred(VBranchPred::BP_UNLIKELY);
nodep->addNotParallelp(ifp);
}
@ -303,23 +307,22 @@ private:
"Expected constant ticks, checked in V3Width");
ticks = VN_CAST(nodep->ticksp(), Const)->toUInt();
}
UASSERT_OBJ(ticks>=1, nodep, "0 tick should have been checked in V3Width");
UASSERT_OBJ(ticks >= 1, nodep, "0 tick should have been checked in V3Width");
AstNode* inp = nodep->exprp()->unlinkFrBack();
AstVar* invarp = NULL;
AstSenTree* sentreep = nodep->sentreep(); sentreep->unlinkFrBack();
AstAlways* alwaysp = new AstAlways(nodep->fileline(), VAlwaysKwd::ALWAYS,
sentreep, NULL);
AstSenTree* sentreep = nodep->sentreep();
sentreep->unlinkFrBack();
AstAlways* alwaysp = new AstAlways(nodep->fileline(), VAlwaysKwd::ALWAYS, sentreep, NULL);
m_modp->addStmtp(alwaysp);
for (uint32_t i=0; i<ticks; ++i) {
for (uint32_t i = 0; i < ticks; ++i) {
AstVar* outvarp = new AstVar(nodep->fileline(), AstVarType::MODULETEMP,
"_Vpast_"+cvtToStr(m_modPastNum++)+"_"+cvtToStr(i),
"_Vpast_" + cvtToStr(m_modPastNum++) + "_" + cvtToStr(i),
inp->dtypep());
m_modp->addStmtp(outvarp);
AstNode* assp = new AstAssignDly(nodep->fileline(),
new AstVarRef(nodep->fileline(), outvarp, true),
inp);
new AstVarRef(nodep->fileline(), outvarp, true), inp);
alwaysp->addStmtp(assp);
//if (debug()>-9) assp->dumpTree(cout, "-ass: ");
// if (debug()>-9) assp->dumpTree(cout, "-ass: ");
invarp = outvarp;
inp = new AstVarRef(nodep->fileline(), invarp, false);
}
@ -334,12 +337,12 @@ private:
virtual void visit(AstDisplay* nodep) VL_OVERRIDE {
iterateChildren(nodep);
// Replace the special types with standard text
if (nodep->displayType()==AstDisplayType::DT_INFO) {
if (nodep->displayType() == AstDisplayType::DT_INFO) {
replaceDisplay(nodep, "-Info");
} else if (nodep->displayType()==AstDisplayType::DT_WARNING) {
} else if (nodep->displayType() == AstDisplayType::DT_WARNING) {
replaceDisplay(nodep, "%%Warning");
} else if (nodep->displayType()==AstDisplayType::DT_ERROR
|| nodep->displayType()==AstDisplayType::DT_FATAL) {
} else if (nodep->displayType() == AstDisplayType::DT_ERROR
|| nodep->displayType() == AstDisplayType::DT_FATAL) {
replaceDisplay(nodep, "%%Error");
}
}
@ -403,9 +406,7 @@ public:
// Top Assert class
void V3Assert::assertAll(AstNetlist* nodep) {
UINFO(2,__FUNCTION__<<": "<<endl);
{
AssertVisitor visitor (nodep);
} // Destruct before checking
UINFO(2, __FUNCTION__ << ": " << endl);
{ AssertVisitor visitor(nodep); } // Destruct before checking
V3Global::dumpCheckGlobalTree("assert", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
}

View File

@ -61,14 +61,12 @@ private:
}
return newp;
}
void clearAssertInfo() {
m_senip = NULL;
}
void clearAssertInfo() { m_senip = NULL; }
// VISITORS
//========== Statements
virtual void visit(AstClocking* nodep) VL_OVERRIDE {
UINFO(8," CLOCKING"<<nodep<<endl);
UINFO(8, " CLOCKING" << nodep << endl);
// Store the new default clock, reset on new module
m_seniDefaultp = nodep->sensesp();
// Trash it, keeping children
@ -81,9 +79,7 @@ private:
}
virtual void visit(AstAlways* nodep) VL_OVERRIDE {
iterateAndNextNull(nodep->sensesp());
if (nodep->sensesp()) {
m_seniAlwaysp = nodep->sensesp()->sensesp();
}
if (nodep->sensesp()) m_seniAlwaysp = nodep->sensesp()->sensesp();
iterateAndNextNull(nodep->bodysp());
m_seniAlwaysp = NULL;
}
@ -93,9 +89,7 @@ private:
clearAssertInfo();
// Find Clocking's buried under nodep->exprsp
iterateChildren(nodep);
if (!nodep->immediate()) {
nodep->sentreep(newSenTree(nodep));
}
if (!nodep->immediate()) nodep->sentreep(newSenTree(nodep));
clearAssertInfo();
}
virtual void visit(AstPast* nodep) VL_OVERRIDE {
@ -106,21 +100,18 @@ private:
virtual void visit(AstPropClocked* nodep) VL_OVERRIDE {
// No need to iterate the body, once replace will get iterated
iterateAndNextNull(nodep->sensesp());
if (m_senip) {
nodep->v3error("Unsupported: Only one PSL clock allowed per assertion");
}
if (m_senip) nodep->v3error("Unsupported: Only one PSL clock allowed per assertion");
// Block is the new expression to evaluate
AstNode* blockp = nodep->propp()->unlinkFrBack();
if (nodep->disablep()) {
if (VN_IS(nodep->backp(), Cover)) {
blockp = new AstAnd(nodep->disablep()->fileline(),
new AstNot(nodep->disablep()->fileline(),
nodep->disablep()->unlinkFrBack()),
blockp);
blockp = new AstAnd(
nodep->disablep()->fileline(),
new AstNot(nodep->disablep()->fileline(), nodep->disablep()->unlinkFrBack()),
blockp);
} else {
blockp = new AstOr(nodep->disablep()->fileline(),
nodep->disablep()->unlinkFrBack(),
blockp);
nodep->disablep()->unlinkFrBack(), blockp);
}
}
// Unlink and just keep a pointer to it, convert to sentree as needed
@ -151,9 +142,7 @@ public:
// Top Assert class
void V3AssertPre::assertPreAll(AstNetlist* nodep) {
UINFO(2,__FUNCTION__<<": "<<endl);
{
AssertPreVisitor visitor (nodep);
} // Destruct before checking
UINFO(2, __FUNCTION__ << ": " << endl);
{ AssertPreVisitor visitor(nodep); } // Destruct before checking
V3Global::dumpCheckGlobalTree("assertpre", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
}

View File

@ -18,12 +18,12 @@
#define _V3ASTCONSTONLY_H_ 1
// Include only in visitors that do not not edit nodes, so should use constant iterators
#define iterateAndNext error_use_iterateAndNextConst
#define iterateChildren error_use_iterateChildrenConst
#define iterateAndNext error_use_iterateAndNextConst
#define iterateChildren error_use_iterateChildrenConst
#define addNext error_no_addNext_in_ConstOnlyVisitor
#define replaceWith error_no_replaceWith_in_ConstOnlyVisitor
#define deleteTree error_no_deleteTree_in_ConstOnlyVisitor
#define unlinkFrBack error_no_unlinkFrBack_in_ConstOnlyVisitor
#define addNext error_no_addNext_in_ConstOnlyVisitor
#define replaceWith error_no_replaceWith_in_ConstOnlyVisitor
#define deleteTree error_no_deleteTree_in_ConstOnlyVisitor
#define unlinkFrBack error_no_unlinkFrBack_in_ConstOnlyVisitor
#endif // Guard

View File

@ -41,15 +41,15 @@ private:
// NODE STATE
// Entire netlist:
// AstFTask::user1() -> int. Number of references
AstUser1InUse m_inuser1;
AstUser1InUse m_inuser1;
// TYPES
typedef std::vector<AstCFunc*> CFuncVec;
// STATE
int m_likely; // Excuses for branch likely taken
int m_unlikely; // Excuses for branch likely not taken
CFuncVec m_cfuncsp; // List of all tasks
int m_likely; // Excuses for branch likely taken
int m_unlikely; // Excuses for branch likely not taken
CFuncVec m_cfuncsp; // List of all tasks
// METHODS
VL_DEBUG_FUNC; // Declare debug()
@ -60,14 +60,14 @@ private:
}
void checkUnlikely(AstNode* nodep) {
if (nodep->isUnlikely()) {
UINFO(4," UNLIKELY: "<<nodep<<endl);
UINFO(4, " UNLIKELY: " << nodep << endl);
m_unlikely++;
}
}
// VISITORS
virtual void visit(AstNodeIf* nodep) VL_OVERRIDE {
UINFO(4," IF: "<<nodep<<endl);
UINFO(4, " IF: " << nodep << endl);
int lastLikely = m_likely;
int lastUnlikely = m_unlikely;
{
@ -109,11 +109,9 @@ private:
// METHODS
void calc_tasks() {
for (CFuncVec::iterator it=m_cfuncsp.begin(); it!=m_cfuncsp.end(); ++it) {
for (CFuncVec::iterator it = m_cfuncsp.begin(); it != m_cfuncsp.end(); ++it) {
AstCFunc* nodep = *it;
if (!nodep->dontInline()) {
nodep->isInline(true);
}
if (!nodep->dontInline()) nodep->isInline(true);
}
}
@ -131,6 +129,6 @@ public:
// Branch class functions
void V3Branch::branchAll(AstNetlist* nodep) {
UINFO(2,__FUNCTION__<<": "<<endl);
BranchVisitor visitor (nodep);
UINFO(2, __FUNCTION__ << ": " << endl);
BranchVisitor visitor(nodep);
}

View File

@ -58,27 +58,21 @@ private:
packagep->classp(nodep);
v3Global.rootp()->addModulep(packagep);
// Add package to hierarchy
AstCell* cellp = new AstCell(packagep->fileline(),
packagep->fileline(),
packagep->name(),
packagep->name(),
NULL, NULL, NULL);
AstCell* cellp = new AstCell(packagep->fileline(), packagep->fileline(), packagep->name(),
packagep->name(), NULL, NULL, NULL);
cellp->modp(packagep);
v3Global.rootp()->topModulep()->addStmtp(cellp);
// Find class's scope
// Alternative would be to move this and related to V3Scope
AstScope* classScopep = NULL;
for (AstNode* itp = nodep->stmtsp(); itp; itp = itp->nextp()) {
if ((classScopep = VN_CAST(itp, Scope))) {
break;
}
if ((classScopep = VN_CAST(itp, Scope))) break;
}
UASSERT_OBJ(classScopep, nodep, "No scope under class");
// Add scope
AstScope* scopep = new AstScope(nodep->fileline(),
packagep, classScopep->name(), classScopep->aboveScopep(),
classScopep->aboveCellp());
AstScope* scopep = new AstScope(nodep->fileline(), packagep, classScopep->name(),
classScopep->aboveScopep(), classScopep->aboveCellp());
packagep->addStmtp(scopep);
// Iterate
string prevPrefix = m_prefix;
@ -103,7 +97,7 @@ private:
iterateChildren(nodep);
// Don't move now, or wouldn't keep interating the class
// TODO move class statics only
//if (m_classScopep) {
// if (m_classScopep) {
// m_moves.push_back(make_pair(nodep, m_classScopep));
//}
}
@ -111,7 +105,7 @@ private:
iterateChildren(nodep);
// Don't move now, or wouldn't keep interating the class
// TODO move function statics only
//if (m_classScopep) {
// if (m_classScopep) {
// m_moves.push_back(make_pair(nodep, m_classScopep));
//}
}

View File

@ -267,7 +267,7 @@ class V3ConfigFile {
LineAttrMap m_lineAttrs; // Atributes to line mapping
IgnLines m_ignLines; // Ignore line settings
Waivers m_waivers; // Waive messages
Waivers m_waivers; // Waive messages
struct {
int lineno; // Last line number
@ -346,7 +346,9 @@ public:
bool waive(V3ErrorCode code, const string& match) {
for (Waivers::const_iterator it = m_waivers.begin(); it != m_waivers.end(); ++it) {
if (((it->first == code) || (it->first == V3ErrorCode::I_LINT))
&& VString::wildmatch(match, it->second)) return true;
&& VString::wildmatch(match, it->second)) {
return true;
}
}
return false;
}

View File

@ -40,14 +40,16 @@
class CoverageVisitor : public AstNVisitor {
private:
// TYPES
typedef std::map<string,int> FileMap;
typedef std::map<string, int> FileMap;
struct ToggleEnt {
string m_comment; // Comment for coverage dump
AstNode* m_varRefp; // How to get to this element
AstNode* m_chgRefp; // How to get to this element
string m_comment; // Comment for coverage dump
AstNode* m_varRefp; // How to get to this element
AstNode* m_chgRefp; // How to get to this element
ToggleEnt(const string& comment, AstNode* vp, AstNode* cp)
: m_comment(comment), m_varRefp(vp), m_chgRefp(cp) {}
: m_comment(comment)
, m_varRefp(vp)
, m_chgRefp(cp) {}
~ToggleEnt() {}
void cleanup() {
VL_DO_CLEAR(m_varRefp->deleteTree(), m_varRefp = NULL);
@ -58,15 +60,15 @@ private:
// NODE STATE
// Entire netlist:
// AstIf::user1() -> bool. True indicates ifelse processed
AstUser1InUse m_inuser1;
AstUser1InUse m_inuser1;
// STATE
bool m_checkBlock; // Should this block get covered?
AstNodeModule* m_modp; // Current module to add statement to
bool m_inToggleOff; // In function/task etc
bool m_inModOff; // In module with no coverage
FileMap m_fileps; // Column counts for each fileline
string m_beginHier; // AstBegin hier name for user coverage points
bool m_checkBlock; // Should this block get covered?
AstNodeModule* m_modp; // Current module to add statement to
bool m_inToggleOff; // In function/task etc
bool m_inModOff; // In module with no coverage
FileMap m_fileps; // Column counts for each fileline
string m_beginHier; // AstBegin hier name for user coverage points
// METHODS
VL_DEBUG_FUNC; // Declare debug()
@ -74,16 +76,13 @@ private:
const char* varIgnoreToggle(AstVar* nodep) {
// Return true if this shouldn't be traced
// See also similar rule in V3TraceDecl::varIgnoreTrace
if (!nodep->isToggleCoverable())
return "Not relevant signal type";
if (!nodep->isToggleCoverable()) return "Not relevant signal type";
if (!v3Global.opt.coverageUnderscore()) {
string prettyName = nodep->prettyName();
if (prettyName[0] == '_')
return "Leading underscore";
if (prettyName.find("._") != string::npos)
return "Inlined leading underscore";
if (prettyName[0] == '_') return "Leading underscore";
if (prettyName.find("._") != string::npos) return "Inlined leading underscore";
}
if ((nodep->width()*nodep->dtypep()->arrayUnpackedElements()) > 256) {
if ((nodep->width() * nodep->dtypep()->arrayUnpackedElements()) > 256) {
return "Wide bus/array > 256 bits";
}
// We allow this, though tracing doesn't
@ -91,19 +90,18 @@ private:
return NULL;
}
AstCoverInc* newCoverInc(FileLine* fl, const string& hier,
const string& page_prefix, const string& comment,
const string& trace_var_name) {
AstCoverInc* newCoverInc(FileLine* fl, const string& hier, const string& page_prefix,
const string& comment, const string& trace_var_name) {
// For line coverage, we may have multiple if's on one line, so disambiguate if
// everything is otherwise identical
// (Don't set column otherwise as it may result in making bins not match up with
// different types of coverage enabled.)
string key = fl->filename()+"\001"+cvtToStr(fl->lineno())
+"\001"+hier+"\001"+page_prefix+"\001"+comment;
string key = fl->filename() + "\001" + cvtToStr(fl->lineno()) + "\001" + hier + "\001"
+ page_prefix + "\001" + comment;
int column = 0;
FileMap::iterator it = m_fileps.find(key);
if (it == m_fileps.end()) {
m_fileps.insert(make_pair(key, column+1));
m_fileps.insert(make_pair(key, column + 1));
} else {
column = (it->second)++;
}
@ -122,27 +120,23 @@ private:
AstCoverInc* incp = new AstCoverInc(fl, declp);
if (!trace_var_name.empty() && v3Global.opt.traceCoverage()) {
AstVar* varp = new AstVar(incp->fileline(),
AstVarType::MODULETEMP, trace_var_name,
AstVar* varp = new AstVar(incp->fileline(), AstVarType::MODULETEMP, trace_var_name,
incp->findUInt32DType());
varp->trace(true);
varp->fileline()->modifyWarnOff(V3ErrorCode::UNUSED, true);
m_modp->addStmtp(varp);
UINFO(5, "New coverage trace: "<<varp<<endl);
AstAssign* assp = new AstAssign(
incp->fileline(),
new AstVarRef(incp->fileline(), varp, true),
new AstAdd(incp->fileline(),
new AstVarRef(incp->fileline(), varp, false),
UINFO(5, "New coverage trace: " << varp << endl);
AstAssign* assp = new AstAssign(
incp->fileline(), new AstVarRef(incp->fileline(), varp, true),
new AstAdd(incp->fileline(), new AstVarRef(incp->fileline(), varp, false),
new AstConst(incp->fileline(), AstConst::WidthedValue(), 32, 1)));
incp->addNext(assp);
}
return incp;
}
string traceNameForLine(AstNode* nodep, const string& type) {
return "vlCoverageLineTrace_"+nodep->fileline()->filebasenameNoExt()
+"__"+cvtToStr(nodep->fileline()->lineno())
+"_"+type;
return "vlCoverageLineTrace_" + nodep->fileline()->filebasenameNoExt() + "__"
+ cvtToStr(nodep->fileline()->lineno()) + "_" + type;
}
// VISITORS - BOTH
virtual void visit(AstNodeModule* nodep) VL_OVERRIDE {
@ -169,13 +163,13 @@ private:
}
virtual void visit(AstVar* nodep) VL_OVERRIDE {
iterateChildren(nodep);
if (m_modp && !m_inModOff && !m_inToggleOff
&& nodep->fileline()->coverageOn() && v3Global.opt.coverageToggle()) {
if (m_modp && !m_inModOff && !m_inToggleOff && nodep->fileline()->coverageOn()
&& v3Global.opt.coverageToggle()) {
const char* disablep = varIgnoreToggle(nodep);
if (disablep) {
UINFO(4, " Disable Toggle: "<<disablep<<" "<<nodep<<endl);
UINFO(4, " Disable Toggle: " << disablep << " " << nodep << endl);
} else {
UINFO(4, " Toggle: "<<nodep<<endl);
UINFO(4, " Toggle: " << nodep << endl);
// There's several overall ways to approach this
// Treat like tracing, where a end-of-timestamp action sees all changes
// Works ok, but would be quite slow as need to reform
@ -188,9 +182,9 @@ private:
// We'll do this, and make the if(...) coverinc later.
// Add signal to hold the old value
string newvarname = string("__Vtogcov__")+nodep->shortName();
AstVar* chgVarp = new AstVar(nodep->fileline(),
AstVarType::MODULETEMP, newvarname, nodep);
string newvarname = string("__Vtogcov__") + nodep->shortName();
AstVar* chgVarp
= new AstVar(nodep->fileline(), AstVarType::MODULETEMP, newvarname, nodep);
chgVarp->fileline()->modifyWarnOff(V3ErrorCode::UNUSED, true);
m_modp->addStmtp(chgVarp);
@ -198,123 +192,108 @@ private:
// This is necessarily an O(n^2) expansion, which is why
// we limit coverage to signals with < 256 bits.
ToggleEnt newvec (string(""),
new AstVarRef(nodep->fileline(), nodep, false),
new AstVarRef(nodep->fileline(), chgVarp, true));
toggleVarRecurse(nodep->dtypeSkipRefp(), 0, newvec,
nodep, chgVarp);
ToggleEnt newvec(string(""), new AstVarRef(nodep->fileline(), nodep, false),
new AstVarRef(nodep->fileline(), chgVarp, true));
toggleVarRecurse(nodep->dtypeSkipRefp(), 0, newvec, nodep, chgVarp);
newvec.cleanup();
}
}
}
void toggleVarBottom(const ToggleEnt& above, const AstVar* varp) {
AstCoverToggle* newp
= new AstCoverToggle(varp->fileline(),
newCoverInc(varp->fileline(), "", "v_toggle",
varp->name()+above.m_comment, ""),
above.m_varRefp->cloneTree(true),
above.m_chgRefp->cloneTree(true));
AstCoverToggle* newp = new AstCoverToggle(
varp->fileline(),
newCoverInc(varp->fileline(), "", "v_toggle", varp->name() + above.m_comment, ""),
above.m_varRefp->cloneTree(true), above.m_chgRefp->cloneTree(true));
m_modp->addStmtp(newp);
}
void toggleVarRecurse(AstNodeDType* dtypep, int depth, // per-iteration
const ToggleEnt& above,
AstVar* varp, AstVar* chgVarp) { // Constant
const ToggleEnt& above, AstVar* varp, AstVar* chgVarp) { // Constant
if (const AstBasicDType* bdtypep = VN_CAST(dtypep, BasicDType)) {
if (bdtypep->isRanged()) {
for (int index_docs=bdtypep->lsb(); index_docs<bdtypep->msb()+1; index_docs++) {
for (int index_docs = bdtypep->lsb(); index_docs < bdtypep->msb() + 1;
index_docs++) {
int index_code = index_docs - bdtypep->lsb();
ToggleEnt newent (above.m_comment+string("[")+cvtToStr(index_docs)+"]",
new AstSel(varp->fileline(),
above.m_varRefp->cloneTree(true), index_code, 1),
new AstSel(varp->fileline(),
above.m_chgRefp->cloneTree(true), index_code, 1));
ToggleEnt newent(above.m_comment + string("[") + cvtToStr(index_docs) + "]",
new AstSel(varp->fileline(), above.m_varRefp->cloneTree(true),
index_code, 1),
new AstSel(varp->fileline(), above.m_chgRefp->cloneTree(true),
index_code, 1));
toggleVarBottom(newent, varp);
newent.cleanup();
}
} else {
toggleVarBottom(above, varp);
}
}
else if (AstUnpackArrayDType* adtypep = VN_CAST(dtypep, UnpackArrayDType)) {
for (int index_docs=adtypep->lsb(); index_docs<=adtypep->msb(); ++index_docs) {
} else if (AstUnpackArrayDType* adtypep = VN_CAST(dtypep, UnpackArrayDType)) {
for (int index_docs = adtypep->lsb(); index_docs <= adtypep->msb(); ++index_docs) {
int index_code = index_docs - adtypep->lsb();
ToggleEnt newent (above.m_comment+string("[")+cvtToStr(index_docs)+"]",
new AstArraySel(varp->fileline(),
above.m_varRefp->cloneTree(true), index_code),
new AstArraySel(varp->fileline(),
above.m_chgRefp->cloneTree(true), index_code));
toggleVarRecurse(adtypep->subDTypep()->skipRefp(), depth+1,
newent,
varp, chgVarp);
ToggleEnt newent(above.m_comment + string("[") + cvtToStr(index_docs) + "]",
new AstArraySel(varp->fileline(),
above.m_varRefp->cloneTree(true), index_code),
new AstArraySel(varp->fileline(),
above.m_chgRefp->cloneTree(true), index_code));
toggleVarRecurse(adtypep->subDTypep()->skipRefp(), depth + 1, newent, varp,
chgVarp);
newent.cleanup();
}
}
else if (AstPackArrayDType* adtypep = VN_CAST(dtypep, PackArrayDType)) {
for (int index_docs=adtypep->lsb(); index_docs<=adtypep->msb(); ++index_docs) {
} else if (AstPackArrayDType* adtypep = VN_CAST(dtypep, PackArrayDType)) {
for (int index_docs = adtypep->lsb(); index_docs <= adtypep->msb(); ++index_docs) {
AstNodeDType* subtypep = adtypep->subDTypep()->skipRefp();
int index_code = index_docs - adtypep->lsb();
ToggleEnt newent (above.m_comment+string("[")+cvtToStr(index_docs)+"]",
new AstSel(varp->fileline(), above.m_varRefp->cloneTree(true),
index_code*subtypep->width(), subtypep->width()),
new AstSel(varp->fileline(), above.m_chgRefp->cloneTree(true),
index_code*subtypep->width(), subtypep->width()));
toggleVarRecurse(adtypep->subDTypep()->skipRefp(), depth+1,
newent,
varp, chgVarp);
ToggleEnt newent(above.m_comment + string("[") + cvtToStr(index_docs) + "]",
new AstSel(varp->fileline(), above.m_varRefp->cloneTree(true),
index_code * subtypep->width(), subtypep->width()),
new AstSel(varp->fileline(), above.m_chgRefp->cloneTree(true),
index_code * subtypep->width(), subtypep->width()));
toggleVarRecurse(adtypep->subDTypep()->skipRefp(), depth + 1, newent, varp,
chgVarp);
newent.cleanup();
}
}
else if (AstStructDType* adtypep = VN_CAST(dtypep, StructDType)) {
} else if (AstStructDType* adtypep = VN_CAST(dtypep, StructDType)) {
// For now it's packed, so similar to array
for (AstMemberDType* itemp = adtypep->membersp();
itemp; itemp=VN_CAST(itemp->nextp(), MemberDType)) {
for (AstMemberDType* itemp = adtypep->membersp(); itemp;
itemp = VN_CAST(itemp->nextp(), MemberDType)) {
AstNodeDType* subtypep = itemp->subDTypep()->skipRefp();
int index_code = itemp->lsb();
ToggleEnt newent (above.m_comment+string(".")+itemp->name(),
new AstSel(varp->fileline(), above.m_varRefp->cloneTree(true),
index_code, subtypep->width()),
new AstSel(varp->fileline(), above.m_chgRefp->cloneTree(true),
index_code, subtypep->width()));
toggleVarRecurse(subtypep, depth+1,
newent,
varp, chgVarp);
ToggleEnt newent(above.m_comment + string(".") + itemp->name(),
new AstSel(varp->fileline(), above.m_varRefp->cloneTree(true),
index_code, subtypep->width()),
new AstSel(varp->fileline(), above.m_chgRefp->cloneTree(true),
index_code, subtypep->width()));
toggleVarRecurse(subtypep, depth + 1, newent, varp, chgVarp);
newent.cleanup();
}
}
else if (AstUnionDType* adtypep = VN_CAST(dtypep, UnionDType)) {
} else if (AstUnionDType* adtypep = VN_CAST(dtypep, UnionDType)) {
// Arbitrarily handle only the first member of the union
if (AstMemberDType* itemp = adtypep->membersp()) {
AstNodeDType* subtypep = itemp->subDTypep()->skipRefp();
ToggleEnt newent (above.m_comment+string(".")+itemp->name(),
above.m_varRefp->cloneTree(true),
above.m_chgRefp->cloneTree(true));
toggleVarRecurse(subtypep, depth+1,
newent,
varp, chgVarp);
ToggleEnt newent(above.m_comment + string(".") + itemp->name(),
above.m_varRefp->cloneTree(true),
above.m_chgRefp->cloneTree(true));
toggleVarRecurse(subtypep, depth + 1, newent, varp, chgVarp);
newent.cleanup();
}
}
else {
} else {
dtypep->v3fatalSrc("Unexpected node data type in toggle coverage generation: "
<<dtypep->prettyTypeName());
<< dtypep->prettyTypeName());
}
}
// VISITORS - LINE COVERAGE
virtual void visit(AstIf* nodep) VL_OVERRIDE { // Note not AstNodeIf; other types don't get covered
UINFO(4," IF: "<<nodep<<endl);
virtual void
visit(AstIf* nodep) VL_OVERRIDE { // Note not AstNodeIf; other types don't get covered
UINFO(4, " IF: " << nodep << endl);
if (m_checkBlock) {
// An else-if. When we iterate the if, use "elsif" marking
bool elsif = (VN_IS(nodep->elsesp(), If)
&& !VN_CAST(nodep->elsesp(), If)->nextp());
bool elsif = (VN_IS(nodep->elsesp(), If) && !VN_CAST(nodep->elsesp(), If)->nextp());
if (elsif) VN_CAST(nodep->elsesp(), If)->user1(true);
//
iterateAndNextNull(nodep->ifsp());
if (m_checkBlock && !m_inModOff
&& nodep->fileline()->coverageOn() && v3Global.opt.coverageLine()) { // if a "if" branch didn't disable it
UINFO(4," COVER: "<<nodep<<endl);
if (m_checkBlock && !m_inModOff && nodep->fileline()->coverageOn()
&& v3Global.opt.coverageLine()) { // if a "if" branch didn't disable it
UINFO(4, " COVER: " << nodep << endl);
if (nodep->user1()) {
nodep->addIfsp(newCoverInc(nodep->fileline(), "", "v_line", "elsif",
traceNameForLine(nodep, "elsif")));
@ -327,13 +306,12 @@ private:
if (nodep->elsesp()) {
m_checkBlock = true;
iterateAndNextNull(nodep->elsesp());
if (m_checkBlock && !m_inModOff
&& nodep->fileline()->coverageOn() && v3Global.opt.coverageLine()) { // if a "else" branch didn't disable it
UINFO(4," COVER: "<<nodep<<endl);
if (m_checkBlock && !m_inModOff && nodep->fileline()->coverageOn()
&& v3Global.opt.coverageLine()) { // if a "else" branch didn't disable it
UINFO(4, " COVER: " << nodep << endl);
if (!elsif) { // elsif done inside if()
nodep->addElsesp(newCoverInc(nodep->elsesp()->fileline(),
"", "v_line", "else",
traceNameForLine(nodep, "else")));
nodep->addElsesp(newCoverInc(nodep->elsesp()->fileline(), "", "v_line",
"else", traceNameForLine(nodep, "else")));
}
}
}
@ -341,12 +319,12 @@ private:
}
}
virtual void visit(AstCaseItem* nodep) VL_OVERRIDE {
UINFO(4," CASEI: "<<nodep<<endl);
if (m_checkBlock && !m_inModOff
&& nodep->fileline()->coverageOn() && v3Global.opt.coverageLine()) {
UINFO(4, " CASEI: " << nodep << endl);
if (m_checkBlock && !m_inModOff && nodep->fileline()->coverageOn()
&& v3Global.opt.coverageLine()) {
iterateAndNextNull(nodep->bodysp());
if (m_checkBlock) { // if the case body didn't disable it
UINFO(4," COVER: "<<nodep<<endl);
UINFO(4, " COVER: " << nodep << endl);
nodep->addBodysp(newCoverInc(nodep->fileline(), "", "v_line", "case",
traceNameForLine(nodep, "case")));
}
@ -354,24 +332,24 @@ private:
}
}
virtual void visit(AstCover* nodep) VL_OVERRIDE {
UINFO(4," COVER: "<<nodep<<endl);
UINFO(4, " COVER: " << nodep << endl);
m_checkBlock = true; // Always do cover blocks, even if there's a $stop
iterateChildren(nodep);
if (!nodep->coverincp()) {
// Note the name may be overridden by V3Assert processing
nodep->coverincp(newCoverInc(nodep->fileline(), m_beginHier, "v_user", "cover",
m_beginHier+"_vlCoverageUserTrace"));
m_beginHier + "_vlCoverageUserTrace"));
}
m_checkBlock = true; // Reset as a child may have cleared it
}
virtual void visit(AstStop* nodep) VL_OVERRIDE {
UINFO(4," STOP: "<<nodep<<endl);
UINFO(4, " STOP: " << nodep << endl);
m_checkBlock = false;
}
virtual void visit(AstPragma* nodep) VL_OVERRIDE {
if (nodep->pragType() == AstPragmaType::COVERAGE_BLOCK_OFF) {
// Skip all NEXT nodes under this block, and skip this if/case branch
UINFO(4," OFF: "<<nodep<<endl);
UINFO(4, " OFF: " << nodep << endl);
m_checkBlock = false;
VL_DO_DANGLING(nodep->unlinkFrBack()->deleteTree(), nodep);
} else {
@ -388,8 +366,8 @@ private:
bool oldtog = m_inToggleOff;
{
m_inToggleOff = true;
if (nodep->name()!="") {
m_beginHier = m_beginHier + (m_beginHier!=""?".":"") + nodep->name();
if (nodep->name() != "") {
m_beginHier = m_beginHier + (m_beginHier != "" ? "." : "") + nodep->name();
}
iterateChildren(nodep);
}
@ -423,9 +401,7 @@ public:
// Coverage class functions
void V3Coverage::coverage(AstNetlist* rootp) {
UINFO(2,__FUNCTION__<<": "<<endl);
{
CoverageVisitor visitor (rootp);
} // Destruct before checking
UINFO(2, __FUNCTION__ << ": " << endl);
{ CoverageVisitor visitor(rootp); } // Destruct before checking
V3Global::dumpCheckGlobalTree("coverage", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
}

View File

@ -17,7 +17,6 @@
// If two COVERTOGGLEs have same VARSCOPE, combine them
//*************************************************************************
#include "config_build.h"
#include "verilatedos.h"
@ -38,23 +37,23 @@ private:
// V3Hashed
// AstCoverToggle->VarRef::user4() // V3Hashed calculation
//AstUser4InUse In V3Hashed
// AstUser4InUse In V3Hashed
// TYPES
typedef std::vector<AstCoverToggle*> ToggleList;
// STATE
ToggleList m_toggleps; // List of of all AstCoverToggle's
ToggleList m_toggleps; // List of of all AstCoverToggle's
VDouble0 m_statToggleJoins; // Statistic tracking
VDouble0 m_statToggleJoins; // Statistic tracking
// METHODS
VL_DEBUG_FUNC; // Declare debug()
void detectDuplicates() {
UINFO(9,"Finding duplicates\n");
UINFO(9, "Finding duplicates\n");
// Note uses user4
V3Hashed hashed; // Duplicate code detection
V3Hashed hashed; // Duplicate code detection
// Hash all of the original signals we toggle cover
for (ToggleList::iterator it = m_toggleps.begin(); it != m_toggleps.end(); ++it) {
AstCoverToggle* nodep = *it;
@ -78,17 +77,18 @@ private:
// covertoggle which is immediately above, so:
AstCoverToggle* removep = VN_CAST(duporigp->backp(), CoverToggle);
UASSERT_OBJ(removep, nodep, "CoverageJoin duplicate of wrong type");
UINFO(8," Orig "<<nodep<<" -->> "<<nodep->incp()->declp()<<endl);
UINFO(8," dup "<<removep<<" -->> "<<removep->incp()->declp()<<endl);
UINFO(8, " Orig " << nodep << " -->> " << nodep->incp()->declp() << endl);
UINFO(8, " dup " << removep << " -->> " << removep->incp()->declp() << endl);
// The CoverDecl the duplicate pointed to now needs to point to the
// original's data. I.e. the duplicate will get the coverage number
// from the non-duplicate
AstCoverDecl* datadeclp = nodep->incp()->declp()->dataDeclThisp();
removep->incp()->declp()->dataDeclp(datadeclp);
UINFO(8," new "<<removep->incp()->declp()<<endl);
UINFO(8, " new " << removep->incp()->declp() << endl);
// Mark the found node as a duplicate of the first node
// (Not vice-versa as we have the iterator for the found node)
removep->unlinkFrBack(); VL_DO_DANGLING(pushDeletep(removep), removep);
removep->unlinkFrBack();
VL_DO_DANGLING(pushDeletep(removep), removep);
// Remove node from comparison so don't hit it again
hashed.erase(dupit);
++m_statToggleJoins;
@ -114,9 +114,7 @@ private:
public:
// CONSTRUCTORS
explicit CoverageJoinVisitor(AstNetlist* nodep) {
iterate(nodep);
}
explicit CoverageJoinVisitor(AstNetlist* nodep) { iterate(nodep); }
virtual ~CoverageJoinVisitor() {
V3Stats::addStat("Coverage, Toggle points joined", m_statToggleJoins);
}
@ -126,9 +124,7 @@ public:
// Coverage class functions
void V3CoverageJoin::coverageJoin(AstNetlist* rootp) {
UINFO(2,__FUNCTION__<<": "<<endl);
{
CoverageJoinVisitor visitor (rootp);
} // Destruct before checking
UINFO(2, __FUNCTION__ << ": " << endl);
{ CoverageJoinVisitor visitor(rootp); } // Destruct before checking
V3Global::dumpCheckGlobalTree("coveragejoin", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
}

View File

@ -40,20 +40,20 @@ private:
// NODE STATE
// STATE
AstNodeModule* m_modp; // Current module
AstCFunc* m_funcp; // Current block
AstNode* m_stmtp; // Current statement
int m_depth; // How deep in an expression
int m_maxdepth; // Maximum depth in an expression
AstNodeModule* m_modp; // Current module
AstCFunc* m_funcp; // Current block
AstNode* m_stmtp; // Current statement
int m_depth; // How deep in an expression
int m_maxdepth; // Maximum depth in an expression
// METHODS
VL_DEBUG_FUNC; // Declare debug()
void createDeepTemp(AstNode* nodep) {
UINFO(6," Deep "<<nodep<<endl);
//if (debug()>=9) nodep->dumpTree(cout, "deep:");
UINFO(6, " Deep " << nodep << endl);
// if (debug()>=9) nodep->dumpTree(cout, "deep:");
string newvarname = (string("__Vdeeptemp")+cvtToStr(m_modp->varNumGetInc()));
string newvarname = (string("__Vdeeptemp") + cvtToStr(m_modp->varNumGetInc()));
AstVar* varp = new AstVar(nodep->fileline(), AstVarType::STMTTEMP, newvarname,
// Width, not widthMin, as we may be in
// middle of BITSEL expression which though
@ -69,8 +69,7 @@ private:
nodep->replaceWith(newp);
// Put assignment before the referencing statement
AstAssign* assp = new AstAssign(nodep->fileline(),
new AstVarRef(nodep->fileline(), varp, true),
nodep);
new AstVarRef(nodep->fileline(), varp, true), nodep);
AstNRelinker linker2;
m_stmtp->unlinkFrBack(&linker2);
assp->addNext(m_stmtp);
@ -79,7 +78,7 @@ private:
// VISITORS
virtual void visit(AstNodeModule* nodep) VL_OVERRIDE {
UINFO(4," MOD "<<nodep<<endl);
UINFO(4, " MOD " << nodep << endl);
AstNodeModule* origModp = m_modp;
{
m_modp = nodep;
@ -110,20 +109,18 @@ private:
}
}
// Operators
virtual void visit(AstNodeTermop* nodep) VL_OVERRIDE {
}
virtual void visit(AstNodeTermop* nodep) VL_OVERRIDE {}
virtual void visit(AstNodeMath* nodep) VL_OVERRIDE {
// We have some operator defines that use 2 parens, so += 2.
m_depth += 2;
if (m_depth>m_maxdepth) m_maxdepth = m_depth;
if (m_depth > m_maxdepth) m_maxdepth = m_depth;
iterateChildren(nodep);
m_depth -= 2;
if (m_stmtp
&& (v3Global.opt.compLimitParens() >= 1) // Else compiler doesn't need it
&& (m_maxdepth-m_depth) > v3Global.opt.compLimitParens()
if (m_stmtp && (v3Global.opt.compLimitParens() >= 1) // Else compiler doesn't need it
&& (m_maxdepth - m_depth) > v3Global.opt.compLimitParens()
&& !VN_IS(nodep->backp(), NodeStmt) // Not much point if we're about to use it
) {
) {
m_maxdepth = m_depth;
createDeepTemp(nodep);
}
@ -135,7 +132,7 @@ private:
void needNonStaticFunc(AstNode* nodep) {
UASSERT_OBJ(m_funcp, nodep, "Non-static accessor not under a function");
if (m_funcp->isStatic().trueUnknown()) {
UINFO(5,"Mark non-public due to "<<nodep<<endl);
UINFO(5, "Mark non-public due to " << nodep << endl);
m_funcp->isStatic(false);
}
}
@ -171,9 +168,7 @@ public:
// Depth class functions
void V3Depth::depthAll(AstNetlist* nodep) {
UINFO(2,__FUNCTION__<<": "<<endl);
{
DepthVisitor visitor (nodep);
} // Destruct before checking
UINFO(2, __FUNCTION__ << ": " << endl);
{ DepthVisitor visitor(nodep); } // Destruct before checking
V3Global::dumpCheckGlobalTree("depth", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 6);
}

View File

@ -38,10 +38,10 @@ private:
// NODE STATE
// STATE
AstNodeModule* m_modp; // Current module
AstCFunc* m_funcp; // Current function
int m_depth; // How deep in an expression
int m_deepNum; // How many functions made
AstNodeModule* m_modp; // Current module
AstCFunc* m_funcp; // Current function
int m_depth; // How deep in an expression
int m_deepNum; // How many functions made
// METHODS
VL_DEBUG_FUNC; // Declare debug()
@ -50,7 +50,7 @@ private:
AstNRelinker relinkHandle;
nodep->unlinkFrBack(&relinkHandle);
// Create function
string name = m_funcp->name()+"__deep"+cvtToStr(++m_deepNum);
string name = m_funcp->name() + "__deep" + cvtToStr(++m_deepNum);
AstCFunc* funcp = new AstCFunc(nodep->fileline(), name, NULL);
funcp->argTypes(EmitCBaseVisitor::symClassVar());
funcp->symProlog(true);
@ -60,7 +60,7 @@ private:
// Call it at the point where the body was removed from
AstCCall* callp = new AstCCall(nodep->fileline(), funcp);
callp->argTypes("vlSymsp");
UINFO(6," New "<<callp<<endl);
UINFO(6, " New " << callp << endl);
//
relinkHandle.relink(callp);
return funcp;
@ -68,7 +68,7 @@ private:
// VISITORS
virtual void visit(AstNodeModule* nodep) VL_OVERRIDE {
UINFO(4," MOD "<<nodep<<endl);
UINFO(4, " MOD " << nodep << endl);
AstNodeModule* origModp = m_modp;
{
m_modp = nodep;
@ -93,13 +93,13 @@ private:
m_depth++;
if (m_depth > v3Global.opt.compLimitBlocks()
&& !VN_IS(nodep, NodeCCall)) { // Already done
UINFO(4, "DeepBlocks "<<m_depth<<" "<<nodep<<endl);
UINFO(4, "DeepBlocks " << m_depth << " " << nodep << endl);
AstNode* backp = nodep->backp(); // Only for debug
if (debug()>=9) backp->dumpTree(cout, "- pre : ");
if (debug() >= 9) backp->dumpTree(cout, "- pre : ");
AstCFunc* funcp = createDeepFunc(nodep);
iterate(funcp);
if (debug()>=9) backp->dumpTree(cout, "- post: ");
if (debug()>=9) funcp->dumpTree(cout, "- func: ");
if (debug() >= 9) backp->dumpTree(cout, "- post: ");
if (debug() >= 9) funcp->dumpTree(cout, "- func: ");
} else {
iterateChildren(nodep);
}
@ -135,9 +135,7 @@ public:
// DepthBlock class functions
void V3DepthBlock::depthBlockAll(AstNetlist* nodep) {
UINFO(2,__FUNCTION__<<": "<<endl);
{
DepthBlockVisitor visitor (nodep);
} // Destruct before checking
UINFO(2, __FUNCTION__ << ": " << endl);
{ DepthBlockVisitor visitor(nodep); } // Destruct before checking
V3Global::dumpCheckGlobalTree("deepblock", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
}

View File

@ -119,8 +119,7 @@ private:
} else if (relativeRefOk && scopep == m_scopep) {
m_needThis = true;
return "this->";
} else if (relativeRefOk && scopep->aboveScopep()
&& scopep->aboveScopep()==m_scopep) {
} else if (relativeRefOk && scopep->aboveScopep() && scopep->aboveScopep() == m_scopep) {
// Reference to scope of cell directly under this module, can just "cell->"
string name = scopep->name();
string::size_type pos;
@ -179,8 +178,8 @@ private:
UASSERT_OBJ(funcp->scopep(), funcp, "Not scoped");
UINFO(6, " Wrapping " << name << " " << funcp << endl);
UINFO(6, " at " << newfuncp->argTypes()
<< " und " << funcp->argTypes() << endl);
UINFO(6,
" at " << newfuncp->argTypes() << " und " << funcp->argTypes() << endl);
funcp->declPrivate(true);
AstNode* argsp = NULL;
for (AstNode* stmtp = newfuncp->argsp(); stmtp; stmtp = stmtp->nextp()) {
@ -310,9 +309,7 @@ public:
// Descope class functions
void V3Descope::descopeAll(AstNetlist* nodep) {
UINFO(2,__FUNCTION__<<": "<<endl);
{
DescopeVisitor visitor (nodep);
} // Destruct before checking
UINFO(2, __FUNCTION__ << ": " << endl);
{ DescopeVisitor visitor(nodep); } // Destruct before checking
V3Global::dumpCheckGlobalTree("descope", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
}

View File

@ -107,16 +107,14 @@ class EmitCInlines : EmitCBaseVisitor {
public:
explicit EmitCInlines(AstNetlist* nodep) {
iterate(nodep);
if (v3Global.needHInlines()) {
emitInt();
}
if (v3Global.needHInlines()) emitInt();
}
};
void EmitCInlines::emitInt() {
string filename = v3Global.opt.makeDir()+"/"+topClassName()+"__Inlines.h";
newCFile(filename, false/*slow*/, false/*source*/);
V3OutCFile hf (filename);
string filename = v3Global.opt.makeDir() + "/" + topClassName() + "__Inlines.h";
newCFile(filename, false /*slow*/, false /*source*/);
V3OutCFile hf(filename);
m_ofp = &hf;
ofp()->putsHeader();

View File

@ -28,10 +28,9 @@
class V3EmitV {
public:
static void emitv();
static void verilogForTree(AstNode* nodep, std::ostream& os=std::cout);
static void verilogPrefixedTree(AstNode* nodep, std::ostream& os,
const string& prefix, int flWidth,
AstSenTree* domainp, bool user3mark);
static void verilogForTree(AstNode* nodep, std::ostream& os = std::cout);
static void verilogPrefixedTree(AstNode* nodep, std::ostream& os, const string& prefix,
int flWidth, AstSenTree* domainp, bool user3mark);
static void emitvFiles();
};

View File

@ -76,7 +76,7 @@ void V3Global::readFiles() {
}
void V3Global::dumpCheckGlobalTree(const string& stagename, int newNumber, bool doDump) {
v3Global.rootp()->dumpTreeFile(v3Global.debugFilename(stagename + ".tree", newNumber),
false, doDump);
v3Global.rootp()->dumpTreeFile(v3Global.debugFilename(stagename + ".tree", newNumber), false,
doDump);
if (v3Global.opt.stats()) V3Stats::statsStage(stagename);
}

View File

@ -17,10 +17,12 @@
#ifndef _V3GLOBAL_H_
#define _V3GLOBAL_H_ 1
// clang-format off
#include "config_build.h"
#ifndef HAVE_CONFIG_BUILD
# error "Something failed during ./configure as config_build.h is incomplete. Perhaps you used autoreconf, don't."
#endif
// clang-format on
#include "verilatedos.h"
@ -35,21 +37,19 @@ class AstNetlist;
//======================================================================
// Statics
//######################################################################
class VWidthMinUsage {
public:
enum en {
LINT_WIDTH,
MATCHES_WIDTH,
VERILOG_WIDTH
};
enum en { LINT_WIDTH, MATCHES_WIDTH, VERILOG_WIDTH };
enum en m_e;
inline VWidthMinUsage() : m_e(LINT_WIDTH) {}
inline VWidthMinUsage()
: m_e(LINT_WIDTH) {}
// cppcheck-suppress noExplicitConstructor
inline VWidthMinUsage(en _e) : m_e(_e) {}
explicit inline VWidthMinUsage(int _e) : m_e(static_cast<en>(_e)) {}
inline VWidthMinUsage(en _e)
: m_e(_e) {}
explicit inline VWidthMinUsage(int _e)
: m_e(static_cast<en>(_e)) {}
operator en() const { return m_e; }
};
inline bool operator==(const VWidthMinUsage& lhs, const VWidthMinUsage& rhs) {
@ -97,7 +97,10 @@ public:
, m_needTraceDumper(false)
, m_dpi(false) {}
AstNetlist* makeNetlist();
void boot() { UASSERT(!m_rootp, "call once"); m_rootp = makeNetlist(); }
void boot() {
UASSERT(!m_rootp, "call once");
m_rootp = makeNetlist();
}
void clear();
// ACCESSORS (general)
AstNetlist* rootp() const { return m_rootp; }
@ -107,16 +110,18 @@ public:
// METHODS
void readFiles();
void checkTree();
static void dumpCheckGlobalTree(const string& stagename, int newNumber=0, bool doDump=true);
static void dumpCheckGlobalTree(const string& stagename, int newNumber = 0,
bool doDump = true);
void assertDTypesResolved(bool flag) { m_assertDTypesResolved = flag; }
void widthMinUsage(const VWidthMinUsage& flag) { m_widthMinUsage = flag; }
bool constRemoveXs() const { return m_constRemoveXs; }
void constRemoveXs(bool flag) { m_constRemoveXs = flag; }
string debugFilename(const string& nameComment, int newNumber=0) {
string debugFilename(const string& nameComment, int newNumber = 0) {
++m_debugFileNumber;
if (newNumber) m_debugFileNumber = newNumber;
char digits[100]; sprintf(digits, "%03d", m_debugFileNumber);
return opt.makeDir()+"/"+opt.prefix()+"_"+digits+"_"+nameComment;
char digits[100];
sprintf(digits, "%03d", m_debugFileNumber);
return opt.makeDir() + "/" + opt.prefix() + "_" + digits + "_" + nameComment;
}
bool needC11() const { return m_needC11; }
void needC11(bool flag) { m_needC11 = flag; }

View File

@ -47,19 +47,23 @@ typedef bool (*V3EdgeFuncP)(const V3GraphEdge* edgep);
class GraphWay {
public:
enum en { FORWARD=0,
REVERSE=1,
NUM_WAYS=2 // NUM_WAYS is not an actual way, it's typically
// // an array dimension or loop bound.
enum en {
FORWARD = 0,
REVERSE = 1,
NUM_WAYS = 2 // NUM_WAYS is not an actual way, it's typically
// // an array dimension or loop bound.
};
enum en m_e;
inline GraphWay() : m_e(FORWARD) {}
inline GraphWay()
: m_e(FORWARD) {}
// cppcheck-suppress noExplicitConstructor
inline GraphWay(en _e) : m_e(_e) {}
explicit inline GraphWay(int _e) : m_e(static_cast<en>(_e)) {}
inline GraphWay(en _e)
: m_e(_e) {}
explicit inline GraphWay(int _e)
: m_e(static_cast<en>(_e)) {}
operator en() const { return m_e; }
const char* ascii() const {
static const char* const names[] = { "FORWARD", "REVERSE" };
static const char* const names[] = {"FORWARD", "REVERSE"};
return names[m_e];
}
// METHODS unique to this class
@ -78,12 +82,14 @@ private:
// MEMBERS
V3List<V3GraphVertex*> m_vertices; // All vertices
static int s_debug;
protected:
friend class V3GraphVertex; friend class V3GraphEdge;
friend class V3GraphVertex;
friend class V3GraphEdge;
friend class GraphAcyc;
// METHODS
void acyclicDFS();
void acyclicDFSIterate(V3GraphVertex *vertexp, int depth, uint32_t currentRank);
void acyclicDFSIterate(V3GraphVertex* vertexp, int depth, uint32_t currentRank);
void acyclicCut();
void acyclicLoop(V3GraphVertex* vertexp, int depth);
double orderDFSIterate(V3GraphVertex* vertexp);
@ -91,6 +97,7 @@ protected:
void verticesUnlink() { m_vertices.reset(); }
// ACCESSORS
static int debug();
public:
V3Graph();
virtual ~V3Graph();
@ -163,10 +170,10 @@ public:
void subtreeLoops(V3EdgeFuncP edgeFuncp, V3GraphVertex* vertexp, V3Graph* loopGraphp);
/// Debugging
void dump(std::ostream& os=std::cout);
void dump(std::ostream& os = std::cout);
void dumpDotFile(const string& filename, bool colorAsSubgraph) const;
void dumpDotFilePrefixed(const string& nameComment, bool colorAsSubgraph=false) const;
void dumpDotFilePrefixedAlways(const string& nameComment, bool colorAsSubgraph=false) const;
void dumpDotFilePrefixed(const string& nameComment, bool colorAsSubgraph = false) const;
void dumpDotFilePrefixedAlways(const string& nameComment, bool colorAsSubgraph = false) const;
void userClearVertices();
void userClearEdges();
static void selfTest();
@ -181,17 +188,19 @@ public:
class V3GraphVertex {
// Vertices may be a 'gate'/wire statement OR a variable
protected:
friend class V3Graph; friend class V3GraphEdge;
friend class GraphAcyc; friend class GraphAlgRank;
friend class V3Graph;
friend class V3GraphEdge;
friend class GraphAcyc;
friend class GraphAlgRank;
V3ListEnt<V3GraphVertex*> m_vertices; // All vertices, linked list
V3List<V3GraphEdge*> m_outs; // Outbound edges,linked list
V3List<V3GraphEdge*> m_ins; // Inbound edges, linked list
double m_fanout; // Order fanout
uint32_t m_color; // Color of the node
uint32_t m_rank; // Rank of edge
V3List<V3GraphEdge*> m_outs; // Outbound edges,linked list
V3List<V3GraphEdge*> m_ins; // Inbound edges, linked list
double m_fanout; // Order fanout
uint32_t m_color; // Color of the node
uint32_t m_rank; // Rank of edge
union {
void* m_userp; // Marker for some algorithms
uint32_t m_user; // Marker for some algorithms
void* m_userp; // Marker for some algorithms
uint32_t m_user; // Marker for some algorithms
};
// METHODS
void verticesPushBack(V3Graph* graphp);
@ -202,14 +211,16 @@ protected:
protected:
// CONSTRUCTORS
V3GraphVertex(V3Graph* graphp, const V3GraphVertex& old);
public:
explicit V3GraphVertex(V3Graph* graphp);
//! Clone copy constructor. Doesn't copy edges or user/userp.
virtual V3GraphVertex* clone(V3Graph* graphp) const {
return new V3GraphVertex(graphp, *this); }
return new V3GraphVertex(graphp, *this);
}
virtual ~V3GraphVertex() {}
void unlinkEdges(V3Graph* graphp);
void unlinkDelete(V3Graph* graphp);
void unlinkEdges(V3Graph* graphp);
void unlinkDelete(V3Graph* graphp);
// ACCESSORS
virtual string name() const { return ""; }
@ -227,27 +238,26 @@ public:
if (m_fanout > rhsp->m_fanout) return 1;
return 0;
}
uint32_t color() const { return m_color; }
void color(uint32_t color) { m_color = color; }
uint32_t rank() const { return m_rank; }
void rank(uint32_t rank) { m_rank = rank; }
double fanout() const { return m_fanout; }
void user(uint32_t user) { m_user = user; }
uint32_t user() const { return m_user; }
void userp(void* userp) { m_userp = userp; }
void* userp() const { return m_userp; }
uint32_t color() const { return m_color; }
void color(uint32_t color) { m_color = color; }
uint32_t rank() const { return m_rank; }
void rank(uint32_t rank) { m_rank = rank; }
double fanout() const { return m_fanout; }
void user(uint32_t user) { m_user = user; }
uint32_t user() const { return m_user; }
void userp(void* userp) { m_userp = userp; }
void* userp() const { return m_userp; }
// ITERATORS
V3GraphVertex* verticesNextp() const { return m_vertices.nextp(); }
V3GraphEdge* inBeginp() const { return m_ins.begin(); }
bool inEmpty() const { return inBeginp()==NULL; }
bool inSize1() const;
uint32_t inHash() const;
bool inEmpty() const { return inBeginp() == NULL; }
bool inSize1() const;
uint32_t inHash() const;
V3GraphEdge* outBeginp() const { return m_outs.begin(); }
bool outEmpty() const { return outBeginp()==NULL; }
bool outSize1() const;
uint32_t outHash() const;
V3GraphEdge* beginp(GraphWay way) const {
return way.forward() ? outBeginp() : inBeginp(); }
bool outEmpty() const { return outBeginp() == NULL; }
bool outSize1() const;
uint32_t outHash() const;
V3GraphEdge* beginp(GraphWay way) const { return way.forward() ? outBeginp() : inBeginp(); }
// METHODS
/// Error reporting
void v3errorEnd(std::ostringstream& str) const;
@ -269,22 +279,24 @@ public:
// ENUMS
enum Cutable { NOT_CUTABLE = false, CUTABLE = true }; // For passing to V3GraphEdge
protected:
friend class V3Graph; friend class V3GraphVertex;
friend class GraphAcyc; friend class GraphAcycEdge;
V3ListEnt<V3GraphEdge*> m_outs; // Next Outbound edge for same vertex (linked list)
V3ListEnt<V3GraphEdge*> m_ins; // Next Inbound edge for same vertex (linked list)
friend class V3Graph;
friend class V3GraphVertex;
friend class GraphAcyc;
friend class GraphAcycEdge;
V3ListEnt<V3GraphEdge*> m_outs; // Next Outbound edge for same vertex (linked list)
V3ListEnt<V3GraphEdge*> m_ins; // Next Inbound edge for same vertex (linked list)
//
V3GraphVertex* m_fromp; // Vertices pointing to this edge
V3GraphVertex* m_top; // Vertices this edge points to
int m_weight; // Weight of the connection
bool m_cutable; // Interconnect may be broken in order sorting
V3GraphVertex* m_fromp; // Vertices pointing to this edge
V3GraphVertex* m_top; // Vertices this edge points to
int m_weight; // Weight of the connection
bool m_cutable; // Interconnect may be broken in order sorting
union {
void* m_userp; // Marker for some algorithms
uint32_t m_user; // Marker for some algorithms
void* m_userp; // Marker for some algorithms
uint32_t m_user; // Marker for some algorithms
};
// METHODS
void init(V3Graph* graphp, V3GraphVertex* fromp, V3GraphVertex* top,
int weight, bool cutable=false);
void init(V3Graph* graphp, V3GraphVertex* fromp, V3GraphVertex* top, int weight,
bool cutable = false);
void cut() { m_weight = 0; } // 0 weight is same as disconnected
void outPushBack();
void inPushBack();
@ -294,21 +306,23 @@ protected:
const V3GraphEdge& old) {
init(graphp, fromp, top, old.m_weight, old.m_cutable);
}
public:
//! Add DAG from one node to the specified node
V3GraphEdge(V3Graph* graphp, V3GraphVertex* fromp, V3GraphVertex* top,
int weight, bool cutable=false) {
V3GraphEdge(V3Graph* graphp, V3GraphVertex* fromp, V3GraphVertex* top, int weight,
bool cutable = false) {
init(graphp, fromp, top, weight, cutable);
}
//! Clone copy constructor. Doesn't copy existing vertices or user/userp.
virtual V3GraphEdge* clone(V3Graph* graphp, V3GraphVertex* fromp, V3GraphVertex* top) const {
return new V3GraphEdge(graphp, fromp, top, *this); }
return new V3GraphEdge(graphp, fromp, top, *this);
}
virtual ~V3GraphEdge() {}
// METHODS
virtual string name() const { return m_fromp->name()+"->"+m_top->name(); }
virtual string name() const { return m_fromp->name() + "->" + m_top->name(); }
virtual string dotLabel() const { return ""; }
virtual string dotColor() const { return cutable()?"yellowGreen":"red"; }
virtual string dotStyle() const { return cutable()?"dashed":""; }
virtual string dotColor() const { return cutable() ? "yellowGreen" : "red"; }
virtual string dotStyle() const { return cutable() ? "dashed" : ""; }
virtual int sortCmp(const V3GraphEdge* rhsp) const {
if (!m_weight || !rhsp->m_weight) return 0;
return top()->sortCmp(rhsp->top());
@ -334,8 +348,7 @@ public:
// ITERATORS
V3GraphEdge* outNextp() const { return m_outs.nextp(); }
V3GraphEdge* inNextp() const { return m_ins.nextp(); }
V3GraphEdge* nextp(GraphWay way) const {
return way.forward() ? outNextp() : inNextp(); }
V3GraphEdge* nextp(GraphWay way) const { return way.forward() ? outNextp() : inNextp(); }
};
//============================================================================

View File

@ -32,8 +32,8 @@
DfaVertex* DfaGraph::findStart() {
DfaVertex* startp = NULL;
for (V3GraphVertex* vertexp = this->verticesBeginp();
vertexp; vertexp=vertexp->verticesNextp()) {
for (V3GraphVertex* vertexp = this->verticesBeginp(); vertexp;
vertexp = vertexp->verticesNextp()) {
if (DfaVertex* vvertexp = dynamic_cast<DfaVertex*>(vertexp)) {
if (vvertexp->start()) {
UASSERT_OBJ(!startp, vertexp, "Multiple start points in NFA graph");
@ -60,11 +60,11 @@ class GraphNfaToDfa : GraphAlg<> {
private:
// TYPES
typedef std::deque<DfaVertex*> DfaStates;
typedef std::multimap<vluint64_t,DfaVertex*> HashMap;
typedef std::multimap<vluint64_t, DfaVertex*> HashMap;
// MEMBERS
uint32_t m_step; // Processing step, so we can avoid clearUser all the time
HashMap m_hashMap; // Dfa Vertex for each set of NFA vertexes
uint32_t m_step; // Processing step, so we can avoid clearUser all the time
HashMap m_hashMap; // Dfa Vertex for each set of NFA vertexes
#ifdef VL_CPPCHECK
static int debug() { return 9; }
@ -74,29 +74,37 @@ private:
// METHODS
DfaGraph* graphp() { return static_cast<DfaGraph*>(m_graphp); }
bool nfaState(V3GraphVertex* vertexp) { return vertexp->color()==0; }
//bool dfaState(V3GraphVertex* vertexp) { return vertexp->color()==1; }
bool nfaState(V3GraphVertex* vertexp) { return vertexp->color() == 0; }
// bool dfaState(V3GraphVertex* vertexp) { return vertexp->color()==1; }
void nextStep() { m_step++; }
bool unseenNfaThisStep(V3GraphVertex* vertexp) {
// A nfa node not already seen this processing step
return (nfaState(vertexp) && !(vertexp->user()==m_step));
return (nfaState(vertexp) && !(vertexp->user() == m_step));
}
DfaVertex* newDfaVertex(DfaVertex* nfaTemplatep=NULL) {
DfaVertex* newDfaVertex(DfaVertex* nfaTemplatep = NULL) {
DfaVertex* vertexp = new DfaVertex(graphp());
vertexp->color(1); // Mark as dfa
if (nfaTemplatep && nfaTemplatep->start()) vertexp->start(true);
if (nfaTemplatep && nfaTemplatep->accepting()) vertexp->accepting(true);
UINFO(9, " New "<<vertexp<<endl);
UINFO(9, " New " << vertexp << endl);
return vertexp;
}
// Hashing
static uint32_t hashVertex(V3GraphVertex* vertexp) {
union { void* up; struct {uint32_t upper; uint32_t lower;} l;} u;
u.l.upper = 0; u.l.lower = 0; u.up = vertexp;
union {
void* up;
struct {
uint32_t upper;
uint32_t lower;
} l;
} u;
u.l.upper = 0;
u.l.lower = 0;
u.up = vertexp;
return u.l.upper ^ u.l.lower;
}
@ -108,8 +116,8 @@ private:
uint32_t hash = 0;
// Foreach NFA state (this DFA state was formed from)
if (debug()) nextStep();
for (V3GraphEdge* dfaEdgep = dfaStatep->outBeginp();
dfaEdgep; dfaEdgep=dfaEdgep->outNextp()) {
for (V3GraphEdge* dfaEdgep = dfaStatep->outBeginp(); dfaEdgep;
dfaEdgep = dfaEdgep->outNextp()) {
if (nfaState(dfaEdgep->top())) {
DfaVertex* nfaStatep = static_cast<DfaVertex*>(dfaEdgep->top());
hash ^= hashVertex(nfaStatep);
@ -126,8 +134,8 @@ private:
uint32_t hashDfaOrigins(const DfaStates& nfasWithInput) {
// Find the NFA states this dfa came from,
uint32_t hash = 0;
for (DfaStates::const_iterator nfaIt=nfasWithInput.begin();
nfaIt!=nfasWithInput.end(); ++nfaIt) {
for (DfaStates::const_iterator nfaIt = nfasWithInput.begin(); nfaIt != nfasWithInput.end();
++nfaIt) {
DfaVertex* nfaStatep = *nfaIt;
hash ^= hashVertex(nfaStatep);
}
@ -140,8 +148,8 @@ private:
nextStep();
// Mark all input vertexes
int num1s = 0;
for (DfaStates::const_iterator nfaIt=nfasWithInput.begin();
nfaIt!=nfasWithInput.end(); ++nfaIt) {
for (DfaStates::const_iterator nfaIt = nfasWithInput.begin(); nfaIt != nfasWithInput.end();
++nfaIt) {
DfaVertex* nfaStatep = *nfaIt;
nfaStatep->user(m_step);
num1s++;
@ -151,7 +159,8 @@ private:
// Check comparison; must all be marked
// (Check all in dfa2p were in dfa1p)
int num2s = 0;
for (V3GraphEdge* dfaEdgep = dfa2p->outBeginp(); dfaEdgep; dfaEdgep=dfaEdgep->outNextp()) {
for (V3GraphEdge* dfaEdgep = dfa2p->outBeginp(); dfaEdgep;
dfaEdgep = dfaEdgep->outNextp()) {
if (nfaState(dfaEdgep->top())) {
if (dfaEdgep->top()->user() != m_step) return false;
num2s++;
@ -174,39 +183,38 @@ private:
// not depend on order of edges
uint32_t hash = hashDfaOrigins(nfasWithInput);
std::pair<HashMap::iterator,HashMap::iterator> eqrange = m_hashMap.equal_range(hash);
std::pair<HashMap::iterator, HashMap::iterator> eqrange = m_hashMap.equal_range(hash);
for (HashMap::iterator it = eqrange.first; it != eqrange.second; ++it) {
DfaVertex* testp = it->second;
if (compareDfaOrigins(nfasWithInput, testp)) {
UINFO(9," DFA match for set: "<<testp<<endl);
UINFO(9, " DFA match for set: " << testp << endl);
return testp; // Identical
}
}
return NULL; // No match
}
void findNfasWithInput(DfaVertex* dfaStatep, DfaInput input,
DfaStates& nfasWithInput) {
void findNfasWithInput(DfaVertex* dfaStatep, DfaInput input, DfaStates& nfasWithInput) {
// Return all NFA states, with the given input transition from
// the nfa states a given dfa state was constructed from.
nextStep();
nfasWithInput.clear(); // NFAs with given input
// Foreach NFA state (this DFA state was formed from)
for (V3GraphEdge* dfaEdgep = dfaStatep->outBeginp();
dfaEdgep; dfaEdgep=dfaEdgep->outNextp()) {
for (V3GraphEdge* dfaEdgep = dfaStatep->outBeginp(); dfaEdgep;
dfaEdgep = dfaEdgep->outNextp()) {
if (nfaState(dfaEdgep->top())) {
DfaVertex* nfaStatep = static_cast<DfaVertex*>(dfaEdgep->top());
// Foreach input transition (on this nfaStatep)
for (V3GraphEdge* nfaEdgep = nfaStatep->outBeginp();
nfaEdgep; nfaEdgep=nfaEdgep->outNextp()) {
for (V3GraphEdge* nfaEdgep = nfaStatep->outBeginp(); nfaEdgep;
nfaEdgep = nfaEdgep->outNextp()) {
DfaEdge* cNfaEdgep = static_cast<DfaEdge*>(nfaEdgep);
if (cNfaEdgep->input().toNodep() == input.toNodep()) {
DfaVertex* nextStatep = static_cast<DfaVertex*>(cNfaEdgep->top());
if (unseenNfaThisStep(nextStatep)) { // Not processed?
nfasWithInput.push_back(nextStatep);
nextStatep->user(m_step);
UINFO(9," Reachable "<<nextStatep<<endl);
UINFO(9, " Reachable " << nextStatep << endl);
}
}
}
@ -219,18 +227,19 @@ private:
DfaStates nfasTodo = nfasWithInput;
nfasWithInput.clear(); // Now the completed list
while (!nfasTodo.empty()) {
DfaVertex* nfaStatep = nfasTodo.front(); nfasTodo.pop_front();
DfaVertex* nfaStatep = nfasTodo.front();
nfasTodo.pop_front();
nfasWithInput.push_back(nfaStatep);
// Foreach epsilon-reachable (on this nfaStatep)
for (V3GraphEdge* nfaEdgep = nfaStatep->outBeginp();
nfaEdgep; nfaEdgep=nfaEdgep->outNextp()) {
for (V3GraphEdge* nfaEdgep = nfaStatep->outBeginp(); nfaEdgep;
nfaEdgep = nfaEdgep->outNextp()) {
DfaEdge* cNfaEdgep = static_cast<DfaEdge*>(nfaEdgep);
if (cNfaEdgep->epsilon()) {
DfaVertex* nextStatep = static_cast<DfaVertex*>(cNfaEdgep->top());
if (unseenNfaThisStep(nextStatep)) { // Not processed?
nfasTodo.push_back(nextStatep);
nextStatep->user(m_step);
UINFO(9," Epsilon Reachable "<<nextStatep<<endl);
UINFO(9, " Epsilon Reachable " << nextStatep << endl);
}
}
}
@ -239,13 +248,13 @@ private:
}
void main() {
UINFO(5,"Dfa to Nfa conversion...\n");
UINFO(5, "Dfa to Nfa conversion...\n");
// Vertex::color() begin: 1 indicates vertex on DFA graph, 0=NFA graph
m_graphp->clearColors();
// Vertex::m_user begin: # indicates processed this m_step number
m_graphp->userClearVertices();
if (debug()>=6) m_graphp->dumpDotFilePrefixed("dfa_nfa");
if (debug() >= 6) m_graphp->dumpDotFilePrefixed("dfa_nfa");
// Find NFA start
DfaVertex* nfaStartp = graphp()->findStart();
@ -256,55 +265,58 @@ private:
DfaStates dfaUnprocps; // Unprocessed DFA nodes
dfaUnprocps.push_back(dfaStartp);
UINFO(5,"Starting state conversion...\n");
UINFO(5, "Starting state conversion...\n");
// Form DFA starting state from epsilon closure of NFA start
nextStep();
DfaStates workps; workps.push_back(nfaStartp);
DfaStates workps;
workps.push_back(nfaStartp);
while (!workps.empty()) { // While work
DfaVertex* nfaStatep = workps.back(); workps.pop_back();
//UINFO(9," Processing "<<nfaStatep<<endl);
DfaVertex* nfaStatep = workps.back();
workps.pop_back();
// UINFO(9," Processing "<<nfaStatep<<endl);
nfaStatep->user(m_step); // Mark as processed
// Add a edge so we can find NFAs from a given DFA.
// The NFA will never see this edge, because we only look at TO edges.
new DfaEdge(graphp(), dfaStartp, nfaStatep, DfaEdge::NA());
// Find epsilon closure of this nfa node, and destinations to work list
for (V3GraphEdge* nfaEdgep = nfaStatep->outBeginp();
nfaEdgep; nfaEdgep=nfaEdgep->outNextp()) {
for (V3GraphEdge* nfaEdgep = nfaStatep->outBeginp(); nfaEdgep;
nfaEdgep = nfaEdgep->outNextp()) {
DfaEdge* cNfaEdgep = static_cast<DfaEdge*>(nfaEdgep);
DfaVertex* ecNfaStatep = static_cast<DfaVertex*>(nfaEdgep->top());
//UINFO(9," Consider "<<nfaEdgep->top()<<" EP "<<cNfaEdgep->epsilon()<<endl);
if (cNfaEdgep->epsilon()
&& unseenNfaThisStep(ecNfaStatep)) { // Not processed?
// UINFO(9," Consider "<<nfaEdgep->top()<<" EP "<<cNfaEdgep->epsilon()<<endl);
if (cNfaEdgep->epsilon() && unseenNfaThisStep(ecNfaStatep)) { // Not processed?
workps.push_back(ecNfaStatep);
}
}
}
if (debug()>=6) m_graphp->dumpDotFilePrefixed("dfa_start");
if (debug() >= 6) m_graphp->dumpDotFilePrefixed("dfa_start");
insertDfaOrigins(dfaStartp);
int i = 0;
UINFO(5,"Main state conversion...\n");
UINFO(5, "Main state conversion...\n");
while (!dfaUnprocps.empty()) {
DfaVertex* dfaStatep = dfaUnprocps.back(); dfaUnprocps.pop_back();
UINFO(9," On dfaState "<<dfaStatep<<endl);
DfaVertex* dfaStatep = dfaUnprocps.back();
dfaUnprocps.pop_back();
UINFO(9, " On dfaState " << dfaStatep << endl);
// From this dfaState, what corresponding nfaStates have what inputs?
std::set<int> inputs;
// Foreach NFA state (this DFA state was formed from)
for (V3GraphEdge* dfaEdgep = dfaStatep->outBeginp();
dfaEdgep; dfaEdgep=dfaEdgep->outNextp()) {
for (V3GraphEdge* dfaEdgep = dfaStatep->outBeginp(); dfaEdgep;
dfaEdgep = dfaEdgep->outNextp()) {
if (nfaState(dfaEdgep->top())) {
DfaVertex* nfaStatep = static_cast<DfaVertex*>(dfaEdgep->top());
// Foreach input on this nfaStatep
for (V3GraphEdge* nfaEdgep = nfaStatep->outBeginp();
nfaEdgep; nfaEdgep=nfaEdgep->outNextp()) {
for (V3GraphEdge* nfaEdgep = nfaStatep->outBeginp(); nfaEdgep;
nfaEdgep = nfaEdgep->outNextp()) {
DfaEdge* cNfaEdgep = static_cast<DfaEdge*>(nfaEdgep);
if (!cNfaEdgep->epsilon()) {
if (inputs.find(cNfaEdgep->input().toInt()) == inputs.end()) {
inputs.insert(cNfaEdgep->input().toInt());
UINFO(9," Input to "<<dfaStatep<<" is "
<<(cNfaEdgep->input().toInt())<<" via "<<nfaStatep<<endl);
UINFO(9, " Input to " << dfaStatep << " is "
<< (cNfaEdgep->input().toInt()) << " via "
<< nfaStatep << endl);
}
}
}
@ -312,14 +324,15 @@ private:
}
// Foreach input state (NFA inputs of this DFA state)
for (std::set<int>::const_iterator inIt=inputs.begin(); inIt!=inputs.end(); ++inIt) {
for (std::set<int>::const_iterator inIt = inputs.begin(); inIt != inputs.end();
++inIt) {
DfaInput input = *inIt;
UINFO(9," ==="<<++i<<"=======================\n");
UINFO(9," On input "<<cvtToHex(input.toNodep())<<endl);
UINFO(9, " ===" << ++i << "=======================\n");
UINFO(9, " On input " << cvtToHex(input.toNodep()) << endl);
// Find all states reachable for given input
DfaStates nfasWithInput;
findNfasWithInput(dfaStatep, input, nfasWithInput/*ref*/);
findNfasWithInput(dfaStatep, input, nfasWithInput /*ref*/);
// nfasWithInput now maps to the DFA we want a transition to.
// Does a DFA already exist with this, and only this subset of NFA's?
@ -329,9 +342,9 @@ private:
toDfaStatep = newDfaVertex();
dfaUnprocps.push_back(toDfaStatep); // Add to process list
// Track what nfa's point to it.
for (DfaStates::const_iterator nfaIt=nfasWithInput.begin();
nfaIt!=nfasWithInput.end(); ++nfaIt) {
UINFO(9," NewContainsNfa "<<*nfaIt<<endl);
for (DfaStates::const_iterator nfaIt = nfasWithInput.begin();
nfaIt != nfasWithInput.end(); ++nfaIt) {
UINFO(9, " NewContainsNfa " << *nfaIt << endl);
new DfaEdge(graphp(), toDfaStatep, *nfaIt, DfaEdge::NA());
if ((*nfaIt)->accepting()) toDfaStatep->accepting(true);
}
@ -340,22 +353,21 @@ private:
// Add input transition
new DfaEdge(graphp(), dfaStatep, toDfaStatep, input);
if (debug()>=6) m_graphp->dumpDotFilePrefixed("step");
if (debug() >= 6) m_graphp->dumpDotFilePrefixed("step");
}
}
// Remove old NFA states
UINFO(5,"Removing NFA states...\n");
if (debug()>=6) m_graphp->dumpDotFilePrefixed("dfa_withnfa");
for (V3GraphVertex* nextp,*vertexp = m_graphp->verticesBeginp(); vertexp; vertexp=nextp) {
UINFO(5, "Removing NFA states...\n");
if (debug() >= 6) m_graphp->dumpDotFilePrefixed("dfa_withnfa");
for (V3GraphVertex *nextp, *vertexp = m_graphp->verticesBeginp(); vertexp;
vertexp = nextp) {
nextp = vertexp->verticesNextp();
if (nfaState(vertexp)) {
VL_DO_DANGLING(vertexp->unlinkDelete(m_graphp), vertexp);
}
if (nfaState(vertexp)) VL_DO_DANGLING(vertexp->unlinkDelete(m_graphp), vertexp);
}
UINFO(5,"Done.\n");
if (debug()>=6) m_graphp->dumpDotFilePrefixed("dfa_done");
UINFO(5, "Done.\n");
if (debug() >= 6) m_graphp->dumpDotFilePrefixed("dfa_done");
}
public:
@ -367,9 +379,7 @@ public:
~GraphNfaToDfa() {}
};
void DfaGraph::nfaToDfa() {
GraphNfaToDfa(this, &V3GraphEdge::followAlwaysTrue);
}
void DfaGraph::nfaToDfa() { GraphNfaToDfa(this, &V3GraphEdge::followAlwaysTrue); }
//######################################################################
//######################################################################
@ -390,7 +400,7 @@ private:
bool isDead(DfaVertex* vertexp) {
// A state is dead if not accepting, and goes nowhere
if (vertexp->accepting() || vertexp->start()) return false;
for (V3GraphEdge* edgep = vertexp->outBeginp(); edgep; edgep=edgep->outNextp()) {
for (V3GraphEdge* edgep = vertexp->outBeginp(); edgep; edgep = edgep->outNextp()) {
if (edgep->top() != vertexp) return false;
}
return true;
@ -399,11 +409,11 @@ private:
void optimize_accepting_out() {
// Delete outbound edges from accepting states
// (As once we've accepted, we no longer care about anything else.)
for (V3GraphVertex* vertexp = m_graphp->verticesBeginp();
vertexp; vertexp=vertexp->verticesNextp()) {
for (V3GraphVertex* vertexp = m_graphp->verticesBeginp(); vertexp;
vertexp = vertexp->verticesNextp()) {
if (DfaVertex* vvertexp = dynamic_cast<DfaVertex*>(vertexp)) {
if (vvertexp->accepting()) {
for (V3GraphEdge* nextp,*edgep = vertexp->outBeginp(); edgep; edgep=nextp) {
for (V3GraphEdge *nextp, *edgep = vertexp->outBeginp(); edgep; edgep = nextp) {
nextp = edgep->outNextp();
VL_DO_DANGLING(edgep->unlinkDelete(), edgep);
}
@ -421,14 +431,16 @@ private:
m_graphp->userClearVertices();
DfaVertex* startp = graphp()->findStart();
std::stack<V3GraphVertex*> workps; workps.push(startp);
std::stack<V3GraphVertex*> workps;
workps.push(startp);
// Mark all nodes connected to start
while (!workps.empty()) {
V3GraphVertex* vertexp = workps.top(); workps.pop();
V3GraphVertex* vertexp = workps.top();
workps.pop();
vertexp->user(2); // Processed
// Add nodes from here to the work list
for (V3GraphEdge* edgep = vertexp->outBeginp(); edgep; edgep=edgep->outNextp()) {
for (V3GraphEdge* edgep = vertexp->outBeginp(); edgep; edgep = edgep->outNextp()) {
V3GraphVertex* tovertexp = edgep->top();
if (!tovertexp->user()) {
workps.push(tovertexp);
@ -438,11 +450,10 @@ private:
}
// Delete all nodes not connected
for (V3GraphVertex* nextp,*vertexp = m_graphp->verticesBeginp(); vertexp; vertexp=nextp) {
for (V3GraphVertex *nextp, *vertexp = m_graphp->verticesBeginp(); vertexp;
vertexp = nextp) {
nextp = vertexp->verticesNextp();
if (!vertexp->user()) {
VL_DO_DANGLING(vertexp->unlinkDelete(m_graphp), vertexp);
}
if (!vertexp->user()) { VL_DO_DANGLING(vertexp->unlinkDelete(m_graphp), vertexp); }
}
}
@ -457,8 +468,8 @@ private:
// Find all dead vertexes
std::stack<DfaVertex*> workps;
for (V3GraphVertex* vertexp = m_graphp->verticesBeginp();
vertexp; vertexp=vertexp->verticesNextp()) {
for (V3GraphVertex* vertexp = m_graphp->verticesBeginp(); vertexp;
vertexp = vertexp->verticesNextp()) {
if (DfaVertex* vvertexp = dynamic_cast<DfaVertex*>(vertexp)) {
workps.push(vvertexp);
vertexp->user(1);
@ -470,14 +481,14 @@ private:
// While deadness... Delete and find new dead nodes.
while (!workps.empty()) {
DfaVertex* vertexp = workps.top(); workps.pop();
DfaVertex* vertexp = workps.top();
workps.pop();
vertexp->user(0);
if (isDead(vertexp)) {
// Add nodes that go here to the work list
for (V3GraphEdge* edgep = vertexp->inBeginp(); edgep; edgep=edgep->inNextp()) {
for (V3GraphEdge* edgep = vertexp->inBeginp(); edgep; edgep = edgep->inNextp()) {
DfaVertex* fromvertexp = static_cast<DfaVertex*>(edgep->fromp());
if (fromvertexp != vertexp
&& !fromvertexp->user()) {
if (fromvertexp != vertexp && !fromvertexp->user()) {
workps.push(fromvertexp);
fromvertexp->user(1);
}
@ -487,23 +498,22 @@ private:
}
}
}
public:
DfaGraphReduce(V3Graph* graphp, V3EdgeFuncP edgeFuncp)
: GraphAlg<>(graphp, edgeFuncp) {
if (debug()>=6) m_graphp->dumpDotFilePrefixed("opt_in");
if (debug() >= 6) m_graphp->dumpDotFilePrefixed("opt_in");
optimize_accepting_out();
if (debug()>=6) m_graphp->dumpDotFilePrefixed("opt_acc");
if (debug() >= 6) m_graphp->dumpDotFilePrefixed("opt_acc");
optimize_orphans();
if (debug()>=6) m_graphp->dumpDotFilePrefixed("opt_orph");
if (debug() >= 6) m_graphp->dumpDotFilePrefixed("opt_orph");
optimize_no_outbound();
if (debug()>=6) m_graphp->dumpDotFilePrefixed("opt_noout");
if (debug() >= 6) m_graphp->dumpDotFilePrefixed("opt_noout");
}
~DfaGraphReduce() {}
};
void DfaGraph::dfaReduce() {
DfaGraphReduce(this, &V3GraphEdge::followAlwaysTrue);
}
void DfaGraph::dfaReduce() { DfaGraphReduce(this, &V3GraphEdge::followAlwaysTrue); }
//######################################################################
//######################################################################
@ -537,8 +547,8 @@ private:
void add_complement_edges() {
// Find accepting vertex
DfaVertex* acceptp = NULL;
for (V3GraphVertex* vertexp = m_graphp->verticesBeginp();
vertexp; vertexp=vertexp->verticesNextp()) {
for (V3GraphVertex* vertexp = m_graphp->verticesBeginp(); vertexp;
vertexp = vertexp->verticesNextp()) {
if (DfaVertex* vvertexp = dynamic_cast<DfaVertex*>(vertexp)) {
if (vvertexp->accepting()) {
acceptp = vvertexp;
@ -549,12 +559,12 @@ private:
if (!acceptp) v3fatalSrc("No accepting vertex in DFA");
// Remap edges
for (V3GraphVertex* vertexp = m_graphp->verticesBeginp();
vertexp; vertexp=vertexp->verticesNextp()) {
for (V3GraphVertex* vertexp = m_graphp->verticesBeginp(); vertexp;
vertexp = vertexp->verticesNextp()) {
if (DfaVertex* vvertexp = dynamic_cast<DfaVertex*>(vertexp)) {
//UINFO(9, " on vertex "<<vvertexp->name()<<endl);
// UINFO(9, " on vertex "<<vvertexp->name()<<endl);
if (!vvertexp->accepting() && vvertexp != m_tempNewerReject) {
for (V3GraphEdge* nextp, *edgep = vertexp->outBeginp(); edgep; edgep=nextp) {
for (V3GraphEdge *nextp, *edgep = vertexp->outBeginp(); edgep; edgep = nextp) {
nextp = edgep->outNextp();
if (!edgep->user()) { // Not processed
// Old edges to accept now go to new reject
@ -568,7 +578,8 @@ private:
// NOT of all values goes to accept
// We make a edge for each value to OR, IE
// edge(complemented,a) edge(complemented,b) means !(a | b)
if (!tovertexp->accepting()) { // Note we must include edges moved above to reject
if (!tovertexp->accepting()) {
// Note we must include edges moved above to reject
DfaEdge* newp = new DfaEdge(graphp(), vvertexp, acceptp, vedgep);
newp->complement(!newp->complement());
newp->user(1);
@ -579,25 +590,24 @@ private:
}
}
}
public:
DfaGraphComplement(V3Graph* dfagraphp, V3EdgeFuncP edgeFuncp)
: GraphAlg<>(dfagraphp, edgeFuncp) {
if (debug()>=6) m_graphp->dumpDotFilePrefixed("comp_in");
if (debug() >= 6) m_graphp->dumpDotFilePrefixed("comp_in");
// Vertex::m_user begin: 1 indicates new edge, no more processing
m_graphp->userClearEdges();
m_tempNewerReject = new DfaVertex(graphp());
add_complement_edges();
if (debug()>=6) m_graphp->dumpDotFilePrefixed("comp_preswap");
if (debug() >= 6) m_graphp->dumpDotFilePrefixed("comp_preswap");
VL_DO_CLEAR(m_tempNewerReject->unlinkDelete(graphp()), m_tempNewerReject = NULL);
if (debug()>=6) m_graphp->dumpDotFilePrefixed("comp_out");
if (debug() >= 6) m_graphp->dumpDotFilePrefixed("comp_out");
}
~DfaGraphComplement() {}
VL_UNCOPYABLE(DfaGraphComplement);
};
void DfaGraph::dfaComplement() {
DfaGraphComplement(this, &V3GraphEdge::followAlwaysTrue);
}
void DfaGraph::dfaComplement() { DfaGraphComplement(this, &V3GraphEdge::followAlwaysTrue); }

View File

@ -85,16 +85,18 @@ class DfaVertex : public V3GraphVertex {
bool m_accepting; // Accepting state?
public:
// CONSTRUCTORS
explicit DfaVertex(DfaGraph* graphp, bool start=false, bool accepting=false)
explicit DfaVertex(DfaGraph* graphp, bool start = false, bool accepting = false)
: V3GraphVertex(graphp)
, m_start(start), m_accepting(accepting) {}
, m_start(start)
, m_accepting(accepting) {}
using V3GraphVertex::clone; // We are overriding, not overloading clone(V3Graph*)
virtual DfaVertex* clone(DfaGraph* graphp) {
return new DfaVertex(graphp, start(), accepting()); }
return new DfaVertex(graphp, start(), accepting());
}
virtual ~DfaVertex() {}
// ACCESSORS
virtual string dotShape() const { return (accepting()?"doublecircle":""); }
virtual string dotColor() const { return start()?"blue":(color()?"red":"black"); }
virtual string dotShape() const { return (accepting() ? "doublecircle" : ""); }
virtual string dotColor() const { return start() ? "blue" : (color() ? "red" : "black"); }
bool start() const { return m_start; }
void start(bool flag) { m_start = flag; }
bool accepting() const { return m_accepting; }
@ -118,24 +120,24 @@ public:
// CONSTRUCTORS
DfaEdge(DfaGraph* graphp, DfaVertex* fromp, DfaVertex* top, const DfaInput& input)
: V3GraphEdge(graphp, fromp, top, 1)
, m_input(input), m_complement(false) {}
, m_input(input)
, m_complement(false) {}
DfaEdge(DfaGraph* graphp, DfaVertex* fromp, DfaVertex* top, const DfaEdge* copyfrom)
: V3GraphEdge(graphp, fromp, top, copyfrom->weight())
, m_input(copyfrom->input()), m_complement(copyfrom->complement()) {}
, m_input(copyfrom->input())
, m_complement(copyfrom->complement()) {}
virtual ~DfaEdge() {}
// METHODS
virtual string dotColor() const {
return (na() ? "yellow"
: epsilon() ? "green"
: "black"); }
virtual string dotColor() const { return (na() ? "yellow" : epsilon() ? "green" : "black"); }
virtual string dotLabel() const {
return (na() ? ""
: epsilon() ? "e"
: complement() ? ("not "+cvtToStr(input().toInt()))
: cvtToStr(input().toInt())); }
virtual string dotStyle() const { return (na()||cutable())?"dashed":""; }
bool epsilon() const { return input().toInt()==EPSILON().toInt(); }
bool na() const { return input().toInt()==NA().toInt(); }
: epsilon() ? "e"
: complement() ? ("not " + cvtToStr(input().toInt()))
: cvtToStr(input().toInt()));
}
virtual string dotStyle() const { return (na() || cutable()) ? "dashed" : ""; }
bool epsilon() const { return input().toInt() == EPSILON().toInt(); }
bool na() const { return input().toInt() == NA().toInt(); }
bool complement() const { return m_complement; }
void complement(bool value) { m_complement = value; }
DfaInput input() const { return m_input; }

View File

@ -41,10 +41,11 @@ struct GraphPCNode {
vluint64_t m_seenAtGeneration;
// CONSTRUCTORS
GraphPCNode() : m_seenAtGeneration(0) {
GraphPCNode()
: m_seenAtGeneration(0) {
for (int w = 0; w < GraphWay::NUM_WAYS; w++) m_cp[w] = 0;
}
~GraphPCNode() { }
~GraphPCNode() {}
};
//######################################################################
@ -53,8 +54,7 @@ struct GraphPCNode {
GraphPathChecker::GraphPathChecker(const V3Graph* graphp, V3EdgeFuncP edgeFuncp)
: GraphAlg<const V3Graph>(graphp, edgeFuncp)
, m_generation(0) {
for (V3GraphVertex* vxp = graphp->verticesBeginp();
vxp; vxp = vxp->verticesNextp()) {
for (V3GraphVertex* vxp = graphp->verticesBeginp(); vxp; vxp = vxp->verticesNextp()) {
// Setup tracking structure for each node. If delete a vertex
// there would be a leak, but ok as accept only const V3Graph*'s.
vxp->userp(new GraphPCNode);
@ -66,8 +66,7 @@ GraphPathChecker::GraphPathChecker(const V3Graph* graphp, V3EdgeFuncP edgeFuncp)
GraphPathChecker::~GraphPathChecker() {
// Free every GraphPCNode
for (V3GraphVertex* vxp = m_graphp->verticesBeginp();
vxp; vxp = vxp->verticesNextp()) {
for (V3GraphVertex* vxp = m_graphp->verticesBeginp(); vxp; vxp = vxp->verticesNextp()) {
GraphPCNode* nodep = static_cast<GraphPCNode*>(vxp->userp());
VL_DO_DANGLING(delete nodep, nodep);
vxp->userp(NULL);
@ -79,8 +78,7 @@ void GraphPathChecker::initHalfCriticalPaths(GraphWay way, bool checkOnly) {
GraphWay rev = way.invert();
while (const V3GraphVertex* vertexp = order.nextp()) {
unsigned critPathCost = 0;
for (V3GraphEdge* edgep = vertexp->beginp(rev);
edgep; edgep = edgep->nextp(rev)) {
for (V3GraphEdge* edgep = vertexp->beginp(rev); edgep; edgep = edgep->nextp(rev)) {
if (!m_edgeFuncp(edgep)) continue;
V3GraphVertex* wrelativep = edgep->furtherp(rev);
@ -90,16 +88,15 @@ void GraphPathChecker::initHalfCriticalPaths(GraphWay way, bool checkOnly) {
GraphPCNode* ourUserp = static_cast<GraphPCNode*>(vertexp->userp());
if (checkOnly) {
UASSERT_OBJ(ourUserp->m_cp[way] == critPathCost,
vertexp, "Validation of critical paths failed");
UASSERT_OBJ(ourUserp->m_cp[way] == critPathCost, vertexp,
"Validation of critical paths failed");
} else {
ourUserp->m_cp[way] = critPathCost;
}
}
}
bool GraphPathChecker::pathExistsInternal(const V3GraphVertex* ap,
const V3GraphVertex* bp,
bool GraphPathChecker::pathExistsInternal(const V3GraphVertex* ap, const V3GraphVertex* bp,
unsigned* costp) {
GraphPCNode* auserp = static_cast<GraphPCNode*>(ap->userp());
GraphPCNode* buserp = static_cast<GraphPCNode*>(bp->userp());
@ -118,31 +115,23 @@ bool GraphPathChecker::pathExistsInternal(const V3GraphVertex* ap,
if (ap == bp) return true;
// Rule out an a->b path based on their CPs
if (auserp->m_cp[GraphWay::REVERSE] < buserp->m_cp[GraphWay::REVERSE] + 1) {
return false;
}
if (buserp->m_cp[GraphWay::FORWARD] < auserp->m_cp[GraphWay::FORWARD] + 1) {
return false;
}
if (auserp->m_cp[GraphWay::REVERSE] < buserp->m_cp[GraphWay::REVERSE] + 1) return false;
if (buserp->m_cp[GraphWay::FORWARD] < auserp->m_cp[GraphWay::FORWARD] + 1) return false;
// Slow path; visit some extended family
bool foundPath = false;
for (V3GraphEdge* edgep = ap->outBeginp();
edgep && !foundPath; edgep = edgep->outNextp()) {
for (V3GraphEdge* edgep = ap->outBeginp(); edgep && !foundPath; edgep = edgep->outNextp()) {
if (!m_edgeFuncp(edgep)) continue;
unsigned childCost;
if (pathExistsInternal(edgep->top(), bp, &childCost)) {
foundPath = true;
}
if (pathExistsInternal(edgep->top(), bp, &childCost)) foundPath = true;
if (costp) *costp += childCost;
}
return foundPath;
}
bool GraphPathChecker::pathExistsFrom(const V3GraphVertex* fromp,
const V3GraphVertex* top) {
bool GraphPathChecker::pathExistsFrom(const V3GraphVertex* fromp, const V3GraphVertex* top) {
incGeneration();
return pathExistsInternal(fromp, top);
}
@ -151,12 +140,10 @@ bool GraphPathChecker::isTransitiveEdge(const V3GraphEdge* edgep) {
const V3GraphVertex* fromp = edgep->fromp();
const V3GraphVertex* top = edgep->top();
incGeneration();
for (const V3GraphEdge* fromOutp = fromp->outBeginp();
fromOutp; fromOutp = fromOutp->outNextp()) {
for (const V3GraphEdge* fromOutp = fromp->outBeginp(); fromOutp;
fromOutp = fromOutp->outNextp()) {
if (fromOutp == edgep) continue;
if (pathExistsInternal(fromOutp->top(), top)) {
return true;
}
if (pathExistsInternal(fromOutp->top(), top)) return true;
}
return false;
}

View File

@ -70,11 +70,12 @@ private:
explicit VxHolderCmp(const T_Compare& lessThan)
: m_lessThan(lessThan) {}
// METHODS
bool operator() (const VxHolder& a, const VxHolder& b) const {
bool operator()(const VxHolder& a, const VxHolder& b) const {
if (m_lessThan.operator()(a.vertexp(), b.vertexp())) return true;
if (m_lessThan.operator()(b.vertexp(), a.vertexp())) return false;
return a.m_pos < b.m_pos;
}
private:
VL_UNCOPYABLE(VxHolderCmp);
};
@ -91,8 +92,7 @@ private:
public:
// CONSTRUCTORS
explicit GraphStream(const V3Graph* graphp,
GraphWay way = GraphWay::FORWARD,
explicit GraphStream(const V3Graph* graphp, GraphWay way = GraphWay::FORWARD,
const T_Compare& lessThan = T_Compare())
// NOTE: Perhaps REVERSE way should also reverse the sense of the
// lessThan function? For now the only usage of REVERSE is not
@ -102,8 +102,8 @@ public:
, m_last(m_readyVertices.end())
, m_way(way) {
uint32_t pos = 0;
for (const V3GraphVertex* vxp = graphp->verticesBeginp();
vxp; vxp=vxp->verticesNextp()) {
for (const V3GraphVertex* vxp = graphp->verticesBeginp(); vxp;
vxp = vxp->verticesNextp()) {
// Every vertex initially is waiting, or ready.
if (way == GraphWay::FORWARD) {
if (vxp->inEmpty()) {
@ -111,8 +111,7 @@ public:
m_readyVertices.insert(newVx);
} else {
uint32_t depCount = 0;
for (V3GraphEdge* depp = vxp->inBeginp();
depp; depp = depp->inNextp()) {
for (V3GraphEdge* depp = vxp->inBeginp(); depp; depp = depp->inNextp()) {
depCount++;
}
VxHolder newVx(vxp, pos++, depCount);
@ -124,8 +123,7 @@ public:
m_readyVertices.insert(newVx);
} else {
uint32_t depCount = 0;
for (V3GraphEdge* depp = vxp->outBeginp();
depp; depp = depp->outNextp()) {
for (V3GraphEdge* depp = vxp->outBeginp(); depp; depp = depp->outNextp()) {
depCount++;
}
VxHolder newVx(vxp, pos++, depCount);
@ -177,9 +175,7 @@ public:
// Wrap curIt. Expect to wrap, and make another pass, to find
// newly-ready elements that could have appeared ahead of the
// m_last iterator
if (curIt == m_readyVertices.end()) {
curIt = m_readyVertices.begin();
}
if (curIt == m_readyVertices.end()) { curIt = m_readyVertices.begin(); }
}
if (curIt != m_readyVertices.end()) {
@ -198,12 +194,10 @@ public:
private:
void unblockDeps(const V3GraphVertex* vertexp) {
if (m_way == GraphWay::FORWARD) {
for (V3GraphEdge* edgep = vertexp->outBeginp();
edgep; edgep=edgep->outNextp()) {
for (V3GraphEdge* edgep = vertexp->outBeginp(); edgep; edgep = edgep->outNextp()) {
V3GraphVertex* toVertexp = edgep->top();
typename WaitingVertices::iterator it =
m_waitingVertices.find(toVertexp);
typename WaitingVertices::iterator it = m_waitingVertices.find(toVertexp);
UASSERT_OBJ(it != m_waitingVertices.end(), toVertexp,
"Found edge into vertex not in waiting list.");
if (it->second.unblock()) {
@ -212,12 +206,10 @@ private:
}
}
} else {
for (V3GraphEdge* edgep = vertexp->inBeginp();
edgep; edgep=edgep->inNextp()) {
for (V3GraphEdge* edgep = vertexp->inBeginp(); edgep; edgep = edgep->inNextp()) {
V3GraphVertex* fromVertexp = edgep->fromp();
typename WaitingVertices::iterator it =
m_waitingVertices.find(fromVertexp);
typename WaitingVertices::iterator it = m_waitingVertices.find(fromVertexp);
UASSERT_OBJ(it != m_waitingVertices.end(), fromVertexp,
"Found edge into vertex not in waiting list.");
if (it->second.unblock()) {

View File

@ -50,8 +50,9 @@ class V3Hashed : public VHashedBase {
// TYPES
public:
typedef std::multimap<V3Hash,AstNode*> HashMmap;
typedef std::multimap<V3Hash, AstNode*> HashMmap;
typedef HashMmap::iterator iterator;
private:
// MEMBERS
HashMmap m_hashMmap; // hashvalue -> nodes with that hash
@ -67,17 +68,21 @@ public:
iterator end() { return m_hashMmap.end(); }
// METHODS
void clear() { m_hashMmap.clear(); AstNode::user4ClearTree(); }
void clear() {
m_hashMmap.clear();
AstNode::user4ClearTree();
}
void check(); // Check assertions on structure
iterator hashAndInsert(AstNode* nodep); // Hash the node, and insert into map. Return iterator to inserted
// Hash the node, and insert into map. Return iterator to inserted
iterator hashAndInsert(AstNode* nodep);
void hash(AstNode* nodep); // Only hash the node
bool sameNodes(AstNode* node1p, AstNode* node2p); // After hashing, and tell if identical
void erase(iterator it); // Remove node from structures
// Return duplicate in hash, if any, with optional user check for sameness
iterator findDuplicate(AstNode* nodep, V3HashedUserSame* checkp=NULL);
iterator findDuplicate(AstNode* nodep, V3HashedUserSame* checkp = NULL);
AstNode* iteratorNodep(iterator it) { return it->second; }
void dumpFile(const string& filename, bool tree);
void dumpFilePrefixed(const string& nameComment, bool tree=false);
void dumpFilePrefixed(const string& nameComment, bool tree = false);
static V3Hash nodeHash(AstNode* nodep) { return V3Hash(nodep->user4p()); }
// Hash of the nodep tree, without caching in user4.
static V3Hash uncachedHash(const AstNode* nodep);

View File

@ -29,8 +29,8 @@ class V3Inst {
public:
static void instAll(AstNetlist* nodep);
static void dearrayAll(AstNetlist* nodep);
static AstAssignW* pinReconnectSimple(AstPin* pinp, AstCell* cellp,
bool forTristate, bool alwaysCvt=false);
static AstAssignW* pinReconnectSimple(AstPin* pinp, AstCell* cellp, bool forTristate,
bool alwaysCvt = false);
static void checkOutputShort(AstPin* nodep);
};

View File

@ -52,15 +52,16 @@ private:
uint32_t m_savedCount;
AstNode* m_nodep;
InstrCountVisitor* m_visitor;
public:
// CONSTRUCTORS
VisitBase(InstrCountVisitor* visitor, AstNode* nodep)
: m_nodep(nodep), m_visitor(visitor) {
: m_nodep(nodep)
, m_visitor(visitor) {
m_savedCount = m_visitor->startVisitBase(nodep);
}
~VisitBase() {
m_visitor->endVisitBase(m_savedCount, m_nodep);
}
~VisitBase() { m_visitor->endVisitBase(m_savedCount, m_nodep); }
private:
VL_UNCOPYABLE(VisitBase);
};
@ -68,13 +69,12 @@ private:
public:
// CONSTRUCTORS
InstrCountVisitor(AstNode* nodep, bool assertNoDups, std::ostream* osp)
: m_instrCount(0),
m_startNodep(nodep),
m_tracingCall(false),
m_inCFunc(false),
m_assertNoDups(assertNoDups),
m_osp(osp)
{
: m_instrCount(0)
, m_startNodep(nodep)
, m_tracingCall(false)
, m_inCFunc(false)
, m_assertNoDups(assertNoDups)
, m_osp(osp) {
if (nodep) iterate(nodep);
}
virtual ~InstrCountVisitor() {}
@ -98,7 +98,7 @@ private:
// collisions in CFuncs.
UASSERT_OBJ(!nodep->user5p(), nodep,
"Node originally inserted below logic vertex "
<<static_cast<AstNode*>(nodep->user5p()));
<< static_cast<AstNode*>(nodep->user5p()));
nodep->user5p(const_cast<void*>(reinterpret_cast<const void*>(m_startNodep)));
}
@ -110,13 +110,12 @@ private:
return savedCount;
}
void endVisitBase(uint32_t savedCount, AstNode* nodep) {
UINFO(8, "cost "<<std::setw(6)<<std::left<<m_instrCount
<<" "<<nodep<<endl);
UINFO(8, "cost " << std::setw(6) << std::left << m_instrCount << " " << nodep << endl);
markCost(nodep);
m_instrCount += savedCount;
}
void markCost(AstNode* nodep) {
if (m_osp) nodep->user4(m_instrCount+1); // Else don't mark to avoid writeback
if (m_osp) nodep->user4(m_instrCount + 1); // Else don't mark to avoid writeback
}
// VISITORS
@ -275,7 +274,8 @@ private:
public:
// CONSTRUCTORS
InstrCountDumpVisitor(AstNode* nodep, std::ostream* osp)
: m_osp(osp), m_depth(0) {
: m_osp(osp)
, m_depth(0) {
// No check for NULL output, so...
UASSERT_OBJ(osp, nodep, "Don't call if not dumping");
if (nodep) iterate(nodep);
@ -284,13 +284,12 @@ public:
private:
// METHODS
string indent() { return string(m_depth, ':')+" "; }
string indent() { return string(m_depth, ':') + " "; }
virtual void visit(AstNode* nodep) VL_OVERRIDE {
++m_depth;
if (unsigned costPlus1 = nodep->user4()) {
*m_osp <<" "<<indent()
<<"cost "<<std::setw(6)<<std::left<<(costPlus1-1)
<<" "<<nodep<<endl;
*m_osp << " " << indent() << "cost " << std::setw(6) << std::left << (costPlus1 - 1)
<< " " << nodep << endl;
iterateChildren(nodep);
}
--m_depth;

View File

@ -43,30 +43,26 @@ public:
_ENUM_END
};
const char* ascii() const {
const char* const names[] = {
// These must match the `begin_keywords values.
" ERROR",
"1364-1995",
"1364-2001",
"1364-2005",
"1800-2005",
"1800-2009",
"1800-2012",
"1800-2017"
};
const char* const names[] = {// These must match the `begin_keywords values.
" ERROR", "1364-1995", "1364-2001", "1364-2005",
"1800-2005", "1800-2009", "1800-2012", "1800-2017"};
return names[m_e];
}
static V3LangCode mostRecent() { return V3LangCode(L1800_2017); }
bool systemVerilog() const { return m_e == L1800_2005 || m_e == L1800_2009
|| m_e == L1800_2012 || m_e == L1800_2017; }
bool systemVerilog() const {
return m_e == L1800_2005 || m_e == L1800_2009 || m_e == L1800_2012 || m_e == L1800_2017;
}
bool legal() const { return m_e != L_ERROR; }
//
enum en m_e;
inline V3LangCode() : m_e(L_ERROR) {}
inline V3LangCode()
: m_e(L_ERROR) {}
// cppcheck-suppress noExplicitConstructor
inline V3LangCode(en _e) : m_e(_e) {}
inline V3LangCode(en _e)
: m_e(_e) {}
explicit V3LangCode(const char* textp);
explicit inline V3LangCode(int _e) : m_e(static_cast<en>(_e)) {}
explicit inline V3LangCode(int _e)
: m_e(static_cast<en>(_e)) {}
operator en() const { return m_e; }
};

View File

@ -26,17 +26,16 @@
class V3LanguageWords {
// List of common reserved keywords
private:
typedef std::map<string,string> KeywordMap;
private:
typedef std::map<string, string> KeywordMap;
struct Singleton {
KeywordMap s_kwdMap; // List of keywords, and what language applies
Singleton() { init(); }
void addKwd(const string& kwd, const string& why) {
s_kwdMap.insert(make_pair(kwd, why));
}
void addKwd(const string& kwd, const string& why) { s_kwdMap.insert(make_pair(kwd, why)); }
void init();
};
public:
public:
typedef KeywordMap::const_iterator const_iterator;
// METHODS
static const_iterator begin() { return s().s_kwdMap.begin(); }
@ -46,12 +45,17 @@ class V3LanguageWords {
if (it == s().s_kwdMap.end()) return "";
return it->second;
}
private:
static Singleton& s() { static Singleton s_s; return s_s; }
static Singleton& s() {
static Singleton s_s;
return s_s;
}
};
inline void V3LanguageWords::Singleton::init() {
// C++ keywords
// clang-format off
addKwd("NULL", "C++ common word");
addKwd("abort", "C++ common word");
addKwd("alignas", "C++11 keyword");
@ -242,6 +246,7 @@ inline void V3LanguageWords::Singleton::init() {
addKwd("`undefineall", "Verilog preprocessor directive");
addKwd("`verilator_config", "Verilator preprocessor directive");
addKwd("`verilog", "Verilator preprocessor directive");
// clang-format on
}
#endif // Guard

View File

@ -31,25 +31,26 @@ class V3LinkDot {
private:
static int debug();
static void linkDotGuts(AstNetlist* rootp, VLinkDotStep step);
public:
static void linkDotPrimary(AstNetlist* nodep) {
UINFO(2,__FUNCTION__<<": "<<endl);
linkDotGuts(nodep,LDS_PRIMARY);
UINFO(2, __FUNCTION__ << ": " << endl);
linkDotGuts(nodep, LDS_PRIMARY);
V3Global::dumpCheckGlobalTree("linkdot", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 6);
}
static void linkDotParamed(AstNetlist* nodep) {
UINFO(2,__FUNCTION__<<": "<<endl);
linkDotGuts(nodep,LDS_PARAMED);
UINFO(2, __FUNCTION__ << ": " << endl);
linkDotGuts(nodep, LDS_PARAMED);
V3Global::dumpCheckGlobalTree("paramlink", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
}
static void linkDotArrayed(AstNetlist* nodep) {
UINFO(2,__FUNCTION__<<": "<<endl);
linkDotGuts(nodep,LDS_ARRAYED);
UINFO(2, __FUNCTION__ << ": " << endl);
linkDotGuts(nodep, LDS_ARRAYED);
V3Global::dumpCheckGlobalTree("linkdot", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 6);
}
static void linkDotScope(AstNetlist* nodep) {
UINFO(2,__FUNCTION__<<": "<<endl);
linkDotGuts(nodep,LDS_SCOPED);
UINFO(2, __FUNCTION__ << ": " << endl);
linkDotGuts(nodep, LDS_SCOPED);
V3Global::dumpCheckGlobalTree("linkdot", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
}
};

View File

@ -38,8 +38,8 @@ private:
// NODE STATE
// STATE
bool m_setRefLvalue; // Set VarRefs to lvalues for pin assignments
AstNodeFTask* m_ftaskp; // Function or task we're inside
bool m_setRefLvalue; // Set VarRefs to lvalues for pin assignments
AstNodeFTask* m_ftaskp; // Function or task we're inside
// METHODS
VL_DEBUG_FUNC; // Declare debug()
@ -48,14 +48,11 @@ private:
// Result handing
virtual void visit(AstNodeVarRef* nodep) VL_OVERRIDE {
// VarRef: LValue its reference
if (m_setRefLvalue) {
nodep->lvalue(true);
}
if (m_setRefLvalue) nodep->lvalue(true);
if (nodep->varp()) {
if (nodep->lvalue() && !m_ftaskp
&& nodep->varp()->isReadOnly()) {
nodep->v3warn(ASSIGNIN, "Assigning to input/const variable: "
<<nodep->prettyNameQ());
if (nodep->lvalue() && !m_ftaskp && nodep->varp()->isReadOnly()) {
nodep->v3warn(ASSIGNIN,
"Assigning to input/const variable: " << nodep->prettyNameQ());
}
}
iterateChildren(nodep);
@ -223,7 +220,7 @@ private:
}
virtual void visit(AstNodeSel* nodep) VL_OVERRIDE {
bool last_setRefLvalue = m_setRefLvalue;
{ // Only set lvalues on the from
{ // Only set lvalues on the from
iterateAndNextNull(nodep->lhsp());
m_setRefLvalue = false;
iterateAndNextNull(nodep->rhsp());
@ -232,7 +229,7 @@ private:
}
virtual void visit(AstCellArrayRef* nodep) VL_OVERRIDE {
bool last_setRefLvalue = m_setRefLvalue;
{ // selp is not an lvalue
{ // selp is not an lvalue
m_setRefLvalue = false;
iterateAndNextNull(nodep->selp());
}
@ -240,7 +237,7 @@ private:
}
virtual void visit(AstNodePreSel* nodep) VL_OVERRIDE {
bool last_setRefLvalue = m_setRefLvalue;
{ // Only set lvalues on the from
{ // Only set lvalues on the from
iterateAndNextNull(nodep->lhsp());
m_setRefLvalue = false;
iterateAndNextNull(nodep->rhsp());
@ -258,7 +255,7 @@ private:
AstNodeFTask* taskp = nodep->taskp();
// We'll deal with mismatching pins later
if (!taskp) return;
for (AstNode* stmtp = taskp->stmtsp(); stmtp && pinp; stmtp=stmtp->nextp()) {
for (AstNode* stmtp = taskp->stmtsp(); stmtp && pinp; stmtp = stmtp->nextp()) {
if (const AstVar* portp = VN_CAST(stmtp, Var)) {
if (portp->isIO()) {
if (portp->isWritable()) {
@ -291,15 +288,13 @@ public:
// Link class functions
void V3LinkLValue::linkLValue(AstNetlist* nodep) {
UINFO(4,__FUNCTION__<<": "<<endl);
{
LinkLValueVisitor visitor(nodep, false);
} // Destruct before checking
UINFO(4, __FUNCTION__ << ": " << endl);
{ LinkLValueVisitor visitor(nodep, false); } // Destruct before checking
V3Global::dumpCheckGlobalTree("linklvalue", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 6);
}
void V3LinkLValue::linkLValueSet(AstNode* nodep) {
// Called by later link functions when it is known a node needs
// to be converted to a lvalue.
UINFO(9,__FUNCTION__<<": "<<endl);
UINFO(9, __FUNCTION__ << ": " << endl);
LinkLValueVisitor visitor(nodep, true);
}

View File

@ -27,29 +27,32 @@
template <class T> class V3List;
template <class T> class V3ListEnt;
template <class T>
class V3List {
template <class T> class V3List {
// List container for linked list of elements of type *T (T is a pointer type)
private:
// MEMBERS
T m_headp; // First element
T m_tailp; // Last element
friend class V3ListEnt<T>;
public:
V3List()
: m_headp(NULL), m_tailp(NULL) {}
: m_headp(NULL)
, m_tailp(NULL) {}
~V3List() {}
// METHODS
T begin() const { return m_headp; }
T end() const { return NULL; }
bool empty() const { return m_headp==NULL; }
void reset() { m_headp = NULL; m_tailp = NULL; } // clear() without walking the list
bool empty() const { return m_headp == NULL; }
void reset() { // clear() without walking the list
m_headp = NULL;
m_tailp = NULL;
}
};
//============================================================================
template <class T>
class V3ListEnt {
template <class T> class V3ListEnt {
// List entry for linked list of elements of type *T (T is a pointer type)
private:
// MEMBERS
@ -60,11 +63,13 @@ private:
// "this" must be a element inside of *basep
// Use that to determine a structure offset, then apply to the new base
// to get our new pointer information
return (V3ListEnt*) ( ((vluint8_t*)newbasep) + offset);
return (V3ListEnt*)(((vluint8_t*)newbasep) + offset);
}
public:
V3ListEnt()
: m_nextp(NULL), m_prevp(NULL) {}
: m_nextp(NULL)
, m_prevp(NULL) {}
~V3ListEnt() {
#ifdef VL_DEBUG
// Load bogus pointers so we can catch deletion bugs
@ -99,10 +104,16 @@ public:
// "this" must be a element inside of *oldp
// cppcheck-suppress thisSubtraction
size_t offset = (size_t)(vluint8_t*)(this) - (size_t)(vluint8_t*)(oldp);
if (m_nextp) baseToListEnt(m_nextp, offset)->m_prevp = m_prevp;
else listr.m_tailp = m_prevp;
if (m_prevp) baseToListEnt(m_prevp, offset)->m_nextp = m_nextp;
else listr.m_headp = m_nextp;
if (m_nextp) {
baseToListEnt(m_nextp, offset)->m_prevp = m_prevp;
} else {
listr.m_tailp = m_prevp;
}
if (m_prevp) {
baseToListEnt(m_prevp, offset)->m_nextp = m_nextp;
} else {
listr.m_headp = m_nextp;
}
m_prevp = m_nextp = NULL;
}
};

View File

@ -52,10 +52,10 @@ protected:
// Per-variable flags
// Used in user()'s so initializes to all zeros
struct {
int m_notOpt:1; // NOT optimizable
int m_notStd:1; // NOT optimizable if a non-blocktemp signal
int m_stdFuncAsn:1; // Found simple assignment
int m_done:1; // Removed
int m_notOpt : 1; // NOT optimizable
int m_notStd : 1; // NOT optimizable if a non-blocktemp signal
int m_stdFuncAsn : 1; // Found simple assignment
int m_done : 1; // Removed
};
// cppcheck-suppress unusedStructMember
uint32_t m_flags;
@ -75,7 +75,7 @@ private:
// METHODS
virtual void visit(AstVarRef* nodep) VL_OVERRIDE {
// cppcheck-suppress unreadVariable // cppcheck 1.90 bug
VarFlags flags (nodep->varp());
VarFlags flags(nodep->varp());
if (flags.m_done) {
nodep->hiername(""); // Remove this->
nodep->hierThis(true);
@ -85,9 +85,7 @@ private:
public:
// CONSTRUCTORS
explicit LocalizeDehierVisitor(AstNetlist* nodep) {
iterate(nodep);
}
explicit LocalizeDehierVisitor(AstNetlist* nodep) { iterate(nodep); }
virtual ~LocalizeDehierVisitor() {}
};
@ -98,9 +96,9 @@ class LocalizeVisitor : public LocalizeBaseVisitor {
private:
// NODE STATE/TYPES
// See above
AstUser1InUse m_inuser1;
AstUser2InUse m_inuser2;
AstUser4InUse m_inuser4;
AstUser1InUse m_inuser1;
AstUser2InUse m_inuser2;
AstUser4InUse m_inuser4;
// STATE
VDouble0 m_statLocVars; // Statistic tracking
@ -109,14 +107,14 @@ private:
// METHODS
void clearOptimizable(AstVar* nodep, const char* reason) {
UINFO(4," NoOpt "<<reason<<" "<<nodep<<endl);
VarFlags flags (nodep);
UINFO(4, " NoOpt " << reason << " " << nodep << endl);
VarFlags flags(nodep);
flags.m_notOpt = true;
flags.setNodeFlags(nodep);
}
void clearStdOptimizable(AstVar* nodep, const char* reason) {
UINFO(4," NoStd "<<reason<<" "<<nodep<<endl);
VarFlags flags (nodep);
UINFO(4, " NoStd " << reason << " " << nodep << endl);
VarFlags flags(nodep);
flags.m_notStd = true;
flags.setNodeFlags(nodep);
}
@ -125,15 +123,14 @@ private:
AstVar* nodep = *it;
if (nodep->valuep()) clearOptimizable(nodep, "HasInitValue");
if (!VarFlags(nodep).m_stdFuncAsn) clearStdOptimizable(nodep, "NoStdAssign");
VarFlags flags (nodep);
VarFlags flags(nodep);
if ((nodep->isMovableToBlock() // Blocktemp
|| !flags.m_notStd) // Or used only in block
&& !flags.m_notOpt // Optimizable
&& !nodep->isClassMember()
&& nodep->user1p()) { // Single cfunc
&& !nodep->isClassMember() && nodep->user1p()) { // Single cfunc
// We don't need to test for tracing; it would be in the tracefunc if it was needed
UINFO(4," ModVar->BlkVar "<<nodep<<endl);
UINFO(4, " ModVar->BlkVar " << nodep << endl);
++m_statLocVars;
AstCFunc* newfuncp = VN_CAST(nodep->user1p(), CFunc);
nodep->unlinkFrBack();
@ -154,7 +151,7 @@ private:
moveVars();
}
virtual void visit(AstCFunc* nodep) VL_OVERRIDE {
UINFO(4," CFUNC "<<nodep<<endl);
UINFO(4, " CFUNC " << nodep << endl);
m_cfuncp = nodep;
searchFuncStmts(nodep->argsp());
searchFuncStmts(nodep->initsp());
@ -168,14 +165,14 @@ private:
// For now we only find simple assignments not under any other statement.
// This could be more complicated; allow always-set under both branches of a IF.
// If so, check for ArrayRef's and such, as they aren't acceptable.
for (; nodep; nodep=nodep->nextp()) {
for (; nodep; nodep = nodep->nextp()) {
if (VN_IS(nodep, NodeAssign)) {
if (AstVarRef* varrefp = VN_CAST(VN_CAST(nodep, NodeAssign)->lhsp(), VarRef)) {
UASSERT_OBJ(varrefp->lvalue(), varrefp, "LHS assignment not lvalue");
if (!varrefp->varp()->user4p()) {
UINFO(4," FuncAsn "<<varrefp<<endl);
UINFO(4, " FuncAsn " << varrefp << endl);
varrefp->varp()->user4p(varrefp);
VarFlags flags (varrefp->varp());
VarFlags flags(varrefp->varp());
flags.m_stdFuncAsn = true;
flags.setNodeFlags(varrefp->varp());
}
@ -185,10 +182,9 @@ private:
}
virtual void visit(AstVar* nodep) VL_OVERRIDE {
if (!nodep->isSigPublic()
&& !nodep->isPrimaryIO()
if (!nodep->isSigPublic() && !nodep->isPrimaryIO()
&& !m_cfuncp) { // Not already inside a function
UINFO(4," BLKVAR "<<nodep<<endl);
UINFO(4, " BLKVAR " << nodep << endl);
m_varps.push_back(nodep);
}
// No iterate; Don't want varrefs under it
@ -197,14 +193,13 @@ private:
if (!VarFlags(nodep->varp()).m_notOpt) {
if (!m_cfuncp) { // Not in function, can't optimize
clearOptimizable(nodep->varp(), "BVnofunc");
}
else {
} else {
// If we're scoping down to it, it isn't really in the same block
if (!nodep->hierThis()) clearOptimizable(nodep->varp(), "HierRef");
// Allow a variable to appear in only a single function
AstNode* oldfunc = nodep->varp()->user1p();
if (!oldfunc) {
UINFO(4," BVnewref "<<nodep<<endl);
UINFO(4, " BVnewref " << nodep << endl);
nodep->varp()->user1p(m_cfuncp); // Remember where it was used
} else if (m_cfuncp == oldfunc) {
// Same usage
@ -214,7 +209,7 @@ private:
}
// First varref in function must be assignment found earlier
AstVarRef* firstasn = static_cast<AstVarRef*>(nodep->varp()->user4p());
if (firstasn && nodep!=firstasn) {
if (firstasn && nodep != firstasn) {
clearStdOptimizable(nodep->varp(), "notFirstAsn");
nodep->varp()->user4p(NULL);
}
@ -239,11 +234,11 @@ public:
// Localize class functions
void V3Localize::localizeAll(AstNetlist* nodep) {
UINFO(2,__FUNCTION__<<": "<<endl);
UINFO(2, __FUNCTION__ << ": " << endl);
{
LocalizeVisitor visitor (nodep);
LocalizeVisitor visitor(nodep);
// Fix up hiernames
LocalizeDehierVisitor dvisitor (nodep);
LocalizeDehierVisitor dvisitor(nodep);
} // Destruct before checking
V3Global::dumpCheckGlobalTree("localize", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 6);
}

View File

@ -41,11 +41,11 @@ private:
// AstCell::user1() -> bool. Set true if already processed
// AstScope::user1() -> bool. Set true if already processed
// AstVar::user1() -> bool. Set true if already processed
AstUser1InUse m_inuser1;
AstUser1InUse m_inuser1;
// STATE
AstNodeModule* m_modp;
V3LanguageWords m_words; // Reserved word detector
AstNodeModule* m_modp;
V3LanguageWords m_words; // Reserved word detector
// METHODS
VL_DEBUG_FUNC; // Declare debug()
@ -53,16 +53,16 @@ private:
void rename(AstNode* nodep, bool addPvt) {
if (!nodep->user1()) { // Not already done
if (addPvt) {
string newname = string("__PVT__")+nodep->name();
string newname = string("__PVT__") + nodep->name();
nodep->name(newname);
nodep->editCountInc();
} else if (VN_IS(nodep, CFunc) && VN_CAST(nodep, CFunc)->isConstructor()) {
} else {
string rsvd = m_words.isKeyword(nodep->name());
if (rsvd != "") {
nodep->v3warn(SYMRSVDWORD, "Symbol matches "+rsvd
+": "<<nodep->prettyNameQ());
string newname = string("__SYM__")+nodep->name();
nodep->v3warn(SYMRSVDWORD,
"Symbol matches " + rsvd + ": " << nodep->prettyNameQ());
string newname = string("__SYM__") + nodep->name();
nodep->name(newname);
nodep->editCountInc();
}
@ -83,10 +83,10 @@ private:
// Add __PVT__ to names of local signals
virtual void visit(AstVar* nodep) VL_OVERRIDE {
// Don't iterate... Don't need temps for RANGES under the Var.
rename(nodep, ((!m_modp || !m_modp->isTop())
&& !nodep->isSigPublic()
&& !nodep->isFuncLocal() // Isn't exposed, and would mess up dpi import wrappers
&& !nodep->isTemp())); // Don't bother to rename internal signals
rename(nodep,
((!m_modp || !m_modp->isTop()) && !nodep->isSigPublic()
&& !nodep->isFuncLocal() // Isn't exposed, and would mess up dpi import wrappers
&& !nodep->isTemp())); // Don't bother to rename internal signals
}
virtual void visit(AstCFunc* nodep) VL_OVERRIDE {
if (!nodep->user1()) {
@ -102,8 +102,7 @@ private:
}
virtual void visit(AstCell* nodep) VL_OVERRIDE {
if (!nodep->user1()) {
rename(nodep, (!nodep->modp()->modPublic()
&& !VN_IS(nodep->modp(), ClassPackage)));
rename(nodep, (!nodep->modp()->modPublic() && !VN_IS(nodep->modp(), ClassPackage)));
iterateChildren(nodep);
}
}
@ -125,10 +124,13 @@ private:
if (nodep->aboveCellp()) iterate(nodep->aboveCellp());
// Always recompute name (as many levels above scope may have changed)
// Same formula as V3Scope
nodep->name(nodep->isTop() ? "TOP"
: VN_IS(m_modp, Class) ? ("TOP." + m_modp->name())
: VN_IS(m_modp, ClassPackage) ? ("TOP." + m_modp->name())
: (nodep->aboveScopep()->name() + "." + nodep->aboveCellp()->name()));
nodep->name(nodep->isTop()
? "TOP"
: VN_IS(m_modp, Class) ? ("TOP." + m_modp->name())
: VN_IS(m_modp, ClassPackage)
? ("TOP." + m_modp->name())
: (nodep->aboveScopep()->name() + "."
+ nodep->aboveCellp()->name()));
nodep->editCountInc();
iterateChildren(nodep);
}
@ -150,9 +152,7 @@ public:
// Name class functions
void V3Name::nameAll(AstNetlist* nodep) {
UINFO(2,__FUNCTION__<<": "<<endl);
{
NameVisitor visitor (nodep);
} // Destruct before checking
UINFO(2, __FUNCTION__ << ": " << endl);
{ NameVisitor visitor(nodep); } // Destruct before checking
V3Global::dumpCheckGlobalTree("name", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 6);
}

View File

@ -36,54 +36,83 @@ void test(const string& lhss, const string& op, const string& rhss, const string
FileLine fl = new FileLine(FileLine::builtInFinename());
V3Number lhnum (fl, l1);
V3Number rhnum (fl, r1);
V3Number expnum (fl, e1);
V3Number gotnum (fl, expnum.width());
V3Number lhnum(fl, l1);
V3Number rhnum(fl, r1);
V3Number expnum(fl, e1);
V3Number gotnum(fl, expnum.width());
if (op=="redOr") gotnum.opRedOr (lhnum);
else if (op=="redAnd") gotnum.opRedAnd (lhnum);
else if (op=="redXor") gotnum.opRedXor (lhnum);
else if (op=="redXnor") gotnum.opRedXnor (lhnum);
else if (op=="concat") gotnum.opConcat (lhnum, rhnum);
else if (op=="repl") gotnum.opRepl (lhnum, rhnum);
else if (op=="~") gotnum.opNot (lhnum);
else if (op=="!") gotnum.opLogNot (lhnum);
else if (op=="negate") gotnum.opNegate (lhnum);
else if (op=="+") gotnum.opAdd (lhnum, rhnum);
else if (op=="-") gotnum.opSub (lhnum, rhnum);
else if (op=="*") gotnum.opMul (lhnum, rhnum);
else if (op=="/") gotnum.opDiv (lhnum, rhnum);
else if (op=="%") gotnum.opModDiv (lhnum, rhnum);
else if (op=="&") gotnum.opAnd (lhnum, rhnum);
else if (op=="|") gotnum.opOr (lhnum, rhnum);
else if (op=="<") gotnum.opLt (lhnum, rhnum);
else if (op==">") gotnum.opGt (lhnum, rhnum);
else if (op==">>") gotnum.opShiftR (lhnum, rhnum);
else if (op=="<<") gotnum.opShiftL (lhnum, rhnum);
else if (op=="==") gotnum.opEq (lhnum, rhnum);
else if (op=="===") gotnum.opCaseEq (lhnum, rhnum);
else if (op=="==?") gotnum.opWildEq (lhnum, rhnum);
else if (op=="!=") gotnum.opNeq (lhnum, rhnum);
else if (op=="!==") gotnum.opCaseNeq (lhnum, rhnum);
else if (op=="!=?") gotnum.opWildNeq (lhnum, rhnum);
else if (op=="<=") gotnum.opLte (lhnum, rhnum);
else if (op==">=") gotnum.opGte (lhnum, rhnum);
else if (op=="&&") gotnum.opLogAnd (lhnum, rhnum);
else if (op=="||") gotnum.opLogOr (lhnum, rhnum);
else v3fatalSrc("Bad opcode: "<<op);
if (op == "redOr") {
gotnum.opRedOr(lhnum);
} else if (op == "redAnd") {
gotnum.opRedAnd(lhnum);
} else if (op == "redXor") {
gotnum.opRedXor(lhnum);
} else if (op == "redXnor") {
gotnum.opRedXnor(lhnum);
} else if (op == "concat") {
gotnum.opConcat(lhnum, rhnum);
} else if (op == "repl") {
gotnum.opRepl(lhnum, rhnum);
} else if (op == "~") {
gotnum.opNot(lhnum);
} else if (op == "!") {
gotnum.opLogNot(lhnum);
} else if (op == "negate") {
gotnum.opNegate(lhnum);
} else if (op == "+") {
gotnum.opAdd(lhnum, rhnum);
} else if (op == "-") {
gotnum.opSub(lhnum, rhnum);
} else if (op == "*") {
gotnum.opMul(lhnum, rhnum);
} else if (op == "/") {
gotnum.opDiv(lhnum, rhnum);
} else if (op == "%") {
gotnum.opModDiv(lhnum, rhnum);
} else if (op == "&") {
gotnum.opAnd(lhnum, rhnum);
} else if (op == "|") {
gotnum.opOr(lhnum, rhnum);
} else if (op == "<") {
gotnum.opLt(lhnum, rhnum);
} else if (op == ">") {
gotnum.opGt(lhnum, rhnum);
} else if (op == ">>") {
gotnum.opShiftR(lhnum, rhnum);
} else if (op == "<<") {
gotnum.opShiftL(lhnum, rhnum);
} else if (op == "==") {
gotnum.opEq(lhnum, rhnum);
} else if (op == "===") {
gotnum.opCaseEq(lhnum, rhnum);
} else if (op == "==?") {
gotnum.opWildEq(lhnum, rhnum);
} else if (op == "!=") {
gotnum.opNeq(lhnum, rhnum);
} else if (op == "!==") {
gotnum.opCaseNeq(lhnum, rhnum);
} else if (op == "!=?") {
gotnum.opWildNeq(lhnum, rhnum);
} else if (op == "<=") {
gotnum.opLte(lhnum, rhnum);
} else if (op == ">=") {
gotnum.opGte(lhnum, rhnum);
} else if (op == "&&") {
gotnum.opLogAnd(lhnum, rhnum);
} else if (op == "||") {
gotnum.opLogOr(lhnum, rhnum);
} else
v3fatalSrc("Bad opcode: " << op);
UINFO(0,"------- Test:\n"
<<" "<<lhnum<<" "<<op<<endl
<<" "<<rhnum<<endl
<<" = "<<expnum<<endl
<<" =? "<<gotnum<<endl);
UINFO(0, "------- Test:\n"
<< " " << lhnum << " " << op << endl
<< " " << rhnum << endl
<< " = " << expnum << endl
<< " =? " << gotnum << endl);
V3Number ok (fl, 1);
V3Number ok(fl, 1);
ok.opCaseEq(expnum, gotnum);
if (ok.toUInt()!=1) {
v3fatalSrc("%Error:Test FAILED");
}
if (ok.toUInt() != 1) { v3fatalSrc("%Error:Test FAILED"); }
free(l1);
free(r1);
@ -91,10 +120,10 @@ void test(const string& lhss, const string& op, const string& rhss, const string
}
int main() {
UINFO(0,"Test starting\n");
UINFO(0, "Test starting\n");
test("32'b10", "|", "32'b10", "32'b10");
test( "2'bx0", "|", "2'b10", "2'b10");
test("2'bx0", "|", "2'b10", "2'b10");
test("32'b0x", "|", "32'b10", "32'b1x");
test("32'b10", "&", "32'b11", "32'b10");
test("32'b10", "+", "32'b10", "32'b100");
@ -106,9 +135,10 @@ int main() {
test("57'h000000010F0CCE7", "*", "57'h10", "57'h10F0CCE70");
test("57'h000000010F0CCE7", "*", "57'h0DE34E7FFFFFFFF", "57'h02A9D57EF0F3319");
test("67'h7FFFFFFFFFFFFFFFF", "*", "67'h4000000003C8A8D6A", "67'h3FFFFFFFFC3757296");
test("99'h7FFFFFFFFFFFFFFFFFFFFFFFF", "*", "99'h0000000000000000091338A80", "99'h7FFFFFFFFFFFFFFFF6ECC7580");
test("99'h7FFFFFFFFFFFFFFFFFFFFFFFF", "*", "99'h0000000000000000091338A80",
"99'h7FFFFFFFFFFFFFFFF6ECC7580");
cout<<"Test completed\n";
cout << "Test completed\n";
}
//###################################################################

View File

@ -36,7 +36,6 @@
// OrderPreCutEdge
//*************************************************************************
#ifndef _V3ORDERGRAPH_H_
#define _V3ORDERGRAPH_H_
@ -56,13 +55,14 @@ class OrderMoveDomScope;
//######################################################################
enum OrderWeights {
WEIGHT_INPUT = 1, // Low weight just so dot graph looks nice
WEIGHT_COMBO = 1, // Breakable combo logic
WEIGHT_INPUT = 1, // Low weight just so dot graph looks nice
WEIGHT_COMBO = 1, // Breakable combo logic
WEIGHT_LOOPBE = 1, // Connection to loop begin/end
WEIGHT_POST = 2, // Post-delayed used var
WEIGHT_PRE = 3, // Breakable pre-delayed used var
WEIGHT_POST = 2, // Post-delayed used var
WEIGHT_PRE = 3, // Breakable pre-delayed used var
WEIGHT_MEDIUM = 8, // Medium weight just so dot graph looks nice
WEIGHT_NORMAL = 32 }; // High weight just so dot graph looks nice
WEIGHT_NORMAL = 32
}; // High weight just so dot graph looks nice
struct OrderVEdgeType {
enum en {
@ -84,20 +84,21 @@ struct OrderVEdgeType {
_ENUM_END
};
const char* ascii() const {
static const char* const names[] = {
"%E-vedge", "VERTEX_INPUTS", "VERTEX_SETTLE", "VERTEX_LOGIC",
"VERTEX_VARSTD", "VERTEX_VARPRE", "VERTEX_VARPOST",
"VERTEX_VARPORD", "VERTEX_VARSETTLE", "VERTEX_MOVE",
"EDGE_STD", "EDGE_CHANGEDET", "EDGE_COMBOCUT",
"EDGE_PRECUT", "EDGE_POSTCUT", "_ENUM_END"
};
static const char* const names[]
= {"%E-vedge", "VERTEX_INPUTS", "VERTEX_SETTLE", "VERTEX_LOGIC",
"VERTEX_VARSTD", "VERTEX_VARPRE", "VERTEX_VARPOST", "VERTEX_VARPORD",
"VERTEX_VARSETTLE", "VERTEX_MOVE", "EDGE_STD", "EDGE_CHANGEDET",
"EDGE_COMBOCUT", "EDGE_PRECUT", "EDGE_POSTCUT", "_ENUM_END"};
return names[m_e];
}
enum en m_e;
inline OrderVEdgeType() : m_e(VERTEX_UNKNOWN) {}
inline OrderVEdgeType()
: m_e(VERTEX_UNKNOWN) {}
// cppcheck-suppress noExplicitConstructor
inline OrderVEdgeType(en _e) : m_e(_e) {}
explicit inline OrderVEdgeType(int _e) : m_e(static_cast<en>(_e)) {}
inline OrderVEdgeType(en _e)
: m_e(_e) {}
explicit inline OrderVEdgeType(int _e)
: m_e(static_cast<en>(_e)) {}
operator en() const { return m_e; }
};
inline bool operator==(const OrderVEdgeType& lhs, const OrderVEdgeType& rhs) {
@ -139,18 +140,23 @@ class OrderEitherVertex : public V3GraphVertex {
bool m_isFromInput; // From input, or derived therefrom (conservatively false)
protected:
OrderEitherVertex(V3Graph* graphp, const OrderEitherVertex& old)
: V3GraphVertex(graphp, old), m_scopep(old.m_scopep), m_domainp(old.m_domainp)
: V3GraphVertex(graphp, old)
, m_scopep(old.m_scopep)
, m_domainp(old.m_domainp)
, m_isFromInput(old.m_isFromInput) {}
public:
OrderEitherVertex(V3Graph* graphp, AstScope* scopep, AstSenTree* domainp)
: V3GraphVertex(graphp), m_scopep(scopep), m_domainp(domainp)
: V3GraphVertex(graphp)
, m_scopep(scopep)
, m_domainp(domainp)
, m_isFromInput(false) {}
virtual ~OrderEitherVertex() {}
virtual OrderEitherVertex* clone(V3Graph* graphp) const = 0;
// Methods
virtual OrderVEdgeType type() const = 0;
virtual bool domainMatters() = 0; // Must be in same domain when cross edge to this vertex
virtual string dotName() const { return cvtToHex(m_scopep)+"_"; }
virtual string dotName() const { return cvtToHex(m_scopep) + "_"; }
// ACCESSORS
void domainp(AstSenTree* domainp) { m_domainp = domainp; }
AstScope* scopep() const { return m_scopep; }
@ -162,6 +168,7 @@ public:
class OrderInputsVertex : public OrderEitherVertex {
OrderInputsVertex(V3Graph* graphp, const OrderInputsVertex& old)
: OrderEitherVertex(graphp, old) {}
public:
OrderInputsVertex(V3Graph* graphp, AstSenTree* domainp)
: OrderEitherVertex(graphp, NULL, domainp) {
@ -169,7 +176,8 @@ public:
}
virtual ~OrderInputsVertex() {}
virtual OrderInputsVertex* clone(V3Graph* graphp) const {
return new OrderInputsVertex(graphp, *this); }
return new OrderInputsVertex(graphp, *this);
}
virtual OrderVEdgeType type() const { return OrderVEdgeType::VERTEX_INPUTS; }
virtual string name() const { return "*INPUTS*"; }
virtual string dotColor() const { return "green"; }
@ -180,12 +188,14 @@ public:
class OrderSettleVertex : public OrderEitherVertex {
OrderSettleVertex(V3Graph* graphp, const OrderSettleVertex& old)
: OrderEitherVertex(graphp, old) {}
public:
OrderSettleVertex(V3Graph* graphp, AstSenTree* domainp)
: OrderEitherVertex(graphp, NULL, domainp) {}
virtual ~OrderSettleVertex() {}
virtual OrderSettleVertex* clone(V3Graph* graphp) const {
return new OrderSettleVertex(graphp, *this); }
return new OrderSettleVertex(graphp, *this);
}
virtual OrderVEdgeType type() const { return OrderVEdgeType::VERTEX_SETTLE; }
virtual string name() const { return "*SETTLE*"; }
virtual string dotColor() const { return "green"; }
@ -194,21 +204,27 @@ public:
};
class OrderLogicVertex : public OrderEitherVertex {
AstNode* m_nodep;
AstNode* m_nodep;
protected:
OrderLogicVertex(V3Graph* graphp, const OrderLogicVertex& old)
: OrderEitherVertex(graphp, old), m_nodep(old.m_nodep) {}
: OrderEitherVertex(graphp, old)
, m_nodep(old.m_nodep) {}
public:
OrderLogicVertex(V3Graph* graphp, AstScope* scopep, AstSenTree* domainp, AstNode* nodep)
: OrderEitherVertex(graphp, scopep, domainp), m_nodep(nodep) {}
: OrderEitherVertex(graphp, scopep, domainp)
, m_nodep(nodep) {}
virtual ~OrderLogicVertex() {}
virtual OrderLogicVertex* clone(V3Graph* graphp) const {
return new OrderLogicVertex(graphp, *this); }
return new OrderLogicVertex(graphp, *this);
}
virtual OrderVEdgeType type() const { return OrderVEdgeType::VERTEX_LOGIC; }
virtual bool domainMatters() { return true; }
// ACCESSORS
virtual string name() const {
return (cvtToHex(m_nodep)+"\\n "+cvtToStr(nodep()->typeName())); }
return (cvtToHex(m_nodep) + "\\n " + cvtToStr(nodep()->typeName()));
}
AstNode* nodep() const { return m_nodep; }
virtual string dotColor() const { return "yellow"; }
};
@ -220,12 +236,16 @@ class OrderVarVertex : public OrderEitherVertex {
protected:
OrderVarVertex(V3Graph* graphp, const OrderVarVertex& old)
: OrderEitherVertex(graphp, old)
, m_varScp(old.m_varScp), m_isClock(old.m_isClock)
, m_varScp(old.m_varScp)
, m_isClock(old.m_isClock)
, m_isDelayed(old.m_isDelayed) {}
public:
OrderVarVertex(V3Graph* graphp, AstScope* scopep, AstVarScope* varScp)
: OrderEitherVertex(graphp, scopep, NULL), m_varScp(varScp)
, m_isClock(false), m_isDelayed(false) {}
: OrderEitherVertex(graphp, scopep, NULL)
, m_varScp(varScp)
, m_isClock(false)
, m_isDelayed(false) {}
virtual ~OrderVarVertex() {}
virtual OrderVarVertex* clone(V3Graph* graphp) const = 0;
virtual OrderVEdgeType type() const = 0;
@ -241,70 +261,80 @@ public:
class OrderVarStdVertex : public OrderVarVertex {
OrderVarStdVertex(V3Graph* graphp, const OrderVarStdVertex& old)
: OrderVarVertex(graphp, old) {}
public:
OrderVarStdVertex(V3Graph* graphp, AstScope* scopep, AstVarScope* varScp)
: OrderVarVertex(graphp, scopep, varScp) {}
virtual ~OrderVarStdVertex() {}
virtual OrderVarStdVertex* clone(V3Graph* graphp) const {
return new OrderVarStdVertex(graphp, *this); }
return new OrderVarStdVertex(graphp, *this);
}
virtual OrderVEdgeType type() const { return OrderVEdgeType::VERTEX_VARSTD; }
virtual string name() const { return (cvtToHex(varScp())+"\\n "+varScp()->name());}
virtual string name() const { return (cvtToHex(varScp()) + "\\n " + varScp()->name()); }
virtual string dotColor() const { return "skyblue"; }
virtual bool domainMatters() { return true; }
};
class OrderVarPreVertex : public OrderVarVertex {
OrderVarPreVertex(V3Graph* graphp, const OrderVarPreVertex& old)
: OrderVarVertex(graphp, old) {}
public:
OrderVarPreVertex(V3Graph* graphp, AstScope* scopep, AstVarScope* varScp)
: OrderVarVertex(graphp, scopep, varScp) {}
virtual ~OrderVarPreVertex() {}
virtual OrderVarPreVertex* clone(V3Graph* graphp) const {
return new OrderVarPreVertex(graphp, *this); }
return new OrderVarPreVertex(graphp, *this);
}
virtual OrderVEdgeType type() const { return OrderVEdgeType::VERTEX_VARPRE; }
virtual string name() const { return (cvtToHex(varScp())+" PRE\\n "+varScp()->name());}
virtual string name() const { return (cvtToHex(varScp()) + " PRE\\n " + varScp()->name()); }
virtual string dotColor() const { return "lightblue"; }
virtual bool domainMatters() { return false; }
};
class OrderVarPostVertex : public OrderVarVertex {
OrderVarPostVertex(V3Graph* graphp, const OrderVarPostVertex& old)
: OrderVarVertex(graphp, old) {}
public:
OrderVarPostVertex(V3Graph* graphp, AstScope* scopep, AstVarScope* varScp)
: OrderVarVertex(graphp, scopep, varScp) {}
virtual OrderVarPostVertex* clone(V3Graph* graphp) const {
return new OrderVarPostVertex(graphp, *this); }
return new OrderVarPostVertex(graphp, *this);
}
virtual OrderVEdgeType type() const { return OrderVEdgeType::VERTEX_VARPOST; }
virtual ~OrderVarPostVertex() {}
virtual string name() const { return (cvtToHex(varScp())+" POST\\n "+varScp()->name());}
virtual string name() const { return (cvtToHex(varScp()) + " POST\\n " + varScp()->name()); }
virtual string dotColor() const { return "CadetBlue"; }
virtual bool domainMatters() { return false; }
};
class OrderVarPordVertex : public OrderVarVertex {
OrderVarPordVertex(V3Graph* graphp, const OrderVarPordVertex& old)
: OrderVarVertex(graphp, old) {}
public:
OrderVarPordVertex(V3Graph* graphp, AstScope* scopep, AstVarScope* varScp)
: OrderVarVertex(graphp, scopep, varScp) {}
virtual ~OrderVarPordVertex() {}
virtual OrderVarPordVertex* clone(V3Graph* graphp) const {
return new OrderVarPordVertex(graphp, *this); }
return new OrderVarPordVertex(graphp, *this);
}
virtual OrderVEdgeType type() const { return OrderVEdgeType::VERTEX_VARPORD; }
virtual string name() const { return (cvtToHex(varScp())+" PORD\\n "+varScp()->name());}
virtual string name() const { return (cvtToHex(varScp()) + " PORD\\n " + varScp()->name()); }
virtual string dotColor() const { return "NavyBlue"; }
virtual bool domainMatters() { return false; }
};
class OrderVarSettleVertex : public OrderVarVertex {
OrderVarSettleVertex(V3Graph* graphp, const OrderVarSettleVertex& old)
: OrderVarVertex(graphp, old) {}
public:
OrderVarSettleVertex(V3Graph* graphp, AstScope* scopep, AstVarScope* varScp)
: OrderVarVertex(graphp, scopep, varScp) {}
virtual ~OrderVarSettleVertex() {}
virtual OrderVarSettleVertex* clone(V3Graph* graphp) const {
return new OrderVarSettleVertex(graphp, *this); }
return new OrderVarSettleVertex(graphp, *this);
}
virtual OrderVEdgeType type() const { return OrderVEdgeType::VERTEX_VARSETTLE; }
virtual string name() const { return (cvtToHex(varScp())+" STL\\n "+varScp()->name());}
virtual string name() const { return (cvtToHex(varScp()) + " STL\\n " + varScp()->name()); }
virtual string dotColor() const { return "PowderBlue"; }
virtual bool domainMatters() { return false; }
};
@ -313,7 +343,7 @@ public:
//--- Following only under the move graph, not the main graph
class OrderMoveVertex : public V3GraphVertex {
typedef enum {POM_WAIT, POM_READY, POM_MOVED} OrderMState;
typedef enum { POM_WAIT, POM_READY, POM_MOVED } OrderMState;
OrderLogicVertex* m_logicp;
OrderMState m_state; // Movement state
@ -329,40 +359,50 @@ protected:
public:
// CONSTRUCTORS
OrderMoveVertex(V3Graph* graphp, OrderLogicVertex* logicp)
: V3GraphVertex(graphp), m_logicp(logicp), m_state(POM_WAIT), m_domScopep(NULL) {}
: V3GraphVertex(graphp)
, m_logicp(logicp)
, m_state(POM_WAIT)
, m_domScopep(NULL) {}
virtual ~OrderMoveVertex() {}
virtual OrderMoveVertex* clone(V3Graph* graphp) const {
v3fatalSrc("Unsupported"); return NULL; }
v3fatalSrc("Unsupported");
return NULL;
}
// METHODS
virtual OrderVEdgeType type() const { return OrderVEdgeType::VERTEX_MOVE; }
virtual string dotColor() const {
if (logicp()) return logicp()->dotColor();
else return "";
if (logicp()) {
return logicp()->dotColor();
} else {
return "";
}
}
virtual FileLine* fileline() const {
if (logicp()) return logicp()->fileline();
else return NULL;
if (logicp()) {
return logicp()->fileline();
} else {
return NULL;
}
}
virtual string name() const {
string nm;
if (logicp()) {
nm = logicp()->name();
nm += (string("\\nMV:")
+" d="+cvtToHex(logicp()->domainp())
+" s="+cvtToHex(logicp()->scopep()));
nm += (string("\\nMV:") + " d=" + cvtToHex(logicp()->domainp())
+ " s=" + cvtToHex(logicp()->scopep()));
} else {
nm = "nul";
}
return nm;
}
OrderLogicVertex* logicp() const { return m_logicp; }
bool isWait() const { return m_state==POM_WAIT; }
bool isWait() const { return m_state == POM_WAIT; }
void setReady() {
UASSERT(m_state==POM_WAIT, "Wait->Ready on node not in proper state");
UASSERT(m_state == POM_WAIT, "Wait->Ready on node not in proper state");
m_state = POM_READY;
}
void setMoved() {
UASSERT(m_state==POM_READY, "Ready->Moved on node not in proper state");
UASSERT(m_state == POM_READY, "Ready->Moved on node not in proper state");
m_state = POM_MOVED;
}
OrderMoveDomScope* domScopep() const { return m_domScopep; }
@ -383,34 +423,40 @@ class MTaskMoveVertex : public V3GraphVertex {
protected:
friend class OrderVisitor;
friend class MTaskMoveVertexMaker;
public:
MTaskMoveVertex(V3Graph* graphp, OrderLogicVertex* logicp,
const OrderEitherVertex* varp,
MTaskMoveVertex(V3Graph* graphp, OrderLogicVertex* logicp, const OrderEitherVertex* varp,
const AstScope* scopep, const AstSenTree* domainp)
: V3GraphVertex(graphp), m_logicp(logicp),
m_varp(varp), m_scopep(scopep), m_domainp(domainp) {
UASSERT(!(logicp && varp),
"MTaskMoveVertex: logicp and varp may not both be set!\n");
: V3GraphVertex(graphp)
, m_logicp(logicp)
, m_varp(varp)
, m_scopep(scopep)
, m_domainp(domainp) {
UASSERT(!(logicp && varp), "MTaskMoveVertex: logicp and varp may not both be set!\n");
}
virtual ~MTaskMoveVertex() {}
virtual MTaskMoveVertex* clone(V3Graph* graphp) const {
v3fatalSrc("Unsupported"); return NULL; }
v3fatalSrc("Unsupported");
return NULL;
}
virtual OrderVEdgeType type() const { return OrderVEdgeType::VERTEX_MOVE; }
virtual string dotColor() const {
if (logicp()) return logicp()->dotColor();
else return "yellow";
if (logicp()) {
return logicp()->dotColor();
} else {
return "yellow";
}
}
virtual string name() const {
string nm;
if (logicp()) {
nm = logicp()->name();
nm += (string("\\nMV:")
+" d="+cvtToHex(logicp()->domainp())
+" s="+cvtToHex(logicp()->scopep())
nm += (string("\\nMV:") + " d=" + cvtToHex(logicp()->domainp()) + " s="
+ cvtToHex(logicp()->scopep())
// "color()" represents the mtask ID.
+"\\nt="+cvtToStr(color()));
+ "\\nt=" + cvtToStr(color()));
} else {
nm = "nolog\\nt="+cvtToStr(color());
nm = "nolog\\nt=" + cvtToStr(color());
}
return nm;
}
@ -426,12 +472,12 @@ public:
class OrderEdge : public V3GraphEdge {
protected:
OrderEdge(V3Graph* graphp, V3GraphVertex* fromp, V3GraphVertex* top,
const OrderEdge& old)
OrderEdge(V3Graph* graphp, V3GraphVertex* fromp, V3GraphVertex* top, const OrderEdge& old)
: V3GraphEdge(graphp, fromp, top, old) {}
public:
OrderEdge(V3Graph* graphp, V3GraphVertex* fromp, V3GraphVertex* top,
int weight, bool cutable=false)
OrderEdge(V3Graph* graphp, V3GraphVertex* fromp, V3GraphVertex* top, int weight,
bool cutable = false)
: V3GraphEdge(graphp, fromp, top, weight, cutable) {}
virtual ~OrderEdge() {}
virtual OrderVEdgeType type() const { return OrderVEdgeType::EDGE_STD; }
@ -461,13 +507,14 @@ class OrderComboCutEdge : public OrderEdge {
OrderComboCutEdge(V3Graph* graphp, V3GraphVertex* fromp, V3GraphVertex* top,
const OrderComboCutEdge& old)
: OrderEdge(graphp, fromp, top, old) {}
public:
OrderComboCutEdge(V3Graph* graphp, V3GraphVertex* fromp, V3GraphVertex* top)
: OrderEdge(graphp, fromp, top, WEIGHT_COMBO, CUTABLE) {}
virtual OrderVEdgeType type() const { return OrderVEdgeType::EDGE_COMBOCUT; }
virtual ~OrderComboCutEdge() {}
virtual OrderComboCutEdge* clone(V3Graph* graphp,
V3GraphVertex* fromp, V3GraphVertex* top) const {
virtual OrderComboCutEdge* clone(V3Graph* graphp, V3GraphVertex* fromp,
V3GraphVertex* top) const {
return new OrderComboCutEdge(graphp, fromp, top, *this);
}
virtual string dotColor() const { return "yellowGreen"; }
@ -482,13 +529,14 @@ class OrderPostCutEdge : public OrderEdge {
OrderPostCutEdge(V3Graph* graphp, V3GraphVertex* fromp, V3GraphVertex* top,
const OrderPostCutEdge& old)
: OrderEdge(graphp, fromp, top, old) {}
public:
OrderPostCutEdge(V3Graph* graphp, V3GraphVertex* fromp, V3GraphVertex* top)
: OrderEdge(graphp, fromp, top, WEIGHT_COMBO, CUTABLE) {}
virtual OrderVEdgeType type() const { return OrderVEdgeType::EDGE_POSTCUT; }
virtual ~OrderPostCutEdge() {}
virtual OrderPostCutEdge* clone(V3Graph* graphp,
V3GraphVertex* fromp, V3GraphVertex* top) const {
virtual OrderPostCutEdge* clone(V3Graph* graphp, V3GraphVertex* fromp,
V3GraphVertex* top) const {
return new OrderPostCutEdge(graphp, fromp, top, *this);
}
virtual string dotColor() const { return "PaleGreen"; }
@ -503,12 +551,13 @@ class OrderPreCutEdge : public OrderEdge {
OrderPreCutEdge(V3Graph* graphp, V3GraphVertex* fromp, V3GraphVertex* top,
const OrderPreCutEdge& old)
: OrderEdge(graphp, fromp, top, old) {}
public:
OrderPreCutEdge(V3Graph* graphp, V3GraphVertex* fromp, V3GraphVertex* top)
: OrderEdge(graphp, fromp, top, WEIGHT_PRE, CUTABLE) {}
virtual OrderVEdgeType type() const { return OrderVEdgeType::EDGE_PRECUT; }
virtual OrderPreCutEdge* clone(V3Graph* graphp,
V3GraphVertex* fromp, V3GraphVertex* top) const {
virtual OrderPreCutEdge* clone(V3Graph* graphp, V3GraphVertex* fromp,
V3GraphVertex* top) const {
return new OrderPreCutEdge(graphp, fromp, top, *this);
}
virtual ~OrderPreCutEdge() {}

View File

@ -34,17 +34,21 @@ public:
// METHODS (generic filename utilities)
static string filenameFromDirBase(const string& dir, const string& basename);
static string filenameNonDir(const string& filename); ///< Return non-directory part of filename
static string filenameNonExt(const string& filename); ///< Return non-extensioned (no .) part of filename
/// Return non-directory part of filename
static string filenameNonDir(const string& filename);
/// Return non-extensioned (no .) part of filename
static string filenameNonExt(const string& filename);
static string filenameNonDirExt(const string& filename) { ///< Return basename of filename
return filenameNonExt(filenameNonDir(filename)); }
return filenameNonExt(filenameNonDir(filename));
}
static string filenameDir(const string& filename); ///< Return directory part of filename
static string filenameSubstitute(const string& filename); ///< Return filename with env vars removed
/// Return filename with env vars removed
static string filenameSubstitute(const string& filename);
static string filenameRealPath(const string& filename); ///< Return realpath of filename
static bool filenameIsRel(const string& filename); ///< True if relative
// METHODS (file utilities)
static string getline(std::istream& is, char delim='\n');
static string getline(std::istream& is, char delim = '\n');
// METHODS (directory utilities)
static void createDir(const string& dirname);
@ -56,7 +60,8 @@ public:
// METHODS (time & performance)
static void u_sleep(int64_t usec); ///< Sleep for a given number of microseconds.
static uint64_t timeUsecs(); ///< Return wall time since epoch in microseconds, or 0 if not implemented
/// Return wall time since epoch in microseconds, or 0 if not implemented
static uint64_t timeUsecs();
static uint64_t memUsageBytes(); ///< Return memory usage in bytes, or 0 if not implemented
};

View File

@ -39,18 +39,15 @@
class V3Lexer : public V3LexerBase {
public:
// CONSTRUCTORS
V3Lexer() : V3LexerBase(NULL) {}
V3Lexer()
: V3LexerBase(NULL) {}
~V3Lexer() {}
// METHODS
void statePop() {
yy_pop_state();
}
void statePop() { yy_pop_state(); }
void unputString(const char* textp, size_t length) {
// Add characters to input stream in back-to-front order
const char* cp = textp;
for (cp += length - 1; length--; cp--) {
unput(*cp);
}
for (cp += length - 1; length--; cp--) unput(*cp);
}
};
@ -74,7 +71,7 @@ int V3ParseImp::yylexReadTok() {
void V3ParseImp::lexNew() {
if (m_lexerp) delete m_lexerp; // Restart from clean slate.
m_lexerp = new V3Lexer();
if (debugFlex()>=9) { m_lexerp->set_debug(~0); }
if (debugFlex() >= 9) { m_lexerp->set_debug(~0); }
}
void V3ParseImp::lexDestroy() {

View File

@ -36,11 +36,11 @@ class V3ParseSym {
private:
// MEMBERS
static int s_anonNum; // Number of next anonymous object (parser use only)
VSymGraph m_syms; // Graph of symbol tree
VSymEnt* m_symTableNextId; // Symbol table for next lexer lookup (parser use only)
VSymEnt* m_symCurrentp; // Active symbol table for additions/lookups
SymStack m_sympStack; // Stack of upper nodes with pending symbol tables
static int s_anonNum; // Number of next anonymous object (parser use only)
VSymGraph m_syms; // Graph of symbol tree
VSymEnt* m_symTableNextId; // Symbol table for next lexer lookup (parser use only)
VSymEnt* m_symCurrentp; // Active symbol table for additions/lookups
SymStack m_sympStack; // Stack of upper nodes with pending symbol tables
public:
// CONSTRUCTORS
@ -74,15 +74,14 @@ public:
}
void nextId(AstNode* entp) {
if (entp) {
UINFO(9,"symTableNextId under "<<entp<<"-"<<entp->type().ascii()<<endl);
UINFO(9, "symTableNextId under " << entp << "-" << entp->type().ascii() << endl);
m_symTableNextId = getTable(entp);
}
else {
UINFO(9,"symTableNextId under NULL"<<endl);
} else {
UINFO(9, "symTableNextId under NULL" << endl);
m_symTableNextId = NULL;
}
}
void reinsert(AstNode* nodep, VSymEnt* parentp=NULL) {
void reinsert(AstNode* nodep, VSymEnt* parentp = NULL) {
reinsert(nodep, parentp, nodep->name());
}
void reinsert(AstNode* nodep, VSymEnt* parentp, string name) {
@ -95,7 +94,8 @@ public:
void pushNew(AstNode* nodep) { pushNewUnder(nodep, NULL); }
void pushNewUnder(AstNode* nodep, VSymEnt* parentp) {
if (!parentp) parentp = symCurrentp();
VSymEnt* symp = findNewTable(nodep); // Will set user4p, which is how we connect table to node
VSymEnt* symp
= findNewTable(nodep); // Will set user4p, which is how we connect table to node
symp->fallbackp(parentp);
reinsert(nodep, parentp);
pushScope(symp);
@ -106,9 +106,13 @@ public:
}
void popScope(AstNode* nodep) {
if (symCurrentp()->nodep() != nodep) {
if (debug()) { showUpward(); dump(cout, "-mism: "); }
nodep->v3fatalSrc("Symbols suggest ending "<<symCurrentp()->nodep()->prettyTypeName()
<<" but parser thinks ending "<<nodep->prettyTypeName());
if (debug()) {
showUpward();
dump(cout, "-mism: ");
}
nodep->v3fatalSrc("Symbols suggest ending " << symCurrentp()->nodep()->prettyTypeName()
<< " but parser thinks ending "
<< nodep->prettyTypeName());
return;
}
m_sympStack.pop_back();
@ -116,21 +120,23 @@ public:
m_symCurrentp = m_sympStack.back();
}
void showUpward() {
UINFO(1,"ParseSym Stack:\n");
for (SymStack::reverse_iterator it=m_sympStack.rbegin(); it!=m_sympStack.rend(); ++it) {
UINFO(1, "ParseSym Stack:\n");
for (SymStack::reverse_iterator it = m_sympStack.rbegin(); it != m_sympStack.rend();
++it) {
VSymEnt* symp = *it;
UINFO(1," "<<symp->nodep()<<endl);
UINFO(1, " " << symp->nodep() << endl);
}
UINFO(1,"ParseSym Current: "<<symCurrentp()->nodep()<<endl);
}
void dump(std::ostream& os, const string& indent="") {
m_syms.dump(os, indent);
UINFO(1, "ParseSym Current: " << symCurrentp()->nodep() << endl);
}
void dump(std::ostream& os, const string& indent = "") { m_syms.dump(os, indent); }
AstNode* findEntUpward(const string& name) {
// Lookup the given string as an identifier, return type of the id, scanning upward
VSymEnt* foundp = symCurrentp()->findIdFallback(name);
if (foundp) return foundp->nodep();
else return NULL;
if (foundp) {
return foundp->nodep();
} else {
return NULL;
}
}
void importItem(AstNode* packagep, const string& id_or_star) {
// Import from package::id_or_star to this

View File

@ -61,6 +61,7 @@ public:
// Operate on the final ExecMTask graph, immediately prior to code
// generation time.
static void finalize();
private:
static void finalizeCosts(V3Graph* execMTaskGraphp);
static void setupMTaskDeps(V3Graph* mtasksp, const Vx2MTaskMap* vx2mtaskp);
@ -75,13 +76,15 @@ private:
class PartPtrIdMap {
private:
// TYPES
typedef vl_unordered_map <const void*, vluint64_t> PtrMap;
typedef vl_unordered_map<const void*, vluint64_t> PtrMap;
// MEMBERS
mutable vluint64_t m_nextId;
mutable PtrMap m_id;
public:
// CONSTRUCTORS
PartPtrIdMap() : m_nextId(0) {}
PartPtrIdMap()
: m_nextId(0) {}
// METHODS
vluint64_t findId(const void* ptrp) const {
PtrMap::const_iterator it = m_id.find(ptrp);

View File

@ -30,7 +30,8 @@
class AbstractMTask : public V3GraphVertex {
public:
AbstractMTask(V3Graph* graphp) : V3GraphVertex(graphp) {}
AbstractMTask(V3Graph* graphp)
: V3GraphVertex(graphp) {}
virtual ~AbstractMTask() {}
virtual uint32_t id() const = 0;
virtual uint32_t cost() const = 0;
@ -41,7 +42,8 @@ public:
// TYPES
typedef std::list<MTaskMoveVertex*> VxList;
// CONSTRUCTORS
AbstractLogicMTask(V3Graph* graphp) : AbstractMTask(graphp) {}
AbstractLogicMTask(V3Graph* graphp)
: AbstractMTask(graphp) {}
virtual ~AbstractLogicMTask() {}
// METHODS
// Set of logic vertices in this mtask. Order is not significant.
@ -52,28 +54,29 @@ public:
class ExecMTask : public AbstractMTask {
private:
AstMTaskBody* m_bodyp; // Task body
uint32_t m_id; // Unique id of this mtask.
uint32_t m_priority; // Predicted critical path from the start of
AstMTaskBody* m_bodyp; // Task body
uint32_t m_id; // Unique id of this mtask.
uint32_t m_priority; // Predicted critical path from the start of
// this mtask to the ends of the graph that are reachable from this
// mtask. In abstract time units.
uint32_t m_cost; // Predicted runtime of this mtask, in the same
uint32_t m_cost; // Predicted runtime of this mtask, in the same
// abstract time units as priority().
uint32_t m_thread; // Thread for static (pack_mtasks) scheduling,
uint32_t m_thread; // Thread for static (pack_mtasks) scheduling,
// or 0xffffffff if not yet assigned.
const ExecMTask* m_packNextp; // Next for static (pack_mtasks) scheduling
bool m_threadRoot; // Is root thread
const ExecMTask* m_packNextp; // Next for static (pack_mtasks) scheduling
bool m_threadRoot; // Is root thread
VL_UNCOPYABLE(ExecMTask);
public:
ExecMTask(V3Graph* graphp, AstMTaskBody* bodyp, uint32_t id)
: AbstractMTask(graphp),
m_bodyp(bodyp),
m_id(id),
m_priority(0),
m_cost(0),
m_thread(0xffffffff),
m_packNextp(NULL),
m_threadRoot(false) {}
: AbstractMTask(graphp)
, m_bodyp(bodyp)
, m_id(id)
, m_priority(0)
, m_cost(0)
, m_thread(0xffffffff)
, m_packNextp(NULL)
, m_threadRoot(false) {}
AstMTaskBody* bodyp() const { return m_bodyp; }
virtual uint32_t id() const { return m_id; }
uint32_t priority() const { return m_priority; }
@ -88,18 +91,20 @@ public:
void threadRoot(bool threadRoot) { m_threadRoot = threadRoot; }
string cFuncName() const {
// If this MTask maps to a C function, this should be the name
return string("__Vmtask")+"__"+cvtToStr(m_id);
return string("__Vmtask") + "__" + cvtToStr(m_id);
}
string name() const { return string("mt")+cvtToStr(id()); }
string name() const { return string("mt") + cvtToStr(id()); }
void dump(std::ostream& str) const {
str <<name()<<"."<<cvtToHex(this);
if (priority() || cost()) str <<" [pr="<<priority()<<" c="<<cvtToStr(cost())<<"]";
if (thread() != 0xffffffff) str <<" th="<<thread();
if (threadRoot()) str <<" [ROOT]";
if (packNextp()) str <<" nx="<<packNextp()->name();
str << name() << "." << cvtToHex(this);
if (priority() || cost()) str << " [pr=" << priority() << " c=" << cvtToStr(cost()) << "]";
if (thread() != 0xffffffff) str << " th=" << thread();
if (threadRoot()) str << " [ROOT]";
if (packNextp()) str << " nx=" << packNextp()->name();
}
};
inline std::ostream& operator<<(std::ostream& os, const ExecMTask& rhs) {
rhs.dump(os); return os; }
rhs.dump(os);
return os;
}
#endif // Guard

View File

@ -34,6 +34,7 @@ class V3PreProcImp;
// Token codes
// If changing, see V3PreProc.cpp's V3PreProcImp::tokenName()
// clang-format off
#define VP_EOF 0 // Must be zero, a.k.a. YY_NULL, a.k.a. yy_terminate();
#define VP_EOF_ERROR 400
@ -65,10 +66,13 @@ class V3PreProcImp;
#define VP_JOIN 314
#define VP_PSL 350
// clang-format on
//======================================================================
// Externs created by flex
// We add a prefix so that other lexers/flexers in the same program won't collide.
// clang-format off
#ifndef yy_create_buffer
# define yy_create_buffer V3PreLex_create_buffer
# define yy_delete_buffer V3PreLex_delete_buffer
@ -97,9 +101,10 @@ class V3PreProcImp;
#ifndef YY_BUFFER_STATE
struct yy_buffer_state;
typedef struct yy_buffer_state *YY_BUFFER_STATE;
typedef struct yy_buffer_state* YY_BUFFER_STATE;
# define YY_BUF_SIZE 16384
#endif
// clang-format on
extern int yylex();
extern void yyrestart(FILE*);
@ -109,7 +114,7 @@ extern char* yyourtext();
extern size_t yyourleng();
extern void yyourtext(const char* textp, size_t size); // Must call with static
YY_BUFFER_STATE yy_create_buffer(FILE *file, int size);
YY_BUFFER_STATE yy_create_buffer(FILE* file, int size);
void yy_switch_to_buffer(YY_BUFFER_STATE new_buffer);
void yy_delete_buffer(YY_BUFFER_STATE b);
@ -123,22 +128,24 @@ void yy_delete_buffer(YY_BUFFER_STATE b);
class VPreStream {
public:
FileLine* m_curFilelinep; // Current processing point (see also m_tokFilelinep)
V3PreLex* m_lexp; // Lexer, for resource tracking
std::deque<string> m_buffers; // Buffer of characters to process
int m_ignNewlines; // Ignore multiline newlines
bool m_eof; // "EOF" buffer
bool m_file; // Buffer is start of new file
int m_termState; // Termination fsm
FileLine* m_curFilelinep; // Current processing point (see also m_tokFilelinep)
V3PreLex* m_lexp; // Lexer, for resource tracking
std::deque<string> m_buffers; // Buffer of characters to process
int m_ignNewlines; // Ignore multiline newlines
bool m_eof; // "EOF" buffer
bool m_file; // Buffer is start of new file
int m_termState; // Termination fsm
VPreStream(FileLine* fl, V3PreLex* lexp)
: m_curFilelinep(fl), m_lexp(lexp),
m_ignNewlines(0),
m_eof(false), m_file(false), m_termState(0) {
: m_curFilelinep(fl)
, m_lexp(lexp)
, m_ignNewlines(0)
, m_eof(false)
, m_file(false)
, m_termState(0) {
lexStreamDepthAdd(1);
}
~VPreStream() {
lexStreamDepthAdd(-1);
}
~VPreStream() { lexStreamDepthAdd(-1); }
private:
void lexStreamDepthAdd(int delta);
};
@ -147,26 +154,26 @@ private:
// Class entry for each per-lexer state
class V3PreLex {
public: // Used only by V3PreLex.cpp and V3PreProc.cpp
V3PreProcImp* m_preimpp; // Preprocessor lexor belongs to
public: // Used only by V3PreLex.cpp and V3PreProc.cpp
V3PreProcImp* m_preimpp; // Preprocessor lexor belongs to
std::stack<VPreStream*> m_streampStack; // Stack of processing files
int m_streamDepth; // Depth of stream processing
YY_BUFFER_STATE m_bufferState; // Flex state
FileLine* m_tokFilelinep; // Starting position of current token
int m_streamDepth; // Depth of stream processing
YY_BUFFER_STATE m_bufferState; // Flex state
FileLine* m_tokFilelinep; // Starting position of current token
// State to lexer
static V3PreLex* s_currentLexp; ///< Current lexing point
int m_keepComments; ///< Emit comments in output text
int m_keepWhitespace; ///< Emit all whitespace in output text
bool m_pedantic; ///< Obey standard; don't Substitute `error
static V3PreLex* s_currentLexp; ///< Current lexing point
int m_keepComments; ///< Emit comments in output text
int m_keepWhitespace; ///< Emit all whitespace in output text
bool m_pedantic; ///< Obey standard; don't Substitute `error
// State from lexer
int m_formalLevel; // Parenthesis counting inside def formals
int m_parenLevel; // Parenthesis counting inside def args
bool m_defCmtSlash; // /*...*/ comment in define had \ ending
bool m_defQuote; // Definition value inside quote
string m_defValue; // Definition value being built.
int m_enterExit; // For VL_LINE, the enter/exit level
int m_formalLevel; // Parenthesis counting inside def formals
int m_parenLevel; // Parenthesis counting inside def args
bool m_defCmtSlash; // /*...*/ comment in define had \ ending
bool m_defQuote; // Definition value inside quote
string m_defValue; // Definition value being built.
int m_enterExit; // For VL_LINE, the enter/exit level
// CONSTRUCTORS
V3PreLex(V3PreProcImp* preimpp, FileLine* filelinep) {
@ -184,7 +191,10 @@ class V3PreLex {
initFirstBuffer(filelinep);
}
~V3PreLex() {
while (!m_streampStack.empty()) { delete m_streampStack.top(); m_streampStack.pop(); }
while (!m_streampStack.empty()) {
delete m_streampStack.top();
m_streampStack.pop();
}
VL_DO_CLEAR(yy_delete_buffer(m_bufferState), m_bufferState = NULL);
}
@ -213,8 +223,8 @@ class V3PreLex {
size_t inputToLex(char* buf, size_t max_size);
/// Called by V3PreProc.cpp to get data from lexer
YY_BUFFER_STATE currentBuffer();
int lex();
int currentStartState() const;
int lex();
int currentStartState() const;
void dumpSummary();
void dumpStack();
void unused();

View File

@ -44,13 +44,13 @@ protected:
public:
// CONSTANTS
enum MiscConsts {
DEFINE_RECURSION_LEVEL_MAX = 1000, // How many `def substitutions before an error
LINE_TOKEN_MAX = 20000, // How many tokens on a line before an error
INCLUDE_DEPTH_MAX = 500, // How many `includes deep before an error
STREAM_DEPTH_LEVEL_MAX = 2000, // How many streams deep (sometimes `def deep) before an error
// // Set more than DEFINE_RECURSION_LEVEL_MAX
// // or INCLUDE_DEPTH_MAX
NEWLINES_VS_TICKLINE = 20 // Use `line in place of this many newlines
DEFINE_RECURSION_LEVEL_MAX = 1000, // How many `def substitutions before an error
LINE_TOKEN_MAX = 20000, // How many tokens on a line before an error
INCLUDE_DEPTH_MAX = 500, // How many `includes deep before an error
// Streams deep (sometimes `def deep) before an error.
// Set more than DEFINE_RECURSION_LEVEL_MAX or INCLUDE_DEPTH_MAX.
STREAM_DEPTH_LEVEL_MAX = 2000,
NEWLINES_VS_TICKLINE = 20 // Use `line in place of this many newlines
};
// ACCESSORS
@ -80,9 +80,10 @@ public:
virtual void include(const string& filename) = 0; // Request a include file be processed
virtual void undef(const string& name) = 0; // Remove a definition
virtual void define(FileLine* fileline, const string& name,
const string& value, const string& params="",
bool cmdline=false) = 0; // `define without any parameters
virtual void define(FileLine* fileline, const string& name, const string& value,
const string& params = "",
bool cmdline = false)
= 0; // `define without any parameters
virtual void defineCmdLine(FileLine* fileline, const string& name,
const string& value) { // `define without any parameters
define(fileline, name, value, "", true);
@ -97,10 +98,9 @@ public:
protected:
// CONSTRUCTORS
V3PreProc() {
m_debug = 0;
}
V3PreProc() { m_debug = 0; }
void configure(FileLine* fl);
public:
static V3PreProc* createPreProc(FileLine* fl);
virtual ~V3PreProc() {}

View File

@ -43,7 +43,7 @@ protected:
//---------------------------------------
// METHODS
static int debug(bool reset=false) {
static int debug(bool reset = false) {
static int level = -1;
if (VL_UNLIKELY(level < 0) || reset) {
level = v3Global.opt.debugSrcLevel(__FILE__);
@ -64,8 +64,10 @@ protected:
s_preprocp->defineCmdLine(prefl, "VERILATOR", "1"); // LEAK_OK
s_preprocp->defineCmdLine(prefl, "verilator", "1"); // LEAK_OK
s_preprocp->defineCmdLine(prefl, "verilator3", "1"); // LEAK_OK
s_preprocp->defineCmdLine(prefl, "systemc_clock", "/*verilator systemc_clock*/"); // LEAK_OK
s_preprocp->defineCmdLine(prefl, "coverage_block_off", "/*verilator coverage_block_off*/"); // LEAK_OK
s_preprocp->defineCmdLine(prefl, "systemc_clock",
"/*verilator systemc_clock*/"); // LEAK_OK
s_preprocp->defineCmdLine(prefl, "coverage_block_off",
"/*verilator coverage_block_off*/"); // LEAK_OK
if (prefl->language().systemVerilog()) {
// Synthesis compatibility
s_preprocp->defineCmdLine(prefl, "SYSTEMVERILOG", "1"); // LEAK_OK
@ -94,7 +96,7 @@ protected:
debug(true); // Recheck if debug on - first check was before command line passed
// Preprocess the given module, putting output in vppFilename
UINFONL(1," Preprocessing "<<modname<<endl);
UINFONL(1, " Preprocessing " << modname << endl);
// Preprocess
s_filterp = filterp;
@ -109,8 +111,8 @@ protected:
// intervening +<lang>ext+ options since it was first encountered.
FileLine* modfileline = new FileLine(modfilename);
modfileline->language(v3Global.opt.fileLanguage(modfilename));
V3Parse::ppPushText(parsep, (string("`begin_keywords \"")
+modfileline->language().ascii()+"\"\n"));
V3Parse::ppPushText(
parsep, (string("`begin_keywords \"") + modfileline->language().ascii() + "\"\n"));
}
while (!s_preprocp->isEof()) {
@ -121,31 +123,32 @@ protected:
}
void preprocInclude(FileLine* fl, const string& modname) {
if (modname[0]=='/' || modname[0]=='\\') {
fl->v3warn(INCABSPATH, "Suggest `include with absolute path be made relative, and use +include: "
<<modname);
if (modname[0] == '/' || modname[0] == '\\') {
fl->v3warn(INCABSPATH,
"Suggest `include with absolute path be made relative, and use +include: "
<< modname);
}
preprocOpen(fl, s_filterp, modname, V3Os::filenameDir(fl->filename()),
"Cannot find include file: ");
}
private:
string preprocOpen(FileLine* fl, VInFilter* filterp,
const string& modname, const string& lastpath,
string preprocOpen(FileLine* fl, VInFilter* filterp, const string& modname,
const string& lastpath,
const string& errmsg) { // Error message or "" to suppress
// Returns filename if successful
// Try a pure name in case user has a bogus `filename they don't expect
string filename = v3Global.opt.filePath(fl, modname, lastpath, errmsg);
if (filename=="") {
if (filename == "") {
// Allow user to put `defined names on the command line instead of filenames,
// then convert them properly.
string ppmodname = s_preprocp->removeDefines(modname);
filename = v3Global.opt.filePath(fl, ppmodname, lastpath, errmsg);
}
if (filename=="") return ""; // Not found
if (filename == "") return ""; // Not found
UINFO(2," Reading "<<filename<<endl);
UINFO(2, " Reading " << filename << endl);
s_preprocp->openFile(fl, filterp, filename);
return filename;
}
@ -163,9 +166,7 @@ VInFilter* V3PreShellImp::s_filterp = NULL;
//######################################################################
// Perl class functions
void V3PreShell::boot(char** env) {
V3PreShellImp::s_preImp.boot(env);
}
void V3PreShell::boot(char** env) { V3PreShellImp::s_preImp.boot(env); }
bool V3PreShell::preproc(FileLine* fl, const string& modname, VInFilter* filterp,
V3ParseImp* parsep, const string& errmsg) {
return V3PreShellImp::s_preImp.preproc(fl, modname, filterp, parsep, errmsg);
@ -177,12 +178,8 @@ void V3PreShell::defineCmdLine(const string& name, const string& value) {
FileLine* prefl = new FileLine(FileLine::commandLineFilename());
V3PreShellImp::s_preprocp->defineCmdLine(prefl, name, value);
}
void V3PreShell::undef(const string& name) {
V3PreShellImp::s_preprocp->undef(name);
}
void V3PreShell::dumpDefines(std::ostream& os) {
V3PreShellImp::s_preprocp->dumpDefines(os);
}
void V3PreShell::undef(const string& name) { V3PreShellImp::s_preprocp->undef(name); }
void V3PreShell::dumpDefines(std::ostream& os) { V3PreShellImp::s_preprocp->dumpDefines(os); }
void V3PreShell::candidateDefines(VSpellCheck* spellerp) {
V3PreShellImp::s_preprocp->candidateDefines(spellerp);
}

View File

@ -47,27 +47,27 @@
class ReloopVisitor : public AstNVisitor {
private:
// TYPES
typedef std::vector<AstNodeAssign*> AssVec;
typedef std::vector<AstNodeAssign*> AssVec;
// NODE STATE
// AstCFunc::user1p -> Var* for temp var, 0=not set yet
AstUser1InUse m_inuser1;
AstUser1InUse m_inuser1;
// STATE
VDouble0 m_statReloops; // Statistic tracking
VDouble0 m_statReItems; // Statistic tracking
AstCFunc* m_cfuncp; // Current block
VDouble0 m_statReloops; // Statistic tracking
VDouble0 m_statReItems; // Statistic tracking
AstCFunc* m_cfuncp; // Current block
AssVec m_mgAssignps; // List of assignments merging
AstCFunc* m_mgCfuncp; // Parent C function
AstNode* m_mgNextp; // Next node
AstNodeSel* m_mgSelLp; // Parent select, NULL = idle
AstNodeSel* m_mgSelRp; // Parent select, NULL = constant
AstNodeVarRef* m_mgVarrefLp; // Parent varref
AstNodeVarRef* m_mgVarrefRp; // Parent varref, NULL = constant
AstConst* m_mgConstRp; // Parent RHS constant, NULL = sel
uint32_t m_mgIndexLo; // Merge range
uint32_t m_mgIndexHi; // Merge range
AssVec m_mgAssignps; // List of assignments merging
AstCFunc* m_mgCfuncp; // Parent C function
AstNode* m_mgNextp; // Next node
AstNodeSel* m_mgSelLp; // Parent select, NULL = idle
AstNodeSel* m_mgSelRp; // Parent select, NULL = constant
AstNodeVarRef* m_mgVarrefLp; // Parent varref
AstNodeVarRef* m_mgVarrefRp; // Parent varref, NULL = constant
AstConst* m_mgConstRp; // Parent RHS constant, NULL = sel
uint32_t m_mgIndexLo; // Merge range
uint32_t m_mgIndexHi; // Merge range
// METHODS
VL_DEBUG_FUNC; // Declare debug()
@ -76,8 +76,7 @@ private:
AstVar* varp = VN_CAST(cfuncp->user1p(), Var);
if (!varp) {
string newvarname = string("__Vilp");
varp = new AstVar(fl, AstVarType::STMTTEMP,
newvarname, VFlagLogicPacked(), 32);
varp = new AstVar(fl, AstVarType::STMTTEMP, newvarname, VFlagLogicPacked(), 32);
UASSERT_OBJ(cfuncp, fl, "Assignment not under a function");
cfuncp->addInitsp(varp);
cfuncp->user1p(varp);
@ -87,11 +86,11 @@ private:
void mergeEnd() {
if (!m_mgAssignps.empty()) {
uint32_t items = m_mgIndexHi - m_mgIndexLo + 1;
UINFO(9, "End merge iter="<<items<<" "<<m_mgIndexHi<<":"<<m_mgIndexLo
<<" "<<m_mgAssignps[0]<<endl);
UINFO(9, "End merge iter=" << items << " " << m_mgIndexHi << ":" << m_mgIndexLo << " "
<< m_mgAssignps[0] << endl);
if (items >= RELOOP_MIN_ITERS) {
UINFO(6, "Reloop merging items="<<items<<" "<<m_mgIndexHi<<":"<<m_mgIndexLo
<<" "<<m_mgAssignps[0]<<endl);
UINFO(6, "Reloop merging items=" << items << " " << m_mgIndexHi << ":"
<< m_mgIndexLo << " " << m_mgAssignps[0] << endl);
++m_statReloops;
m_statReItems += items;
@ -103,11 +102,11 @@ private:
AstNode* initp = new AstAssign(fl, new AstVarRef(fl, itp, true),
new AstConst(fl, m_mgIndexLo));
AstNode* condp = new AstLte(fl, new AstVarRef(fl, itp, false),
new AstConst(fl, m_mgIndexHi));
AstNode* incp = new AstAssign(fl, new AstVarRef(fl, itp, true),
new AstAdd(fl, new AstConst(fl, 1),
new AstVarRef(fl, itp, false)));
AstNode* condp
= new AstLte(fl, new AstVarRef(fl, itp, false), new AstConst(fl, m_mgIndexHi));
AstNode* incp = new AstAssign(
fl, new AstVarRef(fl, itp, true),
new AstAdd(fl, new AstConst(fl, 1), new AstVarRef(fl, itp, false)));
AstWhile* whilep = new AstWhile(fl, condp, NULL, incp);
initp->addNext(whilep);
bodyp->replaceWith(initp);
@ -122,11 +121,11 @@ private:
rbitp->replaceWith(new AstVarRef(fl, itp, false));
VL_DO_DANGLING(rbitp->deleteTree(), lbitp);
}
if (debug()>=9) initp->dumpTree(cout, "-new: ");
if (debug()>=9) whilep->dumpTree(cout, "-new: ");
if (debug() >= 9) initp->dumpTree(cout, "-new: ");
if (debug() >= 9) whilep->dumpTree(cout, "-new: ");
// Remove remaining assigns
for (AssVec::iterator it=m_mgAssignps.begin(); it!=m_mgAssignps.end(); ++it) {
for (AssVec::iterator it = m_mgAssignps.begin(); it != m_mgAssignps.end(); ++it) {
AstNodeAssign* assp = *it;
if (assp != bodyp) {
VL_DO_DANGLING(assp->unlinkFrBack()->deleteTree(), assp);
@ -154,15 +153,27 @@ private:
// Left select WordSel or ArraySel
AstNodeSel* lselp = VN_CAST(nodep->lhsp(), NodeSel);
if (!lselp) { mergeEnd(); return; } // Not ever merged
if (!lselp) { // Not ever merged
mergeEnd();
return;
}
// Of a constant index
AstConst* lbitp = VN_CAST(lselp->bitp(), Const);
if (!lbitp) { mergeEnd(); return; }
if (lbitp->width() > 32) { mergeEnd(); return; } // Assoc arrays can do this
if (!lbitp) {
mergeEnd();
return;
}
if (lbitp->width() > 32) { // Assoc arrays can do this
mergeEnd();
return;
}
uint32_t index = lbitp->toUInt();
// Of variable
AstNodeVarRef* lvarrefp = VN_CAST(lselp->fromp(), NodeVarRef);
if (!lvarrefp) { mergeEnd(); return; }
if (!lvarrefp) {
mergeEnd();
return;
}
// RHS is a constant or a select
AstConst* rconstp = VN_CAST(nodep->rhsp(), Const);
@ -170,38 +181,38 @@ private:
AstNodeVarRef* rvarrefp = NULL;
if (rconstp) { // Ok
} else {
if (!rselp) { mergeEnd(); return; }
if (!rselp) {
mergeEnd();
return;
}
AstConst* rbitp = VN_CAST(rselp->bitp(), Const);
rvarrefp = VN_CAST(rselp->fromp(), NodeVarRef);
if (!rbitp || rbitp->toUInt() != index
|| !rvarrefp
if (!rbitp || rbitp->toUInt() != index || !rvarrefp
|| lvarrefp->varp() == rvarrefp->varp()) {
mergeEnd(); return;
mergeEnd();
return;
}
}
if (m_mgSelLp) { // Old merge
if (m_mgCfuncp == m_cfuncp
&& m_mgNextp == nodep
&& m_mgSelLp->same(lselp)
if (m_mgCfuncp == m_cfuncp && m_mgNextp == nodep && m_mgSelLp->same(lselp)
&& m_mgVarrefLp->same(lvarrefp)
&& (m_mgConstRp
? (rconstp && m_mgConstRp->same(rconstp))
: (rselp
&& m_mgSelRp->same(rselp)
&& m_mgVarrefRp->same(rvarrefp)))
&& (index == m_mgIndexLo-1
|| index == m_mgIndexHi+1)) {
? (rconstp && m_mgConstRp->same(rconstp))
: (rselp && m_mgSelRp->same(rselp) && m_mgVarrefRp->same(rvarrefp)))
&& (index == m_mgIndexLo - 1 || index == m_mgIndexHi + 1)) {
// Sequentially next to last assign; continue merge
if (index == m_mgIndexLo-1) m_mgIndexLo = index;
else if (index == m_mgIndexHi+1) m_mgIndexHi = index;
UINFO(9, "Continue merge i="<<index
<<" "<<m_mgIndexHi<<":"<<m_mgIndexLo<<" "<<nodep<<endl);
if (index == m_mgIndexLo - 1) {
m_mgIndexLo = index;
} else if (index == m_mgIndexHi + 1) {
m_mgIndexHi = index;
}
UINFO(9, "Continue merge i=" << index << " " << m_mgIndexHi << ":" << m_mgIndexLo
<< " " << nodep << endl);
m_mgAssignps.push_back(nodep);
m_mgNextp = nodep->nextp();
return;
}
else {
} else {
// This assign doesn't merge with previous assign,
// but should start a new merge
mergeEnd();
@ -219,7 +230,7 @@ private:
m_mgConstRp = rconstp;
m_mgIndexLo = index;
m_mgIndexHi = index;
UINFO(9, "Start merge i="<<index<<" "<<nodep<<endl);
UINFO(9, "Start merge i=" << index << " " << nodep << endl);
}
//--------------------
virtual void visit(AstVar*) VL_OVERRIDE {} // Accelerate
@ -251,9 +262,7 @@ public:
// Reloop class functions
void V3Reloop::reloopAll(AstNetlist* nodep) {
UINFO(2,__FUNCTION__<<": "<<endl);
{
ReloopVisitor visitor(nodep);
} // Destruct before checking
UINFO(2, __FUNCTION__ << ": " << endl);
{ ReloopVisitor visitor(nodep); } // Destruct before checking
V3Global::dumpCheckGlobalTree("reloop", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 6);
}

View File

@ -25,7 +25,8 @@ public:
uint32_t m_score;
uint32_t m_id;
// CONSTRUCTORS
explicit ScoreboardTestElem(uint32_t score) : m_score(score) {
explicit ScoreboardTestElem(uint32_t score)
: m_score(score) {
static uint32_t s_serial = 0;
m_id = ++s_serial;
}
@ -33,9 +34,7 @@ public:
// METHODS
static uint32_t scoreFn(const ScoreboardTestElem* elp) { return elp->m_score; }
bool operator< (const ScoreboardTestElem& other) const {
return m_id < other.m_id;
}
bool operator<(const ScoreboardTestElem& other) const { return m_id < other.m_id; }
};
void V3ScoreboardBase::selfTest() {
@ -52,8 +51,7 @@ void V3ScoreboardBase::selfTest() {
sb.addElem(&e3);
UASSERT(sb.needsRescore(), "SelfTest: Newly filled sb should need a rescore.");
UASSERT(sb.needsRescore(&e1),
"SelfTest: Individual newly-added element should need rescore");
UASSERT(sb.needsRescore(&e1), "SelfTest: Individual newly-added element should need rescore");
UASSERT(NULL == sb.bestp(),
"SelfTest: Newly filled sb should have nothing eligible for Bestp()");
@ -64,14 +62,12 @@ void V3ScoreboardBase::selfTest() {
"SelfTest: Newly rescored sb should not need an element rescored");
UASSERT(e2.m_score == sb.cachedScore(&e2),
"SelfTest: Cached score should match current score");
UASSERT(&e1 == sb.bestp(),
"SelfTest: Should return element with lowest (best) score");
UASSERT(&e1 == sb.bestp(), "SelfTest: Should return element with lowest (best) score");
// Change one element's score
sb.hintScoreChanged(&e2);
e2.m_score = 21;
UASSERT(sb.needsRescore(&e2),
"SelfTest: Should need rescore on elem after hintScoreChanged");
UASSERT(sb.needsRescore(&e2), "SelfTest: Should need rescore on elem after hintScoreChanged");
// Remove an element
UASSERT(sb.contains(&e1), "SelfTest: e1 should be there");

View File

@ -64,6 +64,7 @@ public:
typedef void pointer;
typedef std::ptrdiff_t difference_type;
typedef std::bidirectional_iterator_tag iterator_category;
protected:
friend class SortByValueMap;
@ -77,8 +78,7 @@ public:
explicit const_iterator(SortByValueMap* sbmvp) // for end()
: m_sbvmp(sbmvp)
, m_end(true) {}
const_iterator(typename Val2Keys::iterator valIt,
typename KeySet::iterator keyIt,
const_iterator(typename Val2Keys::iterator valIt, typename KeySet::iterator keyIt,
SortByValueMap* sbvmp)
: m_keyIt(keyIt)
, m_valIt(valIt)
@ -135,6 +135,7 @@ public:
--m_keyIt;
UASSERT(m_keyIt != m_valIt->second.end(), "Value bucket should have key");
}
public:
const T_Key& key() const { return *m_keyIt; }
const T_Value& value() const { return m_valIt->first; }
@ -151,15 +152,10 @@ public:
// sequences. So check m_end before comparing m_valIt, and
// compare m_valIt's before comparing m_keyIt to ensure nothing
// here is undefined.
if (m_end || other.m_end) {
return m_end && other.m_end;
}
return ((m_valIt == other.m_valIt)
&& (m_keyIt == other.m_keyIt));
}
bool operator!=(const const_iterator& other) const {
return (!this->operator==(other));
if (m_end || other.m_end) return m_end && other.m_end;
return ((m_valIt == other.m_valIt) && (m_keyIt == other.m_keyIt));
}
bool operator!=(const const_iterator& other) const { return (!this->operator==(other)); }
// WARNING: Cleverness.
//
@ -209,8 +205,7 @@ public:
// CONSTRUCTORS
explicit iterator(SortByValueMap* sbvmp)
: const_iterator(sbvmp) {}
iterator(typename Val2Keys::iterator valIt,
typename KeySet::iterator keyIt,
iterator(typename Val2Keys::iterator valIt, typename KeySet::iterator keyIt,
SortByValueMap* sbvmp)
: const_iterator(valIt, keyIt, sbvmp) {}
@ -248,49 +243,33 @@ private:
}
void removeKeyFromOldVal(iterator it) {
it.m_valIt->second.erase(it.m_keyIt);
if (it.m_valIt->second.empty()) {
m_vals.erase(it.m_valIt);
}
if (it.m_valIt->second.empty()) m_vals.erase(it.m_valIt);
}
public:
iterator begin() {
typename Val2Keys::iterator valIt = m_vals.begin();
if (valIt == m_vals.end()) {
return end();
}
if (valIt == m_vals.end()) return end();
typename KeySet::const_iterator keyIt = valIt->second.begin();
return iterator(valIt, keyIt, this);
}
const_iterator begin() const {
SortByValueMap* mutp = const_cast<SortByValueMap*>(this);
typename Val2Keys::iterator valIt = mutp->m_vals.begin();
if (valIt == mutp->m_vals.end()) {
return end();
}
if (valIt == mutp->m_vals.end()) return end();
typename KeySet::const_iterator keyIt = valIt->second.begin();
return const_iterator(valIt, keyIt, mutp);
}
iterator end() {
return iterator(this);
}
iterator end() { return iterator(this); }
const_iterator end() const {
// Safe to cast away const; the const_iterator will still enforce
// it. Same for the const begin() below.
return const_iterator(const_cast<SortByValueMap*>(this));
}
reverse_iterator rbegin() {
return reverse_iterator(end());
}
reverse_iterator rend() {
return reverse_iterator(begin());
}
const_reverse_iterator rbegin() const {
return const_reverse_iterator(end());
}
const_reverse_iterator rend() const {
return const_reverse_iterator(begin());
}
reverse_iterator rbegin() { return reverse_iterator(end()); }
reverse_iterator rend() { return reverse_iterator(begin()); }
const_reverse_iterator rbegin() const { return const_reverse_iterator(end()); }
const_reverse_iterator rend() const { return const_reverse_iterator(begin()); }
iterator find(const T_Key& k) {
typename Key2Val::iterator kvit = m_keys.find(k);
@ -335,12 +314,8 @@ public:
void erase(const reverse_iterator& it) {
erase(*it); // Dereferencing returns a copy of the forward iterator
}
bool has(const T_Key& k) const {
return (m_keys.find(k) != m_keys.end());
}
bool empty() const {
return m_keys.empty();
}
bool has(const T_Key& k) const { return (m_keys.find(k) != m_keys.end()); }
bool empty() const { return m_keys.empty(); }
// Look up a value. Returns a reference for efficiency. Note this must
// be a const reference, otherwise the client could corrupt the sorted
// order of m_byValue by reaching through and changing the value.
@ -375,16 +350,14 @@ private:
/// when the subset of elements whose scores change is much smaller than
/// the full set size.
template <typename T_Elem,
typename T_Score,
class T_ElemCompare = std::less<T_Elem> >
template <typename T_Elem, typename T_Score, class T_ElemCompare = std::less<T_Elem> >
class V3Scoreboard {
private:
// TYPES
typedef vl_unordered_set<const T_Elem*> NeedRescoreSet;
class CmpElems {
public:
bool operator() (const T_Elem* const& ap, const T_Elem* const& bp) const {
bool operator()(const T_Elem* const& ap, const T_Elem* const& bp) const {
T_ElemCompare cmp;
return cmp.operator()(*ap, *bp);
}
@ -412,8 +385,7 @@ public:
// bestp() until after the next rescore().
void addElem(const T_Elem* elp) {
if (m_slowAsserts) {
UASSERT(!contains(elp),
"Adding element to scoreboard that was already in scoreboard");
UASSERT(!contains(elp), "Adding element to scoreboard that was already in scoreboard");
}
m_unknown.insert(elp);
}
@ -470,22 +442,19 @@ public:
bool needsRescore() { return !m_unknown.empty(); }
// False if elp's score is known to V3Scoreboard,
// else true if elp's score is unknown until the next rescore().
bool needsRescore(const T_Elem* elp) {
return (m_unknown.find(elp) != m_unknown.end());
}
bool needsRescore(const T_Elem* elp) { return (m_unknown.find(elp) != m_unknown.end()); }
// Retrieve the last known score for an element.
T_Score cachedScore(const T_Elem* elp) {
typename SortedMap::iterator result = m_sorted.find(elp);
UASSERT(result != m_sorted.end(),
"V3Scoreboard::cachedScore() failed to find element");
UASSERT(result != m_sorted.end(), "V3Scoreboard::cachedScore() failed to find element");
return (*result).value();
}
// For each element whose score is unknown to V3Scoreboard,
// call the client's scoring function to get a new score,
// and sort all elements by their current score.
void rescore() {
for (typename NeedRescoreSet::iterator it = m_unknown.begin();
it != m_unknown.end(); ++it) {
for (typename NeedRescoreSet::iterator it = m_unknown.begin(); it != m_unknown.end();
++it) {
const T_Elem* elp = *it;
T_Score sortScore = m_scoreFnp(elp);
m_sorted.set(elp, sortScore);
@ -500,7 +469,7 @@ private:
//######################################################################
namespace V3ScoreboardBase {
void selfTest();
void selfTest();
} // namespace V3ScoreboardBase
#endif // Guard

View File

@ -53,7 +53,7 @@ private:
class HashSenTree {
public:
HashSenTree() {}
size_t operator() (const AstSenTree* kp) const {
size_t operator()(const AstSenTree* kp) const {
return V3Hashed::uncachedHash(kp).fullValue();
}
// Copying required for OSX's libc++
@ -62,7 +62,7 @@ private:
class EqSenTree {
public:
EqSenTree() {}
bool operator() (const AstSenTree* ap, const AstSenTree* bp) const {
bool operator()(const AstSenTree* ap, const AstSenTree* bp) const {
return ap->sameTree(bp);
}
// Copying required for OSX's libc++
@ -81,9 +81,7 @@ public:
AstSenTree* find(AstSenTree* likep) {
AstSenTree* resultp = NULL;
Set::iterator it = m_trees.find(likep);
if (it != m_trees.end()) {
resultp = *it;
}
if (it != m_trees.end()) resultp = *it;
return resultp;
}
void clear() { m_trees.clear(); }
@ -103,9 +101,7 @@ private:
virtual void visit(AstNodeModule* nodep) VL_OVERRIDE {
// Only do the top
if (nodep->isTop()) {
iterateChildren(nodep);
}
if (nodep->isTop()) iterateChildren(nodep);
}
virtual void visit(AstTopScope* nodep) VL_OVERRIDE {
m_topscopep = nodep;
@ -139,21 +135,18 @@ public:
UASSERT(m_topscopep, "Never called main()");
treep = sensesp->cloneTree(false);
m_topscopep->addStmtsp(treep);
UINFO(8," New SENTREE "<<treep<<endl);
UINFO(8, " New SENTREE " << treep << endl);
m_trees.add(treep);
// Note blocks may have also been added above in the Active visitor
}
return treep;
}
public:
// CONSTRUCTORS
SenTreeFinder() {
clear();
}
SenTreeFinder() { clear(); }
virtual ~SenTreeFinder() {}
void main(AstTopScope* nodep) {
iterate(nodep);
}
void main(AstTopScope* nodep) { iterate(nodep); }
};
#endif // Guard

View File

@ -36,31 +36,31 @@ class StatsVisitor : public AstNVisitor {
private:
// NODE STATE/TYPES
typedef std::map<string,int> NameMap; // Number of times a name appears
typedef std::map<string, int> NameMap; // Number of times a name appears
// STATE
string m_stage; // Name of the stage we are scanning
string m_stage; // Name of the stage we are scanning
/// m_fast = true: Counting only critical branch of fastpath
/// m_fast = false: Counting every node, ignoring structure of program
bool m_fast;
bool m_fast;
AstCFunc* m_cfuncp; // Current CFUNC
VDouble0 m_statInstrLong; // Instruction count
bool m_counting; // Currently counting
double m_instrs; // Current instr count (for determining branch direction)
bool m_tracingCall; // Iterating into a CCall to a CFunc
AstCFunc* m_cfuncp; // Current CFUNC
VDouble0 m_statInstrLong; // Instruction count
bool m_counting; // Currently counting
double m_instrs; // Current instr count (for determining branch direction)
bool m_tracingCall; // Iterating into a CCall to a CFunc
std::vector<VDouble0> m_statTypeCount; // Nodes of given type
VDouble0 m_statAbove[AstType::_ENUM_END][AstType::_ENUM_END]; // Nodes of given type
VDouble0 m_statPred[VBranchPred::_ENUM_END]; // Nodes of given type
VDouble0 m_statInstr; // Instruction count
VDouble0 m_statInstrFast; // Instruction count, non-slow() eval functions only
std::vector<VDouble0> m_statVarWidths; // Variables of given width
std::vector<NameMap> m_statVarWidthNames; // Var names of given width
VDouble0 m_statVarArray; // Statistic tracking
VDouble0 m_statVarBytes; // Statistic tracking
VDouble0 m_statVarClock; // Statistic tracking
VDouble0 m_statVarScpBytes; // Statistic tracking
std::vector<VDouble0> m_statTypeCount; // Nodes of given type
VDouble0 m_statAbove[AstType::_ENUM_END][AstType::_ENUM_END]; // Nodes of given type
VDouble0 m_statPred[VBranchPred::_ENUM_END]; // Nodes of given type
VDouble0 m_statInstr; // Instruction count
VDouble0 m_statInstrFast; // Instruction count, non-slow() eval functions only
std::vector<VDouble0> m_statVarWidths; // Variables of given width
std::vector<NameMap> m_statVarWidthNames; // Var names of given width
VDouble0 m_statVarArray; // Statistic tracking
VDouble0 m_statVarBytes; // Statistic tracking
VDouble0 m_statVarClock; // Statistic tracking
VDouble0 m_statVarScpBytes; // Statistic tracking
// METHODS
VL_DEBUG_FUNC; // Declare debug()
@ -92,13 +92,16 @@ private:
iterateChildrenConst(nodep);
if (m_counting && nodep->dtypep()) {
if (nodep->isUsedClock()) ++m_statVarClock;
if (VN_IS(nodep->dtypeSkipRefp(), UnpackArrayDType)) ++m_statVarArray;
else m_statVarBytes += nodep->dtypeSkipRefp()->widthTotalBytes();
if (int(m_statVarWidths.size()) <= nodep->width()) {
m_statVarWidths.resize(nodep->width()+5);
if (v3Global.opt.statsVars()) m_statVarWidthNames.resize(nodep->width()+5);
if (VN_IS(nodep->dtypeSkipRefp(), UnpackArrayDType)) {
++m_statVarArray;
} else {
m_statVarBytes += nodep->dtypeSkipRefp()->widthTotalBytes();
}
++ m_statVarWidths.at(nodep->width());
if (int(m_statVarWidths.size()) <= nodep->width()) {
m_statVarWidths.resize(nodep->width() + 5);
if (v3Global.opt.statsVars()) m_statVarWidthNames.resize(nodep->width() + 5);
}
++m_statVarWidths.at(nodep->width());
string pn = nodep->prettyName();
if (v3Global.opt.statsVars()) {
NameMap& nameMapr = m_statVarWidthNames.at(nodep->width());
@ -120,14 +123,12 @@ private:
}
}
virtual void visit(AstNodeIf* nodep) VL_OVERRIDE {
UINFO(4," IF i="<<m_instrs<<" "<<nodep<<endl);
UINFO(4, " IF i=" << m_instrs << " " << nodep << endl);
allNodes(nodep);
// Condition is part of cost allocated to PREVIOUS block
iterateAndNextConstNull(nodep->condp());
// Track prediction
if (m_counting) {
++m_statPred[nodep->branchPred()];
}
if (m_counting) ++m_statPred[nodep->branchPred()];
if (!m_fast) {
// Count everything
iterateChildrenConst(nodep);
@ -171,7 +172,7 @@ private:
}
}
// While's we assume evaluate once.
//virtual void visit(AstWhile* nodep) VL_OVERRIDE {
// virtual void visit(AstWhile* nodep) VL_OVERRIDE {
virtual void visit(AstNodeCCall* nodep) VL_OVERRIDE {
allNodes(nodep);
@ -206,11 +207,13 @@ private:
allNodes(nodep);
iterateChildrenConst(nodep);
}
public:
// CONSTRUCTORS
StatsVisitor(AstNetlist* nodep, const string& stage, bool fast)
: m_stage(stage), m_fast(fast) {
UINFO(9,"Starting stats, fast="<<fast<<endl);
: m_stage(stage)
, m_fast(fast) {
UINFO(9, "Starting stats, fast=" << fast << endl);
m_cfuncp = NULL;
m_counting = !m_fast;
m_instrs = 0;
@ -223,53 +226,55 @@ public:
virtual ~StatsVisitor() {
// Done. Publish statistics
V3Stats::addStat(m_stage, "Instruction count, TOTAL", m_statInstr);
V3Stats::addStat(m_stage, "Instruction count, fast critical", m_statInstrFast);
V3Stats::addStat(m_stage, "Instruction count, fast critical", m_statInstrFast);
// Vars
V3Stats::addStat(m_stage, "Vars, unpacked arrayed", m_statVarArray);
V3Stats::addStat(m_stage, "Vars, clock attribute", m_statVarClock);
V3Stats::addStat(m_stage, "Var space, non-arrays, bytes", m_statVarBytes);
if (m_statVarScpBytes!=0.0) {
if (m_statVarScpBytes != 0.0) {
V3Stats::addStat(m_stage, "Var space, scoped, bytes", m_statVarScpBytes);
}
for (unsigned i=0; i<m_statVarWidths.size(); i++) {
for (unsigned i = 0; i < m_statVarWidths.size(); i++) {
double count = double(m_statVarWidths.at(i));
if (count != 0.0) {
if (v3Global.opt.statsVars()) {
NameMap& nameMapr = m_statVarWidthNames.at(i);
for (NameMap::iterator it=nameMapr.begin(); it!=nameMapr.end(); ++it) {
std::ostringstream os; os<<"Vars, width "
<<std::setw(5)<<std::dec<<i<<" "<<it->first;
for (NameMap::iterator it = nameMapr.begin(); it != nameMapr.end(); ++it) {
std::ostringstream os;
os << "Vars, width " << std::setw(5) << std::dec << i << " " << it->first;
V3Stats::addStat(m_stage, os.str(), it->second);
}
} else {
std::ostringstream os; os<<"Vars, width "<<std::setw(5)<<std::dec<<i;
std::ostringstream os;
os << "Vars, width " << std::setw(5) << std::dec << i;
V3Stats::addStat(m_stage, os.str(), count);
}
}
}
// Node types
for (int type=0; type<AstType::_ENUM_END; type++) {
for (int type = 0; type < AstType::_ENUM_END; type++) {
double count = double(m_statTypeCount.at(type));
if (count != 0.0) {
V3Stats::addStat(m_stage, string("Node count, ")+AstType(type).ascii(), count);
V3Stats::addStat(m_stage, string("Node count, ") + AstType(type).ascii(), count);
}
}
for (int type=0; type < AstType::_ENUM_END; type++) {
for (int type2=0; type2 < AstType::_ENUM_END; type2++) {
for (int type = 0; type < AstType::_ENUM_END; type++) {
for (int type2 = 0; type2 < AstType::_ENUM_END; type2++) {
double count = double(m_statAbove[type][type2]);
if (count != 0.0) {
V3Stats::addStat(m_stage, (string("Node pairs, ")
+AstType(type).ascii()+"_"+AstType(type2).ascii()),
V3Stats::addStat(m_stage,
(string("Node pairs, ") + AstType(type).ascii() + "_"
+ AstType(type2).ascii()),
count);
}
}
}
// Branch pred
for (int type=0; type < VBranchPred::_ENUM_END; type++) {
for (int type = 0; type < VBranchPred::_ENUM_END; type++) {
double count = double(m_statPred[type]);
if (count != 0.0) {
V3Stats::addStat(m_stage, (string("Branch prediction, ")
+ VBranchPred(type).ascii()), count);
V3Stats::addStat(
m_stage, (string("Branch prediction, ") + VBranchPred(type).ascii()), count);
}
}
}
@ -279,7 +284,7 @@ public:
// Top Stats class
void V3Stats::statsStageAll(AstNetlist* nodep, const string& stage, bool fast) {
StatsVisitor visitor (nodep, stage, fast);
StatsVisitor visitor(nodep, stage, fast);
}
void V3Stats::statsFinalAll(AstNetlist* nodep) {

View File

@ -31,31 +31,49 @@ class VDouble0 {
double m_d; ///< Count of occurrences/ value
public:
// METHODS
VDouble0() : m_d(0) {}
VDouble0()
: m_d(0) {}
~VDouble0() {}
// Implicit conversion operators:
inline explicit VDouble0(const vluint64_t v) : m_d(v) { }
inline explicit VDouble0(const vluint64_t v)
: m_d(v) {}
inline operator double() const { return m_d; }
// Explicit operators:
inline VDouble0& operator++() { ++m_d; return *this; } // prefix
inline VDouble0 operator++(int) { VDouble0 old=*this; m_d++; return old; } // postfix
inline VDouble0& operator= (const double v) { m_d = v; return *this; }
inline VDouble0& operator+=(const double v) { m_d += v; return *this; }
inline VDouble0& operator-=(const double v) { m_d -= v; return *this; }
inline VDouble0& operator++() { // prefix
++m_d;
return *this;
}
inline VDouble0 operator++(int) { // postfix
VDouble0 old = *this;
m_d++;
return old;
}
inline VDouble0& operator=(const double v) {
m_d = v;
return *this;
}
inline VDouble0& operator+=(const double v) {
m_d += v;
return *this;
}
inline VDouble0& operator-=(const double v) {
m_d -= v;
return *this;
}
};
//============================================================================
class V3Statistic {
// A statistical entry we want published into the database
string m_name; ///< Nameiption of this statistic
double m_count; ///< Count of occurrences/ value
string m_stage; ///< Runtime stage
bool m_sumit; ///< Do summation of similar stats
bool m_perf; ///< Performance section
bool m_printit; ///< Print the results
string m_name; ///< Nameiption of this statistic
double m_count; ///< Count of occurrences/ value
string m_stage; ///< Runtime stage
bool m_sumit; ///< Do summation of similar stats
bool m_perf; ///< Performance section
bool m_printit; ///< Print the results
public:
// METHODS
string stage() const { return m_stage; }
@ -70,9 +88,13 @@ public:
otherp->m_printit = false;
}
// CONSTRUCTORS
V3Statistic(const string& stage, const string& name,
double count, bool sumit=false, bool perf=false)
: m_name(name), m_count(count), m_stage(stage), m_sumit(sumit), m_perf(perf)
V3Statistic(const string& stage, const string& name, double count, bool sumit = false,
bool perf = false)
: m_name(name)
, m_count(count)
, m_stage(stage)
, m_sumit(sumit)
, m_perf(perf)
, m_printit(true) {}
virtual ~V3Statistic() {}
};
@ -83,21 +105,24 @@ class V3Stats {
public:
static void addStat(const V3Statistic&);
static void addStat(const string& stage, const string& name, double count) {
addStat(V3Statistic(stage, name, count)); }
addStat(V3Statistic(stage, name, count));
}
static void addStat(const string& name, double count) {
addStat(V3Statistic("*", name, count)); }
addStat(V3Statistic("*", name, count));
}
static void addStatSum(const string& name, double count) {
addStat(V3Statistic("*", name, count, true)); }
addStat(V3Statistic("*", name, count, true));
}
static void addStatPerf(const string& name, double count) {
addStat(V3Statistic("*", name, count, true, true)); }
addStat(V3Statistic("*", name, count, true, true));
}
/// Called each stage
static void statsStage(const string& name);
/// Called by the top level to collect statistics
static void statsStageAll(AstNetlist* nodep, const string& stage, bool fast=false);
static void statsStageAll(AstNetlist* nodep, const string& stage, bool fast = false);
static void statsFinalAll(AstNetlist* nodep);
/// Called by the top level to dump the statistics
static void statsReport();
};
#endif // Guard

View File

@ -40,31 +40,31 @@ class StatsReport {
static StatColl s_allStats; ///< All statistics
void header() {
os<<"Verilator Statistics Report\n";
os<<endl;
os << "Verilator Statistics Report\n";
os << endl;
os<<"Information:"<<endl;
os<<" "<<V3Options::version()<<endl;
os<<" Arguments: "<<v3Global.opt.allArgsString()<<endl;
os<<endl;
os << "Information:" << endl;
os << " " << V3Options::version() << endl;
os << " Arguments: " << v3Global.opt.allArgsString() << endl;
os << endl;
}
void sumit() {
// If sumit is set on a statistic, combine with others of same name
typedef std::multimap<string,V3Statistic*> ByName;
typedef std::multimap<string, V3Statistic*> ByName;
ByName byName;
// * is always first
for (StatColl::iterator it = s_allStats.begin(); it!=s_allStats.end(); ++it) {
for (StatColl::iterator it = s_allStats.begin(); it != s_allStats.end(); ++it) {
V3Statistic* repp = &(*it);
byName.insert(make_pair(repp->name(), repp));
}
// Process duplicates
V3Statistic* lastp = NULL;
for (ByName::iterator it = byName.begin(); it!=byName.end(); ++it) {
for (ByName::iterator it = byName.begin(); it != byName.end(); ++it) {
V3Statistic* repp = it->second;
if (lastp && lastp->sumit() && lastp->printit()
&& lastp->name() == repp->name() && lastp->stage() == repp->stage()) {
if (lastp && lastp->sumit() && lastp->printit() && lastp->name() == repp->name()
&& lastp->stage() == repp->stage()) {
repp->combineWith(lastp);
}
lastp = repp;
@ -74,10 +74,10 @@ class StatsReport {
void stars() {
// Find all stages
size_t maxWidth = 0;
typedef std::multimap<string,const V3Statistic*> ByName;
typedef std::multimap<string, const V3Statistic*> ByName;
ByName byName;
// * is always first
for (StatColl::iterator it = s_allStats.begin(); it!=s_allStats.end(); ++it) {
for (StatColl::iterator it = s_allStats.begin(); it != s_allStats.end(); ++it) {
const V3Statistic* repp = &(*it);
if (repp->stage() == "*" && repp->printit()) {
if (maxWidth < repp->name().length()) maxWidth = repp->name().length();
@ -86,43 +86,43 @@ class StatsReport {
}
// Print organized by stage
os<<"Global Statistics:\n";
os<<endl;
for (ByName::iterator it = byName.begin(); it!=byName.end(); ++it) {
os << "Global Statistics:\n";
os << endl;
for (ByName::iterator it = byName.begin(); it != byName.end(); ++it) {
const V3Statistic* repp = it->second;
if (repp->perf()) continue;
os<<" "<<std::left<<std::setw(maxWidth)<<repp->name();
os << " " << std::left << std::setw(maxWidth) << repp->name();
repp->dump(os);
os<<endl;
os << endl;
}
os<<endl;
os << endl;
// Print organized by stage
os<<"Performance Statistics:\n";
os<<endl;
for (ByName::iterator it = byName.begin(); it!=byName.end(); ++it) {
os << "Performance Statistics:\n";
os << endl;
for (ByName::iterator it = byName.begin(); it != byName.end(); ++it) {
const V3Statistic* repp = it->second;
if (!repp->perf()) continue;
os<<" "<<std::left<<std::setw(maxWidth)<<repp->name();
os << " " << std::left << std::setw(maxWidth) << repp->name();
repp->dump(os);
os<<endl;
os << endl;
}
os<<endl;
os << endl;
}
void stages() {
os<<"Stage Statistics:\n";
os << "Stage Statistics:\n";
// Find all stages
int stage = 0;
size_t maxWidth = 0;
typedef std::vector<string> Stages;
Stages stages;
vl_unordered_map<string,int> stageInt;
typedef std::multimap<string,const V3Statistic*> ByName;
vl_unordered_map<string, int> stageInt;
typedef std::multimap<string, const V3Statistic*> ByName;
ByName byName;
// * is always first
for (StatColl::iterator it = s_allStats.begin(); it!=s_allStats.end(); ++it) {
for (StatColl::iterator it = s_allStats.begin(); it != s_allStats.end(); ++it) {
const V3Statistic* repp = &(*it);
if (repp->stage() != "*" && repp->printit()) {
if (maxWidth < repp->name().length()) maxWidth = repp->name().length();
@ -135,16 +135,16 @@ class StatsReport {
}
// Header
os<<" Stat "<<std::left<<std::setw(maxWidth-5-2)<<"";
os << " Stat " << std::left << std::setw(maxWidth - 5 - 2) << "";
for (Stages::const_iterator it = stages.begin(); it != stages.end(); ++it) {
os<<" "<<std::left<<std::setw(9)<<*it;
os << " " << std::left << std::setw(9) << *it;
}
os<<endl;
os<<" -------- "<<std::left<<std::setw(maxWidth-5-2)<<"";
os << endl;
os << " -------- " << std::left << std::setw(maxWidth - 5 - 2) << "";
for (Stages::const_iterator it = stages.begin(); it != stages.end(); ++it) {
os<<" "<<std::left<<std::setw(9)<<"-------";
os << " " << std::left << std::setw(9) << "-------";
}
//os<<endl;
// os<<endl;
// Print organized by stage
string lastName = "__NONE__";
@ -157,33 +157,29 @@ class StatsReport {
{
string commaName = lastName;
string::size_type pos;
if ((pos = commaName.find(',')) != string::npos) {
commaName.erase(pos);
}
if ((pos = commaName.find(',')) != string::npos) commaName.erase(pos);
if (lastCommaName != commaName) {
lastCommaName = commaName;
os<<endl;
os << endl;
}
}
os<<endl;
os << endl;
col = 0;
os<<" "<<std::left<<std::setw(maxWidth)<<repp->name();
os << " " << std::left << std::setw(maxWidth) << repp->name();
}
while (col<stages.size() && stages.at(col) != repp->stage()) {
os<<std::setw(11)<<"";
while (col < stages.size() && stages.at(col) != repp->stage()) {
os << std::setw(11) << "";
col++;
}
repp->dump(os);
col++;
}
os<<endl;
os << endl;
}
public:
// METHODS
static void addStat(const V3Statistic& stat) {
s_allStats.push_back(stat);
}
static void addStat(const V3Statistic& stat) { s_allStats.push_back(stat); }
// CONSTRUCTORS
explicit StatsReport(std::ofstream* aofp)
@ -196,52 +192,51 @@ public:
~StatsReport() {}
};
StatsReport::StatColl StatsReport::s_allStats;
StatsReport::StatColl StatsReport::s_allStats;
//######################################################################
// V3Statstic class
void V3Statistic::dump(std::ofstream& os) const {
if (perf()) {
os<<" "<<std::right<<std::fixed<<std::setprecision(6)<<std::setw(9)<<count();
os << " " << std::right << std::fixed << std::setprecision(6) << std::setw(9) << count();
} else {
os<<" "<<std::right<<std::fixed<<std::setprecision(0)<<std::setw(9)<<count();
os << " " << std::right << std::fixed << std::setprecision(0) << std::setw(9) << count();
}
}
//######################################################################
// Top Stats class
void V3Stats::addStat(const V3Statistic& stat) {
StatsReport::addStat(stat);
}
void V3Stats::addStat(const V3Statistic& stat) { StatsReport::addStat(stat); }
void V3Stats::statsStage(const string& name) {
static double lastWallTime = -1;
static int fileNumber = 0;
char digits[100]; sprintf(digits, "%03d", ++fileNumber);
const string digitName = string(digits)+"_"+name;
char digits[100];
sprintf(digits, "%03d", ++fileNumber);
const string digitName = string(digits) + "_" + name;
double wallTime = V3Os::timeUsecs() / 1.0e6;
if (lastWallTime<0) lastWallTime = wallTime;
if (lastWallTime < 0) lastWallTime = wallTime;
double wallTimeDelta = wallTime - lastWallTime;
lastWallTime = wallTime;
V3Stats::addStatPerf("Stage, Elapsed time (sec), "+digitName, wallTimeDelta);
V3Stats::addStatPerf("Stage, Elapsed time (sec), " + digitName, wallTimeDelta);
double memory = V3Os::memUsageBytes()/1024.0/1024.0;
V3Stats::addStatPerf("Stage, Memory (MB), "+digitName, memory);
double memory = V3Os::memUsageBytes() / 1024.0 / 1024.0;
V3Stats::addStatPerf("Stage, Memory (MB), " + digitName, memory);
}
void V3Stats::statsReport() {
UINFO(2,__FUNCTION__<<": "<<endl);
UINFO(2, __FUNCTION__ << ": " << endl);
// Open stats file
string filename = v3Global.opt.makeDir()+"/"+v3Global.opt.prefix()+"__stats.txt";
std::ofstream* ofp (V3File::new_ofstream(filename));
if (ofp->fail()) v3fatal("Can't write "<<filename);
string filename = v3Global.opt.makeDir() + "/" + v3Global.opt.prefix() + "__stats.txt";
std::ofstream* ofp(V3File::new_ofstream(filename));
if (ofp->fail()) v3fatal("Can't write " << filename);
StatsReport reporter (ofp);
StatsReport reporter(ofp);
// Cleanup
ofp->close();

View File

@ -31,18 +31,14 @@ size_t VName::s_maxLength = 0; // Disabled
// Double procedures, inlined, unrolls loop much better
inline bool VString::wildmatchi(const char* s, const char* p) {
for ( ; *p; s++, p++) {
if (*p!='*') {
if (((*s)!=(*p)) && *p != '?')
return false;
}
else {
for (; *p; s++, p++) {
if (*p != '*') {
if (((*s) != (*p)) && *p != '?') return false;
} else {
// Trailing star matches everything.
if (!*++p) return true;
while (!wildmatch(s, p)) {
if (*++s == '\0') {
return false;
}
if (*++s == '\0') return false;
}
return true;
}
@ -51,18 +47,14 @@ inline bool VString::wildmatchi(const char* s, const char* p) {
}
bool VString::wildmatch(const char* s, const char* p) {
for ( ; *p; s++, p++) {
if (*p!='*') {
if (((*s)!=(*p)) && *p != '?')
return false;
}
else {
for (; *p; s++, p++) {
if (*p != '*') {
if (((*s) != (*p)) && *p != '?') return false;
} else {
// Trailing star matches everything.
if (!*++p) return true;
while (!wildmatchi(s, p)) {
if (*++s == '\0') {
return false;
}
if (*++s == '\0') return false;
}
return true;
}
@ -74,29 +66,25 @@ bool VString::wildmatch(const string& s, const string& p) {
return wildmatch(s.c_str(), p.c_str());
}
bool VString::isWildcard(const string &p) {
bool VString::isWildcard(const string& p) {
return ((p.find('*') != string::npos) || (p.find('?') != string::npos));
}
string VString::dot(const string& a, const string& dot, const string& b) {
if (b=="") return a;
if (a=="") return b;
return a+dot+b;
if (b == "") return a;
if (a == "") return b;
return a + dot + b;
}
string VString::downcase(const string& str) {
string out = str;
for (string::iterator pos = out.begin(); pos != out.end(); ++pos) {
*pos = tolower(*pos);
}
for (string::iterator pos = out.begin(); pos != out.end(); ++pos) *pos = tolower(*pos);
return out;
}
string VString::upcase(const string& str) {
string out = str;
for (string::iterator pos = out.begin(); pos != out.end(); ++pos) {
*pos = toupper(*pos);
}
for (string::iterator pos = out.begin(); pos != out.end(); ++pos) *pos = toupper(*pos);
return out;
}
@ -112,8 +100,11 @@ string VString::quotePercent(const string& str) {
string VString::spaceUnprintable(const string& str) {
string out;
for (string::const_iterator pos = str.begin(); pos != str.end(); ++pos) {
if (isprint(*pos)) out += *pos;
else out += ' ';
if (isprint(*pos)) {
out += *pos;
} else {
out += ' ';
}
}
return out;
}
@ -128,16 +119,17 @@ bool VString::isWhitespace(const string& str) {
//######################################################################
// VHashSha256
static const uint32_t sha256K[] = {
0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
};
static const uint32_t sha256K[]
= {0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4,
0xab1c5ed5, 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe,
0x9bdc06a7, 0xc19bf174, 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f,
0x4a7484aa, 0x5cb0a9dc, 0x76f988da, 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7,
0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc,
0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, 0xa2bfe8a1, 0xa81a664b,
0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, 0x19a4c116,
0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7,
0xc67178f2};
static inline uint32_t shaRotr32(uint32_t lhs, uint32_t rhs) VL_ATTR_ALWINLINE;
static inline uint32_t shaRotr32(uint32_t lhs, uint32_t rhs) {
@ -150,9 +142,7 @@ static inline void sha256Block(uint32_t* h, const uint32_t* chunk) {
const uint32_t* p = chunk;
// Initialize working variables to current hash value
for (unsigned i = 0; i < 8; i++) {
ah[i] = h[i];
}
for (unsigned i = 0; i < 8; i++) ah[i] = h[i];
// Compression function main loop
for (unsigned i = 0; i < 4; ++i) {
uint32_t w[16];
@ -164,17 +154,15 @@ static inline void sha256Block(uint32_t* h, const uint32_t* chunk) {
// Extend the first 16 words into the remaining
// 48 words w[16..63] of the message schedule array:
const uint32_t s0 = shaRotr32(w[(j + 1) & 0xf], 7)
^ shaRotr32(w[(j + 1) & 0xf], 18) ^ (w[(j + 1) & 0xf] >> 3);
^ shaRotr32(w[(j + 1) & 0xf], 18) ^ (w[(j + 1) & 0xf] >> 3);
const uint32_t s1 = shaRotr32(w[(j + 14) & 0xf], 17)
^ shaRotr32(w[(j + 14) & 0xf], 19) ^ (w[(j + 14) & 0xf] >> 10);
^ shaRotr32(w[(j + 14) & 0xf], 19) ^ (w[(j + 14) & 0xf] >> 10);
w[j] = w[j] + s0 + w[(j + 9) & 0xf] + s1;
}
const uint32_t s1 = shaRotr32(ah[4], 6)
^ shaRotr32(ah[4], 11) ^ shaRotr32(ah[4], 25);
const uint32_t s1 = shaRotr32(ah[4], 6) ^ shaRotr32(ah[4], 11) ^ shaRotr32(ah[4], 25);
const uint32_t ch = (ah[4] & ah[5]) ^ (~ah[4] & ah[6]);
const uint32_t temp1 = ah[7] + s1 + ch + sha256K[i << 4 | j] + w[j];
const uint32_t s0 = shaRotr32(ah[0], 2)
^ shaRotr32(ah[0], 13) ^ shaRotr32(ah[0], 22);
const uint32_t s0 = shaRotr32(ah[0], 2) ^ shaRotr32(ah[0], 13) ^ shaRotr32(ah[0], 22);
const uint32_t maj = (ah[0] & ah[1]) ^ (ah[0] & ah[2]) ^ (ah[1] & ah[2]);
const uint32_t temp2 = s0 + maj;
@ -191,7 +179,6 @@ static inline void sha256Block(uint32_t* h, const uint32_t* chunk) {
for (unsigned i = 0; i < 8; ++i) h[i] += ah[i];
}
void VHashSha256::insert(const void* datap, size_t length) {
UASSERT(!m_final, "Called VHashSha256::insert after finalized the hash value");
m_totLength += length;
@ -199,7 +186,7 @@ void VHashSha256::insert(const void* datap, size_t length) {
string tempData;
int chunkLen;
const uint8_t* chunkp;
if (m_remainder=="") {
if (m_remainder == "") {
chunkLen = length;
chunkp = static_cast<const uint8_t*>(datap);
} else {
@ -229,7 +216,7 @@ void VHashSha256::insert(const void* datap, size_t length) {
sha256Block(m_inthash, w);
}
m_remainder = string(reinterpret_cast<const char*>(chunkp+posBegin), chunkLen-posEnd);
m_remainder = string(reinterpret_cast<const char*>(chunkp + posBegin), chunkLen - posEnd);
}
void VHashSha256::finalize() {
@ -240,16 +227,16 @@ void VHashSha256::finalize() {
// Process final possibly non-complete 64-byte block
uint32_t w[16]; // Round buffer, [0..15] are input data
for (int i=0; i<16; ++i) w[i] = 0;
for (int i = 0; i < 16; ++i) w[i] = 0;
size_t blockPos = 0;
for (; blockPos < m_remainder.length(); ++blockPos) {
w[blockPos >> 2] |= ((static_cast<uint32_t>(m_remainder[blockPos]))
<< ((3 - (blockPos & 3)) << 3));
w[blockPos >> 2]
|= ((static_cast<uint32_t>(m_remainder[blockPos])) << ((3 - (blockPos & 3)) << 3));
}
w[blockPos >> 2] |= 0x80 << ((3 - (blockPos & 3)) << 3);
if (m_remainder.length() >= 56) {
sha256Block(m_inthash, w);
for (int i=0; i<16; ++i) w[i] = 0;
for (int i = 0; i < 16; ++i) w[i] = 0;
}
w[15] = m_totLength << 3;
sha256Block(m_inthash, w);
@ -260,8 +247,9 @@ void VHashSha256::finalize() {
string VHashSha256::digestBinary() {
finalize();
string out; out.reserve(32);
for (size_t i=0; i<32; ++i) {
string out;
out.reserve(32);
for (size_t i = 0; i < 32; ++i) {
out += (m_inthash[i >> 2] >> (((3 - i) & 0x3) << 3)) & 0xff;
}
return out;
@ -270,20 +258,21 @@ string VHashSha256::digestBinary() {
uint64_t VHashSha256::digestUInt64() {
const string& binhash = digestBinary();
uint64_t out = 0;
for (size_t byte=0; byte<sizeof(uint64_t); ++byte) {
for (size_t byte = 0; byte < sizeof(uint64_t); ++byte) {
unsigned char c = binhash[byte];
out = (out<<8) | c;
out = (out << 8) | c;
}
return out;
}
string VHashSha256::digestHex() {
static const char digits[16+1] = "0123456789abcdef";
static const char digits[16 + 1] = "0123456789abcdef";
const string& binhash = digestBinary();
string out; out.reserve(70);
for (size_t byte=0; byte<32; ++byte) {
out += digits[ (binhash[byte]>>4) & 0xf ];
out += digits[ (binhash[byte]>>0) & 0xf ];
string out;
out.reserve(70);
for (size_t byte = 0; byte < 32; ++byte) {
out += digits[(binhash[byte] >> 4) & 0xf];
out += digits[(binhash[byte] >> 0) & 0xf];
}
return out;
}
@ -293,12 +282,13 @@ string VHashSha256::digestSymbol() {
// has + and / for last two digits, but need C symbol, and we also
// avoid conflicts with use of _, so use "AB" at the end.
// Thus this function is non-reversible.
static const char digits[64+1]
static const char digits[64 + 1]
= "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB";
const string& binhash = digestBinary();
string out; out.reserve(28);
string out;
out.reserve(28);
int pos = 0;
for (; pos < (256/8) - 2; pos += 3) {
for (; pos < (256 / 8) - 2; pos += 3) {
out += digits[((binhash[pos] >> 2) & 0x3f)];
out += digits[((binhash[pos] & 0x3) << 4)
| (static_cast<int>(binhash[pos + 1] & 0xf0) >> 4)];
@ -310,28 +300,26 @@ string VHashSha256::digestSymbol() {
return out;
}
void VHashSha256::selfTestOne(const string& data, const string& data2,
const string& exp, const string& exp64) {
VHashSha256 digest (data);
if (data2!="") digest.insert(data2);
void VHashSha256::selfTestOne(const string& data, const string& data2, const string& exp,
const string& exp64) {
VHashSha256 digest(data);
if (data2 != "") digest.insert(data2);
if (VL_UNCOVERABLE(digest.digestHex() != exp)) {
std::cerr << "%Error: When hashing '"<<data+data2<<"'"<<endl // LCOV_EXCL_LINE
<< " ... got="<<digest.digestHex()<<endl // LCOV_EXCL_LINE
<< " ... exp="<<exp<<endl; // LCOV_EXCL_LINE
std::cerr << "%Error: When hashing '" << data + data2 << "'" << endl // LCOV_EXCL_LINE
<< " ... got=" << digest.digestHex() << endl // LCOV_EXCL_LINE
<< " ... exp=" << exp << endl; // LCOV_EXCL_LINE
}
if (VL_UNCOVERABLE(digest.digestSymbol() != exp64)) {
std::cerr << "%Error: When hashing '"<<data+data2<<"'"<<endl // LCOV_EXCL_LINE
<< " ... got="<<digest.digestSymbol()<<endl // LCOV_EXCL_LINE
<< " ... exp="<<exp64<<endl; // LCOV_EXCL_LINE
std::cerr << "%Error: When hashing '" << data + data2 << "'" << endl // LCOV_EXCL_LINE
<< " ... got=" << digest.digestSymbol() << endl // LCOV_EXCL_LINE
<< " ... exp=" << exp64 << endl; // LCOV_EXCL_LINE
}
}
void VHashSha256::selfTest() {
selfTestOne("", "",
"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
selfTestOne("", "", "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
"47DEQpj8HBSaABTImWA5JCeuQeRkm5NMpJWZG3hS");
selfTestOne("a", "",
"ca978112ca1bbdcafac231b39a23dc4da786eff8147c4e72b9807785afee48bb",
selfTestOne("a", "", "ca978112ca1bbdcafac231b39a23dc4da786eff8147c4e72b9807785afee48bb",
"ypeBEsobvcr6wjGzmiPcTaeG7BgUfE5yuYB3haBu");
selfTestOne("The quick brown fox jumps over the lazy dog", "",
"d7a8fbb307d7809469ca9abcb0082e4f8d5651e46d3cdb762d02d0bf37c9e592",
@ -351,14 +339,14 @@ void VHashSha256::selfTest() {
// VName
string VName::hashedName() {
if (m_name=="") return "";
if (m_hashed!="") return m_hashed; // Memoized
if (s_maxLength==0 || m_name.length() < s_maxLength) {
if (m_name == "") return "";
if (m_hashed != "") return m_hashed; // Memoized
if (s_maxLength == 0 || m_name.length() < s_maxLength) {
m_hashed = m_name;
return m_hashed;
} else {
VHashSha256 hash(m_name);
string suffix = "__Vhsh"+hash.digestSymbol();
string suffix = "__Vhsh" + hash.digestSymbol();
if (s_minLength < s_maxLength) {
m_hashed = m_name.substr(0, s_minLength) + suffix;
} else {
@ -389,9 +377,9 @@ VSpellCheck::EditDistance VSpellCheck::editDistance(const string& s, const strin
for (size_t i = 0; i < tLen; i++) {
s_v_next[0] = i + 1;
for (size_t j = 0; j < sLen; j++) {
EditDistance cost =(s[j] == t[i] ? 0 : 1);
EditDistance deletion = s_v_next[j] + 1;
EditDistance insertion = s_v_one_ago[j + 1] + 1;
EditDistance cost = (s[j] == t[i] ? 0 : 1);
EditDistance deletion = s_v_next[j] + 1;
EditDistance insertion = s_v_one_ago[j + 1] + 1;
EditDistance substitution = s_v_one_ago[j] + cost;
EditDistance cheapest = std::min(deletion, insertion);
cheapest = std::min(cheapest, substitution);
@ -420,13 +408,11 @@ VSpellCheck::EditDistance VSpellCheck::cutoffDistance(size_t goal_len, size_t ca
return (max_length + 2) / 3;
}
string VSpellCheck::bestCandidateInfo(const string& goal,
EditDistance& distancer) {
string VSpellCheck::bestCandidateInfo(const string& goal, EditDistance& distancer) {
string bestCandidate;
size_t gLen = goal.length();
distancer = LENGTH_LIMIT*10;
for (Candidates::const_iterator it = m_candidates.begin();
it != m_candidates.end(); ++it) {
distancer = LENGTH_LIMIT * 10;
for (Candidates::const_iterator it = m_candidates.begin(); it != m_candidates.end(); ++it) {
const string candidate = *it;
size_t cLen = candidate.length();
@ -438,8 +424,8 @@ string VSpellCheck::bestCandidateInfo(const string& goal,
if (min_distance > cutoff) continue; // Short-circuit if already too bad
EditDistance dist = editDistance(goal, candidate);
UINFO(9, "EditDistance dist="<<dist<<" cutoff="<<cutoff
<<" goal="<<goal<<" candidate="<<candidate<<endl);
UINFO(9, "EditDistance dist=" << dist << " cutoff=" << cutoff << " goal=" << goal
<< " candidate=" << candidate << endl);
if (dist < distancer && dist <= cutoff) {
distancer = dist;
bestCandidate = candidate;
@ -451,8 +437,7 @@ string VSpellCheck::bestCandidateInfo(const string& goal,
return bestCandidate;
}
void VSpellCheck::selfTestDistanceOne(const string& a, const string& b,
EditDistance expected) {
void VSpellCheck::selfTestDistanceOne(const string& a, const string& b, EditDistance expected) {
UASSERT_SELFTEST(EditDistance, editDistance(a, b), expected);
UASSERT_SELFTEST(EditDistance, editDistance(b, a), expected);
}
@ -462,7 +447,7 @@ void VSpellCheck::selfTestSuggestOne(bool matches, const string& c, const string
EditDistance gdist;
VSpellCheck speller;
speller.pushCandidate(c);
string got = speller.bestCandidateInfo(goal, gdist/*ref*/);
string got = speller.bestCandidateInfo(goal, gdist /*ref*/);
if (matches) {
UASSERT_SELFTEST(string, got, c);
UASSERT_SELFTEST(EditDistance, gdist, dist);

View File

@ -30,18 +30,30 @@
// Global string-related functions
template <class T> std::string cvtToStr(const T& t) {
std::ostringstream os; os<<t; return os.str();
std::ostringstream os;
os << t;
return os.str();
}
template <class T> std::string cvtToHex(const T* tp) {
std::ostringstream os; os<<static_cast<const void*>(tp); return os.str();
std::ostringstream os;
os << static_cast<const void*>(tp);
return os.str();
}
inline uint32_t cvtToHash(const void* vp) {
// We can shove a 64 bit pointer into a 32 bit bucket
// On 32-bit systems, lower is always 0, but who cares?
union { const void* up; struct {uint32_t upper; uint32_t lower;} l;} u;
u.l.upper = 0; u.l.lower = 0; u.up = vp;
return u.l.upper^u.l.lower;
union {
const void* up;
struct {
uint32_t upper;
uint32_t lower;
} l;
} u;
u.l.upper = 0;
u.l.lower = 0;
u.up = vp;
return u.l.upper ^ u.l.lower;
}
inline string ucfirst(const string& text) {
@ -55,6 +67,7 @@ inline string ucfirst(const string& text) {
class VString {
static bool wildmatchi(const char* s, const char* p);
public:
// METHODS (generic string utilities)
// Return true if p with ? or *'s matches s
@ -62,7 +75,7 @@ public:
// Return true if p with ? or *'s matches s
static bool wildmatch(const string& s, const string& p);
// Return true if this is a wildcard string (contains * or ?)
static bool isWildcard(const string &p);
static bool isWildcard(const string& p);
// Return {a}{dot}{b}, omitting dot if a or b are empty
static string dot(const string& a, const string& dot, const string& b);
// Convert string to lowercase (tolower)
@ -88,14 +101,17 @@ class VHashSha256 {
// Or improve to store 0-63 bytes of data between calls to input().
// MEMBERS
uint32_t m_inthash[8]; // Intermediate hash, in host order
string m_remainder; // Unhashed data
bool m_final; // Finalized
size_t m_totLength; // Total all-chunk length as needed by output digest
uint32_t m_inthash[8]; // Intermediate hash, in host order
string m_remainder; // Unhashed data
bool m_final; // Finalized
size_t m_totLength; // Total all-chunk length as needed by output digest
public:
// CONSTRUCTORS
VHashSha256() { init(); }
explicit VHashSha256(const string& data) { init(); insert(data); }
explicit VHashSha256(const string& data) {
init();
insert(data);
}
~VHashSha256() {}
// METHODS
@ -107,20 +123,26 @@ public:
// Inerting hash data
void insert(const void* datap, size_t length); // Process data into the digest
void insert(const string& data) { insert(data.data(), data.length()); } // Process data into the digest
void insert(const string& data) {
insert(data.data(), data.length());
} // Process data into the digest
void insert(uint64_t value) { insert(cvtToStr(value)); }
private:
void init() {
m_inthash[0] = 0x6a09e667; m_inthash[1] = 0xbb67ae85;
m_inthash[2] = 0x3c6ef372; m_inthash[3] = 0xa54ff53a;
m_inthash[4] = 0x510e527f; m_inthash[5] = 0x9b05688c;
m_inthash[6] = 0x1f83d9ab; m_inthash[7] = 0x5be0cd19;
m_inthash[0] = 0x6a09e667;
m_inthash[1] = 0xbb67ae85;
m_inthash[2] = 0x3c6ef372;
m_inthash[3] = 0xa54ff53a;
m_inthash[4] = 0x510e527f;
m_inthash[5] = 0x9b05688c;
m_inthash[6] = 0x1f83d9ab;
m_inthash[7] = 0x5be0cd19;
m_final = false;
m_totLength = 0;
}
static void selfTestOne(const string& data, const string& data2,
const string& exp, const string& exp64);
static void selfTestOne(const string& data, const string& data2, const string& exp,
const string& exp64);
void finalize(); // Process remaining data
};
@ -136,10 +158,14 @@ class VName {
static size_t s_minLength; // Length to preserve if over maxLength
public:
// CONSTRUCTORS
explicit VName(const string& name) : m_name(name) {}
explicit VName(const string& name)
: m_name(name) {}
~VName() {}
// METHODS
void name(const string& name) { m_name = name; m_hashed = ""; }
void name(const string& name) {
m_name = name;
m_hashed = "";
}
string name() const { return m_name; }
string hashedName();
// CONFIG STATIC METHODS
@ -173,21 +199,24 @@ public:
// Return candidate is closest to provided string, or "" for none
string bestCandidate(const string& goal) {
EditDistance dist;
return bestCandidateInfo(goal, dist/*ref*/);
return bestCandidateInfo(goal, dist /*ref*/);
}
// Return friendly message
string bestCandidateMsg(const string& goal) {
string candidate = bestCandidate(goal);
if (candidate.empty()) return "";
else return string("... Suggested alternative: '")+candidate+"'";
if (candidate.empty()) {
return "";
} else {
return string("... Suggested alternative: '") + candidate + "'";
}
}
static void selfTest();
private:
static EditDistance editDistance(const string& s, const string& t);
static EditDistance cutoffDistance(size_t goal_len, size_t candidate_len);
string bestCandidateInfo(const string& goal, EditDistance& distancer);
static void selfTestDistanceOne(const string& a, const string& b,
EditDistance expected);
static void selfTestDistanceOne(const string& a, const string& b, EditDistance expected);
static void selfTestSuggestOne(bool matches, const string& c, const string& goal,
EditDistance dist);
};

View File

@ -42,15 +42,15 @@ typedef std::set<const VSymEnt*> VSymConstMap;
class VSymEnt {
// Symbol table that can have a "superior" table for resolving upper references
// MEMBERS
typedef std::multimap<string,VSymEnt*> IdNameMap;
IdNameMap m_idNameMap; // Hash of variables by name
AstNode* m_nodep; // Node that entry belongs to
VSymEnt* m_fallbackp; // Table "above" this one in name scope, for fallback resolution
VSymEnt* m_parentp; // Table that created this table, dot notation needed to resolve into it
typedef std::multimap<string, VSymEnt*> IdNameMap;
IdNameMap m_idNameMap; // Hash of variables by name
AstNode* m_nodep; // Node that entry belongs to
VSymEnt* m_fallbackp; // Table "above" this one in name scope, for fallback resolution
VSymEnt* m_parentp; // Table that created this table, dot notation needed to resolve into it
AstNodeModule* m_packagep; // Package node is in (for V3LinkDot, unused here)
string m_symPrefix; // String to prefix symbols with (for V3LinkDot, unused here)
bool m_exported; // Allow importing
bool m_imported; // Was imported
string m_symPrefix; // String to prefix symbols with (for V3LinkDot, unused here)
bool m_exported; // Allow importing
bool m_imported; // Was imported
#ifdef VL_DEBUG
static int debug() {
static int level = -1;
@ -61,32 +61,33 @@ class VSymEnt {
static inline int debug() { return 0; } // NOT runtime, too hot of a function
#endif
public:
typedef IdNameMap::const_iterator const_iterator;
const_iterator begin() const { return m_idNameMap.begin(); }
const_iterator end() const { return m_idNameMap.end(); }
void dumpIterate(std::ostream& os, VSymConstMap& doneSymsr, const string& indent,
int numLevels, const string& searchName) const {
os<<indent<<"+ "<<std::left<<std::setw(30)
<<(searchName==""?"\"\"":searchName)<<std::setw(0)<<std::right;
os<<" se"<<cvtToHex(this)<<std::setw(0);
os<<" fallb=se"<<cvtToHex(m_fallbackp);
if (m_symPrefix!="") os<<" symPrefix="<<m_symPrefix;
os<<" n="<<nodep();
os<<endl;
os << indent << "+ " << std::left << std::setw(30)
<< (searchName == "" ? "\"\"" : searchName) << std::setw(0) << std::right;
os << " se" << cvtToHex(this) << std::setw(0);
os << " fallb=se" << cvtToHex(m_fallbackp);
if (m_symPrefix != "") os << " symPrefix=" << m_symPrefix;
os << " n=" << nodep();
os << endl;
if (doneSymsr.find(this) != doneSymsr.end()) {
os<<indent<<"| ^ duplicate, so no children printed\n";
os << indent << "| ^ duplicate, so no children printed\n";
} else {
doneSymsr.insert(this);
for (IdNameMap::const_iterator it=m_idNameMap.begin(); it!=m_idNameMap.end(); ++it) {
for (IdNameMap::const_iterator it = m_idNameMap.begin(); it != m_idNameMap.end();
++it) {
if (numLevels >= 1) {
it->second->dumpIterate(os, doneSymsr, indent+"| ", numLevels-1, it->first);
it->second->dumpIterate(os, doneSymsr, indent + "| ", numLevels - 1,
it->first);
}
}
}
}
void dump(std::ostream& os, const string& indent="", int numLevels=1) const {
void dump(std::ostream& os, const string& indent = "", int numLevels = 1) const {
VSymConstMap doneSyms;
dumpIterate(os, doneSyms, indent, numLevels, "TOP");
}
@ -120,12 +121,13 @@ public:
bool imported() const { return m_imported; }
void imported(bool flag) { m_imported = flag; }
void insert(const string& name, VSymEnt* entp) {
UINFO(9, " SymInsert se"<<cvtToHex(this)
<<" '"<<name<<"' se"<<cvtToHex(entp)<<" "<<entp->nodep()<<endl);
UINFO(9, " SymInsert se" << cvtToHex(this) << " '" << name << "' se" << cvtToHex(entp)
<< " " << entp->nodep() << endl);
if (name != "" && m_idNameMap.find(name) != m_idNameMap.end()) {
if (!V3Error::errorCount()) { // Else may have just reported warning
if (debug()>=9 || V3Error::debugDefault()) dump(cout,"- err-dump: ", 1);
entp->nodep()->v3fatalSrc("Inserting two symbols with same name: "<<name<<endl);
if (debug() >= 9 || V3Error::debugDefault()) dump(cout, "- err-dump: ", 1);
entp->nodep()->v3fatalSrc("Inserting two symbols with same name: " << name
<< endl);
}
} else {
m_idNameMap.insert(make_pair(name, entp));
@ -133,9 +135,9 @@ public:
}
void reinsert(const string& name, VSymEnt* entp) {
IdNameMap::iterator it = m_idNameMap.find(name);
if (name!="" && it != m_idNameMap.end()) {
UINFO(9, " SymReinsert se"<<cvtToHex(this)
<<" '"<<name<<"' se"<<cvtToHex(entp)<<" "<<entp->nodep()<<endl);
if (name != "" && it != m_idNameMap.end()) {
UINFO(9, " SymReinsert se" << cvtToHex(this) << " '" << name << "' se"
<< cvtToHex(entp) << " " << entp->nodep() << endl);
it->second = entp; // Replace
} else {
insert(name, entp);
@ -145,9 +147,12 @@ public:
// Find identifier without looking upward through symbol hierarchy
// First, scan this begin/end block or module for the name
IdNameMap::const_iterator it = m_idNameMap.find(name);
UINFO(9, " SymFind se"<<cvtToHex(this)<<" '"<<name
<<"' -> "<<(it == m_idNameMap.end() ? "NONE"
: "se"+cvtToHex(it->second)+" n="+cvtToHex(it->second->nodep()))<<endl);
UINFO(9, " SymFind se"
<< cvtToHex(this) << " '" << name << "' -> "
<< (it == m_idNameMap.end()
? "NONE"
: "se" + cvtToHex(it->second) + " n=" + cvtToHex(it->second->nodep()))
<< endl);
if (it != m_idNameMap.end()) return (it->second);
return NULL;
}
@ -161,8 +166,7 @@ public:
}
void candidateIdFlat(VSpellCheck* spellerp, const VNodeMatcher* matcherp) const {
// Suggest alternative symbol candidates without looking upward through symbol hierarchy
for (IdNameMap::const_iterator it = m_idNameMap.begin();
it != m_idNameMap.end(); ++it) {
for (IdNameMap::const_iterator it = m_idNameMap.begin(); it != m_idNameMap.end(); ++it) {
const AstNode* itemp = it->second->nodep();
if (itemp && (!matcherp || matcherp->nodeMatch(itemp))) {
spellerp->pushCandidate(itemp->prettyName());
@ -176,10 +180,10 @@ public:
// Then suggest the upper begin/end block or module
if (m_fallbackp) m_fallbackp->candidateIdFallback(spellerp, matcherp);
}
private:
void importOneSymbol(VSymGraph* graphp, const string& name, const VSymEnt* srcp) {
if (srcp->exported()
&& !findIdFlat(name)) { // Don't insert over existing entry
if (srcp->exported() && !findIdFlat(name)) { // Don't insert over existing entry
VSymEnt* symp = new VSymEnt(graphp, srcp);
symp->exported(false); // Can't reimport an import without an export
symp->imported(true);
@ -193,14 +197,13 @@ private:
}
}
}
public:
void importFromPackage(VSymGraph* graphp, const VSymEnt* srcp, const string& id_or_star) {
// Import tokens from source symbol table into this symbol table
if (id_or_star != "*") {
IdNameMap::const_iterator it = srcp->m_idNameMap.find(id_or_star);
if (it != srcp->m_idNameMap.end()) {
importOneSymbol(graphp, it->first, it->second);
}
if (it != srcp->m_idNameMap.end()) importOneSymbol(graphp, it->first, it->second);
} else {
for (IdNameMap::const_iterator it = srcp->m_idNameMap.begin();
it != srcp->m_idNameMap.end(); ++it) {
@ -212,9 +215,7 @@ public:
// Export tokens from source symbol table into this symbol table
if (id_or_star != "*") {
IdNameMap::const_iterator it = srcp->m_idNameMap.find(id_or_star);
if (it != srcp->m_idNameMap.end()) {
exportOneSymbol(graphp, it->first, it->second);
}
if (it != srcp->m_idNameMap.end()) exportOneSymbol(graphp, it->first, it->second);
} else {
for (IdNameMap::const_iterator it = srcp->m_idNameMap.begin();
it != srcp->m_idNameMap.end(); ++it) {
@ -224,14 +225,14 @@ public:
}
void exportStarStar(VSymGraph* graphp) {
// Export *:*: Export all tokens from imported packages
for (IdNameMap::const_iterator it=m_idNameMap.begin(); it!=m_idNameMap.end(); ++it) {
for (IdNameMap::const_iterator it = m_idNameMap.begin(); it != m_idNameMap.end(); ++it) {
VSymEnt* symp = it->second;
if (!symp->exported()) symp->exported(true);
}
}
void importFromIface(VSymGraph* graphp, const VSymEnt* srcp, bool onlyUnmodportable = false) {
// Import interface tokens from source symbol table into this symbol table, recursively
UINFO(9, " importIf se"<<cvtToHex(this)<<" from se"<<cvtToHex(srcp)<<endl);
UINFO(9, " importIf se" << cvtToHex(this) << " from se" << cvtToHex(srcp) << endl);
for (IdNameMap::const_iterator it = srcp->m_idNameMap.begin();
it != srcp->m_idNameMap.end(); ++it) {
const string& name = it->first;
@ -245,20 +246,19 @@ public:
}
}
}
void cellErrorScopes(AstNode* lookp, string prettyName="") {
if (prettyName=="") prettyName = lookp->prettyName();
void cellErrorScopes(AstNode* lookp, string prettyName = "") {
if (prettyName == "") prettyName = lookp->prettyName();
string scopes;
for (IdNameMap::iterator it = m_idNameMap.begin(); it!=m_idNameMap.end(); ++it) {
for (IdNameMap::iterator it = m_idNameMap.begin(); it != m_idNameMap.end(); ++it) {
AstNode* itemp = it->second->nodep();
if (VN_IS(itemp, Cell)
|| (VN_IS(itemp, Module) && VN_CAST(itemp, Module)->isTop())) {
if (VN_IS(itemp, Cell) || (VN_IS(itemp, Module) && VN_CAST(itemp, Module)->isTop())) {
if (scopes != "") scopes += ", ";
scopes += AstNode::prettyName(it->first);
}
}
if (scopes=="") scopes="<no cells found>";
std::cerr<<V3Error::warnMore()<<"... Known scopes under '"<<prettyName<<"': "
<<scopes<<endl;
if (scopes == "") scopes = "<no cells found>";
std::cerr << V3Error::warnMore() << "... Known scopes under '" << prettyName
<< "': " << scopes << endl;
if (debug()) dump(std::cerr, " KnownScope: ", 1);
}
};
@ -272,43 +272,43 @@ class VSymGraph {
typedef std::vector<VSymEnt*> SymStack;
// MEMBERS
VSymEnt* m_symRootp; // Root symbol table
SymStack m_symsp; // All symbol tables, to cleanup
VSymEnt* m_symRootp; // Root symbol table
SymStack m_symsp; // All symbol tables, to cleanup
// CONSTRUCTORS
VL_UNCOPYABLE(VSymGraph);
public:
explicit VSymGraph(AstNetlist* nodep) {
m_symRootp = new VSymEnt(this, nodep);
}
explicit VSymGraph(AstNetlist* nodep) { m_symRootp = new VSymEnt(this, nodep); }
~VSymGraph() {
for (SymStack::iterator it = m_symsp.begin(); it != m_symsp.end(); ++it) {
delete (*it);
}
for (SymStack::iterator it = m_symsp.begin(); it != m_symsp.end(); ++it) delete (*it);
}
public:
// METHODS
VSymEnt* rootp() const { return m_symRootp; }
// Debug
void dump(std::ostream& os, const string& indent="") {
void dump(std::ostream& os, const string& indent = "") {
VSymConstMap doneSyms;
os<<"SymEnt Dump:\n";
os << "SymEnt Dump:\n";
m_symRootp->dumpIterate(os, doneSyms, indent, 9999, "$root");
bool first = true;
for (SymStack::iterator it = m_symsp.begin(); it != m_symsp.end(); ++it) {
if (doneSyms.find(*it) == doneSyms.end()) {
if (first) { first=false; os<<"%%Warning: SymEnt Orphans:\n"; }
if (first) {
first = false;
os << "%%Warning: SymEnt Orphans:\n";
}
(*it)->dumpIterate(os, doneSyms, indent, 9999, "Orphan");
}
}
}
void dumpFilePrefixed(const string& nameComment) {
if (v3Global.opt.dumpTree()) {
string filename = v3Global.debugFilename(nameComment)+".txt";
UINFO(2,"Dumping "<<filename<<endl);
const vl_unique_ptr<std::ofstream> logp (V3File::new_ofstream(filename));
if (logp->fail()) v3fatal("Can't write "<<filename);
string filename = v3Global.debugFilename(nameComment) + ".txt";
UINFO(2, "Dumping " << filename << endl);
const vl_unique_ptr<std::ofstream> logp(V3File::new_ofstream(filename));
if (logp->fail()) v3fatal("Can't write " << filename);
dump(*logp, "");
}
}
@ -336,7 +336,7 @@ inline VSymEnt::VSymEnt(VSymGraph* graphp, AstNode* nodep)
inline VSymEnt::VSymEnt(VSymGraph* graphp, const VSymEnt* symp)
: m_nodep(symp->m_nodep) {
m_fallbackp = symp->m_fallbackp;
m_parentp = symp->m_parentp;
m_parentp = symp->m_parentp;
m_packagep = symp->m_packagep;
m_exported = symp->m_exported;
m_imported = symp->m_imported;

View File

@ -24,30 +24,30 @@
#include "V3Error.h"
namespace V3TSP {
// Perform a "Traveling Salesman Problem" optimizing sort
// on any type you like -- so long as inherits from TspStateBase.
// Perform a "Traveling Salesman Problem" optimizing sort
// on any type you like -- so long as inherits from TspStateBase.
class TspStateBase {
public:
// This is the cost function that the TSP sort will minimize.
// All costs in V3TSP are int, chosen to match the type of
// V3GraphEdge::weight() which will reflect each edge's cost.
virtual int cost(const TspStateBase* otherp) const = 0;
class TspStateBase {
public:
// This is the cost function that the TSP sort will minimize.
// All costs in V3TSP are int, chosen to match the type of
// V3GraphEdge::weight() which will reflect each edge's cost.
virtual int cost(const TspStateBase* otherp) const = 0;
// This operator< must place a meaningless, arbitrary, but
// stable order on all TspStateBase's. It's used only to
// key maps so that iteration is stable, without relying
// on pointer values that could lead to nondeterminism.
virtual bool operator<(const TspStateBase& otherp) const = 0;
};
// This operator< must place a meaningless, arbitrary, but
// stable order on all TspStateBase's. It's used only to
// key maps so that iteration is stable, without relying
// on pointer values that could lead to nondeterminism.
virtual bool operator<(const TspStateBase& otherp) const = 0;
};
typedef std::vector<const TspStateBase*> StateVec;
typedef std::vector<const TspStateBase*> StateVec;
// Given an unsorted set of TspState's, sort them to minimize
// the transition cost for walking the sorted list.
void tspSort(const StateVec& states, StateVec* resultp);
// Given an unsorted set of TspState's, sort them to minimize
// the transition cost for walking the sorted list.
void tspSort(const StateVec& states, StateVec* resultp);
void selfTest();
void selfTest();
} // namespace V3TSP
#endif // Guard

View File

@ -27,7 +27,7 @@
//============================================================================
typedef std::pair<AstVar*,AstArg*> V3TaskConnect; // [port, pin-connects-to]
typedef std::pair<AstVar*, AstArg*> V3TaskConnect; // [port, pin-connects-to]
typedef std::vector<V3TaskConnect> V3TaskConnects; // [ [port, pin-connects-to] ... ]
//============================================================================

View File

@ -60,22 +60,24 @@
// Graph vertexes
class TraceActivityVertex : public V3GraphVertex {
AstNode* m_insertp; // Insert before this statement
vlsint32_t m_activityCode;
bool m_activityCodeValid;
bool m_slow; // If always slow, we can use the same code
AstNode* m_insertp; // Insert before this statement
vlsint32_t m_activityCode;
bool m_activityCodeValid;
bool m_slow; // If always slow, we can use the same code
public:
enum { ACTIVITY_NEVER =((1UL<<31) - 1) };
enum { ACTIVITY_ALWAYS=((1UL<<31) - 2) };
enum { ACTIVITY_SLOW=0 };
enum { ACTIVITY_NEVER = ((1UL << 31) - 1) };
enum { ACTIVITY_ALWAYS = ((1UL << 31) - 2) };
enum { ACTIVITY_SLOW = 0 };
TraceActivityVertex(V3Graph* graphp, AstNode* nodep, bool slow)
: V3GraphVertex(graphp), m_insertp(nodep) {
: V3GraphVertex(graphp)
, m_insertp(nodep) {
m_activityCode = 0;
m_activityCodeValid = false;
m_slow = slow;
}
TraceActivityVertex(V3Graph* graphp, vlsint32_t code)
: V3GraphVertex(graphp), m_insertp(NULL) {
: V3GraphVertex(graphp)
, m_insertp(NULL) {
m_activityCode = code;
m_activityCodeValid = true;
m_slow = false;
@ -87,24 +89,33 @@ public:
return m_insertp;
}
virtual string name() const {
if (activityAlways()) return "*ALWAYS*";
else return (string(slow()?"*SLOW* ":""))+insertp()->name();
if (activityAlways()) {
return "*ALWAYS*";
} else {
return (string(slow() ? "*SLOW* " : "")) + insertp()->name();
}
}
virtual string dotColor() const { return slow()?"yellowGreen":"green"; }
virtual string dotColor() const { return slow() ? "yellowGreen" : "green"; }
bool activityCodeValid() const { return m_activityCodeValid; }
vlsint32_t activityCode() const { return m_activityCode; }
bool activityAlways() const { return activityCode()==ACTIVITY_ALWAYS; }
void activityCode(vlsint32_t code) { m_activityCode = code; m_activityCodeValid = true;}
bool activityAlways() const { return activityCode() == ACTIVITY_ALWAYS; }
void activityCode(vlsint32_t code) {
m_activityCode = code;
m_activityCodeValid = true;
}
bool slow() const { return m_slow; }
void slow(bool flag) { if (!flag) m_slow = false; }
void slow(bool flag) {
if (!flag) m_slow = false;
}
};
class TraceCFuncVertex : public V3GraphVertex {
AstCFunc* m_nodep;
public:
TraceCFuncVertex(V3Graph* graphp, AstCFunc* nodep)
: V3GraphVertex(graphp), m_nodep(nodep) {
}
: V3GraphVertex(graphp)
, m_nodep(nodep) {}
virtual ~TraceCFuncVertex() {}
// ACCESSORS
AstCFunc* nodep() const { return m_nodep; }
@ -115,10 +126,14 @@ public:
class TraceTraceVertex : public V3GraphVertex {
AstTraceInc* m_nodep; // TRACEINC this represents
TraceTraceVertex* m_duplicatep; // NULL, or other vertex with the real code() that duplicates this one
// NULL, or other vertex with the real code() that duplicates this one
TraceTraceVertex* m_duplicatep;
public:
TraceTraceVertex(V3Graph* graphp, AstTraceInc* nodep)
: V3GraphVertex(graphp), m_nodep(nodep), m_duplicatep(NULL) {}
: V3GraphVertex(graphp)
, m_nodep(nodep)
, m_duplicatep(NULL) {}
virtual ~TraceTraceVertex() {}
// ACCESSORS
AstTraceInc* nodep() const { return m_nodep; }
@ -127,17 +142,18 @@ public:
virtual FileLine* fileline() const { return nodep()->fileline(); }
TraceTraceVertex* duplicatep() const { return m_duplicatep; }
void duplicatep(TraceTraceVertex* dupp) {
UASSERT_OBJ(!duplicatep(), nodep(),
"Assigning duplicatep() to already duplicated node");
UASSERT_OBJ(!duplicatep(), nodep(), "Assigning duplicatep() to already duplicated node");
m_duplicatep = dupp;
}
};
class TraceVarVertex : public V3GraphVertex {
AstVarScope* m_nodep;
AstVarScope* m_nodep;
public:
TraceVarVertex(V3Graph* graphp, AstVarScope* nodep)
: V3GraphVertex(graphp), m_nodep(nodep) {}
: V3GraphVertex(graphp)
, m_nodep(nodep) {}
virtual ~TraceVarVertex() {}
// ACCESSORS
AstVarScope* nodep() const { return m_nodep; }
@ -160,31 +176,31 @@ private:
// AstVarScope::user1() // V3GraphVertex* for this node
// AstCCall::user2() // bool; walked next list for other ccalls
// Ast*::user3() // TraceActivityVertex* for this node
AstUser1InUse m_inuser1;
AstUser2InUse m_inuser2;
AstUser3InUse m_inuser3;
//AstUser4InUse In V3Hashed
AstUser1InUse m_inuser1;
AstUser2InUse m_inuser2;
AstUser3InUse m_inuser3;
// AstUser4InUse In V3Hashed
// STATE
AstNodeModule* m_topModp; // Module to add variables to
AstScope* m_highScopep; // Scope to add variables to
AstCFunc* m_funcp; // C function adding to graph
AstTraceInc* m_tracep; // Trace function adding to graph
AstCFunc* m_initFuncp; // Trace function we add statements to
AstCFunc* m_fullFuncp; // Trace function we add statements to
AstCFunc* m_fullSubFuncp; // Trace function we add statements to (under full)
int m_fullSubStmts; // Statements under function being built
AstCFunc* m_chgFuncp; // Trace function we add statements to
AstCFunc* m_chgSubFuncp; // Trace function we add statements to (under full)
AstNode* m_chgSubParentp;// Which node has call to m_chgSubFuncp
int m_chgSubStmts; // Statements under function being built
AstVarScope* m_activityVscp; // Activity variable
uint32_t m_activityNumber; // Count of fields in activity variable
uint32_t m_code; // Trace ident code# being assigned
V3Graph m_graph; // Var/CFunc tracking
AstNodeModule* m_topModp; // Module to add variables to
AstScope* m_highScopep; // Scope to add variables to
AstCFunc* m_funcp; // C function adding to graph
AstTraceInc* m_tracep; // Trace function adding to graph
AstCFunc* m_initFuncp; // Trace function we add statements to
AstCFunc* m_fullFuncp; // Trace function we add statements to
AstCFunc* m_fullSubFuncp; // Trace function we add statements to (under full)
int m_fullSubStmts; // Statements under function being built
AstCFunc* m_chgFuncp; // Trace function we add statements to
AstCFunc* m_chgSubFuncp; // Trace function we add statements to (under full)
AstNode* m_chgSubParentp; // Which node has call to m_chgSubFuncp
int m_chgSubStmts; // Statements under function being built
AstVarScope* m_activityVscp; // Activity variable
uint32_t m_activityNumber; // Count of fields in activity variable
uint32_t m_code; // Trace ident code# being assigned
V3Graph m_graph; // Var/CFunc tracking
TraceActivityVertex* m_alwaysVtxp; // "Always trace" vertex
bool m_finding; // Pass one of algorithm?
int m_funcNum; // Function number being built
bool m_finding; // Pass one of algorithm?
int m_funcNum; // Function number being built
VDouble0 m_statChgSigs; // Statistic tracking
VDouble0 m_statUniqSigs; // Statistic tracking
@ -194,11 +210,11 @@ private:
VL_DEBUG_FUNC; // Declare debug()
void detectDuplicates() {
UINFO(9,"Finding duplicates\n");
UINFO(9, "Finding duplicates\n");
// Note uses user4
V3Hashed hashed; // Duplicate code detection
// Hash all of the values the traceIncs need
for (V3GraphVertex* itp = m_graph.verticesBeginp(); itp; itp=itp->verticesNextp()) {
for (V3GraphVertex* itp = m_graph.verticesBeginp(); itp; itp = itp->verticesNextp()) {
if (TraceTraceVertex* vvertexp = dynamic_cast<TraceTraceVertex*>(itp)) {
AstTraceInc* nodep = vvertexp->nodep();
if (nodep->valuep()) {
@ -206,8 +222,8 @@ private:
"Trace duplicate back needs consistency,"
" so we can map duplicates back to TRACEINCs");
hashed.hash(nodep->valuep());
UINFO(8, " Hashed "<<std::hex<<hashed.nodeHash(nodep->valuep())
<<" "<<nodep<<endl);
UINFO(8, " Hashed " << std::hex << hashed.nodeHash(nodep->valuep()) << " "
<< nodep << endl);
// Just keep one node in the map and point all duplicates to this node
if (hashed.findDuplicate(nodep->valuep()) == hashed.end()) {
@ -217,7 +233,7 @@ private:
}
}
// Find if there are any duplicates
for (V3GraphVertex* itp = m_graph.verticesBeginp(); itp; itp=itp->verticesNextp()) {
for (V3GraphVertex* itp = m_graph.verticesBeginp(); itp; itp = itp->verticesNextp()) {
if (TraceTraceVertex* vvertexp = dynamic_cast<TraceTraceVertex*>(itp)) {
AstTraceInc* nodep = vvertexp->nodep();
if (nodep->valuep() && !vvertexp->duplicatep()) {
@ -228,8 +244,8 @@ private:
UASSERT_OBJ(dupincp, nodep, "Trace duplicate of wrong type");
TraceTraceVertex* dupvertexp
= dynamic_cast<TraceTraceVertex*>(dupincp->user1u().toGraphVertex());
UINFO(8," Orig "<<nodep<<endl);
UINFO(8," dup "<<dupincp<<endl);
UINFO(8, " Orig " << nodep << endl);
UINFO(8, " dup " << dupincp << endl);
// Mark the hashed node as the original and our
// iterating node as duplicated
vvertexp->duplicatep(dupvertexp);
@ -242,7 +258,7 @@ private:
void graphSimplify() {
// Remove all variable nodes
for (V3GraphVertex* nextp, *itp = m_graph.verticesBeginp(); itp; itp=nextp) {
for (V3GraphVertex *nextp, *itp = m_graph.verticesBeginp(); itp; itp = nextp) {
nextp = itp->verticesNextp();
if (TraceVarVertex* vvertexp = dynamic_cast<TraceVarVertex*>(itp)) {
vvertexp->rerouteEdges(&m_graph);
@ -253,7 +269,7 @@ private:
// We do this twice, as then we have fewer edges to multiply out in the below expansion.
m_graph.removeRedundantEdges(&V3GraphEdge::followAlwaysTrue);
// Remove all Cfunc nodes
for (V3GraphVertex* nextp, *itp = m_graph.verticesBeginp(); itp; itp=nextp) {
for (V3GraphVertex *nextp, *itp = m_graph.verticesBeginp(); itp; itp = nextp) {
nextp = itp->verticesNextp();
if (TraceCFuncVertex* vvertexp = dynamic_cast<TraceCFuncVertex*>(itp)) {
vvertexp->rerouteEdges(&m_graph);
@ -265,10 +281,10 @@ private:
m_graph.removeRedundantEdges(&V3GraphEdge::followAlwaysTrue);
// If there are any edges from a always, keep only the always
for (V3GraphVertex* itp = m_graph.verticesBeginp(); itp; itp=itp->verticesNextp()) {
for (V3GraphVertex* itp = m_graph.verticesBeginp(); itp; itp = itp->verticesNextp()) {
if (TraceTraceVertex* vvertexp = dynamic_cast<TraceTraceVertex*>(itp)) {
V3GraphEdge* alwaysEdgep = NULL;
for (V3GraphEdge* edgep = vvertexp->inBeginp(); edgep; edgep=edgep->inNextp()) {
for (V3GraphEdge* edgep = vvertexp->inBeginp(); edgep; edgep = edgep->inNextp()) {
TraceActivityVertex* actVtxp
= dynamic_cast<TraceActivityVertex*>(edgep->fromp());
UASSERT_OBJ(actVtxp, vvertexp->nodep(),
@ -279,21 +295,19 @@ private:
}
}
if (alwaysEdgep) {
for (V3GraphEdge* nextp, *edgep = vvertexp->inBeginp(); edgep; edgep=nextp) {
for (V3GraphEdge *nextp, *edgep = vvertexp->inBeginp(); edgep; edgep = nextp) {
nextp = edgep->inNextp();
if (edgep!=alwaysEdgep) edgep->unlinkDelete();
if (edgep != alwaysEdgep) edgep->unlinkDelete();
}
}
}
}
// Activity points with no outputs can be removed
for (V3GraphVertex* nextp, *itp = m_graph.verticesBeginp(); itp; itp=nextp) {
for (V3GraphVertex *nextp, *itp = m_graph.verticesBeginp(); itp; itp = nextp) {
nextp = itp->verticesNextp();
if (TraceActivityVertex* vvertexp = dynamic_cast<TraceActivityVertex*>(itp)) {
if (!vvertexp->outBeginp()) {
vvertexp->unlinkDelete(&m_graph);
}
if (!vvertexp->outBeginp()) { vvertexp->unlinkDelete(&m_graph); }
}
}
}
@ -301,7 +315,7 @@ private:
void assignActivity() {
// Select activity numbers and put into each CFunc vertex
m_activityNumber = 1; // Note 0 indicates "slow"
for (V3GraphVertex* itp = m_graph.verticesBeginp(); itp; itp=itp->verticesNextp()) {
for (V3GraphVertex* itp = m_graph.verticesBeginp(); itp; itp = itp->verticesNextp()) {
if (TraceActivityVertex* vvertexp = dynamic_cast<TraceActivityVertex*>(itp)) {
if (!vvertexp->activityCodeValid()) {
if (vvertexp->slow()) {
@ -328,14 +342,11 @@ private:
= new AstBasicDType(m_chgFuncp->fileline(), VFlagLogicPacked(), 1);
v3Global.rootp()->typeTablep()->addTypesp(newScalarDtp);
AstNodeDType* newArrDtp = new AstUnpackArrayDType(
m_chgFuncp->fileline(),
newScalarDtp,
new AstRange(m_chgFuncp->fileline(),
VNumRange(m_activityNumber-1, 0, false)));
m_chgFuncp->fileline(), newScalarDtp,
new AstRange(m_chgFuncp->fileline(), VNumRange(m_activityNumber - 1, 0, false)));
v3Global.rootp()->typeTablep()->addTypesp(newArrDtp);
newvarp = new AstVar(m_chgFuncp->fileline(),
AstVarType::MODULETEMP,
"__Vm_traceActivity", newArrDtp);
newvarp = new AstVar(m_chgFuncp->fileline(), AstVarType::MODULETEMP,
"__Vm_traceActivity", newArrDtp);
} else {
// For tighter code; round to next word point.
int activityBits = VL_WORDS_I(m_activityNumber) * VL_EDATASIZE;
@ -348,14 +359,14 @@ private:
m_activityVscp = newvscp;
// Insert activity setter
for (V3GraphVertex* itp = m_graph.verticesBeginp(); itp; itp=itp->verticesNextp()) {
for (V3GraphVertex* itp = m_graph.verticesBeginp(); itp; itp = itp->verticesNextp()) {
if (TraceActivityVertex* vvertexp = dynamic_cast<TraceActivityVertex*>(itp)) {
if (!vvertexp->activityAlways()) {
FileLine* fl = vvertexp->insertp()->fileline();
uint32_t acode = vvertexp->activityCode();
vvertexp->insertp()->addNextHere
(new AstAssign(fl, selectActivity(fl, acode, true),
new AstConst(fl, AstConst::LogicTrue())));
vvertexp->insertp()->addNextHere(
new AstAssign(fl, selectActivity(fl, acode, true),
new AstConst(fl, AstConst::LogicTrue())));
}
}
}
@ -363,31 +374,29 @@ private:
AstNode* selectActivity(FileLine* flp, uint32_t acode, bool lvalue) {
if (v3Global.opt.mtasks()) {
return new AstArraySel(
flp, new AstVarRef(flp, m_activityVscp, lvalue), acode);
return new AstArraySel(flp, new AstVarRef(flp, m_activityVscp, lvalue), acode);
} else {
return new AstSel(
flp, new AstVarRef(flp, m_activityVscp, lvalue), acode, 1);
return new AstSel(flp, new AstVarRef(flp, m_activityVscp, lvalue), acode, 1);
}
}
AstCFunc* newCFunc(AstCFuncType type, const string& name, AstCFunc* basep) {
AstCFunc* funcp = new AstCFunc(basep->fileline(), name, basep->scopep());
funcp->slow(basep->slow());
funcp->argTypes(EmitCBaseVisitor::symClassVar()
+", "+v3Global.opt.traceClassBase()+"* vcdp, uint32_t code");
funcp->argTypes(EmitCBaseVisitor::symClassVar() + ", " + v3Global.opt.traceClassBase()
+ "* vcdp, uint32_t code");
funcp->funcType(type);
funcp->symProlog(true);
basep->addNext(funcp);
UINFO(5," Newfunc "<<funcp<<endl);
UINFO(5, " Newfunc " << funcp << endl);
return funcp;
}
AstCFunc* newCFuncSub(AstCFunc* basep, AstNode* callfromp) {
string name = basep->name()+"__"+cvtToStr(++m_funcNum);
string name = basep->name() + "__" + cvtToStr(++m_funcNum);
AstCFunc* funcp = NULL;
if (basep->funcType()==AstCFuncType::TRACE_FULL) {
if (basep->funcType() == AstCFuncType::TRACE_FULL) {
funcp = newCFunc(AstCFuncType::TRACE_FULL_SUB, name, basep);
} else if (basep->funcType()==AstCFuncType::TRACE_CHANGE) {
} else if (basep->funcType() == AstCFuncType::TRACE_CHANGE) {
funcp = newCFunc(AstCFuncType::TRACE_CHANGE_SUB, name, basep);
} else {
basep->v3fatalSrc("Strange base function type");
@ -404,8 +413,7 @@ private:
return funcp;
}
void addToChgSub(AstNode* underp, AstNode* stmtsp) {
if (!m_chgSubFuncp
|| (m_chgSubParentp != underp)
if (!m_chgSubFuncp || (m_chgSubParentp != underp)
|| (m_chgSubStmts && v3Global.opt.outputSplitCTrace()
&& m_chgSubStmts > v3Global.opt.outputSplitCTrace())) {
m_chgSubFuncp = newCFuncSub(m_chgFuncp, underp);
@ -418,26 +426,27 @@ private:
void putTracesIntoTree() {
// Form a sorted list of the traces we are interested in
UINFO(9,"Making trees\n");
UINFO(9, "Making trees\n");
typedef std::set<uint32_t> ActCodeSet; // All activity numbers applying to a given trace
typedef std::multimap<ActCodeSet,TraceTraceVertex*> TraceVec; // For activity set, what traces apply
typedef std::multimap<ActCodeSet, TraceTraceVertex*>
TraceVec; // For activity set, what traces apply
TraceVec traces;
// Form sort structure
// If a trace doesn't have activity, it's constant, and we don't
// need to track changes on it.
for (V3GraphVertex* itp = m_graph.verticesBeginp(); itp; itp=itp->verticesNextp()) {
for (V3GraphVertex* itp = m_graph.verticesBeginp(); itp; itp = itp->verticesNextp()) {
if (TraceTraceVertex* vvertexp = dynamic_cast<TraceTraceVertex*>(itp)) {
ActCodeSet actset;
UINFO(9," Add to sort: "<<vvertexp<<endl);
if (debug()>=9) vvertexp->nodep()->dumpTree(cout, "- trnode: ");
for (V3GraphEdge* edgep = vvertexp->inBeginp(); edgep; edgep=edgep->inNextp()) {
UINFO(9, " Add to sort: " << vvertexp << endl);
if (debug() >= 9) vvertexp->nodep()->dumpTree(cout, "- trnode: ");
for (V3GraphEdge* edgep = vvertexp->inBeginp(); edgep; edgep = edgep->inNextp()) {
TraceActivityVertex* cfvertexp
= dynamic_cast<TraceActivityVertex*>(edgep->fromp());
UASSERT_OBJ(cfvertexp, vvertexp->nodep(),
"Should have been function pointing to this trace");
UINFO(9," Activity: "<<cfvertexp<<endl);
UINFO(9, " Activity: " << cfvertexp << endl);
if (cfvertexp->activityAlways()) {
// If code 0, we always trace; ignore other codes
actset.clear();
@ -464,10 +473,10 @@ private:
// Put TRACEs back into the tree
const ActCodeSet* lastactp = NULL;
AstNode* ifnodep = NULL;
for (TraceVec::iterator it = traces.begin(); it!=traces.end(); ++it) {
for (TraceVec::iterator it = traces.begin(); it != traces.end(); ++it) {
const ActCodeSet& actset = it->first;
TraceTraceVertex* vvertexp = it->second;
UINFO(9," Done sort: "<<vvertexp<<endl);
UINFO(9, " Done sort: " << vvertexp << endl);
bool needChg = true;
if (actset.find(TraceActivityVertex::ACTIVITY_NEVER) != actset.end()) {
// No activity needed; it's a constant value or only set in initial block
@ -476,7 +485,8 @@ private:
AstNode* addp = assignTraceCode(vvertexp, vvertexp->nodep(), needChg);
if (addp) { // Else no activity or duplicate
if (actset.find(TraceActivityVertex::ACTIVITY_NEVER) != actset.end()) {
vvertexp->nodep()->v3fatalSrc("If never, needChg=0 and shouldn't need to add.");
vvertexp->nodep()->v3fatalSrc(
"If never, needChg=0 and shouldn't need to add.");
} else if (actset.find(TraceActivityVertex::ACTIVITY_ALWAYS) != actset.end()) {
// Must always set it; add to base of function
addToChgSub(m_chgFuncp, addp);
@ -487,12 +497,14 @@ private:
// Build a new IF statement
FileLine* fl = addp->fileline();
AstNode* condp = NULL;
for (ActCodeSet::const_iterator csit = actset.begin();
csit != actset.end(); ++csit) {
for (ActCodeSet::const_iterator csit = actset.begin(); csit != actset.end();
++csit) {
uint32_t acode = *csit;
AstNode* selp = selectActivity(fl, acode, false);
if (condp) condp = new AstOr(fl, condp, selp);
else condp = selp;
if (condp)
condp = new AstOr(fl, condp, selp);
else
condp = selp;
}
AstIf* ifp = new AstIf(fl, condp, NULL, NULL);
ifp->branchPred(VBranchPred::BP_UNLIKELY);
@ -517,9 +529,9 @@ private:
m_chgFuncp->addFinalsp(clrp);
}
} else {
AstNode* clrp = new AstAssign(fl, new AstVarRef(fl, m_activityVscp, true),
new AstConst(fl, AstConst::WidthedValue(),
m_activityVscp->width(), 0));
AstNode* clrp = new AstAssign(
fl, new AstVarRef(fl, m_activityVscp, true),
new AstConst(fl, AstConst::WidthedValue(), m_activityVscp->width(), 0));
m_fullFuncp->addFinalsp(clrp->cloneTree(true));
m_chgFuncp->addFinalsp(clrp);
}
@ -539,13 +551,13 @@ private:
// Assign trace code, add to tree, return node for change tree or null
// Look for identical copies
uint32_t codePreassigned = 0;
//if (debug()>=9) nodep->dumpTree(cout, "- assnnode: ");
// if (debug()>=9) nodep->dumpTree(cout, "- assnnode: ");
// Find non-duplicated node; note some nodep's maybe null, as they were deleted below
TraceTraceVertex* dupvertexp = vvertexp;
if (dupvertexp->duplicatep()) {
dupvertexp = dupvertexp->duplicatep();
UINFO(9," dupOf "<<cvtToHex(dupvertexp)<<" "<<cvtToHex(dupvertexp->nodep())
<<" "<<dupvertexp<<endl);
UINFO(9, " dupOf " << cvtToHex(dupvertexp) << " " << cvtToHex(dupvertexp->nodep())
<< " " << dupvertexp << endl);
UASSERT_OBJ(!dupvertexp->duplicatep(), dupvertexp->nodep(),
"Original node was marked as a duplicate");
}
@ -558,9 +570,9 @@ private:
} else {
assignDeclCode(nodep->declp());
}
UINFO(8," Created code="<<nodep->declp()->code()
<<" "<<(codePreassigned?"[PREASS]":"")
<<" "<<(needChg?"[CHG]":"")<<" "<<nodep<<endl);
UINFO(8, " Created code=" << nodep->declp()->code() << " "
<< (codePreassigned ? "[PREASS]" : "") << " "
<< (needChg ? "[CHG]" : "") << " " << nodep << endl);
AstNode* incAddp = NULL;
if (!codePreassigned) {
@ -627,9 +639,9 @@ private:
detectDuplicates();
// Simplify it
if (debug()>=6) m_graph.dumpDotFilePrefixed("trace_pre");
if (debug() >= 6) m_graph.dumpDotFilePrefixed("trace_pre");
graphSimplify();
if (debug()>=6) m_graph.dumpDotFilePrefixed("trace_opt");
if (debug() >= 6) m_graph.dumpDotFilePrefixed("trace_opt");
// Create new TRACEINCs
assignActivity();
@ -646,15 +658,15 @@ private:
iterateChildren(nodep);
}
virtual void visit(AstCCall* nodep) VL_OVERRIDE {
UINFO(8," CCALL "<<nodep<<endl);
UINFO(8, " CCALL " << nodep << endl);
if (!m_finding && !nodep->user2()) {
// See if there are other calls in same statement list;
// If so, all funcs might share the same activity code
TraceActivityVertex* activityVtxp = getActivityVertexp(nodep, nodep->funcp()->slow());
for (AstNode* nextp=nodep; nextp; nextp=nextp->nextp()) {
for (AstNode* nextp = nodep; nextp; nextp = nextp->nextp()) {
if (AstCCall* ccallp = VN_CAST(nextp, CCall)) {
ccallp->user2(true); // Processed
UINFO(8," SubCCALL "<<ccallp<<endl);
UINFO(8, " SubCCALL " << ccallp << endl);
V3GraphVertex* ccallFuncVtxp = getCFuncVertexp(ccallp->funcp());
activityVtxp->slow(ccallp->funcp()->slow());
new V3GraphEdge(&m_graph, activityVtxp, ccallFuncVtxp, 1);
@ -664,7 +676,7 @@ private:
iterateChildren(nodep);
}
virtual void visit(AstCFunc* nodep) VL_OVERRIDE {
UINFO(8," CFUNC "<<nodep<<endl);
UINFO(8, " CFUNC " << nodep << endl);
if (nodep->funcType() == AstCFuncType::TRACE_INIT) {
m_initFuncp = nodep;
} else if (nodep->funcType() == AstCFuncType::TRACE_FULL) {
@ -673,12 +685,13 @@ private:
m_chgFuncp = nodep;
}
V3GraphVertex* funcVtxp = getCFuncVertexp(nodep);
if (!m_finding) { // If public, we need a unique activity code to allow for sets directly in this func
if (nodep->funcPublic() || nodep->dpiExport()
|| nodep == v3Global.rootp()->evalp()) {
if (!m_finding) { // If public, we need a unique activity code to allow for sets directly
// in this func
if (nodep->funcPublic() || nodep->dpiExport() || nodep == v3Global.rootp()->evalp()) {
// Need a non-null place to remember to later add a statement; make one
if (!nodep->stmtsp()) nodep->addStmtsp(
new AstComment(nodep->fileline(), "Tracing activity check", true));
if (!nodep->stmtsp())
nodep->addStmtsp(
new AstComment(nodep->fileline(), "Tracing activity check", true));
V3GraphVertex* activityVtxp = getActivityVertexp(nodep->stmtsp(), nodep->slow());
new V3GraphEdge(&m_graph, activityVtxp, funcVtxp, 1);
}
@ -688,7 +701,7 @@ private:
m_funcp = NULL;
}
virtual void visit(AstTraceInc* nodep) VL_OVERRIDE {
UINFO(8," TRACE "<<nodep<<endl);
UINFO(8, " TRACE " << nodep << endl);
UASSERT_OBJ(!m_finding, nodep, "Traces should have been removed in prev step.");
nodep->unlinkFrBack();
@ -715,8 +728,7 @@ private:
|| nodep->varp()->isSigPublic()) { // Or ones user can change
new V3GraphEdge(&m_graph, m_alwaysVtxp, traceVtxp, 1);
}
}
else if (m_funcp && m_finding && nodep->lvalue()) {
} else if (m_funcp && m_finding && nodep->lvalue()) {
UASSERT_OBJ(nodep->varScopep(), nodep, "No var scope?");
V3GraphVertex* funcVtxp = getCFuncVertexp(m_funcp);
V3GraphVertex* varVtxp = nodep->varScopep()->user1u().toGraphVertex();
@ -762,9 +774,7 @@ public:
// Trace class functions
void V3Trace::traceAll(AstNetlist* nodep) {
UINFO(2,__FUNCTION__<<": "<<endl);
{
TraceVisitor visitor(nodep);
} // Destruct before checking
UINFO(2, __FUNCTION__ << ": " << endl);
{ TraceVisitor visitor(nodep); } // Destruct before checking
V3Global::dumpCheckGlobalTree("trace", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
}

View File

@ -38,20 +38,20 @@ private:
// NODE STATE
// STATE
AstScope* m_scopetopp; // Current top scope
AstCFunc* m_initFuncp; // Trace function being built
AstCFunc* m_initSubFuncp; // Trace function being built (under m_init)
int m_initSubStmts; // Number of statements in function
AstCFunc* m_fullFuncp; // Trace function being built
AstCFunc* m_chgFuncp; // Trace function being built
int m_funcNum; // Function number being built
AstVarScope* m_traVscp; // Signal being trace constructed
AstNode* m_traValuep; // Signal being traced's value to trace in it
string m_traShowname; // Signal being traced's component name
bool m_interface; // Currently tracing an interface
AstScope* m_scopetopp; // Current top scope
AstCFunc* m_initFuncp; // Trace function being built
AstCFunc* m_initSubFuncp; // Trace function being built (under m_init)
int m_initSubStmts; // Number of statements in function
AstCFunc* m_fullFuncp; // Trace function being built
AstCFunc* m_chgFuncp; // Trace function being built
int m_funcNum; // Function number being built
AstVarScope* m_traVscp; // Signal being trace constructed
AstNode* m_traValuep; // Signal being traced's value to trace in it
string m_traShowname; // Signal being traced's component name
bool m_interface; // Currently tracing an interface
VDouble0 m_statSigs; // Statistic tracking
VDouble0 m_statIgnSigs; // Statistic tracking
VDouble0 m_statSigs; // Statistic tracking
VDouble0 m_statIgnSigs; // Statistic tracking
// METHODS
VL_DEBUG_FUNC; // Declare debug()
@ -62,16 +62,12 @@ private:
AstVar* varp = nodep->varp();
if (!varp->isTrace()) {
return "Verilator trace_off";
}
else if (!nodep->isTrace()) {
} else if (!nodep->isTrace()) {
return "Verilator cell trace_off";
}
else if (!v3Global.opt.traceUnderscore()) {
} else if (!v3Global.opt.traceUnderscore()) {
string prettyName = varp->prettyName();
if (!prettyName.empty() && prettyName[0] == '_')
return "Leading underscore";
if (prettyName.find("._") != string::npos)
return "Inlined leading underscore";
if (!prettyName.empty() && prettyName[0] == '_') return "Leading underscore";
if (prettyName.find("._") != string::npos) return "Inlined leading underscore";
}
return NULL;
}
@ -79,14 +75,14 @@ private:
AstCFunc* newCFunc(AstCFuncType type, const string& name, bool slow) {
AstCFunc* funcp = new AstCFunc(m_scopetopp->fileline(), name, m_scopetopp);
funcp->slow(slow);
string argTypes(EmitCBaseVisitor::symClassVar()+", "+v3Global.opt.traceClassBase()
+"* vcdp, uint32_t code");
string argTypes(EmitCBaseVisitor::symClassVar() + ", " + v3Global.opt.traceClassBase()
+ "* vcdp, uint32_t code");
if (m_interface) argTypes += ", const char* scopep";
funcp->argTypes(argTypes);
funcp->funcType(type);
funcp->symProlog(true);
m_scopetopp->addActivep(funcp);
UINFO(5," Newfunc "<<funcp<<endl);
UINFO(5, " Newfunc " << funcp << endl);
return funcp;
}
void callCFuncSub(AstCFunc* basep, AstCFunc* funcp, AstIntfRef* irp) {
@ -96,10 +92,10 @@ private:
basep->addStmtsp(callp);
}
AstCFunc* newCFuncSub(AstCFunc* basep) {
string name = basep->name()+"__"+cvtToStr(++m_funcNum);
string name = basep->name() + "__" + cvtToStr(++m_funcNum);
AstCFunc* funcp = NULL;
if (basep->funcType()==AstCFuncType::TRACE_INIT
|| basep->funcType()==AstCFuncType::TRACE_INIT_SUB) {
if (basep->funcType() == AstCFuncType::TRACE_INIT
|| basep->funcType() == AstCFuncType::TRACE_INIT_SUB) {
funcp = newCFunc(AstCFuncType::TRACE_INIT_SUB, name, basep->slow());
} else {
basep->v3fatalSrc("Strange base function type");
@ -108,15 +104,19 @@ private:
return funcp;
}
void addTraceDecl(const VNumRange& arrayRange,
int widthOverride) { // If !=0, is packed struct/array where basicp size misreflects one element
int widthOverride) { // If !=0, is packed struct/array where basicp size
// misreflects one element
VNumRange bitRange;
AstBasicDType* bdtypep = m_traValuep->dtypep()->basicp();
if (widthOverride) bitRange = VNumRange(widthOverride-1, 0, false);
else if (bdtypep) bitRange = bdtypep->nrange();
AstTraceDecl* declp = new AstTraceDecl(m_traVscp->fileline(), m_traShowname,
m_traVscp->varp(), m_traValuep,
bitRange, arrayRange, m_interface);
UINFO(9,"Decl "<<declp<<endl);
if (widthOverride) {
bitRange = VNumRange(widthOverride - 1, 0, false);
} else if (bdtypep) {
bitRange = bdtypep->nrange();
}
AstTraceDecl* declp
= new AstTraceDecl(m_traVscp->fileline(), m_traShowname, m_traVscp->varp(),
m_traValuep, bitRange, arrayRange, m_interface);
UINFO(9, "Decl " << declp << endl);
if (!m_interface && v3Global.opt.outputSplitCTrace()
&& m_initSubStmts > v3Global.opt.outputSplitCTrace()) {
@ -127,15 +127,14 @@ private:
m_initSubFuncp->addStmtsp(declp);
m_initSubStmts += EmitCBaseCounterVisitor(declp).count();
m_chgFuncp->addStmtsp(new AstTraceInc(m_traVscp->fileline(),
declp, m_traValuep->cloneTree(true)));
m_chgFuncp->addStmtsp(
new AstTraceInc(m_traVscp->fileline(), declp, m_traValuep->cloneTree(true)));
// The full version will get constructed in V3Trace
}
void addIgnore(const char* why) {
++m_statIgnSigs;
m_initSubFuncp->addStmtsp(
new AstComment(m_traVscp->fileline(),
"Tracing: "+m_traShowname+" // Ignored: "+why, true));
m_initSubFuncp->addStmtsp(new AstComment(
m_traVscp->fileline(), "Tracing: " + m_traShowname + " // Ignored: " + why, true));
}
// VISITORS
@ -144,7 +143,7 @@ private:
// Make containers for TRACEDECLs first
m_initFuncp = newCFunc(AstCFuncType::TRACE_INIT, "traceInitThis", true);
m_fullFuncp = newCFunc(AstCFuncType::TRACE_FULL, "traceFullThis", true);
m_chgFuncp = newCFunc(AstCFuncType::TRACE_CHANGE, "traceChgThis", false);
m_chgFuncp = newCFunc(AstCFuncType::TRACE_CHANGE, "traceChgThis", false);
//
m_initSubFuncp = newCFuncSub(m_initFuncp);
// And find variables
@ -162,7 +161,7 @@ private:
size_t lastDot = scopeName.find_last_of('.');
UASSERT_OBJ(lastDot != string::npos, nodep,
"Expected an interface scope name to have at least one dot");
scopeName = scopeName.substr(0, lastDot+1);
scopeName = scopeName.substr(0, lastDot + 1);
size_t scopeLen = scopeName.length();
AstIntfRef* nextIrp = cellp->intfRefp();
@ -195,9 +194,8 @@ private:
// Generally this equation doesn't need updating, instead use
// varp->isTrace() and/or vscIgnoreTrace.
if ((!nodep->varp()->isTemp() || nodep->varp()->isTrace())
&& !nodep->varp()->isClassMember()
&& !nodep->varp()->isFuncLocal()) {
UINFO(5, " vsc "<<nodep<<endl);
&& !nodep->varp()->isClassMember() && !nodep->varp()->isFuncLocal()) {
UINFO(5, " vsc " << nodep << endl);
AstVar* varp = nodep->varp();
AstScope* scopep = nodep->scopep();
// Compute show name
@ -217,8 +215,11 @@ private:
addIgnore(vscIgnoreTrace(nodep));
} else {
++m_statSigs;
if (nodep->valuep()) m_traValuep = nodep->valuep()->cloneTree(true);
else m_traValuep = new AstVarRef(nodep->fileline(), nodep, false);
if (nodep->valuep()) {
m_traValuep = nodep->valuep()->cloneTree(true);
} else {
m_traValuep = new AstVarRef(nodep->fileline(), nodep, false);
}
{
// Recurse into data type of the signal; the visitors will call addTraceDecl()
iterate(varp->dtypep()->skipRefToEnump());
@ -233,22 +234,20 @@ private:
}
// VISITORS - Data types when tracing
virtual void visit(AstConstDType* nodep) VL_OVERRIDE {
if (m_traVscp) {
iterate(nodep->subDTypep()->skipRefToEnump());
}
if (m_traVscp) iterate(nodep->subDTypep()->skipRefToEnump());
}
virtual void visit(AstRefDType* nodep) VL_OVERRIDE {
if (m_traVscp) {
iterate(nodep->subDTypep()->skipRefToEnump());
}
if (m_traVscp) iterate(nodep->subDTypep()->skipRefToEnump());
}
virtual void visit(AstUnpackArrayDType* nodep) VL_OVERRIDE {
// Note more specific dtypes above
if (m_traVscp) {
if (static_cast<int>(nodep->arrayUnpackedElements()) > v3Global.opt.traceMaxArray()) {
addIgnore("Wide memory > --trace-max-array ents");
} else if (VN_IS(nodep->subDTypep()->skipRefToEnump(), BasicDType) // Nothing lower than this array
&& m_traVscp->dtypep()->skipRefToEnump() == nodep) { // Nothing above this array
} else if (VN_IS(nodep->subDTypep()->skipRefToEnump(),
BasicDType) // Nothing lower than this array
&& m_traVscp->dtypep()->skipRefToEnump()
== nodep) { // Nothing above this array
// Simple 1-D array, use existing V3EmitC runtime loop rather than unrolling
// This will put "(index)" at end of signal name for us
if (m_traVscp->dtypep()->skipRefToEnump()->isString()) {
@ -259,14 +258,13 @@ private:
} else {
// Unroll now, as have no other method to get right signal names
AstNodeDType* subtypep = nodep->subDTypep()->skipRefToEnump();
for (int i=nodep->lsb(); i<=nodep->msb(); ++i) {
for (int i = nodep->lsb(); i <= nodep->msb(); ++i) {
string oldShowname = m_traShowname;
AstNode* oldValuep = m_traValuep;
{
m_traShowname += string("(")+cvtToStr(i)+string(")");
m_traValuep = new AstArraySel(nodep->fileline(),
m_traValuep->cloneTree(true),
i - nodep->lsb());
m_traShowname += string("(") + cvtToStr(i) + string(")");
m_traValuep = new AstArraySel(
nodep->fileline(), m_traValuep->cloneTree(true), i - nodep->lsb());
m_traValuep->dtypep(subtypep);
iterate(subtypep);
@ -287,13 +285,13 @@ private:
addTraceDecl(VNumRange(), nodep->width());
} else {
AstNodeDType* subtypep = nodep->subDTypep()->skipRefToEnump();
for (int i=nodep->lsb(); i<=nodep->msb(); ++i) {
for (int i = nodep->lsb(); i <= nodep->msb(); ++i) {
string oldShowname = m_traShowname;
AstNode* oldValuep = m_traValuep;
{
m_traShowname += string("(")+cvtToStr(i)+string(")");
m_traShowname += string("(") + cvtToStr(i) + string(")");
m_traValuep = new AstSel(nodep->fileline(), m_traValuep->cloneTree(true),
(i - nodep->lsb())*subtypep->width(),
(i - nodep->lsb()) * subtypep->width(),
subtypep->width());
m_traValuep->dtypep(subtypep);
iterate(subtypep);
@ -316,17 +314,17 @@ private:
if (!nodep->packed()) {
addIgnore("Unsupported: Unpacked struct/union");
} else {
for (AstMemberDType* itemp = nodep->membersp();
itemp; itemp=VN_CAST(itemp->nextp(), MemberDType)) {
for (AstMemberDType* itemp = nodep->membersp(); itemp;
itemp = VN_CAST(itemp->nextp(), MemberDType)) {
AstNodeDType* subtypep = itemp->subDTypep()->skipRefToEnump();
string oldShowname = m_traShowname;
AstNode* oldValuep = m_traValuep;
{
m_traShowname += string(" ")+itemp->prettyName();
m_traShowname += string(" ") + itemp->prettyName();
if (VN_IS(nodep, StructDType)) {
m_traValuep = new AstSel(nodep->fileline(),
m_traValuep->cloneTree(true),
itemp->lsb(), subtypep->width());
m_traValuep
= new AstSel(nodep->fileline(), m_traValuep->cloneTree(true),
itemp->lsb(), subtypep->width());
m_traValuep->dtypep(subtypep);
iterate(subtypep);
VL_DO_CLEAR(m_traValuep->deleteTree(), m_traValuep = NULL);
@ -350,9 +348,7 @@ private:
}
}
}
virtual void visit(AstEnumDType* nodep) VL_OVERRIDE {
iterate(nodep->skipRefp());
}
virtual void visit(AstEnumDType* nodep) VL_OVERRIDE { iterate(nodep->skipRefp()); }
virtual void visit(AstNodeDType* nodep) VL_OVERRIDE {
// Note more specific dtypes above
if (!m_traVscp) return;
@ -387,9 +383,7 @@ public:
// Trace class functions
void V3TraceDecl::traceDeclAll(AstNetlist* nodep) {
UINFO(2,__FUNCTION__<<": "<<endl);
{
TraceDeclVisitor visitor (nodep);
} // Destruct before checking
UINFO(2, __FUNCTION__ << ": " << endl);
{ TraceDeclVisitor visitor(nodep); } // Destruct before checking
V3Global::dumpCheckGlobalTree("tracedecl", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
}

View File

@ -23,9 +23,11 @@
#include "V3Error.h"
#include "V3Ast.h"
// clang-format off
#ifndef _V3WIDTH_CPP_
# error "V3WidthCommit for V3Width internal use only"
#endif
// clang-format on
//######################################################################
@ -55,9 +57,7 @@ public:
// CONSTRUCTORS
WidthRemoveVisitor() {}
virtual ~WidthRemoveVisitor() {}
AstNode* mainAcceptEdit(AstNode* nodep) {
return iterateSubtreeReturnEdits(nodep);
}
AstNode* mainAcceptEdit(AstNode* nodep) { return iterateSubtreeReturnEdits(nodep); }
};
//######################################################################
@ -67,15 +67,14 @@ public:
class WidthCommitVisitor : public AstNVisitor {
// NODE STATE
// AstVar::user1p -> bool, processed
AstUser1InUse m_inuser1;
AstUser1InUse m_inuser1;
public:
// METHODS
static AstConst* newIfConstCommitSize(AstConst* nodep) {
if (((nodep->dtypep()->width() != nodep->num().width())
|| !nodep->num().sized())
if (((nodep->dtypep()->width() != nodep->num().width()) || !nodep->num().sized())
&& !nodep->num().isString()) { // Need to force the number from unsized to sized
V3Number num (nodep, nodep->dtypep()->width());
V3Number num(nodep, nodep->dtypep()->width());
num.opAssign(nodep->num());
num.isSigned(nodep->isSigned());
AstConst* newp = new AstConst(nodep->fileline(), num);
@ -102,9 +101,12 @@ private:
// Look for duplicate
if (AstBasicDType* bdtypep = VN_CAST(nodep, BasicDType)) {
AstBasicDType* newp = nodep->findInsertSameDType(bdtypep);
if (newp != bdtypep && debug()>=9) {
UINFO(9,"dtype replacement "); nodep->dumpSmall(cout);
cout<<" ----> "; newp->dumpSmall(cout); cout<<endl;
if (newp != bdtypep && debug() >= 9) {
UINFO(9, "dtype replacement ");
nodep->dumpSmall(cout);
cout << " ----> ";
newp->dumpSmall(cout);
cout << endl;
}
return newp;
}
@ -116,16 +118,15 @@ private:
iterate(nodep->dtypep()); // Do datatype first
if (AstConst* newp = newIfConstCommitSize(nodep)) {
nodep->replaceWith(newp);
AstNode* oldp = nodep; nodep = newp;
//if (debug()>4) oldp->dumpTree(cout, " fixConstSize_old: ");
//if (debug()>4) newp->dumpTree(cout, " _new: ");
AstNode* oldp = nodep;
nodep = newp;
// if (debug()>4) oldp->dumpTree(cout, " fixConstSize_old: ");
// if (debug()>4) newp->dumpTree(cout, " _new: ");
VL_DO_DANGLING(pushDeletep(oldp), oldp);
}
editDType(nodep);
}
virtual void visit(AstNodeDType* nodep) VL_OVERRIDE {
visitIterateNodeDType(nodep);
}
virtual void visit(AstNodeDType* nodep) VL_OVERRIDE { visitIterateNodeDType(nodep); }
virtual void visit(AstNodeUOrStructDType* nodep) VL_OVERRIDE {
if (nodep->user1SetOnce()) return; // Process once
visitIterateNodeDType(nodep);
@ -158,6 +159,7 @@ private:
iterateChildren(nodep);
editDType(nodep);
}
public:
// CONSTRUCTORS
explicit WidthCommitVisitor(AstNetlist* nodep) {

View File

@ -47,9 +47,7 @@ private:
v3fatal("Out of memory increasing buckets");
}
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:

View File

@ -14,14 +14,16 @@
//
//*************************************************************************
// Cheat for speed and compile .cpp files into one object
// clang-format off
#include "config_build.h"
#ifndef HAVE_CONFIG_BUILD
# error "Something failed during ./configure as config_build.h is incomplete. Perhaps you used autoreconf, don't."
#endif
// clang-format on
#include "verilatedos.h"
// Cheat for speed and compile .cpp files into one object
#define _V3ERROR_NO_GLOBAL_ 1
#include "V3Error.cpp"
#include "V3String.cpp"

View File

@ -34,6 +34,7 @@ typedef std::set<string> VlStringSet;
class VlcOptions {
// MEMBERS (general options)
// clang-format off
string m_annotateOut; // main switch: --annotate I<output_directory>
bool m_annotateAll; // main switch: --annotate-all
int m_annotateMin; // main switch: --annotate-min I<count>
@ -41,6 +42,7 @@ class VlcOptions {
bool m_rank; // main switch: --rank
bool m_unlink; // main switch: --unlink
string m_writeFile; // main switch: --write
// clang-format on
private:
// METHODS

View File

@ -67,8 +67,7 @@ public:
const string namestr = name();
for (const char* cp = namestr.c_str(); *cp; ++cp) {
if (*cp == '\001') {
if (0 == strncmp(cp + 1, shortKey, shortLen)
&& cp[shortLen + 1] == '\002') {
if (0 == strncmp(cp + 1, shortKey, shortLen) && cp[shortLen + 1] == '\002') {
cp += shortLen + 2; // Skip \001+short+\002
const char* ep = cp;
while (*ep && *ep != '\001') ++ep;
@ -110,7 +109,8 @@ public:
public:
// CONSTRUCTORS
VlcPoints() : m_numPoints(0) {}
VlcPoints()
: m_numPoints(0) {}
~VlcPoints() {}
// METHODS

View File

@ -89,9 +89,7 @@ public:
// METHODS
void incCount(int lineno, int column, vluint64_t count, bool ok) {
LinenoMap::iterator lit = m_lines.find(lineno);
if (lit == m_lines.end()) {
lit = m_lines.insert(make_pair(lineno, ColumnMap())).first;
}
if (lit == m_lines.end()) lit = m_lines.insert(make_pair(lineno, ColumnMap())).first;
ColumnMap& cmap = lit->second;
ColumnMap::iterator cit = cmap.find(column);
if (cit == cmap.end()) {

View File

@ -126,9 +126,7 @@ public:
return testp;
}
void clearUser() {
for (ByName::iterator it = m_tests.begin(); it != m_tests.end(); ++it) {
(*it)->user(0);
}
for (ByName::iterator it = m_tests.begin(); it != m_tests.end(); ++it) (*it)->user(0);
}
};

View File

@ -114,7 +114,10 @@ void VlcTop::rank() {
// then hierarchically solve a small subset of tests, and take resulting
// solution and move up to larger subset of tests. (Aka quick sort.)
while (true) {
if (debug()) { UINFO(9, "Left on iter" << nextrank << ": "); remaining.dump(); }
if (debug()) {
UINFO(9, "Left on iter" << nextrank << ": ");
remaining.dump();
}
VlcTest* bestTestp = NULL;
vluint64_t bestRemain = 0;
for (std::vector<VlcTest*>::iterator it = bytime.begin(); it != bytime.end(); ++it) {
@ -151,7 +154,8 @@ void VlcTop::annotateCalc() {
string threshStr = point.thresh();
unsigned thresh = (!threshStr.empty()) ? atoi(threshStr.c_str()) : opt.annotateMin();
bool ok = (point.count() >= thresh);
UINFO(9, "AnnoCalc count " << filename << " " << lineno << " " << point.count() << endl);
UINFO(9,
"AnnoCalc count " << filename << " " << lineno << " " << point.count() << endl);
source.incCount(lineno, column, point.count(), ok);
}
}

View File

@ -37,6 +37,7 @@
// If set to "", this default is ignored and the user is expected
// to set them at Verilator runtime.
// clang-format off
#ifndef DEFENV_SYSTEMC
# define DEFENV_SYSTEMC ""
#endif
@ -52,6 +53,7 @@
#ifndef DEFENV_VERILATOR_ROOT
# define DEFENV_VERILATOR_ROOT ""
#endif
// clang-format on
//**********************************************************************
//**** Compile options