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
|
|
||||||
|
|
@ -29,16 +29,16 @@ int sc_main(int argc, char* argv[]) {
|
||||||
Vtop* top = new Vtop("top");
|
Vtop* top = new Vtop("top");
|
||||||
|
|
||||||
// Initialize SC model
|
// Initialize SC model
|
||||||
#if (SYSTEMC_VERSION>=20070314)
|
#if (SYSTEMC_VERSION >= 20070314)
|
||||||
sc_start(1,SC_NS);
|
sc_start(1, SC_NS);
|
||||||
#else
|
#else
|
||||||
sc_start(1);
|
sc_start(1);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Simulate until $finish
|
// Simulate until $finish
|
||||||
while (!Verilated::gotFinish()) {
|
while (!Verilated::gotFinish()) {
|
||||||
#if (SYSTEMC_VERSION>=20070314)
|
#if (SYSTEMC_VERSION >= 20070314)
|
||||||
sc_start(1,SC_NS);
|
sc_start(1, SC_NS);
|
||||||
#else
|
#else
|
||||||
sc_start(1);
|
sc_start(1);
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -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) {}
|
||||||
|
|
@ -35,7 +33,7 @@ int main(int argc, char** argv, char** env) {
|
||||||
// When tracing, the contents of the secret module will not be seen
|
// When tracing, the contents of the secret module will not be seen
|
||||||
VerilatedVcdC* tfp = NULL;
|
VerilatedVcdC* tfp = NULL;
|
||||||
const char* flag = Verilated::commandArgsPlusMatch("trace");
|
const char* flag = Verilated::commandArgsPlusMatch("trace");
|
||||||
if (flag && 0==strcmp(flag, "+trace")) {
|
if (flag && 0 == strcmp(flag, "+trace")) {
|
||||||
Verilated::traceEverOn(true);
|
Verilated::traceEverOn(true);
|
||||||
VL_PRINTF("Enabling waves into logs/vlt_dump.vcd...\n");
|
VL_PRINTF("Enabling waves into logs/vlt_dump.vcd...\n");
|
||||||
tfp = new VerilatedVcdC;
|
tfp = new VerilatedVcdC;
|
||||||
|
|
@ -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);
|
||||||
|
|
|
||||||
|
|
@ -83,9 +83,9 @@ 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);
|
||||||
|
|
|
||||||
|
|
@ -45,19 +45,19 @@ int sc_main(int argc, char* argv[]) {
|
||||||
ios::sync_with_stdio();
|
ios::sync_with_stdio();
|
||||||
|
|
||||||
// Defaults time
|
// Defaults time
|
||||||
#if (SYSTEMC_VERSION>20011000)
|
#if (SYSTEMC_VERSION > 20011000)
|
||||||
#else
|
#else
|
||||||
sc_time dut(1.0, sc_ns);
|
sc_time dut(1.0, sc_ns);
|
||||||
sc_set_default_time_unit(dut);
|
sc_set_default_time_unit(dut);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Define clocks
|
// Define clocks
|
||||||
#if (SYSTEMC_VERSION>=20070314)
|
#if (SYSTEMC_VERSION >= 20070314)
|
||||||
sc_clock clk ("clk", 10,SC_NS, 0.5, 3,SC_NS, true);
|
sc_clock clk("clk", 10, SC_NS, 0.5, 3, SC_NS, true);
|
||||||
sc_clock fastclk ("fastclk", 2,SC_NS, 0.5, 2,SC_NS, true);
|
sc_clock fastclk("fastclk", 2, SC_NS, 0.5, 2, SC_NS, true);
|
||||||
#else
|
#else
|
||||||
sc_clock clk ("clk", 10, 0.5, 3, true);
|
sc_clock clk("clk", 10, 0.5, 3, true);
|
||||||
sc_clock fastclk ("fastclk", 2, 0.5, 2, true);
|
sc_clock fastclk("fastclk", 2, 0.5, 2, true);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Define interconnect
|
// Define interconnect
|
||||||
|
|
@ -72,15 +72,15 @@ int sc_main(int argc, char* argv[]) {
|
||||||
// Construct the Verilated model, from inside Vtop.h
|
// Construct the Verilated model, from inside Vtop.h
|
||||||
Vtop* top = new Vtop("top");
|
Vtop* top = new Vtop("top");
|
||||||
// Attach signals to the model
|
// Attach signals to the model
|
||||||
top->clk (clk);
|
top->clk(clk);
|
||||||
top->fastclk (fastclk);
|
top->fastclk(fastclk);
|
||||||
top->reset_l (reset_l);
|
top->reset_l(reset_l);
|
||||||
top->in_small (in_small);
|
top->in_small(in_small);
|
||||||
top->in_quad (in_quad);
|
top->in_quad(in_quad);
|
||||||
top->in_wide (in_wide);
|
top->in_wide(in_wide);
|
||||||
top->out_small (out_small);
|
top->out_small(out_small);
|
||||||
top->out_quad (out_quad);
|
top->out_quad(out_quad);
|
||||||
top->out_wide (out_wide);
|
top->out_wide(out_wide);
|
||||||
|
|
||||||
#if VM_TRACE
|
#if VM_TRACE
|
||||||
// Before any evaluation, need to know to calculate those signals only used for tracing
|
// Before any evaluation, need to know to calculate those signals only used for tracing
|
||||||
|
|
@ -89,7 +89,7 @@ int sc_main(int argc, char* argv[]) {
|
||||||
|
|
||||||
// You must do one evaluation before enabling waves, in order to allow
|
// You must do one evaluation before enabling waves, in order to allow
|
||||||
// SystemC to interconnect everything for testing.
|
// SystemC to interconnect everything for testing.
|
||||||
#if (SYSTEMC_VERSION>=20070314)
|
#if (SYSTEMC_VERSION >= 20070314)
|
||||||
sc_start(1, SC_NS);
|
sc_start(1, SC_NS);
|
||||||
#else
|
#else
|
||||||
sc_start(1);
|
sc_start(1);
|
||||||
|
|
@ -100,7 +100,7 @@ int sc_main(int argc, char* argv[]) {
|
||||||
// and if at run time passed the +trace argument, turn on tracing
|
// and if at run time passed the +trace argument, turn on tracing
|
||||||
VerilatedVcdSc* tfp = NULL;
|
VerilatedVcdSc* tfp = NULL;
|
||||||
const char* flag = Verilated::commandArgsPlusMatch("trace");
|
const char* flag = Verilated::commandArgsPlusMatch("trace");
|
||||||
if (flag && 0==strcmp(flag, "+trace")) {
|
if (flag && 0 == strcmp(flag, "+trace")) {
|
||||||
cout << "Enabling waves into logs/vlt_dump.vcd...\n";
|
cout << "Enabling waves into logs/vlt_dump.vcd...\n";
|
||||||
tfp = new VerilatedVcdSc;
|
tfp = new VerilatedVcdSc;
|
||||||
top->trace(tfp, 99); // Trace 99 levels of hierarchy
|
top->trace(tfp, 99); // Trace 99 levels of hierarchy
|
||||||
|
|
@ -118,15 +118,14 @@ 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
|
||||||
}
|
}
|
||||||
|
|
||||||
// Simulate 1ns
|
// Simulate 1ns
|
||||||
#if (SYSTEMC_VERSION>=20070314)
|
#if (SYSTEMC_VERSION >= 20070314)
|
||||||
sc_start(1, SC_NS);
|
sc_start(1, SC_NS);
|
||||||
#else
|
#else
|
||||||
sc_start(1);
|
sc_start(1);
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load Diff
1168
include/verilated.h
1168
include/verilated.h
File diff suppressed because it is too large
Load Diff
|
|
@ -16,9 +16,8 @@
|
||||||
///
|
///
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
|
|
||||||
|
|
||||||
///**** 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.
|
||||||
#define VERILATOR_PRODUCT "@PACKAGE_NAME@"
|
#define VERILATOR_PRODUCT "@PACKAGE_NAME@"
|
||||||
#define VERILATOR_VERSION "@PACKAGE_VERSION@"
|
#define VERILATOR_VERSION "@PACKAGE_VERSION@"
|
||||||
|
|
|
||||||
|
|
@ -47,7 +47,7 @@ public: // But only local to this file
|
||||||
// CONSTRUCTORS
|
// CONSTRUCTORS
|
||||||
// Derived classes should call zero() in their constructor
|
// Derived classes should call zero() in their constructor
|
||||||
VerilatedCovImpItem() {
|
VerilatedCovImpItem() {
|
||||||
for (int i=0; i<MAX_KEYS; ++i) {
|
for (int i = 0; i < MAX_KEYS; ++i) {
|
||||||
m_keys[i] = KEY_UNDEF;
|
m_keys[i] = KEY_UNDEF;
|
||||||
m_vals[i] = 0;
|
m_vals[i] = 0;
|
||||||
}
|
}
|
||||||
|
|
@ -66,7 +66,7 @@ public: // But only local to this file
|
||||||
template <class T> class VerilatedCoverItemSpec : public VerilatedCovImpItem {
|
template <class T> class VerilatedCoverItemSpec : public VerilatedCovImpItem {
|
||||||
private:
|
private:
|
||||||
// MEMBERS
|
// MEMBERS
|
||||||
T* m_countp; ///< Count value
|
T* m_countp; ///< Count value
|
||||||
public:
|
public:
|
||||||
// METHODS
|
// METHODS
|
||||||
// cppcheck-suppress truncLongCastReturn
|
// cppcheck-suppress truncLongCastReturn
|
||||||
|
|
@ -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 {}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -87,20 +90,20 @@ public:
|
||||||
class VerilatedCovImp : VerilatedCovImpBase {
|
class VerilatedCovImp : VerilatedCovImpBase {
|
||||||
private:
|
private:
|
||||||
// TYPES
|
// TYPES
|
||||||
typedef std::map<std::string,int> ValueIndexMap;
|
typedef std::map<std::string, int> ValueIndexMap;
|
||||||
typedef std::map<int,std::string> IndexValueMap;
|
typedef std::map<int, std::string> IndexValueMap;
|
||||||
typedef std::deque<VerilatedCovImpItem*> ItemList;
|
typedef std::deque<VerilatedCovImpItem*> ItemList;
|
||||||
|
|
||||||
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
|
||||||
const char* m_insertFilenamep VL_GUARDED_BY(m_mutex); ///< Filename about to insert
|
const char* m_insertFilenamep VL_GUARDED_BY(m_mutex); ///< Filename about to insert
|
||||||
int m_insertLineno VL_GUARDED_BY(m_mutex); ///< Line number about to insert
|
int m_insertLineno VL_GUARDED_BY(m_mutex); ///< Line number about to insert
|
||||||
|
|
||||||
// CONSTRUCTORS
|
// CONSTRUCTORS
|
||||||
VerilatedCovImp() {
|
VerilatedCovImp() {
|
||||||
|
|
@ -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 {
|
||||||
|
|
@ -119,10 +123,11 @@ public:
|
||||||
private:
|
private:
|
||||||
// PRIVATE METHODS
|
// PRIVATE METHODS
|
||||||
int valueIndex(const std::string& value) VL_REQUIRES(m_mutex) {
|
int valueIndex(const std::string& value) VL_REQUIRES(m_mutex) {
|
||||||
static int nextIndex = KEY_UNDEF+1;
|
static int nextIndex = KEY_UNDEF + 1;
|
||||||
ValueIndexMap::iterator iter = m_valueIndexes.find(value);
|
ValueIndexMap::iterator iter = m_valueIndexes.find(value);
|
||||||
if (iter != m_valueIndexes.end()) return iter->second;
|
if (iter != m_valueIndexes.end()) return iter->second;
|
||||||
nextIndex++; assert(nextIndex>0);
|
nextIndex++;
|
||||||
|
assert(nextIndex > 0); // 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;
|
||||||
|
|
@ -131,8 +136,9 @@ private:
|
||||||
// Quote any special characters
|
// Quote any special characters
|
||||||
std::string rtn;
|
std::string rtn;
|
||||||
for (const char* pos = text.c_str(); *pos; ++pos) {
|
for (const char* pos = text.c_str(); *pos; ++pos) {
|
||||||
if (!isprint(*pos) || *pos=='%' || *pos=='"') {
|
if (!isprint(*pos) || *pos == '%' || *pos == '"') {
|
||||||
char hex[10]; sprintf(hex, "%%%02X", pos[0]);
|
char hex[10];
|
||||||
|
sprintf(hex, "%%%02X", pos[0]);
|
||||||
rtn += hex;
|
rtn += hex;
|
||||||
} else {
|
} else {
|
||||||
rtn += *pos;
|
rtn += *pos;
|
||||||
|
|
@ -145,18 +151,19 @@ private:
|
||||||
// don't want applications to either get confused if they use
|
// don't want applications to either get confused if they use
|
||||||
// a letter differently, nor want them to rely on our compression...
|
// a letter differently, nor want them to rely on our compression...
|
||||||
// (Considered using numeric keys, but will remain back compatible.)
|
// (Considered using numeric keys, but will remain back compatible.)
|
||||||
if (key.length()<2) return false;
|
if (key.length() < 2) return false;
|
||||||
if (key.length()==2 && isdigit(key[1])) return false;
|
if (key.length() == 2 && isdigit(key[1])) return false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
static std::string keyValueFormatter(const std::string& key, const std::string& value) VL_PURE {
|
static std::string keyValueFormatter(const std::string& key,
|
||||||
|
const std::string& value) VL_PURE {
|
||||||
std::string name;
|
std::string name;
|
||||||
if (key.length()==1 && isalpha(key[0])) {
|
if (key.length() == 1 && isalpha(key[0])) {
|
||||||
name += std::string("\001")+key;
|
name += std::string("\001") + key;
|
||||||
} else {
|
} else {
|
||||||
name += std::string("\001")+dequote(key);
|
name += std::string("\001") + dequote(key);
|
||||||
}
|
}
|
||||||
name += std::string("\002")+dequote(value);
|
name += std::string("\002") + dequote(value);
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
static std::string combineHier(const std::string& old, const std::string& add) VL_PURE {
|
static std::string combineHier(const std::string& old, const std::string& add) VL_PURE {
|
||||||
|
|
@ -173,28 +180,35 @@ 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
|
||||||
std::string prefix = std::string(a, apre-a);
|
std::string prefix = std::string(a, apre - a);
|
||||||
|
|
||||||
// Scan backward to last mismatch
|
// Scan backward to last mismatch
|
||||||
const char* apost = a+strlen(a)-1;
|
const char* apost = a + strlen(a) - 1;
|
||||||
const char* bpost = b+strlen(b)-1;
|
const char* bpost = b + strlen(b) - 1;
|
||||||
while (*apost == *bpost
|
while (*apost == *bpost && apost > apre && bpost > bpre) {
|
||||||
&& apost>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)
|
||||||
for (int i=0; i<MAX_KEYS; ++i) {
|
VL_REQUIRES(m_mutex) {
|
||||||
|
for (int i = 0; i < MAX_KEYS; ++i) {
|
||||||
if (itemp->m_keys[i] != KEY_UNDEF) {
|
if (itemp->m_keys[i] != KEY_UNDEF) {
|
||||||
// We don't compare keys, only values
|
// We don't compare keys, only values
|
||||||
std::string val = m_indexValues[itemp->m_vals[i]];
|
std::string val = m_indexValues[itemp->m_vals[i]];
|
||||||
|
|
@ -207,17 +221,23 @@ 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) {
|
||||||
VerilatedCovImpItem* itemp = *(it);
|
VerilatedCovImpItem* itemp = *(it);
|
||||||
VL_DO_DANGLING(delete itemp, itemp);
|
VL_DO_DANGLING(delete itemp, itemp);
|
||||||
}
|
}
|
||||||
|
|
@ -238,7 +258,7 @@ public:
|
||||||
VerilatedLockGuard lock(m_mutex);
|
VerilatedLockGuard lock(m_mutex);
|
||||||
if (matchp && matchp[0]) {
|
if (matchp && matchp[0]) {
|
||||||
ItemList newlist;
|
ItemList newlist;
|
||||||
for (ItemList::iterator it=m_items.begin(); it!=m_items.end(); ++it) {
|
for (ItemList::iterator it = m_items.begin(); it != m_items.end(); ++it) {
|
||||||
VerilatedCovImpItem* itemp = *(it);
|
VerilatedCovImpItem* itemp = *(it);
|
||||||
if (!itemMatchesString(itemp, matchp)) {
|
if (!itemMatchesString(itemp, matchp)) {
|
||||||
VL_DO_DANGLING(delete itemp, itemp);
|
VL_DO_DANGLING(delete itemp, itemp);
|
||||||
|
|
@ -252,7 +272,7 @@ public:
|
||||||
void zero() VL_EXCLUDES(m_mutex) {
|
void zero() VL_EXCLUDES(m_mutex) {
|
||||||
Verilated::quiesce();
|
Verilated::quiesce();
|
||||||
VerilatedLockGuard lock(m_mutex);
|
VerilatedLockGuard lock(m_mutex);
|
||||||
for (ItemList::const_iterator it=m_items.begin(); it!=m_items.end(); ++it) {
|
for (ItemList::const_iterator it = m_items.begin(); it != m_items.end(); ++it) {
|
||||||
(*it)->zero();
|
(*it)->zero();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -268,33 +288,33 @@ 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) {
|
||||||
if (!keys[i].empty()) {
|
if (!keys[i].empty()) {
|
||||||
for (int j=i+1; j<MAX_KEYS; ++j) {
|
for (int j = i + 1; j < MAX_KEYS; ++j) {
|
||||||
if (keys[i] == keys[j]) { // Duplicate key. Keep the last one
|
if (keys[i] == keys[j]) { // Duplicate key. Keep the last one
|
||||||
keys[i] = "";
|
keys[i] = "";
|
||||||
break;
|
break;
|
||||||
|
|
@ -304,18 +324,18 @@ public:
|
||||||
}
|
}
|
||||||
// Insert the values
|
// Insert the values
|
||||||
int addKeynum = 0;
|
int addKeynum = 0;
|
||||||
for (int i=0; i<MAX_KEYS; ++i) {
|
for (int i = 0; i < MAX_KEYS; ++i) {
|
||||||
const std::string key = keys[i];
|
const std::string key = keys[i];
|
||||||
if (!keys[i].empty()) {
|
if (!keys[i].empty()) {
|
||||||
const std::string val = valps[i];
|
const std::string val = valps[i];
|
||||||
//cout<<" "<<__FUNCTION__<<" "<<key<<" = "<<val<<endl;
|
// cout<<" "<<__FUNCTION__<<" "<<key<<" = "<<val<<endl;
|
||||||
m_insertp->m_keys[addKeynum] = valueIndex(key);
|
m_insertp->m_keys[addKeynum] = valueIndex(key);
|
||||||
m_insertp->m_vals[addKeynum] = valueIndex(val);
|
m_insertp->m_vals[addKeynum] = valueIndex(val);
|
||||||
addKeynum++;
|
addKeynum++;
|
||||||
if (!legalKey(key)) {
|
if (!legalKey(key)) {
|
||||||
std::string msg
|
std::string msg
|
||||||
= ("%Error: Coverage keys of one character, or letter+digit are illegal: "
|
= ("%Error: Coverage keys of one character, or letter+digit are illegal: "
|
||||||
+key);
|
+ key);
|
||||||
VL_FATAL_MT("", 0, "", msg.c_str());
|
VL_FATAL_MT("", 0, "", msg.c_str());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -335,22 +355,22 @@ public:
|
||||||
|
|
||||||
std::ofstream os(filename);
|
std::ofstream os(filename);
|
||||||
if (os.fail()) {
|
if (os.fail()) {
|
||||||
std::string msg = std::string("%Error: Can't write '")+filename+"'";
|
std::string msg = std::string("%Error: Can't write '") + filename + "'";
|
||||||
VL_FATAL_MT("", 0, "", msg.c_str());
|
VL_FATAL_MT("", 0, "", msg.c_str());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
os << "# SystemC::Coverage-3\n";
|
os << "# SystemC::Coverage-3\n";
|
||||||
|
|
||||||
// Build list of events; totalize if collapsing hierarchy
|
// Build list of events; totalize if collapsing hierarchy
|
||||||
typedef std::map<std::string,std::pair<std::string,vluint64_t> > EventMap;
|
typedef std::map<std::string, std::pair<std::string, vluint64_t> > EventMap;
|
||||||
EventMap eventCounts;
|
EventMap eventCounts;
|
||||||
for (ItemList::iterator it=m_items.begin(); it!=m_items.end(); ++it) {
|
for (ItemList::iterator it = m_items.begin(); it != m_items.end(); ++it) {
|
||||||
VerilatedCovImpItem* itemp = *(it);
|
VerilatedCovImpItem* itemp = *(it);
|
||||||
std::string name;
|
std::string name;
|
||||||
std::string hier;
|
std::string hier;
|
||||||
bool per_instance = false;
|
bool per_instance = false;
|
||||||
|
|
||||||
for (int i=0; i<MAX_KEYS; ++i) {
|
for (int i = 0; i < MAX_KEYS; ++i) {
|
||||||
if (itemp->m_keys[i] != KEY_UNDEF) {
|
if (itemp->m_keys[i] != KEY_UNDEF) {
|
||||||
std::string key = VerilatedCovKey::shortKey(m_indexValues[itemp->m_keys[i]]);
|
std::string key = VerilatedCovKey::shortKey(m_indexValues[itemp->m_keys[i]]);
|
||||||
std::string val = m_indexValues[itemp->m_vals[i]];
|
std::string val = m_indexValues[itemp->m_vals[i]];
|
||||||
|
|
@ -380,19 +400,19 @@ public:
|
||||||
if (cit != eventCounts.end()) {
|
if (cit != eventCounts.end()) {
|
||||||
const std::string& oldhier = cit->second.first;
|
const std::string& oldhier = cit->second.first;
|
||||||
cit->second.second += itemp->count();
|
cit->second.second += itemp->count();
|
||||||
cit->second.first = combineHier(oldhier, hier);
|
cit->second.first = combineHier(oldhier, hier);
|
||||||
} else {
|
} else {
|
||||||
eventCounts.insert(std::make_pair(name, make_pair(hier, itemp->count())));
|
eventCounts.insert(std::make_pair(name, make_pair(hier, itemp->count())));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Output body
|
// Output body
|
||||||
for (EventMap::const_iterator it=eventCounts.begin(); it!=eventCounts.end(); ++it) {
|
for (EventMap::const_iterator it = eventCounts.begin(); it != eventCounts.end(); ++it) {
|
||||||
os<<"C '"<<std::dec;
|
os << "C '" << std::dec;
|
||||||
os<<it->first;
|
os << it->first;
|
||||||
if (!it->second.first.empty()) os<<keyValueFormatter(VL_CIK_HIER, it->second.first);
|
if (!it->second.first.empty()) os << keyValueFormatter(VL_CIK_HIER, it->second.first);
|
||||||
os<<"' "<<it->second.second;
|
os << "' " << it->second.second;
|
||||||
os<<std::endl;
|
os << std::endl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
@ -422,48 +438,49 @@ void VerilatedCov::_insertf(const char* filename, int lineno) VL_MT_SAFE {
|
||||||
VerilatedCovImp::imp().insertf(filename, lineno);
|
VerilatedCovImp::imp().insertf(filename, lineno);
|
||||||
}
|
}
|
||||||
|
|
||||||
#define K(n) const char* key ## n
|
#define K(n) const char* key##n
|
||||||
#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,
|
||||||
key10,key11,key12,key13,key14,key15,key16,key17,key18,key19,
|
key10, key11, key12, key13, key14, key15, key16, key17, key18, key19,
|
||||||
key20,key21,key22,key23,key24,key25,key26,key27,key28,key29};
|
key20, key21, key22, key23, key24, key25, key26, key27, key28, key29};
|
||||||
const char* valps[VerilatedCovImpBase::MAX_KEYS]
|
const char* valps[VerilatedCovImpBase::MAX_KEYS]
|
||||||
= {NULL,NULL,NULL, // filename,lineno,page
|
= {NULL, NULL, NULL, // filename,lineno,page
|
||||||
valp0,valp1,valp2,valp3,valp4,valp5,valp6,valp7,valp8,valp9,
|
valp0, valp1, valp2, valp3, valp4, valp5, valp6, valp7, valp8, valp9,
|
||||||
valp10,valp11,valp12,valp13,valp14,valp15,valp16,valp17,valp18,valp19,
|
valp10, valp11, valp12, valp13, valp14, valp15, valp16, valp17, valp18, valp19,
|
||||||
valp20,valp21,valp22,valp23,valp24,valp25,valp26,valp27,valp28,valp29};
|
valp20, valp21, valp22, valp23, valp24, valp25, valp26, valp27, valp28, valp29};
|
||||||
VerilatedCovImp::imp().insertp(keyps, valps);
|
VerilatedCovImp::imp().insertp(keyps, valps);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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.
|
||||||
|
|
@ -68,16 +68,17 @@
|
||||||
/// VL_COVER_INSERT(&m_cases[i], "comment", "Coverage Case", "i", cvtToNumStr(i));
|
/// VL_COVER_INSERT(&m_cases[i], "comment", "Coverage Case", "i", cvtToNumStr(i));
|
||||||
/// }
|
/// }
|
||||||
|
|
||||||
#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
|
||||||
|
|
@ -108,18 +110,18 @@ public:
|
||||||
// We could have just the maximum argument version, but this compiles
|
// We could have just the maximum argument version, but this compiles
|
||||||
// much slower (nearly 2x) than having smaller versions also. However
|
// much slower (nearly 2x) than having smaller versions also. However
|
||||||
// there's not much more gain in having a version for each number of args.
|
// there's not much more gain in having a version for each number of args.
|
||||||
#define K(n) const char* key ## n
|
#define K(n) const char* key##n
|
||||||
#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"
|
||||||
|
|
|
||||||
|
|
@ -40,88 +40,80 @@
|
||||||
// Not supported yet
|
// Not supported yet
|
||||||
#define _VL_SVDPI_UNIMP() \
|
#define _VL_SVDPI_UNIMP() \
|
||||||
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
|
||||||
return (((sp[VL_BITWORD_I(bit)].aval >> VL_BITBIT_I(bit)) & 1)
|
return (((sp[VL_BITWORD_I(bit)].aval >> VL_BITBIT_I(bit)) & 1)
|
||||||
| (((sp[VL_BITWORD_I(bit)].bval >> VL_BITBIT_I(bit)) & 1)<<1));
|
| (((sp[VL_BITWORD_I(bit)].bval >> VL_BITBIT_I(bit)) & 1) << 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
void svPutBitselBit(svBitVecVal* dp, int bit, svBit s) {
|
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 & ~(VL_UL(1) << VL_BITBIT_I(bit)))
|
||||||
dp[VL_BITWORD_I(bit)].bval
|
| ((s & 2) >> 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)));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void svGetPartselBit(svBitVecVal* dp, const svBitVecVal* sp, int lsb, int width) {
|
void svGetPartselBit(svBitVecVal* dp, const svBitVecVal* sp, int lsb, int width) {
|
||||||
// See also VL_SEL_WWI
|
// See also VL_SEL_WWI
|
||||||
int msb = lsb+width-1;
|
int msb = lsb + width - 1;
|
||||||
int word_shift = VL_BITWORD_I(lsb);
|
int word_shift = VL_BITWORD_I(lsb);
|
||||||
if (VL_BITBIT_I(lsb)==0) {
|
if (VL_BITBIT_I(lsb) == 0) {
|
||||||
// Just a word extract
|
// Just a word extract
|
||||||
for (int i=0; i<VL_WORDS_I(width); ++i) dp[i] = sp[i+word_shift];
|
for (int i = 0; i < VL_WORDS_I(width); ++i) dp[i] = sp[i + word_shift];
|
||||||
} else {
|
} else {
|
||||||
int loffset = lsb & VL_SIZEBITS_I;
|
int loffset = lsb & VL_SIZEBITS_I;
|
||||||
int nbitsfromlow = 32-loffset; // bits that end up in lword (know loffset!=0)
|
int nbitsfromlow = 32 - loffset; // bits that end up in lword (know loffset!=0)
|
||||||
// Middle words
|
// Middle words
|
||||||
int words = VL_WORDS_I(msb-lsb+1);
|
int words = VL_WORDS_I(msb - lsb + 1);
|
||||||
for (int i=0; i<words; ++i) {
|
for (int i = 0; i < words; ++i) {
|
||||||
dp[i] = sp[i+word_shift]>>loffset;
|
dp[i] = sp[i + word_shift] >> loffset;
|
||||||
int upperword = i+word_shift+1;
|
int upperword = i + word_shift + 1;
|
||||||
if (upperword <= static_cast<int>(VL_BITWORD_I(msb))) {
|
if (upperword <= static_cast<int>(VL_BITWORD_I(msb))) {
|
||||||
dp[i] |= sp[upperword] << nbitsfromlow;
|
dp[i] |= sp[upperword] << nbitsfromlow;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Clean result
|
// Clean result
|
||||||
dp[VL_WORDS_I(width)-1] &= VL_MASK_I(width);
|
dp[VL_WORDS_I(width) - 1] &= VL_MASK_I(width);
|
||||||
}
|
}
|
||||||
void svGetPartselLogic(svLogicVecVal* dp, const svLogicVecVal* sp, int lsb, int width) {
|
void svGetPartselLogic(svLogicVecVal* dp, const svLogicVecVal* sp, int lsb, int width) {
|
||||||
int msb = lsb+width-1;
|
int msb = lsb + width - 1;
|
||||||
int word_shift = VL_BITWORD_I(lsb);
|
int word_shift = VL_BITWORD_I(lsb);
|
||||||
if (VL_BITBIT_I(lsb)==0) {
|
if (VL_BITBIT_I(lsb) == 0) {
|
||||||
// Just a word extract
|
// Just a word extract
|
||||||
for (int i=0; i<VL_WORDS_I(width); ++i) dp[i] = sp[i+word_shift];
|
for (int i = 0; i < VL_WORDS_I(width); ++i) dp[i] = sp[i + word_shift];
|
||||||
} else {
|
} else {
|
||||||
int loffset = lsb & VL_SIZEBITS_I;
|
int loffset = lsb & VL_SIZEBITS_I;
|
||||||
int nbitsfromlow = 32-loffset; // bits that end up in lword (know loffset!=0)
|
int nbitsfromlow = 32 - loffset; // bits that end up in lword (know loffset!=0)
|
||||||
// Middle words
|
// Middle words
|
||||||
int words = VL_WORDS_I(msb-lsb+1);
|
int words = VL_WORDS_I(msb - lsb + 1);
|
||||||
for (int i=0; i<words; ++i) {
|
for (int i = 0; i < words; ++i) {
|
||||||
dp[i].aval = sp[i+word_shift].aval >> loffset;
|
dp[i].aval = sp[i + word_shift].aval >> loffset;
|
||||||
dp[i].bval = sp[i+word_shift].bval >> loffset;
|
dp[i].bval = sp[i + word_shift].bval >> loffset;
|
||||||
int upperword = i+word_shift+1;
|
int upperword = i + word_shift + 1;
|
||||||
if (upperword <= static_cast<int>(VL_BITWORD_I(msb))) {
|
if (upperword <= static_cast<int>(VL_BITWORD_I(msb))) {
|
||||||
dp[i].aval |= sp[upperword].aval << nbitsfromlow;
|
dp[i].aval |= sp[upperword].aval << nbitsfromlow;
|
||||||
dp[i].bval |= sp[upperword].bval << nbitsfromlow;
|
dp[i].bval |= sp[upperword].bval << nbitsfromlow;
|
||||||
|
|
@ -129,58 +121,56 @@ void svGetPartselLogic(svLogicVecVal* dp, const svLogicVecVal* sp, int lsb, int
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Clean result
|
// Clean result
|
||||||
dp[VL_WORDS_I(width)-1].aval &= VL_MASK_I(width);
|
dp[VL_WORDS_I(width) - 1].aval &= VL_MASK_I(width);
|
||||||
dp[VL_WORDS_I(width)-1].bval &= VL_MASK_I(width);
|
dp[VL_WORDS_I(width) - 1].bval &= VL_MASK_I(width);
|
||||||
}
|
}
|
||||||
void svPutPartselBit(svBitVecVal* dp, const svBitVecVal s, int lbit, int width) {
|
void svPutPartselBit(svBitVecVal* dp, const svBitVecVal s, int lbit, int width) {
|
||||||
// See also _VL_INSERT_WI
|
// See also _VL_INSERT_WI
|
||||||
int hbit = lbit+width-1;
|
int hbit = lbit + width - 1;
|
||||||
int hoffset = VL_BITBIT_I(hbit);
|
int hoffset = VL_BITBIT_I(hbit);
|
||||||
int loffset = VL_BITBIT_I(lbit);
|
int loffset = VL_BITBIT_I(lbit);
|
||||||
if (hoffset==VL_SIZEBITS_I && loffset==0) {
|
if (hoffset == VL_SIZEBITS_I && loffset == 0) {
|
||||||
// Fast and common case, word based insertion
|
// 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
|
||||||
IData insmask = (VL_MASK_I(hoffset-loffset+1))<<loffset;
|
IData insmask = (VL_MASK_I(hoffset - loffset + 1)) << loffset;
|
||||||
dp[lword] = (dp[lword] & ~insmask) | ((s<<loffset) & insmask);
|
dp[lword] = (dp[lword] & ~insmask) | ((s << loffset) & insmask);
|
||||||
} else {
|
} else {
|
||||||
IData hinsmask = (VL_MASK_I(hoffset-0+1))<<0;
|
IData hinsmask = (VL_MASK_I(hoffset - 0 + 1)) << 0;
|
||||||
IData linsmask = (VL_MASK_I(31-loffset+1))<<loffset;
|
IData linsmask = (VL_MASK_I(31 - loffset + 1)) << loffset;
|
||||||
int nbitsonright = 32-loffset; // bits that end up in lword
|
int nbitsonright = 32 - loffset; // bits that end up in lword
|
||||||
dp[lword] = (dp[lword] & ~linsmask) | ((s<<loffset) & linsmask);
|
dp[lword] = (dp[lword] & ~linsmask) | ((s << loffset) & linsmask);
|
||||||
dp[hword] = (dp[hword] & ~hinsmask) | ((s>>nbitsonright) & hinsmask);
|
dp[hword] = (dp[hword] & ~hinsmask) | ((s >> nbitsonright) & hinsmask);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// cppcheck-suppress passedByValue
|
// cppcheck-suppress passedByValue
|
||||||
void svPutPartselLogic(svLogicVecVal* dp, const svLogicVecVal s, int lbit, int width) {
|
void svPutPartselLogic(svLogicVecVal* dp, const svLogicVecVal s, int lbit, int width) {
|
||||||
int hbit = lbit+width-1;
|
int hbit = lbit + width - 1;
|
||||||
int hoffset = VL_BITBIT_I(hbit);
|
int hoffset = VL_BITBIT_I(hbit);
|
||||||
int loffset = VL_BITBIT_I(lbit);
|
int loffset = VL_BITBIT_I(lbit);
|
||||||
if (hoffset==VL_SIZEBITS_I && loffset==0) {
|
if (hoffset == VL_SIZEBITS_I && loffset == 0) {
|
||||||
// Fast and common case, word based insertion
|
// 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
|
||||||
IData insmask = (VL_MASK_I(hoffset-loffset+1))<<loffset;
|
IData insmask = (VL_MASK_I(hoffset - loffset + 1)) << loffset;
|
||||||
dp[lword].aval = (dp[lword].aval & ~insmask) | ((s.aval<<loffset) & insmask);
|
dp[lword].aval = (dp[lword].aval & ~insmask) | ((s.aval << loffset) & insmask);
|
||||||
dp[lword].bval = (dp[lword].bval & ~insmask) | ((s.bval<<loffset) & insmask);
|
dp[lword].bval = (dp[lword].bval & ~insmask) | ((s.bval << loffset) & insmask);
|
||||||
} else {
|
} else {
|
||||||
IData hinsmask = (VL_MASK_I(hoffset-0+1))<<0;
|
IData hinsmask = (VL_MASK_I(hoffset - 0 + 1)) << 0;
|
||||||
IData linsmask = (VL_MASK_I(31-loffset+1))<<loffset;
|
IData linsmask = (VL_MASK_I(31 - loffset + 1)) << loffset;
|
||||||
int nbitsonright = 32-loffset; // bits that end up in lword
|
int nbitsonright = 32 - loffset; // bits that end up in lword
|
||||||
dp[lword].aval = (dp[lword].aval & ~linsmask) | ((s.aval<<loffset) & linsmask);
|
dp[lword].aval = (dp[lword].aval & ~linsmask) | ((s.aval << loffset) & linsmask);
|
||||||
dp[lword].bval = (dp[lword].bval & ~linsmask) | ((s.bval<<loffset) & linsmask);
|
dp[lword].bval = (dp[lword].bval & ~linsmask) | ((s.bval << loffset) & linsmask);
|
||||||
dp[hword].aval = (dp[hword].aval & ~hinsmask) | ((s.aval>>nbitsonright) & hinsmask);
|
dp[hword].aval = (dp[hword].aval & ~hinsmask) | ((s.aval >> nbitsonright) & hinsmask);
|
||||||
dp[hword].bval = (dp[hword].bval & ~hinsmask) | ((s.bval>>nbitsonright) & hinsmask);
|
dp[hword].bval = (dp[hword].bval & ~hinsmask) | ((s.bval >> nbitsonright) & hinsmask);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -204,27 +194,14 @@ static inline const VerilatedDpiOpenVar* _vl_openhandle_varp(const svOpenArrayHa
|
||||||
//======================================================================
|
//======================================================================
|
||||||
// Open array querying functions
|
// 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"
|
||||||
|
|
@ -251,26 +228,29 @@ static void* _vl_sv_adjusted_datap(const VerilatedDpiOpenVar* varp,
|
||||||
varp->udims(), nargs);
|
varp->udims(), nargs);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
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,23 +278,25 @@ 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;
|
||||||
switch (varp->vltype()) {
|
switch (varp->vltype()) {
|
||||||
case VLVT_UINT8: d[0] = *(reinterpret_cast<CData*>(datap)); return;
|
case VLVT_UINT8: d[0] = *(reinterpret_cast<CData*>(datap)); return;
|
||||||
case VLVT_UINT16: d[0] = *(reinterpret_cast<SData*>(datap)); return;
|
case VLVT_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: {
|
||||||
WDataOutP wdatap = (reinterpret_cast<WDataOutP>(datap));
|
WDataOutP wdatap = (reinterpret_cast<WDataOutP>(datap));
|
||||||
for (int i=0; i<VL_WORDS_I(varp->packed().elements()); ++i) d[i] = wdatap[i];
|
for (int i = 0; i < VL_WORDS_I(varp->packed().elements()); ++i) d[i] = wdatap[i];
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
|
|
@ -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,19 +349,19 @@ 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;
|
||||||
switch (varp->vltype()) {
|
switch (varp->vltype()) {
|
||||||
case VLVT_UINT8: *(reinterpret_cast<CData*>(datap)) = s[0]; return;
|
case VLVT_UINT8: *(reinterpret_cast<CData*>(datap)) = s[0]; return;
|
||||||
case VLVT_UINT16: *(reinterpret_cast<SData*>(datap)) = s[0]; return;
|
case VLVT_UINT16: *(reinterpret_cast<SData*>(datap)) = s[0]; return;
|
||||||
case VLVT_UINT32: *(reinterpret_cast<IData*>(datap)) = s[0]; return;
|
case VLVT_UINT32: *(reinterpret_cast<IData*>(datap)) = s[0]; return;
|
||||||
case VLVT_UINT64: *(reinterpret_cast<QData*>(datap)) = _VL_SET_QII(s[1], s[0]); break;
|
case VLVT_UINT64: *(reinterpret_cast<QData*>(datap)) = _VL_SET_QII(s[1], s[0]); 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];
|
for (int i = 0; i < VL_WORDS_I(varp->packed().elements()); ++i) wdatap[i] = s[i];
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
|
|
@ -381,80 +377,82 @@ static void _vl_svPutLogicArrElemVecVal(const svOpenArrayHandle d, const svLogic
|
||||||
void* datap = _vl_sv_adjusted_datap(varp, nargs, indx1, indx2, indx3);
|
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: *(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;
|
||||||
}
|
}
|
||||||
if (VL_UNLIKELY(!datap)) return 0;
|
if (VL_UNLIKELY(!datap)) return 0;
|
||||||
switch (varp->vltype()) {
|
switch (varp->vltype()) {
|
||||||
case VLVT_UINT8: return (*(reinterpret_cast<CData*>(datap)) >> lsb) & 1;
|
case VLVT_UINT8: return (*(reinterpret_cast<CData*>(datap)) >> lsb) & 1;
|
||||||
case VLVT_UINT16: return (*(reinterpret_cast<SData*>(datap)) >> lsb) & 1;
|
case VLVT_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);
|
||||||
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;
|
||||||
}
|
}
|
||||||
if (VL_UNLIKELY(!datap)) return;
|
if (VL_UNLIKELY(!datap)) return;
|
||||||
switch (varp->vltype()) {
|
switch (varp->vltype()) {
|
||||||
case VLVT_UINT8: VL_ASSIGNBIT_II(-1, lsb, *(reinterpret_cast<CData*>(datap)), value); return;
|
case VLVT_UINT8: VL_ASSIGNBIT_II(-1, lsb, *(reinterpret_cast<CData*>(datap)), value); return;
|
||||||
case VLVT_UINT16: VL_ASSIGNBIT_II(-1, lsb, *(reinterpret_cast<SData*>(datap)), value); return;
|
case VLVT_UINT16: VL_ASSIGNBIT_II(-1, lsb, *(reinterpret_cast<SData*>(datap)), value); return;
|
||||||
case VLVT_UINT32: VL_ASSIGNBIT_II(-1, lsb, *(reinterpret_cast<IData*>(datap)), value); return;
|
case VLVT_UINT32: VL_ASSIGNBIT_II(-1, lsb, *(reinterpret_cast<IData*>(datap)), value); return;
|
||||||
case VLVT_UINT64: VL_ASSIGNBIT_QI(-1, lsb, *(reinterpret_cast<QData*>(datap)), value); return;
|
case VLVT_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());
|
||||||
}
|
}
|
||||||
|
|
@ -746,16 +819,19 @@ svScope svGetScopeFromName(const char* scopeName) {
|
||||||
}
|
}
|
||||||
|
|
||||||
int svPutUserData(const svScope scope, void* userKey, void* userData) {
|
int svPutUserData(const svScope scope, void* userKey, void* userData) {
|
||||||
VerilatedImp::userInsert(scope,userKey,userData);
|
VerilatedImp::userInsert(scope, userKey, userData);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void* svGetUserData(const svScope scope, void* userKey) {
|
void* svGetUserData(const svScope scope, void* userKey) {
|
||||||
return VerilatedImp::userFind(scope,userKey);
|
return VerilatedImp::userFind(scope, 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;
|
||||||
|
|
||||||
|
|
@ -47,9 +49,11 @@ class VerilatedMsg {
|
||||||
public:
|
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 {
|
||||||
|
|
@ -176,28 +184,33 @@ 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)
|
||||||
bool m_argVecLoaded VL_GUARDED_BY(m_argMutex); ///< Ever loaded argument list
|
ArgVec m_argVec VL_GUARDED_BY(m_argMutex);
|
||||||
|
bool m_argVecLoaded VL_GUARDED_BY(m_argMutex); ///< Ever loaded argument list
|
||||||
|
|
||||||
VerilatedMutex m_userMapMutex; ///< Protect m_userMap
|
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>
|
||||||
int m_exportNext VL_GUARDED_BY(m_exportMutex); ///< Next export funcnum
|
ExportNameMap m_exportMap VL_GUARDED_BY(m_exportMutex);
|
||||||
|
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 {
|
||||||
|
|
@ -278,10 +297,13 @@ private:
|
||||||
static void userDump() VL_MT_SAFE {
|
static void userDump() VL_MT_SAFE {
|
||||||
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -298,9 +320,9 @@ public: // But only for verilated*.cpp
|
||||||
static inline const VerilatedScope* scopeFind(const char* namep) VL_MT_SAFE {
|
static inline const VerilatedScope* scopeFind(const char* namep) VL_MT_SAFE {
|
||||||
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
|
||||||
|
|
@ -360,8 +382,8 @@ public: // But only for verilated*.cpp
|
||||||
VerilatedLockGuard lock(s_s.m_exportMutex);
|
VerilatedLockGuard lock(s_s.m_exportMutex);
|
||||||
ExportNameMap::const_iterator it = s_s.m_exportMap.find(namep);
|
ExportNameMap::const_iterator it = s_s.m_exportMap.find(namep);
|
||||||
if (VL_LIKELY(it != s_s.m_exportMap.end())) return it->second;
|
if (VL_LIKELY(it != s_s.m_exportMap.end())) return it->second;
|
||||||
std::string msg = (std::string("%Error: Testbench C called ")+namep
|
std::string msg = (std::string("%Error: Testbench C called ") + namep
|
||||||
+" but no such DPI export function name exists in ANY model");
|
+ " but no such DPI export function name exists in ANY model");
|
||||||
VL_FATAL_MT("unknown", 0, "", msg.c_str());
|
VL_FATAL_MT("unknown", 0, "", msg.c_str());
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
@ -377,9 +399,12 @@ public: // But only for verilated*.cpp
|
||||||
static void exportsDump() VL_MT_SAFE {
|
static void exportsDump() VL_MT_SAFE {
|
||||||
VerilatedLockGuard lock(s_s.m_exportMutex);
|
VerilatedLockGuard lock(s_s.m_exportMutex);
|
||||||
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -395,12 +420,15 @@ public: // But only for verilated*.cpp
|
||||||
if (s_s.m_fdFree.empty()) {
|
if (s_s.m_fdFree.empty()) {
|
||||||
// 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
|
||||||
}
|
}
|
||||||
static void fdDelete(IData fdi) VL_MT_SAFE {
|
static void fdDelete(IData fdi) VL_MT_SAFE {
|
||||||
IData idx = VL_MASK_I(31) & fdi;
|
IData idx = VL_MASK_I(31) & fdi;
|
||||||
|
|
|
||||||
|
|
@ -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()) {
|
||||||
|
|
@ -176,14 +156,14 @@ public:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// MEMBERS
|
// MEMBERS
|
||||||
size_t m_numElements; // Number of entries present.
|
size_t m_numElements; // Number of entries present.
|
||||||
size_t m_log2Buckets; // Log-base-2 of the number of buckets.
|
size_t m_log2Buckets; // Log-base-2 of the number of buckets.
|
||||||
mutable Bucket* m_bucketsp; // Hash table buckets. May be NULL;
|
mutable Bucket* m_bucketsp; // Hash table buckets. May be NULL;
|
||||||
// // we'll allocate it on the fly when
|
// // we'll allocate it on the fly when
|
||||||
// // the first entries are created.
|
// // the first entries are created.
|
||||||
Bucket m_emptyBucket; // A fake bucket, used to construct end().
|
Bucket m_emptyBucket; // A fake bucket, used to construct end().
|
||||||
T_Hash m_hash; // Hash function provider.
|
T_Hash m_hash; // Hash function provider.
|
||||||
T_Equal m_equal; // Equal-to function provider.
|
T_Equal m_equal; // Equal-to function provider.
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// CONSTRUCTORS
|
// CONSTRUCTORS
|
||||||
|
|
@ -202,26 +182,20 @@ 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_unordered_set() { VL_DO_DANGLING(delete[] m_bucketsp, m_bucketsp); }
|
||||||
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) {
|
||||||
clear();
|
clear();
|
||||||
delete [] m_bucketsp;
|
delete[] m_bucketsp;
|
||||||
m_numElements = other.m_numElements;
|
m_numElements = other.m_numElements;
|
||||||
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:
|
||||||
|
|
|
||||||
|
|
@ -25,21 +25,22 @@
|
||||||
//======================================================================
|
//======================================================================
|
||||||
|
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
#if (SYSTEMC_VERSION>=20050714)
|
#if (SYSTEMC_VERSION >= 20050714)
|
||||||
// SystemC 2.1.v1
|
// SystemC 2.1.v1
|
||||||
// cppcheck-suppress unusedFunction
|
// cppcheck-suppress unusedFunction
|
||||||
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) \
|
||||||
void VerilatedVcdSc::trace( const tp& object, const std::string& name, int width ) {}
|
void VerilatedVcdSc::trace(const tp& object, const std::string& name, int width) {}
|
||||||
|
|
||||||
#if (SYSTEMC_VERSION>=20171012)
|
# if (SYSTEMC_VERSION >= 20171012)
|
||||||
DECL_TRACE_METHOD_A( sc_event )
|
DECL_TRACE_METHOD_A( sc_event )
|
||||||
DECL_TRACE_METHOD_A( sc_time )
|
DECL_TRACE_METHOD_A( sc_time )
|
||||||
#endif
|
# endif
|
||||||
|
|
||||||
DECL_TRACE_METHOD_A( bool )
|
DECL_TRACE_METHOD_A( bool )
|
||||||
DECL_TRACE_METHOD_A( sc_dt::sc_bit )
|
DECL_TRACE_METHOD_A( sc_dt::sc_bit )
|
||||||
|
|
@ -49,9 +50,9 @@ void VerilatedVcdSc::trace(const unsigned int &, const std::string &, const char
|
||||||
DECL_TRACE_METHOD_B( unsigned short )
|
DECL_TRACE_METHOD_B( unsigned short )
|
||||||
DECL_TRACE_METHOD_B( unsigned int )
|
DECL_TRACE_METHOD_B( unsigned int )
|
||||||
DECL_TRACE_METHOD_B( unsigned long )
|
DECL_TRACE_METHOD_B( unsigned long )
|
||||||
#ifdef SYSTEMC_64BIT_PATCHES
|
# ifdef SYSTEMC_64BIT_PATCHES
|
||||||
DECL_TRACE_METHOD_B( unsigned long long)
|
DECL_TRACE_METHOD_B( unsigned long long)
|
||||||
#endif
|
# endif
|
||||||
DECL_TRACE_METHOD_B( char )
|
DECL_TRACE_METHOD_B( char )
|
||||||
DECL_TRACE_METHOD_B( short )
|
DECL_TRACE_METHOD_B( short )
|
||||||
DECL_TRACE_METHOD_B( int )
|
DECL_TRACE_METHOD_B( int )
|
||||||
|
|
@ -73,19 +74,21 @@ void VerilatedVcdSc::trace(const unsigned int &, const std::string &, const char
|
||||||
|
|
||||||
DECL_TRACE_METHOD_A( sc_dt::sc_bv_base )
|
DECL_TRACE_METHOD_A( sc_dt::sc_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
|
||||||
// cppcheck-suppress unusedFunction
|
// cppcheck-suppress unusedFunction
|
||||||
void VerilatedVcdSc::write_comment(const sc_string &) {}
|
void VerilatedVcdSc::write_comment(const sc_string&) {}
|
||||||
void VerilatedVcdSc::trace(const unsigned int&, const sc_string&, const char**) {}
|
void VerilatedVcdSc::trace(const unsigned int&, const sc_string&, const char**) {}
|
||||||
|
|
||||||
#define DECL_TRACE_METHOD_A(tp) \
|
#define DECL_TRACE_METHOD_A(tp) \
|
||||||
void VerilatedVcdSc::trace( const tp& object, const sc_string& name ) {}
|
void VerilatedVcdSc::trace(const tp& object, const sc_string& name) {}
|
||||||
#define DECL_TRACE_METHOD_B(tp) \
|
#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 )
|
||||||
|
|
@ -96,7 +99,7 @@ void VerilatedVcdSc::trace(const unsigned int&, const sc_string&, const char**)
|
||||||
#ifdef SYSTEMC_64BIT_PATCHES
|
#ifdef SYSTEMC_64BIT_PATCHES
|
||||||
DECL_TRACE_METHOD_B( unsigned long long)
|
DECL_TRACE_METHOD_B( unsigned long long)
|
||||||
#endif
|
#endif
|
||||||
#if (SYSTEMC_VERSION>20041000)
|
#if (SYSTEMC_VERSION > 20041000)
|
||||||
DECL_TRACE_METHOD_B( unsigned long long)
|
DECL_TRACE_METHOD_B( unsigned long long)
|
||||||
DECL_TRACE_METHOD_B( long long)
|
DECL_TRACE_METHOD_B( long long)
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -116,19 +119,21 @@ void VerilatedVcdSc::trace(const unsigned int&, const sc_string&, const char**)
|
||||||
DECL_TRACE_METHOD_A( sc_fxnum_fast )
|
DECL_TRACE_METHOD_A( sc_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
|
||||||
// cppcheck-suppress unusedFunction
|
// cppcheck-suppress unusedFunction
|
||||||
void VerilatedVcdSc::write_comment(const sc_string &) {}
|
void VerilatedVcdSc::write_comment(const sc_string&) {}
|
||||||
void VerilatedVcdSc::trace(const unsigned int&, const sc_string&, const char**) {}
|
void VerilatedVcdSc::trace(const unsigned int&, const sc_string&, const char**) {}
|
||||||
|
|
||||||
#define DECL_TRACE_METHOD_A(tp) \
|
#define DECL_TRACE_METHOD_A(tp) \
|
||||||
void VerilatedVcdSc::trace( const tp& object, const sc_string& name ) {}
|
void VerilatedVcdSc::trace(const tp& object, const sc_string& name) {}
|
||||||
#define DECL_TRACE_METHOD_B(tp) \
|
#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,44 +31,42 @@
|
||||||
/// 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);
|
||||||
# if (SYSTEMC_VERSION>=20060505)
|
#if (SYSTEMC_VERSION >= 20060505)
|
||||||
// We want to avoid a depreciated warning, but still be back compatible.
|
// We want to avoid a depreciated warning, but still be back compatible.
|
||||||
// Turning off the message just for this still results in an
|
// Turning off the message just for this still results in an
|
||||||
// annoying "to turn off" message.
|
// annoying "to turn off" message.
|
||||||
sc_time t1sec(1,SC_SEC);
|
sc_time t1sec(1, SC_SEC);
|
||||||
if (t1sec.to_default_time_units()!=0) {
|
if (t1sec.to_default_time_units() != 0) {
|
||||||
sc_time tunits(1.0/t1sec.to_default_time_units(),SC_SEC);
|
sc_time tunits(1.0 / t1sec.to_default_time_units(), SC_SEC);
|
||||||
spTrace()->set_time_unit(tunits.to_string());
|
spTrace()->set_time_unit(tunits.to_string());
|
||||||
}
|
}
|
||||||
spTrace()->set_time_resolution(sc_get_time_resolution().to_string());
|
spTrace()->set_time_resolution(sc_get_time_resolution().to_string());
|
||||||
# elif (SYSTEMC_VERSION>20011000)
|
#elif (SYSTEMC_VERSION > 20011000)
|
||||||
// To confuse matters 2.1.beta returns a char* here, while 2.1.v1 returns a std::string
|
// To confuse matters 2.1.beta returns a char* here, while 2.1.v1 returns a std::string
|
||||||
// we allow both flavors with overloaded set_time_* functions.
|
// we allow both flavors with overloaded set_time_* functions.
|
||||||
spTrace()->set_time_unit(sc_get_default_time_unit().to_string());
|
spTrace()->set_time_unit(sc_get_default_time_unit().to_string());
|
||||||
spTrace()->set_time_resolution(sc_get_time_resolution().to_string());
|
spTrace()->set_time_resolution(sc_get_time_resolution().to_string());
|
||||||
# endif
|
#endif
|
||||||
}
|
}
|
||||||
virtual ~VerilatedVcdSc() { close(); }
|
virtual ~VerilatedVcdSc() { close(); }
|
||||||
|
|
||||||
// METHODS
|
// METHODS
|
||||||
/// Called by SystemC simulate()
|
/// Called by SystemC simulate()
|
||||||
virtual void cycle(bool delta_cycle) {
|
virtual void cycle(bool delta_cycle) {
|
||||||
# if (SYSTEMC_VERSION>20011000)
|
#if (SYSTEMC_VERSION > 20011000)
|
||||||
if (!delta_cycle) { this->dump(sc_time_stamp().to_double()); }
|
if (!delta_cycle) { this->dump(sc_time_stamp().to_double()); }
|
||||||
# else
|
#else
|
||||||
// VCD files must have integer timestamps, so we write all times in
|
// VCD files must have integer timestamps, so we write all times in
|
||||||
// increments of time_resolution
|
// increments of time_resolution
|
||||||
if (!delta_cycle) { this->dump(sc_time_stamp().to_double()); }
|
if (!delta_cycle) { this->dump(sc_time_stamp().to_double()); }
|
||||||
# endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
@ -78,26 +76,26 @@ private:
|
||||||
// Cadence Incisive has these as abstract functions so we must create them
|
// Cadence Incisive has these as abstract functions so we must create them
|
||||||
virtual void set_time_unit(int exponent10_seconds) {} // deprecated
|
virtual void set_time_unit(int exponent10_seconds) {} // deprecated
|
||||||
#endif
|
#endif
|
||||||
#if defined(NC_SYSTEMC) || (SYSTEMC_VERSION>=20111100)
|
#if defined(NC_SYSTEMC) || (SYSTEMC_VERSION >= 20111100)
|
||||||
virtual void set_time_unit(double v, sc_time_unit tu) {}
|
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**);
|
||||||
|
|
||||||
#if (SYSTEMC_VERSION>=20171012)
|
// Formatting matches that of sc_trace.h
|
||||||
|
# if (SYSTEMC_VERSION >= 20171012)
|
||||||
DECL_TRACE_METHOD_A( sc_event )
|
DECL_TRACE_METHOD_A( sc_event )
|
||||||
DECL_TRACE_METHOD_A( sc_time )
|
DECL_TRACE_METHOD_A( sc_time )
|
||||||
#endif
|
# endif
|
||||||
|
|
||||||
DECL_TRACE_METHOD_A( bool )
|
DECL_TRACE_METHOD_A( bool )
|
||||||
DECL_TRACE_METHOD_A( sc_dt::sc_bit )
|
DECL_TRACE_METHOD_A( sc_dt::sc_bit )
|
||||||
|
|
@ -107,9 +105,9 @@ private:
|
||||||
DECL_TRACE_METHOD_B( unsigned short )
|
DECL_TRACE_METHOD_B( unsigned short )
|
||||||
DECL_TRACE_METHOD_B( unsigned int )
|
DECL_TRACE_METHOD_B( unsigned int )
|
||||||
DECL_TRACE_METHOD_B( unsigned long )
|
DECL_TRACE_METHOD_B( unsigned long )
|
||||||
#ifdef SYSTEMC_64BIT_PATCHES
|
# ifdef SYSTEMC_64BIT_PATCHES
|
||||||
DECL_TRACE_METHOD_B( unsigned long long)
|
DECL_TRACE_METHOD_B( unsigned long long)
|
||||||
#endif
|
# endif
|
||||||
DECL_TRACE_METHOD_B( char )
|
DECL_TRACE_METHOD_B( char )
|
||||||
DECL_TRACE_METHOD_B( short )
|
DECL_TRACE_METHOD_B( short )
|
||||||
DECL_TRACE_METHOD_B( int )
|
DECL_TRACE_METHOD_B( int )
|
||||||
|
|
@ -131,12 +129,13 @@ private:
|
||||||
|
|
||||||
DECL_TRACE_METHOD_A( sc_dt::sc_bv_base )
|
DECL_TRACE_METHOD_A( sc_dt::sc_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);
|
||||||
|
|
||||||
|
|
@ -152,13 +151,13 @@ private:
|
||||||
DECL_TRACE_METHOD_B( unsigned short )
|
DECL_TRACE_METHOD_B( unsigned short )
|
||||||
DECL_TRACE_METHOD_B( unsigned int )
|
DECL_TRACE_METHOD_B( unsigned int )
|
||||||
DECL_TRACE_METHOD_B( unsigned long )
|
DECL_TRACE_METHOD_B( unsigned long )
|
||||||
#ifdef SYSTEMC_64BIT_PATCHES
|
# ifdef SYSTEMC_64BIT_PATCHES
|
||||||
DECL_TRACE_METHOD_B( unsigned long long)
|
DECL_TRACE_METHOD_B( unsigned long long)
|
||||||
#endif
|
# endif
|
||||||
#if (SYSTEMC_VERSION>20041000)
|
# if (SYSTEMC_VERSION > 20041000)
|
||||||
DECL_TRACE_METHOD_B( unsigned long long)
|
DECL_TRACE_METHOD_B( unsigned long long)
|
||||||
DECL_TRACE_METHOD_B( long long)
|
DECL_TRACE_METHOD_B( long long)
|
||||||
#endif
|
# endif
|
||||||
DECL_TRACE_METHOD_B( char )
|
DECL_TRACE_METHOD_B( char )
|
||||||
DECL_TRACE_METHOD_B( short )
|
DECL_TRACE_METHOD_B( short )
|
||||||
DECL_TRACE_METHOD_B( int )
|
DECL_TRACE_METHOD_B( int )
|
||||||
|
|
@ -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,9 +213,10 @@ 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
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // Guard
|
#endif // Guard
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load Diff
|
|
@ -25,95 +25,97 @@
|
||||||
#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
|
||||||
|
|
||||||
#ifdef __GNUC__
|
#ifdef __GNUC__
|
||||||
# define VL_ATTR_ALIGNED(alignment) __attribute__ ((aligned (alignment)))
|
# define VL_ATTR_ALIGNED(alignment) __attribute__((aligned(alignment)))
|
||||||
# define VL_ATTR_ALWINLINE __attribute__ ((always_inline))
|
# define VL_ATTR_ALWINLINE __attribute__((always_inline))
|
||||||
# define VL_ATTR_COLD __attribute__ ((cold))
|
# define VL_ATTR_COLD __attribute__((cold))
|
||||||
# define VL_ATTR_HOT __attribute__ ((hot))
|
# define VL_ATTR_HOT __attribute__((hot))
|
||||||
# define VL_ATTR_NORETURN __attribute__ ((noreturn))
|
# define VL_ATTR_NORETURN __attribute__((noreturn))
|
||||||
# define VL_ATTR_PRINTF(fmtArgNum) __attribute__ ((format (printf, (fmtArgNum), (fmtArgNum)+1)))
|
# define VL_ATTR_PRINTF(fmtArgNum) __attribute__((format(printf, (fmtArgNum), (fmtArgNum) + 1)))
|
||||||
# define VL_ATTR_PURE __attribute__ ((pure))
|
# define VL_ATTR_PURE __attribute__((pure))
|
||||||
# define VL_ATTR_UNUSED __attribute__ ((unused))
|
# define VL_ATTR_UNUSED __attribute__((unused))
|
||||||
# define VL_FUNC __func__
|
# define VL_FUNC __func__
|
||||||
# if defined(__clang__) && defined(VL_THREADED)
|
# if defined(__clang__) && defined(VL_THREADED)
|
||||||
# define VL_ACQUIRE(...) __attribute__ ((acquire_capability(__VA_ARGS__)))
|
# define VL_ACQUIRE(...) __attribute__((acquire_capability(__VA_ARGS__)))
|
||||||
# define VL_ACQUIRE_SHARED(...) __attribute__ ((acquire_shared_capability(__VA_ARGS__)))
|
# define VL_ACQUIRE_SHARED(...) __attribute__((acquire_shared_capability(__VA_ARGS__)))
|
||||||
# define VL_RELEASE(...) __attribute__ ((release_capability(__VA_ARGS__)))
|
# define VL_RELEASE(...) __attribute__((release_capability(__VA_ARGS__)))
|
||||||
# define VL_RELEASE_SHARED(...) __attribute__ ((release_shared_capability(__VA_ARGS__)))
|
# define VL_RELEASE_SHARED(...) __attribute__((release_shared_capability(__VA_ARGS__)))
|
||||||
# define VL_TRY_ACQUIRE(...) __attribute__ ((try_acquire_capability(__VA_ARGS__)))
|
# define VL_TRY_ACQUIRE(...) __attribute__((try_acquire_capability(__VA_ARGS__)))
|
||||||
# define VL_TRY_ACQUIRE_SHARED(...) __attribute__ ((try_acquire_shared_capability(__VA_ARGS__)))
|
# define VL_TRY_ACQUIRE_SHARED(...) __attribute__((try_acquire_shared_capability(__VA_ARGS__)))
|
||||||
# define VL_CAPABILITY(x) __attribute__ ((capability(x)))
|
# define VL_CAPABILITY(x) __attribute__((capability(x)))
|
||||||
# define VL_REQUIRES(x) __attribute__ ((requires_capability(x)))
|
# define VL_REQUIRES(x) __attribute__((requires_capability(x)))
|
||||||
# define VL_GUARDED_BY(x) __attribute__ ((guarded_by(x)))
|
# define VL_GUARDED_BY(x) __attribute__((guarded_by(x)))
|
||||||
# define VL_EXCLUDES(x) __attribute__ ((locks_excluded(x)))
|
# define VL_EXCLUDES(x) __attribute__((locks_excluded(x)))
|
||||||
# define VL_SCOPED_CAPABILITY __attribute__ ((scoped_lockable))
|
# define VL_SCOPED_CAPABILITY __attribute__((scoped_lockable))
|
||||||
# endif
|
# endif
|
||||||
# define VL_LIKELY(x) __builtin_expect(!!(x), 1)
|
# define VL_LIKELY(x) __builtin_expect(!!(x), 1)
|
||||||
# define VL_UNLIKELY(x) __builtin_expect(!!(x), 0)
|
# define VL_UNLIKELY(x) __builtin_expect(!!(x), 0)
|
||||||
# define VL_UNREACHABLE __builtin_unreachable();
|
# define VL_UNREACHABLE __builtin_unreachable();
|
||||||
# define VL_PREFETCH_RD(p) __builtin_prefetch((p),0)
|
# define VL_PREFETCH_RD(p) __builtin_prefetch((p), 0)
|
||||||
# define VL_PREFETCH_RW(p) __builtin_prefetch((p),1)
|
# define VL_PREFETCH_RW(p) __builtin_prefetch((p), 1)
|
||||||
#elif defined(_MSC_VER)
|
#elif defined(_MSC_VER)
|
||||||
# define VL_FUNC __FUNCTION__
|
# define VL_FUNC __FUNCTION__
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Defaults for unsupported compiler features
|
// Defaults for unsupported compiler features
|
||||||
#ifndef VL_ATTR_ALIGNED
|
#ifndef VL_ATTR_ALIGNED
|
||||||
# define VL_ATTR_ALIGNED(alignment) ///< Align structure to specified byte alignment
|
# define VL_ATTR_ALIGNED(alignment) ///< Align structure to specified byte alignment
|
||||||
#endif
|
#endif
|
||||||
#ifndef VL_ATTR_ALWINLINE
|
#ifndef VL_ATTR_ALWINLINE
|
||||||
# define VL_ATTR_ALWINLINE ///< Inline, even when not optimizing
|
# define VL_ATTR_ALWINLINE ///< Inline, even when not optimizing
|
||||||
#endif
|
#endif
|
||||||
#ifndef VL_ATTR_COLD
|
#ifndef VL_ATTR_COLD
|
||||||
# define VL_ATTR_COLD ///< Function is rarely executed
|
# define VL_ATTR_COLD ///< Function is rarely executed
|
||||||
#endif
|
#endif
|
||||||
#ifndef VL_ATTR_HOT
|
#ifndef VL_ATTR_HOT
|
||||||
# define VL_ATTR_HOT ///< Function is highly executed
|
# define VL_ATTR_HOT ///< Function is highly executed
|
||||||
#endif
|
#endif
|
||||||
#ifndef VL_ATTR_NORETURN
|
#ifndef VL_ATTR_NORETURN
|
||||||
# define VL_ATTR_NORETURN ///< Function does not ever return
|
# define VL_ATTR_NORETURN ///< Function does not ever return
|
||||||
#endif
|
#endif
|
||||||
#ifndef VL_ATTR_PRINTF
|
#ifndef VL_ATTR_PRINTF
|
||||||
# define VL_ATTR_PRINTF(fmtArgNum) ///< Function with printf format checking
|
# define VL_ATTR_PRINTF(fmtArgNum) ///< Function with printf format checking
|
||||||
#endif
|
#endif
|
||||||
#ifndef VL_ATTR_PURE
|
#ifndef VL_ATTR_PURE
|
||||||
# define VL_ATTR_PURE ///< Function is pure (and thus also VL_MT_SAFE)
|
# define VL_ATTR_PURE ///< Function is pure (and thus also VL_MT_SAFE)
|
||||||
#endif
|
#endif
|
||||||
#ifndef VL_ATTR_UNUSED
|
#ifndef VL_ATTR_UNUSED
|
||||||
# define VL_ATTR_UNUSED ///< Function that may be never used
|
# define VL_ATTR_UNUSED ///< Function that may be never used
|
||||||
#endif
|
#endif
|
||||||
#ifndef VL_FUNC
|
#ifndef VL_FUNC
|
||||||
# define VL_FUNC "__func__" ///< Name of current function for error macros
|
# define VL_FUNC "__func__" ///< Name of current function for error macros
|
||||||
#endif
|
#endif
|
||||||
#ifndef VL_CAPABILITY
|
#ifndef VL_CAPABILITY
|
||||||
# define VL_ACQUIRE(...) ///< Function requires a capability/lock (-fthread-safety)
|
# define VL_ACQUIRE(...) ///< Function requires a capability/lock (-fthread-safety)
|
||||||
# define VL_ACQUIRE_SHARED(...) ///< Function aquires a shared capability/lock (-fthread-safety)
|
# define VL_ACQUIRE_SHARED(...) ///< Function aquires a shared capability/lock (-fthread-safety)
|
||||||
# define VL_RELEASE(...) ///< Function releases a capability/lock (-fthread-safety)
|
# define VL_RELEASE(...) ///< Function releases a capability/lock (-fthread-safety)
|
||||||
# define VL_RELEASE_SHARED(...) ///< Function releases a shared capability/lock (-fthread-safety)
|
# define VL_RELEASE_SHARED(...) ///< Function releases a shared capability/lock (-fthread-safety)
|
||||||
# define VL_TRY_ACQUIRE(...) ///< Function returns bool if aquired a capability (-fthread-safety)
|
# define VL_TRY_ACQUIRE(...) ///< Function returns bool if aquired a capability (-fthread-safety)
|
||||||
# define VL_TRY_ACQUIRE_SHARED(...) ///< Function returns bool if aquired a shared capability (-fthread-safety)
|
# define VL_TRY_ACQUIRE_SHARED(...) ///< Function returns bool if aquired 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)
|
||||||
# define VL_GUARDED_BY(x) ///< Name of mutex protecting this variable (-fthread-safety)
|
# define VL_GUARDED_BY(x) ///< Name of mutex protecting this variable (-fthread-safety)
|
||||||
# define VL_SCOPED_CAPABILITY ///< Scoped threaded capability/lock (-fthread-safety)
|
# define VL_SCOPED_CAPABILITY ///< Scoped threaded capability/lock (-fthread-safety)
|
||||||
#endif
|
#endif
|
||||||
#ifndef VL_LIKELY
|
#ifndef VL_LIKELY
|
||||||
# define VL_LIKELY(x) (!!(x)) ///< Boolean expression more often true than false
|
# define VL_LIKELY(x) (!!(x)) ///< Boolean expression more often true than false
|
||||||
# define VL_UNLIKELY(x) (!!(x)) ///< Boolean expression more often false than true
|
# define VL_UNLIKELY(x) (!!(x)) ///< Boolean expression more often false than true
|
||||||
#endif
|
#endif
|
||||||
#define VL_UNCOVERABLE(x) VL_UNLIKELY(x) ///< Boolean expression never hit by users (no coverage)
|
# define VL_UNCOVERABLE(x) VL_UNLIKELY(x) ///< Boolean expression never hit by users (no coverage)
|
||||||
#ifndef VL_UNREACHABLE
|
#ifndef VL_UNREACHABLE
|
||||||
# define VL_UNREACHABLE ///< Point that may never be reached
|
# define VL_UNREACHABLE ///< Point that may never be reached
|
||||||
#endif
|
#endif
|
||||||
#ifndef VL_PREFETCH_RD
|
#ifndef VL_PREFETCH_RD
|
||||||
# define VL_PREFETCH_RD(p) ///< Prefetch data with read intent
|
# define VL_PREFETCH_RD(p) ///< Prefetch data with read intent
|
||||||
#endif
|
#endif
|
||||||
#ifndef VL_PREFETCH_RW
|
#ifndef VL_PREFETCH_RW
|
||||||
# define VL_PREFETCH_RW(p) ///< Prefetch data with read/write intent
|
# define VL_PREFETCH_RW(p) ///< Prefetch data with read/write intent
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef VL_THREADED
|
#ifdef VL_THREADED
|
||||||
|
|
@ -121,31 +123,34 @@
|
||||||
# define VL_THREAD_LOCAL thread_local
|
# define VL_THREAD_LOCAL thread_local
|
||||||
# elif defined(__GNUC__)
|
# elif defined(__GNUC__)
|
||||||
# if (__cplusplus < 201103L) && !defined(VL_THREADED_NO_C11_WARNING)
|
# if (__cplusplus < 201103L) && !defined(VL_THREADED_NO_C11_WARNING)
|
||||||
# error "VL_THREADED/--threads support requires C++-11 or newer only; use newer compiler"
|
# error "VL_THREADED/--threads support requires C++-11 or newer only; use newer compiler"
|
||||||
# endif
|
# endif
|
||||||
# else
|
# else
|
||||||
# error "Unsupported compiler for VL_THREADED: No thread-local declarator"
|
# error "Unsupported compiler for VL_THREADED: No thread-local declarator"
|
||||||
# endif
|
# endif
|
||||||
# define VL_THREAD_LOCAL thread_local ///< Use new C++ static local thread
|
# define VL_THREAD_LOCAL thread_local ///< Use new C++ static local thread
|
||||||
#else
|
#else
|
||||||
# define VL_THREAD_LOCAL ///< Use new C++ static local thread
|
# define VL_THREAD_LOCAL ///< Use new C++ static local thread
|
||||||
#endif
|
#endif
|
||||||
#define VL_THREAD ///< Deprecated
|
|
||||||
#define VL_STATIC_OR_THREAD static ///< Deprecated
|
#define VL_THREAD ///< Deprecated
|
||||||
|
#define VL_STATIC_OR_THREAD static ///< Deprecated
|
||||||
|
|
||||||
#define VL_PURE ///< Comment tag that Function is pure (and thus also VL_MT_SAFE)
|
#define VL_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
|
||||||
// Was "(c##ui64)". C++11 has standardized on ULL, and MSVC now supports this.
|
// Was "(c##ui64)". C++11 has standardized on ULL, and MSVC now supports this.
|
||||||
// We propose to no longer require using this macro no sooner than June 2020.
|
// We propose to no longer require using this macro no sooner than June 2020.
|
||||||
// File an issue ASAP if this breaks anything.
|
// File an issue ASAP if this breaks anything.
|
||||||
#else
|
#else
|
||||||
# define VL_ULL(c) (c##ULL) ///< Add appropriate suffix to 64-bit constant
|
# define VL_ULL(c) (c##ULL) ///< Add appropriate suffix to 64-bit constant
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// This is not necessarily the same as #UL, depending on what the IData typedef is.
|
// This is not necessarily the same as #UL, depending on what the IData typedef is.
|
||||||
|
|
@ -249,47 +254,47 @@
|
||||||
# include <stdint.h>
|
# include <stdint.h>
|
||||||
# include <sys/types.h> // __WORDSIZE
|
# include <sys/types.h> // __WORDSIZE
|
||||||
# include <unistd.h> // ssize_t
|
# include <unistd.h> // ssize_t
|
||||||
typedef unsigned char uint8_t; ///< 8-bit unsigned type (backward compatibility)
|
typedef unsigned char uint8_t; ///< 8-bit unsigned type (backward compatibility)
|
||||||
typedef unsigned short int uint16_t; ///< 16-bit unsigned type (backward compatibility)
|
typedef unsigned short int uint16_t; ///< 16-bit unsigned type (backward compatibility)
|
||||||
typedef char vlsint8_t; ///< 8-bit signed type
|
typedef char vlsint8_t; ///< 8-bit signed type
|
||||||
typedef unsigned char vluint8_t; ///< 8-bit unsigned type
|
typedef unsigned char vluint8_t; ///< 8-bit unsigned type
|
||||||
typedef short int vlsint16_t; ///< 16-bit signed type
|
typedef short int vlsint16_t; ///< 16-bit signed type
|
||||||
typedef unsigned short int vluint16_t; ///< 16-bit unsigned type
|
typedef unsigned short int vluint16_t; ///< 16-bit unsigned type
|
||||||
# if defined(__uint32_t_defined) || defined(___int32_t_defined) // Newer Cygwin uint32_t in stdint.h as an unsigned int
|
# if defined(__uint32_t_defined) || defined(___int32_t_defined) // Newer Cygwin uint32_t in stdint.h as an unsigned int
|
||||||
typedef int32_t vlsint32_t; ///< 32-bit signed type
|
typedef int32_t vlsint32_t; ///< 32-bit signed type
|
||||||
typedef uint32_t vluint32_t; ///< 32-bit unsigned type
|
typedef uint32_t vluint32_t; ///< 32-bit unsigned type
|
||||||
# else // Older Cygwin has long==uint32_t
|
# else // Older Cygwin has long==uint32_t
|
||||||
typedef unsigned long uint32_t; ///< 32-bit unsigned type (backward compatibility)
|
typedef unsigned long uint32_t; ///< 32-bit unsigned type (backward compatibility)
|
||||||
typedef long vlsint32_t; ///< 32-bit signed type
|
typedef long vlsint32_t; ///< 32-bit signed type
|
||||||
typedef unsigned long vluint32_t; ///< 32-bit unsigned type
|
typedef unsigned long vluint32_t; ///< 32-bit unsigned type
|
||||||
# endif
|
# endif
|
||||||
# if defined(__WORDSIZE) && (__WORDSIZE == 64)
|
# if defined(__WORDSIZE) && (__WORDSIZE == 64)
|
||||||
typedef long vlsint64_t; ///< 64-bit signed type
|
typedef long vlsint64_t; ///< 64-bit signed type
|
||||||
typedef unsigned long vluint64_t; ///< 64-bit unsigned type
|
typedef unsigned long vluint64_t; ///< 64-bit unsigned type
|
||||||
# else
|
# else
|
||||||
typedef long long vlsint64_t; ///< 64-bit signed type
|
typedef long long vlsint64_t; ///< 64-bit signed type
|
||||||
typedef unsigned long long vluint64_t; ///< 64-bit unsigned type
|
typedef unsigned long long vluint64_t; ///< 64-bit unsigned type
|
||||||
# endif
|
# endif
|
||||||
|
|
||||||
#elif defined(_WIN32) && defined(_MSC_VER)
|
#elif defined(_WIN32) && defined(_MSC_VER)
|
||||||
|
|
||||||
typedef unsigned __int8 uint8_t; ///< 8-bit unsigned type (backward compatibility)
|
typedef unsigned __int8 uint8_t; ///< 8-bit unsigned type (backward compatibility)
|
||||||
typedef unsigned __int16 uint16_t; ///< 16-bit unsigned type (backward compatibility)
|
typedef unsigned __int16 uint16_t; ///< 16-bit unsigned type (backward compatibility)
|
||||||
typedef unsigned __int32 uint32_t; ///< 32-bit unsigned type (backward compatibility)
|
typedef unsigned __int32 uint32_t; ///< 32-bit unsigned type (backward compatibility)
|
||||||
typedef signed __int8 vlsint8_t; ///< 8-bit signed type
|
typedef signed __int8 vlsint8_t; ///< 8-bit signed type
|
||||||
typedef unsigned __int8 vluint8_t; ///< 8-bit unsigned type
|
typedef unsigned __int8 vluint8_t; ///< 8-bit unsigned type
|
||||||
typedef signed __int16 vlsint16_t; ///< 16-bit signed type
|
typedef signed __int16 vlsint16_t; ///< 16-bit signed type
|
||||||
typedef unsigned __int16 vluint16_t; ///< 16-bit unsigned type
|
typedef unsigned __int16 vluint16_t; ///< 16-bit unsigned type
|
||||||
typedef signed __int32 vlsint32_t; ///< 32-bit signed type
|
typedef signed __int32 vlsint32_t; ///< 32-bit signed type
|
||||||
typedef unsigned __int32 vluint32_t; ///< 32-bit unsigned type
|
typedef unsigned __int32 vluint32_t; ///< 32-bit unsigned type
|
||||||
typedef signed __int64 vlsint64_t; ///< 64-bit signed type
|
typedef signed __int64 vlsint64_t; ///< 64-bit signed type
|
||||||
typedef unsigned __int64 vluint64_t; ///< 64-bit unsigned type
|
typedef unsigned __int64 vluint64_t; ///< 64-bit unsigned type
|
||||||
|
|
||||||
# ifndef _SSIZE_T_DEFINED
|
# ifndef _SSIZE_T_DEFINED
|
||||||
# ifdef _WIN64
|
# ifdef _WIN64
|
||||||
typedef signed __int64 ssize_t; ///< signed size_t; returned from read()
|
typedef signed __int64 ssize_t; ///< signed size_t; returned from read()
|
||||||
# else
|
# else
|
||||||
typedef signed __int32 ssize_t; ///< signed size_t; returned from read()
|
typedef signed __int32 ssize_t; ///< signed size_t; returned from read()
|
||||||
# endif
|
# endif
|
||||||
# endif
|
# endif
|
||||||
|
|
||||||
|
|
@ -299,18 +304,18 @@ typedef signed __int32 ssize_t; ///< signed size_t; returned fro
|
||||||
# include <stdint.h> // Linux and most flavors
|
# include <stdint.h> // Linux and most flavors
|
||||||
# include <sys/types.h> // __WORDSIZE
|
# include <sys/types.h> // __WORDSIZE
|
||||||
# include <unistd.h> // ssize_t
|
# include <unistd.h> // ssize_t
|
||||||
typedef char vlsint8_t; ///< 8-bit signed type
|
typedef char vlsint8_t; ///< 8-bit signed type
|
||||||
typedef uint8_t vluint8_t; ///< 8-bit unsigned type
|
typedef uint8_t vluint8_t; ///< 8-bit unsigned type
|
||||||
typedef short vlsint16_t; ///< 16-bit signed type
|
typedef short vlsint16_t; ///< 16-bit signed type
|
||||||
typedef uint16_t vluint16_t; ///< 16-bit unsigned type
|
typedef uint16_t vluint16_t; ///< 16-bit unsigned type
|
||||||
typedef int vlsint32_t; ///< 32-bit signed type
|
typedef int vlsint32_t; ///< 32-bit signed type
|
||||||
typedef uint32_t vluint32_t; ///< 32-bit unsigned type
|
typedef uint32_t vluint32_t; ///< 32-bit unsigned type
|
||||||
# if defined(__WORDSIZE) && (__WORDSIZE == 64)
|
# if defined(__WORDSIZE) && (__WORDSIZE == 64)
|
||||||
typedef long vlsint64_t; ///< 64-bit signed type
|
typedef long vlsint64_t; ///< 64-bit signed type
|
||||||
typedef unsigned long vluint64_t; ///< 64-bit unsigned type
|
typedef unsigned long vluint64_t; ///< 64-bit unsigned type
|
||||||
# else
|
# else
|
||||||
typedef long long vlsint64_t; ///< 64-bit signed type
|
typedef long long vlsint64_t; ///< 64-bit signed type
|
||||||
typedef unsigned long long vluint64_t; ///< 64-bit unsigned type
|
typedef unsigned long long vluint64_t; ///< 64-bit unsigned type
|
||||||
# endif
|
# endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
@ -353,14 +358,14 @@ typedef unsigned long long vluint64_t; ///< 64-bit unsigned type
|
||||||
//=========================================================================
|
//=========================================================================
|
||||||
// Integer size macros
|
// Integer size macros
|
||||||
|
|
||||||
#define VL_BYTESIZE 8 ///< Bits in a CData / byte
|
#define VL_BYTESIZE 8 ///< Bits in a CData / byte
|
||||||
#define VL_SHORTSIZE 16 ///< Bits in a SData / short
|
#define VL_SHORTSIZE 16 ///< Bits in a SData / short
|
||||||
#define VL_IDATASIZE 32 ///< Bits in a IData / word
|
#define VL_IDATASIZE 32 ///< Bits in a IData / word
|
||||||
#define VL_WORDSIZE IDATASIZE ///< Legacy define
|
#define VL_WORDSIZE IDATASIZE ///< Legacy define
|
||||||
#define VL_QUADSIZE 64 ///< Bits in a QData / quadword
|
#define VL_QUADSIZE 64 ///< Bits in a QData / quadword
|
||||||
#define VL_EDATASIZE 32 ///< Bits in a EData (WData entry)
|
#define VL_EDATASIZE 32 ///< Bits in a EData (WData entry)
|
||||||
#define VL_EDATASIZE_LOG2 5 ///< log2(VL_EDATASIZE)
|
#define VL_EDATASIZE_LOG2 5 ///< log2(VL_EDATASIZE)
|
||||||
#define VL_CACHE_LINE_BYTES 64 ///< Bytes in a cache line (for alignment)
|
#define VL_CACHE_LINE_BYTES 64 ///< Bytes in a cache line (for alignment)
|
||||||
|
|
||||||
/// Bytes this number of bits needs (1 bit=1 byte)
|
/// Bytes this number of bits needs (1 bit=1 byte)
|
||||||
#define VL_BYTES_I(nbits) (((nbits) + (VL_BYTESIZE - 1)) / VL_BYTESIZE)
|
#define VL_BYTES_I(nbits) (((nbits) + (VL_BYTESIZE - 1)) / VL_BYTESIZE)
|
||||||
|
|
@ -373,9 +378,9 @@ typedef unsigned long long vluint64_t; ///< 64-bit unsigned type
|
||||||
// Class definition helpers
|
// Class definition helpers
|
||||||
|
|
||||||
// Used to declare a class as uncopyable; put after a private:
|
// Used to declare a class as uncopyable; put after a private:
|
||||||
#define VL_UNCOPYABLE(Type) \
|
#define VL_UNCOPYABLE(Type) \
|
||||||
Type(const Type& other) VL_EQ_DELETE; \
|
Type(const Type& other) VL_EQ_DELETE; \
|
||||||
Type& operator= (const Type&) VL_EQ_DELETE
|
Type& operator=(const Type&) VL_EQ_DELETE
|
||||||
|
|
||||||
//=========================================================================
|
//=========================================================================
|
||||||
// Verilated function size macros
|
// Verilated function size macros
|
||||||
|
|
@ -391,11 +396,10 @@ typedef unsigned long long vluint64_t; ///< 64-bit unsigned type
|
||||||
#define VL_SIZEBITS_E (VL_EDATASIZE - 1) ///< Bit mask for bits in a quad
|
#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
|
||||||
|
|
@ -411,8 +415,8 @@ typedef unsigned long long vluint64_t; ///< 64-bit unsigned type
|
||||||
// #defines, to avoid requiring math.h on all compile runs
|
// #defines, to avoid requiring math.h on all compile runs
|
||||||
|
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
# define VL_TRUNC(n) (((n)<0) ? ceil((n)) : floor((n)))
|
# define VL_TRUNC(n) (((n) < 0) ? ceil((n)) : floor((n)))
|
||||||
# define VL_ROUND(n) (((n)<0) ? ceil((n)-0.5) : floor((n)+0.5))
|
# define VL_ROUND(n) (((n) < 0) ? ceil((n)-0.5) : floor((n) + 0.5))
|
||||||
#else
|
#else
|
||||||
# define VL_TRUNC(n) trunc(n)
|
# define VL_TRUNC(n) trunc(n)
|
||||||
# define VL_ROUND(n) round(n)
|
# define VL_ROUND(n) round(n)
|
||||||
|
|
@ -424,13 +428,14 @@ typedef unsigned long long vluint64_t; ///< 64-bit unsigned type
|
||||||
/// The vluint64_t argument is loaded with a high-performance counter for profiling
|
/// 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; \
|
{ \
|
||||||
asm volatile("rdtsc" : "=a" (lo), "=d" (hi)); \
|
vluint32_t hi, lo; \
|
||||||
(val) = ((vluint64_t)lo) | (((vluint64_t)hi)<<32); \
|
asm volatile("rdtsc" : "=a"(lo), "=d"(hi)); \
|
||||||
}
|
(val) = ((vluint64_t)lo) | (((vluint64_t)hi) << 32); \
|
||||||
|
}
|
||||||
#elif defined(__aarch64__)
|
#elif defined(__aarch64__)
|
||||||
# define VL_RDTSC(val) asm volatile("mrs %[rt],PMCCNTR_EL0" : [rt] "=r" (val));
|
# define VL_RDTSC(val) asm volatile("mrs %[rt],PMCCNTR_EL0" : [rt] "=r"(val));
|
||||||
#else
|
#else
|
||||||
// We just silently ignore unknown OSes, as only leads to missing statistics
|
// We just silently ignore unknown OSes, as only leads to missing statistics
|
||||||
# define VL_RDTSC(val) (val) = 0;
|
# define VL_RDTSC(val) (val) = 0;
|
||||||
|
|
@ -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
|
||||||
126
src/V3Active.cpp
126
src/V3Active.cpp
|
|
@ -50,11 +50,11 @@ protected:
|
||||||
|
|
||||||
class ActiveNamer : public ActiveBaseVisitor {
|
class ActiveNamer : public ActiveBaseVisitor {
|
||||||
private:
|
private:
|
||||||
typedef std::map<string,AstActive*> ActiveNameMap;
|
typedef std::map<string, AstActive*> ActiveNameMap;
|
||||||
// STATE
|
// STATE
|
||||||
AstScope* m_scopep; // Current scope to add statement to
|
AstScope* m_scopep; // Current scope to add statement to
|
||||||
AstActive* m_iActivep; // For current scope, the IActive we're building
|
AstActive* m_iActivep; // For current scope, the IActive we're building
|
||||||
AstActive* m_cActivep; // For current scope, the SActive(combo) we're building
|
AstActive* m_cActivep; // For current scope, the SActive(combo) we're building
|
||||||
|
|
||||||
SenTreeSet m_activeSens; // Sen lists for each active we've made
|
SenTreeSet m_activeSens; // Sen lists for each active we've made
|
||||||
typedef vl_unordered_map<AstSenTree*, AstActive*> ActiveMap;
|
typedef vl_unordered_map<AstSenTree*, AstActive*> ActiveMap;
|
||||||
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
@ -122,7 +120,7 @@ public:
|
||||||
AstSenTree* newsenp = sensesp->cloneTree(false);
|
AstSenTree* newsenp = sensesp->cloneTree(false);
|
||||||
activep = new AstActive(fl, "sequent", newsenp);
|
activep = new AstActive(fl, "sequent", newsenp);
|
||||||
activep->sensesStorep(activep->sensesp());
|
activep->sensesStorep(activep->sensesp());
|
||||||
UINFO(8," New ACTIVE "<<activep<<endl);
|
UINFO(8, " New ACTIVE " << activep << endl);
|
||||||
// Form the sensitivity list
|
// Form the sensitivity list
|
||||||
addActive(activep);
|
addActive(activep);
|
||||||
m_activeMap[newsenp] = activep;
|
m_activeMap[newsenp] = activep;
|
||||||
|
|
@ -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,27 +147,29 @@ 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
|
||||||
AstNode* m_assignp; // In assign
|
AstNode* m_assignp; // In assign
|
||||||
// VISITORS
|
// VISITORS
|
||||||
virtual void visit(AstAssignDly* nodep) VL_OVERRIDE {
|
virtual void visit(AstAssignDly* nodep) VL_OVERRIDE {
|
||||||
if (m_check != CT_SEQ) {
|
if (m_check != CT_SEQ) {
|
||||||
// Convert to a non-delayed assignment
|
// Convert to a non-delayed assignment
|
||||||
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -225,15 +225,15 @@ private:
|
||||||
// AstNode::user4() Used by V3Const::constify, called below
|
// AstNode::user4() Used by V3Const::constify, called below
|
||||||
|
|
||||||
// STATE
|
// STATE
|
||||||
ActiveNamer m_namer; // Tracking of active names
|
ActiveNamer m_namer; // Tracking of active names
|
||||||
AstCFunc* m_scopeFinalp; // Final function for this scope
|
AstCFunc* m_scopeFinalp; // Final function for this scope
|
||||||
bool m_itemCombo; // Found a SenItem combo
|
bool m_itemCombo; // Found a SenItem combo
|
||||||
bool m_itemSequent; // Found a SenItem sequential
|
bool m_itemSequent; // Found a SenItem sequential
|
||||||
|
|
||||||
// VISITORS
|
// VISITORS
|
||||||
virtual void visit(AstScope* nodep) VL_OVERRIDE {
|
virtual void visit(AstScope* nodep) VL_OVERRIDE {
|
||||||
// Create required actives and add to scope
|
// Create required actives and add to scope
|
||||||
UINFO(4," SCOPE "<<nodep<<endl);
|
UINFO(4, " SCOPE " << nodep << endl);
|
||||||
// Clear last scope's names, and collect this scope's existing names
|
// Clear last scope's names, and collect this scope's existing names
|
||||||
m_namer.main(nodep);
|
m_namer.main(nodep);
|
||||||
m_scopeFinalp = NULL;
|
m_scopeFinalp = NULL;
|
||||||
|
|
@ -244,48 +244,47 @@ private:
|
||||||
}
|
}
|
||||||
virtual void visit(AstInitial* nodep) VL_OVERRIDE {
|
virtual void visit(AstInitial* nodep) VL_OVERRIDE {
|
||||||
// Relink to IACTIVE, unless already under it
|
// Relink to IACTIVE, unless already under it
|
||||||
UINFO(4," INITIAL "<<nodep<<endl);
|
UINFO(4, " INITIAL " << nodep << endl);
|
||||||
ActiveDlyVisitor dlyvisitor (nodep, ActiveDlyVisitor::CT_INITIAL);
|
ActiveDlyVisitor dlyvisitor(nodep, ActiveDlyVisitor::CT_INITIAL);
|
||||||
AstActive* wantactivep = m_namer.getIActive(nodep->fileline());
|
AstActive* wantactivep = m_namer.getIActive(nodep->fileline());
|
||||||
nodep->unlinkFrBack();
|
nodep->unlinkFrBack();
|
||||||
wantactivep->addStmtsp(nodep);
|
wantactivep->addStmtsp(nodep);
|
||||||
}
|
}
|
||||||
virtual void visit(AstAssignAlias* nodep) VL_OVERRIDE {
|
virtual void visit(AstAssignAlias* nodep) VL_OVERRIDE {
|
||||||
// Relink to CACTIVE, unless already under it
|
// Relink to CACTIVE, unless already under it
|
||||||
UINFO(4," ASSIGNW "<<nodep<<endl);
|
UINFO(4, " ASSIGNW " << nodep << endl);
|
||||||
AstActive* wantactivep = m_namer.getCActive(nodep->fileline());
|
AstActive* wantactivep = m_namer.getCActive(nodep->fileline());
|
||||||
nodep->unlinkFrBack();
|
nodep->unlinkFrBack();
|
||||||
wantactivep->addStmtsp(nodep);
|
wantactivep->addStmtsp(nodep);
|
||||||
}
|
}
|
||||||
virtual void visit(AstAssignW* nodep) VL_OVERRIDE {
|
virtual void visit(AstAssignW* nodep) VL_OVERRIDE {
|
||||||
// Relink to CACTIVE, unless already under it
|
// Relink to CACTIVE, unless already under it
|
||||||
UINFO(4," ASSIGNW "<<nodep<<endl);
|
UINFO(4, " ASSIGNW " << nodep << endl);
|
||||||
AstActive* wantactivep = m_namer.getCActive(nodep->fileline());
|
AstActive* wantactivep = m_namer.getCActive(nodep->fileline());
|
||||||
nodep->unlinkFrBack();
|
nodep->unlinkFrBack();
|
||||||
wantactivep->addStmtsp(nodep);
|
wantactivep->addStmtsp(nodep);
|
||||||
}
|
}
|
||||||
virtual void visit(AstCoverToggle* nodep) VL_OVERRIDE {
|
virtual void visit(AstCoverToggle* nodep) VL_OVERRIDE {
|
||||||
// Relink to CACTIVE, unless already under it
|
// Relink to CACTIVE, unless already under it
|
||||||
UINFO(4," COVERTOGGLE "<<nodep<<endl);
|
UINFO(4, " COVERTOGGLE " << nodep << endl);
|
||||||
AstActive* wantactivep = m_namer.getCActive(nodep->fileline());
|
AstActive* wantactivep = m_namer.getCActive(nodep->fileline());
|
||||||
nodep->unlinkFrBack();
|
nodep->unlinkFrBack();
|
||||||
wantactivep->addStmtsp(nodep);
|
wantactivep->addStmtsp(nodep);
|
||||||
}
|
}
|
||||||
virtual void visit(AstFinal* nodep) VL_OVERRIDE {
|
virtual void visit(AstFinal* nodep) VL_OVERRIDE {
|
||||||
// Relink to CFUNC for the final
|
// Relink to CFUNC for the final
|
||||||
UINFO(4," FINAL "<<nodep<<endl);
|
UINFO(4, " FINAL " << nodep << endl);
|
||||||
if (!nodep->bodysp()) { // Empty, Kill it.
|
if (!nodep->bodysp()) { // Empty, Kill it.
|
||||||
VL_DO_DANGLING(nodep->unlinkFrBack()->deleteTree(), nodep);
|
VL_DO_DANGLING(nodep->unlinkFrBack()->deleteTree(), nodep);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
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"));
|
||||||
m_scopeFinalp->dontCombine(true);
|
m_scopeFinalp->dontCombine(true);
|
||||||
m_scopeFinalp->formCallTree(true);
|
m_scopeFinalp->formCallTree(true);
|
||||||
m_scopeFinalp->slow(true);
|
m_scopeFinalp->slow(true);
|
||||||
|
|
@ -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,
|
||||||
|
|
@ -318,10 +315,11 @@ private:
|
||||||
bool combo = m_itemCombo;
|
bool combo = m_itemCombo;
|
||||||
bool sequent = m_itemSequent;
|
bool sequent = m_itemSequent;
|
||||||
|
|
||||||
if (!combo && !sequent) combo=true; // If no list, Verilog 2000: always @ (*)
|
if (!combo && !sequent) combo = true; // If no list, Verilog 2000: always @ (*)
|
||||||
if (combo && sequent) {
|
if (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);
|
||||||
}
|
}
|
||||||
|
|
@ -354,19 +353,18 @@ private:
|
||||||
// Warn and/or convert any delayed assignments
|
// Warn and/or convert any delayed assignments
|
||||||
if (combo && !sequent) {
|
if (combo && !sequent) {
|
||||||
if (kwd == VAlwaysKwd::ALWAYS_LATCH) {
|
if (kwd == VAlwaysKwd::ALWAYS_LATCH) {
|
||||||
ActiveDlyVisitor dlyvisitor (nodep, ActiveDlyVisitor::CT_LATCH);
|
ActiveDlyVisitor dlyvisitor(nodep, ActiveDlyVisitor::CT_LATCH);
|
||||||
} 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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
virtual void visit(AstAlways* nodep) VL_OVERRIDE {
|
virtual void visit(AstAlways* nodep) VL_OVERRIDE {
|
||||||
// Move always to appropriate ACTIVE based on its sense list
|
// Move always to appropriate ACTIVE based on its sense list
|
||||||
UINFO(4," ALW "<<nodep<<endl);
|
UINFO(4, " ALW " << nodep << endl);
|
||||||
//if (debug()>=9) nodep->dumpTree(cout, " Alw: ");
|
// if (debug()>=9) nodep->dumpTree(cout, " Alw: ");
|
||||||
|
|
||||||
if (!nodep->bodysp()) {
|
if (!nodep->bodysp()) {
|
||||||
// Empty always. Kill it.
|
// Empty always. Kill it.
|
||||||
|
|
@ -377,15 +375,15 @@ private:
|
||||||
}
|
}
|
||||||
virtual void visit(AstAlwaysPublic* nodep) VL_OVERRIDE {
|
virtual void visit(AstAlwaysPublic* nodep) VL_OVERRIDE {
|
||||||
// Move always to appropriate ACTIVE based on its sense list
|
// Move always to appropriate ACTIVE based on its sense list
|
||||||
UINFO(4," ALWPub "<<nodep<<endl);
|
UINFO(4, " ALWPub " << nodep << endl);
|
||||||
//if (debug()>=9) nodep->dumpTree(cout, " Alw: ");
|
// if (debug()>=9) nodep->dumpTree(cout, " Alw: ");
|
||||||
visitAlways(nodep, nodep->sensesp(), VAlwaysKwd::ALWAYS);
|
visitAlways(nodep, nodep->sensesp(), VAlwaysKwd::ALWAYS);
|
||||||
}
|
}
|
||||||
virtual void visit(AstSenGate* nodep) VL_OVERRIDE {
|
virtual void visit(AstSenGate* nodep) VL_OVERRIDE {
|
||||||
AstSenItem* subitemp = nodep->sensesp();
|
AstSenItem* subitemp = nodep->sensesp();
|
||||||
UASSERT_OBJ(subitemp->edgeType() == VEdgeType::ET_ANYEDGE
|
UASSERT_OBJ(subitemp->edgeType() == VEdgeType::ET_ANYEDGE
|
||||||
|| subitemp->edgeType() == VEdgeType::ET_POSEDGE
|
|| subitemp->edgeType() == VEdgeType::ET_POSEDGE
|
||||||
|| subitemp->edgeType() == VEdgeType::ET_NEGEDGE,
|
|| subitemp->edgeType() == VEdgeType::ET_NEGEDGE,
|
||||||
nodep, "Strange activity type under SenGate");
|
nodep, "Strange activity type under SenGate");
|
||||||
iterateChildren(nodep);
|
iterateChildren(nodep);
|
||||||
}
|
}
|
||||||
|
|
@ -399,7 +397,7 @@ private:
|
||||||
// V3LinkResolve should have cleaned most of these up
|
// V3LinkResolve should have cleaned most of these up
|
||||||
if (!nodep->varrefp()->width1()) {
|
if (!nodep->varrefp()->width1()) {
|
||||||
nodep->v3error("Unsupported: Non-single bit wide signal pos/negedge sensitivity: "
|
nodep->v3error("Unsupported: Non-single bit wide signal pos/negedge sensitivity: "
|
||||||
<<nodep->varrefp()->prettyNameQ());
|
<< nodep->varrefp()->prettyNameQ());
|
||||||
}
|
}
|
||||||
m_itemSequent = true;
|
m_itemSequent = true;
|
||||||
nodep->varrefp()->varp()->usedClock(true);
|
nodep->varrefp()->varp()->usedClock(true);
|
||||||
|
|
@ -426,9 +424,7 @@ public:
|
||||||
// Active class functions
|
// Active class functions
|
||||||
|
|
||||||
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);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -42,11 +42,11 @@ private:
|
||||||
// AstNode::user() bool. True if processed
|
// AstNode::user() bool. True if processed
|
||||||
// Each call to V3Const::constify
|
// Each call to V3Const::constify
|
||||||
// AstNode::user4() Used by V3Const::constify, called below
|
// AstNode::user4() Used by V3Const::constify, called below
|
||||||
AstUser1InUse m_inuser1;
|
AstUser1InUse m_inuser1;
|
||||||
|
|
||||||
// STATE
|
// STATE
|
||||||
AstTopScope* m_topscopep; // Top scope for adding sentrees under
|
AstTopScope* m_topscopep; // Top scope for adding sentrees under
|
||||||
SenTreeFinder m_finder; // Find global sentree's and add them
|
SenTreeFinder m_finder; // Find global sentree's and add them
|
||||||
|
|
||||||
// METHODS
|
// METHODS
|
||||||
VL_DEBUG_FUNC; // Declare debug()
|
VL_DEBUG_FUNC; // Declare debug()
|
||||||
|
|
@ -61,16 +61,16 @@ private:
|
||||||
virtual void visit(AstNodeModule* nodep) VL_OVERRIDE {
|
virtual void visit(AstNodeModule* nodep) VL_OVERRIDE {
|
||||||
// Create required actives and add to module
|
// Create required actives and add to module
|
||||||
// We can start ordering at a module, or a scope
|
// We can start ordering at a module, or a scope
|
||||||
UINFO(4," MOD "<<nodep<<endl);
|
UINFO(4, " MOD " << nodep << endl);
|
||||||
iterateChildren(nodep);
|
iterateChildren(nodep);
|
||||||
}
|
}
|
||||||
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,10 +80,9 @@ 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));
|
||||||
nodep->addNextHere(newp);
|
nodep->addNextHere(newp);
|
||||||
|
|
@ -91,10 +90,10 @@ private:
|
||||||
// Move the SENTREE for each active up to the global level.
|
// Move the SENTREE for each active up to the global level.
|
||||||
// This way we'll easily see what clock domains are identical
|
// This way we'll easily see what clock domains are identical
|
||||||
AstSenTree* wantp = m_finder.getSenTree(nodep->fileline(), sensesp);
|
AstSenTree* wantp = m_finder.getSenTree(nodep->fileline(), sensesp);
|
||||||
UINFO(4," lookdone\n");
|
UINFO(4, " lookdone\n");
|
||||||
if (wantp != sensesp) {
|
if (wantp != sensesp) {
|
||||||
// Move the active's contents to the other active
|
// Move the active's contents to the other active
|
||||||
UINFO(4," merge active "<<sensesp<<" into "<<wantp<<endl);
|
UINFO(4, " merge active " << sensesp << " into " << wantp << endl);
|
||||||
if (nodep->sensesStorep()) {
|
if (nodep->sensesStorep()) {
|
||||||
UASSERT_OBJ(sensesp == nodep->sensesStorep(), nodep,
|
UASSERT_OBJ(sensesp == nodep->sensesStorep(), nodep,
|
||||||
"sensesStore should have been deleted earlier if different");
|
"sensesStore should have been deleted earlier if different");
|
||||||
|
|
@ -107,7 +106,7 @@ private:
|
||||||
nodep->sensesp(wantp);
|
nodep->sensesp(wantp);
|
||||||
}
|
}
|
||||||
// No need to do statements under it, they're already moved.
|
// No need to do statements under it, they're already moved.
|
||||||
//iterateChildren(nodep);
|
// iterateChildren(nodep);
|
||||||
}
|
}
|
||||||
virtual void visit(AstInitial* nodep) VL_OVERRIDE { // LCOV_EXCL_LINE
|
virtual void visit(AstInitial* nodep) VL_OVERRIDE { // LCOV_EXCL_LINE
|
||||||
nodep->v3fatalSrc("Node should have been under ACTIVE");
|
nodep->v3fatalSrc("Node should have been under ACTIVE");
|
||||||
|
|
@ -145,9 +144,7 @@ public:
|
||||||
// Active class functions
|
// Active class functions
|
||||||
|
|
||||||
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);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
127
src/V3Assert.cpp
127
src/V3Assert.cpp
|
|
@ -34,24 +34,22 @@ private:
|
||||||
// NODE STATE/TYPES
|
// NODE STATE/TYPES
|
||||||
// Cleared on netlist
|
// Cleared on netlist
|
||||||
// AstNode::user() -> bool. True if processed
|
// AstNode::user() -> bool. True if processed
|
||||||
AstUser1InUse m_inuser1;
|
AstUser1InUse m_inuser1;
|
||||||
|
|
||||||
// STATE
|
// STATE
|
||||||
AstNodeModule* m_modp; // Last module
|
AstNodeModule* m_modp; // Last module
|
||||||
AstBegin* m_beginp; // Last begin
|
AstBegin* m_beginp; // Last begin
|
||||||
unsigned m_modPastNum; // Module past numbering
|
unsigned m_modPastNum; // Module past numbering
|
||||||
VDouble0 m_statCover; // Statistic tracking
|
VDouble0 m_statCover; // Statistic tracking
|
||||||
VDouble0 m_statAsNotImm; // Statistic tracking
|
VDouble0 m_statAsNotImm; // Statistic tracking
|
||||||
VDouble0 m_statAsImm; // Statistic tracking
|
VDouble0 m_statAsImm; // Statistic tracking
|
||||||
VDouble0 m_statAsFull; // Statistic tracking
|
VDouble0 m_statAsFull; // Statistic tracking
|
||||||
|
|
||||||
// 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);
|
||||||
|
|
@ -77,8 +75,8 @@ private:
|
||||||
// If assertions are off, have constant propagation rip them out later
|
// If assertions are off, have constant propagation rip them out later
|
||||||
// This allows syntax errors and such to be detected normally.
|
// This allows syntax errors and such to be detected normally.
|
||||||
(v3Global.opt.assertOn()
|
(v3Global.opt.assertOn()
|
||||||
? static_cast<AstNode*>(new AstCMath(fl, "Verilated::assertOn()", 1))
|
? static_cast<AstNode*>(new AstCMath(fl, "Verilated::assertOn()", 1))
|
||||||
: static_cast<AstNode*>(new AstConst(fl, AstConst::LogicFalse()))),
|
: static_cast<AstNode*>(new AstConst(fl, AstConst::LogicFalse()))),
|
||||||
nodep, NULL);
|
nodep, NULL);
|
||||||
newp->user1(true); // Don't assert/cover this if
|
newp->user1(true); // Don't assert/cover this if
|
||||||
return newp;
|
return newp;
|
||||||
|
|
@ -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));
|
||||||
|
|
@ -129,7 +127,7 @@ private:
|
||||||
AstCoverInc* covincp = VN_CAST(snodep->coverincp(), CoverInc);
|
AstCoverInc* covincp = VN_CAST(snodep->coverincp(), CoverInc);
|
||||||
UASSERT_OBJ(covincp, snodep, "Missing AstCoverInc under assertion");
|
UASSERT_OBJ(covincp, snodep, "Missing AstCoverInc under assertion");
|
||||||
covincp->unlinkFrBackWithNext(); // next() might have AstAssign for trace
|
covincp->unlinkFrBackWithNext(); // next() might have AstAssign for trace
|
||||||
if (message!="") covincp->declp()->comment(message);
|
if (message != "") covincp->declp()->comment(message);
|
||||||
bodysp = covincp;
|
bodysp = covincp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -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,14 +201,12 @@ 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);
|
||||||
|
|
||||||
AstNode *newifp = nodep->cloneTree(false);
|
AstNode* newifp = nodep->cloneTree(false);
|
||||||
bool allow_none = nodep->unique0Pragma();
|
bool allow_none = nodep->unique0Pragma();
|
||||||
|
|
||||||
// Empty case means no property
|
// Empty case means no property
|
||||||
|
|
@ -215,12 +215,11 @@ private:
|
||||||
// Note: if this ends with an 'else', then we don't need to validate that one of the
|
// Note: if this ends with an 'else', then we don't need to validate that one of the
|
||||||
// predicates evaluates to true.
|
// predicates evaluates to true.
|
||||||
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,16 +233,17 @@ 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(
|
||||||
newFireAssert(nodep, "synthesis full_case, but non-match found")));
|
nodep->fileline(), NULL /*DEFAULT*/,
|
||||||
|
newFireAssert(nodep, "synthesis full_case, but non-match found")));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (nodep->parallelPragma() || nodep->uniquePragma() || nodep->unique0Pragma()) {
|
if (nodep->parallelPragma() || nodep->uniquePragma() || nodep->unique0Pragma()) {
|
||||||
|
|
@ -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
|
||||||
|
|
@ -281,12 +284,13 @@ private:
|
||||||
bool allow_none = has_default || nodep->unique0Pragma();
|
bool allow_none = has_default || nodep->unique0Pragma();
|
||||||
AstNode* ohot
|
AstNode* ohot
|
||||||
= (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,
|
||||||
NULL);
|
"synthesis parallel_case, but multiple matches found"),
|
||||||
|
NULL);
|
||||||
ifp->branchPred(VBranchPred::BP_UNLIKELY);
|
ifp->branchPred(VBranchPred::BP_UNLIKELY);
|
||||||
nodep->addNotParallelp(ifp);
|
nodep->addNotParallelp(ifp);
|
||||||
}
|
}
|
||||||
|
|
@ -303,23 +307,22 @@ private:
|
||||||
"Expected constant ticks, checked in V3Width");
|
"Expected constant ticks, checked in V3Width");
|
||||||
ticks = VN_CAST(nodep->ticksp(), Const)->toUInt();
|
ticks = VN_CAST(nodep->ticksp(), Const)->toUInt();
|
||||||
}
|
}
|
||||||
UASSERT_OBJ(ticks>=1, nodep, "0 tick should have been checked in V3Width");
|
UASSERT_OBJ(ticks >= 1, nodep, "0 tick should have been checked in V3Width");
|
||||||
AstNode* inp = nodep->exprp()->unlinkFrBack();
|
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,
|
||||||
"_Vpast_"+cvtToStr(m_modPastNum++)+"_"+cvtToStr(i),
|
"_Vpast_" + cvtToStr(m_modPastNum++) + "_" + cvtToStr(i),
|
||||||
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;
|
||||||
inp = new AstVarRef(nodep->fileline(), invarp, false);
|
inp = new AstVarRef(nodep->fileline(), invarp, false);
|
||||||
}
|
}
|
||||||
|
|
@ -334,12 +337,12 @@ private:
|
||||||
virtual void visit(AstDisplay* nodep) VL_OVERRIDE {
|
virtual void visit(AstDisplay* nodep) VL_OVERRIDE {
|
||||||
iterateChildren(nodep);
|
iterateChildren(nodep);
|
||||||
// Replace the special types with standard text
|
// Replace the special types with standard text
|
||||||
if (nodep->displayType()==AstDisplayType::DT_INFO) {
|
if (nodep->displayType() == AstDisplayType::DT_INFO) {
|
||||||
replaceDisplay(nodep, "-Info");
|
replaceDisplay(nodep, "-Info");
|
||||||
} else if (nodep->displayType()==AstDisplayType::DT_WARNING) {
|
} else if (nodep->displayType() == AstDisplayType::DT_WARNING) {
|
||||||
replaceDisplay(nodep, "%%Warning");
|
replaceDisplay(nodep, "%%Warning");
|
||||||
} else if (nodep->displayType()==AstDisplayType::DT_ERROR
|
} else if (nodep->displayType() == AstDisplayType::DT_ERROR
|
||||||
|| nodep->displayType()==AstDisplayType::DT_FATAL) {
|
|| nodep->displayType() == AstDisplayType::DT_FATAL) {
|
||||||
replaceDisplay(nodep, "%%Error");
|
replaceDisplay(nodep, "%%Error");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -403,9 +406,7 @@ public:
|
||||||
// Top Assert class
|
// Top Assert class
|
||||||
|
|
||||||
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,14 +61,12 @@ private:
|
||||||
}
|
}
|
||||||
return newp;
|
return newp;
|
||||||
}
|
}
|
||||||
void clearAssertInfo() {
|
void clearAssertInfo() { m_senip = NULL; }
|
||||||
m_senip = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
// VISITORS
|
// VISITORS
|
||||||
//========== Statements
|
//========== Statements
|
||||||
virtual void visit(AstClocking* nodep) VL_OVERRIDE {
|
virtual void visit(AstClocking* nodep) VL_OVERRIDE {
|
||||||
UINFO(8," CLOCKING"<<nodep<<endl);
|
UINFO(8, " CLOCKING" << nodep << endl);
|
||||||
// Store the new default clock, reset on new module
|
// Store the new default clock, reset on new module
|
||||||
m_seniDefaultp = nodep->sensesp();
|
m_seniDefaultp = nodep->sensesp();
|
||||||
// Trash it, keeping children
|
// Trash it, keeping children
|
||||||
|
|
@ -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
|
||||||
|
|
@ -151,9 +142,7 @@ public:
|
||||||
// Top Assert class
|
// Top Assert class
|
||||||
|
|
||||||
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);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -18,12 +18,12 @@
|
||||||
#define _V3ASTCONSTONLY_H_ 1
|
#define _V3ASTCONSTONLY_H_ 1
|
||||||
|
|
||||||
// Include only in visitors that do not not edit nodes, so should use constant iterators
|
// Include only in visitors that do not not edit nodes, so should use constant iterators
|
||||||
#define iterateAndNext error_use_iterateAndNextConst
|
#define iterateAndNext error_use_iterateAndNextConst
|
||||||
#define iterateChildren error_use_iterateChildrenConst
|
#define iterateChildren error_use_iterateChildrenConst
|
||||||
|
|
||||||
#define addNext error_no_addNext_in_ConstOnlyVisitor
|
#define addNext error_no_addNext_in_ConstOnlyVisitor
|
||||||
#define replaceWith error_no_replaceWith_in_ConstOnlyVisitor
|
#define replaceWith error_no_replaceWith_in_ConstOnlyVisitor
|
||||||
#define deleteTree error_no_deleteTree_in_ConstOnlyVisitor
|
#define deleteTree error_no_deleteTree_in_ConstOnlyVisitor
|
||||||
#define unlinkFrBack error_no_unlinkFrBack_in_ConstOnlyVisitor
|
#define unlinkFrBack error_no_unlinkFrBack_in_ConstOnlyVisitor
|
||||||
|
|
||||||
#endif // Guard
|
#endif // Guard
|
||||||
|
|
|
||||||
|
|
@ -41,15 +41,15 @@ private:
|
||||||
// NODE STATE
|
// NODE STATE
|
||||||
// Entire netlist:
|
// Entire netlist:
|
||||||
// AstFTask::user1() -> int. Number of references
|
// AstFTask::user1() -> int. Number of references
|
||||||
AstUser1InUse m_inuser1;
|
AstUser1InUse m_inuser1;
|
||||||
|
|
||||||
// TYPES
|
// TYPES
|
||||||
typedef std::vector<AstCFunc*> CFuncVec;
|
typedef std::vector<AstCFunc*> CFuncVec;
|
||||||
|
|
||||||
// STATE
|
// STATE
|
||||||
int m_likely; // Excuses for branch likely taken
|
int m_likely; // Excuses for branch likely taken
|
||||||
int m_unlikely; // Excuses for branch likely not taken
|
int m_unlikely; // Excuses for branch likely not taken
|
||||||
CFuncVec m_cfuncsp; // List of all tasks
|
CFuncVec m_cfuncsp; // List of all tasks
|
||||||
|
|
||||||
// METHODS
|
// METHODS
|
||||||
VL_DEBUG_FUNC; // Declare debug()
|
VL_DEBUG_FUNC; // Declare debug()
|
||||||
|
|
@ -60,14 +60,14 @@ private:
|
||||||
}
|
}
|
||||||
void checkUnlikely(AstNode* nodep) {
|
void checkUnlikely(AstNode* nodep) {
|
||||||
if (nodep->isUnlikely()) {
|
if (nodep->isUnlikely()) {
|
||||||
UINFO(4," UNLIKELY: "<<nodep<<endl);
|
UINFO(4, " UNLIKELY: " << nodep << endl);
|
||||||
m_unlikely++;
|
m_unlikely++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// VISITORS
|
// VISITORS
|
||||||
virtual void visit(AstNodeIf* nodep) VL_OVERRIDE {
|
virtual void visit(AstNodeIf* nodep) VL_OVERRIDE {
|
||||||
UINFO(4," IF: "<<nodep<<endl);
|
UINFO(4, " IF: " << nodep << endl);
|
||||||
int lastLikely = m_likely;
|
int lastLikely = m_likely;
|
||||||
int lastUnlikely = m_unlikely;
|
int lastUnlikely = m_unlikely;
|
||||||
{
|
{
|
||||||
|
|
@ -109,11 +109,9 @@ private:
|
||||||
|
|
||||||
// METHODS
|
// METHODS
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -131,6 +129,6 @@ public:
|
||||||
// Branch class functions
|
// Branch class functions
|
||||||
|
|
||||||
void V3Branch::branchAll(AstNetlist* nodep) {
|
void V3Branch::branchAll(AstNetlist* nodep) {
|
||||||
UINFO(2,__FUNCTION__<<": "<<endl);
|
UINFO(2, __FUNCTION__ << ": " << endl);
|
||||||
BranchVisitor visitor (nodep);
|
BranchVisitor visitor(nodep);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
@ -103,7 +97,7 @@ private:
|
||||||
iterateChildren(nodep);
|
iterateChildren(nodep);
|
||||||
// Don't move now, or wouldn't keep interating the class
|
// Don't move now, or wouldn't keep interating the class
|
||||||
// TODO move class statics only
|
// TODO move class statics only
|
||||||
//if (m_classScopep) {
|
// if (m_classScopep) {
|
||||||
// m_moves.push_back(make_pair(nodep, m_classScopep));
|
// m_moves.push_back(make_pair(nodep, m_classScopep));
|
||||||
//}
|
//}
|
||||||
}
|
}
|
||||||
|
|
@ -111,7 +105,7 @@ private:
|
||||||
iterateChildren(nodep);
|
iterateChildren(nodep);
|
||||||
// Don't move now, or wouldn't keep interating the class
|
// Don't move now, or wouldn't keep interating the class
|
||||||
// TODO move function statics only
|
// TODO move function statics only
|
||||||
//if (m_classScopep) {
|
// if (m_classScopep) {
|
||||||
// m_moves.push_back(make_pair(nodep, m_classScopep));
|
// m_moves.push_back(make_pair(nodep, m_classScopep));
|
||||||
//}
|
//}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -267,7 +267,7 @@ class V3ConfigFile {
|
||||||
|
|
||||||
LineAttrMap m_lineAttrs; // Atributes to line mapping
|
LineAttrMap m_lineAttrs; // Atributes to line mapping
|
||||||
IgnLines m_ignLines; // Ignore line settings
|
IgnLines m_ignLines; // Ignore line settings
|
||||||
Waivers m_waivers; // Waive messages
|
Waivers m_waivers; // Waive messages
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
int lineno; // Last line number
|
int lineno; // Last line number
|
||||||
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -40,14 +40,16 @@
|
||||||
class CoverageVisitor : public AstNVisitor {
|
class CoverageVisitor : public AstNVisitor {
|
||||||
private:
|
private:
|
||||||
// TYPES
|
// TYPES
|
||||||
typedef std::map<string,int> FileMap;
|
typedef std::map<string, int> FileMap;
|
||||||
|
|
||||||
struct ToggleEnt {
|
struct ToggleEnt {
|
||||||
string m_comment; // Comment for coverage dump
|
string m_comment; // Comment for coverage dump
|
||||||
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);
|
||||||
|
|
@ -58,15 +60,15 @@ private:
|
||||||
// NODE STATE
|
// NODE STATE
|
||||||
// Entire netlist:
|
// Entire netlist:
|
||||||
// AstIf::user1() -> bool. True indicates ifelse processed
|
// AstIf::user1() -> bool. True indicates ifelse processed
|
||||||
AstUser1InUse m_inuser1;
|
AstUser1InUse m_inuser1;
|
||||||
|
|
||||||
// STATE
|
// STATE
|
||||||
bool m_checkBlock; // Should this block get covered?
|
bool m_checkBlock; // Should this block get covered?
|
||||||
AstNodeModule* m_modp; // Current module to add statement to
|
AstNodeModule* m_modp; // Current module to add statement to
|
||||||
bool m_inToggleOff; // In function/task etc
|
bool m_inToggleOff; // In function/task etc
|
||||||
bool m_inModOff; // In module with no coverage
|
bool m_inModOff; // In module with no coverage
|
||||||
FileMap m_fileps; // Column counts for each fileline
|
FileMap m_fileps; // Column counts for each fileline
|
||||||
string m_beginHier; // AstBegin hier name for user coverage points
|
string m_beginHier; // AstBegin hier name for user coverage points
|
||||||
|
|
||||||
// METHODS
|
// METHODS
|
||||||
VL_DEBUG_FUNC; // Declare debug()
|
VL_DEBUG_FUNC; // Declare debug()
|
||||||
|
|
@ -74,16 +76,13 @@ 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";
|
||||||
}
|
}
|
||||||
// We allow this, though tracing doesn't
|
// We allow this, though tracing doesn't
|
||||||
|
|
@ -91,19 +90,18 @@ 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()) {
|
||||||
m_fileps.insert(make_pair(key, column+1));
|
m_fileps.insert(make_pair(key, column + 1));
|
||||||
} else {
|
} else {
|
||||||
column = (it->second)++;
|
column = (it->second)++;
|
||||||
}
|
}
|
||||||
|
|
@ -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,13 +163,13 @@ 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);
|
||||||
} else {
|
} else {
|
||||||
UINFO(4, " Toggle: "<<nodep<<endl);
|
UINFO(4, " Toggle: " << nodep << endl);
|
||||||
// There's several overall ways to approach this
|
// There's several overall ways to approach this
|
||||||
// Treat like tracing, where a end-of-timestamp action sees all changes
|
// Treat like tracing, where a end-of-timestamp action sees all changes
|
||||||
// Works ok, but would be quite slow as need to reform
|
// Works ok, but would be quite slow as need to reform
|
||||||
|
|
@ -188,9 +182,9 @@ private:
|
||||||
// We'll do this, and make the if(...) coverinc later.
|
// We'll do this, and make the if(...) coverinc later.
|
||||||
|
|
||||||
// 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,123 +192,108 @@ 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, nodep, chgVarp);
|
||||||
toggleVarRecurse(nodep->dtypeSkipRefp(), 0, newvec,
|
|
||||||
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) + "]",
|
||||||
new AstArraySel(varp->fileline(),
|
new AstArraySel(varp->fileline(),
|
||||||
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();
|
||||||
ToggleEnt newent (above.m_comment+string("[")+cvtToStr(index_docs)+"]",
|
ToggleEnt newent(above.m_comment + string("[") + cvtToStr(index_docs) + "]",
|
||||||
new AstSel(varp->fileline(), above.m_varRefp->cloneTree(true),
|
new AstSel(varp->fileline(), above.m_varRefp->cloneTree(true),
|
||||||
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(),
|
||||||
new AstSel(varp->fileline(), above.m_varRefp->cloneTree(true),
|
new AstSel(varp->fileline(), above.m_varRefp->cloneTree(true),
|
||||||
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
|
||||||
UINFO(4," IF: "<<nodep<<endl);
|
visit(AstIf* nodep) VL_OVERRIDE { // Note not AstNodeIf; other types don't get covered
|
||||||
|
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",
|
||||||
traceNameForLine(nodep, "elsif")));
|
traceNameForLine(nodep, "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")));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -341,12 +319,12 @@ 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);
|
||||||
nodep->addBodysp(newCoverInc(nodep->fileline(), "", "v_line", "case",
|
nodep->addBodysp(newCoverInc(nodep->fileline(), "", "v_line", "case",
|
||||||
traceNameForLine(nodep, "case")));
|
traceNameForLine(nodep, "case")));
|
||||||
}
|
}
|
||||||
|
|
@ -354,24 +332,24 @@ private:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
virtual void visit(AstCover* nodep) VL_OVERRIDE {
|
virtual void visit(AstCover* nodep) VL_OVERRIDE {
|
||||||
UINFO(4," COVER: "<<nodep<<endl);
|
UINFO(4, " COVER: " << nodep << endl);
|
||||||
m_checkBlock = true; // Always do cover blocks, even if there's a $stop
|
m_checkBlock = true; // Always do cover blocks, even if there's a $stop
|
||||||
iterateChildren(nodep);
|
iterateChildren(nodep);
|
||||||
if (!nodep->coverincp()) {
|
if (!nodep->coverincp()) {
|
||||||
// Note the name may be overridden by V3Assert processing
|
// Note the name may be overridden by V3Assert processing
|
||||||
nodep->coverincp(newCoverInc(nodep->fileline(), m_beginHier, "v_user", "cover",
|
nodep->coverincp(newCoverInc(nodep->fileline(), m_beginHier, "v_user", "cover",
|
||||||
m_beginHier+"_vlCoverageUserTrace"));
|
m_beginHier + "_vlCoverageUserTrace"));
|
||||||
}
|
}
|
||||||
m_checkBlock = true; // Reset as a child may have cleared it
|
m_checkBlock = true; // Reset as a child may have cleared it
|
||||||
}
|
}
|
||||||
virtual void visit(AstStop* nodep) VL_OVERRIDE {
|
virtual void visit(AstStop* nodep) VL_OVERRIDE {
|
||||||
UINFO(4," STOP: "<<nodep<<endl);
|
UINFO(4, " STOP: " << nodep << endl);
|
||||||
m_checkBlock = false;
|
m_checkBlock = false;
|
||||||
}
|
}
|
||||||
virtual void visit(AstPragma* nodep) VL_OVERRIDE {
|
virtual void visit(AstPragma* nodep) VL_OVERRIDE {
|
||||||
if (nodep->pragType() == AstPragmaType::COVERAGE_BLOCK_OFF) {
|
if (nodep->pragType() == AstPragmaType::COVERAGE_BLOCK_OFF) {
|
||||||
// Skip all NEXT nodes under this block, and skip this if/case branch
|
// Skip all NEXT nodes under this block, and skip this if/case branch
|
||||||
UINFO(4," OFF: "<<nodep<<endl);
|
UINFO(4, " OFF: " << nodep << endl);
|
||||||
m_checkBlock = false;
|
m_checkBlock = false;
|
||||||
VL_DO_DANGLING(nodep->unlinkFrBack()->deleteTree(), nodep);
|
VL_DO_DANGLING(nodep->unlinkFrBack()->deleteTree(), nodep);
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -388,8 +366,8 @@ private:
|
||||||
bool oldtog = m_inToggleOff;
|
bool oldtog = m_inToggleOff;
|
||||||
{
|
{
|
||||||
m_inToggleOff = true;
|
m_inToggleOff = true;
|
||||||
if (nodep->name()!="") {
|
if (nodep->name() != "") {
|
||||||
m_beginHier = m_beginHier + (m_beginHier!=""?".":"") + nodep->name();
|
m_beginHier = m_beginHier + (m_beginHier != "" ? "." : "") + nodep->name();
|
||||||
}
|
}
|
||||||
iterateChildren(nodep);
|
iterateChildren(nodep);
|
||||||
}
|
}
|
||||||
|
|
@ -423,9 +401,7 @@ public:
|
||||||
// Coverage class functions
|
// Coverage class functions
|
||||||
|
|
||||||
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"
|
||||||
|
|
||||||
|
|
@ -38,23 +37,23 @@ private:
|
||||||
// V3Hashed
|
// V3Hashed
|
||||||
// AstCoverToggle->VarRef::user4() // V3Hashed calculation
|
// AstCoverToggle->VarRef::user4() // V3Hashed calculation
|
||||||
|
|
||||||
//AstUser4InUse In V3Hashed
|
// AstUser4InUse In V3Hashed
|
||||||
|
|
||||||
// TYPES
|
// TYPES
|
||||||
typedef std::vector<AstCoverToggle*> ToggleList;
|
typedef std::vector<AstCoverToggle*> ToggleList;
|
||||||
|
|
||||||
// STATE
|
// STATE
|
||||||
ToggleList m_toggleps; // List of of all AstCoverToggle's
|
ToggleList m_toggleps; // List of of all AstCoverToggle's
|
||||||
|
|
||||||
VDouble0 m_statToggleJoins; // Statistic tracking
|
VDouble0 m_statToggleJoins; // Statistic tracking
|
||||||
|
|
||||||
// METHODS
|
// METHODS
|
||||||
VL_DEBUG_FUNC; // Declare debug()
|
VL_DEBUG_FUNC; // Declare debug()
|
||||||
|
|
||||||
void detectDuplicates() {
|
void detectDuplicates() {
|
||||||
UINFO(9,"Finding duplicates\n");
|
UINFO(9, "Finding duplicates\n");
|
||||||
// Note uses user4
|
// Note uses user4
|
||||||
V3Hashed hashed; // Duplicate code detection
|
V3Hashed hashed; // Duplicate code detection
|
||||||
// Hash all of the original signals we toggle cover
|
// Hash all of the original signals we toggle cover
|
||||||
for (ToggleList::iterator it = m_toggleps.begin(); it != m_toggleps.end(); ++it) {
|
for (ToggleList::iterator it = m_toggleps.begin(); it != m_toggleps.end(); ++it) {
|
||||||
AstCoverToggle* nodep = *it;
|
AstCoverToggle* nodep = *it;
|
||||||
|
|
@ -78,17 +77,18 @@ private:
|
||||||
// covertoggle which is immediately above, so:
|
// covertoggle which is immediately above, so:
|
||||||
AstCoverToggle* removep = VN_CAST(duporigp->backp(), CoverToggle);
|
AstCoverToggle* removep = VN_CAST(duporigp->backp(), CoverToggle);
|
||||||
UASSERT_OBJ(removep, nodep, "CoverageJoin duplicate of wrong type");
|
UASSERT_OBJ(removep, nodep, "CoverageJoin duplicate of wrong type");
|
||||||
UINFO(8," Orig "<<nodep<<" -->> "<<nodep->incp()->declp()<<endl);
|
UINFO(8, " Orig " << nodep << " -->> " << nodep->incp()->declp() << endl);
|
||||||
UINFO(8," dup "<<removep<<" -->> "<<removep->incp()->declp()<<endl);
|
UINFO(8, " dup " << removep << " -->> " << removep->incp()->declp() << endl);
|
||||||
// The CoverDecl the duplicate pointed to now needs to point to the
|
// The CoverDecl the duplicate pointed to now needs to point to the
|
||||||
// original's data. I.e. the duplicate will get the coverage number
|
// original's data. I.e. the duplicate will get the coverage number
|
||||||
// from the non-duplicate
|
// from the non-duplicate
|
||||||
AstCoverDecl* datadeclp = nodep->incp()->declp()->dataDeclThisp();
|
AstCoverDecl* datadeclp = nodep->incp()->declp()->dataDeclThisp();
|
||||||
removep->incp()->declp()->dataDeclp(datadeclp);
|
removep->incp()->declp()->dataDeclp(datadeclp);
|
||||||
UINFO(8," new "<<removep->incp()->declp()<<endl);
|
UINFO(8, " new " << removep->incp()->declp() << endl);
|
||||||
// Mark the found node as a duplicate of the first node
|
// 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);
|
||||||
}
|
}
|
||||||
|
|
@ -126,9 +124,7 @@ public:
|
||||||
// Coverage class functions
|
// Coverage class functions
|
||||||
|
|
||||||
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);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -40,20 +40,20 @@ private:
|
||||||
// NODE STATE
|
// NODE STATE
|
||||||
|
|
||||||
// STATE
|
// STATE
|
||||||
AstNodeModule* m_modp; // Current module
|
AstNodeModule* m_modp; // Current module
|
||||||
AstCFunc* m_funcp; // Current block
|
AstCFunc* m_funcp; // Current block
|
||||||
AstNode* m_stmtp; // Current statement
|
AstNode* m_stmtp; // Current statement
|
||||||
int m_depth; // How deep in an expression
|
int m_depth; // How deep in an expression
|
||||||
int m_maxdepth; // Maximum depth in an expression
|
int m_maxdepth; // Maximum depth in an expression
|
||||||
|
|
||||||
// METHODS
|
// METHODS
|
||||||
VL_DEBUG_FUNC; // Declare debug()
|
VL_DEBUG_FUNC; // Declare debug()
|
||||||
|
|
||||||
void createDeepTemp(AstNode* nodep) {
|
void createDeepTemp(AstNode* nodep) {
|
||||||
UINFO(6," Deep "<<nodep<<endl);
|
UINFO(6, " Deep " << nodep << endl);
|
||||||
//if (debug()>=9) nodep->dumpTree(cout, "deep:");
|
// if (debug()>=9) nodep->dumpTree(cout, "deep:");
|
||||||
|
|
||||||
string newvarname = (string("__Vdeeptemp")+cvtToStr(m_modp->varNumGetInc()));
|
string newvarname = (string("__Vdeeptemp") + cvtToStr(m_modp->varNumGetInc()));
|
||||||
AstVar* varp = new AstVar(nodep->fileline(), AstVarType::STMTTEMP, newvarname,
|
AstVar* varp = new AstVar(nodep->fileline(), AstVarType::STMTTEMP, newvarname,
|
||||||
// Width, not widthMin, as we may be in
|
// Width, not widthMin, as we may be in
|
||||||
// middle of BITSEL expression which though
|
// middle of BITSEL expression which though
|
||||||
|
|
@ -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);
|
||||||
|
|
@ -79,7 +78,7 @@ private:
|
||||||
|
|
||||||
// VISITORS
|
// VISITORS
|
||||||
virtual void visit(AstNodeModule* nodep) VL_OVERRIDE {
|
virtual void visit(AstNodeModule* nodep) VL_OVERRIDE {
|
||||||
UINFO(4," MOD "<<nodep<<endl);
|
UINFO(4, " MOD " << nodep << endl);
|
||||||
AstNodeModule* origModp = m_modp;
|
AstNodeModule* origModp = m_modp;
|
||||||
{
|
{
|
||||||
m_modp = nodep;
|
m_modp = nodep;
|
||||||
|
|
@ -110,20 +109,18 @@ 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;
|
||||||
if (m_depth>m_maxdepth) m_maxdepth = m_depth;
|
if (m_depth > m_maxdepth) m_maxdepth = m_depth;
|
||||||
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
|
||||||
) {
|
) {
|
||||||
m_maxdepth = m_depth;
|
m_maxdepth = m_depth;
|
||||||
createDeepTemp(nodep);
|
createDeepTemp(nodep);
|
||||||
}
|
}
|
||||||
|
|
@ -135,7 +132,7 @@ private:
|
||||||
void needNonStaticFunc(AstNode* nodep) {
|
void needNonStaticFunc(AstNode* nodep) {
|
||||||
UASSERT_OBJ(m_funcp, nodep, "Non-static accessor not under a function");
|
UASSERT_OBJ(m_funcp, nodep, "Non-static accessor not under a function");
|
||||||
if (m_funcp->isStatic().trueUnknown()) {
|
if (m_funcp->isStatic().trueUnknown()) {
|
||||||
UINFO(5,"Mark non-public due to "<<nodep<<endl);
|
UINFO(5, "Mark non-public due to " << nodep << endl);
|
||||||
m_funcp->isStatic(false);
|
m_funcp->isStatic(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -171,9 +168,7 @@ public:
|
||||||
// Depth class functions
|
// Depth class functions
|
||||||
|
|
||||||
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);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -38,10 +38,10 @@ private:
|
||||||
// NODE STATE
|
// NODE STATE
|
||||||
|
|
||||||
// STATE
|
// STATE
|
||||||
AstNodeModule* m_modp; // Current module
|
AstNodeModule* m_modp; // Current module
|
||||||
AstCFunc* m_funcp; // Current function
|
AstCFunc* m_funcp; // Current function
|
||||||
int m_depth; // How deep in an expression
|
int m_depth; // How deep in an expression
|
||||||
int m_deepNum; // How many functions made
|
int m_deepNum; // How many functions made
|
||||||
|
|
||||||
// METHODS
|
// METHODS
|
||||||
VL_DEBUG_FUNC; // Declare debug()
|
VL_DEBUG_FUNC; // Declare debug()
|
||||||
|
|
@ -50,7 +50,7 @@ private:
|
||||||
AstNRelinker relinkHandle;
|
AstNRelinker relinkHandle;
|
||||||
nodep->unlinkFrBack(&relinkHandle);
|
nodep->unlinkFrBack(&relinkHandle);
|
||||||
// Create function
|
// Create function
|
||||||
string name = m_funcp->name()+"__deep"+cvtToStr(++m_deepNum);
|
string name = m_funcp->name() + "__deep" + cvtToStr(++m_deepNum);
|
||||||
AstCFunc* funcp = new AstCFunc(nodep->fileline(), name, NULL);
|
AstCFunc* funcp = new AstCFunc(nodep->fileline(), name, NULL);
|
||||||
funcp->argTypes(EmitCBaseVisitor::symClassVar());
|
funcp->argTypes(EmitCBaseVisitor::symClassVar());
|
||||||
funcp->symProlog(true);
|
funcp->symProlog(true);
|
||||||
|
|
@ -60,7 +60,7 @@ private:
|
||||||
// Call it at the point where the body was removed from
|
// Call it at the point where the body was removed from
|
||||||
AstCCall* callp = new AstCCall(nodep->fileline(), funcp);
|
AstCCall* callp = new AstCCall(nodep->fileline(), funcp);
|
||||||
callp->argTypes("vlSymsp");
|
callp->argTypes("vlSymsp");
|
||||||
UINFO(6," New "<<callp<<endl);
|
UINFO(6, " New " << callp << endl);
|
||||||
//
|
//
|
||||||
relinkHandle.relink(callp);
|
relinkHandle.relink(callp);
|
||||||
return funcp;
|
return funcp;
|
||||||
|
|
@ -68,7 +68,7 @@ private:
|
||||||
|
|
||||||
// VISITORS
|
// VISITORS
|
||||||
virtual void visit(AstNodeModule* nodep) VL_OVERRIDE {
|
virtual void visit(AstNodeModule* nodep) VL_OVERRIDE {
|
||||||
UINFO(4," MOD "<<nodep<<endl);
|
UINFO(4, " MOD " << nodep << endl);
|
||||||
AstNodeModule* origModp = m_modp;
|
AstNodeModule* origModp = m_modp;
|
||||||
{
|
{
|
||||||
m_modp = nodep;
|
m_modp = nodep;
|
||||||
|
|
@ -93,13 +93,13 @@ private:
|
||||||
m_depth++;
|
m_depth++;
|
||||||
if (m_depth > v3Global.opt.compLimitBlocks()
|
if (m_depth > v3Global.opt.compLimitBlocks()
|
||||||
&& !VN_IS(nodep, NodeCCall)) { // Already done
|
&& !VN_IS(nodep, NodeCCall)) { // Already done
|
||||||
UINFO(4, "DeepBlocks "<<m_depth<<" "<<nodep<<endl);
|
UINFO(4, "DeepBlocks " << m_depth << " " << nodep << endl);
|
||||||
AstNode* backp = nodep->backp(); // Only for debug
|
AstNode* backp = nodep->backp(); // Only for debug
|
||||||
if (debug()>=9) backp->dumpTree(cout, "- pre : ");
|
if (debug() >= 9) backp->dumpTree(cout, "- pre : ");
|
||||||
AstCFunc* funcp = createDeepFunc(nodep);
|
AstCFunc* funcp = createDeepFunc(nodep);
|
||||||
iterate(funcp);
|
iterate(funcp);
|
||||||
if (debug()>=9) backp->dumpTree(cout, "- post: ");
|
if (debug() >= 9) backp->dumpTree(cout, "- post: ");
|
||||||
if (debug()>=9) funcp->dumpTree(cout, "- func: ");
|
if (debug() >= 9) funcp->dumpTree(cout, "- func: ");
|
||||||
} else {
|
} else {
|
||||||
iterateChildren(nodep);
|
iterateChildren(nodep);
|
||||||
}
|
}
|
||||||
|
|
@ -135,9 +135,7 @@ public:
|
||||||
// DepthBlock class functions
|
// DepthBlock class functions
|
||||||
|
|
||||||
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()) {
|
||||||
|
|
@ -310,9 +309,7 @@ public:
|
||||||
// Descope class functions
|
// Descope class functions
|
||||||
|
|
||||||
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,16 +107,14 @@ 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();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
void EmitCInlines::emitInt() {
|
void EmitCInlines::emitInt() {
|
||||||
string filename = v3Global.opt.makeDir()+"/"+topClassName()+"__Inlines.h";
|
string filename = v3Global.opt.makeDir() + "/" + topClassName() + "__Inlines.h";
|
||||||
newCFile(filename, false/*slow*/, false/*source*/);
|
newCFile(filename, false /*slow*/, false /*source*/);
|
||||||
V3OutCFile hf (filename);
|
V3OutCFile hf(filename);
|
||||||
m_ofp = &hf;
|
m_ofp = &hf;
|
||||||
|
|
||||||
ofp()->putsHeader();
|
ofp()->putsHeader();
|
||||||
|
|
|
||||||
|
|
@ -28,10 +28,9 @@
|
||||||
class V3EmitV {
|
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,16 +110,18 @@ 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; }
|
||||||
void constRemoveXs(bool flag) { m_constRemoveXs = flag; }
|
void constRemoveXs(bool flag) { m_constRemoveXs = flag; }
|
||||||
string debugFilename(const string& nameComment, int newNumber=0) {
|
string debugFilename(const string& nameComment, int newNumber = 0) {
|
||||||
++m_debugFileNumber;
|
++m_debugFileNumber;
|
||||||
if (newNumber) m_debugFileNumber = newNumber;
|
if (newNumber) m_debugFileNumber = newNumber;
|
||||||
char digits[100]; sprintf(digits, "%03d", m_debugFileNumber);
|
char digits[100];
|
||||||
return opt.makeDir()+"/"+opt.prefix()+"_"+digits+"_"+nameComment;
|
sprintf(digits, "%03d", m_debugFileNumber);
|
||||||
|
return opt.makeDir() + "/" + opt.prefix() + "_" + digits + "_" + nameComment;
|
||||||
}
|
}
|
||||||
bool needC11() const { return m_needC11; }
|
bool needC11() const { return m_needC11; }
|
||||||
void needC11(bool flag) { m_needC11 = flag; }
|
void needC11(bool flag) { m_needC11 = flag; }
|
||||||
|
|
|
||||||
137
src/V3Graph.h
137
src/V3Graph.h
|
|
@ -47,19 +47,23 @@ typedef bool (*V3EdgeFuncP)(const V3GraphEdge* edgep);
|
||||||
|
|
||||||
class GraphWay {
|
class GraphWay {
|
||||||
public:
|
public:
|
||||||
enum en { FORWARD=0,
|
enum en {
|
||||||
REVERSE=1,
|
FORWARD = 0,
|
||||||
NUM_WAYS=2 // NUM_WAYS is not an actual way, it's typically
|
REVERSE = 1,
|
||||||
// // an array dimension or loop bound.
|
NUM_WAYS = 2 // NUM_WAYS is not an actual way, it's typically
|
||||||
|
// // 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"};
|
||||||
return names[m_e];
|
return names[m_e];
|
||||||
}
|
}
|
||||||
// METHODS unique to this class
|
// METHODS unique to this class
|
||||||
|
|
@ -78,12 +82,14 @@ 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();
|
||||||
void acyclicDFSIterate(V3GraphVertex *vertexp, int depth, uint32_t currentRank);
|
void acyclicDFSIterate(V3GraphVertex* vertexp, int depth, uint32_t currentRank);
|
||||||
void acyclicCut();
|
void acyclicCut();
|
||||||
void acyclicLoop(V3GraphVertex* vertexp, int depth);
|
void acyclicLoop(V3GraphVertex* vertexp, int depth);
|
||||||
double orderDFSIterate(V3GraphVertex* vertexp);
|
double orderDFSIterate(V3GraphVertex* vertexp);
|
||||||
|
|
@ -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();
|
||||||
|
|
@ -163,10 +170,10 @@ public:
|
||||||
void subtreeLoops(V3EdgeFuncP edgeFuncp, V3GraphVertex* vertexp, V3Graph* loopGraphp);
|
void subtreeLoops(V3EdgeFuncP edgeFuncp, V3GraphVertex* vertexp, V3Graph* loopGraphp);
|
||||||
|
|
||||||
/// Debugging
|
/// Debugging
|
||||||
void dump(std::ostream& os=std::cout);
|
void dump(std::ostream& os = std::cout);
|
||||||
void dumpDotFile(const string& filename, bool colorAsSubgraph) const;
|
void dumpDotFile(const string& filename, bool colorAsSubgraph) const;
|
||||||
void dumpDotFilePrefixed(const string& nameComment, bool colorAsSubgraph=false) const;
|
void dumpDotFilePrefixed(const string& nameComment, bool colorAsSubgraph = false) const;
|
||||||
void dumpDotFilePrefixedAlways(const string& nameComment, bool colorAsSubgraph=false) const;
|
void dumpDotFilePrefixedAlways(const string& nameComment, bool colorAsSubgraph = false) const;
|
||||||
void userClearVertices();
|
void userClearVertices();
|
||||||
void userClearEdges();
|
void userClearEdges();
|
||||||
static void selfTest();
|
static void selfTest();
|
||||||
|
|
@ -181,17 +188,19 @@ 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
|
||||||
double m_fanout; // Order fanout
|
double m_fanout; // Order fanout
|
||||||
uint32_t m_color; // Color of the node
|
uint32_t m_color; // Color of the node
|
||||||
uint32_t m_rank; // Rank of edge
|
uint32_t m_rank; // Rank of edge
|
||||||
union {
|
union {
|
||||||
void* m_userp; // Marker for some algorithms
|
void* m_userp; // Marker for some algorithms
|
||||||
uint32_t m_user; // Marker for some algorithms
|
uint32_t m_user; // Marker for some algorithms
|
||||||
};
|
};
|
||||||
// METHODS
|
// METHODS
|
||||||
void verticesPushBack(V3Graph* graphp);
|
void verticesPushBack(V3Graph* graphp);
|
||||||
|
|
@ -202,14 +211,16 @@ 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);
|
||||||
|
|
||||||
// ACCESSORS
|
// ACCESSORS
|
||||||
virtual string name() const { return ""; }
|
virtual string name() const { return ""; }
|
||||||
|
|
@ -227,27 +238,26 @@ public:
|
||||||
if (m_fanout > rhsp->m_fanout) return 1;
|
if (m_fanout > rhsp->m_fanout) return 1;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
uint32_t color() const { return m_color; }
|
uint32_t color() const { return m_color; }
|
||||||
void color(uint32_t color) { m_color = color; }
|
void color(uint32_t color) { m_color = color; }
|
||||||
uint32_t rank() const { return m_rank; }
|
uint32_t rank() const { return m_rank; }
|
||||||
void rank(uint32_t rank) { m_rank = rank; }
|
void rank(uint32_t rank) { m_rank = rank; }
|
||||||
double fanout() const { return m_fanout; }
|
double fanout() const { return m_fanout; }
|
||||||
void user(uint32_t user) { m_user = user; }
|
void user(uint32_t user) { m_user = user; }
|
||||||
uint32_t user() const { return m_user; }
|
uint32_t user() const { return m_user; }
|
||||||
void userp(void* userp) { m_userp = userp; }
|
void userp(void* userp) { m_userp = userp; }
|
||||||
void* userp() const { return m_userp; }
|
void* userp() const { return m_userp; }
|
||||||
// ITERATORS
|
// ITERATORS
|
||||||
V3GraphVertex* verticesNextp() const { return m_vertices.nextp(); }
|
V3GraphVertex* verticesNextp() const { return m_vertices.nextp(); }
|
||||||
V3GraphEdge* inBeginp() const { return m_ins.begin(); }
|
V3GraphEdge* inBeginp() const { return m_ins.begin(); }
|
||||||
bool inEmpty() const { return inBeginp()==NULL; }
|
bool inEmpty() const { return inBeginp() == NULL; }
|
||||||
bool inSize1() const;
|
bool inSize1() const;
|
||||||
uint32_t inHash() const;
|
uint32_t inHash() const;
|
||||||
V3GraphEdge* outBeginp() const { return m_outs.begin(); }
|
V3GraphEdge* outBeginp() const { return m_outs.begin(); }
|
||||||
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,22 +279,24 @@ 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;
|
||||||
V3ListEnt<V3GraphEdge*> m_outs; // Next Outbound edge for same vertex (linked list)
|
friend class GraphAcyc;
|
||||||
V3ListEnt<V3GraphEdge*> m_ins; // Next Inbound edge for same vertex (linked list)
|
friend class GraphAcycEdge;
|
||||||
|
V3ListEnt<V3GraphEdge*> m_outs; // Next Outbound edge for same vertex (linked list)
|
||||||
|
V3ListEnt<V3GraphEdge*> m_ins; // Next Inbound edge for same vertex (linked list)
|
||||||
//
|
//
|
||||||
V3GraphVertex* m_fromp; // Vertices pointing to this edge
|
V3GraphVertex* m_fromp; // Vertices pointing to this edge
|
||||||
V3GraphVertex* m_top; // Vertices this edge points to
|
V3GraphVertex* m_top; // Vertices this edge points to
|
||||||
int m_weight; // Weight of the connection
|
int m_weight; // Weight of the connection
|
||||||
bool m_cutable; // Interconnect may be broken in order sorting
|
bool m_cutable; // Interconnect may be broken in order sorting
|
||||||
union {
|
union {
|
||||||
void* m_userp; // Marker for some algorithms
|
void* m_userp; // Marker for some algorithms
|
||||||
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,21 +306,23 @@ 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(); }
|
||||||
virtual string dotLabel() const { return ""; }
|
virtual string dotLabel() const { return ""; }
|
||||||
virtual string dotColor() const { return cutable()?"yellowGreen":"red"; }
|
virtual string dotColor() const { return cutable() ? "yellowGreen" : "red"; }
|
||||||
virtual string dotStyle() const { return cutable()?"dashed":""; }
|
virtual string dotStyle() const { return cutable() ? "dashed" : ""; }
|
||||||
virtual int sortCmp(const V3GraphEdge* rhsp) const {
|
virtual int sortCmp(const V3GraphEdge* rhsp) const {
|
||||||
if (!m_weight || !rhsp->m_weight) return 0;
|
if (!m_weight || !rhsp->m_weight) return 0;
|
||||||
return top()->sortCmp(rhsp->top());
|
return top()->sortCmp(rhsp->top());
|
||||||
|
|
@ -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");
|
||||||
|
|
@ -60,11 +60,11 @@ class GraphNfaToDfa : GraphAlg<> {
|
||||||
private:
|
private:
|
||||||
// TYPES
|
// TYPES
|
||||||
typedef std::deque<DfaVertex*> DfaStates;
|
typedef std::deque<DfaVertex*> DfaStates;
|
||||||
typedef std::multimap<vluint64_t,DfaVertex*> HashMap;
|
typedef std::multimap<vluint64_t, DfaVertex*> HashMap;
|
||||||
|
|
||||||
// MEMBERS
|
// MEMBERS
|
||||||
uint32_t m_step; // Processing step, so we can avoid clearUser all the time
|
uint32_t m_step; // Processing step, so we can avoid clearUser all the time
|
||||||
HashMap m_hashMap; // Dfa Vertex for each set of NFA vertexes
|
HashMap m_hashMap; // Dfa Vertex for each set of NFA vertexes
|
||||||
|
|
||||||
#ifdef VL_CPPCHECK
|
#ifdef VL_CPPCHECK
|
||||||
static int debug() { return 9; }
|
static int debug() { return 9; }
|
||||||
|
|
@ -74,29 +74,37 @@ private:
|
||||||
|
|
||||||
// METHODS
|
// METHODS
|
||||||
DfaGraph* graphp() { return static_cast<DfaGraph*>(m_graphp); }
|
DfaGraph* graphp() { return static_cast<DfaGraph*>(m_graphp); }
|
||||||
bool nfaState(V3GraphVertex* vertexp) { return vertexp->color()==0; }
|
bool nfaState(V3GraphVertex* vertexp) { return vertexp->color() == 0; }
|
||||||
//bool dfaState(V3GraphVertex* vertexp) { return vertexp->color()==1; }
|
// bool dfaState(V3GraphVertex* vertexp) { return vertexp->color()==1; }
|
||||||
|
|
||||||
void nextStep() { m_step++; }
|
void nextStep() { m_step++; }
|
||||||
|
|
||||||
bool unseenNfaThisStep(V3GraphVertex* vertexp) {
|
bool unseenNfaThisStep(V3GraphVertex* vertexp) {
|
||||||
// A nfa node not already seen this processing step
|
// A nfa node not already seen this processing step
|
||||||
return (nfaState(vertexp) && !(vertexp->user()==m_step));
|
return (nfaState(vertexp) && !(vertexp->user() == m_step));
|
||||||
}
|
}
|
||||||
|
|
||||||
DfaVertex* newDfaVertex(DfaVertex* nfaTemplatep=NULL) {
|
DfaVertex* newDfaVertex(DfaVertex* nfaTemplatep = NULL) {
|
||||||
DfaVertex* vertexp = new DfaVertex(graphp());
|
DfaVertex* vertexp = new DfaVertex(graphp());
|
||||||
vertexp->color(1); // Mark as dfa
|
vertexp->color(1); // Mark as dfa
|
||||||
if (nfaTemplatep && nfaTemplatep->start()) vertexp->start(true);
|
if (nfaTemplatep && nfaTemplatep->start()) vertexp->start(true);
|
||||||
if (nfaTemplatep && nfaTemplatep->accepting()) vertexp->accepting(true);
|
if (nfaTemplatep && nfaTemplatep->accepting()) vertexp->accepting(true);
|
||||||
UINFO(9, " New "<<vertexp<<endl);
|
UINFO(9, " New " << vertexp << endl);
|
||||||
return vertexp;
|
return vertexp;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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++;
|
||||||
|
|
@ -174,39 +183,38 @@ private:
|
||||||
// not depend on order of edges
|
// not depend on order of edges
|
||||||
uint32_t hash = hashDfaOrigins(nfasWithInput);
|
uint32_t hash = hashDfaOrigins(nfasWithInput);
|
||||||
|
|
||||||
std::pair<HashMap::iterator,HashMap::iterator> eqrange = m_hashMap.equal_range(hash);
|
std::pair<HashMap::iterator, HashMap::iterator> eqrange = m_hashMap.equal_range(hash);
|
||||||
for (HashMap::iterator it = eqrange.first; it != eqrange.second; ++it) {
|
for (HashMap::iterator it = eqrange.first; it != eqrange.second; ++it) {
|
||||||
DfaVertex* testp = it->second;
|
DfaVertex* testp = it->second;
|
||||||
if (compareDfaOrigins(nfasWithInput, testp)) {
|
if (compareDfaOrigins(nfasWithInput, testp)) {
|
||||||
UINFO(9," DFA match for set: "<<testp<<endl);
|
UINFO(9, " DFA match for set: " << testp << endl);
|
||||||
return testp; // Identical
|
return testp; // Identical
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
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());
|
||||||
if (unseenNfaThisStep(nextStatep)) { // Not processed?
|
if (unseenNfaThisStep(nextStatep)) { // Not processed?
|
||||||
nfasWithInput.push_back(nextStatep);
|
nfasWithInput.push_back(nextStatep);
|
||||||
nextStatep->user(m_step);
|
nextStatep->user(m_step);
|
||||||
UINFO(9," Reachable "<<nextStatep<<endl);
|
UINFO(9, " Reachable " << nextStatep << endl);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -219,18 +227,19 @@ 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());
|
||||||
if (unseenNfaThisStep(nextStatep)) { // Not processed?
|
if (unseenNfaThisStep(nextStatep)) { // Not processed?
|
||||||
nfasTodo.push_back(nextStatep);
|
nfasTodo.push_back(nextStatep);
|
||||||
nextStatep->user(m_step);
|
nextStatep->user(m_step);
|
||||||
UINFO(9," Epsilon Reachable "<<nextStatep<<endl);
|
UINFO(9, " Epsilon Reachable " << nextStatep << endl);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -239,13 +248,13 @@ private:
|
||||||
}
|
}
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
UINFO(5,"Dfa to Nfa conversion...\n");
|
UINFO(5, "Dfa to Nfa conversion...\n");
|
||||||
// Vertex::color() begin: 1 indicates vertex on DFA graph, 0=NFA graph
|
// Vertex::color() begin: 1 indicates vertex on DFA graph, 0=NFA graph
|
||||||
m_graphp->clearColors();
|
m_graphp->clearColors();
|
||||||
// Vertex::m_user begin: # indicates processed this m_step number
|
// Vertex::m_user begin: # indicates processed this m_step number
|
||||||
m_graphp->userClearVertices();
|
m_graphp->userClearVertices();
|
||||||
|
|
||||||
if (debug()>=6) m_graphp->dumpDotFilePrefixed("dfa_nfa");
|
if (debug() >= 6) m_graphp->dumpDotFilePrefixed("dfa_nfa");
|
||||||
|
|
||||||
// Find NFA start
|
// Find NFA start
|
||||||
DfaVertex* nfaStartp = graphp()->findStart();
|
DfaVertex* nfaStartp = graphp()->findStart();
|
||||||
|
|
@ -256,55 +265,58 @@ private:
|
||||||
DfaStates dfaUnprocps; // Unprocessed DFA nodes
|
DfaStates dfaUnprocps; // Unprocessed DFA nodes
|
||||||
dfaUnprocps.push_back(dfaStartp);
|
dfaUnprocps.push_back(dfaStartp);
|
||||||
|
|
||||||
UINFO(5,"Starting state conversion...\n");
|
UINFO(5, "Starting state conversion...\n");
|
||||||
// Form DFA starting state from epsilon closure of NFA start
|
// 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();
|
||||||
//UINFO(9," Processing "<<nfaStatep<<endl);
|
workps.pop_back();
|
||||||
|
// 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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (debug()>=6) m_graphp->dumpDotFilePrefixed("dfa_start");
|
if (debug() >= 6) m_graphp->dumpDotFilePrefixed("dfa_start");
|
||||||
insertDfaOrigins(dfaStartp);
|
insertDfaOrigins(dfaStartp);
|
||||||
|
|
||||||
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();
|
||||||
UINFO(9," On dfaState "<<dfaStatep<<endl);
|
dfaUnprocps.pop_back();
|
||||||
|
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,14 +324,15 @@ 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);
|
||||||
|
|
||||||
// Find all states reachable for given input
|
// Find all states reachable for given input
|
||||||
DfaStates nfasWithInput;
|
DfaStates nfasWithInput;
|
||||||
findNfasWithInput(dfaStatep, input, nfasWithInput/*ref*/);
|
findNfasWithInput(dfaStatep, input, nfasWithInput /*ref*/);
|
||||||
|
|
||||||
// nfasWithInput now maps to the DFA we want a transition to.
|
// nfasWithInput now maps to the DFA we want a transition to.
|
||||||
// Does a DFA already exist with this, and only this subset of NFA's?
|
// Does a DFA already exist with this, and only this subset of NFA's?
|
||||||
|
|
@ -329,9 +342,9 @@ private:
|
||||||
toDfaStatep = newDfaVertex();
|
toDfaStatep = newDfaVertex();
|
||||||
dfaUnprocps.push_back(toDfaStatep); // Add to process list
|
dfaUnprocps.push_back(toDfaStatep); // Add to process list
|
||||||
// Track what nfa's point to it.
|
// Track what nfa's point to it.
|
||||||
for (DfaStates::const_iterator nfaIt=nfasWithInput.begin();
|
for (DfaStates::const_iterator nfaIt = nfasWithInput.begin();
|
||||||
nfaIt!=nfasWithInput.end(); ++nfaIt) {
|
nfaIt != nfasWithInput.end(); ++nfaIt) {
|
||||||
UINFO(9," NewContainsNfa "<<*nfaIt<<endl);
|
UINFO(9, " NewContainsNfa " << *nfaIt << endl);
|
||||||
new DfaEdge(graphp(), toDfaStatep, *nfaIt, DfaEdge::NA());
|
new DfaEdge(graphp(), toDfaStatep, *nfaIt, DfaEdge::NA());
|
||||||
if ((*nfaIt)->accepting()) toDfaStatep->accepting(true);
|
if ((*nfaIt)->accepting()) toDfaStatep->accepting(true);
|
||||||
}
|
}
|
||||||
|
|
@ -340,22 +353,21 @@ private:
|
||||||
// Add input transition
|
// Add input transition
|
||||||
new DfaEdge(graphp(), dfaStatep, toDfaStatep, input);
|
new DfaEdge(graphp(), dfaStatep, toDfaStatep, input);
|
||||||
|
|
||||||
if (debug()>=6) m_graphp->dumpDotFilePrefixed("step");
|
if (debug() >= 6) m_graphp->dumpDotFilePrefixed("step");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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");
|
||||||
if (debug()>=6) m_graphp->dumpDotFilePrefixed("dfa_done");
|
if (debug() >= 6) m_graphp->dumpDotFilePrefixed("dfa_done");
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
@ -367,9 +379,7 @@ public:
|
||||||
~GraphNfaToDfa() {}
|
~GraphNfaToDfa() {}
|
||||||
};
|
};
|
||||||
|
|
||||||
void DfaGraph::nfaToDfa() {
|
void DfaGraph::nfaToDfa() { GraphNfaToDfa(this, &V3GraphEdge::followAlwaysTrue); }
|
||||||
GraphNfaToDfa(this, &V3GraphEdge::followAlwaysTrue);
|
|
||||||
}
|
|
||||||
|
|
||||||
//######################################################################
|
//######################################################################
|
||||||
//######################################################################
|
//######################################################################
|
||||||
|
|
@ -390,7 +400,7 @@ private:
|
||||||
bool isDead(DfaVertex* vertexp) {
|
bool isDead(DfaVertex* vertexp) {
|
||||||
// A state is dead if not accepting, and goes nowhere
|
// A state is dead if not accepting, and goes nowhere
|
||||||
if (vertexp->accepting() || vertexp->start()) return false;
|
if (vertexp->accepting() || vertexp->start()) return false;
|
||||||
for (V3GraphEdge* edgep = vertexp->outBeginp(); edgep; edgep=edgep->outNextp()) {
|
for (V3GraphEdge* edgep = vertexp->outBeginp(); edgep; edgep = edgep->outNextp()) {
|
||||||
if (edgep->top() != vertexp) return false;
|
if (edgep->top() != vertexp) return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
|
@ -399,11 +409,11 @@ 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) {
|
||||||
nextp = edgep->outNextp();
|
nextp = edgep->outNextp();
|
||||||
VL_DO_DANGLING(edgep->unlinkDelete(), edgep);
|
VL_DO_DANGLING(edgep->unlinkDelete(), edgep);
|
||||||
}
|
}
|
||||||
|
|
@ -421,14 +431,16 @@ 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()) {
|
||||||
V3GraphVertex* tovertexp = edgep->top();
|
V3GraphVertex* tovertexp = edgep->top();
|
||||||
if (!tovertexp->user()) {
|
if (!tovertexp->user()) {
|
||||||
workps.push(tovertexp);
|
workps.push(tovertexp);
|
||||||
|
|
@ -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,23 +498,22 @@ private:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
DfaGraphReduce(V3Graph* graphp, V3EdgeFuncP edgeFuncp)
|
DfaGraphReduce(V3Graph* graphp, V3EdgeFuncP edgeFuncp)
|
||||||
: GraphAlg<>(graphp, edgeFuncp) {
|
: GraphAlg<>(graphp, edgeFuncp) {
|
||||||
if (debug()>=6) m_graphp->dumpDotFilePrefixed("opt_in");
|
if (debug() >= 6) m_graphp->dumpDotFilePrefixed("opt_in");
|
||||||
optimize_accepting_out();
|
optimize_accepting_out();
|
||||||
if (debug()>=6) m_graphp->dumpDotFilePrefixed("opt_acc");
|
if (debug() >= 6) m_graphp->dumpDotFilePrefixed("opt_acc");
|
||||||
optimize_orphans();
|
optimize_orphans();
|
||||||
if (debug()>=6) m_graphp->dumpDotFilePrefixed("opt_orph");
|
if (debug() >= 6) m_graphp->dumpDotFilePrefixed("opt_orph");
|
||||||
optimize_no_outbound();
|
optimize_no_outbound();
|
||||||
if (debug()>=6) m_graphp->dumpDotFilePrefixed("opt_noout");
|
if (debug() >= 6) m_graphp->dumpDotFilePrefixed("opt_noout");
|
||||||
}
|
}
|
||||||
~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,12 +559,12 @@ 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) {
|
||||||
for (V3GraphEdge* nextp, *edgep = vertexp->outBeginp(); edgep; edgep=nextp) {
|
for (V3GraphEdge *nextp, *edgep = vertexp->outBeginp(); edgep; edgep = nextp) {
|
||||||
nextp = edgep->outNextp();
|
nextp = edgep->outNextp();
|
||||||
if (!edgep->user()) { // Not processed
|
if (!edgep->user()) { // Not processed
|
||||||
// Old edges to accept now go to new reject
|
// Old edges to accept now go to new reject
|
||||||
|
|
@ -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,25 +590,24 @@ private:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
DfaGraphComplement(V3Graph* dfagraphp, V3EdgeFuncP edgeFuncp)
|
DfaGraphComplement(V3Graph* dfagraphp, V3EdgeFuncP edgeFuncp)
|
||||||
: GraphAlg<>(dfagraphp, edgeFuncp) {
|
: GraphAlg<>(dfagraphp, edgeFuncp) {
|
||||||
if (debug()>=6) m_graphp->dumpDotFilePrefixed("comp_in");
|
if (debug() >= 6) m_graphp->dumpDotFilePrefixed("comp_in");
|
||||||
|
|
||||||
// Vertex::m_user begin: 1 indicates new edge, no more processing
|
// Vertex::m_user begin: 1 indicates new edge, no more processing
|
||||||
m_graphp->userClearEdges();
|
m_graphp->userClearEdges();
|
||||||
|
|
||||||
m_tempNewerReject = new DfaVertex(graphp());
|
m_tempNewerReject = new DfaVertex(graphp());
|
||||||
add_complement_edges();
|
add_complement_edges();
|
||||||
if (debug()>=6) m_graphp->dumpDotFilePrefixed("comp_preswap");
|
if (debug() >= 6) m_graphp->dumpDotFilePrefixed("comp_preswap");
|
||||||
|
|
||||||
VL_DO_CLEAR(m_tempNewerReject->unlinkDelete(graphp()), m_tempNewerReject = NULL);
|
VL_DO_CLEAR(m_tempNewerReject->unlinkDelete(graphp()), m_tempNewerReject = NULL);
|
||||||
if (debug()>=6) m_graphp->dumpDotFilePrefixed("comp_out");
|
if (debug() >= 6) m_graphp->dumpDotFilePrefixed("comp_out");
|
||||||
}
|
}
|
||||||
~DfaGraphComplement() {}
|
~DfaGraphComplement() {}
|
||||||
VL_UNCOPYABLE(DfaGraphComplement);
|
VL_UNCOPYABLE(DfaGraphComplement);
|
||||||
};
|
};
|
||||||
|
|
||||||
void DfaGraph::dfaComplement() {
|
void DfaGraph::dfaComplement() { DfaGraphComplement(this, &V3GraphEdge::followAlwaysTrue); }
|
||||||
DfaGraphComplement(this, &V3GraphEdge::followAlwaysTrue);
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -85,16 +85,18 @@ class DfaVertex : public V3GraphVertex {
|
||||||
bool m_accepting; // Accepting state?
|
bool m_accepting; // Accepting state?
|
||||||
public:
|
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" : ""); }
|
||||||
virtual string dotColor() const { return start()?"blue":(color()?"red":"black"); }
|
virtual string dotColor() const { return start() ? "blue" : (color() ? "red" : "black"); }
|
||||||
bool start() const { return m_start; }
|
bool start() const { return m_start; }
|
||||||
void start(bool flag) { m_start = flag; }
|
void start(bool flag) { m_start = flag; }
|
||||||
bool accepting() const { return m_accepting; }
|
bool accepting() const { return m_accepting; }
|
||||||
|
|
@ -118,24 +120,24 @@ 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":""; }
|
}
|
||||||
bool epsilon() const { return input().toInt()==EPSILON().toInt(); }
|
virtual string dotStyle() const { return (na() || cutable()) ? "dashed" : ""; }
|
||||||
bool na() const { return input().toInt()==NA().toInt(); }
|
bool epsilon() const { return input().toInt() == EPSILON().toInt(); }
|
||||||
|
bool na() const { return input().toInt() == NA().toInt(); }
|
||||||
bool complement() const { return m_complement; }
|
bool complement() const { return m_complement; }
|
||||||
void complement(bool value) { m_complement = value; }
|
void complement(bool value) { m_complement = value; }
|
||||||
DfaInput input() const { return m_input; }
|
DfaInput input() const { return m_input; }
|
||||||
|
|
|
||||||
|
|
@ -41,10 +41,11 @@ 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;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -70,11 +70,12 @@ private:
|
||||||
explicit VxHolderCmp(const T_Compare& lessThan)
|
explicit VxHolderCmp(const T_Compare& lessThan)
|
||||||
: m_lessThan(lessThan) {}
|
: m_lessThan(lessThan) {}
|
||||||
// METHODS
|
// METHODS
|
||||||
bool operator() (const VxHolder& a, const VxHolder& b) const {
|
bool operator()(const VxHolder& a, const VxHolder& b) const {
|
||||||
if (m_lessThan.operator()(a.vertexp(), b.vertexp())) return true;
|
if (m_lessThan.operator()(a.vertexp(), b.vertexp())) return true;
|
||||||
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()) {
|
||||||
|
|
|
||||||
|
|
@ -50,8 +50,9 @@ class V3Hashed : public VHashedBase {
|
||||||
|
|
||||||
// TYPES
|
// TYPES
|
||||||
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,17 +68,21 @@ 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
|
||||||
// Return duplicate in hash, if any, with optional user check for sameness
|
// Return duplicate in hash, if any, with optional user check for sameness
|
||||||
iterator findDuplicate(AstNode* nodep, V3HashedUserSame* checkp=NULL);
|
iterator findDuplicate(AstNode* nodep, V3HashedUserSame* checkp = NULL);
|
||||||
AstNode* iteratorNodep(iterator it) { return it->second; }
|
AstNode* iteratorNodep(iterator it) { return it->second; }
|
||||||
void dumpFile(const string& filename, bool tree);
|
void dumpFile(const string& filename, bool tree);
|
||||||
void dumpFilePrefixed(const string& nameComment, bool tree=false);
|
void dumpFilePrefixed(const string& nameComment, bool tree = false);
|
||||||
static V3Hash nodeHash(AstNode* nodep) { return V3Hash(nodep->user4p()); }
|
static V3Hash nodeHash(AstNode* nodep) { return V3Hash(nodep->user4p()); }
|
||||||
// Hash of the nodep tree, without caching in user4.
|
// Hash of the nodep tree, without caching in user4.
|
||||||
static V3Hash uncachedHash(const AstNode* nodep);
|
static V3Hash uncachedHash(const AstNode* nodep);
|
||||||
|
|
|
||||||
|
|
@ -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() {}
|
||||||
|
|
@ -98,7 +98,7 @@ private:
|
||||||
// collisions in CFuncs.
|
// collisions in CFuncs.
|
||||||
UASSERT_OBJ(!nodep->user5p(), nodep,
|
UASSERT_OBJ(!nodep->user5p(), nodep,
|
||||||
"Node originally inserted below logic vertex "
|
"Node originally inserted below logic vertex "
|
||||||
<<static_cast<AstNode*>(nodep->user5p()));
|
<< static_cast<AstNode*>(nodep->user5p()));
|
||||||
nodep->user5p(const_cast<void*>(reinterpret_cast<const void*>(m_startNodep)));
|
nodep->user5p(const_cast<void*>(reinterpret_cast<const void*>(m_startNodep)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -110,13 +110,12 @@ 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;
|
||||||
}
|
}
|
||||||
void markCost(AstNode* nodep) {
|
void markCost(AstNode* nodep) {
|
||||||
if (m_osp) nodep->user4(m_instrCount+1); // Else don't mark to avoid writeback
|
if (m_osp) nodep->user4(m_instrCount + 1); // Else don't mark to avoid writeback
|
||||||
}
|
}
|
||||||
|
|
||||||
// VISITORS
|
// VISITORS
|
||||||
|
|
@ -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);
|
||||||
|
|
@ -284,13 +284,12 @@ public:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// METHODS
|
// METHODS
|
||||||
string indent() { return string(m_depth, ':')+" "; }
|
string indent() { return string(m_depth, ':') + " "; }
|
||||||
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);
|
||||||
}
|
}
|
||||||
--m_depth;
|
--m_depth;
|
||||||
|
|
|
||||||
|
|
@ -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; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -26,17 +26,16 @@
|
||||||
|
|
||||||
class V3LanguageWords {
|
class V3LanguageWords {
|
||||||
// List of common reserved keywords
|
// List of common reserved keywords
|
||||||
private:
|
private:
|
||||||
typedef std::map<string,string> KeywordMap;
|
typedef std::map<string, string> KeywordMap;
|
||||||
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
|
||||||
static const_iterator begin() { return s().s_kwdMap.begin(); }
|
static const_iterator begin() { return s().s_kwdMap.begin(); }
|
||||||
|
|
@ -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,25 +31,26 @@ 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);
|
||||||
linkDotGuts(nodep,LDS_PRIMARY);
|
linkDotGuts(nodep, LDS_PRIMARY);
|
||||||
V3Global::dumpCheckGlobalTree("linkdot", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 6);
|
V3Global::dumpCheckGlobalTree("linkdot", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 6);
|
||||||
}
|
}
|
||||||
static void linkDotParamed(AstNetlist* nodep) {
|
static void linkDotParamed(AstNetlist* nodep) {
|
||||||
UINFO(2,__FUNCTION__<<": "<<endl);
|
UINFO(2, __FUNCTION__ << ": " << endl);
|
||||||
linkDotGuts(nodep,LDS_PARAMED);
|
linkDotGuts(nodep, LDS_PARAMED);
|
||||||
V3Global::dumpCheckGlobalTree("paramlink", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
|
V3Global::dumpCheckGlobalTree("paramlink", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
|
||||||
}
|
}
|
||||||
static void linkDotArrayed(AstNetlist* nodep) {
|
static void linkDotArrayed(AstNetlist* nodep) {
|
||||||
UINFO(2,__FUNCTION__<<": "<<endl);
|
UINFO(2, __FUNCTION__ << ": " << endl);
|
||||||
linkDotGuts(nodep,LDS_ARRAYED);
|
linkDotGuts(nodep, LDS_ARRAYED);
|
||||||
V3Global::dumpCheckGlobalTree("linkdot", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 6);
|
V3Global::dumpCheckGlobalTree("linkdot", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 6);
|
||||||
}
|
}
|
||||||
static void linkDotScope(AstNetlist* nodep) {
|
static void linkDotScope(AstNetlist* nodep) {
|
||||||
UINFO(2,__FUNCTION__<<": "<<endl);
|
UINFO(2, __FUNCTION__ << ": " << endl);
|
||||||
linkDotGuts(nodep,LDS_SCOPED);
|
linkDotGuts(nodep, LDS_SCOPED);
|
||||||
V3Global::dumpCheckGlobalTree("linkdot", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
|
V3Global::dumpCheckGlobalTree("linkdot", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -38,8 +38,8 @@ private:
|
||||||
// NODE STATE
|
// NODE STATE
|
||||||
|
|
||||||
// STATE
|
// STATE
|
||||||
bool m_setRefLvalue; // Set VarRefs to lvalues for pin assignments
|
bool m_setRefLvalue; // Set VarRefs to lvalues for pin assignments
|
||||||
AstNodeFTask* m_ftaskp; // Function or task we're inside
|
AstNodeFTask* m_ftaskp; // Function or task we're inside
|
||||||
|
|
||||||
// METHODS
|
// METHODS
|
||||||
VL_DEBUG_FUNC; // Declare debug()
|
VL_DEBUG_FUNC; // Declare debug()
|
||||||
|
|
@ -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);
|
||||||
|
|
@ -223,7 +220,7 @@ private:
|
||||||
}
|
}
|
||||||
virtual void visit(AstNodeSel* nodep) VL_OVERRIDE {
|
virtual void visit(AstNodeSel* nodep) VL_OVERRIDE {
|
||||||
bool last_setRefLvalue = m_setRefLvalue;
|
bool last_setRefLvalue = m_setRefLvalue;
|
||||||
{ // Only set lvalues on the from
|
{ // Only set lvalues on the from
|
||||||
iterateAndNextNull(nodep->lhsp());
|
iterateAndNextNull(nodep->lhsp());
|
||||||
m_setRefLvalue = false;
|
m_setRefLvalue = false;
|
||||||
iterateAndNextNull(nodep->rhsp());
|
iterateAndNextNull(nodep->rhsp());
|
||||||
|
|
@ -232,7 +229,7 @@ private:
|
||||||
}
|
}
|
||||||
virtual void visit(AstCellArrayRef* nodep) VL_OVERRIDE {
|
virtual void visit(AstCellArrayRef* nodep) VL_OVERRIDE {
|
||||||
bool last_setRefLvalue = m_setRefLvalue;
|
bool last_setRefLvalue = m_setRefLvalue;
|
||||||
{ // selp is not an lvalue
|
{ // selp is not an lvalue
|
||||||
m_setRefLvalue = false;
|
m_setRefLvalue = false;
|
||||||
iterateAndNextNull(nodep->selp());
|
iterateAndNextNull(nodep->selp());
|
||||||
}
|
}
|
||||||
|
|
@ -240,7 +237,7 @@ private:
|
||||||
}
|
}
|
||||||
virtual void visit(AstNodePreSel* nodep) VL_OVERRIDE {
|
virtual void visit(AstNodePreSel* nodep) VL_OVERRIDE {
|
||||||
bool last_setRefLvalue = m_setRefLvalue;
|
bool last_setRefLvalue = m_setRefLvalue;
|
||||||
{ // Only set lvalues on the from
|
{ // Only set lvalues on the from
|
||||||
iterateAndNextNull(nodep->lhsp());
|
iterateAndNextNull(nodep->lhsp());
|
||||||
m_setRefLvalue = false;
|
m_setRefLvalue = false;
|
||||||
iterateAndNextNull(nodep->rhsp());
|
iterateAndNextNull(nodep->rhsp());
|
||||||
|
|
@ -258,7 +255,7 @@ private:
|
||||||
AstNodeFTask* taskp = nodep->taskp();
|
AstNodeFTask* taskp = nodep->taskp();
|
||||||
// We'll deal with mismatching pins later
|
// We'll deal with mismatching pins later
|
||||||
if (!taskp) return;
|
if (!taskp) return;
|
||||||
for (AstNode* stmtp = taskp->stmtsp(); stmtp && pinp; stmtp=stmtp->nextp()) {
|
for (AstNode* stmtp = taskp->stmtsp(); stmtp && pinp; stmtp = stmtp->nextp()) {
|
||||||
if (const AstVar* portp = VN_CAST(stmtp, Var)) {
|
if (const AstVar* portp = VN_CAST(stmtp, Var)) {
|
||||||
if (portp->isIO()) {
|
if (portp->isIO()) {
|
||||||
if (portp->isWritable()) {
|
if (portp->isWritable()) {
|
||||||
|
|
@ -291,15 +288,13 @@ public:
|
||||||
// Link class functions
|
// Link class functions
|
||||||
|
|
||||||
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) {
|
||||||
// Called by later link functions when it is known a node needs
|
// Called by later link functions when it is known a node needs
|
||||||
// to be converted to a lvalue.
|
// to be converted to a lvalue.
|
||||||
UINFO(9,__FUNCTION__<<": "<<endl);
|
UINFO(9, __FUNCTION__ << ": " << endl);
|
||||||
LinkLValueVisitor visitor(nodep, true);
|
LinkLValueVisitor visitor(nodep, true);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
37
src/V3List.h
37
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
|
||||||
|
|
@ -60,11 +63,13 @@ private:
|
||||||
// "this" must be a element inside of *basep
|
// "this" must be a element inside of *basep
|
||||||
// Use that to determine a structure offset, then apply to the new base
|
// Use that to determine a structure offset, then apply to the new base
|
||||||
// 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;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -52,10 +52,10 @@ protected:
|
||||||
// Per-variable flags
|
// Per-variable flags
|
||||||
// Used in user()'s so initializes to all zeros
|
// Used in user()'s so initializes to all zeros
|
||||||
struct {
|
struct {
|
||||||
int m_notOpt:1; // NOT optimizable
|
int m_notOpt : 1; // NOT optimizable
|
||||||
int m_notStd:1; // NOT optimizable if a non-blocktemp signal
|
int m_notStd : 1; // NOT optimizable if a non-blocktemp signal
|
||||||
int m_stdFuncAsn:1; // Found simple assignment
|
int m_stdFuncAsn : 1; // Found simple assignment
|
||||||
int m_done:1; // Removed
|
int m_done : 1; // Removed
|
||||||
};
|
};
|
||||||
// cppcheck-suppress unusedStructMember
|
// cppcheck-suppress unusedStructMember
|
||||||
uint32_t m_flags;
|
uint32_t m_flags;
|
||||||
|
|
@ -75,7 +75,7 @@ private:
|
||||||
// METHODS
|
// METHODS
|
||||||
virtual void visit(AstVarRef* nodep) VL_OVERRIDE {
|
virtual void visit(AstVarRef* nodep) VL_OVERRIDE {
|
||||||
// cppcheck-suppress unreadVariable // cppcheck 1.90 bug
|
// cppcheck-suppress unreadVariable // cppcheck 1.90 bug
|
||||||
VarFlags flags (nodep->varp());
|
VarFlags flags(nodep->varp());
|
||||||
if (flags.m_done) {
|
if (flags.m_done) {
|
||||||
nodep->hiername(""); // Remove this->
|
nodep->hiername(""); // Remove this->
|
||||||
nodep->hierThis(true);
|
nodep->hierThis(true);
|
||||||
|
|
@ -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() {}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -98,9 +96,9 @@ class LocalizeVisitor : public LocalizeBaseVisitor {
|
||||||
private:
|
private:
|
||||||
// NODE STATE/TYPES
|
// NODE STATE/TYPES
|
||||||
// See above
|
// See above
|
||||||
AstUser1InUse m_inuser1;
|
AstUser1InUse m_inuser1;
|
||||||
AstUser2InUse m_inuser2;
|
AstUser2InUse m_inuser2;
|
||||||
AstUser4InUse m_inuser4;
|
AstUser4InUse m_inuser4;
|
||||||
|
|
||||||
// STATE
|
// STATE
|
||||||
VDouble0 m_statLocVars; // Statistic tracking
|
VDouble0 m_statLocVars; // Statistic tracking
|
||||||
|
|
@ -109,14 +107,14 @@ private:
|
||||||
|
|
||||||
// METHODS
|
// METHODS
|
||||||
void clearOptimizable(AstVar* nodep, const char* reason) {
|
void clearOptimizable(AstVar* nodep, const char* reason) {
|
||||||
UINFO(4," NoOpt "<<reason<<" "<<nodep<<endl);
|
UINFO(4, " NoOpt " << reason << " " << nodep << endl);
|
||||||
VarFlags flags (nodep);
|
VarFlags flags(nodep);
|
||||||
flags.m_notOpt = true;
|
flags.m_notOpt = true;
|
||||||
flags.setNodeFlags(nodep);
|
flags.setNodeFlags(nodep);
|
||||||
}
|
}
|
||||||
void clearStdOptimizable(AstVar* nodep, const char* reason) {
|
void clearStdOptimizable(AstVar* nodep, const char* reason) {
|
||||||
UINFO(4," NoStd "<<reason<<" "<<nodep<<endl);
|
UINFO(4, " NoStd " << reason << " " << nodep << endl);
|
||||||
VarFlags flags (nodep);
|
VarFlags flags(nodep);
|
||||||
flags.m_notStd = true;
|
flags.m_notStd = true;
|
||||||
flags.setNodeFlags(nodep);
|
flags.setNodeFlags(nodep);
|
||||||
}
|
}
|
||||||
|
|
@ -125,15 +123,14 @@ private:
|
||||||
AstVar* nodep = *it;
|
AstVar* nodep = *it;
|
||||||
if (nodep->valuep()) clearOptimizable(nodep, "HasInitValue");
|
if (nodep->valuep()) clearOptimizable(nodep, "HasInitValue");
|
||||||
if (!VarFlags(nodep).m_stdFuncAsn) clearStdOptimizable(nodep, "NoStdAssign");
|
if (!VarFlags(nodep).m_stdFuncAsn) clearStdOptimizable(nodep, "NoStdAssign");
|
||||||
VarFlags flags (nodep);
|
VarFlags flags(nodep);
|
||||||
|
|
||||||
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;
|
||||||
AstCFunc* newfuncp = VN_CAST(nodep->user1p(), CFunc);
|
AstCFunc* newfuncp = VN_CAST(nodep->user1p(), CFunc);
|
||||||
nodep->unlinkFrBack();
|
nodep->unlinkFrBack();
|
||||||
|
|
@ -154,7 +151,7 @@ private:
|
||||||
moveVars();
|
moveVars();
|
||||||
}
|
}
|
||||||
virtual void visit(AstCFunc* nodep) VL_OVERRIDE {
|
virtual void visit(AstCFunc* nodep) VL_OVERRIDE {
|
||||||
UINFO(4," CFUNC "<<nodep<<endl);
|
UINFO(4, " CFUNC " << nodep << endl);
|
||||||
m_cfuncp = nodep;
|
m_cfuncp = nodep;
|
||||||
searchFuncStmts(nodep->argsp());
|
searchFuncStmts(nodep->argsp());
|
||||||
searchFuncStmts(nodep->initsp());
|
searchFuncStmts(nodep->initsp());
|
||||||
|
|
@ -168,14 +165,14 @@ private:
|
||||||
// For now we only find simple assignments not under any other statement.
|
// For now we only find simple assignments not under any other statement.
|
||||||
// This could be more complicated; allow always-set under both branches of a IF.
|
// This could be more complicated; allow always-set under both branches of a IF.
|
||||||
// If so, check for ArrayRef's and such, as they aren't acceptable.
|
// If so, check for ArrayRef's and such, as they aren't acceptable.
|
||||||
for (; nodep; nodep=nodep->nextp()) {
|
for (; nodep; nodep = nodep->nextp()) {
|
||||||
if (VN_IS(nodep, NodeAssign)) {
|
if (VN_IS(nodep, NodeAssign)) {
|
||||||
if (AstVarRef* varrefp = VN_CAST(VN_CAST(nodep, NodeAssign)->lhsp(), VarRef)) {
|
if (AstVarRef* varrefp = VN_CAST(VN_CAST(nodep, NodeAssign)->lhsp(), VarRef)) {
|
||||||
UASSERT_OBJ(varrefp->lvalue(), varrefp, "LHS assignment not lvalue");
|
UASSERT_OBJ(varrefp->lvalue(), varrefp, "LHS assignment not lvalue");
|
||||||
if (!varrefp->varp()->user4p()) {
|
if (!varrefp->varp()->user4p()) {
|
||||||
UINFO(4," FuncAsn "<<varrefp<<endl);
|
UINFO(4, " FuncAsn " << varrefp << endl);
|
||||||
varrefp->varp()->user4p(varrefp);
|
varrefp->varp()->user4p(varrefp);
|
||||||
VarFlags flags (varrefp->varp());
|
VarFlags flags(varrefp->varp());
|
||||||
flags.m_stdFuncAsn = true;
|
flags.m_stdFuncAsn = true;
|
||||||
flags.setNodeFlags(varrefp->varp());
|
flags.setNodeFlags(varrefp->varp());
|
||||||
}
|
}
|
||||||
|
|
@ -185,10 +182,9 @@ 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);
|
||||||
}
|
}
|
||||||
// No iterate; Don't want varrefs under it
|
// No iterate; Don't want varrefs under it
|
||||||
|
|
@ -197,14 +193,13 @@ 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
|
||||||
AstNode* oldfunc = nodep->varp()->user1p();
|
AstNode* oldfunc = nodep->varp()->user1p();
|
||||||
if (!oldfunc) {
|
if (!oldfunc) {
|
||||||
UINFO(4," BVnewref "<<nodep<<endl);
|
UINFO(4, " BVnewref " << nodep << endl);
|
||||||
nodep->varp()->user1p(m_cfuncp); // Remember where it was used
|
nodep->varp()->user1p(m_cfuncp); // Remember where it was used
|
||||||
} else if (m_cfuncp == oldfunc) {
|
} else if (m_cfuncp == oldfunc) {
|
||||||
// Same usage
|
// Same usage
|
||||||
|
|
@ -214,7 +209,7 @@ private:
|
||||||
}
|
}
|
||||||
// First varref in function must be assignment found earlier
|
// First varref in function must be assignment found earlier
|
||||||
AstVarRef* firstasn = static_cast<AstVarRef*>(nodep->varp()->user4p());
|
AstVarRef* firstasn = static_cast<AstVarRef*>(nodep->varp()->user4p());
|
||||||
if (firstasn && nodep!=firstasn) {
|
if (firstasn && nodep != firstasn) {
|
||||||
clearStdOptimizable(nodep->varp(), "notFirstAsn");
|
clearStdOptimizable(nodep->varp(), "notFirstAsn");
|
||||||
nodep->varp()->user4p(NULL);
|
nodep->varp()->user4p(NULL);
|
||||||
}
|
}
|
||||||
|
|
@ -239,11 +234,11 @@ public:
|
||||||
// Localize class functions
|
// Localize class functions
|
||||||
|
|
||||||
void V3Localize::localizeAll(AstNetlist* nodep) {
|
void V3Localize::localizeAll(AstNetlist* nodep) {
|
||||||
UINFO(2,__FUNCTION__<<": "<<endl);
|
UINFO(2, __FUNCTION__ << ": " << endl);
|
||||||
{
|
{
|
||||||
LocalizeVisitor visitor (nodep);
|
LocalizeVisitor visitor(nodep);
|
||||||
// Fix up hiernames
|
// Fix up hiernames
|
||||||
LocalizeDehierVisitor dvisitor (nodep);
|
LocalizeDehierVisitor dvisitor(nodep);
|
||||||
} // Destruct before checking
|
} // Destruct before checking
|
||||||
V3Global::dumpCheckGlobalTree("localize", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 6);
|
V3Global::dumpCheckGlobalTree("localize", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 6);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -41,11 +41,11 @@ private:
|
||||||
// AstCell::user1() -> bool. Set true if already processed
|
// AstCell::user1() -> bool. Set true if already processed
|
||||||
// AstScope::user1() -> bool. Set true if already processed
|
// AstScope::user1() -> bool. Set true if already processed
|
||||||
// AstVar::user1() -> bool. Set true if already processed
|
// AstVar::user1() -> bool. Set true if already processed
|
||||||
AstUser1InUse m_inuser1;
|
AstUser1InUse m_inuser1;
|
||||||
|
|
||||||
// STATE
|
// STATE
|
||||||
AstNodeModule* m_modp;
|
AstNodeModule* m_modp;
|
||||||
V3LanguageWords m_words; // Reserved word detector
|
V3LanguageWords m_words; // Reserved word detector
|
||||||
|
|
||||||
// METHODS
|
// METHODS
|
||||||
VL_DEBUG_FUNC; // Declare debug()
|
VL_DEBUG_FUNC; // Declare debug()
|
||||||
|
|
@ -53,16 +53,16 @@ private:
|
||||||
void rename(AstNode* nodep, bool addPvt) {
|
void rename(AstNode* nodep, bool addPvt) {
|
||||||
if (!nodep->user1()) { // Not already done
|
if (!nodep->user1()) { // Not already done
|
||||||
if (addPvt) {
|
if (addPvt) {
|
||||||
string newname = string("__PVT__")+nodep->name();
|
string newname = string("__PVT__") + nodep->name();
|
||||||
nodep->name(newname);
|
nodep->name(newname);
|
||||||
nodep->editCountInc();
|
nodep->editCountInc();
|
||||||
} else if (VN_IS(nodep, CFunc) && VN_CAST(nodep, CFunc)->isConstructor()) {
|
} else if (VN_IS(nodep, CFunc) && VN_CAST(nodep, CFunc)->isConstructor()) {
|
||||||
} 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,10 +83,10 @@ 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
|
||||||
}
|
}
|
||||||
virtual void visit(AstCFunc* nodep) VL_OVERRIDE {
|
virtual void visit(AstCFunc* nodep) VL_OVERRIDE {
|
||||||
if (!nodep->user1()) {
|
if (!nodep->user1()) {
|
||||||
|
|
@ -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()
|
||||||
: VN_IS(m_modp, Class) ? ("TOP." + m_modp->name())
|
? "TOP"
|
||||||
: VN_IS(m_modp, ClassPackage) ? ("TOP." + m_modp->name())
|
: VN_IS(m_modp, Class) ? ("TOP." + m_modp->name())
|
||||||
: (nodep->aboveScopep()->name() + "." + nodep->aboveCellp()->name()));
|
: VN_IS(m_modp, ClassPackage)
|
||||||
|
? ("TOP." + m_modp->name())
|
||||||
|
: (nodep->aboveScopep()->name() + "."
|
||||||
|
+ nodep->aboveCellp()->name()));
|
||||||
nodep->editCountInc();
|
nodep->editCountInc();
|
||||||
iterateChildren(nodep);
|
iterateChildren(nodep);
|
||||||
}
|
}
|
||||||
|
|
@ -150,9 +152,7 @@ public:
|
||||||
// Name class functions
|
// Name class functions
|
||||||
|
|
||||||
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);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -36,54 +36,83 @@ void test(const string& lhss, const string& op, const string& rhss, const string
|
||||||
|
|
||||||
FileLine fl = new FileLine(FileLine::builtInFinename());
|
FileLine fl = new FileLine(FileLine::builtInFinename());
|
||||||
|
|
||||||
V3Number lhnum (fl, l1);
|
V3Number lhnum(fl, l1);
|
||||||
V3Number rhnum (fl, r1);
|
V3Number rhnum(fl, r1);
|
||||||
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
|
||||||
<<" "<<rhnum<<endl
|
<< " " << rhnum << endl
|
||||||
<<" = "<<expnum<<endl
|
<< " = " << expnum << endl
|
||||||
<<" =? "<<gotnum<<endl);
|
<< " =? " << gotnum << endl);
|
||||||
|
|
||||||
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);
|
||||||
|
|
@ -91,10 +120,10 @@ void test(const string& lhss, const string& op, const string& rhss, const string
|
||||||
}
|
}
|
||||||
|
|
||||||
int main() {
|
int main() {
|
||||||
UINFO(0,"Test starting\n");
|
UINFO(0, "Test starting\n");
|
||||||
|
|
||||||
test("32'b10", "|", "32'b10", "32'b10");
|
test("32'b10", "|", "32'b10", "32'b10");
|
||||||
test( "2'bx0", "|", "2'b10", "2'b10");
|
test("2'bx0", "|", "2'b10", "2'b10");
|
||||||
test("32'b0x", "|", "32'b10", "32'b1x");
|
test("32'b0x", "|", "32'b10", "32'b1x");
|
||||||
test("32'b10", "&", "32'b11", "32'b10");
|
test("32'b10", "&", "32'b11", "32'b10");
|
||||||
test("32'b10", "+", "32'b10", "32'b100");
|
test("32'b10", "+", "32'b10", "32'b100");
|
||||||
|
|
@ -106,9 +135,10 @@ 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_
|
||||||
|
|
||||||
|
|
@ -56,13 +55,14 @@ class OrderMoveDomScope;
|
||||||
//######################################################################
|
//######################################################################
|
||||||
|
|
||||||
enum OrderWeights {
|
enum OrderWeights {
|
||||||
WEIGHT_INPUT = 1, // Low weight just so dot graph looks nice
|
WEIGHT_INPUT = 1, // Low weight just so dot graph looks nice
|
||||||
WEIGHT_COMBO = 1, // Breakable combo logic
|
WEIGHT_COMBO = 1, // Breakable combo logic
|
||||||
WEIGHT_LOOPBE = 1, // Connection to loop begin/end
|
WEIGHT_LOOPBE = 1, // Connection to loop begin/end
|
||||||
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,18 +140,23 @@ 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;
|
||||||
// Methods
|
// Methods
|
||||||
virtual OrderVEdgeType type() const = 0;
|
virtual OrderVEdgeType type() const = 0;
|
||||||
virtual bool domainMatters() = 0; // Must be in same domain when cross edge to this vertex
|
virtual bool domainMatters() = 0; // Must be in same domain when cross edge to this vertex
|
||||||
virtual string dotName() const { return cvtToHex(m_scopep)+"_"; }
|
virtual string dotName() const { return cvtToHex(m_scopep) + "_"; }
|
||||||
// ACCESSORS
|
// ACCESSORS
|
||||||
void domainp(AstSenTree* domainp) { m_domainp = domainp; }
|
void domainp(AstSenTree* domainp) { m_domainp = domainp; }
|
||||||
AstScope* scopep() const { return m_scopep; }
|
AstScope* scopep() const { return m_scopep; }
|
||||||
|
|
@ -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"; }
|
||||||
|
|
@ -194,21 +204,27 @@ 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,70 +261,80 @@ 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"; }
|
||||||
virtual bool domainMatters() { return true; }
|
virtual bool domainMatters() { return true; }
|
||||||
};
|
};
|
||||||
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"; }
|
||||||
virtual bool domainMatters() { return false; }
|
virtual bool domainMatters() { return false; }
|
||||||
};
|
};
|
||||||
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()); }
|
||||||
virtual string dotColor() const { return "CadetBlue"; }
|
virtual string dotColor() const { return "CadetBlue"; }
|
||||||
virtual bool domainMatters() { return false; }
|
virtual bool domainMatters() { return false; }
|
||||||
};
|
};
|
||||||
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"; }
|
||||||
virtual bool domainMatters() { return false; }
|
virtual bool domainMatters() { return false; }
|
||||||
};
|
};
|
||||||
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"; }
|
||||||
virtual bool domainMatters() { return false; }
|
virtual bool domainMatters() { return false; }
|
||||||
};
|
};
|
||||||
|
|
@ -313,7 +343,7 @@ public:
|
||||||
//--- Following only under the move graph, not the main graph
|
//--- Following only under the move graph, not the main graph
|
||||||
|
|
||||||
class OrderMoveVertex : public V3GraphVertex {
|
class OrderMoveVertex : public V3GraphVertex {
|
||||||
typedef enum {POM_WAIT, POM_READY, POM_MOVED} OrderMState;
|
typedef enum { POM_WAIT, POM_READY, POM_MOVED } OrderMState;
|
||||||
|
|
||||||
OrderLogicVertex* m_logicp;
|
OrderLogicVertex* m_logicp;
|
||||||
OrderMState m_state; // Movement state
|
OrderMState m_state; // Movement state
|
||||||
|
|
@ -329,40 +359,50 @@ 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";
|
||||||
}
|
}
|
||||||
return nm;
|
return nm;
|
||||||
}
|
}
|
||||||
OrderLogicVertex* logicp() const { return m_logicp; }
|
OrderLogicVertex* logicp() const { return m_logicp; }
|
||||||
bool isWait() const { return m_state==POM_WAIT; }
|
bool isWait() const { return m_state == POM_WAIT; }
|
||||||
void setReady() {
|
void setReady() {
|
||||||
UASSERT(m_state==POM_WAIT, "Wait->Ready on node not in proper state");
|
UASSERT(m_state == POM_WAIT, "Wait->Ready on node not in proper state");
|
||||||
m_state = POM_READY;
|
m_state = POM_READY;
|
||||||
}
|
}
|
||||||
void setMoved() {
|
void setMoved() {
|
||||||
UASSERT(m_state==POM_READY, "Ready->Moved on node not in proper state");
|
UASSERT(m_state == POM_READY, "Ready->Moved on node not in proper state");
|
||||||
m_state = POM_MOVED;
|
m_state = POM_MOVED;
|
||||||
}
|
}
|
||||||
OrderMoveDomScope* domScopep() const { return m_domScopep; }
|
OrderMoveDomScope* domScopep() const { return m_domScopep; }
|
||||||
|
|
@ -383,34 +423,40 @@ 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 {
|
||||||
nm = "nolog\\nt="+cvtToStr(color());
|
nm = "nolog\\nt=" + cvtToStr(color());
|
||||||
}
|
}
|
||||||
return nm;
|
return nm;
|
||||||
}
|
}
|
||||||
|
|
@ -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() {}
|
||||||
|
|
|
||||||
17
src/V3Os.h
17
src/V3Os.h
|
|
@ -34,17 +34,21 @@ 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
|
||||||
|
|
||||||
// METHODS (file utilities)
|
// METHODS (file utilities)
|
||||||
static string getline(std::istream& is, char delim='\n');
|
static string getline(std::istream& is, char delim = '\n');
|
||||||
|
|
||||||
// METHODS (directory utilities)
|
// METHODS (directory utilities)
|
||||||
static void createDir(const string& dirname);
|
static void createDir(const string& dirname);
|
||||||
|
|
@ -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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -74,7 +71,7 @@ int V3ParseImp::yylexReadTok() {
|
||||||
void V3ParseImp::lexNew() {
|
void V3ParseImp::lexNew() {
|
||||||
if (m_lexerp) delete m_lexerp; // Restart from clean slate.
|
if (m_lexerp) delete m_lexerp; // Restart from clean slate.
|
||||||
m_lexerp = new V3Lexer();
|
m_lexerp = new V3Lexer();
|
||||||
if (debugFlex()>=9) { m_lexerp->set_debug(~0); }
|
if (debugFlex() >= 9) { m_lexerp->set_debug(~0); }
|
||||||
}
|
}
|
||||||
|
|
||||||
void V3ParseImp::lexDestroy() {
|
void V3ParseImp::lexDestroy() {
|
||||||
|
|
|
||||||
|
|
@ -36,11 +36,11 @@ class V3ParseSym {
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// MEMBERS
|
// MEMBERS
|
||||||
static int s_anonNum; // Number of next anonymous object (parser use only)
|
static int s_anonNum; // Number of next anonymous object (parser use only)
|
||||||
VSymGraph m_syms; // Graph of symbol tree
|
VSymGraph m_syms; // Graph of symbol tree
|
||||||
VSymEnt* m_symTableNextId; // Symbol table for next lexer lookup (parser use only)
|
VSymEnt* m_symTableNextId; // Symbol table for next lexer lookup (parser use only)
|
||||||
VSymEnt* m_symCurrentp; // Active symbol table for additions/lookups
|
VSymEnt* m_symCurrentp; // Active symbol table for additions/lookups
|
||||||
SymStack m_sympStack; // Stack of upper nodes with pending symbol tables
|
SymStack m_sympStack; // Stack of upper nodes with pending symbol tables
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// CONSTRUCTORS
|
// CONSTRUCTORS
|
||||||
|
|
@ -74,15 +74,14 @@ public:
|
||||||
}
|
}
|
||||||
void nextId(AstNode* entp) {
|
void nextId(AstNode* entp) {
|
||||||
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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void reinsert(AstNode* nodep, VSymEnt* parentp=NULL) {
|
void reinsert(AstNode* nodep, VSymEnt* parentp = NULL) {
|
||||||
reinsert(nodep, parentp, nodep->name());
|
reinsert(nodep, parentp, nodep->name());
|
||||||
}
|
}
|
||||||
void reinsert(AstNode* nodep, VSymEnt* parentp, string name) {
|
void reinsert(AstNode* nodep, VSymEnt* parentp, string name) {
|
||||||
|
|
@ -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()) {
|
||||||
nodep->v3fatalSrc("Symbols suggest ending "<<symCurrentp()->nodep()->prettyTypeName()
|
showUpward();
|
||||||
<<" but parser thinks ending "<<nodep->prettyTypeName());
|
dump(cout, "-mism: ");
|
||||||
|
}
|
||||||
|
nodep->v3fatalSrc("Symbols suggest ending " << symCurrentp()->nodep()->prettyTypeName()
|
||||||
|
<< " but parser thinks ending "
|
||||||
|
<< nodep->prettyTypeName());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
m_sympStack.pop_back();
|
m_sympStack.pop_back();
|
||||||
|
|
@ -116,21 +120,23 @@ public:
|
||||||
m_symCurrentp = m_sympStack.back();
|
m_symCurrentp = m_sympStack.back();
|
||||||
}
|
}
|
||||||
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="") {
|
|
||||||
m_syms.dump(os, indent);
|
|
||||||
}
|
}
|
||||||
|
void dump(std::ostream& os, const string& 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);
|
||||||
|
|
@ -75,13 +76,15 @@ private:
|
||||||
class PartPtrIdMap {
|
class PartPtrIdMap {
|
||||||
private:
|
private:
|
||||||
// TYPES
|
// TYPES
|
||||||
typedef vl_unordered_map <const void*, vluint64_t> PtrMap;
|
typedef vl_unordered_map<const void*, vluint64_t> PtrMap;
|
||||||
// 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.
|
||||||
|
|
@ -52,28 +54,29 @@ public:
|
||||||
|
|
||||||
class ExecMTask : public AbstractMTask {
|
class ExecMTask : public AbstractMTask {
|
||||||
private:
|
private:
|
||||||
AstMTaskBody* m_bodyp; // Task body
|
AstMTaskBody* m_bodyp; // Task body
|
||||||
uint32_t m_id; // Unique id of this mtask.
|
uint32_t m_id; // Unique id of this mtask.
|
||||||
uint32_t m_priority; // Predicted critical path from the start of
|
uint32_t m_priority; // Predicted critical path from the start of
|
||||||
// this mtask to the ends of the graph that are reachable from this
|
// this mtask to the ends of the graph that are reachable from this
|
||||||
// mtask. In abstract time units.
|
// mtask. In abstract time units.
|
||||||
uint32_t m_cost; // Predicted runtime of this mtask, in the same
|
uint32_t m_cost; // Predicted runtime of this mtask, in the same
|
||||||
// abstract time units as priority().
|
// abstract time units as priority().
|
||||||
uint32_t m_thread; // Thread for static (pack_mtasks) scheduling,
|
uint32_t m_thread; // Thread for static (pack_mtasks) scheduling,
|
||||||
// or 0xffffffff if not yet assigned.
|
// or 0xffffffff if not yet assigned.
|
||||||
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; }
|
||||||
|
|
@ -88,18 +91,20 @@ public:
|
||||||
void threadRoot(bool threadRoot) { m_threadRoot = threadRoot; }
|
void threadRoot(bool threadRoot) { m_threadRoot = threadRoot; }
|
||||||
string cFuncName() const {
|
string cFuncName() const {
|
||||||
// If this MTask maps to a C function, this should be the name
|
// If this MTask maps to a C function, this should be the name
|
||||||
return string("__Vmtask")+"__"+cvtToStr(m_id);
|
return string("__Vmtask") + "__" + cvtToStr(m_id);
|
||||||
}
|
}
|
||||||
string name() const { return string("mt")+cvtToStr(id()); }
|
string name() const { return string("mt") + cvtToStr(id()); }
|
||||||
void dump(std::ostream& str) const {
|
void dump(std::ostream& str) const {
|
||||||
str <<name()<<"."<<cvtToHex(this);
|
str << name() << "." << cvtToHex(this);
|
||||||
if (priority() || cost()) str <<" [pr="<<priority()<<" c="<<cvtToStr(cost())<<"]";
|
if (priority() || cost()) str << " [pr=" << priority() << " c=" << cvtToStr(cost()) << "]";
|
||||||
if (thread() != 0xffffffff) str <<" th="<<thread();
|
if (thread() != 0xffffffff) str << " th=" << thread();
|
||||||
if (threadRoot()) str <<" [ROOT]";
|
if (threadRoot()) str << " [ROOT]";
|
||||||
if (packNextp()) str <<" nx="<<packNextp()->name();
|
if (packNextp()) str << " nx=" << packNextp()->name();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
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
|
||||||
|
|
@ -97,9 +101,10 @@ class V3PreProcImp;
|
||||||
|
|
||||||
#ifndef YY_BUFFER_STATE
|
#ifndef YY_BUFFER_STATE
|
||||||
struct yy_buffer_state;
|
struct yy_buffer_state;
|
||||||
typedef struct yy_buffer_state *YY_BUFFER_STATE;
|
typedef struct yy_buffer_state* YY_BUFFER_STATE;
|
||||||
# define YY_BUF_SIZE 16384
|
# define YY_BUF_SIZE 16384
|
||||||
#endif
|
#endif
|
||||||
|
// clang-format on
|
||||||
|
|
||||||
extern int yylex();
|
extern int yylex();
|
||||||
extern void yyrestart(FILE*);
|
extern void yyrestart(FILE*);
|
||||||
|
|
@ -109,7 +114,7 @@ extern char* yyourtext();
|
||||||
extern size_t yyourleng();
|
extern size_t yyourleng();
|
||||||
extern void yyourtext(const char* textp, size_t size); // Must call with static
|
extern void yyourtext(const char* textp, size_t size); // Must call with static
|
||||||
|
|
||||||
YY_BUFFER_STATE yy_create_buffer(FILE *file, int size);
|
YY_BUFFER_STATE yy_create_buffer(FILE* file, int size);
|
||||||
void yy_switch_to_buffer(YY_BUFFER_STATE new_buffer);
|
void yy_switch_to_buffer(YY_BUFFER_STATE new_buffer);
|
||||||
void yy_delete_buffer(YY_BUFFER_STATE b);
|
void yy_delete_buffer(YY_BUFFER_STATE b);
|
||||||
|
|
||||||
|
|
@ -123,22 +128,24 @@ void yy_delete_buffer(YY_BUFFER_STATE b);
|
||||||
|
|
||||||
class VPreStream {
|
class VPreStream {
|
||||||
public:
|
public:
|
||||||
FileLine* m_curFilelinep; // Current processing point (see also m_tokFilelinep)
|
FileLine* m_curFilelinep; // Current processing point (see also m_tokFilelinep)
|
||||||
V3PreLex* m_lexp; // Lexer, for resource tracking
|
V3PreLex* m_lexp; // Lexer, for resource tracking
|
||||||
std::deque<string> m_buffers; // Buffer of characters to process
|
std::deque<string> m_buffers; // Buffer of characters to process
|
||||||
int m_ignNewlines; // Ignore multiline newlines
|
int m_ignNewlines; // Ignore multiline newlines
|
||||||
bool m_eof; // "EOF" buffer
|
bool m_eof; // "EOF" buffer
|
||||||
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);
|
||||||
};
|
};
|
||||||
|
|
@ -147,26 +154,26 @@ private:
|
||||||
// Class entry for each per-lexer state
|
// Class entry for each per-lexer state
|
||||||
|
|
||||||
class V3PreLex {
|
class V3PreLex {
|
||||||
public: // Used only by V3PreLex.cpp and V3PreProc.cpp
|
public: // Used only by V3PreLex.cpp and V3PreProc.cpp
|
||||||
V3PreProcImp* m_preimpp; // Preprocessor lexor belongs to
|
V3PreProcImp* m_preimpp; // Preprocessor lexor belongs to
|
||||||
std::stack<VPreStream*> m_streampStack; // Stack of processing files
|
std::stack<VPreStream*> m_streampStack; // Stack of processing files
|
||||||
int m_streamDepth; // Depth of stream processing
|
int m_streamDepth; // Depth of stream processing
|
||||||
YY_BUFFER_STATE m_bufferState; // Flex state
|
YY_BUFFER_STATE m_bufferState; // Flex state
|
||||||
FileLine* m_tokFilelinep; // Starting position of current token
|
FileLine* m_tokFilelinep; // Starting position of current token
|
||||||
|
|
||||||
// State to lexer
|
// State to lexer
|
||||||
static V3PreLex* s_currentLexp; ///< Current lexing point
|
static V3PreLex* s_currentLexp; ///< Current lexing point
|
||||||
int m_keepComments; ///< Emit comments in output text
|
int m_keepComments; ///< Emit comments in output text
|
||||||
int m_keepWhitespace; ///< Emit all whitespace in output text
|
int m_keepWhitespace; ///< Emit all whitespace in output text
|
||||||
bool m_pedantic; ///< Obey standard; don't Substitute `error
|
bool m_pedantic; ///< Obey standard; don't Substitute `error
|
||||||
|
|
||||||
// State from lexer
|
// State from lexer
|
||||||
int m_formalLevel; // Parenthesis counting inside def formals
|
int m_formalLevel; // Parenthesis counting inside def formals
|
||||||
int m_parenLevel; // Parenthesis counting inside def args
|
int m_parenLevel; // Parenthesis counting inside def args
|
||||||
bool m_defCmtSlash; // /*...*/ comment in define had \ ending
|
bool m_defCmtSlash; // /*...*/ comment in define had \ ending
|
||||||
bool m_defQuote; // Definition value inside quote
|
bool m_defQuote; // Definition value inside quote
|
||||||
string m_defValue; // Definition value being built.
|
string m_defValue; // Definition value being built.
|
||||||
int m_enterExit; // For VL_LINE, the enter/exit level
|
int m_enterExit; // For VL_LINE, the enter/exit level
|
||||||
|
|
||||||
// CONSTRUCTORS
|
// CONSTRUCTORS
|
||||||
V3PreLex(V3PreProcImp* preimpp, FileLine* filelinep) {
|
V3PreLex(V3PreProcImp* preimpp, FileLine* filelinep) {
|
||||||
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -213,8 +223,8 @@ class V3PreLex {
|
||||||
size_t inputToLex(char* buf, size_t max_size);
|
size_t inputToLex(char* buf, size_t max_size);
|
||||||
/// Called by V3PreProc.cpp to get data from lexer
|
/// Called by V3PreProc.cpp to get data from lexer
|
||||||
YY_BUFFER_STATE currentBuffer();
|
YY_BUFFER_STATE currentBuffer();
|
||||||
int lex();
|
int lex();
|
||||||
int currentStartState() const;
|
int currentStartState() const;
|
||||||
void dumpSummary();
|
void dumpSummary();
|
||||||
void dumpStack();
|
void dumpStack();
|
||||||
void unused();
|
void unused();
|
||||||
|
|
|
||||||
|
|
@ -44,13 +44,13 @@ protected:
|
||||||
public:
|
public:
|
||||||
// CONSTANTS
|
// CONSTANTS
|
||||||
enum MiscConsts {
|
enum MiscConsts {
|
||||||
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
|
||||||
};
|
};
|
||||||
|
|
||||||
// ACCESSORS
|
// ACCESSORS
|
||||||
|
|
@ -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() {}
|
||||||
|
|
|
||||||
|
|
@ -43,7 +43,7 @@ protected:
|
||||||
//---------------------------------------
|
//---------------------------------------
|
||||||
// METHODS
|
// METHODS
|
||||||
|
|
||||||
static int debug(bool reset=false) {
|
static int debug(bool reset = false) {
|
||||||
static int level = -1;
|
static int level = -1;
|
||||||
if (VL_UNLIKELY(level < 0) || reset) {
|
if (VL_UNLIKELY(level < 0) || reset) {
|
||||||
level = v3Global.opt.debugSrcLevel(__FILE__);
|
level = v3Global.opt.debugSrcLevel(__FILE__);
|
||||||
|
|
@ -64,8 +64,10 @@ protected:
|
||||||
s_preprocp->defineCmdLine(prefl, "VERILATOR", "1"); // LEAK_OK
|
s_preprocp->defineCmdLine(prefl, "VERILATOR", "1"); // LEAK_OK
|
||||||
s_preprocp->defineCmdLine(prefl, "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
|
||||||
|
|
@ -94,7 +96,7 @@ protected:
|
||||||
debug(true); // Recheck if debug on - first check was before command line passed
|
debug(true); // Recheck if debug on - first check was before command line passed
|
||||||
|
|
||||||
// Preprocess the given module, putting output in vppFilename
|
// Preprocess the given module, putting output in vppFilename
|
||||||
UINFONL(1," Preprocessing "<<modname<<endl);
|
UINFONL(1, " Preprocessing " << modname << endl);
|
||||||
|
|
||||||
// Preprocess
|
// Preprocess
|
||||||
s_filterp = filterp;
|
s_filterp = filterp;
|
||||||
|
|
@ -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()) {
|
||||||
|
|
@ -121,31 +123,32 @@ 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,
|
||||||
<<modname);
|
"Suggest `include with absolute path be made relative, and use +include: "
|
||||||
|
<< modname);
|
||||||
}
|
}
|
||||||
preprocOpen(fl, s_filterp, modname, V3Os::filenameDir(fl->filename()),
|
preprocOpen(fl, s_filterp, modname, V3Os::filenameDir(fl->filename()),
|
||||||
"Cannot find include file: ");
|
"Cannot find include file: ");
|
||||||
}
|
}
|
||||||
|
|
||||||
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
|
||||||
string filename = v3Global.opt.filePath(fl, modname, lastpath, errmsg);
|
string filename = v3Global.opt.filePath(fl, modname, lastpath, errmsg);
|
||||||
if (filename=="") {
|
if (filename == "") {
|
||||||
// Allow user to put `defined names on the command line instead of filenames,
|
// Allow user to put `defined names on the command line instead of filenames,
|
||||||
// then convert them properly.
|
// then convert them properly.
|
||||||
string ppmodname = s_preprocp->removeDefines(modname);
|
string ppmodname = s_preprocp->removeDefines(modname);
|
||||||
|
|
||||||
filename = v3Global.opt.filePath(fl, ppmodname, lastpath, errmsg);
|
filename = v3Global.opt.filePath(fl, ppmodname, lastpath, errmsg);
|
||||||
}
|
}
|
||||||
if (filename=="") return ""; // Not found
|
if (filename == "") return ""; // Not found
|
||||||
|
|
||||||
UINFO(2," Reading "<<filename<<endl);
|
UINFO(2, " Reading " << filename << endl);
|
||||||
s_preprocp->openFile(fl, filterp, filename);
|
s_preprocp->openFile(fl, filterp, filename);
|
||||||
return filename;
|
return filename;
|
||||||
}
|
}
|
||||||
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
123
src/V3Reloop.cpp
123
src/V3Reloop.cpp
|
|
@ -47,27 +47,27 @@
|
||||||
class ReloopVisitor : public AstNVisitor {
|
class ReloopVisitor : public AstNVisitor {
|
||||||
private:
|
private:
|
||||||
// TYPES
|
// TYPES
|
||||||
typedef std::vector<AstNodeAssign*> AssVec;
|
typedef std::vector<AstNodeAssign*> AssVec;
|
||||||
|
|
||||||
// NODE STATE
|
// NODE STATE
|
||||||
// AstCFunc::user1p -> Var* for temp var, 0=not set yet
|
// AstCFunc::user1p -> Var* for temp var, 0=not set yet
|
||||||
AstUser1InUse m_inuser1;
|
AstUser1InUse m_inuser1;
|
||||||
|
|
||||||
// STATE
|
// STATE
|
||||||
VDouble0 m_statReloops; // Statistic tracking
|
VDouble0 m_statReloops; // Statistic tracking
|
||||||
VDouble0 m_statReItems; // Statistic tracking
|
VDouble0 m_statReItems; // Statistic tracking
|
||||||
AstCFunc* m_cfuncp; // Current block
|
AstCFunc* m_cfuncp; // Current block
|
||||||
|
|
||||||
AssVec m_mgAssignps; // List of assignments merging
|
AssVec m_mgAssignps; // List of assignments merging
|
||||||
AstCFunc* m_mgCfuncp; // Parent C function
|
AstCFunc* m_mgCfuncp; // Parent C function
|
||||||
AstNode* m_mgNextp; // Next node
|
AstNode* m_mgNextp; // Next node
|
||||||
AstNodeSel* m_mgSelLp; // Parent select, NULL = idle
|
AstNodeSel* m_mgSelLp; // Parent select, NULL = idle
|
||||||
AstNodeSel* m_mgSelRp; // Parent select, NULL = constant
|
AstNodeSel* m_mgSelRp; // Parent select, NULL = constant
|
||||||
AstNodeVarRef* m_mgVarrefLp; // Parent varref
|
AstNodeVarRef* m_mgVarrefLp; // Parent varref
|
||||||
AstNodeVarRef* m_mgVarrefRp; // Parent varref, NULL = constant
|
AstNodeVarRef* m_mgVarrefRp; // Parent varref, NULL = constant
|
||||||
AstConst* m_mgConstRp; // Parent RHS constant, NULL = sel
|
AstConst* m_mgConstRp; // Parent RHS constant, NULL = sel
|
||||||
uint32_t m_mgIndexLo; // Merge range
|
uint32_t m_mgIndexLo; // Merge range
|
||||||
uint32_t m_mgIndexHi; // Merge range
|
uint32_t m_mgIndexHi; // Merge range
|
||||||
|
|
||||||
// METHODS
|
// METHODS
|
||||||
VL_DEBUG_FUNC; // Declare debug()
|
VL_DEBUG_FUNC; // Declare debug()
|
||||||
|
|
@ -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);
|
||||||
|
|
@ -122,11 +121,11 @@ private:
|
||||||
rbitp->replaceWith(new AstVarRef(fl, itp, false));
|
rbitp->replaceWith(new AstVarRef(fl, itp, false));
|
||||||
VL_DO_DANGLING(rbitp->deleteTree(), lbitp);
|
VL_DO_DANGLING(rbitp->deleteTree(), lbitp);
|
||||||
}
|
}
|
||||||
if (debug()>=9) initp->dumpTree(cout, "-new: ");
|
if (debug() >= 9) initp->dumpTree(cout, "-new: ");
|
||||||
if (debug()>=9) whilep->dumpTree(cout, "-new: ");
|
if (debug() >= 9) whilep->dumpTree(cout, "-new: ");
|
||||||
|
|
||||||
// Remove remaining assigns
|
// Remove remaining assigns
|
||||||
for (AssVec::iterator it=m_mgAssignps.begin(); it!=m_mgAssignps.end(); ++it) {
|
for (AssVec::iterator it = m_mgAssignps.begin(); it != m_mgAssignps.end(); ++it) {
|
||||||
AstNodeAssign* assp = *it;
|
AstNodeAssign* assp = *it;
|
||||||
if (assp != bodyp) {
|
if (assp != bodyp) {
|
||||||
VL_DO_DANGLING(assp->unlinkFrBack()->deleteTree(), assp);
|
VL_DO_DANGLING(assp->unlinkFrBack()->deleteTree(), assp);
|
||||||
|
|
@ -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();
|
||||||
|
|
@ -219,7 +230,7 @@ private:
|
||||||
m_mgConstRp = rconstp;
|
m_mgConstRp = rconstp;
|
||||||
m_mgIndexLo = index;
|
m_mgIndexLo = index;
|
||||||
m_mgIndexHi = index;
|
m_mgIndexHi = index;
|
||||||
UINFO(9, "Start merge i="<<index<<" "<<nodep<<endl);
|
UINFO(9, "Start merge i=" << index << " " << nodep << endl);
|
||||||
}
|
}
|
||||||
//--------------------
|
//--------------------
|
||||||
virtual void visit(AstVar*) VL_OVERRIDE {} // Accelerate
|
virtual void visit(AstVar*) VL_OVERRIDE {} // Accelerate
|
||||||
|
|
@ -251,9 +262,7 @@ public:
|
||||||
// Reloop class functions
|
// Reloop class functions
|
||||||
|
|
||||||
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,16 +350,14 @@ 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
|
||||||
typedef vl_unordered_set<const T_Elem*> NeedRescoreSet;
|
typedef vl_unordered_set<const T_Elem*> NeedRescoreSet;
|
||||||
class CmpElems {
|
class CmpElems {
|
||||||
public:
|
public:
|
||||||
bool operator() (const T_Elem* const& ap, const T_Elem* const& bp) const {
|
bool operator()(const T_Elem* const& ap, const T_Elem* const& bp) const {
|
||||||
T_ElemCompare cmp;
|
T_ElemCompare cmp;
|
||||||
return cmp.operator()(*ap, *bp);
|
return cmp.operator()(*ap, *bp);
|
||||||
}
|
}
|
||||||
|
|
@ -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);
|
||||||
|
|
@ -500,7 +469,7 @@ private:
|
||||||
//######################################################################
|
//######################################################################
|
||||||
|
|
||||||
namespace V3ScoreboardBase {
|
namespace V3ScoreboardBase {
|
||||||
void selfTest();
|
void selfTest();
|
||||||
} // namespace V3ScoreboardBase
|
} // namespace V3ScoreboardBase
|
||||||
|
|
||||||
#endif // Guard
|
#endif // Guard
|
||||||
|
|
|
||||||
|
|
@ -53,7 +53,7 @@ private:
|
||||||
class HashSenTree {
|
class HashSenTree {
|
||||||
public:
|
public:
|
||||||
HashSenTree() {}
|
HashSenTree() {}
|
||||||
size_t operator() (const AstSenTree* kp) const {
|
size_t operator()(const AstSenTree* kp) const {
|
||||||
return V3Hashed::uncachedHash(kp).fullValue();
|
return V3Hashed::uncachedHash(kp).fullValue();
|
||||||
}
|
}
|
||||||
// Copying required for OSX's libc++
|
// Copying required for OSX's libc++
|
||||||
|
|
@ -62,7 +62,7 @@ private:
|
||||||
class EqSenTree {
|
class EqSenTree {
|
||||||
public:
|
public:
|
||||||
EqSenTree() {}
|
EqSenTree() {}
|
||||||
bool operator() (const AstSenTree* ap, const AstSenTree* bp) const {
|
bool operator()(const AstSenTree* ap, const AstSenTree* bp) const {
|
||||||
return ap->sameTree(bp);
|
return ap->sameTree(bp);
|
||||||
}
|
}
|
||||||
// Copying required for OSX's libc++
|
// Copying required for OSX's libc++
|
||||||
|
|
@ -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;
|
||||||
|
|
@ -139,21 +135,18 @@ public:
|
||||||
UASSERT(m_topscopep, "Never called main()");
|
UASSERT(m_topscopep, "Never called main()");
|
||||||
treep = sensesp->cloneTree(false);
|
treep = sensesp->cloneTree(false);
|
||||||
m_topscopep->addStmtsp(treep);
|
m_topscopep->addStmtsp(treep);
|
||||||
UINFO(8," New SENTREE "<<treep<<endl);
|
UINFO(8, " New SENTREE " << treep << endl);
|
||||||
m_trees.add(treep);
|
m_trees.add(treep);
|
||||||
// Note blocks may have also been added above in the Active visitor
|
// Note blocks may have also been added above in the Active visitor
|
||||||
}
|
}
|
||||||
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
|
||||||
|
|
|
||||||
103
src/V3Stats.cpp
103
src/V3Stats.cpp
|
|
@ -36,31 +36,31 @@ class StatsVisitor : public AstNVisitor {
|
||||||
private:
|
private:
|
||||||
// NODE STATE/TYPES
|
// NODE STATE/TYPES
|
||||||
|
|
||||||
typedef std::map<string,int> NameMap; // Number of times a name appears
|
typedef std::map<string, int> NameMap; // Number of times a name appears
|
||||||
|
|
||||||
// STATE
|
// STATE
|
||||||
string m_stage; // Name of the stage we are scanning
|
string m_stage; // Name of the stage we are scanning
|
||||||
/// m_fast = true: Counting only critical branch of fastpath
|
/// m_fast = true: Counting only critical branch of fastpath
|
||||||
/// m_fast = false: Counting every node, ignoring structure of program
|
/// m_fast = false: Counting every node, ignoring structure of program
|
||||||
bool m_fast;
|
bool m_fast;
|
||||||
|
|
||||||
AstCFunc* m_cfuncp; // Current CFUNC
|
AstCFunc* m_cfuncp; // Current CFUNC
|
||||||
VDouble0 m_statInstrLong; // Instruction count
|
VDouble0 m_statInstrLong; // Instruction count
|
||||||
bool m_counting; // Currently counting
|
bool m_counting; // Currently counting
|
||||||
double m_instrs; // Current instr count (for determining branch direction)
|
double m_instrs; // Current instr count (for determining branch direction)
|
||||||
bool m_tracingCall; // Iterating into a CCall to a CFunc
|
bool m_tracingCall; // Iterating into a CCall to a CFunc
|
||||||
|
|
||||||
std::vector<VDouble0> m_statTypeCount; // Nodes of given type
|
std::vector<VDouble0> m_statTypeCount; // Nodes of given type
|
||||||
VDouble0 m_statAbove[AstType::_ENUM_END][AstType::_ENUM_END]; // Nodes of given type
|
VDouble0 m_statAbove[AstType::_ENUM_END][AstType::_ENUM_END]; // Nodes of given type
|
||||||
VDouble0 m_statPred[VBranchPred::_ENUM_END]; // Nodes of given type
|
VDouble0 m_statPred[VBranchPred::_ENUM_END]; // Nodes of given type
|
||||||
VDouble0 m_statInstr; // Instruction count
|
VDouble0 m_statInstr; // Instruction count
|
||||||
VDouble0 m_statInstrFast; // Instruction count, non-slow() eval functions only
|
VDouble0 m_statInstrFast; // Instruction count, non-slow() eval functions only
|
||||||
std::vector<VDouble0> m_statVarWidths; // Variables of given width
|
std::vector<VDouble0> m_statVarWidths; // Variables of given width
|
||||||
std::vector<NameMap> m_statVarWidthNames; // Var names of given width
|
std::vector<NameMap> m_statVarWidthNames; // Var names of given width
|
||||||
VDouble0 m_statVarArray; // Statistic tracking
|
VDouble0 m_statVarArray; // Statistic tracking
|
||||||
VDouble0 m_statVarBytes; // Statistic tracking
|
VDouble0 m_statVarBytes; // Statistic tracking
|
||||||
VDouble0 m_statVarClock; // Statistic tracking
|
VDouble0 m_statVarClock; // Statistic tracking
|
||||||
VDouble0 m_statVarScpBytes; // Statistic tracking
|
VDouble0 m_statVarScpBytes; // Statistic tracking
|
||||||
|
|
||||||
// METHODS
|
// METHODS
|
||||||
VL_DEBUG_FUNC; // Declare debug()
|
VL_DEBUG_FUNC; // Declare debug()
|
||||||
|
|
@ -92,13 +92,16 @@ 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;
|
||||||
if (int(m_statVarWidths.size()) <= nodep->width()) {
|
} else {
|
||||||
m_statVarWidths.resize(nodep->width()+5);
|
m_statVarBytes += nodep->dtypeSkipRefp()->widthTotalBytes();
|
||||||
if (v3Global.opt.statsVars()) m_statVarWidthNames.resize(nodep->width()+5);
|
|
||||||
}
|
}
|
||||||
++ m_statVarWidths.at(nodep->width());
|
if (int(m_statVarWidths.size()) <= nodep->width()) {
|
||||||
|
m_statVarWidths.resize(nodep->width() + 5);
|
||||||
|
if (v3Global.opt.statsVars()) m_statVarWidthNames.resize(nodep->width() + 5);
|
||||||
|
}
|
||||||
|
++m_statVarWidths.at(nodep->width());
|
||||||
string pn = nodep->prettyName();
|
string pn = nodep->prettyName();
|
||||||
if (v3Global.opt.statsVars()) {
|
if (v3Global.opt.statsVars()) {
|
||||||
NameMap& nameMapr = m_statVarWidthNames.at(nodep->width());
|
NameMap& nameMapr = m_statVarWidthNames.at(nodep->width());
|
||||||
|
|
@ -120,14 +123,12 @@ private:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
virtual void visit(AstNodeIf* nodep) VL_OVERRIDE {
|
virtual void visit(AstNodeIf* nodep) VL_OVERRIDE {
|
||||||
UINFO(4," IF i="<<m_instrs<<" "<<nodep<<endl);
|
UINFO(4, " IF i=" << m_instrs << " " << nodep << endl);
|
||||||
allNodes(nodep);
|
allNodes(nodep);
|
||||||
// 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);
|
||||||
|
|
@ -171,7 +172,7 @@ private:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// While's we assume evaluate once.
|
// While's we assume evaluate once.
|
||||||
//virtual void visit(AstWhile* nodep) VL_OVERRIDE {
|
// virtual void visit(AstWhile* nodep) VL_OVERRIDE {
|
||||||
|
|
||||||
virtual void visit(AstNodeCCall* nodep) VL_OVERRIDE {
|
virtual void visit(AstNodeCCall* nodep) VL_OVERRIDE {
|
||||||
allNodes(nodep);
|
allNodes(nodep);
|
||||||
|
|
@ -206,11 +207,13 @@ 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)
|
||||||
UINFO(9,"Starting stats, fast="<<fast<<endl);
|
, m_fast(fast) {
|
||||||
|
UINFO(9, "Starting stats, fast=" << fast << endl);
|
||||||
m_cfuncp = NULL;
|
m_cfuncp = NULL;
|
||||||
m_counting = !m_fast;
|
m_counting = !m_fast;
|
||||||
m_instrs = 0;
|
m_instrs = 0;
|
||||||
|
|
@ -223,53 +226,55 @@ public:
|
||||||
virtual ~StatsVisitor() {
|
virtual ~StatsVisitor() {
|
||||||
// Done. Publish statistics
|
// Done. Publish statistics
|
||||||
V3Stats::addStat(m_stage, "Instruction count, TOTAL", m_statInstr);
|
V3Stats::addStat(m_stage, "Instruction count, TOTAL", m_statInstr);
|
||||||
V3Stats::addStat(m_stage, "Instruction count, fast critical", m_statInstrFast);
|
V3Stats::addStat(m_stage, "Instruction count, fast critical", m_statInstrFast);
|
||||||
// Vars
|
// Vars
|
||||||
V3Stats::addStat(m_stage, "Vars, unpacked arrayed", m_statVarArray);
|
V3Stats::addStat(m_stage, "Vars, unpacked arrayed", m_statVarArray);
|
||||||
V3Stats::addStat(m_stage, "Vars, clock attribute", m_statVarClock);
|
V3Stats::addStat(m_stage, "Vars, clock attribute", m_statVarClock);
|
||||||
V3Stats::addStat(m_stage, "Var space, non-arrays, bytes", m_statVarBytes);
|
V3Stats::addStat(m_stage, "Var space, non-arrays, bytes", m_statVarBytes);
|
||||||
if (m_statVarScpBytes!=0.0) {
|
if (m_statVarScpBytes != 0.0) {
|
||||||
V3Stats::addStat(m_stage, "Var space, scoped, bytes", m_statVarScpBytes);
|
V3Stats::addStat(m_stage, "Var space, scoped, bytes", m_statVarScpBytes);
|
||||||
}
|
}
|
||||||
for (unsigned i=0; i<m_statVarWidths.size(); i++) {
|
for (unsigned i = 0; i < m_statVarWidths.size(); i++) {
|
||||||
double count = double(m_statVarWidths.at(i));
|
double count = double(m_statVarWidths.at(i));
|
||||||
if (count != 0.0) {
|
if (count != 0.0) {
|
||||||
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Node types
|
// Node types
|
||||||
for (int type=0; type<AstType::_ENUM_END; type++) {
|
for (int type = 0; type < AstType::_ENUM_END; type++) {
|
||||||
double count = double(m_statTypeCount.at(type));
|
double count = double(m_statTypeCount.at(type));
|
||||||
if (count != 0.0) {
|
if (count != 0.0) {
|
||||||
V3Stats::addStat(m_stage, string("Node count, ")+AstType(type).ascii(), count);
|
V3Stats::addStat(m_stage, string("Node count, ") + AstType(type).ascii(), count);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (int type=0; type < AstType::_ENUM_END; type++) {
|
for (int type = 0; type < AstType::_ENUM_END; type++) {
|
||||||
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Branch pred
|
// Branch pred
|
||||||
for (int type=0; type < VBranchPred::_ENUM_END; type++) {
|
for (int type = 0; type < VBranchPred::_ENUM_END; type++) {
|
||||||
double count = double(m_statPred[type]);
|
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -279,7 +284,7 @@ public:
|
||||||
// Top Stats class
|
// Top Stats class
|
||||||
|
|
||||||
void V3Stats::statsStageAll(AstNetlist* nodep, const string& stage, bool fast) {
|
void V3Stats::statsStageAll(AstNetlist* nodep, const string& stage, bool fast) {
|
||||||
StatsVisitor visitor (nodep, stage, fast);
|
StatsVisitor visitor(nodep, stage, fast);
|
||||||
}
|
}
|
||||||
|
|
||||||
void V3Stats::statsFinalAll(AstNetlist* nodep) {
|
void V3Stats::statsFinalAll(AstNetlist* nodep) {
|
||||||
|
|
|
||||||
|
|
@ -31,31 +31,49 @@ 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;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
//============================================================================
|
//============================================================================
|
||||||
|
|
||||||
class V3Statistic {
|
class V3Statistic {
|
||||||
// A statistical entry we want published into the database
|
// A statistical entry we want published into the database
|
||||||
string m_name; ///< Nameiption of this statistic
|
string m_name; ///< Nameiption of this statistic
|
||||||
double m_count; ///< Count of occurrences/ value
|
double m_count; ///< Count of occurrences/ value
|
||||||
string m_stage; ///< Runtime stage
|
string m_stage; ///< Runtime stage
|
||||||
bool m_sumit; ///< Do summation of similar stats
|
bool m_sumit; ///< Do summation of similar stats
|
||||||
bool m_perf; ///< Performance section
|
bool m_perf; ///< Performance section
|
||||||
bool m_printit; ///< Print the results
|
bool m_printit; ///< Print the results
|
||||||
public:
|
public:
|
||||||
// METHODS
|
// METHODS
|
||||||
string stage() const { return m_stage; }
|
string stage() const { return m_stage; }
|
||||||
|
|
@ -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,21 +105,24 @@ 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
|
||||||
static void statsStageAll(AstNetlist* nodep, const string& stage, bool fast=false);
|
static void statsStageAll(AstNetlist* nodep, const string& stage, bool fast = false);
|
||||||
static void statsFinalAll(AstNetlist* nodep);
|
static void statsFinalAll(AstNetlist* nodep);
|
||||||
/// Called by the top level to dump the statistics
|
/// Called by the top level to dump the statistics
|
||||||
static void statsReport();
|
static void statsReport();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
#endif // Guard
|
#endif // Guard
|
||||||
|
|
|
||||||
|
|
@ -40,31 +40,31 @@ class StatsReport {
|
||||||
static StatColl s_allStats; ///< All statistics
|
static StatColl s_allStats; ///< All statistics
|
||||||
|
|
||||||
void header() {
|
void header() {
|
||||||
os<<"Verilator Statistics Report\n";
|
os << "Verilator Statistics Report\n";
|
||||||
os<<endl;
|
os << endl;
|
||||||
|
|
||||||
os<<"Information:"<<endl;
|
os << "Information:" << endl;
|
||||||
os<<" "<<V3Options::version()<<endl;
|
os << " " << V3Options::version() << endl;
|
||||||
os<<" Arguments: "<<v3Global.opt.allArgsString()<<endl;
|
os << " Arguments: " << v3Global.opt.allArgsString() << endl;
|
||||||
os<<endl;
|
os << endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
void sumit() {
|
void sumit() {
|
||||||
// If sumit is set on a statistic, combine with others of same name
|
// If sumit is set on a statistic, combine with others of same name
|
||||||
typedef std::multimap<string,V3Statistic*> ByName;
|
typedef std::multimap<string, V3Statistic*> ByName;
|
||||||
ByName byName;
|
ByName byName;
|
||||||
// * is always first
|
// * is always first
|
||||||
for (StatColl::iterator it = s_allStats.begin(); it!=s_allStats.end(); ++it) {
|
for (StatColl::iterator it = s_allStats.begin(); it != s_allStats.end(); ++it) {
|
||||||
V3Statistic* repp = &(*it);
|
V3Statistic* repp = &(*it);
|
||||||
byName.insert(make_pair(repp->name(), repp));
|
byName.insert(make_pair(repp->name(), repp));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Process duplicates
|
// Process duplicates
|
||||||
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;
|
||||||
|
|
@ -74,10 +74,10 @@ class StatsReport {
|
||||||
void stars() {
|
void stars() {
|
||||||
// Find all stages
|
// Find all stages
|
||||||
size_t maxWidth = 0;
|
size_t maxWidth = 0;
|
||||||
typedef std::multimap<string,const V3Statistic*> ByName;
|
typedef std::multimap<string, const V3Statistic*> ByName;
|
||||||
ByName byName;
|
ByName byName;
|
||||||
// * is always first
|
// * is always first
|
||||||
for (StatColl::iterator it = s_allStats.begin(); it!=s_allStats.end(); ++it) {
|
for (StatColl::iterator it = s_allStats.begin(); it != s_allStats.end(); ++it) {
|
||||||
const V3Statistic* repp = &(*it);
|
const V3Statistic* repp = &(*it);
|
||||||
if (repp->stage() == "*" && repp->printit()) {
|
if (repp->stage() == "*" && repp->printit()) {
|
||||||
if (maxWidth < repp->name().length()) maxWidth = repp->name().length();
|
if (maxWidth < repp->name().length()) maxWidth = repp->name().length();
|
||||||
|
|
@ -86,43 +86,43 @@ class StatsReport {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Print organized by stage
|
// Print organized by stage
|
||||||
os<<"Global Statistics:\n";
|
os << "Global Statistics:\n";
|
||||||
os<<endl;
|
os << endl;
|
||||||
for (ByName::iterator it = byName.begin(); it!=byName.end(); ++it) {
|
for (ByName::iterator it = byName.begin(); it != byName.end(); ++it) {
|
||||||
const V3Statistic* repp = it->second;
|
const V3Statistic* repp = it->second;
|
||||||
if (repp->perf()) continue;
|
if (repp->perf()) continue;
|
||||||
os<<" "<<std::left<<std::setw(maxWidth)<<repp->name();
|
os << " " << std::left << std::setw(maxWidth) << repp->name();
|
||||||
repp->dump(os);
|
repp->dump(os);
|
||||||
os<<endl;
|
os << endl;
|
||||||
}
|
}
|
||||||
os<<endl;
|
os << endl;
|
||||||
|
|
||||||
// Print organized by stage
|
// Print organized by stage
|
||||||
os<<"Performance Statistics:\n";
|
os << "Performance Statistics:\n";
|
||||||
os<<endl;
|
os << endl;
|
||||||
for (ByName::iterator it = byName.begin(); it!=byName.end(); ++it) {
|
for (ByName::iterator it = byName.begin(); it != byName.end(); ++it) {
|
||||||
const V3Statistic* repp = it->second;
|
const V3Statistic* repp = it->second;
|
||||||
if (!repp->perf()) continue;
|
if (!repp->perf()) continue;
|
||||||
os<<" "<<std::left<<std::setw(maxWidth)<<repp->name();
|
os << " " << std::left << std::setw(maxWidth) << repp->name();
|
||||||
repp->dump(os);
|
repp->dump(os);
|
||||||
os<<endl;
|
os << endl;
|
||||||
}
|
}
|
||||||
os<<endl;
|
os << endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
void stages() {
|
void stages() {
|
||||||
os<<"Stage Statistics:\n";
|
os << "Stage Statistics:\n";
|
||||||
|
|
||||||
// Find all stages
|
// Find all stages
|
||||||
int stage = 0;
|
int stage = 0;
|
||||||
size_t maxWidth = 0;
|
size_t maxWidth = 0;
|
||||||
typedef std::vector<string> Stages;
|
typedef std::vector<string> Stages;
|
||||||
Stages stages;
|
Stages stages;
|
||||||
vl_unordered_map<string,int> stageInt;
|
vl_unordered_map<string, int> stageInt;
|
||||||
typedef std::multimap<string,const V3Statistic*> ByName;
|
typedef std::multimap<string, const V3Statistic*> ByName;
|
||||||
ByName byName;
|
ByName byName;
|
||||||
// * is always first
|
// * is always first
|
||||||
for (StatColl::iterator it = s_allStats.begin(); it!=s_allStats.end(); ++it) {
|
for (StatColl::iterator it = s_allStats.begin(); it != s_allStats.end(); ++it) {
|
||||||
const V3Statistic* repp = &(*it);
|
const V3Statistic* repp = &(*it);
|
||||||
if (repp->stage() != "*" && repp->printit()) {
|
if (repp->stage() != "*" && repp->printit()) {
|
||||||
if (maxWidth < repp->name().length()) maxWidth = repp->name().length();
|
if (maxWidth < repp->name().length()) maxWidth = repp->name().length();
|
||||||
|
|
@ -135,16 +135,16 @@ class StatsReport {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Header
|
// Header
|
||||||
os<<" Stat "<<std::left<<std::setw(maxWidth-5-2)<<"";
|
os << " Stat " << std::left << std::setw(maxWidth - 5 - 2) << "";
|
||||||
for (Stages::const_iterator it = stages.begin(); it != stages.end(); ++it) {
|
for (Stages::const_iterator it = stages.begin(); it != stages.end(); ++it) {
|
||||||
os<<" "<<std::left<<std::setw(9)<<*it;
|
os << " " << std::left << std::setw(9) << *it;
|
||||||
}
|
}
|
||||||
os<<endl;
|
os << endl;
|
||||||
os<<" -------- "<<std::left<<std::setw(maxWidth-5-2)<<"";
|
os << " -------- " << std::left << std::setw(maxWidth - 5 - 2) << "";
|
||||||
for (Stages::const_iterator it = stages.begin(); it != stages.end(); ++it) {
|
for (Stages::const_iterator it = stages.begin(); it != stages.end(); ++it) {
|
||||||
os<<" "<<std::left<<std::setw(9)<<"-------";
|
os << " " << std::left << std::setw(9) << "-------";
|
||||||
}
|
}
|
||||||
//os<<endl;
|
// os<<endl;
|
||||||
|
|
||||||
// Print organized by stage
|
// Print organized by stage
|
||||||
string lastName = "__NONE__";
|
string lastName = "__NONE__";
|
||||||
|
|
@ -157,33 +157,29 @@ 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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
os<<endl;
|
os << endl;
|
||||||
col = 0;
|
col = 0;
|
||||||
os<<" "<<std::left<<std::setw(maxWidth)<<repp->name();
|
os << " " << std::left << std::setw(maxWidth) << repp->name();
|
||||||
}
|
}
|
||||||
while (col<stages.size() && stages.at(col) != repp->stage()) {
|
while (col < stages.size() && stages.at(col) != repp->stage()) {
|
||||||
os<<std::setw(11)<<"";
|
os << std::setw(11) << "";
|
||||||
col++;
|
col++;
|
||||||
}
|
}
|
||||||
repp->dump(os);
|
repp->dump(os);
|
||||||
col++;
|
col++;
|
||||||
}
|
}
|
||||||
os<<endl;
|
os << endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
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)
|
||||||
|
|
@ -196,52 +192,51 @@ public:
|
||||||
~StatsReport() {}
|
~StatsReport() {}
|
||||||
};
|
};
|
||||||
|
|
||||||
StatsReport::StatColl StatsReport::s_allStats;
|
StatsReport::StatColl StatsReport::s_allStats;
|
||||||
|
|
||||||
//######################################################################
|
//######################################################################
|
||||||
// V3Statstic class
|
// V3Statstic class
|
||||||
|
|
||||||
void V3Statistic::dump(std::ofstream& os) const {
|
void V3Statistic::dump(std::ofstream& os) const {
|
||||||
if (perf()) {
|
if (perf()) {
|
||||||
os<<" "<<std::right<<std::fixed<<std::setprecision(6)<<std::setw(9)<<count();
|
os << " " << std::right << std::fixed << std::setprecision(6) << std::setw(9) << count();
|
||||||
} else {
|
} else {
|
||||||
os<<" "<<std::right<<std::fixed<<std::setprecision(0)<<std::setw(9)<<count();
|
os << " " << std::right << std::fixed << std::setprecision(0) << std::setw(9) << count();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//######################################################################
|
//######################################################################
|
||||||
// Top Stats class
|
// 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];
|
||||||
const string digitName = string(digits)+"_"+name;
|
sprintf(digits, "%03d", ++fileNumber);
|
||||||
|
const string digitName = string(digits) + "_" + name;
|
||||||
|
|
||||||
double wallTime = V3Os::timeUsecs() / 1.0e6;
|
double wallTime = V3Os::timeUsecs() / 1.0e6;
|
||||||
if (lastWallTime<0) lastWallTime = wallTime;
|
if (lastWallTime < 0) lastWallTime = wallTime;
|
||||||
double wallTimeDelta = wallTime - lastWallTime;
|
double wallTimeDelta = wallTime - lastWallTime;
|
||||||
lastWallTime = wallTime;
|
lastWallTime = wallTime;
|
||||||
V3Stats::addStatPerf("Stage, Elapsed time (sec), "+digitName, wallTimeDelta);
|
V3Stats::addStatPerf("Stage, Elapsed time (sec), " + digitName, wallTimeDelta);
|
||||||
|
|
||||||
double memory = V3Os::memUsageBytes()/1024.0/1024.0;
|
double memory = V3Os::memUsageBytes() / 1024.0 / 1024.0;
|
||||||
V3Stats::addStatPerf("Stage, Memory (MB), "+digitName, memory);
|
V3Stats::addStatPerf("Stage, Memory (MB), " + digitName, memory);
|
||||||
}
|
}
|
||||||
|
|
||||||
void V3Stats::statsReport() {
|
void V3Stats::statsReport() {
|
||||||
UINFO(2,__FUNCTION__<<": "<<endl);
|
UINFO(2, __FUNCTION__ << ": " << endl);
|
||||||
|
|
||||||
// Open stats file
|
// Open stats file
|
||||||
string filename = v3Global.opt.makeDir()+"/"+v3Global.opt.prefix()+"__stats.txt";
|
string filename = v3Global.opt.makeDir() + "/" + v3Global.opt.prefix() + "__stats.txt";
|
||||||
std::ofstream* ofp (V3File::new_ofstream(filename));
|
std::ofstream* ofp(V3File::new_ofstream(filename));
|
||||||
if (ofp->fail()) v3fatal("Can't write "<<filename);
|
if (ofp->fail()) v3fatal("Can't write " << filename);
|
||||||
|
|
||||||
StatsReport reporter (ofp);
|
StatsReport reporter(ofp);
|
||||||
|
|
||||||
// Cleanup
|
// Cleanup
|
||||||
ofp->close();
|
ofp->close();
|
||||||
|
|
|
||||||
183
src/V3String.cpp
183
src/V3String.cpp
|
|
@ -31,18 +31,14 @@ size_t VName::s_maxLength = 0; // Disabled
|
||||||
|
|
||||||
// Double procedures, inlined, unrolls loop much better
|
// Double procedures, inlined, unrolls loop much better
|
||||||
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;
|
||||||
}
|
}
|
||||||
|
|
@ -51,18 +47,14 @@ 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;
|
||||||
}
|
}
|
||||||
|
|
@ -74,29 +66,25 @@ bool VString::wildmatch(const string& s, const string& p) {
|
||||||
return wildmatch(s.c_str(), p.c_str());
|
return wildmatch(s.c_str(), p.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
bool VString::isWildcard(const string &p) {
|
bool VString::isWildcard(const string& p) {
|
||||||
return ((p.find('*') != string::npos) || (p.find('?') != string::npos));
|
return ((p.find('*') != string::npos) || (p.find('?') != string::npos));
|
||||||
}
|
}
|
||||||
|
|
||||||
string VString::dot(const string& a, const string& dot, const string& b) {
|
string VString::dot(const string& a, const string& dot, const string& b) {
|
||||||
if (b=="") return a;
|
if (b == "") return a;
|
||||||
if (a=="") return b;
|
if (a == "") return b;
|
||||||
return a+dot+b;
|
return a + dot + 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];
|
||||||
|
|
@ -164,17 +154,15 @@ static inline void sha256Block(uint32_t* h, const uint32_t* chunk) {
|
||||||
// Extend the first 16 words into the remaining
|
// Extend the first 16 words into the remaining
|
||||||
// 48 words w[16..63] of the message schedule array:
|
// 48 words w[16..63] of the message schedule array:
|
||||||
const uint32_t s0 = shaRotr32(w[(j + 1) & 0xf], 7)
|
const uint32_t s0 = shaRotr32(w[(j + 1) & 0xf], 7)
|
||||||
^ shaRotr32(w[(j + 1) & 0xf], 18) ^ (w[(j + 1) & 0xf] >> 3);
|
^ shaRotr32(w[(j + 1) & 0xf], 18) ^ (w[(j + 1) & 0xf] >> 3);
|
||||||
const uint32_t s1 = shaRotr32(w[(j + 14) & 0xf], 17)
|
const uint32_t s1 = shaRotr32(w[(j + 14) & 0xf], 17)
|
||||||
^ shaRotr32(w[(j + 14) & 0xf], 19) ^ (w[(j + 14) & 0xf] >> 10);
|
^ shaRotr32(w[(j + 14) & 0xf], 19) ^ (w[(j + 14) & 0xf] >> 10);
|
||||||
w[j] = w[j] + s0 + w[(j + 9) & 0xf] + s1;
|
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;
|
||||||
|
|
@ -199,7 +186,7 @@ void VHashSha256::insert(const void* datap, size_t length) {
|
||||||
string tempData;
|
string tempData;
|
||||||
int chunkLen;
|
int chunkLen;
|
||||||
const uint8_t* chunkp;
|
const uint8_t* chunkp;
|
||||||
if (m_remainder=="") {
|
if (m_remainder == "") {
|
||||||
chunkLen = length;
|
chunkLen = length;
|
||||||
chunkp = static_cast<const uint8_t*>(datap);
|
chunkp = static_cast<const uint8_t*>(datap);
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -229,7 +216,7 @@ void VHashSha256::insert(const void* datap, size_t length) {
|
||||||
sha256Block(m_inthash, w);
|
sha256Block(m_inthash, w);
|
||||||
}
|
}
|
||||||
|
|
||||||
m_remainder = string(reinterpret_cast<const char*>(chunkp+posBegin), chunkLen-posEnd);
|
m_remainder = string(reinterpret_cast<const char*>(chunkp + posBegin), chunkLen - posEnd);
|
||||||
}
|
}
|
||||||
|
|
||||||
void VHashSha256::finalize() {
|
void VHashSha256::finalize() {
|
||||||
|
|
@ -240,16 +227,16 @@ void VHashSha256::finalize() {
|
||||||
|
|
||||||
// Process final possibly non-complete 64-byte block
|
// Process final possibly non-complete 64-byte block
|
||||||
uint32_t w[16]; // Round buffer, [0..15] are input data
|
uint32_t w[16]; // Round buffer, [0..15] are input data
|
||||||
for (int i=0; i<16; ++i) w[i] = 0;
|
for (int i = 0; i < 16; ++i) w[i] = 0;
|
||||||
size_t blockPos = 0;
|
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) {
|
||||||
sha256Block(m_inthash, w);
|
sha256Block(m_inthash, w);
|
||||||
for (int i=0; i<16; ++i) w[i] = 0;
|
for (int i = 0; i < 16; ++i) w[i] = 0;
|
||||||
}
|
}
|
||||||
w[15] = m_totLength << 3;
|
w[15] = m_totLength << 3;
|
||||||
sha256Block(m_inthash, w);
|
sha256Block(m_inthash, w);
|
||||||
|
|
@ -260,8 +247,9 @@ void VHashSha256::finalize() {
|
||||||
|
|
||||||
string VHashSha256::digestBinary() {
|
string VHashSha256::digestBinary() {
|
||||||
finalize();
|
finalize();
|
||||||
string out; out.reserve(32);
|
string out;
|
||||||
for (size_t i=0; i<32; ++i) {
|
out.reserve(32);
|
||||||
|
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;
|
||||||
}
|
}
|
||||||
return out;
|
return out;
|
||||||
|
|
@ -270,20 +258,21 @@ string VHashSha256::digestBinary() {
|
||||||
uint64_t VHashSha256::digestUInt64() {
|
uint64_t VHashSha256::digestUInt64() {
|
||||||
const string& binhash = digestBinary();
|
const string& binhash = digestBinary();
|
||||||
uint64_t out = 0;
|
uint64_t out = 0;
|
||||||
for (size_t byte=0; byte<sizeof(uint64_t); ++byte) {
|
for (size_t byte = 0; byte < sizeof(uint64_t); ++byte) {
|
||||||
unsigned char c = binhash[byte];
|
unsigned char c = binhash[byte];
|
||||||
out = (out<<8) | c;
|
out = (out << 8) | c;
|
||||||
}
|
}
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
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;
|
||||||
for (size_t byte=0; byte<32; ++byte) {
|
out.reserve(70);
|
||||||
out += digits[ (binhash[byte]>>4) & 0xf ];
|
for (size_t byte = 0; byte < 32; ++byte) {
|
||||||
out += digits[ (binhash[byte]>>0) & 0xf ];
|
out += digits[(binhash[byte] >> 4) & 0xf];
|
||||||
|
out += digits[(binhash[byte] >> 0) & 0xf];
|
||||||
}
|
}
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
@ -293,12 +282,13 @@ string VHashSha256::digestSymbol() {
|
||||||
// has + and / for last two digits, but need C symbol, and we also
|
// has + and / for last two digits, but need C symbol, and we also
|
||||||
// avoid conflicts with use of _, so use "AB" at the end.
|
// avoid conflicts with use of _, so use "AB" at the end.
|
||||||
// Thus this function is non-reversible.
|
// Thus this function is non-reversible.
|
||||||
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)];
|
||||||
out += digits[((binhash[pos] & 0x3) << 4)
|
out += digits[((binhash[pos] & 0x3) << 4)
|
||||||
| (static_cast<int>(binhash[pos + 1] & 0xf0) >> 4)];
|
| (static_cast<int>(binhash[pos + 1] & 0xf0) >> 4)];
|
||||||
|
|
@ -310,28 +300,26 @@ 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)) {
|
||||||
std::cerr << "%Error: When hashing '"<<data+data2<<"'"<<endl // LCOV_EXCL_LINE
|
std::cerr << "%Error: When hashing '" << data + data2 << "'" << endl // LCOV_EXCL_LINE
|
||||||
<< " ... got="<<digest.digestHex()<<endl // LCOV_EXCL_LINE
|
<< " ... got=" << digest.digestHex() << endl // LCOV_EXCL_LINE
|
||||||
<< " ... exp="<<exp<<endl; // LCOV_EXCL_LINE
|
<< " ... exp=" << exp << endl; // LCOV_EXCL_LINE
|
||||||
}
|
}
|
||||||
if (VL_UNCOVERABLE(digest.digestSymbol() != exp64)) {
|
if (VL_UNCOVERABLE(digest.digestSymbol() != exp64)) {
|
||||||
std::cerr << "%Error: When hashing '"<<data+data2<<"'"<<endl // LCOV_EXCL_LINE
|
std::cerr << "%Error: When hashing '" << data + data2 << "'" << endl // LCOV_EXCL_LINE
|
||||||
<< " ... got="<<digest.digestSymbol()<<endl // LCOV_EXCL_LINE
|
<< " ... got=" << digest.digestSymbol() << endl // LCOV_EXCL_LINE
|
||||||
<< " ... exp="<<exp64<<endl; // LCOV_EXCL_LINE
|
<< " ... exp=" << exp64 << endl; // LCOV_EXCL_LINE
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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",
|
||||||
|
|
@ -351,14 +339,14 @@ void VHashSha256::selfTest() {
|
||||||
// VName
|
// VName
|
||||||
|
|
||||||
string VName::hashedName() {
|
string VName::hashedName() {
|
||||||
if (m_name=="") return "";
|
if (m_name == "") return "";
|
||||||
if (m_hashed!="") return m_hashed; // Memoized
|
if (m_hashed != "") return m_hashed; // Memoized
|
||||||
if (s_maxLength==0 || m_name.length() < s_maxLength) {
|
if (s_maxLength == 0 || m_name.length() < s_maxLength) {
|
||||||
m_hashed = m_name;
|
m_hashed = m_name;
|
||||||
return m_hashed;
|
return m_hashed;
|
||||||
} else {
|
} else {
|
||||||
VHashSha256 hash(m_name);
|
VHashSha256 hash(m_name);
|
||||||
string suffix = "__Vhsh"+hash.digestSymbol();
|
string suffix = "__Vhsh" + hash.digestSymbol();
|
||||||
if (s_minLength < s_maxLength) {
|
if (s_minLength < s_maxLength) {
|
||||||
m_hashed = m_name.substr(0, s_minLength) + suffix;
|
m_hashed = m_name.substr(0, s_minLength) + suffix;
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -389,9 +377,9 @@ VSpellCheck::EditDistance VSpellCheck::editDistance(const string& s, const strin
|
||||||
for (size_t i = 0; i < tLen; i++) {
|
for (size_t i = 0; i < tLen; i++) {
|
||||||
s_v_next[0] = i + 1;
|
s_v_next[0] = i + 1;
|
||||||
for (size_t j = 0; j < sLen; j++) {
|
for (size_t j = 0; j < sLen; j++) {
|
||||||
EditDistance cost =(s[j] == t[i] ? 0 : 1);
|
EditDistance cost = (s[j] == t[i] ? 0 : 1);
|
||||||
EditDistance deletion = s_v_next[j] + 1;
|
EditDistance deletion = s_v_next[j] + 1;
|
||||||
EditDistance insertion = s_v_one_ago[j + 1] + 1;
|
EditDistance insertion = s_v_one_ago[j + 1] + 1;
|
||||||
EditDistance substitution = s_v_one_ago[j] + cost;
|
EditDistance substitution = s_v_one_ago[j] + cost;
|
||||||
EditDistance cheapest = std::min(deletion, insertion);
|
EditDistance cheapest = std::min(deletion, insertion);
|
||||||
cheapest = std::min(cheapest, substitution);
|
cheapest = std::min(cheapest, substitution);
|
||||||
|
|
@ -420,13 +408,11 @@ VSpellCheck::EditDistance VSpellCheck::cutoffDistance(size_t goal_len, size_t ca
|
||||||
return (max_length + 2) / 3;
|
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);
|
||||||
}
|
}
|
||||||
|
|
@ -462,7 +447,7 @@ void VSpellCheck::selfTestSuggestOne(bool matches, const string& c, const string
|
||||||
EditDistance gdist;
|
EditDistance gdist;
|
||||||
VSpellCheck speller;
|
VSpellCheck speller;
|
||||||
speller.pushCandidate(c);
|
speller.pushCandidate(c);
|
||||||
string got = speller.bestCandidateInfo(goal, gdist/*ref*/);
|
string got = speller.bestCandidateInfo(goal, gdist /*ref*/);
|
||||||
if (matches) {
|
if (matches) {
|
||||||
UASSERT_SELFTEST(string, got, c);
|
UASSERT_SELFTEST(string, got, c);
|
||||||
UASSERT_SELFTEST(EditDistance, gdist, dist);
|
UASSERT_SELFTEST(EditDistance, gdist, dist);
|
||||||
|
|
|
||||||
|
|
@ -30,18 +30,30 @@
|
||||||
// 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;
|
||||||
return u.l.upper^u.l.lower;
|
struct {
|
||||||
|
uint32_t upper;
|
||||||
|
uint32_t lower;
|
||||||
|
} l;
|
||||||
|
} u;
|
||||||
|
u.l.upper = 0;
|
||||||
|
u.l.lower = 0;
|
||||||
|
u.up = vp;
|
||||||
|
return u.l.upper ^ u.l.lower;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline string ucfirst(const string& text) {
|
inline string ucfirst(const string& text) {
|
||||||
|
|
@ -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
|
||||||
|
|
@ -62,7 +75,7 @@ public:
|
||||||
// Return true if p with ? or *'s matches s
|
// Return true if p with ? or *'s matches s
|
||||||
static bool wildmatch(const string& s, const string& p);
|
static bool wildmatch(const string& s, const string& p);
|
||||||
// Return true if this is a wildcard string (contains * or ?)
|
// Return true if this is a wildcard string (contains * or ?)
|
||||||
static bool isWildcard(const string &p);
|
static bool isWildcard(const string& p);
|
||||||
// Return {a}{dot}{b}, omitting dot if a or b are empty
|
// Return {a}{dot}{b}, omitting dot if a or b are empty
|
||||||
static string dot(const string& a, const string& dot, const string& b);
|
static string dot(const string& a, const string& dot, const string& b);
|
||||||
// Convert string to lowercase (tolower)
|
// Convert string to lowercase (tolower)
|
||||||
|
|
@ -88,14 +101,17 @@ class VHashSha256 {
|
||||||
// Or improve to store 0-63 bytes of data between calls to input().
|
// Or improve to store 0-63 bytes of data between calls to input().
|
||||||
|
|
||||||
// MEMBERS
|
// MEMBERS
|
||||||
uint32_t m_inthash[8]; // Intermediate hash, in host order
|
uint32_t m_inthash[8]; // Intermediate hash, in host order
|
||||||
string m_remainder; // Unhashed data
|
string m_remainder; // Unhashed data
|
||||||
bool m_final; // Finalized
|
bool m_final; // Finalized
|
||||||
size_t m_totLength; // Total all-chunk length as needed by output digest
|
size_t m_totLength; // Total all-chunk length as needed by output digest
|
||||||
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
|
||||||
|
|
@ -173,21 +199,24 @@ public:
|
||||||
// Return candidate is closest to provided string, or "" for none
|
// Return candidate is closest to provided string, or "" for none
|
||||||
string bestCandidate(const string& goal) {
|
string bestCandidate(const string& goal) {
|
||||||
EditDistance dist;
|
EditDistance dist;
|
||||||
return bestCandidateInfo(goal, dist/*ref*/);
|
return bestCandidateInfo(goal, dist /*ref*/);
|
||||||
}
|
}
|
||||||
// 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);
|
||||||
};
|
};
|
||||||
|
|
|
||||||
132
src/V3SymTable.h
132
src/V3SymTable.h
|
|
@ -42,15 +42,15 @@ typedef std::set<const VSymEnt*> VSymConstMap;
|
||||||
class VSymEnt {
|
class VSymEnt {
|
||||||
// Symbol table that can have a "superior" table for resolving upper references
|
// Symbol table that can have a "superior" table for resolving upper references
|
||||||
// MEMBERS
|
// MEMBERS
|
||||||
typedef std::multimap<string,VSymEnt*> IdNameMap;
|
typedef std::multimap<string, VSymEnt*> IdNameMap;
|
||||||
IdNameMap m_idNameMap; // Hash of variables by name
|
IdNameMap m_idNameMap; // Hash of variables by name
|
||||||
AstNode* m_nodep; // Node that entry belongs to
|
AstNode* m_nodep; // Node that entry belongs to
|
||||||
VSymEnt* m_fallbackp; // Table "above" this one in name scope, for fallback resolution
|
VSymEnt* m_fallbackp; // Table "above" this one in name scope, for fallback resolution
|
||||||
VSymEnt* m_parentp; // Table that created this table, dot notation needed to resolve into it
|
VSymEnt* m_parentp; // Table that created this table, dot notation needed to resolve into it
|
||||||
AstNodeModule* m_packagep; // Package node is in (for V3LinkDot, unused here)
|
AstNodeModule* m_packagep; // Package node is in (for V3LinkDot, unused here)
|
||||||
string m_symPrefix; // String to prefix symbols with (for V3LinkDot, unused here)
|
string m_symPrefix; // String to prefix symbols with (for V3LinkDot, unused here)
|
||||||
bool m_exported; // Allow importing
|
bool m_exported; // Allow importing
|
||||||
bool m_imported; // Was imported
|
bool m_imported; // Was imported
|
||||||
#ifdef VL_DEBUG
|
#ifdef VL_DEBUG
|
||||||
static int debug() {
|
static int debug() {
|
||||||
static int level = -1;
|
static int level = -1;
|
||||||
|
|
@ -61,32 +61,33 @@ 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(); }
|
||||||
|
|
||||||
void dumpIterate(std::ostream& os, VSymConstMap& doneSymsr, const string& indent,
|
void dumpIterate(std::ostream& os, VSymConstMap& doneSymsr, const string& indent,
|
||||||
int numLevels, const string& searchName) const {
|
int numLevels, const string& searchName) const {
|
||||||
os<<indent<<"+ "<<std::left<<std::setw(30)
|
os << indent << "+ " << std::left << std::setw(30)
|
||||||
<<(searchName==""?"\"\"":searchName)<<std::setw(0)<<std::right;
|
<< (searchName == "" ? "\"\"" : searchName) << std::setw(0) << std::right;
|
||||||
os<<" se"<<cvtToHex(this)<<std::setw(0);
|
os << " se" << cvtToHex(this) << std::setw(0);
|
||||||
os<<" fallb=se"<<cvtToHex(m_fallbackp);
|
os << " fallb=se" << cvtToHex(m_fallbackp);
|
||||||
if (m_symPrefix!="") os<<" symPrefix="<<m_symPrefix;
|
if (m_symPrefix != "") os << " symPrefix=" << m_symPrefix;
|
||||||
os<<" n="<<nodep();
|
os << " n=" << nodep();
|
||||||
os<<endl;
|
os << endl;
|
||||||
if (doneSymsr.find(this) != doneSymsr.end()) {
|
if (doneSymsr.find(this) != doneSymsr.end()) {
|
||||||
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void dump(std::ostream& os, const string& indent="", int numLevels=1) const {
|
void dump(std::ostream& os, const string& indent = "", int numLevels = 1) const {
|
||||||
VSymConstMap doneSyms;
|
VSymConstMap doneSyms;
|
||||||
dumpIterate(os, doneSyms, indent, numLevels, "TOP");
|
dumpIterate(os, doneSyms, indent, numLevels, "TOP");
|
||||||
}
|
}
|
||||||
|
|
@ -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));
|
||||||
|
|
@ -133,9 +135,9 @@ 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) {
|
||||||
|
|
@ -224,14 +225,14 @@ public:
|
||||||
}
|
}
|
||||||
void exportStarStar(VSymGraph* graphp) {
|
void exportStarStar(VSymGraph* graphp) {
|
||||||
// Export *:*: Export all tokens from imported packages
|
// Export *:*: Export all tokens from imported packages
|
||||||
for (IdNameMap::const_iterator it=m_idNameMap.begin(); it!=m_idNameMap.end(); ++it) {
|
for (IdNameMap::const_iterator it = m_idNameMap.begin(); it != m_idNameMap.end(); ++it) {
|
||||||
VSymEnt* symp = it->second;
|
VSymEnt* symp = it->second;
|
||||||
if (!symp->exported()) symp->exported(true);
|
if (!symp->exported()) symp->exported(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void importFromIface(VSymGraph* graphp, const VSymEnt* srcp, bool onlyUnmodportable = false) {
|
void importFromIface(VSymGraph* graphp, const VSymEnt* srcp, bool onlyUnmodportable = false) {
|
||||||
// Import interface tokens from source symbol table into this symbol table, recursively
|
// Import interface tokens from source symbol table into this symbol table, recursively
|
||||||
UINFO(9, " importIf se"<<cvtToHex(this)<<" from se"<<cvtToHex(srcp)<<endl);
|
UINFO(9, " importIf se" << cvtToHex(this) << " from se" << cvtToHex(srcp) << endl);
|
||||||
for (IdNameMap::const_iterator it = srcp->m_idNameMap.begin();
|
for (IdNameMap::const_iterator it = srcp->m_idNameMap.begin();
|
||||||
it != srcp->m_idNameMap.end(); ++it) {
|
it != srcp->m_idNameMap.end(); ++it) {
|
||||||
const string& name = it->first;
|
const string& name = it->first;
|
||||||
|
|
@ -245,20 +246,19 @@ public:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void cellErrorScopes(AstNode* lookp, string prettyName="") {
|
void cellErrorScopes(AstNode* lookp, string prettyName = "") {
|
||||||
if (prettyName=="") prettyName = lookp->prettyName();
|
if (prettyName == "") prettyName = lookp->prettyName();
|
||||||
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);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
@ -272,43 +272,43 @@ class VSymGraph {
|
||||||
typedef std::vector<VSymEnt*> SymStack;
|
typedef std::vector<VSymEnt*> SymStack;
|
||||||
|
|
||||||
// MEMBERS
|
// MEMBERS
|
||||||
VSymEnt* m_symRootp; // Root symbol table
|
VSymEnt* m_symRootp; // Root symbol table
|
||||||
SymStack m_symsp; // All symbol tables, to cleanup
|
SymStack m_symsp; // All symbol tables, to cleanup
|
||||||
|
|
||||||
// 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:
|
||||||
// METHODS
|
// METHODS
|
||||||
VSymEnt* rootp() const { return m_symRootp; }
|
VSymEnt* rootp() const { return m_symRootp; }
|
||||||
// Debug
|
// Debug
|
||||||
void dump(std::ostream& os, const string& indent="") {
|
void dump(std::ostream& os, const string& indent = "") {
|
||||||
VSymConstMap doneSyms;
|
VSymConstMap doneSyms;
|
||||||
os<<"SymEnt Dump:\n";
|
os << "SymEnt Dump:\n";
|
||||||
m_symRootp->dumpIterate(os, doneSyms, indent, 9999, "$root");
|
m_symRootp->dumpIterate(os, doneSyms, indent, 9999, "$root");
|
||||||
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");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void dumpFilePrefixed(const string& nameComment) {
|
void dumpFilePrefixed(const string& nameComment) {
|
||||||
if (v3Global.opt.dumpTree()) {
|
if (v3Global.opt.dumpTree()) {
|
||||||
string filename = v3Global.debugFilename(nameComment)+".txt";
|
string filename = v3Global.debugFilename(nameComment) + ".txt";
|
||||||
UINFO(2,"Dumping "<<filename<<endl);
|
UINFO(2, "Dumping " << filename << endl);
|
||||||
const vl_unique_ptr<std::ofstream> logp (V3File::new_ofstream(filename));
|
const vl_unique_ptr<std::ofstream> logp(V3File::new_ofstream(filename));
|
||||||
if (logp->fail()) v3fatal("Can't write "<<filename);
|
if (logp->fail()) v3fatal("Can't write " << filename);
|
||||||
dump(*logp, "");
|
dump(*logp, "");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -336,7 +336,7 @@ inline VSymEnt::VSymEnt(VSymGraph* graphp, AstNode* nodep)
|
||||||
inline VSymEnt::VSymEnt(VSymGraph* graphp, const VSymEnt* symp)
|
inline VSymEnt::VSymEnt(VSymGraph* graphp, const VSymEnt* symp)
|
||||||
: m_nodep(symp->m_nodep) {
|
: m_nodep(symp->m_nodep) {
|
||||||
m_fallbackp = symp->m_fallbackp;
|
m_fallbackp = symp->m_fallbackp;
|
||||||
m_parentp = symp->m_parentp;
|
m_parentp = symp->m_parentp;
|
||||||
m_packagep = symp->m_packagep;
|
m_packagep = symp->m_packagep;
|
||||||
m_exported = symp->m_exported;
|
m_exported = symp->m_exported;
|
||||||
m_imported = symp->m_imported;
|
m_imported = symp->m_imported;
|
||||||
|
|
|
||||||
38
src/V3TSP.h
38
src/V3TSP.h
|
|
@ -24,30 +24,30 @@
|
||||||
#include "V3Error.h"
|
#include "V3Error.h"
|
||||||
|
|
||||||
namespace V3TSP {
|
namespace V3TSP {
|
||||||
// Perform a "Traveling Salesman Problem" optimizing sort
|
// Perform a "Traveling Salesman Problem" optimizing sort
|
||||||
// on any type you like -- so long as inherits from TspStateBase.
|
// on any type you like -- so long as inherits from TspStateBase.
|
||||||
|
|
||||||
class TspStateBase {
|
class TspStateBase {
|
||||||
public:
|
public:
|
||||||
// This is the cost function that the TSP sort will minimize.
|
// This is the cost function that the TSP sort will minimize.
|
||||||
// All costs in V3TSP are int, chosen to match the type of
|
// All costs in V3TSP are int, chosen to match the type of
|
||||||
// V3GraphEdge::weight() which will reflect each edge's cost.
|
// V3GraphEdge::weight() which will reflect each edge's cost.
|
||||||
virtual int cost(const TspStateBase* otherp) const = 0;
|
virtual int cost(const TspStateBase* otherp) const = 0;
|
||||||
|
|
||||||
// This operator< must place a meaningless, arbitrary, but
|
// This operator< must place a meaningless, arbitrary, but
|
||||||
// stable order on all TspStateBase's. It's used only to
|
// stable order on all TspStateBase's. It's used only to
|
||||||
// key maps so that iteration is stable, without relying
|
// key maps so that iteration is stable, without relying
|
||||||
// on pointer values that could lead to nondeterminism.
|
// on pointer values that could lead to nondeterminism.
|
||||||
virtual bool operator<(const TspStateBase& otherp) const = 0;
|
virtual bool operator<(const TspStateBase& otherp) const = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef std::vector<const TspStateBase*> StateVec;
|
typedef std::vector<const TspStateBase*> StateVec;
|
||||||
|
|
||||||
// Given an unsorted set of TspState's, sort them to minimize
|
// Given an unsorted set of TspState's, sort them to minimize
|
||||||
// the transition cost for walking the sorted list.
|
// the transition cost for walking the sorted list.
|
||||||
void tspSort(const StateVec& states, StateVec* resultp);
|
void tspSort(const StateVec& states, StateVec* resultp);
|
||||||
|
|
||||||
void selfTest();
|
void selfTest();
|
||||||
} // namespace V3TSP
|
} // namespace V3TSP
|
||||||
|
|
||||||
#endif // Guard
|
#endif // Guard
|
||||||
|
|
|
||||||
|
|
@ -27,7 +27,7 @@
|
||||||
|
|
||||||
//============================================================================
|
//============================================================================
|
||||||
|
|
||||||
typedef std::pair<AstVar*,AstArg*> V3TaskConnect; // [port, pin-connects-to]
|
typedef std::pair<AstVar*, AstArg*> V3TaskConnect; // [port, pin-connects-to]
|
||||||
typedef std::vector<V3TaskConnect> V3TaskConnects; // [ [port, pin-connects-to] ... ]
|
typedef std::vector<V3TaskConnect> V3TaskConnects; // [ [port, pin-connects-to] ... ]
|
||||||
|
|
||||||
//============================================================================
|
//============================================================================
|
||||||
|
|
|
||||||
264
src/V3Trace.cpp
264
src/V3Trace.cpp
|
|
@ -60,22 +60,24 @@
|
||||||
// Graph vertexes
|
// Graph vertexes
|
||||||
|
|
||||||
class TraceActivityVertex : public V3GraphVertex {
|
class TraceActivityVertex : public V3GraphVertex {
|
||||||
AstNode* m_insertp; // Insert before this statement
|
AstNode* m_insertp; // Insert before this statement
|
||||||
vlsint32_t m_activityCode;
|
vlsint32_t m_activityCode;
|
||||||
bool m_activityCodeValid;
|
bool m_activityCodeValid;
|
||||||
bool m_slow; // If always slow, we can use the same code
|
bool m_slow; // If always slow, we can use the same code
|
||||||
public:
|
public:
|
||||||
enum { ACTIVITY_NEVER =((1UL<<31) - 1) };
|
enum { ACTIVITY_NEVER = ((1UL << 31) - 1) };
|
||||||
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; }
|
||||||
|
|
@ -160,31 +176,31 @@ private:
|
||||||
// AstVarScope::user1() // V3GraphVertex* for this node
|
// AstVarScope::user1() // V3GraphVertex* for this node
|
||||||
// AstCCall::user2() // bool; walked next list for other ccalls
|
// AstCCall::user2() // bool; walked next list for other ccalls
|
||||||
// Ast*::user3() // TraceActivityVertex* for this node
|
// Ast*::user3() // TraceActivityVertex* for this node
|
||||||
AstUser1InUse m_inuser1;
|
AstUser1InUse m_inuser1;
|
||||||
AstUser2InUse m_inuser2;
|
AstUser2InUse m_inuser2;
|
||||||
AstUser3InUse m_inuser3;
|
AstUser3InUse m_inuser3;
|
||||||
//AstUser4InUse In V3Hashed
|
// AstUser4InUse In V3Hashed
|
||||||
|
|
||||||
// STATE
|
// STATE
|
||||||
AstNodeModule* m_topModp; // Module to add variables to
|
AstNodeModule* m_topModp; // Module to add variables to
|
||||||
AstScope* m_highScopep; // Scope to add variables to
|
AstScope* m_highScopep; // Scope to add variables to
|
||||||
AstCFunc* m_funcp; // C function adding to graph
|
AstCFunc* m_funcp; // C function adding to graph
|
||||||
AstTraceInc* m_tracep; // Trace function adding to graph
|
AstTraceInc* m_tracep; // Trace function adding to graph
|
||||||
AstCFunc* m_initFuncp; // Trace function we add statements to
|
AstCFunc* m_initFuncp; // Trace function we add statements to
|
||||||
AstCFunc* m_fullFuncp; // Trace function we add statements to
|
AstCFunc* m_fullFuncp; // Trace function we add statements to
|
||||||
AstCFunc* m_fullSubFuncp; // Trace function we add statements to (under full)
|
AstCFunc* m_fullSubFuncp; // Trace function we add statements to (under full)
|
||||||
int m_fullSubStmts; // Statements under function being built
|
int m_fullSubStmts; // Statements under function being built
|
||||||
AstCFunc* m_chgFuncp; // Trace function we add statements to
|
AstCFunc* m_chgFuncp; // Trace function we add statements to
|
||||||
AstCFunc* m_chgSubFuncp; // Trace function we add statements to (under full)
|
AstCFunc* m_chgSubFuncp; // Trace function we add statements to (under full)
|
||||||
AstNode* m_chgSubParentp;// Which node has call to m_chgSubFuncp
|
AstNode* m_chgSubParentp; // Which node has call to m_chgSubFuncp
|
||||||
int m_chgSubStmts; // Statements under function being built
|
int m_chgSubStmts; // Statements under function being built
|
||||||
AstVarScope* m_activityVscp; // Activity variable
|
AstVarScope* m_activityVscp; // Activity variable
|
||||||
uint32_t m_activityNumber; // Count of fields in activity variable
|
uint32_t m_activityNumber; // Count of fields in activity variable
|
||||||
uint32_t m_code; // Trace ident code# being assigned
|
uint32_t m_code; // Trace ident code# being assigned
|
||||||
V3Graph m_graph; // Var/CFunc tracking
|
V3Graph m_graph; // Var/CFunc tracking
|
||||||
TraceActivityVertex* m_alwaysVtxp; // "Always trace" vertex
|
TraceActivityVertex* m_alwaysVtxp; // "Always trace" vertex
|
||||||
bool m_finding; // Pass one of algorithm?
|
bool m_finding; // Pass one of algorithm?
|
||||||
int m_funcNum; // Function number being built
|
int m_funcNum; // Function number being built
|
||||||
|
|
||||||
VDouble0 m_statChgSigs; // Statistic tracking
|
VDouble0 m_statChgSigs; // Statistic tracking
|
||||||
VDouble0 m_statUniqSigs; // Statistic tracking
|
VDouble0 m_statUniqSigs; // Statistic tracking
|
||||||
|
|
@ -194,11 +210,11 @@ private:
|
||||||
VL_DEBUG_FUNC; // Declare debug()
|
VL_DEBUG_FUNC; // Declare debug()
|
||||||
|
|
||||||
void detectDuplicates() {
|
void detectDuplicates() {
|
||||||
UINFO(9,"Finding duplicates\n");
|
UINFO(9, "Finding duplicates\n");
|
||||||
// Note uses user4
|
// Note uses user4
|
||||||
V3Hashed hashed; // Duplicate code detection
|
V3Hashed hashed; // Duplicate code detection
|
||||||
// Hash all of the values the traceIncs need
|
// Hash all of the values the traceIncs need
|
||||||
for (V3GraphVertex* itp = m_graph.verticesBeginp(); itp; itp=itp->verticesNextp()) {
|
for (V3GraphVertex* itp = m_graph.verticesBeginp(); itp; itp = itp->verticesNextp()) {
|
||||||
if (TraceTraceVertex* vvertexp = dynamic_cast<TraceTraceVertex*>(itp)) {
|
if (TraceTraceVertex* vvertexp = dynamic_cast<TraceTraceVertex*>(itp)) {
|
||||||
AstTraceInc* nodep = vvertexp->nodep();
|
AstTraceInc* nodep = vvertexp->nodep();
|
||||||
if (nodep->valuep()) {
|
if (nodep->valuep()) {
|
||||||
|
|
@ -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()) {
|
||||||
|
|
@ -217,7 +233,7 @@ private:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Find if there are any duplicates
|
// Find if there are any duplicates
|
||||||
for (V3GraphVertex* itp = m_graph.verticesBeginp(); itp; itp=itp->verticesNextp()) {
|
for (V3GraphVertex* itp = m_graph.verticesBeginp(); itp; itp = itp->verticesNextp()) {
|
||||||
if (TraceTraceVertex* vvertexp = dynamic_cast<TraceTraceVertex*>(itp)) {
|
if (TraceTraceVertex* vvertexp = dynamic_cast<TraceTraceVertex*>(itp)) {
|
||||||
AstTraceInc* nodep = vvertexp->nodep();
|
AstTraceInc* nodep = vvertexp->nodep();
|
||||||
if (nodep->valuep() && !vvertexp->duplicatep()) {
|
if (nodep->valuep() && !vvertexp->duplicatep()) {
|
||||||
|
|
@ -228,8 +244,8 @@ private:
|
||||||
UASSERT_OBJ(dupincp, nodep, "Trace duplicate of wrong type");
|
UASSERT_OBJ(dupincp, nodep, "Trace duplicate of wrong type");
|
||||||
TraceTraceVertex* dupvertexp
|
TraceTraceVertex* dupvertexp
|
||||||
= dynamic_cast<TraceTraceVertex*>(dupincp->user1u().toGraphVertex());
|
= dynamic_cast<TraceTraceVertex*>(dupincp->user1u().toGraphVertex());
|
||||||
UINFO(8," Orig "<<nodep<<endl);
|
UINFO(8, " Orig " << nodep << endl);
|
||||||
UINFO(8," dup "<<dupincp<<endl);
|
UINFO(8, " dup " << dupincp << endl);
|
||||||
// Mark the hashed node as the original and our
|
// Mark the hashed node as the original and our
|
||||||
// iterating node as duplicated
|
// iterating node as duplicated
|
||||||
vvertexp->duplicatep(dupvertexp);
|
vvertexp->duplicatep(dupvertexp);
|
||||||
|
|
@ -242,7 +258,7 @@ private:
|
||||||
|
|
||||||
void graphSimplify() {
|
void graphSimplify() {
|
||||||
// Remove all variable nodes
|
// Remove all variable nodes
|
||||||
for (V3GraphVertex* nextp, *itp = m_graph.verticesBeginp(); itp; itp=nextp) {
|
for (V3GraphVertex *nextp, *itp = m_graph.verticesBeginp(); itp; itp = nextp) {
|
||||||
nextp = itp->verticesNextp();
|
nextp = itp->verticesNextp();
|
||||||
if (TraceVarVertex* vvertexp = dynamic_cast<TraceVarVertex*>(itp)) {
|
if (TraceVarVertex* vvertexp = dynamic_cast<TraceVarVertex*>(itp)) {
|
||||||
vvertexp->rerouteEdges(&m_graph);
|
vvertexp->rerouteEdges(&m_graph);
|
||||||
|
|
@ -253,7 +269,7 @@ private:
|
||||||
// We do this twice, as then we have fewer edges to multiply out in the below expansion.
|
// We do this twice, as then we have fewer edges to multiply out in the below expansion.
|
||||||
m_graph.removeRedundantEdges(&V3GraphEdge::followAlwaysTrue);
|
m_graph.removeRedundantEdges(&V3GraphEdge::followAlwaysTrue);
|
||||||
// Remove all Cfunc nodes
|
// Remove all Cfunc nodes
|
||||||
for (V3GraphVertex* nextp, *itp = m_graph.verticesBeginp(); itp; itp=nextp) {
|
for (V3GraphVertex *nextp, *itp = m_graph.verticesBeginp(); itp; itp = nextp) {
|
||||||
nextp = itp->verticesNextp();
|
nextp = itp->verticesNextp();
|
||||||
if (TraceCFuncVertex* vvertexp = dynamic_cast<TraceCFuncVertex*>(itp)) {
|
if (TraceCFuncVertex* vvertexp = dynamic_cast<TraceCFuncVertex*>(itp)) {
|
||||||
vvertexp->rerouteEdges(&m_graph);
|
vvertexp->rerouteEdges(&m_graph);
|
||||||
|
|
@ -265,10 +281,10 @@ private:
|
||||||
m_graph.removeRedundantEdges(&V3GraphEdge::followAlwaysTrue);
|
m_graph.removeRedundantEdges(&V3GraphEdge::followAlwaysTrue);
|
||||||
|
|
||||||
// If there are any edges from a always, keep only the always
|
// If there are any edges from a always, keep only the always
|
||||||
for (V3GraphVertex* itp = m_graph.verticesBeginp(); itp; itp=itp->verticesNextp()) {
|
for (V3GraphVertex* itp = m_graph.verticesBeginp(); itp; itp = itp->verticesNextp()) {
|
||||||
if (TraceTraceVertex* vvertexp = dynamic_cast<TraceTraceVertex*>(itp)) {
|
if (TraceTraceVertex* vvertexp = dynamic_cast<TraceTraceVertex*>(itp)) {
|
||||||
V3GraphEdge* alwaysEdgep = NULL;
|
V3GraphEdge* alwaysEdgep = NULL;
|
||||||
for (V3GraphEdge* edgep = vvertexp->inBeginp(); edgep; edgep=edgep->inNextp()) {
|
for (V3GraphEdge* edgep = vvertexp->inBeginp(); edgep; edgep = edgep->inNextp()) {
|
||||||
TraceActivityVertex* actVtxp
|
TraceActivityVertex* actVtxp
|
||||||
= dynamic_cast<TraceActivityVertex*>(edgep->fromp());
|
= dynamic_cast<TraceActivityVertex*>(edgep->fromp());
|
||||||
UASSERT_OBJ(actVtxp, vvertexp->nodep(),
|
UASSERT_OBJ(actVtxp, vvertexp->nodep(),
|
||||||
|
|
@ -279,21 +295,19 @@ private:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (alwaysEdgep) {
|
if (alwaysEdgep) {
|
||||||
for (V3GraphEdge* nextp, *edgep = vvertexp->inBeginp(); edgep; edgep=nextp) {
|
for (V3GraphEdge *nextp, *edgep = vvertexp->inBeginp(); edgep; edgep = nextp) {
|
||||||
nextp = edgep->inNextp();
|
nextp = edgep->inNextp();
|
||||||
if (edgep!=alwaysEdgep) edgep->unlinkDelete();
|
if (edgep != alwaysEdgep) edgep->unlinkDelete();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Activity points with no outputs can be removed
|
// Activity points with no outputs can be removed
|
||||||
for (V3GraphVertex* nextp, *itp = m_graph.verticesBeginp(); itp; itp=nextp) {
|
for (V3GraphVertex *nextp, *itp = m_graph.verticesBeginp(); itp; itp = nextp) {
|
||||||
nextp = itp->verticesNextp();
|
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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -301,7 +315,7 @@ private:
|
||||||
void assignActivity() {
|
void assignActivity() {
|
||||||
// Select activity numbers and put into each CFunc vertex
|
// Select activity numbers and put into each CFunc vertex
|
||||||
m_activityNumber = 1; // Note 0 indicates "slow"
|
m_activityNumber = 1; // Note 0 indicates "slow"
|
||||||
for (V3GraphVertex* itp = m_graph.verticesBeginp(); itp; itp=itp->verticesNextp()) {
|
for (V3GraphVertex* itp = m_graph.verticesBeginp(); itp; itp = itp->verticesNextp()) {
|
||||||
if (TraceActivityVertex* vvertexp = dynamic_cast<TraceActivityVertex*>(itp)) {
|
if (TraceActivityVertex* vvertexp = dynamic_cast<TraceActivityVertex*>(itp)) {
|
||||||
if (!vvertexp->activityCodeValid()) {
|
if (!vvertexp->activityCodeValid()) {
|
||||||
if (vvertexp->slow()) {
|
if (vvertexp->slow()) {
|
||||||
|
|
@ -328,14 +342,11 @@ 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.
|
||||||
int activityBits = VL_WORDS_I(m_activityNumber) * VL_EDATASIZE;
|
int activityBits = VL_WORDS_I(m_activityNumber) * VL_EDATASIZE;
|
||||||
|
|
@ -348,14 +359,14 @@ private:
|
||||||
m_activityVscp = newvscp;
|
m_activityVscp = newvscp;
|
||||||
|
|
||||||
// Insert activity setter
|
// Insert activity setter
|
||||||
for (V3GraphVertex* itp = m_graph.verticesBeginp(); itp; itp=itp->verticesNextp()) {
|
for (V3GraphVertex* itp = m_graph.verticesBeginp(); itp; itp = itp->verticesNextp()) {
|
||||||
if (TraceActivityVertex* vvertexp = dynamic_cast<TraceActivityVertex*>(itp)) {
|
if (TraceActivityVertex* vvertexp = dynamic_cast<TraceActivityVertex*>(itp)) {
|
||||||
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,31 +374,29 @@ 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);
|
||||||
UINFO(5," Newfunc "<<funcp<<endl);
|
UINFO(5, " Newfunc " << funcp << endl);
|
||||||
return funcp;
|
return funcp;
|
||||||
}
|
}
|
||||||
AstCFunc* newCFuncSub(AstCFunc* basep, AstNode* callfromp) {
|
AstCFunc* newCFuncSub(AstCFunc* basep, AstNode* callfromp) {
|
||||||
string name = basep->name()+"__"+cvtToStr(++m_funcNum);
|
string name = basep->name() + "__" + cvtToStr(++m_funcNum);
|
||||||
AstCFunc* funcp = NULL;
|
AstCFunc* funcp = NULL;
|
||||||
if (basep->funcType()==AstCFuncType::TRACE_FULL) {
|
if (basep->funcType() == AstCFuncType::TRACE_FULL) {
|
||||||
funcp = newCFunc(AstCFuncType::TRACE_FULL_SUB, name, basep);
|
funcp = newCFunc(AstCFuncType::TRACE_FULL_SUB, name, basep);
|
||||||
} else if (basep->funcType()==AstCFuncType::TRACE_CHANGE) {
|
} else if (basep->funcType() == AstCFuncType::TRACE_CHANGE) {
|
||||||
funcp = newCFunc(AstCFuncType::TRACE_CHANGE_SUB, name, basep);
|
funcp = newCFunc(AstCFuncType::TRACE_CHANGE_SUB, name, basep);
|
||||||
} else {
|
} else {
|
||||||
basep->v3fatalSrc("Strange base function type");
|
basep->v3fatalSrc("Strange base function type");
|
||||||
|
|
@ -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);
|
||||||
|
|
@ -418,26 +426,27 @@ private:
|
||||||
|
|
||||||
void putTracesIntoTree() {
|
void putTracesIntoTree() {
|
||||||
// Form a sorted list of the traces we are interested in
|
// Form a sorted list of the traces we are interested in
|
||||||
UINFO(9,"Making trees\n");
|
UINFO(9, "Making trees\n");
|
||||||
|
|
||||||
typedef std::set<uint32_t> ActCodeSet; // All activity numbers applying to a given trace
|
typedef std::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
|
||||||
// If a trace doesn't have activity, it's constant, and we don't
|
// If a trace doesn't have activity, it's constant, and we don't
|
||||||
// need to track changes on it.
|
// need to track changes on it.
|
||||||
for (V3GraphVertex* itp = m_graph.verticesBeginp(); itp; itp=itp->verticesNextp()) {
|
for (V3GraphVertex* itp = m_graph.verticesBeginp(); itp; itp = itp->verticesNextp()) {
|
||||||
if (TraceTraceVertex* vvertexp = dynamic_cast<TraceTraceVertex*>(itp)) {
|
if (TraceTraceVertex* vvertexp = dynamic_cast<TraceTraceVertex*>(itp)) {
|
||||||
ActCodeSet actset;
|
ActCodeSet actset;
|
||||||
UINFO(9," Add to sort: "<<vvertexp<<endl);
|
UINFO(9, " Add to sort: " << vvertexp << endl);
|
||||||
if (debug()>=9) vvertexp->nodep()->dumpTree(cout, "- trnode: ");
|
if (debug() >= 9) vvertexp->nodep()->dumpTree(cout, "- trnode: ");
|
||||||
for (V3GraphEdge* edgep = vvertexp->inBeginp(); edgep; edgep=edgep->inNextp()) {
|
for (V3GraphEdge* edgep = vvertexp->inBeginp(); edgep; edgep = edgep->inNextp()) {
|
||||||
TraceActivityVertex* cfvertexp
|
TraceActivityVertex* cfvertexp
|
||||||
= dynamic_cast<TraceActivityVertex*>(edgep->fromp());
|
= dynamic_cast<TraceActivityVertex*>(edgep->fromp());
|
||||||
UASSERT_OBJ(cfvertexp, vvertexp->nodep(),
|
UASSERT_OBJ(cfvertexp, vvertexp->nodep(),
|
||||||
"Should have been function pointing to this trace");
|
"Should have been function pointing to this trace");
|
||||||
UINFO(9," Activity: "<<cfvertexp<<endl);
|
UINFO(9, " Activity: " << cfvertexp << endl);
|
||||||
if (cfvertexp->activityAlways()) {
|
if (cfvertexp->activityAlways()) {
|
||||||
// If code 0, we always trace; ignore other codes
|
// If code 0, we always trace; ignore other codes
|
||||||
actset.clear();
|
actset.clear();
|
||||||
|
|
@ -464,10 +473,10 @@ private:
|
||||||
// Put TRACEs back into the tree
|
// Put TRACEs back into the tree
|
||||||
const ActCodeSet* lastactp = NULL;
|
const ActCodeSet* lastactp = NULL;
|
||||||
AstNode* ifnodep = NULL;
|
AstNode* ifnodep = NULL;
|
||||||
for (TraceVec::iterator it = traces.begin(); it!=traces.end(); ++it) {
|
for (TraceVec::iterator it = traces.begin(); it != traces.end(); ++it) {
|
||||||
const ActCodeSet& actset = it->first;
|
const ActCodeSet& actset = it->first;
|
||||||
TraceTraceVertex* vvertexp = it->second;
|
TraceTraceVertex* vvertexp = it->second;
|
||||||
UINFO(9," Done sort: "<<vvertexp<<endl);
|
UINFO(9, " Done sort: " << vvertexp << endl);
|
||||||
bool needChg = true;
|
bool needChg = true;
|
||||||
if (actset.find(TraceActivityVertex::ACTIVITY_NEVER) != actset.end()) {
|
if (actset.find(TraceActivityVertex::ACTIVITY_NEVER) != actset.end()) {
|
||||||
// No activity needed; it's a constant value or only set in initial block
|
// No activity needed; it's a constant value or only set in initial block
|
||||||
|
|
@ -476,7 +485,8 @@ private:
|
||||||
AstNode* addp = assignTraceCode(vvertexp, vvertexp->nodep(), needChg);
|
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);
|
||||||
}
|
}
|
||||||
|
|
@ -539,13 +551,13 @@ private:
|
||||||
// Assign trace code, add to tree, return node for change tree or null
|
// Assign trace code, add to tree, return node for change tree or null
|
||||||
// Look for identical copies
|
// Look for identical copies
|
||||||
uint32_t codePreassigned = 0;
|
uint32_t codePreassigned = 0;
|
||||||
//if (debug()>=9) nodep->dumpTree(cout, "- assnnode: ");
|
// if (debug()>=9) nodep->dumpTree(cout, "- assnnode: ");
|
||||||
// Find non-duplicated node; note some nodep's maybe null, as they were deleted below
|
// Find non-duplicated node; note some nodep's maybe null, as they were deleted below
|
||||||
TraceTraceVertex* dupvertexp = vvertexp;
|
TraceTraceVertex* dupvertexp = vvertexp;
|
||||||
if (dupvertexp->duplicatep()) {
|
if (dupvertexp->duplicatep()) {
|
||||||
dupvertexp = dupvertexp->duplicatep();
|
dupvertexp = dupvertexp->duplicatep();
|
||||||
UINFO(9," dupOf "<<cvtToHex(dupvertexp)<<" "<<cvtToHex(dupvertexp->nodep())
|
UINFO(9, " dupOf " << cvtToHex(dupvertexp) << " " << cvtToHex(dupvertexp->nodep())
|
||||||
<<" "<<dupvertexp<<endl);
|
<< " " << dupvertexp << endl);
|
||||||
UASSERT_OBJ(!dupvertexp->duplicatep(), dupvertexp->nodep(),
|
UASSERT_OBJ(!dupvertexp->duplicatep(), dupvertexp->nodep(),
|
||||||
"Original node was marked as a duplicate");
|
"Original node was marked as a duplicate");
|
||||||
}
|
}
|
||||||
|
|
@ -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) {
|
||||||
|
|
@ -627,9 +639,9 @@ private:
|
||||||
detectDuplicates();
|
detectDuplicates();
|
||||||
|
|
||||||
// Simplify it
|
// Simplify it
|
||||||
if (debug()>=6) m_graph.dumpDotFilePrefixed("trace_pre");
|
if (debug() >= 6) m_graph.dumpDotFilePrefixed("trace_pre");
|
||||||
graphSimplify();
|
graphSimplify();
|
||||||
if (debug()>=6) m_graph.dumpDotFilePrefixed("trace_opt");
|
if (debug() >= 6) m_graph.dumpDotFilePrefixed("trace_opt");
|
||||||
|
|
||||||
// Create new TRACEINCs
|
// Create new TRACEINCs
|
||||||
assignActivity();
|
assignActivity();
|
||||||
|
|
@ -646,15 +658,15 @@ private:
|
||||||
iterateChildren(nodep);
|
iterateChildren(nodep);
|
||||||
}
|
}
|
||||||
virtual void visit(AstCCall* nodep) VL_OVERRIDE {
|
virtual void visit(AstCCall* nodep) VL_OVERRIDE {
|
||||||
UINFO(8," CCALL "<<nodep<<endl);
|
UINFO(8, " CCALL " << nodep << endl);
|
||||||
if (!m_finding && !nodep->user2()) {
|
if (!m_finding && !nodep->user2()) {
|
||||||
// See if there are other calls in same statement list;
|
// See if there are other calls in same statement list;
|
||||||
// If so, all funcs might share the same activity code
|
// If so, all funcs might share the same activity code
|
||||||
TraceActivityVertex* activityVtxp = getActivityVertexp(nodep, nodep->funcp()->slow());
|
TraceActivityVertex* activityVtxp = getActivityVertexp(nodep, nodep->funcp()->slow());
|
||||||
for (AstNode* nextp=nodep; nextp; nextp=nextp->nextp()) {
|
for (AstNode* nextp = nodep; nextp; nextp = nextp->nextp()) {
|
||||||
if (AstCCall* ccallp = VN_CAST(nextp, CCall)) {
|
if (AstCCall* ccallp = VN_CAST(nextp, CCall)) {
|
||||||
ccallp->user2(true); // Processed
|
ccallp->user2(true); // Processed
|
||||||
UINFO(8," SubCCALL "<<ccallp<<endl);
|
UINFO(8, " SubCCALL " << ccallp << endl);
|
||||||
V3GraphVertex* ccallFuncVtxp = getCFuncVertexp(ccallp->funcp());
|
V3GraphVertex* ccallFuncVtxp = getCFuncVertexp(ccallp->funcp());
|
||||||
activityVtxp->slow(ccallp->funcp()->slow());
|
activityVtxp->slow(ccallp->funcp()->slow());
|
||||||
new V3GraphEdge(&m_graph, activityVtxp, ccallFuncVtxp, 1);
|
new V3GraphEdge(&m_graph, activityVtxp, ccallFuncVtxp, 1);
|
||||||
|
|
@ -664,7 +676,7 @@ private:
|
||||||
iterateChildren(nodep);
|
iterateChildren(nodep);
|
||||||
}
|
}
|
||||||
virtual void visit(AstCFunc* nodep) VL_OVERRIDE {
|
virtual void visit(AstCFunc* nodep) VL_OVERRIDE {
|
||||||
UINFO(8," CFUNC "<<nodep<<endl);
|
UINFO(8, " CFUNC " << nodep << endl);
|
||||||
if (nodep->funcType() == AstCFuncType::TRACE_INIT) {
|
if (nodep->funcType() == AstCFuncType::TRACE_INIT) {
|
||||||
m_initFuncp = nodep;
|
m_initFuncp = nodep;
|
||||||
} else if (nodep->funcType() == AstCFuncType::TRACE_FULL) {
|
} else if (nodep->funcType() == AstCFuncType::TRACE_FULL) {
|
||||||
|
|
@ -673,12 +685,13 @@ 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())
|
||||||
new AstComment(nodep->fileline(), "Tracing activity check", true));
|
nodep->addStmtsp(
|
||||||
|
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);
|
||||||
}
|
}
|
||||||
|
|
@ -688,7 +701,7 @@ private:
|
||||||
m_funcp = NULL;
|
m_funcp = NULL;
|
||||||
}
|
}
|
||||||
virtual void visit(AstTraceInc* nodep) VL_OVERRIDE {
|
virtual void visit(AstTraceInc* nodep) VL_OVERRIDE {
|
||||||
UINFO(8," TRACE "<<nodep<<endl);
|
UINFO(8, " TRACE " << nodep << endl);
|
||||||
UASSERT_OBJ(!m_finding, nodep, "Traces should have been removed in prev step.");
|
UASSERT_OBJ(!m_finding, nodep, "Traces should have been removed in prev step.");
|
||||||
nodep->unlinkFrBack();
|
nodep->unlinkFrBack();
|
||||||
|
|
||||||
|
|
@ -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();
|
||||||
|
|
@ -762,9 +774,7 @@ public:
|
||||||
// Trace class functions
|
// Trace class functions
|
||||||
|
|
||||||
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);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -38,20 +38,20 @@ private:
|
||||||
// NODE STATE
|
// NODE STATE
|
||||||
|
|
||||||
// STATE
|
// STATE
|
||||||
AstScope* m_scopetopp; // Current top scope
|
AstScope* m_scopetopp; // Current top scope
|
||||||
AstCFunc* m_initFuncp; // Trace function being built
|
AstCFunc* m_initFuncp; // Trace function being built
|
||||||
AstCFunc* m_initSubFuncp; // Trace function being built (under m_init)
|
AstCFunc* m_initSubFuncp; // Trace function being built (under m_init)
|
||||||
int m_initSubStmts; // Number of statements in function
|
int m_initSubStmts; // Number of statements in function
|
||||||
AstCFunc* m_fullFuncp; // Trace function being built
|
AstCFunc* m_fullFuncp; // Trace function being built
|
||||||
AstCFunc* m_chgFuncp; // Trace function being built
|
AstCFunc* m_chgFuncp; // Trace function being built
|
||||||
int m_funcNum; // Function number being built
|
int m_funcNum; // Function number being built
|
||||||
AstVarScope* m_traVscp; // Signal being trace constructed
|
AstVarScope* m_traVscp; // Signal being trace constructed
|
||||||
AstNode* m_traValuep; // Signal being traced's value to trace in it
|
AstNode* m_traValuep; // Signal being traced's value to trace in it
|
||||||
string m_traShowname; // Signal being traced's component name
|
string m_traShowname; // Signal being traced's component name
|
||||||
bool m_interface; // Currently tracing an interface
|
bool m_interface; // Currently tracing an interface
|
||||||
|
|
||||||
VDouble0 m_statSigs; // Statistic tracking
|
VDouble0 m_statSigs; // Statistic tracking
|
||||||
VDouble0 m_statIgnSigs; // Statistic tracking
|
VDouble0 m_statIgnSigs; // Statistic tracking
|
||||||
|
|
||||||
// METHODS
|
// METHODS
|
||||||
VL_DEBUG_FUNC; // Declare debug()
|
VL_DEBUG_FUNC; // Declare debug()
|
||||||
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
@ -79,14 +75,14 @@ private:
|
||||||
AstCFunc* newCFunc(AstCFuncType type, const string& name, bool slow) {
|
AstCFunc* newCFunc(AstCFuncType type, const string& name, bool slow) {
|
||||||
AstCFunc* funcp = new AstCFunc(m_scopetopp->fileline(), name, m_scopetopp);
|
AstCFunc* funcp = new AstCFunc(m_scopetopp->fileline(), name, m_scopetopp);
|
||||||
funcp->slow(slow);
|
funcp->slow(slow);
|
||||||
string argTypes(EmitCBaseVisitor::symClassVar()+", "+v3Global.opt.traceClassBase()
|
string argTypes(EmitCBaseVisitor::symClassVar() + ", " + v3Global.opt.traceClassBase()
|
||||||
+"* vcdp, uint32_t code");
|
+ "* vcdp, uint32_t code");
|
||||||
if (m_interface) argTypes += ", const char* scopep";
|
if (m_interface) argTypes += ", const char* scopep";
|
||||||
funcp->argTypes(argTypes);
|
funcp->argTypes(argTypes);
|
||||||
funcp->funcType(type);
|
funcp->funcType(type);
|
||||||
funcp->symProlog(true);
|
funcp->symProlog(true);
|
||||||
m_scopetopp->addActivep(funcp);
|
m_scopetopp->addActivep(funcp);
|
||||||
UINFO(5," Newfunc "<<funcp<<endl);
|
UINFO(5, " Newfunc " << funcp << endl);
|
||||||
return funcp;
|
return funcp;
|
||||||
}
|
}
|
||||||
void callCFuncSub(AstCFunc* basep, AstCFunc* funcp, AstIntfRef* irp) {
|
void callCFuncSub(AstCFunc* basep, AstCFunc* funcp, AstIntfRef* irp) {
|
||||||
|
|
@ -96,10 +92,10 @@ private:
|
||||||
basep->addStmtsp(callp);
|
basep->addStmtsp(callp);
|
||||||
}
|
}
|
||||||
AstCFunc* newCFuncSub(AstCFunc* basep) {
|
AstCFunc* newCFuncSub(AstCFunc* basep) {
|
||||||
string name = basep->name()+"__"+cvtToStr(++m_funcNum);
|
string name = basep->name() + "__" + cvtToStr(++m_funcNum);
|
||||||
AstCFunc* funcp = NULL;
|
AstCFunc* funcp = NULL;
|
||||||
if (basep->funcType()==AstCFuncType::TRACE_INIT
|
if (basep->funcType() == AstCFuncType::TRACE_INIT
|
||||||
|| basep->funcType()==AstCFuncType::TRACE_INIT_SUB) {
|
|| basep->funcType() == AstCFuncType::TRACE_INIT_SUB) {
|
||||||
funcp = newCFunc(AstCFuncType::TRACE_INIT_SUB, name, basep->slow());
|
funcp = newCFunc(AstCFuncType::TRACE_INIT_SUB, name, basep->slow());
|
||||||
} else {
|
} else {
|
||||||
basep->v3fatalSrc("Strange base function type");
|
basep->v3fatalSrc("Strange base function type");
|
||||||
|
|
@ -108,15 +104,19 @@ 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);
|
}
|
||||||
UINFO(9,"Decl "<<declp<<endl);
|
AstTraceDecl* declp
|
||||||
|
= new AstTraceDecl(m_traVscp->fileline(), m_traShowname, m_traVscp->varp(),
|
||||||
|
m_traValuep, bitRange, arrayRange, m_interface);
|
||||||
|
UINFO(9, "Decl " << declp << endl);
|
||||||
|
|
||||||
if (!m_interface && v3Global.opt.outputSplitCTrace()
|
if (!m_interface && v3Global.opt.outputSplitCTrace()
|
||||||
&& m_initSubStmts > v3Global.opt.outputSplitCTrace()) {
|
&& m_initSubStmts > 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
|
||||||
|
|
@ -144,7 +143,7 @@ private:
|
||||||
// Make containers for TRACEDECLs first
|
// Make containers for TRACEDECLs first
|
||||||
m_initFuncp = newCFunc(AstCFuncType::TRACE_INIT, "traceInitThis", true);
|
m_initFuncp = newCFunc(AstCFuncType::TRACE_INIT, "traceInitThis", true);
|
||||||
m_fullFuncp = newCFunc(AstCFuncType::TRACE_FULL, "traceFullThis", true);
|
m_fullFuncp = newCFunc(AstCFuncType::TRACE_FULL, "traceFullThis", true);
|
||||||
m_chgFuncp = newCFunc(AstCFuncType::TRACE_CHANGE, "traceChgThis", false);
|
m_chgFuncp = newCFunc(AstCFuncType::TRACE_CHANGE, "traceChgThis", false);
|
||||||
//
|
//
|
||||||
m_initSubFuncp = newCFuncSub(m_initFuncp);
|
m_initSubFuncp = newCFuncSub(m_initFuncp);
|
||||||
// And find variables
|
// And find variables
|
||||||
|
|
@ -162,7 +161,7 @@ private:
|
||||||
size_t lastDot = scopeName.find_last_of('.');
|
size_t lastDot = scopeName.find_last_of('.');
|
||||||
UASSERT_OBJ(lastDot != string::npos, nodep,
|
UASSERT_OBJ(lastDot != string::npos, nodep,
|
||||||
"Expected an interface scope name to have at least one dot");
|
"Expected an interface scope name to have at least one dot");
|
||||||
scopeName = scopeName.substr(0, lastDot+1);
|
scopeName = scopeName.substr(0, lastDot + 1);
|
||||||
size_t scopeLen = scopeName.length();
|
size_t scopeLen = scopeName.length();
|
||||||
|
|
||||||
AstIntfRef* nextIrp = cellp->intfRefp();
|
AstIntfRef* nextIrp = cellp->intfRefp();
|
||||||
|
|
@ -195,9 +194,8 @@ 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();
|
||||||
// Compute show name
|
// Compute show name
|
||||||
|
|
@ -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()) {
|
||||||
|
|
@ -259,14 +258,13 @@ private:
|
||||||
} else {
|
} else {
|
||||||
// Unroll now, as have no other method to get right signal names
|
// Unroll now, as have no other method to get right signal names
|
||||||
AstNodeDType* subtypep = nodep->subDTypep()->skipRefToEnump();
|
AstNodeDType* subtypep = nodep->subDTypep()->skipRefToEnump();
|
||||||
for (int i=nodep->lsb(); i<=nodep->msb(); ++i) {
|
for (int i = nodep->lsb(); i <= nodep->msb(); ++i) {
|
||||||
string oldShowname = m_traShowname;
|
string oldShowname = m_traShowname;
|
||||||
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);
|
||||||
|
|
@ -287,13 +285,13 @@ private:
|
||||||
addTraceDecl(VNumRange(), nodep->width());
|
addTraceDecl(VNumRange(), nodep->width());
|
||||||
} else {
|
} else {
|
||||||
AstNodeDType* subtypep = nodep->subDTypep()->skipRefToEnump();
|
AstNodeDType* subtypep = nodep->subDTypep()->skipRefToEnump();
|
||||||
for (int i=nodep->lsb(); i<=nodep->msb(); ++i) {
|
for (int i = nodep->lsb(); i <= nodep->msb(); ++i) {
|
||||||
string oldShowname = m_traShowname;
|
string oldShowname = m_traShowname;
|
||||||
AstNode* oldValuep = m_traValuep;
|
AstNode* oldValuep = m_traValuep;
|
||||||
{
|
{
|
||||||
m_traShowname += string("(")+cvtToStr(i)+string(")");
|
m_traShowname += string("(") + cvtToStr(i) + string(")");
|
||||||
m_traValuep = new AstSel(nodep->fileline(), m_traValuep->cloneTree(true),
|
m_traValuep = new AstSel(nodep->fileline(), m_traValuep->cloneTree(true),
|
||||||
(i - nodep->lsb())*subtypep->width(),
|
(i - nodep->lsb()) * subtypep->width(),
|
||||||
subtypep->width());
|
subtypep->width());
|
||||||
m_traValuep->dtypep(subtypep);
|
m_traValuep->dtypep(subtypep);
|
||||||
iterate(subtypep);
|
iterate(subtypep);
|
||||||
|
|
@ -316,17 +314,17 @@ 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);
|
||||||
VL_DO_CLEAR(m_traValuep->deleteTree(), m_traValuep = NULL);
|
VL_DO_CLEAR(m_traValuep->deleteTree(), m_traValuep = NULL);
|
||||||
|
|
@ -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;
|
||||||
|
|
@ -387,9 +383,7 @@ public:
|
||||||
// Trace class functions
|
// Trace class functions
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
//######################################################################
|
//######################################################################
|
||||||
|
|
@ -67,15 +67,14 @@ public:
|
||||||
class WidthCommitVisitor : public AstNVisitor {
|
class WidthCommitVisitor : public AstNVisitor {
|
||||||
// NODE STATE
|
// NODE STATE
|
||||||
// AstVar::user1p -> bool, processed
|
// AstVar::user1p -> bool, processed
|
||||||
AstUser1InUse m_inuser1;
|
AstUser1InUse m_inuser1;
|
||||||
|
|
||||||
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());
|
||||||
num.isSigned(nodep->isSigned());
|
num.isSigned(nodep->isSigned());
|
||||||
AstConst* newp = new AstConst(nodep->fileline(), num);
|
AstConst* newp = new AstConst(nodep->fileline(), num);
|
||||||
|
|
@ -102,9 +101,12 @@ private:
|
||||||
// Look for duplicate
|
// Look for duplicate
|
||||||
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;
|
||||||
//if (debug()>4) oldp->dumpTree(cout, " fixConstSize_old: ");
|
nodep = newp;
|
||||||
//if (debug()>4) newp->dumpTree(cout, " _new: ");
|
// if (debug()>4) oldp->dumpTree(cout, " fixConstSize_old: ");
|
||||||
|
// 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