clang-format many files. No functional change.
Use nodist/clang_formatter to reformat files that are now clean.
This commit is contained in:
parent
dc5c259069
commit
5c966ec510
|
|
@ -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
|
|
||||||
|
|
@ -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);
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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
|
|
@ -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.
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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"
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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 {
|
||||||
|
|
|
||||||
|
|
@ -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,
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
|
||||||
|
|
@ -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:
|
||||||
|
|
|
||||||
|
|
@ -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();
|
||||||
|
|
|
||||||
|
|
@ -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:
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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; }
|
||||||
|
|
|
||||||
|
|
@ -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(); }
|
|
||||||
};
|
};
|
||||||
|
|
||||||
//============================================================================
|
//============================================================================
|
||||||
|
|
|
||||||
|
|
@ -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);
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -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(); }
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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()) {
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
|
||||||
|
|
@ -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) {
|
||||||
|
|
|
||||||
33
src/V3List.h
33
src/V3List.h
|
|
@ -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;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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";
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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() {}
|
||||||
|
|
|
||||||
15
src/V3Os.h
15
src/V3Os.h
|
|
@ -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
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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() {}
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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");
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
103
src/V3String.cpp
103
src/V3String.cpp
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -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");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
120
src/V3Trace.cpp
120
src/V3Trace.cpp
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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) {
|
||||||
|
|
|
||||||
|
|
@ -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:
|
||||||
|
|
|
||||||
|
|
@ -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"
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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()) {
|
||||||
|
|
|
||||||
|
|
@ -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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue