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

@ -17,9 +17,7 @@
#endif #endif
vluint64_t main_time = 0; vluint64_t main_time = 0;
double sc_time_stamp() { double sc_time_stamp() { return main_time; }
return main_time;
}
int main(int argc, char** argv, char** env) { int main(int argc, char** argv, char** env) {
if (0 && argc && argv && env) {} if (0 && argc && argv && env) {}
@ -62,11 +60,15 @@ int main(int argc, char** argv, char** env) {
// Close trace if opened // Close trace if opened
#if VM_TRACE #if VM_TRACE
if (tfp) { tfp->close(); tfp = NULL; } if (tfp) {
tfp->close();
tfp = NULL;
}
#endif #endif
// Destroy model // Destroy model
delete top; top = NULL; delete top;
top = NULL;
// Fin // Fin
exit(0); exit(0);

View File

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

View File

@ -118,8 +118,7 @@ int sc_main(int argc, char* argv[]) {
#endif #endif
// Apply inputs // Apply inputs
if (sc_time_stamp() > sc_time(1, SC_NS) if (sc_time_stamp() > sc_time(1, SC_NS) && sc_time_stamp() < sc_time(10, SC_NS)) {
&& sc_time_stamp() < sc_time(10, SC_NS)) {
reset_l = !1; // Assert reset reset_l = !1; // Assert reset
} else { } else {
reset_l = !0; // Deassert reset reset_l = !0; // Deassert reset
@ -138,7 +137,10 @@ int sc_main(int argc, char* argv[]) {
// Close trace if opened // Close trace if opened
#if VM_TRACE #if VM_TRACE
if (tfp) { tfp->close(); tfp = NULL; } if (tfp) {
tfp->close();
tfp = NULL;
}
#endif #endif
// Coverage analysis (since test passed) // Coverage analysis (since test passed)
@ -148,7 +150,8 @@ int sc_main(int argc, char* argv[]) {
#endif #endif
// Destroy model // Destroy model
delete top; top = NULL; delete top;
top = NULL;
// Fin // Fin
return 0; return 0;

View File

@ -31,9 +31,11 @@
#include <cerrno> #include <cerrno>
#include <sys/stat.h> // mkdir #include <sys/stat.h> // mkdir
// clang-format off
#if defined(_WIN32) || defined(__MINGW32__) #if defined(_WIN32) || defined(__MINGW32__)
# include <direct.h> // mkdir # include <direct.h> // mkdir
#endif #endif
// clang-format on
#define VL_VALUE_STRING_MAX_WIDTH 8192 ///< Max static char array for VL_VALUE_STRING #define VL_VALUE_STRING_MAX_WIDTH 8192 ///< Max static char array for VL_VALUE_STRING
@ -114,7 +116,8 @@ void vl_stop_maybe(const char* filename, int linenum, const char* hier, bool may
Verilated::errorCountInc(); Verilated::errorCountInc();
if (maybe && Verilated::errorCount() < Verilated::errorLimit()) { if (maybe && Verilated::errorCount() < Verilated::errorLimit()) {
VL_PRINTF( // Not VL_PRINTF_MT, already on main thread VL_PRINTF( // Not VL_PRINTF_MT, already on main thread
"-Info: %s:%d: %s\n", filename, linenum, "Verilog $stop, ignored due to +verilator+error+limit"); "-Info: %s:%d: %s\n", filename, linenum,
"Verilog $stop, ignored due to +verilator+error+limit");
} else { } else {
vl_stop(filename, linenum, hier); vl_stop(filename, linenum, hier);
} }
@ -126,7 +129,7 @@ void vl_stop_maybe(const char* filename, int linenum, const char* hier, bool may
void VL_FINISH_MT(const char* filename, int linenum, const char* hier) VL_MT_SAFE { void VL_FINISH_MT(const char* filename, int linenum, const char* hier) VL_MT_SAFE {
#ifdef VL_THREADED #ifdef VL_THREADED
VerilatedThreadMsgQueue::post(VerilatedMsg([=](){ VerilatedThreadMsgQueue::post(VerilatedMsg([=]() { //
vl_finish(filename, linenum, hier); vl_finish(filename, linenum, hier);
})); }));
#else #else
@ -136,7 +139,7 @@ void VL_FINISH_MT(const char* filename, int linenum, const char* hier) VL_MT_SAF
void VL_STOP_MT(const char* filename, int linenum, const char* hier, bool maybe) VL_MT_SAFE { void VL_STOP_MT(const char* filename, int linenum, const char* hier, bool maybe) VL_MT_SAFE {
#ifdef VL_THREADED #ifdef VL_THREADED
VerilatedThreadMsgQueue::post(VerilatedMsg([=](){ VerilatedThreadMsgQueue::post(VerilatedMsg([=]() { //
vl_stop_maybe(filename, linenum, hier, maybe); vl_stop_maybe(filename, linenum, hier, maybe);
})); }));
#else #else
@ -146,7 +149,7 @@ void VL_STOP_MT(const char* filename, int linenum, const char* hier, bool maybe)
void VL_FATAL_MT(const char* filename, int linenum, const char* hier, const char* msg) VL_MT_SAFE { void VL_FATAL_MT(const char* filename, int linenum, const char* hier, const char* msg) VL_MT_SAFE {
#ifdef VL_THREADED #ifdef VL_THREADED
VerilatedThreadMsgQueue::post(VerilatedMsg([=](){ VerilatedThreadMsgQueue::post(VerilatedMsg([=]() { //
vl_fatal(filename, linenum, hier, msg); vl_fatal(filename, linenum, hier, msg);
})); }));
#else #else
@ -163,9 +166,7 @@ std::string _vl_string_vprintf(const char* formatp, va_list ap) VL_MT_SAFE {
va_copy(aq, ap); va_copy(aq, ap);
int len = VL_VSNPRINTF(NULL, 0, formatp, aq); int len = VL_VSNPRINTF(NULL, 0, formatp, aq);
va_end(aq); va_end(aq);
if (VL_UNLIKELY(len < 1)) { if (VL_UNLIKELY(len < 1)) return "";
return "";
}
char* bufp = new char[len + 1]; char* bufp = new char[len + 1];
VL_VSNPRINTF(bufp, len + 1, formatp, ap); VL_VSNPRINTF(bufp, len + 1, formatp, ap);
@ -203,7 +204,8 @@ void VL_DBG_MSGF(const char* formatp, ...) VL_MT_SAFE {
va_start(ap, formatp); va_start(ap, formatp);
std::string out = _vl_string_vprintf(formatp, ap); std::string out = _vl_string_vprintf(formatp, ap);
va_end(ap); va_end(ap);
// printf("-imm-V{t%d,%" VL_PRI64 "d}%s", VL_THREAD_ID(), _vl_dbg_sequence_number(), out.c_str()); // printf("-imm-V{t%d,%" VL_PRI64 "d}%s", VL_THREAD_ID(), _vl_dbg_sequence_number(),
// out.c_str());
// Using VL_PRINTF not VL_PRINTF_MT so that we can call VL_DBG_MSGF // Using VL_PRINTF not VL_PRINTF_MT so that we can call VL_DBG_MSGF
// from within the guts of the thread execution machinery (and it goes // from within the guts of the thread execution machinery (and it goes
@ -217,7 +219,7 @@ void VL_PRINTF_MT(const char* formatp, ...) VL_MT_SAFE {
va_start(ap, formatp); va_start(ap, formatp);
std::string out = _vl_string_vprintf(formatp, ap); std::string out = _vl_string_vprintf(formatp, ap);
va_end(ap); va_end(ap);
VerilatedThreadMsgQueue::post(VerilatedMsg([=](){ VerilatedThreadMsgQueue::post(VerilatedMsg([=]() { //
VL_PRINTF("%s", out.c_str()); VL_PRINTF("%s", out.c_str());
})); }));
} }
@ -292,18 +294,13 @@ vluint64_t vl_rand64() VL_MT_SAFE {
// Xoroshiro128+ algorithm // Xoroshiro128+ algorithm
vluint64_t result = t_state[0] + t_state[1]; vluint64_t result = t_state[0] + t_state[1];
t_state[1] ^= t_state[0]; t_state[1] ^= t_state[0];
t_state[0] = (((t_state[0] << 55) | (t_state[0] >> 9)) t_state[0] = (((t_state[0] << 55) | (t_state[0] >> 9)) ^ t_state[1] ^ (t_state[1] << 14));
^ t_state[1] ^ (t_state[1] << 14));
t_state[1] = (t_state[1] << 36) | (t_state[1] >> 28); t_state[1] = (t_state[1] << 36) | (t_state[1] >> 28);
return result; return result;
} }
IData VL_RANDOM_I(int obits) VL_MT_SAFE { IData VL_RANDOM_I(int obits) VL_MT_SAFE { return vl_rand64() & VL_MASK_I(obits); }
return vl_rand64() & VL_MASK_I(obits); QData VL_RANDOM_Q(int obits) VL_MT_SAFE { return vl_rand64() & VL_MASK_Q(obits); }
}
QData VL_RANDOM_Q(int obits) VL_MT_SAFE {
return vl_rand64() & VL_MASK_Q(obits);
}
// VL_RANDOM_W currently unused as $random always 32 bits // VL_RANDOM_W currently unused as $random always 32 bits
WDataOutP VL_RANDOM_W(int obits, WDataOutP outwp) VL_MT_SAFE { WDataOutP VL_RANDOM_W(int obits, WDataOutP outwp) VL_MT_SAFE {
for (int i = 0; i < VL_WORDS_I(obits); ++i) { for (int i = 0; i < VL_WORDS_I(obits); ++i) {
@ -355,9 +352,7 @@ WDataOutP VL_ZERO_RESET_W(int obits, WDataOutP outwp) VL_MT_SAFE {
void _VL_DEBUG_PRINT_W(int lbits, WDataInP iwp) VL_MT_SAFE { void _VL_DEBUG_PRINT_W(int lbits, WDataInP iwp) VL_MT_SAFE {
VL_PRINTF_MT(" Data: w%d: ", lbits); VL_PRINTF_MT(" Data: w%d: ", lbits);
for (int i = VL_WORDS_I(lbits) - 1; i >= 0; --i) { for (int i = VL_WORDS_I(lbits) - 1; i >= 0; --i) VL_PRINTF_MT("%08x ", iwp[i]);
VL_PRINTF_MT("%08x ", iwp[i]);
}
VL_PRINTF_MT("\n"); VL_PRINTF_MT("\n");
} }
@ -415,8 +410,11 @@ WDataOutP _vl_moddiv_w(int lbits, WDataOutP owp, WDataInP lwp, WDataInP rwp,
vn[0] = rwp[0] << s; vn[0] = rwp[0] << s;
// Copy and shift dividend by same amount; may set new upper word // Copy and shift dividend by same amount; may set new upper word
if (s) un[uw] = lwp[uw-1] >> (32-s); if (s) {
else un[uw] = 0; un[uw] = lwp[uw - 1] >> (32 - s);
} else {
un[uw] = 0;
}
for (int i = uw - 1; i > 0; --i) { for (int i = uw - 1; i > 0; --i) {
un[i] = (lwp[i] << s) | (shift_mask & (lwp[i - 1] >> (32 - s))); un[i] = (lwp[i] << s) | (shift_mask & (lwp[i - 1] >> (32 - s)));
} }
@ -475,8 +473,8 @@ WDataOutP _vl_moddiv_w(int lbits, WDataOutP owp, WDataInP lwp, WDataInP rwp,
} }
} }
WDataOutP VL_POW_WWW(int obits, int, int rbits, WDataOutP VL_POW_WWW(int obits, int, int rbits, WDataOutP owp, WDataInP lwp,
WDataOutP owp, WDataInP lwp, WDataInP rwp) VL_MT_SAFE { WDataInP rwp) VL_MT_SAFE {
// obits==lbits, rbits can be different // obits==lbits, rbits can be different
owp[0] = 1; owp[0] = 1;
for (int i = 1; i < VL_WORDS_I(obits); i++) owp[i] = 0; for (int i = 1; i < VL_WORDS_I(obits); i++) owp[i] = 0;
@ -498,9 +496,10 @@ WDataOutP VL_POW_WWW(int obits, int, int rbits,
} }
return owp; return owp;
} }
WDataOutP VL_POW_WWQ(int obits, int lbits, int rbits, WDataOutP VL_POW_WWQ(int obits, int lbits, int rbits, WDataOutP owp, WDataInP lwp,
WDataOutP owp, WDataInP lwp, QData rhs) VL_MT_SAFE { QData rhs) VL_MT_SAFE {
WData rhsw[VL_WQ_WORDS_E]; VL_SET_WQ(rhsw, rhs); WData rhsw[VL_WQ_WORDS_E];
VL_SET_WQ(rhsw, rhs);
return VL_POW_WWW(obits, lbits, rbits, owp, lwp, rhsw); return VL_POW_WWW(obits, lbits, rbits, owp, lwp, rhsw);
} }
QData VL_POW_QQW(int, int, int rbits, QData lhs, WDataInP rwp) VL_MT_SAFE { QData VL_POW_QQW(int, int, int rbits, QData lhs, WDataInP rwp) VL_MT_SAFE {
@ -522,35 +521,45 @@ WDataOutP VL_POWSS_WWW(int obits, int, int rbits, WDataOutP owp, WDataInP lwp, W
int words = VL_WORDS_I(obits); int words = VL_WORDS_I(obits);
VL_ZERO_W(obits, owp); VL_ZERO_W(obits, owp);
EData lor = 0; // 0=all zeros, ~0=all ones, else mix EData lor = 0; // 0=all zeros, ~0=all ones, else mix
for (int i=1; i < (words-1); ++i) { for (int i = 1; i < (words - 1); ++i) { lor |= lwp[i]; }
lor |= lwp[i];
}
lor |= ((lwp[words - 1] == VL_MASK_E(rbits)) ? ~VL_EUL(0) : 0); lor |= ((lwp[words - 1] == VL_MASK_E(rbits)) ? ~VL_EUL(0) : 0);
if (lor==0 && lwp[0]==0) { return owp; } // "X" so return 0 if (lor == 0 && lwp[0] == 0) { // "X" so return 0
else if (lor==0 && lwp[0]==1) { owp[0] = 1; return owp; } // 1 return owp;
else if (lsign && lor == ~VL_EUL(0) && lwp[0] == ~VL_EUL(0)) { // -1 } else if (lor == 0 && lwp[0] == 1) { // 1
if (rwp[0] & 1) { return VL_ALLONES_W(obits, owp); } // -1^odd=-1 owp[0] = 1;
else { owp[0] = 1; return owp; } // -1^even=1 return owp;
} else if (lsign && lor == ~VL_EUL(0) && lwp[0] == ~VL_EUL(0)) { // -1
if (rwp[0] & 1) { // -1^odd=-1
return VL_ALLONES_W(obits, owp);
} else { // -1^even=1
owp[0] = 1;
return owp;
}
} }
return 0; return 0;
} }
return VL_POW_WWW(obits, rbits, rbits, owp, lwp, rwp); return VL_POW_WWW(obits, rbits, rbits, owp, lwp, rwp);
} }
WDataOutP VL_POWSS_WWQ(int obits, int lbits, int rbits, WDataOutP VL_POWSS_WWQ(int obits, int lbits, int rbits, WDataOutP owp, WDataInP lwp, QData rhs,
WDataOutP owp, WDataInP lwp, QData rhs,
bool lsign, bool rsign) VL_MT_SAFE { bool lsign, bool rsign) VL_MT_SAFE {
WData rhsw[VL_WQ_WORDS_E]; VL_SET_WQ(rhsw, rhs); WData rhsw[VL_WQ_WORDS_E];
VL_SET_WQ(rhsw, rhs);
return VL_POWSS_WWW(obits, lbits, rbits, owp, lwp, rhsw, lsign, rsign); return VL_POWSS_WWW(obits, lbits, rbits, owp, lwp, rhsw, lsign, rsign);
} }
QData VL_POWSS_QQW(int obits, int, int rbits, QData VL_POWSS_QQW(int obits, int, int rbits, QData lhs, WDataInP rwp, bool lsign,
QData lhs, WDataInP rwp, bool lsign, bool rsign) VL_MT_SAFE { bool rsign) VL_MT_SAFE {
// Skip check for rhs == 0, as short-circuit doesn't save time // Skip check for rhs == 0, as short-circuit doesn't save time
if (rsign && VL_SIGN_W(rbits, rwp)) { if (rsign && VL_SIGN_W(rbits, rwp)) {
if (lhs == 0) return 0; // "X" if (lhs == 0) {
else if (lhs == 1) return 1; return 0; // "X"
else if (lsign && lhs == VL_MASK_Q(obits)) { // -1 } else if (lhs == 1) {
if (rwp[0] & 1) return VL_MASK_Q(obits); // -1^odd=-1 return 1;
else return 1; // -1^even=1 } else if (lsign && lhs == VL_MASK_Q(obits)) { // -1
if (rwp[0] & 1) {
return VL_MASK_Q(obits); // -1^odd=-1
} else {
return 1; // -1^even=1
}
} }
return 0; return 0;
} }
@ -570,7 +579,7 @@ std::string VL_DECIMAL_NW(int width, WDataInP lwp) VL_MT_SAFE {
WData tmp2[VL_VALUE_STRING_MAX_WIDTH / 4 + 2]; WData tmp2[VL_VALUE_STRING_MAX_WIDTH / 4 + 2];
int from_bit = width - 1; int from_bit = width - 1;
// Skip all leading zeros // Skip all leading zeros
for (; from_bit >= 0 && !(VL_BITRSHIFT_W(lwp, from_bit) & 1); --from_bit); for (; from_bit >= 0 && !(VL_BITRSHIFT_W(lwp, from_bit) & 1); --from_bit) {}
// Double-dabble algorithm // Double-dabble algorithm
for (; from_bit >= 0; --from_bit) { for (; from_bit >= 0; --from_bit) {
// Any digits >= 5 need an add 3 (via tmp) // Any digits >= 5 need an add 3 (via tmp)
@ -634,8 +643,7 @@ void _vl_vsformat(std::string& output, const char* formatp, va_list ap) VL_MT_SA
inPct = false; inPct = false;
char fmt = pos[0]; char fmt = pos[0];
switch (fmt) { switch (fmt) {
case '0': case '1': case '2': case '3': case '4': case '0' ... '9':
case '5': case '6': case '7': case '8': case '9':
inPct = true; // Get more digits inPct = true; // Get more digits
widthSet = true; widthSet = true;
width = width * 10 + (fmt - '0'); width = width * 10 + (fmt - '0');
@ -647,12 +655,15 @@ void _vl_vsformat(std::string& output, const char* formatp, va_list ap) VL_MT_SA
case '.': case '.':
inPct = true; // Get more digits inPct = true; // Get more digits
break; break;
case '%': case '%': //
output += '%'; output += '%';
break; break;
case 'N': { // "C" string with name of module, add . if needed case 'N': { // "C" string with name of module, add . if needed
const char* cstrp = va_arg(ap, const char*); const char* cstrp = va_arg(ap, const char*);
if (VL_LIKELY(*cstrp)) { output += cstrp; output += '.'; } if (VL_LIKELY(*cstrp)) {
output += cstrp;
output += '.';
}
break; break;
} }
case 'S': { // "C" string case 'S': { // "C" string
@ -688,7 +699,7 @@ void _vl_vsformat(std::string& output, const char* formatp, va_list ap) VL_MT_SA
sprintf(tmp, fmt.c_str(), d); sprintf(tmp, fmt.c_str(), d);
output += tmp; output += tmp;
break; break;
} } //
break; break;
} // switch } // switch
break; break;
@ -708,7 +719,9 @@ void _vl_vsformat(std::string& output, const char* formatp, va_list ap) VL_MT_SA
ld = lwp[0]; ld = lwp[0];
} }
int lsb = lbits - 1; int lsb = lbits - 1;
if (widthSet && width==0) while (lsb && !VL_BITISSET_W(lwp, lsb)) --lsb; if (widthSet && width == 0) {
while (lsb && !VL_BITISSET_W(lwp, lsb)) --lsb;
}
switch (fmt) { switch (fmt) {
case 'c': { case 'c': {
IData charval = ld & 0xff; IData charval = ld & 0xff;
@ -796,9 +809,7 @@ void _vl_vsformat(std::string& output, const char* formatp, va_list ap) VL_MT_SA
break; break;
} }
case 'b': case 'b':
for (; lsb>=0; --lsb) { for (; lsb >= 0; --lsb) output += (VL_BITRSHIFT_W(lwp, lsb) & 1) + '0';
output += (VL_BITRSHIFT_W(lwp, lsb) & 1) + '0';
}
break; break;
case 'o': case 'o':
for (; lsb >= 0; --lsb) { for (; lsb >= 0; --lsb) {
@ -806,8 +817,7 @@ void _vl_vsformat(std::string& output, const char* formatp, va_list ap) VL_MT_SA
// Octal numbers may span more than one wide word, // Octal numbers may span more than one wide word,
// so we need to grab each bit separately and check for overrun // so we need to grab each bit separately and check for overrun
// Octal is rare, so we'll do it a slow simple way // Octal is rare, so we'll do it a slow simple way
output += ('0' output += ('0' + ((VL_BITISSETLIMIT_W(lwp, lbits, lsb + 0)) ? 1 : 0)
+ ((VL_BITISSETLIMIT_W(lwp, lbits, lsb+0)) ? 1 : 0)
+ ((VL_BITISSETLIMIT_W(lwp, lbits, lsb + 1)) ? 2 : 0) + ((VL_BITISSETLIMIT_W(lwp, lbits, lsb + 1)) ? 2 : 0)
+ ((VL_BITISSETLIMIT_W(lwp, lbits, lsb + 2)) ? 4 : 0)); + ((VL_BITISSETLIMIT_W(lwp, lbits, lsb + 2)) ? 4 : 0));
} }
@ -833,8 +843,11 @@ void _vl_vsformat(std::string& output, const char* formatp, va_list ap) VL_MT_SA
break; break;
case 'v': // Strength; assume always strong case 'v': // Strength; assume always strong
for (lsb = lbits - 1; lsb >= 0; --lsb) { for (lsb = lbits - 1; lsb >= 0; --lsb) {
if (VL_BITRSHIFT_W(lwp, lsb) & 1) output += "St1 "; if (VL_BITRSHIFT_W(lwp, lsb) & 1) {
else output += "St0 "; output += "St1 ";
} else {
output += "St0 ";
}
} }
break; break;
case 'x': case 'x':
@ -863,8 +876,11 @@ static inline bool _vl_vsss_eof(FILE* fp, int floc) VL_MT_SAFE {
} }
} }
static inline void _vl_vsss_advance(FILE* fp, int& floc) VL_MT_SAFE { static inline void _vl_vsss_advance(FILE* fp, int& floc) VL_MT_SAFE {
if (fp) fgetc(fp); if (fp) {
else floc -= 8; fgetc(fp);
} else {
floc -= 8;
}
} }
static inline int _vl_vsss_peek(FILE* fp, int& floc, WDataInP fromp, static inline int _vl_vsss_peek(FILE* fp, int& floc, WDataInP fromp,
const std::string& fstr) VL_MT_SAFE { const std::string& fstr) VL_MT_SAFE {
@ -884,8 +900,8 @@ static inline int _vl_vsss_peek(FILE* fp, int& floc, WDataInP fromp,
} }
} }
} }
static inline void _vl_vsss_skipspace(FILE* fp, int& floc, static inline void _vl_vsss_skipspace(FILE* fp, int& floc, WDataInP fromp,
WDataInP fromp, const std::string& fstr) VL_MT_SAFE { const std::string& fstr) VL_MT_SAFE {
while (true) { while (true) {
int c = _vl_vsss_peek(fp, floc, fromp, fstr); int c = _vl_vsss_peek(fp, floc, fromp, fstr);
if (c == EOF || !isspace(c)) return; if (c == EOF || !isspace(c)) return;
@ -899,8 +915,7 @@ static inline void _vl_vsss_read(FILE* fp, int& floc, WDataInP fromp, const std:
while (true) { while (true) {
int c = _vl_vsss_peek(fp, floc, fromp, fstr); int c = _vl_vsss_peek(fp, floc, fromp, fstr);
if (c == EOF || isspace(c)) break; if (c == EOF || isspace(c)) break;
if (acceptp // String - allow anything if (acceptp && NULL == strchr(acceptp, c)) break; // String - allow anything
&& NULL==strchr(acceptp, c)) break;
if (acceptp) c = tolower(c); // Non-strings we'll simplify if (acceptp) c = tolower(c); // Non-strings we'll simplify
*cp++ = c; *cp++ = c;
_vl_vsss_advance(fp, floc); _vl_vsss_advance(fp, floc);
@ -908,19 +923,19 @@ static inline void _vl_vsss_read(FILE* fp, int& floc, WDataInP fromp, const std:
*cp++ = '\0'; *cp++ = '\0';
// VL_DBG_MSGF(" _read got='"<<tmpp<<"'\n"); // VL_DBG_MSGF(" _read got='"<<tmpp<<"'\n");
} }
static inline void _vl_vsss_setbit(WDataOutP owp, int obits, int lsb, static inline void _vl_vsss_setbit(WDataOutP owp, int obits, int lsb, int nbits,
int nbits, IData ld) VL_MT_SAFE { IData ld) VL_MT_SAFE {
for (; nbits && lsb < obits; nbits--, lsb++, ld >>= 1) { for (; nbits && lsb < obits; nbits--, lsb++, ld >>= 1) {
VL_ASSIGNBIT_WI(0, lsb, owp, ld & 1); VL_ASSIGNBIT_WI(0, lsb, owp, ld & 1);
} }
} }
static inline void _vl_vsss_based(WDataOutP owp, int obits, int baseLog2, static inline void _vl_vsss_based(WDataOutP owp, int obits, int baseLog2, const char* strp,
const char* strp,
size_t posstart, size_t posend) VL_MT_SAFE { size_t posstart, size_t posend) VL_MT_SAFE {
// Read in base "2^^baseLog2" digits from strp[posstart..posend-1] into owp of size obits. // Read in base "2^^baseLog2" digits from strp[posstart..posend-1] into owp of size obits.
int lsb = 0; int lsb = 0;
for (int i = 0, pos = static_cast<int>(posend) - 1; for (int i = 0, pos = static_cast<int>(posend) - 1;
i < obits && pos >= static_cast<int>(posstart); --pos) { i < obits && pos >= static_cast<int>(posstart); --pos) {
// clang-format off
switch (tolower (strp[pos])) { switch (tolower (strp[pos])) {
case 'x': case 'z': case '?': // FALLTHRU case 'x': case 'z': case '?': // FALLTHRU
case '0': lsb += baseLog2; break; case '0': lsb += baseLog2; break;
@ -941,6 +956,7 @@ static inline void _vl_vsss_based(WDataOutP owp, int obits, int baseLog2,
case 'f': _vl_vsss_setbit(owp, obits, lsb, baseLog2, 15); lsb += baseLog2; break; case 'f': _vl_vsss_setbit(owp, obits, lsb, baseLog2, 15); lsb += baseLog2; break;
case '_': break; case '_': break;
} }
// clang-format on
} }
} }
@ -957,7 +973,8 @@ IData _vl_vsscanf(FILE* fp, // If a fscanf
bool inPct = false; bool inPct = false;
const char* pos = formatp; const char* pos = formatp;
for (; *pos && !_vl_vsss_eof(fp, floc); ++pos) { for (; *pos && !_vl_vsss_eof(fp, floc); ++pos) {
//VL_DBG_MSGF("_vlscan fmt='"<<pos[0]<<"' floc="<<floc<<" file='"<<_vl_vsss_peek(fp, floc, fromp, fstr)<<"'"<<endl); // VL_DBG_MSGF("_vlscan fmt='"<<pos[0]<<"' floc="<<floc<<" file='"<<_vl_vsss_peek(fp, floc,
// fromp, fstr)<<"'"<<endl);
if (!inPct && pos[0] == '%') { if (!inPct && pos[0] == '%') {
inPct = true; inPct = true;
} else if (!inPct && isspace(pos[0])) { // Format spaces } else if (!inPct && isspace(pos[0])) { // Format spaces
@ -967,7 +984,7 @@ IData _vl_vsscanf(FILE* fp, // If a fscanf
_vl_vsss_skipspace(fp, floc, fromp, fstr); _vl_vsss_skipspace(fp, floc, fromp, fstr);
int c = _vl_vsss_peek(fp, floc, fromp, fstr); int c = _vl_vsss_peek(fp, floc, fromp, fstr);
if (c != pos[0]) goto done; if (c != pos[0]) goto done;
else _vl_vsss_advance(fp, floc); _vl_vsss_advance(fp, floc);
} else { // Format character } else { // Format character
// Skip loading spaces // Skip loading spaces
inPct = false; inPct = false;
@ -976,24 +993,23 @@ IData _vl_vsscanf(FILE* fp, // If a fscanf
case '%': { case '%': {
int c = _vl_vsss_peek(fp, floc, fromp, fstr); int c = _vl_vsss_peek(fp, floc, fromp, fstr);
if (c != '%') goto done; if (c != '%') goto done;
else _vl_vsss_advance(fp, floc); _vl_vsss_advance(fp, floc);
break; break;
} }
default: { default: {
// Deal with all read-and-scan somethings // Deal with all read-and-scan somethings
// Note LSBs are preserved if there's an overflow // Note LSBs are preserved if there's an overflow
const int obits = va_arg(ap, int); const int obits = va_arg(ap, int);
WData qowp[VL_WQ_WORDS_E]; VL_SET_WQ(qowp, VL_ULL(0)); WData qowp[VL_WQ_WORDS_E];
VL_SET_WQ(qowp, VL_ULL(0));
WDataOutP owp = qowp; WDataOutP owp = qowp;
if (obits > VL_QUADSIZE) { if (obits > VL_QUADSIZE) owp = va_arg(ap, WDataOutP);
owp = va_arg(ap, WDataOutP);
}
for (int i = 0; i < VL_WORDS_I(obits); ++i) owp[i] = 0; for (int i = 0; i < VL_WORDS_I(obits); ++i) owp[i] = 0;
switch (fmt) { switch (fmt) {
case 'c': { case 'c': {
int c = _vl_vsss_peek(fp, floc, fromp, fstr); int c = _vl_vsss_peek(fp, floc, fromp, fstr);
if (c == EOF) goto done; if (c == EOF) goto done;
else _vl_vsss_advance(fp, floc); _vl_vsss_advance(fp, floc);
owp[0] = c; owp[0] = c;
break; break;
} }
@ -1004,7 +1020,8 @@ IData _vl_vsscanf(FILE* fp, // If a fscanf
int lpos = (static_cast<int>(strlen(tmp))) - 1; int lpos = (static_cast<int>(strlen(tmp))) - 1;
int lsb = 0; int lsb = 0;
for (int i = 0; i < obits && lpos >= 0; --lpos) { for (int i = 0; i < obits && lpos >= 0; --lpos) {
_vl_vsss_setbit(owp, obits, lsb, 8, tmp[lpos]); lsb+=8; _vl_vsss_setbit(owp, obits, lsb, 8, tmp[lpos]);
lsb += 8;
} }
break; break;
} }
@ -1024,7 +1041,10 @@ IData _vl_vsscanf(FILE* fp, // If a fscanf
_vl_vsss_read(fp, floc, fromp, fstr, tmp, "+-.0123456789eE"); _vl_vsss_read(fp, floc, fromp, fstr, tmp, "+-.0123456789eE");
if (!tmp[0]) goto done; if (!tmp[0]) goto done;
// cppcheck-suppress unusedStructMember // It's used // cppcheck-suppress unusedStructMember // It's used
union { double r; vlsint64_t ld; } u; union {
double r;
vlsint64_t ld;
} u;
u.r = strtod(tmp, NULL); u.r = strtod(tmp, NULL);
VL_SET_WQ(owp, u.ld); VL_SET_WQ(owp, u.ld);
break; break;
@ -1069,13 +1089,17 @@ IData _vl_vsscanf(FILE* fp, // If a fscanf
got++; got++;
// Reload data if non-wide (if wide, we put it in the right place directly) // Reload data if non-wide (if wide, we put it in the right place directly)
if (obits <= VL_BYTESIZE) { if (obits <= VL_BYTESIZE) {
CData* p = va_arg(ap, CData*); *p = owp[0]; CData* p = va_arg(ap, CData*);
*p = owp[0];
} else if (obits <= VL_SHORTSIZE) { } else if (obits <= VL_SHORTSIZE) {
SData* p = va_arg(ap, SData*); *p = owp[0]; SData* p = va_arg(ap, SData*);
*p = owp[0];
} else if (obits <= VL_IDATASIZE) { } else if (obits <= VL_IDATASIZE) {
IData* p = va_arg(ap, IData*); *p = owp[0]; IData* p = va_arg(ap, IData*);
*p = owp[0];
} else if (obits <= VL_QUADSIZE) { } else if (obits <= VL_QUADSIZE) {
QData* p = va_arg(ap, QData*); *p = VL_SET_QW(owp); QData* p = va_arg(ap, QData*);
*p = VL_SET_QW(owp);
} }
} }
} // switch } // switch
@ -1088,9 +1112,7 @@ IData _vl_vsscanf(FILE* fp, // If a fscanf
//=========================================================================== //===========================================================================
// File I/O // File I/O
FILE* VL_CVT_I_FP(IData lhs) VL_MT_SAFE { FILE* VL_CVT_I_FP(IData lhs) VL_MT_SAFE { return VerilatedImp::fdToFp(lhs); }
return VerilatedImp::fdToFp(lhs);
}
void _VL_VINT_TO_STRING(int obits, char* destoutp, WDataInP sourcep) VL_MT_SAFE { void _VL_VINT_TO_STRING(int obits, char* destoutp, WDataInP sourcep) VL_MT_SAFE {
// See also VL_DATA_TO_STRING_NW // See also VL_DATA_TO_STRING_NW
@ -1106,8 +1128,9 @@ void _VL_VINT_TO_STRING(int obits, char* destoutp, WDataInP sourcep) VL_MT_SAFE
} }
} }
*destp = '\0'; // Terminate *destp = '\0'; // Terminate
// Drop trailing spaces if (!start) { // Drop trailing spaces
if (!start) while (isspace(*(destp-1)) && destp>destoutp) *--destp = '\0'; while (isspace(*(destp - 1)) && destp > destoutp) *--destp = '\0';
}
} }
void _VL_STRING_TO_VINT(int obits, void* destp, size_t srclen, const char* srcp) VL_MT_SAFE { void _VL_STRING_TO_VINT(int obits, void* destp, size_t srclen, const char* srcp) VL_MT_SAFE {
@ -1141,7 +1164,8 @@ IData VL_FGETS_IXI(int obits, void* destp, IData fpi) VL_MT_SAFE {
while (got < bytes) { while (got < bytes) {
int c = getc(fp); // getc() is threadsafe int c = getc(fp); // getc() is threadsafe
if (c == EOF) break; if (c == EOF) break;
*cp++ = c; got++; *cp++ = c;
got++;
if (c == '\n') break; if (c == '\n') break;
} }
@ -1165,7 +1189,8 @@ IData VL_FOPEN_NI(const std::string& filename, IData mode) VL_MT_SAFE {
} }
IData VL_FOPEN_QI(QData filename, IData mode) VL_MT_SAFE { IData VL_FOPEN_QI(QData filename, IData mode) VL_MT_SAFE {
// While threadsafe, each thread can only access different file handles // While threadsafe, each thread can only access different file handles
WData fnw[VL_WQ_WORDS_E]; VL_SET_WQ(fnw, filename); WData fnw[VL_WQ_WORDS_E];
VL_SET_WQ(fnw, filename);
return VL_FOPEN_WI(VL_WQ_WORDS_E, fnw, mode); return VL_FOPEN_WI(VL_WQ_WORDS_E, fnw, mode);
} }
IData VL_FOPEN_WI(int fnwords, WDataInP filenamep, IData mode) VL_MT_SAFE { IData VL_FOPEN_WI(int fnwords, WDataInP filenamep, IData mode) VL_MT_SAFE {
@ -1189,9 +1214,7 @@ void VL_FCLOSE_I(IData fdi) VL_MT_SAFE {
VerilatedImp::fdDelete(fdi); VerilatedImp::fdDelete(fdi);
} }
void VL_FFLUSH_ALL() VL_MT_SAFE { void VL_FFLUSH_ALL() VL_MT_SAFE { fflush(stdout); }
fflush(stdout);
}
void VL_SFORMAT_X(int obits, CData& destr, const char* formatp, ...) VL_MT_SAFE { void VL_SFORMAT_X(int obits, CData& destr, const char* formatp, ...) VL_MT_SAFE {
static VL_THREAD_LOCAL std::string output; // static only for speed static VL_THREAD_LOCAL std::string output; // static only for speed
@ -1307,7 +1330,8 @@ IData VL_FSCANF_IX(IData fpi, const char* formatp, ...) VL_MT_SAFE {
} }
IData VL_SSCANF_IIX(int lbits, IData ld, const char* formatp, ...) VL_MT_SAFE { IData VL_SSCANF_IIX(int lbits, IData ld, const char* formatp, ...) VL_MT_SAFE {
WData fnw[VL_WQ_WORDS_E]; VL_SET_WI(fnw, ld); WData fnw[VL_WQ_WORDS_E];
VL_SET_WI(fnw, ld);
va_list ap; va_list ap;
va_start(ap, formatp); va_start(ap, formatp);
@ -1316,7 +1340,8 @@ IData VL_SSCANF_IIX(int lbits, IData ld, const char* formatp, ...) VL_MT_SAFE {
return got; return got;
} }
IData VL_SSCANF_IQX(int lbits, QData ld, const char* formatp, ...) VL_MT_SAFE { IData VL_SSCANF_IQX(int lbits, QData ld, const char* formatp, ...) VL_MT_SAFE {
WData fnw[VL_WQ_WORDS_E]; VL_SET_WQ(fnw, ld); WData fnw[VL_WQ_WORDS_E];
VL_SET_WQ(fnw, ld);
va_list ap; va_list ap;
va_start(ap, formatp); va_start(ap, formatp);
@ -1339,8 +1364,8 @@ IData VL_SSCANF_INX(int, const std::string& ld, const char* formatp, ...) VL_MT_
return got; return got;
} }
IData VL_FREAD_I(int width, int array_lsb, int array_size, IData VL_FREAD_I(int width, int array_lsb, int array_size, void* memp, IData fpi, IData start,
void* memp, IData fpi, IData start, IData count) VL_MT_SAFE { IData count) VL_MT_SAFE {
// While threadsafe, each thread can only access different file handles // While threadsafe, each thread can only access different file handles
FILE* fp = VL_CVT_I_FP(fpi); FILE* fp = VL_CVT_I_FP(fpi);
if (VL_UNLIKELY(!fp)) return 0; if (VL_UNLIKELY(!fp)) return 0;
@ -1373,11 +1398,10 @@ IData VL_FREAD_I(int width, int array_lsb, int array_size,
} else if (width <= VL_QUADSIZE) { } else if (width <= VL_QUADSIZE) {
QData* datap = &(reinterpret_cast<QData*>(memp))[entry]; QData* datap = &(reinterpret_cast<QData*>(memp))[entry];
if (shift == start_shift) { *datap = 0; } if (shift == start_shift) { *datap = 0; }
*datap |= ((static_cast<QData>(c) << static_cast<QData>(shift)) *datap |= ((static_cast<QData>(c) << static_cast<QData>(shift)) & VL_MASK_Q(width));
& VL_MASK_Q(width));
} else { } else {
WDataOutP datap = &(reinterpret_cast<WDataOutP>(memp))[entry * VL_WORDS_I(width)]; WDataOutP datap = &(reinterpret_cast<WDataOutP>(memp))[entry * VL_WORDS_I(width)];
if (shift == start_shift) { VL_ZERO_RESET_W(width, datap); } if (shift == start_shift) VL_ZERO_RESET_W(width, datap);
datap[VL_BITWORD_E(shift)] |= (static_cast<EData>(c) << VL_BITBIT_E(shift)); datap[VL_BITWORD_E(shift)] |= (static_cast<EData>(c) << VL_BITBIT_E(shift));
} }
// Prep for next // Prep for next
@ -1393,7 +1417,8 @@ IData VL_FREAD_I(int width, int array_lsb, int array_size,
} }
IData VL_SYSTEM_IQ(QData lhs) VL_MT_SAFE { IData VL_SYSTEM_IQ(QData lhs) VL_MT_SAFE {
WData lhsw[VL_WQ_WORDS_E]; VL_SET_WQ(lhsw, lhs); WData lhsw[VL_WQ_WORDS_E];
VL_SET_WQ(lhsw, lhs);
return VL_SYSTEM_IW(VL_WQ_WORDS_E, lhsw); return VL_SYSTEM_IW(VL_WQ_WORDS_E, lhsw);
} }
IData VL_SYSTEM_IW(int lhswords, WDataInP lhsp) VL_MT_SAFE { IData VL_SYSTEM_IW(int lhswords, WDataInP lhsp) VL_MT_SAFE {
@ -1405,8 +1430,7 @@ IData VL_SYSTEM_IW(int lhswords, WDataInP lhsp) VL_MT_SAFE {
IData VL_TESTPLUSARGS_I(const char* formatp) VL_MT_SAFE { IData VL_TESTPLUSARGS_I(const char* formatp) VL_MT_SAFE {
const std::string& match = VerilatedImp::argPlusMatch(formatp); const std::string& match = VerilatedImp::argPlusMatch(formatp);
if (match.empty()) return 0; return match.empty() ? 0 : 1;
else return 1;
} }
IData VL_VALUEPLUSARGS_INW(int rbits, const std::string& ld, WDataOutP rwp) VL_MT_SAFE { IData VL_VALUEPLUSARGS_INW(int rbits, const std::string& ld, WDataOutP rwp) VL_MT_SAFE {
@ -1444,19 +1468,15 @@ IData VL_VALUEPLUSARGS_INW(int rbits, const std::string& ld, WDataOutP rwp) VL_M
sscanf(dp, "%30" VL_PRI64 "d", &lld); sscanf(dp, "%30" VL_PRI64 "d", &lld);
VL_SET_WQ(rwp, lld); VL_SET_WQ(rwp, lld);
break; break;
case 'b': case 'b': _vl_vsss_based(rwp, rbits, 1, dp, 0, strlen(dp)); break;
_vl_vsss_based(rwp, rbits, 1, dp, 0, strlen(dp)); case 'o': _vl_vsss_based(rwp, rbits, 3, dp, 0, strlen(dp)); break;
break;
case 'o':
_vl_vsss_based(rwp, rbits, 3, dp, 0, strlen(dp));
break;
case 'h': // FALLTHRU case 'h': // FALLTHRU
case 'x': case 'x': _vl_vsss_based(rwp, rbits, 4, dp, 0, strlen(dp)); break;
_vl_vsss_based(rwp, rbits, 4, dp, 0, strlen(dp));
break;
case 's': // string/no conversion case 's': // string/no conversion
for (int i=0, lsb=0, posp=static_cast<int>(strlen(dp))-1; i<rbits && posp>=0; --posp) { for (int i = 0, lsb = 0, posp = static_cast<int>(strlen(dp)) - 1; i < rbits && posp >= 0;
_vl_vsss_setbit(rwp, rbits, lsb, 8, dp[posp]); lsb+=8; --posp) {
_vl_vsss_setbit(rwp, rbits, lsb, 8, dp[posp]);
lsb += 8;
} }
break; break;
case 'e': { case 'e': {
@ -1498,7 +1518,7 @@ IData VL_VALUEPLUSARGS_INN(int, const std::string& ld, std::string& rdr) VL_MT_S
prefix += *posp; prefix += *posp;
inPct = false; inPct = false;
break; break;
default: default: //
done = true; done = true;
break; break;
} }
@ -1524,34 +1544,22 @@ const char* vl_mc_scan_plusargs(const char* prefixp) VL_MT_SAFE {
//=========================================================================== //===========================================================================
// Heavy string functions // Heavy string functions
std::string VL_TO_STRING(CData lhs) { std::string VL_TO_STRING(CData lhs) { return VL_SFORMATF_NX("'h%0x", 8, lhs); }
return VL_SFORMATF_NX("'h%0x", 8, lhs); std::string VL_TO_STRING(SData lhs) { return VL_SFORMATF_NX("'h%0x", 16, lhs); }
} std::string VL_TO_STRING(IData lhs) { return VL_SFORMATF_NX("'h%0x", 32, lhs); }
std::string VL_TO_STRING(SData lhs) { std::string VL_TO_STRING(QData lhs) { return VL_SFORMATF_NX("'h%0x", 64, lhs); }
return VL_SFORMATF_NX("'h%0x", 16, lhs);
}
std::string VL_TO_STRING(IData lhs) {
return VL_SFORMATF_NX("'h%0x", 32, lhs);
}
std::string VL_TO_STRING(QData lhs) {
return VL_SFORMATF_NX("'h%0x", 64, lhs);
}
std::string VL_TO_STRING_W(int words, WDataInP obj) { std::string VL_TO_STRING_W(int words, WDataInP obj) {
return VL_SFORMATF_NX("'h%0x", words * VL_EDATASIZE, obj); return VL_SFORMATF_NX("'h%0x", words * VL_EDATASIZE, obj);
} }
std::string VL_TOLOWER_NN(const std::string& ld) VL_MT_SAFE { std::string VL_TOLOWER_NN(const std::string& ld) VL_MT_SAFE {
std::string out = ld; std::string out = ld;
for (std::string::iterator it = out.begin(); it != out.end(); ++it) { for (std::string::iterator it = out.begin(); it != out.end(); ++it) *it = tolower(*it);
*it = tolower(*it);
}
return out; return out;
} }
std::string VL_TOUPPER_NN(const std::string& ld) VL_MT_SAFE { std::string VL_TOUPPER_NN(const std::string& ld) VL_MT_SAFE {
std::string out = ld; std::string out = ld;
for (std::string::iterator it = out.begin(); it != out.end(); ++it) { for (std::string::iterator it = out.begin(); it != out.end(); ++it) *it = toupper(*it);
*it = toupper(*it);
}
return out; return out;
} }
@ -1667,7 +1675,10 @@ VlReadMem::VlReadMem(bool hex, int bits, const std::string& filename, QData star
} }
} }
VlReadMem::~VlReadMem() { VlReadMem::~VlReadMem() {
if (m_fp) { fclose(m_fp); m_fp = NULL; } if (m_fp) {
fclose(m_fp);
m_fp = NULL;
}
} }
bool VlReadMem::get(QData& addrr, std::string& valuer) { bool VlReadMem::get(QData& addrr, std::string& valuer) {
if (VL_UNLIKELY(!m_fp)) return false; if (VL_UNLIKELY(!m_fp)) return false;
@ -1697,7 +1708,8 @@ bool VlReadMem::get(QData& addrr, std::string& valuer) {
} }
// Parse line // Parse line
if (c == '\n') { if (c == '\n') {
++m_linenum; ignore_to_eol = false; ++m_linenum;
ignore_to_eol = false;
reading_addr = false; reading_addr = false;
} else if (c == '\t' || c == ' ' || c == '\r' || c == '\f') { } else if (c == '\t' || c == ' ' || c == '\r' || c == '\f') {
reading_addr = false; reading_addr = false;
@ -1707,15 +1719,22 @@ bool VlReadMem::get(QData& addrr, std::string& valuer) {
ignore_to_cmt = false; ignore_to_cmt = false;
reading_addr = false; reading_addr = false;
} else if (!ignore_to_eol && !ignore_to_cmt) { } else if (!ignore_to_eol && !ignore_to_cmt) {
if (lastc == '/' && c == '*') { ignore_to_cmt = true; } if (lastc == '/' && c == '*') {
else if (lastc == '/' && c == '/') { ignore_to_eol = true; } ignore_to_cmt = true;
else if (c == '/') {} // Part of /* or // } else if (lastc == '/' && c == '/') {
else if (c == '#') { ignore_to_eol = true; } ignore_to_eol = true;
else if (c == '@') { reading_addr = true; m_addr = 0; } } else if (c == '/') { // Part of /* or //
} else if (c == '#') {
ignore_to_eol = true;
} else if (c == '@') {
reading_addr = true;
m_addr = 0;
}
// Check for hex or binary digits as file format requests // Check for hex or binary digits as file format requests
else if (isxdigit(c) || (!reading_addr && (c == 'x' || c == 'X'))) { else if (isxdigit(c) || (!reading_addr && (c == 'x' || c == 'X'))) {
c = tolower(c); c = tolower(c);
int value = (c >= 'a' ? (c == 'x' ? VL_RAND_RESET_I(4) : (c-'a'+10)) : (c-'0')); int value
= (c >= 'a' ? (c == 'x' ? VL_RAND_RESET_I(4) : (c - 'a' + 10)) : (c - '0'));
if (reading_addr) { if (reading_addr) {
// Decode @ addresses // Decode @ addresses
m_addr = (m_addr << 4) + value; m_addr = (m_addr << 4) + value;
@ -1768,7 +1787,7 @@ void VlReadMem::setData(void* valuep, const std::string& rhs) {
& VL_MASK_Q(m_bits); & VL_MASK_Q(m_bits);
} else { } else {
WDataOutP datap = reinterpret_cast<WDataOutP>(valuep); WDataOutP datap = reinterpret_cast<WDataOutP>(valuep);
if (!innum) { VL_ZERO_RESET_W(m_bits, datap); } if (!innum) VL_ZERO_RESET_W(m_bits, datap);
_VL_SHIFTL_INPLACE_W(m_bits, datap, static_cast<IData>(shift)); _VL_SHIFTL_INPLACE_W(m_bits, datap, static_cast<IData>(shift));
datap[0] |= value; datap[0] |= value;
} }
@ -1798,7 +1817,10 @@ VlWriteMem::VlWriteMem(bool hex, int bits, const std::string& filename, QData st
} }
} }
VlWriteMem::~VlWriteMem() { VlWriteMem::~VlWriteMem() {
if (m_fp) { fclose(m_fp); m_fp = NULL; } if (m_fp) {
fclose(m_fp);
m_fp = NULL;
}
} }
void VlWriteMem::print(QData addr, bool addrstamp, const void* valuep) { void VlWriteMem::print(QData addr, bool addrstamp, const void* valuep) {
if (VL_UNLIKELY(!m_fp)) return; if (VL_UNLIKELY(!m_fp)) return;
@ -1886,8 +1908,8 @@ void VL_READMEM_N(bool hex, // Hex format, else binary
QData* datap = &(reinterpret_cast<QData*>(memp))[entry]; QData* datap = &(reinterpret_cast<QData*>(memp))[entry];
rmem.setData(datap, value); rmem.setData(datap, value);
} else { } else {
WDataOutP datap = &(reinterpret_cast<WDataOutP>(memp)) WDataOutP datap
[ entry*VL_WORDS_I(bits) ]; = &(reinterpret_cast<WDataOutP>(memp))[entry * VL_WORDS_I(bits)];
rmem.setData(datap, value); rmem.setData(datap, value);
} }
} }
@ -1945,7 +1967,10 @@ int VL_TIME_STR_CONVERT(const char* strp) {
int scale = 0; int scale = 0;
if (!strp) return 0; if (!strp) return 0;
if (*strp++ != '1') return 0; if (*strp++ != '1') return 0;
while (*strp == '0') { scale++; strp++; } while (*strp == '0') {
scale++;
strp++;
}
switch (*strp++) { switch (*strp++) {
case 's': break; case 's': break;
case 'm': scale -= 3; break; case 'm': scale -= 3; break;
@ -1966,13 +1991,15 @@ int VL_TIME_STR_CONVERT(const char* strp) {
Verilated::ThreadLocal::ThreadLocal() Verilated::ThreadLocal::ThreadLocal()
: :
#ifdef VL_THREADED #ifdef VL_THREADED
t_mtaskId(0), t_mtaskId(0)
t_endOfEvalReqd(0), , t_endOfEvalReqd(0)
,
#endif #endif
t_dpiScopep(NULL), t_dpiFilename(0), t_dpiLineno(0) { t_dpiScopep(NULL)
} , t_dpiFilename(0)
Verilated::ThreadLocal::~ThreadLocal() { , t_dpiLineno(0) {
} }
Verilated::ThreadLocal::~ThreadLocal() {}
void Verilated::debug(int level) VL_MT_SAFE { void Verilated::debug(int level) VL_MT_SAFE {
VerilatedLockGuard lock(m_mutex); VerilatedLockGuard lock(m_mutex);
@ -2038,7 +2065,6 @@ void Verilated::profThreadsFilenamep(const char* flagp) VL_MT_SAFE {
s_ns.s_profThreadsFilenamep = strdup(flagp); s_ns.s_profThreadsFilenamep = strdup(flagp);
} }
const char* Verilated::catName(const char* n1, const char* n2, const char* delimiter) VL_MT_SAFE { const char* Verilated::catName(const char* n1, const char* n2, const char* delimiter) VL_MT_SAFE {
// Returns new'ed data // Returns new'ed data
// Used by symbol table creation to make module names // Used by symbol table creation to make module names
@ -2058,9 +2084,10 @@ const char* Verilated::catName(const char* n1, const char* n2, const char* delim
void Verilated::flushCb(VerilatedVoidCb cb) VL_MT_SAFE { void Verilated::flushCb(VerilatedVoidCb cb) VL_MT_SAFE {
VerilatedLockGuard lock(m_mutex); VerilatedLockGuard lock(m_mutex);
if (s_flushCb == cb) {} // Ok - don't duplicate if (s_flushCb == cb) { // Ok - don't duplicate
else if (!s_flushCb) { s_flushCb=cb; } } else if (!s_flushCb) {
else { // LCOV_EXCL_LINE s_flushCb = cb;
} else { // LCOV_EXCL_LINE
// Someday we may allow multiple callbacks ala atexit(), but until then // Someday we may allow multiple callbacks ala atexit(), but until then
VL_FATAL_MT("unknown", 0, "", // LCOV_EXCL_LINE VL_FATAL_MT("unknown", 0, "", // LCOV_EXCL_LINE
"Verilated::flushCb called twice with different callbacks"); "Verilated::flushCb called twice with different callbacks");
@ -2074,12 +2101,8 @@ void Verilated::flushCall() VL_MT_SAFE {
fflush(stdout); fflush(stdout);
} }
const char* Verilated::productName() VL_PURE { const char* Verilated::productName() VL_PURE { return VERILATOR_PRODUCT; }
return VERILATOR_PRODUCT; const char* Verilated::productVersion() VL_PURE { return VERILATOR_VERSION; }
}
const char* Verilated::productVersion() VL_PURE {
return VERILATOR_VERSION;
}
void Verilated::commandArgs(int argc, const char** argv) VL_MT_SAFE { void Verilated::commandArgs(int argc, const char** argv) VL_MT_SAFE {
VerilatedLockGuard lock(s_args.m_argMutex); VerilatedLockGuard lock(s_args.m_argMutex);
@ -2105,8 +2128,7 @@ void Verilated::nullPointerError(const char* filename, int linenum) VL_MT_SAFE {
void Verilated::overWidthError(const char* signame) VL_MT_SAFE { void Verilated::overWidthError(const char* signame) VL_MT_SAFE {
// Slowpath - Called only when signal sets too high of a bit // Slowpath - Called only when signal sets too high of a bit
std::string msg = (std::string("Testbench C set input '") std::string msg = (std::string("Testbench C set input '") + signame
+ signame
+ "' to value that overflows what the signal's width can fit"); + "' to value that overflows what the signal's width can fit");
VL_FATAL_MT("unknown", 0, "", msg.c_str()); VL_FATAL_MT("unknown", 0, "", msg.c_str());
VL_UNREACHABLE VL_UNREACHABLE
@ -2127,13 +2149,9 @@ void Verilated::quiesce() VL_MT_SAFE {
#endif #endif
} }
void Verilated::internalsDump() VL_MT_SAFE { void Verilated::internalsDump() VL_MT_SAFE { VerilatedImp::internalsDump(); }
VerilatedImp::internalsDump();
}
void Verilated::scopesDump() VL_MT_SAFE { void Verilated::scopesDump() VL_MT_SAFE { VerilatedImp::scopesDump(); }
VerilatedImp::scopesDump();
}
const VerilatedScope* Verilated::scopeFind(const char* namep) VL_MT_SAFE { const VerilatedScope* Verilated::scopeFind(const char* namep) VL_MT_SAFE {
return VerilatedImp::scopeFind(namep); return VerilatedImp::scopeFind(namep);
@ -2176,8 +2194,7 @@ void VerilatedImp::internalsDump() VL_MT_SAFE {
userDump(); userDump();
} }
void VerilatedImp::versionDump() VL_MT_SAFE { void VerilatedImp::versionDump() VL_MT_SAFE {
VL_PRINTF_MT(" Version: %s %s\n", VL_PRINTF_MT(" Version: %s %s\n", Verilated::productName(), Verilated::productVersion());
Verilated::productName(), Verilated::productVersion());
} }
void VerilatedImp::commandArgs(int argc, const char** argv) VL_EXCLUDES(s_s.m_argMutex) { void VerilatedImp::commandArgs(int argc, const char** argv) VL_EXCLUDES(s_s.m_argMutex) {
@ -2202,53 +2219,42 @@ void VerilatedImp::commandArgVl(const std::string& arg) {
std::string value; std::string value;
if (arg == "+verilator+debug") { if (arg == "+verilator+debug") {
Verilated::debug(4); Verilated::debug(4);
} } else if (commandArgVlValue(arg, "+verilator+debugi+", value /*ref*/)) {
else if (commandArgVlValue(arg, "+verilator+debugi+", value/*ref*/)) {
Verilated::debug(atoi(value.c_str())); Verilated::debug(atoi(value.c_str()));
} } else if (commandArgVlValue(arg, "+verilator+error+limit+", value /*ref*/)) {
else if (commandArgVlValue(arg, "+verilator+error+limit+", value/*ref*/)) {
Verilated::errorLimit(atoi(value.c_str())); Verilated::errorLimit(atoi(value.c_str()));
} } else if (arg == "+verilator+help") {
else if (arg == "+verilator+help") {
versionDump(); versionDump();
VL_PRINTF_MT("For help, please see 'verilator --help'\n"); VL_PRINTF_MT("For help, please see 'verilator --help'\n");
VL_FATAL_MT("COMMAND_LINE", 0, "", "Exiting due to command line argument (not an error)"); VL_FATAL_MT("COMMAND_LINE", 0, "",
} "Exiting due to command line argument (not an error)");
else if (commandArgVlValue(arg, "+verilator+prof+threads+start+", value/*ref*/)) { } else if (commandArgVlValue(arg, "+verilator+prof+threads+start+", value /*ref*/)) {
Verilated::profThreadsStart(atoll(value.c_str())); Verilated::profThreadsStart(atoll(value.c_str()));
} } else if (commandArgVlValue(arg, "+verilator+prof+threads+window+", value /*ref*/)) {
else if (commandArgVlValue(arg, "+verilator+prof+threads+window+", value/*ref*/)) {
Verilated::profThreadsWindow(atol(value.c_str())); Verilated::profThreadsWindow(atol(value.c_str()));
} } else if (commandArgVlValue(arg, "+verilator+prof+threads+file+", value /*ref*/)) {
else if (commandArgVlValue(arg, "+verilator+prof+threads+file+", value/*ref*/)) {
Verilated::profThreadsFilenamep(value.c_str()); Verilated::profThreadsFilenamep(value.c_str());
} } else if (commandArgVlValue(arg, "+verilator+rand+reset+", value /*ref*/)) {
else if (commandArgVlValue(arg, "+verilator+rand+reset+", value/*ref*/)) {
Verilated::randReset(atoi(value.c_str())); Verilated::randReset(atoi(value.c_str()));
} } else if (commandArgVlValue(arg, "+verilator+seed+", value /*ref*/)) {
else if (commandArgVlValue(arg, "+verilator+seed+", value/*ref*/)) {
Verilated::randSeed(atoi(value.c_str())); Verilated::randSeed(atoi(value.c_str()));
} } else if (arg == "+verilator+noassert") {
else if (arg == "+verilator+noassert") {
Verilated::assertOn(false); Verilated::assertOn(false);
} } else if (arg == "+verilator+V") {
else if (arg == "+verilator+V") {
versionDump(); // Someday more info too versionDump(); // Someday more info too
VL_FATAL_MT("COMMAND_LINE", 0, "", VL_FATAL_MT("COMMAND_LINE", 0, "",
"Exiting due to command line argument (not an error)"); "Exiting due to command line argument (not an error)");
} } else if (arg == "+verilator+version") {
else if (arg == "+verilator+version") {
versionDump(); versionDump();
VL_FATAL_MT("COMMAND_LINE", 0, "", VL_FATAL_MT("COMMAND_LINE", 0, "",
"Exiting due to command line argument (not an error)"); "Exiting due to command line argument (not an error)");
} } else {
else {
VL_PRINTF_MT("%%Warning: Unknown +verilator runtime argument: '%s'\n", arg.c_str()); VL_PRINTF_MT("%%Warning: Unknown +verilator runtime argument: '%s'\n", arg.c_str());
} }
} }
} }
bool VerilatedImp::commandArgVlValue(const std::string& arg, bool VerilatedImp::commandArgVlValue(const std::string& arg, const std::string& prefix,
const std::string& prefix, std::string& valuer) { std::string& valuer) {
size_t len = prefix.length(); size_t len = prefix.length();
if (0 == strncmp(prefix.c_str(), arg.c_str(), len)) { if (0 == strncmp(prefix.c_str(), arg.c_str(), len)) {
valuer = arg.substr(len); valuer = arg.substr(len);
@ -2276,8 +2282,7 @@ VerilatedSyms::~VerilatedSyms() {
// VerilatedModule:: Methods // VerilatedModule:: Methods
VerilatedModule::VerilatedModule(const char* namep) VerilatedModule::VerilatedModule(const char* namep)
: m_namep(strdup(namep)) { : m_namep(strdup(namep)) {}
}
VerilatedModule::~VerilatedModule() { VerilatedModule::~VerilatedModule() {
// Memory cleanup - not called during normal operation // Memory cleanup - not called during normal operation
@ -2305,9 +2310,7 @@ vluint32_t VerilatedVarProps::entSize() const {
size_t VerilatedVarProps::totalSize() const { size_t VerilatedVarProps::totalSize() const {
size_t size = entSize(); size_t size = entSize();
for (int dim=1; dim<=dims(); ++dim) { for (int dim = 1; dim <= dims(); ++dim) size *= m_unpacked[dim].elements();
size *= m_unpacked[dim].elements();
}
return size; return size;
} }
@ -2345,9 +2348,8 @@ VerilatedScope::~VerilatedScope() {
m_funcnumMax = 0; // Force callback table to empty m_funcnumMax = 0; // Force callback table to empty
} }
void VerilatedScope::configure(VerilatedSyms* symsp, const char* prefixp, void VerilatedScope::configure(VerilatedSyms* symsp, const char* prefixp, const char* suffixp,
const char* suffixp, const char* identifier, const char* identifier, const Type type) VL_MT_UNSAFE {
const Type type) VL_MT_UNSAFE {
// Slowpath - called once/scope at construction // Slowpath - called once/scope at construction
// We don't want the space and reference-count access overhead of strings. // We don't want the space and reference-count access overhead of strings.
m_symsp = symsp; m_symsp = symsp;
@ -2406,9 +2408,9 @@ void VerilatedScope::varInsert(int finalize, const char* namep, void* datap,
} else { } else {
// We could have a linked list of ranges, but really this whole thing needs // We could have a linked list of ranges, but really this whole thing needs
// to be generalized to support structs and unions, etc. // to be generalized to support structs and unions, etc.
VL_FATAL_MT(__FILE__, __LINE__, "", VL_FATAL_MT(
(std::string("Unsupported multi-dimensional public varInsert: ") __FILE__, __LINE__, "",
+ namep).c_str()); (std::string("Unsupported multi-dimensional public varInsert: ") + namep).c_str());
} }
} }
va_end(ap); va_end(ap);
@ -2420,9 +2422,7 @@ void VerilatedScope::varInsert(int finalize, const char* namep, void* datap,
VerilatedVar* VerilatedScope::varFind(const char* namep) const VL_MT_SAFE_POSTINIT { VerilatedVar* VerilatedScope::varFind(const char* namep) const VL_MT_SAFE_POSTINIT {
if (VL_LIKELY(m_varsp)) { if (VL_LIKELY(m_varsp)) {
VerilatedVarNameMap::iterator it = m_varsp->find(namep); VerilatedVarNameMap::iterator it = m_varsp->find(namep);
if (VL_LIKELY(it != m_varsp->end())) { if (VL_LIKELY(it != m_varsp->end())) return &(it->second);
return &(it->second);
}
} }
return NULL; return NULL;
} }
@ -2438,8 +2438,7 @@ void* VerilatedScope::exportFindNullError(int funcnum) VL_MT_SAFE {
void* VerilatedScope::exportFindError(int funcnum) const { void* VerilatedScope::exportFindError(int funcnum) const {
// Slowpath - Called only when find has failed // Slowpath - Called only when find has failed
std::string msg = (std::string("Testbench C called '") std::string msg = (std::string("Testbench C called '") + VerilatedImp::exportName(funcnum)
+VerilatedImp::exportName(funcnum)
+ "' but this DPI export function exists only in other scopes, not scope '" + "' but this DPI export function exists only in other scopes, not scope '"
+ name() + "'"); + name() + "'");
VL_FATAL_MT("unknown", 0, "", msg.c_str()); VL_FATAL_MT("unknown", 0, "", msg.c_str());
@ -2450,13 +2449,12 @@ void VerilatedScope::scopeDump() const {
VL_PRINTF_MT(" SCOPE %p: %s\n", this, name()); VL_PRINTF_MT(" SCOPE %p: %s\n", this, name());
for (int i = 0; i < m_funcnumMax; ++i) { for (int i = 0; i < m_funcnumMax; ++i) {
if (m_callbacksp && m_callbacksp[i]) { if (m_callbacksp && m_callbacksp[i]) {
VL_PRINTF_MT(" DPI-EXPORT %p: %s\n", VL_PRINTF_MT(" DPI-EXPORT %p: %s\n", m_callbacksp[i],
m_callbacksp[i], VerilatedImp::exportName(i)); VerilatedImp::exportName(i));
} }
} }
if (VerilatedVarNameMap* varsp = this->varsp()) { if (VerilatedVarNameMap* varsp = this->varsp()) {
for (VerilatedVarNameMap::const_iterator it = varsp->begin(); for (VerilatedVarNameMap::const_iterator it = varsp->begin(); it != varsp->end(); ++it) {
it != varsp->end(); ++it) {
VL_PRINTF_MT(" VAR %p: %s\n", &(it->second), it->first); VL_PRINTF_MT(" VAR %p: %s\n", &(it->second), it->first);
} }
} }
@ -2471,7 +2469,8 @@ void VerilatedHierarchy::add(VerilatedScope* fromp, VerilatedScope* top) {
#if defined(VL_THREADED) && defined(VL_DEBUG) #if defined(VL_THREADED) && defined(VL_DEBUG)
void VerilatedAssertOneThread::fatal_different() VL_MT_SAFE { void VerilatedAssertOneThread::fatal_different() VL_MT_SAFE {
VL_FATAL_MT(__FILE__, __LINE__, "", "Routine called that is single threaded, but called from" VL_FATAL_MT(__FILE__, __LINE__, "",
"Routine called that is single threaded, but called from"
" a different thread then the expected constructing thread"); " a different thread then the expected constructing thread");
} }
#endif #endif

File diff suppressed because it is too large Load Diff

View File

@ -16,7 +16,6 @@
/// ///
//************************************************************************* //*************************************************************************
///**** Product and Version name ///**** Product and Version name
// Autoconf substitutes this with the strings from AC_INIT. // Autoconf substitutes this with the strings from AC_INIT.

View File

@ -74,7 +74,10 @@ public:
virtual void zero() const VL_OVERRIDE { *m_countp = 0; } virtual void zero() const VL_OVERRIDE { *m_countp = 0; }
// CONSTRUCTORS // CONSTRUCTORS
// cppcheck-suppress noExplicitConstructor // 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 {} virtual ~VerilatedCoverItemSpec() VL_OVERRIDE {}
}; };
@ -93,9 +96,9 @@ private:
private: private:
// MEMBERS // MEMBERS
VerilatedMutex m_mutex; ///< Protects all members, when VL_THREADED. Wrapper deals with setting it. VerilatedMutex m_mutex; ///< Protects all members
ValueIndexMap m_valueIndexes VL_GUARDED_BY(m_mutex); ///< For each key/value a unique arbitrary index value ValueIndexMap m_valueIndexes VL_GUARDED_BY(m_mutex); ///< Unique arbitrary value for values
IndexValueMap m_indexValues VL_GUARDED_BY(m_mutex); ///< For each key/value a unique arbitrary index value IndexValueMap m_indexValues VL_GUARDED_BY(m_mutex); ///< Unique arbitrary value for keys
ItemList m_items VL_GUARDED_BY(m_mutex); ///< List of all items ItemList m_items VL_GUARDED_BY(m_mutex); ///< List of all items
VerilatedCovImpItem* m_insertp VL_GUARDED_BY(m_mutex); ///< Item about to insert VerilatedCovImpItem* m_insertp VL_GUARDED_BY(m_mutex); ///< Item about to insert
@ -109,6 +112,7 @@ private:
m_insertLineno = 0; m_insertLineno = 0;
} }
VL_UNCOPYABLE(VerilatedCovImp); VL_UNCOPYABLE(VerilatedCovImp);
public: public:
~VerilatedCovImp() { clearGuts(); } ~VerilatedCovImp() { clearGuts(); }
static VerilatedCovImp& imp() VL_MT_SAFE { static VerilatedCovImp& imp() VL_MT_SAFE {
@ -122,7 +126,8 @@ private:
static int nextIndex = KEY_UNDEF + 1; static int nextIndex = KEY_UNDEF + 1;
ValueIndexMap::iterator iter = m_valueIndexes.find(value); ValueIndexMap::iterator iter = m_valueIndexes.find(value);
if (iter != m_valueIndexes.end()) return iter->second; if (iter != m_valueIndexes.end()) return iter->second;
nextIndex++; assert(nextIndex>0); nextIndex++;
assert(nextIndex > 0); // Didn't rollover
m_valueIndexes.insert(std::make_pair(value, nextIndex)); m_valueIndexes.insert(std::make_pair(value, nextIndex));
m_indexValues.insert(std::make_pair(nextIndex, value)); m_indexValues.insert(std::make_pair(nextIndex, value));
return nextIndex; return nextIndex;
@ -132,7 +137,8 @@ private:
std::string rtn; std::string rtn;
for (const char* pos = text.c_str(); *pos; ++pos) { for (const char* pos = text.c_str(); *pos; ++pos) {
if (!isprint(*pos) || *pos == '%' || *pos == '"') { if (!isprint(*pos) || *pos == '%' || *pos == '"') {
char hex[10]; sprintf(hex, "%%%02X", pos[0]); char hex[10];
sprintf(hex, "%%%02X", pos[0]);
rtn += hex; rtn += hex;
} else { } else {
rtn += *pos; rtn += *pos;
@ -149,7 +155,8 @@ private:
if (key.length() == 2 && isdigit(key[1])) return false; if (key.length() == 2 && isdigit(key[1])) return false;
return true; return true;
} }
static std::string keyValueFormatter(const std::string& key, const std::string& value) VL_PURE { static std::string keyValueFormatter(const std::string& key,
const std::string& value) VL_PURE {
std::string name; std::string name;
if (key.length() == 1 && isalpha(key[0])) { if (key.length() == 1 && isalpha(key[0])) {
name += std::string("\001") + key; name += std::string("\001") + key;
@ -173,7 +180,10 @@ private:
// Scan forward to first mismatch // Scan forward to first mismatch
const char* apre = a; const char* apre = a;
const char* bpre = b; const char* bpre = b;
while (*apre == *bpre) { apre++; bpre++; } while (*apre == *bpre) {
apre++;
bpre++;
}
// We used to backup and split on only .'s but it seems better to be verbose // We used to backup and split on only .'s but it seems better to be verbose
// and not assume . is the separator // and not assume . is the separator
@ -182,18 +192,22 @@ private:
// Scan backward to last mismatch // Scan backward to last mismatch
const char* apost = a + strlen(a) - 1; const char* apost = a + strlen(a) - 1;
const char* bpost = b + strlen(b) - 1; const char* bpost = b + strlen(b) - 1;
while (*apost == *bpost while (*apost == *bpost && apost > apre && bpost > bpre) {
&& apost>apre && bpost>bpre) { apost--; bpost--; } apost--;
bpost--;
}
// Forward to . so we have a whole word // Forward to . so we have a whole word
std::string suffix = *bpost ? std::string(bpost + 1) : ""; std::string suffix = *bpost ? std::string(bpost + 1) : "";
std::string out = prefix + "*" + suffix; std::string out = prefix + "*" + suffix;
//cout << "\nch pre="<<prefix<<" s="<<suffix<<"\nch a="<<old<<"\nch b="<<add<<"\nch o="<<out<<endl; // cout << "\nch pre="<<prefix<<" s="<<suffix<<"\nch a="<<old<<"\nch b="<<add
// <<"\ncho="<<out<<endl;
return out; return out;
} }
bool itemMatchesString(VerilatedCovImpItem* itemp, const std::string& match) VL_REQUIRES(m_mutex) { bool itemMatchesString(VerilatedCovImpItem* itemp, const std::string& match)
VL_REQUIRES(m_mutex) {
for (int i = 0; i < MAX_KEYS; ++i) { for (int i = 0; i < MAX_KEYS; ++i) {
if (itemp->m_keys[i] != KEY_UNDEF) { if (itemp->m_keys[i] != KEY_UNDEF) {
// We don't compare keys, only values // We don't compare keys, only values
@ -207,14 +221,20 @@ private:
} }
static void selftest() VL_MT_SAFE { static void selftest() VL_MT_SAFE {
// Little selftest // Little selftest
if (combineHier("a.b.c","a.b.c") !="a.b.c") VL_FATAL_MT(__FILE__,__LINE__,"","%Error: selftest\n"); #define VL_CST_CHECK(got, exp) \
if (combineHier("a.b.c","a.b") !="a.b*") VL_FATAL_MT(__FILE__,__LINE__,"","%Error: selftest\n"); do { \
if (combineHier("a.x.c","a.y.c") !="a.*.c") VL_FATAL_MT(__FILE__,__LINE__,"","%Error: selftest\n"); if ((got) != (exp)) 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"); } while (0)
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"); VL_CST_CHECK(combineHier("a.b.c", "a.b.c"), "a.b.c");
if (combineHier("q.za","q.zb") !="q.z*") VL_FATAL_MT(__FILE__,__LINE__,"","%Error: selftest\n"); VL_CST_CHECK(combineHier("a.b.c", "a.b"), "a.b*");
if (combineHier("1.2.3.a","9.8.7.a") !="*.a") VL_FATAL_MT(__FILE__,__LINE__,"","%Error: selftest\n"); 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) { 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) {
@ -268,28 +288,28 @@ public:
m_insertFilenamep = filenamep; m_insertFilenamep = filenamep;
m_insertLineno = lineno; m_insertLineno = lineno;
} }
void insertp(const char* ckeyps[MAX_KEYS], void insertp(const char* ckeyps[MAX_KEYS], const char* valps[MAX_KEYS]) VL_EXCLUDES(m_mutex) {
const char* valps[MAX_KEYS]) VL_EXCLUDES(m_mutex) {
VerilatedLockGuard lock(m_mutex); VerilatedLockGuard lock(m_mutex);
assert(m_insertp); assert(m_insertp);
// First two key/vals are filename // First two key/vals are filename
ckeyps[0]="filename"; valps[0]=m_insertFilenamep; ckeyps[0] = "filename";
valps[0] = m_insertFilenamep;
std::string linestr = vlCovCvtToStr(m_insertLineno); std::string linestr = vlCovCvtToStr(m_insertLineno);
ckeyps[1]="lineno"; valps[1]=linestr.c_str(); ckeyps[1] = "lineno";
valps[1] = linestr.c_str();
// Default page if not specified // Default page if not specified
const char* fnstartp = m_insertFilenamep; const char* fnstartp = m_insertFilenamep;
while (const char* foundp = strchr(fnstartp, '/')) fnstartp = foundp + 1; while (const char* foundp = strchr(fnstartp, '/')) fnstartp = foundp + 1;
const char* fnendp = fnstartp; const char* fnendp = fnstartp;
while (*fnendp && *fnendp!='.') fnendp++; for (; *fnendp && *fnendp != '.'; fnendp++) {}
std::string page_default = "sp_user/" + std::string(fnstartp, fnendp - fnstartp); std::string page_default = "sp_user/" + std::string(fnstartp, fnendp - fnstartp);
ckeyps[2]="page"; valps[2]=page_default.c_str(); ckeyps[2] = "page";
valps[2] = page_default.c_str();
// Keys -> strings // Keys -> strings
std::string keys[MAX_KEYS]; std::string keys[MAX_KEYS];
for (int i = 0; i < MAX_KEYS; ++i) { for (int i = 0; i < MAX_KEYS; ++i) {
if (ckeyps[i] && ckeyps[i][0]) { if (ckeyps[i] && ckeyps[i][0]) { keys[i] = ckeyps[i]; }
keys[i] = ckeyps[i];
}
} }
// Ignore empty keys // Ignore empty keys
for (int i = 0; i < MAX_KEYS; ++i) { for (int i = 0; i < MAX_KEYS; ++i) {
@ -400,15 +420,11 @@ public:
//============================================================================= //=============================================================================
// VerilatedCov // VerilatedCov
void VerilatedCov::clear() VL_MT_SAFE { void VerilatedCov::clear() VL_MT_SAFE { VerilatedCovImp::imp().clear(); }
VerilatedCovImp::imp().clear();
}
void VerilatedCov::clearNonMatch(const char* matchp) VL_MT_SAFE { void VerilatedCov::clearNonMatch(const char* matchp) VL_MT_SAFE {
VerilatedCovImp::imp().clearNonMatch(matchp); VerilatedCovImp::imp().clearNonMatch(matchp);
} }
void VerilatedCov::zero() VL_MT_SAFE { void VerilatedCov::zero() VL_MT_SAFE { VerilatedCovImp::imp().zero(); }
VerilatedCovImp::imp().zero();
}
void VerilatedCov::write(const char* filenamep) VL_MT_SAFE { void VerilatedCov::write(const char* filenamep) VL_MT_SAFE {
VerilatedCovImp::imp().write(filenamep); VerilatedCovImp::imp().write(filenamep);
} }
@ -426,9 +442,10 @@ void VerilatedCov::_insertf(const char* filename, int lineno) VL_MT_SAFE {
#define A(n) const char *key##n, const char *valp##n // Argument list #define A(n) const char *key##n, const char *valp##n // Argument list
#define C(n) key##n, valp##n // Calling argument list #define C(n) key##n, valp##n // Calling argument list
#define N(n) "", "" // Null 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), 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(10),A(11),A(12),A(13),A(14),A(15),A(16),A(17),A(18),A(19), A(11), A(12), A(13), A(14), A(15), A(16), A(17), A(18), A(19), A(20),
A(20),A(21),A(22),A(23),A(24),A(25),A(26),A(27),A(28),A(29)) VL_MT_SAFE { 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] const char* keyps[VerilatedCovImpBase::MAX_KEYS]
= {NULL, NULL, NULL, // filename,lineno,page = {NULL, NULL, NULL, // filename,lineno,page
key0, key1, key2, key3, key4, key5, key6, key7, key8, key9, key0, key1, key2, key3, key4, key5, key6, key7, key8, key9,
@ -443,27 +460,27 @@ void VerilatedCov::_insertp(A(0),A(1),A(2),A(3),A(4),A(5),A(6),A(7),A(8),A(9),
} }
// And versions with fewer arguments (oh for a language with named parameters!) // And versions with fewer arguments (oh for a language with named parameters!)
void VerilatedCov::_insertp(A(0),A(1),A(2),A(3),A(4),A(5),A(6),A(7),A(8),A(9)) VL_MT_SAFE { void VerilatedCov::_insertp(A(0), A(1), A(2), A(3), A(4), A(5), A(6), A(7), A(8),
_insertp(C(0),C(1),C(2),C(3),C(4),C(5),C(6),C(7),C(8),C(9), A(9)) VL_MT_SAFE {
N(10),N(11),N(12),N(13),N(14),N(15),N(16),N(17),N(18),N(19), _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(20),N(21),N(22),N(23),N(24),N(25),N(26),N(27),N(28),N(29)); 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), 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(10),A(11),A(12),A(13),A(14),A(15),A(16),A(17),A(18),A(19)) VL_MT_SAFE { A(11), A(12), A(13), A(14), A(15), A(16), A(17), A(18),
_insertp(C(0),C(1),C(2),C(3),C(4),C(5),C(6),C(7),C(8),C(9), A(19)) VL_MT_SAFE {
C(10),C(11),C(12),C(13),C(14),C(15),C(16),C(17),C(18),C(19), _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),
N(20),N(21),N(22),N(23),N(24),N(25),N(26),N(27),N(28),N(29)); 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 // Backward compatibility for Verilator
void VerilatedCov::_insertp(A(0), A(1), K(2),int val2, K(3),int val3, void VerilatedCov::_insertp(A(0), A(1), K(2), int val2, K(3), int val3, K(4),
K(4),const std::string& val4, A(5),A(6)) VL_MT_SAFE { const std::string& val4, A(5), A(6)) VL_MT_SAFE {
std::string val2str = vlCovCvtToStr(val2); std::string val2str = vlCovCvtToStr(val2);
std::string val3str = vlCovCvtToStr(val3); std::string val3str = vlCovCvtToStr(val3);
_insertp(C(0),C(1), _insertp(C(0), C(1), key2, val2str.c_str(), key3, val3str.c_str(), key4, val4.c_str(), C(5),
key2,val2str.c_str(), key3,val3str.c_str(), key4, val4.c_str(), 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),
C(5),C(6),N(7),N(8),N(9), N(19), N(20), N(21), N(22), N(23), N(24), N(25), N(26), N(27), N(28), N(29));
N(10),N(11),N(12),N(13),N(14),N(15),N(16),N(17),N(18),N(19),
N(20),N(21),N(22),N(23),N(24),N(25),N(26),N(27),N(28),N(29));
} }
#undef A #undef A
#undef C #undef C

View File

@ -28,17 +28,17 @@
//============================================================================= //=============================================================================
/// Conditionally compile coverage code /// Conditionally compile coverage code
// clang-format off
#ifdef VM_COVERAGE #ifdef VM_COVERAGE
# define VL_IF_COVER(stmts) \ # define VL_IF_COVER(stmts) \
do { \ do { stmts; } while (false)
stmts; \
} while (false)
#else #else
# define VL_IF_COVER(stmts) \ # define VL_IF_COVER(stmts) \
do { \ do { \
if (false) { stmts; } \ if (false) { stmts; } \
} while (false) } while (false)
#endif #endif
// clang-format on
//============================================================================= //=============================================================================
/// Insert a item for coverage analysis. /// Insert a item for coverage analysis.
@ -69,15 +69,16 @@
/// } /// }
#define VL_COVER_INSERT(countp, ...) \ #define VL_COVER_INSERT(countp, ...) \
VL_IF_COVER(VerilatedCov::_inserti(countp); \ VL_IF_COVER(VerilatedCov::_inserti(countp); VerilatedCov::_insertf(__FILE__, __LINE__); \
VerilatedCov::_insertf(__FILE__, __LINE__); \
VerilatedCov::_insertp("hier", name(), __VA_ARGS__)) VerilatedCov::_insertp("hier", name(), __VA_ARGS__))
//============================================================================= //=============================================================================
/// Convert VL_COVER_INSERT value arguments to strings /// Convert VL_COVER_INSERT value arguments to strings
template <class T> std::string vlCovCvtToStr(const T& t) VL_PURE { template <class T> std::string vlCovCvtToStr(const T& t) VL_PURE {
std::ostringstream os; os<<t; return os.str(); 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 { class VerilatedCov {
VL_UNCOPYABLE(VerilatedCov); VL_UNCOPYABLE(VerilatedCov);
public: public:
// GLOBAL METHODS // GLOBAL METHODS
/// Return default filename /// Return default filename
@ -112,14 +114,14 @@ public:
#define A(n) const char *key##n, const char *valp##n // Argument list #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 #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(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) 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),
,A(10),D(11),D(12),D(13),D(14),D(15),D(16),D(17),D(18),D(19)); 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) 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(10),A(11),A(12),A(13),A(14),A(15),A(16),A(17),A(18),A(19) A(12), A(13), A(14), A(15), A(16), A(17), A(18), A(19), A(20), D(21),
,A(20),D(21),D(22),D(23),D(24),D(25),D(26),D(27),D(28),D(29)); D(22), D(23), D(24), D(25), D(26), D(27), D(28), D(29));
// Backward compatibility for Verilator // Backward compatibility for Verilator
static void _insertp(A(0), A(1), K(2),int val2, K(3),int val3, static void _insertp(A(0), A(1), K(2), int val2, K(3), int val3, K(4), const std::string& val4,
K(4),const std::string& val4, A(5),A(6)); A(5), A(6));
#undef K #undef K
#undef A #undef A

View File

@ -28,6 +28,7 @@
#define VLCOVGEN_ITEM(string_parsed_by_vlcovgen) #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=>'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=>'col1_name', short=>'C1', group=>1, default=>undef, ")
VLCOVGEN_ITEM("name=>'col2_name', short=>'C2', 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=>'row2', short=>'r2', group=>0, default=>undef, ")
VLCOVGEN_ITEM("name=>'row3', short=>'r3', 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'") 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 // VLCOVGEN_CIK_AUTO_EDIT_BEGIN
#define VL_CIK_COL0 "c0" #define VL_CIK_COL0 "c0"

View File

@ -42,28 +42,24 @@
VL_FATAL_MT(__FILE__, __LINE__, "", \ 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(...) \ #define _VL_SVDPI_WARN(...) VL_PRINTF_MT(__VA_ARGS__)
VL_PRINTF_MT(__VA_ARGS__)
// Function requires a "context" in the import declaration // Function requires a "context" in the import declaration
#define _VL_SVDPI_CONTEXT_WARN() \ #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 // DPI ROUTINES
const char* svDpiVersion() { const char* svDpiVersion() { return "1800-2005"; }
return "1800-2005";
}
//====================================================================== //======================================================================
// Bit-select utility functions. // Bit-select utility functions.
svBit svGetBitselBit(const svBitVecVal* sp, int bit) { svBit svGetBitselBit(const svBitVecVal* sp, int bit) { return VL_BITRSHIFT_W(sp, bit) & 1; }
return VL_BITRSHIFT_W(sp,bit) & 1;
}
svLogic svGetBitselLogic(const svLogicVecVal* sp, int bit) { svLogic svGetBitselLogic(const svLogicVecVal* sp, int bit) {
// Not VL_BITRSHIFT_W as sp is a different structure type // Not VL_BITRSHIFT_W as sp is a different structure type
// Verilator doesn't support X/Z so only aval // Verilator doesn't support X/Z so only aval
@ -71,16 +67,12 @@ svLogic svGetBitselLogic(const svLogicVecVal* sp, int bit) {
| (((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) { void svPutBitselBit(svBitVecVal* dp, int bit, svBit s) { VL_ASSIGNBIT_WI(32, bit, dp, s); }
VL_ASSIGNBIT_WI(32, bit, dp, s);
}
void svPutBitselLogic(svLogicVecVal* dp, int bit, svLogic s) { void svPutBitselLogic(svLogicVecVal* dp, int bit, svLogic s) {
// Verilator doesn't support X/Z so only aval // Verilator doesn't support X/Z so only aval
dp[VL_BITWORD_I(bit)].aval dp[VL_BITWORD_I(bit)].aval = ((dp[VL_BITWORD_I(bit)].aval & ~(VL_UL(1) << VL_BITBIT_I(bit)))
= ((dp[VL_BITWORD_I(bit)].aval & ~(VL_UL(1)<<VL_BITBIT_I(bit)))
| ((s & 1) << VL_BITBIT_I(bit))); | ((s & 1) << VL_BITBIT_I(bit)));
dp[VL_BITWORD_I(bit)].bval dp[VL_BITWORD_I(bit)].bval = ((dp[VL_BITWORD_I(bit)].bval & ~(VL_UL(1) << VL_BITBIT_I(bit)))
= ((dp[VL_BITWORD_I(bit)].bval & ~(VL_UL(1)<<VL_BITBIT_I(bit)))
| ((s & 2) >> 1 << VL_BITBIT_I(bit))); | ((s & 2) >> 1 << VL_BITBIT_I(bit)));
} }
@ -140,8 +132,7 @@ void svPutPartselBit(svBitVecVal* dp, const svBitVecVal s, int lbit, int width)
if (hoffset == VL_SIZEBITS_I && loffset == 0) { if (hoffset == VL_SIZEBITS_I && loffset == 0) {
// Fast and common case, word based insertion // Fast and common case, word based insertion
dp[VL_BITWORD_I(lbit)] = s; dp[VL_BITWORD_I(lbit)] = s;
} } else {
else {
int hword = VL_BITWORD_I(hbit); int hword = VL_BITWORD_I(hbit);
int lword = VL_BITWORD_I(lbit); int lword = VL_BITWORD_I(lbit);
if (hword == lword) { // know < 32 bits because above checks it if (hword == lword) { // know < 32 bits because above checks it
@ -165,8 +156,7 @@ void svPutPartselLogic(svLogicVecVal* dp, const svLogicVecVal s, int lbit, int w
// Fast and common case, word based insertion // Fast and common case, word based insertion
dp[VL_BITWORD_I(lbit)].aval = s.aval; dp[VL_BITWORD_I(lbit)].aval = s.aval;
dp[VL_BITWORD_I(lbit)].bval = s.bval; dp[VL_BITWORD_I(lbit)].bval = s.bval;
} } else {
else {
int hword = VL_BITWORD_I(hbit); int hword = VL_BITWORD_I(hbit);
int lword = VL_BITWORD_I(lbit); int lword = VL_BITWORD_I(lbit);
if (hword == lword) { // know < 32 bits because above checks it if (hword == lword) { // know < 32 bits because above checks it
@ -204,27 +194,14 @@ static inline const VerilatedDpiOpenVar* _vl_openhandle_varp(const svOpenArrayHa
//====================================================================== //======================================================================
// Open array querying functions // Open array querying functions
int svLeft(const svOpenArrayHandle h, int d) { int svLeft(const svOpenArrayHandle h, int d) { return _vl_openhandle_varp(h)->left(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 svRight(const svOpenArrayHandle h, int d) { int svHigh(const svOpenArrayHandle h, int d) { return _vl_openhandle_varp(h)->high(d); }
return _vl_openhandle_varp(h)->right(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 svLow(const svOpenArrayHandle h, int d) { int svDimensions(const svOpenArrayHandle h) { return _vl_openhandle_varp(h)->udims(); }
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 /// Return pointer to open array data, or NULL if not in IEEE standard C layout
void* svGetArrayPtr(const svOpenArrayHandle h) { void* svGetArrayPtr(const svOpenArrayHandle h) {
const VerilatedDpiOpenVar* varp = _vl_openhandle_varp(h); const VerilatedDpiOpenVar* varp = _vl_openhandle_varp(h);
@ -242,8 +219,8 @@ int svSizeOfArray(const svOpenArrayHandle h) {
//====================================================================== //======================================================================
// Open array access internals // Open array access internals
static void* _vl_sv_adjusted_datap(const VerilatedDpiOpenVar* varp, static void* _vl_sv_adjusted_datap(const VerilatedDpiOpenVar* varp, int nargs, int indx1,
int nargs, int indx1, int indx2, int indx3) { int indx2, int indx3) {
void* datap = varp->datap(); void* datap = varp->datap();
if (VL_UNLIKELY(nargs != varp->udims())) { if (VL_UNLIKELY(nargs != varp->udims())) {
_VL_SVDPI_WARN("%%Warning: DPI svOpenArrayHandle function called on" _VL_SVDPI_WARN("%%Warning: DPI svOpenArrayHandle function called on"
@ -254,7 +231,8 @@ static void* _vl_sv_adjusted_datap(const VerilatedDpiOpenVar* varp,
if (nargs >= 1) { if (nargs >= 1) {
datap = varp->datapAdjustIndex(datap, 1, indx1); datap = varp->datapAdjustIndex(datap, 1, indx1);
if (VL_UNLIKELY(!datap)) { 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)); indx1, varp->left(1), varp->right(1));
return NULL; return NULL;
} }
@ -262,7 +240,8 @@ static void* _vl_sv_adjusted_datap(const VerilatedDpiOpenVar* varp,
if (nargs >= 2) { if (nargs >= 2) {
datap = varp->datapAdjustIndex(datap, 2, indx2); datap = varp->datapAdjustIndex(datap, 2, indx2);
if (VL_UNLIKELY(!datap)) { 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)); indx2, varp->left(2), varp->right(2));
return NULL; return NULL;
} }
@ -270,7 +249,8 @@ static void* _vl_sv_adjusted_datap(const VerilatedDpiOpenVar* varp,
if (nargs >= 3) { if (nargs >= 3) {
datap = varp->datapAdjustIndex(datap, 3, indx3); datap = varp->datapAdjustIndex(datap, 3, indx3);
if (VL_UNLIKELY(!datap)) { 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)); indx1, varp->left(3), varp->right(3));
return NULL; 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) { static int _vl_sv_adjusted_bit(const VerilatedDpiOpenVar* varp, int indx) {
if (VL_UNLIKELY(indx < varp->low(0) || indx > varp->high(0))) { 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)); indx, varp->left(0), varp->right(0));
return 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 /// Return pointer to simulator open array element, or NULL if outside range
static void* _vl_svGetArrElemPtr(const svOpenArrayHandle h, static void* _vl_svGetArrElemPtr(const svOpenArrayHandle h, int nargs, int indx1, int indx2,
int nargs, int indx1, int indx2, int indx3) VL_MT_SAFE { int indx3) VL_MT_SAFE {
const VerilatedDpiOpenVar* varp = _vl_openhandle_varp(h); const VerilatedDpiOpenVar* varp = _vl_openhandle_varp(h);
if (VL_UNLIKELY(!varp->isDpiStdLayout())) return NULL; if (VL_UNLIKELY(!varp->isDpiStdLayout())) return NULL;
void* datap = _vl_sv_adjusted_datap(varp, nargs, indx1, indx2, indx3); void* datap = _vl_sv_adjusted_datap(varp, nargs, indx1, indx2, indx3);
@ -297,8 +278,8 @@ static void* _vl_svGetArrElemPtr(const svOpenArrayHandle h,
} }
/// Copy to user bit array from simulator open array /// Copy to user bit array from simulator open array
static void _vl_svGetBitArrElemVecVal(svBitVecVal* d, const svOpenArrayHandle s, static void _vl_svGetBitArrElemVecVal(svBitVecVal* d, const svOpenArrayHandle s, int nargs,
int nargs, int indx1, int indx2, int indx3) VL_MT_SAFE { int indx1, int indx2, int indx3) VL_MT_SAFE {
const VerilatedDpiOpenVar* varp = _vl_openhandle_varp(s); const VerilatedDpiOpenVar* varp = _vl_openhandle_varp(s);
void* datap = _vl_sv_adjusted_datap(varp, nargs, indx1, indx2, indx3); void* datap = _vl_sv_adjusted_datap(varp, nargs, indx1, indx2, indx3);
if (VL_UNLIKELY(!datap)) return; if (VL_UNLIKELY(!datap)) return;
@ -307,8 +288,10 @@ static void _vl_svGetBitArrElemVecVal(svBitVecVal* d, const svOpenArrayHandle s,
case VLVT_UINT16: d[0] = *(reinterpret_cast<SData*>(datap)); return; case VLVT_UINT16: d[0] = *(reinterpret_cast<SData*>(datap)); return;
case VLVT_UINT32: d[0] = *(reinterpret_cast<IData*>(datap)); return; case VLVT_UINT32: d[0] = *(reinterpret_cast<IData*>(datap)); return;
case VLVT_UINT64: { case VLVT_UINT64: {
WData lwp[2]; VL_SET_WQ(lwp, *(reinterpret_cast<QData*>(datap))); WData lwp[2];
d[0] = lwp[0]; d[1] = lwp[1]; VL_SET_WQ(lwp, *(reinterpret_cast<QData*>(datap)));
d[0] = lwp[0];
d[1] = lwp[1];
break; break;
} }
case VLVT_WDATA: { case VLVT_WDATA: {
@ -323,25 +306,38 @@ static void _vl_svGetBitArrElemVecVal(svBitVecVal* d, const svOpenArrayHandle s,
} }
} }
/// Copy to user logic array from simulator open array /// Copy to user logic array from simulator open array
static void _vl_svGetLogicArrElemVecVal(svLogicVecVal* d, const svOpenArrayHandle s, static void _vl_svGetLogicArrElemVecVal(svLogicVecVal* d, const svOpenArrayHandle s, int nargs,
int nargs, int indx1, int indx2, int indx3) VL_MT_SAFE { int indx1, int indx2, int indx3) VL_MT_SAFE {
const VerilatedDpiOpenVar* varp = _vl_openhandle_varp(s); const VerilatedDpiOpenVar* varp = _vl_openhandle_varp(s);
void* datap = _vl_sv_adjusted_datap(varp, nargs, indx1, indx2, indx3); void* datap = _vl_sv_adjusted_datap(varp, nargs, indx1, indx2, indx3);
if (VL_UNLIKELY(!datap)) return; if (VL_UNLIKELY(!datap)) return;
switch (varp->vltype()) { switch (varp->vltype()) {
case VLVT_UINT8: d[0].aval = *(reinterpret_cast<CData*>(datap)); d[0].bval=0; return; case VLVT_UINT8:
case VLVT_UINT16: d[0].aval = *(reinterpret_cast<SData*>(datap)); d[0].bval=0; return; d[0].aval = *(reinterpret_cast<CData*>(datap));
case VLVT_UINT32: d[0].aval = *(reinterpret_cast<IData*>(datap)); d[0].bval=0; return; 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: { case VLVT_UINT64: {
WData lwp[2]; VL_SET_WQ(lwp, *(reinterpret_cast<QData*>(datap))); WData lwp[2];
d[0].aval = lwp[0]; d[0].bval=0; VL_SET_WQ(lwp, *(reinterpret_cast<QData*>(datap)));
d[1].aval = lwp[1]; d[0].bval=0; d[0].aval = lwp[0];
d[0].bval = 0;
d[1].aval = lwp[1];
d[0].bval = 0;
break; break;
} }
case VLVT_WDATA: { case VLVT_WDATA: {
WDataOutP wdatap = (reinterpret_cast<WDataOutP>(datap)); WDataOutP wdatap = (reinterpret_cast<WDataOutP>(datap));
for (int i = 0; i < VL_WORDS_I(varp->packed().elements()); ++i) { for (int i = 0; i < VL_WORDS_I(varp->packed().elements()); ++i) {
d[i].aval = wdatap[i]; d[i].bval = 0; d[i].aval = wdatap[i];
d[i].bval = 0;
} }
return; return;
} }
@ -353,8 +349,8 @@ static void _vl_svGetLogicArrElemVecVal(svLogicVecVal* d, const svOpenArrayHandl
} }
/// Copy to simulator open array from from user bit array /// Copy to simulator open array from from user bit array
static void _vl_svPutBitArrElemVecVal(const svOpenArrayHandle d, const svBitVecVal* s, static void _vl_svPutBitArrElemVecVal(const svOpenArrayHandle d, const svBitVecVal* s, int nargs,
int nargs, int indx1, int indx2, int indx3) VL_MT_SAFE { int indx1, int indx2, int indx3) VL_MT_SAFE {
const VerilatedDpiOpenVar* varp = _vl_openhandle_varp(d); const VerilatedDpiOpenVar* varp = _vl_openhandle_varp(d);
void* datap = _vl_sv_adjusted_datap(varp, nargs, indx1, indx2, indx3); void* datap = _vl_sv_adjusted_datap(varp, nargs, indx1, indx2, indx3);
if (VL_UNLIKELY(!datap)) return; if (VL_UNLIKELY(!datap)) return;
@ -384,31 +380,32 @@ static void _vl_svPutLogicArrElemVecVal(const svOpenArrayHandle d, const svLogic
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_UINT16: *(reinterpret_cast<SData*>(datap)) = s[0].aval; return;
case VLVT_UINT32: *(reinterpret_cast<IData*>(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: { case VLVT_WDATA: {
WDataOutP wdatap = (reinterpret_cast<WDataOutP>(datap)); 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; return;
} }
default: 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;
} }
} }
/// Return bit from simulator open array /// Return bit from simulator open array
static svBit _vl_svGetBitArrElem(const svOpenArrayHandle s, static svBit _vl_svGetBitArrElem(const svOpenArrayHandle s, int nargs, int indx1, int indx2,
int nargs, int indx1, int indx2, int indx3, int indx4) VL_MT_SAFE { int indx3, int indx4) VL_MT_SAFE {
// One extra index supported, as need bit number // One extra index supported, as need bit number
const VerilatedDpiOpenVar* varp = _vl_openhandle_varp(s); const VerilatedDpiOpenVar* varp = _vl_openhandle_varp(s);
void* datap; void* datap;
int lsb; int lsb;
if (varp->packed().elements()) { if (varp->packed().elements()) {
datap = _vl_sv_adjusted_datap(varp, nargs - 1, indx1, indx2, indx3); datap = _vl_sv_adjusted_datap(varp, nargs - 1, indx1, indx2, indx3);
lsb = _vl_sv_adjusted_bit(varp, ((nargs==1) ? indx1 lsb = _vl_sv_adjusted_bit(
: (nargs==2) ? indx2 varp, ((nargs == 1) ? indx1 : (nargs == 2) ? indx2 : (nargs == 3) ? indx3 : indx4));
: (nargs==3) ? indx3
: indx4));
} else { } else {
datap = _vl_sv_adjusted_datap(varp, nargs, indx1, indx2, indx3); datap = _vl_sv_adjusted_datap(varp, nargs, indx1, indx2, indx3);
lsb = 0; lsb = 0;
@ -418,19 +415,21 @@ static svBit _vl_svGetBitArrElem(const svOpenArrayHandle s,
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_UINT16: return (*(reinterpret_cast<SData*>(datap)) >> lsb) & 1;
case VLVT_UINT32: return (*(reinterpret_cast<IData*>(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: { case VLVT_WDATA: {
WDataOutP wdatap = (reinterpret_cast<WDataOutP>(datap)); WDataOutP wdatap = (reinterpret_cast<WDataOutP>(datap));
return VL_BITRSHIFT_W(wdatap, lsb) & 1; return VL_BITRSHIFT_W(wdatap, lsb) & 1;
} }
default: 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; return 0;
} }
} }
/// Update simulator open array from bit /// Update simulator open array from bit
static void _vl_svPutBitArrElem(const svOpenArrayHandle d, svBit value, static void _vl_svPutBitArrElem(const svOpenArrayHandle d, svBit value, int nargs, int indx1,
int nargs, int indx1, int indx2, int indx3, int indx4) VL_MT_SAFE { int indx2, int indx3, int indx4) VL_MT_SAFE {
// One extra index supported, as need bit number // One extra index supported, as need bit number
value &= 1; // Make sure clean value &= 1; // Make sure clean
const VerilatedDpiOpenVar* varp = _vl_openhandle_varp(d); const VerilatedDpiOpenVar* varp = _vl_openhandle_varp(d);
@ -438,10 +437,8 @@ static void _vl_svPutBitArrElem(const svOpenArrayHandle d, svBit value,
int lsb; int lsb;
if (varp->packed().elements()) { if (varp->packed().elements()) {
datap = _vl_sv_adjusted_datap(varp, nargs - 1, indx1, indx2, indx3); datap = _vl_sv_adjusted_datap(varp, nargs - 1, indx1, indx2, indx3);
lsb = _vl_sv_adjusted_bit(varp, ((nargs==1) ? indx1 lsb = _vl_sv_adjusted_bit(
: (nargs==2) ? indx2 varp, ((nargs == 1) ? indx1 : (nargs == 2) ? indx2 : (nargs == 3) ? indx3 : indx4));
: (nargs==3) ? indx3
: indx4));
} else { } else {
datap = _vl_sv_adjusted_datap(varp, nargs, indx1, indx2, indx3); datap = _vl_sv_adjusted_datap(varp, nargs, indx1, indx2, indx3);
lsb = 0; lsb = 0;
@ -454,7 +451,8 @@ static void _vl_svPutBitArrElem(const svOpenArrayHandle d, svBit value,
case VLVT_UINT64: VL_ASSIGNBIT_QI(-1, lsb, *(reinterpret_cast<QData*>(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: 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;
} }
} }
@ -470,10 +468,17 @@ void* svGetArrElemPtr(const svOpenArrayHandle h, int indx1, ...) {
// va_arg is a macro, so need temporaries as used below // va_arg is a macro, so need temporaries as used below
switch (varp->udims()) { switch (varp->udims()) {
case 1: datap = _vl_svGetArrElemPtr(h, 1, indx1, 0, 0); break; case 1: datap = _vl_svGetArrElemPtr(h, 1, indx1, 0, 0); break;
case 2: { int indx2=va_arg(ap,int); case 2: {
datap = _vl_svGetArrElemPtr(h, 2, indx1, indx2, 0); break; } int indx2 = va_arg(ap, int);
case 3: { int indx2=va_arg(ap,int); int indx3=va_arg(ap,int); datap = _vl_svGetArrElemPtr(h, 2, indx1, indx2, 0);
datap = _vl_svGetArrElemPtr(h, 3, indx1, indx2, indx3); break; } 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 default: datap = _vl_svGetArrElemPtr(h, -1, 0, 0, 0); break; // Will error
} }
va_end(ap); 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); return _vl_svGetArrElemPtr(h, 3, indx1, indx2, indx3);
} }
void svPutBitArrElemVecVal(const svOpenArrayHandle d, const svBitVecVal* s, void svPutBitArrElemVecVal(const svOpenArrayHandle d, const svBitVecVal* s, int indx1, ...) {
int indx1, ...) {
const VerilatedDpiOpenVar* varp = _vl_openhandle_varp(d); const VerilatedDpiOpenVar* varp = _vl_openhandle_varp(d);
va_list ap; va_list ap;
va_start(ap, indx1); va_start(ap, indx1);
switch (varp->udims()) { switch (varp->udims()) {
case 1: _vl_svPutBitArrElemVecVal(d, s, 1, indx1, 0, 0); break; case 1: _vl_svPutBitArrElemVecVal(d, s, 1, indx1, 0, 0); break;
case 2: { int indx2=va_arg(ap,int); case 2: {
_vl_svPutBitArrElemVecVal(d, s, 2, indx1, indx2, 0); break; } int indx2 = va_arg(ap, int);
case 3: { int indx2=va_arg(ap,int); int indx3=va_arg(ap,int); _vl_svPutBitArrElemVecVal(d, s, 2, indx1, indx2, 0);
_vl_svPutBitArrElemVecVal(d, s, 3, indx1, indx2, indx3); break; } 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 default: _vl_svPutBitArrElemVecVal(d, s, -1, 0, 0, 0); break; // Will error
} }
va_end(ap); va_end(ap);
} }
void svPutBitArrElem1VecVal(const svOpenArrayHandle d, const svBitVecVal* s, void svPutBitArrElem1VecVal(const svOpenArrayHandle d, const svBitVecVal* s, int indx1) {
int indx1) {
_vl_svPutBitArrElemVecVal(d, s, 1, indx1, 0, 0); _vl_svPutBitArrElemVecVal(d, s, 1, indx1, 0, 0);
} }
void svPutBitArrElem2VecVal(const svOpenArrayHandle d, const svBitVecVal* s, void svPutBitArrElem2VecVal(const svOpenArrayHandle d, const svBitVecVal* s, int indx1,
int indx1, int indx2) { int indx2) {
_vl_svPutBitArrElemVecVal(d, s, 2, indx1, indx2, 0); _vl_svPutBitArrElemVecVal(d, s, 2, indx1, indx2, 0);
} }
void svPutBitArrElem3VecVal(const svOpenArrayHandle d, const svBitVecVal* s, void svPutBitArrElem3VecVal(const svOpenArrayHandle d, const svBitVecVal* s, int indx1, int indx2,
int indx1, int indx2, int indx3) { int indx3) {
_vl_svPutBitArrElemVecVal(d, s, 3, indx1, indx2, indx3); _vl_svPutBitArrElemVecVal(d, s, 3, indx1, indx2, indx3);
} }
void svPutLogicArrElemVecVal(const svOpenArrayHandle d, const svLogicVecVal* s, void svPutLogicArrElemVecVal(const svOpenArrayHandle d, const svLogicVecVal* s, int indx1, ...) {
int indx1, ...) {
const VerilatedDpiOpenVar* varp = _vl_openhandle_varp(d); const VerilatedDpiOpenVar* varp = _vl_openhandle_varp(d);
va_list ap; va_list ap;
va_start(ap, indx1); va_start(ap, indx1);
switch (varp->udims()) { switch (varp->udims()) {
case 1: _vl_svPutLogicArrElemVecVal(d, s, 1, indx1, 0, 0); break; case 1: _vl_svPutLogicArrElemVecVal(d, s, 1, indx1, 0, 0); break;
case 2: { int indx2=va_arg(ap,int); case 2: {
_vl_svPutLogicArrElemVecVal(d, s, 2, indx1, indx2, 0); break; } int indx2 = va_arg(ap, int);
case 3: { int indx2=va_arg(ap,int); int indx3=va_arg(ap,int); _vl_svPutLogicArrElemVecVal(d, s, 2, indx1, indx2, 0);
_vl_svPutLogicArrElemVecVal(d, s, 3, indx1, indx2, indx3); break; } 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 default: _vl_svPutLogicArrElemVecVal(d, s, -1, 0, 0, 0); break; // Will error
} }
va_end(ap); va_end(ap);
} }
void svPutLogicArrElem1VecVal(const svOpenArrayHandle d, const svLogicVecVal* s, void svPutLogicArrElem1VecVal(const svOpenArrayHandle d, const svLogicVecVal* s, int indx1) {
int indx1) {
_vl_svPutLogicArrElemVecVal(d, s, 1, indx1, 0, 0); _vl_svPutLogicArrElemVecVal(d, s, 1, indx1, 0, 0);
} }
void svPutLogicArrElem2VecVal(const svOpenArrayHandle d, const svLogicVecVal* s, void svPutLogicArrElem2VecVal(const svOpenArrayHandle d, const svLogicVecVal* s, int indx1,
int indx1, int indx2) { int indx2) {
_vl_svPutLogicArrElemVecVal(d, s, 2, indx1, indx2, 0); _vl_svPutLogicArrElemVecVal(d, s, 2, indx1, indx2, 0);
} }
void svPutLogicArrElem3VecVal(const svOpenArrayHandle d, const svLogicVecVal* s, void svPutLogicArrElem3VecVal(const svOpenArrayHandle d, const svLogicVecVal* s, int indx1,
int indx1, int indx2, int indx3) { int indx2, int indx3) {
_vl_svPutLogicArrElemVecVal(d, s, 3, indx1, indx2, indx3); _vl_svPutLogicArrElemVecVal(d, s, 3, indx1, indx2, indx3);
} }
//====================================================================== //======================================================================
// From simulator storage into user space // From simulator storage into user space
void svGetBitArrElemVecVal(svBitVecVal* d, const svOpenArrayHandle s, void svGetBitArrElemVecVal(svBitVecVal* d, const svOpenArrayHandle s, int indx1, ...) {
int indx1, ...) {
const VerilatedDpiOpenVar* varp = _vl_openhandle_varp(s); const VerilatedDpiOpenVar* varp = _vl_openhandle_varp(s);
va_list ap; va_list ap;
va_start(ap, indx1); va_start(ap, indx1);
switch (varp->udims()) { switch (varp->udims()) {
case 1: _vl_svGetBitArrElemVecVal(d, s, 1, indx1, 0, 0); break; case 1: _vl_svGetBitArrElemVecVal(d, s, 1, indx1, 0, 0); break;
case 2: { int indx2=va_arg(ap,int); case 2: {
_vl_svGetBitArrElemVecVal(d, s, 2, indx1, indx2, 0); break; } int indx2 = va_arg(ap, int);
case 3: { int indx2=va_arg(ap,int); int indx3=va_arg(ap,int); _vl_svGetBitArrElemVecVal(d, s, 2, indx1, indx2, 0);
_vl_svGetBitArrElemVecVal(d, s, 3, indx1, indx2, indx3); break; } 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 default: _vl_svGetBitArrElemVecVal(d, s, -1, 0, 0, 0); break; // Will error
} }
va_end(ap); va_end(ap);
} }
void svGetBitArrElem1VecVal(svBitVecVal* d, const svOpenArrayHandle s, void svGetBitArrElem1VecVal(svBitVecVal* d, const svOpenArrayHandle s, int indx1) {
int indx1) {
_vl_svGetBitArrElemVecVal(d, s, 1, indx1, 0, 0); _vl_svGetBitArrElemVecVal(d, s, 1, indx1, 0, 0);
} }
void svGetBitArrElem2VecVal(svBitVecVal* d, const svOpenArrayHandle s, void svGetBitArrElem2VecVal(svBitVecVal* d, const svOpenArrayHandle s, int indx1, int indx2) {
int indx1, int indx2) {
_vl_svGetBitArrElemVecVal(d, s, 2, indx1, indx2, 0); _vl_svGetBitArrElemVecVal(d, s, 2, indx1, indx2, 0);
} }
void svGetBitArrElem3VecVal(svBitVecVal* d, const svOpenArrayHandle s, void svGetBitArrElem3VecVal(svBitVecVal* d, const svOpenArrayHandle s, int indx1, int indx2,
int indx1, int indx2, int indx3) { int indx3) {
_vl_svGetBitArrElemVecVal(d, s, 3, indx1, indx2, indx3); _vl_svGetBitArrElemVecVal(d, s, 3, indx1, indx2, indx3);
} }
void svGetLogicArrElemVecVal(svLogicVecVal* d, const svOpenArrayHandle s, void svGetLogicArrElemVecVal(svLogicVecVal* d, const svOpenArrayHandle s, int indx1, ...) {
int indx1, ...) {
const VerilatedDpiOpenVar* varp = _vl_openhandle_varp(s); const VerilatedDpiOpenVar* varp = _vl_openhandle_varp(s);
va_list ap; va_list ap;
va_start(ap, indx1); va_start(ap, indx1);
switch (varp->udims()) { switch (varp->udims()) {
case 1: _vl_svGetLogicArrElemVecVal(d, s, 1, indx1, 0, 0); break; case 1: _vl_svGetLogicArrElemVecVal(d, s, 1, indx1, 0, 0); break;
case 2: { int indx2=va_arg(ap,int); case 2: {
_vl_svGetLogicArrElemVecVal(d, s, 2, indx1, indx2, 0); break; } int indx2 = va_arg(ap, int);
case 3: { int indx2=va_arg(ap,int); int indx3=va_arg(ap,int); _vl_svGetLogicArrElemVecVal(d, s, 2, indx1, indx2, 0);
_vl_svGetLogicArrElemVecVal(d, s, 3, indx1, indx2, indx3); break; } 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 default: _vl_svGetLogicArrElemVecVal(d, s, -1, 0, 0, 0); break; // Will error
} }
va_end(ap); va_end(ap);
} }
void svGetLogicArrElem1VecVal(svLogicVecVal* d, const svOpenArrayHandle s, void svGetLogicArrElem1VecVal(svLogicVecVal* d, const svOpenArrayHandle s, int indx1) {
int indx1) {
_vl_svGetLogicArrElemVecVal(d, s, 1, indx1, 0, 0); _vl_svGetLogicArrElemVecVal(d, s, 1, indx1, 0, 0);
} }
void svGetLogicArrElem2VecVal(svLogicVecVal* d, const svOpenArrayHandle s, void svGetLogicArrElem2VecVal(svLogicVecVal* d, const svOpenArrayHandle s, int indx1, int indx2) {
int indx1, int indx2) {
_vl_svGetLogicArrElemVecVal(d, s, 2, indx1, indx2, 0); _vl_svGetLogicArrElemVecVal(d, s, 2, indx1, indx2, 0);
} }
void svGetLogicArrElem3VecVal(svLogicVecVal* d, const svOpenArrayHandle s, void svGetLogicArrElem3VecVal(svLogicVecVal* d, const svOpenArrayHandle s, int indx1, int indx2,
int indx1, int indx2, int indx3) { int indx3) {
_vl_svGetLogicArrElemVecVal(d, s, 3, indx1, indx2, indx3); _vl_svGetLogicArrElemVecVal(d, s, 3, indx1, indx2, indx3);
} }
@ -609,12 +632,24 @@ svBit svGetBitArrElem(const svOpenArrayHandle s, int indx1, ...) {
va_start(ap, indx1); va_start(ap, indx1);
switch (varp->udims()) { switch (varp->udims()) {
case 1: out = _vl_svGetBitArrElem(s, 1, indx1, 0, 0, 0); break; case 1: out = _vl_svGetBitArrElem(s, 1, indx1, 0, 0, 0); break;
case 2: { int indx2=va_arg(ap,int); case 2: {
out = _vl_svGetBitArrElem(s, 2, indx1, indx2, 0, 0); break; } int indx2 = va_arg(ap, int);
case 3: { int indx2=va_arg(ap,int); int indx3=va_arg(ap,int); out = _vl_svGetBitArrElem(s, 2, indx1, indx2, 0, 0);
out = _vl_svGetBitArrElem(s, 3, indx1, indx2, indx3, 0); break; } 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 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 default: out = _vl_svGetBitArrElem(s, -1, 0, 0, 0, 0); break; // Will error
} }
va_end(ap); va_end(ap);
@ -637,12 +672,24 @@ svLogic svGetLogicArrElem(const svOpenArrayHandle s, int indx1, ...) {
va_start(ap, indx1); va_start(ap, indx1);
switch (varp->udims()) { switch (varp->udims()) {
case 1: out = _vl_svGetBitArrElem(s, 1, indx1, 0, 0, 0); break; case 1: out = _vl_svGetBitArrElem(s, 1, indx1, 0, 0, 0); break;
case 2: { int indx2=va_arg(ap,int); case 2: {
out = _vl_svGetBitArrElem(s, 2, indx1, indx2, 0, 0); break; } int indx2 = va_arg(ap, int);
case 3: { int indx2=va_arg(ap,int); int indx3=va_arg(ap,int); out = _vl_svGetBitArrElem(s, 2, indx1, indx2, 0, 0);
out = _vl_svGetBitArrElem(s, 3, indx1, indx2, indx3, 0); break; } 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 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 default: out = _vl_svGetBitArrElem(s, -1, 0, 0, 0, 0); break; // Will error
} }
va_end(ap); va_end(ap);
@ -667,12 +714,24 @@ void svPutBitArrElem(const svOpenArrayHandle d, svBit value, int indx1, ...) {
va_start(ap, indx1); va_start(ap, indx1);
switch (varp->udims()) { switch (varp->udims()) {
case 1: _vl_svPutBitArrElem(d, value, 1, indx1, 0, 0, 0); break; case 1: _vl_svPutBitArrElem(d, value, 1, indx1, 0, 0, 0); break;
case 2: { int indx2=va_arg(ap,int); case 2: {
_vl_svPutBitArrElem(d, value, 2, indx1, indx2, 0, 0); break; } int indx2 = va_arg(ap, int);
case 3: { int indx2=va_arg(ap,int); int indx3=va_arg(ap,int); _vl_svPutBitArrElem(d, value, 2, indx1, indx2, 0, 0);
_vl_svPutBitArrElem(d, value, 3, indx1, indx2, indx3, 0); break; } 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 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 default: _vl_svPutBitArrElem(d, value, -1, 0, 0, 0, 0); break; // Will error
} }
va_end(ap); va_end(ap);
@ -693,12 +752,24 @@ void svPutLogicArrElem(const svOpenArrayHandle d, svLogic value, int indx1, ...)
va_start(ap, indx1); va_start(ap, indx1);
switch (varp->udims()) { switch (varp->udims()) {
case 1: _vl_svPutBitArrElem(d, value, 1, indx1, 0, 0, 0); break; case 1: _vl_svPutBitArrElem(d, value, 1, indx1, 0, 0, 0); break;
case 2: { int indx2=va_arg(ap,int); case 2: {
_vl_svPutBitArrElem(d, value, 2, indx1, indx2, 0, 0); break; } int indx2 = va_arg(ap, int);
case 3: { int indx2=va_arg(ap,int); int indx3=va_arg(ap,int); _vl_svPutBitArrElem(d, value, 2, indx1, indx2, 0, 0);
_vl_svPutBitArrElem(d, value, 3, indx1, indx2, indx3, 0); break; } 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 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 default: _vl_svPutBitArrElem(d, value, -1, 0, 0, 0, 0); break; // Will error
} }
va_end(ap); 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 // Verilator doesn't support X/Z so can just call Bit version
svPutBitArrElem1(d, value, indx1); svPutBitArrElem1(d, value, indx1);
} }
void svPutLogicArrElem2(const svOpenArrayHandle d, svLogic value, void svPutLogicArrElem2(const svOpenArrayHandle d, svLogic value, int indx1, int indx2) {
int indx1, int indx2) {
// Verilator doesn't support X/Z so can just call Bit version // Verilator doesn't support X/Z so can just call Bit version
svPutBitArrElem2(d, value, indx1, indx2); svPutBitArrElem2(d, value, indx1, indx2);
} }
void svPutLogicArrElem3(const svOpenArrayHandle d, svLogic value, void svPutLogicArrElem3(const svOpenArrayHandle d, svLogic value, int indx1, int indx2,
int indx1, int indx2, int indx3) { int indx3) {
// Verilator doesn't support X/Z so can just call Bit version // Verilator doesn't support X/Z so can just call Bit version
svPutBitArrElem3(d, value, indx1, indx2, indx3); svPutBitArrElem3(d, value, indx1, indx2, indx3);
} }
@ -722,7 +792,10 @@ void svPutLogicArrElem3(const svOpenArrayHandle d, svLogic value,
// Functions for working with DPI context // Functions for working with DPI context
svScope svGetScope() { 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) // NOLINTNEXTLINE(google-readability-casting)
return (svScope)(Verilated::dpiScope()); return (svScope)(Verilated::dpiScope());
} }
@ -755,7 +828,10 @@ void* svGetUserData(const svScope scope, void* userKey) {
} }
int svGetCallerInfo(const char** fileNamepp, int* lineNumberp) { int svGetCallerInfo(const char** fileNamepp, int* lineNumberp) {
if (VL_UNLIKELY(!Verilated::dpiInContext())) { _VL_SVDPI_CONTEXT_WARN(); return false; } if (VL_UNLIKELY(!Verilated::dpiInContext())) {
_VL_SVDPI_CONTEXT_WARN();
return false;
}
if (VL_LIKELY(fileNamepp)) *fileNamepp = Verilated::dpiFilenamep(); // thread local if (VL_LIKELY(fileNamepp)) *fileNamepp = Verilated::dpiFilenamep(); // thread local
if (VL_LIKELY(lineNumberp)) *lineNumberp = Verilated::dpiLineno(); // thread local if (VL_LIKELY(lineNumberp)) *lineNumberp = Verilated::dpiLineno(); // thread local
return true; return true;

View File

@ -35,29 +35,21 @@
/// Convert svBitVecVal to Verilator internal data /// Convert svBitVecVal to Verilator internal data
static inline void VL_SET_W_SVBV(int obits, WDataOutP owp, const svBitVecVal* lwp) VL_MT_SAFE { static inline void VL_SET_W_SVBV(int obits, WDataOutP owp, const svBitVecVal* lwp) VL_MT_SAFE {
int words = VL_WORDS_I(obits); int words = VL_WORDS_I(obits);
for (int i = 0; i < words - 1; ++i) { for (int i = 0; i < words - 1; ++i) owp[i] = lwp[i];
owp[i] = lwp[i];
}
owp[words - 1] = lwp[words - 1] & VL_MASK_I(obits); owp[words - 1] = lwp[words - 1] & VL_MASK_I(obits);
} }
static inline QData VL_SET_Q_SVBV(const svBitVecVal* lwp) VL_MT_SAFE { static inline QData VL_SET_Q_SVBV(const svBitVecVal* lwp) VL_MT_SAFE {
return _VL_SET_QII(lwp[1], lwp[0]); return _VL_SET_QII(lwp[1], lwp[0]);
} }
static inline IData VL_SET_I_SVBV(const svBitVecVal* lwp) VL_MT_SAFE { static inline IData VL_SET_I_SVBV(const svBitVecVal* lwp) VL_MT_SAFE { return lwp[0]; }
return lwp[0];
}
/// Convert Verilator internal data to svBitVecVal /// Convert Verilator internal data to svBitVecVal
static inline void VL_SET_SVBV_W(int obits, svBitVecVal* owp, WDataInP lwp) VL_MT_SAFE { static inline void VL_SET_SVBV_W(int obits, svBitVecVal* owp, WDataInP lwp) VL_MT_SAFE {
int words = VL_WORDS_I(obits); int words = VL_WORDS_I(obits);
for (int i = 0; i < words - 1; ++i) { for (int i = 0; i < words - 1; ++i) owp[i] = lwp[i];
owp[i] = lwp[i];
}
owp[words - 1] = lwp[words - 1] & VL_MASK_I(obits); 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 { static inline void VL_SET_SVBV_I(int, svBitVecVal* owp, IData ld) VL_MT_SAFE { owp[0] = ld; }
owp[0] = ld;
}
static inline void VL_SET_SVBV_Q(int, svBitVecVal* owp, QData ld) VL_MT_SAFE { static inline void VL_SET_SVBV_Q(int, svBitVecVal* owp, QData ld) VL_MT_SAFE {
VL_SET_WQ(owp, ld); 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 /// 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 { static inline void VL_SET_W_SVLV(int obits, WDataOutP owp, const svLogicVecVal* lwp) VL_MT_SAFE {
int words = VL_WORDS_I(obits); int words = VL_WORDS_I(obits);
for (int i = 0; i < words - 1; ++i) { for (int i = 0; i < words - 1; ++i) owp[i] = lwp[i].aval;
owp[i] = lwp[i].aval;
}
owp[words - 1] = lwp[words - 1].aval & VL_MASK_I(obits); owp[words - 1] = lwp[words - 1].aval & VL_MASK_I(obits);
} }
static inline QData VL_SET_Q_SVLV(const svLogicVecVal* lwp) VL_MT_SAFE { static inline QData VL_SET_Q_SVLV(const svLogicVecVal* lwp) VL_MT_SAFE {
return _VL_SET_QII(lwp[1].aval, lwp[0].aval); return _VL_SET_QII(lwp[1].aval, lwp[0].aval);
} }
static inline IData VL_SET_I_SVLV(const svLogicVecVal* lwp) VL_MT_SAFE { static inline IData VL_SET_I_SVLV(const svLogicVecVal* lwp) VL_MT_SAFE { return lwp[0].aval; }
return lwp[0].aval;
}
/// Convert Verilator internal data to svLogicVecVal /// Convert Verilator internal data to svLogicVecVal
/// Note these functions never create X/Z in 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 { static inline void VL_SET_SVLV_W(int obits, svLogicVecVal* owp, WDataInP lwp) VL_MT_SAFE {
int words = VL_WORDS_I(obits); int words = VL_WORDS_I(obits);
for (int i = 0; i < words; ++i) { for (int i = 0; i < words; ++i) owp[i].bval = 0;
owp[i].bval = 0; for (int i = 0; i < words - 1; ++i) owp[i].aval = lwp[i];
}
for (int i = 0; i < words - 1; ++i) {
owp[i].aval = lwp[i];
}
owp[words - 1].aval = lwp[words - 1] & VL_MASK_I(obits); 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 { 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 // be protected by other means
// //
// clang-format off
#if (defined(_MSC_VER) && _MSC_VER >= 1900) || (__cplusplus >= 201103L) #if (defined(_MSC_VER) && _MSC_VER >= 1900) || (__cplusplus >= 201103L)
# define VlClassRef std::shared_ptr # define VlClassRef std::shared_ptr
#else #else
# define VlClassRef VlClassRef__SystemVerilog_class_support_requires_a_C11_or_newer_compiler # define VlClassRef VlClassRef__SystemVerilog_class_support_requires_a_C11_or_newer_compiler
#endif #endif
// clang-format on
template <class T> // T typically of type VlClassRef<x> template <class T> // T typically of type VlClassRef<x>
inline T VL_NULL_CHECK(T t, const char* filename, int linenum) { 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 { inline std::string VL_REPLICATEN_NNQ(int, int, int, const std::string& lhs, IData rep) VL_PURE {
std::string out; std::string out;
out.reserve(lhs.length() * rep); out.reserve(lhs.length() * rep);
for (unsigned times = 0; times < rep; ++times) { for (unsigned times = 0; times < rep; ++times) out += lhs;
out += lhs;
}
return out; return out;
} }
inline std::string VL_REPLICATEN_NNI(int obits, int lbits, int rbits, const std::string& lhs, 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_ #ifndef _VERILATED_IMP_H_
#define _VERILATED_IMP_H_ 1 ///< Header Guard #define _VERILATED_IMP_H_ 1 ///< Header Guard
// clang-format off
#if !defined(_VERILATED_CPP_) && !defined(_VERILATED_DPI_CPP_) && !defined(_VERILATED_VPI_CPP_) #if !defined(_VERILATED_CPP_) && !defined(_VERILATED_DPI_CPP_) && !defined(_VERILATED_VPI_CPP_)
# error "verilated_imp.h only to be included by verilated*.cpp internals" # error "verilated_imp.h only to be included by verilated*.cpp internals"
#endif #endif
@ -35,6 +36,7 @@
# include <functional> # include <functional>
# include <queue> # include <queue>
#endif #endif
// clang-format on
class VerilatedScope; class VerilatedScope;
@ -48,8 +50,10 @@ public:
// TYPES // TYPES
struct Cmp { struct Cmp {
bool operator()(const VerilatedMsg& a, const VerilatedMsg& b) const { bool operator()(const VerilatedMsg& a, const VerilatedMsg& b) const {
return a.mtaskId() < b.mtaskId(); } return a.mtaskId() < b.mtaskId();
}
}; };
private: private:
// MEMBERS // MEMBERS
vluint32_t m_mtaskId; ///< MTask that did enqueue vluint32_t m_mtaskId; ///< MTask that did enqueue
@ -86,6 +90,7 @@ public:
private: private:
VL_UNCOPYABLE(VerilatedEvalMsgQueue); VL_UNCOPYABLE(VerilatedEvalMsgQueue);
public: public:
// METHODS // METHODS
//// Add message to queue (called by producer) //// 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 /// Each thread has a local queue to build up messages until the end of the eval() call
class VerilatedThreadMsgQueue { class VerilatedThreadMsgQueue {
std::queue<VerilatedMsg> m_queue; std::queue<VerilatedMsg> m_queue;
public: public:
// CONSTRUCTORS // CONSTRUCTORS
VerilatedThreadMsgQueue() {} VerilatedThreadMsgQueue() {}
@ -129,6 +135,7 @@ public:
// The only call of this with a non-empty queue is a fatal error. // 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. // So this does not flush the queue, as the destination queue is not known to this class.
} }
private: private:
VL_UNCOPYABLE(VerilatedThreadMsgQueue); VL_UNCOPYABLE(VerilatedThreadMsgQueue);
// METHODS // METHODS
@ -136,6 +143,7 @@ private:
static VL_THREAD_LOCAL VerilatedThreadMsgQueue t_s; static VL_THREAD_LOCAL VerilatedThreadMsgQueue t_s;
return t_s; return t_s;
} }
public: public:
/// Add message to queue, called by producer /// Add message to queue, called by producer
static void post(const VerilatedMsg& msg) VL_MT_SAFE { static void post(const VerilatedMsg& msg) VL_MT_SAFE {
@ -177,27 +185,32 @@ class VerilatedImp {
// Nothing here is save-restored; users expected to re-register appropriately // Nothing here is save-restored; users expected to re-register appropriately
VerilatedMutex m_argMutex; ///< Protect m_argVec, m_argVecLoaded 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) /// 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 bool m_argVecLoaded VL_GUARDED_BY(m_argMutex); ///< Ever loaded argument list
VerilatedMutex m_userMapMutex; ///< Protect m_userMap VerilatedMutex m_userMapMutex; ///< Protect m_userMap
UserMap m_userMap VL_GUARDED_BY(m_userMapMutex); ///< Map of <(scope,userkey), userData> UserMap m_userMap VL_GUARDED_BY(m_userMapMutex); ///< Map of <(scope,userkey), userData>
VerilatedMutex m_nameMutex; ///< Protect m_nameMap VerilatedMutex m_nameMutex; ///< Protect m_nameMap
VerilatedScopeNameMap m_nameMap VL_GUARDED_BY(m_nameMutex); ///< Map of <scope_name, scope pointer> /// Map of <scope_name, scope pointer>
VerilatedScopeNameMap m_nameMap VL_GUARDED_BY(m_nameMutex);
VerilatedMutex m_hierMapMutex; ///< Protect m_hierMap VerilatedMutex m_hierMapMutex; ///< Protect m_hierMap
VerilatedHierarchyMap m_hierMap VL_GUARDED_BY(m_hierMapMutex); ///< Map the represents scope hierarchy /// Map the represents scope hierarchy
VerilatedHierarchyMap m_hierMap VL_GUARDED_BY(m_hierMapMutex);
// Slow - somewhat static: // Slow - somewhat static:
VerilatedMutex m_exportMutex; ///< Protect m_nameMap VerilatedMutex m_exportMutex; ///< Protect m_nameMap
ExportNameMap m_exportMap VL_GUARDED_BY(m_exportMutex); ///< Map of <export_func_proto, func number> /// 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 int m_exportNext VL_GUARDED_BY(m_exportMutex); ///< Next export funcnum
// File I/O // File I/O
VerilatedMutex m_fdMutex; ///< Protect m_fdps, m_fdFree VerilatedMutex m_fdMutex; ///< Protect m_fdps, m_fdFree
std::vector<FILE*> m_fdps VL_GUARDED_BY(m_fdMutex); ///< File descriptors 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) /// List of free descriptors (SLOW - FOPEN/CLOSE only)
std::deque<IData> m_fdFree VL_GUARDED_BY(m_fdMutex);
public: // But only for verilated*.cpp public: // But only for verilated*.cpp
// CONSTRUCTORS // CONSTRUCTORS
@ -210,8 +223,10 @@ public: // But only for verilated*.cpp
m_fdps[2] = stderr; m_fdps[2] = stderr;
} }
~VerilatedImp() {} ~VerilatedImp() {}
private: private:
VL_UNCOPYABLE(VerilatedImp); VL_UNCOPYABLE(VerilatedImp);
public: public:
// METHODS - debug // METHODS - debug
static void internalsDump() VL_MT_SAFE; static void internalsDump() VL_MT_SAFE;
@ -238,11 +253,12 @@ public:
} }
return ""; return "";
} }
private: private:
static void commandArgsAddGuts(int argc, const char** argv) VL_REQUIRES(s_s.m_argMutex); static void commandArgsAddGuts(int argc, const char** argv) VL_REQUIRES(s_s.m_argMutex);
static void commandArgVl(const std::string& arg); static void commandArgVl(const std::string& arg);
static bool commandArgVlValue(const std::string& arg, static bool commandArgVlValue(const std::string& arg, const std::string& prefix,
const std::string& prefix, std::string& valuer); std::string& valuer);
public: public:
// METHODS - user scope tracking // METHODS - user scope tracking
@ -252,16 +268,19 @@ public:
static inline void userInsert(const void* scopep, void* userKey, void* userData) VL_MT_SAFE { static inline void userInsert(const void* scopep, void* userKey, void* userData) VL_MT_SAFE {
VerilatedLockGuard lock(s_s.m_userMapMutex); VerilatedLockGuard lock(s_s.m_userMapMutex);
UserMap::iterator it = s_s.m_userMap.find(std::make_pair(scopep, userKey)); UserMap::iterator it = s_s.m_userMap.find(std::make_pair(scopep, userKey));
if (it != s_s.m_userMap.end()) it->second = userData; if (it != s_s.m_userMap.end()) {
// When we support VL_THREADs, we need a lock around this insert, as it's runtime it->second = userData;
else s_s.m_userMap.insert(it, std::make_pair(std::make_pair(scopep, userKey), 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 { static inline void* userFind(const void* scopep, void* userKey) VL_MT_SAFE {
VerilatedLockGuard lock(s_s.m_userMapMutex); VerilatedLockGuard lock(s_s.m_userMapMutex);
UserMap::const_iterator it = s_s.m_userMap.find(std::make_pair(scopep, userKey)); 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; if (VL_UNLIKELY(it == s_s.m_userMap.end())) return NULL;
else return NULL; return it->second;
} }
private: private:
/// Symbol table destruction cleans up the entries for each scope. /// Symbol table destruction cleans up the entries for each scope.
static void userEraseScope(const VerilatedScope* scopep) VL_MT_SAFE { static void userEraseScope(const VerilatedScope* scopep) VL_MT_SAFE {
@ -279,9 +298,12 @@ private:
VerilatedLockGuard lock(s_s.m_userMapMutex); // Avoid it changing in middle of dump VerilatedLockGuard lock(s_s.m_userMapMutex); // Avoid it changing in middle of dump
bool first = true; bool first = true;
for (UserMap::const_iterator it = s_s.m_userMap.begin(); it != s_s.m_userMap.end(); ++it) { 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; } if (first) {
VL_PRINTF_MT(" DPI_USER_DATA scope %p key %p: %p\n", VL_PRINTF_MT(" userDump:\n");
it->first.first, it->first.second, it->second); first = false;
}
VL_PRINTF_MT(" DPI_USER_DATA scope %p key %p: %p\n", it->first.first,
it->first.second, it->second);
} }
} }
@ -299,8 +321,8 @@ public: // But only for verilated*.cpp
VerilatedLockGuard lock(s_s.m_nameMutex); VerilatedLockGuard lock(s_s.m_nameMutex);
// If too slow, can assume this is only VL_MT_SAFE_POSINIT // If too slow, can assume this is only VL_MT_SAFE_POSINIT
VerilatedScopeNameMap::const_iterator it = s_s.m_nameMap.find(namep); VerilatedScopeNameMap::const_iterator it = s_s.m_nameMap.find(namep);
if (VL_LIKELY(it != s_s.m_nameMap.end())) return it->second; if (VL_UNLIKELY(it == s_s.m_nameMap.end())) return NULL;
else return NULL; return it->second;
} }
static void scopeErase(const VerilatedScope* scopep) VL_MT_SAFE { static void scopeErase(const VerilatedScope* scopep) VL_MT_SAFE {
// Slow ok - called once/scope at destruction // Slow ok - called once/scope at destruction
@ -379,7 +401,10 @@ public: // But only for verilated*.cpp
bool first = true; bool first = true;
for (ExportNameMap::const_iterator it = s_s.m_exportMap.begin(); for (ExportNameMap::const_iterator it = s_s.m_exportMap.begin();
it != s_s.m_exportMap.end(); ++it) { it != s_s.m_exportMap.end(); ++it) {
if (first) { VL_PRINTF_MT(" exportDump:\n"); first=false; } if (first) {
VL_PRINTF_MT(" exportDump:\n");
first = false;
}
VL_PRINTF_MT(" DPI_EXPORT_NAME %05d: %s\n", it->second, it->first); VL_PRINTF_MT(" DPI_EXPORT_NAME %05d: %s\n", it->second, it->first);
} }
} }
@ -396,9 +421,12 @@ public: // But only for verilated*.cpp
// Need to create more space in m_fdps and m_fdFree // Need to create more space in m_fdps and m_fdFree
size_t start = s_s.m_fdps.size(); size_t start = s_s.m_fdps.size();
s_s.m_fdps.resize(start * 2); 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)); 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; s_s.m_fdps[idx] = fp;
return (idx | (1UL << 31)); // bit 31 indicates not MCD return (idx | (1UL << 31)); // bit 31 indicates not MCD
} }

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -31,6 +31,7 @@
void VerilatedVcdSc::write_comment(const std::string&) {} void VerilatedVcdSc::write_comment(const std::string&) {}
void VerilatedVcdSc::trace(const unsigned int&, const std::string&, const char**) {} void VerilatedVcdSc::trace(const unsigned int&, const std::string&, const char**) {}
// clang-format off
# define DECL_TRACE_METHOD_A(tp) \ # 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) \ # define DECL_TRACE_METHOD_B(tp) \
@ -73,6 +74,7 @@ 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_bv_base )
DECL_TRACE_METHOD_A( sc_dt::sc_lv_base ) DECL_TRACE_METHOD_A( sc_dt::sc_lv_base )
// clang-format on
//-------------------------------------------------- //--------------------------------------------------
#elif (SYSTEMC_VERSION > 20011000) #elif (SYSTEMC_VERSION > 20011000)
@ -86,6 +88,7 @@ void VerilatedVcdSc::trace(const unsigned int&, const sc_string&, const char**)
#define DECL_TRACE_METHOD_B(tp) \ #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( bool )
DECL_TRACE_METHOD_A( sc_bit ) DECL_TRACE_METHOD_A( sc_bit )
DECL_TRACE_METHOD_A( sc_logic ) DECL_TRACE_METHOD_A( sc_logic )
@ -116,6 +119,7 @@ void VerilatedVcdSc::trace(const unsigned int&, const sc_string&, const char**)
DECL_TRACE_METHOD_A( sc_fxnum_fast ) DECL_TRACE_METHOD_A( sc_fxnum_fast )
DECL_TRACE_METHOD_A( sc_bv_base ) DECL_TRACE_METHOD_A( sc_bv_base )
DECL_TRACE_METHOD_A( sc_lv_base ) DECL_TRACE_METHOD_A( sc_lv_base )
// clang-format on
//-------------------------------------------------- //--------------------------------------------------
#else #else
@ -129,6 +133,7 @@ void VerilatedVcdSc::trace(const unsigned int&, const sc_string&, const char**)
#define DECL_TRACE_METHOD_B(tp) \ #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( bool )
DECL_TRACE_METHOD_B( unsigned char ) DECL_TRACE_METHOD_B( unsigned char )
DECL_TRACE_METHOD_B( short unsigned int ) 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_signal_resolved_vector )
DECL_TRACE_METHOD_A( sc_bv_ns::sc_bv_base ) DECL_TRACE_METHOD_A( sc_bv_ns::sc_bv_base )
DECL_TRACE_METHOD_A( sc_bv_ns::sc_lv_base ) DECL_TRACE_METHOD_A( sc_bv_ns::sc_lv_base )
// clang-format on
#endif #endif
#undef DECL_TRACE_METHOD_A #undef DECL_TRACE_METHOD_A

View File

@ -31,12 +31,10 @@
/// This class is passed to the SystemC simulation kernel, just like a /// This class is passed to the SystemC simulation kernel, just like a
/// documented SystemC trace format. /// documented SystemC trace format.
class VerilatedVcdSc class VerilatedVcdSc : sc_trace_file, public VerilatedVcdC {
: sc_trace_file
, public VerilatedVcdC
{
// CONSTRUCTORS // CONSTRUCTORS
VL_UNCOPYABLE(VerilatedVcdSc); VL_UNCOPYABLE(VerilatedVcdSc);
public: public:
VerilatedVcdSc() { VerilatedVcdSc() {
sc_get_curr_simcontext()->add_trace_file(this); sc_get_curr_simcontext()->add_trace_file(this);
@ -82,18 +80,18 @@ private:
virtual void set_time_unit(double v, sc_time_unit tu) {} virtual void set_time_unit(double v, sc_time_unit tu) {}
#endif #endif
//-------------------------------------------------- //--------------------------------------------------
#if (SYSTEMC_VERSION >= 20050714) #if (SYSTEMC_VERSION >= 20050714)
// SystemC 2.1.v1 // SystemC 2.1.v1
# define DECL_TRACE_METHOD_A(tp) \ // clang-format off
virtual void trace(const tp& object, const std::string& name); # define DECL_TRACE_METHOD_A(tp) virtual void trace(const tp& object, const std::string& name);
# define DECL_TRACE_METHOD_B(tp) \ # define DECL_TRACE_METHOD_B(tp) \
virtual void trace(const tp& object, const std::string& name, int width); virtual void trace(const tp& object, const std::string& name, int width);
virtual void write_comment(const std::string&); virtual void write_comment(const std::string&);
virtual void trace(const unsigned int&, const std::string&, const char**); virtual void trace(const unsigned int&, const std::string&, const char**);
// Formatting matches that of sc_trace.h
# if (SYSTEMC_VERSION >= 20171012) # if (SYSTEMC_VERSION >= 20171012)
DECL_TRACE_METHOD_A( sc_event ) DECL_TRACE_METHOD_A( sc_event )
DECL_TRACE_METHOD_A( sc_time ) DECL_TRACE_METHOD_A( sc_time )
@ -131,12 +129,13 @@ private:
DECL_TRACE_METHOD_A( sc_dt::sc_bv_base ) DECL_TRACE_METHOD_A( sc_dt::sc_bv_base )
DECL_TRACE_METHOD_A( sc_dt::sc_lv_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 // SystemC 2.0.1
# define DECL_TRACE_METHOD_A(tp) \ // clang-format off
virtual void trace(const tp& object, const sc_string& name); # define DECL_TRACE_METHOD_A(tp) virtual void trace(const tp& object, const sc_string& name);
# define DECL_TRACE_METHOD_B(tp) \ # define DECL_TRACE_METHOD_B(tp) \
virtual void trace(const tp& object, const sc_string& name, int width); virtual void trace(const tp& object, const sc_string& name, int width);
@ -175,12 +174,13 @@ private:
DECL_TRACE_METHOD_A( sc_fxnum_fast ) DECL_TRACE_METHOD_A( sc_fxnum_fast )
DECL_TRACE_METHOD_A( sc_bv_base ) DECL_TRACE_METHOD_A( sc_bv_base )
DECL_TRACE_METHOD_A( sc_lv_base ) DECL_TRACE_METHOD_A( sc_lv_base )
// clang-format on
//-------------------------------------------------- //--------------------------------------------------
#else #else
// SystemC 1.2.1beta // SystemC 1.2.1beta
# define DECL_TRACE_METHOD_A(tp) \ // clang-format off
virtual void trace(const tp& object, const sc_string& name); # define DECL_TRACE_METHOD_A(tp) virtual void trace(const tp& object, const sc_string& name);
# define DECL_TRACE_METHOD_B(tp) \ # define DECL_TRACE_METHOD_B(tp) \
virtual void trace(const tp& object, const sc_string& name, int width); virtual void trace(const tp& object, const sc_string& name, int width);
@ -213,6 +213,7 @@ private:
DECL_TRACE_METHOD_A( sc_bv_ns::sc_bv_base ) DECL_TRACE_METHOD_A( sc_bv_ns::sc_bv_base )
DECL_TRACE_METHOD_A( sc_bv_ns::sc_lv_base ) DECL_TRACE_METHOD_A( sc_bv_ns::sc_lv_base )
# endif # endif
// clang-format on
#undef DECL_TRACE_METHOD_A #undef DECL_TRACE_METHOD_A
#undef DECL_TRACE_METHOD_B #undef DECL_TRACE_METHOD_B

View File

@ -23,9 +23,6 @@
#define _VERILATED_VPI_CPP_ #define _VERILATED_VPI_CPP_
#if VM_SC
# include "verilated_sc.h"
#endif
#include "verilated.h" #include "verilated.h"
#include "verilated_vpi.h" #include "verilated_vpi.h"
#include "verilated_imp.h" #include "verilated_imp.h"
@ -109,10 +106,12 @@ class VerilatedVpioCb : public VerilatedVpio {
t_cb_data m_cbData; t_cb_data m_cbData;
s_vpi_value m_value; s_vpi_value m_value;
QData m_time; QData m_time;
public: public:
// cppcheck-suppress uninitVar // m_value // cppcheck-suppress uninitVar // m_value
VerilatedVpioCb(const t_cb_data* cbDatap, QData time) VerilatedVpioCb(const t_cb_data* cbDatap, QData time)
: m_cbData(*cbDatap), m_time(time) { : m_cbData(*cbDatap)
, m_time(time) {
m_value.format = cbDatap->value ? cbDatap->value->format : vpiSuppressVal; m_value.format = cbDatap->value ? cbDatap->value->format : vpiSuppressVal;
m_cbData.value = &m_value; m_cbData.value = &m_value;
} }
@ -129,8 +128,10 @@ public:
class VerilatedVpioConst : public VerilatedVpio { class VerilatedVpioConst : public VerilatedVpio {
vlsint32_t m_num; vlsint32_t m_num;
public: public:
explicit VerilatedVpioConst(vlsint32_t num) : m_num(num) {} explicit VerilatedVpioConst(vlsint32_t num)
: m_num(num) {}
virtual ~VerilatedVpioConst() {} virtual ~VerilatedVpioConst() {}
static inline VerilatedVpioConst* castp(vpiHandle h) { static inline VerilatedVpioConst* castp(vpiHandle h) {
return dynamic_cast<VerilatedVpioConst*>(reinterpret_cast<VerilatedVpio*>(h)); return dynamic_cast<VerilatedVpioConst*>(reinterpret_cast<VerilatedVpio*>(h));
@ -142,8 +143,11 @@ public:
class VerilatedVpioRange : public VerilatedVpio { class VerilatedVpioRange : public VerilatedVpio {
const VerilatedRange* m_range; const VerilatedRange* m_range;
vlsint32_t m_iteration; vlsint32_t m_iteration;
public: public:
explicit VerilatedVpioRange(const VerilatedRange* range) : m_range(range), m_iteration(0) {} explicit VerilatedVpioRange(const VerilatedRange* range)
: m_range(range)
, m_iteration(0) {}
virtual ~VerilatedVpioRange() {} virtual ~VerilatedVpioRange() {}
static inline VerilatedVpioRange* castp(vpiHandle h) { static inline VerilatedVpioRange* castp(vpiHandle h) {
return dynamic_cast<VerilatedVpioRange*>(reinterpret_cast<VerilatedVpio*>(h)); return dynamic_cast<VerilatedVpioRange*>(reinterpret_cast<VerilatedVpio*>(h));
@ -166,6 +170,7 @@ public:
class VerilatedVpioScope : public VerilatedVpio { class VerilatedVpioScope : public VerilatedVpio {
protected: protected:
const VerilatedScope* m_scopep; const VerilatedScope* m_scopep;
public: public:
explicit VerilatedVpioScope(const VerilatedScope* scopep) explicit VerilatedVpioScope(const VerilatedScope* scopep)
: m_scopep(scopep) {} : m_scopep(scopep) {}
@ -195,9 +200,12 @@ protected:
// Determine number of dimensions and return outermost // Determine number of dimensions and return outermost
return (m_varp->dims() > 1) ? m_varp->unpacked() : m_varp->packed(); return (m_varp->dims() > 1) ? m_varp->unpacked() : m_varp->packed();
} }
public: public:
VerilatedVpioVar(const VerilatedVar* varp, const VerilatedScope* scopep) VerilatedVpioVar(const VerilatedVar* varp, const VerilatedScope* scopep)
: m_varp(varp), m_scopep(scopep), m_index(0) { : m_varp(varp)
, m_scopep(scopep)
, m_index(0) {
m_prevDatap = NULL; m_prevDatap = NULL;
m_mask.u32 = VL_MASK_I(varp->packed().elements()); m_mask.u32 = VL_MASK_I(varp->packed().elements());
m_entSize = varp->entSize(); m_entSize = varp->entSize();
@ -253,7 +261,8 @@ public:
virtual const VerilatedRange* rangep() const { return &(varp()->packed()); } virtual const VerilatedRange* rangep() const { return &(varp()->packed()); }
virtual const char* fullname() const { virtual const char* fullname() const {
static VL_THREAD_LOCAL std::string out; static VL_THREAD_LOCAL std::string out;
char num[20]; sprintf(num, "%d", m_index); char num[20];
sprintf(num, "%d", m_index);
out = std::string(scopep()->name()) + "." + name() + "[" + num + "]"; out = std::string(scopep()->name()) + "." + name() + "[" + num + "]";
return out.c_str(); return out.c_str();
} }
@ -263,9 +272,11 @@ class VerilatedVpioVarIter : public VerilatedVpio {
const VerilatedScope* m_scopep; const VerilatedScope* m_scopep;
VerilatedVarNameMap::const_iterator m_it; VerilatedVarNameMap::const_iterator m_it;
bool m_started; bool m_started;
public: public:
explicit VerilatedVpioVarIter(const VerilatedScope* scopep) explicit VerilatedVpioVarIter(const VerilatedScope* scopep)
: m_scopep(scopep), m_started(false) { } : m_scopep(scopep)
, m_started(false) {}
virtual ~VerilatedVpioVarIter() {} virtual ~VerilatedVpioVarIter() {}
static inline VerilatedVpioVarIter* castp(vpiHandle h) { static inline VerilatedVpioVarIter* castp(vpiHandle h) {
return dynamic_cast<VerilatedVpioVarIter*>(reinterpret_cast<VerilatedVpio*>(h)); return dynamic_cast<VerilatedVpioVarIter*>(reinterpret_cast<VerilatedVpio*>(h));
@ -274,12 +285,16 @@ public:
virtual vpiHandle dovpi_scan() { virtual vpiHandle dovpi_scan() {
if (VL_LIKELY(m_scopep->varsp())) { if (VL_LIKELY(m_scopep->varsp())) {
VerilatedVarNameMap* varsp = m_scopep->varsp(); VerilatedVarNameMap* varsp = m_scopep->varsp();
if (VL_UNLIKELY(!m_started)) { m_it = varsp->begin(); m_started=true; } if (VL_UNLIKELY(!m_started)) {
else if (VL_UNLIKELY(m_it == varsp->end())) return 0; m_it = varsp->begin();
else ++m_it; m_started = true;
} else if (VL_UNLIKELY(m_it == varsp->end())) {
return 0;
} else {
++m_it;
}
if (m_it == varsp->end()) return 0; if (m_it == varsp->end()) return 0;
return ((new VerilatedVpioVar(&(m_it->second), m_scopep)) return ((new VerilatedVpioVar(&(m_it->second), m_scopep))->castVpiHandle());
->castVpiHandle());
} }
return 0; // End of list - only one deep return 0; // End of list - only one deep
} }
@ -291,21 +306,21 @@ class VerilatedVpioMemoryWordIter : public VerilatedVpio {
vlsint32_t m_iteration; vlsint32_t m_iteration;
vlsint32_t m_direction; vlsint32_t m_direction;
bool m_done; bool m_done;
public: public:
VerilatedVpioMemoryWordIter(const vpiHandle handle, const VerilatedVar* varp) VerilatedVpioMemoryWordIter(const vpiHandle handle, const VerilatedVar* varp)
: m_handle(handle), m_varp(varp), m_iteration(varp->unpacked().right()), : m_handle(handle)
m_direction(VL_LIKELY(varp->unpacked().left() > varp->unpacked().right()) , m_varp(varp)
? 1 : -1), , m_iteration(varp->unpacked().right())
m_done(false) { } , m_direction(VL_LIKELY(varp->unpacked().left() > varp->unpacked().right()) ? 1 : -1)
, m_done(false) {}
virtual ~VerilatedVpioMemoryWordIter() {} virtual ~VerilatedVpioMemoryWordIter() {}
static inline VerilatedVpioMemoryWordIter* castp(vpiHandle h) { static inline VerilatedVpioMemoryWordIter* castp(vpiHandle h) {
return dynamic_cast<VerilatedVpioMemoryWordIter*>(reinterpret_cast<VerilatedVpio*>(h)); return dynamic_cast<VerilatedVpioMemoryWordIter*>(reinterpret_cast<VerilatedVpio*>(h));
} }
virtual vluint32_t type() const { return vpiIterator; } virtual vluint32_t type() const { return vpiIterator; }
void iterationInc() { void iterationInc() {
if (!(m_done = (m_iteration == m_varp->unpacked().left()))) { if (!(m_done = (m_iteration == m_varp->unpacked().left()))) m_iteration += m_direction;
m_iteration += m_direction;
}
} }
virtual vpiHandle dovpi_scan() { virtual vpiHandle dovpi_scan() {
vpiHandle result; vpiHandle result;
@ -319,6 +334,7 @@ public:
class VerilatedVpioModule : public VerilatedVpioScope { class VerilatedVpioModule : public VerilatedVpioScope {
const char* m_name; const char* m_name;
const char* m_fullname; const char* m_fullname;
public: public:
explicit VerilatedVpioModule(const VerilatedScope* modulep) explicit VerilatedVpioModule(const VerilatedScope* modulep)
: VerilatedVpioScope(modulep) { : VerilatedVpioScope(modulep) {
@ -337,8 +353,10 @@ public:
class VerilatedVpioModuleIter : public VerilatedVpio { class VerilatedVpioModuleIter : public VerilatedVpio {
const std::vector<const VerilatedScope*>* m_vec; const std::vector<const VerilatedScope*>* m_vec;
std::vector<const VerilatedScope*>::const_iterator m_it; std::vector<const VerilatedScope*>::const_iterator m_it;
public: public:
explicit VerilatedVpioModuleIter(const std::vector<const VerilatedScope*>& vec) : m_vec(&vec) { explicit VerilatedVpioModuleIter(const std::vector<const VerilatedScope*>& vec)
: m_vec(&vec) {
m_it = m_vec->begin(); m_it = m_vec->begin();
} }
virtual ~VerilatedVpioModuleIter() {} virtual ~VerilatedVpioModuleIter() {}
@ -347,9 +365,7 @@ public:
} }
virtual vluint32_t type() const { return vpiIterator; } virtual vluint32_t type() const { return vpiIterator; }
virtual vpiHandle dovpi_scan() { virtual vpiHandle dovpi_scan() {
if (m_it == m_vec->end()) { if (m_it == m_vec->end()) return 0;
return 0;
}
const VerilatedScope* modp = *m_it++; const VerilatedScope* modp = *m_it++;
return (new VerilatedVpioModule(modp))->castVpiHandle(); return (new VerilatedVpioModule(modp))->castVpiHandle();
} }
@ -413,9 +429,7 @@ public:
} }
static void cbTimedRemove(VerilatedVpioCb* cbp) { static void cbTimedRemove(VerilatedVpioCb* cbp) {
VpioTimedCbs::iterator it = s_s.m_timedCbs.find(std::make_pair(cbp->time(), cbp)); VpioTimedCbs::iterator it = s_s.m_timedCbs.find(std::make_pair(cbp->time(), cbp));
if (VL_LIKELY(it != s_s.m_timedCbs.end())) { if (VL_LIKELY(it != s_s.m_timedCbs.end())) { s_s.m_timedCbs.erase(it); }
s_s.m_timedCbs.erase(it);
}
} }
static void callTimedCbs() VL_MT_UNSAFE_ONE { static void callTimedCbs() VL_MT_UNSAFE_ONE {
assertOneCheck(); assertOneCheck();
@ -428,15 +442,14 @@ public:
s_s.m_timedCbs.erase(last_it); s_s.m_timedCbs.erase(last_it);
VL_DEBUG_IF_PLI(VL_DBG_MSGF("- vpi: timed_callback %p\n", vop);); VL_DEBUG_IF_PLI(VL_DBG_MSGF("- vpi: timed_callback %p\n", vop););
(vop->cb_rtnp())(vop->cb_datap()); (vop->cb_rtnp())(vop->cb_datap());
} else {
++it;
} }
else { ++it; }
} }
} }
static QData cbNextDeadline() { static QData cbNextDeadline() {
VpioTimedCbs::const_iterator it = s_s.m_timedCbs.begin(); VpioTimedCbs::const_iterator it = s_s.m_timedCbs.begin();
if (VL_LIKELY(it != s_s.m_timedCbs.end())) { if (VL_LIKELY(it != s_s.m_timedCbs.end())) return it->first;
return it->first;
}
return ~VL_ULL(0); // maxquad return ~VL_ULL(0); // maxquad
} }
static bool callCbs(vluint32_t reason) VL_MT_UNSAFE_ONE { static bool callCbs(vluint32_t reason) VL_MT_UNSAFE_ONE {
@ -469,12 +482,11 @@ public:
void* newDatap = varop->varDatap(); void* newDatap = varop->varDatap();
void* prevDatap = varop->prevDatap(); // Was malloced when we added the callback void* prevDatap = varop->prevDatap(); // Was malloced when we added the callback
VL_DEBUG_IF_PLI(VL_DBG_MSGF("- vpi: value_test %s v[0]=%d/%d %p %p\n", VL_DEBUG_IF_PLI(VL_DBG_MSGF("- vpi: value_test %s v[0]=%d/%d %p %p\n",
varop->fullname(), varop->fullname(), *((CData*)newDatap),
*((CData*)newDatap), *((CData*)prevDatap), *((CData*)prevDatap), newDatap, prevDatap););
newDatap, prevDatap););
if (memcmp(prevDatap, newDatap, varop->entSize()) != 0) { if (memcmp(prevDatap, newDatap, varop->entSize()) != 0) {
VL_DEBUG_IF_PLI(VL_DBG_MSGF("- vpi: value_callback %p %s v[0]=%d\n", VL_DEBUG_IF_PLI(VL_DBG_MSGF("- vpi: value_callback %p %s v[0]=%d\n", vop,
vop, varop->fullname(), *((CData*)newDatap));); varop->fullname(), *((CData*)newDatap)););
update.insert(varop); update.insert(varop);
vpi_get_value(vop->cb_datap()->obj, vop->cb_datap()->value); vpi_get_value(vop->cb_datap()->obj, vop->cb_datap()->value);
(vop->cb_rtnp())(vop->cb_datap()); (vop->cb_rtnp())(vop->cb_datap());
@ -512,9 +524,10 @@ class VerilatedVpiError {
// as it will be overwritten. // as it will be overwritten.
VerilatedVpiImp::callCbs(cbPLIError); VerilatedVpiImp::callCbs(cbPLIError);
} }
public:
VerilatedVpiError() : m_flag(false) { public:
VerilatedVpiError()
: m_flag(false) {
m_buff[0] = '\0'; m_buff[0] = '\0';
m_errorInfo.product = const_cast<PLI_BYTE8*>(Verilated::productName()); m_errorInfo.product = const_cast<PLI_BYTE8*>(Verilated::productName());
} }
@ -565,30 +578,22 @@ VL_THREAD_LOCAL vluint8_t* VerilatedVpio::t_freeHead = NULL;
//====================================================================== //======================================================================
// VerilatedVpi implementation // VerilatedVpi implementation
void VerilatedVpi::callTimedCbs() VL_MT_UNSAFE_ONE { void VerilatedVpi::callTimedCbs() VL_MT_UNSAFE_ONE { VerilatedVpiImp::callTimedCbs(); }
VerilatedVpiImp::callTimedCbs();
}
void VerilatedVpi::callValueCbs() VL_MT_UNSAFE_ONE { void VerilatedVpi::callValueCbs() VL_MT_UNSAFE_ONE { VerilatedVpiImp::callValueCbs(); }
VerilatedVpiImp::callValueCbs();
}
bool VerilatedVpi::callCbs(vluint32_t reason) VL_MT_UNSAFE_ONE { bool VerilatedVpi::callCbs(vluint32_t reason) VL_MT_UNSAFE_ONE {
return VerilatedVpiImp::callCbs(reason); return VerilatedVpiImp::callCbs(reason);
} }
QData VerilatedVpi::cbNextDeadline() VL_MT_UNSAFE_ONE { QData VerilatedVpi::cbNextDeadline() VL_MT_UNSAFE_ONE { return VerilatedVpiImp::cbNextDeadline(); }
return VerilatedVpiImp::cbNextDeadline();
}
//====================================================================== //======================================================================
// VerilatedVpiImp implementation // VerilatedVpiImp implementation
VerilatedVpiError* VerilatedVpiImp::error_info() VL_MT_UNSAFE_ONE { VerilatedVpiError* VerilatedVpiImp::error_info() VL_MT_UNSAFE_ONE {
VerilatedVpiImp::assertOneCheck(); VerilatedVpiImp::assertOneCheck();
if (VL_UNLIKELY(!s_s.m_errorInfop)) { if (VL_UNLIKELY(!s_s.m_errorInfop)) { s_s.m_errorInfop = new VerilatedVpiError(); }
s_s.m_errorInfop = new VerilatedVpiError();
}
return s_s.m_errorInfop; return s_s.m_errorInfop;
} }
@ -596,6 +601,7 @@ VerilatedVpiError* VerilatedVpiImp::error_info() VL_MT_UNSAFE_ONE {
// VerilatedVpiError Methods // VerilatedVpiError Methods
const char* VerilatedVpiError::strFromVpiVal(PLI_INT32 vpiVal) VL_MT_SAFE { const char* VerilatedVpiError::strFromVpiVal(PLI_INT32 vpiVal) VL_MT_SAFE {
// clang-format off
static const char* const names[] = { static const char* const names[] = {
"*undefined*", "*undefined*",
"vpiBinStrVal", "vpiBinStrVal",
@ -617,10 +623,12 @@ const char* VerilatedVpiError::strFromVpiVal(PLI_INT32 vpiVal) VL_MT_SAFE {
"vpiRawTwoStateVal", "vpiRawTwoStateVal",
"vpiRawFourStateVal", "vpiRawFourStateVal",
}; };
// clang-format on
if (vpiVal < 0) return names[0]; if (vpiVal < 0) return names[0];
return names[(vpiVal <= vpiRawFourStateVal) ? vpiVal : 0]; return names[(vpiVal <= vpiRawFourStateVal) ? vpiVal : 0];
} }
const char* VerilatedVpiError::strFromVpiObjType(PLI_INT32 vpiVal) VL_MT_SAFE { const char* VerilatedVpiError::strFromVpiObjType(PLI_INT32 vpiVal) VL_MT_SAFE {
// clang-format off
static const char* const names[] = { static const char* const names[] = {
"*undefined*", "*undefined*",
"vpiAlways", "vpiAlways",
@ -759,10 +767,12 @@ const char* VerilatedVpiError::strFromVpiObjType(PLI_INT32 vpiVal) VL_MT_SAFE {
"vpiGenScope", "vpiGenScope",
"vpiGenVar" "vpiGenVar"
}; };
// clang-format on
if (vpiVal < 0) return names[0]; if (vpiVal < 0) return names[0];
return names[(vpiVal <= vpiGenVar) ? vpiVal : 0]; return names[(vpiVal <= vpiGenVar) ? vpiVal : 0];
} }
const char* VerilatedVpiError::strFromVpiMethod(PLI_INT32 vpiVal) VL_MT_SAFE { const char* VerilatedVpiError::strFromVpiMethod(PLI_INT32 vpiVal) VL_MT_SAFE {
// clang-format off
static const char* const names[] = { static const char* const names[] = {
"vpiCondition", "vpiCondition",
"vpiDelay", "vpiDelay",
@ -799,13 +809,13 @@ const char* VerilatedVpiError::strFromVpiMethod(PLI_INT32 vpiVal) VL_MT_SAFE {
"vpiPrimitive", "vpiPrimitive",
"vpiStmt" "vpiStmt"
}; };
if (vpiVal>vpiStmt || vpiVal<vpiCondition) { // clang-format on
return "*undefined*"; if (vpiVal > vpiStmt || vpiVal < vpiCondition) return "*undefined*";
}
return names[vpiVal - vpiCondition]; return names[vpiVal - vpiCondition];
} }
const char* VerilatedVpiError::strFromVpiCallbackReason(PLI_INT32 vpiVal) VL_MT_SAFE { const char* VerilatedVpiError::strFromVpiCallbackReason(PLI_INT32 vpiVal) VL_MT_SAFE {
// clang-format off
static const char* const names[] = { static const char* const names[] = {
"*undefined*", "*undefined*",
"cbValueChange", "cbValueChange",
@ -840,11 +850,13 @@ const char* VerilatedVpiError::strFromVpiCallbackReason(PLI_INT32 vpiVal) VL_MT_
"cbNBASynch", "cbNBASynch",
"cbAtEndOfSimTime" "cbAtEndOfSimTime"
}; };
// clang-format on
if (vpiVal < 0) return names[0]; if (vpiVal < 0) return names[0];
return names[(vpiVal <= cbAtEndOfSimTime) ? vpiVal : 0]; return names[(vpiVal <= cbAtEndOfSimTime) ? vpiVal : 0];
} }
const char* VerilatedVpiError::strFromVpiProp(PLI_INT32 vpiVal) VL_MT_SAFE { const char* VerilatedVpiError::strFromVpiProp(PLI_INT32 vpiVal) VL_MT_SAFE {
// clang-format off
static const char* const names[] = { static const char* const names[] = {
"*undefined or other*", "*undefined or other*",
"vpiType", "vpiType",
@ -922,9 +934,8 @@ const char* VerilatedVpiError::strFromVpiProp(PLI_INT32 vpiVal) VL_MT_SAFE {
"vpiIsMemory", "vpiIsMemory",
"vpiIsProtected" "vpiIsProtected"
}; };
if (vpiVal == vpiUndefined) { // clang-format on
return "vpiUndefined"; if (vpiVal == vpiUndefined) return "vpiUndefined";
}
return names[(vpiVal <= vpiIsProtected) ? vpiVal : 0]; return names[(vpiVal <= vpiIsProtected) ? vpiVal : 0];
} }
@ -941,9 +952,7 @@ const char* VerilatedVpiError::strFromVpiProp(PLI_INT32 vpiVal) VL_MT_SAFE {
CHECK_RESULT_CSTR(strVal, #enum); \ CHECK_RESULT_CSTR(strVal, #enum); \
} while (0) } while (0)
void VerilatedVpi::selfTest() VL_MT_UNSAFE_ONE { void VerilatedVpi::selfTest() VL_MT_UNSAFE_ONE { VerilatedVpiError::selfTest(); }
VerilatedVpiError::selfTest();
}
void VerilatedVpiError::selfTest() VL_MT_UNSAFE_ONE { void VerilatedVpiError::selfTest() VL_MT_UNSAFE_ONE {
VerilatedVpiImp::assertOneCheck(); VerilatedVpiImp::assertOneCheck();
@ -1014,8 +1023,8 @@ vpiHandle vpi_register_cb(p_cb_data cb_data_p) {
return vop->castVpiHandle(); return vop->castVpiHandle();
} }
default: default:
_VL_VPI_WARNING(__FILE__, __LINE__, "%s: Unsupported callback type %s", _VL_VPI_WARNING(__FILE__, __LINE__, "%s: Unsupported callback type %s", VL_FUNC,
VL_FUNC, VerilatedVpiError::strFromVpiCallbackReason(cb_data_p->reason)); VerilatedVpiError::strFromVpiCallbackReason(cb_data_p->reason));
return NULL; return NULL;
}; };
} }
@ -1079,9 +1088,7 @@ vpiHandle vpi_handle_by_name(PLI_BYTE8* namep, vpiHandle scope) {
if (scopename.find('.') == std::string::npos) { if (scopename.find('.') == std::string::npos) {
// This is a toplevel, hence search in our TOP ports first. // This is a toplevel, hence search in our TOP ports first.
scopep = Verilated::scopeFind("TOP"); scopep = Verilated::scopeFind("TOP");
if (scopep) { if (scopep) { varp = scopep->varFind(baseNamep); }
varp = scopep->varFind(baseNamep);
}
} }
if (!varp) { if (!varp) {
scopep = Verilated::scopeFind(scopename.c_str()); scopep = Verilated::scopeFind(scopename.c_str());
@ -1103,13 +1110,15 @@ vpiHandle vpi_handle_by_index(vpiHandle object, PLI_INT32 indx) {
if (varop->varp()->dims() < 2) return 0; if (varop->varp()->dims() < 2) return 0;
if (VL_LIKELY(varop->varp()->unpacked().left() >= varop->varp()->unpacked().right())) { if (VL_LIKELY(varop->varp()->unpacked().left() >= varop->varp()->unpacked().right())) {
if (VL_UNLIKELY(indx > varop->varp()->unpacked().left() if (VL_UNLIKELY(indx > varop->varp()->unpacked().left()
|| indx < varop->varp()->unpacked().right())) return 0; || indx < varop->varp()->unpacked().right()))
return 0;
return (new VerilatedVpioMemoryWord(varop->varp(), varop->scopep(), indx, return (new VerilatedVpioMemoryWord(varop->varp(), varop->scopep(), indx,
indx - varop->varp()->unpacked().right())) indx - varop->varp()->unpacked().right()))
->castVpiHandle(); ->castVpiHandle();
} }
if (VL_UNLIKELY(indx < varop->varp()->unpacked().left() if (VL_UNLIKELY(indx < varop->varp()->unpacked().left()
|| indx > varop->varp()->unpacked().right())) return 0; || indx > varop->varp()->unpacked().right()))
return 0;
return (new VerilatedVpioMemoryWord(varop->varp(), varop->scopep(), indx, return (new VerilatedVpioMemoryWord(varop->varp(), varop->scopep(), indx,
indx - varop->varp()->unpacked().left())) indx - varop->varp()->unpacked().left()))
->castVpiHandle(); ->castVpiHandle();
@ -1176,9 +1185,9 @@ vpiHandle vpi_iterate(PLI_INT32 type, vpiHandle object) {
if (vop->varp()->dims() < 2) return 0; if (vop->varp()->dims() < 2) return 0;
if (vop->varp()->dims() > 2) { if (vop->varp()->dims() > 2) {
_VL_VPI_WARNING(__FILE__, __LINE__, _VL_VPI_WARNING(__FILE__, __LINE__,
"%s: %s, object %s has unsupported number of indices (%d)", "%s: %s, object %s has unsupported number of indices (%d)", VL_FUNC,
VL_FUNC, VerilatedVpiError::strFromVpiMethod(type), VerilatedVpiError::strFromVpiMethod(type), vop->fullname(),
vop->fullname() , vop->varp()->dims()); vop->varp()->dims());
} }
return (new VerilatedVpioMemoryWordIter(object, vop->varp()))->castVpiHandle(); return (new VerilatedVpioMemoryWordIter(object, vop->varp()))->castVpiHandle();
} }
@ -1189,17 +1198,16 @@ vpiHandle vpi_iterate(PLI_INT32 type, vpiHandle object) {
// Unsupported is multidim list // Unsupported is multidim list
if (vop->varp()->dims() > 2) { if (vop->varp()->dims() > 2) {
_VL_VPI_WARNING(__FILE__, __LINE__, _VL_VPI_WARNING(__FILE__, __LINE__,
"%s: %s, object %s has unsupported number of indices (%d)", "%s: %s, object %s has unsupported number of indices (%d)", VL_FUNC,
VL_FUNC, VerilatedVpiError::strFromVpiMethod(type), VerilatedVpiError::strFromVpiMethod(type), vop->fullname(),
vop->fullname() , vop->varp()->dims()); vop->varp()->dims());
} }
return ((new VerilatedVpioRange(vop->rangep()))->castVpiHandle()); return ((new VerilatedVpioRange(vop->rangep()))->castVpiHandle());
} }
case vpiReg: { case vpiReg: {
VerilatedVpioScope* vop = VerilatedVpioScope::castp(object); VerilatedVpioScope* vop = VerilatedVpioScope::castp(object);
if (VL_UNLIKELY(!vop)) return 0; if (VL_UNLIKELY(!vop)) return 0;
return ((new VerilatedVpioVarIter(vop->scopep())) return ((new VerilatedVpioVarIter(vop->scopep()))->castVpiHandle());
->castVpiHandle());
} }
case vpiModule: { case vpiModule: {
VerilatedVpioModule* vop = VerilatedVpioModule::castp(object); VerilatedVpioModule* vop = VerilatedVpioModule::castp(object);
@ -1338,7 +1346,8 @@ void vpi_get_value(vpiHandle object, p_vpi_value value_p) {
case VLVT_WDATA: { case VLVT_WDATA: {
int words = VL_WORDS_I(vop->varp()->packed().elements()); int words = VL_WORDS_I(vop->varp()->packed().elements());
if (VL_UNCOVERABLE(words >= VL_MULS_MAX_WORDS)) { if (VL_UNCOVERABLE(words >= VL_MULS_MAX_WORDS)) {
VL_FATAL_MT(__FILE__, __LINE__, "", VL_FATAL_MT(
__FILE__, __LINE__, "",
"vpi_get_value with more than VL_MULS_MAX_WORDS; increase and recompile"); "vpi_get_value with more than VL_MULS_MAX_WORDS; increase and recompile");
} }
WDataInP datap = (reinterpret_cast<EData*>(vop->varDatap())); WDataInP datap = (reinterpret_cast<EData*>(vop->varDatap()));
@ -1357,9 +1366,8 @@ void vpi_get_value(vpiHandle object, p_vpi_value value_p) {
return; return;
} }
default: { default: {
_VL_VPI_ERROR(__FILE__, __LINE__, "%s: Unsupported format (%s) for %s", _VL_VPI_ERROR(__FILE__, __LINE__, "%s: Unsupported format (%s) for %s", VL_FUNC,
VL_FUNC, VerilatedVpiError::strFromVpiVal(value_p->format), VerilatedVpiError::strFromVpiVal(value_p->format), vop->fullname());
vop->fullname());
return; return;
} }
} }
@ -1377,7 +1385,9 @@ void vpi_get_value(vpiHandle object, p_vpi_value value_p) {
if (bits > outStrSz) { if (bits > outStrSz) {
// limit maximum size of output to size of buffer to prevent overrun. // limit maximum size of output to size of buffer to prevent overrun.
bits = outStrSz; bits = outStrSz;
_VL_VPI_WARNING(__FILE__, __LINE__, "%s: Truncating string value of %s for %s" _VL_VPI_WARNING(
__FILE__, __LINE__,
"%s: Truncating string value of %s for %s"
" as buffer size (%d, VL_MULS_MAX_WORDS=%d) is less than required (%d)", " as buffer size (%d, VL_MULS_MAX_WORDS=%d) is less than required (%d)",
VL_FUNC, VerilatedVpiError::strFromVpiVal(value_p->format), VL_FUNC, VerilatedVpiError::strFromVpiVal(value_p->format),
vop->fullname(), outStrSz, VL_MULS_MAX_WORDS, bits); vop->fullname(), outStrSz, VL_MULS_MAX_WORDS, bits);
@ -1390,9 +1400,8 @@ void vpi_get_value(vpiHandle object, p_vpi_value value_p) {
return; return;
} }
default: default:
_VL_VPI_ERROR(__FILE__, __LINE__, "%s: Unsupported format (%s) for %s", _VL_VPI_ERROR(__FILE__, __LINE__, "%s: Unsupported format (%s) for %s", VL_FUNC,
VL_FUNC, VerilatedVpiError::strFromVpiVal(value_p->format), VerilatedVpiError::strFromVpiVal(value_p->format), vop->fullname());
vop->fullname());
return; return;
} }
} else if (value_p->format == vpiOctStrVal) { } else if (value_p->format == vpiOctStrVal) {
@ -1409,7 +1418,9 @@ void vpi_get_value(vpiHandle object, p_vpi_value value_p) {
int i; int i;
if (chars > outStrSz) { if (chars > outStrSz) {
// limit maximum size of output to size of buffer to prevent overrun. // limit maximum size of output to size of buffer to prevent overrun.
_VL_VPI_WARNING(__FILE__, __LINE__, "%s: Truncating string value of %s for %s" _VL_VPI_WARNING(
__FILE__, __LINE__,
"%s: Truncating string value of %s for %s"
" as buffer size (%d, VL_MULS_MAX_WORDS=%d) is less than required (%d)", " as buffer size (%d, VL_MULS_MAX_WORDS=%d) is less than required (%d)",
VL_FUNC, VerilatedVpiError::strFromVpiVal(value_p->format), VL_FUNC, VerilatedVpiError::strFromVpiVal(value_p->format),
vop->fullname(), outStrSz, VL_MULS_MAX_WORDS, chars); vop->fullname(), outStrSz, VL_MULS_MAX_WORDS, chars);
@ -1441,9 +1452,8 @@ void vpi_get_value(vpiHandle object, p_vpi_value value_p) {
} }
default: default:
strcpy(outStr, "0"); strcpy(outStr, "0");
_VL_VPI_ERROR(__FILE__, __LINE__, "%s: Unsupported format (%s) for %s", _VL_VPI_ERROR(__FILE__, __LINE__, "%s: Unsupported format (%s) for %s", VL_FUNC,
VL_FUNC, VerilatedVpiError::strFromVpiVal(value_p->format), VerilatedVpiError::strFromVpiVal(value_p->format), vop->fullname());
vop->fullname());
return; return;
} }
} else if (value_p->format == vpiDecStrVal) { } else if (value_p->format == vpiDecStrVal) {
@ -1451,26 +1461,31 @@ void vpi_get_value(vpiHandle object, p_vpi_value value_p) {
switch (vop->varp()->vltype()) { switch (vop->varp()->vltype()) {
// outStrSz does not include NULL termination so add one // outStrSz does not include NULL termination so add one
case VLVT_UINT8: case VLVT_UINT8:
VL_SNPRINTF(outStr, outStrSz+1, "%hhu", VL_SNPRINTF(
outStr, outStrSz + 1, "%hhu",
static_cast<unsigned char>(*(reinterpret_cast<CData*>(vop->varDatap())))); static_cast<unsigned char>(*(reinterpret_cast<CData*>(vop->varDatap()))));
return; return;
case VLVT_UINT16: case VLVT_UINT16:
VL_SNPRINTF(outStr, outStrSz+1, "%hu", VL_SNPRINTF(
outStr, outStrSz + 1, "%hu",
static_cast<unsigned short>(*(reinterpret_cast<SData*>(vop->varDatap())))); static_cast<unsigned short>(*(reinterpret_cast<SData*>(vop->varDatap()))));
return; return;
case VLVT_UINT32: case VLVT_UINT32:
VL_SNPRINTF(outStr, outStrSz+1, "%u", VL_SNPRINTF(
outStr, outStrSz + 1, "%u",
static_cast<unsigned int>(*(reinterpret_cast<IData*>(vop->varDatap())))); static_cast<unsigned int>(*(reinterpret_cast<IData*>(vop->varDatap()))));
return; return;
case VLVT_UINT64: case VLVT_UINT64:
VL_SNPRINTF(outStr, outStrSz+1, "%llu", VL_SNPRINTF(
outStr, outStrSz + 1, "%llu",
static_cast<unsigned long long>(*(reinterpret_cast<QData*>(vop->varDatap())))); static_cast<unsigned long long>(*(reinterpret_cast<QData*>(vop->varDatap()))));
return; return;
default: default:
strcpy(outStr, "-1"); strcpy(outStr, "-1");
_VL_VPI_ERROR(__FILE__, __LINE__, _VL_VPI_ERROR(__FILE__, __LINE__,
"%s: Unsupported format (%s) for %s, maximum limit is 64 bits", "%s: Unsupported format (%s) for %s, maximum limit is 64 bits",
VL_FUNC, VerilatedVpiError::strFromVpiVal(value_p->format), vop->fullname()); VL_FUNC, VerilatedVpiError::strFromVpiVal(value_p->format),
vop->fullname());
return; return;
} }
} else if (value_p->format == vpiHexStrVal) { } else if (value_p->format == vpiHexStrVal) {
@ -1486,7 +1501,9 @@ void vpi_get_value(vpiHandle object, p_vpi_value value_p) {
int i; int i;
if (chars > outStrSz) { if (chars > outStrSz) {
// limit maximum size of output to size of buffer to prevent overrun. // limit maximum size of output to size of buffer to prevent overrun.
_VL_VPI_WARNING(__FILE__, __LINE__, "%s: Truncating string value of %s for %s" _VL_VPI_WARNING(
__FILE__, __LINE__,
"%s: Truncating string value of %s for %s"
" as buffer size (%d, VL_MULS_MAX_WORDS=%d) is less than required (%d)", " as buffer size (%d, VL_MULS_MAX_WORDS=%d) is less than required (%d)",
VL_FUNC, VerilatedVpiError::strFromVpiVal(value_p->format), VL_FUNC, VerilatedVpiError::strFromVpiVal(value_p->format),
vop->fullname(), outStrSz, VL_MULS_MAX_WORDS, chars); vop->fullname(), outStrSz, VL_MULS_MAX_WORDS, chars);
@ -1509,9 +1526,8 @@ void vpi_get_value(vpiHandle object, p_vpi_value value_p) {
return; return;
} }
default: default:
_VL_VPI_ERROR(__FILE__, __LINE__, "%s: Unsupported format (%s) for %s", _VL_VPI_ERROR(__FILE__, __LINE__, "%s: Unsupported format (%s) for %s", VL_FUNC,
VL_FUNC, VerilatedVpiError::strFromVpiVal(value_p->format), VerilatedVpiError::strFromVpiVal(value_p->format), vop->fullname());
vop->fullname());
return; return;
} }
} else if (value_p->format == vpiStringVal) { } else if (value_p->format == vpiStringVal) {
@ -1527,7 +1543,9 @@ void vpi_get_value(vpiHandle object, p_vpi_value value_p) {
int i; int i;
if (bytes > outStrSz) { if (bytes > outStrSz) {
// limit maximum size of output to size of buffer to prevent overrun. // limit maximum size of output to size of buffer to prevent overrun.
_VL_VPI_WARNING(__FILE__, __LINE__, "%s: Truncating string value of %s for %s" _VL_VPI_WARNING(
__FILE__, __LINE__,
"%s: Truncating string value of %s for %s"
" as buffer size (%d, VL_MULS_MAX_WORDS=%d) is less than required (%d)", " as buffer size (%d, VL_MULS_MAX_WORDS=%d) is less than required (%d)",
VL_FUNC, VerilatedVpiError::strFromVpiVal(value_p->format), VL_FUNC, VerilatedVpiError::strFromVpiVal(value_p->format),
vop->fullname(), outStrSz, VL_MULS_MAX_WORDS, bytes); vop->fullname(), outStrSz, VL_MULS_MAX_WORDS, bytes);
@ -1542,9 +1560,8 @@ void vpi_get_value(vpiHandle object, p_vpi_value value_p) {
return; return;
} }
default: default:
_VL_VPI_ERROR(__FILE__, __LINE__, "%s: Unsupported format (%s) for %s", _VL_VPI_ERROR(__FILE__, __LINE__, "%s: Unsupported format (%s) for %s", VL_FUNC,
VL_FUNC, VerilatedVpiError::strFromVpiVal(value_p->format), VerilatedVpiError::strFromVpiVal(value_p->format), vop->fullname());
vop->fullname());
return; return;
} }
} else if (value_p->format == vpiIntVal) { } else if (value_p->format == vpiIntVal) {
@ -1562,9 +1579,8 @@ void vpi_get_value(vpiHandle object, p_vpi_value value_p) {
case VLVT_UINT64: // FALLTHRU case VLVT_UINT64: // FALLTHRU
default: default:
value_p->value.integer = 0; value_p->value.integer = 0;
_VL_VPI_ERROR(__FILE__, __LINE__, "%s: Unsupported format (%s) for %s", _VL_VPI_ERROR(__FILE__, __LINE__, "%s: Unsupported format (%s) for %s", VL_FUNC,
VL_FUNC, VerilatedVpiError::strFromVpiVal(value_p->format), VerilatedVpiError::strFromVpiVal(value_p->format), vop->fullname());
vop->fullname());
return; return;
} }
} else if (value_p->format == vpiSuppressVal) { } else if (value_p->format == vpiSuppressVal) {
@ -1573,18 +1589,17 @@ void vpi_get_value(vpiHandle object, p_vpi_value value_p) {
_VL_VPI_ERROR(__FILE__, __LINE__, "%s: Unsupported format (%s) as requested for %s", _VL_VPI_ERROR(__FILE__, __LINE__, "%s: Unsupported format (%s) as requested for %s",
VL_FUNC, VerilatedVpiError::strFromVpiVal(value_p->format), vop->fullname()); VL_FUNC, VerilatedVpiError::strFromVpiVal(value_p->format), vop->fullname());
return; return;
} } else if (VerilatedVpioConst* vop = VerilatedVpioConst::castp(object)) {
else if (VerilatedVpioConst* vop = VerilatedVpioConst::castp(object)) {
if (value_p->format == vpiIntVal) { if (value_p->format == vpiIntVal) {
value_p->value.integer = vop->num(); value_p->value.integer = vop->num();
return; return;
} }
_VL_VPI_ERROR(__FILE__, __LINE__, "%s: Unsupported format (%s) for %s", _VL_VPI_ERROR(__FILE__, __LINE__, "%s: Unsupported format (%s) for %s", VL_FUNC,
VL_FUNC, VerilatedVpiError::strFromVpiVal(value_p->format), vop->fullname()); VerilatedVpiError::strFromVpiVal(value_p->format), vop->fullname());
return; return;
} }
_VL_VPI_ERROR(__FILE__, __LINE__, "%s: Unsupported format %s", _VL_VPI_ERROR(__FILE__, __LINE__, "%s: Unsupported format %s", VL_FUNC,
VL_FUNC, VerilatedVpiError::strFromVpiVal(value_p->format)); VerilatedVpiError::strFromVpiVal(value_p->format));
} }
vpiHandle vpi_put_value(vpiHandle object, p_vpi_value value_p, p_vpi_time /*time_p*/, vpiHandle vpi_put_value(vpiHandle object, p_vpi_value value_p, p_vpi_time /*time_p*/,
@ -1597,10 +1612,10 @@ vpiHandle vpi_put_value(vpiHandle object, p_vpi_value value_p, p_vpi_time /*time
return 0; return 0;
} }
if (VerilatedVpioVar* vop = VerilatedVpioVar::castp(object)) { if (VerilatedVpioVar* vop = VerilatedVpioVar::castp(object)) {
VL_DEBUG_IF_PLI(VL_DBG_MSGF("- vpi: vpi_put_value name=%s fmt=%d vali=%d\n", VL_DEBUG_IF_PLI(
vop->fullname(), value_p->format, value_p->value.integer); VL_DBG_MSGF("- vpi: vpi_put_value name=%s fmt=%d vali=%d\n", vop->fullname(),
VL_DBG_MSGF("- vpi: varp=%p putatp=%p\n", value_p->format, value_p->value.integer);
vop->varp()->datap(), vop->varDatap());); VL_DBG_MSGF("- vpi: varp=%p putatp=%p\n", vop->varp()->datap(), vop->varDatap()););
if (VL_UNLIKELY(!vop->varp()->isPublicRW())) { if (VL_UNLIKELY(!vop->varp()->isPublicRW())) {
_VL_VPI_WARNING(__FILE__, __LINE__, _VL_VPI_WARNING(__FILE__, __LINE__,
"Ignoring vpi_put_value to signal marked read-only," "Ignoring vpi_put_value to signal marked read-only,"
@ -1628,22 +1643,18 @@ vpiHandle vpi_put_value(vpiHandle object, p_vpi_value value_p, p_vpi_time /*time
WDataOutP datap = (reinterpret_cast<EData*>(vop->varDatap())); WDataOutP datap = (reinterpret_cast<EData*>(vop->varDatap()));
for (int i = 0; i < words; ++i) { for (int i = 0; i < words; ++i) {
datap[i] = value_p->value.vector[i].aval; datap[i] = value_p->value.vector[i].aval;
if (i==(words-1)) { if (i == (words - 1)) datap[i] &= vop->mask();
datap[i] &= vop->mask();
}
} }
return object; return object;
} }
case VLVT_UINT64: { case VLVT_UINT64: {
*(reinterpret_cast<QData*>(vop->varDatap())) = _VL_SET_QII( *(reinterpret_cast<QData*>(vop->varDatap())) = _VL_SET_QII(
value_p->value.vector[1].aval & vop->mask(), value_p->value.vector[1].aval & vop->mask(), value_p->value.vector[0].aval);
value_p->value.vector[0].aval);
return object; return object;
} }
default: { default: {
_VL_VPI_ERROR(__FILE__, __LINE__, "%s: Unsupported format (%s) for %s", _VL_VPI_ERROR(__FILE__, __LINE__, "%s: Unsupported format (%s) for %s", VL_FUNC,
VL_FUNC, VerilatedVpiError::strFromVpiVal(value_p->format), VerilatedVpiError::strFromVpiVal(value_p->format), vop->fullname());
vop->fullname());
return NULL; return NULL;
} }
} }
@ -1670,9 +1681,8 @@ vpiHandle vpi_put_value(vpiHandle object, p_vpi_value value_p, p_vpi_time /*time
return object; return object;
} }
default: default:
_VL_VPI_ERROR(__FILE__, __LINE__, "%s: Unsupported format (%s) for %s", _VL_VPI_ERROR(__FILE__, __LINE__, "%s: Unsupported format (%s) for %s", VL_FUNC,
VL_FUNC, VerilatedVpiError::strFromVpiVal(value_p->format), VerilatedVpiError::strFromVpiVal(value_p->format), vop->fullname());
vop->fullname());
return 0; return 0;
} }
} else if (value_p->format == vpiOctStrVal) { } else if (value_p->format == vpiOctStrVal) {
@ -1700,9 +1710,10 @@ vpiHandle vpi_put_value(vpiHandle object, p_vpi_value value_p, p_vpi_time /*time
if (digit >= '0' && digit <= '7') { if (digit >= '0' && digit <= '7') {
val.half = digit - '0'; val.half = digit - '0';
} else { } else {
_VL_VPI_WARNING(__FILE__, __LINE__, _VL_VPI_WARNING(
"%s: Non octal character '%c' in '%s' as value %s for %s", __FILE__, __LINE__,
VL_FUNC, digit, value_p->value.str, "%s: Non octal character '%c' in '%s' as value %s for %s", VL_FUNC,
digit, value_p->value.str,
VerilatedVpiError::strFromVpiVal(value_p->format), VerilatedVpiError::strFromVpiVal(value_p->format),
vop->fullname()); vop->fullname());
val.half = 0; val.half = 0;
@ -1729,15 +1740,12 @@ vpiHandle vpi_put_value(vpiHandle object, p_vpi_value value_p, p_vpi_time /*time
datap[idx.quot + 1] &= vop->mask_byte(idx.quot + 1); datap[idx.quot + 1] &= vop->mask_byte(idx.quot + 1);
} }
// zero off remaining top bytes // zero off remaining top bytes
for (int i=idx.quot+2; i<bytes; ++i) { for (int i = idx.quot + 2; i < bytes; ++i) datap[i] = 0;
datap[i] = 0;
}
return object; return object;
} }
default: default:
_VL_VPI_ERROR(__FILE__, __LINE__, "%s: Unsupported format (%s) for %s", _VL_VPI_ERROR(__FILE__, __LINE__, "%s: Unsupported format (%s) for %s", VL_FUNC,
VL_FUNC, VerilatedVpiError::strFromVpiVal(value_p->format), VerilatedVpiError::strFromVpiVal(value_p->format), vop->fullname());
vop->fullname());
return 0; return 0;
} }
} else if (value_p->format == vpiDecStrVal) { } else if (value_p->format == vpiDecStrVal) {
@ -1745,28 +1753,31 @@ vpiHandle vpi_put_value(vpiHandle object, p_vpi_value value_p, p_vpi_time /*time
unsigned long long val; unsigned long long val;
int success = sscanf(value_p->value.str, "%30llu%15s", &val, remainder); int success = sscanf(value_p->value.str, "%30llu%15s", &val, remainder);
if (success < 1) { if (success < 1) {
_VL_VPI_ERROR(__FILE__, __LINE__, _VL_VPI_ERROR(__FILE__, __LINE__, "%s: Parsing failed for '%s' as value %s for %s",
"%s: Parsing failed for '%s' as value %s for %s",
VL_FUNC, value_p->value.str, VL_FUNC, value_p->value.str,
VerilatedVpiError::strFromVpiVal(value_p->format), vop->fullname()); VerilatedVpiError::strFromVpiVal(value_p->format), vop->fullname());
return 0; return 0;
} }
if (success > 1) { if (success > 1) {
_VL_VPI_WARNING(__FILE__, __LINE__, _VL_VPI_WARNING(
"%s: Trailing garbage '%s' in '%s' as value %s for %s", __FILE__, __LINE__, "%s: Trailing garbage '%s' in '%s' as value %s for %s",
VL_FUNC, remainder, value_p->value.str, VL_FUNC, remainder, value_p->value.str,
VerilatedVpiError::strFromVpiVal(value_p->format), VerilatedVpiError::strFromVpiVal(value_p->format), vop->fullname());
vop->fullname());
} }
switch (vop->varp()->vltype()) { switch (vop->varp()->vltype()) {
case VLVT_UINT8: case VLVT_UINT8:
*(reinterpret_cast<CData*>(vop->varDatap())) = val & vop->mask(); break; *(reinterpret_cast<CData*>(vop->varDatap())) = val & vop->mask();
break;
case VLVT_UINT16: case VLVT_UINT16:
*(reinterpret_cast<SData*>(vop->varDatap())) = val & vop->mask(); break; *(reinterpret_cast<SData*>(vop->varDatap())) = val & vop->mask();
break;
case VLVT_UINT32: case VLVT_UINT32:
*(reinterpret_cast<IData*>(vop->varDatap())) = val & vop->mask(); break; *(reinterpret_cast<IData*>(vop->varDatap())) = val & vop->mask();
case VLVT_UINT64: *(reinterpret_cast<QData*>(vop->varDatap())) = val; break;
(reinterpret_cast<IData*>(vop->varDatap()))[1] &= vop->mask(); break; case VLVT_UINT64:
*(reinterpret_cast<QData*>(vop->varDatap())) = val;
(reinterpret_cast<IData*>(vop->varDatap()))[1] &= vop->mask();
break;
case VLVT_WDATA: case VLVT_WDATA:
default: default:
_VL_VPI_ERROR(__FILE__, __LINE__, _VL_VPI_ERROR(__FILE__, __LINE__,
@ -1787,22 +1798,24 @@ vpiHandle vpi_put_value(vpiHandle object, p_vpi_value value_p, p_vpi_time /*time
CData* datap = (reinterpret_cast<CData*>(vop->varDatap())); CData* datap = (reinterpret_cast<CData*>(vop->varDatap()));
char* val = value_p->value.str; char* val = value_p->value.str;
// skip hex ident if one is detected at the start of the string // skip hex ident if one is detected at the start of the string
if (val[0] == '0' && (val[1] == 'x' || val[1] == 'X')) { if (val[0] == '0' && (val[1] == 'x' || val[1] == 'X')) val += 2;
val += 2;
}
int len = strlen(val); int len = strlen(val);
for (int i = 0; i < chars; ++i) { for (int i = 0; i < chars; ++i) {
char hex; char hex;
// compute hex digit value // compute hex digit value
if (i < len) { if (i < len) {
char digit = val[len - i - 1]; char digit = val[len - i - 1];
if (digit >= '0' && digit <= '9') hex = digit - '0'; if (digit >= '0' && digit <= '9') {
else if (digit >= 'a' && digit <= 'f') hex = digit - 'a' + 10; hex = digit - '0';
else if (digit >= 'A' && digit <= 'F') hex = digit - 'A' + 10; } else if (digit >= 'a' && digit <= 'f') {
else { hex = digit - 'a' + 10;
_VL_VPI_WARNING(__FILE__, __LINE__, } else if (digit >= 'A' && digit <= 'F') {
"%s: Non hex character '%c' in '%s' as value %s for %s", hex = digit - 'A' + 10;
VL_FUNC, digit, value_p->value.str, } else {
_VL_VPI_WARNING(
__FILE__, __LINE__,
"%s: Non hex character '%c' in '%s' as value %s for %s", VL_FUNC,
digit, value_p->value.str,
VerilatedVpiError::strFromVpiVal(value_p->format), VerilatedVpiError::strFromVpiVal(value_p->format),
vop->fullname()); vop->fullname());
hex = 0; hex = 0;
@ -1823,9 +1836,8 @@ vpiHandle vpi_put_value(vpiHandle object, p_vpi_value value_p, p_vpi_time /*time
return object; return object;
} }
default: default:
_VL_VPI_ERROR(__FILE__, __LINE__, "%s: Unsupported format (%s) for %s", _VL_VPI_ERROR(__FILE__, __LINE__, "%s: Unsupported format (%s) for %s", VL_FUNC,
VL_FUNC, VerilatedVpiError::strFromVpiVal(value_p->format), VerilatedVpiError::strFromVpiVal(value_p->format), vop->fullname());
vop->fullname());
return 0; return 0;
} }
} else if (value_p->format == vpiStringVal) { } else if (value_p->format == vpiStringVal) {
@ -1845,9 +1857,8 @@ vpiHandle vpi_put_value(vpiHandle object, p_vpi_value value_p, p_vpi_time /*time
return object; return object;
} }
default: default:
_VL_VPI_ERROR(__FILE__, __LINE__, "%s: Unsupported format (%s) for %s", _VL_VPI_ERROR(__FILE__, __LINE__, "%s: Unsupported format (%s) for %s", VL_FUNC,
VL_FUNC, VerilatedVpiError::strFromVpiVal(value_p->format), VerilatedVpiError::strFromVpiVal(value_p->format), vop->fullname());
vop->fullname());
return 0; return 0;
} }
} else if (value_p->format == vpiIntVal) { } else if (value_p->format == vpiIntVal) {
@ -1876,8 +1887,8 @@ vpiHandle vpi_put_value(vpiHandle object, p_vpi_value value_p, p_vpi_time /*time
VL_FUNC, VerilatedVpiError::strFromVpiVal(value_p->format), vop->fullname()); VL_FUNC, VerilatedVpiError::strFromVpiVal(value_p->format), vop->fullname());
return NULL; return NULL;
} }
_VL_VPI_ERROR(__FILE__, __LINE__, "%s: Unsupported format (%s) for ??", _VL_VPI_ERROR(__FILE__, __LINE__, "%s: Unsupported format (%s) for ??", VL_FUNC,
VL_FUNC, VerilatedVpiError::strFromVpiVal(value_p->format)); VerilatedVpiError::strFromVpiVal(value_p->format));
return NULL; return NULL;
} }
@ -1907,8 +1918,7 @@ void vpi_get_time(vpiHandle /*object*/, p_vpi_time time_p) {
time_p->high = itime[1]; time_p->high = itime[1];
return; return;
} }
_VL_VPI_ERROR(__FILE__, __LINE__, "%s: Unsupported type (%d)", _VL_VPI_ERROR(__FILE__, __LINE__, "%s: Unsupported type (%d)", VL_FUNC, time_p->type);
VL_FUNC, time_p->type);
} }
// I/O routines // I/O routines
@ -1994,9 +2004,7 @@ PLI_INT32 vpi_chk_error(p_vpi_error_info error_info_p) {
// error_info_p can be NULL, so only return level in that case // error_info_p can be NULL, so only return level in that case
VerilatedVpiImp::assertOneCheck(); VerilatedVpiImp::assertOneCheck();
p_vpi_error_info _error_info_p = VerilatedVpiImp::error_info()->getError(); p_vpi_error_info _error_info_p = VerilatedVpiImp::error_info()->getError();
if (error_info_p && _error_info_p) { if (error_info_p && _error_info_p) *error_info_p = *_error_info_p;
*error_info_p = *_error_info_p;
}
if (!_error_info_p) return 0; // no error occured if (!_error_info_p) return 0; // no error occured
return _error_info_p->level; // return error severity level return _error_info_p->level; // return error severity level
} }
@ -2061,8 +2069,8 @@ PLI_INT32 vpi_control(PLI_INT32 operation, ...) {
return 1; return 1;
} }
} }
_VL_VPI_WARNING(__FILE__, __LINE__, "%s: Unsupported type %s, ignoring", _VL_VPI_WARNING(__FILE__, __LINE__, "%s: Unsupported type %s, ignoring", VL_FUNC,
VL_FUNC, VerilatedVpiError::strFromVpiProp(operation)); VerilatedVpiError::strFromVpiProp(operation));
return 0; return 0;
} }

View File

@ -25,6 +25,8 @@
#ifndef _VERILATEDOS_H_ #ifndef _VERILATEDOS_H_
#define _VERILATEDOS_H_ 1 ///< Header Guard #define _VERILATEDOS_H_ 1 ///< Header Guard
// Current clang-format versions botch #ifdef inclusion, so
// clang-format off
//========================================================================= //=========================================================================
// Compiler pragma abstraction // Compiler pragma abstraction
@ -94,7 +96,7 @@
# define VL_RELEASE(...) ///< Function releases a capability/lock (-fthread-safety) # define VL_RELEASE(...) ///< Function releases a capability/lock (-fthread-safety)
# define VL_RELEASE_SHARED(...) ///< Function releases a shared capability/lock (-fthread-safety) # define VL_RELEASE_SHARED(...) ///< Function releases a shared capability/lock (-fthread-safety)
# define VL_TRY_ACQUIRE(...) ///< Function returns bool if aquired a capability (-fthread-safety) # define VL_TRY_ACQUIRE(...) ///< Function returns bool if aquired a capability (-fthread-safety)
# define VL_TRY_ACQUIRE_SHARED(...) ///< Function returns bool if aquired a shared capability (-fthread-safety) # define VL_TRY_ACQUIRE_SHARED(...) ///< Function returns bool if aquired shared (-fthread-safety)
# define VL_REQUIRES(x) ///< Function requires a capability inbound (-fthread-safety) # define VL_REQUIRES(x) ///< Function requires a capability inbound (-fthread-safety)
# define VL_EXCLUDES(x) ///< Function requires not having a capability inbound (-fthread-safety) # define VL_EXCLUDES(x) ///< Function requires not having a capability inbound (-fthread-safety)
# define VL_CAPABILITY(x) ///< Name of capability/lock (-fthread-safety) # define VL_CAPABILITY(x) ///< Name of capability/lock (-fthread-safety)
@ -130,14 +132,17 @@
#else #else
# define VL_THREAD_LOCAL ///< Use new C++ static local thread # define VL_THREAD_LOCAL ///< Use new C++ static local thread
#endif #endif
#define VL_THREAD ///< Deprecated #define VL_THREAD ///< Deprecated
#define VL_STATIC_OR_THREAD static ///< Deprecated #define VL_STATIC_OR_THREAD static ///< Deprecated
#define VL_PURE ///< Comment tag that Function is pure (and thus also VL_MT_SAFE) #define VL_PURE ///< Comment tag that Function is pure (and thus also VL_MT_SAFE)
#define VL_MT_SAFE ///< Comment tag that function is threadsafe when VL_THREADED #define VL_MT_SAFE ///< Comment tag that function is threadsafe when VL_THREADED
#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 ///< 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 #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
@ -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 #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) /// Mask for words with 1's where relevant bits are (0=all bits)
#define VL_MASK_I(nbits) (((nbits) & VL_SIZEBITS_I) \ #define VL_MASK_I(nbits) (((nbits) & VL_SIZEBITS_I) ? ((1U << ((nbits) & VL_SIZEBITS_I)) - 1) : ~0)
? ((1U << ((nbits) & VL_SIZEBITS_I) )-1) : ~0)
/// Mask for quads with 1's where relevant bits are (0=all bits) /// Mask for quads with 1's where relevant bits are (0=all bits)
#define VL_MASK_Q(nbits) (((nbits) & VL_SIZEBITS_Q) \ #define VL_MASK_Q(nbits) \
? ((VL_ULL(1) << ((nbits) & VL_SIZEBITS_Q) )-VL_ULL(1)) : VL_ULL(~0)) (((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) /// Mask for EData with 1's where relevant bits are (0=all bits)
#define VL_MASK_E(nbits) VL_MASK_I(nbits) #define VL_MASK_E(nbits) VL_MASK_I(nbits)
#define VL_EUL(n) VL_UL(n) ///< Make constant number EData sized #define VL_EUL(n) VL_UL(n) ///< Make constant number EData sized
@ -424,7 +428,8 @@ typedef unsigned long long vluint64_t; ///< 64-bit unsigned type
/// The vluint64_t argument is loaded with a high-performance counter for profiling /// The vluint64_t argument is loaded with a high-performance counter for profiling
/// or 0x0 if not implemeted on this platform /// or 0x0 if not implemeted on this platform
#if defined(__i386__) || defined(__x86_64__) #if defined(__i386__) || defined(__x86_64__)
# define VL_RDTSC(val) { \ #define VL_RDTSC(val) \
{ \
vluint32_t hi, lo; \ vluint32_t hi, lo; \
asm volatile("rdtsc" : "=a"(lo), "=d"(hi)); \ asm volatile("rdtsc" : "=a"(lo), "=d"(hi)); \
(val) = ((vluint64_t)lo) | (((vluint64_t)hi) << 32); \ (val) = ((vluint64_t)lo) | (((vluint64_t)hi) << 32); \
@ -468,6 +473,7 @@ typedef unsigned long long vluint64_t; ///< 64-bit unsigned type
#else #else
# define VL_STRCASECMP strcasecmp # define VL_STRCASECMP strcasecmp
#endif #endif
// clang-format on
//========================================================================= //=========================================================================
// Stringify macros // 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

@ -89,8 +89,7 @@ public:
AstActive* getCActive(FileLine* fl) { AstActive* getCActive(FileLine* fl) {
if (!m_cActivep) { if (!m_cActivep) {
m_cActivep = new AstActive( m_cActivep = new AstActive(
fl, "combo", fl, "combo", new AstSenTree(fl, new AstSenItem(fl, AstSenItem::Combo())));
new AstSenTree(fl, new AstSenItem(fl, AstSenItem::Combo())));
m_cActivep->sensesStorep(m_cActivep->sensesp()); m_cActivep->sensesStorep(m_cActivep->sensesp());
addActive(m_cActivep); addActive(m_cActivep);
} }
@ -99,8 +98,7 @@ public:
AstActive* getIActive(FileLine* fl) { AstActive* getIActive(FileLine* fl) {
if (!m_iActivep) { if (!m_iActivep) {
m_iActivep = new AstActive( m_iActivep = new AstActive(
fl, "initial", fl, "initial", new AstSenTree(fl, new AstSenItem(fl, AstSenItem::Initial())));
new AstSenTree(fl, new AstSenItem(fl, AstSenItem::Initial())));
m_iActivep->sensesStorep(m_iActivep->sensesp()); m_iActivep->sensesStorep(m_iActivep->sensesp());
addActive(m_iActivep); addActive(m_iActivep);
} }
@ -131,6 +129,7 @@ public:
} }
return activep; return activep;
} }
public: public:
// CONSTRUCTORS // CONSTRUCTORS
ActiveNamer() { ActiveNamer() {
@ -139,9 +138,7 @@ public:
m_cActivep = NULL; m_cActivep = NULL;
} }
virtual ~ActiveNamer() {} virtual ~ActiveNamer() {}
void main(AstScope* nodep) { void main(AstScope* nodep) { iterate(nodep); }
iterate(nodep);
}
}; };
//###################################################################### //######################################################################
@ -150,6 +147,7 @@ public:
class ActiveDlyVisitor : public ActiveBaseVisitor { class ActiveDlyVisitor : public ActiveBaseVisitor {
public: public:
enum CheckType { CT_SEQ, CT_COMBO, CT_INITIAL, CT_LATCH }; enum CheckType { CT_SEQ, CT_COMBO, CT_INITIAL, CT_LATCH };
private: private:
CheckType m_check; // Combo logic or other CheckType m_check; // Combo logic or other
AstNode* m_alwaysp; // Always we're under AstNode* m_alwaysp; // Always we're under
@ -161,16 +159,17 @@ private:
UINFO(5, " ASSIGNDLY " << nodep << endl); UINFO(5, " ASSIGNDLY " << nodep << endl);
if (m_check == CT_INITIAL) { if (m_check == CT_INITIAL) {
nodep->v3warn(INITIALDLY, "Delayed assignments (<=) in initial or final block\n" 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) { } else if (m_check == CT_LATCH) {
// Suppress. Shouldn't matter that the interior of the latch races // Suppress. Shouldn't matter that the interior of the latch races
} else { } else {
nodep->v3warn(COMBDLY, "Delayed assignments (<=) in non-clocked" nodep->v3warn(COMBDLY, "Delayed assignments (<=) in non-clocked"
" (non flop or latch) block\n" " (non flop or latch) block\n"
<<nodep->warnMore()<<"... Suggest blocking assignments (=)"); << nodep->warnMore()
<< "... Suggest blocking assignments (=)");
} }
AstNode* newp = new AstAssign(nodep->fileline(), AstNode* newp = new AstAssign(nodep->fileline(), nodep->lhsp()->unlinkFrBack(),
nodep->lhsp()->unlinkFrBack(),
nodep->rhsp()->unlinkFrBack()); nodep->rhsp()->unlinkFrBack());
nodep->replaceWith(newp); nodep->replaceWith(newp);
VL_DO_DANGLING(nodep->deleteTree(), nodep); VL_DO_DANGLING(nodep->deleteTree(), nodep);
@ -186,17 +185,18 @@ private:
} }
virtual void visit(AstVarRef* nodep) VL_OVERRIDE { virtual void visit(AstVarRef* nodep) VL_OVERRIDE {
AstVar* varp = nodep->varp(); AstVar* varp = nodep->varp();
if (m_check == CT_SEQ if (m_check == CT_SEQ && m_assignp && !varp->isUsedLoopIdx() // Ignore loop indices
&& m_assignp
&& !varp->isUsedLoopIdx() // Ignore loop indices
&& !varp->isTemp()) { && !varp->isTemp()) {
// Allow turning off warnings on the always, or the variable also // Allow turning off warnings on the always, or the variable also
if (!m_alwaysp->fileline()->warnIsOff(V3ErrorCode::BLKSEQ) if (!m_alwaysp->fileline()->warnIsOff(V3ErrorCode::BLKSEQ)
&& !m_assignp->fileline()->warnIsOff(V3ErrorCode::BLKSEQ) && !m_assignp->fileline()->warnIsOff(V3ErrorCode::BLKSEQ)
&& !varp->fileline()->warnIsOff(V3ErrorCode::BLKSEQ)) { && !varp->fileline()->warnIsOff(V3ErrorCode::BLKSEQ)) {
m_assignp->v3warn(BLKSEQ, "Blocking assignments (=) in sequential (flop or latch) block\n" m_assignp->v3warn(BLKSEQ,
<<m_assignp->warnMore()<<"... Suggest delayed assignments (<=)"); "Blocking assignments (=) in sequential (flop or latch) block\n"
m_alwaysp->fileline()->modifyWarnOff(V3ErrorCode::BLKSEQ, true); // Complain just once for the entire always << 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); varp->fileline()->modifyWarnOff(V3ErrorCode::BLKSEQ, true);
} }
} }
@ -281,8 +281,7 @@ private:
ActiveDlyVisitor dlyvisitor(nodep, ActiveDlyVisitor::CT_INITIAL); ActiveDlyVisitor dlyvisitor(nodep, ActiveDlyVisitor::CT_INITIAL);
if (!m_scopeFinalp) { if (!m_scopeFinalp) {
m_scopeFinalp = new AstCFunc( m_scopeFinalp = new AstCFunc(
nodep->fileline(), "_final_"+m_namer.scopep()->nameDotless(), nodep->fileline(), "_final_" + m_namer.scopep()->nameDotless(), m_namer.scopep());
m_namer.scopep());
m_scopeFinalp->argTypes(EmitCBaseVisitor::symClassVar()); m_scopeFinalp->argTypes(EmitCBaseVisitor::symClassVar());
m_scopeFinalp->addInitsp( m_scopeFinalp->addInitsp(
new AstCStmt(nodep->fileline(), EmitCBaseVisitor::symTopAssign() + "\n")); new AstCStmt(nodep->fileline(), EmitCBaseVisitor::symTopAssign() + "\n"));
@ -300,9 +299,7 @@ private:
// METHODS // METHODS
void visitAlways(AstNode* nodep, AstSenTree* oldsensesp, VAlwaysKwd kwd) { void visitAlways(AstNode* nodep, AstSenTree* oldsensesp, VAlwaysKwd kwd) {
// Move always to appropriate ACTIVE based on its sense list // Move always to appropriate ACTIVE based on its sense list
if (oldsensesp if (oldsensesp && oldsensesp->sensesp() && VN_IS(oldsensesp->sensesp(), SenItem)
&& oldsensesp->sensesp()
&& VN_IS(oldsensesp->sensesp(), SenItem)
&& VN_CAST(oldsensesp->sensesp(), SenItem)->isNever()) { && VN_CAST(oldsensesp->sensesp(), SenItem)->isNever()) {
// Never executing. Kill it. // Never executing. Kill it.
UASSERT_OBJ(!oldsensesp->sensesp()->nextp(), nodep, UASSERT_OBJ(!oldsensesp->sensesp()->nextp(), nodep,
@ -321,7 +318,8 @@ private:
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 (combo && sequent) {
if (!v3Global.opt.bboxUnsup()) { 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; sequent = false;
} }
@ -336,8 +334,9 @@ private:
// always (posedge RESET) { if (RESET).... } we know RESET is true. // always (posedge RESET) { if (RESET).... } we know RESET is true.
// Summarize a long list of combo inputs as just "combo" // Summarize a long list of combo inputs as just "combo"
#ifndef __COVERITY__ // Else dead code on next line. #ifndef __COVERITY__ // Else dead code on next line.
if (combo) oldsensesp->addSensesp if (combo) {
(new AstSenItem(nodep->fileline(), AstSenItem::Combo())); oldsensesp->addSensesp(new AstSenItem(nodep->fileline(), AstSenItem::Combo()));
}
#endif #endif
wantactivep = m_namer.getActive(nodep->fileline(), oldsensesp); wantactivep = m_namer.getActive(nodep->fileline(), oldsensesp);
} }
@ -358,8 +357,7 @@ private:
} else { } else {
ActiveDlyVisitor dlyvisitor(nodep, ActiveDlyVisitor::CT_COMBO); ActiveDlyVisitor dlyvisitor(nodep, ActiveDlyVisitor::CT_COMBO);
} }
} } else if (!combo && sequent) {
else if (!combo && sequent) {
ActiveDlyVisitor dlyvisitor(nodep, ActiveDlyVisitor::CT_SEQ); ActiveDlyVisitor dlyvisitor(nodep, ActiveDlyVisitor::CT_SEQ);
} }
} }
@ -427,8 +425,6 @@ public:
void V3Active::activeAll(AstNetlist* nodep) { void V3Active::activeAll(AstNetlist* nodep) {
UINFO(2, __FUNCTION__ << ": " << endl); UINFO(2, __FUNCTION__ << ": " << endl);
{ { ActiveVisitor visitor(nodep); } // Destruct before checking
ActiveVisitor visitor (nodep);
} // Destruct before checking
V3Global::dumpCheckGlobalTree("active", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3); V3Global::dumpCheckGlobalTree("active", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
} }

View File

@ -66,11 +66,11 @@ private:
} }
virtual void visit(AstActive* nodep) VL_OVERRIDE { virtual void visit(AstActive* nodep) VL_OVERRIDE {
UINFO(4, " ACTIVE " << nodep << endl); UINFO(4, " ACTIVE " << nodep << endl);
V3Const::constifyExpensiveEdit(nodep); // Remove duplicate clocks and such; sensesp() may change! // Remove duplicate clocks and such; sensesp() may change!
V3Const::constifyExpensiveEdit(nodep);
AstSenTree* sensesp = nodep->sensesp(); AstSenTree* sensesp = nodep->sensesp();
UASSERT_OBJ(sensesp, nodep, "NULL"); UASSERT_OBJ(sensesp, nodep, "NULL");
if (sensesp->sensesp() if (sensesp->sensesp() && VN_IS(sensesp->sensesp(), SenItem)
&& VN_IS(sensesp->sensesp(), SenItem)
&& VN_CAST(sensesp->sensesp(), SenItem)->isNever()) { && VN_CAST(sensesp->sensesp(), SenItem)->isNever()) {
// Never executing. Kill it. // Never executing. Kill it.
UASSERT_OBJ(!sensesp->sensesp()->nextp(), nodep, UASSERT_OBJ(!sensesp->sensesp()->nextp(), nodep,
@ -80,9 +80,8 @@ private:
} }
// Copy combo tree to settlement tree with duplicated statements // Copy combo tree to settlement tree with duplicated statements
if (sensesp->hasCombo()) { if (sensesp->hasCombo()) {
AstSenTree* newsentreep AstSenTree* newsentreep = new AstSenTree(
= new AstSenTree(nodep->fileline(), nodep->fileline(), new AstSenItem(nodep->fileline(), AstSenItem::Settle()));
new AstSenItem(nodep->fileline(), AstSenItem::Settle()));
AstActive* newp = new AstActive(nodep->fileline(), "settle", newsentreep); AstActive* newp = new AstActive(nodep->fileline(), "settle", newsentreep);
newp->sensesStorep(newsentreep); newp->sensesStorep(newsentreep);
if (nodep->stmtsp()) newp->addStmtsp(nodep->stmtsp()->cloneTree(true)); if (nodep->stmtsp()) newp->addStmtsp(nodep->stmtsp()->cloneTree(true));
@ -146,8 +145,6 @@ public:
void V3ActiveTop::activeTopAll(AstNetlist* nodep) { void V3ActiveTop::activeTopAll(AstNetlist* nodep) {
UINFO(2, __FUNCTION__ << ": " << endl); UINFO(2, __FUNCTION__ << ": " << endl);
{ { ActiveTopVisitor visitor(nodep); } // Destruct before checking
ActiveTopVisitor visitor (nodep);
} // Destruct before checking
V3Global::dumpCheckGlobalTree("activetop", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3); V3Global::dumpCheckGlobalTree("activetop", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
} }

View File

@ -47,11 +47,9 @@ private:
// METHODS // METHODS
string assertDisplayMessage(AstNode* nodep, const string& prefix, const string& message) { string assertDisplayMessage(AstNode* nodep, const string& prefix, const string& message) {
return (string("[%0t] "+prefix+": ")+nodep->fileline()->filebasename() return (string("[%0t] " + prefix + ": ") + nodep->fileline()->filebasename() + ":"
+":"+cvtToStr(nodep->fileline()->lineno()) + cvtToStr(nodep->fileline()->lineno()) + ": Assertion failed in %m"
+": Assertion failed in %m" + ((message != "") ? ": " : "") + message + "\n");
+((message != "")?": ":"")+message
+"\n");
} }
void replaceDisplay(AstDisplay* nodep, const string& prefix) { void replaceDisplay(AstDisplay* nodep, const string& prefix) {
nodep->displayType(AstDisplayType::DT_WRITE); nodep->displayType(AstDisplayType::DT_WRITE);
@ -86,8 +84,8 @@ private:
AstNode* newFireAssertUnchecked(AstNode* nodep, const string& message) { AstNode* newFireAssertUnchecked(AstNode* nodep, const string& message) {
// Like newFireAssert() but omits the asserts-on check // Like newFireAssert() but omits the asserts-on check
AstDisplay* dispp = new AstDisplay(nodep->fileline(), AstDisplay* dispp
AstDisplayType::DT_ERROR, message, NULL, NULL); = new AstDisplay(nodep->fileline(), AstDisplayType::DT_ERROR, message, NULL, NULL);
AstNode* bodysp = dispp; AstNode* bodysp = dispp;
replaceDisplay(dispp, "%%Error"); // Convert to standard DISPLAY format replaceDisplay(dispp, "%%Error"); // Convert to standard DISPLAY format
bodysp->addNext(new AstStop(nodep->fileline(), true)); bodysp->addNext(new AstStop(nodep->fileline(), true));
@ -137,8 +135,11 @@ private:
ifp = new AstIf(nodep->fileline(), propp, bodysp, NULL); ifp = new AstIf(nodep->fileline(), propp, bodysp, NULL);
bodysp = ifp; bodysp = ifp;
} else if (VN_IS(nodep, Assert)) { } else if (VN_IS(nodep, Assert)) {
if (nodep->immediate()) ++m_statAsImm; if (nodep->immediate()) {
else ++m_statAsNotImm; ++m_statAsImm;
} else {
++m_statAsNotImm;
}
if (passsp) passsp = newIfAssertOn(passsp); if (passsp) passsp = newIfAssertOn(passsp);
if (failsp) failsp = newIfAssertOn(failsp); if (failsp) failsp = newIfAssertOn(failsp);
if (!failsp) failsp = newFireAssertUnchecked(nodep, "'assert' failed."); if (!failsp) failsp = newFireAssertUnchecked(nodep, "'assert' failed.");
@ -153,9 +154,10 @@ private:
AstNode* newp; AstNode* newp;
if (sentreep) { if (sentreep) {
newp = new AstAlways(nodep->fileline(), newp = new AstAlways(nodep->fileline(), VAlwaysKwd::ALWAYS, sentreep, bodysp);
VAlwaysKwd::ALWAYS, sentreep, bodysp); } else {
} else { newp = bodysp; } newp = bodysp;
}
// Install it // Install it
if (selfDestruct) { if (selfDestruct) {
// Delete it after making the tree. This way we can tell the user // Delete it after making the tree. This way we can tell the user
@ -186,7 +188,7 @@ private:
iterateAndNextNull(ifp->ifsp()); iterateAndNextNull(ifp->ifsp());
// If the last else is not an else if, recurse into that too. // If the last else is not an else if, recurse into that too.
if (ifp->elsesp() && !nextifp) { if (ifp->elsesp() && !nextifp) { //
iterateAndNextNull(ifp->elsesp()); iterateAndNextNull(ifp->elsesp());
} }
@ -199,9 +201,7 @@ private:
} }
// Record if this ends with an 'else' that does not have an if // Record if this ends with an 'else' that does not have an if
if (ifp->elsesp() && !nextifp) { if (ifp->elsesp() && !nextifp) hasDefaultElse = true;
hasDefaultElse = true;
}
ifp = nextifp; ifp = nextifp;
} while (ifp); } while (ifp);
@ -217,10 +217,9 @@ private:
AstNode* ohot = ((allow_none || hasDefaultElse) AstNode* ohot = ((allow_none || hasDefaultElse)
? static_cast<AstNode*>(new AstOneHot0(nodep->fileline(), propp)) ? static_cast<AstNode*>(new AstOneHot0(nodep->fileline(), propp))
: static_cast<AstNode*>(new AstOneHot(nodep->fileline(), propp))); : static_cast<AstNode*>(new AstOneHot(nodep->fileline(), propp)));
AstIf* checkifp = new AstIf(nodep->fileline(), AstIf* checkifp
new AstLogNot(nodep->fileline(), ohot), = new AstIf(nodep->fileline(), new AstLogNot(nodep->fileline(), ohot),
newFireAssert(nodep, "'unique if' statement violated"), newFireAssert(nodep, "'unique if' statement violated"), newifp);
newifp);
checkifp->branchPred(VBranchPred::BP_UNLIKELY); checkifp->branchPred(VBranchPred::BP_UNLIKELY);
nodep->replaceWith(checkifp); nodep->replaceWith(checkifp);
pushDeletep(nodep); pushDeletep(nodep);
@ -234,15 +233,16 @@ private:
iterateChildren(nodep); iterateChildren(nodep);
if (!nodep->user1SetOnce()) { if (!nodep->user1SetOnce()) {
bool has_default = false; bool has_default = false;
for (AstCaseItem* itemp = nodep->itemsp(); for (AstCaseItem* itemp = nodep->itemsp(); itemp;
itemp; itemp = VN_CAST(itemp->nextp(), CaseItem)) { itemp = VN_CAST(itemp->nextp(), CaseItem)) {
if (itemp->isDefault()) has_default = true; if (itemp->isDefault()) has_default = true;
} }
if (nodep->fullPragma() || nodep->priorityPragma()) { if (nodep->fullPragma() || nodep->priorityPragma()) {
// Simply need to add a default if there isn't one already // Simply need to add a default if there isn't one already
++m_statAsFull; ++m_statAsFull;
if (!has_default) { if (!has_default) {
nodep->addItemsp(new AstCaseItem(nodep->fileline(), NULL/*DEFAULT*/, nodep->addItemsp(new AstCaseItem(
nodep->fileline(), NULL /*DEFAULT*/,
newFireAssert(nodep, "synthesis full_case, but non-match found"))); newFireAssert(nodep, "synthesis full_case, but non-match found")));
} }
} }
@ -271,8 +271,11 @@ private:
nodep->exprp()->cloneTree(false), nodep->exprp()->cloneTree(false),
icondp->cloneTree(false)); icondp->cloneTree(false));
} }
if (propp) propp = new AstConcat(icondp->fileline(), onep, propp); if (propp) {
else propp = onep; propp = new AstConcat(icondp->fileline(), onep, propp);
} else {
propp = onep;
}
} }
} }
// Empty case means no property // Empty case means no property
@ -283,9 +286,10 @@ private:
= (allow_none = (allow_none
? static_cast<AstNode*>(new AstOneHot0(nodep->fileline(), propp)) ? static_cast<AstNode*>(new AstOneHot0(nodep->fileline(), propp))
: static_cast<AstNode*>(new AstOneHot(nodep->fileline(), propp))); : static_cast<AstNode*>(new AstOneHot(nodep->fileline(), propp)));
AstIf* ifp = new AstIf(nodep->fileline(), AstIf* ifp = new AstIf(
new AstLogNot(nodep->fileline(), ohot), nodep->fileline(), new AstLogNot(nodep->fileline(), ohot),
newFireAssert(nodep, "synthesis parallel_case, but multiple matches found"), newFireAssert(nodep,
"synthesis parallel_case, but multiple matches found"),
NULL); NULL);
ifp->branchPred(VBranchPred::BP_UNLIKELY); ifp->branchPred(VBranchPred::BP_UNLIKELY);
nodep->addNotParallelp(ifp); nodep->addNotParallelp(ifp);
@ -306,9 +310,9 @@ private:
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(); AstNode* inp = nodep->exprp()->unlinkFrBack();
AstVar* invarp = NULL; AstVar* invarp = NULL;
AstSenTree* sentreep = nodep->sentreep(); sentreep->unlinkFrBack(); AstSenTree* sentreep = nodep->sentreep();
AstAlways* alwaysp = new AstAlways(nodep->fileline(), VAlwaysKwd::ALWAYS, sentreep->unlinkFrBack();
sentreep, NULL); AstAlways* alwaysp = new AstAlways(nodep->fileline(), VAlwaysKwd::ALWAYS, sentreep, NULL);
m_modp->addStmtp(alwaysp); 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, AstVar* outvarp = new AstVar(nodep->fileline(), AstVarType::MODULETEMP,
@ -316,8 +320,7 @@ private:
inp->dtypep()); inp->dtypep());
m_modp->addStmtp(outvarp); m_modp->addStmtp(outvarp);
AstNode* assp = new AstAssignDly(nodep->fileline(), AstNode* assp = new AstAssignDly(nodep->fileline(),
new AstVarRef(nodep->fileline(), outvarp, true), new AstVarRef(nodep->fileline(), outvarp, true), inp);
inp);
alwaysp->addStmtp(assp); alwaysp->addStmtp(assp);
// if (debug()>-9) assp->dumpTree(cout, "-ass: "); // if (debug()>-9) assp->dumpTree(cout, "-ass: ");
invarp = outvarp; invarp = outvarp;
@ -404,8 +407,6 @@ public:
void V3Assert::assertAll(AstNetlist* nodep) { void V3Assert::assertAll(AstNetlist* nodep) {
UINFO(2, __FUNCTION__ << ": " << endl); UINFO(2, __FUNCTION__ << ": " << endl);
{ { AssertVisitor visitor(nodep); } // Destruct before checking
AssertVisitor visitor (nodep);
} // Destruct before checking
V3Global::dumpCheckGlobalTree("assert", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3); V3Global::dumpCheckGlobalTree("assert", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
} }

View File

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

View File

@ -111,9 +111,7 @@ private:
void calc_tasks() { 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; AstCFunc* nodep = *it;
if (!nodep->dontInline()) { if (!nodep->dontInline()) nodep->isInline(true);
nodep->isInline(true);
}
} }
} }

View File

@ -58,27 +58,21 @@ private:
packagep->classp(nodep); packagep->classp(nodep);
v3Global.rootp()->addModulep(packagep); v3Global.rootp()->addModulep(packagep);
// Add package to hierarchy // Add package to hierarchy
AstCell* cellp = new AstCell(packagep->fileline(), AstCell* cellp = new AstCell(packagep->fileline(), packagep->fileline(), packagep->name(),
packagep->fileline(), packagep->name(), NULL, NULL, NULL);
packagep->name(),
packagep->name(),
NULL, NULL, NULL);
cellp->modp(packagep); cellp->modp(packagep);
v3Global.rootp()->topModulep()->addStmtp(cellp); v3Global.rootp()->topModulep()->addStmtp(cellp);
// Find class's scope // Find class's scope
// Alternative would be to move this and related to V3Scope // Alternative would be to move this and related to V3Scope
AstScope* classScopep = NULL; AstScope* classScopep = NULL;
for (AstNode* itp = nodep->stmtsp(); itp; itp = itp->nextp()) { for (AstNode* itp = nodep->stmtsp(); itp; itp = itp->nextp()) {
if ((classScopep = VN_CAST(itp, Scope))) { if ((classScopep = VN_CAST(itp, Scope))) break;
break;
}
} }
UASSERT_OBJ(classScopep, nodep, "No scope under class"); UASSERT_OBJ(classScopep, nodep, "No scope under class");
// Add scope // Add scope
AstScope* scopep = new AstScope(nodep->fileline(), AstScope* scopep = new AstScope(nodep->fileline(), packagep, classScopep->name(),
packagep, classScopep->name(), classScopep->aboveScopep(), classScopep->aboveScopep(), classScopep->aboveCellp());
classScopep->aboveCellp());
packagep->addStmtp(scopep); packagep->addStmtp(scopep);
// Iterate // Iterate
string prevPrefix = m_prefix; string prevPrefix = m_prefix;

View File

@ -346,7 +346,9 @@ public:
bool waive(V3ErrorCode code, const string& match) { bool waive(V3ErrorCode code, const string& match) {
for (Waivers::const_iterator it = m_waivers.begin(); it != m_waivers.end(); ++it) { for (Waivers::const_iterator it = m_waivers.begin(); it != m_waivers.end(); ++it) {
if (((it->first == code) || (it->first == V3ErrorCode::I_LINT)) 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; return false;
} }

View File

@ -47,7 +47,9 @@ private:
AstNode* m_varRefp; // How to get to this element AstNode* m_varRefp; // How to get to this element
AstNode* m_chgRefp; // How to get to this element AstNode* m_chgRefp; // How to get to this element
ToggleEnt(const string& comment, AstNode* vp, AstNode* cp) 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() {} ~ToggleEnt() {}
void cleanup() { void cleanup() {
VL_DO_CLEAR(m_varRefp->deleteTree(), m_varRefp = NULL); VL_DO_CLEAR(m_varRefp->deleteTree(), m_varRefp = NULL);
@ -74,14 +76,11 @@ private:
const char* varIgnoreToggle(AstVar* nodep) { const char* varIgnoreToggle(AstVar* nodep) {
// Return true if this shouldn't be traced // Return true if this shouldn't be traced
// See also similar rule in V3TraceDecl::varIgnoreTrace // See also similar rule in V3TraceDecl::varIgnoreTrace
if (!nodep->isToggleCoverable()) if (!nodep->isToggleCoverable()) return "Not relevant signal type";
return "Not relevant signal type";
if (!v3Global.opt.coverageUnderscore()) { if (!v3Global.opt.coverageUnderscore()) {
string prettyName = nodep->prettyName(); string prettyName = nodep->prettyName();
if (prettyName[0] == '_') if (prettyName[0] == '_') return "Leading underscore";
return "Leading underscore"; if (prettyName.find("._") != string::npos) return "Inlined 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"; return "Wide bus/array > 256 bits";
@ -91,15 +90,14 @@ private:
return NULL; return NULL;
} }
AstCoverInc* newCoverInc(FileLine* fl, const string& hier, AstCoverInc* newCoverInc(FileLine* fl, const string& hier, const string& page_prefix,
const string& page_prefix, const string& comment, const string& comment, const string& trace_var_name) {
const string& trace_var_name) {
// For line coverage, we may have multiple if's on one line, so disambiguate if // For line coverage, we may have multiple if's on one line, so disambiguate if
// everything is otherwise identical // everything is otherwise identical
// (Don't set column otherwise as it may result in making bins not match up with // (Don't set column otherwise as it may result in making bins not match up with
// different types of coverage enabled.) // different types of coverage enabled.)
string key = fl->filename()+"\001"+cvtToStr(fl->lineno()) string key = fl->filename() + "\001" + cvtToStr(fl->lineno()) + "\001" + hier + "\001"
+"\001"+hier+"\001"+page_prefix+"\001"+comment; + page_prefix + "\001" + comment;
int column = 0; int column = 0;
FileMap::iterator it = m_fileps.find(key); FileMap::iterator it = m_fileps.find(key);
if (it == m_fileps.end()) { if (it == m_fileps.end()) {
@ -122,27 +120,23 @@ private:
AstCoverInc* incp = new AstCoverInc(fl, declp); AstCoverInc* incp = new AstCoverInc(fl, declp);
if (!trace_var_name.empty() && v3Global.opt.traceCoverage()) { if (!trace_var_name.empty() && v3Global.opt.traceCoverage()) {
AstVar* varp = new AstVar(incp->fileline(), AstVar* varp = new AstVar(incp->fileline(), AstVarType::MODULETEMP, trace_var_name,
AstVarType::MODULETEMP, trace_var_name,
incp->findUInt32DType()); incp->findUInt32DType());
varp->trace(true); varp->trace(true);
varp->fileline()->modifyWarnOff(V3ErrorCode::UNUSED, true); varp->fileline()->modifyWarnOff(V3ErrorCode::UNUSED, true);
m_modp->addStmtp(varp); m_modp->addStmtp(varp);
UINFO(5, "New coverage trace: " << varp << endl); UINFO(5, "New coverage trace: " << varp << endl);
AstAssign* assp = new AstAssign( AstAssign* assp = new AstAssign(
incp->fileline(), incp->fileline(), new AstVarRef(incp->fileline(), varp, true),
new AstVarRef(incp->fileline(), varp, true), new AstAdd(incp->fileline(), new AstVarRef(incp->fileline(), varp, false),
new AstAdd(incp->fileline(),
new AstVarRef(incp->fileline(), varp, false),
new AstConst(incp->fileline(), AstConst::WidthedValue(), 32, 1))); new AstConst(incp->fileline(), AstConst::WidthedValue(), 32, 1)));
incp->addNext(assp); incp->addNext(assp);
} }
return incp; return incp;
} }
string traceNameForLine(AstNode* nodep, const string& type) { string traceNameForLine(AstNode* nodep, const string& type) {
return "vlCoverageLineTrace_"+nodep->fileline()->filebasenameNoExt() return "vlCoverageLineTrace_" + nodep->fileline()->filebasenameNoExt() + "__"
+"__"+cvtToStr(nodep->fileline()->lineno()) + cvtToStr(nodep->fileline()->lineno()) + "_" + type;
+"_"+type;
} }
// VISITORS - BOTH // VISITORS - BOTH
virtual void visit(AstNodeModule* nodep) VL_OVERRIDE { virtual void visit(AstNodeModule* nodep) VL_OVERRIDE {
@ -169,8 +163,8 @@ private:
} }
virtual void visit(AstVar* nodep) VL_OVERRIDE { virtual void visit(AstVar* nodep) VL_OVERRIDE {
iterateChildren(nodep); iterateChildren(nodep);
if (m_modp && !m_inModOff && !m_inToggleOff if (m_modp && !m_inModOff && !m_inToggleOff && nodep->fileline()->coverageOn()
&& nodep->fileline()->coverageOn() && v3Global.opt.coverageToggle()) { && v3Global.opt.coverageToggle()) {
const char* disablep = varIgnoreToggle(nodep); const char* disablep = varIgnoreToggle(nodep);
if (disablep) { if (disablep) {
UINFO(4, " Disable Toggle: " << disablep << " " << nodep << endl); UINFO(4, " Disable Toggle: " << disablep << " " << nodep << endl);
@ -189,8 +183,8 @@ private:
// Add signal to hold the old value // Add signal to hold the old value
string newvarname = string("__Vtogcov__") + nodep->shortName(); string newvarname = string("__Vtogcov__") + nodep->shortName();
AstVar* chgVarp = new AstVar(nodep->fileline(), AstVar* chgVarp
AstVarType::MODULETEMP, newvarname, nodep); = new AstVar(nodep->fileline(), AstVarType::MODULETEMP, newvarname, nodep);
chgVarp->fileline()->modifyWarnOff(V3ErrorCode::UNUSED, true); chgVarp->fileline()->modifyWarnOff(V3ErrorCode::UNUSED, true);
m_modp->addStmtp(chgVarp); m_modp->addStmtp(chgVarp);
@ -198,46 +192,41 @@ private:
// This is necessarily an O(n^2) expansion, which is why // This is necessarily an O(n^2) expansion, which is why
// we limit coverage to signals with < 256 bits. // we limit coverage to signals with < 256 bits.
ToggleEnt newvec (string(""), ToggleEnt newvec(string(""), new AstVarRef(nodep->fileline(), nodep, false),
new AstVarRef(nodep->fileline(), nodep, false),
new AstVarRef(nodep->fileline(), chgVarp, true)); new AstVarRef(nodep->fileline(), chgVarp, true));
toggleVarRecurse(nodep->dtypeSkipRefp(), 0, newvec, toggleVarRecurse(nodep->dtypeSkipRefp(), 0, newvec, nodep, chgVarp);
nodep, chgVarp);
newvec.cleanup(); newvec.cleanup();
} }
} }
} }
void toggleVarBottom(const ToggleEnt& above, const AstVar* varp) { void toggleVarBottom(const ToggleEnt& above, const AstVar* varp) {
AstCoverToggle* newp AstCoverToggle* newp = new AstCoverToggle(
= new AstCoverToggle(varp->fileline(), varp->fileline(),
newCoverInc(varp->fileline(), "", "v_toggle", newCoverInc(varp->fileline(), "", "v_toggle", varp->name() + above.m_comment, ""),
varp->name()+above.m_comment, ""), above.m_varRefp->cloneTree(true), above.m_chgRefp->cloneTree(true));
above.m_varRefp->cloneTree(true),
above.m_chgRefp->cloneTree(true));
m_modp->addStmtp(newp); m_modp->addStmtp(newp);
} }
void toggleVarRecurse(AstNodeDType* dtypep, int depth, // per-iteration void toggleVarRecurse(AstNodeDType* dtypep, int depth, // per-iteration
const ToggleEnt& above, const ToggleEnt& above, AstVar* varp, AstVar* chgVarp) { // Constant
AstVar* varp, AstVar* chgVarp) { // Constant
if (const AstBasicDType* bdtypep = VN_CAST(dtypep, BasicDType)) { if (const AstBasicDType* bdtypep = VN_CAST(dtypep, BasicDType)) {
if (bdtypep->isRanged()) { 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(); int index_code = index_docs - bdtypep->lsb();
ToggleEnt newent(above.m_comment + string("[") + cvtToStr(index_docs) + "]", ToggleEnt newent(above.m_comment + string("[") + cvtToStr(index_docs) + "]",
new AstSel(varp->fileline(), new AstSel(varp->fileline(), above.m_varRefp->cloneTree(true),
above.m_varRefp->cloneTree(true), index_code, 1), index_code, 1),
new AstSel(varp->fileline(), new AstSel(varp->fileline(), above.m_chgRefp->cloneTree(true),
above.m_chgRefp->cloneTree(true), index_code, 1)); index_code, 1));
toggleVarBottom(newent, varp); toggleVarBottom(newent, varp);
newent.cleanup(); newent.cleanup();
} }
} else { } else {
toggleVarBottom(above, varp); toggleVarBottom(above, varp);
} }
} } else if (AstUnpackArrayDType* adtypep = VN_CAST(dtypep, UnpackArrayDType)) {
else if (AstUnpackArrayDType* adtypep = VN_CAST(dtypep, UnpackArrayDType)) {
for (int index_docs = adtypep->lsb(); index_docs <= adtypep->msb(); ++index_docs) { for (int index_docs = adtypep->lsb(); index_docs <= adtypep->msb(); ++index_docs) {
int index_code = index_docs - adtypep->lsb(); int index_code = index_docs - adtypep->lsb();
ToggleEnt newent(above.m_comment + string("[") + cvtToStr(index_docs) + "]", ToggleEnt newent(above.m_comment + string("[") + cvtToStr(index_docs) + "]",
@ -245,13 +234,11 @@ private:
above.m_varRefp->cloneTree(true), index_code), above.m_varRefp->cloneTree(true), index_code),
new AstArraySel(varp->fileline(), new AstArraySel(varp->fileline(),
above.m_chgRefp->cloneTree(true), index_code)); above.m_chgRefp->cloneTree(true), index_code));
toggleVarRecurse(adtypep->subDTypep()->skipRefp(), depth+1, toggleVarRecurse(adtypep->subDTypep()->skipRefp(), depth + 1, newent, varp,
newent, chgVarp);
varp, chgVarp);
newent.cleanup(); newent.cleanup();
} }
} } else if (AstPackArrayDType* adtypep = VN_CAST(dtypep, PackArrayDType)) {
else if (AstPackArrayDType* adtypep = VN_CAST(dtypep, PackArrayDType)) {
for (int index_docs = adtypep->lsb(); index_docs <= adtypep->msb(); ++index_docs) { for (int index_docs = adtypep->lsb(); index_docs <= adtypep->msb(); ++index_docs) {
AstNodeDType* subtypep = adtypep->subDTypep()->skipRefp(); AstNodeDType* subtypep = adtypep->subDTypep()->skipRefp();
int index_code = index_docs - adtypep->lsb(); int index_code = index_docs - adtypep->lsb();
@ -260,16 +247,14 @@ private:
index_code * subtypep->width(), subtypep->width()), index_code * subtypep->width(), subtypep->width()),
new AstSel(varp->fileline(), above.m_chgRefp->cloneTree(true), new AstSel(varp->fileline(), above.m_chgRefp->cloneTree(true),
index_code * subtypep->width(), subtypep->width())); index_code * subtypep->width(), subtypep->width()));
toggleVarRecurse(adtypep->subDTypep()->skipRefp(), depth+1, toggleVarRecurse(adtypep->subDTypep()->skipRefp(), depth + 1, newent, varp,
newent, chgVarp);
varp, chgVarp);
newent.cleanup(); 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 now it's packed, so similar to array
for (AstMemberDType* itemp = adtypep->membersp(); for (AstMemberDType* itemp = adtypep->membersp(); itemp;
itemp; itemp=VN_CAST(itemp->nextp(), MemberDType)) { itemp = VN_CAST(itemp->nextp(), MemberDType)) {
AstNodeDType* subtypep = itemp->subDTypep()->skipRefp(); AstNodeDType* subtypep = itemp->subDTypep()->skipRefp();
int index_code = itemp->lsb(); int index_code = itemp->lsb();
ToggleEnt newent(above.m_comment + string(".") + itemp->name(), ToggleEnt newent(above.m_comment + string(".") + itemp->name(),
@ -277,43 +262,37 @@ private:
index_code, subtypep->width()), index_code, subtypep->width()),
new AstSel(varp->fileline(), above.m_chgRefp->cloneTree(true), new AstSel(varp->fileline(), above.m_chgRefp->cloneTree(true),
index_code, subtypep->width())); index_code, subtypep->width()));
toggleVarRecurse(subtypep, depth+1, toggleVarRecurse(subtypep, depth + 1, newent, varp, chgVarp);
newent,
varp, chgVarp);
newent.cleanup(); 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 // Arbitrarily handle only the first member of the union
if (AstMemberDType* itemp = adtypep->membersp()) { if (AstMemberDType* itemp = adtypep->membersp()) {
AstNodeDType* subtypep = itemp->subDTypep()->skipRefp(); AstNodeDType* subtypep = itemp->subDTypep()->skipRefp();
ToggleEnt newent(above.m_comment + string(".") + itemp->name(), ToggleEnt newent(above.m_comment + string(".") + itemp->name(),
above.m_varRefp->cloneTree(true), above.m_varRefp->cloneTree(true),
above.m_chgRefp->cloneTree(true)); above.m_chgRefp->cloneTree(true));
toggleVarRecurse(subtypep, depth+1, toggleVarRecurse(subtypep, depth + 1, newent, varp, chgVarp);
newent,
varp, chgVarp);
newent.cleanup(); newent.cleanup();
} }
} } else {
else {
dtypep->v3fatalSrc("Unexpected node data type in toggle coverage generation: " dtypep->v3fatalSrc("Unexpected node data type in toggle coverage generation: "
<< dtypep->prettyTypeName()); << dtypep->prettyTypeName());
} }
} }
// VISITORS - LINE COVERAGE // VISITORS - LINE COVERAGE
virtual void visit(AstIf* nodep) VL_OVERRIDE { // Note not AstNodeIf; other types don't get covered virtual void
visit(AstIf* nodep) VL_OVERRIDE { // Note not AstNodeIf; other types don't get covered
UINFO(4, " IF: " << nodep << endl); UINFO(4, " IF: " << nodep << endl);
if (m_checkBlock) { if (m_checkBlock) {
// An else-if. When we iterate the if, use "elsif" marking // An else-if. When we iterate the if, use "elsif" marking
bool elsif = (VN_IS(nodep->elsesp(), If) bool elsif = (VN_IS(nodep->elsesp(), If) && !VN_CAST(nodep->elsesp(), If)->nextp());
&& !VN_CAST(nodep->elsesp(), If)->nextp());
if (elsif) VN_CAST(nodep->elsesp(), If)->user1(true); if (elsif) VN_CAST(nodep->elsesp(), If)->user1(true);
// //
iterateAndNextNull(nodep->ifsp()); iterateAndNextNull(nodep->ifsp());
if (m_checkBlock && !m_inModOff if (m_checkBlock && !m_inModOff && nodep->fileline()->coverageOn()
&& nodep->fileline()->coverageOn() && v3Global.opt.coverageLine()) { // if a "if" branch didn't disable it && v3Global.opt.coverageLine()) { // if a "if" branch didn't disable it
UINFO(4, " COVER: " << nodep << endl); UINFO(4, " COVER: " << nodep << endl);
if (nodep->user1()) { if (nodep->user1()) {
nodep->addIfsp(newCoverInc(nodep->fileline(), "", "v_line", "elsif", nodep->addIfsp(newCoverInc(nodep->fileline(), "", "v_line", "elsif",
@ -327,13 +306,12 @@ private:
if (nodep->elsesp()) { if (nodep->elsesp()) {
m_checkBlock = true; m_checkBlock = true;
iterateAndNextNull(nodep->elsesp()); iterateAndNextNull(nodep->elsesp());
if (m_checkBlock && !m_inModOff if (m_checkBlock && !m_inModOff && nodep->fileline()->coverageOn()
&& nodep->fileline()->coverageOn() && v3Global.opt.coverageLine()) { // if a "else" branch didn't disable it && v3Global.opt.coverageLine()) { // if a "else" branch didn't disable it
UINFO(4, " COVER: " << nodep << endl); UINFO(4, " COVER: " << nodep << endl);
if (!elsif) { // elsif done inside if() if (!elsif) { // elsif done inside if()
nodep->addElsesp(newCoverInc(nodep->elsesp()->fileline(), nodep->addElsesp(newCoverInc(nodep->elsesp()->fileline(), "", "v_line",
"", "v_line", "else", "else", traceNameForLine(nodep, "else")));
traceNameForLine(nodep, "else")));
} }
} }
} }
@ -342,8 +320,8 @@ private:
} }
virtual void visit(AstCaseItem* nodep) VL_OVERRIDE { virtual void visit(AstCaseItem* nodep) VL_OVERRIDE {
UINFO(4, " CASEI: " << nodep << endl); UINFO(4, " CASEI: " << nodep << endl);
if (m_checkBlock && !m_inModOff if (m_checkBlock && !m_inModOff && nodep->fileline()->coverageOn()
&& nodep->fileline()->coverageOn() && v3Global.opt.coverageLine()) { && v3Global.opt.coverageLine()) {
iterateAndNextNull(nodep->bodysp()); iterateAndNextNull(nodep->bodysp());
if (m_checkBlock) { // if the case body didn't disable it if (m_checkBlock) { // if the case body didn't disable it
UINFO(4, " COVER: " << nodep << endl); UINFO(4, " COVER: " << nodep << endl);
@ -424,8 +402,6 @@ public:
void V3Coverage::coverage(AstNetlist* rootp) { void V3Coverage::coverage(AstNetlist* rootp) {
UINFO(2, __FUNCTION__ << ": " << endl); UINFO(2, __FUNCTION__ << ": " << endl);
{ { CoverageVisitor visitor(rootp); } // Destruct before checking
CoverageVisitor visitor (rootp);
} // Destruct before checking
V3Global::dumpCheckGlobalTree("coverage", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3); V3Global::dumpCheckGlobalTree("coverage", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
} }

View File

@ -17,7 +17,6 @@
// If two COVERTOGGLEs have same VARSCOPE, combine them // If two COVERTOGGLEs have same VARSCOPE, combine them
//************************************************************************* //*************************************************************************
#include "config_build.h" #include "config_build.h"
#include "verilatedos.h" #include "verilatedos.h"
@ -88,7 +87,8 @@ private:
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 // Mark the found node as a duplicate of the first node
// (Not vice-versa as we have the iterator for the found 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 // Remove node from comparison so don't hit it again
hashed.erase(dupit); hashed.erase(dupit);
++m_statToggleJoins; ++m_statToggleJoins;
@ -114,9 +114,7 @@ private:
public: public:
// CONSTRUCTORS // CONSTRUCTORS
explicit CoverageJoinVisitor(AstNetlist* nodep) { explicit CoverageJoinVisitor(AstNetlist* nodep) { iterate(nodep); }
iterate(nodep);
}
virtual ~CoverageJoinVisitor() { virtual ~CoverageJoinVisitor() {
V3Stats::addStat("Coverage, Toggle points joined", m_statToggleJoins); V3Stats::addStat("Coverage, Toggle points joined", m_statToggleJoins);
} }
@ -127,8 +125,6 @@ public:
void V3CoverageJoin::coverageJoin(AstNetlist* rootp) { void V3CoverageJoin::coverageJoin(AstNetlist* rootp) {
UINFO(2, __FUNCTION__ << ": " << endl); UINFO(2, __FUNCTION__ << ": " << endl);
{ { CoverageJoinVisitor visitor(rootp); } // Destruct before checking
CoverageJoinVisitor visitor (rootp);
} // Destruct before checking
V3Global::dumpCheckGlobalTree("coveragejoin", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3); V3Global::dumpCheckGlobalTree("coveragejoin", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
} }

View File

@ -69,8 +69,7 @@ private:
nodep->replaceWith(newp); nodep->replaceWith(newp);
// Put assignment before the referencing statement // Put assignment before the referencing statement
AstAssign* assp = new AstAssign(nodep->fileline(), AstAssign* assp = new AstAssign(nodep->fileline(),
new AstVarRef(nodep->fileline(), varp, true), new AstVarRef(nodep->fileline(), varp, true), nodep);
nodep);
AstNRelinker linker2; AstNRelinker linker2;
m_stmtp->unlinkFrBack(&linker2); m_stmtp->unlinkFrBack(&linker2);
assp->addNext(m_stmtp); assp->addNext(m_stmtp);
@ -110,8 +109,7 @@ private:
} }
} }
// Operators // Operators
virtual void visit(AstNodeTermop* nodep) VL_OVERRIDE { virtual void visit(AstNodeTermop* nodep) VL_OVERRIDE {}
}
virtual void visit(AstNodeMath* nodep) VL_OVERRIDE { virtual void visit(AstNodeMath* nodep) VL_OVERRIDE {
// We have some operator defines that use 2 parens, so += 2. // We have some operator defines that use 2 parens, so += 2.
m_depth += 2; m_depth += 2;
@ -119,8 +117,7 @@ private:
iterateChildren(nodep); iterateChildren(nodep);
m_depth -= 2; m_depth -= 2;
if (m_stmtp if (m_stmtp && (v3Global.opt.compLimitParens() >= 1) // Else compiler doesn't need it
&& (v3Global.opt.compLimitParens() >= 1) // Else compiler doesn't need it
&& (m_maxdepth - m_depth) > v3Global.opt.compLimitParens() && (m_maxdepth - m_depth) > v3Global.opt.compLimitParens()
&& !VN_IS(nodep->backp(), NodeStmt) // Not much point if we're about to use it && !VN_IS(nodep->backp(), NodeStmt) // Not much point if we're about to use it
) { ) {
@ -172,8 +169,6 @@ public:
void V3Depth::depthAll(AstNetlist* nodep) { void V3Depth::depthAll(AstNetlist* nodep) {
UINFO(2, __FUNCTION__ << ": " << endl); UINFO(2, __FUNCTION__ << ": " << endl);
{ { DepthVisitor visitor(nodep); } // Destruct before checking
DepthVisitor visitor (nodep);
} // Destruct before checking
V3Global::dumpCheckGlobalTree("depth", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 6); V3Global::dumpCheckGlobalTree("depth", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 6);
} }

View File

@ -136,8 +136,6 @@ public:
void V3DepthBlock::depthBlockAll(AstNetlist* nodep) { void V3DepthBlock::depthBlockAll(AstNetlist* nodep) {
UINFO(2, __FUNCTION__ << ": " << endl); UINFO(2, __FUNCTION__ << ": " << endl);
{ { DepthBlockVisitor visitor(nodep); } // Destruct before checking
DepthBlockVisitor visitor (nodep);
} // Destruct before checking
V3Global::dumpCheckGlobalTree("deepblock", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3); V3Global::dumpCheckGlobalTree("deepblock", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
} }

View File

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

View File

@ -107,9 +107,7 @@ class EmitCInlines : EmitCBaseVisitor {
public: public:
explicit EmitCInlines(AstNetlist* nodep) { explicit EmitCInlines(AstNetlist* nodep) {
iterate(nodep); iterate(nodep);
if (v3Global.needHInlines()) { if (v3Global.needHInlines()) emitInt();
emitInt();
}
} }
}; };

View File

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

View File

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

View File

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

View File

@ -47,16 +47,20 @@ typedef bool (*V3EdgeFuncP)(const V3GraphEdge* edgep);
class GraphWay { class GraphWay {
public: public:
enum en { FORWARD=0, enum en {
FORWARD = 0,
REVERSE = 1, REVERSE = 1,
NUM_WAYS = 2 // NUM_WAYS is not an actual way, it's typically NUM_WAYS = 2 // NUM_WAYS is not an actual way, it's typically
// // an array dimension or loop bound. // // an array dimension or loop bound.
}; };
enum en m_e; enum en m_e;
inline GraphWay() : m_e(FORWARD) {} inline GraphWay()
: m_e(FORWARD) {}
// cppcheck-suppress noExplicitConstructor // cppcheck-suppress noExplicitConstructor
inline GraphWay(en _e) : m_e(_e) {} inline GraphWay(en _e)
explicit inline GraphWay(int _e) : m_e(static_cast<en>(_e)) {} : m_e(_e) {}
explicit inline GraphWay(int _e)
: m_e(static_cast<en>(_e)) {}
operator en() const { return m_e; } operator en() const { return m_e; }
const char* ascii() const { const char* ascii() const {
static const char* const names[] = {"FORWARD", "REVERSE"}; static const char* const names[] = {"FORWARD", "REVERSE"};
@ -78,8 +82,10 @@ private:
// MEMBERS // MEMBERS
V3List<V3GraphVertex*> m_vertices; // All vertices V3List<V3GraphVertex*> m_vertices; // All vertices
static int s_debug; static int s_debug;
protected: protected:
friend class V3GraphVertex; friend class V3GraphEdge; friend class V3GraphVertex;
friend class V3GraphEdge;
friend class GraphAcyc; friend class GraphAcyc;
// METHODS // METHODS
void acyclicDFS(); void acyclicDFS();
@ -91,6 +97,7 @@ protected:
void verticesUnlink() { m_vertices.reset(); } void verticesUnlink() { m_vertices.reset(); }
// ACCESSORS // ACCESSORS
static int debug(); static int debug();
public: public:
V3Graph(); V3Graph();
virtual ~V3Graph(); virtual ~V3Graph();
@ -181,8 +188,10 @@ public:
class V3GraphVertex { class V3GraphVertex {
// Vertices may be a 'gate'/wire statement OR a variable // Vertices may be a 'gate'/wire statement OR a variable
protected: protected:
friend class V3Graph; friend class V3GraphEdge; friend class V3Graph;
friend class GraphAcyc; friend class GraphAlgRank; friend class V3GraphEdge;
friend class GraphAcyc;
friend class GraphAlgRank;
V3ListEnt<V3GraphVertex*> m_vertices; // All vertices, linked list V3ListEnt<V3GraphVertex*> m_vertices; // All vertices, linked list
V3List<V3GraphEdge*> m_outs; // Outbound edges,linked list V3List<V3GraphEdge*> m_outs; // Outbound edges,linked list
V3List<V3GraphEdge*> m_ins; // Inbound edges, linked list V3List<V3GraphEdge*> m_ins; // Inbound edges, linked list
@ -202,11 +211,13 @@ protected:
protected: protected:
// CONSTRUCTORS // CONSTRUCTORS
V3GraphVertex(V3Graph* graphp, const V3GraphVertex& old); V3GraphVertex(V3Graph* graphp, const V3GraphVertex& old);
public: public:
explicit V3GraphVertex(V3Graph* graphp); explicit V3GraphVertex(V3Graph* graphp);
//! Clone copy constructor. Doesn't copy edges or user/userp. //! Clone copy constructor. Doesn't copy edges or user/userp.
virtual V3GraphVertex* clone(V3Graph* graphp) const { virtual V3GraphVertex* clone(V3Graph* graphp) const {
return new V3GraphVertex(graphp, *this); } return new V3GraphVertex(graphp, *this);
}
virtual ~V3GraphVertex() {} virtual ~V3GraphVertex() {}
void unlinkEdges(V3Graph* graphp); void unlinkEdges(V3Graph* graphp);
void unlinkDelete(V3Graph* graphp); void unlinkDelete(V3Graph* graphp);
@ -246,8 +257,7 @@ public:
bool outEmpty() const { return outBeginp() == NULL; } bool outEmpty() const { return outBeginp() == NULL; }
bool outSize1() const; bool outSize1() const;
uint32_t outHash() const; uint32_t outHash() const;
V3GraphEdge* beginp(GraphWay way) const { V3GraphEdge* beginp(GraphWay way) const { return way.forward() ? outBeginp() : inBeginp(); }
return way.forward() ? outBeginp() : inBeginp(); }
// METHODS // METHODS
/// Error reporting /// Error reporting
void v3errorEnd(std::ostringstream& str) const; void v3errorEnd(std::ostringstream& str) const;
@ -269,8 +279,10 @@ public:
// ENUMS // ENUMS
enum Cutable { NOT_CUTABLE = false, CUTABLE = true }; // For passing to V3GraphEdge enum Cutable { NOT_CUTABLE = false, CUTABLE = true }; // For passing to V3GraphEdge
protected: protected:
friend class V3Graph; friend class V3GraphVertex; friend class V3Graph;
friend class GraphAcyc; friend class GraphAcycEdge; friend class V3GraphVertex;
friend class GraphAcyc;
friend class GraphAcycEdge;
V3ListEnt<V3GraphEdge*> m_outs; // Next Outbound edge for same vertex (linked list) V3ListEnt<V3GraphEdge*> m_outs; // Next Outbound edge for same vertex (linked list)
V3ListEnt<V3GraphEdge*> m_ins; // Next Inbound edge for same vertex (linked list) V3ListEnt<V3GraphEdge*> m_ins; // Next Inbound edge for same vertex (linked list)
// //
@ -283,8 +295,8 @@ protected:
uint32_t m_user; // Marker for some algorithms uint32_t m_user; // Marker for some algorithms
}; };
// METHODS // METHODS
void init(V3Graph* graphp, V3GraphVertex* fromp, V3GraphVertex* top, void init(V3Graph* graphp, V3GraphVertex* fromp, V3GraphVertex* top, int weight,
int weight, bool cutable=false); bool cutable = false);
void cut() { m_weight = 0; } // 0 weight is same as disconnected void cut() { m_weight = 0; } // 0 weight is same as disconnected
void outPushBack(); void outPushBack();
void inPushBack(); void inPushBack();
@ -294,15 +306,17 @@ protected:
const V3GraphEdge& old) { const V3GraphEdge& old) {
init(graphp, fromp, top, old.m_weight, old.m_cutable); init(graphp, fromp, top, old.m_weight, old.m_cutable);
} }
public: public:
//! Add DAG from one node to the specified node //! Add DAG from one node to the specified node
V3GraphEdge(V3Graph* graphp, V3GraphVertex* fromp, V3GraphVertex* top, V3GraphEdge(V3Graph* graphp, V3GraphVertex* fromp, V3GraphVertex* top, int weight,
int weight, bool cutable=false) { bool cutable = false) {
init(graphp, fromp, top, weight, cutable); init(graphp, fromp, top, weight, cutable);
} }
//! Clone copy constructor. Doesn't copy existing vertices or user/userp. //! Clone copy constructor. Doesn't copy existing vertices or user/userp.
virtual V3GraphEdge* clone(V3Graph* graphp, V3GraphVertex* fromp, V3GraphVertex* top) const { 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() {} virtual ~V3GraphEdge() {}
// METHODS // METHODS
virtual string name() const { return m_fromp->name() + "->" + m_top->name(); } virtual string name() const { return m_fromp->name() + "->" + m_top->name(); }
@ -334,8 +348,7 @@ public:
// ITERATORS // ITERATORS
V3GraphEdge* outNextp() const { return m_outs.nextp(); } V3GraphEdge* outNextp() const { return m_outs.nextp(); }
V3GraphEdge* inNextp() const { return m_ins.nextp(); } V3GraphEdge* inNextp() const { return m_ins.nextp(); }
V3GraphEdge* nextp(GraphWay way) const { V3GraphEdge* nextp(GraphWay way) const { return way.forward() ? outNextp() : inNextp(); }
return way.forward() ? outNextp() : inNextp(); }
}; };
//============================================================================ //============================================================================

View File

@ -32,8 +32,8 @@
DfaVertex* DfaGraph::findStart() { DfaVertex* DfaGraph::findStart() {
DfaVertex* startp = NULL; DfaVertex* startp = NULL;
for (V3GraphVertex* vertexp = this->verticesBeginp(); for (V3GraphVertex* vertexp = this->verticesBeginp(); vertexp;
vertexp; vertexp=vertexp->verticesNextp()) { vertexp = vertexp->verticesNextp()) {
if (DfaVertex* vvertexp = dynamic_cast<DfaVertex*>(vertexp)) { if (DfaVertex* vvertexp = dynamic_cast<DfaVertex*>(vertexp)) {
if (vvertexp->start()) { if (vvertexp->start()) {
UASSERT_OBJ(!startp, vertexp, "Multiple start points in NFA graph"); UASSERT_OBJ(!startp, vertexp, "Multiple start points in NFA graph");
@ -95,8 +95,16 @@ private:
// Hashing // Hashing
static uint32_t hashVertex(V3GraphVertex* vertexp) { static uint32_t hashVertex(V3GraphVertex* vertexp) {
union { void* up; struct {uint32_t upper; uint32_t lower;} l;} u; union {
u.l.upper = 0; u.l.lower = 0; u.up = vertexp; 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; return u.l.upper ^ u.l.lower;
} }
@ -108,8 +116,8 @@ private:
uint32_t hash = 0; uint32_t hash = 0;
// Foreach NFA state (this DFA state was formed from) // Foreach NFA state (this DFA state was formed from)
if (debug()) nextStep(); if (debug()) nextStep();
for (V3GraphEdge* dfaEdgep = dfaStatep->outBeginp(); for (V3GraphEdge* dfaEdgep = dfaStatep->outBeginp(); dfaEdgep;
dfaEdgep; dfaEdgep=dfaEdgep->outNextp()) { dfaEdgep = dfaEdgep->outNextp()) {
if (nfaState(dfaEdgep->top())) { if (nfaState(dfaEdgep->top())) {
DfaVertex* nfaStatep = static_cast<DfaVertex*>(dfaEdgep->top()); DfaVertex* nfaStatep = static_cast<DfaVertex*>(dfaEdgep->top());
hash ^= hashVertex(nfaStatep); hash ^= hashVertex(nfaStatep);
@ -126,8 +134,8 @@ private:
uint32_t hashDfaOrigins(const DfaStates& nfasWithInput) { uint32_t hashDfaOrigins(const DfaStates& nfasWithInput) {
// Find the NFA states this dfa came from, // Find the NFA states this dfa came from,
uint32_t hash = 0; uint32_t hash = 0;
for (DfaStates::const_iterator nfaIt=nfasWithInput.begin(); for (DfaStates::const_iterator nfaIt = nfasWithInput.begin(); nfaIt != nfasWithInput.end();
nfaIt!=nfasWithInput.end(); ++nfaIt) { ++nfaIt) {
DfaVertex* nfaStatep = *nfaIt; DfaVertex* nfaStatep = *nfaIt;
hash ^= hashVertex(nfaStatep); hash ^= hashVertex(nfaStatep);
} }
@ -140,8 +148,8 @@ private:
nextStep(); nextStep();
// Mark all input vertexes // Mark all input vertexes
int num1s = 0; int num1s = 0;
for (DfaStates::const_iterator nfaIt=nfasWithInput.begin(); for (DfaStates::const_iterator nfaIt = nfasWithInput.begin(); nfaIt != nfasWithInput.end();
nfaIt!=nfasWithInput.end(); ++nfaIt) { ++nfaIt) {
DfaVertex* nfaStatep = *nfaIt; DfaVertex* nfaStatep = *nfaIt;
nfaStatep->user(m_step); nfaStatep->user(m_step);
num1s++; num1s++;
@ -151,7 +159,8 @@ private:
// Check comparison; must all be marked // Check comparison; must all be marked
// (Check all in dfa2p were in dfa1p) // (Check all in dfa2p were in dfa1p)
int num2s = 0; 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 (nfaState(dfaEdgep->top())) {
if (dfaEdgep->top()->user() != m_step) return false; if (dfaEdgep->top()->user() != m_step) return false;
num2s++; num2s++;
@ -185,21 +194,20 @@ private:
return NULL; // No match return NULL; // No match
} }
void findNfasWithInput(DfaVertex* dfaStatep, DfaInput input, void findNfasWithInput(DfaVertex* dfaStatep, DfaInput input, DfaStates& nfasWithInput) {
DfaStates& nfasWithInput) {
// Return all NFA states, with the given input transition from // Return all NFA states, with the given input transition from
// the nfa states a given dfa state was constructed from. // the nfa states a given dfa state was constructed from.
nextStep(); nextStep();
nfasWithInput.clear(); // NFAs with given input nfasWithInput.clear(); // NFAs with given input
// Foreach NFA state (this DFA state was formed from) // Foreach NFA state (this DFA state was formed from)
for (V3GraphEdge* dfaEdgep = dfaStatep->outBeginp(); for (V3GraphEdge* dfaEdgep = dfaStatep->outBeginp(); dfaEdgep;
dfaEdgep; dfaEdgep=dfaEdgep->outNextp()) { dfaEdgep = dfaEdgep->outNextp()) {
if (nfaState(dfaEdgep->top())) { if (nfaState(dfaEdgep->top())) {
DfaVertex* nfaStatep = static_cast<DfaVertex*>(dfaEdgep->top()); DfaVertex* nfaStatep = static_cast<DfaVertex*>(dfaEdgep->top());
// Foreach input transition (on this nfaStatep) // Foreach input transition (on this nfaStatep)
for (V3GraphEdge* nfaEdgep = nfaStatep->outBeginp(); for (V3GraphEdge* nfaEdgep = nfaStatep->outBeginp(); nfaEdgep;
nfaEdgep; nfaEdgep=nfaEdgep->outNextp()) { nfaEdgep = nfaEdgep->outNextp()) {
DfaEdge* cNfaEdgep = static_cast<DfaEdge*>(nfaEdgep); DfaEdge* cNfaEdgep = static_cast<DfaEdge*>(nfaEdgep);
if (cNfaEdgep->input().toNodep() == input.toNodep()) { if (cNfaEdgep->input().toNodep() == input.toNodep()) {
DfaVertex* nextStatep = static_cast<DfaVertex*>(cNfaEdgep->top()); DfaVertex* nextStatep = static_cast<DfaVertex*>(cNfaEdgep->top());
@ -219,11 +227,12 @@ private:
DfaStates nfasTodo = nfasWithInput; DfaStates nfasTodo = nfasWithInput;
nfasWithInput.clear(); // Now the completed list nfasWithInput.clear(); // Now the completed list
while (!nfasTodo.empty()) { while (!nfasTodo.empty()) {
DfaVertex* nfaStatep = nfasTodo.front(); nfasTodo.pop_front(); DfaVertex* nfaStatep = nfasTodo.front();
nfasTodo.pop_front();
nfasWithInput.push_back(nfaStatep); nfasWithInput.push_back(nfaStatep);
// Foreach epsilon-reachable (on this nfaStatep) // Foreach epsilon-reachable (on this nfaStatep)
for (V3GraphEdge* nfaEdgep = nfaStatep->outBeginp(); for (V3GraphEdge* nfaEdgep = nfaStatep->outBeginp(); nfaEdgep;
nfaEdgep; nfaEdgep=nfaEdgep->outNextp()) { nfaEdgep = nfaEdgep->outNextp()) {
DfaEdge* cNfaEdgep = static_cast<DfaEdge*>(nfaEdgep); DfaEdge* cNfaEdgep = static_cast<DfaEdge*>(nfaEdgep);
if (cNfaEdgep->epsilon()) { if (cNfaEdgep->epsilon()) {
DfaVertex* nextStatep = static_cast<DfaVertex*>(cNfaEdgep->top()); DfaVertex* nextStatep = static_cast<DfaVertex*>(cNfaEdgep->top());
@ -259,23 +268,24 @@ private:
UINFO(5, "Starting state conversion...\n"); UINFO(5, "Starting state conversion...\n");
// Form DFA starting state from epsilon closure of NFA start // Form DFA starting state from epsilon closure of NFA start
nextStep(); nextStep();
DfaStates workps; workps.push_back(nfaStartp); DfaStates workps;
workps.push_back(nfaStartp);
while (!workps.empty()) { // While work while (!workps.empty()) { // While work
DfaVertex* nfaStatep = workps.back(); workps.pop_back(); DfaVertex* nfaStatep = workps.back();
workps.pop_back();
// UINFO(9," Processing "<<nfaStatep<<endl); // UINFO(9," Processing "<<nfaStatep<<endl);
nfaStatep->user(m_step); // Mark as processed nfaStatep->user(m_step); // Mark as processed
// Add a edge so we can find NFAs from a given DFA. // 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. // The NFA will never see this edge, because we only look at TO edges.
new DfaEdge(graphp(), dfaStartp, nfaStatep, DfaEdge::NA()); new DfaEdge(graphp(), dfaStartp, nfaStatep, DfaEdge::NA());
// Find epsilon closure of this nfa node, and destinations to work list // Find epsilon closure of this nfa node, and destinations to work list
for (V3GraphEdge* nfaEdgep = nfaStatep->outBeginp(); for (V3GraphEdge* nfaEdgep = nfaStatep->outBeginp(); nfaEdgep;
nfaEdgep; nfaEdgep=nfaEdgep->outNextp()) { nfaEdgep = nfaEdgep->outNextp()) {
DfaEdge* cNfaEdgep = static_cast<DfaEdge*>(nfaEdgep); DfaEdge* cNfaEdgep = static_cast<DfaEdge*>(nfaEdgep);
DfaVertex* ecNfaStatep = static_cast<DfaVertex*>(nfaEdgep->top()); DfaVertex* ecNfaStatep = static_cast<DfaVertex*>(nfaEdgep->top());
// UINFO(9," Consider "<<nfaEdgep->top()<<" EP "<<cNfaEdgep->epsilon()<<endl); // UINFO(9," Consider "<<nfaEdgep->top()<<" EP "<<cNfaEdgep->epsilon()<<endl);
if (cNfaEdgep->epsilon() if (cNfaEdgep->epsilon() && unseenNfaThisStep(ecNfaStatep)) { // Not processed?
&& unseenNfaThisStep(ecNfaStatep)) { // Not processed?
workps.push_back(ecNfaStatep); workps.push_back(ecNfaStatep);
} }
} }
@ -286,25 +296,27 @@ private:
int i = 0; int i = 0;
UINFO(5, "Main state conversion...\n"); UINFO(5, "Main state conversion...\n");
while (!dfaUnprocps.empty()) { while (!dfaUnprocps.empty()) {
DfaVertex* dfaStatep = dfaUnprocps.back(); dfaUnprocps.pop_back(); DfaVertex* dfaStatep = dfaUnprocps.back();
dfaUnprocps.pop_back();
UINFO(9, " On dfaState " << dfaStatep << endl); UINFO(9, " On dfaState " << dfaStatep << endl);
// From this dfaState, what corresponding nfaStates have what inputs? // From this dfaState, what corresponding nfaStates have what inputs?
std::set<int> inputs; std::set<int> inputs;
// Foreach NFA state (this DFA state was formed from) // Foreach NFA state (this DFA state was formed from)
for (V3GraphEdge* dfaEdgep = dfaStatep->outBeginp(); for (V3GraphEdge* dfaEdgep = dfaStatep->outBeginp(); dfaEdgep;
dfaEdgep; dfaEdgep=dfaEdgep->outNextp()) { dfaEdgep = dfaEdgep->outNextp()) {
if (nfaState(dfaEdgep->top())) { if (nfaState(dfaEdgep->top())) {
DfaVertex* nfaStatep = static_cast<DfaVertex*>(dfaEdgep->top()); DfaVertex* nfaStatep = static_cast<DfaVertex*>(dfaEdgep->top());
// Foreach input on this nfaStatep // Foreach input on this nfaStatep
for (V3GraphEdge* nfaEdgep = nfaStatep->outBeginp(); for (V3GraphEdge* nfaEdgep = nfaStatep->outBeginp(); nfaEdgep;
nfaEdgep; nfaEdgep=nfaEdgep->outNextp()) { nfaEdgep = nfaEdgep->outNextp()) {
DfaEdge* cNfaEdgep = static_cast<DfaEdge*>(nfaEdgep); DfaEdge* cNfaEdgep = static_cast<DfaEdge*>(nfaEdgep);
if (!cNfaEdgep->epsilon()) { if (!cNfaEdgep->epsilon()) {
if (inputs.find(cNfaEdgep->input().toInt()) == inputs.end()) { if (inputs.find(cNfaEdgep->input().toInt()) == inputs.end()) {
inputs.insert(cNfaEdgep->input().toInt()); inputs.insert(cNfaEdgep->input().toInt());
UINFO(9, " Input to " << dfaStatep << " is " UINFO(9, " Input to " << dfaStatep << " is "
<<(cNfaEdgep->input().toInt())<<" via "<<nfaStatep<<endl); << (cNfaEdgep->input().toInt()) << " via "
<< nfaStatep << endl);
} }
} }
} }
@ -312,7 +324,8 @@ private:
} }
// Foreach input state (NFA inputs of this DFA state) // 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; DfaInput input = *inIt;
UINFO(9, " ===" << ++i << "=======================\n"); UINFO(9, " ===" << ++i << "=======================\n");
UINFO(9, " On input " << cvtToHex(input.toNodep()) << endl); UINFO(9, " On input " << cvtToHex(input.toNodep()) << endl);
@ -347,11 +360,10 @@ private:
// Remove old NFA states // Remove old NFA states
UINFO(5, "Removing NFA states...\n"); UINFO(5, "Removing NFA states...\n");
if (debug() >= 6) m_graphp->dumpDotFilePrefixed("dfa_withnfa"); if (debug() >= 6) m_graphp->dumpDotFilePrefixed("dfa_withnfa");
for (V3GraphVertex* nextp,*vertexp = m_graphp->verticesBeginp(); vertexp; vertexp=nextp) { for (V3GraphVertex *nextp, *vertexp = m_graphp->verticesBeginp(); vertexp;
vertexp = nextp) {
nextp = vertexp->verticesNextp(); nextp = vertexp->verticesNextp();
if (nfaState(vertexp)) { if (nfaState(vertexp)) VL_DO_DANGLING(vertexp->unlinkDelete(m_graphp), vertexp);
VL_DO_DANGLING(vertexp->unlinkDelete(m_graphp), vertexp);
}
} }
UINFO(5, "Done.\n"); UINFO(5, "Done.\n");
@ -367,9 +379,7 @@ public:
~GraphNfaToDfa() {} ~GraphNfaToDfa() {}
}; };
void DfaGraph::nfaToDfa() { void DfaGraph::nfaToDfa() { GraphNfaToDfa(this, &V3GraphEdge::followAlwaysTrue); }
GraphNfaToDfa(this, &V3GraphEdge::followAlwaysTrue);
}
//###################################################################### //######################################################################
//###################################################################### //######################################################################
@ -399,8 +409,8 @@ private:
void optimize_accepting_out() { void optimize_accepting_out() {
// Delete outbound edges from accepting states // Delete outbound edges from accepting states
// (As once we've accepted, we no longer care about anything else.) // (As once we've accepted, we no longer care about anything else.)
for (V3GraphVertex* vertexp = m_graphp->verticesBeginp(); for (V3GraphVertex* vertexp = m_graphp->verticesBeginp(); vertexp;
vertexp; vertexp=vertexp->verticesNextp()) { vertexp = vertexp->verticesNextp()) {
if (DfaVertex* vvertexp = dynamic_cast<DfaVertex*>(vertexp)) { if (DfaVertex* vvertexp = dynamic_cast<DfaVertex*>(vertexp)) {
if (vvertexp->accepting()) { if (vvertexp->accepting()) {
for (V3GraphEdge *nextp, *edgep = vertexp->outBeginp(); edgep; edgep = nextp) { for (V3GraphEdge *nextp, *edgep = vertexp->outBeginp(); edgep; edgep = nextp) {
@ -421,11 +431,13 @@ private:
m_graphp->userClearVertices(); m_graphp->userClearVertices();
DfaVertex* startp = graphp()->findStart(); DfaVertex* startp = graphp()->findStart();
std::stack<V3GraphVertex*> workps; workps.push(startp); std::stack<V3GraphVertex*> workps;
workps.push(startp);
// Mark all nodes connected to start // Mark all nodes connected to start
while (!workps.empty()) { while (!workps.empty()) {
V3GraphVertex* vertexp = workps.top(); workps.pop(); V3GraphVertex* vertexp = workps.top();
workps.pop();
vertexp->user(2); // Processed vertexp->user(2); // Processed
// Add nodes from here to the work list // 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()) {
@ -438,11 +450,10 @@ private:
} }
// Delete all nodes not connected // 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(); nextp = vertexp->verticesNextp();
if (!vertexp->user()) { if (!vertexp->user()) { VL_DO_DANGLING(vertexp->unlinkDelete(m_graphp), vertexp); }
VL_DO_DANGLING(vertexp->unlinkDelete(m_graphp), vertexp);
}
} }
} }
@ -457,8 +468,8 @@ private:
// Find all dead vertexes // Find all dead vertexes
std::stack<DfaVertex*> workps; std::stack<DfaVertex*> workps;
for (V3GraphVertex* vertexp = m_graphp->verticesBeginp(); for (V3GraphVertex* vertexp = m_graphp->verticesBeginp(); vertexp;
vertexp; vertexp=vertexp->verticesNextp()) { vertexp = vertexp->verticesNextp()) {
if (DfaVertex* vvertexp = dynamic_cast<DfaVertex*>(vertexp)) { if (DfaVertex* vvertexp = dynamic_cast<DfaVertex*>(vertexp)) {
workps.push(vvertexp); workps.push(vvertexp);
vertexp->user(1); vertexp->user(1);
@ -470,14 +481,14 @@ private:
// While deadness... Delete and find new dead nodes. // While deadness... Delete and find new dead nodes.
while (!workps.empty()) { while (!workps.empty()) {
DfaVertex* vertexp = workps.top(); workps.pop(); DfaVertex* vertexp = workps.top();
workps.pop();
vertexp->user(0); vertexp->user(0);
if (isDead(vertexp)) { if (isDead(vertexp)) {
// Add nodes that go here to the work list // 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()); DfaVertex* fromvertexp = static_cast<DfaVertex*>(edgep->fromp());
if (fromvertexp != vertexp if (fromvertexp != vertexp && !fromvertexp->user()) {
&& !fromvertexp->user()) {
workps.push(fromvertexp); workps.push(fromvertexp);
fromvertexp->user(1); fromvertexp->user(1);
} }
@ -487,6 +498,7 @@ private:
} }
} }
} }
public: public:
DfaGraphReduce(V3Graph* graphp, V3EdgeFuncP edgeFuncp) DfaGraphReduce(V3Graph* graphp, V3EdgeFuncP edgeFuncp)
: GraphAlg<>(graphp, edgeFuncp) { : GraphAlg<>(graphp, edgeFuncp) {
@ -501,9 +513,7 @@ public:
~DfaGraphReduce() {} ~DfaGraphReduce() {}
}; };
void DfaGraph::dfaReduce() { void DfaGraph::dfaReduce() { DfaGraphReduce(this, &V3GraphEdge::followAlwaysTrue); }
DfaGraphReduce(this, &V3GraphEdge::followAlwaysTrue);
}
//###################################################################### //######################################################################
//###################################################################### //######################################################################
@ -537,8 +547,8 @@ private:
void add_complement_edges() { void add_complement_edges() {
// Find accepting vertex // Find accepting vertex
DfaVertex* acceptp = NULL; DfaVertex* acceptp = NULL;
for (V3GraphVertex* vertexp = m_graphp->verticesBeginp(); for (V3GraphVertex* vertexp = m_graphp->verticesBeginp(); vertexp;
vertexp; vertexp=vertexp->verticesNextp()) { vertexp = vertexp->verticesNextp()) {
if (DfaVertex* vvertexp = dynamic_cast<DfaVertex*>(vertexp)) { if (DfaVertex* vvertexp = dynamic_cast<DfaVertex*>(vertexp)) {
if (vvertexp->accepting()) { if (vvertexp->accepting()) {
acceptp = vvertexp; acceptp = vvertexp;
@ -549,8 +559,8 @@ private:
if (!acceptp) v3fatalSrc("No accepting vertex in DFA"); if (!acceptp) v3fatalSrc("No accepting vertex in DFA");
// Remap edges // Remap edges
for (V3GraphVertex* vertexp = m_graphp->verticesBeginp(); for (V3GraphVertex* vertexp = m_graphp->verticesBeginp(); vertexp;
vertexp; vertexp=vertexp->verticesNextp()) { vertexp = vertexp->verticesNextp()) {
if (DfaVertex* vvertexp = dynamic_cast<DfaVertex*>(vertexp)) { 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) { if (!vvertexp->accepting() && vvertexp != m_tempNewerReject) {
@ -568,7 +578,8 @@ private:
// NOT of all values goes to accept // NOT of all values goes to accept
// We make a edge for each value to OR, IE // We make a edge for each value to OR, IE
// edge(complemented,a) edge(complemented,b) means !(a | b) // 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); DfaEdge* newp = new DfaEdge(graphp(), vvertexp, acceptp, vedgep);
newp->complement(!newp->complement()); newp->complement(!newp->complement());
newp->user(1); newp->user(1);
@ -579,6 +590,7 @@ private:
} }
} }
} }
public: public:
DfaGraphComplement(V3Graph* dfagraphp, V3EdgeFuncP edgeFuncp) DfaGraphComplement(V3Graph* dfagraphp, V3EdgeFuncP edgeFuncp)
: GraphAlg<>(dfagraphp, edgeFuncp) { : GraphAlg<>(dfagraphp, edgeFuncp) {
@ -598,6 +610,4 @@ public:
VL_UNCOPYABLE(DfaGraphComplement); VL_UNCOPYABLE(DfaGraphComplement);
}; };
void DfaGraph::dfaComplement() { void DfaGraph::dfaComplement() { DfaGraphComplement(this, &V3GraphEdge::followAlwaysTrue); }
DfaGraphComplement(this, &V3GraphEdge::followAlwaysTrue);
}

View File

@ -87,10 +87,12 @@ public:
// CONSTRUCTORS // CONSTRUCTORS
explicit DfaVertex(DfaGraph* graphp, bool start = false, bool accepting = false) explicit DfaVertex(DfaGraph* graphp, bool start = false, bool accepting = false)
: V3GraphVertex(graphp) : V3GraphVertex(graphp)
, m_start(start), m_accepting(accepting) {} , m_start(start)
, m_accepting(accepting) {}
using V3GraphVertex::clone; // We are overriding, not overloading clone(V3Graph*) using V3GraphVertex::clone; // We are overriding, not overloading clone(V3Graph*)
virtual DfaVertex* clone(DfaGraph* graphp) { virtual DfaVertex* clone(DfaGraph* graphp) {
return new DfaVertex(graphp, start(), accepting()); } return new DfaVertex(graphp, start(), accepting());
}
virtual ~DfaVertex() {} virtual ~DfaVertex() {}
// ACCESSORS // ACCESSORS
virtual string dotShape() const { return (accepting() ? "doublecircle" : ""); } virtual string dotShape() const { return (accepting() ? "doublecircle" : ""); }
@ -118,21 +120,21 @@ public:
// CONSTRUCTORS // CONSTRUCTORS
DfaEdge(DfaGraph* graphp, DfaVertex* fromp, DfaVertex* top, const DfaInput& input) DfaEdge(DfaGraph* graphp, DfaVertex* fromp, DfaVertex* top, const DfaInput& input)
: V3GraphEdge(graphp, fromp, top, 1) : 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) DfaEdge(DfaGraph* graphp, DfaVertex* fromp, DfaVertex* top, const DfaEdge* copyfrom)
: V3GraphEdge(graphp, fromp, top, copyfrom->weight()) : V3GraphEdge(graphp, fromp, top, copyfrom->weight())
, m_input(copyfrom->input()), m_complement(copyfrom->complement()) {} , m_input(copyfrom->input())
, m_complement(copyfrom->complement()) {}
virtual ~DfaEdge() {} virtual ~DfaEdge() {}
// METHODS // METHODS
virtual string dotColor() const { virtual string dotColor() const { return (na() ? "yellow" : epsilon() ? "green" : "black"); }
return (na() ? "yellow"
: epsilon() ? "green"
: "black"); }
virtual string dotLabel() const { virtual string dotLabel() const {
return (na() ? "" return (na() ? ""
: epsilon() ? "e" : epsilon() ? "e"
: complement() ? ("not " + cvtToStr(input().toInt())) : complement() ? ("not " + cvtToStr(input().toInt()))
: cvtToStr(input().toInt())); } : cvtToStr(input().toInt()));
}
virtual string dotStyle() const { return (na() || cutable()) ? "dashed" : ""; } virtual string dotStyle() const { return (na() || cutable()) ? "dashed" : ""; }
bool epsilon() const { return input().toInt() == EPSILON().toInt(); } bool epsilon() const { return input().toInt() == EPSILON().toInt(); }
bool na() const { return input().toInt() == NA().toInt(); } bool na() const { return input().toInt() == NA().toInt(); }

View File

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

View File

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

View File

@ -52,6 +52,7 @@ class V3Hashed : public VHashedBase {
public: public:
typedef std::multimap<V3Hash, AstNode*> HashMmap; typedef std::multimap<V3Hash, AstNode*> HashMmap;
typedef HashMmap::iterator iterator; typedef HashMmap::iterator iterator;
private: private:
// MEMBERS // MEMBERS
HashMmap m_hashMmap; // hashvalue -> nodes with that hash HashMmap m_hashMmap; // hashvalue -> nodes with that hash
@ -67,9 +68,13 @@ public:
iterator end() { return m_hashMmap.end(); } iterator end() { return m_hashMmap.end(); }
// METHODS // METHODS
void clear() { m_hashMmap.clear(); AstNode::user4ClearTree(); } void clear() {
m_hashMmap.clear();
AstNode::user4ClearTree();
}
void check(); // Check assertions on structure 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 void hash(AstNode* nodep); // Only hash the node
bool sameNodes(AstNode* node1p, AstNode* node2p); // After hashing, and tell if identical bool sameNodes(AstNode* node1p, AstNode* node2p); // After hashing, and tell if identical
void erase(iterator it); // Remove node from structures void erase(iterator it); // Remove node from structures

View File

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

View File

@ -52,15 +52,16 @@ private:
uint32_t m_savedCount; uint32_t m_savedCount;
AstNode* m_nodep; AstNode* m_nodep;
InstrCountVisitor* m_visitor; InstrCountVisitor* m_visitor;
public: public:
// CONSTRUCTORS // CONSTRUCTORS
VisitBase(InstrCountVisitor* visitor, AstNode* nodep) VisitBase(InstrCountVisitor* visitor, AstNode* nodep)
: m_nodep(nodep), m_visitor(visitor) { : m_nodep(nodep)
, m_visitor(visitor) {
m_savedCount = m_visitor->startVisitBase(nodep); m_savedCount = m_visitor->startVisitBase(nodep);
} }
~VisitBase() { ~VisitBase() { m_visitor->endVisitBase(m_savedCount, m_nodep); }
m_visitor->endVisitBase(m_savedCount, m_nodep);
}
private: private:
VL_UNCOPYABLE(VisitBase); VL_UNCOPYABLE(VisitBase);
}; };
@ -68,13 +69,12 @@ private:
public: public:
// CONSTRUCTORS // CONSTRUCTORS
InstrCountVisitor(AstNode* nodep, bool assertNoDups, std::ostream* osp) InstrCountVisitor(AstNode* nodep, bool assertNoDups, std::ostream* osp)
: m_instrCount(0), : m_instrCount(0)
m_startNodep(nodep), , m_startNodep(nodep)
m_tracingCall(false), , m_tracingCall(false)
m_inCFunc(false), , m_inCFunc(false)
m_assertNoDups(assertNoDups), , m_assertNoDups(assertNoDups)
m_osp(osp) , m_osp(osp) {
{
if (nodep) iterate(nodep); if (nodep) iterate(nodep);
} }
virtual ~InstrCountVisitor() {} virtual ~InstrCountVisitor() {}
@ -110,8 +110,7 @@ private:
return savedCount; return savedCount;
} }
void endVisitBase(uint32_t savedCount, AstNode* nodep) { void endVisitBase(uint32_t savedCount, AstNode* nodep) {
UINFO(8, "cost "<<std::setw(6)<<std::left<<m_instrCount UINFO(8, "cost " << std::setw(6) << std::left << m_instrCount << " " << nodep << endl);
<<" "<<nodep<<endl);
markCost(nodep); markCost(nodep);
m_instrCount += savedCount; m_instrCount += savedCount;
} }
@ -275,7 +274,8 @@ private:
public: public:
// CONSTRUCTORS // CONSTRUCTORS
InstrCountDumpVisitor(AstNode* nodep, std::ostream* osp) InstrCountDumpVisitor(AstNode* nodep, std::ostream* osp)
: m_osp(osp), m_depth(0) { : m_osp(osp)
, m_depth(0) {
// No check for NULL output, so... // No check for NULL output, so...
UASSERT_OBJ(osp, nodep, "Don't call if not dumping"); UASSERT_OBJ(osp, nodep, "Don't call if not dumping");
if (nodep) iterate(nodep); if (nodep) iterate(nodep);
@ -288,8 +288,7 @@ private:
virtual void visit(AstNode* nodep) VL_OVERRIDE { virtual void visit(AstNode* nodep) VL_OVERRIDE {
++m_depth; ++m_depth;
if (unsigned costPlus1 = nodep->user4()) { if (unsigned costPlus1 = nodep->user4()) {
*m_osp <<" "<<indent() *m_osp << " " << indent() << "cost " << std::setw(6) << std::left << (costPlus1 - 1)
<<"cost "<<std::setw(6)<<std::left<<(costPlus1-1)
<< " " << nodep << endl; << " " << nodep << endl;
iterateChildren(nodep); iterateChildren(nodep);
} }

View File

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

View File

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

View File

@ -31,6 +31,7 @@ class V3LinkDot {
private: private:
static int debug(); static int debug();
static void linkDotGuts(AstNetlist* rootp, VLinkDotStep step); static void linkDotGuts(AstNetlist* rootp, VLinkDotStep step);
public: public:
static void linkDotPrimary(AstNetlist* nodep) { static void linkDotPrimary(AstNetlist* nodep) {
UINFO(2, __FUNCTION__ << ": " << endl); UINFO(2, __FUNCTION__ << ": " << endl);

View File

@ -48,14 +48,11 @@ private:
// Result handing // Result handing
virtual void visit(AstNodeVarRef* nodep) VL_OVERRIDE { virtual void visit(AstNodeVarRef* nodep) VL_OVERRIDE {
// VarRef: LValue its reference // VarRef: LValue its reference
if (m_setRefLvalue) { if (m_setRefLvalue) nodep->lvalue(true);
nodep->lvalue(true);
}
if (nodep->varp()) { if (nodep->varp()) {
if (nodep->lvalue() && !m_ftaskp if (nodep->lvalue() && !m_ftaskp && nodep->varp()->isReadOnly()) {
&& nodep->varp()->isReadOnly()) { nodep->v3warn(ASSIGNIN,
nodep->v3warn(ASSIGNIN, "Assigning to input/const variable: " "Assigning to input/const variable: " << nodep->prettyNameQ());
<<nodep->prettyNameQ());
} }
} }
iterateChildren(nodep); iterateChildren(nodep);
@ -292,9 +289,7 @@ public:
void V3LinkLValue::linkLValue(AstNetlist* nodep) { void V3LinkLValue::linkLValue(AstNetlist* nodep) {
UINFO(4, __FUNCTION__ << ": " << endl); UINFO(4, __FUNCTION__ << ": " << endl);
{ { LinkLValueVisitor visitor(nodep, false); } // Destruct before checking
LinkLValueVisitor visitor(nodep, false);
} // Destruct before checking
V3Global::dumpCheckGlobalTree("linklvalue", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 6); V3Global::dumpCheckGlobalTree("linklvalue", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 6);
} }
void V3LinkLValue::linkLValueSet(AstNode* nodep) { void V3LinkLValue::linkLValueSet(AstNode* nodep) {

View File

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

View File

@ -85,9 +85,7 @@ private:
public: public:
// CONSTRUCTORS // CONSTRUCTORS
explicit LocalizeDehierVisitor(AstNetlist* nodep) { explicit LocalizeDehierVisitor(AstNetlist* nodep) { iterate(nodep); }
iterate(nodep);
}
virtual ~LocalizeDehierVisitor() {} virtual ~LocalizeDehierVisitor() {}
}; };
@ -130,8 +128,7 @@ private:
if ((nodep->isMovableToBlock() // Blocktemp if ((nodep->isMovableToBlock() // Blocktemp
|| !flags.m_notStd) // Or used only in block || !flags.m_notStd) // Or used only in block
&& !flags.m_notOpt // Optimizable && !flags.m_notOpt // Optimizable
&& !nodep->isClassMember() && !nodep->isClassMember() && nodep->user1p()) { // Single cfunc
&& nodep->user1p()) { // Single cfunc
// We don't need to test for tracing; it would be in the tracefunc if it was needed // 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; ++m_statLocVars;
@ -185,8 +182,7 @@ private:
} }
virtual void visit(AstVar* nodep) VL_OVERRIDE { virtual void visit(AstVar* nodep) VL_OVERRIDE {
if (!nodep->isSigPublic() if (!nodep->isSigPublic() && !nodep->isPrimaryIO()
&& !nodep->isPrimaryIO()
&& !m_cfuncp) { // Not already inside a function && !m_cfuncp) { // Not already inside a function
UINFO(4, " BLKVAR " << nodep << endl); UINFO(4, " BLKVAR " << nodep << endl);
m_varps.push_back(nodep); m_varps.push_back(nodep);
@ -197,8 +193,7 @@ private:
if (!VarFlags(nodep->varp()).m_notOpt) { if (!VarFlags(nodep->varp()).m_notOpt) {
if (!m_cfuncp) { // Not in function, can't optimize if (!m_cfuncp) { // Not in function, can't optimize
clearOptimizable(nodep->varp(), "BVnofunc"); clearOptimizable(nodep->varp(), "BVnofunc");
} } else {
else {
// If we're scoping down to it, it isn't really in the same block // If we're scoping down to it, it isn't really in the same block
if (!nodep->hierThis()) clearOptimizable(nodep->varp(), "HierRef"); if (!nodep->hierThis()) clearOptimizable(nodep->varp(), "HierRef");
// Allow a variable to appear in only a single function // Allow a variable to appear in only a single function

View File

@ -60,8 +60,8 @@ private:
} else { } else {
string rsvd = m_words.isKeyword(nodep->name()); string rsvd = m_words.isKeyword(nodep->name());
if (rsvd != "") { if (rsvd != "") {
nodep->v3warn(SYMRSVDWORD, "Symbol matches "+rsvd nodep->v3warn(SYMRSVDWORD,
+": "<<nodep->prettyNameQ()); "Symbol matches " + rsvd + ": " << nodep->prettyNameQ());
string newname = string("__SYM__") + nodep->name(); string newname = string("__SYM__") + nodep->name();
nodep->name(newname); nodep->name(newname);
nodep->editCountInc(); nodep->editCountInc();
@ -83,8 +83,8 @@ private:
// Add __PVT__ to names of local signals // Add __PVT__ to names of local signals
virtual void visit(AstVar* nodep) VL_OVERRIDE { virtual void visit(AstVar* nodep) VL_OVERRIDE {
// Don't iterate... Don't need temps for RANGES under the Var. // Don't iterate... Don't need temps for RANGES under the Var.
rename(nodep, ((!m_modp || !m_modp->isTop()) rename(nodep,
&& !nodep->isSigPublic() ((!m_modp || !m_modp->isTop()) && !nodep->isSigPublic()
&& !nodep->isFuncLocal() // Isn't exposed, and would mess up dpi import wrappers && !nodep->isFuncLocal() // Isn't exposed, and would mess up dpi import wrappers
&& !nodep->isTemp())); // Don't bother to rename internal signals && !nodep->isTemp())); // Don't bother to rename internal signals
} }
@ -102,8 +102,7 @@ private:
} }
virtual void visit(AstCell* nodep) VL_OVERRIDE { virtual void visit(AstCell* nodep) VL_OVERRIDE {
if (!nodep->user1()) { if (!nodep->user1()) {
rename(nodep, (!nodep->modp()->modPublic() rename(nodep, (!nodep->modp()->modPublic() && !VN_IS(nodep->modp(), ClassPackage)));
&& !VN_IS(nodep->modp(), ClassPackage)));
iterateChildren(nodep); iterateChildren(nodep);
} }
} }
@ -125,10 +124,13 @@ private:
if (nodep->aboveCellp()) iterate(nodep->aboveCellp()); if (nodep->aboveCellp()) iterate(nodep->aboveCellp());
// Always recompute name (as many levels above scope may have changed) // Always recompute name (as many levels above scope may have changed)
// Same formula as V3Scope // Same formula as V3Scope
nodep->name(nodep->isTop() ? "TOP" nodep->name(nodep->isTop()
? "TOP"
: VN_IS(m_modp, Class) ? ("TOP." + m_modp->name()) : VN_IS(m_modp, Class) ? ("TOP." + m_modp->name())
: VN_IS(m_modp, ClassPackage) ? ("TOP." + m_modp->name()) : VN_IS(m_modp, ClassPackage)
: (nodep->aboveScopep()->name() + "." + nodep->aboveCellp()->name())); ? ("TOP." + m_modp->name())
: (nodep->aboveScopep()->name() + "."
+ nodep->aboveCellp()->name()));
nodep->editCountInc(); nodep->editCountInc();
iterateChildren(nodep); iterateChildren(nodep);
} }
@ -151,8 +153,6 @@ public:
void V3Name::nameAll(AstNetlist* nodep) { void V3Name::nameAll(AstNetlist* nodep) {
UINFO(2, __FUNCTION__ << ": " << endl); UINFO(2, __FUNCTION__ << ": " << endl);
{ { NameVisitor visitor(nodep); } // Destruct before checking
NameVisitor visitor (nodep);
} // Destruct before checking
V3Global::dumpCheckGlobalTree("name", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 6); V3Global::dumpCheckGlobalTree("name", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 6);
} }

View File

@ -41,37 +41,68 @@ void test(const string& lhss, const string& op, const string& rhss, const string
V3Number expnum(fl, e1); V3Number expnum(fl, e1);
V3Number gotnum(fl, expnum.width()); V3Number gotnum(fl, expnum.width());
if (op=="redOr") gotnum.opRedOr (lhnum); if (op == "redOr") {
else if (op=="redAnd") gotnum.opRedAnd (lhnum); gotnum.opRedOr(lhnum);
else if (op=="redXor") gotnum.opRedXor (lhnum); } else if (op == "redAnd") {
else if (op=="redXnor") gotnum.opRedXnor (lhnum); gotnum.opRedAnd(lhnum);
else if (op=="concat") gotnum.opConcat (lhnum, rhnum); } else if (op == "redXor") {
else if (op=="repl") gotnum.opRepl (lhnum, rhnum); gotnum.opRedXor(lhnum);
else if (op=="~") gotnum.opNot (lhnum); } else if (op == "redXnor") {
else if (op=="!") gotnum.opLogNot (lhnum); gotnum.opRedXnor(lhnum);
else if (op=="negate") gotnum.opNegate (lhnum); } else if (op == "concat") {
else if (op=="+") gotnum.opAdd (lhnum, rhnum); gotnum.opConcat(lhnum, rhnum);
else if (op=="-") gotnum.opSub (lhnum, rhnum); } else if (op == "repl") {
else if (op=="*") gotnum.opMul (lhnum, rhnum); gotnum.opRepl(lhnum, rhnum);
else if (op=="/") gotnum.opDiv (lhnum, rhnum); } else if (op == "~") {
else if (op=="%") gotnum.opModDiv (lhnum, rhnum); gotnum.opNot(lhnum);
else if (op=="&") gotnum.opAnd (lhnum, rhnum); } else if (op == "!") {
else if (op=="|") gotnum.opOr (lhnum, rhnum); gotnum.opLogNot(lhnum);
else if (op=="<") gotnum.opLt (lhnum, rhnum); } else if (op == "negate") {
else if (op==">") gotnum.opGt (lhnum, rhnum); gotnum.opNegate(lhnum);
else if (op==">>") gotnum.opShiftR (lhnum, rhnum); } else if (op == "+") {
else if (op=="<<") gotnum.opShiftL (lhnum, rhnum); gotnum.opAdd(lhnum, rhnum);
else if (op=="==") gotnum.opEq (lhnum, rhnum); } else if (op == "-") {
else if (op=="===") gotnum.opCaseEq (lhnum, rhnum); gotnum.opSub(lhnum, rhnum);
else if (op=="==?") gotnum.opWildEq (lhnum, rhnum); } else if (op == "*") {
else if (op=="!=") gotnum.opNeq (lhnum, rhnum); gotnum.opMul(lhnum, rhnum);
else if (op=="!==") gotnum.opCaseNeq (lhnum, rhnum); } else if (op == "/") {
else if (op=="!=?") gotnum.opWildNeq (lhnum, rhnum); gotnum.opDiv(lhnum, rhnum);
else if (op=="<=") gotnum.opLte (lhnum, rhnum); } else if (op == "%") {
else if (op==">=") gotnum.opGte (lhnum, rhnum); gotnum.opModDiv(lhnum, rhnum);
else if (op=="&&") gotnum.opLogAnd (lhnum, rhnum); } else if (op == "&") {
else if (op=="||") gotnum.opLogOr (lhnum, rhnum); gotnum.opAnd(lhnum, rhnum);
else v3fatalSrc("Bad opcode: "<<op); } 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" UINFO(0, "------- Test:\n"
<< " " << lhnum << " " << op << endl << " " << lhnum << " " << op << endl
@ -81,9 +112,7 @@ void test(const string& lhss, const string& op, const string& rhss, const string
V3Number ok(fl, 1); V3Number ok(fl, 1);
ok.opCaseEq(expnum, gotnum); ok.opCaseEq(expnum, gotnum);
if (ok.toUInt()!=1) { if (ok.toUInt() != 1) { v3fatalSrc("%Error:Test FAILED"); }
v3fatalSrc("%Error:Test FAILED");
}
free(l1); free(l1);
free(r1); free(r1);
@ -106,7 +135,8 @@ int main() {
test("57'h000000010F0CCE7", "*", "57'h10", "57'h10F0CCE70"); test("57'h000000010F0CCE7", "*", "57'h10", "57'h10F0CCE70");
test("57'h000000010F0CCE7", "*", "57'h0DE34E7FFFFFFFF", "57'h02A9D57EF0F3319"); test("57'h000000010F0CCE7", "*", "57'h0DE34E7FFFFFFFF", "57'h02A9D57EF0F3319");
test("67'h7FFFFFFFFFFFFFFFF", "*", "67'h4000000003C8A8D6A", "67'h3FFFFFFFFC3757296"); 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 // OrderPreCutEdge
//************************************************************************* //*************************************************************************
#ifndef _V3ORDERGRAPH_H_ #ifndef _V3ORDERGRAPH_H_
#define _V3ORDERGRAPH_H_ #define _V3ORDERGRAPH_H_
@ -62,7 +61,8 @@ enum OrderWeights {
WEIGHT_POST = 2, // Post-delayed used var WEIGHT_POST = 2, // Post-delayed used var
WEIGHT_PRE = 3, // Breakable pre-delayed used var WEIGHT_PRE = 3, // Breakable pre-delayed used var
WEIGHT_MEDIUM = 8, // Medium weight just so dot graph looks nice 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 { struct OrderVEdgeType {
enum en { enum en {
@ -84,20 +84,21 @@ struct OrderVEdgeType {
_ENUM_END _ENUM_END
}; };
const char* ascii() const { const char* ascii() const {
static const char* const names[] = { static const char* const names[]
"%E-vedge", "VERTEX_INPUTS", "VERTEX_SETTLE", "VERTEX_LOGIC", = {"%E-vedge", "VERTEX_INPUTS", "VERTEX_SETTLE", "VERTEX_LOGIC",
"VERTEX_VARSTD", "VERTEX_VARPRE", "VERTEX_VARPOST", "VERTEX_VARSTD", "VERTEX_VARPRE", "VERTEX_VARPOST", "VERTEX_VARPORD",
"VERTEX_VARPORD", "VERTEX_VARSETTLE", "VERTEX_MOVE", "VERTEX_VARSETTLE", "VERTEX_MOVE", "EDGE_STD", "EDGE_CHANGEDET",
"EDGE_STD", "EDGE_CHANGEDET", "EDGE_COMBOCUT", "EDGE_COMBOCUT", "EDGE_PRECUT", "EDGE_POSTCUT", "_ENUM_END"};
"EDGE_PRECUT", "EDGE_POSTCUT", "_ENUM_END"
};
return names[m_e]; return names[m_e];
} }
enum en m_e; enum en m_e;
inline OrderVEdgeType() : m_e(VERTEX_UNKNOWN) {} inline OrderVEdgeType()
: m_e(VERTEX_UNKNOWN) {}
// cppcheck-suppress noExplicitConstructor // cppcheck-suppress noExplicitConstructor
inline OrderVEdgeType(en _e) : m_e(_e) {} inline OrderVEdgeType(en _e)
explicit inline OrderVEdgeType(int _e) : m_e(static_cast<en>(_e)) {} : m_e(_e) {}
explicit inline OrderVEdgeType(int _e)
: m_e(static_cast<en>(_e)) {}
operator en() const { return m_e; } operator en() const { return m_e; }
}; };
inline bool operator==(const OrderVEdgeType& lhs, const OrderVEdgeType& rhs) { inline bool operator==(const OrderVEdgeType& lhs, const OrderVEdgeType& rhs) {
@ -139,11 +140,16 @@ class OrderEitherVertex : public V3GraphVertex {
bool m_isFromInput; // From input, or derived therefrom (conservatively false) bool m_isFromInput; // From input, or derived therefrom (conservatively false)
protected: protected:
OrderEitherVertex(V3Graph* graphp, const OrderEitherVertex& old) 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) {} , m_isFromInput(old.m_isFromInput) {}
public: public:
OrderEitherVertex(V3Graph* graphp, AstScope* scopep, AstSenTree* domainp) 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) {} , m_isFromInput(false) {}
virtual ~OrderEitherVertex() {} virtual ~OrderEitherVertex() {}
virtual OrderEitherVertex* clone(V3Graph* graphp) const = 0; virtual OrderEitherVertex* clone(V3Graph* graphp) const = 0;
@ -162,6 +168,7 @@ public:
class OrderInputsVertex : public OrderEitherVertex { class OrderInputsVertex : public OrderEitherVertex {
OrderInputsVertex(V3Graph* graphp, const OrderInputsVertex& old) OrderInputsVertex(V3Graph* graphp, const OrderInputsVertex& old)
: OrderEitherVertex(graphp, old) {} : OrderEitherVertex(graphp, old) {}
public: public:
OrderInputsVertex(V3Graph* graphp, AstSenTree* domainp) OrderInputsVertex(V3Graph* graphp, AstSenTree* domainp)
: OrderEitherVertex(graphp, NULL, domainp) { : OrderEitherVertex(graphp, NULL, domainp) {
@ -169,7 +176,8 @@ public:
} }
virtual ~OrderInputsVertex() {} virtual ~OrderInputsVertex() {}
virtual OrderInputsVertex* clone(V3Graph* graphp) const { 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 OrderVEdgeType type() const { return OrderVEdgeType::VERTEX_INPUTS; }
virtual string name() const { return "*INPUTS*"; } virtual string name() const { return "*INPUTS*"; }
virtual string dotColor() const { return "green"; } virtual string dotColor() const { return "green"; }
@ -180,12 +188,14 @@ public:
class OrderSettleVertex : public OrderEitherVertex { class OrderSettleVertex : public OrderEitherVertex {
OrderSettleVertex(V3Graph* graphp, const OrderSettleVertex& old) OrderSettleVertex(V3Graph* graphp, const OrderSettleVertex& old)
: OrderEitherVertex(graphp, old) {} : OrderEitherVertex(graphp, old) {}
public: public:
OrderSettleVertex(V3Graph* graphp, AstSenTree* domainp) OrderSettleVertex(V3Graph* graphp, AstSenTree* domainp)
: OrderEitherVertex(graphp, NULL, domainp) {} : OrderEitherVertex(graphp, NULL, domainp) {}
virtual ~OrderSettleVertex() {} virtual ~OrderSettleVertex() {}
virtual OrderSettleVertex* clone(V3Graph* graphp) const { 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 OrderVEdgeType type() const { return OrderVEdgeType::VERTEX_SETTLE; }
virtual string name() const { return "*SETTLE*"; } virtual string name() const { return "*SETTLE*"; }
virtual string dotColor() const { return "green"; } virtual string dotColor() const { return "green"; }
@ -195,20 +205,26 @@ public:
class OrderLogicVertex : public OrderEitherVertex { class OrderLogicVertex : public OrderEitherVertex {
AstNode* m_nodep; AstNode* m_nodep;
protected: protected:
OrderLogicVertex(V3Graph* graphp, const OrderLogicVertex& old) OrderLogicVertex(V3Graph* graphp, const OrderLogicVertex& old)
: OrderEitherVertex(graphp, old), m_nodep(old.m_nodep) {} : OrderEitherVertex(graphp, old)
, m_nodep(old.m_nodep) {}
public: public:
OrderLogicVertex(V3Graph* graphp, AstScope* scopep, AstSenTree* domainp, AstNode* nodep) 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() {}
virtual OrderLogicVertex* clone(V3Graph* graphp) const { 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 OrderVEdgeType type() const { return OrderVEdgeType::VERTEX_LOGIC; }
virtual bool domainMatters() { return true; } virtual bool domainMatters() { return true; }
// ACCESSORS // ACCESSORS
virtual string name() const { 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; } AstNode* nodep() const { return m_nodep; }
virtual string dotColor() const { return "yellow"; } virtual string dotColor() const { return "yellow"; }
}; };
@ -220,12 +236,16 @@ class OrderVarVertex : public OrderEitherVertex {
protected: protected:
OrderVarVertex(V3Graph* graphp, const OrderVarVertex& old) OrderVarVertex(V3Graph* graphp, const OrderVarVertex& old)
: OrderEitherVertex(graphp, 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) {} , m_isDelayed(old.m_isDelayed) {}
public: public:
OrderVarVertex(V3Graph* graphp, AstScope* scopep, AstVarScope* varScp) OrderVarVertex(V3Graph* graphp, AstScope* scopep, AstVarScope* varScp)
: OrderEitherVertex(graphp, scopep, NULL), m_varScp(varScp) : OrderEitherVertex(graphp, scopep, NULL)
, m_isClock(false), m_isDelayed(false) {} , m_varScp(varScp)
, m_isClock(false)
, m_isDelayed(false) {}
virtual ~OrderVarVertex() {} virtual ~OrderVarVertex() {}
virtual OrderVarVertex* clone(V3Graph* graphp) const = 0; virtual OrderVarVertex* clone(V3Graph* graphp) const = 0;
virtual OrderVEdgeType type() const = 0; virtual OrderVEdgeType type() const = 0;
@ -241,12 +261,14 @@ public:
class OrderVarStdVertex : public OrderVarVertex { class OrderVarStdVertex : public OrderVarVertex {
OrderVarStdVertex(V3Graph* graphp, const OrderVarStdVertex& old) OrderVarStdVertex(V3Graph* graphp, const OrderVarStdVertex& old)
: OrderVarVertex(graphp, old) {} : OrderVarVertex(graphp, old) {}
public: public:
OrderVarStdVertex(V3Graph* graphp, AstScope* scopep, AstVarScope* varScp) OrderVarStdVertex(V3Graph* graphp, AstScope* scopep, AstVarScope* varScp)
: OrderVarVertex(graphp, scopep, varScp) {} : OrderVarVertex(graphp, scopep, varScp) {}
virtual ~OrderVarStdVertex() {} virtual ~OrderVarStdVertex() {}
virtual OrderVarStdVertex* clone(V3Graph* graphp) const { 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 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 string dotColor() const { return "skyblue"; }
@ -255,12 +277,14 @@ public:
class OrderVarPreVertex : public OrderVarVertex { class OrderVarPreVertex : public OrderVarVertex {
OrderVarPreVertex(V3Graph* graphp, const OrderVarPreVertex& old) OrderVarPreVertex(V3Graph* graphp, const OrderVarPreVertex& old)
: OrderVarVertex(graphp, old) {} : OrderVarVertex(graphp, old) {}
public: public:
OrderVarPreVertex(V3Graph* graphp, AstScope* scopep, AstVarScope* varScp) OrderVarPreVertex(V3Graph* graphp, AstScope* scopep, AstVarScope* varScp)
: OrderVarVertex(graphp, scopep, varScp) {} : OrderVarVertex(graphp, scopep, varScp) {}
virtual ~OrderVarPreVertex() {} virtual ~OrderVarPreVertex() {}
virtual OrderVarPreVertex* clone(V3Graph* graphp) const { 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 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 string dotColor() const { return "lightblue"; }
@ -269,11 +293,13 @@ public:
class OrderVarPostVertex : public OrderVarVertex { class OrderVarPostVertex : public OrderVarVertex {
OrderVarPostVertex(V3Graph* graphp, const OrderVarPostVertex& old) OrderVarPostVertex(V3Graph* graphp, const OrderVarPostVertex& old)
: OrderVarVertex(graphp, old) {} : OrderVarVertex(graphp, old) {}
public: public:
OrderVarPostVertex(V3Graph* graphp, AstScope* scopep, AstVarScope* varScp) OrderVarPostVertex(V3Graph* graphp, AstScope* scopep, AstVarScope* varScp)
: OrderVarVertex(graphp, scopep, varScp) {} : OrderVarVertex(graphp, scopep, varScp) {}
virtual OrderVarPostVertex* clone(V3Graph* graphp) const { 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 OrderVEdgeType type() const { return OrderVEdgeType::VERTEX_VARPOST; }
virtual ~OrderVarPostVertex() {} virtual ~OrderVarPostVertex() {}
virtual string name() const { return (cvtToHex(varScp()) + " POST\\n " + varScp()->name()); } virtual string name() const { return (cvtToHex(varScp()) + " POST\\n " + varScp()->name()); }
@ -283,12 +309,14 @@ public:
class OrderVarPordVertex : public OrderVarVertex { class OrderVarPordVertex : public OrderVarVertex {
OrderVarPordVertex(V3Graph* graphp, const OrderVarPordVertex& old) OrderVarPordVertex(V3Graph* graphp, const OrderVarPordVertex& old)
: OrderVarVertex(graphp, old) {} : OrderVarVertex(graphp, old) {}
public: public:
OrderVarPordVertex(V3Graph* graphp, AstScope* scopep, AstVarScope* varScp) OrderVarPordVertex(V3Graph* graphp, AstScope* scopep, AstVarScope* varScp)
: OrderVarVertex(graphp, scopep, varScp) {} : OrderVarVertex(graphp, scopep, varScp) {}
virtual ~OrderVarPordVertex() {} virtual ~OrderVarPordVertex() {}
virtual OrderVarPordVertex* clone(V3Graph* graphp) const { 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 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 string dotColor() const { return "NavyBlue"; }
@ -297,12 +325,14 @@ public:
class OrderVarSettleVertex : public OrderVarVertex { class OrderVarSettleVertex : public OrderVarVertex {
OrderVarSettleVertex(V3Graph* graphp, const OrderVarSettleVertex& old) OrderVarSettleVertex(V3Graph* graphp, const OrderVarSettleVertex& old)
: OrderVarVertex(graphp, old) {} : OrderVarVertex(graphp, old) {}
public: public:
OrderVarSettleVertex(V3Graph* graphp, AstScope* scopep, AstVarScope* varScp) OrderVarSettleVertex(V3Graph* graphp, AstScope* scopep, AstVarScope* varScp)
: OrderVarVertex(graphp, scopep, varScp) {} : OrderVarVertex(graphp, scopep, varScp) {}
virtual ~OrderVarSettleVertex() {} virtual ~OrderVarSettleVertex() {}
virtual OrderVarSettleVertex* clone(V3Graph* graphp) const { 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 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 string dotColor() const { return "PowderBlue"; }
@ -329,26 +359,36 @@ protected:
public: public:
// CONSTRUCTORS // CONSTRUCTORS
OrderMoveVertex(V3Graph* graphp, OrderLogicVertex* logicp) 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() {}
virtual OrderMoveVertex* clone(V3Graph* graphp) const { virtual OrderMoveVertex* clone(V3Graph* graphp) const {
v3fatalSrc("Unsupported"); return NULL; } v3fatalSrc("Unsupported");
return NULL;
}
// METHODS // METHODS
virtual OrderVEdgeType type() const { return OrderVEdgeType::VERTEX_MOVE; } virtual OrderVEdgeType type() const { return OrderVEdgeType::VERTEX_MOVE; }
virtual string dotColor() const { virtual string dotColor() const {
if (logicp()) return logicp()->dotColor(); if (logicp()) {
else return ""; return logicp()->dotColor();
} else {
return "";
}
} }
virtual FileLine* fileline() const { virtual FileLine* fileline() const {
if (logicp()) return logicp()->fileline(); if (logicp()) {
else return NULL; return logicp()->fileline();
} else {
return NULL;
}
} }
virtual string name() const { virtual string name() const {
string nm; string nm;
if (logicp()) { if (logicp()) {
nm = logicp()->name(); nm = logicp()->name();
nm += (string("\\nMV:") nm += (string("\\nMV:") + " d=" + cvtToHex(logicp()->domainp())
+" d="+cvtToHex(logicp()->domainp())
+ " s=" + cvtToHex(logicp()->scopep())); + " s=" + cvtToHex(logicp()->scopep()));
} else { } else {
nm = "nul"; nm = "nul";
@ -383,30 +423,36 @@ class MTaskMoveVertex : public V3GraphVertex {
protected: protected:
friend class OrderVisitor; friend class OrderVisitor;
friend class MTaskMoveVertexMaker; friend class MTaskMoveVertexMaker;
public: public:
MTaskMoveVertex(V3Graph* graphp, OrderLogicVertex* logicp, MTaskMoveVertex(V3Graph* graphp, OrderLogicVertex* logicp, const OrderEitherVertex* varp,
const OrderEitherVertex* varp,
const AstScope* scopep, const AstSenTree* domainp) const AstScope* scopep, const AstSenTree* domainp)
: V3GraphVertex(graphp), m_logicp(logicp), : V3GraphVertex(graphp)
m_varp(varp), m_scopep(scopep), m_domainp(domainp) { , m_logicp(logicp)
UASSERT(!(logicp && varp), , m_varp(varp)
"MTaskMoveVertex: logicp and varp may not both be set!\n"); , m_scopep(scopep)
, m_domainp(domainp) {
UASSERT(!(logicp && varp), "MTaskMoveVertex: logicp and varp may not both be set!\n");
} }
virtual ~MTaskMoveVertex() {} virtual ~MTaskMoveVertex() {}
virtual MTaskMoveVertex* clone(V3Graph* graphp) const { virtual MTaskMoveVertex* clone(V3Graph* graphp) const {
v3fatalSrc("Unsupported"); return NULL; } v3fatalSrc("Unsupported");
return NULL;
}
virtual OrderVEdgeType type() const { return OrderVEdgeType::VERTEX_MOVE; } virtual OrderVEdgeType type() const { return OrderVEdgeType::VERTEX_MOVE; }
virtual string dotColor() const { virtual string dotColor() const {
if (logicp()) return logicp()->dotColor(); if (logicp()) {
else return "yellow"; return logicp()->dotColor();
} else {
return "yellow";
}
} }
virtual string name() const { virtual string name() const {
string nm; string nm;
if (logicp()) { if (logicp()) {
nm = logicp()->name(); nm = logicp()->name();
nm += (string("\\nMV:") nm += (string("\\nMV:") + " d=" + cvtToHex(logicp()->domainp()) + " s="
+" d="+cvtToHex(logicp()->domainp()) + cvtToHex(logicp()->scopep())
+" s="+cvtToHex(logicp()->scopep())
// "color()" represents the mtask ID. // "color()" represents the mtask ID.
+ "\\nt=" + cvtToStr(color())); + "\\nt=" + cvtToStr(color()));
} else { } else {
@ -426,12 +472,12 @@ public:
class OrderEdge : public V3GraphEdge { class OrderEdge : public V3GraphEdge {
protected: protected:
OrderEdge(V3Graph* graphp, V3GraphVertex* fromp, V3GraphVertex* top, OrderEdge(V3Graph* graphp, V3GraphVertex* fromp, V3GraphVertex* top, const OrderEdge& old)
const OrderEdge& old)
: V3GraphEdge(graphp, fromp, top, old) {} : V3GraphEdge(graphp, fromp, top, old) {}
public: public:
OrderEdge(V3Graph* graphp, V3GraphVertex* fromp, V3GraphVertex* top, OrderEdge(V3Graph* graphp, V3GraphVertex* fromp, V3GraphVertex* top, int weight,
int weight, bool cutable=false) bool cutable = false)
: V3GraphEdge(graphp, fromp, top, weight, cutable) {} : V3GraphEdge(graphp, fromp, top, weight, cutable) {}
virtual ~OrderEdge() {} virtual ~OrderEdge() {}
virtual OrderVEdgeType type() const { return OrderVEdgeType::EDGE_STD; } virtual OrderVEdgeType type() const { return OrderVEdgeType::EDGE_STD; }
@ -461,13 +507,14 @@ class OrderComboCutEdge : public OrderEdge {
OrderComboCutEdge(V3Graph* graphp, V3GraphVertex* fromp, V3GraphVertex* top, OrderComboCutEdge(V3Graph* graphp, V3GraphVertex* fromp, V3GraphVertex* top,
const OrderComboCutEdge& old) const OrderComboCutEdge& old)
: OrderEdge(graphp, fromp, top, old) {} : OrderEdge(graphp, fromp, top, old) {}
public: public:
OrderComboCutEdge(V3Graph* graphp, V3GraphVertex* fromp, V3GraphVertex* top) OrderComboCutEdge(V3Graph* graphp, V3GraphVertex* fromp, V3GraphVertex* top)
: OrderEdge(graphp, fromp, top, WEIGHT_COMBO, CUTABLE) {} : OrderEdge(graphp, fromp, top, WEIGHT_COMBO, CUTABLE) {}
virtual OrderVEdgeType type() const { return OrderVEdgeType::EDGE_COMBOCUT; } virtual OrderVEdgeType type() const { return OrderVEdgeType::EDGE_COMBOCUT; }
virtual ~OrderComboCutEdge() {} virtual ~OrderComboCutEdge() {}
virtual OrderComboCutEdge* clone(V3Graph* graphp, virtual OrderComboCutEdge* clone(V3Graph* graphp, V3GraphVertex* fromp,
V3GraphVertex* fromp, V3GraphVertex* top) const { V3GraphVertex* top) const {
return new OrderComboCutEdge(graphp, fromp, top, *this); return new OrderComboCutEdge(graphp, fromp, top, *this);
} }
virtual string dotColor() const { return "yellowGreen"; } virtual string dotColor() const { return "yellowGreen"; }
@ -482,13 +529,14 @@ class OrderPostCutEdge : public OrderEdge {
OrderPostCutEdge(V3Graph* graphp, V3GraphVertex* fromp, V3GraphVertex* top, OrderPostCutEdge(V3Graph* graphp, V3GraphVertex* fromp, V3GraphVertex* top,
const OrderPostCutEdge& old) const OrderPostCutEdge& old)
: OrderEdge(graphp, fromp, top, old) {} : OrderEdge(graphp, fromp, top, old) {}
public: public:
OrderPostCutEdge(V3Graph* graphp, V3GraphVertex* fromp, V3GraphVertex* top) OrderPostCutEdge(V3Graph* graphp, V3GraphVertex* fromp, V3GraphVertex* top)
: OrderEdge(graphp, fromp, top, WEIGHT_COMBO, CUTABLE) {} : OrderEdge(graphp, fromp, top, WEIGHT_COMBO, CUTABLE) {}
virtual OrderVEdgeType type() const { return OrderVEdgeType::EDGE_POSTCUT; } virtual OrderVEdgeType type() const { return OrderVEdgeType::EDGE_POSTCUT; }
virtual ~OrderPostCutEdge() {} virtual ~OrderPostCutEdge() {}
virtual OrderPostCutEdge* clone(V3Graph* graphp, virtual OrderPostCutEdge* clone(V3Graph* graphp, V3GraphVertex* fromp,
V3GraphVertex* fromp, V3GraphVertex* top) const { V3GraphVertex* top) const {
return new OrderPostCutEdge(graphp, fromp, top, *this); return new OrderPostCutEdge(graphp, fromp, top, *this);
} }
virtual string dotColor() const { return "PaleGreen"; } virtual string dotColor() const { return "PaleGreen"; }
@ -503,12 +551,13 @@ class OrderPreCutEdge : public OrderEdge {
OrderPreCutEdge(V3Graph* graphp, V3GraphVertex* fromp, V3GraphVertex* top, OrderPreCutEdge(V3Graph* graphp, V3GraphVertex* fromp, V3GraphVertex* top,
const OrderPreCutEdge& old) const OrderPreCutEdge& old)
: OrderEdge(graphp, fromp, top, old) {} : OrderEdge(graphp, fromp, top, old) {}
public: public:
OrderPreCutEdge(V3Graph* graphp, V3GraphVertex* fromp, V3GraphVertex* top) OrderPreCutEdge(V3Graph* graphp, V3GraphVertex* fromp, V3GraphVertex* top)
: OrderEdge(graphp, fromp, top, WEIGHT_PRE, CUTABLE) {} : OrderEdge(graphp, fromp, top, WEIGHT_PRE, CUTABLE) {}
virtual OrderVEdgeType type() const { return OrderVEdgeType::EDGE_PRECUT; } virtual OrderVEdgeType type() const { return OrderVEdgeType::EDGE_PRECUT; }
virtual OrderPreCutEdge* clone(V3Graph* graphp, virtual OrderPreCutEdge* clone(V3Graph* graphp, V3GraphVertex* fromp,
V3GraphVertex* fromp, V3GraphVertex* top) const { V3GraphVertex* top) const {
return new OrderPreCutEdge(graphp, fromp, top, *this); return new OrderPreCutEdge(graphp, fromp, top, *this);
} }
virtual ~OrderPreCutEdge() {} virtual ~OrderPreCutEdge() {}

View File

@ -34,12 +34,16 @@ public:
// METHODS (generic filename utilities) // METHODS (generic filename utilities)
static string filenameFromDirBase(const string& dir, const string& basename); static string filenameFromDirBase(const string& dir, const string& basename);
static string filenameNonDir(const string& filename); ///< Return non-directory part of filename /// Return non-directory part of filename
static string filenameNonExt(const string& filename); ///< Return non-extensioned (no .) 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 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 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 string filenameRealPath(const string& filename); ///< Return realpath of filename
static bool filenameIsRel(const string& filename); ///< True if relative static bool filenameIsRel(const string& filename); ///< True if relative
@ -56,7 +60,8 @@ public:
// METHODS (time & performance) // METHODS (time & performance)
static void u_sleep(int64_t usec); ///< Sleep for a given number of microseconds. 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 static uint64_t memUsageBytes(); ///< Return memory usage in bytes, or 0 if not implemented
}; };

View File

@ -39,18 +39,15 @@
class V3Lexer : public V3LexerBase { class V3Lexer : public V3LexerBase {
public: public:
// CONSTRUCTORS // CONSTRUCTORS
V3Lexer() : V3LexerBase(NULL) {} V3Lexer()
: V3LexerBase(NULL) {}
~V3Lexer() {} ~V3Lexer() {}
// METHODS // METHODS
void statePop() { void statePop() { yy_pop_state(); }
yy_pop_state();
}
void unputString(const char* textp, size_t length) { void unputString(const char* textp, size_t length) {
// Add characters to input stream in back-to-front order // Add characters to input stream in back-to-front order
const char* cp = textp; const char* cp = textp;
for (cp += length - 1; length--; cp--) { for (cp += length - 1; length--; cp--) unput(*cp);
unput(*cp);
}
} }
}; };

View File

@ -76,8 +76,7 @@ public:
if (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); m_symTableNextId = getTable(entp);
} } else {
else {
UINFO(9, "symTableNextId under NULL" << endl); UINFO(9, "symTableNextId under NULL" << endl);
m_symTableNextId = NULL; m_symTableNextId = NULL;
} }
@ -95,7 +94,8 @@ public:
void pushNew(AstNode* nodep) { pushNewUnder(nodep, NULL); } void pushNew(AstNode* nodep) { pushNewUnder(nodep, NULL); }
void pushNewUnder(AstNode* nodep, VSymEnt* parentp) { void pushNewUnder(AstNode* nodep, VSymEnt* parentp) {
if (!parentp) parentp = symCurrentp(); 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); symp->fallbackp(parentp);
reinsert(nodep, parentp); reinsert(nodep, parentp);
pushScope(symp); pushScope(symp);
@ -106,9 +106,13 @@ public:
} }
void popScope(AstNode* nodep) { void popScope(AstNode* nodep) {
if (symCurrentp()->nodep() != nodep) { if (symCurrentp()->nodep() != nodep) {
if (debug()) { showUpward(); dump(cout, "-mism: "); } if (debug()) {
showUpward();
dump(cout, "-mism: ");
}
nodep->v3fatalSrc("Symbols suggest ending " << symCurrentp()->nodep()->prettyTypeName() nodep->v3fatalSrc("Symbols suggest ending " << symCurrentp()->nodep()->prettyTypeName()
<<" but parser thinks ending "<<nodep->prettyTypeName()); << " but parser thinks ending "
<< nodep->prettyTypeName());
return; return;
} }
m_sympStack.pop_back(); m_sympStack.pop_back();
@ -117,20 +121,22 @@ public:
} }
void showUpward() { void showUpward() {
UINFO(1, "ParseSym Stack:\n"); UINFO(1, "ParseSym Stack:\n");
for (SymStack::reverse_iterator it=m_sympStack.rbegin(); it!=m_sympStack.rend(); ++it) { for (SymStack::reverse_iterator it = m_sympStack.rbegin(); it != m_sympStack.rend();
++it) {
VSymEnt* symp = *it; VSymEnt* symp = *it;
UINFO(1, " " << symp->nodep() << endl); UINFO(1, " " << symp->nodep() << endl);
} }
UINFO(1, "ParseSym Current: " << symCurrentp()->nodep() << endl); UINFO(1, "ParseSym Current: " << symCurrentp()->nodep() << endl);
} }
void dump(std::ostream& os, const string& indent="") { void dump(std::ostream& os, const string& indent = "") { m_syms.dump(os, indent); }
m_syms.dump(os, indent);
}
AstNode* findEntUpward(const string& name) { AstNode* findEntUpward(const string& name) {
// Lookup the given string as an identifier, return type of the id, scanning upward // Lookup the given string as an identifier, return type of the id, scanning upward
VSymEnt* foundp = symCurrentp()->findIdFallback(name); VSymEnt* foundp = symCurrentp()->findIdFallback(name);
if (foundp) return foundp->nodep(); if (foundp) {
else return NULL; return foundp->nodep();
} else {
return NULL;
}
} }
void importItem(AstNode* packagep, const string& id_or_star) { void importItem(AstNode* packagep, const string& id_or_star) {
// Import from package::id_or_star to this // 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 // Operate on the final ExecMTask graph, immediately prior to code
// generation time. // generation time.
static void finalize(); static void finalize();
private: private:
static void finalizeCosts(V3Graph* execMTaskGraphp); static void finalizeCosts(V3Graph* execMTaskGraphp);
static void setupMTaskDeps(V3Graph* mtasksp, const Vx2MTaskMap* vx2mtaskp); static void setupMTaskDeps(V3Graph* mtasksp, const Vx2MTaskMap* vx2mtaskp);
@ -79,9 +80,11 @@ private:
// MEMBERS // MEMBERS
mutable vluint64_t m_nextId; mutable vluint64_t m_nextId;
mutable PtrMap m_id; mutable PtrMap m_id;
public: public:
// CONSTRUCTORS // CONSTRUCTORS
PartPtrIdMap() : m_nextId(0) {} PartPtrIdMap()
: m_nextId(0) {}
// METHODS // METHODS
vluint64_t findId(const void* ptrp) const { vluint64_t findId(const void* ptrp) const {
PtrMap::const_iterator it = m_id.find(ptrp); PtrMap::const_iterator it = m_id.find(ptrp);

View File

@ -30,7 +30,8 @@
class AbstractMTask : public V3GraphVertex { class AbstractMTask : public V3GraphVertex {
public: public:
AbstractMTask(V3Graph* graphp) : V3GraphVertex(graphp) {} AbstractMTask(V3Graph* graphp)
: V3GraphVertex(graphp) {}
virtual ~AbstractMTask() {} virtual ~AbstractMTask() {}
virtual uint32_t id() const = 0; virtual uint32_t id() const = 0;
virtual uint32_t cost() const = 0; virtual uint32_t cost() const = 0;
@ -41,7 +42,8 @@ public:
// TYPES // TYPES
typedef std::list<MTaskMoveVertex*> VxList; typedef std::list<MTaskMoveVertex*> VxList;
// CONSTRUCTORS // CONSTRUCTORS
AbstractLogicMTask(V3Graph* graphp) : AbstractMTask(graphp) {} AbstractLogicMTask(V3Graph* graphp)
: AbstractMTask(graphp) {}
virtual ~AbstractLogicMTask() {} virtual ~AbstractLogicMTask() {}
// METHODS // METHODS
// Set of logic vertices in this mtask. Order is not significant. // Set of logic vertices in this mtask. Order is not significant.
@ -64,16 +66,17 @@ private:
const ExecMTask* m_packNextp; // Next for static (pack_mtasks) scheduling const ExecMTask* m_packNextp; // Next for static (pack_mtasks) scheduling
bool m_threadRoot; // Is root thread bool m_threadRoot; // Is root thread
VL_UNCOPYABLE(ExecMTask); VL_UNCOPYABLE(ExecMTask);
public: public:
ExecMTask(V3Graph* graphp, AstMTaskBody* bodyp, uint32_t id) ExecMTask(V3Graph* graphp, AstMTaskBody* bodyp, uint32_t id)
: AbstractMTask(graphp), : AbstractMTask(graphp)
m_bodyp(bodyp), , m_bodyp(bodyp)
m_id(id), , m_id(id)
m_priority(0), , m_priority(0)
m_cost(0), , m_cost(0)
m_thread(0xffffffff), , m_thread(0xffffffff)
m_packNextp(NULL), , m_packNextp(NULL)
m_threadRoot(false) {} , m_threadRoot(false) {}
AstMTaskBody* bodyp() const { return m_bodyp; } AstMTaskBody* bodyp() const { return m_bodyp; }
virtual uint32_t id() const { return m_id; } virtual uint32_t id() const { return m_id; }
uint32_t priority() const { return m_priority; } uint32_t priority() const { return m_priority; }
@ -100,6 +103,8 @@ public:
} }
}; };
inline std::ostream& operator<<(std::ostream& os, const ExecMTask& rhs) { inline std::ostream& operator<<(std::ostream& os, const ExecMTask& rhs) {
rhs.dump(os); return os; } rhs.dump(os);
return os;
}
#endif // Guard #endif // Guard

View File

@ -34,6 +34,7 @@ class V3PreProcImp;
// Token codes // Token codes
// If changing, see V3PreProc.cpp's V3PreProcImp::tokenName() // 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 0 // Must be zero, a.k.a. YY_NULL, a.k.a. yy_terminate();
#define VP_EOF_ERROR 400 #define VP_EOF_ERROR 400
@ -65,10 +66,13 @@ class V3PreProcImp;
#define VP_JOIN 314 #define VP_JOIN 314
#define VP_PSL 350 #define VP_PSL 350
// clang-format on
//====================================================================== //======================================================================
// Externs created by flex // Externs created by flex
// We add a prefix so that other lexers/flexers in the same program won't collide. // We add a prefix so that other lexers/flexers in the same program won't collide.
// clang-format off
#ifndef yy_create_buffer #ifndef yy_create_buffer
# define yy_create_buffer V3PreLex_create_buffer # define yy_create_buffer V3PreLex_create_buffer
# define yy_delete_buffer V3PreLex_delete_buffer # define yy_delete_buffer V3PreLex_delete_buffer
@ -100,6 +104,7 @@ 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 # define YY_BUF_SIZE 16384
#endif #endif
// clang-format on
extern int yylex(); extern int yylex();
extern void yyrestart(FILE*); extern void yyrestart(FILE*);
@ -131,14 +136,16 @@ public:
bool m_file; // Buffer is start of new file bool m_file; // Buffer is start of new file
int m_termState; // Termination fsm int m_termState; // Termination fsm
VPreStream(FileLine* fl, V3PreLex* lexp) VPreStream(FileLine* fl, V3PreLex* lexp)
: m_curFilelinep(fl), m_lexp(lexp), : m_curFilelinep(fl)
m_ignNewlines(0), , m_lexp(lexp)
m_eof(false), m_file(false), m_termState(0) { , m_ignNewlines(0)
, m_eof(false)
, m_file(false)
, m_termState(0) {
lexStreamDepthAdd(1); lexStreamDepthAdd(1);
} }
~VPreStream() { ~VPreStream() { lexStreamDepthAdd(-1); }
lexStreamDepthAdd(-1);
}
private: private:
void lexStreamDepthAdd(int delta); void lexStreamDepthAdd(int delta);
}; };
@ -184,7 +191,10 @@ class V3PreLex {
initFirstBuffer(filelinep); initFirstBuffer(filelinep);
} }
~V3PreLex() { ~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); VL_DO_CLEAR(yy_delete_buffer(m_bufferState), m_bufferState = NULL);
} }

View File

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

View 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, "verilator", "1"); // LEAK_OK s_preprocp->defineCmdLine(prefl, "verilator", "1"); // LEAK_OK
s_preprocp->defineCmdLine(prefl, "verilator3", "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, "systemc_clock",
s_preprocp->defineCmdLine(prefl, "coverage_block_off", "/*verilator coverage_block_off*/"); // LEAK_OK "/*verilator systemc_clock*/"); // LEAK_OK
s_preprocp->defineCmdLine(prefl, "coverage_block_off",
"/*verilator coverage_block_off*/"); // LEAK_OK
if (prefl->language().systemVerilog()) { if (prefl->language().systemVerilog()) {
// Synthesis compatibility // Synthesis compatibility
s_preprocp->defineCmdLine(prefl, "SYSTEMVERILOG", "1"); // LEAK_OK s_preprocp->defineCmdLine(prefl, "SYSTEMVERILOG", "1"); // LEAK_OK
@ -109,8 +111,8 @@ protected:
// intervening +<lang>ext+ options since it was first encountered. // intervening +<lang>ext+ options since it was first encountered.
FileLine* modfileline = new FileLine(modfilename); FileLine* modfileline = new FileLine(modfilename);
modfileline->language(v3Global.opt.fileLanguage(modfilename)); modfileline->language(v3Global.opt.fileLanguage(modfilename));
V3Parse::ppPushText(parsep, (string("`begin_keywords \"") V3Parse::ppPushText(
+modfileline->language().ascii()+"\"\n")); parsep, (string("`begin_keywords \"") + modfileline->language().ascii() + "\"\n"));
} }
while (!s_preprocp->isEof()) { while (!s_preprocp->isEof()) {
@ -122,7 +124,8 @@ protected:
void preprocInclude(FileLine* fl, const string& modname) { void preprocInclude(FileLine* fl, const string& modname) {
if (modname[0] == '/' || modname[0] == '\\') { if (modname[0] == '/' || modname[0] == '\\') {
fl->v3warn(INCABSPATH, "Suggest `include with absolute path be made relative, and use +include: " fl->v3warn(INCABSPATH,
"Suggest `include with absolute path be made relative, and use +include: "
<< modname); << modname);
} }
preprocOpen(fl, s_filterp, modname, V3Os::filenameDir(fl->filename()), preprocOpen(fl, s_filterp, modname, V3Os::filenameDir(fl->filename()),
@ -130,8 +133,8 @@ protected:
} }
private: private:
string preprocOpen(FileLine* fl, VInFilter* filterp, string preprocOpen(FileLine* fl, VInFilter* filterp, const string& modname,
const string& modname, const string& lastpath, const string& lastpath,
const string& errmsg) { // Error message or "" to suppress const string& errmsg) { // Error message or "" to suppress
// Returns filename if successful // Returns filename if successful
// Try a pure name in case user has a bogus `filename they don't expect // Try a pure name in case user has a bogus `filename they don't expect
@ -163,9 +166,7 @@ VInFilter* V3PreShellImp::s_filterp = NULL;
//###################################################################### //######################################################################
// Perl class functions // Perl class functions
void V3PreShell::boot(char** env) { void V3PreShell::boot(char** env) { V3PreShellImp::s_preImp.boot(env); }
V3PreShellImp::s_preImp.boot(env);
}
bool V3PreShell::preproc(FileLine* fl, const string& modname, VInFilter* filterp, bool V3PreShell::preproc(FileLine* fl, const string& modname, VInFilter* filterp,
V3ParseImp* parsep, const string& errmsg) { V3ParseImp* parsep, const string& errmsg) {
return V3PreShellImp::s_preImp.preproc(fl, modname, filterp, parsep, 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()); FileLine* prefl = new FileLine(FileLine::commandLineFilename());
V3PreShellImp::s_preprocp->defineCmdLine(prefl, name, value); V3PreShellImp::s_preprocp->defineCmdLine(prefl, name, value);
} }
void V3PreShell::undef(const string& name) { void V3PreShell::undef(const string& name) { V3PreShellImp::s_preprocp->undef(name); }
V3PreShellImp::s_preprocp->undef(name); void V3PreShell::dumpDefines(std::ostream& os) { V3PreShellImp::s_preprocp->dumpDefines(os); }
}
void V3PreShell::dumpDefines(std::ostream& os) {
V3PreShellImp::s_preprocp->dumpDefines(os);
}
void V3PreShell::candidateDefines(VSpellCheck* spellerp) { void V3PreShell::candidateDefines(VSpellCheck* spellerp) {
V3PreShellImp::s_preprocp->candidateDefines(spellerp); V3PreShellImp::s_preprocp->candidateDefines(spellerp);
} }

View File

@ -76,8 +76,7 @@ private:
AstVar* varp = VN_CAST(cfuncp->user1p(), Var); AstVar* varp = VN_CAST(cfuncp->user1p(), Var);
if (!varp) { if (!varp) {
string newvarname = string("__Vilp"); string newvarname = string("__Vilp");
varp = new AstVar(fl, AstVarType::STMTTEMP, varp = new AstVar(fl, AstVarType::STMTTEMP, newvarname, VFlagLogicPacked(), 32);
newvarname, VFlagLogicPacked(), 32);
UASSERT_OBJ(cfuncp, fl, "Assignment not under a function"); UASSERT_OBJ(cfuncp, fl, "Assignment not under a function");
cfuncp->addInitsp(varp); cfuncp->addInitsp(varp);
cfuncp->user1p(varp); cfuncp->user1p(varp);
@ -87,11 +86,11 @@ private:
void mergeEnd() { void mergeEnd() {
if (!m_mgAssignps.empty()) { if (!m_mgAssignps.empty()) {
uint32_t items = m_mgIndexHi - m_mgIndexLo + 1; uint32_t items = m_mgIndexHi - m_mgIndexLo + 1;
UINFO(9, "End merge iter="<<items<<" "<<m_mgIndexHi<<":"<<m_mgIndexLo UINFO(9, "End merge iter=" << items << " " << m_mgIndexHi << ":" << m_mgIndexLo << " "
<<" "<<m_mgAssignps[0]<<endl); << m_mgAssignps[0] << endl);
if (items >= RELOOP_MIN_ITERS) { if (items >= RELOOP_MIN_ITERS) {
UINFO(6, "Reloop merging items="<<items<<" "<<m_mgIndexHi<<":"<<m_mgIndexLo UINFO(6, "Reloop merging items=" << items << " " << m_mgIndexHi << ":"
<<" "<<m_mgAssignps[0]<<endl); << m_mgIndexLo << " " << m_mgAssignps[0] << endl);
++m_statReloops; ++m_statReloops;
m_statReItems += items; m_statReItems += items;
@ -103,11 +102,11 @@ private:
AstNode* initp = new AstAssign(fl, new AstVarRef(fl, itp, true), AstNode* initp = new AstAssign(fl, new AstVarRef(fl, itp, true),
new AstConst(fl, m_mgIndexLo)); new AstConst(fl, m_mgIndexLo));
AstNode* condp = new AstLte(fl, new AstVarRef(fl, itp, false), AstNode* condp
new AstConst(fl, m_mgIndexHi)); = new AstLte(fl, new AstVarRef(fl, itp, false), new AstConst(fl, m_mgIndexHi));
AstNode* incp = new AstAssign(fl, new AstVarRef(fl, itp, true), AstNode* incp = new AstAssign(
new AstAdd(fl, new AstConst(fl, 1), fl, new AstVarRef(fl, itp, true),
new AstVarRef(fl, itp, false))); new AstAdd(fl, new AstConst(fl, 1), new AstVarRef(fl, itp, false)));
AstWhile* whilep = new AstWhile(fl, condp, NULL, incp); AstWhile* whilep = new AstWhile(fl, condp, NULL, incp);
initp->addNext(whilep); initp->addNext(whilep);
bodyp->replaceWith(initp); bodyp->replaceWith(initp);
@ -154,15 +153,27 @@ private:
// Left select WordSel or ArraySel // Left select WordSel or ArraySel
AstNodeSel* lselp = VN_CAST(nodep->lhsp(), NodeSel); 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 // Of a constant index
AstConst* lbitp = VN_CAST(lselp->bitp(), Const); AstConst* lbitp = VN_CAST(lselp->bitp(), Const);
if (!lbitp) { mergeEnd(); return; } if (!lbitp) {
if (lbitp->width() > 32) { mergeEnd(); return; } // Assoc arrays can do this mergeEnd();
return;
}
if (lbitp->width() > 32) { // Assoc arrays can do this
mergeEnd();
return;
}
uint32_t index = lbitp->toUInt(); uint32_t index = lbitp->toUInt();
// Of variable // Of variable
AstNodeVarRef* lvarrefp = VN_CAST(lselp->fromp(), NodeVarRef); AstNodeVarRef* lvarrefp = VN_CAST(lselp->fromp(), NodeVarRef);
if (!lvarrefp) { mergeEnd(); return; } if (!lvarrefp) {
mergeEnd();
return;
}
// RHS is a constant or a select // RHS is a constant or a select
AstConst* rconstp = VN_CAST(nodep->rhsp(), Const); AstConst* rconstp = VN_CAST(nodep->rhsp(), Const);
@ -170,38 +181,38 @@ private:
AstNodeVarRef* rvarrefp = NULL; AstNodeVarRef* rvarrefp = NULL;
if (rconstp) { // Ok if (rconstp) { // Ok
} else { } else {
if (!rselp) { mergeEnd(); return; } if (!rselp) {
mergeEnd();
return;
}
AstConst* rbitp = VN_CAST(rselp->bitp(), Const); AstConst* rbitp = VN_CAST(rselp->bitp(), Const);
rvarrefp = VN_CAST(rselp->fromp(), NodeVarRef); rvarrefp = VN_CAST(rselp->fromp(), NodeVarRef);
if (!rbitp || rbitp->toUInt() != index if (!rbitp || rbitp->toUInt() != index || !rvarrefp
|| !rvarrefp
|| lvarrefp->varp() == rvarrefp->varp()) { || lvarrefp->varp() == rvarrefp->varp()) {
mergeEnd(); return; mergeEnd();
return;
} }
} }
if (m_mgSelLp) { // Old merge if (m_mgSelLp) { // Old merge
if (m_mgCfuncp == m_cfuncp if (m_mgCfuncp == m_cfuncp && m_mgNextp == nodep && m_mgSelLp->same(lselp)
&& m_mgNextp == nodep
&& m_mgSelLp->same(lselp)
&& m_mgVarrefLp->same(lvarrefp) && m_mgVarrefLp->same(lvarrefp)
&& (m_mgConstRp && (m_mgConstRp
? (rconstp && m_mgConstRp->same(rconstp)) ? (rconstp && m_mgConstRp->same(rconstp))
: (rselp : (rselp && m_mgSelRp->same(rselp) && m_mgVarrefRp->same(rvarrefp)))
&& m_mgSelRp->same(rselp) && (index == m_mgIndexLo - 1 || index == m_mgIndexHi + 1)) {
&& m_mgVarrefRp->same(rvarrefp)))
&& (index == m_mgIndexLo-1
|| index == m_mgIndexHi+1)) {
// Sequentially next to last assign; continue merge // Sequentially next to last assign; continue merge
if (index == m_mgIndexLo-1) m_mgIndexLo = index; if (index == m_mgIndexLo - 1) {
else if (index == m_mgIndexHi+1) m_mgIndexHi = index; m_mgIndexLo = index;
UINFO(9, "Continue merge i="<<index } else if (index == m_mgIndexHi + 1) {
<<" "<<m_mgIndexHi<<":"<<m_mgIndexLo<<" "<<nodep<<endl); m_mgIndexHi = index;
}
UINFO(9, "Continue merge i=" << index << " " << m_mgIndexHi << ":" << m_mgIndexLo
<< " " << nodep << endl);
m_mgAssignps.push_back(nodep); m_mgAssignps.push_back(nodep);
m_mgNextp = nodep->nextp(); m_mgNextp = nodep->nextp();
return; return;
} } else {
else {
// This assign doesn't merge with previous assign, // This assign doesn't merge with previous assign,
// but should start a new merge // but should start a new merge
mergeEnd(); mergeEnd();
@ -252,8 +263,6 @@ public:
void V3Reloop::reloopAll(AstNetlist* nodep) { void V3Reloop::reloopAll(AstNetlist* nodep) {
UINFO(2, __FUNCTION__ << ": " << endl); UINFO(2, __FUNCTION__ << ": " << endl);
{ { ReloopVisitor visitor(nodep); } // Destruct before checking
ReloopVisitor visitor(nodep);
} // Destruct before checking
V3Global::dumpCheckGlobalTree("reloop", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 6); V3Global::dumpCheckGlobalTree("reloop", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 6);
} }

View File

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

View File

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

View File

@ -81,9 +81,7 @@ public:
AstSenTree* find(AstSenTree* likep) { AstSenTree* find(AstSenTree* likep) {
AstSenTree* resultp = NULL; AstSenTree* resultp = NULL;
Set::iterator it = m_trees.find(likep); Set::iterator it = m_trees.find(likep);
if (it != m_trees.end()) { if (it != m_trees.end()) resultp = *it;
resultp = *it;
}
return resultp; return resultp;
} }
void clear() { m_trees.clear(); } void clear() { m_trees.clear(); }
@ -103,9 +101,7 @@ private:
virtual void visit(AstNodeModule* nodep) VL_OVERRIDE { virtual void visit(AstNodeModule* nodep) VL_OVERRIDE {
// Only do the top // Only do the top
if (nodep->isTop()) { if (nodep->isTop()) iterateChildren(nodep);
iterateChildren(nodep);
}
} }
virtual void visit(AstTopScope* nodep) VL_OVERRIDE { virtual void visit(AstTopScope* nodep) VL_OVERRIDE {
m_topscopep = nodep; m_topscopep = nodep;
@ -145,15 +141,12 @@ public:
} }
return treep; return treep;
} }
public: public:
// CONSTRUCTORS // CONSTRUCTORS
SenTreeFinder() { SenTreeFinder() { clear(); }
clear();
}
virtual ~SenTreeFinder() {} virtual ~SenTreeFinder() {}
void main(AstTopScope* nodep) { void main(AstTopScope* nodep) { iterate(nodep); }
iterate(nodep);
}
}; };
#endif // Guard #endif // Guard

View File

@ -92,8 +92,11 @@ private:
iterateChildrenConst(nodep); iterateChildrenConst(nodep);
if (m_counting && nodep->dtypep()) { if (m_counting && nodep->dtypep()) {
if (nodep->isUsedClock()) ++m_statVarClock; if (nodep->isUsedClock()) ++m_statVarClock;
if (VN_IS(nodep->dtypeSkipRefp(), UnpackArrayDType)) ++m_statVarArray; if (VN_IS(nodep->dtypeSkipRefp(), UnpackArrayDType)) {
else m_statVarBytes += nodep->dtypeSkipRefp()->widthTotalBytes(); ++m_statVarArray;
} else {
m_statVarBytes += nodep->dtypeSkipRefp()->widthTotalBytes();
}
if (int(m_statVarWidths.size()) <= nodep->width()) { if (int(m_statVarWidths.size()) <= nodep->width()) {
m_statVarWidths.resize(nodep->width() + 5); m_statVarWidths.resize(nodep->width() + 5);
if (v3Global.opt.statsVars()) m_statVarWidthNames.resize(nodep->width() + 5); if (v3Global.opt.statsVars()) m_statVarWidthNames.resize(nodep->width() + 5);
@ -125,9 +128,7 @@ private:
// Condition is part of cost allocated to PREVIOUS block // Condition is part of cost allocated to PREVIOUS block
iterateAndNextConstNull(nodep->condp()); iterateAndNextConstNull(nodep->condp());
// Track prediction // Track prediction
if (m_counting) { if (m_counting) ++m_statPred[nodep->branchPred()];
++m_statPred[nodep->branchPred()];
}
if (!m_fast) { if (!m_fast) {
// Count everything // Count everything
iterateChildrenConst(nodep); iterateChildrenConst(nodep);
@ -206,10 +207,12 @@ private:
allNodes(nodep); allNodes(nodep);
iterateChildrenConst(nodep); iterateChildrenConst(nodep);
} }
public: public:
// CONSTRUCTORS // CONSTRUCTORS
StatsVisitor(AstNetlist* nodep, const string& stage, bool fast) StatsVisitor(AstNetlist* nodep, const string& stage, bool fast)
: m_stage(stage), m_fast(fast) { : m_stage(stage)
, m_fast(fast) {
UINFO(9, "Starting stats, fast=" << fast << endl); UINFO(9, "Starting stats, fast=" << fast << endl);
m_cfuncp = NULL; m_cfuncp = NULL;
m_counting = !m_fast; m_counting = !m_fast;
@ -237,12 +240,13 @@ public:
if (v3Global.opt.statsVars()) { if (v3Global.opt.statsVars()) {
NameMap& nameMapr = m_statVarWidthNames.at(i); NameMap& nameMapr = m_statVarWidthNames.at(i);
for (NameMap::iterator it = nameMapr.begin(); it != nameMapr.end(); ++it) { for (NameMap::iterator it = nameMapr.begin(); it != nameMapr.end(); ++it) {
std::ostringstream os; os<<"Vars, width " std::ostringstream os;
<<std::setw(5)<<std::dec<<i<<" "<<it->first; os << "Vars, width " << std::setw(5) << std::dec << i << " " << it->first;
V3Stats::addStat(m_stage, os.str(), it->second); V3Stats::addStat(m_stage, os.str(), it->second);
} }
} else { } 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); V3Stats::addStat(m_stage, os.str(), count);
} }
} }
@ -258,8 +262,9 @@ public:
for (int type2 = 0; type2 < AstType::_ENUM_END; type2++) { for (int type2 = 0; type2 < AstType::_ENUM_END; type2++) {
double count = double(m_statAbove[type][type2]); double count = double(m_statAbove[type][type2]);
if (count != 0.0) { if (count != 0.0) {
V3Stats::addStat(m_stage, (string("Node pairs, ") V3Stats::addStat(m_stage,
+AstType(type).ascii()+"_"+AstType(type2).ascii()), (string("Node pairs, ") + AstType(type).ascii() + "_"
+ AstType(type2).ascii()),
count); count);
} }
} }
@ -268,8 +273,8 @@ public:
for (int type = 0; type < VBranchPred::_ENUM_END; type++) { for (int type = 0; type < VBranchPred::_ENUM_END; type++) {
double count = double(m_statPred[type]); double count = double(m_statPred[type]);
if (count != 0.0) { if (count != 0.0) {
V3Stats::addStat(m_stage, (string("Branch prediction, ") V3Stats::addStat(
+ VBranchPred(type).ascii()), count); m_stage, (string("Branch prediction, ") + VBranchPred(type).ascii()), count);
} }
} }
} }

View File

@ -31,19 +31,37 @@ class VDouble0 {
double m_d; ///< Count of occurrences/ value double m_d; ///< Count of occurrences/ value
public: public:
// METHODS // METHODS
VDouble0() : m_d(0) {} VDouble0()
: m_d(0) {}
~VDouble0() {} ~VDouble0() {}
// Implicit conversion operators: // 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; } inline operator double() const { return m_d; }
// Explicit operators: // Explicit operators:
inline VDouble0& operator++() { ++m_d; return *this; } // prefix inline VDouble0& operator++() { // prefix
inline VDouble0 operator++(int) { VDouble0 old=*this; m_d++; return old; } // postfix ++m_d;
inline VDouble0& operator= (const double v) { m_d = v; return *this; } 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++(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;
}
}; };
//============================================================================ //============================================================================
@ -70,9 +88,13 @@ public:
otherp->m_printit = false; otherp->m_printit = false;
} }
// CONSTRUCTORS // CONSTRUCTORS
V3Statistic(const string& stage, const string& name, V3Statistic(const string& stage, const string& name, double count, bool sumit = false,
double count, bool sumit=false, bool perf=false) bool perf = false)
: m_name(name), m_count(count), m_stage(stage), m_sumit(sumit), m_perf(perf) : m_name(name)
, m_count(count)
, m_stage(stage)
, m_sumit(sumit)
, m_perf(perf)
, m_printit(true) {} , m_printit(true) {}
virtual ~V3Statistic() {} virtual ~V3Statistic() {}
}; };
@ -83,13 +105,17 @@ class V3Stats {
public: public:
static void addStat(const V3Statistic&); static void addStat(const V3Statistic&);
static void addStat(const string& stage, const string& name, double count) { 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) { static void addStat(const string& name, double count) {
addStat(V3Statistic("*", name, count)); } addStat(V3Statistic("*", name, count));
}
static void addStatSum(const string& name, double 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) { static void addStatPerf(const string& name, double count) {
addStat(V3Statistic("*", name, count, true, true)); } addStat(V3Statistic("*", name, count, true, true));
}
/// Called each stage /// Called each stage
static void statsStage(const string& name); static void statsStage(const string& name);
/// Called by the top level to collect statistics /// Called by the top level to collect statistics
@ -99,5 +125,4 @@ public:
static void statsReport(); static void statsReport();
}; };
#endif // Guard #endif // Guard

View File

@ -63,8 +63,8 @@ class StatsReport {
V3Statistic* lastp = NULL; 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; V3Statistic* repp = it->second;
if (lastp && lastp->sumit() && lastp->printit() if (lastp && lastp->sumit() && lastp->printit() && lastp->name() == repp->name()
&& lastp->name() == repp->name() && lastp->stage() == repp->stage()) { && lastp->stage() == repp->stage()) {
repp->combineWith(lastp); repp->combineWith(lastp);
} }
lastp = repp; lastp = repp;
@ -157,9 +157,7 @@ class StatsReport {
{ {
string commaName = lastName; string commaName = lastName;
string::size_type pos; string::size_type pos;
if ((pos = commaName.find(',')) != string::npos) { if ((pos = commaName.find(',')) != string::npos) commaName.erase(pos);
commaName.erase(pos);
}
if (lastCommaName != commaName) { if (lastCommaName != commaName) {
lastCommaName = commaName; lastCommaName = commaName;
os << endl; os << endl;
@ -181,9 +179,7 @@ class StatsReport {
public: public:
// METHODS // METHODS
static void addStat(const V3Statistic& stat) { static void addStat(const V3Statistic& stat) { s_allStats.push_back(stat); }
s_allStats.push_back(stat);
}
// CONSTRUCTORS // CONSTRUCTORS
explicit StatsReport(std::ofstream* aofp) explicit StatsReport(std::ofstream* aofp)
@ -212,15 +208,14 @@ void V3Statistic::dump(std::ofstream& os) const {
//###################################################################### //######################################################################
// Top Stats class // Top Stats class
void V3Stats::addStat(const V3Statistic& stat) { void V3Stats::addStat(const V3Statistic& stat) { StatsReport::addStat(stat); }
StatsReport::addStat(stat);
}
void V3Stats::statsStage(const string& name) { void V3Stats::statsStage(const string& name) {
static double lastWallTime = -1; static double lastWallTime = -1;
static int fileNumber = 0; static int fileNumber = 0;
char digits[100]; sprintf(digits, "%03d", ++fileNumber); char digits[100];
sprintf(digits, "%03d", ++fileNumber);
const string digitName = string(digits) + "_" + name; const string digitName = string(digits) + "_" + name;
double wallTime = V3Os::timeUsecs() / 1.0e6; double wallTime = V3Os::timeUsecs() / 1.0e6;

View File

@ -33,16 +33,12 @@ size_t VName::s_maxLength = 0; // Disabled
inline bool VString::wildmatchi(const char* s, const char* p) { inline bool VString::wildmatchi(const char* s, const char* p) {
for (; *p; s++, p++) { for (; *p; s++, p++) {
if (*p != '*') { if (*p != '*') {
if (((*s)!=(*p)) && *p != '?') if (((*s) != (*p)) && *p != '?') return false;
return false; } else {
}
else {
// Trailing star matches everything. // Trailing star matches everything.
if (!*++p) return true; if (!*++p) return true;
while (!wildmatch(s, p)) { while (!wildmatch(s, p)) {
if (*++s == '\0') { if (*++s == '\0') return false;
return false;
}
} }
return true; return true;
} }
@ -53,16 +49,12 @@ inline bool VString::wildmatchi(const char* s, const char* p) {
bool VString::wildmatch(const char* s, const char* p) { bool VString::wildmatch(const char* s, const char* p) {
for (; *p; s++, p++) { for (; *p; s++, p++) {
if (*p != '*') { if (*p != '*') {
if (((*s)!=(*p)) && *p != '?') if (((*s) != (*p)) && *p != '?') return false;
return false; } else {
}
else {
// Trailing star matches everything. // Trailing star matches everything.
if (!*++p) return true; if (!*++p) return true;
while (!wildmatchi(s, p)) { while (!wildmatchi(s, p)) {
if (*++s == '\0') { if (*++s == '\0') return false;
return false;
}
} }
return true; return true;
} }
@ -86,17 +78,13 @@ string VString::dot(const string& a, const string& dot, const string& b) {
string VString::downcase(const string& str) { string VString::downcase(const string& str) {
string out = str; string out = str;
for (string::iterator pos = out.begin(); pos != out.end(); ++pos) { for (string::iterator pos = out.begin(); pos != out.end(); ++pos) *pos = tolower(*pos);
*pos = tolower(*pos);
}
return out; return out;
} }
string VString::upcase(const string& str) { string VString::upcase(const string& str) {
string out = str; string out = str;
for (string::iterator pos = out.begin(); pos != out.end(); ++pos) { for (string::iterator pos = out.begin(); pos != out.end(); ++pos) *pos = toupper(*pos);
*pos = toupper(*pos);
}
return out; return out;
} }
@ -112,8 +100,11 @@ string VString::quotePercent(const string& str) {
string VString::spaceUnprintable(const string& str) { string VString::spaceUnprintable(const string& str) {
string out; string out;
for (string::const_iterator pos = str.begin(); pos != str.end(); ++pos) { for (string::const_iterator pos = str.begin(); pos != str.end(); ++pos) {
if (isprint(*pos)) out += *pos; if (isprint(*pos)) {
else out += ' '; out += *pos;
} else {
out += ' ';
}
} }
return out; return out;
} }
@ -128,16 +119,17 @@ bool VString::isWhitespace(const string& str) {
//###################################################################### //######################################################################
// VHashSha256 // VHashSha256
static const uint32_t sha256K[] = { static const uint32_t sha256K[]
0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, = {0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4,
0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, 0xab1c5ed5, 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe,
0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, 0x9bdc06a7, 0xc19bf174, 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f,
0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7,
0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc,
0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, 0xa2bfe8a1, 0xa81a664b,
0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, 0x19a4c116,
0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 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) VL_ATTR_ALWINLINE;
static inline uint32_t shaRotr32(uint32_t lhs, uint32_t rhs) { 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; const uint32_t* p = chunk;
// Initialize working variables to current hash value // Initialize working variables to current hash value
for (unsigned i = 0; i < 8; i++) { for (unsigned i = 0; i < 8; i++) ah[i] = h[i];
ah[i] = h[i];
}
// Compression function main loop // Compression function main loop
for (unsigned i = 0; i < 4; ++i) { for (unsigned i = 0; i < 4; ++i) {
uint32_t w[16]; uint32_t w[16];
@ -169,12 +159,10 @@ static inline void sha256Block(uint32_t* h, const uint32_t* chunk) {
^ 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; w[j] = w[j] + s0 + w[(j + 9) & 0xf] + s1;
} }
const uint32_t s1 = shaRotr32(ah[4], 6) const uint32_t s1 = shaRotr32(ah[4], 6) ^ shaRotr32(ah[4], 11) ^ shaRotr32(ah[4], 25);
^ shaRotr32(ah[4], 11) ^ shaRotr32(ah[4], 25);
const uint32_t ch = (ah[4] & ah[5]) ^ (~ah[4] & ah[6]); 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 temp1 = ah[7] + s1 + ch + sha256K[i << 4 | j] + w[j];
const uint32_t s0 = shaRotr32(ah[0], 2) const uint32_t s0 = shaRotr32(ah[0], 2) ^ shaRotr32(ah[0], 13) ^ shaRotr32(ah[0], 22);
^ 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 maj = (ah[0] & ah[1]) ^ (ah[0] & ah[2]) ^ (ah[1] & ah[2]);
const uint32_t temp2 = s0 + maj; 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]; for (unsigned i = 0; i < 8; ++i) h[i] += ah[i];
} }
void VHashSha256::insert(const void* datap, size_t length) { void VHashSha256::insert(const void* datap, size_t length) {
UASSERT(!m_final, "Called VHashSha256::insert after finalized the hash value"); UASSERT(!m_final, "Called VHashSha256::insert after finalized the hash value");
m_totLength += length; m_totLength += length;
@ -243,8 +230,8 @@ void VHashSha256::finalize() {
for (int i = 0; i < 16; ++i) w[i] = 0; for (int i = 0; i < 16; ++i) w[i] = 0;
size_t blockPos = 0; size_t blockPos = 0;
for (; blockPos < m_remainder.length(); ++blockPos) { for (; blockPos < m_remainder.length(); ++blockPos) {
w[blockPos >> 2] |= ((static_cast<uint32_t>(m_remainder[blockPos])) w[blockPos >> 2]
<< ((3 - (blockPos & 3)) << 3)); |= ((static_cast<uint32_t>(m_remainder[blockPos])) << ((3 - (blockPos & 3)) << 3));
} }
w[blockPos >> 2] |= 0x80 << ((3 - (blockPos & 3)) << 3); w[blockPos >> 2] |= 0x80 << ((3 - (blockPos & 3)) << 3);
if (m_remainder.length() >= 56) { if (m_remainder.length() >= 56) {
@ -260,7 +247,8 @@ void VHashSha256::finalize() {
string VHashSha256::digestBinary() { string VHashSha256::digestBinary() {
finalize(); finalize();
string out; out.reserve(32); string out;
out.reserve(32);
for (size_t i = 0; i < 32; ++i) { for (size_t i = 0; i < 32; ++i) {
out += (m_inthash[i >> 2] >> (((3 - i) & 0x3) << 3)) & 0xff; out += (m_inthash[i >> 2] >> (((3 - i) & 0x3) << 3)) & 0xff;
} }
@ -280,7 +268,8 @@ uint64_t VHashSha256::digestUInt64() {
string VHashSha256::digestHex() { string VHashSha256::digestHex() {
static const char digits[16 + 1] = "0123456789abcdef"; static const char digits[16 + 1] = "0123456789abcdef";
const string& binhash = digestBinary(); const string& binhash = digestBinary();
string out; out.reserve(70); string out;
out.reserve(70);
for (size_t byte = 0; byte < 32; ++byte) { for (size_t byte = 0; byte < 32; ++byte) {
out += digits[(binhash[byte] >> 4) & 0xf]; out += digits[(binhash[byte] >> 4) & 0xf];
out += digits[(binhash[byte] >> 0) & 0xf]; out += digits[(binhash[byte] >> 0) & 0xf];
@ -296,7 +285,8 @@ string VHashSha256::digestSymbol() {
static const char digits[64 + 1] static const char digits[64 + 1]
= "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"; = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB";
const string& binhash = digestBinary(); const string& binhash = digestBinary();
string out; out.reserve(28); string out;
out.reserve(28);
int pos = 0; 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] >> 2) & 0x3f)];
@ -310,8 +300,8 @@ string VHashSha256::digestSymbol() {
return out; return out;
} }
void VHashSha256::selfTestOne(const string& data, const string& data2, void VHashSha256::selfTestOne(const string& data, const string& data2, const string& exp,
const string& exp, const string& exp64) { const string& exp64) {
VHashSha256 digest(data); VHashSha256 digest(data);
if (data2 != "") digest.insert(data2); if (data2 != "") digest.insert(data2);
if (VL_UNCOVERABLE(digest.digestHex() != exp)) { if (VL_UNCOVERABLE(digest.digestHex() != exp)) {
@ -327,11 +317,9 @@ void VHashSha256::selfTestOne(const string& data, const string& data2,
} }
void VHashSha256::selfTest() { void VHashSha256::selfTest() {
selfTestOne("", "", selfTestOne("", "", "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
"47DEQpj8HBSaABTImWA5JCeuQeRkm5NMpJWZG3hS"); "47DEQpj8HBSaABTImWA5JCeuQeRkm5NMpJWZG3hS");
selfTestOne("a", "", selfTestOne("a", "", "ca978112ca1bbdcafac231b39a23dc4da786eff8147c4e72b9807785afee48bb",
"ca978112ca1bbdcafac231b39a23dc4da786eff8147c4e72b9807785afee48bb",
"ypeBEsobvcr6wjGzmiPcTaeG7BgUfE5yuYB3haBu"); "ypeBEsobvcr6wjGzmiPcTaeG7BgUfE5yuYB3haBu");
selfTestOne("The quick brown fox jumps over the lazy dog", "", selfTestOne("The quick brown fox jumps over the lazy dog", "",
"d7a8fbb307d7809469ca9abcb0082e4f8d5651e46d3cdb762d02d0bf37c9e592", "d7a8fbb307d7809469ca9abcb0082e4f8d5651e46d3cdb762d02d0bf37c9e592",
@ -420,13 +408,11 @@ VSpellCheck::EditDistance VSpellCheck::cutoffDistance(size_t goal_len, size_t ca
return (max_length + 2) / 3; return (max_length + 2) / 3;
} }
string VSpellCheck::bestCandidateInfo(const string& goal, string VSpellCheck::bestCandidateInfo(const string& goal, EditDistance& distancer) {
EditDistance& distancer) {
string bestCandidate; string bestCandidate;
size_t gLen = goal.length(); size_t gLen = goal.length();
distancer = LENGTH_LIMIT * 10; distancer = LENGTH_LIMIT * 10;
for (Candidates::const_iterator it = m_candidates.begin(); for (Candidates::const_iterator it = m_candidates.begin(); it != m_candidates.end(); ++it) {
it != m_candidates.end(); ++it) {
const string candidate = *it; const string candidate = *it;
size_t cLen = candidate.length(); 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 if (min_distance > cutoff) continue; // Short-circuit if already too bad
EditDistance dist = editDistance(goal, candidate); EditDistance dist = editDistance(goal, candidate);
UINFO(9, "EditDistance dist="<<dist<<" cutoff="<<cutoff UINFO(9, "EditDistance dist=" << dist << " cutoff=" << cutoff << " goal=" << goal
<<" goal="<<goal<<" candidate="<<candidate<<endl); << " candidate=" << candidate << endl);
if (dist < distancer && dist <= cutoff) { if (dist < distancer && dist <= cutoff) {
distancer = dist; distancer = dist;
bestCandidate = candidate; bestCandidate = candidate;
@ -451,8 +437,7 @@ string VSpellCheck::bestCandidateInfo(const string& goal,
return bestCandidate; return bestCandidate;
} }
void VSpellCheck::selfTestDistanceOne(const string& a, const string& b, void VSpellCheck::selfTestDistanceOne(const string& a, const string& b, EditDistance expected) {
EditDistance expected) {
UASSERT_SELFTEST(EditDistance, editDistance(a, b), expected); UASSERT_SELFTEST(EditDistance, editDistance(a, b), expected);
UASSERT_SELFTEST(EditDistance, editDistance(b, a), expected); UASSERT_SELFTEST(EditDistance, editDistance(b, a), expected);
} }

View File

@ -30,17 +30,29 @@
// Global string-related functions // Global string-related functions
template <class T> std::string cvtToStr(const T& t) { 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) { 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) { inline uint32_t cvtToHash(const void* vp) {
// We can shove a 64 bit pointer into a 32 bit bucket // We can shove a 64 bit pointer into a 32 bit bucket
// On 32-bit systems, lower is always 0, but who cares? // On 32-bit systems, lower is always 0, but who cares?
union { const void* up; struct {uint32_t upper; uint32_t lower;} l;} u; union {
u.l.upper = 0; u.l.lower = 0; u.up = vp; 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; return u.l.upper ^ u.l.lower;
} }
@ -55,6 +67,7 @@ inline string ucfirst(const string& text) {
class VString { class VString {
static bool wildmatchi(const char* s, const char* p); static bool wildmatchi(const char* s, const char* p);
public: public:
// METHODS (generic string utilities) // METHODS (generic string utilities)
// Return true if p with ? or *'s matches s // Return true if p with ? or *'s matches s
@ -95,7 +108,10 @@ class VHashSha256 {
public: public:
// CONSTRUCTORS // CONSTRUCTORS
VHashSha256() { init(); } VHashSha256() { init(); }
explicit VHashSha256(const string& data) { init(); insert(data); } explicit VHashSha256(const string& data) {
init();
insert(data);
}
~VHashSha256() {} ~VHashSha256() {}
// METHODS // METHODS
@ -107,20 +123,26 @@ public:
// Inerting hash data // Inerting hash data
void insert(const void* datap, size_t length); // Process data into the digest 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)); } void insert(uint64_t value) { insert(cvtToStr(value)); }
private: private:
void init() { void init() {
m_inthash[0] = 0x6a09e667; m_inthash[1] = 0xbb67ae85; m_inthash[0] = 0x6a09e667;
m_inthash[2] = 0x3c6ef372; m_inthash[3] = 0xa54ff53a; m_inthash[1] = 0xbb67ae85;
m_inthash[4] = 0x510e527f; m_inthash[5] = 0x9b05688c; m_inthash[2] = 0x3c6ef372;
m_inthash[6] = 0x1f83d9ab; m_inthash[7] = 0x5be0cd19; m_inthash[3] = 0xa54ff53a;
m_inthash[4] = 0x510e527f;
m_inthash[5] = 0x9b05688c;
m_inthash[6] = 0x1f83d9ab;
m_inthash[7] = 0x5be0cd19;
m_final = false; m_final = false;
m_totLength = 0; m_totLength = 0;
} }
static void selfTestOne(const string& data, const string& data2, static void selfTestOne(const string& data, const string& data2, const string& exp,
const string& exp, const string& exp64); const string& exp64);
void finalize(); // Process remaining data void finalize(); // Process remaining data
}; };
@ -136,10 +158,14 @@ class VName {
static size_t s_minLength; // Length to preserve if over maxLength static size_t s_minLength; // Length to preserve if over maxLength
public: public:
// CONSTRUCTORS // CONSTRUCTORS
explicit VName(const string& name) : m_name(name) {} explicit VName(const string& name)
: m_name(name) {}
~VName() {} ~VName() {}
// METHODS // 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 name() const { return m_name; }
string hashedName(); string hashedName();
// CONFIG STATIC METHODS // CONFIG STATIC METHODS
@ -178,16 +204,19 @@ public:
// Return friendly message // Return friendly message
string bestCandidateMsg(const string& goal) { string bestCandidateMsg(const string& goal) {
string candidate = bestCandidate(goal); string candidate = bestCandidate(goal);
if (candidate.empty()) return ""; if (candidate.empty()) {
else return string("... Suggested alternative: '")+candidate+"'"; return "";
} else {
return string("... Suggested alternative: '") + candidate + "'";
}
} }
static void selfTest(); static void selfTest();
private: private:
static EditDistance editDistance(const string& s, const string& t); static EditDistance editDistance(const string& s, const string& t);
static EditDistance cutoffDistance(size_t goal_len, size_t candidate_len); static EditDistance cutoffDistance(size_t goal_len, size_t candidate_len);
string bestCandidateInfo(const string& goal, EditDistance& distancer); string bestCandidateInfo(const string& goal, EditDistance& distancer);
static void selfTestDistanceOne(const string& a, const string& b, static void selfTestDistanceOne(const string& a, const string& b, EditDistance expected);
EditDistance expected);
static void selfTestSuggestOne(bool matches, const string& c, const string& goal, static void selfTestSuggestOne(bool matches, const string& c, const string& goal,
EditDistance dist); EditDistance dist);
}; };

View File

@ -61,7 +61,6 @@ class VSymEnt {
static inline int debug() { return 0; } // NOT runtime, too hot of a function static inline int debug() { return 0; } // NOT runtime, too hot of a function
#endif #endif
public: public:
typedef IdNameMap::const_iterator const_iterator; typedef IdNameMap::const_iterator const_iterator;
const_iterator begin() const { return m_idNameMap.begin(); } const_iterator begin() const { return m_idNameMap.begin(); }
const_iterator end() const { return m_idNameMap.end(); } const_iterator end() const { return m_idNameMap.end(); }
@ -79,9 +78,11 @@ public:
os << indent << "| ^ duplicate, so no children printed\n"; os << indent << "| ^ duplicate, so no children printed\n";
} else { } else {
doneSymsr.insert(this); 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) { if (numLevels >= 1) {
it->second->dumpIterate(os, doneSymsr, indent+"| ", numLevels-1, it->first); it->second->dumpIterate(os, doneSymsr, indent + "| ", numLevels - 1,
it->first);
} }
} }
} }
@ -120,12 +121,13 @@ public:
bool imported() const { return m_imported; } bool imported() const { return m_imported; }
void imported(bool flag) { m_imported = flag; } void imported(bool flag) { m_imported = flag; }
void insert(const string& name, VSymEnt* entp) { void insert(const string& name, VSymEnt* entp) {
UINFO(9, " SymInsert se"<<cvtToHex(this) UINFO(9, " SymInsert se" << cvtToHex(this) << " '" << name << "' se" << cvtToHex(entp)
<<" '"<<name<<"' se"<<cvtToHex(entp)<<" "<<entp->nodep()<<endl); << " " << entp->nodep() << endl);
if (name != "" && m_idNameMap.find(name) != m_idNameMap.end()) { if (name != "" && m_idNameMap.find(name) != m_idNameMap.end()) {
if (!V3Error::errorCount()) { // Else may have just reported warning if (!V3Error::errorCount()) { // Else may have just reported warning
if (debug() >= 9 || V3Error::debugDefault()) dump(cout, "- err-dump: ", 1); if (debug() >= 9 || V3Error::debugDefault()) dump(cout, "- err-dump: ", 1);
entp->nodep()->v3fatalSrc("Inserting two symbols with same name: "<<name<<endl); entp->nodep()->v3fatalSrc("Inserting two symbols with same name: " << name
<< endl);
} }
} else { } else {
m_idNameMap.insert(make_pair(name, entp)); m_idNameMap.insert(make_pair(name, entp));
@ -134,8 +136,8 @@ public:
void reinsert(const string& name, VSymEnt* entp) { void reinsert(const string& name, VSymEnt* entp) {
IdNameMap::iterator it = m_idNameMap.find(name); IdNameMap::iterator it = m_idNameMap.find(name);
if (name != "" && it != m_idNameMap.end()) { if (name != "" && it != m_idNameMap.end()) {
UINFO(9, " SymReinsert se"<<cvtToHex(this) UINFO(9, " SymReinsert se" << cvtToHex(this) << " '" << name << "' se"
<<" '"<<name<<"' se"<<cvtToHex(entp)<<" "<<entp->nodep()<<endl); << cvtToHex(entp) << " " << entp->nodep() << endl);
it->second = entp; // Replace it->second = entp; // Replace
} else { } else {
insert(name, entp); insert(name, entp);
@ -145,9 +147,12 @@ public:
// Find identifier without looking upward through symbol hierarchy // Find identifier without looking upward through symbol hierarchy
// First, scan this begin/end block or module for the name // First, scan this begin/end block or module for the name
IdNameMap::const_iterator it = m_idNameMap.find(name); IdNameMap::const_iterator it = m_idNameMap.find(name);
UINFO(9, " SymFind se"<<cvtToHex(this)<<" '"<<name UINFO(9, " SymFind se"
<<"' -> "<<(it == m_idNameMap.end() ? "NONE" << cvtToHex(this) << " '" << name << "' -> "
: "se"+cvtToHex(it->second)+" n="+cvtToHex(it->second->nodep()))<<endl); << (it == m_idNameMap.end()
? "NONE"
: "se" + cvtToHex(it->second) + " n=" + cvtToHex(it->second->nodep()))
<< endl);
if (it != m_idNameMap.end()) return (it->second); if (it != m_idNameMap.end()) return (it->second);
return NULL; return NULL;
} }
@ -161,8 +166,7 @@ public:
} }
void candidateIdFlat(VSpellCheck* spellerp, const VNodeMatcher* matcherp) const { void candidateIdFlat(VSpellCheck* spellerp, const VNodeMatcher* matcherp) const {
// Suggest alternative symbol candidates without looking upward through symbol hierarchy // Suggest alternative symbol candidates without looking upward through symbol hierarchy
for (IdNameMap::const_iterator it = m_idNameMap.begin(); for (IdNameMap::const_iterator it = m_idNameMap.begin(); it != m_idNameMap.end(); ++it) {
it != m_idNameMap.end(); ++it) {
const AstNode* itemp = it->second->nodep(); const AstNode* itemp = it->second->nodep();
if (itemp && (!matcherp || matcherp->nodeMatch(itemp))) { if (itemp && (!matcherp || matcherp->nodeMatch(itemp))) {
spellerp->pushCandidate(itemp->prettyName()); spellerp->pushCandidate(itemp->prettyName());
@ -176,10 +180,10 @@ public:
// Then suggest the upper begin/end block or module // Then suggest the upper begin/end block or module
if (m_fallbackp) m_fallbackp->candidateIdFallback(spellerp, matcherp); if (m_fallbackp) m_fallbackp->candidateIdFallback(spellerp, matcherp);
} }
private: private:
void importOneSymbol(VSymGraph* graphp, const string& name, const VSymEnt* srcp) { void importOneSymbol(VSymGraph* graphp, const string& name, const VSymEnt* srcp) {
if (srcp->exported() if (srcp->exported() && !findIdFlat(name)) { // Don't insert over existing entry
&& !findIdFlat(name)) { // Don't insert over existing entry
VSymEnt* symp = new VSymEnt(graphp, srcp); VSymEnt* symp = new VSymEnt(graphp, srcp);
symp->exported(false); // Can't reimport an import without an export symp->exported(false); // Can't reimport an import without an export
symp->imported(true); symp->imported(true);
@ -193,14 +197,13 @@ private:
} }
} }
} }
public: public:
void importFromPackage(VSymGraph* graphp, const VSymEnt* srcp, const string& id_or_star) { void importFromPackage(VSymGraph* graphp, const VSymEnt* srcp, const string& id_or_star) {
// Import tokens from source symbol table into this symbol table // Import tokens from source symbol table into this symbol table
if (id_or_star != "*") { if (id_or_star != "*") {
IdNameMap::const_iterator it = srcp->m_idNameMap.find(id_or_star); IdNameMap::const_iterator it = srcp->m_idNameMap.find(id_or_star);
if (it != srcp->m_idNameMap.end()) { if (it != srcp->m_idNameMap.end()) importOneSymbol(graphp, it->first, it->second);
importOneSymbol(graphp, it->first, it->second);
}
} else { } else {
for (IdNameMap::const_iterator it = srcp->m_idNameMap.begin(); for (IdNameMap::const_iterator it = srcp->m_idNameMap.begin();
it != srcp->m_idNameMap.end(); ++it) { it != srcp->m_idNameMap.end(); ++it) {
@ -212,9 +215,7 @@ public:
// Export tokens from source symbol table into this symbol table // Export tokens from source symbol table into this symbol table
if (id_or_star != "*") { if (id_or_star != "*") {
IdNameMap::const_iterator it = srcp->m_idNameMap.find(id_or_star); IdNameMap::const_iterator it = srcp->m_idNameMap.find(id_or_star);
if (it != srcp->m_idNameMap.end()) { if (it != srcp->m_idNameMap.end()) exportOneSymbol(graphp, it->first, it->second);
exportOneSymbol(graphp, it->first, it->second);
}
} else { } else {
for (IdNameMap::const_iterator it = srcp->m_idNameMap.begin(); for (IdNameMap::const_iterator it = srcp->m_idNameMap.begin();
it != srcp->m_idNameMap.end(); ++it) { it != srcp->m_idNameMap.end(); ++it) {
@ -250,15 +251,14 @@ public:
string scopes; 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(); AstNode* itemp = it->second->nodep();
if (VN_IS(itemp, Cell) if (VN_IS(itemp, Cell) || (VN_IS(itemp, Module) && VN_CAST(itemp, Module)->isTop())) {
|| (VN_IS(itemp, Module) && VN_CAST(itemp, Module)->isTop())) {
if (scopes != "") scopes += ", "; if (scopes != "") scopes += ", ";
scopes += AstNode::prettyName(it->first); scopes += AstNode::prettyName(it->first);
} }
} }
if (scopes == "") scopes = "<no cells found>"; if (scopes == "") scopes = "<no cells found>";
std::cerr<<V3Error::warnMore()<<"... Known scopes under '"<<prettyName<<"': " std::cerr << V3Error::warnMore() << "... Known scopes under '" << prettyName
<<scopes<<endl; << "': " << scopes << endl;
if (debug()) dump(std::cerr, " KnownScope: ", 1); if (debug()) dump(std::cerr, " KnownScope: ", 1);
} }
}; };
@ -277,14 +277,11 @@ class VSymGraph {
// CONSTRUCTORS // CONSTRUCTORS
VL_UNCOPYABLE(VSymGraph); VL_UNCOPYABLE(VSymGraph);
public: public:
explicit VSymGraph(AstNetlist* nodep) { explicit VSymGraph(AstNetlist* nodep) { m_symRootp = new VSymEnt(this, nodep); }
m_symRootp = new VSymEnt(this, nodep);
}
~VSymGraph() { ~VSymGraph() {
for (SymStack::iterator it = m_symsp.begin(); it != m_symsp.end(); ++it) { for (SymStack::iterator it = m_symsp.begin(); it != m_symsp.end(); ++it) delete (*it);
delete (*it);
}
} }
public: public:
@ -298,7 +295,10 @@ public:
bool first = true; bool first = true;
for (SymStack::iterator it = m_symsp.begin(); it != m_symsp.end(); ++it) { for (SymStack::iterator it = m_symsp.begin(); it != m_symsp.end(); ++it) {
if (doneSyms.find(*it) == doneSyms.end()) { 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"); (*it)->dumpIterate(os, doneSyms, indent, 9999, "Orphan");
} }
} }

View File

@ -69,13 +69,15 @@ public:
enum { ACTIVITY_ALWAYS = ((1UL << 31) - 2) }; enum { ACTIVITY_ALWAYS = ((1UL << 31) - 2) };
enum { ACTIVITY_SLOW = 0 }; enum { ACTIVITY_SLOW = 0 };
TraceActivityVertex(V3Graph* graphp, AstNode* nodep, bool slow) TraceActivityVertex(V3Graph* graphp, AstNode* nodep, bool slow)
: V3GraphVertex(graphp), m_insertp(nodep) { : V3GraphVertex(graphp)
, m_insertp(nodep) {
m_activityCode = 0; m_activityCode = 0;
m_activityCodeValid = false; m_activityCodeValid = false;
m_slow = slow; m_slow = slow;
} }
TraceActivityVertex(V3Graph* graphp, vlsint32_t code) TraceActivityVertex(V3Graph* graphp, vlsint32_t code)
: V3GraphVertex(graphp), m_insertp(NULL) { : V3GraphVertex(graphp)
, m_insertp(NULL) {
m_activityCode = code; m_activityCode = code;
m_activityCodeValid = true; m_activityCodeValid = true;
m_slow = false; m_slow = false;
@ -87,24 +89,33 @@ public:
return m_insertp; return m_insertp;
} }
virtual string name() const { virtual string name() const {
if (activityAlways()) return "*ALWAYS*"; if (activityAlways()) {
else return (string(slow()?"*SLOW* ":""))+insertp()->name(); 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; } bool activityCodeValid() const { return m_activityCodeValid; }
vlsint32_t activityCode() const { return m_activityCode; } vlsint32_t activityCode() const { return m_activityCode; }
bool activityAlways() const { return activityCode() == ACTIVITY_ALWAYS; } bool activityAlways() const { return activityCode() == ACTIVITY_ALWAYS; }
void activityCode(vlsint32_t code) { m_activityCode = code; m_activityCodeValid = true;} void activityCode(vlsint32_t code) {
m_activityCode = code;
m_activityCodeValid = true;
}
bool slow() const { return m_slow; } 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 { class TraceCFuncVertex : public V3GraphVertex {
AstCFunc* m_nodep; AstCFunc* m_nodep;
public: public:
TraceCFuncVertex(V3Graph* graphp, AstCFunc* nodep) TraceCFuncVertex(V3Graph* graphp, AstCFunc* nodep)
: V3GraphVertex(graphp), m_nodep(nodep) { : V3GraphVertex(graphp)
} , m_nodep(nodep) {}
virtual ~TraceCFuncVertex() {} virtual ~TraceCFuncVertex() {}
// ACCESSORS // ACCESSORS
AstCFunc* nodep() const { return m_nodep; } AstCFunc* nodep() const { return m_nodep; }
@ -115,10 +126,14 @@ public:
class TraceTraceVertex : public V3GraphVertex { class TraceTraceVertex : public V3GraphVertex {
AstTraceInc* m_nodep; // TRACEINC this represents 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: public:
TraceTraceVertex(V3Graph* graphp, AstTraceInc* nodep) TraceTraceVertex(V3Graph* graphp, AstTraceInc* nodep)
: V3GraphVertex(graphp), m_nodep(nodep), m_duplicatep(NULL) {} : V3GraphVertex(graphp)
, m_nodep(nodep)
, m_duplicatep(NULL) {}
virtual ~TraceTraceVertex() {} virtual ~TraceTraceVertex() {}
// ACCESSORS // ACCESSORS
AstTraceInc* nodep() const { return m_nodep; } AstTraceInc* nodep() const { return m_nodep; }
@ -127,17 +142,18 @@ public:
virtual FileLine* fileline() const { return nodep()->fileline(); } virtual FileLine* fileline() const { return nodep()->fileline(); }
TraceTraceVertex* duplicatep() const { return m_duplicatep; } TraceTraceVertex* duplicatep() const { return m_duplicatep; }
void duplicatep(TraceTraceVertex* dupp) { void duplicatep(TraceTraceVertex* dupp) {
UASSERT_OBJ(!duplicatep(), nodep(), UASSERT_OBJ(!duplicatep(), nodep(), "Assigning duplicatep() to already duplicated node");
"Assigning duplicatep() to already duplicated node");
m_duplicatep = dupp; m_duplicatep = dupp;
} }
}; };
class TraceVarVertex : public V3GraphVertex { class TraceVarVertex : public V3GraphVertex {
AstVarScope* m_nodep; AstVarScope* m_nodep;
public: public:
TraceVarVertex(V3Graph* graphp, AstVarScope* nodep) TraceVarVertex(V3Graph* graphp, AstVarScope* nodep)
: V3GraphVertex(graphp), m_nodep(nodep) {} : V3GraphVertex(graphp)
, m_nodep(nodep) {}
virtual ~TraceVarVertex() {} virtual ~TraceVarVertex() {}
// ACCESSORS // ACCESSORS
AstVarScope* nodep() const { return m_nodep; } AstVarScope* nodep() const { return m_nodep; }
@ -206,8 +222,8 @@ private:
"Trace duplicate back needs consistency," "Trace duplicate back needs consistency,"
" so we can map duplicates back to TRACEINCs"); " so we can map duplicates back to TRACEINCs");
hashed.hash(nodep->valuep()); hashed.hash(nodep->valuep());
UINFO(8, " Hashed "<<std::hex<<hashed.nodeHash(nodep->valuep()) UINFO(8, " Hashed " << std::hex << hashed.nodeHash(nodep->valuep()) << " "
<<" "<<nodep<<endl); << nodep << endl);
// Just keep one node in the map and point all duplicates to this node // Just keep one node in the map and point all duplicates to this node
if (hashed.findDuplicate(nodep->valuep()) == hashed.end()) { if (hashed.findDuplicate(nodep->valuep()) == hashed.end()) {
@ -291,9 +307,7 @@ private:
for (V3GraphVertex *nextp, *itp = m_graph.verticesBeginp(); itp; itp = nextp) { for (V3GraphVertex *nextp, *itp = m_graph.verticesBeginp(); itp; itp = nextp) {
nextp = itp->verticesNextp(); nextp = itp->verticesNextp();
if (TraceActivityVertex* vvertexp = dynamic_cast<TraceActivityVertex*>(itp)) { if (TraceActivityVertex* vvertexp = dynamic_cast<TraceActivityVertex*>(itp)) {
if (!vvertexp->outBeginp()) { if (!vvertexp->outBeginp()) { vvertexp->unlinkDelete(&m_graph); }
vvertexp->unlinkDelete(&m_graph);
}
} }
} }
} }
@ -328,13 +342,10 @@ private:
= new AstBasicDType(m_chgFuncp->fileline(), VFlagLogicPacked(), 1); = new AstBasicDType(m_chgFuncp->fileline(), VFlagLogicPacked(), 1);
v3Global.rootp()->typeTablep()->addTypesp(newScalarDtp); v3Global.rootp()->typeTablep()->addTypesp(newScalarDtp);
AstNodeDType* newArrDtp = new AstUnpackArrayDType( AstNodeDType* newArrDtp = new AstUnpackArrayDType(
m_chgFuncp->fileline(), m_chgFuncp->fileline(), newScalarDtp,
newScalarDtp, new AstRange(m_chgFuncp->fileline(), VNumRange(m_activityNumber - 1, 0, false)));
new AstRange(m_chgFuncp->fileline(),
VNumRange(m_activityNumber-1, 0, false)));
v3Global.rootp()->typeTablep()->addTypesp(newArrDtp); v3Global.rootp()->typeTablep()->addTypesp(newArrDtp);
newvarp = new AstVar(m_chgFuncp->fileline(), newvarp = new AstVar(m_chgFuncp->fileline(), AstVarType::MODULETEMP,
AstVarType::MODULETEMP,
"__Vm_traceActivity", newArrDtp); "__Vm_traceActivity", newArrDtp);
} else { } else {
// For tighter code; round to next word point. // For tighter code; round to next word point.
@ -353,8 +364,8 @@ private:
if (!vvertexp->activityAlways()) { if (!vvertexp->activityAlways()) {
FileLine* fl = vvertexp->insertp()->fileline(); FileLine* fl = vvertexp->insertp()->fileline();
uint32_t acode = vvertexp->activityCode(); uint32_t acode = vvertexp->activityCode();
vvertexp->insertp()->addNextHere vvertexp->insertp()->addNextHere(
(new AstAssign(fl, selectActivity(fl, acode, true), new AstAssign(fl, selectActivity(fl, acode, true),
new AstConst(fl, AstConst::LogicTrue()))); new AstConst(fl, AstConst::LogicTrue())));
} }
} }
@ -363,19 +374,17 @@ private:
AstNode* selectActivity(FileLine* flp, uint32_t acode, bool lvalue) { AstNode* selectActivity(FileLine* flp, uint32_t acode, bool lvalue) {
if (v3Global.opt.mtasks()) { if (v3Global.opt.mtasks()) {
return new AstArraySel( return new AstArraySel(flp, new AstVarRef(flp, m_activityVscp, lvalue), acode);
flp, new AstVarRef(flp, m_activityVscp, lvalue), acode);
} else { } else {
return new AstSel( return new AstSel(flp, new AstVarRef(flp, m_activityVscp, lvalue), acode, 1);
flp, new AstVarRef(flp, m_activityVscp, lvalue), acode, 1);
} }
} }
AstCFunc* newCFunc(AstCFuncType type, const string& name, AstCFunc* basep) { AstCFunc* newCFunc(AstCFuncType type, const string& name, AstCFunc* basep) {
AstCFunc* funcp = new AstCFunc(basep->fileline(), name, basep->scopep()); AstCFunc* funcp = new AstCFunc(basep->fileline(), name, basep->scopep());
funcp->slow(basep->slow()); funcp->slow(basep->slow());
funcp->argTypes(EmitCBaseVisitor::symClassVar() funcp->argTypes(EmitCBaseVisitor::symClassVar() + ", " + v3Global.opt.traceClassBase()
+", "+v3Global.opt.traceClassBase()+"* vcdp, uint32_t code"); + "* vcdp, uint32_t code");
funcp->funcType(type); funcp->funcType(type);
funcp->symProlog(true); funcp->symProlog(true);
basep->addNext(funcp); basep->addNext(funcp);
@ -404,8 +413,7 @@ private:
return funcp; return funcp;
} }
void addToChgSub(AstNode* underp, AstNode* stmtsp) { void addToChgSub(AstNode* underp, AstNode* stmtsp) {
if (!m_chgSubFuncp if (!m_chgSubFuncp || (m_chgSubParentp != underp)
|| (m_chgSubParentp != underp)
|| (m_chgSubStmts && v3Global.opt.outputSplitCTrace() || (m_chgSubStmts && v3Global.opt.outputSplitCTrace()
&& m_chgSubStmts > v3Global.opt.outputSplitCTrace())) { && m_chgSubStmts > v3Global.opt.outputSplitCTrace())) {
m_chgSubFuncp = newCFuncSub(m_chgFuncp, underp); m_chgSubFuncp = newCFuncSub(m_chgFuncp, underp);
@ -421,7 +429,8 @@ private:
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::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; TraceVec traces;
// Form sort structure // Form sort structure
@ -476,7 +485,8 @@ private:
AstNode* addp = assignTraceCode(vvertexp, vvertexp->nodep(), needChg); AstNode* addp = assignTraceCode(vvertexp, vvertexp->nodep(), needChg);
if (addp) { // Else no activity or duplicate if (addp) { // Else no activity or duplicate
if (actset.find(TraceActivityVertex::ACTIVITY_NEVER) != actset.end()) { 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()) { } else if (actset.find(TraceActivityVertex::ACTIVITY_ALWAYS) != actset.end()) {
// Must always set it; add to base of function // Must always set it; add to base of function
addToChgSub(m_chgFuncp, addp); addToChgSub(m_chgFuncp, addp);
@ -487,12 +497,14 @@ private:
// Build a new IF statement // Build a new IF statement
FileLine* fl = addp->fileline(); FileLine* fl = addp->fileline();
AstNode* condp = NULL; AstNode* condp = NULL;
for (ActCodeSet::const_iterator csit = actset.begin(); for (ActCodeSet::const_iterator csit = actset.begin(); csit != actset.end();
csit != actset.end(); ++csit) { ++csit) {
uint32_t acode = *csit; uint32_t acode = *csit;
AstNode* selp = selectActivity(fl, acode, false); AstNode* selp = selectActivity(fl, acode, false);
if (condp) condp = new AstOr(fl, condp, selp); if (condp)
else condp = selp; condp = new AstOr(fl, condp, selp);
else
condp = selp;
} }
AstIf* ifp = new AstIf(fl, condp, NULL, NULL); AstIf* ifp = new AstIf(fl, condp, NULL, NULL);
ifp->branchPred(VBranchPred::BP_UNLIKELY); ifp->branchPred(VBranchPred::BP_UNLIKELY);
@ -517,9 +529,9 @@ private:
m_chgFuncp->addFinalsp(clrp); m_chgFuncp->addFinalsp(clrp);
} }
} else { } else {
AstNode* clrp = new AstAssign(fl, new AstVarRef(fl, m_activityVscp, true), AstNode* clrp = new AstAssign(
new AstConst(fl, AstConst::WidthedValue(), fl, new AstVarRef(fl, m_activityVscp, true),
m_activityVscp->width(), 0)); new AstConst(fl, AstConst::WidthedValue(), m_activityVscp->width(), 0));
m_fullFuncp->addFinalsp(clrp->cloneTree(true)); m_fullFuncp->addFinalsp(clrp->cloneTree(true));
m_chgFuncp->addFinalsp(clrp); m_chgFuncp->addFinalsp(clrp);
} }
@ -558,9 +570,9 @@ private:
} else { } else {
assignDeclCode(nodep->declp()); assignDeclCode(nodep->declp());
} }
UINFO(8," Created code="<<nodep->declp()->code() UINFO(8, " Created code=" << nodep->declp()->code() << " "
<<" "<<(codePreassigned?"[PREASS]":"") << (codePreassigned ? "[PREASS]" : "") << " "
<<" "<<(needChg?"[CHG]":"")<<" "<<nodep<<endl); << (needChg ? "[CHG]" : "") << " " << nodep << endl);
AstNode* incAddp = NULL; AstNode* incAddp = NULL;
if (!codePreassigned) { if (!codePreassigned) {
@ -673,11 +685,12 @@ private:
m_chgFuncp = nodep; m_chgFuncp = nodep;
} }
V3GraphVertex* funcVtxp = getCFuncVertexp(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 (!m_finding) { // If public, we need a unique activity code to allow for sets directly
if (nodep->funcPublic() || nodep->dpiExport() // in this func
|| nodep == v3Global.rootp()->evalp()) { if (nodep->funcPublic() || nodep->dpiExport() || nodep == v3Global.rootp()->evalp()) {
// Need a non-null place to remember to later add a statement; make one // Need a non-null place to remember to later add a statement; make one
if (!nodep->stmtsp()) nodep->addStmtsp( if (!nodep->stmtsp())
nodep->addStmtsp(
new AstComment(nodep->fileline(), "Tracing activity check", true)); new AstComment(nodep->fileline(), "Tracing activity check", true));
V3GraphVertex* activityVtxp = getActivityVertexp(nodep->stmtsp(), nodep->slow()); V3GraphVertex* activityVtxp = getActivityVertexp(nodep->stmtsp(), nodep->slow());
new V3GraphEdge(&m_graph, activityVtxp, funcVtxp, 1); new V3GraphEdge(&m_graph, activityVtxp, funcVtxp, 1);
@ -715,8 +728,7 @@ private:
|| nodep->varp()->isSigPublic()) { // Or ones user can change || nodep->varp()->isSigPublic()) { // Or ones user can change
new V3GraphEdge(&m_graph, m_alwaysVtxp, traceVtxp, 1); 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?"); UASSERT_OBJ(nodep->varScopep(), nodep, "No var scope?");
V3GraphVertex* funcVtxp = getCFuncVertexp(m_funcp); V3GraphVertex* funcVtxp = getCFuncVertexp(m_funcp);
V3GraphVertex* varVtxp = nodep->varScopep()->user1u().toGraphVertex(); V3GraphVertex* varVtxp = nodep->varScopep()->user1u().toGraphVertex();
@ -763,8 +775,6 @@ public:
void V3Trace::traceAll(AstNetlist* nodep) { void V3Trace::traceAll(AstNetlist* nodep) {
UINFO(2, __FUNCTION__ << ": " << endl); UINFO(2, __FUNCTION__ << ": " << endl);
{ { TraceVisitor visitor(nodep); } // Destruct before checking
TraceVisitor visitor(nodep);
} // Destruct before checking
V3Global::dumpCheckGlobalTree("trace", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3); V3Global::dumpCheckGlobalTree("trace", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
} }

View File

@ -62,16 +62,12 @@ private:
AstVar* varp = nodep->varp(); AstVar* varp = nodep->varp();
if (!varp->isTrace()) { if (!varp->isTrace()) {
return "Verilator trace_off"; return "Verilator trace_off";
} } else if (!nodep->isTrace()) {
else if (!nodep->isTrace()) {
return "Verilator cell trace_off"; return "Verilator cell trace_off";
} } else if (!v3Global.opt.traceUnderscore()) {
else if (!v3Global.opt.traceUnderscore()) {
string prettyName = varp->prettyName(); string prettyName = varp->prettyName();
if (!prettyName.empty() && prettyName[0] == '_') if (!prettyName.empty() && prettyName[0] == '_') return "Leading underscore";
return "Leading underscore"; if (prettyName.find("._") != string::npos) return "Inlined leading underscore";
if (prettyName.find("._") != string::npos)
return "Inlined leading underscore";
} }
return NULL; return NULL;
} }
@ -108,14 +104,18 @@ private:
return funcp; return funcp;
} }
void addTraceDecl(const VNumRange& arrayRange, 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; VNumRange bitRange;
AstBasicDType* bdtypep = m_traValuep->dtypep()->basicp(); AstBasicDType* bdtypep = m_traValuep->dtypep()->basicp();
if (widthOverride) bitRange = VNumRange(widthOverride-1, 0, false); if (widthOverride) {
else if (bdtypep) bitRange = bdtypep->nrange(); bitRange = VNumRange(widthOverride - 1, 0, false);
AstTraceDecl* declp = new AstTraceDecl(m_traVscp->fileline(), m_traShowname, } else if (bdtypep) {
m_traVscp->varp(), m_traValuep, bitRange = bdtypep->nrange();
bitRange, arrayRange, m_interface); }
AstTraceDecl* declp
= new AstTraceDecl(m_traVscp->fileline(), m_traShowname, m_traVscp->varp(),
m_traValuep, bitRange, arrayRange, m_interface);
UINFO(9, "Decl " << declp << endl); UINFO(9, "Decl " << declp << endl);
if (!m_interface && v3Global.opt.outputSplitCTrace() if (!m_interface && v3Global.opt.outputSplitCTrace()
@ -127,15 +127,14 @@ private:
m_initSubFuncp->addStmtsp(declp); m_initSubFuncp->addStmtsp(declp);
m_initSubStmts += EmitCBaseCounterVisitor(declp).count(); m_initSubStmts += EmitCBaseCounterVisitor(declp).count();
m_chgFuncp->addStmtsp(new AstTraceInc(m_traVscp->fileline(), m_chgFuncp->addStmtsp(
declp, m_traValuep->cloneTree(true))); new AstTraceInc(m_traVscp->fileline(), declp, m_traValuep->cloneTree(true)));
// The full version will get constructed in V3Trace // The full version will get constructed in V3Trace
} }
void addIgnore(const char* why) { void addIgnore(const char* why) {
++m_statIgnSigs; ++m_statIgnSigs;
m_initSubFuncp->addStmtsp( m_initSubFuncp->addStmtsp(new AstComment(
new AstComment(m_traVscp->fileline(), m_traVscp->fileline(), "Tracing: " + m_traShowname + " // Ignored: " + why, true));
"Tracing: "+m_traShowname+" // Ignored: "+why, true));
} }
// VISITORS // VISITORS
@ -195,8 +194,7 @@ private:
// Generally this equation doesn't need updating, instead use // Generally this equation doesn't need updating, instead use
// varp->isTrace() and/or vscIgnoreTrace. // varp->isTrace() and/or vscIgnoreTrace.
if ((!nodep->varp()->isTemp() || nodep->varp()->isTrace()) if ((!nodep->varp()->isTemp() || nodep->varp()->isTrace())
&& !nodep->varp()->isClassMember() && !nodep->varp()->isClassMember() && !nodep->varp()->isFuncLocal()) {
&& !nodep->varp()->isFuncLocal()) {
UINFO(5, " vsc " << nodep << endl); UINFO(5, " vsc " << nodep << endl);
AstVar* varp = nodep->varp(); AstVar* varp = nodep->varp();
AstScope* scopep = nodep->scopep(); AstScope* scopep = nodep->scopep();
@ -217,8 +215,11 @@ private:
addIgnore(vscIgnoreTrace(nodep)); addIgnore(vscIgnoreTrace(nodep));
} else { } else {
++m_statSigs; ++m_statSigs;
if (nodep->valuep()) m_traValuep = nodep->valuep()->cloneTree(true); if (nodep->valuep()) {
else m_traValuep = new AstVarRef(nodep->fileline(), nodep, false); 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() // Recurse into data type of the signal; the visitors will call addTraceDecl()
iterate(varp->dtypep()->skipRefToEnump()); iterate(varp->dtypep()->skipRefToEnump());
@ -233,22 +234,20 @@ private:
} }
// VISITORS - Data types when tracing // VISITORS - Data types when tracing
virtual void visit(AstConstDType* nodep) VL_OVERRIDE { virtual void visit(AstConstDType* nodep) VL_OVERRIDE {
if (m_traVscp) { if (m_traVscp) iterate(nodep->subDTypep()->skipRefToEnump());
iterate(nodep->subDTypep()->skipRefToEnump());
}
} }
virtual void visit(AstRefDType* nodep) VL_OVERRIDE { virtual void visit(AstRefDType* nodep) VL_OVERRIDE {
if (m_traVscp) { if (m_traVscp) iterate(nodep->subDTypep()->skipRefToEnump());
iterate(nodep->subDTypep()->skipRefToEnump());
}
} }
virtual void visit(AstUnpackArrayDType* nodep) VL_OVERRIDE { virtual void visit(AstUnpackArrayDType* nodep) VL_OVERRIDE {
// Note more specific dtypes above // Note more specific dtypes above
if (m_traVscp) { if (m_traVscp) {
if (static_cast<int>(nodep->arrayUnpackedElements()) > v3Global.opt.traceMaxArray()) { if (static_cast<int>(nodep->arrayUnpackedElements()) > v3Global.opt.traceMaxArray()) {
addIgnore("Wide memory > --trace-max-array ents"); addIgnore("Wide memory > --trace-max-array ents");
} else if (VN_IS(nodep->subDTypep()->skipRefToEnump(), BasicDType) // Nothing lower than this array } else if (VN_IS(nodep->subDTypep()->skipRefToEnump(),
&& m_traVscp->dtypep()->skipRefToEnump() == nodep) { // Nothing above this array 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 // Simple 1-D array, use existing V3EmitC runtime loop rather than unrolling
// This will put "(index)" at end of signal name for us // This will put "(index)" at end of signal name for us
if (m_traVscp->dtypep()->skipRefToEnump()->isString()) { if (m_traVscp->dtypep()->skipRefToEnump()->isString()) {
@ -264,9 +263,8 @@ private:
AstNode* oldValuep = m_traValuep; AstNode* oldValuep = m_traValuep;
{ {
m_traShowname += string("(") + cvtToStr(i) + string(")"); m_traShowname += string("(") + cvtToStr(i) + string(")");
m_traValuep = new AstArraySel(nodep->fileline(), m_traValuep = new AstArraySel(
m_traValuep->cloneTree(true), nodep->fileline(), m_traValuep->cloneTree(true), i - nodep->lsb());
i - nodep->lsb());
m_traValuep->dtypep(subtypep); m_traValuep->dtypep(subtypep);
iterate(subtypep); iterate(subtypep);
@ -316,16 +314,16 @@ private:
if (!nodep->packed()) { if (!nodep->packed()) {
addIgnore("Unsupported: Unpacked struct/union"); addIgnore("Unsupported: Unpacked struct/union");
} else { } else {
for (AstMemberDType* itemp = nodep->membersp(); for (AstMemberDType* itemp = nodep->membersp(); itemp;
itemp; itemp=VN_CAST(itemp->nextp(), MemberDType)) { itemp = VN_CAST(itemp->nextp(), MemberDType)) {
AstNodeDType* subtypep = itemp->subDTypep()->skipRefToEnump(); AstNodeDType* subtypep = itemp->subDTypep()->skipRefToEnump();
string oldShowname = m_traShowname; string oldShowname = m_traShowname;
AstNode* oldValuep = m_traValuep; AstNode* oldValuep = m_traValuep;
{ {
m_traShowname += string(" ") + itemp->prettyName(); m_traShowname += string(" ") + itemp->prettyName();
if (VN_IS(nodep, StructDType)) { if (VN_IS(nodep, StructDType)) {
m_traValuep = new AstSel(nodep->fileline(), m_traValuep
m_traValuep->cloneTree(true), = new AstSel(nodep->fileline(), m_traValuep->cloneTree(true),
itemp->lsb(), subtypep->width()); itemp->lsb(), subtypep->width());
m_traValuep->dtypep(subtypep); m_traValuep->dtypep(subtypep);
iterate(subtypep); iterate(subtypep);
@ -350,9 +348,7 @@ private:
} }
} }
} }
virtual void visit(AstEnumDType* nodep) VL_OVERRIDE { virtual void visit(AstEnumDType* nodep) VL_OVERRIDE { iterate(nodep->skipRefp()); }
iterate(nodep->skipRefp());
}
virtual void visit(AstNodeDType* nodep) VL_OVERRIDE { virtual void visit(AstNodeDType* nodep) VL_OVERRIDE {
// Note more specific dtypes above // Note more specific dtypes above
if (!m_traVscp) return; if (!m_traVscp) return;
@ -388,8 +384,6 @@ public:
void V3TraceDecl::traceDeclAll(AstNetlist* nodep) { void V3TraceDecl::traceDeclAll(AstNetlist* nodep) {
UINFO(2, __FUNCTION__ << ": " << endl); UINFO(2, __FUNCTION__ << ": " << endl);
{ { TraceDeclVisitor visitor(nodep); } // Destruct before checking
TraceDeclVisitor visitor (nodep);
} // Destruct before checking
V3Global::dumpCheckGlobalTree("tracedecl", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3); V3Global::dumpCheckGlobalTree("tracedecl", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
} }

View File

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

View File

@ -47,9 +47,7 @@ private:
v3fatal("Out of memory increasing buckets"); v3fatal("Out of memory increasing buckets");
} }
m_datap = newp; m_datap = newp;
for (vluint64_t i = oldsize; i < m_dataSize; i += 64) { for (vluint64_t i = oldsize; i < m_dataSize; i += 64) m_datap[i / 64] = 0;
m_datap[i / 64] = 0;
}
} }
public: public:

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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