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");
|
||||
|
||||
// Initialize SC model
|
||||
#if (SYSTEMC_VERSION>=20070314)
|
||||
sc_start(1,SC_NS);
|
||||
#if (SYSTEMC_VERSION >= 20070314)
|
||||
sc_start(1, SC_NS);
|
||||
#else
|
||||
sc_start(1);
|
||||
#endif
|
||||
|
||||
// Simulate until $finish
|
||||
while (!Verilated::gotFinish()) {
|
||||
#if (SYSTEMC_VERSION>=20070314)
|
||||
sc_start(1,SC_NS);
|
||||
#if (SYSTEMC_VERSION >= 20070314)
|
||||
sc_start(1, SC_NS);
|
||||
#else
|
||||
sc_start(1);
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -17,9 +17,7 @@
|
|||
#endif
|
||||
|
||||
vluint64_t main_time = 0;
|
||||
double sc_time_stamp() {
|
||||
return main_time;
|
||||
}
|
||||
double sc_time_stamp() { return main_time; }
|
||||
|
||||
int main(int argc, char** argv, char** env) {
|
||||
if (0 && argc && argv && env) {}
|
||||
|
|
@ -35,7 +33,7 @@ int main(int argc, char** argv, char** env) {
|
|||
// When tracing, the contents of the secret module will not be seen
|
||||
VerilatedVcdC* tfp = NULL;
|
||||
const char* flag = Verilated::commandArgsPlusMatch("trace");
|
||||
if (flag && 0==strcmp(flag, "+trace")) {
|
||||
if (flag && 0 == strcmp(flag, "+trace")) {
|
||||
Verilated::traceEverOn(true);
|
||||
VL_PRINTF("Enabling waves into logs/vlt_dump.vcd...\n");
|
||||
tfp = new VerilatedVcdC;
|
||||
|
|
@ -62,11 +60,15 @@ int main(int argc, char** argv, char** env) {
|
|||
|
||||
// Close trace if opened
|
||||
#if VM_TRACE
|
||||
if (tfp) { tfp->close(); tfp = NULL; }
|
||||
if (tfp) {
|
||||
tfp->close();
|
||||
tfp = NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Destroy model
|
||||
delete top; top = NULL;
|
||||
delete top;
|
||||
top = NULL;
|
||||
|
||||
// Fin
|
||||
exit(0);
|
||||
|
|
|
|||
|
|
@ -83,9 +83,9 @@ int main(int argc, char** argv, char** env) {
|
|||
|
||||
// Read outputs
|
||||
VL_PRINTF("[%" VL_PRI64 "d] clk=%x rstl=%x iquad=%" VL_PRI64 "x"
|
||||
" -> oquad=%" VL_PRI64"x owide=%x_%08x_%08x\n",
|
||||
main_time, top->clk, top->reset_l, top->in_quad,
|
||||
top->out_quad, top->out_wide[2], top->out_wide[1], top->out_wide[0]);
|
||||
" -> oquad=%" VL_PRI64 "x owide=%x_%08x_%08x\n",
|
||||
main_time, top->clk, top->reset_l, top->in_quad, top->out_quad, top->out_wide[2],
|
||||
top->out_wide[1], top->out_wide[0]);
|
||||
}
|
||||
|
||||
// Final model cleanup
|
||||
|
|
@ -98,7 +98,8 @@ int main(int argc, char** argv, char** env) {
|
|||
#endif
|
||||
|
||||
// Destroy model
|
||||
delete top; top = NULL;
|
||||
delete top;
|
||||
top = NULL;
|
||||
|
||||
// Fin
|
||||
exit(0);
|
||||
|
|
|
|||
|
|
@ -45,19 +45,19 @@ int sc_main(int argc, char* argv[]) {
|
|||
ios::sync_with_stdio();
|
||||
|
||||
// Defaults time
|
||||
#if (SYSTEMC_VERSION>20011000)
|
||||
#if (SYSTEMC_VERSION > 20011000)
|
||||
#else
|
||||
sc_time dut(1.0, sc_ns);
|
||||
sc_set_default_time_unit(dut);
|
||||
#endif
|
||||
|
||||
// Define clocks
|
||||
#if (SYSTEMC_VERSION>=20070314)
|
||||
sc_clock clk ("clk", 10,SC_NS, 0.5, 3,SC_NS, true);
|
||||
sc_clock fastclk ("fastclk", 2,SC_NS, 0.5, 2,SC_NS, true);
|
||||
#if (SYSTEMC_VERSION >= 20070314)
|
||||
sc_clock clk("clk", 10, SC_NS, 0.5, 3, SC_NS, true);
|
||||
sc_clock fastclk("fastclk", 2, SC_NS, 0.5, 2, SC_NS, true);
|
||||
#else
|
||||
sc_clock clk ("clk", 10, 0.5, 3, true);
|
||||
sc_clock fastclk ("fastclk", 2, 0.5, 2, true);
|
||||
sc_clock clk("clk", 10, 0.5, 3, true);
|
||||
sc_clock fastclk("fastclk", 2, 0.5, 2, true);
|
||||
#endif
|
||||
|
||||
// Define interconnect
|
||||
|
|
@ -72,15 +72,15 @@ int sc_main(int argc, char* argv[]) {
|
|||
// Construct the Verilated model, from inside Vtop.h
|
||||
Vtop* top = new Vtop("top");
|
||||
// Attach signals to the model
|
||||
top->clk (clk);
|
||||
top->fastclk (fastclk);
|
||||
top->reset_l (reset_l);
|
||||
top->in_small (in_small);
|
||||
top->in_quad (in_quad);
|
||||
top->in_wide (in_wide);
|
||||
top->out_small (out_small);
|
||||
top->out_quad (out_quad);
|
||||
top->out_wide (out_wide);
|
||||
top->clk(clk);
|
||||
top->fastclk(fastclk);
|
||||
top->reset_l(reset_l);
|
||||
top->in_small(in_small);
|
||||
top->in_quad(in_quad);
|
||||
top->in_wide(in_wide);
|
||||
top->out_small(out_small);
|
||||
top->out_quad(out_quad);
|
||||
top->out_wide(out_wide);
|
||||
|
||||
#if VM_TRACE
|
||||
// Before any evaluation, need to know to calculate those signals only used for tracing
|
||||
|
|
@ -89,7 +89,7 @@ int sc_main(int argc, char* argv[]) {
|
|||
|
||||
// You must do one evaluation before enabling waves, in order to allow
|
||||
// SystemC to interconnect everything for testing.
|
||||
#if (SYSTEMC_VERSION>=20070314)
|
||||
#if (SYSTEMC_VERSION >= 20070314)
|
||||
sc_start(1, SC_NS);
|
||||
#else
|
||||
sc_start(1);
|
||||
|
|
@ -100,7 +100,7 @@ int sc_main(int argc, char* argv[]) {
|
|||
// and if at run time passed the +trace argument, turn on tracing
|
||||
VerilatedVcdSc* tfp = NULL;
|
||||
const char* flag = Verilated::commandArgsPlusMatch("trace");
|
||||
if (flag && 0==strcmp(flag, "+trace")) {
|
||||
if (flag && 0 == strcmp(flag, "+trace")) {
|
||||
cout << "Enabling waves into logs/vlt_dump.vcd...\n";
|
||||
tfp = new VerilatedVcdSc;
|
||||
top->trace(tfp, 99); // Trace 99 levels of hierarchy
|
||||
|
|
@ -118,15 +118,14 @@ int sc_main(int argc, char* argv[]) {
|
|||
#endif
|
||||
|
||||
// Apply inputs
|
||||
if (sc_time_stamp() > sc_time(1, SC_NS)
|
||||
&& sc_time_stamp() < sc_time(10, SC_NS)) {
|
||||
if (sc_time_stamp() > sc_time(1, SC_NS) && sc_time_stamp() < sc_time(10, SC_NS)) {
|
||||
reset_l = !1; // Assert reset
|
||||
} else {
|
||||
reset_l = !0; // Deassert reset
|
||||
}
|
||||
|
||||
// Simulate 1ns
|
||||
#if (SYSTEMC_VERSION>=20070314)
|
||||
#if (SYSTEMC_VERSION >= 20070314)
|
||||
sc_start(1, SC_NS);
|
||||
#else
|
||||
sc_start(1);
|
||||
|
|
@ -138,7 +137,10 @@ int sc_main(int argc, char* argv[]) {
|
|||
|
||||
// Close trace if opened
|
||||
#if VM_TRACE
|
||||
if (tfp) { tfp->close(); tfp = NULL; }
|
||||
if (tfp) {
|
||||
tfp->close();
|
||||
tfp = NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Coverage analysis (since test passed)
|
||||
|
|
@ -148,7 +150,8 @@ int sc_main(int argc, char* argv[]) {
|
|||
#endif
|
||||
|
||||
// Destroy model
|
||||
delete top; top = NULL;
|
||||
delete top;
|
||||
top = NULL;
|
||||
|
||||
// Fin
|
||||
return 0;
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
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
|
||||
|
||||
// Autoconf substitutes this with the strings from AC_INIT.
|
||||
#define VERILATOR_PRODUCT "@PACKAGE_NAME@"
|
||||
#define VERILATOR_VERSION "@PACKAGE_VERSION@"
|
||||
#define VERILATOR_PRODUCT "@PACKAGE_NAME@"
|
||||
#define VERILATOR_VERSION "@PACKAGE_VERSION@"
|
||||
|
|
|
|||
|
|
@ -47,7 +47,7 @@ public: // But only local to this file
|
|||
// CONSTRUCTORS
|
||||
// Derived classes should call zero() in their constructor
|
||||
VerilatedCovImpItem() {
|
||||
for (int i=0; i<MAX_KEYS; ++i) {
|
||||
for (int i = 0; i < MAX_KEYS; ++i) {
|
||||
m_keys[i] = KEY_UNDEF;
|
||||
m_vals[i] = 0;
|
||||
}
|
||||
|
|
@ -66,7 +66,7 @@ public: // But only local to this file
|
|||
template <class T> class VerilatedCoverItemSpec : public VerilatedCovImpItem {
|
||||
private:
|
||||
// MEMBERS
|
||||
T* m_countp; ///< Count value
|
||||
T* m_countp; ///< Count value
|
||||
public:
|
||||
// METHODS
|
||||
// cppcheck-suppress truncLongCastReturn
|
||||
|
|
@ -74,7 +74,10 @@ public:
|
|||
virtual void zero() const VL_OVERRIDE { *m_countp = 0; }
|
||||
// CONSTRUCTORS
|
||||
// cppcheck-suppress noExplicitConstructor
|
||||
explicit VerilatedCoverItemSpec(T* countp) : m_countp(countp) { *m_countp = 0; }
|
||||
explicit VerilatedCoverItemSpec(T* countp)
|
||||
: m_countp(countp) {
|
||||
*m_countp = 0;
|
||||
}
|
||||
virtual ~VerilatedCoverItemSpec() VL_OVERRIDE {}
|
||||
};
|
||||
|
||||
|
|
@ -87,20 +90,20 @@ public:
|
|||
class VerilatedCovImp : VerilatedCovImpBase {
|
||||
private:
|
||||
// TYPES
|
||||
typedef std::map<std::string,int> ValueIndexMap;
|
||||
typedef std::map<int,std::string> IndexValueMap;
|
||||
typedef std::map<std::string, int> ValueIndexMap;
|
||||
typedef std::map<int, std::string> IndexValueMap;
|
||||
typedef std::deque<VerilatedCovImpItem*> ItemList;
|
||||
|
||||
private:
|
||||
// MEMBERS
|
||||
VerilatedMutex m_mutex; ///< Protects all members, when VL_THREADED. Wrapper deals with setting it.
|
||||
ValueIndexMap m_valueIndexes VL_GUARDED_BY(m_mutex); ///< For each key/value a unique arbitrary index value
|
||||
IndexValueMap m_indexValues VL_GUARDED_BY(m_mutex); ///< For each key/value a unique arbitrary index value
|
||||
ItemList m_items VL_GUARDED_BY(m_mutex); ///< List of all items
|
||||
VerilatedMutex m_mutex; ///< Protects all members
|
||||
ValueIndexMap m_valueIndexes VL_GUARDED_BY(m_mutex); ///< Unique arbitrary value for values
|
||||
IndexValueMap m_indexValues VL_GUARDED_BY(m_mutex); ///< Unique arbitrary value for keys
|
||||
ItemList m_items VL_GUARDED_BY(m_mutex); ///< List of all items
|
||||
|
||||
VerilatedCovImpItem* m_insertp VL_GUARDED_BY(m_mutex); ///< Item about to insert
|
||||
const char* m_insertFilenamep VL_GUARDED_BY(m_mutex); ///< Filename about to insert
|
||||
int m_insertLineno VL_GUARDED_BY(m_mutex); ///< Line number about to insert
|
||||
const char* m_insertFilenamep VL_GUARDED_BY(m_mutex); ///< Filename about to insert
|
||||
int m_insertLineno VL_GUARDED_BY(m_mutex); ///< Line number about to insert
|
||||
|
||||
// CONSTRUCTORS
|
||||
VerilatedCovImp() {
|
||||
|
|
@ -109,6 +112,7 @@ private:
|
|||
m_insertLineno = 0;
|
||||
}
|
||||
VL_UNCOPYABLE(VerilatedCovImp);
|
||||
|
||||
public:
|
||||
~VerilatedCovImp() { clearGuts(); }
|
||||
static VerilatedCovImp& imp() VL_MT_SAFE {
|
||||
|
|
@ -119,10 +123,11 @@ public:
|
|||
private:
|
||||
// PRIVATE METHODS
|
||||
int valueIndex(const std::string& value) VL_REQUIRES(m_mutex) {
|
||||
static int nextIndex = KEY_UNDEF+1;
|
||||
static int nextIndex = KEY_UNDEF + 1;
|
||||
ValueIndexMap::iterator iter = m_valueIndexes.find(value);
|
||||
if (iter != m_valueIndexes.end()) return iter->second;
|
||||
nextIndex++; assert(nextIndex>0);
|
||||
nextIndex++;
|
||||
assert(nextIndex > 0); // Didn't rollover
|
||||
m_valueIndexes.insert(std::make_pair(value, nextIndex));
|
||||
m_indexValues.insert(std::make_pair(nextIndex, value));
|
||||
return nextIndex;
|
||||
|
|
@ -131,8 +136,9 @@ private:
|
|||
// Quote any special characters
|
||||
std::string rtn;
|
||||
for (const char* pos = text.c_str(); *pos; ++pos) {
|
||||
if (!isprint(*pos) || *pos=='%' || *pos=='"') {
|
||||
char hex[10]; sprintf(hex, "%%%02X", pos[0]);
|
||||
if (!isprint(*pos) || *pos == '%' || *pos == '"') {
|
||||
char hex[10];
|
||||
sprintf(hex, "%%%02X", pos[0]);
|
||||
rtn += hex;
|
||||
} else {
|
||||
rtn += *pos;
|
||||
|
|
@ -145,18 +151,19 @@ private:
|
|||
// don't want applications to either get confused if they use
|
||||
// a letter differently, nor want them to rely on our compression...
|
||||
// (Considered using numeric keys, but will remain back compatible.)
|
||||
if (key.length()<2) return false;
|
||||
if (key.length()==2 && isdigit(key[1])) return false;
|
||||
if (key.length() < 2) return false;
|
||||
if (key.length() == 2 && isdigit(key[1])) return false;
|
||||
return true;
|
||||
}
|
||||
static std::string keyValueFormatter(const std::string& key, const std::string& value) VL_PURE {
|
||||
static std::string keyValueFormatter(const std::string& key,
|
||||
const std::string& value) VL_PURE {
|
||||
std::string name;
|
||||
if (key.length()==1 && isalpha(key[0])) {
|
||||
name += std::string("\001")+key;
|
||||
if (key.length() == 1 && isalpha(key[0])) {
|
||||
name += std::string("\001") + key;
|
||||
} else {
|
||||
name += std::string("\001")+dequote(key);
|
||||
name += std::string("\001") + dequote(key);
|
||||
}
|
||||
name += std::string("\002")+dequote(value);
|
||||
name += std::string("\002") + dequote(value);
|
||||
return name;
|
||||
}
|
||||
static std::string combineHier(const std::string& old, const std::string& add) VL_PURE {
|
||||
|
|
@ -173,28 +180,35 @@ private:
|
|||
// Scan forward to first mismatch
|
||||
const char* apre = a;
|
||||
const char* bpre = b;
|
||||
while (*apre == *bpre) { apre++; bpre++; }
|
||||
while (*apre == *bpre) {
|
||||
apre++;
|
||||
bpre++;
|
||||
}
|
||||
|
||||
// We used to backup and split on only .'s but it seems better to be verbose
|
||||
// and not assume . is the separator
|
||||
std::string prefix = std::string(a, apre-a);
|
||||
std::string prefix = std::string(a, apre - a);
|
||||
|
||||
// Scan backward to last mismatch
|
||||
const char* apost = a+strlen(a)-1;
|
||||
const char* bpost = b+strlen(b)-1;
|
||||
while (*apost == *bpost
|
||||
&& apost>apre && bpost>bpre) { apost--; bpost--; }
|
||||
const char* apost = a + strlen(a) - 1;
|
||||
const char* bpost = b + strlen(b) - 1;
|
||||
while (*apost == *bpost && apost > apre && bpost > bpre) {
|
||||
apost--;
|
||||
bpost--;
|
||||
}
|
||||
|
||||
// Forward to . so we have a whole word
|
||||
std::string suffix = *bpost ? std::string(bpost+1) : "";
|
||||
std::string suffix = *bpost ? std::string(bpost + 1) : "";
|
||||
|
||||
std::string out = prefix+"*"+suffix;
|
||||
std::string out = prefix + "*" + suffix;
|
||||
|
||||
//cout << "\nch pre="<<prefix<<" s="<<suffix<<"\nch a="<<old<<"\nch b="<<add<<"\nch o="<<out<<endl;
|
||||
// cout << "\nch pre="<<prefix<<" s="<<suffix<<"\nch a="<<old<<"\nch b="<<add
|
||||
// <<"\ncho="<<out<<endl;
|
||||
return out;
|
||||
}
|
||||
bool itemMatchesString(VerilatedCovImpItem* itemp, const std::string& match) VL_REQUIRES(m_mutex) {
|
||||
for (int i=0; i<MAX_KEYS; ++i) {
|
||||
bool itemMatchesString(VerilatedCovImpItem* itemp, const std::string& match)
|
||||
VL_REQUIRES(m_mutex) {
|
||||
for (int i = 0; i < MAX_KEYS; ++i) {
|
||||
if (itemp->m_keys[i] != KEY_UNDEF) {
|
||||
// We don't compare keys, only values
|
||||
std::string val = m_indexValues[itemp->m_vals[i]];
|
||||
|
|
@ -207,17 +221,23 @@ private:
|
|||
}
|
||||
static void selftest() VL_MT_SAFE {
|
||||
// Little selftest
|
||||
if (combineHier("a.b.c","a.b.c") !="a.b.c") VL_FATAL_MT(__FILE__,__LINE__,"","%Error: selftest\n");
|
||||
if (combineHier("a.b.c","a.b") !="a.b*") VL_FATAL_MT(__FILE__,__LINE__,"","%Error: selftest\n");
|
||||
if (combineHier("a.x.c","a.y.c") !="a.*.c") VL_FATAL_MT(__FILE__,__LINE__,"","%Error: selftest\n");
|
||||
if (combineHier("a.z.z.z.c","a.b.c") !="a.*.c") VL_FATAL_MT(__FILE__,__LINE__,"","%Error: selftest\n");
|
||||
if (combineHier("z","a") !="*") VL_FATAL_MT(__FILE__,__LINE__,"","%Error: selftest\n");
|
||||
if (combineHier("q.a","q.b") !="q.*") VL_FATAL_MT(__FILE__,__LINE__,"","%Error: selftest\n");
|
||||
if (combineHier("q.za","q.zb") !="q.z*") VL_FATAL_MT(__FILE__,__LINE__,"","%Error: selftest\n");
|
||||
if (combineHier("1.2.3.a","9.8.7.a") !="*.a") VL_FATAL_MT(__FILE__,__LINE__,"","%Error: selftest\n");
|
||||
#define VL_CST_CHECK(got, exp) \
|
||||
do { \
|
||||
if ((got) != (exp)) VL_FATAL_MT(__FILE__, __LINE__, "", "%Error: selftest\n"); \
|
||||
} while (0)
|
||||
|
||||
VL_CST_CHECK(combineHier("a.b.c", "a.b.c"), "a.b.c");
|
||||
VL_CST_CHECK(combineHier("a.b.c", "a.b"), "a.b*");
|
||||
VL_CST_CHECK(combineHier("a.x.c", "a.y.c"), "a.*.c");
|
||||
VL_CST_CHECK(combineHier("a.z.z.z.c", "a.b.c"), "a.*.c");
|
||||
VL_CST_CHECK(combineHier("z", "a"), "*");
|
||||
VL_CST_CHECK(combineHier("q.a", "q.b"), "q.*");
|
||||
VL_CST_CHECK(combineHier("q.za", "q.zb"), "q.z*");
|
||||
VL_CST_CHECK(combineHier("1.2.3.a", "9.8.7.a"), "*.a");
|
||||
#undef VL_CST_CHECK
|
||||
}
|
||||
void clearGuts() VL_REQUIRES(m_mutex) {
|
||||
for (ItemList::const_iterator it=m_items.begin(); it!=m_items.end(); ++it) {
|
||||
for (ItemList::const_iterator it = m_items.begin(); it != m_items.end(); ++it) {
|
||||
VerilatedCovImpItem* itemp = *(it);
|
||||
VL_DO_DANGLING(delete itemp, itemp);
|
||||
}
|
||||
|
|
@ -238,7 +258,7 @@ public:
|
|||
VerilatedLockGuard lock(m_mutex);
|
||||
if (matchp && matchp[0]) {
|
||||
ItemList newlist;
|
||||
for (ItemList::iterator it=m_items.begin(); it!=m_items.end(); ++it) {
|
||||
for (ItemList::iterator it = m_items.begin(); it != m_items.end(); ++it) {
|
||||
VerilatedCovImpItem* itemp = *(it);
|
||||
if (!itemMatchesString(itemp, matchp)) {
|
||||
VL_DO_DANGLING(delete itemp, itemp);
|
||||
|
|
@ -252,7 +272,7 @@ public:
|
|||
void zero() VL_EXCLUDES(m_mutex) {
|
||||
Verilated::quiesce();
|
||||
VerilatedLockGuard lock(m_mutex);
|
||||
for (ItemList::const_iterator it=m_items.begin(); it!=m_items.end(); ++it) {
|
||||
for (ItemList::const_iterator it = m_items.begin(); it != m_items.end(); ++it) {
|
||||
(*it)->zero();
|
||||
}
|
||||
}
|
||||
|
|
@ -268,33 +288,33 @@ public:
|
|||
m_insertFilenamep = filenamep;
|
||||
m_insertLineno = lineno;
|
||||
}
|
||||
void insertp(const char* ckeyps[MAX_KEYS],
|
||||
const char* valps[MAX_KEYS]) VL_EXCLUDES(m_mutex) {
|
||||
void insertp(const char* ckeyps[MAX_KEYS], const char* valps[MAX_KEYS]) VL_EXCLUDES(m_mutex) {
|
||||
VerilatedLockGuard lock(m_mutex);
|
||||
assert(m_insertp);
|
||||
// First two key/vals are filename
|
||||
ckeyps[0]="filename"; valps[0]=m_insertFilenamep;
|
||||
ckeyps[0] = "filename";
|
||||
valps[0] = m_insertFilenamep;
|
||||
std::string linestr = vlCovCvtToStr(m_insertLineno);
|
||||
ckeyps[1]="lineno"; valps[1]=linestr.c_str();
|
||||
ckeyps[1] = "lineno";
|
||||
valps[1] = linestr.c_str();
|
||||
// Default page if not specified
|
||||
const char* fnstartp = m_insertFilenamep;
|
||||
while (const char* foundp = strchr(fnstartp,'/')) fnstartp = foundp+1;
|
||||
while (const char* foundp = strchr(fnstartp, '/')) fnstartp = foundp + 1;
|
||||
const char* fnendp = fnstartp;
|
||||
while (*fnendp && *fnendp!='.') fnendp++;
|
||||
std::string page_default = "sp_user/"+std::string(fnstartp, fnendp-fnstartp);
|
||||
ckeyps[2]="page"; valps[2]=page_default.c_str();
|
||||
for (; *fnendp && *fnendp != '.'; fnendp++) {}
|
||||
std::string page_default = "sp_user/" + std::string(fnstartp, fnendp - fnstartp);
|
||||
ckeyps[2] = "page";
|
||||
valps[2] = page_default.c_str();
|
||||
|
||||
// Keys -> strings
|
||||
std::string keys[MAX_KEYS];
|
||||
for (int i=0; i<MAX_KEYS; ++i) {
|
||||
if (ckeyps[i] && ckeyps[i][0]) {
|
||||
keys[i] = ckeyps[i];
|
||||
}
|
||||
for (int i = 0; i < MAX_KEYS; ++i) {
|
||||
if (ckeyps[i] && ckeyps[i][0]) { keys[i] = ckeyps[i]; }
|
||||
}
|
||||
// Ignore empty keys
|
||||
for (int i=0; i<MAX_KEYS; ++i) {
|
||||
for (int i = 0; i < MAX_KEYS; ++i) {
|
||||
if (!keys[i].empty()) {
|
||||
for (int j=i+1; j<MAX_KEYS; ++j) {
|
||||
for (int j = i + 1; j < MAX_KEYS; ++j) {
|
||||
if (keys[i] == keys[j]) { // Duplicate key. Keep the last one
|
||||
keys[i] = "";
|
||||
break;
|
||||
|
|
@ -304,18 +324,18 @@ public:
|
|||
}
|
||||
// Insert the values
|
||||
int addKeynum = 0;
|
||||
for (int i=0; i<MAX_KEYS; ++i) {
|
||||
for (int i = 0; i < MAX_KEYS; ++i) {
|
||||
const std::string key = keys[i];
|
||||
if (!keys[i].empty()) {
|
||||
const std::string val = valps[i];
|
||||
//cout<<" "<<__FUNCTION__<<" "<<key<<" = "<<val<<endl;
|
||||
// cout<<" "<<__FUNCTION__<<" "<<key<<" = "<<val<<endl;
|
||||
m_insertp->m_keys[addKeynum] = valueIndex(key);
|
||||
m_insertp->m_vals[addKeynum] = valueIndex(val);
|
||||
addKeynum++;
|
||||
if (!legalKey(key)) {
|
||||
std::string msg
|
||||
= ("%Error: Coverage keys of one character, or letter+digit are illegal: "
|
||||
+key);
|
||||
+ key);
|
||||
VL_FATAL_MT("", 0, "", msg.c_str());
|
||||
}
|
||||
}
|
||||
|
|
@ -335,22 +355,22 @@ public:
|
|||
|
||||
std::ofstream os(filename);
|
||||
if (os.fail()) {
|
||||
std::string msg = std::string("%Error: Can't write '")+filename+"'";
|
||||
std::string msg = std::string("%Error: Can't write '") + filename + "'";
|
||||
VL_FATAL_MT("", 0, "", msg.c_str());
|
||||
return;
|
||||
}
|
||||
os << "# SystemC::Coverage-3\n";
|
||||
|
||||
// Build list of events; totalize if collapsing hierarchy
|
||||
typedef std::map<std::string,std::pair<std::string,vluint64_t> > EventMap;
|
||||
typedef std::map<std::string, std::pair<std::string, vluint64_t> > EventMap;
|
||||
EventMap eventCounts;
|
||||
for (ItemList::iterator it=m_items.begin(); it!=m_items.end(); ++it) {
|
||||
for (ItemList::iterator it = m_items.begin(); it != m_items.end(); ++it) {
|
||||
VerilatedCovImpItem* itemp = *(it);
|
||||
std::string name;
|
||||
std::string hier;
|
||||
bool per_instance = false;
|
||||
|
||||
for (int i=0; i<MAX_KEYS; ++i) {
|
||||
for (int i = 0; i < MAX_KEYS; ++i) {
|
||||
if (itemp->m_keys[i] != KEY_UNDEF) {
|
||||
std::string key = VerilatedCovKey::shortKey(m_indexValues[itemp->m_keys[i]]);
|
||||
std::string val = m_indexValues[itemp->m_vals[i]];
|
||||
|
|
@ -380,19 +400,19 @@ public:
|
|||
if (cit != eventCounts.end()) {
|
||||
const std::string& oldhier = cit->second.first;
|
||||
cit->second.second += itemp->count();
|
||||
cit->second.first = combineHier(oldhier, hier);
|
||||
cit->second.first = combineHier(oldhier, hier);
|
||||
} else {
|
||||
eventCounts.insert(std::make_pair(name, make_pair(hier, itemp->count())));
|
||||
}
|
||||
}
|
||||
|
||||
// Output body
|
||||
for (EventMap::const_iterator it=eventCounts.begin(); it!=eventCounts.end(); ++it) {
|
||||
os<<"C '"<<std::dec;
|
||||
os<<it->first;
|
||||
if (!it->second.first.empty()) os<<keyValueFormatter(VL_CIK_HIER, it->second.first);
|
||||
os<<"' "<<it->second.second;
|
||||
os<<std::endl;
|
||||
for (EventMap::const_iterator it = eventCounts.begin(); it != eventCounts.end(); ++it) {
|
||||
os << "C '" << std::dec;
|
||||
os << it->first;
|
||||
if (!it->second.first.empty()) os << keyValueFormatter(VL_CIK_HIER, it->second.first);
|
||||
os << "' " << it->second.second;
|
||||
os << std::endl;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
@ -400,15 +420,11 @@ public:
|
|||
//=============================================================================
|
||||
// VerilatedCov
|
||||
|
||||
void VerilatedCov::clear() VL_MT_SAFE {
|
||||
VerilatedCovImp::imp().clear();
|
||||
}
|
||||
void VerilatedCov::clear() VL_MT_SAFE { VerilatedCovImp::imp().clear(); }
|
||||
void VerilatedCov::clearNonMatch(const char* matchp) VL_MT_SAFE {
|
||||
VerilatedCovImp::imp().clearNonMatch(matchp);
|
||||
}
|
||||
void VerilatedCov::zero() VL_MT_SAFE {
|
||||
VerilatedCovImp::imp().zero();
|
||||
}
|
||||
void VerilatedCov::zero() VL_MT_SAFE { VerilatedCovImp::imp().zero(); }
|
||||
void VerilatedCov::write(const char* filenamep) VL_MT_SAFE {
|
||||
VerilatedCovImp::imp().write(filenamep);
|
||||
}
|
||||
|
|
@ -422,48 +438,49 @@ void VerilatedCov::_insertf(const char* filename, int lineno) VL_MT_SAFE {
|
|||
VerilatedCovImp::imp().insertf(filename, lineno);
|
||||
}
|
||||
|
||||
#define K(n) const char* key ## n
|
||||
#define A(n) const char* key ## n, const char* valp ## n // Argument list
|
||||
#define C(n) key ## n, valp ## n // Calling argument list
|
||||
#define N(n) "","" // Null argument list
|
||||
void VerilatedCov::_insertp(A(0),A(1),A(2),A(3),A(4),A(5),A(6),A(7),A(8),A(9),
|
||||
A(10),A(11),A(12),A(13),A(14),A(15),A(16),A(17),A(18),A(19),
|
||||
A(20),A(21),A(22),A(23),A(24),A(25),A(26),A(27),A(28),A(29)) VL_MT_SAFE {
|
||||
#define K(n) const char* key##n
|
||||
#define A(n) const char *key##n, const char *valp##n // Argument list
|
||||
#define C(n) key##n, valp##n // Calling argument list
|
||||
#define N(n) "", "" // Null argument list
|
||||
void VerilatedCov::_insertp(A(0), A(1), A(2), A(3), A(4), A(5), A(6), A(7), A(8), A(9), A(10),
|
||||
A(11), A(12), A(13), A(14), A(15), A(16), A(17), A(18), A(19), A(20),
|
||||
A(21), A(22), A(23), A(24), A(25), A(26), A(27), A(28),
|
||||
A(29)) VL_MT_SAFE {
|
||||
const char* keyps[VerilatedCovImpBase::MAX_KEYS]
|
||||
= {NULL,NULL,NULL, // filename,lineno,page
|
||||
key0,key1,key2,key3,key4,key5,key6,key7,key8,key9,
|
||||
key10,key11,key12,key13,key14,key15,key16,key17,key18,key19,
|
||||
key20,key21,key22,key23,key24,key25,key26,key27,key28,key29};
|
||||
= {NULL, NULL, NULL, // filename,lineno,page
|
||||
key0, key1, key2, key3, key4, key5, key6, key7, key8, key9,
|
||||
key10, key11, key12, key13, key14, key15, key16, key17, key18, key19,
|
||||
key20, key21, key22, key23, key24, key25, key26, key27, key28, key29};
|
||||
const char* valps[VerilatedCovImpBase::MAX_KEYS]
|
||||
= {NULL,NULL,NULL, // filename,lineno,page
|
||||
valp0,valp1,valp2,valp3,valp4,valp5,valp6,valp7,valp8,valp9,
|
||||
valp10,valp11,valp12,valp13,valp14,valp15,valp16,valp17,valp18,valp19,
|
||||
valp20,valp21,valp22,valp23,valp24,valp25,valp26,valp27,valp28,valp29};
|
||||
= {NULL, NULL, NULL, // filename,lineno,page
|
||||
valp0, valp1, valp2, valp3, valp4, valp5, valp6, valp7, valp8, valp9,
|
||||
valp10, valp11, valp12, valp13, valp14, valp15, valp16, valp17, valp18, valp19,
|
||||
valp20, valp21, valp22, valp23, valp24, valp25, valp26, valp27, valp28, valp29};
|
||||
VerilatedCovImp::imp().insertp(keyps, valps);
|
||||
}
|
||||
|
||||
// And versions with fewer arguments (oh for a language with named parameters!)
|
||||
void VerilatedCov::_insertp(A(0),A(1),A(2),A(3),A(4),A(5),A(6),A(7),A(8),A(9)) VL_MT_SAFE {
|
||||
_insertp(C(0),C(1),C(2),C(3),C(4),C(5),C(6),C(7),C(8),C(9),
|
||||
N(10),N(11),N(12),N(13),N(14),N(15),N(16),N(17),N(18),N(19),
|
||||
N(20),N(21),N(22),N(23),N(24),N(25),N(26),N(27),N(28),N(29));
|
||||
void VerilatedCov::_insertp(A(0), A(1), A(2), A(3), A(4), A(5), A(6), A(7), A(8),
|
||||
A(9)) VL_MT_SAFE {
|
||||
_insertp(C(0), C(1), C(2), C(3), C(4), C(5), C(6), C(7), C(8), C(9), N(10), N(11), N(12),
|
||||
N(13), N(14), N(15), N(16), N(17), N(18), N(19), N(20), N(21), N(22), N(23), N(24),
|
||||
N(25), N(26), N(27), N(28), N(29));
|
||||
}
|
||||
void VerilatedCov::_insertp(A(0),A(1),A(2),A(3),A(4),A(5),A(6),A(7),A(8),A(9),
|
||||
A(10),A(11),A(12),A(13),A(14),A(15),A(16),A(17),A(18),A(19)) VL_MT_SAFE {
|
||||
_insertp(C(0),C(1),C(2),C(3),C(4),C(5),C(6),C(7),C(8),C(9),
|
||||
C(10),C(11),C(12),C(13),C(14),C(15),C(16),C(17),C(18),C(19),
|
||||
N(20),N(21),N(22),N(23),N(24),N(25),N(26),N(27),N(28),N(29));
|
||||
void VerilatedCov::_insertp(A(0), A(1), A(2), A(3), A(4), A(5), A(6), A(7), A(8), A(9), A(10),
|
||||
A(11), A(12), A(13), A(14), A(15), A(16), A(17), A(18),
|
||||
A(19)) VL_MT_SAFE {
|
||||
_insertp(C(0), C(1), C(2), C(3), C(4), C(5), C(6), C(7), C(8), C(9), C(10), C(11), C(12),
|
||||
C(13), C(14), C(15), C(16), C(17), C(18), C(19), N(20), N(21), N(22), N(23), N(24),
|
||||
N(25), N(26), N(27), N(28), N(29));
|
||||
}
|
||||
// Backward compatibility for Verilator
|
||||
void VerilatedCov::_insertp(A(0), A(1), K(2),int val2, K(3),int val3,
|
||||
K(4),const std::string& val4, A(5),A(6)) VL_MT_SAFE {
|
||||
void VerilatedCov::_insertp(A(0), A(1), K(2), int val2, K(3), int val3, K(4),
|
||||
const std::string& val4, A(5), A(6)) VL_MT_SAFE {
|
||||
std::string val2str = vlCovCvtToStr(val2);
|
||||
std::string val3str = vlCovCvtToStr(val3);
|
||||
_insertp(C(0),C(1),
|
||||
key2,val2str.c_str(), key3,val3str.c_str(), key4, val4.c_str(),
|
||||
C(5),C(6),N(7),N(8),N(9),
|
||||
N(10),N(11),N(12),N(13),N(14),N(15),N(16),N(17),N(18),N(19),
|
||||
N(20),N(21),N(22),N(23),N(24),N(25),N(26),N(27),N(28),N(29));
|
||||
_insertp(C(0), C(1), key2, val2str.c_str(), key3, val3str.c_str(), key4, val4.c_str(), C(5),
|
||||
C(6), N(7), N(8), N(9), N(10), N(11), N(12), N(13), N(14), N(15), N(16), N(17), N(18),
|
||||
N(19), N(20), N(21), N(22), N(23), N(24), N(25), N(26), N(27), N(28), N(29));
|
||||
}
|
||||
#undef A
|
||||
#undef C
|
||||
|
|
|
|||
|
|
@ -28,17 +28,17 @@
|
|||
//=============================================================================
|
||||
/// Conditionally compile coverage code
|
||||
|
||||
// clang-format off
|
||||
#ifdef VM_COVERAGE
|
||||
# define VL_IF_COVER(stmts) \
|
||||
do { \
|
||||
stmts; \
|
||||
} while (false)
|
||||
do { stmts; } while (false)
|
||||
#else
|
||||
# define VL_IF_COVER(stmts) \
|
||||
do { \
|
||||
if (false) { stmts; } \
|
||||
} while (false)
|
||||
#endif
|
||||
// clang-format on
|
||||
|
||||
//=============================================================================
|
||||
/// Insert a item for coverage analysis.
|
||||
|
|
@ -68,16 +68,17 @@
|
|||
/// VL_COVER_INSERT(&m_cases[i], "comment", "Coverage Case", "i", cvtToNumStr(i));
|
||||
/// }
|
||||
|
||||
#define VL_COVER_INSERT(countp,...) \
|
||||
VL_IF_COVER(VerilatedCov::_inserti(countp); \
|
||||
VerilatedCov::_insertf(__FILE__, __LINE__); \
|
||||
#define VL_COVER_INSERT(countp, ...) \
|
||||
VL_IF_COVER(VerilatedCov::_inserti(countp); VerilatedCov::_insertf(__FILE__, __LINE__); \
|
||||
VerilatedCov::_insertp("hier", name(), __VA_ARGS__))
|
||||
|
||||
//=============================================================================
|
||||
/// Convert VL_COVER_INSERT value arguments to strings
|
||||
|
||||
template< class T> std::string vlCovCvtToStr(const T& t) VL_PURE {
|
||||
std::ostringstream os; os<<t; return os.str();
|
||||
template <class T> std::string vlCovCvtToStr(const T& t) VL_PURE {
|
||||
std::ostringstream os;
|
||||
os << t;
|
||||
return os.str();
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
|
|
@ -89,6 +90,7 @@ template< class T> std::string vlCovCvtToStr(const T& t) VL_PURE {
|
|||
|
||||
class VerilatedCov {
|
||||
VL_UNCOPYABLE(VerilatedCov);
|
||||
|
||||
public:
|
||||
// GLOBAL METHODS
|
||||
/// Return default filename
|
||||
|
|
@ -108,18 +110,18 @@ public:
|
|||
// We could have just the maximum argument version, but this compiles
|
||||
// much slower (nearly 2x) than having smaller versions also. However
|
||||
// there's not much more gain in having a version for each number of args.
|
||||
#define K(n) const char* key ## n
|
||||
#define A(n) const char* key ## n, const char* valp ## n // Argument list
|
||||
#define D(n) const char* key ## n = NULL, const char* valp ## n = NULL // Argument list
|
||||
static void _insertp(D(0),D(1),D(2),D(3),D(4),D(5),D(6),D(7),D(8),D(9));
|
||||
static void _insertp(A(0),A(1),A(2),A(3),A(4),A(5),A(6),A(7),A(8),A(9)
|
||||
,A(10),D(11),D(12),D(13),D(14),D(15),D(16),D(17),D(18),D(19));
|
||||
static void _insertp(A(0),A(1),A(2),A(3),A(4),A(5),A(6),A(7),A(8),A(9)
|
||||
,A(10),A(11),A(12),A(13),A(14),A(15),A(16),A(17),A(18),A(19)
|
||||
,A(20),D(21),D(22),D(23),D(24),D(25),D(26),D(27),D(28),D(29));
|
||||
#define K(n) const char* key##n
|
||||
#define A(n) const char *key##n, const char *valp##n // Argument list
|
||||
#define D(n) const char *key##n = NULL, const char *valp##n = NULL // Argument list
|
||||
static void _insertp(D(0), D(1), D(2), D(3), D(4), D(5), D(6), D(7), D(8), D(9));
|
||||
static void _insertp(A(0), A(1), A(2), A(3), A(4), A(5), A(6), A(7), A(8), A(9), A(10), D(11),
|
||||
D(12), D(13), D(14), D(15), D(16), D(17), D(18), D(19));
|
||||
static void _insertp(A(0), A(1), A(2), A(3), A(4), A(5), A(6), A(7), A(8), A(9), A(10), A(11),
|
||||
A(12), A(13), A(14), A(15), A(16), A(17), A(18), A(19), A(20), D(21),
|
||||
D(22), D(23), D(24), D(25), D(26), D(27), D(28), D(29));
|
||||
// Backward compatibility for Verilator
|
||||
static void _insertp(A(0), A(1), K(2),int val2, K(3),int val3,
|
||||
K(4),const std::string& val4, A(5),A(6));
|
||||
static void _insertp(A(0), A(1), K(2), int val2, K(3), int val3, K(4), const std::string& val4,
|
||||
A(5), A(6));
|
||||
|
||||
#undef K
|
||||
#undef A
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@
|
|||
|
||||
#define VLCOVGEN_ITEM(string_parsed_by_vlcovgen)
|
||||
|
||||
// clang-format off
|
||||
VLCOVGEN_ITEM("name=>'col0_name', short=>'C0', group=>1, default=>undef, descr=>'The column title for the header line of this column'")
|
||||
VLCOVGEN_ITEM("name=>'col1_name', short=>'C1', group=>1, default=>undef, ")
|
||||
VLCOVGEN_ITEM("name=>'col2_name', short=>'C2', group=>1, default=>undef, ")
|
||||
|
|
@ -59,6 +60,7 @@ VLCOVGEN_ITEM("name=>'row1', short=>'r1', group=>0, default=>undef, ")
|
|||
VLCOVGEN_ITEM("name=>'row2', short=>'r2', group=>0, default=>undef, ")
|
||||
VLCOVGEN_ITEM("name=>'row3', short=>'r3', group=>0, default=>undef, ")
|
||||
VLCOVGEN_ITEM("name=>'weight', short=>'w', group=>0, default=>undef, descr=>'For totaling items, weight of this item'")
|
||||
// clang-format on
|
||||
|
||||
// VLCOVGEN_CIK_AUTO_EDIT_BEGIN
|
||||
#define VL_CIK_COL0 "c0"
|
||||
|
|
|
|||
|
|
@ -40,88 +40,80 @@
|
|||
// Not supported yet
|
||||
#define _VL_SVDPI_UNIMP() \
|
||||
VL_FATAL_MT(__FILE__, __LINE__, "", \
|
||||
(std::string("%%Error: Unsupported DPI function: ")+VL_FUNC).c_str())
|
||||
(std::string("%%Error: Unsupported DPI function: ") + VL_FUNC).c_str())
|
||||
|
||||
#define _VL_SVDPI_WARN(...) \
|
||||
VL_PRINTF_MT(__VA_ARGS__)
|
||||
#define _VL_SVDPI_WARN(...) VL_PRINTF_MT(__VA_ARGS__)
|
||||
|
||||
// Function requires a "context" in the import declaration
|
||||
#define _VL_SVDPI_CONTEXT_WARN() \
|
||||
_VL_SVDPI_WARN("%%Warning: DPI C Function called by Verilog DPI import with missing 'context' keyword.\n");
|
||||
_VL_SVDPI_WARN("%%Warning: DPI C Function called by Verilog DPI import with missing " \
|
||||
"'context' keyword.\n");
|
||||
|
||||
//======================================================================
|
||||
//======================================================================
|
||||
//======================================================================
|
||||
// DPI ROUTINES
|
||||
|
||||
const char* svDpiVersion() {
|
||||
return "1800-2005";
|
||||
}
|
||||
const char* svDpiVersion() { return "1800-2005"; }
|
||||
|
||||
//======================================================================
|
||||
// Bit-select utility functions.
|
||||
|
||||
svBit svGetBitselBit(const svBitVecVal* sp, int bit) {
|
||||
return VL_BITRSHIFT_W(sp,bit) & 1;
|
||||
}
|
||||
svBit svGetBitselBit(const svBitVecVal* sp, int bit) { return VL_BITRSHIFT_W(sp, bit) & 1; }
|
||||
svLogic svGetBitselLogic(const svLogicVecVal* sp, int bit) {
|
||||
// Not VL_BITRSHIFT_W as sp is a different structure type
|
||||
// Verilator doesn't support X/Z so only aval
|
||||
return (((sp[VL_BITWORD_I(bit)].aval >> VL_BITBIT_I(bit)) & 1)
|
||||
| (((sp[VL_BITWORD_I(bit)].bval >> VL_BITBIT_I(bit)) & 1)<<1));
|
||||
| (((sp[VL_BITWORD_I(bit)].bval >> VL_BITBIT_I(bit)) & 1) << 1));
|
||||
}
|
||||
|
||||
void svPutBitselBit(svBitVecVal* dp, int bit, svBit s) {
|
||||
VL_ASSIGNBIT_WI(32, bit, dp, s);
|
||||
}
|
||||
void svPutBitselBit(svBitVecVal* dp, int bit, svBit s) { VL_ASSIGNBIT_WI(32, bit, dp, s); }
|
||||
void svPutBitselLogic(svLogicVecVal* dp, int bit, svLogic s) {
|
||||
// Verilator doesn't support X/Z so only aval
|
||||
dp[VL_BITWORD_I(bit)].aval
|
||||
= ((dp[VL_BITWORD_I(bit)].aval & ~(VL_UL(1)<<VL_BITBIT_I(bit)))
|
||||
| ((s&1)<<VL_BITBIT_I(bit)));
|
||||
dp[VL_BITWORD_I(bit)].bval
|
||||
= ((dp[VL_BITWORD_I(bit)].bval & ~(VL_UL(1)<<VL_BITBIT_I(bit)))
|
||||
| ((s&2)>>1<<VL_BITBIT_I(bit)));
|
||||
dp[VL_BITWORD_I(bit)].aval = ((dp[VL_BITWORD_I(bit)].aval & ~(VL_UL(1) << VL_BITBIT_I(bit)))
|
||||
| ((s & 1) << VL_BITBIT_I(bit)));
|
||||
dp[VL_BITWORD_I(bit)].bval = ((dp[VL_BITWORD_I(bit)].bval & ~(VL_UL(1) << VL_BITBIT_I(bit)))
|
||||
| ((s & 2) >> 1 << VL_BITBIT_I(bit)));
|
||||
}
|
||||
|
||||
void svGetPartselBit(svBitVecVal* dp, const svBitVecVal* sp, int lsb, int width) {
|
||||
// See also VL_SEL_WWI
|
||||
int msb = lsb+width-1;
|
||||
int msb = lsb + width - 1;
|
||||
int word_shift = VL_BITWORD_I(lsb);
|
||||
if (VL_BITBIT_I(lsb)==0) {
|
||||
if (VL_BITBIT_I(lsb) == 0) {
|
||||
// Just a word extract
|
||||
for (int i=0; i<VL_WORDS_I(width); ++i) dp[i] = sp[i+word_shift];
|
||||
for (int i = 0; i < VL_WORDS_I(width); ++i) dp[i] = sp[i + word_shift];
|
||||
} else {
|
||||
int loffset = lsb & VL_SIZEBITS_I;
|
||||
int nbitsfromlow = 32-loffset; // bits that end up in lword (know loffset!=0)
|
||||
int nbitsfromlow = 32 - loffset; // bits that end up in lword (know loffset!=0)
|
||||
// Middle words
|
||||
int words = VL_WORDS_I(msb-lsb+1);
|
||||
for (int i=0; i<words; ++i) {
|
||||
dp[i] = sp[i+word_shift]>>loffset;
|
||||
int upperword = i+word_shift+1;
|
||||
int words = VL_WORDS_I(msb - lsb + 1);
|
||||
for (int i = 0; i < words; ++i) {
|
||||
dp[i] = sp[i + word_shift] >> loffset;
|
||||
int upperword = i + word_shift + 1;
|
||||
if (upperword <= static_cast<int>(VL_BITWORD_I(msb))) {
|
||||
dp[i] |= sp[upperword] << nbitsfromlow;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Clean result
|
||||
dp[VL_WORDS_I(width)-1] &= VL_MASK_I(width);
|
||||
dp[VL_WORDS_I(width) - 1] &= VL_MASK_I(width);
|
||||
}
|
||||
void svGetPartselLogic(svLogicVecVal* dp, const svLogicVecVal* sp, int lsb, int width) {
|
||||
int msb = lsb+width-1;
|
||||
int msb = lsb + width - 1;
|
||||
int word_shift = VL_BITWORD_I(lsb);
|
||||
if (VL_BITBIT_I(lsb)==0) {
|
||||
if (VL_BITBIT_I(lsb) == 0) {
|
||||
// Just a word extract
|
||||
for (int i=0; i<VL_WORDS_I(width); ++i) dp[i] = sp[i+word_shift];
|
||||
for (int i = 0; i < VL_WORDS_I(width); ++i) dp[i] = sp[i + word_shift];
|
||||
} else {
|
||||
int loffset = lsb & VL_SIZEBITS_I;
|
||||
int nbitsfromlow = 32-loffset; // bits that end up in lword (know loffset!=0)
|
||||
int nbitsfromlow = 32 - loffset; // bits that end up in lword (know loffset!=0)
|
||||
// Middle words
|
||||
int words = VL_WORDS_I(msb-lsb+1);
|
||||
for (int i=0; i<words; ++i) {
|
||||
dp[i].aval = sp[i+word_shift].aval >> loffset;
|
||||
dp[i].bval = sp[i+word_shift].bval >> loffset;
|
||||
int upperword = i+word_shift+1;
|
||||
int words = VL_WORDS_I(msb - lsb + 1);
|
||||
for (int i = 0; i < words; ++i) {
|
||||
dp[i].aval = sp[i + word_shift].aval >> loffset;
|
||||
dp[i].bval = sp[i + word_shift].bval >> loffset;
|
||||
int upperword = i + word_shift + 1;
|
||||
if (upperword <= static_cast<int>(VL_BITWORD_I(msb))) {
|
||||
dp[i].aval |= sp[upperword].aval << nbitsfromlow;
|
||||
dp[i].bval |= sp[upperword].bval << nbitsfromlow;
|
||||
|
|
@ -129,58 +121,56 @@ void svGetPartselLogic(svLogicVecVal* dp, const svLogicVecVal* sp, int lsb, int
|
|||
}
|
||||
}
|
||||
// Clean result
|
||||
dp[VL_WORDS_I(width)-1].aval &= VL_MASK_I(width);
|
||||
dp[VL_WORDS_I(width)-1].bval &= VL_MASK_I(width);
|
||||
dp[VL_WORDS_I(width) - 1].aval &= VL_MASK_I(width);
|
||||
dp[VL_WORDS_I(width) - 1].bval &= VL_MASK_I(width);
|
||||
}
|
||||
void svPutPartselBit(svBitVecVal* dp, const svBitVecVal s, int lbit, int width) {
|
||||
// See also _VL_INSERT_WI
|
||||
int hbit = lbit+width-1;
|
||||
int hbit = lbit + width - 1;
|
||||
int hoffset = VL_BITBIT_I(hbit);
|
||||
int loffset = VL_BITBIT_I(lbit);
|
||||
if (hoffset==VL_SIZEBITS_I && loffset==0) {
|
||||
if (hoffset == VL_SIZEBITS_I && loffset == 0) {
|
||||
// Fast and common case, word based insertion
|
||||
dp[VL_BITWORD_I(lbit)] = s;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
int hword = VL_BITWORD_I(hbit);
|
||||
int lword = VL_BITWORD_I(lbit);
|
||||
if (hword==lword) { // know < 32 bits because above checks it
|
||||
IData insmask = (VL_MASK_I(hoffset-loffset+1))<<loffset;
|
||||
dp[lword] = (dp[lword] & ~insmask) | ((s<<loffset) & insmask);
|
||||
if (hword == lword) { // know < 32 bits because above checks it
|
||||
IData insmask = (VL_MASK_I(hoffset - loffset + 1)) << loffset;
|
||||
dp[lword] = (dp[lword] & ~insmask) | ((s << loffset) & insmask);
|
||||
} else {
|
||||
IData hinsmask = (VL_MASK_I(hoffset-0+1))<<0;
|
||||
IData linsmask = (VL_MASK_I(31-loffset+1))<<loffset;
|
||||
int nbitsonright = 32-loffset; // bits that end up in lword
|
||||
dp[lword] = (dp[lword] & ~linsmask) | ((s<<loffset) & linsmask);
|
||||
dp[hword] = (dp[hword] & ~hinsmask) | ((s>>nbitsonright) & hinsmask);
|
||||
IData hinsmask = (VL_MASK_I(hoffset - 0 + 1)) << 0;
|
||||
IData linsmask = (VL_MASK_I(31 - loffset + 1)) << loffset;
|
||||
int nbitsonright = 32 - loffset; // bits that end up in lword
|
||||
dp[lword] = (dp[lword] & ~linsmask) | ((s << loffset) & linsmask);
|
||||
dp[hword] = (dp[hword] & ~hinsmask) | ((s >> nbitsonright) & hinsmask);
|
||||
}
|
||||
}
|
||||
}
|
||||
// cppcheck-suppress passedByValue
|
||||
void svPutPartselLogic(svLogicVecVal* dp, const svLogicVecVal s, int lbit, int width) {
|
||||
int hbit = lbit+width-1;
|
||||
int hbit = lbit + width - 1;
|
||||
int hoffset = VL_BITBIT_I(hbit);
|
||||
int loffset = VL_BITBIT_I(lbit);
|
||||
if (hoffset==VL_SIZEBITS_I && loffset==0) {
|
||||
if (hoffset == VL_SIZEBITS_I && loffset == 0) {
|
||||
// Fast and common case, word based insertion
|
||||
dp[VL_BITWORD_I(lbit)].aval = s.aval;
|
||||
dp[VL_BITWORD_I(lbit)].bval = s.bval;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
int hword = VL_BITWORD_I(hbit);
|
||||
int lword = VL_BITWORD_I(lbit);
|
||||
if (hword==lword) { // know < 32 bits because above checks it
|
||||
IData insmask = (VL_MASK_I(hoffset-loffset+1))<<loffset;
|
||||
dp[lword].aval = (dp[lword].aval & ~insmask) | ((s.aval<<loffset) & insmask);
|
||||
dp[lword].bval = (dp[lword].bval & ~insmask) | ((s.bval<<loffset) & insmask);
|
||||
if (hword == lword) { // know < 32 bits because above checks it
|
||||
IData insmask = (VL_MASK_I(hoffset - loffset + 1)) << loffset;
|
||||
dp[lword].aval = (dp[lword].aval & ~insmask) | ((s.aval << loffset) & insmask);
|
||||
dp[lword].bval = (dp[lword].bval & ~insmask) | ((s.bval << loffset) & insmask);
|
||||
} else {
|
||||
IData hinsmask = (VL_MASK_I(hoffset-0+1))<<0;
|
||||
IData linsmask = (VL_MASK_I(31-loffset+1))<<loffset;
|
||||
int nbitsonright = 32-loffset; // bits that end up in lword
|
||||
dp[lword].aval = (dp[lword].aval & ~linsmask) | ((s.aval<<loffset) & linsmask);
|
||||
dp[lword].bval = (dp[lword].bval & ~linsmask) | ((s.bval<<loffset) & linsmask);
|
||||
dp[hword].aval = (dp[hword].aval & ~hinsmask) | ((s.aval>>nbitsonright) & hinsmask);
|
||||
dp[hword].bval = (dp[hword].bval & ~hinsmask) | ((s.bval>>nbitsonright) & hinsmask);
|
||||
IData hinsmask = (VL_MASK_I(hoffset - 0 + 1)) << 0;
|
||||
IData linsmask = (VL_MASK_I(31 - loffset + 1)) << loffset;
|
||||
int nbitsonright = 32 - loffset; // bits that end up in lword
|
||||
dp[lword].aval = (dp[lword].aval & ~linsmask) | ((s.aval << loffset) & linsmask);
|
||||
dp[lword].bval = (dp[lword].bval & ~linsmask) | ((s.bval << loffset) & linsmask);
|
||||
dp[hword].aval = (dp[hword].aval & ~hinsmask) | ((s.aval >> nbitsonright) & hinsmask);
|
||||
dp[hword].bval = (dp[hword].bval & ~hinsmask) | ((s.bval >> nbitsonright) & hinsmask);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -204,27 +194,14 @@ static inline const VerilatedDpiOpenVar* _vl_openhandle_varp(const svOpenArrayHa
|
|||
//======================================================================
|
||||
// Open array querying functions
|
||||
|
||||
int svLeft(const svOpenArrayHandle h, int d) {
|
||||
return _vl_openhandle_varp(h)->left(d);
|
||||
}
|
||||
int svRight(const svOpenArrayHandle h, int d) {
|
||||
return _vl_openhandle_varp(h)->right(d);
|
||||
}
|
||||
int svLow(const svOpenArrayHandle h, int d) {
|
||||
return _vl_openhandle_varp(h)->low(d);
|
||||
}
|
||||
int svHigh(const svOpenArrayHandle h, int d) {
|
||||
return _vl_openhandle_varp(h)->high(d);
|
||||
}
|
||||
int svIncrement(const svOpenArrayHandle h, int d) {
|
||||
return _vl_openhandle_varp(h)->increment(d);
|
||||
}
|
||||
int svSize(const svOpenArrayHandle h, int d) {
|
||||
return _vl_openhandle_varp(h)->elements(d);
|
||||
}
|
||||
int svDimensions(const svOpenArrayHandle h) {
|
||||
return _vl_openhandle_varp(h)->udims();
|
||||
}
|
||||
int svLeft(const svOpenArrayHandle h, int d) { return _vl_openhandle_varp(h)->left(d); }
|
||||
int svRight(const svOpenArrayHandle h, int d) { return _vl_openhandle_varp(h)->right(d); }
|
||||
int svLow(const svOpenArrayHandle h, int d) { return _vl_openhandle_varp(h)->low(d); }
|
||||
int svHigh(const svOpenArrayHandle h, int d) { return _vl_openhandle_varp(h)->high(d); }
|
||||
int svIncrement(const svOpenArrayHandle h, int d) { return _vl_openhandle_varp(h)->increment(d); }
|
||||
int svSize(const svOpenArrayHandle h, int d) { return _vl_openhandle_varp(h)->elements(d); }
|
||||
int svDimensions(const svOpenArrayHandle h) { return _vl_openhandle_varp(h)->udims(); }
|
||||
|
||||
/// Return pointer to open array data, or NULL if not in IEEE standard C layout
|
||||
void* svGetArrayPtr(const svOpenArrayHandle h) {
|
||||
const VerilatedDpiOpenVar* varp = _vl_openhandle_varp(h);
|
||||
|
|
@ -242,8 +219,8 @@ int svSizeOfArray(const svOpenArrayHandle h) {
|
|||
//======================================================================
|
||||
// Open array access internals
|
||||
|
||||
static void* _vl_sv_adjusted_datap(const VerilatedDpiOpenVar* varp,
|
||||
int nargs, int indx1, int indx2, int indx3) {
|
||||
static void* _vl_sv_adjusted_datap(const VerilatedDpiOpenVar* varp, int nargs, int indx1,
|
||||
int indx2, int indx3) {
|
||||
void* datap = varp->datap();
|
||||
if (VL_UNLIKELY(nargs != varp->udims())) {
|
||||
_VL_SVDPI_WARN("%%Warning: DPI svOpenArrayHandle function called on"
|
||||
|
|
@ -251,26 +228,29 @@ static void* _vl_sv_adjusted_datap(const VerilatedDpiOpenVar* varp,
|
|||
varp->udims(), nargs);
|
||||
return NULL;
|
||||
}
|
||||
if (nargs>=1) {
|
||||
if (nargs >= 1) {
|
||||
datap = varp->datapAdjustIndex(datap, 1, indx1);
|
||||
if (VL_UNLIKELY(!datap)) {
|
||||
_VL_SVDPI_WARN("%%Warning: DPI svOpenArrayHandle function index 1 out of bounds; %d outside [%d:%d].\n",
|
||||
_VL_SVDPI_WARN("%%Warning: DPI svOpenArrayHandle function index 1 "
|
||||
"out of bounds; %d outside [%d:%d].\n",
|
||||
indx1, varp->left(1), varp->right(1));
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
if (nargs>=2) {
|
||||
if (nargs >= 2) {
|
||||
datap = varp->datapAdjustIndex(datap, 2, indx2);
|
||||
if (VL_UNLIKELY(!datap)) {
|
||||
_VL_SVDPI_WARN("%%Warning: DPI svOpenArrayHandle function index 2 out of bounds; %d outside [%d:%d].\n",
|
||||
_VL_SVDPI_WARN("%%Warning: DPI svOpenArrayHandle function index 2 "
|
||||
"out of bounds; %d outside [%d:%d].\n",
|
||||
indx2, varp->left(2), varp->right(2));
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
if (nargs>=3) {
|
||||
if (nargs >= 3) {
|
||||
datap = varp->datapAdjustIndex(datap, 3, indx3);
|
||||
if (VL_UNLIKELY(!datap)) {
|
||||
_VL_SVDPI_WARN("%%Warning: DPI svOpenArrayHandle function index 3 out of bounds; %d outside [%d:%d].\n",
|
||||
_VL_SVDPI_WARN("%%Warning: DPI svOpenArrayHandle function index 3 "
|
||||
"out of bounds; %d outside [%d:%d].\n",
|
||||
indx1, varp->left(3), varp->right(3));
|
||||
return NULL;
|
||||
}
|
||||
|
|
@ -280,7 +260,8 @@ static void* _vl_sv_adjusted_datap(const VerilatedDpiOpenVar* varp,
|
|||
|
||||
static int _vl_sv_adjusted_bit(const VerilatedDpiOpenVar* varp, int indx) {
|
||||
if (VL_UNLIKELY(indx < varp->low(0) || indx > varp->high(0))) {
|
||||
_VL_SVDPI_WARN("%%Warning: DPI svOpenArrayHandle function packed index out of bounds; %d outside [%d:%d].\n",
|
||||
_VL_SVDPI_WARN("%%Warning: DPI svOpenArrayHandle function packed index out of bounds; %d "
|
||||
"outside [%d:%d].\n",
|
||||
indx, varp->left(0), varp->right(0));
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -288,8 +269,8 @@ static int _vl_sv_adjusted_bit(const VerilatedDpiOpenVar* varp, int indx) {
|
|||
}
|
||||
|
||||
/// Return pointer to simulator open array element, or NULL if outside range
|
||||
static void* _vl_svGetArrElemPtr(const svOpenArrayHandle h,
|
||||
int nargs, int indx1, int indx2, int indx3) VL_MT_SAFE {
|
||||
static void* _vl_svGetArrElemPtr(const svOpenArrayHandle h, int nargs, int indx1, int indx2,
|
||||
int indx3) VL_MT_SAFE {
|
||||
const VerilatedDpiOpenVar* varp = _vl_openhandle_varp(h);
|
||||
if (VL_UNLIKELY(!varp->isDpiStdLayout())) return NULL;
|
||||
void* datap = _vl_sv_adjusted_datap(varp, nargs, indx1, indx2, indx3);
|
||||
|
|
@ -297,23 +278,25 @@ static void* _vl_svGetArrElemPtr(const svOpenArrayHandle h,
|
|||
}
|
||||
|
||||
/// Copy to user bit array from simulator open array
|
||||
static void _vl_svGetBitArrElemVecVal(svBitVecVal* d, const svOpenArrayHandle s,
|
||||
int nargs, int indx1, int indx2, int indx3) VL_MT_SAFE {
|
||||
static void _vl_svGetBitArrElemVecVal(svBitVecVal* d, const svOpenArrayHandle s, int nargs,
|
||||
int indx1, int indx2, int indx3) VL_MT_SAFE {
|
||||
const VerilatedDpiOpenVar* varp = _vl_openhandle_varp(s);
|
||||
void* datap = _vl_sv_adjusted_datap(varp, nargs, indx1, indx2, indx3);
|
||||
if (VL_UNLIKELY(!datap)) return;
|
||||
switch (varp->vltype()) {
|
||||
case VLVT_UINT8: d[0] = *(reinterpret_cast<CData*>(datap)); return;
|
||||
case VLVT_UINT8: d[0] = *(reinterpret_cast<CData*>(datap)); return;
|
||||
case VLVT_UINT16: d[0] = *(reinterpret_cast<SData*>(datap)); return;
|
||||
case VLVT_UINT32: d[0] = *(reinterpret_cast<IData*>(datap)); return;
|
||||
case VLVT_UINT64: {
|
||||
WData lwp[2]; VL_SET_WQ(lwp, *(reinterpret_cast<QData*>(datap)));
|
||||
d[0] = lwp[0]; d[1] = lwp[1];
|
||||
WData lwp[2];
|
||||
VL_SET_WQ(lwp, *(reinterpret_cast<QData*>(datap)));
|
||||
d[0] = lwp[0];
|
||||
d[1] = lwp[1];
|
||||
break;
|
||||
}
|
||||
case VLVT_WDATA: {
|
||||
WDataOutP wdatap = (reinterpret_cast<WDataOutP>(datap));
|
||||
for (int i=0; i<VL_WORDS_I(varp->packed().elements()); ++i) d[i] = wdatap[i];
|
||||
for (int i = 0; i < VL_WORDS_I(varp->packed().elements()); ++i) d[i] = wdatap[i];
|
||||
return;
|
||||
}
|
||||
default:
|
||||
|
|
@ -323,25 +306,38 @@ static void _vl_svGetBitArrElemVecVal(svBitVecVal* d, const svOpenArrayHandle s,
|
|||
}
|
||||
}
|
||||
/// Copy to user logic array from simulator open array
|
||||
static void _vl_svGetLogicArrElemVecVal(svLogicVecVal* d, const svOpenArrayHandle s,
|
||||
int nargs, int indx1, int indx2, int indx3) VL_MT_SAFE {
|
||||
static void _vl_svGetLogicArrElemVecVal(svLogicVecVal* d, const svOpenArrayHandle s, int nargs,
|
||||
int indx1, int indx2, int indx3) VL_MT_SAFE {
|
||||
const VerilatedDpiOpenVar* varp = _vl_openhandle_varp(s);
|
||||
void* datap = _vl_sv_adjusted_datap(varp, nargs, indx1, indx2, indx3);
|
||||
if (VL_UNLIKELY(!datap)) return;
|
||||
switch (varp->vltype()) {
|
||||
case VLVT_UINT8: d[0].aval = *(reinterpret_cast<CData*>(datap)); d[0].bval=0; return;
|
||||
case VLVT_UINT16: d[0].aval = *(reinterpret_cast<SData*>(datap)); d[0].bval=0; return;
|
||||
case VLVT_UINT32: d[0].aval = *(reinterpret_cast<IData*>(datap)); d[0].bval=0; return;
|
||||
case VLVT_UINT8:
|
||||
d[0].aval = *(reinterpret_cast<CData*>(datap));
|
||||
d[0].bval = 0;
|
||||
return;
|
||||
case VLVT_UINT16:
|
||||
d[0].aval = *(reinterpret_cast<SData*>(datap));
|
||||
d[0].bval = 0;
|
||||
return;
|
||||
case VLVT_UINT32:
|
||||
d[0].aval = *(reinterpret_cast<IData*>(datap));
|
||||
d[0].bval = 0;
|
||||
return;
|
||||
case VLVT_UINT64: {
|
||||
WData lwp[2]; VL_SET_WQ(lwp, *(reinterpret_cast<QData*>(datap)));
|
||||
d[0].aval = lwp[0]; d[0].bval=0;
|
||||
d[1].aval = lwp[1]; d[0].bval=0;
|
||||
WData lwp[2];
|
||||
VL_SET_WQ(lwp, *(reinterpret_cast<QData*>(datap)));
|
||||
d[0].aval = lwp[0];
|
||||
d[0].bval = 0;
|
||||
d[1].aval = lwp[1];
|
||||
d[0].bval = 0;
|
||||
break;
|
||||
}
|
||||
case VLVT_WDATA: {
|
||||
WDataOutP wdatap = (reinterpret_cast<WDataOutP>(datap));
|
||||
for (int i=0; i<VL_WORDS_I(varp->packed().elements()); ++i) {
|
||||
d[i].aval = wdatap[i]; d[i].bval = 0;
|
||||
for (int i = 0; i < VL_WORDS_I(varp->packed().elements()); ++i) {
|
||||
d[i].aval = wdatap[i];
|
||||
d[i].bval = 0;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
|
@ -353,19 +349,19 @@ static void _vl_svGetLogicArrElemVecVal(svLogicVecVal* d, const svOpenArrayHandl
|
|||
}
|
||||
|
||||
/// Copy to simulator open array from from user bit array
|
||||
static void _vl_svPutBitArrElemVecVal(const svOpenArrayHandle d, const svBitVecVal* s,
|
||||
int nargs, int indx1, int indx2, int indx3) VL_MT_SAFE {
|
||||
static void _vl_svPutBitArrElemVecVal(const svOpenArrayHandle d, const svBitVecVal* s, int nargs,
|
||||
int indx1, int indx2, int indx3) VL_MT_SAFE {
|
||||
const VerilatedDpiOpenVar* varp = _vl_openhandle_varp(d);
|
||||
void* datap = _vl_sv_adjusted_datap(varp, nargs, indx1, indx2, indx3);
|
||||
if (VL_UNLIKELY(!datap)) return;
|
||||
switch (varp->vltype()) {
|
||||
case VLVT_UINT8: *(reinterpret_cast<CData*>(datap)) = s[0]; return;
|
||||
case VLVT_UINT8: *(reinterpret_cast<CData*>(datap)) = s[0]; return;
|
||||
case VLVT_UINT16: *(reinterpret_cast<SData*>(datap)) = s[0]; return;
|
||||
case VLVT_UINT32: *(reinterpret_cast<IData*>(datap)) = s[0]; return;
|
||||
case VLVT_UINT64: *(reinterpret_cast<QData*>(datap)) = _VL_SET_QII(s[1], s[0]); break;
|
||||
case VLVT_WDATA: {
|
||||
WDataOutP wdatap = (reinterpret_cast<WDataOutP>(datap));
|
||||
for (int i=0; i<VL_WORDS_I(varp->packed().elements()); ++i) wdatap[i] = s[i];
|
||||
for (int i = 0; i < VL_WORDS_I(varp->packed().elements()); ++i) wdatap[i] = s[i];
|
||||
return;
|
||||
}
|
||||
default:
|
||||
|
|
@ -381,80 +377,82 @@ static void _vl_svPutLogicArrElemVecVal(const svOpenArrayHandle d, const svLogic
|
|||
void* datap = _vl_sv_adjusted_datap(varp, nargs, indx1, indx2, indx3);
|
||||
if (VL_UNLIKELY(!datap)) return;
|
||||
switch (varp->vltype()) {
|
||||
case VLVT_UINT8: *(reinterpret_cast<CData*>(datap)) = s[0].aval; return;
|
||||
case VLVT_UINT8: *(reinterpret_cast<CData*>(datap)) = s[0].aval; return;
|
||||
case VLVT_UINT16: *(reinterpret_cast<SData*>(datap)) = s[0].aval; return;
|
||||
case VLVT_UINT32: *(reinterpret_cast<IData*>(datap)) = s[0].aval; return;
|
||||
case VLVT_UINT64: *(reinterpret_cast<QData*>(datap)) = _VL_SET_QII(s[1].aval, s[0].aval); break;
|
||||
case VLVT_UINT64:
|
||||
*(reinterpret_cast<QData*>(datap)) = _VL_SET_QII(s[1].aval, s[0].aval);
|
||||
break;
|
||||
case VLVT_WDATA: {
|
||||
WDataOutP wdatap = (reinterpret_cast<WDataOutP>(datap));
|
||||
for (int i=0; i<VL_WORDS_I(varp->packed().elements()); ++i) wdatap[i] = s[i].aval;
|
||||
for (int i = 0; i < VL_WORDS_I(varp->packed().elements()); ++i) wdatap[i] = s[i].aval;
|
||||
return;
|
||||
}
|
||||
default:
|
||||
_VL_SVDPI_WARN("%%Warning: DPI svOpenArrayHandle function unsupported datatype (%d).\n", varp->vltype());
|
||||
_VL_SVDPI_WARN("%%Warning: DPI svOpenArrayHandle function unsupported datatype (%d).\n",
|
||||
varp->vltype());
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/// Return bit from simulator open array
|
||||
static svBit _vl_svGetBitArrElem(const svOpenArrayHandle s,
|
||||
int nargs, int indx1, int indx2, int indx3, int indx4) VL_MT_SAFE {
|
||||
static svBit _vl_svGetBitArrElem(const svOpenArrayHandle s, int nargs, int indx1, int indx2,
|
||||
int indx3, int indx4) VL_MT_SAFE {
|
||||
// One extra index supported, as need bit number
|
||||
const VerilatedDpiOpenVar* varp = _vl_openhandle_varp(s);
|
||||
void* datap;
|
||||
int lsb;
|
||||
if (varp->packed().elements()) {
|
||||
datap = _vl_sv_adjusted_datap(varp, nargs-1, indx1, indx2, indx3);
|
||||
lsb = _vl_sv_adjusted_bit(varp, ((nargs==1) ? indx1
|
||||
: (nargs==2) ? indx2
|
||||
: (nargs==3) ? indx3
|
||||
: indx4));
|
||||
datap = _vl_sv_adjusted_datap(varp, nargs - 1, indx1, indx2, indx3);
|
||||
lsb = _vl_sv_adjusted_bit(
|
||||
varp, ((nargs == 1) ? indx1 : (nargs == 2) ? indx2 : (nargs == 3) ? indx3 : indx4));
|
||||
} else {
|
||||
datap = _vl_sv_adjusted_datap(varp, nargs, indx1, indx2, indx3);
|
||||
lsb = 0;
|
||||
}
|
||||
if (VL_UNLIKELY(!datap)) return 0;
|
||||
switch (varp->vltype()) {
|
||||
case VLVT_UINT8: return (*(reinterpret_cast<CData*>(datap)) >> lsb) & 1;
|
||||
case VLVT_UINT8: return (*(reinterpret_cast<CData*>(datap)) >> lsb) & 1;
|
||||
case VLVT_UINT16: return (*(reinterpret_cast<SData*>(datap)) >> lsb) & 1;
|
||||
case VLVT_UINT32: return (*(reinterpret_cast<IData*>(datap)) >> lsb) & 1;
|
||||
case VLVT_UINT64: return (*(reinterpret_cast<QData*>(datap)) >> static_cast<QData>(lsb)) & VL_ULL(1);
|
||||
case VLVT_UINT64:
|
||||
return (*(reinterpret_cast<QData*>(datap)) >> static_cast<QData>(lsb)) & VL_ULL(1);
|
||||
case VLVT_WDATA: {
|
||||
WDataOutP wdatap = (reinterpret_cast<WDataOutP>(datap));
|
||||
return VL_BITRSHIFT_W(wdatap, lsb) & 1;
|
||||
}
|
||||
default:
|
||||
_VL_SVDPI_WARN("%%Warning: DPI svOpenArrayHandle function unsupported datatype (%d).\n", varp->vltype());
|
||||
_VL_SVDPI_WARN("%%Warning: DPI svOpenArrayHandle function unsupported datatype (%d).\n",
|
||||
varp->vltype());
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
/// Update simulator open array from bit
|
||||
static void _vl_svPutBitArrElem(const svOpenArrayHandle d, svBit value,
|
||||
int nargs, int indx1, int indx2, int indx3, int indx4) VL_MT_SAFE {
|
||||
static void _vl_svPutBitArrElem(const svOpenArrayHandle d, svBit value, int nargs, int indx1,
|
||||
int indx2, int indx3, int indx4) VL_MT_SAFE {
|
||||
// One extra index supported, as need bit number
|
||||
value &= 1; // Make sure clean
|
||||
const VerilatedDpiOpenVar* varp = _vl_openhandle_varp(d);
|
||||
void* datap;
|
||||
int lsb;
|
||||
if (varp->packed().elements()) {
|
||||
datap = _vl_sv_adjusted_datap(varp, nargs-1, indx1, indx2, indx3);
|
||||
lsb = _vl_sv_adjusted_bit(varp, ((nargs==1) ? indx1
|
||||
: (nargs==2) ? indx2
|
||||
: (nargs==3) ? indx3
|
||||
: indx4));
|
||||
datap = _vl_sv_adjusted_datap(varp, nargs - 1, indx1, indx2, indx3);
|
||||
lsb = _vl_sv_adjusted_bit(
|
||||
varp, ((nargs == 1) ? indx1 : (nargs == 2) ? indx2 : (nargs == 3) ? indx3 : indx4));
|
||||
} else {
|
||||
datap = _vl_sv_adjusted_datap(varp, nargs, indx1, indx2, indx3);
|
||||
lsb = 0;
|
||||
}
|
||||
if (VL_UNLIKELY(!datap)) return;
|
||||
switch (varp->vltype()) {
|
||||
case VLVT_UINT8: VL_ASSIGNBIT_II(-1, lsb, *(reinterpret_cast<CData*>(datap)), value); return;
|
||||
case VLVT_UINT8: VL_ASSIGNBIT_II(-1, lsb, *(reinterpret_cast<CData*>(datap)), value); return;
|
||||
case VLVT_UINT16: VL_ASSIGNBIT_II(-1, lsb, *(reinterpret_cast<SData*>(datap)), value); return;
|
||||
case VLVT_UINT32: VL_ASSIGNBIT_II(-1, lsb, *(reinterpret_cast<IData*>(datap)), value); return;
|
||||
case VLVT_UINT64: VL_ASSIGNBIT_QI(-1, lsb, *(reinterpret_cast<QData*>(datap)), value); return;
|
||||
case VLVT_WDATA: VL_ASSIGNBIT_WI(-1, lsb, (reinterpret_cast<WDataOutP>(datap)), value); return;
|
||||
case VLVT_WDATA: VL_ASSIGNBIT_WI(-1, lsb, (reinterpret_cast<WDataOutP>(datap)), value); return;
|
||||
default:
|
||||
_VL_SVDPI_WARN("%%Warning: DPI svOpenArrayHandle function unsupported datatype (%d).\n", varp->vltype());
|
||||
_VL_SVDPI_WARN("%%Warning: DPI svOpenArrayHandle function unsupported datatype (%d).\n",
|
||||
varp->vltype());
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
@ -470,10 +468,17 @@ void* svGetArrElemPtr(const svOpenArrayHandle h, int indx1, ...) {
|
|||
// va_arg is a macro, so need temporaries as used below
|
||||
switch (varp->udims()) {
|
||||
case 1: datap = _vl_svGetArrElemPtr(h, 1, indx1, 0, 0); break;
|
||||
case 2: { int indx2=va_arg(ap,int);
|
||||
datap = _vl_svGetArrElemPtr(h, 2, indx1, indx2, 0); break; }
|
||||
case 3: { int indx2=va_arg(ap,int); int indx3=va_arg(ap,int);
|
||||
datap = _vl_svGetArrElemPtr(h, 3, indx1, indx2, indx3); break; }
|
||||
case 2: {
|
||||
int indx2 = va_arg(ap, int);
|
||||
datap = _vl_svGetArrElemPtr(h, 2, indx1, indx2, 0);
|
||||
break;
|
||||
}
|
||||
case 3: {
|
||||
int indx2 = va_arg(ap, int);
|
||||
int indx3 = va_arg(ap, int);
|
||||
datap = _vl_svGetArrElemPtr(h, 3, indx1, indx2, indx3);
|
||||
break;
|
||||
}
|
||||
default: datap = _vl_svGetArrElemPtr(h, -1, 0, 0, 0); break; // Will error
|
||||
}
|
||||
va_end(ap);
|
||||
|
|
@ -489,116 +494,134 @@ void* svGetArrElemPtr3(const svOpenArrayHandle h, int indx1, int indx2, int indx
|
|||
return _vl_svGetArrElemPtr(h, 3, indx1, indx2, indx3);
|
||||
}
|
||||
|
||||
void svPutBitArrElemVecVal(const svOpenArrayHandle d, const svBitVecVal* s,
|
||||
int indx1, ...) {
|
||||
void svPutBitArrElemVecVal(const svOpenArrayHandle d, const svBitVecVal* s, int indx1, ...) {
|
||||
const VerilatedDpiOpenVar* varp = _vl_openhandle_varp(d);
|
||||
va_list ap;
|
||||
va_start(ap, indx1);
|
||||
switch (varp->udims()) {
|
||||
case 1: _vl_svPutBitArrElemVecVal(d, s, 1, indx1, 0, 0); break;
|
||||
case 2: { int indx2=va_arg(ap,int);
|
||||
_vl_svPutBitArrElemVecVal(d, s, 2, indx1, indx2, 0); break; }
|
||||
case 3: { int indx2=va_arg(ap,int); int indx3=va_arg(ap,int);
|
||||
_vl_svPutBitArrElemVecVal(d, s, 3, indx1, indx2, indx3); break; }
|
||||
case 2: {
|
||||
int indx2 = va_arg(ap, int);
|
||||
_vl_svPutBitArrElemVecVal(d, s, 2, indx1, indx2, 0);
|
||||
break;
|
||||
}
|
||||
case 3: {
|
||||
int indx2 = va_arg(ap, int);
|
||||
int indx3 = va_arg(ap, int);
|
||||
_vl_svPutBitArrElemVecVal(d, s, 3, indx1, indx2, indx3);
|
||||
break;
|
||||
}
|
||||
default: _vl_svPutBitArrElemVecVal(d, s, -1, 0, 0, 0); break; // Will error
|
||||
}
|
||||
va_end(ap);
|
||||
}
|
||||
void svPutBitArrElem1VecVal(const svOpenArrayHandle d, const svBitVecVal* s,
|
||||
int indx1) {
|
||||
void svPutBitArrElem1VecVal(const svOpenArrayHandle d, const svBitVecVal* s, int indx1) {
|
||||
_vl_svPutBitArrElemVecVal(d, s, 1, indx1, 0, 0);
|
||||
}
|
||||
void svPutBitArrElem2VecVal(const svOpenArrayHandle d, const svBitVecVal* s,
|
||||
int indx1, int indx2) {
|
||||
void svPutBitArrElem2VecVal(const svOpenArrayHandle d, const svBitVecVal* s, int indx1,
|
||||
int indx2) {
|
||||
_vl_svPutBitArrElemVecVal(d, s, 2, indx1, indx2, 0);
|
||||
}
|
||||
void svPutBitArrElem3VecVal(const svOpenArrayHandle d, const svBitVecVal* s,
|
||||
int indx1, int indx2, int indx3) {
|
||||
void svPutBitArrElem3VecVal(const svOpenArrayHandle d, const svBitVecVal* s, int indx1, int indx2,
|
||||
int indx3) {
|
||||
_vl_svPutBitArrElemVecVal(d, s, 3, indx1, indx2, indx3);
|
||||
}
|
||||
void svPutLogicArrElemVecVal(const svOpenArrayHandle d, const svLogicVecVal* s,
|
||||
int indx1, ...) {
|
||||
void svPutLogicArrElemVecVal(const svOpenArrayHandle d, const svLogicVecVal* s, int indx1, ...) {
|
||||
const VerilatedDpiOpenVar* varp = _vl_openhandle_varp(d);
|
||||
va_list ap;
|
||||
va_start(ap, indx1);
|
||||
switch (varp->udims()) {
|
||||
case 1: _vl_svPutLogicArrElemVecVal(d, s, 1, indx1, 0, 0); break;
|
||||
case 2: { int indx2=va_arg(ap,int);
|
||||
_vl_svPutLogicArrElemVecVal(d, s, 2, indx1, indx2, 0); break; }
|
||||
case 3: { int indx2=va_arg(ap,int); int indx3=va_arg(ap,int);
|
||||
_vl_svPutLogicArrElemVecVal(d, s, 3, indx1, indx2, indx3); break; }
|
||||
case 2: {
|
||||
int indx2 = va_arg(ap, int);
|
||||
_vl_svPutLogicArrElemVecVal(d, s, 2, indx1, indx2, 0);
|
||||
break;
|
||||
}
|
||||
case 3: {
|
||||
int indx2 = va_arg(ap, int);
|
||||
int indx3 = va_arg(ap, int);
|
||||
_vl_svPutLogicArrElemVecVal(d, s, 3, indx1, indx2, indx3);
|
||||
break;
|
||||
}
|
||||
default: _vl_svPutLogicArrElemVecVal(d, s, -1, 0, 0, 0); break; // Will error
|
||||
}
|
||||
va_end(ap);
|
||||
}
|
||||
void svPutLogicArrElem1VecVal(const svOpenArrayHandle d, const svLogicVecVal* s,
|
||||
int indx1) {
|
||||
void svPutLogicArrElem1VecVal(const svOpenArrayHandle d, const svLogicVecVal* s, int indx1) {
|
||||
_vl_svPutLogicArrElemVecVal(d, s, 1, indx1, 0, 0);
|
||||
}
|
||||
void svPutLogicArrElem2VecVal(const svOpenArrayHandle d, const svLogicVecVal* s,
|
||||
int indx1, int indx2) {
|
||||
void svPutLogicArrElem2VecVal(const svOpenArrayHandle d, const svLogicVecVal* s, int indx1,
|
||||
int indx2) {
|
||||
_vl_svPutLogicArrElemVecVal(d, s, 2, indx1, indx2, 0);
|
||||
}
|
||||
void svPutLogicArrElem3VecVal(const svOpenArrayHandle d, const svLogicVecVal* s,
|
||||
int indx1, int indx2, int indx3) {
|
||||
void svPutLogicArrElem3VecVal(const svOpenArrayHandle d, const svLogicVecVal* s, int indx1,
|
||||
int indx2, int indx3) {
|
||||
_vl_svPutLogicArrElemVecVal(d, s, 3, indx1, indx2, indx3);
|
||||
}
|
||||
|
||||
//======================================================================
|
||||
// From simulator storage into user space
|
||||
|
||||
void svGetBitArrElemVecVal(svBitVecVal* d, const svOpenArrayHandle s,
|
||||
int indx1, ...) {
|
||||
void svGetBitArrElemVecVal(svBitVecVal* d, const svOpenArrayHandle s, int indx1, ...) {
|
||||
const VerilatedDpiOpenVar* varp = _vl_openhandle_varp(s);
|
||||
va_list ap;
|
||||
va_start(ap, indx1);
|
||||
switch (varp->udims()) {
|
||||
case 1: _vl_svGetBitArrElemVecVal(d, s, 1, indx1, 0, 0); break;
|
||||
case 2: { int indx2=va_arg(ap,int);
|
||||
_vl_svGetBitArrElemVecVal(d, s, 2, indx1, indx2, 0); break; }
|
||||
case 3: { int indx2=va_arg(ap,int); int indx3=va_arg(ap,int);
|
||||
_vl_svGetBitArrElemVecVal(d, s, 3, indx1, indx2, indx3); break; }
|
||||
case 2: {
|
||||
int indx2 = va_arg(ap, int);
|
||||
_vl_svGetBitArrElemVecVal(d, s, 2, indx1, indx2, 0);
|
||||
break;
|
||||
}
|
||||
case 3: {
|
||||
int indx2 = va_arg(ap, int);
|
||||
int indx3 = va_arg(ap, int);
|
||||
_vl_svGetBitArrElemVecVal(d, s, 3, indx1, indx2, indx3);
|
||||
break;
|
||||
}
|
||||
default: _vl_svGetBitArrElemVecVal(d, s, -1, 0, 0, 0); break; // Will error
|
||||
}
|
||||
va_end(ap);
|
||||
}
|
||||
void svGetBitArrElem1VecVal(svBitVecVal* d, const svOpenArrayHandle s,
|
||||
int indx1) {
|
||||
void svGetBitArrElem1VecVal(svBitVecVal* d, const svOpenArrayHandle s, int indx1) {
|
||||
_vl_svGetBitArrElemVecVal(d, s, 1, indx1, 0, 0);
|
||||
}
|
||||
void svGetBitArrElem2VecVal(svBitVecVal* d, const svOpenArrayHandle s,
|
||||
int indx1, int indx2) {
|
||||
void svGetBitArrElem2VecVal(svBitVecVal* d, const svOpenArrayHandle s, int indx1, int indx2) {
|
||||
_vl_svGetBitArrElemVecVal(d, s, 2, indx1, indx2, 0);
|
||||
}
|
||||
void svGetBitArrElem3VecVal(svBitVecVal* d, const svOpenArrayHandle s,
|
||||
int indx1, int indx2, int indx3) {
|
||||
void svGetBitArrElem3VecVal(svBitVecVal* d, const svOpenArrayHandle s, int indx1, int indx2,
|
||||
int indx3) {
|
||||
_vl_svGetBitArrElemVecVal(d, s, 3, indx1, indx2, indx3);
|
||||
}
|
||||
void svGetLogicArrElemVecVal(svLogicVecVal* d, const svOpenArrayHandle s,
|
||||
int indx1, ...) {
|
||||
void svGetLogicArrElemVecVal(svLogicVecVal* d, const svOpenArrayHandle s, int indx1, ...) {
|
||||
const VerilatedDpiOpenVar* varp = _vl_openhandle_varp(s);
|
||||
va_list ap;
|
||||
va_start(ap, indx1);
|
||||
switch (varp->udims()) {
|
||||
case 1: _vl_svGetLogicArrElemVecVal(d, s, 1, indx1, 0, 0); break;
|
||||
case 2: { int indx2=va_arg(ap,int);
|
||||
_vl_svGetLogicArrElemVecVal(d, s, 2, indx1, indx2, 0); break; }
|
||||
case 3: { int indx2=va_arg(ap,int); int indx3=va_arg(ap,int);
|
||||
_vl_svGetLogicArrElemVecVal(d, s, 3, indx1, indx2, indx3); break; }
|
||||
case 2: {
|
||||
int indx2 = va_arg(ap, int);
|
||||
_vl_svGetLogicArrElemVecVal(d, s, 2, indx1, indx2, 0);
|
||||
break;
|
||||
}
|
||||
case 3: {
|
||||
int indx2 = va_arg(ap, int);
|
||||
int indx3 = va_arg(ap, int);
|
||||
_vl_svGetLogicArrElemVecVal(d, s, 3, indx1, indx2, indx3);
|
||||
break;
|
||||
}
|
||||
default: _vl_svGetLogicArrElemVecVal(d, s, -1, 0, 0, 0); break; // Will error
|
||||
}
|
||||
va_end(ap);
|
||||
}
|
||||
void svGetLogicArrElem1VecVal(svLogicVecVal* d, const svOpenArrayHandle s,
|
||||
int indx1) {
|
||||
void svGetLogicArrElem1VecVal(svLogicVecVal* d, const svOpenArrayHandle s, int indx1) {
|
||||
_vl_svGetLogicArrElemVecVal(d, s, 1, indx1, 0, 0);
|
||||
}
|
||||
void svGetLogicArrElem2VecVal(svLogicVecVal* d, const svOpenArrayHandle s,
|
||||
int indx1, int indx2) {
|
||||
void svGetLogicArrElem2VecVal(svLogicVecVal* d, const svOpenArrayHandle s, int indx1, int indx2) {
|
||||
_vl_svGetLogicArrElemVecVal(d, s, 2, indx1, indx2, 0);
|
||||
}
|
||||
void svGetLogicArrElem3VecVal(svLogicVecVal* d, const svOpenArrayHandle s,
|
||||
int indx1, int indx2, int indx3) {
|
||||
void svGetLogicArrElem3VecVal(svLogicVecVal* d, const svOpenArrayHandle s, int indx1, int indx2,
|
||||
int indx3) {
|
||||
_vl_svGetLogicArrElemVecVal(d, s, 3, indx1, indx2, indx3);
|
||||
}
|
||||
|
||||
|
|
@ -609,12 +632,24 @@ svBit svGetBitArrElem(const svOpenArrayHandle s, int indx1, ...) {
|
|||
va_start(ap, indx1);
|
||||
switch (varp->udims()) {
|
||||
case 1: out = _vl_svGetBitArrElem(s, 1, indx1, 0, 0, 0); break;
|
||||
case 2: { int indx2=va_arg(ap,int);
|
||||
out = _vl_svGetBitArrElem(s, 2, indx1, indx2, 0, 0); break; }
|
||||
case 3: { int indx2=va_arg(ap,int); int indx3=va_arg(ap,int);
|
||||
out = _vl_svGetBitArrElem(s, 3, indx1, indx2, indx3, 0); break; }
|
||||
case 4: { int indx2=va_arg(ap,int); int indx3=va_arg(ap,int); int indx4=va_arg(ap,int);
|
||||
out = _vl_svGetBitArrElem(s, 4, indx1, indx2, indx3, indx4); break; }
|
||||
case 2: {
|
||||
int indx2 = va_arg(ap, int);
|
||||
out = _vl_svGetBitArrElem(s, 2, indx1, indx2, 0, 0);
|
||||
break;
|
||||
}
|
||||
case 3: {
|
||||
int indx2 = va_arg(ap, int);
|
||||
int indx3 = va_arg(ap, int);
|
||||
out = _vl_svGetBitArrElem(s, 3, indx1, indx2, indx3, 0);
|
||||
break;
|
||||
}
|
||||
case 4: {
|
||||
int indx2 = va_arg(ap, int);
|
||||
int indx3 = va_arg(ap, int);
|
||||
int indx4 = va_arg(ap, int);
|
||||
out = _vl_svGetBitArrElem(s, 4, indx1, indx2, indx3, indx4);
|
||||
break;
|
||||
}
|
||||
default: out = _vl_svGetBitArrElem(s, -1, 0, 0, 0, 0); break; // Will error
|
||||
}
|
||||
va_end(ap);
|
||||
|
|
@ -637,12 +672,24 @@ svLogic svGetLogicArrElem(const svOpenArrayHandle s, int indx1, ...) {
|
|||
va_start(ap, indx1);
|
||||
switch (varp->udims()) {
|
||||
case 1: out = _vl_svGetBitArrElem(s, 1, indx1, 0, 0, 0); break;
|
||||
case 2: { int indx2=va_arg(ap,int);
|
||||
out = _vl_svGetBitArrElem(s, 2, indx1, indx2, 0, 0); break; }
|
||||
case 3: { int indx2=va_arg(ap,int); int indx3=va_arg(ap,int);
|
||||
out = _vl_svGetBitArrElem(s, 3, indx1, indx2, indx3, 0); break; }
|
||||
case 4: { int indx2=va_arg(ap,int); int indx3=va_arg(ap,int); int indx4=va_arg(ap,int);
|
||||
out = _vl_svGetBitArrElem(s, 4, indx1, indx2, indx3, indx4); break; }
|
||||
case 2: {
|
||||
int indx2 = va_arg(ap, int);
|
||||
out = _vl_svGetBitArrElem(s, 2, indx1, indx2, 0, 0);
|
||||
break;
|
||||
}
|
||||
case 3: {
|
||||
int indx2 = va_arg(ap, int);
|
||||
int indx3 = va_arg(ap, int);
|
||||
out = _vl_svGetBitArrElem(s, 3, indx1, indx2, indx3, 0);
|
||||
break;
|
||||
}
|
||||
case 4: {
|
||||
int indx2 = va_arg(ap, int);
|
||||
int indx3 = va_arg(ap, int);
|
||||
int indx4 = va_arg(ap, int);
|
||||
out = _vl_svGetBitArrElem(s, 4, indx1, indx2, indx3, indx4);
|
||||
break;
|
||||
}
|
||||
default: out = _vl_svGetBitArrElem(s, -1, 0, 0, 0, 0); break; // Will error
|
||||
}
|
||||
va_end(ap);
|
||||
|
|
@ -667,12 +714,24 @@ void svPutBitArrElem(const svOpenArrayHandle d, svBit value, int indx1, ...) {
|
|||
va_start(ap, indx1);
|
||||
switch (varp->udims()) {
|
||||
case 1: _vl_svPutBitArrElem(d, value, 1, indx1, 0, 0, 0); break;
|
||||
case 2: { int indx2=va_arg(ap,int);
|
||||
_vl_svPutBitArrElem(d, value, 2, indx1, indx2, 0, 0); break; }
|
||||
case 3: { int indx2=va_arg(ap,int); int indx3=va_arg(ap,int);
|
||||
_vl_svPutBitArrElem(d, value, 3, indx1, indx2, indx3, 0); break; }
|
||||
case 4: { int indx2=va_arg(ap,int); int indx3=va_arg(ap,int); int indx4=va_arg(ap,int);
|
||||
_vl_svPutBitArrElem(d, value, 4, indx1, indx2, indx3, indx4); break; }
|
||||
case 2: {
|
||||
int indx2 = va_arg(ap, int);
|
||||
_vl_svPutBitArrElem(d, value, 2, indx1, indx2, 0, 0);
|
||||
break;
|
||||
}
|
||||
case 3: {
|
||||
int indx2 = va_arg(ap, int);
|
||||
int indx3 = va_arg(ap, int);
|
||||
_vl_svPutBitArrElem(d, value, 3, indx1, indx2, indx3, 0);
|
||||
break;
|
||||
}
|
||||
case 4: {
|
||||
int indx2 = va_arg(ap, int);
|
||||
int indx3 = va_arg(ap, int);
|
||||
int indx4 = va_arg(ap, int);
|
||||
_vl_svPutBitArrElem(d, value, 4, indx1, indx2, indx3, indx4);
|
||||
break;
|
||||
}
|
||||
default: _vl_svPutBitArrElem(d, value, -1, 0, 0, 0, 0); break; // Will error
|
||||
}
|
||||
va_end(ap);
|
||||
|
|
@ -693,12 +752,24 @@ void svPutLogicArrElem(const svOpenArrayHandle d, svLogic value, int indx1, ...)
|
|||
va_start(ap, indx1);
|
||||
switch (varp->udims()) {
|
||||
case 1: _vl_svPutBitArrElem(d, value, 1, indx1, 0, 0, 0); break;
|
||||
case 2: { int indx2=va_arg(ap,int);
|
||||
_vl_svPutBitArrElem(d, value, 2, indx1, indx2, 0, 0); break; }
|
||||
case 3: { int indx2=va_arg(ap,int); int indx3=va_arg(ap,int);
|
||||
_vl_svPutBitArrElem(d, value, 3, indx1, indx2, indx3, 0); break; }
|
||||
case 4: { int indx2=va_arg(ap,int); int indx3=va_arg(ap,int); int indx4=va_arg(ap,int);
|
||||
_vl_svPutBitArrElem(d, value, 4, indx1, indx2, indx3, indx4); break; }
|
||||
case 2: {
|
||||
int indx2 = va_arg(ap, int);
|
||||
_vl_svPutBitArrElem(d, value, 2, indx1, indx2, 0, 0);
|
||||
break;
|
||||
}
|
||||
case 3: {
|
||||
int indx2 = va_arg(ap, int);
|
||||
int indx3 = va_arg(ap, int);
|
||||
_vl_svPutBitArrElem(d, value, 3, indx1, indx2, indx3, 0);
|
||||
break;
|
||||
}
|
||||
case 4: {
|
||||
int indx2 = va_arg(ap, int);
|
||||
int indx3 = va_arg(ap, int);
|
||||
int indx4 = va_arg(ap, int);
|
||||
_vl_svPutBitArrElem(d, value, 4, indx1, indx2, indx3, indx4);
|
||||
break;
|
||||
}
|
||||
default: _vl_svPutBitArrElem(d, value, -1, 0, 0, 0, 0); break; // Will error
|
||||
}
|
||||
va_end(ap);
|
||||
|
|
@ -707,13 +778,12 @@ void svPutLogicArrElem1(const svOpenArrayHandle d, svLogic value, int indx1) {
|
|||
// Verilator doesn't support X/Z so can just call Bit version
|
||||
svPutBitArrElem1(d, value, indx1);
|
||||
}
|
||||
void svPutLogicArrElem2(const svOpenArrayHandle d, svLogic value,
|
||||
int indx1, int indx2) {
|
||||
void svPutLogicArrElem2(const svOpenArrayHandle d, svLogic value, int indx1, int indx2) {
|
||||
// Verilator doesn't support X/Z so can just call Bit version
|
||||
svPutBitArrElem2(d, value, indx1, indx2);
|
||||
}
|
||||
void svPutLogicArrElem3(const svOpenArrayHandle d, svLogic value,
|
||||
int indx1, int indx2, int indx3) {
|
||||
void svPutLogicArrElem3(const svOpenArrayHandle d, svLogic value, int indx1, int indx2,
|
||||
int indx3) {
|
||||
// Verilator doesn't support X/Z so can just call Bit version
|
||||
svPutBitArrElem3(d, value, indx1, indx2, indx3);
|
||||
}
|
||||
|
|
@ -722,7 +792,10 @@ void svPutLogicArrElem3(const svOpenArrayHandle d, svLogic value,
|
|||
// Functions for working with DPI context
|
||||
|
||||
svScope svGetScope() {
|
||||
if (VL_UNLIKELY(!Verilated::dpiInContext())) { _VL_SVDPI_CONTEXT_WARN(); return NULL; }
|
||||
if (VL_UNLIKELY(!Verilated::dpiInContext())) {
|
||||
_VL_SVDPI_CONTEXT_WARN();
|
||||
return NULL;
|
||||
}
|
||||
// NOLINTNEXTLINE(google-readability-casting)
|
||||
return (svScope)(Verilated::dpiScope());
|
||||
}
|
||||
|
|
@ -746,16 +819,19 @@ svScope svGetScopeFromName(const char* scopeName) {
|
|||
}
|
||||
|
||||
int svPutUserData(const svScope scope, void* userKey, void* userData) {
|
||||
VerilatedImp::userInsert(scope,userKey,userData);
|
||||
VerilatedImp::userInsert(scope, userKey, userData);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void* svGetUserData(const svScope scope, void* userKey) {
|
||||
return VerilatedImp::userFind(scope,userKey);
|
||||
return VerilatedImp::userFind(scope, userKey);
|
||||
}
|
||||
|
||||
int svGetCallerInfo(const char** fileNamepp, int *lineNumberp) {
|
||||
if (VL_UNLIKELY(!Verilated::dpiInContext())) { _VL_SVDPI_CONTEXT_WARN(); return false; }
|
||||
int svGetCallerInfo(const char** fileNamepp, int* lineNumberp) {
|
||||
if (VL_UNLIKELY(!Verilated::dpiInContext())) {
|
||||
_VL_SVDPI_CONTEXT_WARN();
|
||||
return false;
|
||||
}
|
||||
if (VL_LIKELY(fileNamepp)) *fileNamepp = Verilated::dpiFilenamep(); // thread local
|
||||
if (VL_LIKELY(lineNumberp)) *lineNumberp = Verilated::dpiLineno(); // thread local
|
||||
return true;
|
||||
|
|
|
|||
|
|
@ -35,29 +35,21 @@
|
|||
/// Convert svBitVecVal to Verilator internal data
|
||||
static inline void VL_SET_W_SVBV(int obits, WDataOutP owp, const svBitVecVal* lwp) VL_MT_SAFE {
|
||||
int words = VL_WORDS_I(obits);
|
||||
for (int i = 0; i < words - 1; ++i) {
|
||||
owp[i] = lwp[i];
|
||||
}
|
||||
for (int i = 0; i < words - 1; ++i) owp[i] = lwp[i];
|
||||
owp[words - 1] = lwp[words - 1] & VL_MASK_I(obits);
|
||||
}
|
||||
static inline QData VL_SET_Q_SVBV(const svBitVecVal* lwp) VL_MT_SAFE {
|
||||
return _VL_SET_QII(lwp[1], lwp[0]);
|
||||
}
|
||||
static inline IData VL_SET_I_SVBV(const svBitVecVal* lwp) VL_MT_SAFE {
|
||||
return lwp[0];
|
||||
}
|
||||
static inline IData VL_SET_I_SVBV(const svBitVecVal* lwp) VL_MT_SAFE { return lwp[0]; }
|
||||
|
||||
/// Convert Verilator internal data to svBitVecVal
|
||||
static inline void VL_SET_SVBV_W(int obits, svBitVecVal* owp, WDataInP lwp) VL_MT_SAFE {
|
||||
int words = VL_WORDS_I(obits);
|
||||
for (int i = 0; i < words - 1; ++i) {
|
||||
owp[i] = lwp[i];
|
||||
}
|
||||
for (int i = 0; i < words - 1; ++i) owp[i] = lwp[i];
|
||||
owp[words - 1] = lwp[words - 1] & VL_MASK_I(obits);
|
||||
}
|
||||
static inline void VL_SET_SVBV_I(int, svBitVecVal* owp, IData ld) VL_MT_SAFE {
|
||||
owp[0] = ld;
|
||||
}
|
||||
static inline void VL_SET_SVBV_I(int, svBitVecVal* owp, IData ld) VL_MT_SAFE { owp[0] = ld; }
|
||||
static inline void VL_SET_SVBV_Q(int, svBitVecVal* owp, QData ld) VL_MT_SAFE {
|
||||
VL_SET_WQ(owp, ld);
|
||||
}
|
||||
|
|
@ -66,28 +58,20 @@ static inline void VL_SET_SVBV_Q(int, svBitVecVal* owp, QData ld) VL_MT_SAFE {
|
|||
/// Note these functions ignore X/Z in svLogicVecVal
|
||||
static inline void VL_SET_W_SVLV(int obits, WDataOutP owp, const svLogicVecVal* lwp) VL_MT_SAFE {
|
||||
int words = VL_WORDS_I(obits);
|
||||
for (int i = 0; i < words - 1; ++i) {
|
||||
owp[i] = lwp[i].aval;
|
||||
}
|
||||
for (int i = 0; i < words - 1; ++i) owp[i] = lwp[i].aval;
|
||||
owp[words - 1] = lwp[words - 1].aval & VL_MASK_I(obits);
|
||||
}
|
||||
static inline QData VL_SET_Q_SVLV(const svLogicVecVal* lwp) VL_MT_SAFE {
|
||||
return _VL_SET_QII(lwp[1].aval, lwp[0].aval);
|
||||
}
|
||||
static inline IData VL_SET_I_SVLV(const svLogicVecVal* lwp) VL_MT_SAFE {
|
||||
return lwp[0].aval;
|
||||
}
|
||||
static inline IData VL_SET_I_SVLV(const svLogicVecVal* lwp) VL_MT_SAFE { return lwp[0].aval; }
|
||||
|
||||
/// Convert Verilator internal data to svLogicVecVal
|
||||
/// Note these functions never create X/Z in svLogicVecVal
|
||||
static inline void VL_SET_SVLV_W(int obits, svLogicVecVal* owp, WDataInP lwp) VL_MT_SAFE {
|
||||
int words = VL_WORDS_I(obits);
|
||||
for (int i = 0; i < words; ++i) {
|
||||
owp[i].bval = 0;
|
||||
}
|
||||
for (int i = 0; i < words - 1; ++i) {
|
||||
owp[i].aval = lwp[i];
|
||||
}
|
||||
for (int i = 0; i < words; ++i) owp[i].bval = 0;
|
||||
for (int i = 0; i < words - 1; ++i) owp[i].aval = lwp[i];
|
||||
owp[words - 1].aval = lwp[words - 1] & VL_MASK_I(obits);
|
||||
}
|
||||
static inline void VL_SET_SVLV_I(int, svLogicVecVal* owp, IData ld) VL_MT_SAFE {
|
||||
|
|
|
|||
|
|
@ -379,11 +379,13 @@ template <class T_Value> std::string VL_TO_STRING(const VlQueue<T_Value>& obj) {
|
|||
// be protected by other means
|
||||
//
|
||||
|
||||
// clang-format off
|
||||
#if (defined(_MSC_VER) && _MSC_VER >= 1900) || (__cplusplus >= 201103L)
|
||||
# define VlClassRef std::shared_ptr
|
||||
#else
|
||||
# define VlClassRef VlClassRef__SystemVerilog_class_support_requires_a_C11_or_newer_compiler
|
||||
#endif
|
||||
// clang-format on
|
||||
|
||||
template <class T> // T typically of type VlClassRef<x>
|
||||
inline T VL_NULL_CHECK(T t, const char* filename, int linenum) {
|
||||
|
|
@ -412,9 +414,7 @@ inline std::string VL_CONCATN_NNN(const std::string& lhs, const std::string& rhs
|
|||
inline std::string VL_REPLICATEN_NNQ(int, int, int, const std::string& lhs, IData rep) VL_PURE {
|
||||
std::string out;
|
||||
out.reserve(lhs.length() * rep);
|
||||
for (unsigned times = 0; times < rep; ++times) {
|
||||
out += lhs;
|
||||
}
|
||||
for (unsigned times = 0; times < rep; ++times) out += lhs;
|
||||
return out;
|
||||
}
|
||||
inline std::string VL_REPLICATEN_NNI(int obits, int lbits, int rbits, const std::string& lhs,
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@
|
|||
#ifndef _VERILATED_IMP_H_
|
||||
#define _VERILATED_IMP_H_ 1 ///< Header Guard
|
||||
|
||||
// clang-format off
|
||||
#if !defined(_VERILATED_CPP_) && !defined(_VERILATED_DPI_CPP_) && !defined(_VERILATED_VPI_CPP_)
|
||||
# error "verilated_imp.h only to be included by verilated*.cpp internals"
|
||||
#endif
|
||||
|
|
@ -35,6 +36,7 @@
|
|||
# include <functional>
|
||||
# include <queue>
|
||||
#endif
|
||||
// clang-format on
|
||||
|
||||
class VerilatedScope;
|
||||
|
||||
|
|
@ -47,9 +49,11 @@ class VerilatedMsg {
|
|||
public:
|
||||
// TYPES
|
||||
struct Cmp {
|
||||
bool operator() (const VerilatedMsg& a, const VerilatedMsg& b) const {
|
||||
return a.mtaskId() < b.mtaskId(); }
|
||||
bool operator()(const VerilatedMsg& a, const VerilatedMsg& b) const {
|
||||
return a.mtaskId() < b.mtaskId();
|
||||
}
|
||||
};
|
||||
|
||||
private:
|
||||
// MEMBERS
|
||||
vluint32_t m_mtaskId; ///< MTask that did enqueue
|
||||
|
|
@ -86,6 +90,7 @@ public:
|
|||
|
||||
private:
|
||||
VL_UNCOPYABLE(VerilatedEvalMsgQueue);
|
||||
|
||||
public:
|
||||
// METHODS
|
||||
//// Add message to queue (called by producer)
|
||||
|
|
@ -122,6 +127,7 @@ public:
|
|||
/// Each thread has a local queue to build up messages until the end of the eval() call
|
||||
class VerilatedThreadMsgQueue {
|
||||
std::queue<VerilatedMsg> m_queue;
|
||||
|
||||
public:
|
||||
// CONSTRUCTORS
|
||||
VerilatedThreadMsgQueue() {}
|
||||
|
|
@ -129,6 +135,7 @@ public:
|
|||
// The only call of this with a non-empty queue is a fatal error.
|
||||
// So this does not flush the queue, as the destination queue is not known to this class.
|
||||
}
|
||||
|
||||
private:
|
||||
VL_UNCOPYABLE(VerilatedThreadMsgQueue);
|
||||
// METHODS
|
||||
|
|
@ -136,6 +143,7 @@ private:
|
|||
static VL_THREAD_LOCAL VerilatedThreadMsgQueue t_s;
|
||||
return t_s;
|
||||
}
|
||||
|
||||
public:
|
||||
/// Add message to queue, called by producer
|
||||
static void post(const VerilatedMsg& msg) VL_MT_SAFE {
|
||||
|
|
@ -176,28 +184,33 @@ class VerilatedImp {
|
|||
|
||||
// Nothing here is save-restored; users expected to re-register appropriately
|
||||
|
||||
VerilatedMutex m_argMutex; ///< Protect m_argVec, m_argVecLoaded
|
||||
ArgVec m_argVec VL_GUARDED_BY(m_argMutex); ///< Argument list (NOT save-restored, may want different results)
|
||||
bool m_argVecLoaded VL_GUARDED_BY(m_argMutex); ///< Ever loaded argument list
|
||||
VerilatedMutex m_argMutex; ///< Protect m_argVec, m_argVecLoaded
|
||||
/// Argument list (NOT save-restored, may want different results)
|
||||
ArgVec m_argVec VL_GUARDED_BY(m_argMutex);
|
||||
bool m_argVecLoaded VL_GUARDED_BY(m_argMutex); ///< Ever loaded argument list
|
||||
|
||||
VerilatedMutex m_userMapMutex; ///< Protect m_userMap
|
||||
UserMap m_userMap VL_GUARDED_BY(m_userMapMutex); ///< Map of <(scope,userkey), userData>
|
||||
VerilatedMutex m_userMapMutex; ///< Protect m_userMap
|
||||
UserMap m_userMap VL_GUARDED_BY(m_userMapMutex); ///< Map of <(scope,userkey), userData>
|
||||
|
||||
VerilatedMutex m_nameMutex; ///< Protect m_nameMap
|
||||
VerilatedScopeNameMap m_nameMap VL_GUARDED_BY(m_nameMutex); ///< Map of <scope_name, scope pointer>
|
||||
VerilatedMutex m_nameMutex; ///< Protect m_nameMap
|
||||
/// Map of <scope_name, scope pointer>
|
||||
VerilatedScopeNameMap m_nameMap VL_GUARDED_BY(m_nameMutex);
|
||||
|
||||
VerilatedMutex m_hierMapMutex; ///< Protect m_hierMap
|
||||
VerilatedHierarchyMap m_hierMap VL_GUARDED_BY(m_hierMapMutex); ///< Map the represents scope hierarchy
|
||||
VerilatedMutex m_hierMapMutex; ///< Protect m_hierMap
|
||||
/// Map the represents scope hierarchy
|
||||
VerilatedHierarchyMap m_hierMap VL_GUARDED_BY(m_hierMapMutex);
|
||||
|
||||
// Slow - somewhat static:
|
||||
VerilatedMutex m_exportMutex; ///< Protect m_nameMap
|
||||
ExportNameMap m_exportMap VL_GUARDED_BY(m_exportMutex); ///< Map of <export_func_proto, func number>
|
||||
int m_exportNext VL_GUARDED_BY(m_exportMutex); ///< Next export funcnum
|
||||
VerilatedMutex m_exportMutex; ///< Protect m_nameMap
|
||||
/// Map of <export_func_proto, func number>
|
||||
ExportNameMap m_exportMap VL_GUARDED_BY(m_exportMutex);
|
||||
int m_exportNext VL_GUARDED_BY(m_exportMutex); ///< Next export funcnum
|
||||
|
||||
// File I/O
|
||||
VerilatedMutex m_fdMutex; ///< Protect m_fdps, m_fdFree
|
||||
std::vector<FILE*> m_fdps VL_GUARDED_BY(m_fdMutex); ///< File descriptors
|
||||
std::deque<IData> m_fdFree VL_GUARDED_BY(m_fdMutex); ///< List of free descriptors (SLOW - FOPEN/CLOSE only)
|
||||
VerilatedMutex m_fdMutex; ///< Protect m_fdps, m_fdFree
|
||||
std::vector<FILE*> m_fdps VL_GUARDED_BY(m_fdMutex); ///< File descriptors
|
||||
/// List of free descriptors (SLOW - FOPEN/CLOSE only)
|
||||
std::deque<IData> m_fdFree VL_GUARDED_BY(m_fdMutex);
|
||||
|
||||
public: // But only for verilated*.cpp
|
||||
// CONSTRUCTORS
|
||||
|
|
@ -210,8 +223,10 @@ public: // But only for verilated*.cpp
|
|||
m_fdps[2] = stderr;
|
||||
}
|
||||
~VerilatedImp() {}
|
||||
|
||||
private:
|
||||
VL_UNCOPYABLE(VerilatedImp);
|
||||
|
||||
public:
|
||||
// METHODS - debug
|
||||
static void internalsDump() VL_MT_SAFE;
|
||||
|
|
@ -238,11 +253,12 @@ public:
|
|||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
private:
|
||||
static void commandArgsAddGuts(int argc, const char** argv) VL_REQUIRES(s_s.m_argMutex);
|
||||
static void commandArgVl(const std::string& arg);
|
||||
static bool commandArgVlValue(const std::string& arg,
|
||||
const std::string& prefix, std::string& valuer);
|
||||
static bool commandArgVlValue(const std::string& arg, const std::string& prefix,
|
||||
std::string& valuer);
|
||||
|
||||
public:
|
||||
// METHODS - user scope tracking
|
||||
|
|
@ -252,16 +268,19 @@ public:
|
|||
static inline void userInsert(const void* scopep, void* userKey, void* userData) VL_MT_SAFE {
|
||||
VerilatedLockGuard lock(s_s.m_userMapMutex);
|
||||
UserMap::iterator it = s_s.m_userMap.find(std::make_pair(scopep, userKey));
|
||||
if (it != s_s.m_userMap.end()) it->second = userData;
|
||||
// When we support VL_THREADs, we need a lock around this insert, as it's runtime
|
||||
else s_s.m_userMap.insert(it, std::make_pair(std::make_pair(scopep, userKey), userData));
|
||||
if (it != s_s.m_userMap.end()) {
|
||||
it->second = userData;
|
||||
} else {
|
||||
s_s.m_userMap.insert(it, std::make_pair(std::make_pair(scopep, userKey), userData));
|
||||
}
|
||||
}
|
||||
static inline void* userFind(const void* scopep, void* userKey) VL_MT_SAFE {
|
||||
VerilatedLockGuard lock(s_s.m_userMapMutex);
|
||||
UserMap::const_iterator it=s_s.m_userMap.find(std::make_pair(scopep, userKey));
|
||||
if (VL_LIKELY(it != s_s.m_userMap.end())) return it->second;
|
||||
else return NULL;
|
||||
UserMap::const_iterator it = s_s.m_userMap.find(std::make_pair(scopep, userKey));
|
||||
if (VL_UNLIKELY(it == s_s.m_userMap.end())) return NULL;
|
||||
return it->second;
|
||||
}
|
||||
|
||||
private:
|
||||
/// Symbol table destruction cleans up the entries for each scope.
|
||||
static void userEraseScope(const VerilatedScope* scopep) VL_MT_SAFE {
|
||||
|
|
@ -278,10 +297,13 @@ private:
|
|||
static void userDump() VL_MT_SAFE {
|
||||
VerilatedLockGuard lock(s_s.m_userMapMutex); // Avoid it changing in middle of dump
|
||||
bool first = true;
|
||||
for (UserMap::const_iterator it=s_s.m_userMap.begin(); it!=s_s.m_userMap.end(); ++it) {
|
||||
if (first) { VL_PRINTF_MT(" userDump:\n"); first=false; }
|
||||
VL_PRINTF_MT(" DPI_USER_DATA scope %p key %p: %p\n",
|
||||
it->first.first, it->first.second, it->second);
|
||||
for (UserMap::const_iterator it = s_s.m_userMap.begin(); it != s_s.m_userMap.end(); ++it) {
|
||||
if (first) {
|
||||
VL_PRINTF_MT(" userDump:\n");
|
||||
first = false;
|
||||
}
|
||||
VL_PRINTF_MT(" DPI_USER_DATA scope %p key %p: %p\n", it->first.first,
|
||||
it->first.second, it->second);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -298,9 +320,9 @@ public: // But only for verilated*.cpp
|
|||
static inline const VerilatedScope* scopeFind(const char* namep) VL_MT_SAFE {
|
||||
VerilatedLockGuard lock(s_s.m_nameMutex);
|
||||
// If too slow, can assume this is only VL_MT_SAFE_POSINIT
|
||||
VerilatedScopeNameMap::const_iterator it=s_s.m_nameMap.find(namep);
|
||||
if (VL_LIKELY(it != s_s.m_nameMap.end())) return it->second;
|
||||
else return NULL;
|
||||
VerilatedScopeNameMap::const_iterator it = s_s.m_nameMap.find(namep);
|
||||
if (VL_UNLIKELY(it == s_s.m_nameMap.end())) return NULL;
|
||||
return it->second;
|
||||
}
|
||||
static void scopeErase(const VerilatedScope* scopep) VL_MT_SAFE {
|
||||
// Slow ok - called once/scope at destruction
|
||||
|
|
@ -360,8 +382,8 @@ public: // But only for verilated*.cpp
|
|||
VerilatedLockGuard lock(s_s.m_exportMutex);
|
||||
ExportNameMap::const_iterator it = s_s.m_exportMap.find(namep);
|
||||
if (VL_LIKELY(it != s_s.m_exportMap.end())) return it->second;
|
||||
std::string msg = (std::string("%Error: Testbench C called ")+namep
|
||||
+" but no such DPI export function name exists in ANY model");
|
||||
std::string msg = (std::string("%Error: Testbench C called ") + namep
|
||||
+ " but no such DPI export function name exists in ANY model");
|
||||
VL_FATAL_MT("unknown", 0, "", msg.c_str());
|
||||
return -1;
|
||||
}
|
||||
|
|
@ -377,9 +399,12 @@ public: // But only for verilated*.cpp
|
|||
static void exportsDump() VL_MT_SAFE {
|
||||
VerilatedLockGuard lock(s_s.m_exportMutex);
|
||||
bool first = true;
|
||||
for (ExportNameMap::const_iterator it=s_s.m_exportMap.begin();
|
||||
it!=s_s.m_exportMap.end(); ++it) {
|
||||
if (first) { VL_PRINTF_MT(" exportDump:\n"); first=false; }
|
||||
for (ExportNameMap::const_iterator it = s_s.m_exportMap.begin();
|
||||
it != s_s.m_exportMap.end(); ++it) {
|
||||
if (first) {
|
||||
VL_PRINTF_MT(" exportDump:\n");
|
||||
first = false;
|
||||
}
|
||||
VL_PRINTF_MT(" DPI_EXPORT_NAME %05d: %s\n", it->second, it->first);
|
||||
}
|
||||
}
|
||||
|
|
@ -395,12 +420,15 @@ public: // But only for verilated*.cpp
|
|||
if (s_s.m_fdFree.empty()) {
|
||||
// Need to create more space in m_fdps and m_fdFree
|
||||
size_t start = s_s.m_fdps.size();
|
||||
s_s.m_fdps.resize(start*2);
|
||||
for (size_t i=start; i<start*2; ++i) s_s.m_fdFree.push_back(static_cast<IData>(i));
|
||||
s_s.m_fdps.resize(start * 2);
|
||||
for (size_t i = start; i < start * 2; ++i) {
|
||||
s_s.m_fdFree.push_back(static_cast<IData>(i));
|
||||
}
|
||||
}
|
||||
IData idx = s_s.m_fdFree.back(); s_s.m_fdFree.pop_back();
|
||||
IData idx = s_s.m_fdFree.back();
|
||||
s_s.m_fdFree.pop_back();
|
||||
s_s.m_fdps[idx] = fp;
|
||||
return (idx | (1UL<<31)); // bit 31 indicates not MCD
|
||||
return (idx | (1UL << 31)); // bit 31 indicates not MCD
|
||||
}
|
||||
static void fdDelete(IData fdi) VL_MT_SAFE {
|
||||
IData idx = VL_MASK_I(31) & fdi;
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@
|
|||
#include <cerrno>
|
||||
#include <fcntl.h>
|
||||
|
||||
// clang-format off
|
||||
#if defined(_WIN32) && !defined(__MINGW32__) && !defined(__CYGWIN__)
|
||||
# include <io.h>
|
||||
#else
|
||||
|
|
@ -38,6 +39,7 @@
|
|||
#ifndef O_CLOEXEC
|
||||
# define O_CLOEXEC 0
|
||||
#endif
|
||||
// clang-format on
|
||||
|
||||
// CONSTANTS
|
||||
static const char* const VLTSAVE_HEADER_STR
|
||||
|
|
@ -54,9 +56,7 @@ bool VerilatedDeserialize::readDiffers(const void* __restrict datap,
|
|||
bufferCheck();
|
||||
const vluint8_t* __restrict dp = static_cast<const vluint8_t* __restrict>(datap);
|
||||
vluint8_t miss = 0;
|
||||
while (size--) {
|
||||
miss |= (*dp++ ^ *m_cp++);
|
||||
}
|
||||
while (size--) miss |= (*dp++ ^ *m_cp++);
|
||||
return (miss != 0);
|
||||
}
|
||||
|
||||
|
|
@ -232,9 +232,7 @@ void VerilatedRestore::fill() VL_MT_UNSAFE_ONE {
|
|||
} else { // got==0, EOF
|
||||
// Fill buffer from here to end with NULLs so reader's don't
|
||||
// need to check eof each character.
|
||||
while (m_endp < m_bufp + bufferSize()) {
|
||||
*m_endp++ = '\0';
|
||||
}
|
||||
while (m_endp < m_bufp + bufferSize()) *m_endp++ = '\0';
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -132,7 +132,7 @@ public:
|
|||
size_t blk = size;
|
||||
if (blk > bufferInsertSize()) blk = bufferInsertSize();
|
||||
const vluint8_t* __restrict maxp = dp + blk;
|
||||
for (; dp < maxp; *dp++ = *m_cp++);
|
||||
for (; dp < maxp; *dp++ = *m_cp++) {}
|
||||
size -= blk;
|
||||
}
|
||||
return *this; // For function chaining
|
||||
|
|
@ -257,8 +257,8 @@ VerilatedSerialize& operator<<(VerilatedSerialize& os, VlAssocArray<T_Key, T_Val
|
|||
os << rhs.atDefault();
|
||||
vluint32_t len = rhs.size();
|
||||
os << len;
|
||||
for (typename VlAssocArray<T_Key, T_Value>::const_iterator it = rhs.begin();
|
||||
it != rhs.end(); ++it) {
|
||||
for (typename VlAssocArray<T_Key, T_Value>::const_iterator it = rhs.begin(); it != rhs.end();
|
||||
++it) {
|
||||
T_Key index = it->first; // Copy to get around const_iterator
|
||||
T_Value value = it->second;
|
||||
os << index << value;
|
||||
|
|
|
|||
|
|
@ -41,8 +41,12 @@ class VerilatedRange {
|
|||
protected:
|
||||
friend class VerilatedVarProps;
|
||||
friend class VerilatedScope;
|
||||
VerilatedRange() : m_left(0), m_right(0) {}
|
||||
VerilatedRange(int left, int right) : m_left(left), m_right(right) {}
|
||||
VerilatedRange()
|
||||
: m_left(0)
|
||||
, m_right(0) {}
|
||||
VerilatedRange(int left, int right)
|
||||
: m_left(left)
|
||||
, m_right(right) {}
|
||||
void init(int left, int right) {
|
||||
m_left = left;
|
||||
m_right = right;
|
||||
|
|
@ -78,63 +82,89 @@ class VerilatedVarProps {
|
|||
// CONSTRUCTORS
|
||||
protected:
|
||||
friend class VerilatedScope;
|
||||
VerilatedVarProps(VerilatedVarType vltype, VerilatedVarFlags vlflags,
|
||||
int pdims, int udims)
|
||||
: m_magic(MAGIC), m_vltype(vltype), m_vlflags(vlflags), m_pdims(pdims), m_udims(udims) {}
|
||||
VerilatedVarProps(VerilatedVarType vltype, VerilatedVarFlags vlflags, int pdims, int udims)
|
||||
: m_magic(MAGIC)
|
||||
, m_vltype(vltype)
|
||||
, m_vlflags(vlflags)
|
||||
, m_pdims(pdims)
|
||||
, m_udims(udims) {}
|
||||
|
||||
public:
|
||||
class Unpacked {};
|
||||
// Without packed
|
||||
VerilatedVarProps(VerilatedVarType vltype, int vlflags)
|
||||
: m_magic(MAGIC), m_vltype(vltype),
|
||||
m_vlflags(VerilatedVarFlags(vlflags)), m_pdims(0), m_udims(0) {}
|
||||
VerilatedVarProps(VerilatedVarType vltype, int vlflags,
|
||||
Unpacked, int u0l, int u0r)
|
||||
: m_magic(MAGIC), m_vltype(vltype),
|
||||
m_vlflags(VerilatedVarFlags(vlflags)), m_pdims(0), m_udims(1) {
|
||||
: m_magic(MAGIC)
|
||||
, m_vltype(vltype)
|
||||
, m_vlflags(VerilatedVarFlags(vlflags))
|
||||
, m_pdims(0)
|
||||
, m_udims(0) {}
|
||||
VerilatedVarProps(VerilatedVarType vltype, int vlflags, Unpacked, int u0l, int u0r)
|
||||
: m_magic(MAGIC)
|
||||
, m_vltype(vltype)
|
||||
, m_vlflags(VerilatedVarFlags(vlflags))
|
||||
, m_pdims(0)
|
||||
, m_udims(1) {
|
||||
m_unpacked[0].init(u0l, u0r);
|
||||
}
|
||||
VerilatedVarProps(VerilatedVarType vltype, int vlflags,
|
||||
Unpacked, int u0l, int u0r, int u1l, int u1r)
|
||||
: m_magic(MAGIC), m_vltype(vltype),
|
||||
m_vlflags(VerilatedVarFlags(vlflags)), m_pdims(0), m_udims(2) {
|
||||
VerilatedVarProps(VerilatedVarType vltype, int vlflags, Unpacked, int u0l, int u0r, int u1l,
|
||||
int u1r)
|
||||
: m_magic(MAGIC)
|
||||
, m_vltype(vltype)
|
||||
, m_vlflags(VerilatedVarFlags(vlflags))
|
||||
, m_pdims(0)
|
||||
, m_udims(2) {
|
||||
m_unpacked[0].init(u0l, u0r);
|
||||
m_unpacked[1].init(u1l, u1r);
|
||||
}
|
||||
VerilatedVarProps(VerilatedVarType vltype, int vlflags,
|
||||
Unpacked, int u0l, int u0r, int u1l, int u1r, int u2l, int u2r)
|
||||
: m_magic(MAGIC), m_vltype(vltype),
|
||||
m_vlflags(VerilatedVarFlags(vlflags)), m_pdims(0), m_udims(3) {
|
||||
VerilatedVarProps(VerilatedVarType vltype, int vlflags, Unpacked, int u0l, int u0r, int u1l,
|
||||
int u1r, int u2l, int u2r)
|
||||
: m_magic(MAGIC)
|
||||
, m_vltype(vltype)
|
||||
, m_vlflags(VerilatedVarFlags(vlflags))
|
||||
, m_pdims(0)
|
||||
, m_udims(3) {
|
||||
m_unpacked[0].init(u0l, u0r);
|
||||
m_unpacked[1].init(u1l, u1r);
|
||||
m_unpacked[2].init(u2l, u2r);
|
||||
}
|
||||
// With packed
|
||||
class Packed {};
|
||||
VerilatedVarProps(VerilatedVarType vltype, int vlflags,
|
||||
Packed, int pl, int pr)
|
||||
: m_magic(MAGIC), m_vltype(vltype),
|
||||
m_vlflags(VerilatedVarFlags(vlflags)), m_pdims(1), m_udims(0), m_packed(pl,pr) {}
|
||||
VerilatedVarProps(VerilatedVarType vltype, int vlflags,
|
||||
Packed, int pl, int pr,
|
||||
Unpacked, int u0l, int u0r)
|
||||
: m_magic(MAGIC), m_vltype(vltype),
|
||||
m_vlflags(VerilatedVarFlags(vlflags)), m_pdims(1), m_udims(1), m_packed(pl,pr) {
|
||||
VerilatedVarProps(VerilatedVarType vltype, int vlflags, Packed, int pl, int pr)
|
||||
: m_magic(MAGIC)
|
||||
, m_vltype(vltype)
|
||||
, m_vlflags(VerilatedVarFlags(vlflags))
|
||||
, m_pdims(1)
|
||||
, m_udims(0)
|
||||
, m_packed(pl, pr) {}
|
||||
VerilatedVarProps(VerilatedVarType vltype, int vlflags, Packed, int pl, int pr, Unpacked,
|
||||
int u0l, int u0r)
|
||||
: m_magic(MAGIC)
|
||||
, m_vltype(vltype)
|
||||
, m_vlflags(VerilatedVarFlags(vlflags))
|
||||
, m_pdims(1)
|
||||
, m_udims(1)
|
||||
, m_packed(pl, pr) {
|
||||
m_unpacked[0].init(u0l, u0r);
|
||||
}
|
||||
VerilatedVarProps(VerilatedVarType vltype, int vlflags,
|
||||
Packed, int pl, int pr,
|
||||
Unpacked, int u0l, int u0r, int u1l, int u1r)
|
||||
: m_magic(MAGIC), m_vltype(vltype), m_vlflags(VerilatedVarFlags(vlflags)),
|
||||
m_pdims(1), m_udims(2), m_packed(pl,pr) {
|
||||
VerilatedVarProps(VerilatedVarType vltype, int vlflags, Packed, int pl, int pr, Unpacked,
|
||||
int u0l, int u0r, int u1l, int u1r)
|
||||
: m_magic(MAGIC)
|
||||
, m_vltype(vltype)
|
||||
, m_vlflags(VerilatedVarFlags(vlflags))
|
||||
, m_pdims(1)
|
||||
, m_udims(2)
|
||||
, m_packed(pl, pr) {
|
||||
m_unpacked[0].init(u0l, u0r);
|
||||
m_unpacked[1].init(u1l, u1r);
|
||||
}
|
||||
VerilatedVarProps(VerilatedVarType vltype, int vlflags,
|
||||
Packed, int pl, int pr,
|
||||
Unpacked, int u0l, int u0r, int u1l, int u1r, int u2l, int u2r)
|
||||
: m_magic(MAGIC), m_vltype(vltype),
|
||||
m_vlflags(VerilatedVarFlags(vlflags)), m_pdims(1), m_udims(3), m_packed(pl,pr) {
|
||||
VerilatedVarProps(VerilatedVarType vltype, int vlflags, Packed, int pl, int pr, Unpacked,
|
||||
int u0l, int u0r, int u1l, int u1r, int u2l, int u2r)
|
||||
: m_magic(MAGIC)
|
||||
, m_vltype(vltype)
|
||||
, m_vlflags(VerilatedVarFlags(vlflags))
|
||||
, m_pdims(1)
|
||||
, m_udims(3)
|
||||
, m_packed(pl, pr) {
|
||||
m_unpacked[0].init(u0l, u0r);
|
||||
m_unpacked[1].init(u1l, u1r);
|
||||
m_unpacked[2].init(u2l, u2r);
|
||||
|
|
|
|||
|
|
@ -61,8 +61,7 @@ void VlWorkerThread::workerLoop() {
|
|||
if (VL_LIKELY(!work.m_fnp)) dequeWork(&work);
|
||||
|
||||
// Do this here, not above, to avoid a race with the destructor.
|
||||
if (VL_UNLIKELY(m_exiting.load(std::memory_order_acquire)))
|
||||
break;
|
||||
if (VL_UNLIKELY(m_exiting.load(std::memory_order_acquire))) break;
|
||||
|
||||
if (VL_LIKELY(work.m_fnp)) {
|
||||
work.m_fnp(work.m_evenCycle, work.m_sym);
|
||||
|
|
@ -128,8 +127,7 @@ void VlThreadPool::setupProfilingClientThread() {
|
|||
|
||||
void VlThreadPool::profileAppendAll(const VlProfileRec& rec) {
|
||||
VerilatedLockGuard lk(m_mutex);
|
||||
for (ProfileSet::iterator it = m_allProfiles.begin();
|
||||
it != m_allProfiles.end(); ++it) {
|
||||
for (ProfileSet::iterator it = m_allProfiles.begin(); it != m_allProfiles.end(); ++it) {
|
||||
// Every thread's profile trace gets a copy of rec.
|
||||
(*it)->emplace_back(rec);
|
||||
}
|
||||
|
|
@ -156,14 +154,14 @@ void VlThreadPool::profileDump(const char* filenamep, vluint64_t ticksElapsed) {
|
|||
fprintf(fp, "VLPROF stat yields %" VL_PRI64 "u\n", VlMTaskVertex::yields());
|
||||
|
||||
vluint32_t thread_id = 0;
|
||||
for (ProfileSet::const_iterator pit = m_allProfiles.begin();
|
||||
pit != m_allProfiles.end(); ++pit) {
|
||||
for (ProfileSet::const_iterator pit = m_allProfiles.begin(); pit != m_allProfiles.end();
|
||||
++pit) {
|
||||
++thread_id;
|
||||
|
||||
bool printing = false; // False while in warmup phase
|
||||
for (ProfileTrace::const_iterator eit = (*pit)->begin(); eit != (*pit)->end(); ++eit) {
|
||||
switch (eit->m_type) {
|
||||
case VlProfileRec::TYPE_BARRIER:
|
||||
case VlProfileRec::TYPE_BARRIER: //
|
||||
printing = true;
|
||||
break;
|
||||
case VlProfileRec::TYPE_MTASK_RUN:
|
||||
|
|
|
|||
|
|
@ -25,12 +25,15 @@
|
|||
#include <condition_variable>
|
||||
#include <set>
|
||||
#include <vector>
|
||||
|
||||
// clang-format off
|
||||
#if defined(__linux)
|
||||
#include <sched.h> // For sched_getcpu()
|
||||
# include <sched.h> // For sched_getcpu()
|
||||
#endif
|
||||
#if defined(__APPLE__)
|
||||
# include <cpuid.h> // For __cpuid_count()
|
||||
#endif
|
||||
// clang-format on
|
||||
|
||||
// VlMTaskVertex and VlThreadpool will work with multiple symbol table types.
|
||||
// Since the type is opaque to VlMTaskVertex and VlThreadPool, represent it
|
||||
|
|
@ -115,10 +118,7 @@ public:
|
|||
class VlProfileRec {
|
||||
protected:
|
||||
friend class VlThreadPool;
|
||||
enum VlProfileE {
|
||||
TYPE_MTASK_RUN,
|
||||
TYPE_BARRIER
|
||||
};
|
||||
enum VlProfileE { TYPE_MTASK_RUN, TYPE_BARRIER };
|
||||
VlProfileE m_type; // Record type
|
||||
vluint32_t m_mtaskId; // Mtask we're logging
|
||||
vluint32_t m_predictTime; // How long scheduler predicted would take
|
||||
|
|
@ -173,9 +173,14 @@ private:
|
|||
VlExecFnp m_fnp; // Function to execute
|
||||
VlThrSymTab m_sym; // Symbol table to execute
|
||||
bool m_evenCycle; // Even/odd for flag alternation
|
||||
ExecRec() : m_fnp(NULL), m_sym(NULL), m_evenCycle(false) {}
|
||||
ExecRec()
|
||||
: m_fnp(NULL)
|
||||
, m_sym(NULL)
|
||||
, m_evenCycle(false) {}
|
||||
ExecRec(VlExecFnp fnp, bool evenCycle, VlThrSymTab sym)
|
||||
: m_fnp(fnp), m_sym(sym), m_evenCycle(evenCycle) {}
|
||||
: m_fnp(fnp)
|
||||
, m_sym(sym)
|
||||
, m_evenCycle(evenCycle) {}
|
||||
};
|
||||
|
||||
// MEMBERS
|
||||
|
|
@ -208,7 +213,7 @@ public:
|
|||
inline void dequeWork(ExecRec* workp) {
|
||||
// Spin for a while, waiting for new data
|
||||
for (int i = 0; i < VL_LOCK_SPINS; ++i) {
|
||||
if (VL_LIKELY(m_ready_size.load(std::memory_order_relaxed))) {
|
||||
if (VL_LIKELY(m_ready_size.load(std::memory_order_relaxed))) { //
|
||||
break;
|
||||
}
|
||||
VL_CPU_RELAX();
|
||||
|
|
|
|||
|
|
@ -41,13 +41,9 @@
|
|||
#include <string>
|
||||
|
||||
// Abstract 'vl_hash' and 'vl_equal_to' templates.
|
||||
template <typename T> struct vl_hash {
|
||||
size_t operator()(const T& k) const;
|
||||
};
|
||||
template <typename T> struct vl_hash { size_t operator()(const T& k) const; };
|
||||
|
||||
template <typename T> struct vl_equal_to {
|
||||
bool operator()(const T& a, const T& b) const;
|
||||
};
|
||||
template <typename T> struct vl_equal_to { bool operator()(const T& a, const T& b) const; };
|
||||
|
||||
// Specializations of 'vl_hash' and 'vl_equal_to'.
|
||||
inline size_t vl_hash_bytes(const void* vbufp, size_t nbytes) {
|
||||
|
|
@ -59,60 +55,50 @@ inline size_t vl_hash_bytes(const void* vbufp, size_t nbytes) {
|
|||
return hash;
|
||||
}
|
||||
|
||||
template <> inline size_t
|
||||
vl_hash<unsigned int>::operator()(const unsigned int& k) const {
|
||||
template <> inline size_t vl_hash<unsigned int>::operator()(const unsigned int& k) const {
|
||||
return k;
|
||||
}
|
||||
|
||||
template <> inline bool
|
||||
vl_equal_to<unsigned int>::operator()(const unsigned int& a,
|
||||
const unsigned int& b) const {
|
||||
template <>
|
||||
inline bool vl_equal_to<unsigned int>::operator()(const unsigned int& a,
|
||||
const unsigned int& b) const {
|
||||
return a == b;
|
||||
}
|
||||
|
||||
template <> inline size_t
|
||||
vl_hash<std::string>::operator()(const std::string& k) const {
|
||||
template <> inline size_t vl_hash<std::string>::operator()(const std::string& k) const {
|
||||
return vl_hash_bytes(k.data(), k.size());
|
||||
}
|
||||
|
||||
template <> inline bool
|
||||
vl_equal_to<std::string>::operator()(const std::string& a,
|
||||
const std::string& b) const {
|
||||
template <>
|
||||
inline bool vl_equal_to<std::string>::operator()(const std::string& a,
|
||||
const std::string& b) const {
|
||||
// Don't scan the strings if the sizes are different.
|
||||
if (a.size() != b.size()) {
|
||||
return false;
|
||||
}
|
||||
if (a.size() != b.size()) return false;
|
||||
return (0 == a.compare(b)); // Must scan.
|
||||
}
|
||||
|
||||
template <typename T> struct vl_hash<T*> {
|
||||
size_t operator()(T* kp) const {
|
||||
return ((sizeof(size_t) == sizeof(kp))
|
||||
? reinterpret_cast<size_t>(kp)
|
||||
: vl_hash_bytes(&kp, sizeof(kp)));
|
||||
return ((sizeof(size_t) == sizeof(kp)) ? reinterpret_cast<size_t>(kp)
|
||||
: vl_hash_bytes(&kp, sizeof(kp)));
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T> struct vl_equal_to<T*> {
|
||||
bool operator()(T* ap, T* bp) const {
|
||||
return ap == bp;
|
||||
}
|
||||
bool operator()(T* ap, T* bp) const { return ap == bp; }
|
||||
};
|
||||
|
||||
//===================================================================
|
||||
//
|
||||
/// Functional clone of the std::unordered_set hash table.
|
||||
template <class T_Key,
|
||||
class T_Hash = vl_hash<T_Key>,
|
||||
class T_Equal = vl_equal_to<T_Key> >
|
||||
template <class T_Key, class T_Hash = vl_hash<T_Key>, class T_Equal = vl_equal_to<T_Key> >
|
||||
class vl_unordered_set {
|
||||
public:
|
||||
// TYPES
|
||||
typedef std::list<T_Key> Bucket;
|
||||
enum RehashType { GROW, SHRINK };
|
||||
|
||||
template <class KK, class VV,
|
||||
class HH, class EQ> friend class vl_unordered_map;
|
||||
template <class KK, class VV, class HH, class EQ> friend class vl_unordered_map;
|
||||
|
||||
class iterator {
|
||||
protected:
|
||||
|
|
@ -123,29 +109,23 @@ public:
|
|||
|
||||
public:
|
||||
// CONSTRUCTORS
|
||||
iterator(size_t bucketIdx, typename Bucket::iterator bit,
|
||||
const vl_unordered_set* setp)
|
||||
: m_bucketIdx(bucketIdx), m_bit(bit), m_setp(setp) {}
|
||||
iterator(size_t bucketIdx, typename Bucket::iterator bit, const vl_unordered_set* setp)
|
||||
: m_bucketIdx(bucketIdx)
|
||||
, m_bit(bit)
|
||||
, m_setp(setp) {}
|
||||
|
||||
// METHODS
|
||||
const T_Key& operator*() const {
|
||||
return *m_bit;
|
||||
}
|
||||
const T_Key& operator*() const { return *m_bit; }
|
||||
// This should really be 'const T_Key*' type for unordered_set,
|
||||
// however this iterator is shared with unordered_map whose
|
||||
// operator-> returns a non-const ValueType*, so keep this
|
||||
// non-const to avoid having to define a whole separate iterator
|
||||
// for unordered_map.
|
||||
T_Key* operator->() const {
|
||||
return &(*m_bit);
|
||||
}
|
||||
T_Key* operator->() const { return &(*m_bit); }
|
||||
bool operator==(const iterator& other) const {
|
||||
return ((m_bucketIdx == other.m_bucketIdx)
|
||||
&& (m_bit == other.m_bit));
|
||||
}
|
||||
bool operator!=(const iterator& other) const {
|
||||
return (!this->operator==(other));
|
||||
return ((m_bucketIdx == other.m_bucketIdx) && (m_bit == other.m_bit));
|
||||
}
|
||||
bool operator!=(const iterator& other) const { return (!this->operator==(other)); }
|
||||
void advanceUntilValid() {
|
||||
while (true) {
|
||||
if (m_bit != m_setp->m_bucketsp[m_bucketIdx].end()) {
|
||||
|
|
@ -176,14 +156,14 @@ public:
|
|||
|
||||
private:
|
||||
// MEMBERS
|
||||
size_t m_numElements; // Number of entries present.
|
||||
size_t m_log2Buckets; // Log-base-2 of the number of buckets.
|
||||
mutable Bucket* m_bucketsp; // Hash table buckets. May be NULL;
|
||||
size_t m_numElements; // Number of entries present.
|
||||
size_t m_log2Buckets; // Log-base-2 of the number of buckets.
|
||||
mutable Bucket* m_bucketsp; // Hash table buckets. May be NULL;
|
||||
// // we'll allocate it on the fly when
|
||||
// // the first entries are created.
|
||||
Bucket m_emptyBucket; // A fake bucket, used to construct end().
|
||||
T_Hash m_hash; // Hash function provider.
|
||||
T_Equal m_equal; // Equal-to function provider.
|
||||
Bucket m_emptyBucket; // A fake bucket, used to construct end().
|
||||
T_Hash m_hash; // Hash function provider.
|
||||
T_Equal m_equal; // Equal-to function provider.
|
||||
|
||||
public:
|
||||
// CONSTRUCTORS
|
||||
|
|
@ -202,26 +182,20 @@ public:
|
|||
, m_equal() {
|
||||
if (other.m_bucketsp) {
|
||||
m_bucketsp = new Bucket[numBuckets()];
|
||||
for (size_t i = 0; i < numBuckets(); i++) {
|
||||
m_bucketsp[i] = other.m_bucketsp[i];
|
||||
}
|
||||
for (size_t i = 0; i < numBuckets(); i++) m_bucketsp[i] = other.m_bucketsp[i];
|
||||
}
|
||||
}
|
||||
~vl_unordered_set() {
|
||||
VL_DO_DANGLING(delete [] m_bucketsp, m_bucketsp);
|
||||
}
|
||||
~vl_unordered_set() { VL_DO_DANGLING(delete[] m_bucketsp, m_bucketsp); }
|
||||
|
||||
vl_unordered_set& operator=(const vl_unordered_set& other) {
|
||||
if (this != &other) {
|
||||
clear();
|
||||
delete [] m_bucketsp;
|
||||
delete[] m_bucketsp;
|
||||
m_numElements = other.m_numElements;
|
||||
m_log2Buckets = other.m_log2Buckets;
|
||||
if (other.m_bucketsp) {
|
||||
m_bucketsp = new Bucket[numBuckets()];
|
||||
for (size_t i = 0; i < numBuckets(); i++) {
|
||||
m_bucketsp[i] = other.m_bucketsp[i];
|
||||
}
|
||||
for (size_t i = 0; i < numBuckets(); i++) m_bucketsp[i] = other.m_bucketsp[i];
|
||||
} else {
|
||||
m_bucketsp = NULL;
|
||||
}
|
||||
|
|
@ -251,24 +225,21 @@ public:
|
|||
return end();
|
||||
}
|
||||
const_iterator end() const {
|
||||
return iterator(VL_ULL(0xFFFFFFFFFFFFFFFF),
|
||||
const_cast<Bucket&>(m_emptyBucket).begin(), this);
|
||||
return iterator(VL_ULL(0xFFFFFFFFFFFFFFFF), const_cast<Bucket&>(m_emptyBucket).begin(),
|
||||
this);
|
||||
}
|
||||
|
||||
bool empty() const { return m_numElements == 0; }
|
||||
|
||||
size_t size() const { return m_numElements; }
|
||||
|
||||
size_t count(const T_Key& key) const {
|
||||
return (find(key) == end()) ? 0 : 1;
|
||||
}
|
||||
size_t count(const T_Key& key) const { return (find(key) == end()) ? 0 : 1; }
|
||||
|
||||
size_t hashToBucket(size_t hashVal) const {
|
||||
return hashToBucket(hashVal, m_log2Buckets);
|
||||
}
|
||||
size_t hashToBucket(size_t hashVal) const { return hashToBucket(hashVal, m_log2Buckets); }
|
||||
static size_t hashToBucket(size_t hashVal, unsigned log2Buckets) {
|
||||
// Fibonacci hashing
|
||||
// See https://probablydance.com/2018/06/16/fibonacci-hashing-the-optimization-that-the-world-forgot-or-a-better-alternative-to-integer-modulo/
|
||||
// Fibonacci hashing, see
|
||||
// https://probablydance.com/2018/06/16/fibonacci-hashing-the-optimization
|
||||
// -that-the-world-forgot-or-a-better-alternative-to-integer-modulo/
|
||||
//
|
||||
// * The magic numbers below are UINT_MAX/phi where phi is the
|
||||
// golden ratio number (1.618...) for either 64- or 32-bit
|
||||
|
|
@ -278,11 +249,9 @@ public:
|
|||
// function further. This permits the use of very fast client
|
||||
// hash funcs (like just returning the int or pointer value as
|
||||
// is!) and tolerates crappy client hash functions pretty well.
|
||||
size_t mult = hashVal * ((sizeof(size_t) == 8)
|
||||
? VL_ULL(11400714819323198485)
|
||||
: 2654435769lu);
|
||||
size_t result = (mult >> (((sizeof(size_t) == 8)
|
||||
? 64 : 32) - log2Buckets));
|
||||
size_t mult
|
||||
= hashVal * ((sizeof(size_t) == 8) ? VL_ULL(11400714819323198485) : 2654435769lu);
|
||||
size_t result = (mult >> (((sizeof(size_t) == 8) ? 64 : 32) - log2Buckets));
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
@ -292,19 +261,15 @@ public:
|
|||
initBuckets();
|
||||
Bucket* bucketp = &m_bucketsp[bucketIdxOut];
|
||||
|
||||
for (typename Bucket::iterator it = bucketp->begin();
|
||||
it != bucketp->end(); ++it) {
|
||||
if (m_equal.operator()(*it, key)) {
|
||||
return iterator(bucketIdxOut, it, this);
|
||||
}
|
||||
for (typename Bucket::iterator it = bucketp->begin(); it != bucketp->end(); ++it) {
|
||||
if (m_equal.operator()(*it, key)) return iterator(bucketIdxOut, it, this);
|
||||
}
|
||||
return end();
|
||||
}
|
||||
|
||||
const_iterator find(const T_Key& key) const {
|
||||
size_t bucketIdx;
|
||||
return const_cast<vl_unordered_set*>(this)->find_internal(key,
|
||||
bucketIdx);
|
||||
return const_cast<vl_unordered_set*>(this)->find_internal(key, bucketIdx);
|
||||
}
|
||||
|
||||
iterator find(const T_Key& key) {
|
||||
|
|
@ -358,9 +323,7 @@ public:
|
|||
// for the Scoreboard in V3Partition, which begins tracking
|
||||
// a huge number of vertices and then tracks a successively
|
||||
// smaller number over time.
|
||||
if (needToRehash(SHRINK)) {
|
||||
rehash(SHRINK);
|
||||
}
|
||||
if (needToRehash(SHRINK)) rehash(SHRINK);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
|
|
@ -419,8 +382,7 @@ private:
|
|||
size_t new_idx = hashToBucket(hash, new_log2Buckets);
|
||||
// Avoid mallocing one list elem and freeing another;
|
||||
// splice just moves it over.
|
||||
new_bucketsp[new_idx].splice(new_bucketsp[new_idx].begin(),
|
||||
m_bucketsp[i], bit);
|
||||
new_bucketsp[new_idx].splice(new_bucketsp[new_idx].begin(), m_bucketsp[i], bit);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -433,9 +395,7 @@ private:
|
|||
//===================================================================
|
||||
//
|
||||
/// Functional clone of the std::unordered_map hash table.
|
||||
template <class T_Key,
|
||||
class T_Value,
|
||||
class T_Hash = vl_hash<T_Key>,
|
||||
template <class T_Key, class T_Value, class T_Hash = vl_hash<T_Key>,
|
||||
class T_Equal = vl_equal_to<T_Key> >
|
||||
class vl_unordered_map {
|
||||
private:
|
||||
|
|
@ -445,6 +405,7 @@ private:
|
|||
class KeyHash {
|
||||
private:
|
||||
T_Hash key_hash;
|
||||
|
||||
public:
|
||||
KeyHash() {}
|
||||
size_t operator()(const KeyValPair& kv_pair) const {
|
||||
|
|
@ -455,6 +416,7 @@ private:
|
|||
class KeyEqual {
|
||||
private:
|
||||
T_Equal key_eq;
|
||||
|
||||
public:
|
||||
KeyEqual() {}
|
||||
bool operator()(const KeyValPair& kv_a, const KeyValPair& kv_b) const {
|
||||
|
|
@ -491,24 +453,19 @@ public:
|
|||
size_t bucketIdxOut = m_set.hashToBucket(hash);
|
||||
typename MapSet::Bucket* bucketp = m_set.getBucket(bucketIdxOut);
|
||||
|
||||
for (typename MapSet::Bucket::iterator it = bucketp->begin();
|
||||
it != bucketp->end(); ++it) {
|
||||
if (mapEq.operator()(it->first, k)) {
|
||||
return iterator(bucketIdxOut, it, &m_set);
|
||||
}
|
||||
for (typename MapSet::Bucket::iterator it = bucketp->begin(); it != bucketp->end(); ++it) {
|
||||
if (mapEq.operator()(it->first, k)) return iterator(bucketIdxOut, it, &m_set);
|
||||
}
|
||||
return end();
|
||||
}
|
||||
const_iterator find(const T_Key& k) const {
|
||||
return const_cast<vl_unordered_map*>(this)->find(k);
|
||||
}
|
||||
std::pair<iterator, bool> insert(const KeyValPair& val) {
|
||||
return m_set.insert(val);
|
||||
}
|
||||
std::pair<iterator, bool> insert(const KeyValPair& val) { return m_set.insert(val); }
|
||||
iterator erase(iterator it) { return m_set.erase(it); }
|
||||
size_t erase(const T_Key& k) {
|
||||
iterator it = find(k);
|
||||
if (it == end()) { return 0; }
|
||||
if (it == end()) return 0;
|
||||
m_set.erase(it);
|
||||
return 1;
|
||||
}
|
||||
|
|
@ -517,9 +474,7 @@ public:
|
|||
// std::unordered_map::operator[] relies on it too.
|
||||
KeyValPair dummy = std::make_pair(k, T_Value());
|
||||
iterator it = m_set.find(dummy);
|
||||
if (it == m_set.end()) {
|
||||
it = m_set.insert(dummy).first;
|
||||
}
|
||||
if (it == m_set.end()) it = m_set.insert(dummy).first;
|
||||
// For the 'set', it's generally not safe to modify
|
||||
// the value after deref. For the 'map' though, we know
|
||||
// it's safe to modify the value field and we can allow it:
|
||||
|
|
|
|||
|
|
@ -25,21 +25,22 @@
|
|||
//======================================================================
|
||||
|
||||
//--------------------------------------------------
|
||||
#if (SYSTEMC_VERSION>=20050714)
|
||||
// SystemC 2.1.v1
|
||||
#if (SYSTEMC_VERSION >= 20050714)
|
||||
// SystemC 2.1.v1
|
||||
// cppcheck-suppress unusedFunction
|
||||
void VerilatedVcdSc::write_comment(const std::string &) {}
|
||||
void VerilatedVcdSc::trace(const unsigned int &, const std::string &, const char**) {}
|
||||
void VerilatedVcdSc::write_comment(const std::string&) {}
|
||||
void VerilatedVcdSc::trace(const unsigned int&, const std::string&, const char**) {}
|
||||
|
||||
// clang-format off
|
||||
# define DECL_TRACE_METHOD_A(tp) \
|
||||
void VerilatedVcdSc::trace( const tp& object, const std::string& name ) {}
|
||||
void VerilatedVcdSc::trace(const tp& object, const std::string& name) {}
|
||||
# define DECL_TRACE_METHOD_B(tp) \
|
||||
void VerilatedVcdSc::trace( const tp& object, const std::string& name, int width ) {}
|
||||
void VerilatedVcdSc::trace(const tp& object, const std::string& name, int width) {}
|
||||
|
||||
#if (SYSTEMC_VERSION>=20171012)
|
||||
# if (SYSTEMC_VERSION >= 20171012)
|
||||
DECL_TRACE_METHOD_A( sc_event )
|
||||
DECL_TRACE_METHOD_A( sc_time )
|
||||
#endif
|
||||
# endif
|
||||
|
||||
DECL_TRACE_METHOD_A( bool )
|
||||
DECL_TRACE_METHOD_A( sc_dt::sc_bit )
|
||||
|
|
@ -49,9 +50,9 @@ void VerilatedVcdSc::trace(const unsigned int &, const std::string &, const char
|
|||
DECL_TRACE_METHOD_B( unsigned short )
|
||||
DECL_TRACE_METHOD_B( unsigned int )
|
||||
DECL_TRACE_METHOD_B( unsigned long )
|
||||
#ifdef SYSTEMC_64BIT_PATCHES
|
||||
# ifdef SYSTEMC_64BIT_PATCHES
|
||||
DECL_TRACE_METHOD_B( unsigned long long)
|
||||
#endif
|
||||
# endif
|
||||
DECL_TRACE_METHOD_B( char )
|
||||
DECL_TRACE_METHOD_B( short )
|
||||
DECL_TRACE_METHOD_B( int )
|
||||
|
|
@ -73,19 +74,21 @@ void VerilatedVcdSc::trace(const unsigned int &, const std::string &, const char
|
|||
|
||||
DECL_TRACE_METHOD_A( sc_dt::sc_bv_base )
|
||||
DECL_TRACE_METHOD_A( sc_dt::sc_lv_base )
|
||||
// clang-format on
|
||||
|
||||
//--------------------------------------------------
|
||||
#elif (SYSTEMC_VERSION>20011000)
|
||||
// SystemC 2.0.1
|
||||
#elif (SYSTEMC_VERSION > 20011000)
|
||||
// SystemC 2.0.1
|
||||
// cppcheck-suppress unusedFunction
|
||||
void VerilatedVcdSc::write_comment(const sc_string &) {}
|
||||
void VerilatedVcdSc::write_comment(const sc_string&) {}
|
||||
void VerilatedVcdSc::trace(const unsigned int&, const sc_string&, const char**) {}
|
||||
|
||||
#define DECL_TRACE_METHOD_A(tp) \
|
||||
void VerilatedVcdSc::trace( const tp& object, const sc_string& name ) {}
|
||||
void VerilatedVcdSc::trace(const tp& object, const sc_string& name) {}
|
||||
#define DECL_TRACE_METHOD_B(tp) \
|
||||
void VerilatedVcdSc::trace( const tp& object, const sc_string& name, int width ) {}
|
||||
void VerilatedVcdSc::trace(const tp& object, const sc_string& name, int width) {}
|
||||
|
||||
// clang-format off
|
||||
DECL_TRACE_METHOD_A( bool )
|
||||
DECL_TRACE_METHOD_A( sc_bit )
|
||||
DECL_TRACE_METHOD_A( sc_logic )
|
||||
|
|
@ -96,7 +99,7 @@ void VerilatedVcdSc::trace(const unsigned int&, const sc_string&, const char**)
|
|||
#ifdef SYSTEMC_64BIT_PATCHES
|
||||
DECL_TRACE_METHOD_B( unsigned long long)
|
||||
#endif
|
||||
#if (SYSTEMC_VERSION>20041000)
|
||||
#if (SYSTEMC_VERSION > 20041000)
|
||||
DECL_TRACE_METHOD_B( unsigned long long)
|
||||
DECL_TRACE_METHOD_B( long long)
|
||||
#endif
|
||||
|
|
@ -116,19 +119,21 @@ void VerilatedVcdSc::trace(const unsigned int&, const sc_string&, const char**)
|
|||
DECL_TRACE_METHOD_A( sc_fxnum_fast )
|
||||
DECL_TRACE_METHOD_A( sc_bv_base )
|
||||
DECL_TRACE_METHOD_A( sc_lv_base )
|
||||
// clang-format on
|
||||
|
||||
//--------------------------------------------------
|
||||
#else
|
||||
// SystemC 1.2.1beta
|
||||
// SystemC 1.2.1beta
|
||||
// cppcheck-suppress unusedFunction
|
||||
void VerilatedVcdSc::write_comment(const sc_string &) {}
|
||||
void VerilatedVcdSc::write_comment(const sc_string&) {}
|
||||
void VerilatedVcdSc::trace(const unsigned int&, const sc_string&, const char**) {}
|
||||
|
||||
#define DECL_TRACE_METHOD_A(tp) \
|
||||
void VerilatedVcdSc::trace( const tp& object, const sc_string& name ) {}
|
||||
void VerilatedVcdSc::trace(const tp& object, const sc_string& name) {}
|
||||
#define DECL_TRACE_METHOD_B(tp) \
|
||||
void VerilatedVcdSc::trace( const tp& object, const sc_string& name, int width ) {}
|
||||
void VerilatedVcdSc::trace(const tp& object, const sc_string& name, int width) {}
|
||||
|
||||
// clang-format off
|
||||
DECL_TRACE_METHOD_A( bool )
|
||||
DECL_TRACE_METHOD_B( unsigned char )
|
||||
DECL_TRACE_METHOD_B( short unsigned int )
|
||||
|
|
@ -154,6 +159,7 @@ void VerilatedVcdSc::trace(const unsigned int&, const sc_string&, const char**)
|
|||
DECL_TRACE_METHOD_A( sc_signal_resolved_vector )
|
||||
DECL_TRACE_METHOD_A( sc_bv_ns::sc_bv_base )
|
||||
DECL_TRACE_METHOD_A( sc_bv_ns::sc_lv_base )
|
||||
// clang-format on
|
||||
#endif
|
||||
|
||||
#undef DECL_TRACE_METHOD_A
|
||||
|
|
|
|||
|
|
@ -31,44 +31,42 @@
|
|||
/// This class is passed to the SystemC simulation kernel, just like a
|
||||
/// documented SystemC trace format.
|
||||
|
||||
class VerilatedVcdSc
|
||||
: sc_trace_file
|
||||
, public VerilatedVcdC
|
||||
{
|
||||
class VerilatedVcdSc : sc_trace_file, public VerilatedVcdC {
|
||||
// CONSTRUCTORS
|
||||
VL_UNCOPYABLE(VerilatedVcdSc);
|
||||
|
||||
public:
|
||||
VerilatedVcdSc() {
|
||||
sc_get_curr_simcontext()->add_trace_file(this);
|
||||
# if (SYSTEMC_VERSION>=20060505)
|
||||
#if (SYSTEMC_VERSION >= 20060505)
|
||||
// We want to avoid a depreciated warning, but still be back compatible.
|
||||
// Turning off the message just for this still results in an
|
||||
// annoying "to turn off" message.
|
||||
sc_time t1sec(1,SC_SEC);
|
||||
if (t1sec.to_default_time_units()!=0) {
|
||||
sc_time tunits(1.0/t1sec.to_default_time_units(),SC_SEC);
|
||||
sc_time t1sec(1, SC_SEC);
|
||||
if (t1sec.to_default_time_units() != 0) {
|
||||
sc_time tunits(1.0 / t1sec.to_default_time_units(), SC_SEC);
|
||||
spTrace()->set_time_unit(tunits.to_string());
|
||||
}
|
||||
spTrace()->set_time_resolution(sc_get_time_resolution().to_string());
|
||||
# elif (SYSTEMC_VERSION>20011000)
|
||||
#elif (SYSTEMC_VERSION > 20011000)
|
||||
// To confuse matters 2.1.beta returns a char* here, while 2.1.v1 returns a std::string
|
||||
// we allow both flavors with overloaded set_time_* functions.
|
||||
spTrace()->set_time_unit(sc_get_default_time_unit().to_string());
|
||||
spTrace()->set_time_resolution(sc_get_time_resolution().to_string());
|
||||
# endif
|
||||
#endif
|
||||
}
|
||||
virtual ~VerilatedVcdSc() { close(); }
|
||||
|
||||
// METHODS
|
||||
/// Called by SystemC simulate()
|
||||
virtual void cycle(bool delta_cycle) {
|
||||
# if (SYSTEMC_VERSION>20011000)
|
||||
#if (SYSTEMC_VERSION > 20011000)
|
||||
if (!delta_cycle) { this->dump(sc_time_stamp().to_double()); }
|
||||
# else
|
||||
#else
|
||||
// VCD files must have integer timestamps, so we write all times in
|
||||
// increments of time_resolution
|
||||
if (!delta_cycle) { this->dump(sc_time_stamp().to_double()); }
|
||||
# endif
|
||||
#endif
|
||||
}
|
||||
|
||||
private:
|
||||
|
|
@ -78,26 +76,26 @@ private:
|
|||
// Cadence Incisive has these as abstract functions so we must create them
|
||||
virtual void set_time_unit(int exponent10_seconds) {} // deprecated
|
||||
#endif
|
||||
#if defined(NC_SYSTEMC) || (SYSTEMC_VERSION>=20111100)
|
||||
#if defined(NC_SYSTEMC) || (SYSTEMC_VERSION >= 20111100)
|
||||
virtual void set_time_unit(double v, sc_time_unit tu) {}
|
||||
#endif
|
||||
|
||||
|
||||
//--------------------------------------------------
|
||||
# if (SYSTEMC_VERSION>=20050714)
|
||||
#if (SYSTEMC_VERSION >= 20050714)
|
||||
// SystemC 2.1.v1
|
||||
# define DECL_TRACE_METHOD_A(tp) \
|
||||
virtual void trace(const tp& object, const std::string& name);
|
||||
// clang-format off
|
||||
# define DECL_TRACE_METHOD_A(tp) virtual void trace(const tp& object, const std::string& name);
|
||||
# define DECL_TRACE_METHOD_B(tp) \
|
||||
virtual void trace(const tp& object, const std::string& name, int width);
|
||||
|
||||
virtual void write_comment(const std::string&);
|
||||
virtual void trace(const unsigned int&, const std::string&, const char**);
|
||||
|
||||
#if (SYSTEMC_VERSION>=20171012)
|
||||
// Formatting matches that of sc_trace.h
|
||||
# if (SYSTEMC_VERSION >= 20171012)
|
||||
DECL_TRACE_METHOD_A( sc_event )
|
||||
DECL_TRACE_METHOD_A( sc_time )
|
||||
#endif
|
||||
# endif
|
||||
|
||||
DECL_TRACE_METHOD_A( bool )
|
||||
DECL_TRACE_METHOD_A( sc_dt::sc_bit )
|
||||
|
|
@ -107,9 +105,9 @@ private:
|
|||
DECL_TRACE_METHOD_B( unsigned short )
|
||||
DECL_TRACE_METHOD_B( unsigned int )
|
||||
DECL_TRACE_METHOD_B( unsigned long )
|
||||
#ifdef SYSTEMC_64BIT_PATCHES
|
||||
# ifdef SYSTEMC_64BIT_PATCHES
|
||||
DECL_TRACE_METHOD_B( unsigned long long)
|
||||
#endif
|
||||
# endif
|
||||
DECL_TRACE_METHOD_B( char )
|
||||
DECL_TRACE_METHOD_B( short )
|
||||
DECL_TRACE_METHOD_B( int )
|
||||
|
|
@ -131,12 +129,13 @@ private:
|
|||
|
||||
DECL_TRACE_METHOD_A( sc_dt::sc_bv_base )
|
||||
DECL_TRACE_METHOD_A( sc_dt::sc_lv_base )
|
||||
// clang-format on
|
||||
|
||||
//--------------------------------------------------
|
||||
# elif (SYSTEMC_VERSION>20011000)
|
||||
#elif (SYSTEMC_VERSION > 20011000)
|
||||
// SystemC 2.0.1
|
||||
# define DECL_TRACE_METHOD_A(tp) \
|
||||
virtual void trace(const tp& object, const sc_string& name);
|
||||
// clang-format off
|
||||
# define DECL_TRACE_METHOD_A(tp) virtual void trace(const tp& object, const sc_string& name);
|
||||
# define DECL_TRACE_METHOD_B(tp) \
|
||||
virtual void trace(const tp& object, const sc_string& name, int width);
|
||||
|
||||
|
|
@ -152,13 +151,13 @@ private:
|
|||
DECL_TRACE_METHOD_B( unsigned short )
|
||||
DECL_TRACE_METHOD_B( unsigned int )
|
||||
DECL_TRACE_METHOD_B( unsigned long )
|
||||
#ifdef SYSTEMC_64BIT_PATCHES
|
||||
# ifdef SYSTEMC_64BIT_PATCHES
|
||||
DECL_TRACE_METHOD_B( unsigned long long)
|
||||
#endif
|
||||
#if (SYSTEMC_VERSION>20041000)
|
||||
# endif
|
||||
# if (SYSTEMC_VERSION > 20041000)
|
||||
DECL_TRACE_METHOD_B( unsigned long long)
|
||||
DECL_TRACE_METHOD_B( long long)
|
||||
#endif
|
||||
# endif
|
||||
DECL_TRACE_METHOD_B( char )
|
||||
DECL_TRACE_METHOD_B( short )
|
||||
DECL_TRACE_METHOD_B( int )
|
||||
|
|
@ -175,12 +174,13 @@ private:
|
|||
DECL_TRACE_METHOD_A( sc_fxnum_fast )
|
||||
DECL_TRACE_METHOD_A( sc_bv_base )
|
||||
DECL_TRACE_METHOD_A( sc_lv_base )
|
||||
// clang-format on
|
||||
|
||||
//--------------------------------------------------
|
||||
# else
|
||||
#else
|
||||
// SystemC 1.2.1beta
|
||||
# define DECL_TRACE_METHOD_A(tp) \
|
||||
virtual void trace(const tp& object, const sc_string& name);
|
||||
// clang-format off
|
||||
# define DECL_TRACE_METHOD_A(tp) virtual void trace(const tp& object, const sc_string& name);
|
||||
# define DECL_TRACE_METHOD_B(tp) \
|
||||
virtual void trace(const tp& object, const sc_string& name, int width);
|
||||
|
||||
|
|
@ -213,9 +213,10 @@ private:
|
|||
DECL_TRACE_METHOD_A( sc_bv_ns::sc_bv_base )
|
||||
DECL_TRACE_METHOD_A( sc_bv_ns::sc_lv_base )
|
||||
# endif
|
||||
// clang-format on
|
||||
|
||||
# undef DECL_TRACE_METHOD_A
|
||||
# undef DECL_TRACE_METHOD_B
|
||||
#undef DECL_TRACE_METHOD_A
|
||||
#undef DECL_TRACE_METHOD_B
|
||||
};
|
||||
|
||||
#endif // Guard
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
|
|
@ -25,95 +25,97 @@
|
|||
#ifndef _VERILATEDOS_H_
|
||||
#define _VERILATEDOS_H_ 1 ///< Header Guard
|
||||
|
||||
// Current clang-format versions botch #ifdef inclusion, so
|
||||
// clang-format off
|
||||
//=========================================================================
|
||||
// Compiler pragma abstraction
|
||||
|
||||
#ifdef __GNUC__
|
||||
# define VL_ATTR_ALIGNED(alignment) __attribute__ ((aligned (alignment)))
|
||||
# define VL_ATTR_ALWINLINE __attribute__ ((always_inline))
|
||||
# define VL_ATTR_COLD __attribute__ ((cold))
|
||||
# define VL_ATTR_HOT __attribute__ ((hot))
|
||||
# define VL_ATTR_NORETURN __attribute__ ((noreturn))
|
||||
# define VL_ATTR_PRINTF(fmtArgNum) __attribute__ ((format (printf, (fmtArgNum), (fmtArgNum)+1)))
|
||||
# define VL_ATTR_PURE __attribute__ ((pure))
|
||||
# define VL_ATTR_UNUSED __attribute__ ((unused))
|
||||
# define VL_FUNC __func__
|
||||
# define VL_ATTR_ALIGNED(alignment) __attribute__((aligned(alignment)))
|
||||
# define VL_ATTR_ALWINLINE __attribute__((always_inline))
|
||||
# define VL_ATTR_COLD __attribute__((cold))
|
||||
# define VL_ATTR_HOT __attribute__((hot))
|
||||
# define VL_ATTR_NORETURN __attribute__((noreturn))
|
||||
# define VL_ATTR_PRINTF(fmtArgNum) __attribute__((format(printf, (fmtArgNum), (fmtArgNum) + 1)))
|
||||
# define VL_ATTR_PURE __attribute__((pure))
|
||||
# define VL_ATTR_UNUSED __attribute__((unused))
|
||||
# define VL_FUNC __func__
|
||||
# if defined(__clang__) && defined(VL_THREADED)
|
||||
# define VL_ACQUIRE(...) __attribute__ ((acquire_capability(__VA_ARGS__)))
|
||||
# define VL_ACQUIRE_SHARED(...) __attribute__ ((acquire_shared_capability(__VA_ARGS__)))
|
||||
# define VL_RELEASE(...) __attribute__ ((release_capability(__VA_ARGS__)))
|
||||
# define VL_RELEASE_SHARED(...) __attribute__ ((release_shared_capability(__VA_ARGS__)))
|
||||
# define VL_TRY_ACQUIRE(...) __attribute__ ((try_acquire_capability(__VA_ARGS__)))
|
||||
# define VL_TRY_ACQUIRE_SHARED(...) __attribute__ ((try_acquire_shared_capability(__VA_ARGS__)))
|
||||
# define VL_CAPABILITY(x) __attribute__ ((capability(x)))
|
||||
# define VL_REQUIRES(x) __attribute__ ((requires_capability(x)))
|
||||
# define VL_GUARDED_BY(x) __attribute__ ((guarded_by(x)))
|
||||
# define VL_EXCLUDES(x) __attribute__ ((locks_excluded(x)))
|
||||
# define VL_SCOPED_CAPABILITY __attribute__ ((scoped_lockable))
|
||||
# define VL_ACQUIRE(...) __attribute__((acquire_capability(__VA_ARGS__)))
|
||||
# define VL_ACQUIRE_SHARED(...) __attribute__((acquire_shared_capability(__VA_ARGS__)))
|
||||
# define VL_RELEASE(...) __attribute__((release_capability(__VA_ARGS__)))
|
||||
# define VL_RELEASE_SHARED(...) __attribute__((release_shared_capability(__VA_ARGS__)))
|
||||
# define VL_TRY_ACQUIRE(...) __attribute__((try_acquire_capability(__VA_ARGS__)))
|
||||
# define VL_TRY_ACQUIRE_SHARED(...) __attribute__((try_acquire_shared_capability(__VA_ARGS__)))
|
||||
# define VL_CAPABILITY(x) __attribute__((capability(x)))
|
||||
# define VL_REQUIRES(x) __attribute__((requires_capability(x)))
|
||||
# define VL_GUARDED_BY(x) __attribute__((guarded_by(x)))
|
||||
# define VL_EXCLUDES(x) __attribute__((locks_excluded(x)))
|
||||
# define VL_SCOPED_CAPABILITY __attribute__((scoped_lockable))
|
||||
# endif
|
||||
# define VL_LIKELY(x) __builtin_expect(!!(x), 1)
|
||||
# define VL_LIKELY(x) __builtin_expect(!!(x), 1)
|
||||
# define VL_UNLIKELY(x) __builtin_expect(!!(x), 0)
|
||||
# define VL_UNREACHABLE __builtin_unreachable();
|
||||
# define VL_PREFETCH_RD(p) __builtin_prefetch((p),0)
|
||||
# define VL_PREFETCH_RW(p) __builtin_prefetch((p),1)
|
||||
# define VL_PREFETCH_RD(p) __builtin_prefetch((p), 0)
|
||||
# define VL_PREFETCH_RW(p) __builtin_prefetch((p), 1)
|
||||
#elif defined(_MSC_VER)
|
||||
# define VL_FUNC __FUNCTION__
|
||||
# define VL_FUNC __FUNCTION__
|
||||
#endif
|
||||
|
||||
// Defaults for unsupported compiler features
|
||||
#ifndef VL_ATTR_ALIGNED
|
||||
# define VL_ATTR_ALIGNED(alignment) ///< Align structure to specified byte alignment
|
||||
# define VL_ATTR_ALIGNED(alignment) ///< Align structure to specified byte alignment
|
||||
#endif
|
||||
#ifndef VL_ATTR_ALWINLINE
|
||||
# define VL_ATTR_ALWINLINE ///< Inline, even when not optimizing
|
||||
# define VL_ATTR_ALWINLINE ///< Inline, even when not optimizing
|
||||
#endif
|
||||
#ifndef VL_ATTR_COLD
|
||||
# define VL_ATTR_COLD ///< Function is rarely executed
|
||||
# define VL_ATTR_COLD ///< Function is rarely executed
|
||||
#endif
|
||||
#ifndef VL_ATTR_HOT
|
||||
# define VL_ATTR_HOT ///< Function is highly executed
|
||||
# define VL_ATTR_HOT ///< Function is highly executed
|
||||
#endif
|
||||
#ifndef VL_ATTR_NORETURN
|
||||
# define VL_ATTR_NORETURN ///< Function does not ever return
|
||||
# define VL_ATTR_NORETURN ///< Function does not ever return
|
||||
#endif
|
||||
#ifndef VL_ATTR_PRINTF
|
||||
# define VL_ATTR_PRINTF(fmtArgNum) ///< Function with printf format checking
|
||||
# define VL_ATTR_PRINTF(fmtArgNum) ///< Function with printf format checking
|
||||
#endif
|
||||
#ifndef VL_ATTR_PURE
|
||||
# define VL_ATTR_PURE ///< Function is pure (and thus also VL_MT_SAFE)
|
||||
# define VL_ATTR_PURE ///< Function is pure (and thus also VL_MT_SAFE)
|
||||
#endif
|
||||
#ifndef VL_ATTR_UNUSED
|
||||
# define VL_ATTR_UNUSED ///< Function that may be never used
|
||||
# define VL_ATTR_UNUSED ///< Function that may be never used
|
||||
#endif
|
||||
#ifndef VL_FUNC
|
||||
# define VL_FUNC "__func__" ///< Name of current function for error macros
|
||||
# define VL_FUNC "__func__" ///< Name of current function for error macros
|
||||
#endif
|
||||
#ifndef VL_CAPABILITY
|
||||
# define VL_ACQUIRE(...) ///< Function requires a capability/lock (-fthread-safety)
|
||||
# define VL_ACQUIRE_SHARED(...) ///< Function aquires a shared capability/lock (-fthread-safety)
|
||||
# define VL_RELEASE(...) ///< Function releases a capability/lock (-fthread-safety)
|
||||
# define VL_RELEASE_SHARED(...) ///< Function releases a shared capability/lock (-fthread-safety)
|
||||
# define VL_TRY_ACQUIRE(...) ///< Function returns bool if aquired a capability (-fthread-safety)
|
||||
# define VL_TRY_ACQUIRE_SHARED(...) ///< Function returns bool if aquired a shared capability (-fthread-safety)
|
||||
# define VL_REQUIRES(x) ///< Function requires a capability inbound (-fthread-safety)
|
||||
# define VL_EXCLUDES(x) ///< Function requires not having a capability inbound (-fthread-safety)
|
||||
# define VL_CAPABILITY(x) ///< Name of capability/lock (-fthread-safety)
|
||||
# define VL_GUARDED_BY(x) ///< Name of mutex protecting this variable (-fthread-safety)
|
||||
# define VL_SCOPED_CAPABILITY ///< Scoped threaded capability/lock (-fthread-safety)
|
||||
# define VL_ACQUIRE(...) ///< Function requires a capability/lock (-fthread-safety)
|
||||
# define VL_ACQUIRE_SHARED(...) ///< Function aquires a shared capability/lock (-fthread-safety)
|
||||
# define VL_RELEASE(...) ///< Function releases a capability/lock (-fthread-safety)
|
||||
# define VL_RELEASE_SHARED(...) ///< Function releases a shared capability/lock (-fthread-safety)
|
||||
# define VL_TRY_ACQUIRE(...) ///< Function returns bool if aquired a capability (-fthread-safety)
|
||||
# define VL_TRY_ACQUIRE_SHARED(...) ///< Function returns bool if aquired shared (-fthread-safety)
|
||||
# define VL_REQUIRES(x) ///< Function requires a capability inbound (-fthread-safety)
|
||||
# define VL_EXCLUDES(x) ///< Function requires not having a capability inbound (-fthread-safety)
|
||||
# define VL_CAPABILITY(x) ///< Name of capability/lock (-fthread-safety)
|
||||
# define VL_GUARDED_BY(x) ///< Name of mutex protecting this variable (-fthread-safety)
|
||||
# define VL_SCOPED_CAPABILITY ///< Scoped threaded capability/lock (-fthread-safety)
|
||||
#endif
|
||||
#ifndef VL_LIKELY
|
||||
# define VL_LIKELY(x) (!!(x)) ///< Boolean expression more often true than false
|
||||
# define VL_UNLIKELY(x) (!!(x)) ///< Boolean expression more often false than true
|
||||
# define VL_LIKELY(x) (!!(x)) ///< Boolean expression more often true than false
|
||||
# define VL_UNLIKELY(x) (!!(x)) ///< Boolean expression more often false than true
|
||||
#endif
|
||||
#define VL_UNCOVERABLE(x) VL_UNLIKELY(x) ///< Boolean expression never hit by users (no coverage)
|
||||
# define VL_UNCOVERABLE(x) VL_UNLIKELY(x) ///< Boolean expression never hit by users (no coverage)
|
||||
#ifndef VL_UNREACHABLE
|
||||
# define VL_UNREACHABLE ///< Point that may never be reached
|
||||
# define VL_UNREACHABLE ///< Point that may never be reached
|
||||
#endif
|
||||
#ifndef VL_PREFETCH_RD
|
||||
# define VL_PREFETCH_RD(p) ///< Prefetch data with read intent
|
||||
# define VL_PREFETCH_RD(p) ///< Prefetch data with read intent
|
||||
#endif
|
||||
#ifndef VL_PREFETCH_RW
|
||||
# define VL_PREFETCH_RW(p) ///< Prefetch data with read/write intent
|
||||
# define VL_PREFETCH_RW(p) ///< Prefetch data with read/write intent
|
||||
#endif
|
||||
|
||||
#ifdef VL_THREADED
|
||||
|
|
@ -121,31 +123,34 @@
|
|||
# define VL_THREAD_LOCAL thread_local
|
||||
# elif defined(__GNUC__)
|
||||
# if (__cplusplus < 201103L) && !defined(VL_THREADED_NO_C11_WARNING)
|
||||
# error "VL_THREADED/--threads support requires C++-11 or newer only; use newer compiler"
|
||||
# error "VL_THREADED/--threads support requires C++-11 or newer only; use newer compiler"
|
||||
# endif
|
||||
# else
|
||||
# error "Unsupported compiler for VL_THREADED: No thread-local declarator"
|
||||
# endif
|
||||
# define VL_THREAD_LOCAL thread_local ///< Use new C++ static local thread
|
||||
# define VL_THREAD_LOCAL thread_local ///< Use new C++ static local thread
|
||||
#else
|
||||
# define VL_THREAD_LOCAL ///< Use new C++ static local thread
|
||||
# define VL_THREAD_LOCAL ///< Use new C++ static local thread
|
||||
#endif
|
||||
#define VL_THREAD ///< Deprecated
|
||||
#define VL_STATIC_OR_THREAD static ///< Deprecated
|
||||
|
||||
#define VL_THREAD ///< Deprecated
|
||||
#define VL_STATIC_OR_THREAD static ///< Deprecated
|
||||
|
||||
#define VL_PURE ///< Comment tag that Function is pure (and thus also VL_MT_SAFE)
|
||||
#define VL_MT_SAFE ///< Comment tag that function is threadsafe when VL_THREADED
|
||||
#define VL_MT_SAFE_POSTINIT ///< Comment tag that function is threadsafe when VL_THREADED, only during normal operation (post-init)
|
||||
#define VL_MT_SAFE_POSTINIT ///< Comment tag that function is threadsafe when VL_THREADED, only
|
||||
///< during normal operation (post-init)
|
||||
#define VL_MT_UNSAFE ///< Comment tag that function is not threadsafe when VL_THREADED
|
||||
#define VL_MT_UNSAFE_ONE ///< Comment tag that function is not threadsafe when VL_THREADED, protected to make sure single-caller
|
||||
#define VL_MT_UNSAFE_ONE ///< Comment tag that function is not threadsafe when VL_THREADED,
|
||||
///< protected to make sure single-caller
|
||||
|
||||
#ifdef _MSC_VER
|
||||
# define VL_ULL(c) (c##ULL) ///< Add appropriate suffix to 64-bit constant
|
||||
# define VL_ULL(c) (c##ULL) ///< Add appropriate suffix to 64-bit constant
|
||||
// Was "(c##ui64)". C++11 has standardized on ULL, and MSVC now supports this.
|
||||
// We propose to no longer require using this macro no sooner than June 2020.
|
||||
// File an issue ASAP if this breaks anything.
|
||||
#else
|
||||
# define VL_ULL(c) (c##ULL) ///< Add appropriate suffix to 64-bit constant
|
||||
# define VL_ULL(c) (c##ULL) ///< Add appropriate suffix to 64-bit constant
|
||||
#endif
|
||||
|
||||
// This is not necessarily the same as #UL, depending on what the IData typedef is.
|
||||
|
|
@ -249,47 +254,47 @@
|
|||
# include <stdint.h>
|
||||
# include <sys/types.h> // __WORDSIZE
|
||||
# include <unistd.h> // ssize_t
|
||||
typedef unsigned char uint8_t; ///< 8-bit unsigned type (backward compatibility)
|
||||
typedef unsigned short int uint16_t; ///< 16-bit unsigned type (backward compatibility)
|
||||
typedef char vlsint8_t; ///< 8-bit signed type
|
||||
typedef unsigned char vluint8_t; ///< 8-bit unsigned type
|
||||
typedef short int vlsint16_t; ///< 16-bit signed type
|
||||
typedef unsigned short int vluint16_t; ///< 16-bit unsigned type
|
||||
typedef unsigned char uint8_t; ///< 8-bit unsigned type (backward compatibility)
|
||||
typedef unsigned short int uint16_t; ///< 16-bit unsigned type (backward compatibility)
|
||||
typedef char vlsint8_t; ///< 8-bit signed type
|
||||
typedef unsigned char vluint8_t; ///< 8-bit unsigned type
|
||||
typedef short int vlsint16_t; ///< 16-bit signed type
|
||||
typedef unsigned short int vluint16_t; ///< 16-bit unsigned type
|
||||
# if defined(__uint32_t_defined) || defined(___int32_t_defined) // Newer Cygwin uint32_t in stdint.h as an unsigned int
|
||||
typedef int32_t vlsint32_t; ///< 32-bit signed type
|
||||
typedef uint32_t vluint32_t; ///< 32-bit unsigned type
|
||||
typedef int32_t vlsint32_t; ///< 32-bit signed type
|
||||
typedef uint32_t vluint32_t; ///< 32-bit unsigned type
|
||||
# else // Older Cygwin has long==uint32_t
|
||||
typedef unsigned long uint32_t; ///< 32-bit unsigned type (backward compatibility)
|
||||
typedef long vlsint32_t; ///< 32-bit signed type
|
||||
typedef unsigned long vluint32_t; ///< 32-bit unsigned type
|
||||
typedef unsigned long uint32_t; ///< 32-bit unsigned type (backward compatibility)
|
||||
typedef long vlsint32_t; ///< 32-bit signed type
|
||||
typedef unsigned long vluint32_t; ///< 32-bit unsigned type
|
||||
# endif
|
||||
# if defined(__WORDSIZE) && (__WORDSIZE == 64)
|
||||
typedef long vlsint64_t; ///< 64-bit signed type
|
||||
typedef unsigned long vluint64_t; ///< 64-bit unsigned type
|
||||
typedef long vlsint64_t; ///< 64-bit signed type
|
||||
typedef unsigned long vluint64_t; ///< 64-bit unsigned type
|
||||
# else
|
||||
typedef long long vlsint64_t; ///< 64-bit signed type
|
||||
typedef unsigned long long vluint64_t; ///< 64-bit unsigned type
|
||||
typedef long long vlsint64_t; ///< 64-bit signed type
|
||||
typedef unsigned long long vluint64_t; ///< 64-bit unsigned type
|
||||
# endif
|
||||
|
||||
#elif defined(_WIN32) && defined(_MSC_VER)
|
||||
|
||||
typedef unsigned __int8 uint8_t; ///< 8-bit unsigned type (backward compatibility)
|
||||
typedef unsigned __int16 uint16_t; ///< 16-bit unsigned type (backward compatibility)
|
||||
typedef unsigned __int32 uint32_t; ///< 32-bit unsigned type (backward compatibility)
|
||||
typedef signed __int8 vlsint8_t; ///< 8-bit signed type
|
||||
typedef unsigned __int8 vluint8_t; ///< 8-bit unsigned type
|
||||
typedef signed __int16 vlsint16_t; ///< 16-bit signed type
|
||||
typedef unsigned __int16 vluint16_t; ///< 16-bit unsigned type
|
||||
typedef signed __int32 vlsint32_t; ///< 32-bit signed type
|
||||
typedef unsigned __int32 vluint32_t; ///< 32-bit unsigned type
|
||||
typedef signed __int64 vlsint64_t; ///< 64-bit signed type
|
||||
typedef unsigned __int64 vluint64_t; ///< 64-bit unsigned type
|
||||
typedef unsigned __int8 uint8_t; ///< 8-bit unsigned type (backward compatibility)
|
||||
typedef unsigned __int16 uint16_t; ///< 16-bit unsigned type (backward compatibility)
|
||||
typedef unsigned __int32 uint32_t; ///< 32-bit unsigned type (backward compatibility)
|
||||
typedef signed __int8 vlsint8_t; ///< 8-bit signed type
|
||||
typedef unsigned __int8 vluint8_t; ///< 8-bit unsigned type
|
||||
typedef signed __int16 vlsint16_t; ///< 16-bit signed type
|
||||
typedef unsigned __int16 vluint16_t; ///< 16-bit unsigned type
|
||||
typedef signed __int32 vlsint32_t; ///< 32-bit signed type
|
||||
typedef unsigned __int32 vluint32_t; ///< 32-bit unsigned type
|
||||
typedef signed __int64 vlsint64_t; ///< 64-bit signed type
|
||||
typedef unsigned __int64 vluint64_t; ///< 64-bit unsigned type
|
||||
|
||||
# ifndef _SSIZE_T_DEFINED
|
||||
# ifdef _WIN64
|
||||
typedef signed __int64 ssize_t; ///< signed size_t; returned from read()
|
||||
# ifdef _WIN64
|
||||
typedef signed __int64 ssize_t; ///< signed size_t; returned from read()
|
||||
# else
|
||||
typedef signed __int32 ssize_t; ///< signed size_t; returned from read()
|
||||
typedef signed __int32 ssize_t; ///< signed size_t; returned from read()
|
||||
# endif
|
||||
# endif
|
||||
|
||||
|
|
@ -299,18 +304,18 @@ typedef signed __int32 ssize_t; ///< signed size_t; returned fro
|
|||
# include <stdint.h> // Linux and most flavors
|
||||
# include <sys/types.h> // __WORDSIZE
|
||||
# include <unistd.h> // ssize_t
|
||||
typedef char vlsint8_t; ///< 8-bit signed type
|
||||
typedef uint8_t vluint8_t; ///< 8-bit unsigned type
|
||||
typedef short vlsint16_t; ///< 16-bit signed type
|
||||
typedef uint16_t vluint16_t; ///< 16-bit unsigned type
|
||||
typedef int vlsint32_t; ///< 32-bit signed type
|
||||
typedef uint32_t vluint32_t; ///< 32-bit unsigned type
|
||||
typedef char vlsint8_t; ///< 8-bit signed type
|
||||
typedef uint8_t vluint8_t; ///< 8-bit unsigned type
|
||||
typedef short vlsint16_t; ///< 16-bit signed type
|
||||
typedef uint16_t vluint16_t; ///< 16-bit unsigned type
|
||||
typedef int vlsint32_t; ///< 32-bit signed type
|
||||
typedef uint32_t vluint32_t; ///< 32-bit unsigned type
|
||||
# if defined(__WORDSIZE) && (__WORDSIZE == 64)
|
||||
typedef long vlsint64_t; ///< 64-bit signed type
|
||||
typedef unsigned long vluint64_t; ///< 64-bit unsigned type
|
||||
typedef long vlsint64_t; ///< 64-bit signed type
|
||||
typedef unsigned long vluint64_t; ///< 64-bit unsigned type
|
||||
# else
|
||||
typedef long long vlsint64_t; ///< 64-bit signed type
|
||||
typedef unsigned long long vluint64_t; ///< 64-bit unsigned type
|
||||
typedef long long vlsint64_t; ///< 64-bit signed type
|
||||
typedef unsigned long long vluint64_t; ///< 64-bit unsigned type
|
||||
# endif
|
||||
#endif
|
||||
|
||||
|
|
@ -353,14 +358,14 @@ typedef unsigned long long vluint64_t; ///< 64-bit unsigned type
|
|||
//=========================================================================
|
||||
// Integer size macros
|
||||
|
||||
#define VL_BYTESIZE 8 ///< Bits in a CData / byte
|
||||
#define VL_SHORTSIZE 16 ///< Bits in a SData / short
|
||||
#define VL_IDATASIZE 32 ///< Bits in a IData / word
|
||||
#define VL_WORDSIZE IDATASIZE ///< Legacy define
|
||||
#define VL_QUADSIZE 64 ///< Bits in a QData / quadword
|
||||
#define VL_EDATASIZE 32 ///< Bits in a EData (WData entry)
|
||||
#define VL_EDATASIZE_LOG2 5 ///< log2(VL_EDATASIZE)
|
||||
#define VL_CACHE_LINE_BYTES 64 ///< Bytes in a cache line (for alignment)
|
||||
#define VL_BYTESIZE 8 ///< Bits in a CData / byte
|
||||
#define VL_SHORTSIZE 16 ///< Bits in a SData / short
|
||||
#define VL_IDATASIZE 32 ///< Bits in a IData / word
|
||||
#define VL_WORDSIZE IDATASIZE ///< Legacy define
|
||||
#define VL_QUADSIZE 64 ///< Bits in a QData / quadword
|
||||
#define VL_EDATASIZE 32 ///< Bits in a EData (WData entry)
|
||||
#define VL_EDATASIZE_LOG2 5 ///< log2(VL_EDATASIZE)
|
||||
#define VL_CACHE_LINE_BYTES 64 ///< Bytes in a cache line (for alignment)
|
||||
|
||||
/// Bytes this number of bits needs (1 bit=1 byte)
|
||||
#define VL_BYTES_I(nbits) (((nbits) + (VL_BYTESIZE - 1)) / VL_BYTESIZE)
|
||||
|
|
@ -373,9 +378,9 @@ typedef unsigned long long vluint64_t; ///< 64-bit unsigned type
|
|||
// Class definition helpers
|
||||
|
||||
// Used to declare a class as uncopyable; put after a private:
|
||||
#define VL_UNCOPYABLE(Type) \
|
||||
Type(const Type& other) VL_EQ_DELETE; \
|
||||
Type& operator= (const Type&) VL_EQ_DELETE
|
||||
#define VL_UNCOPYABLE(Type) \
|
||||
Type(const Type& other) VL_EQ_DELETE; \
|
||||
Type& operator=(const Type&) VL_EQ_DELETE
|
||||
|
||||
//=========================================================================
|
||||
// Verilated function size macros
|
||||
|
|
@ -391,11 +396,10 @@ typedef unsigned long long vluint64_t; ///< 64-bit unsigned type
|
|||
#define VL_SIZEBITS_E (VL_EDATASIZE - 1) ///< Bit mask for bits in a quad
|
||||
|
||||
/// Mask for words with 1's where relevant bits are (0=all bits)
|
||||
#define VL_MASK_I(nbits) (((nbits) & VL_SIZEBITS_I) \
|
||||
? ((1U << ((nbits) & VL_SIZEBITS_I) )-1) : ~0)
|
||||
#define VL_MASK_I(nbits) (((nbits) & VL_SIZEBITS_I) ? ((1U << ((nbits) & VL_SIZEBITS_I)) - 1) : ~0)
|
||||
/// Mask for quads with 1's where relevant bits are (0=all bits)
|
||||
#define VL_MASK_Q(nbits) (((nbits) & VL_SIZEBITS_Q) \
|
||||
? ((VL_ULL(1) << ((nbits) & VL_SIZEBITS_Q) )-VL_ULL(1)) : VL_ULL(~0))
|
||||
#define VL_MASK_Q(nbits) \
|
||||
(((nbits) & VL_SIZEBITS_Q) ? ((VL_ULL(1) << ((nbits) & VL_SIZEBITS_Q)) - VL_ULL(1)) : VL_ULL(~0))
|
||||
/// Mask for EData with 1's where relevant bits are (0=all bits)
|
||||
#define VL_MASK_E(nbits) VL_MASK_I(nbits)
|
||||
#define VL_EUL(n) VL_UL(n) ///< Make constant number EData sized
|
||||
|
|
@ -411,8 +415,8 @@ typedef unsigned long long vluint64_t; ///< 64-bit unsigned type
|
|||
// #defines, to avoid requiring math.h on all compile runs
|
||||
|
||||
#ifdef _MSC_VER
|
||||
# define VL_TRUNC(n) (((n)<0) ? ceil((n)) : floor((n)))
|
||||
# define VL_ROUND(n) (((n)<0) ? ceil((n)-0.5) : floor((n)+0.5))
|
||||
# define VL_TRUNC(n) (((n) < 0) ? ceil((n)) : floor((n)))
|
||||
# define VL_ROUND(n) (((n) < 0) ? ceil((n)-0.5) : floor((n) + 0.5))
|
||||
#else
|
||||
# define VL_TRUNC(n) trunc(n)
|
||||
# define VL_ROUND(n) round(n)
|
||||
|
|
@ -424,13 +428,14 @@ typedef unsigned long long vluint64_t; ///< 64-bit unsigned type
|
|||
/// The vluint64_t argument is loaded with a high-performance counter for profiling
|
||||
/// or 0x0 if not implemeted on this platform
|
||||
#if defined(__i386__) || defined(__x86_64__)
|
||||
# define VL_RDTSC(val) { \
|
||||
vluint32_t hi, lo; \
|
||||
asm volatile("rdtsc" : "=a" (lo), "=d" (hi)); \
|
||||
(val) = ((vluint64_t)lo) | (((vluint64_t)hi)<<32); \
|
||||
}
|
||||
#define VL_RDTSC(val) \
|
||||
{ \
|
||||
vluint32_t hi, lo; \
|
||||
asm volatile("rdtsc" : "=a"(lo), "=d"(hi)); \
|
||||
(val) = ((vluint64_t)lo) | (((vluint64_t)hi) << 32); \
|
||||
}
|
||||
#elif defined(__aarch64__)
|
||||
# define VL_RDTSC(val) asm volatile("mrs %[rt],PMCCNTR_EL0" : [rt] "=r" (val));
|
||||
# define VL_RDTSC(val) asm volatile("mrs %[rt],PMCCNTR_EL0" : [rt] "=r"(val));
|
||||
#else
|
||||
// We just silently ignore unknown OSes, as only leads to missing statistics
|
||||
# define VL_RDTSC(val) (val) = 0;
|
||||
|
|
@ -468,6 +473,7 @@ typedef unsigned long long vluint64_t; ///< 64-bit unsigned type
|
|||
#else
|
||||
# define VL_STRCASECMP strcasecmp
|
||||
#endif
|
||||
// clang-format on
|
||||
|
||||
//=========================================================================
|
||||
// Stringify macros
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
private:
|
||||
typedef std::map<string,AstActive*> ActiveNameMap;
|
||||
typedef std::map<string, AstActive*> ActiveNameMap;
|
||||
// STATE
|
||||
AstScope* m_scopep; // Current scope to add statement to
|
||||
AstActive* m_iActivep; // For current scope, the IActive we're building
|
||||
AstActive* m_cActivep; // For current scope, the SActive(combo) we're building
|
||||
AstScope* m_scopep; // Current scope to add statement to
|
||||
AstActive* m_iActivep; // For current scope, the IActive we're building
|
||||
AstActive* m_cActivep; // For current scope, the SActive(combo) we're building
|
||||
|
||||
SenTreeSet m_activeSens; // Sen lists for each active we've made
|
||||
typedef vl_unordered_map<AstSenTree*, AstActive*> ActiveMap;
|
||||
|
|
@ -89,8 +89,7 @@ public:
|
|||
AstActive* getCActive(FileLine* fl) {
|
||||
if (!m_cActivep) {
|
||||
m_cActivep = new AstActive(
|
||||
fl, "combo",
|
||||
new AstSenTree(fl, new AstSenItem(fl, AstSenItem::Combo())));
|
||||
fl, "combo", new AstSenTree(fl, new AstSenItem(fl, AstSenItem::Combo())));
|
||||
m_cActivep->sensesStorep(m_cActivep->sensesp());
|
||||
addActive(m_cActivep);
|
||||
}
|
||||
|
|
@ -99,8 +98,7 @@ public:
|
|||
AstActive* getIActive(FileLine* fl) {
|
||||
if (!m_iActivep) {
|
||||
m_iActivep = new AstActive(
|
||||
fl, "initial",
|
||||
new AstSenTree(fl, new AstSenItem(fl, AstSenItem::Initial())));
|
||||
fl, "initial", new AstSenTree(fl, new AstSenItem(fl, AstSenItem::Initial())));
|
||||
m_iActivep->sensesStorep(m_iActivep->sensesp());
|
||||
addActive(m_iActivep);
|
||||
}
|
||||
|
|
@ -122,7 +120,7 @@ public:
|
|||
AstSenTree* newsenp = sensesp->cloneTree(false);
|
||||
activep = new AstActive(fl, "sequent", newsenp);
|
||||
activep->sensesStorep(activep->sensesp());
|
||||
UINFO(8," New ACTIVE "<<activep<<endl);
|
||||
UINFO(8, " New ACTIVE " << activep << endl);
|
||||
// Form the sensitivity list
|
||||
addActive(activep);
|
||||
m_activeMap[newsenp] = activep;
|
||||
|
|
@ -131,6 +129,7 @@ public:
|
|||
}
|
||||
return activep;
|
||||
}
|
||||
|
||||
public:
|
||||
// CONSTRUCTORS
|
||||
ActiveNamer() {
|
||||
|
|
@ -139,9 +138,7 @@ public:
|
|||
m_cActivep = NULL;
|
||||
}
|
||||
virtual ~ActiveNamer() {}
|
||||
void main(AstScope* nodep) {
|
||||
iterate(nodep);
|
||||
}
|
||||
void main(AstScope* nodep) { iterate(nodep); }
|
||||
};
|
||||
|
||||
//######################################################################
|
||||
|
|
@ -150,27 +147,29 @@ public:
|
|||
class ActiveDlyVisitor : public ActiveBaseVisitor {
|
||||
public:
|
||||
enum CheckType { CT_SEQ, CT_COMBO, CT_INITIAL, CT_LATCH };
|
||||
|
||||
private:
|
||||
CheckType m_check; // Combo logic or other
|
||||
AstNode* m_alwaysp; // Always we're under
|
||||
AstNode* m_assignp; // In assign
|
||||
CheckType m_check; // Combo logic or other
|
||||
AstNode* m_alwaysp; // Always we're under
|
||||
AstNode* m_assignp; // In assign
|
||||
// VISITORS
|
||||
virtual void visit(AstAssignDly* nodep) VL_OVERRIDE {
|
||||
if (m_check != CT_SEQ) {
|
||||
// Convert to a non-delayed assignment
|
||||
UINFO(5," ASSIGNDLY "<<nodep<<endl);
|
||||
UINFO(5, " ASSIGNDLY " << nodep << endl);
|
||||
if (m_check == CT_INITIAL) {
|
||||
nodep->v3warn(INITIALDLY, "Delayed assignments (<=) in initial or final block\n"
|
||||
<<nodep->warnMore()<<"... Suggest blocking assignments (=)");
|
||||
<< nodep->warnMore()
|
||||
<< "... Suggest blocking assignments (=)");
|
||||
} else if (m_check == CT_LATCH) {
|
||||
// Suppress. Shouldn't matter that the interior of the latch races
|
||||
} else {
|
||||
nodep->v3warn(COMBDLY, "Delayed assignments (<=) in non-clocked"
|
||||
" (non flop or latch) block\n"
|
||||
<<nodep->warnMore()<<"... Suggest blocking assignments (=)");
|
||||
" (non flop or latch) block\n"
|
||||
<< nodep->warnMore()
|
||||
<< "... Suggest blocking assignments (=)");
|
||||
}
|
||||
AstNode* newp = new AstAssign(nodep->fileline(),
|
||||
nodep->lhsp()->unlinkFrBack(),
|
||||
AstNode* newp = new AstAssign(nodep->fileline(), nodep->lhsp()->unlinkFrBack(),
|
||||
nodep->rhsp()->unlinkFrBack());
|
||||
nodep->replaceWith(newp);
|
||||
VL_DO_DANGLING(nodep->deleteTree(), nodep);
|
||||
|
|
@ -186,17 +185,18 @@ private:
|
|||
}
|
||||
virtual void visit(AstVarRef* nodep) VL_OVERRIDE {
|
||||
AstVar* varp = nodep->varp();
|
||||
if (m_check == CT_SEQ
|
||||
&& m_assignp
|
||||
&& !varp->isUsedLoopIdx() // Ignore loop indices
|
||||
if (m_check == CT_SEQ && m_assignp && !varp->isUsedLoopIdx() // Ignore loop indices
|
||||
&& !varp->isTemp()) {
|
||||
// Allow turning off warnings on the always, or the variable also
|
||||
if (!m_alwaysp->fileline()->warnIsOff(V3ErrorCode::BLKSEQ)
|
||||
&& !m_assignp->fileline()->warnIsOff(V3ErrorCode::BLKSEQ)
|
||||
&& !varp->fileline()->warnIsOff(V3ErrorCode::BLKSEQ)) {
|
||||
m_assignp->v3warn(BLKSEQ, "Blocking assignments (=) in sequential (flop or latch) block\n"
|
||||
<<m_assignp->warnMore()<<"... Suggest delayed assignments (<=)");
|
||||
m_alwaysp->fileline()->modifyWarnOff(V3ErrorCode::BLKSEQ, true); // Complain just once for the entire always
|
||||
m_assignp->v3warn(BLKSEQ,
|
||||
"Blocking assignments (=) in sequential (flop or latch) block\n"
|
||||
<< m_assignp->warnMore()
|
||||
<< "... Suggest delayed assignments (<=)");
|
||||
m_alwaysp->fileline()->modifyWarnOff(
|
||||
V3ErrorCode::BLKSEQ, true); // Complain just once for the entire always
|
||||
varp->fileline()->modifyWarnOff(V3ErrorCode::BLKSEQ, true);
|
||||
}
|
||||
}
|
||||
|
|
@ -225,15 +225,15 @@ private:
|
|||
// AstNode::user4() Used by V3Const::constify, called below
|
||||
|
||||
// STATE
|
||||
ActiveNamer m_namer; // Tracking of active names
|
||||
AstCFunc* m_scopeFinalp; // Final function for this scope
|
||||
bool m_itemCombo; // Found a SenItem combo
|
||||
bool m_itemSequent; // Found a SenItem sequential
|
||||
ActiveNamer m_namer; // Tracking of active names
|
||||
AstCFunc* m_scopeFinalp; // Final function for this scope
|
||||
bool m_itemCombo; // Found a SenItem combo
|
||||
bool m_itemSequent; // Found a SenItem sequential
|
||||
|
||||
// VISITORS
|
||||
virtual void visit(AstScope* nodep) VL_OVERRIDE {
|
||||
// Create required actives and add to scope
|
||||
UINFO(4," SCOPE "<<nodep<<endl);
|
||||
UINFO(4, " SCOPE " << nodep << endl);
|
||||
// Clear last scope's names, and collect this scope's existing names
|
||||
m_namer.main(nodep);
|
||||
m_scopeFinalp = NULL;
|
||||
|
|
@ -244,48 +244,47 @@ private:
|
|||
}
|
||||
virtual void visit(AstInitial* nodep) VL_OVERRIDE {
|
||||
// Relink to IACTIVE, unless already under it
|
||||
UINFO(4," INITIAL "<<nodep<<endl);
|
||||
ActiveDlyVisitor dlyvisitor (nodep, ActiveDlyVisitor::CT_INITIAL);
|
||||
UINFO(4, " INITIAL " << nodep << endl);
|
||||
ActiveDlyVisitor dlyvisitor(nodep, ActiveDlyVisitor::CT_INITIAL);
|
||||
AstActive* wantactivep = m_namer.getIActive(nodep->fileline());
|
||||
nodep->unlinkFrBack();
|
||||
wantactivep->addStmtsp(nodep);
|
||||
}
|
||||
virtual void visit(AstAssignAlias* nodep) VL_OVERRIDE {
|
||||
// Relink to CACTIVE, unless already under it
|
||||
UINFO(4," ASSIGNW "<<nodep<<endl);
|
||||
UINFO(4, " ASSIGNW " << nodep << endl);
|
||||
AstActive* wantactivep = m_namer.getCActive(nodep->fileline());
|
||||
nodep->unlinkFrBack();
|
||||
wantactivep->addStmtsp(nodep);
|
||||
}
|
||||
virtual void visit(AstAssignW* nodep) VL_OVERRIDE {
|
||||
// Relink to CACTIVE, unless already under it
|
||||
UINFO(4," ASSIGNW "<<nodep<<endl);
|
||||
UINFO(4, " ASSIGNW " << nodep << endl);
|
||||
AstActive* wantactivep = m_namer.getCActive(nodep->fileline());
|
||||
nodep->unlinkFrBack();
|
||||
wantactivep->addStmtsp(nodep);
|
||||
}
|
||||
virtual void visit(AstCoverToggle* nodep) VL_OVERRIDE {
|
||||
// Relink to CACTIVE, unless already under it
|
||||
UINFO(4," COVERTOGGLE "<<nodep<<endl);
|
||||
UINFO(4, " COVERTOGGLE " << nodep << endl);
|
||||
AstActive* wantactivep = m_namer.getCActive(nodep->fileline());
|
||||
nodep->unlinkFrBack();
|
||||
wantactivep->addStmtsp(nodep);
|
||||
}
|
||||
virtual void visit(AstFinal* nodep) VL_OVERRIDE {
|
||||
// Relink to CFUNC for the final
|
||||
UINFO(4," FINAL "<<nodep<<endl);
|
||||
UINFO(4, " FINAL " << nodep << endl);
|
||||
if (!nodep->bodysp()) { // Empty, Kill it.
|
||||
VL_DO_DANGLING(nodep->unlinkFrBack()->deleteTree(), nodep);
|
||||
return;
|
||||
}
|
||||
ActiveDlyVisitor dlyvisitor (nodep, ActiveDlyVisitor::CT_INITIAL);
|
||||
ActiveDlyVisitor dlyvisitor(nodep, ActiveDlyVisitor::CT_INITIAL);
|
||||
if (!m_scopeFinalp) {
|
||||
m_scopeFinalp = new AstCFunc(
|
||||
nodep->fileline(), "_final_"+m_namer.scopep()->nameDotless(),
|
||||
m_namer.scopep());
|
||||
nodep->fileline(), "_final_" + m_namer.scopep()->nameDotless(), m_namer.scopep());
|
||||
m_scopeFinalp->argTypes(EmitCBaseVisitor::symClassVar());
|
||||
m_scopeFinalp->addInitsp(
|
||||
new AstCStmt(nodep->fileline(), EmitCBaseVisitor::symTopAssign()+"\n"));
|
||||
new AstCStmt(nodep->fileline(), EmitCBaseVisitor::symTopAssign() + "\n"));
|
||||
m_scopeFinalp->dontCombine(true);
|
||||
m_scopeFinalp->formCallTree(true);
|
||||
m_scopeFinalp->slow(true);
|
||||
|
|
@ -300,9 +299,7 @@ private:
|
|||
// METHODS
|
||||
void visitAlways(AstNode* nodep, AstSenTree* oldsensesp, VAlwaysKwd kwd) {
|
||||
// Move always to appropriate ACTIVE based on its sense list
|
||||
if (oldsensesp
|
||||
&& oldsensesp->sensesp()
|
||||
&& VN_IS(oldsensesp->sensesp(), SenItem)
|
||||
if (oldsensesp && oldsensesp->sensesp() && VN_IS(oldsensesp->sensesp(), SenItem)
|
||||
&& VN_CAST(oldsensesp->sensesp(), SenItem)->isNever()) {
|
||||
// Never executing. Kill it.
|
||||
UASSERT_OBJ(!oldsensesp->sensesp()->nextp(), nodep,
|
||||
|
|
@ -318,10 +315,11 @@ private:
|
|||
bool combo = m_itemCombo;
|
||||
bool sequent = m_itemSequent;
|
||||
|
||||
if (!combo && !sequent) combo=true; // If no list, Verilog 2000: always @ (*)
|
||||
if (!combo && !sequent) combo = true; // If no list, Verilog 2000: always @ (*)
|
||||
if (combo && sequent) {
|
||||
if (!v3Global.opt.bboxUnsup()) {
|
||||
nodep->v3error("Unsupported: Mixed edge (pos/negedge) and activity (no edge) sensitive activity list");
|
||||
nodep->v3error("Unsupported: Mixed edge (pos/negedge) and activity "
|
||||
"(no edge) sensitive activity list");
|
||||
}
|
||||
sequent = false;
|
||||
}
|
||||
|
|
@ -336,8 +334,9 @@ private:
|
|||
// always (posedge RESET) { if (RESET).... } we know RESET is true.
|
||||
// Summarize a long list of combo inputs as just "combo"
|
||||
#ifndef __COVERITY__ // Else dead code on next line.
|
||||
if (combo) oldsensesp->addSensesp
|
||||
(new AstSenItem(nodep->fileline(), AstSenItem::Combo()));
|
||||
if (combo) {
|
||||
oldsensesp->addSensesp(new AstSenItem(nodep->fileline(), AstSenItem::Combo()));
|
||||
}
|
||||
#endif
|
||||
wantactivep = m_namer.getActive(nodep->fileline(), oldsensesp);
|
||||
}
|
||||
|
|
@ -354,19 +353,18 @@ private:
|
|||
// Warn and/or convert any delayed assignments
|
||||
if (combo && !sequent) {
|
||||
if (kwd == VAlwaysKwd::ALWAYS_LATCH) {
|
||||
ActiveDlyVisitor dlyvisitor (nodep, ActiveDlyVisitor::CT_LATCH);
|
||||
ActiveDlyVisitor dlyvisitor(nodep, ActiveDlyVisitor::CT_LATCH);
|
||||
} else {
|
||||
ActiveDlyVisitor dlyvisitor (nodep, ActiveDlyVisitor::CT_COMBO);
|
||||
ActiveDlyVisitor dlyvisitor(nodep, ActiveDlyVisitor::CT_COMBO);
|
||||
}
|
||||
}
|
||||
else if (!combo && sequent) {
|
||||
ActiveDlyVisitor dlyvisitor (nodep, ActiveDlyVisitor::CT_SEQ);
|
||||
} else if (!combo && sequent) {
|
||||
ActiveDlyVisitor dlyvisitor(nodep, ActiveDlyVisitor::CT_SEQ);
|
||||
}
|
||||
}
|
||||
virtual void visit(AstAlways* nodep) VL_OVERRIDE {
|
||||
// Move always to appropriate ACTIVE based on its sense list
|
||||
UINFO(4," ALW "<<nodep<<endl);
|
||||
//if (debug()>=9) nodep->dumpTree(cout, " Alw: ");
|
||||
UINFO(4, " ALW " << nodep << endl);
|
||||
// if (debug()>=9) nodep->dumpTree(cout, " Alw: ");
|
||||
|
||||
if (!nodep->bodysp()) {
|
||||
// Empty always. Kill it.
|
||||
|
|
@ -377,15 +375,15 @@ private:
|
|||
}
|
||||
virtual void visit(AstAlwaysPublic* nodep) VL_OVERRIDE {
|
||||
// Move always to appropriate ACTIVE based on its sense list
|
||||
UINFO(4," ALWPub "<<nodep<<endl);
|
||||
//if (debug()>=9) nodep->dumpTree(cout, " Alw: ");
|
||||
UINFO(4, " ALWPub " << nodep << endl);
|
||||
// if (debug()>=9) nodep->dumpTree(cout, " Alw: ");
|
||||
visitAlways(nodep, nodep->sensesp(), VAlwaysKwd::ALWAYS);
|
||||
}
|
||||
virtual void visit(AstSenGate* nodep) VL_OVERRIDE {
|
||||
AstSenItem* subitemp = nodep->sensesp();
|
||||
UASSERT_OBJ(subitemp->edgeType() == VEdgeType::ET_ANYEDGE
|
||||
|| subitemp->edgeType() == VEdgeType::ET_POSEDGE
|
||||
|| subitemp->edgeType() == VEdgeType::ET_NEGEDGE,
|
||||
|| subitemp->edgeType() == VEdgeType::ET_POSEDGE
|
||||
|| subitemp->edgeType() == VEdgeType::ET_NEGEDGE,
|
||||
nodep, "Strange activity type under SenGate");
|
||||
iterateChildren(nodep);
|
||||
}
|
||||
|
|
@ -399,7 +397,7 @@ private:
|
|||
// V3LinkResolve should have cleaned most of these up
|
||||
if (!nodep->varrefp()->width1()) {
|
||||
nodep->v3error("Unsupported: Non-single bit wide signal pos/negedge sensitivity: "
|
||||
<<nodep->varrefp()->prettyNameQ());
|
||||
<< nodep->varrefp()->prettyNameQ());
|
||||
}
|
||||
m_itemSequent = true;
|
||||
nodep->varrefp()->varp()->usedClock(true);
|
||||
|
|
@ -426,9 +424,7 @@ public:
|
|||
// Active class functions
|
||||
|
||||
void V3Active::activeAll(AstNetlist* nodep) {
|
||||
UINFO(2,__FUNCTION__<<": "<<endl);
|
||||
{
|
||||
ActiveVisitor visitor (nodep);
|
||||
} // Destruct before checking
|
||||
UINFO(2, __FUNCTION__ << ": " << endl);
|
||||
{ ActiveVisitor visitor(nodep); } // Destruct before checking
|
||||
V3Global::dumpCheckGlobalTree("active", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -42,11 +42,11 @@ private:
|
|||
// AstNode::user() bool. True if processed
|
||||
// Each call to V3Const::constify
|
||||
// AstNode::user4() Used by V3Const::constify, called below
|
||||
AstUser1InUse m_inuser1;
|
||||
AstUser1InUse m_inuser1;
|
||||
|
||||
// STATE
|
||||
AstTopScope* m_topscopep; // Top scope for adding sentrees under
|
||||
SenTreeFinder m_finder; // Find global sentree's and add them
|
||||
AstTopScope* m_topscopep; // Top scope for adding sentrees under
|
||||
SenTreeFinder m_finder; // Find global sentree's and add them
|
||||
|
||||
// METHODS
|
||||
VL_DEBUG_FUNC; // Declare debug()
|
||||
|
|
@ -61,16 +61,16 @@ private:
|
|||
virtual void visit(AstNodeModule* nodep) VL_OVERRIDE {
|
||||
// Create required actives and add to module
|
||||
// We can start ordering at a module, or a scope
|
||||
UINFO(4," MOD "<<nodep<<endl);
|
||||
UINFO(4, " MOD " << nodep << endl);
|
||||
iterateChildren(nodep);
|
||||
}
|
||||
virtual void visit(AstActive* nodep) VL_OVERRIDE {
|
||||
UINFO(4," ACTIVE "<<nodep<<endl);
|
||||
V3Const::constifyExpensiveEdit(nodep); // Remove duplicate clocks and such; sensesp() may change!
|
||||
UINFO(4, " ACTIVE " << nodep << endl);
|
||||
// Remove duplicate clocks and such; sensesp() may change!
|
||||
V3Const::constifyExpensiveEdit(nodep);
|
||||
AstSenTree* sensesp = nodep->sensesp();
|
||||
UASSERT_OBJ(sensesp, nodep, "NULL");
|
||||
if (sensesp->sensesp()
|
||||
&& VN_IS(sensesp->sensesp(), SenItem)
|
||||
if (sensesp->sensesp() && VN_IS(sensesp->sensesp(), SenItem)
|
||||
&& VN_CAST(sensesp->sensesp(), SenItem)->isNever()) {
|
||||
// Never executing. Kill it.
|
||||
UASSERT_OBJ(!sensesp->sensesp()->nextp(), nodep,
|
||||
|
|
@ -80,10 +80,9 @@ private:
|
|||
}
|
||||
// Copy combo tree to settlement tree with duplicated statements
|
||||
if (sensesp->hasCombo()) {
|
||||
AstSenTree* newsentreep
|
||||
= new AstSenTree(nodep->fileline(),
|
||||
new AstSenItem(nodep->fileline(), AstSenItem::Settle()));
|
||||
AstActive* newp = new AstActive(nodep->fileline(),"settle", newsentreep);
|
||||
AstSenTree* newsentreep = new AstSenTree(
|
||||
nodep->fileline(), new AstSenItem(nodep->fileline(), AstSenItem::Settle()));
|
||||
AstActive* newp = new AstActive(nodep->fileline(), "settle", newsentreep);
|
||||
newp->sensesStorep(newsentreep);
|
||||
if (nodep->stmtsp()) newp->addStmtsp(nodep->stmtsp()->cloneTree(true));
|
||||
nodep->addNextHere(newp);
|
||||
|
|
@ -91,10 +90,10 @@ private:
|
|||
// Move the SENTREE for each active up to the global level.
|
||||
// This way we'll easily see what clock domains are identical
|
||||
AstSenTree* wantp = m_finder.getSenTree(nodep->fileline(), sensesp);
|
||||
UINFO(4," lookdone\n");
|
||||
UINFO(4, " lookdone\n");
|
||||
if (wantp != sensesp) {
|
||||
// Move the active's contents to the other active
|
||||
UINFO(4," merge active "<<sensesp<<" into "<<wantp<<endl);
|
||||
UINFO(4, " merge active " << sensesp << " into " << wantp << endl);
|
||||
if (nodep->sensesStorep()) {
|
||||
UASSERT_OBJ(sensesp == nodep->sensesStorep(), nodep,
|
||||
"sensesStore should have been deleted earlier if different");
|
||||
|
|
@ -107,7 +106,7 @@ private:
|
|||
nodep->sensesp(wantp);
|
||||
}
|
||||
// No need to do statements under it, they're already moved.
|
||||
//iterateChildren(nodep);
|
||||
// iterateChildren(nodep);
|
||||
}
|
||||
virtual void visit(AstInitial* nodep) VL_OVERRIDE { // LCOV_EXCL_LINE
|
||||
nodep->v3fatalSrc("Node should have been under ACTIVE");
|
||||
|
|
@ -145,9 +144,7 @@ public:
|
|||
// Active class functions
|
||||
|
||||
void V3ActiveTop::activeTopAll(AstNetlist* nodep) {
|
||||
UINFO(2,__FUNCTION__<<": "<<endl);
|
||||
{
|
||||
ActiveTopVisitor visitor (nodep);
|
||||
} // Destruct before checking
|
||||
UINFO(2, __FUNCTION__ << ": " << endl);
|
||||
{ ActiveTopVisitor visitor(nodep); } // Destruct before checking
|
||||
V3Global::dumpCheckGlobalTree("activetop", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
|
||||
}
|
||||
|
|
|
|||
127
src/V3Assert.cpp
127
src/V3Assert.cpp
|
|
@ -34,24 +34,22 @@ private:
|
|||
// NODE STATE/TYPES
|
||||
// Cleared on netlist
|
||||
// AstNode::user() -> bool. True if processed
|
||||
AstUser1InUse m_inuser1;
|
||||
AstUser1InUse m_inuser1;
|
||||
|
||||
// STATE
|
||||
AstNodeModule* m_modp; // Last module
|
||||
AstBegin* m_beginp; // Last begin
|
||||
unsigned m_modPastNum; // Module past numbering
|
||||
VDouble0 m_statCover; // Statistic tracking
|
||||
VDouble0 m_statAsNotImm; // Statistic tracking
|
||||
VDouble0 m_statAsImm; // Statistic tracking
|
||||
VDouble0 m_statAsFull; // Statistic tracking
|
||||
AstNodeModule* m_modp; // Last module
|
||||
AstBegin* m_beginp; // Last begin
|
||||
unsigned m_modPastNum; // Module past numbering
|
||||
VDouble0 m_statCover; // Statistic tracking
|
||||
VDouble0 m_statAsNotImm; // Statistic tracking
|
||||
VDouble0 m_statAsImm; // Statistic tracking
|
||||
VDouble0 m_statAsFull; // Statistic tracking
|
||||
|
||||
// METHODS
|
||||
string assertDisplayMessage(AstNode* nodep, const string& prefix, const string& message) {
|
||||
return (string("[%0t] "+prefix+": ")+nodep->fileline()->filebasename()
|
||||
+":"+cvtToStr(nodep->fileline()->lineno())
|
||||
+": Assertion failed in %m"
|
||||
+((message != "")?": ":"")+message
|
||||
+"\n");
|
||||
return (string("[%0t] " + prefix + ": ") + nodep->fileline()->filebasename() + ":"
|
||||
+ cvtToStr(nodep->fileline()->lineno()) + ": Assertion failed in %m"
|
||||
+ ((message != "") ? ": " : "") + message + "\n");
|
||||
}
|
||||
void replaceDisplay(AstDisplay* nodep, const string& prefix) {
|
||||
nodep->displayType(AstDisplayType::DT_WRITE);
|
||||
|
|
@ -77,8 +75,8 @@ private:
|
|||
// If assertions are off, have constant propagation rip them out later
|
||||
// This allows syntax errors and such to be detected normally.
|
||||
(v3Global.opt.assertOn()
|
||||
? static_cast<AstNode*>(new AstCMath(fl, "Verilated::assertOn()", 1))
|
||||
: static_cast<AstNode*>(new AstConst(fl, AstConst::LogicFalse()))),
|
||||
? static_cast<AstNode*>(new AstCMath(fl, "Verilated::assertOn()", 1))
|
||||
: static_cast<AstNode*>(new AstConst(fl, AstConst::LogicFalse()))),
|
||||
nodep, NULL);
|
||||
newp->user1(true); // Don't assert/cover this if
|
||||
return newp;
|
||||
|
|
@ -86,8 +84,8 @@ private:
|
|||
|
||||
AstNode* newFireAssertUnchecked(AstNode* nodep, const string& message) {
|
||||
// Like newFireAssert() but omits the asserts-on check
|
||||
AstDisplay* dispp = new AstDisplay(nodep->fileline(),
|
||||
AstDisplayType::DT_ERROR, message, NULL, NULL);
|
||||
AstDisplay* dispp
|
||||
= new AstDisplay(nodep->fileline(), AstDisplayType::DT_ERROR, message, NULL, NULL);
|
||||
AstNode* bodysp = dispp;
|
||||
replaceDisplay(dispp, "%%Error"); // Convert to standard DISPLAY format
|
||||
bodysp->addNext(new AstStop(nodep->fileline(), true));
|
||||
|
|
@ -129,7 +127,7 @@ private:
|
|||
AstCoverInc* covincp = VN_CAST(snodep->coverincp(), CoverInc);
|
||||
UASSERT_OBJ(covincp, snodep, "Missing AstCoverInc under assertion");
|
||||
covincp->unlinkFrBackWithNext(); // next() might have AstAssign for trace
|
||||
if (message!="") covincp->declp()->comment(message);
|
||||
if (message != "") covincp->declp()->comment(message);
|
||||
bodysp = covincp;
|
||||
}
|
||||
|
||||
|
|
@ -137,8 +135,11 @@ private:
|
|||
ifp = new AstIf(nodep->fileline(), propp, bodysp, NULL);
|
||||
bodysp = ifp;
|
||||
} else if (VN_IS(nodep, Assert)) {
|
||||
if (nodep->immediate()) ++m_statAsImm;
|
||||
else ++m_statAsNotImm;
|
||||
if (nodep->immediate()) {
|
||||
++m_statAsImm;
|
||||
} else {
|
||||
++m_statAsNotImm;
|
||||
}
|
||||
if (passsp) passsp = newIfAssertOn(passsp);
|
||||
if (failsp) failsp = newIfAssertOn(failsp);
|
||||
if (!failsp) failsp = newFireAssertUnchecked(nodep, "'assert' failed.");
|
||||
|
|
@ -153,9 +154,10 @@ private:
|
|||
|
||||
AstNode* newp;
|
||||
if (sentreep) {
|
||||
newp = new AstAlways(nodep->fileline(),
|
||||
VAlwaysKwd::ALWAYS, sentreep, bodysp);
|
||||
} else { newp = bodysp; }
|
||||
newp = new AstAlways(nodep->fileline(), VAlwaysKwd::ALWAYS, sentreep, bodysp);
|
||||
} else {
|
||||
newp = bodysp;
|
||||
}
|
||||
// Install it
|
||||
if (selfDestruct) {
|
||||
// Delete it after making the tree. This way we can tell the user
|
||||
|
|
@ -186,7 +188,7 @@ private:
|
|||
iterateAndNextNull(ifp->ifsp());
|
||||
|
||||
// If the last else is not an else if, recurse into that too.
|
||||
if (ifp->elsesp() && !nextifp) {
|
||||
if (ifp->elsesp() && !nextifp) { //
|
||||
iterateAndNextNull(ifp->elsesp());
|
||||
}
|
||||
|
||||
|
|
@ -199,14 +201,12 @@ private:
|
|||
}
|
||||
|
||||
// Record if this ends with an 'else' that does not have an if
|
||||
if (ifp->elsesp() && !nextifp) {
|
||||
hasDefaultElse = true;
|
||||
}
|
||||
if (ifp->elsesp() && !nextifp) hasDefaultElse = true;
|
||||
|
||||
ifp = nextifp;
|
||||
} while (ifp);
|
||||
|
||||
AstNode *newifp = nodep->cloneTree(false);
|
||||
AstNode* newifp = nodep->cloneTree(false);
|
||||
bool allow_none = nodep->unique0Pragma();
|
||||
|
||||
// Empty case means no property
|
||||
|
|
@ -215,12 +215,11 @@ private:
|
|||
// Note: if this ends with an 'else', then we don't need to validate that one of the
|
||||
// predicates evaluates to true.
|
||||
AstNode* ohot = ((allow_none || hasDefaultElse)
|
||||
? static_cast<AstNode*>(new AstOneHot0(nodep->fileline(), propp))
|
||||
: static_cast<AstNode*>(new AstOneHot(nodep->fileline(), propp)));
|
||||
AstIf* checkifp = new AstIf(nodep->fileline(),
|
||||
new AstLogNot(nodep->fileline(), ohot),
|
||||
newFireAssert(nodep, "'unique if' statement violated"),
|
||||
newifp);
|
||||
? static_cast<AstNode*>(new AstOneHot0(nodep->fileline(), propp))
|
||||
: static_cast<AstNode*>(new AstOneHot(nodep->fileline(), propp)));
|
||||
AstIf* checkifp
|
||||
= new AstIf(nodep->fileline(), new AstLogNot(nodep->fileline(), ohot),
|
||||
newFireAssert(nodep, "'unique if' statement violated"), newifp);
|
||||
checkifp->branchPred(VBranchPred::BP_UNLIKELY);
|
||||
nodep->replaceWith(checkifp);
|
||||
pushDeletep(nodep);
|
||||
|
|
@ -234,16 +233,17 @@ private:
|
|||
iterateChildren(nodep);
|
||||
if (!nodep->user1SetOnce()) {
|
||||
bool has_default = false;
|
||||
for (AstCaseItem* itemp = nodep->itemsp();
|
||||
itemp; itemp = VN_CAST(itemp->nextp(), CaseItem)) {
|
||||
for (AstCaseItem* itemp = nodep->itemsp(); itemp;
|
||||
itemp = VN_CAST(itemp->nextp(), CaseItem)) {
|
||||
if (itemp->isDefault()) has_default = true;
|
||||
}
|
||||
if (nodep->fullPragma() || nodep->priorityPragma()) {
|
||||
// Simply need to add a default if there isn't one already
|
||||
++m_statAsFull;
|
||||
if (!has_default) {
|
||||
nodep->addItemsp(new AstCaseItem(nodep->fileline(), NULL/*DEFAULT*/,
|
||||
newFireAssert(nodep, "synthesis full_case, but non-match found")));
|
||||
nodep->addItemsp(new AstCaseItem(
|
||||
nodep->fileline(), NULL /*DEFAULT*/,
|
||||
newFireAssert(nodep, "synthesis full_case, but non-match found")));
|
||||
}
|
||||
}
|
||||
if (nodep->parallelPragma() || nodep->uniquePragma() || nodep->unique0Pragma()) {
|
||||
|
|
@ -271,8 +271,11 @@ private:
|
|||
nodep->exprp()->cloneTree(false),
|
||||
icondp->cloneTree(false));
|
||||
}
|
||||
if (propp) propp = new AstConcat(icondp->fileline(), onep, propp);
|
||||
else propp = onep;
|
||||
if (propp) {
|
||||
propp = new AstConcat(icondp->fileline(), onep, propp);
|
||||
} else {
|
||||
propp = onep;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Empty case means no property
|
||||
|
|
@ -281,12 +284,13 @@ private:
|
|||
bool allow_none = has_default || nodep->unique0Pragma();
|
||||
AstNode* ohot
|
||||
= (allow_none
|
||||
? static_cast<AstNode*>(new AstOneHot0(nodep->fileline(), propp))
|
||||
: static_cast<AstNode*>(new AstOneHot(nodep->fileline(), propp)));
|
||||
AstIf* ifp = new AstIf(nodep->fileline(),
|
||||
new AstLogNot(nodep->fileline(), ohot),
|
||||
newFireAssert(nodep, "synthesis parallel_case, but multiple matches found"),
|
||||
NULL);
|
||||
? static_cast<AstNode*>(new AstOneHot0(nodep->fileline(), propp))
|
||||
: static_cast<AstNode*>(new AstOneHot(nodep->fileline(), propp)));
|
||||
AstIf* ifp = new AstIf(
|
||||
nodep->fileline(), new AstLogNot(nodep->fileline(), ohot),
|
||||
newFireAssert(nodep,
|
||||
"synthesis parallel_case, but multiple matches found"),
|
||||
NULL);
|
||||
ifp->branchPred(VBranchPred::BP_UNLIKELY);
|
||||
nodep->addNotParallelp(ifp);
|
||||
}
|
||||
|
|
@ -303,23 +307,22 @@ private:
|
|||
"Expected constant ticks, checked in V3Width");
|
||||
ticks = VN_CAST(nodep->ticksp(), Const)->toUInt();
|
||||
}
|
||||
UASSERT_OBJ(ticks>=1, nodep, "0 tick should have been checked in V3Width");
|
||||
UASSERT_OBJ(ticks >= 1, nodep, "0 tick should have been checked in V3Width");
|
||||
AstNode* inp = nodep->exprp()->unlinkFrBack();
|
||||
AstVar* invarp = NULL;
|
||||
AstSenTree* sentreep = nodep->sentreep(); sentreep->unlinkFrBack();
|
||||
AstAlways* alwaysp = new AstAlways(nodep->fileline(), VAlwaysKwd::ALWAYS,
|
||||
sentreep, NULL);
|
||||
AstSenTree* sentreep = nodep->sentreep();
|
||||
sentreep->unlinkFrBack();
|
||||
AstAlways* alwaysp = new AstAlways(nodep->fileline(), VAlwaysKwd::ALWAYS, sentreep, NULL);
|
||||
m_modp->addStmtp(alwaysp);
|
||||
for (uint32_t i=0; i<ticks; ++i) {
|
||||
for (uint32_t i = 0; i < ticks; ++i) {
|
||||
AstVar* outvarp = new AstVar(nodep->fileline(), AstVarType::MODULETEMP,
|
||||
"_Vpast_"+cvtToStr(m_modPastNum++)+"_"+cvtToStr(i),
|
||||
"_Vpast_" + cvtToStr(m_modPastNum++) + "_" + cvtToStr(i),
|
||||
inp->dtypep());
|
||||
m_modp->addStmtp(outvarp);
|
||||
AstNode* assp = new AstAssignDly(nodep->fileline(),
|
||||
new AstVarRef(nodep->fileline(), outvarp, true),
|
||||
inp);
|
||||
new AstVarRef(nodep->fileline(), outvarp, true), inp);
|
||||
alwaysp->addStmtp(assp);
|
||||
//if (debug()>-9) assp->dumpTree(cout, "-ass: ");
|
||||
// if (debug()>-9) assp->dumpTree(cout, "-ass: ");
|
||||
invarp = outvarp;
|
||||
inp = new AstVarRef(nodep->fileline(), invarp, false);
|
||||
}
|
||||
|
|
@ -334,12 +337,12 @@ private:
|
|||
virtual void visit(AstDisplay* nodep) VL_OVERRIDE {
|
||||
iterateChildren(nodep);
|
||||
// Replace the special types with standard text
|
||||
if (nodep->displayType()==AstDisplayType::DT_INFO) {
|
||||
if (nodep->displayType() == AstDisplayType::DT_INFO) {
|
||||
replaceDisplay(nodep, "-Info");
|
||||
} else if (nodep->displayType()==AstDisplayType::DT_WARNING) {
|
||||
} else if (nodep->displayType() == AstDisplayType::DT_WARNING) {
|
||||
replaceDisplay(nodep, "%%Warning");
|
||||
} else if (nodep->displayType()==AstDisplayType::DT_ERROR
|
||||
|| nodep->displayType()==AstDisplayType::DT_FATAL) {
|
||||
} else if (nodep->displayType() == AstDisplayType::DT_ERROR
|
||||
|| nodep->displayType() == AstDisplayType::DT_FATAL) {
|
||||
replaceDisplay(nodep, "%%Error");
|
||||
}
|
||||
}
|
||||
|
|
@ -403,9 +406,7 @@ public:
|
|||
// Top Assert class
|
||||
|
||||
void V3Assert::assertAll(AstNetlist* nodep) {
|
||||
UINFO(2,__FUNCTION__<<": "<<endl);
|
||||
{
|
||||
AssertVisitor visitor (nodep);
|
||||
} // Destruct before checking
|
||||
UINFO(2, __FUNCTION__ << ": " << endl);
|
||||
{ AssertVisitor visitor(nodep); } // Destruct before checking
|
||||
V3Global::dumpCheckGlobalTree("assert", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -61,14 +61,12 @@ private:
|
|||
}
|
||||
return newp;
|
||||
}
|
||||
void clearAssertInfo() {
|
||||
m_senip = NULL;
|
||||
}
|
||||
void clearAssertInfo() { m_senip = NULL; }
|
||||
|
||||
// VISITORS
|
||||
//========== Statements
|
||||
virtual void visit(AstClocking* nodep) VL_OVERRIDE {
|
||||
UINFO(8," CLOCKING"<<nodep<<endl);
|
||||
UINFO(8, " CLOCKING" << nodep << endl);
|
||||
// Store the new default clock, reset on new module
|
||||
m_seniDefaultp = nodep->sensesp();
|
||||
// Trash it, keeping children
|
||||
|
|
@ -81,9 +79,7 @@ private:
|
|||
}
|
||||
virtual void visit(AstAlways* nodep) VL_OVERRIDE {
|
||||
iterateAndNextNull(nodep->sensesp());
|
||||
if (nodep->sensesp()) {
|
||||
m_seniAlwaysp = nodep->sensesp()->sensesp();
|
||||
}
|
||||
if (nodep->sensesp()) m_seniAlwaysp = nodep->sensesp()->sensesp();
|
||||
iterateAndNextNull(nodep->bodysp());
|
||||
m_seniAlwaysp = NULL;
|
||||
}
|
||||
|
|
@ -93,9 +89,7 @@ private:
|
|||
clearAssertInfo();
|
||||
// Find Clocking's buried under nodep->exprsp
|
||||
iterateChildren(nodep);
|
||||
if (!nodep->immediate()) {
|
||||
nodep->sentreep(newSenTree(nodep));
|
||||
}
|
||||
if (!nodep->immediate()) nodep->sentreep(newSenTree(nodep));
|
||||
clearAssertInfo();
|
||||
}
|
||||
virtual void visit(AstPast* nodep) VL_OVERRIDE {
|
||||
|
|
@ -106,21 +100,18 @@ private:
|
|||
virtual void visit(AstPropClocked* nodep) VL_OVERRIDE {
|
||||
// No need to iterate the body, once replace will get iterated
|
||||
iterateAndNextNull(nodep->sensesp());
|
||||
if (m_senip) {
|
||||
nodep->v3error("Unsupported: Only one PSL clock allowed per assertion");
|
||||
}
|
||||
if (m_senip) nodep->v3error("Unsupported: Only one PSL clock allowed per assertion");
|
||||
// Block is the new expression to evaluate
|
||||
AstNode* blockp = nodep->propp()->unlinkFrBack();
|
||||
if (nodep->disablep()) {
|
||||
if (VN_IS(nodep->backp(), Cover)) {
|
||||
blockp = new AstAnd(nodep->disablep()->fileline(),
|
||||
new AstNot(nodep->disablep()->fileline(),
|
||||
nodep->disablep()->unlinkFrBack()),
|
||||
blockp);
|
||||
blockp = new AstAnd(
|
||||
nodep->disablep()->fileline(),
|
||||
new AstNot(nodep->disablep()->fileline(), nodep->disablep()->unlinkFrBack()),
|
||||
blockp);
|
||||
} else {
|
||||
blockp = new AstOr(nodep->disablep()->fileline(),
|
||||
nodep->disablep()->unlinkFrBack(),
|
||||
blockp);
|
||||
nodep->disablep()->unlinkFrBack(), blockp);
|
||||
}
|
||||
}
|
||||
// Unlink and just keep a pointer to it, convert to sentree as needed
|
||||
|
|
@ -151,9 +142,7 @@ public:
|
|||
// Top Assert class
|
||||
|
||||
void V3AssertPre::assertPreAll(AstNetlist* nodep) {
|
||||
UINFO(2,__FUNCTION__<<": "<<endl);
|
||||
{
|
||||
AssertPreVisitor visitor (nodep);
|
||||
} // Destruct before checking
|
||||
UINFO(2, __FUNCTION__ << ": " << endl);
|
||||
{ AssertPreVisitor visitor(nodep); } // Destruct before checking
|
||||
V3Global::dumpCheckGlobalTree("assertpre", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,12 +18,12 @@
|
|||
#define _V3ASTCONSTONLY_H_ 1
|
||||
|
||||
// Include only in visitors that do not not edit nodes, so should use constant iterators
|
||||
#define iterateAndNext error_use_iterateAndNextConst
|
||||
#define iterateChildren error_use_iterateChildrenConst
|
||||
#define iterateAndNext error_use_iterateAndNextConst
|
||||
#define iterateChildren error_use_iterateChildrenConst
|
||||
|
||||
#define addNext error_no_addNext_in_ConstOnlyVisitor
|
||||
#define replaceWith error_no_replaceWith_in_ConstOnlyVisitor
|
||||
#define deleteTree error_no_deleteTree_in_ConstOnlyVisitor
|
||||
#define unlinkFrBack error_no_unlinkFrBack_in_ConstOnlyVisitor
|
||||
#define addNext error_no_addNext_in_ConstOnlyVisitor
|
||||
#define replaceWith error_no_replaceWith_in_ConstOnlyVisitor
|
||||
#define deleteTree error_no_deleteTree_in_ConstOnlyVisitor
|
||||
#define unlinkFrBack error_no_unlinkFrBack_in_ConstOnlyVisitor
|
||||
|
||||
#endif // Guard
|
||||
|
|
|
|||
|
|
@ -41,15 +41,15 @@ private:
|
|||
// NODE STATE
|
||||
// Entire netlist:
|
||||
// AstFTask::user1() -> int. Number of references
|
||||
AstUser1InUse m_inuser1;
|
||||
AstUser1InUse m_inuser1;
|
||||
|
||||
// TYPES
|
||||
typedef std::vector<AstCFunc*> CFuncVec;
|
||||
|
||||
// STATE
|
||||
int m_likely; // Excuses for branch likely taken
|
||||
int m_unlikely; // Excuses for branch likely not taken
|
||||
CFuncVec m_cfuncsp; // List of all tasks
|
||||
int m_likely; // Excuses for branch likely taken
|
||||
int m_unlikely; // Excuses for branch likely not taken
|
||||
CFuncVec m_cfuncsp; // List of all tasks
|
||||
|
||||
// METHODS
|
||||
VL_DEBUG_FUNC; // Declare debug()
|
||||
|
|
@ -60,14 +60,14 @@ private:
|
|||
}
|
||||
void checkUnlikely(AstNode* nodep) {
|
||||
if (nodep->isUnlikely()) {
|
||||
UINFO(4," UNLIKELY: "<<nodep<<endl);
|
||||
UINFO(4, " UNLIKELY: " << nodep << endl);
|
||||
m_unlikely++;
|
||||
}
|
||||
}
|
||||
|
||||
// VISITORS
|
||||
virtual void visit(AstNodeIf* nodep) VL_OVERRIDE {
|
||||
UINFO(4," IF: "<<nodep<<endl);
|
||||
UINFO(4, " IF: " << nodep << endl);
|
||||
int lastLikely = m_likely;
|
||||
int lastUnlikely = m_unlikely;
|
||||
{
|
||||
|
|
@ -109,11 +109,9 @@ private:
|
|||
|
||||
// METHODS
|
||||
void calc_tasks() {
|
||||
for (CFuncVec::iterator it=m_cfuncsp.begin(); it!=m_cfuncsp.end(); ++it) {
|
||||
for (CFuncVec::iterator it = m_cfuncsp.begin(); it != m_cfuncsp.end(); ++it) {
|
||||
AstCFunc* nodep = *it;
|
||||
if (!nodep->dontInline()) {
|
||||
nodep->isInline(true);
|
||||
}
|
||||
if (!nodep->dontInline()) nodep->isInline(true);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -131,6 +129,6 @@ public:
|
|||
// Branch class functions
|
||||
|
||||
void V3Branch::branchAll(AstNetlist* nodep) {
|
||||
UINFO(2,__FUNCTION__<<": "<<endl);
|
||||
BranchVisitor visitor (nodep);
|
||||
UINFO(2, __FUNCTION__ << ": " << endl);
|
||||
BranchVisitor visitor(nodep);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -58,27 +58,21 @@ private:
|
|||
packagep->classp(nodep);
|
||||
v3Global.rootp()->addModulep(packagep);
|
||||
// Add package to hierarchy
|
||||
AstCell* cellp = new AstCell(packagep->fileline(),
|
||||
packagep->fileline(),
|
||||
packagep->name(),
|
||||
packagep->name(),
|
||||
NULL, NULL, NULL);
|
||||
AstCell* cellp = new AstCell(packagep->fileline(), packagep->fileline(), packagep->name(),
|
||||
packagep->name(), NULL, NULL, NULL);
|
||||
cellp->modp(packagep);
|
||||
v3Global.rootp()->topModulep()->addStmtp(cellp);
|
||||
// Find class's scope
|
||||
// Alternative would be to move this and related to V3Scope
|
||||
AstScope* classScopep = NULL;
|
||||
for (AstNode* itp = nodep->stmtsp(); itp; itp = itp->nextp()) {
|
||||
if ((classScopep = VN_CAST(itp, Scope))) {
|
||||
break;
|
||||
}
|
||||
if ((classScopep = VN_CAST(itp, Scope))) break;
|
||||
}
|
||||
UASSERT_OBJ(classScopep, nodep, "No scope under class");
|
||||
|
||||
// Add scope
|
||||
AstScope* scopep = new AstScope(nodep->fileline(),
|
||||
packagep, classScopep->name(), classScopep->aboveScopep(),
|
||||
classScopep->aboveCellp());
|
||||
AstScope* scopep = new AstScope(nodep->fileline(), packagep, classScopep->name(),
|
||||
classScopep->aboveScopep(), classScopep->aboveCellp());
|
||||
packagep->addStmtp(scopep);
|
||||
// Iterate
|
||||
string prevPrefix = m_prefix;
|
||||
|
|
@ -103,7 +97,7 @@ private:
|
|||
iterateChildren(nodep);
|
||||
// Don't move now, or wouldn't keep interating the class
|
||||
// TODO move class statics only
|
||||
//if (m_classScopep) {
|
||||
// if (m_classScopep) {
|
||||
// m_moves.push_back(make_pair(nodep, m_classScopep));
|
||||
//}
|
||||
}
|
||||
|
|
@ -111,7 +105,7 @@ private:
|
|||
iterateChildren(nodep);
|
||||
// Don't move now, or wouldn't keep interating the class
|
||||
// TODO move function statics only
|
||||
//if (m_classScopep) {
|
||||
// if (m_classScopep) {
|
||||
// m_moves.push_back(make_pair(nodep, m_classScopep));
|
||||
//}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -267,7 +267,7 @@ class V3ConfigFile {
|
|||
|
||||
LineAttrMap m_lineAttrs; // Atributes to line mapping
|
||||
IgnLines m_ignLines; // Ignore line settings
|
||||
Waivers m_waivers; // Waive messages
|
||||
Waivers m_waivers; // Waive messages
|
||||
|
||||
struct {
|
||||
int lineno; // Last line number
|
||||
|
|
@ -346,7 +346,9 @@ public:
|
|||
bool waive(V3ErrorCode code, const string& match) {
|
||||
for (Waivers::const_iterator it = m_waivers.begin(); it != m_waivers.end(); ++it) {
|
||||
if (((it->first == code) || (it->first == V3ErrorCode::I_LINT))
|
||||
&& VString::wildmatch(match, it->second)) return true;
|
||||
&& VString::wildmatch(match, it->second)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -40,14 +40,16 @@
|
|||
class CoverageVisitor : public AstNVisitor {
|
||||
private:
|
||||
// TYPES
|
||||
typedef std::map<string,int> FileMap;
|
||||
typedef std::map<string, int> FileMap;
|
||||
|
||||
struct ToggleEnt {
|
||||
string m_comment; // Comment for coverage dump
|
||||
AstNode* m_varRefp; // How to get to this element
|
||||
AstNode* m_chgRefp; // How to get to this element
|
||||
string m_comment; // Comment for coverage dump
|
||||
AstNode* m_varRefp; // How to get to this element
|
||||
AstNode* m_chgRefp; // How to get to this element
|
||||
ToggleEnt(const string& comment, AstNode* vp, AstNode* cp)
|
||||
: m_comment(comment), m_varRefp(vp), m_chgRefp(cp) {}
|
||||
: m_comment(comment)
|
||||
, m_varRefp(vp)
|
||||
, m_chgRefp(cp) {}
|
||||
~ToggleEnt() {}
|
||||
void cleanup() {
|
||||
VL_DO_CLEAR(m_varRefp->deleteTree(), m_varRefp = NULL);
|
||||
|
|
@ -58,15 +60,15 @@ private:
|
|||
// NODE STATE
|
||||
// Entire netlist:
|
||||
// AstIf::user1() -> bool. True indicates ifelse processed
|
||||
AstUser1InUse m_inuser1;
|
||||
AstUser1InUse m_inuser1;
|
||||
|
||||
// STATE
|
||||
bool m_checkBlock; // Should this block get covered?
|
||||
AstNodeModule* m_modp; // Current module to add statement to
|
||||
bool m_inToggleOff; // In function/task etc
|
||||
bool m_inModOff; // In module with no coverage
|
||||
FileMap m_fileps; // Column counts for each fileline
|
||||
string m_beginHier; // AstBegin hier name for user coverage points
|
||||
bool m_checkBlock; // Should this block get covered?
|
||||
AstNodeModule* m_modp; // Current module to add statement to
|
||||
bool m_inToggleOff; // In function/task etc
|
||||
bool m_inModOff; // In module with no coverage
|
||||
FileMap m_fileps; // Column counts for each fileline
|
||||
string m_beginHier; // AstBegin hier name for user coverage points
|
||||
|
||||
// METHODS
|
||||
VL_DEBUG_FUNC; // Declare debug()
|
||||
|
|
@ -74,16 +76,13 @@ private:
|
|||
const char* varIgnoreToggle(AstVar* nodep) {
|
||||
// Return true if this shouldn't be traced
|
||||
// See also similar rule in V3TraceDecl::varIgnoreTrace
|
||||
if (!nodep->isToggleCoverable())
|
||||
return "Not relevant signal type";
|
||||
if (!nodep->isToggleCoverable()) return "Not relevant signal type";
|
||||
if (!v3Global.opt.coverageUnderscore()) {
|
||||
string prettyName = nodep->prettyName();
|
||||
if (prettyName[0] == '_')
|
||||
return "Leading underscore";
|
||||
if (prettyName.find("._") != string::npos)
|
||||
return "Inlined leading underscore";
|
||||
if (prettyName[0] == '_') return "Leading underscore";
|
||||
if (prettyName.find("._") != string::npos) return "Inlined leading underscore";
|
||||
}
|
||||
if ((nodep->width()*nodep->dtypep()->arrayUnpackedElements()) > 256) {
|
||||
if ((nodep->width() * nodep->dtypep()->arrayUnpackedElements()) > 256) {
|
||||
return "Wide bus/array > 256 bits";
|
||||
}
|
||||
// We allow this, though tracing doesn't
|
||||
|
|
@ -91,19 +90,18 @@ private:
|
|||
return NULL;
|
||||
}
|
||||
|
||||
AstCoverInc* newCoverInc(FileLine* fl, const string& hier,
|
||||
const string& page_prefix, const string& comment,
|
||||
const string& trace_var_name) {
|
||||
AstCoverInc* newCoverInc(FileLine* fl, const string& hier, const string& page_prefix,
|
||||
const string& comment, const string& trace_var_name) {
|
||||
// For line coverage, we may have multiple if's on one line, so disambiguate if
|
||||
// everything is otherwise identical
|
||||
// (Don't set column otherwise as it may result in making bins not match up with
|
||||
// different types of coverage enabled.)
|
||||
string key = fl->filename()+"\001"+cvtToStr(fl->lineno())
|
||||
+"\001"+hier+"\001"+page_prefix+"\001"+comment;
|
||||
string key = fl->filename() + "\001" + cvtToStr(fl->lineno()) + "\001" + hier + "\001"
|
||||
+ page_prefix + "\001" + comment;
|
||||
int column = 0;
|
||||
FileMap::iterator it = m_fileps.find(key);
|
||||
if (it == m_fileps.end()) {
|
||||
m_fileps.insert(make_pair(key, column+1));
|
||||
m_fileps.insert(make_pair(key, column + 1));
|
||||
} else {
|
||||
column = (it->second)++;
|
||||
}
|
||||
|
|
@ -122,27 +120,23 @@ private:
|
|||
|
||||
AstCoverInc* incp = new AstCoverInc(fl, declp);
|
||||
if (!trace_var_name.empty() && v3Global.opt.traceCoverage()) {
|
||||
AstVar* varp = new AstVar(incp->fileline(),
|
||||
AstVarType::MODULETEMP, trace_var_name,
|
||||
AstVar* varp = new AstVar(incp->fileline(), AstVarType::MODULETEMP, trace_var_name,
|
||||
incp->findUInt32DType());
|
||||
varp->trace(true);
|
||||
varp->fileline()->modifyWarnOff(V3ErrorCode::UNUSED, true);
|
||||
m_modp->addStmtp(varp);
|
||||
UINFO(5, "New coverage trace: "<<varp<<endl);
|
||||
AstAssign* assp = new AstAssign(
|
||||
incp->fileline(),
|
||||
new AstVarRef(incp->fileline(), varp, true),
|
||||
new AstAdd(incp->fileline(),
|
||||
new AstVarRef(incp->fileline(), varp, false),
|
||||
UINFO(5, "New coverage trace: " << varp << endl);
|
||||
AstAssign* assp = new AstAssign(
|
||||
incp->fileline(), new AstVarRef(incp->fileline(), varp, true),
|
||||
new AstAdd(incp->fileline(), new AstVarRef(incp->fileline(), varp, false),
|
||||
new AstConst(incp->fileline(), AstConst::WidthedValue(), 32, 1)));
|
||||
incp->addNext(assp);
|
||||
}
|
||||
return incp;
|
||||
}
|
||||
string traceNameForLine(AstNode* nodep, const string& type) {
|
||||
return "vlCoverageLineTrace_"+nodep->fileline()->filebasenameNoExt()
|
||||
+"__"+cvtToStr(nodep->fileline()->lineno())
|
||||
+"_"+type;
|
||||
return "vlCoverageLineTrace_" + nodep->fileline()->filebasenameNoExt() + "__"
|
||||
+ cvtToStr(nodep->fileline()->lineno()) + "_" + type;
|
||||
}
|
||||
// VISITORS - BOTH
|
||||
virtual void visit(AstNodeModule* nodep) VL_OVERRIDE {
|
||||
|
|
@ -169,13 +163,13 @@ private:
|
|||
}
|
||||
virtual void visit(AstVar* nodep) VL_OVERRIDE {
|
||||
iterateChildren(nodep);
|
||||
if (m_modp && !m_inModOff && !m_inToggleOff
|
||||
&& nodep->fileline()->coverageOn() && v3Global.opt.coverageToggle()) {
|
||||
if (m_modp && !m_inModOff && !m_inToggleOff && nodep->fileline()->coverageOn()
|
||||
&& v3Global.opt.coverageToggle()) {
|
||||
const char* disablep = varIgnoreToggle(nodep);
|
||||
if (disablep) {
|
||||
UINFO(4, " Disable Toggle: "<<disablep<<" "<<nodep<<endl);
|
||||
UINFO(4, " Disable Toggle: " << disablep << " " << nodep << endl);
|
||||
} else {
|
||||
UINFO(4, " Toggle: "<<nodep<<endl);
|
||||
UINFO(4, " Toggle: " << nodep << endl);
|
||||
// There's several overall ways to approach this
|
||||
// Treat like tracing, where a end-of-timestamp action sees all changes
|
||||
// Works ok, but would be quite slow as need to reform
|
||||
|
|
@ -188,9 +182,9 @@ private:
|
|||
// We'll do this, and make the if(...) coverinc later.
|
||||
|
||||
// Add signal to hold the old value
|
||||
string newvarname = string("__Vtogcov__")+nodep->shortName();
|
||||
AstVar* chgVarp = new AstVar(nodep->fileline(),
|
||||
AstVarType::MODULETEMP, newvarname, nodep);
|
||||
string newvarname = string("__Vtogcov__") + nodep->shortName();
|
||||
AstVar* chgVarp
|
||||
= new AstVar(nodep->fileline(), AstVarType::MODULETEMP, newvarname, nodep);
|
||||
chgVarp->fileline()->modifyWarnOff(V3ErrorCode::UNUSED, true);
|
||||
m_modp->addStmtp(chgVarp);
|
||||
|
||||
|
|
@ -198,123 +192,108 @@ private:
|
|||
// This is necessarily an O(n^2) expansion, which is why
|
||||
// we limit coverage to signals with < 256 bits.
|
||||
|
||||
ToggleEnt newvec (string(""),
|
||||
new AstVarRef(nodep->fileline(), nodep, false),
|
||||
new AstVarRef(nodep->fileline(), chgVarp, true));
|
||||
toggleVarRecurse(nodep->dtypeSkipRefp(), 0, newvec,
|
||||
nodep, chgVarp);
|
||||
ToggleEnt newvec(string(""), new AstVarRef(nodep->fileline(), nodep, false),
|
||||
new AstVarRef(nodep->fileline(), chgVarp, true));
|
||||
toggleVarRecurse(nodep->dtypeSkipRefp(), 0, newvec, nodep, chgVarp);
|
||||
newvec.cleanup();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void toggleVarBottom(const ToggleEnt& above, const AstVar* varp) {
|
||||
AstCoverToggle* newp
|
||||
= new AstCoverToggle(varp->fileline(),
|
||||
newCoverInc(varp->fileline(), "", "v_toggle",
|
||||
varp->name()+above.m_comment, ""),
|
||||
above.m_varRefp->cloneTree(true),
|
||||
above.m_chgRefp->cloneTree(true));
|
||||
AstCoverToggle* newp = new AstCoverToggle(
|
||||
varp->fileline(),
|
||||
newCoverInc(varp->fileline(), "", "v_toggle", varp->name() + above.m_comment, ""),
|
||||
above.m_varRefp->cloneTree(true), above.m_chgRefp->cloneTree(true));
|
||||
m_modp->addStmtp(newp);
|
||||
}
|
||||
|
||||
void toggleVarRecurse(AstNodeDType* dtypep, int depth, // per-iteration
|
||||
const ToggleEnt& above,
|
||||
AstVar* varp, AstVar* chgVarp) { // Constant
|
||||
const ToggleEnt& above, AstVar* varp, AstVar* chgVarp) { // Constant
|
||||
if (const AstBasicDType* bdtypep = VN_CAST(dtypep, BasicDType)) {
|
||||
if (bdtypep->isRanged()) {
|
||||
for (int index_docs=bdtypep->lsb(); index_docs<bdtypep->msb()+1; index_docs++) {
|
||||
for (int index_docs = bdtypep->lsb(); index_docs < bdtypep->msb() + 1;
|
||||
index_docs++) {
|
||||
int index_code = index_docs - bdtypep->lsb();
|
||||
ToggleEnt newent (above.m_comment+string("[")+cvtToStr(index_docs)+"]",
|
||||
new AstSel(varp->fileline(),
|
||||
above.m_varRefp->cloneTree(true), index_code, 1),
|
||||
new AstSel(varp->fileline(),
|
||||
above.m_chgRefp->cloneTree(true), index_code, 1));
|
||||
ToggleEnt newent(above.m_comment + string("[") + cvtToStr(index_docs) + "]",
|
||||
new AstSel(varp->fileline(), above.m_varRefp->cloneTree(true),
|
||||
index_code, 1),
|
||||
new AstSel(varp->fileline(), above.m_chgRefp->cloneTree(true),
|
||||
index_code, 1));
|
||||
toggleVarBottom(newent, varp);
|
||||
newent.cleanup();
|
||||
}
|
||||
} else {
|
||||
toggleVarBottom(above, varp);
|
||||
}
|
||||
}
|
||||
else if (AstUnpackArrayDType* adtypep = VN_CAST(dtypep, UnpackArrayDType)) {
|
||||
for (int index_docs=adtypep->lsb(); index_docs<=adtypep->msb(); ++index_docs) {
|
||||
} else if (AstUnpackArrayDType* adtypep = VN_CAST(dtypep, UnpackArrayDType)) {
|
||||
for (int index_docs = adtypep->lsb(); index_docs <= adtypep->msb(); ++index_docs) {
|
||||
int index_code = index_docs - adtypep->lsb();
|
||||
ToggleEnt newent (above.m_comment+string("[")+cvtToStr(index_docs)+"]",
|
||||
new AstArraySel(varp->fileline(),
|
||||
above.m_varRefp->cloneTree(true), index_code),
|
||||
new AstArraySel(varp->fileline(),
|
||||
above.m_chgRefp->cloneTree(true), index_code));
|
||||
toggleVarRecurse(adtypep->subDTypep()->skipRefp(), depth+1,
|
||||
newent,
|
||||
varp, chgVarp);
|
||||
ToggleEnt newent(above.m_comment + string("[") + cvtToStr(index_docs) + "]",
|
||||
new AstArraySel(varp->fileline(),
|
||||
above.m_varRefp->cloneTree(true), index_code),
|
||||
new AstArraySel(varp->fileline(),
|
||||
above.m_chgRefp->cloneTree(true), index_code));
|
||||
toggleVarRecurse(adtypep->subDTypep()->skipRefp(), depth + 1, newent, varp,
|
||||
chgVarp);
|
||||
newent.cleanup();
|
||||
}
|
||||
}
|
||||
else if (AstPackArrayDType* adtypep = VN_CAST(dtypep, PackArrayDType)) {
|
||||
for (int index_docs=adtypep->lsb(); index_docs<=adtypep->msb(); ++index_docs) {
|
||||
} else if (AstPackArrayDType* adtypep = VN_CAST(dtypep, PackArrayDType)) {
|
||||
for (int index_docs = adtypep->lsb(); index_docs <= adtypep->msb(); ++index_docs) {
|
||||
AstNodeDType* subtypep = adtypep->subDTypep()->skipRefp();
|
||||
int index_code = index_docs - adtypep->lsb();
|
||||
ToggleEnt newent (above.m_comment+string("[")+cvtToStr(index_docs)+"]",
|
||||
new AstSel(varp->fileline(), above.m_varRefp->cloneTree(true),
|
||||
index_code*subtypep->width(), subtypep->width()),
|
||||
new AstSel(varp->fileline(), above.m_chgRefp->cloneTree(true),
|
||||
index_code*subtypep->width(), subtypep->width()));
|
||||
toggleVarRecurse(adtypep->subDTypep()->skipRefp(), depth+1,
|
||||
newent,
|
||||
varp, chgVarp);
|
||||
ToggleEnt newent(above.m_comment + string("[") + cvtToStr(index_docs) + "]",
|
||||
new AstSel(varp->fileline(), above.m_varRefp->cloneTree(true),
|
||||
index_code * subtypep->width(), subtypep->width()),
|
||||
new AstSel(varp->fileline(), above.m_chgRefp->cloneTree(true),
|
||||
index_code * subtypep->width(), subtypep->width()));
|
||||
toggleVarRecurse(adtypep->subDTypep()->skipRefp(), depth + 1, newent, varp,
|
||||
chgVarp);
|
||||
newent.cleanup();
|
||||
}
|
||||
}
|
||||
else if (AstStructDType* adtypep = VN_CAST(dtypep, StructDType)) {
|
||||
} else if (AstStructDType* adtypep = VN_CAST(dtypep, StructDType)) {
|
||||
// For now it's packed, so similar to array
|
||||
for (AstMemberDType* itemp = adtypep->membersp();
|
||||
itemp; itemp=VN_CAST(itemp->nextp(), MemberDType)) {
|
||||
for (AstMemberDType* itemp = adtypep->membersp(); itemp;
|
||||
itemp = VN_CAST(itemp->nextp(), MemberDType)) {
|
||||
AstNodeDType* subtypep = itemp->subDTypep()->skipRefp();
|
||||
int index_code = itemp->lsb();
|
||||
ToggleEnt newent (above.m_comment+string(".")+itemp->name(),
|
||||
new AstSel(varp->fileline(), above.m_varRefp->cloneTree(true),
|
||||
index_code, subtypep->width()),
|
||||
new AstSel(varp->fileline(), above.m_chgRefp->cloneTree(true),
|
||||
index_code, subtypep->width()));
|
||||
toggleVarRecurse(subtypep, depth+1,
|
||||
newent,
|
||||
varp, chgVarp);
|
||||
ToggleEnt newent(above.m_comment + string(".") + itemp->name(),
|
||||
new AstSel(varp->fileline(), above.m_varRefp->cloneTree(true),
|
||||
index_code, subtypep->width()),
|
||||
new AstSel(varp->fileline(), above.m_chgRefp->cloneTree(true),
|
||||
index_code, subtypep->width()));
|
||||
toggleVarRecurse(subtypep, depth + 1, newent, varp, chgVarp);
|
||||
newent.cleanup();
|
||||
}
|
||||
}
|
||||
else if (AstUnionDType* adtypep = VN_CAST(dtypep, UnionDType)) {
|
||||
} else if (AstUnionDType* adtypep = VN_CAST(dtypep, UnionDType)) {
|
||||
// Arbitrarily handle only the first member of the union
|
||||
if (AstMemberDType* itemp = adtypep->membersp()) {
|
||||
AstNodeDType* subtypep = itemp->subDTypep()->skipRefp();
|
||||
ToggleEnt newent (above.m_comment+string(".")+itemp->name(),
|
||||
above.m_varRefp->cloneTree(true),
|
||||
above.m_chgRefp->cloneTree(true));
|
||||
toggleVarRecurse(subtypep, depth+1,
|
||||
newent,
|
||||
varp, chgVarp);
|
||||
ToggleEnt newent(above.m_comment + string(".") + itemp->name(),
|
||||
above.m_varRefp->cloneTree(true),
|
||||
above.m_chgRefp->cloneTree(true));
|
||||
toggleVarRecurse(subtypep, depth + 1, newent, varp, chgVarp);
|
||||
newent.cleanup();
|
||||
}
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
dtypep->v3fatalSrc("Unexpected node data type in toggle coverage generation: "
|
||||
<<dtypep->prettyTypeName());
|
||||
<< dtypep->prettyTypeName());
|
||||
}
|
||||
}
|
||||
|
||||
// VISITORS - LINE COVERAGE
|
||||
virtual void visit(AstIf* nodep) VL_OVERRIDE { // Note not AstNodeIf; other types don't get covered
|
||||
UINFO(4," IF: "<<nodep<<endl);
|
||||
virtual void
|
||||
visit(AstIf* nodep) VL_OVERRIDE { // Note not AstNodeIf; other types don't get covered
|
||||
UINFO(4, " IF: " << nodep << endl);
|
||||
if (m_checkBlock) {
|
||||
// An else-if. When we iterate the if, use "elsif" marking
|
||||
bool elsif = (VN_IS(nodep->elsesp(), If)
|
||||
&& !VN_CAST(nodep->elsesp(), If)->nextp());
|
||||
bool elsif = (VN_IS(nodep->elsesp(), If) && !VN_CAST(nodep->elsesp(), If)->nextp());
|
||||
if (elsif) VN_CAST(nodep->elsesp(), If)->user1(true);
|
||||
//
|
||||
iterateAndNextNull(nodep->ifsp());
|
||||
if (m_checkBlock && !m_inModOff
|
||||
&& nodep->fileline()->coverageOn() && v3Global.opt.coverageLine()) { // if a "if" branch didn't disable it
|
||||
UINFO(4," COVER: "<<nodep<<endl);
|
||||
if (m_checkBlock && !m_inModOff && nodep->fileline()->coverageOn()
|
||||
&& v3Global.opt.coverageLine()) { // if a "if" branch didn't disable it
|
||||
UINFO(4, " COVER: " << nodep << endl);
|
||||
if (nodep->user1()) {
|
||||
nodep->addIfsp(newCoverInc(nodep->fileline(), "", "v_line", "elsif",
|
||||
traceNameForLine(nodep, "elsif")));
|
||||
|
|
@ -327,13 +306,12 @@ private:
|
|||
if (nodep->elsesp()) {
|
||||
m_checkBlock = true;
|
||||
iterateAndNextNull(nodep->elsesp());
|
||||
if (m_checkBlock && !m_inModOff
|
||||
&& nodep->fileline()->coverageOn() && v3Global.opt.coverageLine()) { // if a "else" branch didn't disable it
|
||||
UINFO(4," COVER: "<<nodep<<endl);
|
||||
if (m_checkBlock && !m_inModOff && nodep->fileline()->coverageOn()
|
||||
&& v3Global.opt.coverageLine()) { // if a "else" branch didn't disable it
|
||||
UINFO(4, " COVER: " << nodep << endl);
|
||||
if (!elsif) { // elsif done inside if()
|
||||
nodep->addElsesp(newCoverInc(nodep->elsesp()->fileline(),
|
||||
"", "v_line", "else",
|
||||
traceNameForLine(nodep, "else")));
|
||||
nodep->addElsesp(newCoverInc(nodep->elsesp()->fileline(), "", "v_line",
|
||||
"else", traceNameForLine(nodep, "else")));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -341,12 +319,12 @@ private:
|
|||
}
|
||||
}
|
||||
virtual void visit(AstCaseItem* nodep) VL_OVERRIDE {
|
||||
UINFO(4," CASEI: "<<nodep<<endl);
|
||||
if (m_checkBlock && !m_inModOff
|
||||
&& nodep->fileline()->coverageOn() && v3Global.opt.coverageLine()) {
|
||||
UINFO(4, " CASEI: " << nodep << endl);
|
||||
if (m_checkBlock && !m_inModOff && nodep->fileline()->coverageOn()
|
||||
&& v3Global.opt.coverageLine()) {
|
||||
iterateAndNextNull(nodep->bodysp());
|
||||
if (m_checkBlock) { // if the case body didn't disable it
|
||||
UINFO(4," COVER: "<<nodep<<endl);
|
||||
UINFO(4, " COVER: " << nodep << endl);
|
||||
nodep->addBodysp(newCoverInc(nodep->fileline(), "", "v_line", "case",
|
||||
traceNameForLine(nodep, "case")));
|
||||
}
|
||||
|
|
@ -354,24 +332,24 @@ private:
|
|||
}
|
||||
}
|
||||
virtual void visit(AstCover* nodep) VL_OVERRIDE {
|
||||
UINFO(4," COVER: "<<nodep<<endl);
|
||||
UINFO(4, " COVER: " << nodep << endl);
|
||||
m_checkBlock = true; // Always do cover blocks, even if there's a $stop
|
||||
iterateChildren(nodep);
|
||||
if (!nodep->coverincp()) {
|
||||
// Note the name may be overridden by V3Assert processing
|
||||
nodep->coverincp(newCoverInc(nodep->fileline(), m_beginHier, "v_user", "cover",
|
||||
m_beginHier+"_vlCoverageUserTrace"));
|
||||
m_beginHier + "_vlCoverageUserTrace"));
|
||||
}
|
||||
m_checkBlock = true; // Reset as a child may have cleared it
|
||||
}
|
||||
virtual void visit(AstStop* nodep) VL_OVERRIDE {
|
||||
UINFO(4," STOP: "<<nodep<<endl);
|
||||
UINFO(4, " STOP: " << nodep << endl);
|
||||
m_checkBlock = false;
|
||||
}
|
||||
virtual void visit(AstPragma* nodep) VL_OVERRIDE {
|
||||
if (nodep->pragType() == AstPragmaType::COVERAGE_BLOCK_OFF) {
|
||||
// Skip all NEXT nodes under this block, and skip this if/case branch
|
||||
UINFO(4," OFF: "<<nodep<<endl);
|
||||
UINFO(4, " OFF: " << nodep << endl);
|
||||
m_checkBlock = false;
|
||||
VL_DO_DANGLING(nodep->unlinkFrBack()->deleteTree(), nodep);
|
||||
} else {
|
||||
|
|
@ -388,8 +366,8 @@ private:
|
|||
bool oldtog = m_inToggleOff;
|
||||
{
|
||||
m_inToggleOff = true;
|
||||
if (nodep->name()!="") {
|
||||
m_beginHier = m_beginHier + (m_beginHier!=""?".":"") + nodep->name();
|
||||
if (nodep->name() != "") {
|
||||
m_beginHier = m_beginHier + (m_beginHier != "" ? "." : "") + nodep->name();
|
||||
}
|
||||
iterateChildren(nodep);
|
||||
}
|
||||
|
|
@ -423,9 +401,7 @@ public:
|
|||
// Coverage class functions
|
||||
|
||||
void V3Coverage::coverage(AstNetlist* rootp) {
|
||||
UINFO(2,__FUNCTION__<<": "<<endl);
|
||||
{
|
||||
CoverageVisitor visitor (rootp);
|
||||
} // Destruct before checking
|
||||
UINFO(2, __FUNCTION__ << ": " << endl);
|
||||
{ CoverageVisitor visitor(rootp); } // Destruct before checking
|
||||
V3Global::dumpCheckGlobalTree("coverage", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,7 +17,6 @@
|
|||
// If two COVERTOGGLEs have same VARSCOPE, combine them
|
||||
//*************************************************************************
|
||||
|
||||
|
||||
#include "config_build.h"
|
||||
#include "verilatedos.h"
|
||||
|
||||
|
|
@ -38,23 +37,23 @@ private:
|
|||
// V3Hashed
|
||||
// AstCoverToggle->VarRef::user4() // V3Hashed calculation
|
||||
|
||||
//AstUser4InUse In V3Hashed
|
||||
// AstUser4InUse In V3Hashed
|
||||
|
||||
// TYPES
|
||||
typedef std::vector<AstCoverToggle*> ToggleList;
|
||||
|
||||
// STATE
|
||||
ToggleList m_toggleps; // List of of all AstCoverToggle's
|
||||
ToggleList m_toggleps; // List of of all AstCoverToggle's
|
||||
|
||||
VDouble0 m_statToggleJoins; // Statistic tracking
|
||||
VDouble0 m_statToggleJoins; // Statistic tracking
|
||||
|
||||
// METHODS
|
||||
VL_DEBUG_FUNC; // Declare debug()
|
||||
|
||||
void detectDuplicates() {
|
||||
UINFO(9,"Finding duplicates\n");
|
||||
UINFO(9, "Finding duplicates\n");
|
||||
// Note uses user4
|
||||
V3Hashed hashed; // Duplicate code detection
|
||||
V3Hashed hashed; // Duplicate code detection
|
||||
// Hash all of the original signals we toggle cover
|
||||
for (ToggleList::iterator it = m_toggleps.begin(); it != m_toggleps.end(); ++it) {
|
||||
AstCoverToggle* nodep = *it;
|
||||
|
|
@ -78,17 +77,18 @@ private:
|
|||
// covertoggle which is immediately above, so:
|
||||
AstCoverToggle* removep = VN_CAST(duporigp->backp(), CoverToggle);
|
||||
UASSERT_OBJ(removep, nodep, "CoverageJoin duplicate of wrong type");
|
||||
UINFO(8," Orig "<<nodep<<" -->> "<<nodep->incp()->declp()<<endl);
|
||||
UINFO(8," dup "<<removep<<" -->> "<<removep->incp()->declp()<<endl);
|
||||
UINFO(8, " Orig " << nodep << " -->> " << nodep->incp()->declp() << endl);
|
||||
UINFO(8, " dup " << removep << " -->> " << removep->incp()->declp() << endl);
|
||||
// The CoverDecl the duplicate pointed to now needs to point to the
|
||||
// original's data. I.e. the duplicate will get the coverage number
|
||||
// from the non-duplicate
|
||||
AstCoverDecl* datadeclp = nodep->incp()->declp()->dataDeclThisp();
|
||||
removep->incp()->declp()->dataDeclp(datadeclp);
|
||||
UINFO(8," new "<<removep->incp()->declp()<<endl);
|
||||
UINFO(8, " new " << removep->incp()->declp() << endl);
|
||||
// Mark the found node as a duplicate of the first node
|
||||
// (Not vice-versa as we have the iterator for the found node)
|
||||
removep->unlinkFrBack(); VL_DO_DANGLING(pushDeletep(removep), removep);
|
||||
removep->unlinkFrBack();
|
||||
VL_DO_DANGLING(pushDeletep(removep), removep);
|
||||
// Remove node from comparison so don't hit it again
|
||||
hashed.erase(dupit);
|
||||
++m_statToggleJoins;
|
||||
|
|
@ -114,9 +114,7 @@ private:
|
|||
|
||||
public:
|
||||
// CONSTRUCTORS
|
||||
explicit CoverageJoinVisitor(AstNetlist* nodep) {
|
||||
iterate(nodep);
|
||||
}
|
||||
explicit CoverageJoinVisitor(AstNetlist* nodep) { iterate(nodep); }
|
||||
virtual ~CoverageJoinVisitor() {
|
||||
V3Stats::addStat("Coverage, Toggle points joined", m_statToggleJoins);
|
||||
}
|
||||
|
|
@ -126,9 +124,7 @@ public:
|
|||
// Coverage class functions
|
||||
|
||||
void V3CoverageJoin::coverageJoin(AstNetlist* rootp) {
|
||||
UINFO(2,__FUNCTION__<<": "<<endl);
|
||||
{
|
||||
CoverageJoinVisitor visitor (rootp);
|
||||
} // Destruct before checking
|
||||
UINFO(2, __FUNCTION__ << ": " << endl);
|
||||
{ CoverageJoinVisitor visitor(rootp); } // Destruct before checking
|
||||
V3Global::dumpCheckGlobalTree("coveragejoin", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -40,20 +40,20 @@ private:
|
|||
// NODE STATE
|
||||
|
||||
// STATE
|
||||
AstNodeModule* m_modp; // Current module
|
||||
AstCFunc* m_funcp; // Current block
|
||||
AstNode* m_stmtp; // Current statement
|
||||
int m_depth; // How deep in an expression
|
||||
int m_maxdepth; // Maximum depth in an expression
|
||||
AstNodeModule* m_modp; // Current module
|
||||
AstCFunc* m_funcp; // Current block
|
||||
AstNode* m_stmtp; // Current statement
|
||||
int m_depth; // How deep in an expression
|
||||
int m_maxdepth; // Maximum depth in an expression
|
||||
|
||||
// METHODS
|
||||
VL_DEBUG_FUNC; // Declare debug()
|
||||
|
||||
void createDeepTemp(AstNode* nodep) {
|
||||
UINFO(6," Deep "<<nodep<<endl);
|
||||
//if (debug()>=9) nodep->dumpTree(cout, "deep:");
|
||||
UINFO(6, " Deep " << nodep << endl);
|
||||
// if (debug()>=9) nodep->dumpTree(cout, "deep:");
|
||||
|
||||
string newvarname = (string("__Vdeeptemp")+cvtToStr(m_modp->varNumGetInc()));
|
||||
string newvarname = (string("__Vdeeptemp") + cvtToStr(m_modp->varNumGetInc()));
|
||||
AstVar* varp = new AstVar(nodep->fileline(), AstVarType::STMTTEMP, newvarname,
|
||||
// Width, not widthMin, as we may be in
|
||||
// middle of BITSEL expression which though
|
||||
|
|
@ -69,8 +69,7 @@ private:
|
|||
nodep->replaceWith(newp);
|
||||
// Put assignment before the referencing statement
|
||||
AstAssign* assp = new AstAssign(nodep->fileline(),
|
||||
new AstVarRef(nodep->fileline(), varp, true),
|
||||
nodep);
|
||||
new AstVarRef(nodep->fileline(), varp, true), nodep);
|
||||
AstNRelinker linker2;
|
||||
m_stmtp->unlinkFrBack(&linker2);
|
||||
assp->addNext(m_stmtp);
|
||||
|
|
@ -79,7 +78,7 @@ private:
|
|||
|
||||
// VISITORS
|
||||
virtual void visit(AstNodeModule* nodep) VL_OVERRIDE {
|
||||
UINFO(4," MOD "<<nodep<<endl);
|
||||
UINFO(4, " MOD " << nodep << endl);
|
||||
AstNodeModule* origModp = m_modp;
|
||||
{
|
||||
m_modp = nodep;
|
||||
|
|
@ -110,20 +109,18 @@ private:
|
|||
}
|
||||
}
|
||||
// Operators
|
||||
virtual void visit(AstNodeTermop* nodep) VL_OVERRIDE {
|
||||
}
|
||||
virtual void visit(AstNodeTermop* nodep) VL_OVERRIDE {}
|
||||
virtual void visit(AstNodeMath* nodep) VL_OVERRIDE {
|
||||
// We have some operator defines that use 2 parens, so += 2.
|
||||
m_depth += 2;
|
||||
if (m_depth>m_maxdepth) m_maxdepth = m_depth;
|
||||
if (m_depth > m_maxdepth) m_maxdepth = m_depth;
|
||||
iterateChildren(nodep);
|
||||
m_depth -= 2;
|
||||
|
||||
if (m_stmtp
|
||||
&& (v3Global.opt.compLimitParens() >= 1) // Else compiler doesn't need it
|
||||
&& (m_maxdepth-m_depth) > v3Global.opt.compLimitParens()
|
||||
if (m_stmtp && (v3Global.opt.compLimitParens() >= 1) // Else compiler doesn't need it
|
||||
&& (m_maxdepth - m_depth) > v3Global.opt.compLimitParens()
|
||||
&& !VN_IS(nodep->backp(), NodeStmt) // Not much point if we're about to use it
|
||||
) {
|
||||
) {
|
||||
m_maxdepth = m_depth;
|
||||
createDeepTemp(nodep);
|
||||
}
|
||||
|
|
@ -135,7 +132,7 @@ private:
|
|||
void needNonStaticFunc(AstNode* nodep) {
|
||||
UASSERT_OBJ(m_funcp, nodep, "Non-static accessor not under a function");
|
||||
if (m_funcp->isStatic().trueUnknown()) {
|
||||
UINFO(5,"Mark non-public due to "<<nodep<<endl);
|
||||
UINFO(5, "Mark non-public due to " << nodep << endl);
|
||||
m_funcp->isStatic(false);
|
||||
}
|
||||
}
|
||||
|
|
@ -171,9 +168,7 @@ public:
|
|||
// Depth class functions
|
||||
|
||||
void V3Depth::depthAll(AstNetlist* nodep) {
|
||||
UINFO(2,__FUNCTION__<<": "<<endl);
|
||||
{
|
||||
DepthVisitor visitor (nodep);
|
||||
} // Destruct before checking
|
||||
UINFO(2, __FUNCTION__ << ": " << endl);
|
||||
{ DepthVisitor visitor(nodep); } // Destruct before checking
|
||||
V3Global::dumpCheckGlobalTree("depth", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 6);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -38,10 +38,10 @@ private:
|
|||
// NODE STATE
|
||||
|
||||
// STATE
|
||||
AstNodeModule* m_modp; // Current module
|
||||
AstCFunc* m_funcp; // Current function
|
||||
int m_depth; // How deep in an expression
|
||||
int m_deepNum; // How many functions made
|
||||
AstNodeModule* m_modp; // Current module
|
||||
AstCFunc* m_funcp; // Current function
|
||||
int m_depth; // How deep in an expression
|
||||
int m_deepNum; // How many functions made
|
||||
|
||||
// METHODS
|
||||
VL_DEBUG_FUNC; // Declare debug()
|
||||
|
|
@ -50,7 +50,7 @@ private:
|
|||
AstNRelinker relinkHandle;
|
||||
nodep->unlinkFrBack(&relinkHandle);
|
||||
// Create function
|
||||
string name = m_funcp->name()+"__deep"+cvtToStr(++m_deepNum);
|
||||
string name = m_funcp->name() + "__deep" + cvtToStr(++m_deepNum);
|
||||
AstCFunc* funcp = new AstCFunc(nodep->fileline(), name, NULL);
|
||||
funcp->argTypes(EmitCBaseVisitor::symClassVar());
|
||||
funcp->symProlog(true);
|
||||
|
|
@ -60,7 +60,7 @@ private:
|
|||
// Call it at the point where the body was removed from
|
||||
AstCCall* callp = new AstCCall(nodep->fileline(), funcp);
|
||||
callp->argTypes("vlSymsp");
|
||||
UINFO(6," New "<<callp<<endl);
|
||||
UINFO(6, " New " << callp << endl);
|
||||
//
|
||||
relinkHandle.relink(callp);
|
||||
return funcp;
|
||||
|
|
@ -68,7 +68,7 @@ private:
|
|||
|
||||
// VISITORS
|
||||
virtual void visit(AstNodeModule* nodep) VL_OVERRIDE {
|
||||
UINFO(4," MOD "<<nodep<<endl);
|
||||
UINFO(4, " MOD " << nodep << endl);
|
||||
AstNodeModule* origModp = m_modp;
|
||||
{
|
||||
m_modp = nodep;
|
||||
|
|
@ -93,13 +93,13 @@ private:
|
|||
m_depth++;
|
||||
if (m_depth > v3Global.opt.compLimitBlocks()
|
||||
&& !VN_IS(nodep, NodeCCall)) { // Already done
|
||||
UINFO(4, "DeepBlocks "<<m_depth<<" "<<nodep<<endl);
|
||||
UINFO(4, "DeepBlocks " << m_depth << " " << nodep << endl);
|
||||
AstNode* backp = nodep->backp(); // Only for debug
|
||||
if (debug()>=9) backp->dumpTree(cout, "- pre : ");
|
||||
if (debug() >= 9) backp->dumpTree(cout, "- pre : ");
|
||||
AstCFunc* funcp = createDeepFunc(nodep);
|
||||
iterate(funcp);
|
||||
if (debug()>=9) backp->dumpTree(cout, "- post: ");
|
||||
if (debug()>=9) funcp->dumpTree(cout, "- func: ");
|
||||
if (debug() >= 9) backp->dumpTree(cout, "- post: ");
|
||||
if (debug() >= 9) funcp->dumpTree(cout, "- func: ");
|
||||
} else {
|
||||
iterateChildren(nodep);
|
||||
}
|
||||
|
|
@ -135,9 +135,7 @@ public:
|
|||
// DepthBlock class functions
|
||||
|
||||
void V3DepthBlock::depthBlockAll(AstNetlist* nodep) {
|
||||
UINFO(2,__FUNCTION__<<": "<<endl);
|
||||
{
|
||||
DepthBlockVisitor visitor (nodep);
|
||||
} // Destruct before checking
|
||||
UINFO(2, __FUNCTION__ << ": " << endl);
|
||||
{ DepthBlockVisitor visitor(nodep); } // Destruct before checking
|
||||
V3Global::dumpCheckGlobalTree("deepblock", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -119,8 +119,7 @@ private:
|
|||
} else if (relativeRefOk && scopep == m_scopep) {
|
||||
m_needThis = true;
|
||||
return "this->";
|
||||
} else if (relativeRefOk && scopep->aboveScopep()
|
||||
&& scopep->aboveScopep()==m_scopep) {
|
||||
} else if (relativeRefOk && scopep->aboveScopep() && scopep->aboveScopep() == m_scopep) {
|
||||
// Reference to scope of cell directly under this module, can just "cell->"
|
||||
string name = scopep->name();
|
||||
string::size_type pos;
|
||||
|
|
@ -179,8 +178,8 @@ private:
|
|||
UASSERT_OBJ(funcp->scopep(), funcp, "Not scoped");
|
||||
|
||||
UINFO(6, " Wrapping " << name << " " << funcp << endl);
|
||||
UINFO(6, " at " << newfuncp->argTypes()
|
||||
<< " und " << funcp->argTypes() << endl);
|
||||
UINFO(6,
|
||||
" at " << newfuncp->argTypes() << " und " << funcp->argTypes() << endl);
|
||||
funcp->declPrivate(true);
|
||||
AstNode* argsp = NULL;
|
||||
for (AstNode* stmtp = newfuncp->argsp(); stmtp; stmtp = stmtp->nextp()) {
|
||||
|
|
@ -310,9 +309,7 @@ public:
|
|||
// Descope class functions
|
||||
|
||||
void V3Descope::descopeAll(AstNetlist* nodep) {
|
||||
UINFO(2,__FUNCTION__<<": "<<endl);
|
||||
{
|
||||
DescopeVisitor visitor (nodep);
|
||||
} // Destruct before checking
|
||||
UINFO(2, __FUNCTION__ << ": " << endl);
|
||||
{ DescopeVisitor visitor(nodep); } // Destruct before checking
|
||||
V3Global::dumpCheckGlobalTree("descope", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -107,16 +107,14 @@ class EmitCInlines : EmitCBaseVisitor {
|
|||
public:
|
||||
explicit EmitCInlines(AstNetlist* nodep) {
|
||||
iterate(nodep);
|
||||
if (v3Global.needHInlines()) {
|
||||
emitInt();
|
||||
}
|
||||
if (v3Global.needHInlines()) emitInt();
|
||||
}
|
||||
};
|
||||
|
||||
void EmitCInlines::emitInt() {
|
||||
string filename = v3Global.opt.makeDir()+"/"+topClassName()+"__Inlines.h";
|
||||
newCFile(filename, false/*slow*/, false/*source*/);
|
||||
V3OutCFile hf (filename);
|
||||
string filename = v3Global.opt.makeDir() + "/" + topClassName() + "__Inlines.h";
|
||||
newCFile(filename, false /*slow*/, false /*source*/);
|
||||
V3OutCFile hf(filename);
|
||||
m_ofp = &hf;
|
||||
|
||||
ofp()->putsHeader();
|
||||
|
|
|
|||
|
|
@ -28,10 +28,9 @@
|
|||
class V3EmitV {
|
||||
public:
|
||||
static void emitv();
|
||||
static void verilogForTree(AstNode* nodep, std::ostream& os=std::cout);
|
||||
static void verilogPrefixedTree(AstNode* nodep, std::ostream& os,
|
||||
const string& prefix, int flWidth,
|
||||
AstSenTree* domainp, bool user3mark);
|
||||
static void verilogForTree(AstNode* nodep, std::ostream& os = std::cout);
|
||||
static void verilogPrefixedTree(AstNode* nodep, std::ostream& os, const string& prefix,
|
||||
int flWidth, AstSenTree* domainp, bool user3mark);
|
||||
static void emitvFiles();
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -76,7 +76,7 @@ void V3Global::readFiles() {
|
|||
}
|
||||
|
||||
void V3Global::dumpCheckGlobalTree(const string& stagename, int newNumber, bool doDump) {
|
||||
v3Global.rootp()->dumpTreeFile(v3Global.debugFilename(stagename + ".tree", newNumber),
|
||||
false, doDump);
|
||||
v3Global.rootp()->dumpTreeFile(v3Global.debugFilename(stagename + ".tree", newNumber), false,
|
||||
doDump);
|
||||
if (v3Global.opt.stats()) V3Stats::statsStage(stagename);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,10 +17,12 @@
|
|||
#ifndef _V3GLOBAL_H_
|
||||
#define _V3GLOBAL_H_ 1
|
||||
|
||||
// clang-format off
|
||||
#include "config_build.h"
|
||||
#ifndef HAVE_CONFIG_BUILD
|
||||
# error "Something failed during ./configure as config_build.h is incomplete. Perhaps you used autoreconf, don't."
|
||||
#endif
|
||||
// clang-format on
|
||||
|
||||
#include "verilatedos.h"
|
||||
|
||||
|
|
@ -35,21 +37,19 @@ class AstNetlist;
|
|||
//======================================================================
|
||||
// Statics
|
||||
|
||||
|
||||
//######################################################################
|
||||
|
||||
class VWidthMinUsage {
|
||||
public:
|
||||
enum en {
|
||||
LINT_WIDTH,
|
||||
MATCHES_WIDTH,
|
||||
VERILOG_WIDTH
|
||||
};
|
||||
enum en { LINT_WIDTH, MATCHES_WIDTH, VERILOG_WIDTH };
|
||||
enum en m_e;
|
||||
inline VWidthMinUsage() : m_e(LINT_WIDTH) {}
|
||||
inline VWidthMinUsage()
|
||||
: m_e(LINT_WIDTH) {}
|
||||
// cppcheck-suppress noExplicitConstructor
|
||||
inline VWidthMinUsage(en _e) : m_e(_e) {}
|
||||
explicit inline VWidthMinUsage(int _e) : m_e(static_cast<en>(_e)) {}
|
||||
inline VWidthMinUsage(en _e)
|
||||
: m_e(_e) {}
|
||||
explicit inline VWidthMinUsage(int _e)
|
||||
: m_e(static_cast<en>(_e)) {}
|
||||
operator en() const { return m_e; }
|
||||
};
|
||||
inline bool operator==(const VWidthMinUsage& lhs, const VWidthMinUsage& rhs) {
|
||||
|
|
@ -97,7 +97,10 @@ public:
|
|||
, m_needTraceDumper(false)
|
||||
, m_dpi(false) {}
|
||||
AstNetlist* makeNetlist();
|
||||
void boot() { UASSERT(!m_rootp, "call once"); m_rootp = makeNetlist(); }
|
||||
void boot() {
|
||||
UASSERT(!m_rootp, "call once");
|
||||
m_rootp = makeNetlist();
|
||||
}
|
||||
void clear();
|
||||
// ACCESSORS (general)
|
||||
AstNetlist* rootp() const { return m_rootp; }
|
||||
|
|
@ -107,16 +110,18 @@ public:
|
|||
// METHODS
|
||||
void readFiles();
|
||||
void checkTree();
|
||||
static void dumpCheckGlobalTree(const string& stagename, int newNumber=0, bool doDump=true);
|
||||
static void dumpCheckGlobalTree(const string& stagename, int newNumber = 0,
|
||||
bool doDump = true);
|
||||
void assertDTypesResolved(bool flag) { m_assertDTypesResolved = flag; }
|
||||
void widthMinUsage(const VWidthMinUsage& flag) { m_widthMinUsage = flag; }
|
||||
bool constRemoveXs() const { return m_constRemoveXs; }
|
||||
void constRemoveXs(bool flag) { m_constRemoveXs = flag; }
|
||||
string debugFilename(const string& nameComment, int newNumber=0) {
|
||||
string debugFilename(const string& nameComment, int newNumber = 0) {
|
||||
++m_debugFileNumber;
|
||||
if (newNumber) m_debugFileNumber = newNumber;
|
||||
char digits[100]; sprintf(digits, "%03d", m_debugFileNumber);
|
||||
return opt.makeDir()+"/"+opt.prefix()+"_"+digits+"_"+nameComment;
|
||||
char digits[100];
|
||||
sprintf(digits, "%03d", m_debugFileNumber);
|
||||
return opt.makeDir() + "/" + opt.prefix() + "_" + digits + "_" + nameComment;
|
||||
}
|
||||
bool needC11() const { return m_needC11; }
|
||||
void needC11(bool flag) { m_needC11 = flag; }
|
||||
|
|
|
|||
137
src/V3Graph.h
137
src/V3Graph.h
|
|
@ -47,19 +47,23 @@ typedef bool (*V3EdgeFuncP)(const V3GraphEdge* edgep);
|
|||
|
||||
class GraphWay {
|
||||
public:
|
||||
enum en { FORWARD=0,
|
||||
REVERSE=1,
|
||||
NUM_WAYS=2 // NUM_WAYS is not an actual way, it's typically
|
||||
// // an array dimension or loop bound.
|
||||
enum en {
|
||||
FORWARD = 0,
|
||||
REVERSE = 1,
|
||||
NUM_WAYS = 2 // NUM_WAYS is not an actual way, it's typically
|
||||
// // an array dimension or loop bound.
|
||||
};
|
||||
enum en m_e;
|
||||
inline GraphWay() : m_e(FORWARD) {}
|
||||
inline GraphWay()
|
||||
: m_e(FORWARD) {}
|
||||
// cppcheck-suppress noExplicitConstructor
|
||||
inline GraphWay(en _e) : m_e(_e) {}
|
||||
explicit inline GraphWay(int _e) : m_e(static_cast<en>(_e)) {}
|
||||
inline GraphWay(en _e)
|
||||
: m_e(_e) {}
|
||||
explicit inline GraphWay(int _e)
|
||||
: m_e(static_cast<en>(_e)) {}
|
||||
operator en() const { return m_e; }
|
||||
const char* ascii() const {
|
||||
static const char* const names[] = { "FORWARD", "REVERSE" };
|
||||
static const char* const names[] = {"FORWARD", "REVERSE"};
|
||||
return names[m_e];
|
||||
}
|
||||
// METHODS unique to this class
|
||||
|
|
@ -78,12 +82,14 @@ private:
|
|||
// MEMBERS
|
||||
V3List<V3GraphVertex*> m_vertices; // All vertices
|
||||
static int s_debug;
|
||||
|
||||
protected:
|
||||
friend class V3GraphVertex; friend class V3GraphEdge;
|
||||
friend class V3GraphVertex;
|
||||
friend class V3GraphEdge;
|
||||
friend class GraphAcyc;
|
||||
// METHODS
|
||||
void acyclicDFS();
|
||||
void acyclicDFSIterate(V3GraphVertex *vertexp, int depth, uint32_t currentRank);
|
||||
void acyclicDFSIterate(V3GraphVertex* vertexp, int depth, uint32_t currentRank);
|
||||
void acyclicCut();
|
||||
void acyclicLoop(V3GraphVertex* vertexp, int depth);
|
||||
double orderDFSIterate(V3GraphVertex* vertexp);
|
||||
|
|
@ -91,6 +97,7 @@ protected:
|
|||
void verticesUnlink() { m_vertices.reset(); }
|
||||
// ACCESSORS
|
||||
static int debug();
|
||||
|
||||
public:
|
||||
V3Graph();
|
||||
virtual ~V3Graph();
|
||||
|
|
@ -163,10 +170,10 @@ public:
|
|||
void subtreeLoops(V3EdgeFuncP edgeFuncp, V3GraphVertex* vertexp, V3Graph* loopGraphp);
|
||||
|
||||
/// Debugging
|
||||
void dump(std::ostream& os=std::cout);
|
||||
void dump(std::ostream& os = std::cout);
|
||||
void dumpDotFile(const string& filename, bool colorAsSubgraph) const;
|
||||
void dumpDotFilePrefixed(const string& nameComment, bool colorAsSubgraph=false) const;
|
||||
void dumpDotFilePrefixedAlways(const string& nameComment, bool colorAsSubgraph=false) const;
|
||||
void dumpDotFilePrefixed(const string& nameComment, bool colorAsSubgraph = false) const;
|
||||
void dumpDotFilePrefixedAlways(const string& nameComment, bool colorAsSubgraph = false) const;
|
||||
void userClearVertices();
|
||||
void userClearEdges();
|
||||
static void selfTest();
|
||||
|
|
@ -181,17 +188,19 @@ public:
|
|||
class V3GraphVertex {
|
||||
// Vertices may be a 'gate'/wire statement OR a variable
|
||||
protected:
|
||||
friend class V3Graph; friend class V3GraphEdge;
|
||||
friend class GraphAcyc; friend class GraphAlgRank;
|
||||
friend class V3Graph;
|
||||
friend class V3GraphEdge;
|
||||
friend class GraphAcyc;
|
||||
friend class GraphAlgRank;
|
||||
V3ListEnt<V3GraphVertex*> m_vertices; // All vertices, linked list
|
||||
V3List<V3GraphEdge*> m_outs; // Outbound edges,linked list
|
||||
V3List<V3GraphEdge*> m_ins; // Inbound edges, linked list
|
||||
double m_fanout; // Order fanout
|
||||
uint32_t m_color; // Color of the node
|
||||
uint32_t m_rank; // Rank of edge
|
||||
V3List<V3GraphEdge*> m_outs; // Outbound edges,linked list
|
||||
V3List<V3GraphEdge*> m_ins; // Inbound edges, linked list
|
||||
double m_fanout; // Order fanout
|
||||
uint32_t m_color; // Color of the node
|
||||
uint32_t m_rank; // Rank of edge
|
||||
union {
|
||||
void* m_userp; // Marker for some algorithms
|
||||
uint32_t m_user; // Marker for some algorithms
|
||||
void* m_userp; // Marker for some algorithms
|
||||
uint32_t m_user; // Marker for some algorithms
|
||||
};
|
||||
// METHODS
|
||||
void verticesPushBack(V3Graph* graphp);
|
||||
|
|
@ -202,14 +211,16 @@ protected:
|
|||
protected:
|
||||
// CONSTRUCTORS
|
||||
V3GraphVertex(V3Graph* graphp, const V3GraphVertex& old);
|
||||
|
||||
public:
|
||||
explicit V3GraphVertex(V3Graph* graphp);
|
||||
//! Clone copy constructor. Doesn't copy edges or user/userp.
|
||||
virtual V3GraphVertex* clone(V3Graph* graphp) const {
|
||||
return new V3GraphVertex(graphp, *this); }
|
||||
return new V3GraphVertex(graphp, *this);
|
||||
}
|
||||
virtual ~V3GraphVertex() {}
|
||||
void unlinkEdges(V3Graph* graphp);
|
||||
void unlinkDelete(V3Graph* graphp);
|
||||
void unlinkEdges(V3Graph* graphp);
|
||||
void unlinkDelete(V3Graph* graphp);
|
||||
|
||||
// ACCESSORS
|
||||
virtual string name() const { return ""; }
|
||||
|
|
@ -227,27 +238,26 @@ public:
|
|||
if (m_fanout > rhsp->m_fanout) return 1;
|
||||
return 0;
|
||||
}
|
||||
uint32_t color() const { return m_color; }
|
||||
void color(uint32_t color) { m_color = color; }
|
||||
uint32_t rank() const { return m_rank; }
|
||||
void rank(uint32_t rank) { m_rank = rank; }
|
||||
double fanout() const { return m_fanout; }
|
||||
void user(uint32_t user) { m_user = user; }
|
||||
uint32_t user() const { return m_user; }
|
||||
void userp(void* userp) { m_userp = userp; }
|
||||
void* userp() const { return m_userp; }
|
||||
uint32_t color() const { return m_color; }
|
||||
void color(uint32_t color) { m_color = color; }
|
||||
uint32_t rank() const { return m_rank; }
|
||||
void rank(uint32_t rank) { m_rank = rank; }
|
||||
double fanout() const { return m_fanout; }
|
||||
void user(uint32_t user) { m_user = user; }
|
||||
uint32_t user() const { return m_user; }
|
||||
void userp(void* userp) { m_userp = userp; }
|
||||
void* userp() const { return m_userp; }
|
||||
// ITERATORS
|
||||
V3GraphVertex* verticesNextp() const { return m_vertices.nextp(); }
|
||||
V3GraphEdge* inBeginp() const { return m_ins.begin(); }
|
||||
bool inEmpty() const { return inBeginp()==NULL; }
|
||||
bool inSize1() const;
|
||||
uint32_t inHash() const;
|
||||
bool inEmpty() const { return inBeginp() == NULL; }
|
||||
bool inSize1() const;
|
||||
uint32_t inHash() const;
|
||||
V3GraphEdge* outBeginp() const { return m_outs.begin(); }
|
||||
bool outEmpty() const { return outBeginp()==NULL; }
|
||||
bool outSize1() const;
|
||||
uint32_t outHash() const;
|
||||
V3GraphEdge* beginp(GraphWay way) const {
|
||||
return way.forward() ? outBeginp() : inBeginp(); }
|
||||
bool outEmpty() const { return outBeginp() == NULL; }
|
||||
bool outSize1() const;
|
||||
uint32_t outHash() const;
|
||||
V3GraphEdge* beginp(GraphWay way) const { return way.forward() ? outBeginp() : inBeginp(); }
|
||||
// METHODS
|
||||
/// Error reporting
|
||||
void v3errorEnd(std::ostringstream& str) const;
|
||||
|
|
@ -269,22 +279,24 @@ public:
|
|||
// ENUMS
|
||||
enum Cutable { NOT_CUTABLE = false, CUTABLE = true }; // For passing to V3GraphEdge
|
||||
protected:
|
||||
friend class V3Graph; friend class V3GraphVertex;
|
||||
friend class GraphAcyc; friend class GraphAcycEdge;
|
||||
V3ListEnt<V3GraphEdge*> m_outs; // Next Outbound edge for same vertex (linked list)
|
||||
V3ListEnt<V3GraphEdge*> m_ins; // Next Inbound edge for same vertex (linked list)
|
||||
friend class V3Graph;
|
||||
friend class V3GraphVertex;
|
||||
friend class GraphAcyc;
|
||||
friend class GraphAcycEdge;
|
||||
V3ListEnt<V3GraphEdge*> m_outs; // Next Outbound edge for same vertex (linked list)
|
||||
V3ListEnt<V3GraphEdge*> m_ins; // Next Inbound edge for same vertex (linked list)
|
||||
//
|
||||
V3GraphVertex* m_fromp; // Vertices pointing to this edge
|
||||
V3GraphVertex* m_top; // Vertices this edge points to
|
||||
int m_weight; // Weight of the connection
|
||||
bool m_cutable; // Interconnect may be broken in order sorting
|
||||
V3GraphVertex* m_fromp; // Vertices pointing to this edge
|
||||
V3GraphVertex* m_top; // Vertices this edge points to
|
||||
int m_weight; // Weight of the connection
|
||||
bool m_cutable; // Interconnect may be broken in order sorting
|
||||
union {
|
||||
void* m_userp; // Marker for some algorithms
|
||||
uint32_t m_user; // Marker for some algorithms
|
||||
void* m_userp; // Marker for some algorithms
|
||||
uint32_t m_user; // Marker for some algorithms
|
||||
};
|
||||
// METHODS
|
||||
void init(V3Graph* graphp, V3GraphVertex* fromp, V3GraphVertex* top,
|
||||
int weight, bool cutable=false);
|
||||
void init(V3Graph* graphp, V3GraphVertex* fromp, V3GraphVertex* top, int weight,
|
||||
bool cutable = false);
|
||||
void cut() { m_weight = 0; } // 0 weight is same as disconnected
|
||||
void outPushBack();
|
||||
void inPushBack();
|
||||
|
|
@ -294,21 +306,23 @@ protected:
|
|||
const V3GraphEdge& old) {
|
||||
init(graphp, fromp, top, old.m_weight, old.m_cutable);
|
||||
}
|
||||
|
||||
public:
|
||||
//! Add DAG from one node to the specified node
|
||||
V3GraphEdge(V3Graph* graphp, V3GraphVertex* fromp, V3GraphVertex* top,
|
||||
int weight, bool cutable=false) {
|
||||
V3GraphEdge(V3Graph* graphp, V3GraphVertex* fromp, V3GraphVertex* top, int weight,
|
||||
bool cutable = false) {
|
||||
init(graphp, fromp, top, weight, cutable);
|
||||
}
|
||||
//! Clone copy constructor. Doesn't copy existing vertices or user/userp.
|
||||
virtual V3GraphEdge* clone(V3Graph* graphp, V3GraphVertex* fromp, V3GraphVertex* top) const {
|
||||
return new V3GraphEdge(graphp, fromp, top, *this); }
|
||||
return new V3GraphEdge(graphp, fromp, top, *this);
|
||||
}
|
||||
virtual ~V3GraphEdge() {}
|
||||
// METHODS
|
||||
virtual string name() const { return m_fromp->name()+"->"+m_top->name(); }
|
||||
virtual string name() const { return m_fromp->name() + "->" + m_top->name(); }
|
||||
virtual string dotLabel() const { return ""; }
|
||||
virtual string dotColor() const { return cutable()?"yellowGreen":"red"; }
|
||||
virtual string dotStyle() const { return cutable()?"dashed":""; }
|
||||
virtual string dotColor() const { return cutable() ? "yellowGreen" : "red"; }
|
||||
virtual string dotStyle() const { return cutable() ? "dashed" : ""; }
|
||||
virtual int sortCmp(const V3GraphEdge* rhsp) const {
|
||||
if (!m_weight || !rhsp->m_weight) return 0;
|
||||
return top()->sortCmp(rhsp->top());
|
||||
|
|
@ -334,8 +348,7 @@ public:
|
|||
// ITERATORS
|
||||
V3GraphEdge* outNextp() const { return m_outs.nextp(); }
|
||||
V3GraphEdge* inNextp() const { return m_ins.nextp(); }
|
||||
V3GraphEdge* nextp(GraphWay way) const {
|
||||
return way.forward() ? outNextp() : inNextp(); }
|
||||
V3GraphEdge* nextp(GraphWay way) const { return way.forward() ? outNextp() : inNextp(); }
|
||||
};
|
||||
|
||||
//============================================================================
|
||||
|
|
|
|||
|
|
@ -32,8 +32,8 @@
|
|||
|
||||
DfaVertex* DfaGraph::findStart() {
|
||||
DfaVertex* startp = NULL;
|
||||
for (V3GraphVertex* vertexp = this->verticesBeginp();
|
||||
vertexp; vertexp=vertexp->verticesNextp()) {
|
||||
for (V3GraphVertex* vertexp = this->verticesBeginp(); vertexp;
|
||||
vertexp = vertexp->verticesNextp()) {
|
||||
if (DfaVertex* vvertexp = dynamic_cast<DfaVertex*>(vertexp)) {
|
||||
if (vvertexp->start()) {
|
||||
UASSERT_OBJ(!startp, vertexp, "Multiple start points in NFA graph");
|
||||
|
|
@ -60,11 +60,11 @@ class GraphNfaToDfa : GraphAlg<> {
|
|||
private:
|
||||
// TYPES
|
||||
typedef std::deque<DfaVertex*> DfaStates;
|
||||
typedef std::multimap<vluint64_t,DfaVertex*> HashMap;
|
||||
typedef std::multimap<vluint64_t, DfaVertex*> HashMap;
|
||||
|
||||
// MEMBERS
|
||||
uint32_t m_step; // Processing step, so we can avoid clearUser all the time
|
||||
HashMap m_hashMap; // Dfa Vertex for each set of NFA vertexes
|
||||
uint32_t m_step; // Processing step, so we can avoid clearUser all the time
|
||||
HashMap m_hashMap; // Dfa Vertex for each set of NFA vertexes
|
||||
|
||||
#ifdef VL_CPPCHECK
|
||||
static int debug() { return 9; }
|
||||
|
|
@ -74,29 +74,37 @@ private:
|
|||
|
||||
// METHODS
|
||||
DfaGraph* graphp() { return static_cast<DfaGraph*>(m_graphp); }
|
||||
bool nfaState(V3GraphVertex* vertexp) { return vertexp->color()==0; }
|
||||
//bool dfaState(V3GraphVertex* vertexp) { return vertexp->color()==1; }
|
||||
bool nfaState(V3GraphVertex* vertexp) { return vertexp->color() == 0; }
|
||||
// bool dfaState(V3GraphVertex* vertexp) { return vertexp->color()==1; }
|
||||
|
||||
void nextStep() { m_step++; }
|
||||
|
||||
bool unseenNfaThisStep(V3GraphVertex* vertexp) {
|
||||
// A nfa node not already seen this processing step
|
||||
return (nfaState(vertexp) && !(vertexp->user()==m_step));
|
||||
return (nfaState(vertexp) && !(vertexp->user() == m_step));
|
||||
}
|
||||
|
||||
DfaVertex* newDfaVertex(DfaVertex* nfaTemplatep=NULL) {
|
||||
DfaVertex* newDfaVertex(DfaVertex* nfaTemplatep = NULL) {
|
||||
DfaVertex* vertexp = new DfaVertex(graphp());
|
||||
vertexp->color(1); // Mark as dfa
|
||||
if (nfaTemplatep && nfaTemplatep->start()) vertexp->start(true);
|
||||
if (nfaTemplatep && nfaTemplatep->accepting()) vertexp->accepting(true);
|
||||
UINFO(9, " New "<<vertexp<<endl);
|
||||
UINFO(9, " New " << vertexp << endl);
|
||||
return vertexp;
|
||||
}
|
||||
|
||||
// Hashing
|
||||
static uint32_t hashVertex(V3GraphVertex* vertexp) {
|
||||
union { void* up; struct {uint32_t upper; uint32_t lower;} l;} u;
|
||||
u.l.upper = 0; u.l.lower = 0; u.up = vertexp;
|
||||
union {
|
||||
void* up;
|
||||
struct {
|
||||
uint32_t upper;
|
||||
uint32_t lower;
|
||||
} l;
|
||||
} u;
|
||||
u.l.upper = 0;
|
||||
u.l.lower = 0;
|
||||
u.up = vertexp;
|
||||
return u.l.upper ^ u.l.lower;
|
||||
}
|
||||
|
||||
|
|
@ -108,8 +116,8 @@ private:
|
|||
uint32_t hash = 0;
|
||||
// Foreach NFA state (this DFA state was formed from)
|
||||
if (debug()) nextStep();
|
||||
for (V3GraphEdge* dfaEdgep = dfaStatep->outBeginp();
|
||||
dfaEdgep; dfaEdgep=dfaEdgep->outNextp()) {
|
||||
for (V3GraphEdge* dfaEdgep = dfaStatep->outBeginp(); dfaEdgep;
|
||||
dfaEdgep = dfaEdgep->outNextp()) {
|
||||
if (nfaState(dfaEdgep->top())) {
|
||||
DfaVertex* nfaStatep = static_cast<DfaVertex*>(dfaEdgep->top());
|
||||
hash ^= hashVertex(nfaStatep);
|
||||
|
|
@ -126,8 +134,8 @@ private:
|
|||
uint32_t hashDfaOrigins(const DfaStates& nfasWithInput) {
|
||||
// Find the NFA states this dfa came from,
|
||||
uint32_t hash = 0;
|
||||
for (DfaStates::const_iterator nfaIt=nfasWithInput.begin();
|
||||
nfaIt!=nfasWithInput.end(); ++nfaIt) {
|
||||
for (DfaStates::const_iterator nfaIt = nfasWithInput.begin(); nfaIt != nfasWithInput.end();
|
||||
++nfaIt) {
|
||||
DfaVertex* nfaStatep = *nfaIt;
|
||||
hash ^= hashVertex(nfaStatep);
|
||||
}
|
||||
|
|
@ -140,8 +148,8 @@ private:
|
|||
nextStep();
|
||||
// Mark all input vertexes
|
||||
int num1s = 0;
|
||||
for (DfaStates::const_iterator nfaIt=nfasWithInput.begin();
|
||||
nfaIt!=nfasWithInput.end(); ++nfaIt) {
|
||||
for (DfaStates::const_iterator nfaIt = nfasWithInput.begin(); nfaIt != nfasWithInput.end();
|
||||
++nfaIt) {
|
||||
DfaVertex* nfaStatep = *nfaIt;
|
||||
nfaStatep->user(m_step);
|
||||
num1s++;
|
||||
|
|
@ -151,7 +159,8 @@ private:
|
|||
// Check comparison; must all be marked
|
||||
// (Check all in dfa2p were in dfa1p)
|
||||
int num2s = 0;
|
||||
for (V3GraphEdge* dfaEdgep = dfa2p->outBeginp(); dfaEdgep; dfaEdgep=dfaEdgep->outNextp()) {
|
||||
for (V3GraphEdge* dfaEdgep = dfa2p->outBeginp(); dfaEdgep;
|
||||
dfaEdgep = dfaEdgep->outNextp()) {
|
||||
if (nfaState(dfaEdgep->top())) {
|
||||
if (dfaEdgep->top()->user() != m_step) return false;
|
||||
num2s++;
|
||||
|
|
@ -174,39 +183,38 @@ private:
|
|||
// not depend on order of edges
|
||||
uint32_t hash = hashDfaOrigins(nfasWithInput);
|
||||
|
||||
std::pair<HashMap::iterator,HashMap::iterator> eqrange = m_hashMap.equal_range(hash);
|
||||
std::pair<HashMap::iterator, HashMap::iterator> eqrange = m_hashMap.equal_range(hash);
|
||||
for (HashMap::iterator it = eqrange.first; it != eqrange.second; ++it) {
|
||||
DfaVertex* testp = it->second;
|
||||
if (compareDfaOrigins(nfasWithInput, testp)) {
|
||||
UINFO(9," DFA match for set: "<<testp<<endl);
|
||||
UINFO(9, " DFA match for set: " << testp << endl);
|
||||
return testp; // Identical
|
||||
}
|
||||
}
|
||||
return NULL; // No match
|
||||
}
|
||||
|
||||
void findNfasWithInput(DfaVertex* dfaStatep, DfaInput input,
|
||||
DfaStates& nfasWithInput) {
|
||||
void findNfasWithInput(DfaVertex* dfaStatep, DfaInput input, DfaStates& nfasWithInput) {
|
||||
// Return all NFA states, with the given input transition from
|
||||
// the nfa states a given dfa state was constructed from.
|
||||
nextStep();
|
||||
nfasWithInput.clear(); // NFAs with given input
|
||||
|
||||
// Foreach NFA state (this DFA state was formed from)
|
||||
for (V3GraphEdge* dfaEdgep = dfaStatep->outBeginp();
|
||||
dfaEdgep; dfaEdgep=dfaEdgep->outNextp()) {
|
||||
for (V3GraphEdge* dfaEdgep = dfaStatep->outBeginp(); dfaEdgep;
|
||||
dfaEdgep = dfaEdgep->outNextp()) {
|
||||
if (nfaState(dfaEdgep->top())) {
|
||||
DfaVertex* nfaStatep = static_cast<DfaVertex*>(dfaEdgep->top());
|
||||
// Foreach input transition (on this nfaStatep)
|
||||
for (V3GraphEdge* nfaEdgep = nfaStatep->outBeginp();
|
||||
nfaEdgep; nfaEdgep=nfaEdgep->outNextp()) {
|
||||
for (V3GraphEdge* nfaEdgep = nfaStatep->outBeginp(); nfaEdgep;
|
||||
nfaEdgep = nfaEdgep->outNextp()) {
|
||||
DfaEdge* cNfaEdgep = static_cast<DfaEdge*>(nfaEdgep);
|
||||
if (cNfaEdgep->input().toNodep() == input.toNodep()) {
|
||||
DfaVertex* nextStatep = static_cast<DfaVertex*>(cNfaEdgep->top());
|
||||
if (unseenNfaThisStep(nextStatep)) { // Not processed?
|
||||
nfasWithInput.push_back(nextStatep);
|
||||
nextStatep->user(m_step);
|
||||
UINFO(9," Reachable "<<nextStatep<<endl);
|
||||
UINFO(9, " Reachable " << nextStatep << endl);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -219,18 +227,19 @@ private:
|
|||
DfaStates nfasTodo = nfasWithInput;
|
||||
nfasWithInput.clear(); // Now the completed list
|
||||
while (!nfasTodo.empty()) {
|
||||
DfaVertex* nfaStatep = nfasTodo.front(); nfasTodo.pop_front();
|
||||
DfaVertex* nfaStatep = nfasTodo.front();
|
||||
nfasTodo.pop_front();
|
||||
nfasWithInput.push_back(nfaStatep);
|
||||
// Foreach epsilon-reachable (on this nfaStatep)
|
||||
for (V3GraphEdge* nfaEdgep = nfaStatep->outBeginp();
|
||||
nfaEdgep; nfaEdgep=nfaEdgep->outNextp()) {
|
||||
for (V3GraphEdge* nfaEdgep = nfaStatep->outBeginp(); nfaEdgep;
|
||||
nfaEdgep = nfaEdgep->outNextp()) {
|
||||
DfaEdge* cNfaEdgep = static_cast<DfaEdge*>(nfaEdgep);
|
||||
if (cNfaEdgep->epsilon()) {
|
||||
DfaVertex* nextStatep = static_cast<DfaVertex*>(cNfaEdgep->top());
|
||||
if (unseenNfaThisStep(nextStatep)) { // Not processed?
|
||||
nfasTodo.push_back(nextStatep);
|
||||
nextStatep->user(m_step);
|
||||
UINFO(9," Epsilon Reachable "<<nextStatep<<endl);
|
||||
UINFO(9, " Epsilon Reachable " << nextStatep << endl);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -239,13 +248,13 @@ private:
|
|||
}
|
||||
|
||||
void main() {
|
||||
UINFO(5,"Dfa to Nfa conversion...\n");
|
||||
UINFO(5, "Dfa to Nfa conversion...\n");
|
||||
// Vertex::color() begin: 1 indicates vertex on DFA graph, 0=NFA graph
|
||||
m_graphp->clearColors();
|
||||
// Vertex::m_user begin: # indicates processed this m_step number
|
||||
m_graphp->userClearVertices();
|
||||
|
||||
if (debug()>=6) m_graphp->dumpDotFilePrefixed("dfa_nfa");
|
||||
if (debug() >= 6) m_graphp->dumpDotFilePrefixed("dfa_nfa");
|
||||
|
||||
// Find NFA start
|
||||
DfaVertex* nfaStartp = graphp()->findStart();
|
||||
|
|
@ -256,55 +265,58 @@ private:
|
|||
DfaStates dfaUnprocps; // Unprocessed DFA nodes
|
||||
dfaUnprocps.push_back(dfaStartp);
|
||||
|
||||
UINFO(5,"Starting state conversion...\n");
|
||||
UINFO(5, "Starting state conversion...\n");
|
||||
// Form DFA starting state from epsilon closure of NFA start
|
||||
nextStep();
|
||||
DfaStates workps; workps.push_back(nfaStartp);
|
||||
DfaStates workps;
|
||||
workps.push_back(nfaStartp);
|
||||
|
||||
while (!workps.empty()) { // While work
|
||||
DfaVertex* nfaStatep = workps.back(); workps.pop_back();
|
||||
//UINFO(9," Processing "<<nfaStatep<<endl);
|
||||
DfaVertex* nfaStatep = workps.back();
|
||||
workps.pop_back();
|
||||
// UINFO(9," Processing "<<nfaStatep<<endl);
|
||||
nfaStatep->user(m_step); // Mark as processed
|
||||
// Add a edge so we can find NFAs from a given DFA.
|
||||
// The NFA will never see this edge, because we only look at TO edges.
|
||||
new DfaEdge(graphp(), dfaStartp, nfaStatep, DfaEdge::NA());
|
||||
// Find epsilon closure of this nfa node, and destinations to work list
|
||||
for (V3GraphEdge* nfaEdgep = nfaStatep->outBeginp();
|
||||
nfaEdgep; nfaEdgep=nfaEdgep->outNextp()) {
|
||||
for (V3GraphEdge* nfaEdgep = nfaStatep->outBeginp(); nfaEdgep;
|
||||
nfaEdgep = nfaEdgep->outNextp()) {
|
||||
DfaEdge* cNfaEdgep = static_cast<DfaEdge*>(nfaEdgep);
|
||||
DfaVertex* ecNfaStatep = static_cast<DfaVertex*>(nfaEdgep->top());
|
||||
//UINFO(9," Consider "<<nfaEdgep->top()<<" EP "<<cNfaEdgep->epsilon()<<endl);
|
||||
if (cNfaEdgep->epsilon()
|
||||
&& unseenNfaThisStep(ecNfaStatep)) { // Not processed?
|
||||
// UINFO(9," Consider "<<nfaEdgep->top()<<" EP "<<cNfaEdgep->epsilon()<<endl);
|
||||
if (cNfaEdgep->epsilon() && unseenNfaThisStep(ecNfaStatep)) { // Not processed?
|
||||
workps.push_back(ecNfaStatep);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (debug()>=6) m_graphp->dumpDotFilePrefixed("dfa_start");
|
||||
if (debug() >= 6) m_graphp->dumpDotFilePrefixed("dfa_start");
|
||||
insertDfaOrigins(dfaStartp);
|
||||
|
||||
int i = 0;
|
||||
UINFO(5,"Main state conversion...\n");
|
||||
UINFO(5, "Main state conversion...\n");
|
||||
while (!dfaUnprocps.empty()) {
|
||||
DfaVertex* dfaStatep = dfaUnprocps.back(); dfaUnprocps.pop_back();
|
||||
UINFO(9," On dfaState "<<dfaStatep<<endl);
|
||||
DfaVertex* dfaStatep = dfaUnprocps.back();
|
||||
dfaUnprocps.pop_back();
|
||||
UINFO(9, " On dfaState " << dfaStatep << endl);
|
||||
|
||||
// From this dfaState, what corresponding nfaStates have what inputs?
|
||||
std::set<int> inputs;
|
||||
// Foreach NFA state (this DFA state was formed from)
|
||||
for (V3GraphEdge* dfaEdgep = dfaStatep->outBeginp();
|
||||
dfaEdgep; dfaEdgep=dfaEdgep->outNextp()) {
|
||||
for (V3GraphEdge* dfaEdgep = dfaStatep->outBeginp(); dfaEdgep;
|
||||
dfaEdgep = dfaEdgep->outNextp()) {
|
||||
if (nfaState(dfaEdgep->top())) {
|
||||
DfaVertex* nfaStatep = static_cast<DfaVertex*>(dfaEdgep->top());
|
||||
// Foreach input on this nfaStatep
|
||||
for (V3GraphEdge* nfaEdgep = nfaStatep->outBeginp();
|
||||
nfaEdgep; nfaEdgep=nfaEdgep->outNextp()) {
|
||||
for (V3GraphEdge* nfaEdgep = nfaStatep->outBeginp(); nfaEdgep;
|
||||
nfaEdgep = nfaEdgep->outNextp()) {
|
||||
DfaEdge* cNfaEdgep = static_cast<DfaEdge*>(nfaEdgep);
|
||||
if (!cNfaEdgep->epsilon()) {
|
||||
if (inputs.find(cNfaEdgep->input().toInt()) == inputs.end()) {
|
||||
inputs.insert(cNfaEdgep->input().toInt());
|
||||
UINFO(9," Input to "<<dfaStatep<<" is "
|
||||
<<(cNfaEdgep->input().toInt())<<" via "<<nfaStatep<<endl);
|
||||
UINFO(9, " Input to " << dfaStatep << " is "
|
||||
<< (cNfaEdgep->input().toInt()) << " via "
|
||||
<< nfaStatep << endl);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -312,14 +324,15 @@ private:
|
|||
}
|
||||
|
||||
// Foreach input state (NFA inputs of this DFA state)
|
||||
for (std::set<int>::const_iterator inIt=inputs.begin(); inIt!=inputs.end(); ++inIt) {
|
||||
for (std::set<int>::const_iterator inIt = inputs.begin(); inIt != inputs.end();
|
||||
++inIt) {
|
||||
DfaInput input = *inIt;
|
||||
UINFO(9," ==="<<++i<<"=======================\n");
|
||||
UINFO(9," On input "<<cvtToHex(input.toNodep())<<endl);
|
||||
UINFO(9, " ===" << ++i << "=======================\n");
|
||||
UINFO(9, " On input " << cvtToHex(input.toNodep()) << endl);
|
||||
|
||||
// Find all states reachable for given input
|
||||
DfaStates nfasWithInput;
|
||||
findNfasWithInput(dfaStatep, input, nfasWithInput/*ref*/);
|
||||
findNfasWithInput(dfaStatep, input, nfasWithInput /*ref*/);
|
||||
|
||||
// nfasWithInput now maps to the DFA we want a transition to.
|
||||
// Does a DFA already exist with this, and only this subset of NFA's?
|
||||
|
|
@ -329,9 +342,9 @@ private:
|
|||
toDfaStatep = newDfaVertex();
|
||||
dfaUnprocps.push_back(toDfaStatep); // Add to process list
|
||||
// Track what nfa's point to it.
|
||||
for (DfaStates::const_iterator nfaIt=nfasWithInput.begin();
|
||||
nfaIt!=nfasWithInput.end(); ++nfaIt) {
|
||||
UINFO(9," NewContainsNfa "<<*nfaIt<<endl);
|
||||
for (DfaStates::const_iterator nfaIt = nfasWithInput.begin();
|
||||
nfaIt != nfasWithInput.end(); ++nfaIt) {
|
||||
UINFO(9, " NewContainsNfa " << *nfaIt << endl);
|
||||
new DfaEdge(graphp(), toDfaStatep, *nfaIt, DfaEdge::NA());
|
||||
if ((*nfaIt)->accepting()) toDfaStatep->accepting(true);
|
||||
}
|
||||
|
|
@ -340,22 +353,21 @@ private:
|
|||
// Add input transition
|
||||
new DfaEdge(graphp(), dfaStatep, toDfaStatep, input);
|
||||
|
||||
if (debug()>=6) m_graphp->dumpDotFilePrefixed("step");
|
||||
if (debug() >= 6) m_graphp->dumpDotFilePrefixed("step");
|
||||
}
|
||||
}
|
||||
|
||||
// Remove old NFA states
|
||||
UINFO(5,"Removing NFA states...\n");
|
||||
if (debug()>=6) m_graphp->dumpDotFilePrefixed("dfa_withnfa");
|
||||
for (V3GraphVertex* nextp,*vertexp = m_graphp->verticesBeginp(); vertexp; vertexp=nextp) {
|
||||
UINFO(5, "Removing NFA states...\n");
|
||||
if (debug() >= 6) m_graphp->dumpDotFilePrefixed("dfa_withnfa");
|
||||
for (V3GraphVertex *nextp, *vertexp = m_graphp->verticesBeginp(); vertexp;
|
||||
vertexp = nextp) {
|
||||
nextp = vertexp->verticesNextp();
|
||||
if (nfaState(vertexp)) {
|
||||
VL_DO_DANGLING(vertexp->unlinkDelete(m_graphp), vertexp);
|
||||
}
|
||||
if (nfaState(vertexp)) VL_DO_DANGLING(vertexp->unlinkDelete(m_graphp), vertexp);
|
||||
}
|
||||
|
||||
UINFO(5,"Done.\n");
|
||||
if (debug()>=6) m_graphp->dumpDotFilePrefixed("dfa_done");
|
||||
UINFO(5, "Done.\n");
|
||||
if (debug() >= 6) m_graphp->dumpDotFilePrefixed("dfa_done");
|
||||
}
|
||||
|
||||
public:
|
||||
|
|
@ -367,9 +379,7 @@ public:
|
|||
~GraphNfaToDfa() {}
|
||||
};
|
||||
|
||||
void DfaGraph::nfaToDfa() {
|
||||
GraphNfaToDfa(this, &V3GraphEdge::followAlwaysTrue);
|
||||
}
|
||||
void DfaGraph::nfaToDfa() { GraphNfaToDfa(this, &V3GraphEdge::followAlwaysTrue); }
|
||||
|
||||
//######################################################################
|
||||
//######################################################################
|
||||
|
|
@ -390,7 +400,7 @@ private:
|
|||
bool isDead(DfaVertex* vertexp) {
|
||||
// A state is dead if not accepting, and goes nowhere
|
||||
if (vertexp->accepting() || vertexp->start()) return false;
|
||||
for (V3GraphEdge* edgep = vertexp->outBeginp(); edgep; edgep=edgep->outNextp()) {
|
||||
for (V3GraphEdge* edgep = vertexp->outBeginp(); edgep; edgep = edgep->outNextp()) {
|
||||
if (edgep->top() != vertexp) return false;
|
||||
}
|
||||
return true;
|
||||
|
|
@ -399,11 +409,11 @@ private:
|
|||
void optimize_accepting_out() {
|
||||
// Delete outbound edges from accepting states
|
||||
// (As once we've accepted, we no longer care about anything else.)
|
||||
for (V3GraphVertex* vertexp = m_graphp->verticesBeginp();
|
||||
vertexp; vertexp=vertexp->verticesNextp()) {
|
||||
for (V3GraphVertex* vertexp = m_graphp->verticesBeginp(); vertexp;
|
||||
vertexp = vertexp->verticesNextp()) {
|
||||
if (DfaVertex* vvertexp = dynamic_cast<DfaVertex*>(vertexp)) {
|
||||
if (vvertexp->accepting()) {
|
||||
for (V3GraphEdge* nextp,*edgep = vertexp->outBeginp(); edgep; edgep=nextp) {
|
||||
for (V3GraphEdge *nextp, *edgep = vertexp->outBeginp(); edgep; edgep = nextp) {
|
||||
nextp = edgep->outNextp();
|
||||
VL_DO_DANGLING(edgep->unlinkDelete(), edgep);
|
||||
}
|
||||
|
|
@ -421,14 +431,16 @@ private:
|
|||
m_graphp->userClearVertices();
|
||||
|
||||
DfaVertex* startp = graphp()->findStart();
|
||||
std::stack<V3GraphVertex*> workps; workps.push(startp);
|
||||
std::stack<V3GraphVertex*> workps;
|
||||
workps.push(startp);
|
||||
|
||||
// Mark all nodes connected to start
|
||||
while (!workps.empty()) {
|
||||
V3GraphVertex* vertexp = workps.top(); workps.pop();
|
||||
V3GraphVertex* vertexp = workps.top();
|
||||
workps.pop();
|
||||
vertexp->user(2); // Processed
|
||||
// Add nodes from here to the work list
|
||||
for (V3GraphEdge* edgep = vertexp->outBeginp(); edgep; edgep=edgep->outNextp()) {
|
||||
for (V3GraphEdge* edgep = vertexp->outBeginp(); edgep; edgep = edgep->outNextp()) {
|
||||
V3GraphVertex* tovertexp = edgep->top();
|
||||
if (!tovertexp->user()) {
|
||||
workps.push(tovertexp);
|
||||
|
|
@ -438,11 +450,10 @@ private:
|
|||
}
|
||||
|
||||
// Delete all nodes not connected
|
||||
for (V3GraphVertex* nextp,*vertexp = m_graphp->verticesBeginp(); vertexp; vertexp=nextp) {
|
||||
for (V3GraphVertex *nextp, *vertexp = m_graphp->verticesBeginp(); vertexp;
|
||||
vertexp = nextp) {
|
||||
nextp = vertexp->verticesNextp();
|
||||
if (!vertexp->user()) {
|
||||
VL_DO_DANGLING(vertexp->unlinkDelete(m_graphp), vertexp);
|
||||
}
|
||||
if (!vertexp->user()) { VL_DO_DANGLING(vertexp->unlinkDelete(m_graphp), vertexp); }
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -457,8 +468,8 @@ private:
|
|||
|
||||
// Find all dead vertexes
|
||||
std::stack<DfaVertex*> workps;
|
||||
for (V3GraphVertex* vertexp = m_graphp->verticesBeginp();
|
||||
vertexp; vertexp=vertexp->verticesNextp()) {
|
||||
for (V3GraphVertex* vertexp = m_graphp->verticesBeginp(); vertexp;
|
||||
vertexp = vertexp->verticesNextp()) {
|
||||
if (DfaVertex* vvertexp = dynamic_cast<DfaVertex*>(vertexp)) {
|
||||
workps.push(vvertexp);
|
||||
vertexp->user(1);
|
||||
|
|
@ -470,14 +481,14 @@ private:
|
|||
|
||||
// While deadness... Delete and find new dead nodes.
|
||||
while (!workps.empty()) {
|
||||
DfaVertex* vertexp = workps.top(); workps.pop();
|
||||
DfaVertex* vertexp = workps.top();
|
||||
workps.pop();
|
||||
vertexp->user(0);
|
||||
if (isDead(vertexp)) {
|
||||
// Add nodes that go here to the work list
|
||||
for (V3GraphEdge* edgep = vertexp->inBeginp(); edgep; edgep=edgep->inNextp()) {
|
||||
for (V3GraphEdge* edgep = vertexp->inBeginp(); edgep; edgep = edgep->inNextp()) {
|
||||
DfaVertex* fromvertexp = static_cast<DfaVertex*>(edgep->fromp());
|
||||
if (fromvertexp != vertexp
|
||||
&& !fromvertexp->user()) {
|
||||
if (fromvertexp != vertexp && !fromvertexp->user()) {
|
||||
workps.push(fromvertexp);
|
||||
fromvertexp->user(1);
|
||||
}
|
||||
|
|
@ -487,23 +498,22 @@ private:
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
DfaGraphReduce(V3Graph* graphp, V3EdgeFuncP edgeFuncp)
|
||||
: GraphAlg<>(graphp, edgeFuncp) {
|
||||
if (debug()>=6) m_graphp->dumpDotFilePrefixed("opt_in");
|
||||
if (debug() >= 6) m_graphp->dumpDotFilePrefixed("opt_in");
|
||||
optimize_accepting_out();
|
||||
if (debug()>=6) m_graphp->dumpDotFilePrefixed("opt_acc");
|
||||
if (debug() >= 6) m_graphp->dumpDotFilePrefixed("opt_acc");
|
||||
optimize_orphans();
|
||||
if (debug()>=6) m_graphp->dumpDotFilePrefixed("opt_orph");
|
||||
if (debug() >= 6) m_graphp->dumpDotFilePrefixed("opt_orph");
|
||||
optimize_no_outbound();
|
||||
if (debug()>=6) m_graphp->dumpDotFilePrefixed("opt_noout");
|
||||
if (debug() >= 6) m_graphp->dumpDotFilePrefixed("opt_noout");
|
||||
}
|
||||
~DfaGraphReduce() {}
|
||||
};
|
||||
|
||||
void DfaGraph::dfaReduce() {
|
||||
DfaGraphReduce(this, &V3GraphEdge::followAlwaysTrue);
|
||||
}
|
||||
void DfaGraph::dfaReduce() { DfaGraphReduce(this, &V3GraphEdge::followAlwaysTrue); }
|
||||
|
||||
//######################################################################
|
||||
//######################################################################
|
||||
|
|
@ -537,8 +547,8 @@ private:
|
|||
void add_complement_edges() {
|
||||
// Find accepting vertex
|
||||
DfaVertex* acceptp = NULL;
|
||||
for (V3GraphVertex* vertexp = m_graphp->verticesBeginp();
|
||||
vertexp; vertexp=vertexp->verticesNextp()) {
|
||||
for (V3GraphVertex* vertexp = m_graphp->verticesBeginp(); vertexp;
|
||||
vertexp = vertexp->verticesNextp()) {
|
||||
if (DfaVertex* vvertexp = dynamic_cast<DfaVertex*>(vertexp)) {
|
||||
if (vvertexp->accepting()) {
|
||||
acceptp = vvertexp;
|
||||
|
|
@ -549,12 +559,12 @@ private:
|
|||
if (!acceptp) v3fatalSrc("No accepting vertex in DFA");
|
||||
|
||||
// Remap edges
|
||||
for (V3GraphVertex* vertexp = m_graphp->verticesBeginp();
|
||||
vertexp; vertexp=vertexp->verticesNextp()) {
|
||||
for (V3GraphVertex* vertexp = m_graphp->verticesBeginp(); vertexp;
|
||||
vertexp = vertexp->verticesNextp()) {
|
||||
if (DfaVertex* vvertexp = dynamic_cast<DfaVertex*>(vertexp)) {
|
||||
//UINFO(9, " on vertex "<<vvertexp->name()<<endl);
|
||||
// UINFO(9, " on vertex "<<vvertexp->name()<<endl);
|
||||
if (!vvertexp->accepting() && vvertexp != m_tempNewerReject) {
|
||||
for (V3GraphEdge* nextp, *edgep = vertexp->outBeginp(); edgep; edgep=nextp) {
|
||||
for (V3GraphEdge *nextp, *edgep = vertexp->outBeginp(); edgep; edgep = nextp) {
|
||||
nextp = edgep->outNextp();
|
||||
if (!edgep->user()) { // Not processed
|
||||
// Old edges to accept now go to new reject
|
||||
|
|
@ -568,7 +578,8 @@ private:
|
|||
// NOT of all values goes to accept
|
||||
// We make a edge for each value to OR, IE
|
||||
// edge(complemented,a) edge(complemented,b) means !(a | b)
|
||||
if (!tovertexp->accepting()) { // Note we must include edges moved above to reject
|
||||
if (!tovertexp->accepting()) {
|
||||
// Note we must include edges moved above to reject
|
||||
DfaEdge* newp = new DfaEdge(graphp(), vvertexp, acceptp, vedgep);
|
||||
newp->complement(!newp->complement());
|
||||
newp->user(1);
|
||||
|
|
@ -579,25 +590,24 @@ private:
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
DfaGraphComplement(V3Graph* dfagraphp, V3EdgeFuncP edgeFuncp)
|
||||
: GraphAlg<>(dfagraphp, edgeFuncp) {
|
||||
if (debug()>=6) m_graphp->dumpDotFilePrefixed("comp_in");
|
||||
if (debug() >= 6) m_graphp->dumpDotFilePrefixed("comp_in");
|
||||
|
||||
// Vertex::m_user begin: 1 indicates new edge, no more processing
|
||||
m_graphp->userClearEdges();
|
||||
|
||||
m_tempNewerReject = new DfaVertex(graphp());
|
||||
add_complement_edges();
|
||||
if (debug()>=6) m_graphp->dumpDotFilePrefixed("comp_preswap");
|
||||
if (debug() >= 6) m_graphp->dumpDotFilePrefixed("comp_preswap");
|
||||
|
||||
VL_DO_CLEAR(m_tempNewerReject->unlinkDelete(graphp()), m_tempNewerReject = NULL);
|
||||
if (debug()>=6) m_graphp->dumpDotFilePrefixed("comp_out");
|
||||
if (debug() >= 6) m_graphp->dumpDotFilePrefixed("comp_out");
|
||||
}
|
||||
~DfaGraphComplement() {}
|
||||
VL_UNCOPYABLE(DfaGraphComplement);
|
||||
};
|
||||
|
||||
void DfaGraph::dfaComplement() {
|
||||
DfaGraphComplement(this, &V3GraphEdge::followAlwaysTrue);
|
||||
}
|
||||
void DfaGraph::dfaComplement() { DfaGraphComplement(this, &V3GraphEdge::followAlwaysTrue); }
|
||||
|
|
|
|||
|
|
@ -85,16 +85,18 @@ class DfaVertex : public V3GraphVertex {
|
|||
bool m_accepting; // Accepting state?
|
||||
public:
|
||||
// CONSTRUCTORS
|
||||
explicit DfaVertex(DfaGraph* graphp, bool start=false, bool accepting=false)
|
||||
explicit DfaVertex(DfaGraph* graphp, bool start = false, bool accepting = false)
|
||||
: V3GraphVertex(graphp)
|
||||
, m_start(start), m_accepting(accepting) {}
|
||||
, m_start(start)
|
||||
, m_accepting(accepting) {}
|
||||
using V3GraphVertex::clone; // We are overriding, not overloading clone(V3Graph*)
|
||||
virtual DfaVertex* clone(DfaGraph* graphp) {
|
||||
return new DfaVertex(graphp, start(), accepting()); }
|
||||
return new DfaVertex(graphp, start(), accepting());
|
||||
}
|
||||
virtual ~DfaVertex() {}
|
||||
// ACCESSORS
|
||||
virtual string dotShape() const { return (accepting()?"doublecircle":""); }
|
||||
virtual string dotColor() const { return start()?"blue":(color()?"red":"black"); }
|
||||
virtual string dotShape() const { return (accepting() ? "doublecircle" : ""); }
|
||||
virtual string dotColor() const { return start() ? "blue" : (color() ? "red" : "black"); }
|
||||
bool start() const { return m_start; }
|
||||
void start(bool flag) { m_start = flag; }
|
||||
bool accepting() const { return m_accepting; }
|
||||
|
|
@ -118,24 +120,24 @@ public:
|
|||
// CONSTRUCTORS
|
||||
DfaEdge(DfaGraph* graphp, DfaVertex* fromp, DfaVertex* top, const DfaInput& input)
|
||||
: V3GraphEdge(graphp, fromp, top, 1)
|
||||
, m_input(input), m_complement(false) {}
|
||||
, m_input(input)
|
||||
, m_complement(false) {}
|
||||
DfaEdge(DfaGraph* graphp, DfaVertex* fromp, DfaVertex* top, const DfaEdge* copyfrom)
|
||||
: V3GraphEdge(graphp, fromp, top, copyfrom->weight())
|
||||
, m_input(copyfrom->input()), m_complement(copyfrom->complement()) {}
|
||||
, m_input(copyfrom->input())
|
||||
, m_complement(copyfrom->complement()) {}
|
||||
virtual ~DfaEdge() {}
|
||||
// METHODS
|
||||
virtual string dotColor() const {
|
||||
return (na() ? "yellow"
|
||||
: epsilon() ? "green"
|
||||
: "black"); }
|
||||
virtual string dotColor() const { return (na() ? "yellow" : epsilon() ? "green" : "black"); }
|
||||
virtual string dotLabel() const {
|
||||
return (na() ? ""
|
||||
: epsilon() ? "e"
|
||||
: complement() ? ("not "+cvtToStr(input().toInt()))
|
||||
: cvtToStr(input().toInt())); }
|
||||
virtual string dotStyle() const { return (na()||cutable())?"dashed":""; }
|
||||
bool epsilon() const { return input().toInt()==EPSILON().toInt(); }
|
||||
bool na() const { return input().toInt()==NA().toInt(); }
|
||||
: epsilon() ? "e"
|
||||
: complement() ? ("not " + cvtToStr(input().toInt()))
|
||||
: cvtToStr(input().toInt()));
|
||||
}
|
||||
virtual string dotStyle() const { return (na() || cutable()) ? "dashed" : ""; }
|
||||
bool epsilon() const { return input().toInt() == EPSILON().toInt(); }
|
||||
bool na() const { return input().toInt() == NA().toInt(); }
|
||||
bool complement() const { return m_complement; }
|
||||
void complement(bool value) { m_complement = value; }
|
||||
DfaInput input() const { return m_input; }
|
||||
|
|
|
|||
|
|
@ -41,10 +41,11 @@ struct GraphPCNode {
|
|||
vluint64_t m_seenAtGeneration;
|
||||
|
||||
// CONSTRUCTORS
|
||||
GraphPCNode() : m_seenAtGeneration(0) {
|
||||
GraphPCNode()
|
||||
: m_seenAtGeneration(0) {
|
||||
for (int w = 0; w < GraphWay::NUM_WAYS; w++) m_cp[w] = 0;
|
||||
}
|
||||
~GraphPCNode() { }
|
||||
~GraphPCNode() {}
|
||||
};
|
||||
|
||||
//######################################################################
|
||||
|
|
@ -53,8 +54,7 @@ struct GraphPCNode {
|
|||
GraphPathChecker::GraphPathChecker(const V3Graph* graphp, V3EdgeFuncP edgeFuncp)
|
||||
: GraphAlg<const V3Graph>(graphp, edgeFuncp)
|
||||
, m_generation(0) {
|
||||
for (V3GraphVertex* vxp = graphp->verticesBeginp();
|
||||
vxp; vxp = vxp->verticesNextp()) {
|
||||
for (V3GraphVertex* vxp = graphp->verticesBeginp(); vxp; vxp = vxp->verticesNextp()) {
|
||||
// Setup tracking structure for each node. If delete a vertex
|
||||
// there would be a leak, but ok as accept only const V3Graph*'s.
|
||||
vxp->userp(new GraphPCNode);
|
||||
|
|
@ -66,8 +66,7 @@ GraphPathChecker::GraphPathChecker(const V3Graph* graphp, V3EdgeFuncP edgeFuncp)
|
|||
|
||||
GraphPathChecker::~GraphPathChecker() {
|
||||
// Free every GraphPCNode
|
||||
for (V3GraphVertex* vxp = m_graphp->verticesBeginp();
|
||||
vxp; vxp = vxp->verticesNextp()) {
|
||||
for (V3GraphVertex* vxp = m_graphp->verticesBeginp(); vxp; vxp = vxp->verticesNextp()) {
|
||||
GraphPCNode* nodep = static_cast<GraphPCNode*>(vxp->userp());
|
||||
VL_DO_DANGLING(delete nodep, nodep);
|
||||
vxp->userp(NULL);
|
||||
|
|
@ -79,8 +78,7 @@ void GraphPathChecker::initHalfCriticalPaths(GraphWay way, bool checkOnly) {
|
|||
GraphWay rev = way.invert();
|
||||
while (const V3GraphVertex* vertexp = order.nextp()) {
|
||||
unsigned critPathCost = 0;
|
||||
for (V3GraphEdge* edgep = vertexp->beginp(rev);
|
||||
edgep; edgep = edgep->nextp(rev)) {
|
||||
for (V3GraphEdge* edgep = vertexp->beginp(rev); edgep; edgep = edgep->nextp(rev)) {
|
||||
if (!m_edgeFuncp(edgep)) continue;
|
||||
|
||||
V3GraphVertex* wrelativep = edgep->furtherp(rev);
|
||||
|
|
@ -90,16 +88,15 @@ void GraphPathChecker::initHalfCriticalPaths(GraphWay way, bool checkOnly) {
|
|||
|
||||
GraphPCNode* ourUserp = static_cast<GraphPCNode*>(vertexp->userp());
|
||||
if (checkOnly) {
|
||||
UASSERT_OBJ(ourUserp->m_cp[way] == critPathCost,
|
||||
vertexp, "Validation of critical paths failed");
|
||||
UASSERT_OBJ(ourUserp->m_cp[way] == critPathCost, vertexp,
|
||||
"Validation of critical paths failed");
|
||||
} else {
|
||||
ourUserp->m_cp[way] = critPathCost;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool GraphPathChecker::pathExistsInternal(const V3GraphVertex* ap,
|
||||
const V3GraphVertex* bp,
|
||||
bool GraphPathChecker::pathExistsInternal(const V3GraphVertex* ap, const V3GraphVertex* bp,
|
||||
unsigned* costp) {
|
||||
GraphPCNode* auserp = static_cast<GraphPCNode*>(ap->userp());
|
||||
GraphPCNode* buserp = static_cast<GraphPCNode*>(bp->userp());
|
||||
|
|
@ -118,31 +115,23 @@ bool GraphPathChecker::pathExistsInternal(const V3GraphVertex* ap,
|
|||
if (ap == bp) return true;
|
||||
|
||||
// Rule out an a->b path based on their CPs
|
||||
if (auserp->m_cp[GraphWay::REVERSE] < buserp->m_cp[GraphWay::REVERSE] + 1) {
|
||||
return false;
|
||||
}
|
||||
if (buserp->m_cp[GraphWay::FORWARD] < auserp->m_cp[GraphWay::FORWARD] + 1) {
|
||||
return false;
|
||||
}
|
||||
if (auserp->m_cp[GraphWay::REVERSE] < buserp->m_cp[GraphWay::REVERSE] + 1) return false;
|
||||
if (buserp->m_cp[GraphWay::FORWARD] < auserp->m_cp[GraphWay::FORWARD] + 1) return false;
|
||||
|
||||
// Slow path; visit some extended family
|
||||
bool foundPath = false;
|
||||
for (V3GraphEdge* edgep = ap->outBeginp();
|
||||
edgep && !foundPath; edgep = edgep->outNextp()) {
|
||||
for (V3GraphEdge* edgep = ap->outBeginp(); edgep && !foundPath; edgep = edgep->outNextp()) {
|
||||
if (!m_edgeFuncp(edgep)) continue;
|
||||
|
||||
unsigned childCost;
|
||||
if (pathExistsInternal(edgep->top(), bp, &childCost)) {
|
||||
foundPath = true;
|
||||
}
|
||||
if (pathExistsInternal(edgep->top(), bp, &childCost)) foundPath = true;
|
||||
if (costp) *costp += childCost;
|
||||
}
|
||||
|
||||
return foundPath;
|
||||
}
|
||||
|
||||
bool GraphPathChecker::pathExistsFrom(const V3GraphVertex* fromp,
|
||||
const V3GraphVertex* top) {
|
||||
bool GraphPathChecker::pathExistsFrom(const V3GraphVertex* fromp, const V3GraphVertex* top) {
|
||||
incGeneration();
|
||||
return pathExistsInternal(fromp, top);
|
||||
}
|
||||
|
|
@ -151,12 +140,10 @@ bool GraphPathChecker::isTransitiveEdge(const V3GraphEdge* edgep) {
|
|||
const V3GraphVertex* fromp = edgep->fromp();
|
||||
const V3GraphVertex* top = edgep->top();
|
||||
incGeneration();
|
||||
for (const V3GraphEdge* fromOutp = fromp->outBeginp();
|
||||
fromOutp; fromOutp = fromOutp->outNextp()) {
|
||||
for (const V3GraphEdge* fromOutp = fromp->outBeginp(); fromOutp;
|
||||
fromOutp = fromOutp->outNextp()) {
|
||||
if (fromOutp == edgep) continue;
|
||||
if (pathExistsInternal(fromOutp->top(), top)) {
|
||||
return true;
|
||||
}
|
||||
if (pathExistsInternal(fromOutp->top(), top)) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -70,11 +70,12 @@ private:
|
|||
explicit VxHolderCmp(const T_Compare& lessThan)
|
||||
: m_lessThan(lessThan) {}
|
||||
// METHODS
|
||||
bool operator() (const VxHolder& a, const VxHolder& b) const {
|
||||
bool operator()(const VxHolder& a, const VxHolder& b) const {
|
||||
if (m_lessThan.operator()(a.vertexp(), b.vertexp())) return true;
|
||||
if (m_lessThan.operator()(b.vertexp(), a.vertexp())) return false;
|
||||
return a.m_pos < b.m_pos;
|
||||
}
|
||||
|
||||
private:
|
||||
VL_UNCOPYABLE(VxHolderCmp);
|
||||
};
|
||||
|
|
@ -91,8 +92,7 @@ private:
|
|||
|
||||
public:
|
||||
// CONSTRUCTORS
|
||||
explicit GraphStream(const V3Graph* graphp,
|
||||
GraphWay way = GraphWay::FORWARD,
|
||||
explicit GraphStream(const V3Graph* graphp, GraphWay way = GraphWay::FORWARD,
|
||||
const T_Compare& lessThan = T_Compare())
|
||||
// NOTE: Perhaps REVERSE way should also reverse the sense of the
|
||||
// lessThan function? For now the only usage of REVERSE is not
|
||||
|
|
@ -102,8 +102,8 @@ public:
|
|||
, m_last(m_readyVertices.end())
|
||||
, m_way(way) {
|
||||
uint32_t pos = 0;
|
||||
for (const V3GraphVertex* vxp = graphp->verticesBeginp();
|
||||
vxp; vxp=vxp->verticesNextp()) {
|
||||
for (const V3GraphVertex* vxp = graphp->verticesBeginp(); vxp;
|
||||
vxp = vxp->verticesNextp()) {
|
||||
// Every vertex initially is waiting, or ready.
|
||||
if (way == GraphWay::FORWARD) {
|
||||
if (vxp->inEmpty()) {
|
||||
|
|
@ -111,8 +111,7 @@ public:
|
|||
m_readyVertices.insert(newVx);
|
||||
} else {
|
||||
uint32_t depCount = 0;
|
||||
for (V3GraphEdge* depp = vxp->inBeginp();
|
||||
depp; depp = depp->inNextp()) {
|
||||
for (V3GraphEdge* depp = vxp->inBeginp(); depp; depp = depp->inNextp()) {
|
||||
depCount++;
|
||||
}
|
||||
VxHolder newVx(vxp, pos++, depCount);
|
||||
|
|
@ -124,8 +123,7 @@ public:
|
|||
m_readyVertices.insert(newVx);
|
||||
} else {
|
||||
uint32_t depCount = 0;
|
||||
for (V3GraphEdge* depp = vxp->outBeginp();
|
||||
depp; depp = depp->outNextp()) {
|
||||
for (V3GraphEdge* depp = vxp->outBeginp(); depp; depp = depp->outNextp()) {
|
||||
depCount++;
|
||||
}
|
||||
VxHolder newVx(vxp, pos++, depCount);
|
||||
|
|
@ -177,9 +175,7 @@ public:
|
|||
// Wrap curIt. Expect to wrap, and make another pass, to find
|
||||
// newly-ready elements that could have appeared ahead of the
|
||||
// m_last iterator
|
||||
if (curIt == m_readyVertices.end()) {
|
||||
curIt = m_readyVertices.begin();
|
||||
}
|
||||
if (curIt == m_readyVertices.end()) { curIt = m_readyVertices.begin(); }
|
||||
}
|
||||
|
||||
if (curIt != m_readyVertices.end()) {
|
||||
|
|
@ -198,12 +194,10 @@ public:
|
|||
private:
|
||||
void unblockDeps(const V3GraphVertex* vertexp) {
|
||||
if (m_way == GraphWay::FORWARD) {
|
||||
for (V3GraphEdge* edgep = vertexp->outBeginp();
|
||||
edgep; edgep=edgep->outNextp()) {
|
||||
for (V3GraphEdge* edgep = vertexp->outBeginp(); edgep; edgep = edgep->outNextp()) {
|
||||
V3GraphVertex* toVertexp = edgep->top();
|
||||
|
||||
typename WaitingVertices::iterator it =
|
||||
m_waitingVertices.find(toVertexp);
|
||||
typename WaitingVertices::iterator it = m_waitingVertices.find(toVertexp);
|
||||
UASSERT_OBJ(it != m_waitingVertices.end(), toVertexp,
|
||||
"Found edge into vertex not in waiting list.");
|
||||
if (it->second.unblock()) {
|
||||
|
|
@ -212,12 +206,10 @@ private:
|
|||
}
|
||||
}
|
||||
} else {
|
||||
for (V3GraphEdge* edgep = vertexp->inBeginp();
|
||||
edgep; edgep=edgep->inNextp()) {
|
||||
for (V3GraphEdge* edgep = vertexp->inBeginp(); edgep; edgep = edgep->inNextp()) {
|
||||
V3GraphVertex* fromVertexp = edgep->fromp();
|
||||
|
||||
typename WaitingVertices::iterator it =
|
||||
m_waitingVertices.find(fromVertexp);
|
||||
typename WaitingVertices::iterator it = m_waitingVertices.find(fromVertexp);
|
||||
UASSERT_OBJ(it != m_waitingVertices.end(), fromVertexp,
|
||||
"Found edge into vertex not in waiting list.");
|
||||
if (it->second.unblock()) {
|
||||
|
|
|
|||
|
|
@ -50,8 +50,9 @@ class V3Hashed : public VHashedBase {
|
|||
|
||||
// TYPES
|
||||
public:
|
||||
typedef std::multimap<V3Hash,AstNode*> HashMmap;
|
||||
typedef std::multimap<V3Hash, AstNode*> HashMmap;
|
||||
typedef HashMmap::iterator iterator;
|
||||
|
||||
private:
|
||||
// MEMBERS
|
||||
HashMmap m_hashMmap; // hashvalue -> nodes with that hash
|
||||
|
|
@ -67,17 +68,21 @@ public:
|
|||
iterator end() { return m_hashMmap.end(); }
|
||||
|
||||
// METHODS
|
||||
void clear() { m_hashMmap.clear(); AstNode::user4ClearTree(); }
|
||||
void clear() {
|
||||
m_hashMmap.clear();
|
||||
AstNode::user4ClearTree();
|
||||
}
|
||||
void check(); // Check assertions on structure
|
||||
iterator hashAndInsert(AstNode* nodep); // Hash the node, and insert into map. Return iterator to inserted
|
||||
// Hash the node, and insert into map. Return iterator to inserted
|
||||
iterator hashAndInsert(AstNode* nodep);
|
||||
void hash(AstNode* nodep); // Only hash the node
|
||||
bool sameNodes(AstNode* node1p, AstNode* node2p); // After hashing, and tell if identical
|
||||
void erase(iterator it); // Remove node from structures
|
||||
// Return duplicate in hash, if any, with optional user check for sameness
|
||||
iterator findDuplicate(AstNode* nodep, V3HashedUserSame* checkp=NULL);
|
||||
iterator findDuplicate(AstNode* nodep, V3HashedUserSame* checkp = NULL);
|
||||
AstNode* iteratorNodep(iterator it) { return it->second; }
|
||||
void dumpFile(const string& filename, bool tree);
|
||||
void dumpFilePrefixed(const string& nameComment, bool tree=false);
|
||||
void dumpFilePrefixed(const string& nameComment, bool tree = false);
|
||||
static V3Hash nodeHash(AstNode* nodep) { return V3Hash(nodep->user4p()); }
|
||||
// Hash of the nodep tree, without caching in user4.
|
||||
static V3Hash uncachedHash(const AstNode* nodep);
|
||||
|
|
|
|||
|
|
@ -29,8 +29,8 @@ class V3Inst {
|
|||
public:
|
||||
static void instAll(AstNetlist* nodep);
|
||||
static void dearrayAll(AstNetlist* nodep);
|
||||
static AstAssignW* pinReconnectSimple(AstPin* pinp, AstCell* cellp,
|
||||
bool forTristate, bool alwaysCvt=false);
|
||||
static AstAssignW* pinReconnectSimple(AstPin* pinp, AstCell* cellp, bool forTristate,
|
||||
bool alwaysCvt = false);
|
||||
static void checkOutputShort(AstPin* nodep);
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -52,15 +52,16 @@ private:
|
|||
uint32_t m_savedCount;
|
||||
AstNode* m_nodep;
|
||||
InstrCountVisitor* m_visitor;
|
||||
|
||||
public:
|
||||
// CONSTRUCTORS
|
||||
VisitBase(InstrCountVisitor* visitor, AstNode* nodep)
|
||||
: m_nodep(nodep), m_visitor(visitor) {
|
||||
: m_nodep(nodep)
|
||||
, m_visitor(visitor) {
|
||||
m_savedCount = m_visitor->startVisitBase(nodep);
|
||||
}
|
||||
~VisitBase() {
|
||||
m_visitor->endVisitBase(m_savedCount, m_nodep);
|
||||
}
|
||||
~VisitBase() { m_visitor->endVisitBase(m_savedCount, m_nodep); }
|
||||
|
||||
private:
|
||||
VL_UNCOPYABLE(VisitBase);
|
||||
};
|
||||
|
|
@ -68,13 +69,12 @@ private:
|
|||
public:
|
||||
// CONSTRUCTORS
|
||||
InstrCountVisitor(AstNode* nodep, bool assertNoDups, std::ostream* osp)
|
||||
: m_instrCount(0),
|
||||
m_startNodep(nodep),
|
||||
m_tracingCall(false),
|
||||
m_inCFunc(false),
|
||||
m_assertNoDups(assertNoDups),
|
||||
m_osp(osp)
|
||||
{
|
||||
: m_instrCount(0)
|
||||
, m_startNodep(nodep)
|
||||
, m_tracingCall(false)
|
||||
, m_inCFunc(false)
|
||||
, m_assertNoDups(assertNoDups)
|
||||
, m_osp(osp) {
|
||||
if (nodep) iterate(nodep);
|
||||
}
|
||||
virtual ~InstrCountVisitor() {}
|
||||
|
|
@ -98,7 +98,7 @@ private:
|
|||
// collisions in CFuncs.
|
||||
UASSERT_OBJ(!nodep->user5p(), nodep,
|
||||
"Node originally inserted below logic vertex "
|
||||
<<static_cast<AstNode*>(nodep->user5p()));
|
||||
<< static_cast<AstNode*>(nodep->user5p()));
|
||||
nodep->user5p(const_cast<void*>(reinterpret_cast<const void*>(m_startNodep)));
|
||||
}
|
||||
|
||||
|
|
@ -110,13 +110,12 @@ private:
|
|||
return savedCount;
|
||||
}
|
||||
void endVisitBase(uint32_t savedCount, AstNode* nodep) {
|
||||
UINFO(8, "cost "<<std::setw(6)<<std::left<<m_instrCount
|
||||
<<" "<<nodep<<endl);
|
||||
UINFO(8, "cost " << std::setw(6) << std::left << m_instrCount << " " << nodep << endl);
|
||||
markCost(nodep);
|
||||
m_instrCount += savedCount;
|
||||
}
|
||||
void markCost(AstNode* nodep) {
|
||||
if (m_osp) nodep->user4(m_instrCount+1); // Else don't mark to avoid writeback
|
||||
if (m_osp) nodep->user4(m_instrCount + 1); // Else don't mark to avoid writeback
|
||||
}
|
||||
|
||||
// VISITORS
|
||||
|
|
@ -275,7 +274,8 @@ private:
|
|||
public:
|
||||
// CONSTRUCTORS
|
||||
InstrCountDumpVisitor(AstNode* nodep, std::ostream* osp)
|
||||
: m_osp(osp), m_depth(0) {
|
||||
: m_osp(osp)
|
||||
, m_depth(0) {
|
||||
// No check for NULL output, so...
|
||||
UASSERT_OBJ(osp, nodep, "Don't call if not dumping");
|
||||
if (nodep) iterate(nodep);
|
||||
|
|
@ -284,13 +284,12 @@ public:
|
|||
|
||||
private:
|
||||
// METHODS
|
||||
string indent() { return string(m_depth, ':')+" "; }
|
||||
string indent() { return string(m_depth, ':') + " "; }
|
||||
virtual void visit(AstNode* nodep) VL_OVERRIDE {
|
||||
++m_depth;
|
||||
if (unsigned costPlus1 = nodep->user4()) {
|
||||
*m_osp <<" "<<indent()
|
||||
<<"cost "<<std::setw(6)<<std::left<<(costPlus1-1)
|
||||
<<" "<<nodep<<endl;
|
||||
*m_osp << " " << indent() << "cost " << std::setw(6) << std::left << (costPlus1 - 1)
|
||||
<< " " << nodep << endl;
|
||||
iterateChildren(nodep);
|
||||
}
|
||||
--m_depth;
|
||||
|
|
|
|||
|
|
@ -43,30 +43,26 @@ public:
|
|||
_ENUM_END
|
||||
};
|
||||
const char* ascii() const {
|
||||
const char* const names[] = {
|
||||
// These must match the `begin_keywords values.
|
||||
" ERROR",
|
||||
"1364-1995",
|
||||
"1364-2001",
|
||||
"1364-2005",
|
||||
"1800-2005",
|
||||
"1800-2009",
|
||||
"1800-2012",
|
||||
"1800-2017"
|
||||
};
|
||||
const char* const names[] = {// These must match the `begin_keywords values.
|
||||
" ERROR", "1364-1995", "1364-2001", "1364-2005",
|
||||
"1800-2005", "1800-2009", "1800-2012", "1800-2017"};
|
||||
return names[m_e];
|
||||
}
|
||||
static V3LangCode mostRecent() { return V3LangCode(L1800_2017); }
|
||||
bool systemVerilog() const { return m_e == L1800_2005 || m_e == L1800_2009
|
||||
|| m_e == L1800_2012 || m_e == L1800_2017; }
|
||||
bool systemVerilog() const {
|
||||
return m_e == L1800_2005 || m_e == L1800_2009 || m_e == L1800_2012 || m_e == L1800_2017;
|
||||
}
|
||||
bool legal() const { return m_e != L_ERROR; }
|
||||
//
|
||||
enum en m_e;
|
||||
inline V3LangCode() : m_e(L_ERROR) {}
|
||||
inline V3LangCode()
|
||||
: m_e(L_ERROR) {}
|
||||
// cppcheck-suppress noExplicitConstructor
|
||||
inline V3LangCode(en _e) : m_e(_e) {}
|
||||
inline V3LangCode(en _e)
|
||||
: m_e(_e) {}
|
||||
explicit V3LangCode(const char* textp);
|
||||
explicit inline V3LangCode(int _e) : m_e(static_cast<en>(_e)) {}
|
||||
explicit inline V3LangCode(int _e)
|
||||
: m_e(static_cast<en>(_e)) {}
|
||||
operator en() const { return m_e; }
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -26,17 +26,16 @@
|
|||
|
||||
class V3LanguageWords {
|
||||
// List of common reserved keywords
|
||||
private:
|
||||
typedef std::map<string,string> KeywordMap;
|
||||
private:
|
||||
typedef std::map<string, string> KeywordMap;
|
||||
struct Singleton {
|
||||
KeywordMap s_kwdMap; // List of keywords, and what language applies
|
||||
Singleton() { init(); }
|
||||
void addKwd(const string& kwd, const string& why) {
|
||||
s_kwdMap.insert(make_pair(kwd, why));
|
||||
}
|
||||
void addKwd(const string& kwd, const string& why) { s_kwdMap.insert(make_pair(kwd, why)); }
|
||||
void init();
|
||||
};
|
||||
public:
|
||||
|
||||
public:
|
||||
typedef KeywordMap::const_iterator const_iterator;
|
||||
// METHODS
|
||||
static const_iterator begin() { return s().s_kwdMap.begin(); }
|
||||
|
|
@ -46,12 +45,17 @@ class V3LanguageWords {
|
|||
if (it == s().s_kwdMap.end()) return "";
|
||||
return it->second;
|
||||
}
|
||||
|
||||
private:
|
||||
static Singleton& s() { static Singleton s_s; return s_s; }
|
||||
static Singleton& s() {
|
||||
static Singleton s_s;
|
||||
return s_s;
|
||||
}
|
||||
};
|
||||
|
||||
inline void V3LanguageWords::Singleton::init() {
|
||||
// C++ keywords
|
||||
// clang-format off
|
||||
addKwd("NULL", "C++ common word");
|
||||
addKwd("abort", "C++ common word");
|
||||
addKwd("alignas", "C++11 keyword");
|
||||
|
|
@ -242,6 +246,7 @@ inline void V3LanguageWords::Singleton::init() {
|
|||
addKwd("`undefineall", "Verilog preprocessor directive");
|
||||
addKwd("`verilator_config", "Verilator preprocessor directive");
|
||||
addKwd("`verilog", "Verilator preprocessor directive");
|
||||
// clang-format on
|
||||
}
|
||||
|
||||
#endif // Guard
|
||||
|
|
|
|||
|
|
@ -31,25 +31,26 @@ class V3LinkDot {
|
|||
private:
|
||||
static int debug();
|
||||
static void linkDotGuts(AstNetlist* rootp, VLinkDotStep step);
|
||||
|
||||
public:
|
||||
static void linkDotPrimary(AstNetlist* nodep) {
|
||||
UINFO(2,__FUNCTION__<<": "<<endl);
|
||||
linkDotGuts(nodep,LDS_PRIMARY);
|
||||
UINFO(2, __FUNCTION__ << ": " << endl);
|
||||
linkDotGuts(nodep, LDS_PRIMARY);
|
||||
V3Global::dumpCheckGlobalTree("linkdot", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 6);
|
||||
}
|
||||
static void linkDotParamed(AstNetlist* nodep) {
|
||||
UINFO(2,__FUNCTION__<<": "<<endl);
|
||||
linkDotGuts(nodep,LDS_PARAMED);
|
||||
UINFO(2, __FUNCTION__ << ": " << endl);
|
||||
linkDotGuts(nodep, LDS_PARAMED);
|
||||
V3Global::dumpCheckGlobalTree("paramlink", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
|
||||
}
|
||||
static void linkDotArrayed(AstNetlist* nodep) {
|
||||
UINFO(2,__FUNCTION__<<": "<<endl);
|
||||
linkDotGuts(nodep,LDS_ARRAYED);
|
||||
UINFO(2, __FUNCTION__ << ": " << endl);
|
||||
linkDotGuts(nodep, LDS_ARRAYED);
|
||||
V3Global::dumpCheckGlobalTree("linkdot", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 6);
|
||||
}
|
||||
static void linkDotScope(AstNetlist* nodep) {
|
||||
UINFO(2,__FUNCTION__<<": "<<endl);
|
||||
linkDotGuts(nodep,LDS_SCOPED);
|
||||
UINFO(2, __FUNCTION__ << ": " << endl);
|
||||
linkDotGuts(nodep, LDS_SCOPED);
|
||||
V3Global::dumpCheckGlobalTree("linkdot", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -38,8 +38,8 @@ private:
|
|||
// NODE STATE
|
||||
|
||||
// STATE
|
||||
bool m_setRefLvalue; // Set VarRefs to lvalues for pin assignments
|
||||
AstNodeFTask* m_ftaskp; // Function or task we're inside
|
||||
bool m_setRefLvalue; // Set VarRefs to lvalues for pin assignments
|
||||
AstNodeFTask* m_ftaskp; // Function or task we're inside
|
||||
|
||||
// METHODS
|
||||
VL_DEBUG_FUNC; // Declare debug()
|
||||
|
|
@ -48,14 +48,11 @@ private:
|
|||
// Result handing
|
||||
virtual void visit(AstNodeVarRef* nodep) VL_OVERRIDE {
|
||||
// VarRef: LValue its reference
|
||||
if (m_setRefLvalue) {
|
||||
nodep->lvalue(true);
|
||||
}
|
||||
if (m_setRefLvalue) nodep->lvalue(true);
|
||||
if (nodep->varp()) {
|
||||
if (nodep->lvalue() && !m_ftaskp
|
||||
&& nodep->varp()->isReadOnly()) {
|
||||
nodep->v3warn(ASSIGNIN, "Assigning to input/const variable: "
|
||||
<<nodep->prettyNameQ());
|
||||
if (nodep->lvalue() && !m_ftaskp && nodep->varp()->isReadOnly()) {
|
||||
nodep->v3warn(ASSIGNIN,
|
||||
"Assigning to input/const variable: " << nodep->prettyNameQ());
|
||||
}
|
||||
}
|
||||
iterateChildren(nodep);
|
||||
|
|
@ -223,7 +220,7 @@ private:
|
|||
}
|
||||
virtual void visit(AstNodeSel* nodep) VL_OVERRIDE {
|
||||
bool last_setRefLvalue = m_setRefLvalue;
|
||||
{ // Only set lvalues on the from
|
||||
{ // Only set lvalues on the from
|
||||
iterateAndNextNull(nodep->lhsp());
|
||||
m_setRefLvalue = false;
|
||||
iterateAndNextNull(nodep->rhsp());
|
||||
|
|
@ -232,7 +229,7 @@ private:
|
|||
}
|
||||
virtual void visit(AstCellArrayRef* nodep) VL_OVERRIDE {
|
||||
bool last_setRefLvalue = m_setRefLvalue;
|
||||
{ // selp is not an lvalue
|
||||
{ // selp is not an lvalue
|
||||
m_setRefLvalue = false;
|
||||
iterateAndNextNull(nodep->selp());
|
||||
}
|
||||
|
|
@ -240,7 +237,7 @@ private:
|
|||
}
|
||||
virtual void visit(AstNodePreSel* nodep) VL_OVERRIDE {
|
||||
bool last_setRefLvalue = m_setRefLvalue;
|
||||
{ // Only set lvalues on the from
|
||||
{ // Only set lvalues on the from
|
||||
iterateAndNextNull(nodep->lhsp());
|
||||
m_setRefLvalue = false;
|
||||
iterateAndNextNull(nodep->rhsp());
|
||||
|
|
@ -258,7 +255,7 @@ private:
|
|||
AstNodeFTask* taskp = nodep->taskp();
|
||||
// We'll deal with mismatching pins later
|
||||
if (!taskp) return;
|
||||
for (AstNode* stmtp = taskp->stmtsp(); stmtp && pinp; stmtp=stmtp->nextp()) {
|
||||
for (AstNode* stmtp = taskp->stmtsp(); stmtp && pinp; stmtp = stmtp->nextp()) {
|
||||
if (const AstVar* portp = VN_CAST(stmtp, Var)) {
|
||||
if (portp->isIO()) {
|
||||
if (portp->isWritable()) {
|
||||
|
|
@ -291,15 +288,13 @@ public:
|
|||
// Link class functions
|
||||
|
||||
void V3LinkLValue::linkLValue(AstNetlist* nodep) {
|
||||
UINFO(4,__FUNCTION__<<": "<<endl);
|
||||
{
|
||||
LinkLValueVisitor visitor(nodep, false);
|
||||
} // Destruct before checking
|
||||
UINFO(4, __FUNCTION__ << ": " << endl);
|
||||
{ LinkLValueVisitor visitor(nodep, false); } // Destruct before checking
|
||||
V3Global::dumpCheckGlobalTree("linklvalue", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 6);
|
||||
}
|
||||
void V3LinkLValue::linkLValueSet(AstNode* nodep) {
|
||||
// Called by later link functions when it is known a node needs
|
||||
// to be converted to a lvalue.
|
||||
UINFO(9,__FUNCTION__<<": "<<endl);
|
||||
UINFO(9, __FUNCTION__ << ": " << endl);
|
||||
LinkLValueVisitor visitor(nodep, true);
|
||||
}
|
||||
|
|
|
|||
37
src/V3List.h
37
src/V3List.h
|
|
@ -27,29 +27,32 @@
|
|||
template <class T> class V3List;
|
||||
template <class T> class V3ListEnt;
|
||||
|
||||
template <class T>
|
||||
class V3List {
|
||||
template <class T> class V3List {
|
||||
// List container for linked list of elements of type *T (T is a pointer type)
|
||||
private:
|
||||
// MEMBERS
|
||||
T m_headp; // First element
|
||||
T m_tailp; // Last element
|
||||
friend class V3ListEnt<T>;
|
||||
|
||||
public:
|
||||
V3List()
|
||||
: m_headp(NULL), m_tailp(NULL) {}
|
||||
: m_headp(NULL)
|
||||
, m_tailp(NULL) {}
|
||||
~V3List() {}
|
||||
// METHODS
|
||||
T begin() const { return m_headp; }
|
||||
T end() const { return NULL; }
|
||||
bool empty() const { return m_headp==NULL; }
|
||||
void reset() { m_headp = NULL; m_tailp = NULL; } // clear() without walking the list
|
||||
bool empty() const { return m_headp == NULL; }
|
||||
void reset() { // clear() without walking the list
|
||||
m_headp = NULL;
|
||||
m_tailp = NULL;
|
||||
}
|
||||
};
|
||||
|
||||
//============================================================================
|
||||
|
||||
template <class T>
|
||||
class V3ListEnt {
|
||||
template <class T> class V3ListEnt {
|
||||
// List entry for linked list of elements of type *T (T is a pointer type)
|
||||
private:
|
||||
// MEMBERS
|
||||
|
|
@ -60,11 +63,13 @@ private:
|
|||
// "this" must be a element inside of *basep
|
||||
// Use that to determine a structure offset, then apply to the new base
|
||||
// to get our new pointer information
|
||||
return (V3ListEnt*) ( ((vluint8_t*)newbasep) + offset);
|
||||
return (V3ListEnt*)(((vluint8_t*)newbasep) + offset);
|
||||
}
|
||||
|
||||
public:
|
||||
V3ListEnt()
|
||||
: m_nextp(NULL), m_prevp(NULL) {}
|
||||
: m_nextp(NULL)
|
||||
, m_prevp(NULL) {}
|
||||
~V3ListEnt() {
|
||||
#ifdef VL_DEBUG
|
||||
// Load bogus pointers so we can catch deletion bugs
|
||||
|
|
@ -99,10 +104,16 @@ public:
|
|||
// "this" must be a element inside of *oldp
|
||||
// cppcheck-suppress thisSubtraction
|
||||
size_t offset = (size_t)(vluint8_t*)(this) - (size_t)(vluint8_t*)(oldp);
|
||||
if (m_nextp) baseToListEnt(m_nextp, offset)->m_prevp = m_prevp;
|
||||
else listr.m_tailp = m_prevp;
|
||||
if (m_prevp) baseToListEnt(m_prevp, offset)->m_nextp = m_nextp;
|
||||
else listr.m_headp = m_nextp;
|
||||
if (m_nextp) {
|
||||
baseToListEnt(m_nextp, offset)->m_prevp = m_prevp;
|
||||
} else {
|
||||
listr.m_tailp = m_prevp;
|
||||
}
|
||||
if (m_prevp) {
|
||||
baseToListEnt(m_prevp, offset)->m_nextp = m_nextp;
|
||||
} else {
|
||||
listr.m_headp = m_nextp;
|
||||
}
|
||||
m_prevp = m_nextp = NULL;
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -52,10 +52,10 @@ protected:
|
|||
// Per-variable flags
|
||||
// Used in user()'s so initializes to all zeros
|
||||
struct {
|
||||
int m_notOpt:1; // NOT optimizable
|
||||
int m_notStd:1; // NOT optimizable if a non-blocktemp signal
|
||||
int m_stdFuncAsn:1; // Found simple assignment
|
||||
int m_done:1; // Removed
|
||||
int m_notOpt : 1; // NOT optimizable
|
||||
int m_notStd : 1; // NOT optimizable if a non-blocktemp signal
|
||||
int m_stdFuncAsn : 1; // Found simple assignment
|
||||
int m_done : 1; // Removed
|
||||
};
|
||||
// cppcheck-suppress unusedStructMember
|
||||
uint32_t m_flags;
|
||||
|
|
@ -75,7 +75,7 @@ private:
|
|||
// METHODS
|
||||
virtual void visit(AstVarRef* nodep) VL_OVERRIDE {
|
||||
// cppcheck-suppress unreadVariable // cppcheck 1.90 bug
|
||||
VarFlags flags (nodep->varp());
|
||||
VarFlags flags(nodep->varp());
|
||||
if (flags.m_done) {
|
||||
nodep->hiername(""); // Remove this->
|
||||
nodep->hierThis(true);
|
||||
|
|
@ -85,9 +85,7 @@ private:
|
|||
|
||||
public:
|
||||
// CONSTRUCTORS
|
||||
explicit LocalizeDehierVisitor(AstNetlist* nodep) {
|
||||
iterate(nodep);
|
||||
}
|
||||
explicit LocalizeDehierVisitor(AstNetlist* nodep) { iterate(nodep); }
|
||||
virtual ~LocalizeDehierVisitor() {}
|
||||
};
|
||||
|
||||
|
|
@ -98,9 +96,9 @@ class LocalizeVisitor : public LocalizeBaseVisitor {
|
|||
private:
|
||||
// NODE STATE/TYPES
|
||||
// See above
|
||||
AstUser1InUse m_inuser1;
|
||||
AstUser2InUse m_inuser2;
|
||||
AstUser4InUse m_inuser4;
|
||||
AstUser1InUse m_inuser1;
|
||||
AstUser2InUse m_inuser2;
|
||||
AstUser4InUse m_inuser4;
|
||||
|
||||
// STATE
|
||||
VDouble0 m_statLocVars; // Statistic tracking
|
||||
|
|
@ -109,14 +107,14 @@ private:
|
|||
|
||||
// METHODS
|
||||
void clearOptimizable(AstVar* nodep, const char* reason) {
|
||||
UINFO(4," NoOpt "<<reason<<" "<<nodep<<endl);
|
||||
VarFlags flags (nodep);
|
||||
UINFO(4, " NoOpt " << reason << " " << nodep << endl);
|
||||
VarFlags flags(nodep);
|
||||
flags.m_notOpt = true;
|
||||
flags.setNodeFlags(nodep);
|
||||
}
|
||||
void clearStdOptimizable(AstVar* nodep, const char* reason) {
|
||||
UINFO(4," NoStd "<<reason<<" "<<nodep<<endl);
|
||||
VarFlags flags (nodep);
|
||||
UINFO(4, " NoStd " << reason << " " << nodep << endl);
|
||||
VarFlags flags(nodep);
|
||||
flags.m_notStd = true;
|
||||
flags.setNodeFlags(nodep);
|
||||
}
|
||||
|
|
@ -125,15 +123,14 @@ private:
|
|||
AstVar* nodep = *it;
|
||||
if (nodep->valuep()) clearOptimizable(nodep, "HasInitValue");
|
||||
if (!VarFlags(nodep).m_stdFuncAsn) clearStdOptimizable(nodep, "NoStdAssign");
|
||||
VarFlags flags (nodep);
|
||||
VarFlags flags(nodep);
|
||||
|
||||
if ((nodep->isMovableToBlock() // Blocktemp
|
||||
|| !flags.m_notStd) // Or used only in block
|
||||
&& !flags.m_notOpt // Optimizable
|
||||
&& !nodep->isClassMember()
|
||||
&& nodep->user1p()) { // Single cfunc
|
||||
&& !nodep->isClassMember() && nodep->user1p()) { // Single cfunc
|
||||
// We don't need to test for tracing; it would be in the tracefunc if it was needed
|
||||
UINFO(4," ModVar->BlkVar "<<nodep<<endl);
|
||||
UINFO(4, " ModVar->BlkVar " << nodep << endl);
|
||||
++m_statLocVars;
|
||||
AstCFunc* newfuncp = VN_CAST(nodep->user1p(), CFunc);
|
||||
nodep->unlinkFrBack();
|
||||
|
|
@ -154,7 +151,7 @@ private:
|
|||
moveVars();
|
||||
}
|
||||
virtual void visit(AstCFunc* nodep) VL_OVERRIDE {
|
||||
UINFO(4," CFUNC "<<nodep<<endl);
|
||||
UINFO(4, " CFUNC " << nodep << endl);
|
||||
m_cfuncp = nodep;
|
||||
searchFuncStmts(nodep->argsp());
|
||||
searchFuncStmts(nodep->initsp());
|
||||
|
|
@ -168,14 +165,14 @@ private:
|
|||
// For now we only find simple assignments not under any other statement.
|
||||
// This could be more complicated; allow always-set under both branches of a IF.
|
||||
// If so, check for ArrayRef's and such, as they aren't acceptable.
|
||||
for (; nodep; nodep=nodep->nextp()) {
|
||||
for (; nodep; nodep = nodep->nextp()) {
|
||||
if (VN_IS(nodep, NodeAssign)) {
|
||||
if (AstVarRef* varrefp = VN_CAST(VN_CAST(nodep, NodeAssign)->lhsp(), VarRef)) {
|
||||
UASSERT_OBJ(varrefp->lvalue(), varrefp, "LHS assignment not lvalue");
|
||||
if (!varrefp->varp()->user4p()) {
|
||||
UINFO(4," FuncAsn "<<varrefp<<endl);
|
||||
UINFO(4, " FuncAsn " << varrefp << endl);
|
||||
varrefp->varp()->user4p(varrefp);
|
||||
VarFlags flags (varrefp->varp());
|
||||
VarFlags flags(varrefp->varp());
|
||||
flags.m_stdFuncAsn = true;
|
||||
flags.setNodeFlags(varrefp->varp());
|
||||
}
|
||||
|
|
@ -185,10 +182,9 @@ private:
|
|||
}
|
||||
|
||||
virtual void visit(AstVar* nodep) VL_OVERRIDE {
|
||||
if (!nodep->isSigPublic()
|
||||
&& !nodep->isPrimaryIO()
|
||||
if (!nodep->isSigPublic() && !nodep->isPrimaryIO()
|
||||
&& !m_cfuncp) { // Not already inside a function
|
||||
UINFO(4," BLKVAR "<<nodep<<endl);
|
||||
UINFO(4, " BLKVAR " << nodep << endl);
|
||||
m_varps.push_back(nodep);
|
||||
}
|
||||
// No iterate; Don't want varrefs under it
|
||||
|
|
@ -197,14 +193,13 @@ private:
|
|||
if (!VarFlags(nodep->varp()).m_notOpt) {
|
||||
if (!m_cfuncp) { // Not in function, can't optimize
|
||||
clearOptimizable(nodep->varp(), "BVnofunc");
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
// If we're scoping down to it, it isn't really in the same block
|
||||
if (!nodep->hierThis()) clearOptimizable(nodep->varp(), "HierRef");
|
||||
// Allow a variable to appear in only a single function
|
||||
AstNode* oldfunc = nodep->varp()->user1p();
|
||||
if (!oldfunc) {
|
||||
UINFO(4," BVnewref "<<nodep<<endl);
|
||||
UINFO(4, " BVnewref " << nodep << endl);
|
||||
nodep->varp()->user1p(m_cfuncp); // Remember where it was used
|
||||
} else if (m_cfuncp == oldfunc) {
|
||||
// Same usage
|
||||
|
|
@ -214,7 +209,7 @@ private:
|
|||
}
|
||||
// First varref in function must be assignment found earlier
|
||||
AstVarRef* firstasn = static_cast<AstVarRef*>(nodep->varp()->user4p());
|
||||
if (firstasn && nodep!=firstasn) {
|
||||
if (firstasn && nodep != firstasn) {
|
||||
clearStdOptimizable(nodep->varp(), "notFirstAsn");
|
||||
nodep->varp()->user4p(NULL);
|
||||
}
|
||||
|
|
@ -239,11 +234,11 @@ public:
|
|||
// Localize class functions
|
||||
|
||||
void V3Localize::localizeAll(AstNetlist* nodep) {
|
||||
UINFO(2,__FUNCTION__<<": "<<endl);
|
||||
UINFO(2, __FUNCTION__ << ": " << endl);
|
||||
{
|
||||
LocalizeVisitor visitor (nodep);
|
||||
LocalizeVisitor visitor(nodep);
|
||||
// Fix up hiernames
|
||||
LocalizeDehierVisitor dvisitor (nodep);
|
||||
LocalizeDehierVisitor dvisitor(nodep);
|
||||
} // Destruct before checking
|
||||
V3Global::dumpCheckGlobalTree("localize", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 6);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -41,11 +41,11 @@ private:
|
|||
// AstCell::user1() -> bool. Set true if already processed
|
||||
// AstScope::user1() -> bool. Set true if already processed
|
||||
// AstVar::user1() -> bool. Set true if already processed
|
||||
AstUser1InUse m_inuser1;
|
||||
AstUser1InUse m_inuser1;
|
||||
|
||||
// STATE
|
||||
AstNodeModule* m_modp;
|
||||
V3LanguageWords m_words; // Reserved word detector
|
||||
AstNodeModule* m_modp;
|
||||
V3LanguageWords m_words; // Reserved word detector
|
||||
|
||||
// METHODS
|
||||
VL_DEBUG_FUNC; // Declare debug()
|
||||
|
|
@ -53,16 +53,16 @@ private:
|
|||
void rename(AstNode* nodep, bool addPvt) {
|
||||
if (!nodep->user1()) { // Not already done
|
||||
if (addPvt) {
|
||||
string newname = string("__PVT__")+nodep->name();
|
||||
string newname = string("__PVT__") + nodep->name();
|
||||
nodep->name(newname);
|
||||
nodep->editCountInc();
|
||||
} else if (VN_IS(nodep, CFunc) && VN_CAST(nodep, CFunc)->isConstructor()) {
|
||||
} else {
|
||||
string rsvd = m_words.isKeyword(nodep->name());
|
||||
if (rsvd != "") {
|
||||
nodep->v3warn(SYMRSVDWORD, "Symbol matches "+rsvd
|
||||
+": "<<nodep->prettyNameQ());
|
||||
string newname = string("__SYM__")+nodep->name();
|
||||
nodep->v3warn(SYMRSVDWORD,
|
||||
"Symbol matches " + rsvd + ": " << nodep->prettyNameQ());
|
||||
string newname = string("__SYM__") + nodep->name();
|
||||
nodep->name(newname);
|
||||
nodep->editCountInc();
|
||||
}
|
||||
|
|
@ -83,10 +83,10 @@ private:
|
|||
// Add __PVT__ to names of local signals
|
||||
virtual void visit(AstVar* nodep) VL_OVERRIDE {
|
||||
// Don't iterate... Don't need temps for RANGES under the Var.
|
||||
rename(nodep, ((!m_modp || !m_modp->isTop())
|
||||
&& !nodep->isSigPublic()
|
||||
&& !nodep->isFuncLocal() // Isn't exposed, and would mess up dpi import wrappers
|
||||
&& !nodep->isTemp())); // Don't bother to rename internal signals
|
||||
rename(nodep,
|
||||
((!m_modp || !m_modp->isTop()) && !nodep->isSigPublic()
|
||||
&& !nodep->isFuncLocal() // Isn't exposed, and would mess up dpi import wrappers
|
||||
&& !nodep->isTemp())); // Don't bother to rename internal signals
|
||||
}
|
||||
virtual void visit(AstCFunc* nodep) VL_OVERRIDE {
|
||||
if (!nodep->user1()) {
|
||||
|
|
@ -102,8 +102,7 @@ private:
|
|||
}
|
||||
virtual void visit(AstCell* nodep) VL_OVERRIDE {
|
||||
if (!nodep->user1()) {
|
||||
rename(nodep, (!nodep->modp()->modPublic()
|
||||
&& !VN_IS(nodep->modp(), ClassPackage)));
|
||||
rename(nodep, (!nodep->modp()->modPublic() && !VN_IS(nodep->modp(), ClassPackage)));
|
||||
iterateChildren(nodep);
|
||||
}
|
||||
}
|
||||
|
|
@ -125,10 +124,13 @@ private:
|
|||
if (nodep->aboveCellp()) iterate(nodep->aboveCellp());
|
||||
// Always recompute name (as many levels above scope may have changed)
|
||||
// Same formula as V3Scope
|
||||
nodep->name(nodep->isTop() ? "TOP"
|
||||
: VN_IS(m_modp, Class) ? ("TOP." + m_modp->name())
|
||||
: VN_IS(m_modp, ClassPackage) ? ("TOP." + m_modp->name())
|
||||
: (nodep->aboveScopep()->name() + "." + nodep->aboveCellp()->name()));
|
||||
nodep->name(nodep->isTop()
|
||||
? "TOP"
|
||||
: VN_IS(m_modp, Class) ? ("TOP." + m_modp->name())
|
||||
: VN_IS(m_modp, ClassPackage)
|
||||
? ("TOP." + m_modp->name())
|
||||
: (nodep->aboveScopep()->name() + "."
|
||||
+ nodep->aboveCellp()->name()));
|
||||
nodep->editCountInc();
|
||||
iterateChildren(nodep);
|
||||
}
|
||||
|
|
@ -150,9 +152,7 @@ public:
|
|||
// Name class functions
|
||||
|
||||
void V3Name::nameAll(AstNetlist* nodep) {
|
||||
UINFO(2,__FUNCTION__<<": "<<endl);
|
||||
{
|
||||
NameVisitor visitor (nodep);
|
||||
} // Destruct before checking
|
||||
UINFO(2, __FUNCTION__ << ": " << endl);
|
||||
{ NameVisitor visitor(nodep); } // Destruct before checking
|
||||
V3Global::dumpCheckGlobalTree("name", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 6);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -36,54 +36,83 @@ void test(const string& lhss, const string& op, const string& rhss, const string
|
|||
|
||||
FileLine fl = new FileLine(FileLine::builtInFinename());
|
||||
|
||||
V3Number lhnum (fl, l1);
|
||||
V3Number rhnum (fl, r1);
|
||||
V3Number expnum (fl, e1);
|
||||
V3Number gotnum (fl, expnum.width());
|
||||
V3Number lhnum(fl, l1);
|
||||
V3Number rhnum(fl, r1);
|
||||
V3Number expnum(fl, e1);
|
||||
V3Number gotnum(fl, expnum.width());
|
||||
|
||||
if (op=="redOr") gotnum.opRedOr (lhnum);
|
||||
else if (op=="redAnd") gotnum.opRedAnd (lhnum);
|
||||
else if (op=="redXor") gotnum.opRedXor (lhnum);
|
||||
else if (op=="redXnor") gotnum.opRedXnor (lhnum);
|
||||
else if (op=="concat") gotnum.opConcat (lhnum, rhnum);
|
||||
else if (op=="repl") gotnum.opRepl (lhnum, rhnum);
|
||||
else if (op=="~") gotnum.opNot (lhnum);
|
||||
else if (op=="!") gotnum.opLogNot (lhnum);
|
||||
else if (op=="negate") gotnum.opNegate (lhnum);
|
||||
else if (op=="+") gotnum.opAdd (lhnum, rhnum);
|
||||
else if (op=="-") gotnum.opSub (lhnum, rhnum);
|
||||
else if (op=="*") gotnum.opMul (lhnum, rhnum);
|
||||
else if (op=="/") gotnum.opDiv (lhnum, rhnum);
|
||||
else if (op=="%") gotnum.opModDiv (lhnum, rhnum);
|
||||
else if (op=="&") gotnum.opAnd (lhnum, rhnum);
|
||||
else if (op=="|") gotnum.opOr (lhnum, rhnum);
|
||||
else if (op=="<") gotnum.opLt (lhnum, rhnum);
|
||||
else if (op==">") gotnum.opGt (lhnum, rhnum);
|
||||
else if (op==">>") gotnum.opShiftR (lhnum, rhnum);
|
||||
else if (op=="<<") gotnum.opShiftL (lhnum, rhnum);
|
||||
else if (op=="==") gotnum.opEq (lhnum, rhnum);
|
||||
else if (op=="===") gotnum.opCaseEq (lhnum, rhnum);
|
||||
else if (op=="==?") gotnum.opWildEq (lhnum, rhnum);
|
||||
else if (op=="!=") gotnum.opNeq (lhnum, rhnum);
|
||||
else if (op=="!==") gotnum.opCaseNeq (lhnum, rhnum);
|
||||
else if (op=="!=?") gotnum.opWildNeq (lhnum, rhnum);
|
||||
else if (op=="<=") gotnum.opLte (lhnum, rhnum);
|
||||
else if (op==">=") gotnum.opGte (lhnum, rhnum);
|
||||
else if (op=="&&") gotnum.opLogAnd (lhnum, rhnum);
|
||||
else if (op=="||") gotnum.opLogOr (lhnum, rhnum);
|
||||
else v3fatalSrc("Bad opcode: "<<op);
|
||||
if (op == "redOr") {
|
||||
gotnum.opRedOr(lhnum);
|
||||
} else if (op == "redAnd") {
|
||||
gotnum.opRedAnd(lhnum);
|
||||
} else if (op == "redXor") {
|
||||
gotnum.opRedXor(lhnum);
|
||||
} else if (op == "redXnor") {
|
||||
gotnum.opRedXnor(lhnum);
|
||||
} else if (op == "concat") {
|
||||
gotnum.opConcat(lhnum, rhnum);
|
||||
} else if (op == "repl") {
|
||||
gotnum.opRepl(lhnum, rhnum);
|
||||
} else if (op == "~") {
|
||||
gotnum.opNot(lhnum);
|
||||
} else if (op == "!") {
|
||||
gotnum.opLogNot(lhnum);
|
||||
} else if (op == "negate") {
|
||||
gotnum.opNegate(lhnum);
|
||||
} else if (op == "+") {
|
||||
gotnum.opAdd(lhnum, rhnum);
|
||||
} else if (op == "-") {
|
||||
gotnum.opSub(lhnum, rhnum);
|
||||
} else if (op == "*") {
|
||||
gotnum.opMul(lhnum, rhnum);
|
||||
} else if (op == "/") {
|
||||
gotnum.opDiv(lhnum, rhnum);
|
||||
} else if (op == "%") {
|
||||
gotnum.opModDiv(lhnum, rhnum);
|
||||
} else if (op == "&") {
|
||||
gotnum.opAnd(lhnum, rhnum);
|
||||
} else if (op == "|") {
|
||||
gotnum.opOr(lhnum, rhnum);
|
||||
} else if (op == "<") {
|
||||
gotnum.opLt(lhnum, rhnum);
|
||||
} else if (op == ">") {
|
||||
gotnum.opGt(lhnum, rhnum);
|
||||
} else if (op == ">>") {
|
||||
gotnum.opShiftR(lhnum, rhnum);
|
||||
} else if (op == "<<") {
|
||||
gotnum.opShiftL(lhnum, rhnum);
|
||||
} else if (op == "==") {
|
||||
gotnum.opEq(lhnum, rhnum);
|
||||
} else if (op == "===") {
|
||||
gotnum.opCaseEq(lhnum, rhnum);
|
||||
} else if (op == "==?") {
|
||||
gotnum.opWildEq(lhnum, rhnum);
|
||||
} else if (op == "!=") {
|
||||
gotnum.opNeq(lhnum, rhnum);
|
||||
} else if (op == "!==") {
|
||||
gotnum.opCaseNeq(lhnum, rhnum);
|
||||
} else if (op == "!=?") {
|
||||
gotnum.opWildNeq(lhnum, rhnum);
|
||||
} else if (op == "<=") {
|
||||
gotnum.opLte(lhnum, rhnum);
|
||||
} else if (op == ">=") {
|
||||
gotnum.opGte(lhnum, rhnum);
|
||||
} else if (op == "&&") {
|
||||
gotnum.opLogAnd(lhnum, rhnum);
|
||||
} else if (op == "||") {
|
||||
gotnum.opLogOr(lhnum, rhnum);
|
||||
} else
|
||||
v3fatalSrc("Bad opcode: " << op);
|
||||
|
||||
UINFO(0,"------- Test:\n"
|
||||
<<" "<<lhnum<<" "<<op<<endl
|
||||
<<" "<<rhnum<<endl
|
||||
<<" = "<<expnum<<endl
|
||||
<<" =? "<<gotnum<<endl);
|
||||
UINFO(0, "------- Test:\n"
|
||||
<< " " << lhnum << " " << op << endl
|
||||
<< " " << rhnum << endl
|
||||
<< " = " << expnum << endl
|
||||
<< " =? " << gotnum << endl);
|
||||
|
||||
V3Number ok (fl, 1);
|
||||
V3Number ok(fl, 1);
|
||||
ok.opCaseEq(expnum, gotnum);
|
||||
if (ok.toUInt()!=1) {
|
||||
v3fatalSrc("%Error:Test FAILED");
|
||||
}
|
||||
if (ok.toUInt() != 1) { v3fatalSrc("%Error:Test FAILED"); }
|
||||
|
||||
free(l1);
|
||||
free(r1);
|
||||
|
|
@ -91,10 +120,10 @@ void test(const string& lhss, const string& op, const string& rhss, const string
|
|||
}
|
||||
|
||||
int main() {
|
||||
UINFO(0,"Test starting\n");
|
||||
UINFO(0, "Test starting\n");
|
||||
|
||||
test("32'b10", "|", "32'b10", "32'b10");
|
||||
test( "2'bx0", "|", "2'b10", "2'b10");
|
||||
test("2'bx0", "|", "2'b10", "2'b10");
|
||||
test("32'b0x", "|", "32'b10", "32'b1x");
|
||||
test("32'b10", "&", "32'b11", "32'b10");
|
||||
test("32'b10", "+", "32'b10", "32'b100");
|
||||
|
|
@ -106,9 +135,10 @@ int main() {
|
|||
test("57'h000000010F0CCE7", "*", "57'h10", "57'h10F0CCE70");
|
||||
test("57'h000000010F0CCE7", "*", "57'h0DE34E7FFFFFFFF", "57'h02A9D57EF0F3319");
|
||||
test("67'h7FFFFFFFFFFFFFFFF", "*", "67'h4000000003C8A8D6A", "67'h3FFFFFFFFC3757296");
|
||||
test("99'h7FFFFFFFFFFFFFFFFFFFFFFFF", "*", "99'h0000000000000000091338A80", "99'h7FFFFFFFFFFFFFFFF6ECC7580");
|
||||
test("99'h7FFFFFFFFFFFFFFFFFFFFFFFF", "*", "99'h0000000000000000091338A80",
|
||||
"99'h7FFFFFFFFFFFFFFFF6ECC7580");
|
||||
|
||||
cout<<"Test completed\n";
|
||||
cout << "Test completed\n";
|
||||
}
|
||||
|
||||
//###################################################################
|
||||
|
|
|
|||
|
|
@ -36,7 +36,6 @@
|
|||
// OrderPreCutEdge
|
||||
//*************************************************************************
|
||||
|
||||
|
||||
#ifndef _V3ORDERGRAPH_H_
|
||||
#define _V3ORDERGRAPH_H_
|
||||
|
||||
|
|
@ -56,13 +55,14 @@ class OrderMoveDomScope;
|
|||
//######################################################################
|
||||
|
||||
enum OrderWeights {
|
||||
WEIGHT_INPUT = 1, // Low weight just so dot graph looks nice
|
||||
WEIGHT_COMBO = 1, // Breakable combo logic
|
||||
WEIGHT_INPUT = 1, // Low weight just so dot graph looks nice
|
||||
WEIGHT_COMBO = 1, // Breakable combo logic
|
||||
WEIGHT_LOOPBE = 1, // Connection to loop begin/end
|
||||
WEIGHT_POST = 2, // Post-delayed used var
|
||||
WEIGHT_PRE = 3, // Breakable pre-delayed used var
|
||||
WEIGHT_POST = 2, // Post-delayed used var
|
||||
WEIGHT_PRE = 3, // Breakable pre-delayed used var
|
||||
WEIGHT_MEDIUM = 8, // Medium weight just so dot graph looks nice
|
||||
WEIGHT_NORMAL = 32 }; // High weight just so dot graph looks nice
|
||||
WEIGHT_NORMAL = 32
|
||||
}; // High weight just so dot graph looks nice
|
||||
|
||||
struct OrderVEdgeType {
|
||||
enum en {
|
||||
|
|
@ -84,20 +84,21 @@ struct OrderVEdgeType {
|
|||
_ENUM_END
|
||||
};
|
||||
const char* ascii() const {
|
||||
static const char* const names[] = {
|
||||
"%E-vedge", "VERTEX_INPUTS", "VERTEX_SETTLE", "VERTEX_LOGIC",
|
||||
"VERTEX_VARSTD", "VERTEX_VARPRE", "VERTEX_VARPOST",
|
||||
"VERTEX_VARPORD", "VERTEX_VARSETTLE", "VERTEX_MOVE",
|
||||
"EDGE_STD", "EDGE_CHANGEDET", "EDGE_COMBOCUT",
|
||||
"EDGE_PRECUT", "EDGE_POSTCUT", "_ENUM_END"
|
||||
};
|
||||
static const char* const names[]
|
||||
= {"%E-vedge", "VERTEX_INPUTS", "VERTEX_SETTLE", "VERTEX_LOGIC",
|
||||
"VERTEX_VARSTD", "VERTEX_VARPRE", "VERTEX_VARPOST", "VERTEX_VARPORD",
|
||||
"VERTEX_VARSETTLE", "VERTEX_MOVE", "EDGE_STD", "EDGE_CHANGEDET",
|
||||
"EDGE_COMBOCUT", "EDGE_PRECUT", "EDGE_POSTCUT", "_ENUM_END"};
|
||||
return names[m_e];
|
||||
}
|
||||
enum en m_e;
|
||||
inline OrderVEdgeType() : m_e(VERTEX_UNKNOWN) {}
|
||||
inline OrderVEdgeType()
|
||||
: m_e(VERTEX_UNKNOWN) {}
|
||||
// cppcheck-suppress noExplicitConstructor
|
||||
inline OrderVEdgeType(en _e) : m_e(_e) {}
|
||||
explicit inline OrderVEdgeType(int _e) : m_e(static_cast<en>(_e)) {}
|
||||
inline OrderVEdgeType(en _e)
|
||||
: m_e(_e) {}
|
||||
explicit inline OrderVEdgeType(int _e)
|
||||
: m_e(static_cast<en>(_e)) {}
|
||||
operator en() const { return m_e; }
|
||||
};
|
||||
inline bool operator==(const OrderVEdgeType& lhs, const OrderVEdgeType& rhs) {
|
||||
|
|
@ -139,18 +140,23 @@ class OrderEitherVertex : public V3GraphVertex {
|
|||
bool m_isFromInput; // From input, or derived therefrom (conservatively false)
|
||||
protected:
|
||||
OrderEitherVertex(V3Graph* graphp, const OrderEitherVertex& old)
|
||||
: V3GraphVertex(graphp, old), m_scopep(old.m_scopep), m_domainp(old.m_domainp)
|
||||
: V3GraphVertex(graphp, old)
|
||||
, m_scopep(old.m_scopep)
|
||||
, m_domainp(old.m_domainp)
|
||||
, m_isFromInput(old.m_isFromInput) {}
|
||||
|
||||
public:
|
||||
OrderEitherVertex(V3Graph* graphp, AstScope* scopep, AstSenTree* domainp)
|
||||
: V3GraphVertex(graphp), m_scopep(scopep), m_domainp(domainp)
|
||||
: V3GraphVertex(graphp)
|
||||
, m_scopep(scopep)
|
||||
, m_domainp(domainp)
|
||||
, m_isFromInput(false) {}
|
||||
virtual ~OrderEitherVertex() {}
|
||||
virtual OrderEitherVertex* clone(V3Graph* graphp) const = 0;
|
||||
// Methods
|
||||
virtual OrderVEdgeType type() const = 0;
|
||||
virtual bool domainMatters() = 0; // Must be in same domain when cross edge to this vertex
|
||||
virtual string dotName() const { return cvtToHex(m_scopep)+"_"; }
|
||||
virtual string dotName() const { return cvtToHex(m_scopep) + "_"; }
|
||||
// ACCESSORS
|
||||
void domainp(AstSenTree* domainp) { m_domainp = domainp; }
|
||||
AstScope* scopep() const { return m_scopep; }
|
||||
|
|
@ -162,6 +168,7 @@ public:
|
|||
class OrderInputsVertex : public OrderEitherVertex {
|
||||
OrderInputsVertex(V3Graph* graphp, const OrderInputsVertex& old)
|
||||
: OrderEitherVertex(graphp, old) {}
|
||||
|
||||
public:
|
||||
OrderInputsVertex(V3Graph* graphp, AstSenTree* domainp)
|
||||
: OrderEitherVertex(graphp, NULL, domainp) {
|
||||
|
|
@ -169,7 +176,8 @@ public:
|
|||
}
|
||||
virtual ~OrderInputsVertex() {}
|
||||
virtual OrderInputsVertex* clone(V3Graph* graphp) const {
|
||||
return new OrderInputsVertex(graphp, *this); }
|
||||
return new OrderInputsVertex(graphp, *this);
|
||||
}
|
||||
virtual OrderVEdgeType type() const { return OrderVEdgeType::VERTEX_INPUTS; }
|
||||
virtual string name() const { return "*INPUTS*"; }
|
||||
virtual string dotColor() const { return "green"; }
|
||||
|
|
@ -180,12 +188,14 @@ public:
|
|||
class OrderSettleVertex : public OrderEitherVertex {
|
||||
OrderSettleVertex(V3Graph* graphp, const OrderSettleVertex& old)
|
||||
: OrderEitherVertex(graphp, old) {}
|
||||
|
||||
public:
|
||||
OrderSettleVertex(V3Graph* graphp, AstSenTree* domainp)
|
||||
: OrderEitherVertex(graphp, NULL, domainp) {}
|
||||
virtual ~OrderSettleVertex() {}
|
||||
virtual OrderSettleVertex* clone(V3Graph* graphp) const {
|
||||
return new OrderSettleVertex(graphp, *this); }
|
||||
return new OrderSettleVertex(graphp, *this);
|
||||
}
|
||||
virtual OrderVEdgeType type() const { return OrderVEdgeType::VERTEX_SETTLE; }
|
||||
virtual string name() const { return "*SETTLE*"; }
|
||||
virtual string dotColor() const { return "green"; }
|
||||
|
|
@ -194,21 +204,27 @@ public:
|
|||
};
|
||||
|
||||
class OrderLogicVertex : public OrderEitherVertex {
|
||||
AstNode* m_nodep;
|
||||
AstNode* m_nodep;
|
||||
|
||||
protected:
|
||||
OrderLogicVertex(V3Graph* graphp, const OrderLogicVertex& old)
|
||||
: OrderEitherVertex(graphp, old), m_nodep(old.m_nodep) {}
|
||||
: OrderEitherVertex(graphp, old)
|
||||
, m_nodep(old.m_nodep) {}
|
||||
|
||||
public:
|
||||
OrderLogicVertex(V3Graph* graphp, AstScope* scopep, AstSenTree* domainp, AstNode* nodep)
|
||||
: OrderEitherVertex(graphp, scopep, domainp), m_nodep(nodep) {}
|
||||
: OrderEitherVertex(graphp, scopep, domainp)
|
||||
, m_nodep(nodep) {}
|
||||
virtual ~OrderLogicVertex() {}
|
||||
virtual OrderLogicVertex* clone(V3Graph* graphp) const {
|
||||
return new OrderLogicVertex(graphp, *this); }
|
||||
return new OrderLogicVertex(graphp, *this);
|
||||
}
|
||||
virtual OrderVEdgeType type() const { return OrderVEdgeType::VERTEX_LOGIC; }
|
||||
virtual bool domainMatters() { return true; }
|
||||
// ACCESSORS
|
||||
virtual string name() const {
|
||||
return (cvtToHex(m_nodep)+"\\n "+cvtToStr(nodep()->typeName())); }
|
||||
return (cvtToHex(m_nodep) + "\\n " + cvtToStr(nodep()->typeName()));
|
||||
}
|
||||
AstNode* nodep() const { return m_nodep; }
|
||||
virtual string dotColor() const { return "yellow"; }
|
||||
};
|
||||
|
|
@ -220,12 +236,16 @@ class OrderVarVertex : public OrderEitherVertex {
|
|||
protected:
|
||||
OrderVarVertex(V3Graph* graphp, const OrderVarVertex& old)
|
||||
: OrderEitherVertex(graphp, old)
|
||||
, m_varScp(old.m_varScp), m_isClock(old.m_isClock)
|
||||
, m_varScp(old.m_varScp)
|
||||
, m_isClock(old.m_isClock)
|
||||
, m_isDelayed(old.m_isDelayed) {}
|
||||
|
||||
public:
|
||||
OrderVarVertex(V3Graph* graphp, AstScope* scopep, AstVarScope* varScp)
|
||||
: OrderEitherVertex(graphp, scopep, NULL), m_varScp(varScp)
|
||||
, m_isClock(false), m_isDelayed(false) {}
|
||||
: OrderEitherVertex(graphp, scopep, NULL)
|
||||
, m_varScp(varScp)
|
||||
, m_isClock(false)
|
||||
, m_isDelayed(false) {}
|
||||
virtual ~OrderVarVertex() {}
|
||||
virtual OrderVarVertex* clone(V3Graph* graphp) const = 0;
|
||||
virtual OrderVEdgeType type() const = 0;
|
||||
|
|
@ -241,70 +261,80 @@ public:
|
|||
class OrderVarStdVertex : public OrderVarVertex {
|
||||
OrderVarStdVertex(V3Graph* graphp, const OrderVarStdVertex& old)
|
||||
: OrderVarVertex(graphp, old) {}
|
||||
|
||||
public:
|
||||
OrderVarStdVertex(V3Graph* graphp, AstScope* scopep, AstVarScope* varScp)
|
||||
: OrderVarVertex(graphp, scopep, varScp) {}
|
||||
virtual ~OrderVarStdVertex() {}
|
||||
virtual OrderVarStdVertex* clone(V3Graph* graphp) const {
|
||||
return new OrderVarStdVertex(graphp, *this); }
|
||||
return new OrderVarStdVertex(graphp, *this);
|
||||
}
|
||||
virtual OrderVEdgeType type() const { return OrderVEdgeType::VERTEX_VARSTD; }
|
||||
virtual string name() const { return (cvtToHex(varScp())+"\\n "+varScp()->name());}
|
||||
virtual string name() const { return (cvtToHex(varScp()) + "\\n " + varScp()->name()); }
|
||||
virtual string dotColor() const { return "skyblue"; }
|
||||
virtual bool domainMatters() { return true; }
|
||||
};
|
||||
class OrderVarPreVertex : public OrderVarVertex {
|
||||
OrderVarPreVertex(V3Graph* graphp, const OrderVarPreVertex& old)
|
||||
: OrderVarVertex(graphp, old) {}
|
||||
|
||||
public:
|
||||
OrderVarPreVertex(V3Graph* graphp, AstScope* scopep, AstVarScope* varScp)
|
||||
: OrderVarVertex(graphp, scopep, varScp) {}
|
||||
virtual ~OrderVarPreVertex() {}
|
||||
virtual OrderVarPreVertex* clone(V3Graph* graphp) const {
|
||||
return new OrderVarPreVertex(graphp, *this); }
|
||||
return new OrderVarPreVertex(graphp, *this);
|
||||
}
|
||||
virtual OrderVEdgeType type() const { return OrderVEdgeType::VERTEX_VARPRE; }
|
||||
virtual string name() const { return (cvtToHex(varScp())+" PRE\\n "+varScp()->name());}
|
||||
virtual string name() const { return (cvtToHex(varScp()) + " PRE\\n " + varScp()->name()); }
|
||||
virtual string dotColor() const { return "lightblue"; }
|
||||
virtual bool domainMatters() { return false; }
|
||||
};
|
||||
class OrderVarPostVertex : public OrderVarVertex {
|
||||
OrderVarPostVertex(V3Graph* graphp, const OrderVarPostVertex& old)
|
||||
: OrderVarVertex(graphp, old) {}
|
||||
|
||||
public:
|
||||
OrderVarPostVertex(V3Graph* graphp, AstScope* scopep, AstVarScope* varScp)
|
||||
: OrderVarVertex(graphp, scopep, varScp) {}
|
||||
virtual OrderVarPostVertex* clone(V3Graph* graphp) const {
|
||||
return new OrderVarPostVertex(graphp, *this); }
|
||||
return new OrderVarPostVertex(graphp, *this);
|
||||
}
|
||||
virtual OrderVEdgeType type() const { return OrderVEdgeType::VERTEX_VARPOST; }
|
||||
virtual ~OrderVarPostVertex() {}
|
||||
virtual string name() const { return (cvtToHex(varScp())+" POST\\n "+varScp()->name());}
|
||||
virtual string name() const { return (cvtToHex(varScp()) + " POST\\n " + varScp()->name()); }
|
||||
virtual string dotColor() const { return "CadetBlue"; }
|
||||
virtual bool domainMatters() { return false; }
|
||||
};
|
||||
class OrderVarPordVertex : public OrderVarVertex {
|
||||
OrderVarPordVertex(V3Graph* graphp, const OrderVarPordVertex& old)
|
||||
: OrderVarVertex(graphp, old) {}
|
||||
|
||||
public:
|
||||
OrderVarPordVertex(V3Graph* graphp, AstScope* scopep, AstVarScope* varScp)
|
||||
: OrderVarVertex(graphp, scopep, varScp) {}
|
||||
virtual ~OrderVarPordVertex() {}
|
||||
virtual OrderVarPordVertex* clone(V3Graph* graphp) const {
|
||||
return new OrderVarPordVertex(graphp, *this); }
|
||||
return new OrderVarPordVertex(graphp, *this);
|
||||
}
|
||||
virtual OrderVEdgeType type() const { return OrderVEdgeType::VERTEX_VARPORD; }
|
||||
virtual string name() const { return (cvtToHex(varScp())+" PORD\\n "+varScp()->name());}
|
||||
virtual string name() const { return (cvtToHex(varScp()) + " PORD\\n " + varScp()->name()); }
|
||||
virtual string dotColor() const { return "NavyBlue"; }
|
||||
virtual bool domainMatters() { return false; }
|
||||
};
|
||||
class OrderVarSettleVertex : public OrderVarVertex {
|
||||
OrderVarSettleVertex(V3Graph* graphp, const OrderVarSettleVertex& old)
|
||||
: OrderVarVertex(graphp, old) {}
|
||||
|
||||
public:
|
||||
OrderVarSettleVertex(V3Graph* graphp, AstScope* scopep, AstVarScope* varScp)
|
||||
: OrderVarVertex(graphp, scopep, varScp) {}
|
||||
virtual ~OrderVarSettleVertex() {}
|
||||
virtual OrderVarSettleVertex* clone(V3Graph* graphp) const {
|
||||
return new OrderVarSettleVertex(graphp, *this); }
|
||||
return new OrderVarSettleVertex(graphp, *this);
|
||||
}
|
||||
virtual OrderVEdgeType type() const { return OrderVEdgeType::VERTEX_VARSETTLE; }
|
||||
virtual string name() const { return (cvtToHex(varScp())+" STL\\n "+varScp()->name());}
|
||||
virtual string name() const { return (cvtToHex(varScp()) + " STL\\n " + varScp()->name()); }
|
||||
virtual string dotColor() const { return "PowderBlue"; }
|
||||
virtual bool domainMatters() { return false; }
|
||||
};
|
||||
|
|
@ -313,7 +343,7 @@ public:
|
|||
//--- Following only under the move graph, not the main graph
|
||||
|
||||
class OrderMoveVertex : public V3GraphVertex {
|
||||
typedef enum {POM_WAIT, POM_READY, POM_MOVED} OrderMState;
|
||||
typedef enum { POM_WAIT, POM_READY, POM_MOVED } OrderMState;
|
||||
|
||||
OrderLogicVertex* m_logicp;
|
||||
OrderMState m_state; // Movement state
|
||||
|
|
@ -329,40 +359,50 @@ protected:
|
|||
public:
|
||||
// CONSTRUCTORS
|
||||
OrderMoveVertex(V3Graph* graphp, OrderLogicVertex* logicp)
|
||||
: V3GraphVertex(graphp), m_logicp(logicp), m_state(POM_WAIT), m_domScopep(NULL) {}
|
||||
: V3GraphVertex(graphp)
|
||||
, m_logicp(logicp)
|
||||
, m_state(POM_WAIT)
|
||||
, m_domScopep(NULL) {}
|
||||
virtual ~OrderMoveVertex() {}
|
||||
virtual OrderMoveVertex* clone(V3Graph* graphp) const {
|
||||
v3fatalSrc("Unsupported"); return NULL; }
|
||||
v3fatalSrc("Unsupported");
|
||||
return NULL;
|
||||
}
|
||||
// METHODS
|
||||
virtual OrderVEdgeType type() const { return OrderVEdgeType::VERTEX_MOVE; }
|
||||
virtual string dotColor() const {
|
||||
if (logicp()) return logicp()->dotColor();
|
||||
else return "";
|
||||
if (logicp()) {
|
||||
return logicp()->dotColor();
|
||||
} else {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
virtual FileLine* fileline() const {
|
||||
if (logicp()) return logicp()->fileline();
|
||||
else return NULL;
|
||||
if (logicp()) {
|
||||
return logicp()->fileline();
|
||||
} else {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
virtual string name() const {
|
||||
string nm;
|
||||
if (logicp()) {
|
||||
nm = logicp()->name();
|
||||
nm += (string("\\nMV:")
|
||||
+" d="+cvtToHex(logicp()->domainp())
|
||||
+" s="+cvtToHex(logicp()->scopep()));
|
||||
nm += (string("\\nMV:") + " d=" + cvtToHex(logicp()->domainp())
|
||||
+ " s=" + cvtToHex(logicp()->scopep()));
|
||||
} else {
|
||||
nm = "nul";
|
||||
}
|
||||
return nm;
|
||||
}
|
||||
OrderLogicVertex* logicp() const { return m_logicp; }
|
||||
bool isWait() const { return m_state==POM_WAIT; }
|
||||
bool isWait() const { return m_state == POM_WAIT; }
|
||||
void setReady() {
|
||||
UASSERT(m_state==POM_WAIT, "Wait->Ready on node not in proper state");
|
||||
UASSERT(m_state == POM_WAIT, "Wait->Ready on node not in proper state");
|
||||
m_state = POM_READY;
|
||||
}
|
||||
void setMoved() {
|
||||
UASSERT(m_state==POM_READY, "Ready->Moved on node not in proper state");
|
||||
UASSERT(m_state == POM_READY, "Ready->Moved on node not in proper state");
|
||||
m_state = POM_MOVED;
|
||||
}
|
||||
OrderMoveDomScope* domScopep() const { return m_domScopep; }
|
||||
|
|
@ -383,34 +423,40 @@ class MTaskMoveVertex : public V3GraphVertex {
|
|||
protected:
|
||||
friend class OrderVisitor;
|
||||
friend class MTaskMoveVertexMaker;
|
||||
|
||||
public:
|
||||
MTaskMoveVertex(V3Graph* graphp, OrderLogicVertex* logicp,
|
||||
const OrderEitherVertex* varp,
|
||||
MTaskMoveVertex(V3Graph* graphp, OrderLogicVertex* logicp, const OrderEitherVertex* varp,
|
||||
const AstScope* scopep, const AstSenTree* domainp)
|
||||
: V3GraphVertex(graphp), m_logicp(logicp),
|
||||
m_varp(varp), m_scopep(scopep), m_domainp(domainp) {
|
||||
UASSERT(!(logicp && varp),
|
||||
"MTaskMoveVertex: logicp and varp may not both be set!\n");
|
||||
: V3GraphVertex(graphp)
|
||||
, m_logicp(logicp)
|
||||
, m_varp(varp)
|
||||
, m_scopep(scopep)
|
||||
, m_domainp(domainp) {
|
||||
UASSERT(!(logicp && varp), "MTaskMoveVertex: logicp and varp may not both be set!\n");
|
||||
}
|
||||
virtual ~MTaskMoveVertex() {}
|
||||
virtual MTaskMoveVertex* clone(V3Graph* graphp) const {
|
||||
v3fatalSrc("Unsupported"); return NULL; }
|
||||
v3fatalSrc("Unsupported");
|
||||
return NULL;
|
||||
}
|
||||
virtual OrderVEdgeType type() const { return OrderVEdgeType::VERTEX_MOVE; }
|
||||
virtual string dotColor() const {
|
||||
if (logicp()) return logicp()->dotColor();
|
||||
else return "yellow";
|
||||
if (logicp()) {
|
||||
return logicp()->dotColor();
|
||||
} else {
|
||||
return "yellow";
|
||||
}
|
||||
}
|
||||
virtual string name() const {
|
||||
string nm;
|
||||
if (logicp()) {
|
||||
nm = logicp()->name();
|
||||
nm += (string("\\nMV:")
|
||||
+" d="+cvtToHex(logicp()->domainp())
|
||||
+" s="+cvtToHex(logicp()->scopep())
|
||||
nm += (string("\\nMV:") + " d=" + cvtToHex(logicp()->domainp()) + " s="
|
||||
+ cvtToHex(logicp()->scopep())
|
||||
// "color()" represents the mtask ID.
|
||||
+"\\nt="+cvtToStr(color()));
|
||||
+ "\\nt=" + cvtToStr(color()));
|
||||
} else {
|
||||
nm = "nolog\\nt="+cvtToStr(color());
|
||||
nm = "nolog\\nt=" + cvtToStr(color());
|
||||
}
|
||||
return nm;
|
||||
}
|
||||
|
|
@ -426,12 +472,12 @@ public:
|
|||
|
||||
class OrderEdge : public V3GraphEdge {
|
||||
protected:
|
||||
OrderEdge(V3Graph* graphp, V3GraphVertex* fromp, V3GraphVertex* top,
|
||||
const OrderEdge& old)
|
||||
OrderEdge(V3Graph* graphp, V3GraphVertex* fromp, V3GraphVertex* top, const OrderEdge& old)
|
||||
: V3GraphEdge(graphp, fromp, top, old) {}
|
||||
|
||||
public:
|
||||
OrderEdge(V3Graph* graphp, V3GraphVertex* fromp, V3GraphVertex* top,
|
||||
int weight, bool cutable=false)
|
||||
OrderEdge(V3Graph* graphp, V3GraphVertex* fromp, V3GraphVertex* top, int weight,
|
||||
bool cutable = false)
|
||||
: V3GraphEdge(graphp, fromp, top, weight, cutable) {}
|
||||
virtual ~OrderEdge() {}
|
||||
virtual OrderVEdgeType type() const { return OrderVEdgeType::EDGE_STD; }
|
||||
|
|
@ -461,13 +507,14 @@ class OrderComboCutEdge : public OrderEdge {
|
|||
OrderComboCutEdge(V3Graph* graphp, V3GraphVertex* fromp, V3GraphVertex* top,
|
||||
const OrderComboCutEdge& old)
|
||||
: OrderEdge(graphp, fromp, top, old) {}
|
||||
|
||||
public:
|
||||
OrderComboCutEdge(V3Graph* graphp, V3GraphVertex* fromp, V3GraphVertex* top)
|
||||
: OrderEdge(graphp, fromp, top, WEIGHT_COMBO, CUTABLE) {}
|
||||
virtual OrderVEdgeType type() const { return OrderVEdgeType::EDGE_COMBOCUT; }
|
||||
virtual ~OrderComboCutEdge() {}
|
||||
virtual OrderComboCutEdge* clone(V3Graph* graphp,
|
||||
V3GraphVertex* fromp, V3GraphVertex* top) const {
|
||||
virtual OrderComboCutEdge* clone(V3Graph* graphp, V3GraphVertex* fromp,
|
||||
V3GraphVertex* top) const {
|
||||
return new OrderComboCutEdge(graphp, fromp, top, *this);
|
||||
}
|
||||
virtual string dotColor() const { return "yellowGreen"; }
|
||||
|
|
@ -482,13 +529,14 @@ class OrderPostCutEdge : public OrderEdge {
|
|||
OrderPostCutEdge(V3Graph* graphp, V3GraphVertex* fromp, V3GraphVertex* top,
|
||||
const OrderPostCutEdge& old)
|
||||
: OrderEdge(graphp, fromp, top, old) {}
|
||||
|
||||
public:
|
||||
OrderPostCutEdge(V3Graph* graphp, V3GraphVertex* fromp, V3GraphVertex* top)
|
||||
: OrderEdge(graphp, fromp, top, WEIGHT_COMBO, CUTABLE) {}
|
||||
virtual OrderVEdgeType type() const { return OrderVEdgeType::EDGE_POSTCUT; }
|
||||
virtual ~OrderPostCutEdge() {}
|
||||
virtual OrderPostCutEdge* clone(V3Graph* graphp,
|
||||
V3GraphVertex* fromp, V3GraphVertex* top) const {
|
||||
virtual OrderPostCutEdge* clone(V3Graph* graphp, V3GraphVertex* fromp,
|
||||
V3GraphVertex* top) const {
|
||||
return new OrderPostCutEdge(graphp, fromp, top, *this);
|
||||
}
|
||||
virtual string dotColor() const { return "PaleGreen"; }
|
||||
|
|
@ -503,12 +551,13 @@ class OrderPreCutEdge : public OrderEdge {
|
|||
OrderPreCutEdge(V3Graph* graphp, V3GraphVertex* fromp, V3GraphVertex* top,
|
||||
const OrderPreCutEdge& old)
|
||||
: OrderEdge(graphp, fromp, top, old) {}
|
||||
|
||||
public:
|
||||
OrderPreCutEdge(V3Graph* graphp, V3GraphVertex* fromp, V3GraphVertex* top)
|
||||
: OrderEdge(graphp, fromp, top, WEIGHT_PRE, CUTABLE) {}
|
||||
virtual OrderVEdgeType type() const { return OrderVEdgeType::EDGE_PRECUT; }
|
||||
virtual OrderPreCutEdge* clone(V3Graph* graphp,
|
||||
V3GraphVertex* fromp, V3GraphVertex* top) const {
|
||||
virtual OrderPreCutEdge* clone(V3Graph* graphp, V3GraphVertex* fromp,
|
||||
V3GraphVertex* top) const {
|
||||
return new OrderPreCutEdge(graphp, fromp, top, *this);
|
||||
}
|
||||
virtual ~OrderPreCutEdge() {}
|
||||
|
|
|
|||
17
src/V3Os.h
17
src/V3Os.h
|
|
@ -34,17 +34,21 @@ public:
|
|||
|
||||
// METHODS (generic filename utilities)
|
||||
static string filenameFromDirBase(const string& dir, const string& basename);
|
||||
static string filenameNonDir(const string& filename); ///< Return non-directory part of filename
|
||||
static string filenameNonExt(const string& filename); ///< Return non-extensioned (no .) part of filename
|
||||
/// Return non-directory part of filename
|
||||
static string filenameNonDir(const string& filename);
|
||||
/// Return non-extensioned (no .) part of filename
|
||||
static string filenameNonExt(const string& filename);
|
||||
static string filenameNonDirExt(const string& filename) { ///< Return basename of filename
|
||||
return filenameNonExt(filenameNonDir(filename)); }
|
||||
return filenameNonExt(filenameNonDir(filename));
|
||||
}
|
||||
static string filenameDir(const string& filename); ///< Return directory part of filename
|
||||
static string filenameSubstitute(const string& filename); ///< Return filename with env vars removed
|
||||
/// Return filename with env vars removed
|
||||
static string filenameSubstitute(const string& filename);
|
||||
static string filenameRealPath(const string& filename); ///< Return realpath of filename
|
||||
static bool filenameIsRel(const string& filename); ///< True if relative
|
||||
|
||||
// METHODS (file utilities)
|
||||
static string getline(std::istream& is, char delim='\n');
|
||||
static string getline(std::istream& is, char delim = '\n');
|
||||
|
||||
// METHODS (directory utilities)
|
||||
static void createDir(const string& dirname);
|
||||
|
|
@ -56,7 +60,8 @@ public:
|
|||
|
||||
// METHODS (time & performance)
|
||||
static void u_sleep(int64_t usec); ///< Sleep for a given number of microseconds.
|
||||
static uint64_t timeUsecs(); ///< Return wall time since epoch in microseconds, or 0 if not implemented
|
||||
/// Return wall time since epoch in microseconds, or 0 if not implemented
|
||||
static uint64_t timeUsecs();
|
||||
static uint64_t memUsageBytes(); ///< Return memory usage in bytes, or 0 if not implemented
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -39,18 +39,15 @@
|
|||
class V3Lexer : public V3LexerBase {
|
||||
public:
|
||||
// CONSTRUCTORS
|
||||
V3Lexer() : V3LexerBase(NULL) {}
|
||||
V3Lexer()
|
||||
: V3LexerBase(NULL) {}
|
||||
~V3Lexer() {}
|
||||
// METHODS
|
||||
void statePop() {
|
||||
yy_pop_state();
|
||||
}
|
||||
void statePop() { yy_pop_state(); }
|
||||
void unputString(const char* textp, size_t length) {
|
||||
// Add characters to input stream in back-to-front order
|
||||
const char* cp = textp;
|
||||
for (cp += length - 1; length--; cp--) {
|
||||
unput(*cp);
|
||||
}
|
||||
for (cp += length - 1; length--; cp--) unput(*cp);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -74,7 +71,7 @@ int V3ParseImp::yylexReadTok() {
|
|||
void V3ParseImp::lexNew() {
|
||||
if (m_lexerp) delete m_lexerp; // Restart from clean slate.
|
||||
m_lexerp = new V3Lexer();
|
||||
if (debugFlex()>=9) { m_lexerp->set_debug(~0); }
|
||||
if (debugFlex() >= 9) { m_lexerp->set_debug(~0); }
|
||||
}
|
||||
|
||||
void V3ParseImp::lexDestroy() {
|
||||
|
|
|
|||
|
|
@ -36,11 +36,11 @@ class V3ParseSym {
|
|||
|
||||
private:
|
||||
// MEMBERS
|
||||
static int s_anonNum; // Number of next anonymous object (parser use only)
|
||||
VSymGraph m_syms; // Graph of symbol tree
|
||||
VSymEnt* m_symTableNextId; // Symbol table for next lexer lookup (parser use only)
|
||||
VSymEnt* m_symCurrentp; // Active symbol table for additions/lookups
|
||||
SymStack m_sympStack; // Stack of upper nodes with pending symbol tables
|
||||
static int s_anonNum; // Number of next anonymous object (parser use only)
|
||||
VSymGraph m_syms; // Graph of symbol tree
|
||||
VSymEnt* m_symTableNextId; // Symbol table for next lexer lookup (parser use only)
|
||||
VSymEnt* m_symCurrentp; // Active symbol table for additions/lookups
|
||||
SymStack m_sympStack; // Stack of upper nodes with pending symbol tables
|
||||
|
||||
public:
|
||||
// CONSTRUCTORS
|
||||
|
|
@ -74,15 +74,14 @@ public:
|
|||
}
|
||||
void nextId(AstNode* entp) {
|
||||
if (entp) {
|
||||
UINFO(9,"symTableNextId under "<<entp<<"-"<<entp->type().ascii()<<endl);
|
||||
UINFO(9, "symTableNextId under " << entp << "-" << entp->type().ascii() << endl);
|
||||
m_symTableNextId = getTable(entp);
|
||||
}
|
||||
else {
|
||||
UINFO(9,"symTableNextId under NULL"<<endl);
|
||||
} else {
|
||||
UINFO(9, "symTableNextId under NULL" << endl);
|
||||
m_symTableNextId = NULL;
|
||||
}
|
||||
}
|
||||
void reinsert(AstNode* nodep, VSymEnt* parentp=NULL) {
|
||||
void reinsert(AstNode* nodep, VSymEnt* parentp = NULL) {
|
||||
reinsert(nodep, parentp, nodep->name());
|
||||
}
|
||||
void reinsert(AstNode* nodep, VSymEnt* parentp, string name) {
|
||||
|
|
@ -95,7 +94,8 @@ public:
|
|||
void pushNew(AstNode* nodep) { pushNewUnder(nodep, NULL); }
|
||||
void pushNewUnder(AstNode* nodep, VSymEnt* parentp) {
|
||||
if (!parentp) parentp = symCurrentp();
|
||||
VSymEnt* symp = findNewTable(nodep); // Will set user4p, which is how we connect table to node
|
||||
VSymEnt* symp
|
||||
= findNewTable(nodep); // Will set user4p, which is how we connect table to node
|
||||
symp->fallbackp(parentp);
|
||||
reinsert(nodep, parentp);
|
||||
pushScope(symp);
|
||||
|
|
@ -106,9 +106,13 @@ public:
|
|||
}
|
||||
void popScope(AstNode* nodep) {
|
||||
if (symCurrentp()->nodep() != nodep) {
|
||||
if (debug()) { showUpward(); dump(cout, "-mism: "); }
|
||||
nodep->v3fatalSrc("Symbols suggest ending "<<symCurrentp()->nodep()->prettyTypeName()
|
||||
<<" but parser thinks ending "<<nodep->prettyTypeName());
|
||||
if (debug()) {
|
||||
showUpward();
|
||||
dump(cout, "-mism: ");
|
||||
}
|
||||
nodep->v3fatalSrc("Symbols suggest ending " << symCurrentp()->nodep()->prettyTypeName()
|
||||
<< " but parser thinks ending "
|
||||
<< nodep->prettyTypeName());
|
||||
return;
|
||||
}
|
||||
m_sympStack.pop_back();
|
||||
|
|
@ -116,21 +120,23 @@ public:
|
|||
m_symCurrentp = m_sympStack.back();
|
||||
}
|
||||
void showUpward() {
|
||||
UINFO(1,"ParseSym Stack:\n");
|
||||
for (SymStack::reverse_iterator it=m_sympStack.rbegin(); it!=m_sympStack.rend(); ++it) {
|
||||
UINFO(1, "ParseSym Stack:\n");
|
||||
for (SymStack::reverse_iterator it = m_sympStack.rbegin(); it != m_sympStack.rend();
|
||||
++it) {
|
||||
VSymEnt* symp = *it;
|
||||
UINFO(1," "<<symp->nodep()<<endl);
|
||||
UINFO(1, " " << symp->nodep() << endl);
|
||||
}
|
||||
UINFO(1,"ParseSym Current: "<<symCurrentp()->nodep()<<endl);
|
||||
}
|
||||
void dump(std::ostream& os, const string& indent="") {
|
||||
m_syms.dump(os, indent);
|
||||
UINFO(1, "ParseSym Current: " << symCurrentp()->nodep() << endl);
|
||||
}
|
||||
void dump(std::ostream& os, const string& indent = "") { m_syms.dump(os, indent); }
|
||||
AstNode* findEntUpward(const string& name) {
|
||||
// Lookup the given string as an identifier, return type of the id, scanning upward
|
||||
VSymEnt* foundp = symCurrentp()->findIdFallback(name);
|
||||
if (foundp) return foundp->nodep();
|
||||
else return NULL;
|
||||
if (foundp) {
|
||||
return foundp->nodep();
|
||||
} else {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
void importItem(AstNode* packagep, const string& id_or_star) {
|
||||
// Import from package::id_or_star to this
|
||||
|
|
|
|||
|
|
@ -61,6 +61,7 @@ public:
|
|||
// Operate on the final ExecMTask graph, immediately prior to code
|
||||
// generation time.
|
||||
static void finalize();
|
||||
|
||||
private:
|
||||
static void finalizeCosts(V3Graph* execMTaskGraphp);
|
||||
static void setupMTaskDeps(V3Graph* mtasksp, const Vx2MTaskMap* vx2mtaskp);
|
||||
|
|
@ -75,13 +76,15 @@ private:
|
|||
class PartPtrIdMap {
|
||||
private:
|
||||
// TYPES
|
||||
typedef vl_unordered_map <const void*, vluint64_t> PtrMap;
|
||||
typedef vl_unordered_map<const void*, vluint64_t> PtrMap;
|
||||
// MEMBERS
|
||||
mutable vluint64_t m_nextId;
|
||||
mutable PtrMap m_id;
|
||||
|
||||
public:
|
||||
// CONSTRUCTORS
|
||||
PartPtrIdMap() : m_nextId(0) {}
|
||||
PartPtrIdMap()
|
||||
: m_nextId(0) {}
|
||||
// METHODS
|
||||
vluint64_t findId(const void* ptrp) const {
|
||||
PtrMap::const_iterator it = m_id.find(ptrp);
|
||||
|
|
|
|||
|
|
@ -30,7 +30,8 @@
|
|||
|
||||
class AbstractMTask : public V3GraphVertex {
|
||||
public:
|
||||
AbstractMTask(V3Graph* graphp) : V3GraphVertex(graphp) {}
|
||||
AbstractMTask(V3Graph* graphp)
|
||||
: V3GraphVertex(graphp) {}
|
||||
virtual ~AbstractMTask() {}
|
||||
virtual uint32_t id() const = 0;
|
||||
virtual uint32_t cost() const = 0;
|
||||
|
|
@ -41,7 +42,8 @@ public:
|
|||
// TYPES
|
||||
typedef std::list<MTaskMoveVertex*> VxList;
|
||||
// CONSTRUCTORS
|
||||
AbstractLogicMTask(V3Graph* graphp) : AbstractMTask(graphp) {}
|
||||
AbstractLogicMTask(V3Graph* graphp)
|
||||
: AbstractMTask(graphp) {}
|
||||
virtual ~AbstractLogicMTask() {}
|
||||
// METHODS
|
||||
// Set of logic vertices in this mtask. Order is not significant.
|
||||
|
|
@ -52,28 +54,29 @@ public:
|
|||
|
||||
class ExecMTask : public AbstractMTask {
|
||||
private:
|
||||
AstMTaskBody* m_bodyp; // Task body
|
||||
uint32_t m_id; // Unique id of this mtask.
|
||||
uint32_t m_priority; // Predicted critical path from the start of
|
||||
AstMTaskBody* m_bodyp; // Task body
|
||||
uint32_t m_id; // Unique id of this mtask.
|
||||
uint32_t m_priority; // Predicted critical path from the start of
|
||||
// this mtask to the ends of the graph that are reachable from this
|
||||
// mtask. In abstract time units.
|
||||
uint32_t m_cost; // Predicted runtime of this mtask, in the same
|
||||
uint32_t m_cost; // Predicted runtime of this mtask, in the same
|
||||
// abstract time units as priority().
|
||||
uint32_t m_thread; // Thread for static (pack_mtasks) scheduling,
|
||||
uint32_t m_thread; // Thread for static (pack_mtasks) scheduling,
|
||||
// or 0xffffffff if not yet assigned.
|
||||
const ExecMTask* m_packNextp; // Next for static (pack_mtasks) scheduling
|
||||
bool m_threadRoot; // Is root thread
|
||||
const ExecMTask* m_packNextp; // Next for static (pack_mtasks) scheduling
|
||||
bool m_threadRoot; // Is root thread
|
||||
VL_UNCOPYABLE(ExecMTask);
|
||||
|
||||
public:
|
||||
ExecMTask(V3Graph* graphp, AstMTaskBody* bodyp, uint32_t id)
|
||||
: AbstractMTask(graphp),
|
||||
m_bodyp(bodyp),
|
||||
m_id(id),
|
||||
m_priority(0),
|
||||
m_cost(0),
|
||||
m_thread(0xffffffff),
|
||||
m_packNextp(NULL),
|
||||
m_threadRoot(false) {}
|
||||
: AbstractMTask(graphp)
|
||||
, m_bodyp(bodyp)
|
||||
, m_id(id)
|
||||
, m_priority(0)
|
||||
, m_cost(0)
|
||||
, m_thread(0xffffffff)
|
||||
, m_packNextp(NULL)
|
||||
, m_threadRoot(false) {}
|
||||
AstMTaskBody* bodyp() const { return m_bodyp; }
|
||||
virtual uint32_t id() const { return m_id; }
|
||||
uint32_t priority() const { return m_priority; }
|
||||
|
|
@ -88,18 +91,20 @@ public:
|
|||
void threadRoot(bool threadRoot) { m_threadRoot = threadRoot; }
|
||||
string cFuncName() const {
|
||||
// If this MTask maps to a C function, this should be the name
|
||||
return string("__Vmtask")+"__"+cvtToStr(m_id);
|
||||
return string("__Vmtask") + "__" + cvtToStr(m_id);
|
||||
}
|
||||
string name() const { return string("mt")+cvtToStr(id()); }
|
||||
string name() const { return string("mt") + cvtToStr(id()); }
|
||||
void dump(std::ostream& str) const {
|
||||
str <<name()<<"."<<cvtToHex(this);
|
||||
if (priority() || cost()) str <<" [pr="<<priority()<<" c="<<cvtToStr(cost())<<"]";
|
||||
if (thread() != 0xffffffff) str <<" th="<<thread();
|
||||
if (threadRoot()) str <<" [ROOT]";
|
||||
if (packNextp()) str <<" nx="<<packNextp()->name();
|
||||
str << name() << "." << cvtToHex(this);
|
||||
if (priority() || cost()) str << " [pr=" << priority() << " c=" << cvtToStr(cost()) << "]";
|
||||
if (thread() != 0xffffffff) str << " th=" << thread();
|
||||
if (threadRoot()) str << " [ROOT]";
|
||||
if (packNextp()) str << " nx=" << packNextp()->name();
|
||||
}
|
||||
};
|
||||
inline std::ostream& operator<<(std::ostream& os, const ExecMTask& rhs) {
|
||||
rhs.dump(os); return os; }
|
||||
rhs.dump(os);
|
||||
return os;
|
||||
}
|
||||
|
||||
#endif // Guard
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@ class V3PreProcImp;
|
|||
|
||||
// Token codes
|
||||
// If changing, see V3PreProc.cpp's V3PreProcImp::tokenName()
|
||||
// clang-format off
|
||||
#define VP_EOF 0 // Must be zero, a.k.a. YY_NULL, a.k.a. yy_terminate();
|
||||
#define VP_EOF_ERROR 400
|
||||
|
||||
|
|
@ -65,10 +66,13 @@ class V3PreProcImp;
|
|||
#define VP_JOIN 314
|
||||
|
||||
#define VP_PSL 350
|
||||
// clang-format on
|
||||
|
||||
//======================================================================
|
||||
// Externs created by flex
|
||||
// We add a prefix so that other lexers/flexers in the same program won't collide.
|
||||
|
||||
// clang-format off
|
||||
#ifndef yy_create_buffer
|
||||
# define yy_create_buffer V3PreLex_create_buffer
|
||||
# define yy_delete_buffer V3PreLex_delete_buffer
|
||||
|
|
@ -97,9 +101,10 @@ class V3PreProcImp;
|
|||
|
||||
#ifndef YY_BUFFER_STATE
|
||||
struct yy_buffer_state;
|
||||
typedef struct yy_buffer_state *YY_BUFFER_STATE;
|
||||
typedef struct yy_buffer_state* YY_BUFFER_STATE;
|
||||
# define YY_BUF_SIZE 16384
|
||||
#endif
|
||||
// clang-format on
|
||||
|
||||
extern int yylex();
|
||||
extern void yyrestart(FILE*);
|
||||
|
|
@ -109,7 +114,7 @@ extern char* yyourtext();
|
|||
extern size_t yyourleng();
|
||||
extern void yyourtext(const char* textp, size_t size); // Must call with static
|
||||
|
||||
YY_BUFFER_STATE yy_create_buffer(FILE *file, int size);
|
||||
YY_BUFFER_STATE yy_create_buffer(FILE* file, int size);
|
||||
void yy_switch_to_buffer(YY_BUFFER_STATE new_buffer);
|
||||
void yy_delete_buffer(YY_BUFFER_STATE b);
|
||||
|
||||
|
|
@ -123,22 +128,24 @@ void yy_delete_buffer(YY_BUFFER_STATE b);
|
|||
|
||||
class VPreStream {
|
||||
public:
|
||||
FileLine* m_curFilelinep; // Current processing point (see also m_tokFilelinep)
|
||||
V3PreLex* m_lexp; // Lexer, for resource tracking
|
||||
std::deque<string> m_buffers; // Buffer of characters to process
|
||||
int m_ignNewlines; // Ignore multiline newlines
|
||||
bool m_eof; // "EOF" buffer
|
||||
bool m_file; // Buffer is start of new file
|
||||
int m_termState; // Termination fsm
|
||||
FileLine* m_curFilelinep; // Current processing point (see also m_tokFilelinep)
|
||||
V3PreLex* m_lexp; // Lexer, for resource tracking
|
||||
std::deque<string> m_buffers; // Buffer of characters to process
|
||||
int m_ignNewlines; // Ignore multiline newlines
|
||||
bool m_eof; // "EOF" buffer
|
||||
bool m_file; // Buffer is start of new file
|
||||
int m_termState; // Termination fsm
|
||||
VPreStream(FileLine* fl, V3PreLex* lexp)
|
||||
: m_curFilelinep(fl), m_lexp(lexp),
|
||||
m_ignNewlines(0),
|
||||
m_eof(false), m_file(false), m_termState(0) {
|
||||
: m_curFilelinep(fl)
|
||||
, m_lexp(lexp)
|
||||
, m_ignNewlines(0)
|
||||
, m_eof(false)
|
||||
, m_file(false)
|
||||
, m_termState(0) {
|
||||
lexStreamDepthAdd(1);
|
||||
}
|
||||
~VPreStream() {
|
||||
lexStreamDepthAdd(-1);
|
||||
}
|
||||
~VPreStream() { lexStreamDepthAdd(-1); }
|
||||
|
||||
private:
|
||||
void lexStreamDepthAdd(int delta);
|
||||
};
|
||||
|
|
@ -147,26 +154,26 @@ private:
|
|||
// Class entry for each per-lexer state
|
||||
|
||||
class V3PreLex {
|
||||
public: // Used only by V3PreLex.cpp and V3PreProc.cpp
|
||||
V3PreProcImp* m_preimpp; // Preprocessor lexor belongs to
|
||||
public: // Used only by V3PreLex.cpp and V3PreProc.cpp
|
||||
V3PreProcImp* m_preimpp; // Preprocessor lexor belongs to
|
||||
std::stack<VPreStream*> m_streampStack; // Stack of processing files
|
||||
int m_streamDepth; // Depth of stream processing
|
||||
YY_BUFFER_STATE m_bufferState; // Flex state
|
||||
FileLine* m_tokFilelinep; // Starting position of current token
|
||||
int m_streamDepth; // Depth of stream processing
|
||||
YY_BUFFER_STATE m_bufferState; // Flex state
|
||||
FileLine* m_tokFilelinep; // Starting position of current token
|
||||
|
||||
// State to lexer
|
||||
static V3PreLex* s_currentLexp; ///< Current lexing point
|
||||
int m_keepComments; ///< Emit comments in output text
|
||||
int m_keepWhitespace; ///< Emit all whitespace in output text
|
||||
bool m_pedantic; ///< Obey standard; don't Substitute `error
|
||||
static V3PreLex* s_currentLexp; ///< Current lexing point
|
||||
int m_keepComments; ///< Emit comments in output text
|
||||
int m_keepWhitespace; ///< Emit all whitespace in output text
|
||||
bool m_pedantic; ///< Obey standard; don't Substitute `error
|
||||
|
||||
// State from lexer
|
||||
int m_formalLevel; // Parenthesis counting inside def formals
|
||||
int m_parenLevel; // Parenthesis counting inside def args
|
||||
bool m_defCmtSlash; // /*...*/ comment in define had \ ending
|
||||
bool m_defQuote; // Definition value inside quote
|
||||
string m_defValue; // Definition value being built.
|
||||
int m_enterExit; // For VL_LINE, the enter/exit level
|
||||
int m_formalLevel; // Parenthesis counting inside def formals
|
||||
int m_parenLevel; // Parenthesis counting inside def args
|
||||
bool m_defCmtSlash; // /*...*/ comment in define had \ ending
|
||||
bool m_defQuote; // Definition value inside quote
|
||||
string m_defValue; // Definition value being built.
|
||||
int m_enterExit; // For VL_LINE, the enter/exit level
|
||||
|
||||
// CONSTRUCTORS
|
||||
V3PreLex(V3PreProcImp* preimpp, FileLine* filelinep) {
|
||||
|
|
@ -184,7 +191,10 @@ class V3PreLex {
|
|||
initFirstBuffer(filelinep);
|
||||
}
|
||||
~V3PreLex() {
|
||||
while (!m_streampStack.empty()) { delete m_streampStack.top(); m_streampStack.pop(); }
|
||||
while (!m_streampStack.empty()) {
|
||||
delete m_streampStack.top();
|
||||
m_streampStack.pop();
|
||||
}
|
||||
VL_DO_CLEAR(yy_delete_buffer(m_bufferState), m_bufferState = NULL);
|
||||
}
|
||||
|
||||
|
|
@ -213,8 +223,8 @@ class V3PreLex {
|
|||
size_t inputToLex(char* buf, size_t max_size);
|
||||
/// Called by V3PreProc.cpp to get data from lexer
|
||||
YY_BUFFER_STATE currentBuffer();
|
||||
int lex();
|
||||
int currentStartState() const;
|
||||
int lex();
|
||||
int currentStartState() const;
|
||||
void dumpSummary();
|
||||
void dumpStack();
|
||||
void unused();
|
||||
|
|
|
|||
|
|
@ -44,13 +44,13 @@ protected:
|
|||
public:
|
||||
// CONSTANTS
|
||||
enum MiscConsts {
|
||||
DEFINE_RECURSION_LEVEL_MAX = 1000, // How many `def substitutions before an error
|
||||
LINE_TOKEN_MAX = 20000, // How many tokens on a line before an error
|
||||
INCLUDE_DEPTH_MAX = 500, // How many `includes deep before an error
|
||||
STREAM_DEPTH_LEVEL_MAX = 2000, // How many streams deep (sometimes `def deep) before an error
|
||||
// // Set more than DEFINE_RECURSION_LEVEL_MAX
|
||||
// // or INCLUDE_DEPTH_MAX
|
||||
NEWLINES_VS_TICKLINE = 20 // Use `line in place of this many newlines
|
||||
DEFINE_RECURSION_LEVEL_MAX = 1000, // How many `def substitutions before an error
|
||||
LINE_TOKEN_MAX = 20000, // How many tokens on a line before an error
|
||||
INCLUDE_DEPTH_MAX = 500, // How many `includes deep before an error
|
||||
// Streams deep (sometimes `def deep) before an error.
|
||||
// Set more than DEFINE_RECURSION_LEVEL_MAX or INCLUDE_DEPTH_MAX.
|
||||
STREAM_DEPTH_LEVEL_MAX = 2000,
|
||||
NEWLINES_VS_TICKLINE = 20 // Use `line in place of this many newlines
|
||||
};
|
||||
|
||||
// ACCESSORS
|
||||
|
|
@ -80,9 +80,10 @@ public:
|
|||
virtual void include(const string& filename) = 0; // Request a include file be processed
|
||||
|
||||
virtual void undef(const string& name) = 0; // Remove a definition
|
||||
virtual void define(FileLine* fileline, const string& name,
|
||||
const string& value, const string& params="",
|
||||
bool cmdline=false) = 0; // `define without any parameters
|
||||
virtual void define(FileLine* fileline, const string& name, const string& value,
|
||||
const string& params = "",
|
||||
bool cmdline = false)
|
||||
= 0; // `define without any parameters
|
||||
virtual void defineCmdLine(FileLine* fileline, const string& name,
|
||||
const string& value) { // `define without any parameters
|
||||
define(fileline, name, value, "", true);
|
||||
|
|
@ -97,10 +98,9 @@ public:
|
|||
|
||||
protected:
|
||||
// CONSTRUCTORS
|
||||
V3PreProc() {
|
||||
m_debug = 0;
|
||||
}
|
||||
V3PreProc() { m_debug = 0; }
|
||||
void configure(FileLine* fl);
|
||||
|
||||
public:
|
||||
static V3PreProc* createPreProc(FileLine* fl);
|
||||
virtual ~V3PreProc() {}
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@ protected:
|
|||
//---------------------------------------
|
||||
// METHODS
|
||||
|
||||
static int debug(bool reset=false) {
|
||||
static int debug(bool reset = false) {
|
||||
static int level = -1;
|
||||
if (VL_UNLIKELY(level < 0) || reset) {
|
||||
level = v3Global.opt.debugSrcLevel(__FILE__);
|
||||
|
|
@ -64,8 +64,10 @@ protected:
|
|||
s_preprocp->defineCmdLine(prefl, "VERILATOR", "1"); // LEAK_OK
|
||||
s_preprocp->defineCmdLine(prefl, "verilator", "1"); // LEAK_OK
|
||||
s_preprocp->defineCmdLine(prefl, "verilator3", "1"); // LEAK_OK
|
||||
s_preprocp->defineCmdLine(prefl, "systemc_clock", "/*verilator systemc_clock*/"); // LEAK_OK
|
||||
s_preprocp->defineCmdLine(prefl, "coverage_block_off", "/*verilator coverage_block_off*/"); // LEAK_OK
|
||||
s_preprocp->defineCmdLine(prefl, "systemc_clock",
|
||||
"/*verilator systemc_clock*/"); // LEAK_OK
|
||||
s_preprocp->defineCmdLine(prefl, "coverage_block_off",
|
||||
"/*verilator coverage_block_off*/"); // LEAK_OK
|
||||
if (prefl->language().systemVerilog()) {
|
||||
// Synthesis compatibility
|
||||
s_preprocp->defineCmdLine(prefl, "SYSTEMVERILOG", "1"); // LEAK_OK
|
||||
|
|
@ -94,7 +96,7 @@ protected:
|
|||
debug(true); // Recheck if debug on - first check was before command line passed
|
||||
|
||||
// Preprocess the given module, putting output in vppFilename
|
||||
UINFONL(1," Preprocessing "<<modname<<endl);
|
||||
UINFONL(1, " Preprocessing " << modname << endl);
|
||||
|
||||
// Preprocess
|
||||
s_filterp = filterp;
|
||||
|
|
@ -109,8 +111,8 @@ protected:
|
|||
// intervening +<lang>ext+ options since it was first encountered.
|
||||
FileLine* modfileline = new FileLine(modfilename);
|
||||
modfileline->language(v3Global.opt.fileLanguage(modfilename));
|
||||
V3Parse::ppPushText(parsep, (string("`begin_keywords \"")
|
||||
+modfileline->language().ascii()+"\"\n"));
|
||||
V3Parse::ppPushText(
|
||||
parsep, (string("`begin_keywords \"") + modfileline->language().ascii() + "\"\n"));
|
||||
}
|
||||
|
||||
while (!s_preprocp->isEof()) {
|
||||
|
|
@ -121,31 +123,32 @@ protected:
|
|||
}
|
||||
|
||||
void preprocInclude(FileLine* fl, const string& modname) {
|
||||
if (modname[0]=='/' || modname[0]=='\\') {
|
||||
fl->v3warn(INCABSPATH, "Suggest `include with absolute path be made relative, and use +include: "
|
||||
<<modname);
|
||||
if (modname[0] == '/' || modname[0] == '\\') {
|
||||
fl->v3warn(INCABSPATH,
|
||||
"Suggest `include with absolute path be made relative, and use +include: "
|
||||
<< modname);
|
||||
}
|
||||
preprocOpen(fl, s_filterp, modname, V3Os::filenameDir(fl->filename()),
|
||||
"Cannot find include file: ");
|
||||
}
|
||||
|
||||
private:
|
||||
string preprocOpen(FileLine* fl, VInFilter* filterp,
|
||||
const string& modname, const string& lastpath,
|
||||
string preprocOpen(FileLine* fl, VInFilter* filterp, const string& modname,
|
||||
const string& lastpath,
|
||||
const string& errmsg) { // Error message or "" to suppress
|
||||
// Returns filename if successful
|
||||
// Try a pure name in case user has a bogus `filename they don't expect
|
||||
string filename = v3Global.opt.filePath(fl, modname, lastpath, errmsg);
|
||||
if (filename=="") {
|
||||
if (filename == "") {
|
||||
// Allow user to put `defined names on the command line instead of filenames,
|
||||
// then convert them properly.
|
||||
string ppmodname = s_preprocp->removeDefines(modname);
|
||||
|
||||
filename = v3Global.opt.filePath(fl, ppmodname, lastpath, errmsg);
|
||||
}
|
||||
if (filename=="") return ""; // Not found
|
||||
if (filename == "") return ""; // Not found
|
||||
|
||||
UINFO(2," Reading "<<filename<<endl);
|
||||
UINFO(2, " Reading " << filename << endl);
|
||||
s_preprocp->openFile(fl, filterp, filename);
|
||||
return filename;
|
||||
}
|
||||
|
|
@ -163,9 +166,7 @@ VInFilter* V3PreShellImp::s_filterp = NULL;
|
|||
//######################################################################
|
||||
// Perl class functions
|
||||
|
||||
void V3PreShell::boot(char** env) {
|
||||
V3PreShellImp::s_preImp.boot(env);
|
||||
}
|
||||
void V3PreShell::boot(char** env) { V3PreShellImp::s_preImp.boot(env); }
|
||||
bool V3PreShell::preproc(FileLine* fl, const string& modname, VInFilter* filterp,
|
||||
V3ParseImp* parsep, const string& errmsg) {
|
||||
return V3PreShellImp::s_preImp.preproc(fl, modname, filterp, parsep, errmsg);
|
||||
|
|
@ -177,12 +178,8 @@ void V3PreShell::defineCmdLine(const string& name, const string& value) {
|
|||
FileLine* prefl = new FileLine(FileLine::commandLineFilename());
|
||||
V3PreShellImp::s_preprocp->defineCmdLine(prefl, name, value);
|
||||
}
|
||||
void V3PreShell::undef(const string& name) {
|
||||
V3PreShellImp::s_preprocp->undef(name);
|
||||
}
|
||||
void V3PreShell::dumpDefines(std::ostream& os) {
|
||||
V3PreShellImp::s_preprocp->dumpDefines(os);
|
||||
}
|
||||
void V3PreShell::undef(const string& name) { V3PreShellImp::s_preprocp->undef(name); }
|
||||
void V3PreShell::dumpDefines(std::ostream& os) { V3PreShellImp::s_preprocp->dumpDefines(os); }
|
||||
void V3PreShell::candidateDefines(VSpellCheck* spellerp) {
|
||||
V3PreShellImp::s_preprocp->candidateDefines(spellerp);
|
||||
}
|
||||
|
|
|
|||
123
src/V3Reloop.cpp
123
src/V3Reloop.cpp
|
|
@ -47,27 +47,27 @@
|
|||
class ReloopVisitor : public AstNVisitor {
|
||||
private:
|
||||
// TYPES
|
||||
typedef std::vector<AstNodeAssign*> AssVec;
|
||||
typedef std::vector<AstNodeAssign*> AssVec;
|
||||
|
||||
// NODE STATE
|
||||
// AstCFunc::user1p -> Var* for temp var, 0=not set yet
|
||||
AstUser1InUse m_inuser1;
|
||||
AstUser1InUse m_inuser1;
|
||||
|
||||
// STATE
|
||||
VDouble0 m_statReloops; // Statistic tracking
|
||||
VDouble0 m_statReItems; // Statistic tracking
|
||||
AstCFunc* m_cfuncp; // Current block
|
||||
VDouble0 m_statReloops; // Statistic tracking
|
||||
VDouble0 m_statReItems; // Statistic tracking
|
||||
AstCFunc* m_cfuncp; // Current block
|
||||
|
||||
AssVec m_mgAssignps; // List of assignments merging
|
||||
AstCFunc* m_mgCfuncp; // Parent C function
|
||||
AstNode* m_mgNextp; // Next node
|
||||
AstNodeSel* m_mgSelLp; // Parent select, NULL = idle
|
||||
AstNodeSel* m_mgSelRp; // Parent select, NULL = constant
|
||||
AstNodeVarRef* m_mgVarrefLp; // Parent varref
|
||||
AstNodeVarRef* m_mgVarrefRp; // Parent varref, NULL = constant
|
||||
AstConst* m_mgConstRp; // Parent RHS constant, NULL = sel
|
||||
uint32_t m_mgIndexLo; // Merge range
|
||||
uint32_t m_mgIndexHi; // Merge range
|
||||
AssVec m_mgAssignps; // List of assignments merging
|
||||
AstCFunc* m_mgCfuncp; // Parent C function
|
||||
AstNode* m_mgNextp; // Next node
|
||||
AstNodeSel* m_mgSelLp; // Parent select, NULL = idle
|
||||
AstNodeSel* m_mgSelRp; // Parent select, NULL = constant
|
||||
AstNodeVarRef* m_mgVarrefLp; // Parent varref
|
||||
AstNodeVarRef* m_mgVarrefRp; // Parent varref, NULL = constant
|
||||
AstConst* m_mgConstRp; // Parent RHS constant, NULL = sel
|
||||
uint32_t m_mgIndexLo; // Merge range
|
||||
uint32_t m_mgIndexHi; // Merge range
|
||||
|
||||
// METHODS
|
||||
VL_DEBUG_FUNC; // Declare debug()
|
||||
|
|
@ -76,8 +76,7 @@ private:
|
|||
AstVar* varp = VN_CAST(cfuncp->user1p(), Var);
|
||||
if (!varp) {
|
||||
string newvarname = string("__Vilp");
|
||||
varp = new AstVar(fl, AstVarType::STMTTEMP,
|
||||
newvarname, VFlagLogicPacked(), 32);
|
||||
varp = new AstVar(fl, AstVarType::STMTTEMP, newvarname, VFlagLogicPacked(), 32);
|
||||
UASSERT_OBJ(cfuncp, fl, "Assignment not under a function");
|
||||
cfuncp->addInitsp(varp);
|
||||
cfuncp->user1p(varp);
|
||||
|
|
@ -87,11 +86,11 @@ private:
|
|||
void mergeEnd() {
|
||||
if (!m_mgAssignps.empty()) {
|
||||
uint32_t items = m_mgIndexHi - m_mgIndexLo + 1;
|
||||
UINFO(9, "End merge iter="<<items<<" "<<m_mgIndexHi<<":"<<m_mgIndexLo
|
||||
<<" "<<m_mgAssignps[0]<<endl);
|
||||
UINFO(9, "End merge iter=" << items << " " << m_mgIndexHi << ":" << m_mgIndexLo << " "
|
||||
<< m_mgAssignps[0] << endl);
|
||||
if (items >= RELOOP_MIN_ITERS) {
|
||||
UINFO(6, "Reloop merging items="<<items<<" "<<m_mgIndexHi<<":"<<m_mgIndexLo
|
||||
<<" "<<m_mgAssignps[0]<<endl);
|
||||
UINFO(6, "Reloop merging items=" << items << " " << m_mgIndexHi << ":"
|
||||
<< m_mgIndexLo << " " << m_mgAssignps[0] << endl);
|
||||
++m_statReloops;
|
||||
m_statReItems += items;
|
||||
|
||||
|
|
@ -103,11 +102,11 @@ private:
|
|||
|
||||
AstNode* initp = new AstAssign(fl, new AstVarRef(fl, itp, true),
|
||||
new AstConst(fl, m_mgIndexLo));
|
||||
AstNode* condp = new AstLte(fl, new AstVarRef(fl, itp, false),
|
||||
new AstConst(fl, m_mgIndexHi));
|
||||
AstNode* incp = new AstAssign(fl, new AstVarRef(fl, itp, true),
|
||||
new AstAdd(fl, new AstConst(fl, 1),
|
||||
new AstVarRef(fl, itp, false)));
|
||||
AstNode* condp
|
||||
= new AstLte(fl, new AstVarRef(fl, itp, false), new AstConst(fl, m_mgIndexHi));
|
||||
AstNode* incp = new AstAssign(
|
||||
fl, new AstVarRef(fl, itp, true),
|
||||
new AstAdd(fl, new AstConst(fl, 1), new AstVarRef(fl, itp, false)));
|
||||
AstWhile* whilep = new AstWhile(fl, condp, NULL, incp);
|
||||
initp->addNext(whilep);
|
||||
bodyp->replaceWith(initp);
|
||||
|
|
@ -122,11 +121,11 @@ private:
|
|||
rbitp->replaceWith(new AstVarRef(fl, itp, false));
|
||||
VL_DO_DANGLING(rbitp->deleteTree(), lbitp);
|
||||
}
|
||||
if (debug()>=9) initp->dumpTree(cout, "-new: ");
|
||||
if (debug()>=9) whilep->dumpTree(cout, "-new: ");
|
||||
if (debug() >= 9) initp->dumpTree(cout, "-new: ");
|
||||
if (debug() >= 9) whilep->dumpTree(cout, "-new: ");
|
||||
|
||||
// Remove remaining assigns
|
||||
for (AssVec::iterator it=m_mgAssignps.begin(); it!=m_mgAssignps.end(); ++it) {
|
||||
for (AssVec::iterator it = m_mgAssignps.begin(); it != m_mgAssignps.end(); ++it) {
|
||||
AstNodeAssign* assp = *it;
|
||||
if (assp != bodyp) {
|
||||
VL_DO_DANGLING(assp->unlinkFrBack()->deleteTree(), assp);
|
||||
|
|
@ -154,15 +153,27 @@ private:
|
|||
|
||||
// Left select WordSel or ArraySel
|
||||
AstNodeSel* lselp = VN_CAST(nodep->lhsp(), NodeSel);
|
||||
if (!lselp) { mergeEnd(); return; } // Not ever merged
|
||||
if (!lselp) { // Not ever merged
|
||||
mergeEnd();
|
||||
return;
|
||||
}
|
||||
// Of a constant index
|
||||
AstConst* lbitp = VN_CAST(lselp->bitp(), Const);
|
||||
if (!lbitp) { mergeEnd(); return; }
|
||||
if (lbitp->width() > 32) { mergeEnd(); return; } // Assoc arrays can do this
|
||||
if (!lbitp) {
|
||||
mergeEnd();
|
||||
return;
|
||||
}
|
||||
if (lbitp->width() > 32) { // Assoc arrays can do this
|
||||
mergeEnd();
|
||||
return;
|
||||
}
|
||||
uint32_t index = lbitp->toUInt();
|
||||
// Of variable
|
||||
AstNodeVarRef* lvarrefp = VN_CAST(lselp->fromp(), NodeVarRef);
|
||||
if (!lvarrefp) { mergeEnd(); return; }
|
||||
if (!lvarrefp) {
|
||||
mergeEnd();
|
||||
return;
|
||||
}
|
||||
|
||||
// RHS is a constant or a select
|
||||
AstConst* rconstp = VN_CAST(nodep->rhsp(), Const);
|
||||
|
|
@ -170,38 +181,38 @@ private:
|
|||
AstNodeVarRef* rvarrefp = NULL;
|
||||
if (rconstp) { // Ok
|
||||
} else {
|
||||
if (!rselp) { mergeEnd(); return; }
|
||||
if (!rselp) {
|
||||
mergeEnd();
|
||||
return;
|
||||
}
|
||||
AstConst* rbitp = VN_CAST(rselp->bitp(), Const);
|
||||
rvarrefp = VN_CAST(rselp->fromp(), NodeVarRef);
|
||||
if (!rbitp || rbitp->toUInt() != index
|
||||
|| !rvarrefp
|
||||
if (!rbitp || rbitp->toUInt() != index || !rvarrefp
|
||||
|| lvarrefp->varp() == rvarrefp->varp()) {
|
||||
mergeEnd(); return;
|
||||
mergeEnd();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (m_mgSelLp) { // Old merge
|
||||
if (m_mgCfuncp == m_cfuncp
|
||||
&& m_mgNextp == nodep
|
||||
&& m_mgSelLp->same(lselp)
|
||||
if (m_mgCfuncp == m_cfuncp && m_mgNextp == nodep && m_mgSelLp->same(lselp)
|
||||
&& m_mgVarrefLp->same(lvarrefp)
|
||||
&& (m_mgConstRp
|
||||
? (rconstp && m_mgConstRp->same(rconstp))
|
||||
: (rselp
|
||||
&& m_mgSelRp->same(rselp)
|
||||
&& m_mgVarrefRp->same(rvarrefp)))
|
||||
&& (index == m_mgIndexLo-1
|
||||
|| index == m_mgIndexHi+1)) {
|
||||
? (rconstp && m_mgConstRp->same(rconstp))
|
||||
: (rselp && m_mgSelRp->same(rselp) && m_mgVarrefRp->same(rvarrefp)))
|
||||
&& (index == m_mgIndexLo - 1 || index == m_mgIndexHi + 1)) {
|
||||
// Sequentially next to last assign; continue merge
|
||||
if (index == m_mgIndexLo-1) m_mgIndexLo = index;
|
||||
else if (index == m_mgIndexHi+1) m_mgIndexHi = index;
|
||||
UINFO(9, "Continue merge i="<<index
|
||||
<<" "<<m_mgIndexHi<<":"<<m_mgIndexLo<<" "<<nodep<<endl);
|
||||
if (index == m_mgIndexLo - 1) {
|
||||
m_mgIndexLo = index;
|
||||
} else if (index == m_mgIndexHi + 1) {
|
||||
m_mgIndexHi = index;
|
||||
}
|
||||
UINFO(9, "Continue merge i=" << index << " " << m_mgIndexHi << ":" << m_mgIndexLo
|
||||
<< " " << nodep << endl);
|
||||
m_mgAssignps.push_back(nodep);
|
||||
m_mgNextp = nodep->nextp();
|
||||
return;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
// This assign doesn't merge with previous assign,
|
||||
// but should start a new merge
|
||||
mergeEnd();
|
||||
|
|
@ -219,7 +230,7 @@ private:
|
|||
m_mgConstRp = rconstp;
|
||||
m_mgIndexLo = index;
|
||||
m_mgIndexHi = index;
|
||||
UINFO(9, "Start merge i="<<index<<" "<<nodep<<endl);
|
||||
UINFO(9, "Start merge i=" << index << " " << nodep << endl);
|
||||
}
|
||||
//--------------------
|
||||
virtual void visit(AstVar*) VL_OVERRIDE {} // Accelerate
|
||||
|
|
@ -251,9 +262,7 @@ public:
|
|||
// Reloop class functions
|
||||
|
||||
void V3Reloop::reloopAll(AstNetlist* nodep) {
|
||||
UINFO(2,__FUNCTION__<<": "<<endl);
|
||||
{
|
||||
ReloopVisitor visitor(nodep);
|
||||
} // Destruct before checking
|
||||
UINFO(2, __FUNCTION__ << ": " << endl);
|
||||
{ ReloopVisitor visitor(nodep); } // Destruct before checking
|
||||
V3Global::dumpCheckGlobalTree("reloop", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 6);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,7 +25,8 @@ public:
|
|||
uint32_t m_score;
|
||||
uint32_t m_id;
|
||||
// CONSTRUCTORS
|
||||
explicit ScoreboardTestElem(uint32_t score) : m_score(score) {
|
||||
explicit ScoreboardTestElem(uint32_t score)
|
||||
: m_score(score) {
|
||||
static uint32_t s_serial = 0;
|
||||
m_id = ++s_serial;
|
||||
}
|
||||
|
|
@ -33,9 +34,7 @@ public:
|
|||
// METHODS
|
||||
static uint32_t scoreFn(const ScoreboardTestElem* elp) { return elp->m_score; }
|
||||
|
||||
bool operator< (const ScoreboardTestElem& other) const {
|
||||
return m_id < other.m_id;
|
||||
}
|
||||
bool operator<(const ScoreboardTestElem& other) const { return m_id < other.m_id; }
|
||||
};
|
||||
|
||||
void V3ScoreboardBase::selfTest() {
|
||||
|
|
@ -52,8 +51,7 @@ void V3ScoreboardBase::selfTest() {
|
|||
sb.addElem(&e3);
|
||||
|
||||
UASSERT(sb.needsRescore(), "SelfTest: Newly filled sb should need a rescore.");
|
||||
UASSERT(sb.needsRescore(&e1),
|
||||
"SelfTest: Individual newly-added element should need rescore");
|
||||
UASSERT(sb.needsRescore(&e1), "SelfTest: Individual newly-added element should need rescore");
|
||||
UASSERT(NULL == sb.bestp(),
|
||||
"SelfTest: Newly filled sb should have nothing eligible for Bestp()");
|
||||
|
||||
|
|
@ -64,14 +62,12 @@ void V3ScoreboardBase::selfTest() {
|
|||
"SelfTest: Newly rescored sb should not need an element rescored");
|
||||
UASSERT(e2.m_score == sb.cachedScore(&e2),
|
||||
"SelfTest: Cached score should match current score");
|
||||
UASSERT(&e1 == sb.bestp(),
|
||||
"SelfTest: Should return element with lowest (best) score");
|
||||
UASSERT(&e1 == sb.bestp(), "SelfTest: Should return element with lowest (best) score");
|
||||
|
||||
// Change one element's score
|
||||
sb.hintScoreChanged(&e2);
|
||||
e2.m_score = 21;
|
||||
UASSERT(sb.needsRescore(&e2),
|
||||
"SelfTest: Should need rescore on elem after hintScoreChanged");
|
||||
UASSERT(sb.needsRescore(&e2), "SelfTest: Should need rescore on elem after hintScoreChanged");
|
||||
|
||||
// Remove an element
|
||||
UASSERT(sb.contains(&e1), "SelfTest: e1 should be there");
|
||||
|
|
|
|||
|
|
@ -64,6 +64,7 @@ public:
|
|||
typedef void pointer;
|
||||
typedef std::ptrdiff_t difference_type;
|
||||
typedef std::bidirectional_iterator_tag iterator_category;
|
||||
|
||||
protected:
|
||||
friend class SortByValueMap;
|
||||
|
||||
|
|
@ -77,8 +78,7 @@ public:
|
|||
explicit const_iterator(SortByValueMap* sbmvp) // for end()
|
||||
: m_sbvmp(sbmvp)
|
||||
, m_end(true) {}
|
||||
const_iterator(typename Val2Keys::iterator valIt,
|
||||
typename KeySet::iterator keyIt,
|
||||
const_iterator(typename Val2Keys::iterator valIt, typename KeySet::iterator keyIt,
|
||||
SortByValueMap* sbvmp)
|
||||
: m_keyIt(keyIt)
|
||||
, m_valIt(valIt)
|
||||
|
|
@ -135,6 +135,7 @@ public:
|
|||
--m_keyIt;
|
||||
UASSERT(m_keyIt != m_valIt->second.end(), "Value bucket should have key");
|
||||
}
|
||||
|
||||
public:
|
||||
const T_Key& key() const { return *m_keyIt; }
|
||||
const T_Value& value() const { return m_valIt->first; }
|
||||
|
|
@ -151,15 +152,10 @@ public:
|
|||
// sequences. So check m_end before comparing m_valIt, and
|
||||
// compare m_valIt's before comparing m_keyIt to ensure nothing
|
||||
// here is undefined.
|
||||
if (m_end || other.m_end) {
|
||||
return m_end && other.m_end;
|
||||
}
|
||||
return ((m_valIt == other.m_valIt)
|
||||
&& (m_keyIt == other.m_keyIt));
|
||||
}
|
||||
bool operator!=(const const_iterator& other) const {
|
||||
return (!this->operator==(other));
|
||||
if (m_end || other.m_end) return m_end && other.m_end;
|
||||
return ((m_valIt == other.m_valIt) && (m_keyIt == other.m_keyIt));
|
||||
}
|
||||
bool operator!=(const const_iterator& other) const { return (!this->operator==(other)); }
|
||||
|
||||
// WARNING: Cleverness.
|
||||
//
|
||||
|
|
@ -209,8 +205,7 @@ public:
|
|||
// CONSTRUCTORS
|
||||
explicit iterator(SortByValueMap* sbvmp)
|
||||
: const_iterator(sbvmp) {}
|
||||
iterator(typename Val2Keys::iterator valIt,
|
||||
typename KeySet::iterator keyIt,
|
||||
iterator(typename Val2Keys::iterator valIt, typename KeySet::iterator keyIt,
|
||||
SortByValueMap* sbvmp)
|
||||
: const_iterator(valIt, keyIt, sbvmp) {}
|
||||
|
||||
|
|
@ -248,49 +243,33 @@ private:
|
|||
}
|
||||
void removeKeyFromOldVal(iterator it) {
|
||||
it.m_valIt->second.erase(it.m_keyIt);
|
||||
if (it.m_valIt->second.empty()) {
|
||||
m_vals.erase(it.m_valIt);
|
||||
}
|
||||
if (it.m_valIt->second.empty()) m_vals.erase(it.m_valIt);
|
||||
}
|
||||
|
||||
public:
|
||||
iterator begin() {
|
||||
typename Val2Keys::iterator valIt = m_vals.begin();
|
||||
if (valIt == m_vals.end()) {
|
||||
return end();
|
||||
}
|
||||
if (valIt == m_vals.end()) return end();
|
||||
typename KeySet::const_iterator keyIt = valIt->second.begin();
|
||||
return iterator(valIt, keyIt, this);
|
||||
}
|
||||
const_iterator begin() const {
|
||||
SortByValueMap* mutp = const_cast<SortByValueMap*>(this);
|
||||
typename Val2Keys::iterator valIt = mutp->m_vals.begin();
|
||||
if (valIt == mutp->m_vals.end()) {
|
||||
return end();
|
||||
}
|
||||
if (valIt == mutp->m_vals.end()) return end();
|
||||
typename KeySet::const_iterator keyIt = valIt->second.begin();
|
||||
return const_iterator(valIt, keyIt, mutp);
|
||||
}
|
||||
iterator end() {
|
||||
return iterator(this);
|
||||
}
|
||||
iterator end() { return iterator(this); }
|
||||
const_iterator end() const {
|
||||
// Safe to cast away const; the const_iterator will still enforce
|
||||
// it. Same for the const begin() below.
|
||||
return const_iterator(const_cast<SortByValueMap*>(this));
|
||||
}
|
||||
reverse_iterator rbegin() {
|
||||
return reverse_iterator(end());
|
||||
}
|
||||
reverse_iterator rend() {
|
||||
return reverse_iterator(begin());
|
||||
}
|
||||
const_reverse_iterator rbegin() const {
|
||||
return const_reverse_iterator(end());
|
||||
}
|
||||
const_reverse_iterator rend() const {
|
||||
return const_reverse_iterator(begin());
|
||||
}
|
||||
reverse_iterator rbegin() { return reverse_iterator(end()); }
|
||||
reverse_iterator rend() { return reverse_iterator(begin()); }
|
||||
const_reverse_iterator rbegin() const { return const_reverse_iterator(end()); }
|
||||
const_reverse_iterator rend() const { return const_reverse_iterator(begin()); }
|
||||
|
||||
iterator find(const T_Key& k) {
|
||||
typename Key2Val::iterator kvit = m_keys.find(k);
|
||||
|
|
@ -335,12 +314,8 @@ public:
|
|||
void erase(const reverse_iterator& it) {
|
||||
erase(*it); // Dereferencing returns a copy of the forward iterator
|
||||
}
|
||||
bool has(const T_Key& k) const {
|
||||
return (m_keys.find(k) != m_keys.end());
|
||||
}
|
||||
bool empty() const {
|
||||
return m_keys.empty();
|
||||
}
|
||||
bool has(const T_Key& k) const { return (m_keys.find(k) != m_keys.end()); }
|
||||
bool empty() const { return m_keys.empty(); }
|
||||
// Look up a value. Returns a reference for efficiency. Note this must
|
||||
// be a const reference, otherwise the client could corrupt the sorted
|
||||
// order of m_byValue by reaching through and changing the value.
|
||||
|
|
@ -375,16 +350,14 @@ private:
|
|||
/// when the subset of elements whose scores change is much smaller than
|
||||
/// the full set size.
|
||||
|
||||
template <typename T_Elem,
|
||||
typename T_Score,
|
||||
class T_ElemCompare = std::less<T_Elem> >
|
||||
template <typename T_Elem, typename T_Score, class T_ElemCompare = std::less<T_Elem> >
|
||||
class V3Scoreboard {
|
||||
private:
|
||||
// TYPES
|
||||
typedef vl_unordered_set<const T_Elem*> NeedRescoreSet;
|
||||
class CmpElems {
|
||||
public:
|
||||
bool operator() (const T_Elem* const& ap, const T_Elem* const& bp) const {
|
||||
bool operator()(const T_Elem* const& ap, const T_Elem* const& bp) const {
|
||||
T_ElemCompare cmp;
|
||||
return cmp.operator()(*ap, *bp);
|
||||
}
|
||||
|
|
@ -412,8 +385,7 @@ public:
|
|||
// bestp() until after the next rescore().
|
||||
void addElem(const T_Elem* elp) {
|
||||
if (m_slowAsserts) {
|
||||
UASSERT(!contains(elp),
|
||||
"Adding element to scoreboard that was already in scoreboard");
|
||||
UASSERT(!contains(elp), "Adding element to scoreboard that was already in scoreboard");
|
||||
}
|
||||
m_unknown.insert(elp);
|
||||
}
|
||||
|
|
@ -470,22 +442,19 @@ public:
|
|||
bool needsRescore() { return !m_unknown.empty(); }
|
||||
// False if elp's score is known to V3Scoreboard,
|
||||
// else true if elp's score is unknown until the next rescore().
|
||||
bool needsRescore(const T_Elem* elp) {
|
||||
return (m_unknown.find(elp) != m_unknown.end());
|
||||
}
|
||||
bool needsRescore(const T_Elem* elp) { return (m_unknown.find(elp) != m_unknown.end()); }
|
||||
// Retrieve the last known score for an element.
|
||||
T_Score cachedScore(const T_Elem* elp) {
|
||||
typename SortedMap::iterator result = m_sorted.find(elp);
|
||||
UASSERT(result != m_sorted.end(),
|
||||
"V3Scoreboard::cachedScore() failed to find element");
|
||||
UASSERT(result != m_sorted.end(), "V3Scoreboard::cachedScore() failed to find element");
|
||||
return (*result).value();
|
||||
}
|
||||
// For each element whose score is unknown to V3Scoreboard,
|
||||
// call the client's scoring function to get a new score,
|
||||
// and sort all elements by their current score.
|
||||
void rescore() {
|
||||
for (typename NeedRescoreSet::iterator it = m_unknown.begin();
|
||||
it != m_unknown.end(); ++it) {
|
||||
for (typename NeedRescoreSet::iterator it = m_unknown.begin(); it != m_unknown.end();
|
||||
++it) {
|
||||
const T_Elem* elp = *it;
|
||||
T_Score sortScore = m_scoreFnp(elp);
|
||||
m_sorted.set(elp, sortScore);
|
||||
|
|
@ -500,7 +469,7 @@ private:
|
|||
//######################################################################
|
||||
|
||||
namespace V3ScoreboardBase {
|
||||
void selfTest();
|
||||
void selfTest();
|
||||
} // namespace V3ScoreboardBase
|
||||
|
||||
#endif // Guard
|
||||
|
|
|
|||
|
|
@ -53,7 +53,7 @@ private:
|
|||
class HashSenTree {
|
||||
public:
|
||||
HashSenTree() {}
|
||||
size_t operator() (const AstSenTree* kp) const {
|
||||
size_t operator()(const AstSenTree* kp) const {
|
||||
return V3Hashed::uncachedHash(kp).fullValue();
|
||||
}
|
||||
// Copying required for OSX's libc++
|
||||
|
|
@ -62,7 +62,7 @@ private:
|
|||
class EqSenTree {
|
||||
public:
|
||||
EqSenTree() {}
|
||||
bool operator() (const AstSenTree* ap, const AstSenTree* bp) const {
|
||||
bool operator()(const AstSenTree* ap, const AstSenTree* bp) const {
|
||||
return ap->sameTree(bp);
|
||||
}
|
||||
// Copying required for OSX's libc++
|
||||
|
|
@ -81,9 +81,7 @@ public:
|
|||
AstSenTree* find(AstSenTree* likep) {
|
||||
AstSenTree* resultp = NULL;
|
||||
Set::iterator it = m_trees.find(likep);
|
||||
if (it != m_trees.end()) {
|
||||
resultp = *it;
|
||||
}
|
||||
if (it != m_trees.end()) resultp = *it;
|
||||
return resultp;
|
||||
}
|
||||
void clear() { m_trees.clear(); }
|
||||
|
|
@ -103,9 +101,7 @@ private:
|
|||
|
||||
virtual void visit(AstNodeModule* nodep) VL_OVERRIDE {
|
||||
// Only do the top
|
||||
if (nodep->isTop()) {
|
||||
iterateChildren(nodep);
|
||||
}
|
||||
if (nodep->isTop()) iterateChildren(nodep);
|
||||
}
|
||||
virtual void visit(AstTopScope* nodep) VL_OVERRIDE {
|
||||
m_topscopep = nodep;
|
||||
|
|
@ -139,21 +135,18 @@ public:
|
|||
UASSERT(m_topscopep, "Never called main()");
|
||||
treep = sensesp->cloneTree(false);
|
||||
m_topscopep->addStmtsp(treep);
|
||||
UINFO(8," New SENTREE "<<treep<<endl);
|
||||
UINFO(8, " New SENTREE " << treep << endl);
|
||||
m_trees.add(treep);
|
||||
// Note blocks may have also been added above in the Active visitor
|
||||
}
|
||||
return treep;
|
||||
}
|
||||
|
||||
public:
|
||||
// CONSTRUCTORS
|
||||
SenTreeFinder() {
|
||||
clear();
|
||||
}
|
||||
SenTreeFinder() { clear(); }
|
||||
virtual ~SenTreeFinder() {}
|
||||
void main(AstTopScope* nodep) {
|
||||
iterate(nodep);
|
||||
}
|
||||
void main(AstTopScope* nodep) { iterate(nodep); }
|
||||
};
|
||||
|
||||
#endif // Guard
|
||||
|
|
|
|||
103
src/V3Stats.cpp
103
src/V3Stats.cpp
|
|
@ -36,31 +36,31 @@ class StatsVisitor : public AstNVisitor {
|
|||
private:
|
||||
// NODE STATE/TYPES
|
||||
|
||||
typedef std::map<string,int> NameMap; // Number of times a name appears
|
||||
typedef std::map<string, int> NameMap; // Number of times a name appears
|
||||
|
||||
// STATE
|
||||
string m_stage; // Name of the stage we are scanning
|
||||
string m_stage; // Name of the stage we are scanning
|
||||
/// m_fast = true: Counting only critical branch of fastpath
|
||||
/// m_fast = false: Counting every node, ignoring structure of program
|
||||
bool m_fast;
|
||||
bool m_fast;
|
||||
|
||||
AstCFunc* m_cfuncp; // Current CFUNC
|
||||
VDouble0 m_statInstrLong; // Instruction count
|
||||
bool m_counting; // Currently counting
|
||||
double m_instrs; // Current instr count (for determining branch direction)
|
||||
bool m_tracingCall; // Iterating into a CCall to a CFunc
|
||||
AstCFunc* m_cfuncp; // Current CFUNC
|
||||
VDouble0 m_statInstrLong; // Instruction count
|
||||
bool m_counting; // Currently counting
|
||||
double m_instrs; // Current instr count (for determining branch direction)
|
||||
bool m_tracingCall; // Iterating into a CCall to a CFunc
|
||||
|
||||
std::vector<VDouble0> m_statTypeCount; // Nodes of given type
|
||||
VDouble0 m_statAbove[AstType::_ENUM_END][AstType::_ENUM_END]; // Nodes of given type
|
||||
VDouble0 m_statPred[VBranchPred::_ENUM_END]; // Nodes of given type
|
||||
VDouble0 m_statInstr; // Instruction count
|
||||
VDouble0 m_statInstrFast; // Instruction count, non-slow() eval functions only
|
||||
std::vector<VDouble0> m_statVarWidths; // Variables of given width
|
||||
std::vector<NameMap> m_statVarWidthNames; // Var names of given width
|
||||
VDouble0 m_statVarArray; // Statistic tracking
|
||||
VDouble0 m_statVarBytes; // Statistic tracking
|
||||
VDouble0 m_statVarClock; // Statistic tracking
|
||||
VDouble0 m_statVarScpBytes; // Statistic tracking
|
||||
std::vector<VDouble0> m_statTypeCount; // Nodes of given type
|
||||
VDouble0 m_statAbove[AstType::_ENUM_END][AstType::_ENUM_END]; // Nodes of given type
|
||||
VDouble0 m_statPred[VBranchPred::_ENUM_END]; // Nodes of given type
|
||||
VDouble0 m_statInstr; // Instruction count
|
||||
VDouble0 m_statInstrFast; // Instruction count, non-slow() eval functions only
|
||||
std::vector<VDouble0> m_statVarWidths; // Variables of given width
|
||||
std::vector<NameMap> m_statVarWidthNames; // Var names of given width
|
||||
VDouble0 m_statVarArray; // Statistic tracking
|
||||
VDouble0 m_statVarBytes; // Statistic tracking
|
||||
VDouble0 m_statVarClock; // Statistic tracking
|
||||
VDouble0 m_statVarScpBytes; // Statistic tracking
|
||||
|
||||
// METHODS
|
||||
VL_DEBUG_FUNC; // Declare debug()
|
||||
|
|
@ -92,13 +92,16 @@ private:
|
|||
iterateChildrenConst(nodep);
|
||||
if (m_counting && nodep->dtypep()) {
|
||||
if (nodep->isUsedClock()) ++m_statVarClock;
|
||||
if (VN_IS(nodep->dtypeSkipRefp(), UnpackArrayDType)) ++m_statVarArray;
|
||||
else m_statVarBytes += nodep->dtypeSkipRefp()->widthTotalBytes();
|
||||
if (int(m_statVarWidths.size()) <= nodep->width()) {
|
||||
m_statVarWidths.resize(nodep->width()+5);
|
||||
if (v3Global.opt.statsVars()) m_statVarWidthNames.resize(nodep->width()+5);
|
||||
if (VN_IS(nodep->dtypeSkipRefp(), UnpackArrayDType)) {
|
||||
++m_statVarArray;
|
||||
} else {
|
||||
m_statVarBytes += nodep->dtypeSkipRefp()->widthTotalBytes();
|
||||
}
|
||||
++ m_statVarWidths.at(nodep->width());
|
||||
if (int(m_statVarWidths.size()) <= nodep->width()) {
|
||||
m_statVarWidths.resize(nodep->width() + 5);
|
||||
if (v3Global.opt.statsVars()) m_statVarWidthNames.resize(nodep->width() + 5);
|
||||
}
|
||||
++m_statVarWidths.at(nodep->width());
|
||||
string pn = nodep->prettyName();
|
||||
if (v3Global.opt.statsVars()) {
|
||||
NameMap& nameMapr = m_statVarWidthNames.at(nodep->width());
|
||||
|
|
@ -120,14 +123,12 @@ private:
|
|||
}
|
||||
}
|
||||
virtual void visit(AstNodeIf* nodep) VL_OVERRIDE {
|
||||
UINFO(4," IF i="<<m_instrs<<" "<<nodep<<endl);
|
||||
UINFO(4, " IF i=" << m_instrs << " " << nodep << endl);
|
||||
allNodes(nodep);
|
||||
// Condition is part of cost allocated to PREVIOUS block
|
||||
iterateAndNextConstNull(nodep->condp());
|
||||
// Track prediction
|
||||
if (m_counting) {
|
||||
++m_statPred[nodep->branchPred()];
|
||||
}
|
||||
if (m_counting) ++m_statPred[nodep->branchPred()];
|
||||
if (!m_fast) {
|
||||
// Count everything
|
||||
iterateChildrenConst(nodep);
|
||||
|
|
@ -171,7 +172,7 @@ private:
|
|||
}
|
||||
}
|
||||
// While's we assume evaluate once.
|
||||
//virtual void visit(AstWhile* nodep) VL_OVERRIDE {
|
||||
// virtual void visit(AstWhile* nodep) VL_OVERRIDE {
|
||||
|
||||
virtual void visit(AstNodeCCall* nodep) VL_OVERRIDE {
|
||||
allNodes(nodep);
|
||||
|
|
@ -206,11 +207,13 @@ private:
|
|||
allNodes(nodep);
|
||||
iterateChildrenConst(nodep);
|
||||
}
|
||||
|
||||
public:
|
||||
// CONSTRUCTORS
|
||||
StatsVisitor(AstNetlist* nodep, const string& stage, bool fast)
|
||||
: m_stage(stage), m_fast(fast) {
|
||||
UINFO(9,"Starting stats, fast="<<fast<<endl);
|
||||
: m_stage(stage)
|
||||
, m_fast(fast) {
|
||||
UINFO(9, "Starting stats, fast=" << fast << endl);
|
||||
m_cfuncp = NULL;
|
||||
m_counting = !m_fast;
|
||||
m_instrs = 0;
|
||||
|
|
@ -223,53 +226,55 @@ public:
|
|||
virtual ~StatsVisitor() {
|
||||
// Done. Publish statistics
|
||||
V3Stats::addStat(m_stage, "Instruction count, TOTAL", m_statInstr);
|
||||
V3Stats::addStat(m_stage, "Instruction count, fast critical", m_statInstrFast);
|
||||
V3Stats::addStat(m_stage, "Instruction count, fast critical", m_statInstrFast);
|
||||
// Vars
|
||||
V3Stats::addStat(m_stage, "Vars, unpacked arrayed", m_statVarArray);
|
||||
V3Stats::addStat(m_stage, "Vars, clock attribute", m_statVarClock);
|
||||
V3Stats::addStat(m_stage, "Var space, non-arrays, bytes", m_statVarBytes);
|
||||
if (m_statVarScpBytes!=0.0) {
|
||||
if (m_statVarScpBytes != 0.0) {
|
||||
V3Stats::addStat(m_stage, "Var space, scoped, bytes", m_statVarScpBytes);
|
||||
}
|
||||
for (unsigned i=0; i<m_statVarWidths.size(); i++) {
|
||||
for (unsigned i = 0; i < m_statVarWidths.size(); i++) {
|
||||
double count = double(m_statVarWidths.at(i));
|
||||
if (count != 0.0) {
|
||||
if (v3Global.opt.statsVars()) {
|
||||
NameMap& nameMapr = m_statVarWidthNames.at(i);
|
||||
for (NameMap::iterator it=nameMapr.begin(); it!=nameMapr.end(); ++it) {
|
||||
std::ostringstream os; os<<"Vars, width "
|
||||
<<std::setw(5)<<std::dec<<i<<" "<<it->first;
|
||||
for (NameMap::iterator it = nameMapr.begin(); it != nameMapr.end(); ++it) {
|
||||
std::ostringstream os;
|
||||
os << "Vars, width " << std::setw(5) << std::dec << i << " " << it->first;
|
||||
V3Stats::addStat(m_stage, os.str(), it->second);
|
||||
}
|
||||
} else {
|
||||
std::ostringstream os; os<<"Vars, width "<<std::setw(5)<<std::dec<<i;
|
||||
std::ostringstream os;
|
||||
os << "Vars, width " << std::setw(5) << std::dec << i;
|
||||
V3Stats::addStat(m_stage, os.str(), count);
|
||||
}
|
||||
}
|
||||
}
|
||||
// Node types
|
||||
for (int type=0; type<AstType::_ENUM_END; type++) {
|
||||
for (int type = 0; type < AstType::_ENUM_END; type++) {
|
||||
double count = double(m_statTypeCount.at(type));
|
||||
if (count != 0.0) {
|
||||
V3Stats::addStat(m_stage, string("Node count, ")+AstType(type).ascii(), count);
|
||||
V3Stats::addStat(m_stage, string("Node count, ") + AstType(type).ascii(), count);
|
||||
}
|
||||
}
|
||||
for (int type=0; type < AstType::_ENUM_END; type++) {
|
||||
for (int type2=0; type2 < AstType::_ENUM_END; type2++) {
|
||||
for (int type = 0; type < AstType::_ENUM_END; type++) {
|
||||
for (int type2 = 0; type2 < AstType::_ENUM_END; type2++) {
|
||||
double count = double(m_statAbove[type][type2]);
|
||||
if (count != 0.0) {
|
||||
V3Stats::addStat(m_stage, (string("Node pairs, ")
|
||||
+AstType(type).ascii()+"_"+AstType(type2).ascii()),
|
||||
V3Stats::addStat(m_stage,
|
||||
(string("Node pairs, ") + AstType(type).ascii() + "_"
|
||||
+ AstType(type2).ascii()),
|
||||
count);
|
||||
}
|
||||
}
|
||||
}
|
||||
// Branch pred
|
||||
for (int type=0; type < VBranchPred::_ENUM_END; type++) {
|
||||
for (int type = 0; type < VBranchPred::_ENUM_END; type++) {
|
||||
double count = double(m_statPred[type]);
|
||||
if (count != 0.0) {
|
||||
V3Stats::addStat(m_stage, (string("Branch prediction, ")
|
||||
+ VBranchPred(type).ascii()), count);
|
||||
V3Stats::addStat(
|
||||
m_stage, (string("Branch prediction, ") + VBranchPred(type).ascii()), count);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -279,7 +284,7 @@ public:
|
|||
// Top Stats class
|
||||
|
||||
void V3Stats::statsStageAll(AstNetlist* nodep, const string& stage, bool fast) {
|
||||
StatsVisitor visitor (nodep, stage, fast);
|
||||
StatsVisitor visitor(nodep, stage, fast);
|
||||
}
|
||||
|
||||
void V3Stats::statsFinalAll(AstNetlist* nodep) {
|
||||
|
|
|
|||
|
|
@ -31,31 +31,49 @@ class VDouble0 {
|
|||
double m_d; ///< Count of occurrences/ value
|
||||
public:
|
||||
// METHODS
|
||||
VDouble0() : m_d(0) {}
|
||||
VDouble0()
|
||||
: m_d(0) {}
|
||||
~VDouble0() {}
|
||||
|
||||
// Implicit conversion operators:
|
||||
inline explicit VDouble0(const vluint64_t v) : m_d(v) { }
|
||||
inline explicit VDouble0(const vluint64_t v)
|
||||
: m_d(v) {}
|
||||
inline operator double() const { return m_d; }
|
||||
|
||||
// Explicit operators:
|
||||
inline VDouble0& operator++() { ++m_d; return *this; } // prefix
|
||||
inline VDouble0 operator++(int) { VDouble0 old=*this; m_d++; return old; } // postfix
|
||||
inline VDouble0& operator= (const double v) { m_d = v; return *this; }
|
||||
inline VDouble0& operator+=(const double v) { m_d += v; return *this; }
|
||||
inline VDouble0& operator-=(const double v) { m_d -= v; return *this; }
|
||||
inline VDouble0& operator++() { // prefix
|
||||
++m_d;
|
||||
return *this;
|
||||
}
|
||||
inline VDouble0 operator++(int) { // postfix
|
||||
VDouble0 old = *this;
|
||||
m_d++;
|
||||
return old;
|
||||
}
|
||||
inline VDouble0& operator=(const double v) {
|
||||
m_d = v;
|
||||
return *this;
|
||||
}
|
||||
inline VDouble0& operator+=(const double v) {
|
||||
m_d += v;
|
||||
return *this;
|
||||
}
|
||||
inline VDouble0& operator-=(const double v) {
|
||||
m_d -= v;
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
|
||||
//============================================================================
|
||||
|
||||
class V3Statistic {
|
||||
// A statistical entry we want published into the database
|
||||
string m_name; ///< Nameiption of this statistic
|
||||
double m_count; ///< Count of occurrences/ value
|
||||
string m_stage; ///< Runtime stage
|
||||
bool m_sumit; ///< Do summation of similar stats
|
||||
bool m_perf; ///< Performance section
|
||||
bool m_printit; ///< Print the results
|
||||
string m_name; ///< Nameiption of this statistic
|
||||
double m_count; ///< Count of occurrences/ value
|
||||
string m_stage; ///< Runtime stage
|
||||
bool m_sumit; ///< Do summation of similar stats
|
||||
bool m_perf; ///< Performance section
|
||||
bool m_printit; ///< Print the results
|
||||
public:
|
||||
// METHODS
|
||||
string stage() const { return m_stage; }
|
||||
|
|
@ -70,9 +88,13 @@ public:
|
|||
otherp->m_printit = false;
|
||||
}
|
||||
// CONSTRUCTORS
|
||||
V3Statistic(const string& stage, const string& name,
|
||||
double count, bool sumit=false, bool perf=false)
|
||||
: m_name(name), m_count(count), m_stage(stage), m_sumit(sumit), m_perf(perf)
|
||||
V3Statistic(const string& stage, const string& name, double count, bool sumit = false,
|
||||
bool perf = false)
|
||||
: m_name(name)
|
||||
, m_count(count)
|
||||
, m_stage(stage)
|
||||
, m_sumit(sumit)
|
||||
, m_perf(perf)
|
||||
, m_printit(true) {}
|
||||
virtual ~V3Statistic() {}
|
||||
};
|
||||
|
|
@ -83,21 +105,24 @@ class V3Stats {
|
|||
public:
|
||||
static void addStat(const V3Statistic&);
|
||||
static void addStat(const string& stage, const string& name, double count) {
|
||||
addStat(V3Statistic(stage, name, count)); }
|
||||
addStat(V3Statistic(stage, name, count));
|
||||
}
|
||||
static void addStat(const string& name, double count) {
|
||||
addStat(V3Statistic("*", name, count)); }
|
||||
addStat(V3Statistic("*", name, count));
|
||||
}
|
||||
static void addStatSum(const string& name, double count) {
|
||||
addStat(V3Statistic("*", name, count, true)); }
|
||||
addStat(V3Statistic("*", name, count, true));
|
||||
}
|
||||
static void addStatPerf(const string& name, double count) {
|
||||
addStat(V3Statistic("*", name, count, true, true)); }
|
||||
addStat(V3Statistic("*", name, count, true, true));
|
||||
}
|
||||
/// Called each stage
|
||||
static void statsStage(const string& name);
|
||||
/// Called by the top level to collect statistics
|
||||
static void statsStageAll(AstNetlist* nodep, const string& stage, bool fast=false);
|
||||
static void statsStageAll(AstNetlist* nodep, const string& stage, bool fast = false);
|
||||
static void statsFinalAll(AstNetlist* nodep);
|
||||
/// Called by the top level to dump the statistics
|
||||
static void statsReport();
|
||||
};
|
||||
|
||||
|
||||
#endif // Guard
|
||||
|
|
|
|||
|
|
@ -40,31 +40,31 @@ class StatsReport {
|
|||
static StatColl s_allStats; ///< All statistics
|
||||
|
||||
void header() {
|
||||
os<<"Verilator Statistics Report\n";
|
||||
os<<endl;
|
||||
os << "Verilator Statistics Report\n";
|
||||
os << endl;
|
||||
|
||||
os<<"Information:"<<endl;
|
||||
os<<" "<<V3Options::version()<<endl;
|
||||
os<<" Arguments: "<<v3Global.opt.allArgsString()<<endl;
|
||||
os<<endl;
|
||||
os << "Information:" << endl;
|
||||
os << " " << V3Options::version() << endl;
|
||||
os << " Arguments: " << v3Global.opt.allArgsString() << endl;
|
||||
os << endl;
|
||||
}
|
||||
|
||||
void sumit() {
|
||||
// If sumit is set on a statistic, combine with others of same name
|
||||
typedef std::multimap<string,V3Statistic*> ByName;
|
||||
typedef std::multimap<string, V3Statistic*> ByName;
|
||||
ByName byName;
|
||||
// * is always first
|
||||
for (StatColl::iterator it = s_allStats.begin(); it!=s_allStats.end(); ++it) {
|
||||
for (StatColl::iterator it = s_allStats.begin(); it != s_allStats.end(); ++it) {
|
||||
V3Statistic* repp = &(*it);
|
||||
byName.insert(make_pair(repp->name(), repp));
|
||||
}
|
||||
|
||||
// Process duplicates
|
||||
V3Statistic* lastp = NULL;
|
||||
for (ByName::iterator it = byName.begin(); it!=byName.end(); ++it) {
|
||||
for (ByName::iterator it = byName.begin(); it != byName.end(); ++it) {
|
||||
V3Statistic* repp = it->second;
|
||||
if (lastp && lastp->sumit() && lastp->printit()
|
||||
&& lastp->name() == repp->name() && lastp->stage() == repp->stage()) {
|
||||
if (lastp && lastp->sumit() && lastp->printit() && lastp->name() == repp->name()
|
||||
&& lastp->stage() == repp->stage()) {
|
||||
repp->combineWith(lastp);
|
||||
}
|
||||
lastp = repp;
|
||||
|
|
@ -74,10 +74,10 @@ class StatsReport {
|
|||
void stars() {
|
||||
// Find all stages
|
||||
size_t maxWidth = 0;
|
||||
typedef std::multimap<string,const V3Statistic*> ByName;
|
||||
typedef std::multimap<string, const V3Statistic*> ByName;
|
||||
ByName byName;
|
||||
// * is always first
|
||||
for (StatColl::iterator it = s_allStats.begin(); it!=s_allStats.end(); ++it) {
|
||||
for (StatColl::iterator it = s_allStats.begin(); it != s_allStats.end(); ++it) {
|
||||
const V3Statistic* repp = &(*it);
|
||||
if (repp->stage() == "*" && repp->printit()) {
|
||||
if (maxWidth < repp->name().length()) maxWidth = repp->name().length();
|
||||
|
|
@ -86,43 +86,43 @@ class StatsReport {
|
|||
}
|
||||
|
||||
// Print organized by stage
|
||||
os<<"Global Statistics:\n";
|
||||
os<<endl;
|
||||
for (ByName::iterator it = byName.begin(); it!=byName.end(); ++it) {
|
||||
os << "Global Statistics:\n";
|
||||
os << endl;
|
||||
for (ByName::iterator it = byName.begin(); it != byName.end(); ++it) {
|
||||
const V3Statistic* repp = it->second;
|
||||
if (repp->perf()) continue;
|
||||
os<<" "<<std::left<<std::setw(maxWidth)<<repp->name();
|
||||
os << " " << std::left << std::setw(maxWidth) << repp->name();
|
||||
repp->dump(os);
|
||||
os<<endl;
|
||||
os << endl;
|
||||
}
|
||||
os<<endl;
|
||||
os << endl;
|
||||
|
||||
// Print organized by stage
|
||||
os<<"Performance Statistics:\n";
|
||||
os<<endl;
|
||||
for (ByName::iterator it = byName.begin(); it!=byName.end(); ++it) {
|
||||
os << "Performance Statistics:\n";
|
||||
os << endl;
|
||||
for (ByName::iterator it = byName.begin(); it != byName.end(); ++it) {
|
||||
const V3Statistic* repp = it->second;
|
||||
if (!repp->perf()) continue;
|
||||
os<<" "<<std::left<<std::setw(maxWidth)<<repp->name();
|
||||
os << " " << std::left << std::setw(maxWidth) << repp->name();
|
||||
repp->dump(os);
|
||||
os<<endl;
|
||||
os << endl;
|
||||
}
|
||||
os<<endl;
|
||||
os << endl;
|
||||
}
|
||||
|
||||
void stages() {
|
||||
os<<"Stage Statistics:\n";
|
||||
os << "Stage Statistics:\n";
|
||||
|
||||
// Find all stages
|
||||
int stage = 0;
|
||||
size_t maxWidth = 0;
|
||||
typedef std::vector<string> Stages;
|
||||
Stages stages;
|
||||
vl_unordered_map<string,int> stageInt;
|
||||
typedef std::multimap<string,const V3Statistic*> ByName;
|
||||
vl_unordered_map<string, int> stageInt;
|
||||
typedef std::multimap<string, const V3Statistic*> ByName;
|
||||
ByName byName;
|
||||
// * is always first
|
||||
for (StatColl::iterator it = s_allStats.begin(); it!=s_allStats.end(); ++it) {
|
||||
for (StatColl::iterator it = s_allStats.begin(); it != s_allStats.end(); ++it) {
|
||||
const V3Statistic* repp = &(*it);
|
||||
if (repp->stage() != "*" && repp->printit()) {
|
||||
if (maxWidth < repp->name().length()) maxWidth = repp->name().length();
|
||||
|
|
@ -135,16 +135,16 @@ class StatsReport {
|
|||
}
|
||||
|
||||
// Header
|
||||
os<<" Stat "<<std::left<<std::setw(maxWidth-5-2)<<"";
|
||||
os << " Stat " << std::left << std::setw(maxWidth - 5 - 2) << "";
|
||||
for (Stages::const_iterator it = stages.begin(); it != stages.end(); ++it) {
|
||||
os<<" "<<std::left<<std::setw(9)<<*it;
|
||||
os << " " << std::left << std::setw(9) << *it;
|
||||
}
|
||||
os<<endl;
|
||||
os<<" -------- "<<std::left<<std::setw(maxWidth-5-2)<<"";
|
||||
os << endl;
|
||||
os << " -------- " << std::left << std::setw(maxWidth - 5 - 2) << "";
|
||||
for (Stages::const_iterator it = stages.begin(); it != stages.end(); ++it) {
|
||||
os<<" "<<std::left<<std::setw(9)<<"-------";
|
||||
os << " " << std::left << std::setw(9) << "-------";
|
||||
}
|
||||
//os<<endl;
|
||||
// os<<endl;
|
||||
|
||||
// Print organized by stage
|
||||
string lastName = "__NONE__";
|
||||
|
|
@ -157,33 +157,29 @@ class StatsReport {
|
|||
{
|
||||
string commaName = lastName;
|
||||
string::size_type pos;
|
||||
if ((pos = commaName.find(',')) != string::npos) {
|
||||
commaName.erase(pos);
|
||||
}
|
||||
if ((pos = commaName.find(',')) != string::npos) commaName.erase(pos);
|
||||
if (lastCommaName != commaName) {
|
||||
lastCommaName = commaName;
|
||||
os<<endl;
|
||||
os << endl;
|
||||
}
|
||||
}
|
||||
os<<endl;
|
||||
os << endl;
|
||||
col = 0;
|
||||
os<<" "<<std::left<<std::setw(maxWidth)<<repp->name();
|
||||
os << " " << std::left << std::setw(maxWidth) << repp->name();
|
||||
}
|
||||
while (col<stages.size() && stages.at(col) != repp->stage()) {
|
||||
os<<std::setw(11)<<"";
|
||||
while (col < stages.size() && stages.at(col) != repp->stage()) {
|
||||
os << std::setw(11) << "";
|
||||
col++;
|
||||
}
|
||||
repp->dump(os);
|
||||
col++;
|
||||
}
|
||||
os<<endl;
|
||||
os << endl;
|
||||
}
|
||||
|
||||
public:
|
||||
// METHODS
|
||||
static void addStat(const V3Statistic& stat) {
|
||||
s_allStats.push_back(stat);
|
||||
}
|
||||
static void addStat(const V3Statistic& stat) { s_allStats.push_back(stat); }
|
||||
|
||||
// CONSTRUCTORS
|
||||
explicit StatsReport(std::ofstream* aofp)
|
||||
|
|
@ -196,52 +192,51 @@ public:
|
|||
~StatsReport() {}
|
||||
};
|
||||
|
||||
StatsReport::StatColl StatsReport::s_allStats;
|
||||
StatsReport::StatColl StatsReport::s_allStats;
|
||||
|
||||
//######################################################################
|
||||
// V3Statstic class
|
||||
|
||||
void V3Statistic::dump(std::ofstream& os) const {
|
||||
if (perf()) {
|
||||
os<<" "<<std::right<<std::fixed<<std::setprecision(6)<<std::setw(9)<<count();
|
||||
os << " " << std::right << std::fixed << std::setprecision(6) << std::setw(9) << count();
|
||||
} else {
|
||||
os<<" "<<std::right<<std::fixed<<std::setprecision(0)<<std::setw(9)<<count();
|
||||
os << " " << std::right << std::fixed << std::setprecision(0) << std::setw(9) << count();
|
||||
}
|
||||
}
|
||||
|
||||
//######################################################################
|
||||
// Top Stats class
|
||||
|
||||
void V3Stats::addStat(const V3Statistic& stat) {
|
||||
StatsReport::addStat(stat);
|
||||
}
|
||||
void V3Stats::addStat(const V3Statistic& stat) { StatsReport::addStat(stat); }
|
||||
|
||||
void V3Stats::statsStage(const string& name) {
|
||||
static double lastWallTime = -1;
|
||||
static int fileNumber = 0;
|
||||
|
||||
char digits[100]; sprintf(digits, "%03d", ++fileNumber);
|
||||
const string digitName = string(digits)+"_"+name;
|
||||
char digits[100];
|
||||
sprintf(digits, "%03d", ++fileNumber);
|
||||
const string digitName = string(digits) + "_" + name;
|
||||
|
||||
double wallTime = V3Os::timeUsecs() / 1.0e6;
|
||||
if (lastWallTime<0) lastWallTime = wallTime;
|
||||
if (lastWallTime < 0) lastWallTime = wallTime;
|
||||
double wallTimeDelta = wallTime - lastWallTime;
|
||||
lastWallTime = wallTime;
|
||||
V3Stats::addStatPerf("Stage, Elapsed time (sec), "+digitName, wallTimeDelta);
|
||||
V3Stats::addStatPerf("Stage, Elapsed time (sec), " + digitName, wallTimeDelta);
|
||||
|
||||
double memory = V3Os::memUsageBytes()/1024.0/1024.0;
|
||||
V3Stats::addStatPerf("Stage, Memory (MB), "+digitName, memory);
|
||||
double memory = V3Os::memUsageBytes() / 1024.0 / 1024.0;
|
||||
V3Stats::addStatPerf("Stage, Memory (MB), " + digitName, memory);
|
||||
}
|
||||
|
||||
void V3Stats::statsReport() {
|
||||
UINFO(2,__FUNCTION__<<": "<<endl);
|
||||
UINFO(2, __FUNCTION__ << ": " << endl);
|
||||
|
||||
// Open stats file
|
||||
string filename = v3Global.opt.makeDir()+"/"+v3Global.opt.prefix()+"__stats.txt";
|
||||
std::ofstream* ofp (V3File::new_ofstream(filename));
|
||||
if (ofp->fail()) v3fatal("Can't write "<<filename);
|
||||
string filename = v3Global.opt.makeDir() + "/" + v3Global.opt.prefix() + "__stats.txt";
|
||||
std::ofstream* ofp(V3File::new_ofstream(filename));
|
||||
if (ofp->fail()) v3fatal("Can't write " << filename);
|
||||
|
||||
StatsReport reporter (ofp);
|
||||
StatsReport reporter(ofp);
|
||||
|
||||
// Cleanup
|
||||
ofp->close();
|
||||
|
|
|
|||
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
|
||||
inline bool VString::wildmatchi(const char* s, const char* p) {
|
||||
for ( ; *p; s++, p++) {
|
||||
if (*p!='*') {
|
||||
if (((*s)!=(*p)) && *p != '?')
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
for (; *p; s++, p++) {
|
||||
if (*p != '*') {
|
||||
if (((*s) != (*p)) && *p != '?') return false;
|
||||
} else {
|
||||
// Trailing star matches everything.
|
||||
if (!*++p) return true;
|
||||
while (!wildmatch(s, p)) {
|
||||
if (*++s == '\0') {
|
||||
return false;
|
||||
}
|
||||
if (*++s == '\0') return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
|
@ -51,18 +47,14 @@ inline bool VString::wildmatchi(const char* s, const char* p) {
|
|||
}
|
||||
|
||||
bool VString::wildmatch(const char* s, const char* p) {
|
||||
for ( ; *p; s++, p++) {
|
||||
if (*p!='*') {
|
||||
if (((*s)!=(*p)) && *p != '?')
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
for (; *p; s++, p++) {
|
||||
if (*p != '*') {
|
||||
if (((*s) != (*p)) && *p != '?') return false;
|
||||
} else {
|
||||
// Trailing star matches everything.
|
||||
if (!*++p) return true;
|
||||
while (!wildmatchi(s, p)) {
|
||||
if (*++s == '\0') {
|
||||
return false;
|
||||
}
|
||||
if (*++s == '\0') return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
|
@ -74,29 +66,25 @@ bool VString::wildmatch(const string& s, const string& p) {
|
|||
return wildmatch(s.c_str(), p.c_str());
|
||||
}
|
||||
|
||||
bool VString::isWildcard(const string &p) {
|
||||
bool VString::isWildcard(const string& p) {
|
||||
return ((p.find('*') != string::npos) || (p.find('?') != string::npos));
|
||||
}
|
||||
|
||||
string VString::dot(const string& a, const string& dot, const string& b) {
|
||||
if (b=="") return a;
|
||||
if (a=="") return b;
|
||||
return a+dot+b;
|
||||
if (b == "") return a;
|
||||
if (a == "") return b;
|
||||
return a + dot + b;
|
||||
}
|
||||
|
||||
string VString::downcase(const string& str) {
|
||||
string out = str;
|
||||
for (string::iterator pos = out.begin(); pos != out.end(); ++pos) {
|
||||
*pos = tolower(*pos);
|
||||
}
|
||||
for (string::iterator pos = out.begin(); pos != out.end(); ++pos) *pos = tolower(*pos);
|
||||
return out;
|
||||
}
|
||||
|
||||
string VString::upcase(const string& str) {
|
||||
string out = str;
|
||||
for (string::iterator pos = out.begin(); pos != out.end(); ++pos) {
|
||||
*pos = toupper(*pos);
|
||||
}
|
||||
for (string::iterator pos = out.begin(); pos != out.end(); ++pos) *pos = toupper(*pos);
|
||||
return out;
|
||||
}
|
||||
|
||||
|
|
@ -112,8 +100,11 @@ string VString::quotePercent(const string& str) {
|
|||
string VString::spaceUnprintable(const string& str) {
|
||||
string out;
|
||||
for (string::const_iterator pos = str.begin(); pos != str.end(); ++pos) {
|
||||
if (isprint(*pos)) out += *pos;
|
||||
else out += ' ';
|
||||
if (isprint(*pos)) {
|
||||
out += *pos;
|
||||
} else {
|
||||
out += ' ';
|
||||
}
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
|
@ -128,16 +119,17 @@ bool VString::isWhitespace(const string& str) {
|
|||
//######################################################################
|
||||
// VHashSha256
|
||||
|
||||
static const uint32_t sha256K[] = {
|
||||
0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
|
||||
0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
|
||||
0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
|
||||
0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
|
||||
0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
|
||||
0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
|
||||
0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
|
||||
0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
|
||||
};
|
||||
static const uint32_t sha256K[]
|
||||
= {0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4,
|
||||
0xab1c5ed5, 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe,
|
||||
0x9bdc06a7, 0xc19bf174, 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f,
|
||||
0x4a7484aa, 0x5cb0a9dc, 0x76f988da, 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7,
|
||||
0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc,
|
||||
0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, 0xa2bfe8a1, 0xa81a664b,
|
||||
0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, 0x19a4c116,
|
||||
0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
|
||||
0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7,
|
||||
0xc67178f2};
|
||||
|
||||
static inline uint32_t shaRotr32(uint32_t lhs, uint32_t rhs) VL_ATTR_ALWINLINE;
|
||||
static inline uint32_t shaRotr32(uint32_t lhs, uint32_t rhs) {
|
||||
|
|
@ -150,9 +142,7 @@ static inline void sha256Block(uint32_t* h, const uint32_t* chunk) {
|
|||
const uint32_t* p = chunk;
|
||||
|
||||
// Initialize working variables to current hash value
|
||||
for (unsigned i = 0; i < 8; i++) {
|
||||
ah[i] = h[i];
|
||||
}
|
||||
for (unsigned i = 0; i < 8; i++) ah[i] = h[i];
|
||||
// Compression function main loop
|
||||
for (unsigned i = 0; i < 4; ++i) {
|
||||
uint32_t w[16];
|
||||
|
|
@ -164,17 +154,15 @@ static inline void sha256Block(uint32_t* h, const uint32_t* chunk) {
|
|||
// Extend the first 16 words into the remaining
|
||||
// 48 words w[16..63] of the message schedule array:
|
||||
const uint32_t s0 = shaRotr32(w[(j + 1) & 0xf], 7)
|
||||
^ shaRotr32(w[(j + 1) & 0xf], 18) ^ (w[(j + 1) & 0xf] >> 3);
|
||||
^ shaRotr32(w[(j + 1) & 0xf], 18) ^ (w[(j + 1) & 0xf] >> 3);
|
||||
const uint32_t s1 = shaRotr32(w[(j + 14) & 0xf], 17)
|
||||
^ shaRotr32(w[(j + 14) & 0xf], 19) ^ (w[(j + 14) & 0xf] >> 10);
|
||||
^ shaRotr32(w[(j + 14) & 0xf], 19) ^ (w[(j + 14) & 0xf] >> 10);
|
||||
w[j] = w[j] + s0 + w[(j + 9) & 0xf] + s1;
|
||||
}
|
||||
const uint32_t s1 = shaRotr32(ah[4], 6)
|
||||
^ shaRotr32(ah[4], 11) ^ shaRotr32(ah[4], 25);
|
||||
const uint32_t s1 = shaRotr32(ah[4], 6) ^ shaRotr32(ah[4], 11) ^ shaRotr32(ah[4], 25);
|
||||
const uint32_t ch = (ah[4] & ah[5]) ^ (~ah[4] & ah[6]);
|
||||
const uint32_t temp1 = ah[7] + s1 + ch + sha256K[i << 4 | j] + w[j];
|
||||
const uint32_t s0 = shaRotr32(ah[0], 2)
|
||||
^ shaRotr32(ah[0], 13) ^ shaRotr32(ah[0], 22);
|
||||
const uint32_t s0 = shaRotr32(ah[0], 2) ^ shaRotr32(ah[0], 13) ^ shaRotr32(ah[0], 22);
|
||||
const uint32_t maj = (ah[0] & ah[1]) ^ (ah[0] & ah[2]) ^ (ah[1] & ah[2]);
|
||||
const uint32_t temp2 = s0 + maj;
|
||||
|
||||
|
|
@ -191,7 +179,6 @@ static inline void sha256Block(uint32_t* h, const uint32_t* chunk) {
|
|||
for (unsigned i = 0; i < 8; ++i) h[i] += ah[i];
|
||||
}
|
||||
|
||||
|
||||
void VHashSha256::insert(const void* datap, size_t length) {
|
||||
UASSERT(!m_final, "Called VHashSha256::insert after finalized the hash value");
|
||||
m_totLength += length;
|
||||
|
|
@ -199,7 +186,7 @@ void VHashSha256::insert(const void* datap, size_t length) {
|
|||
string tempData;
|
||||
int chunkLen;
|
||||
const uint8_t* chunkp;
|
||||
if (m_remainder=="") {
|
||||
if (m_remainder == "") {
|
||||
chunkLen = length;
|
||||
chunkp = static_cast<const uint8_t*>(datap);
|
||||
} else {
|
||||
|
|
@ -229,7 +216,7 @@ void VHashSha256::insert(const void* datap, size_t length) {
|
|||
sha256Block(m_inthash, w);
|
||||
}
|
||||
|
||||
m_remainder = string(reinterpret_cast<const char*>(chunkp+posBegin), chunkLen-posEnd);
|
||||
m_remainder = string(reinterpret_cast<const char*>(chunkp + posBegin), chunkLen - posEnd);
|
||||
}
|
||||
|
||||
void VHashSha256::finalize() {
|
||||
|
|
@ -240,16 +227,16 @@ void VHashSha256::finalize() {
|
|||
|
||||
// Process final possibly non-complete 64-byte block
|
||||
uint32_t w[16]; // Round buffer, [0..15] are input data
|
||||
for (int i=0; i<16; ++i) w[i] = 0;
|
||||
for (int i = 0; i < 16; ++i) w[i] = 0;
|
||||
size_t blockPos = 0;
|
||||
for (; blockPos < m_remainder.length(); ++blockPos) {
|
||||
w[blockPos >> 2] |= ((static_cast<uint32_t>(m_remainder[blockPos]))
|
||||
<< ((3 - (blockPos & 3)) << 3));
|
||||
w[blockPos >> 2]
|
||||
|= ((static_cast<uint32_t>(m_remainder[blockPos])) << ((3 - (blockPos & 3)) << 3));
|
||||
}
|
||||
w[blockPos >> 2] |= 0x80 << ((3 - (blockPos & 3)) << 3);
|
||||
if (m_remainder.length() >= 56) {
|
||||
sha256Block(m_inthash, w);
|
||||
for (int i=0; i<16; ++i) w[i] = 0;
|
||||
for (int i = 0; i < 16; ++i) w[i] = 0;
|
||||
}
|
||||
w[15] = m_totLength << 3;
|
||||
sha256Block(m_inthash, w);
|
||||
|
|
@ -260,8 +247,9 @@ void VHashSha256::finalize() {
|
|||
|
||||
string VHashSha256::digestBinary() {
|
||||
finalize();
|
||||
string out; out.reserve(32);
|
||||
for (size_t i=0; i<32; ++i) {
|
||||
string out;
|
||||
out.reserve(32);
|
||||
for (size_t i = 0; i < 32; ++i) {
|
||||
out += (m_inthash[i >> 2] >> (((3 - i) & 0x3) << 3)) & 0xff;
|
||||
}
|
||||
return out;
|
||||
|
|
@ -270,20 +258,21 @@ string VHashSha256::digestBinary() {
|
|||
uint64_t VHashSha256::digestUInt64() {
|
||||
const string& binhash = digestBinary();
|
||||
uint64_t out = 0;
|
||||
for (size_t byte=0; byte<sizeof(uint64_t); ++byte) {
|
||||
for (size_t byte = 0; byte < sizeof(uint64_t); ++byte) {
|
||||
unsigned char c = binhash[byte];
|
||||
out = (out<<8) | c;
|
||||
out = (out << 8) | c;
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
string VHashSha256::digestHex() {
|
||||
static const char digits[16+1] = "0123456789abcdef";
|
||||
static const char digits[16 + 1] = "0123456789abcdef";
|
||||
const string& binhash = digestBinary();
|
||||
string out; out.reserve(70);
|
||||
for (size_t byte=0; byte<32; ++byte) {
|
||||
out += digits[ (binhash[byte]>>4) & 0xf ];
|
||||
out += digits[ (binhash[byte]>>0) & 0xf ];
|
||||
string out;
|
||||
out.reserve(70);
|
||||
for (size_t byte = 0; byte < 32; ++byte) {
|
||||
out += digits[(binhash[byte] >> 4) & 0xf];
|
||||
out += digits[(binhash[byte] >> 0) & 0xf];
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
|
@ -293,12 +282,13 @@ string VHashSha256::digestSymbol() {
|
|||
// has + and / for last two digits, but need C symbol, and we also
|
||||
// avoid conflicts with use of _, so use "AB" at the end.
|
||||
// Thus this function is non-reversible.
|
||||
static const char digits[64+1]
|
||||
static const char digits[64 + 1]
|
||||
= "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB";
|
||||
const string& binhash = digestBinary();
|
||||
string out; out.reserve(28);
|
||||
string out;
|
||||
out.reserve(28);
|
||||
int pos = 0;
|
||||
for (; pos < (256/8) - 2; pos += 3) {
|
||||
for (; pos < (256 / 8) - 2; pos += 3) {
|
||||
out += digits[((binhash[pos] >> 2) & 0x3f)];
|
||||
out += digits[((binhash[pos] & 0x3) << 4)
|
||||
| (static_cast<int>(binhash[pos + 1] & 0xf0) >> 4)];
|
||||
|
|
@ -310,28 +300,26 @@ string VHashSha256::digestSymbol() {
|
|||
return out;
|
||||
}
|
||||
|
||||
void VHashSha256::selfTestOne(const string& data, const string& data2,
|
||||
const string& exp, const string& exp64) {
|
||||
VHashSha256 digest (data);
|
||||
if (data2!="") digest.insert(data2);
|
||||
void VHashSha256::selfTestOne(const string& data, const string& data2, const string& exp,
|
||||
const string& exp64) {
|
||||
VHashSha256 digest(data);
|
||||
if (data2 != "") digest.insert(data2);
|
||||
if (VL_UNCOVERABLE(digest.digestHex() != exp)) {
|
||||
std::cerr << "%Error: When hashing '"<<data+data2<<"'"<<endl // LCOV_EXCL_LINE
|
||||
<< " ... got="<<digest.digestHex()<<endl // LCOV_EXCL_LINE
|
||||
<< " ... exp="<<exp<<endl; // LCOV_EXCL_LINE
|
||||
std::cerr << "%Error: When hashing '" << data + data2 << "'" << endl // LCOV_EXCL_LINE
|
||||
<< " ... got=" << digest.digestHex() << endl // LCOV_EXCL_LINE
|
||||
<< " ... exp=" << exp << endl; // LCOV_EXCL_LINE
|
||||
}
|
||||
if (VL_UNCOVERABLE(digest.digestSymbol() != exp64)) {
|
||||
std::cerr << "%Error: When hashing '"<<data+data2<<"'"<<endl // LCOV_EXCL_LINE
|
||||
<< " ... got="<<digest.digestSymbol()<<endl // LCOV_EXCL_LINE
|
||||
<< " ... exp="<<exp64<<endl; // LCOV_EXCL_LINE
|
||||
std::cerr << "%Error: When hashing '" << data + data2 << "'" << endl // LCOV_EXCL_LINE
|
||||
<< " ... got=" << digest.digestSymbol() << endl // LCOV_EXCL_LINE
|
||||
<< " ... exp=" << exp64 << endl; // LCOV_EXCL_LINE
|
||||
}
|
||||
}
|
||||
|
||||
void VHashSha256::selfTest() {
|
||||
selfTestOne("", "",
|
||||
"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
|
||||
selfTestOne("", "", "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
|
||||
"47DEQpj8HBSaABTImWA5JCeuQeRkm5NMpJWZG3hS");
|
||||
selfTestOne("a", "",
|
||||
"ca978112ca1bbdcafac231b39a23dc4da786eff8147c4e72b9807785afee48bb",
|
||||
selfTestOne("a", "", "ca978112ca1bbdcafac231b39a23dc4da786eff8147c4e72b9807785afee48bb",
|
||||
"ypeBEsobvcr6wjGzmiPcTaeG7BgUfE5yuYB3haBu");
|
||||
selfTestOne("The quick brown fox jumps over the lazy dog", "",
|
||||
"d7a8fbb307d7809469ca9abcb0082e4f8d5651e46d3cdb762d02d0bf37c9e592",
|
||||
|
|
@ -351,14 +339,14 @@ void VHashSha256::selfTest() {
|
|||
// VName
|
||||
|
||||
string VName::hashedName() {
|
||||
if (m_name=="") return "";
|
||||
if (m_hashed!="") return m_hashed; // Memoized
|
||||
if (s_maxLength==0 || m_name.length() < s_maxLength) {
|
||||
if (m_name == "") return "";
|
||||
if (m_hashed != "") return m_hashed; // Memoized
|
||||
if (s_maxLength == 0 || m_name.length() < s_maxLength) {
|
||||
m_hashed = m_name;
|
||||
return m_hashed;
|
||||
} else {
|
||||
VHashSha256 hash(m_name);
|
||||
string suffix = "__Vhsh"+hash.digestSymbol();
|
||||
string suffix = "__Vhsh" + hash.digestSymbol();
|
||||
if (s_minLength < s_maxLength) {
|
||||
m_hashed = m_name.substr(0, s_minLength) + suffix;
|
||||
} else {
|
||||
|
|
@ -389,9 +377,9 @@ VSpellCheck::EditDistance VSpellCheck::editDistance(const string& s, const strin
|
|||
for (size_t i = 0; i < tLen; i++) {
|
||||
s_v_next[0] = i + 1;
|
||||
for (size_t j = 0; j < sLen; j++) {
|
||||
EditDistance cost =(s[j] == t[i] ? 0 : 1);
|
||||
EditDistance deletion = s_v_next[j] + 1;
|
||||
EditDistance insertion = s_v_one_ago[j + 1] + 1;
|
||||
EditDistance cost = (s[j] == t[i] ? 0 : 1);
|
||||
EditDistance deletion = s_v_next[j] + 1;
|
||||
EditDistance insertion = s_v_one_ago[j + 1] + 1;
|
||||
EditDistance substitution = s_v_one_ago[j] + cost;
|
||||
EditDistance cheapest = std::min(deletion, insertion);
|
||||
cheapest = std::min(cheapest, substitution);
|
||||
|
|
@ -420,13 +408,11 @@ VSpellCheck::EditDistance VSpellCheck::cutoffDistance(size_t goal_len, size_t ca
|
|||
return (max_length + 2) / 3;
|
||||
}
|
||||
|
||||
string VSpellCheck::bestCandidateInfo(const string& goal,
|
||||
EditDistance& distancer) {
|
||||
string VSpellCheck::bestCandidateInfo(const string& goal, EditDistance& distancer) {
|
||||
string bestCandidate;
|
||||
size_t gLen = goal.length();
|
||||
distancer = LENGTH_LIMIT*10;
|
||||
for (Candidates::const_iterator it = m_candidates.begin();
|
||||
it != m_candidates.end(); ++it) {
|
||||
distancer = LENGTH_LIMIT * 10;
|
||||
for (Candidates::const_iterator it = m_candidates.begin(); it != m_candidates.end(); ++it) {
|
||||
const string candidate = *it;
|
||||
size_t cLen = candidate.length();
|
||||
|
||||
|
|
@ -438,8 +424,8 @@ string VSpellCheck::bestCandidateInfo(const string& goal,
|
|||
if (min_distance > cutoff) continue; // Short-circuit if already too bad
|
||||
|
||||
EditDistance dist = editDistance(goal, candidate);
|
||||
UINFO(9, "EditDistance dist="<<dist<<" cutoff="<<cutoff
|
||||
<<" goal="<<goal<<" candidate="<<candidate<<endl);
|
||||
UINFO(9, "EditDistance dist=" << dist << " cutoff=" << cutoff << " goal=" << goal
|
||||
<< " candidate=" << candidate << endl);
|
||||
if (dist < distancer && dist <= cutoff) {
|
||||
distancer = dist;
|
||||
bestCandidate = candidate;
|
||||
|
|
@ -451,8 +437,7 @@ string VSpellCheck::bestCandidateInfo(const string& goal,
|
|||
return bestCandidate;
|
||||
}
|
||||
|
||||
void VSpellCheck::selfTestDistanceOne(const string& a, const string& b,
|
||||
EditDistance expected) {
|
||||
void VSpellCheck::selfTestDistanceOne(const string& a, const string& b, EditDistance expected) {
|
||||
UASSERT_SELFTEST(EditDistance, editDistance(a, b), expected);
|
||||
UASSERT_SELFTEST(EditDistance, editDistance(b, a), expected);
|
||||
}
|
||||
|
|
@ -462,7 +447,7 @@ void VSpellCheck::selfTestSuggestOne(bool matches, const string& c, const string
|
|||
EditDistance gdist;
|
||||
VSpellCheck speller;
|
||||
speller.pushCandidate(c);
|
||||
string got = speller.bestCandidateInfo(goal, gdist/*ref*/);
|
||||
string got = speller.bestCandidateInfo(goal, gdist /*ref*/);
|
||||
if (matches) {
|
||||
UASSERT_SELFTEST(string, got, c);
|
||||
UASSERT_SELFTEST(EditDistance, gdist, dist);
|
||||
|
|
|
|||
|
|
@ -30,18 +30,30 @@
|
|||
// Global string-related functions
|
||||
|
||||
template <class T> std::string cvtToStr(const T& t) {
|
||||
std::ostringstream os; os<<t; return os.str();
|
||||
std::ostringstream os;
|
||||
os << t;
|
||||
return os.str();
|
||||
}
|
||||
template <class T> std::string cvtToHex(const T* tp) {
|
||||
std::ostringstream os; os<<static_cast<const void*>(tp); return os.str();
|
||||
std::ostringstream os;
|
||||
os << static_cast<const void*>(tp);
|
||||
return os.str();
|
||||
}
|
||||
|
||||
inline uint32_t cvtToHash(const void* vp) {
|
||||
// We can shove a 64 bit pointer into a 32 bit bucket
|
||||
// On 32-bit systems, lower is always 0, but who cares?
|
||||
union { const void* up; struct {uint32_t upper; uint32_t lower;} l;} u;
|
||||
u.l.upper = 0; u.l.lower = 0; u.up = vp;
|
||||
return u.l.upper^u.l.lower;
|
||||
union {
|
||||
const void* up;
|
||||
struct {
|
||||
uint32_t upper;
|
||||
uint32_t lower;
|
||||
} l;
|
||||
} u;
|
||||
u.l.upper = 0;
|
||||
u.l.lower = 0;
|
||||
u.up = vp;
|
||||
return u.l.upper ^ u.l.lower;
|
||||
}
|
||||
|
||||
inline string ucfirst(const string& text) {
|
||||
|
|
@ -55,6 +67,7 @@ inline string ucfirst(const string& text) {
|
|||
|
||||
class VString {
|
||||
static bool wildmatchi(const char* s, const char* p);
|
||||
|
||||
public:
|
||||
// METHODS (generic string utilities)
|
||||
// Return true if p with ? or *'s matches s
|
||||
|
|
@ -62,7 +75,7 @@ public:
|
|||
// Return true if p with ? or *'s matches s
|
||||
static bool wildmatch(const string& s, const string& p);
|
||||
// Return true if this is a wildcard string (contains * or ?)
|
||||
static bool isWildcard(const string &p);
|
||||
static bool isWildcard(const string& p);
|
||||
// Return {a}{dot}{b}, omitting dot if a or b are empty
|
||||
static string dot(const string& a, const string& dot, const string& b);
|
||||
// Convert string to lowercase (tolower)
|
||||
|
|
@ -88,14 +101,17 @@ class VHashSha256 {
|
|||
// Or improve to store 0-63 bytes of data between calls to input().
|
||||
|
||||
// MEMBERS
|
||||
uint32_t m_inthash[8]; // Intermediate hash, in host order
|
||||
string m_remainder; // Unhashed data
|
||||
bool m_final; // Finalized
|
||||
size_t m_totLength; // Total all-chunk length as needed by output digest
|
||||
uint32_t m_inthash[8]; // Intermediate hash, in host order
|
||||
string m_remainder; // Unhashed data
|
||||
bool m_final; // Finalized
|
||||
size_t m_totLength; // Total all-chunk length as needed by output digest
|
||||
public:
|
||||
// CONSTRUCTORS
|
||||
VHashSha256() { init(); }
|
||||
explicit VHashSha256(const string& data) { init(); insert(data); }
|
||||
explicit VHashSha256(const string& data) {
|
||||
init();
|
||||
insert(data);
|
||||
}
|
||||
~VHashSha256() {}
|
||||
|
||||
// METHODS
|
||||
|
|
@ -107,20 +123,26 @@ public:
|
|||
|
||||
// Inerting hash data
|
||||
void insert(const void* datap, size_t length); // Process data into the digest
|
||||
void insert(const string& data) { insert(data.data(), data.length()); } // Process data into the digest
|
||||
void insert(const string& data) {
|
||||
insert(data.data(), data.length());
|
||||
} // Process data into the digest
|
||||
void insert(uint64_t value) { insert(cvtToStr(value)); }
|
||||
|
||||
private:
|
||||
void init() {
|
||||
m_inthash[0] = 0x6a09e667; m_inthash[1] = 0xbb67ae85;
|
||||
m_inthash[2] = 0x3c6ef372; m_inthash[3] = 0xa54ff53a;
|
||||
m_inthash[4] = 0x510e527f; m_inthash[5] = 0x9b05688c;
|
||||
m_inthash[6] = 0x1f83d9ab; m_inthash[7] = 0x5be0cd19;
|
||||
m_inthash[0] = 0x6a09e667;
|
||||
m_inthash[1] = 0xbb67ae85;
|
||||
m_inthash[2] = 0x3c6ef372;
|
||||
m_inthash[3] = 0xa54ff53a;
|
||||
m_inthash[4] = 0x510e527f;
|
||||
m_inthash[5] = 0x9b05688c;
|
||||
m_inthash[6] = 0x1f83d9ab;
|
||||
m_inthash[7] = 0x5be0cd19;
|
||||
m_final = false;
|
||||
m_totLength = 0;
|
||||
}
|
||||
static void selfTestOne(const string& data, const string& data2,
|
||||
const string& exp, const string& exp64);
|
||||
static void selfTestOne(const string& data, const string& data2, const string& exp,
|
||||
const string& exp64);
|
||||
void finalize(); // Process remaining data
|
||||
};
|
||||
|
||||
|
|
@ -136,10 +158,14 @@ class VName {
|
|||
static size_t s_minLength; // Length to preserve if over maxLength
|
||||
public:
|
||||
// CONSTRUCTORS
|
||||
explicit VName(const string& name) : m_name(name) {}
|
||||
explicit VName(const string& name)
|
||||
: m_name(name) {}
|
||||
~VName() {}
|
||||
// METHODS
|
||||
void name(const string& name) { m_name = name; m_hashed = ""; }
|
||||
void name(const string& name) {
|
||||
m_name = name;
|
||||
m_hashed = "";
|
||||
}
|
||||
string name() const { return m_name; }
|
||||
string hashedName();
|
||||
// CONFIG STATIC METHODS
|
||||
|
|
@ -173,21 +199,24 @@ public:
|
|||
// Return candidate is closest to provided string, or "" for none
|
||||
string bestCandidate(const string& goal) {
|
||||
EditDistance dist;
|
||||
return bestCandidateInfo(goal, dist/*ref*/);
|
||||
return bestCandidateInfo(goal, dist /*ref*/);
|
||||
}
|
||||
// Return friendly message
|
||||
string bestCandidateMsg(const string& goal) {
|
||||
string candidate = bestCandidate(goal);
|
||||
if (candidate.empty()) return "";
|
||||
else return string("... Suggested alternative: '")+candidate+"'";
|
||||
if (candidate.empty()) {
|
||||
return "";
|
||||
} else {
|
||||
return string("... Suggested alternative: '") + candidate + "'";
|
||||
}
|
||||
}
|
||||
static void selfTest();
|
||||
|
||||
private:
|
||||
static EditDistance editDistance(const string& s, const string& t);
|
||||
static EditDistance cutoffDistance(size_t goal_len, size_t candidate_len);
|
||||
string bestCandidateInfo(const string& goal, EditDistance& distancer);
|
||||
static void selfTestDistanceOne(const string& a, const string& b,
|
||||
EditDistance expected);
|
||||
static void selfTestDistanceOne(const string& a, const string& b, EditDistance expected);
|
||||
static void selfTestSuggestOne(bool matches, const string& c, const string& goal,
|
||||
EditDistance dist);
|
||||
};
|
||||
|
|
|
|||
132
src/V3SymTable.h
132
src/V3SymTable.h
|
|
@ -42,15 +42,15 @@ typedef std::set<const VSymEnt*> VSymConstMap;
|
|||
class VSymEnt {
|
||||
// Symbol table that can have a "superior" table for resolving upper references
|
||||
// MEMBERS
|
||||
typedef std::multimap<string,VSymEnt*> IdNameMap;
|
||||
IdNameMap m_idNameMap; // Hash of variables by name
|
||||
AstNode* m_nodep; // Node that entry belongs to
|
||||
VSymEnt* m_fallbackp; // Table "above" this one in name scope, for fallback resolution
|
||||
VSymEnt* m_parentp; // Table that created this table, dot notation needed to resolve into it
|
||||
typedef std::multimap<string, VSymEnt*> IdNameMap;
|
||||
IdNameMap m_idNameMap; // Hash of variables by name
|
||||
AstNode* m_nodep; // Node that entry belongs to
|
||||
VSymEnt* m_fallbackp; // Table "above" this one in name scope, for fallback resolution
|
||||
VSymEnt* m_parentp; // Table that created this table, dot notation needed to resolve into it
|
||||
AstNodeModule* m_packagep; // Package node is in (for V3LinkDot, unused here)
|
||||
string m_symPrefix; // String to prefix symbols with (for V3LinkDot, unused here)
|
||||
bool m_exported; // Allow importing
|
||||
bool m_imported; // Was imported
|
||||
string m_symPrefix; // String to prefix symbols with (for V3LinkDot, unused here)
|
||||
bool m_exported; // Allow importing
|
||||
bool m_imported; // Was imported
|
||||
#ifdef VL_DEBUG
|
||||
static int debug() {
|
||||
static int level = -1;
|
||||
|
|
@ -61,32 +61,33 @@ class VSymEnt {
|
|||
static inline int debug() { return 0; } // NOT runtime, too hot of a function
|
||||
#endif
|
||||
public:
|
||||
|
||||
typedef IdNameMap::const_iterator const_iterator;
|
||||
const_iterator begin() const { return m_idNameMap.begin(); }
|
||||
const_iterator end() const { return m_idNameMap.end(); }
|
||||
|
||||
void dumpIterate(std::ostream& os, VSymConstMap& doneSymsr, const string& indent,
|
||||
int numLevels, const string& searchName) const {
|
||||
os<<indent<<"+ "<<std::left<<std::setw(30)
|
||||
<<(searchName==""?"\"\"":searchName)<<std::setw(0)<<std::right;
|
||||
os<<" se"<<cvtToHex(this)<<std::setw(0);
|
||||
os<<" fallb=se"<<cvtToHex(m_fallbackp);
|
||||
if (m_symPrefix!="") os<<" symPrefix="<<m_symPrefix;
|
||||
os<<" n="<<nodep();
|
||||
os<<endl;
|
||||
os << indent << "+ " << std::left << std::setw(30)
|
||||
<< (searchName == "" ? "\"\"" : searchName) << std::setw(0) << std::right;
|
||||
os << " se" << cvtToHex(this) << std::setw(0);
|
||||
os << " fallb=se" << cvtToHex(m_fallbackp);
|
||||
if (m_symPrefix != "") os << " symPrefix=" << m_symPrefix;
|
||||
os << " n=" << nodep();
|
||||
os << endl;
|
||||
if (doneSymsr.find(this) != doneSymsr.end()) {
|
||||
os<<indent<<"| ^ duplicate, so no children printed\n";
|
||||
os << indent << "| ^ duplicate, so no children printed\n";
|
||||
} else {
|
||||
doneSymsr.insert(this);
|
||||
for (IdNameMap::const_iterator it=m_idNameMap.begin(); it!=m_idNameMap.end(); ++it) {
|
||||
for (IdNameMap::const_iterator it = m_idNameMap.begin(); it != m_idNameMap.end();
|
||||
++it) {
|
||||
if (numLevels >= 1) {
|
||||
it->second->dumpIterate(os, doneSymsr, indent+"| ", numLevels-1, it->first);
|
||||
it->second->dumpIterate(os, doneSymsr, indent + "| ", numLevels - 1,
|
||||
it->first);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
void dump(std::ostream& os, const string& indent="", int numLevels=1) const {
|
||||
void dump(std::ostream& os, const string& indent = "", int numLevels = 1) const {
|
||||
VSymConstMap doneSyms;
|
||||
dumpIterate(os, doneSyms, indent, numLevels, "TOP");
|
||||
}
|
||||
|
|
@ -120,12 +121,13 @@ public:
|
|||
bool imported() const { return m_imported; }
|
||||
void imported(bool flag) { m_imported = flag; }
|
||||
void insert(const string& name, VSymEnt* entp) {
|
||||
UINFO(9, " SymInsert se"<<cvtToHex(this)
|
||||
<<" '"<<name<<"' se"<<cvtToHex(entp)<<" "<<entp->nodep()<<endl);
|
||||
UINFO(9, " SymInsert se" << cvtToHex(this) << " '" << name << "' se" << cvtToHex(entp)
|
||||
<< " " << entp->nodep() << endl);
|
||||
if (name != "" && m_idNameMap.find(name) != m_idNameMap.end()) {
|
||||
if (!V3Error::errorCount()) { // Else may have just reported warning
|
||||
if (debug()>=9 || V3Error::debugDefault()) dump(cout,"- err-dump: ", 1);
|
||||
entp->nodep()->v3fatalSrc("Inserting two symbols with same name: "<<name<<endl);
|
||||
if (debug() >= 9 || V3Error::debugDefault()) dump(cout, "- err-dump: ", 1);
|
||||
entp->nodep()->v3fatalSrc("Inserting two symbols with same name: " << name
|
||||
<< endl);
|
||||
}
|
||||
} else {
|
||||
m_idNameMap.insert(make_pair(name, entp));
|
||||
|
|
@ -133,9 +135,9 @@ public:
|
|||
}
|
||||
void reinsert(const string& name, VSymEnt* entp) {
|
||||
IdNameMap::iterator it = m_idNameMap.find(name);
|
||||
if (name!="" && it != m_idNameMap.end()) {
|
||||
UINFO(9, " SymReinsert se"<<cvtToHex(this)
|
||||
<<" '"<<name<<"' se"<<cvtToHex(entp)<<" "<<entp->nodep()<<endl);
|
||||
if (name != "" && it != m_idNameMap.end()) {
|
||||
UINFO(9, " SymReinsert se" << cvtToHex(this) << " '" << name << "' se"
|
||||
<< cvtToHex(entp) << " " << entp->nodep() << endl);
|
||||
it->second = entp; // Replace
|
||||
} else {
|
||||
insert(name, entp);
|
||||
|
|
@ -145,9 +147,12 @@ public:
|
|||
// Find identifier without looking upward through symbol hierarchy
|
||||
// First, scan this begin/end block or module for the name
|
||||
IdNameMap::const_iterator it = m_idNameMap.find(name);
|
||||
UINFO(9, " SymFind se"<<cvtToHex(this)<<" '"<<name
|
||||
<<"' -> "<<(it == m_idNameMap.end() ? "NONE"
|
||||
: "se"+cvtToHex(it->second)+" n="+cvtToHex(it->second->nodep()))<<endl);
|
||||
UINFO(9, " SymFind se"
|
||||
<< cvtToHex(this) << " '" << name << "' -> "
|
||||
<< (it == m_idNameMap.end()
|
||||
? "NONE"
|
||||
: "se" + cvtToHex(it->second) + " n=" + cvtToHex(it->second->nodep()))
|
||||
<< endl);
|
||||
if (it != m_idNameMap.end()) return (it->second);
|
||||
return NULL;
|
||||
}
|
||||
|
|
@ -161,8 +166,7 @@ public:
|
|||
}
|
||||
void candidateIdFlat(VSpellCheck* spellerp, const VNodeMatcher* matcherp) const {
|
||||
// Suggest alternative symbol candidates without looking upward through symbol hierarchy
|
||||
for (IdNameMap::const_iterator it = m_idNameMap.begin();
|
||||
it != m_idNameMap.end(); ++it) {
|
||||
for (IdNameMap::const_iterator it = m_idNameMap.begin(); it != m_idNameMap.end(); ++it) {
|
||||
const AstNode* itemp = it->second->nodep();
|
||||
if (itemp && (!matcherp || matcherp->nodeMatch(itemp))) {
|
||||
spellerp->pushCandidate(itemp->prettyName());
|
||||
|
|
@ -176,10 +180,10 @@ public:
|
|||
// Then suggest the upper begin/end block or module
|
||||
if (m_fallbackp) m_fallbackp->candidateIdFallback(spellerp, matcherp);
|
||||
}
|
||||
|
||||
private:
|
||||
void importOneSymbol(VSymGraph* graphp, const string& name, const VSymEnt* srcp) {
|
||||
if (srcp->exported()
|
||||
&& !findIdFlat(name)) { // Don't insert over existing entry
|
||||
if (srcp->exported() && !findIdFlat(name)) { // Don't insert over existing entry
|
||||
VSymEnt* symp = new VSymEnt(graphp, srcp);
|
||||
symp->exported(false); // Can't reimport an import without an export
|
||||
symp->imported(true);
|
||||
|
|
@ -193,14 +197,13 @@ private:
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
void importFromPackage(VSymGraph* graphp, const VSymEnt* srcp, const string& id_or_star) {
|
||||
// Import tokens from source symbol table into this symbol table
|
||||
if (id_or_star != "*") {
|
||||
IdNameMap::const_iterator it = srcp->m_idNameMap.find(id_or_star);
|
||||
if (it != srcp->m_idNameMap.end()) {
|
||||
importOneSymbol(graphp, it->first, it->second);
|
||||
}
|
||||
if (it != srcp->m_idNameMap.end()) importOneSymbol(graphp, it->first, it->second);
|
||||
} else {
|
||||
for (IdNameMap::const_iterator it = srcp->m_idNameMap.begin();
|
||||
it != srcp->m_idNameMap.end(); ++it) {
|
||||
|
|
@ -212,9 +215,7 @@ public:
|
|||
// Export tokens from source symbol table into this symbol table
|
||||
if (id_or_star != "*") {
|
||||
IdNameMap::const_iterator it = srcp->m_idNameMap.find(id_or_star);
|
||||
if (it != srcp->m_idNameMap.end()) {
|
||||
exportOneSymbol(graphp, it->first, it->second);
|
||||
}
|
||||
if (it != srcp->m_idNameMap.end()) exportOneSymbol(graphp, it->first, it->second);
|
||||
} else {
|
||||
for (IdNameMap::const_iterator it = srcp->m_idNameMap.begin();
|
||||
it != srcp->m_idNameMap.end(); ++it) {
|
||||
|
|
@ -224,14 +225,14 @@ public:
|
|||
}
|
||||
void exportStarStar(VSymGraph* graphp) {
|
||||
// Export *:*: Export all tokens from imported packages
|
||||
for (IdNameMap::const_iterator it=m_idNameMap.begin(); it!=m_idNameMap.end(); ++it) {
|
||||
for (IdNameMap::const_iterator it = m_idNameMap.begin(); it != m_idNameMap.end(); ++it) {
|
||||
VSymEnt* symp = it->second;
|
||||
if (!symp->exported()) symp->exported(true);
|
||||
}
|
||||
}
|
||||
void importFromIface(VSymGraph* graphp, const VSymEnt* srcp, bool onlyUnmodportable = false) {
|
||||
// Import interface tokens from source symbol table into this symbol table, recursively
|
||||
UINFO(9, " importIf se"<<cvtToHex(this)<<" from se"<<cvtToHex(srcp)<<endl);
|
||||
UINFO(9, " importIf se" << cvtToHex(this) << " from se" << cvtToHex(srcp) << endl);
|
||||
for (IdNameMap::const_iterator it = srcp->m_idNameMap.begin();
|
||||
it != srcp->m_idNameMap.end(); ++it) {
|
||||
const string& name = it->first;
|
||||
|
|
@ -245,20 +246,19 @@ public:
|
|||
}
|
||||
}
|
||||
}
|
||||
void cellErrorScopes(AstNode* lookp, string prettyName="") {
|
||||
if (prettyName=="") prettyName = lookp->prettyName();
|
||||
void cellErrorScopes(AstNode* lookp, string prettyName = "") {
|
||||
if (prettyName == "") prettyName = lookp->prettyName();
|
||||
string scopes;
|
||||
for (IdNameMap::iterator it = m_idNameMap.begin(); it!=m_idNameMap.end(); ++it) {
|
||||
for (IdNameMap::iterator it = m_idNameMap.begin(); it != m_idNameMap.end(); ++it) {
|
||||
AstNode* itemp = it->second->nodep();
|
||||
if (VN_IS(itemp, Cell)
|
||||
|| (VN_IS(itemp, Module) && VN_CAST(itemp, Module)->isTop())) {
|
||||
if (VN_IS(itemp, Cell) || (VN_IS(itemp, Module) && VN_CAST(itemp, Module)->isTop())) {
|
||||
if (scopes != "") scopes += ", ";
|
||||
scopes += AstNode::prettyName(it->first);
|
||||
}
|
||||
}
|
||||
if (scopes=="") scopes="<no cells found>";
|
||||
std::cerr<<V3Error::warnMore()<<"... Known scopes under '"<<prettyName<<"': "
|
||||
<<scopes<<endl;
|
||||
if (scopes == "") scopes = "<no cells found>";
|
||||
std::cerr << V3Error::warnMore() << "... Known scopes under '" << prettyName
|
||||
<< "': " << scopes << endl;
|
||||
if (debug()) dump(std::cerr, " KnownScope: ", 1);
|
||||
}
|
||||
};
|
||||
|
|
@ -272,43 +272,43 @@ class VSymGraph {
|
|||
typedef std::vector<VSymEnt*> SymStack;
|
||||
|
||||
// MEMBERS
|
||||
VSymEnt* m_symRootp; // Root symbol table
|
||||
SymStack m_symsp; // All symbol tables, to cleanup
|
||||
VSymEnt* m_symRootp; // Root symbol table
|
||||
SymStack m_symsp; // All symbol tables, to cleanup
|
||||
|
||||
// CONSTRUCTORS
|
||||
VL_UNCOPYABLE(VSymGraph);
|
||||
|
||||
public:
|
||||
explicit VSymGraph(AstNetlist* nodep) {
|
||||
m_symRootp = new VSymEnt(this, nodep);
|
||||
}
|
||||
explicit VSymGraph(AstNetlist* nodep) { m_symRootp = new VSymEnt(this, nodep); }
|
||||
~VSymGraph() {
|
||||
for (SymStack::iterator it = m_symsp.begin(); it != m_symsp.end(); ++it) {
|
||||
delete (*it);
|
||||
}
|
||||
for (SymStack::iterator it = m_symsp.begin(); it != m_symsp.end(); ++it) delete (*it);
|
||||
}
|
||||
|
||||
public:
|
||||
// METHODS
|
||||
VSymEnt* rootp() const { return m_symRootp; }
|
||||
// Debug
|
||||
void dump(std::ostream& os, const string& indent="") {
|
||||
void dump(std::ostream& os, const string& indent = "") {
|
||||
VSymConstMap doneSyms;
|
||||
os<<"SymEnt Dump:\n";
|
||||
os << "SymEnt Dump:\n";
|
||||
m_symRootp->dumpIterate(os, doneSyms, indent, 9999, "$root");
|
||||
bool first = true;
|
||||
for (SymStack::iterator it = m_symsp.begin(); it != m_symsp.end(); ++it) {
|
||||
if (doneSyms.find(*it) == doneSyms.end()) {
|
||||
if (first) { first=false; os<<"%%Warning: SymEnt Orphans:\n"; }
|
||||
if (first) {
|
||||
first = false;
|
||||
os << "%%Warning: SymEnt Orphans:\n";
|
||||
}
|
||||
(*it)->dumpIterate(os, doneSyms, indent, 9999, "Orphan");
|
||||
}
|
||||
}
|
||||
}
|
||||
void dumpFilePrefixed(const string& nameComment) {
|
||||
if (v3Global.opt.dumpTree()) {
|
||||
string filename = v3Global.debugFilename(nameComment)+".txt";
|
||||
UINFO(2,"Dumping "<<filename<<endl);
|
||||
const vl_unique_ptr<std::ofstream> logp (V3File::new_ofstream(filename));
|
||||
if (logp->fail()) v3fatal("Can't write "<<filename);
|
||||
string filename = v3Global.debugFilename(nameComment) + ".txt";
|
||||
UINFO(2, "Dumping " << filename << endl);
|
||||
const vl_unique_ptr<std::ofstream> logp(V3File::new_ofstream(filename));
|
||||
if (logp->fail()) v3fatal("Can't write " << filename);
|
||||
dump(*logp, "");
|
||||
}
|
||||
}
|
||||
|
|
@ -336,7 +336,7 @@ inline VSymEnt::VSymEnt(VSymGraph* graphp, AstNode* nodep)
|
|||
inline VSymEnt::VSymEnt(VSymGraph* graphp, const VSymEnt* symp)
|
||||
: m_nodep(symp->m_nodep) {
|
||||
m_fallbackp = symp->m_fallbackp;
|
||||
m_parentp = symp->m_parentp;
|
||||
m_parentp = symp->m_parentp;
|
||||
m_packagep = symp->m_packagep;
|
||||
m_exported = symp->m_exported;
|
||||
m_imported = symp->m_imported;
|
||||
|
|
|
|||
38
src/V3TSP.h
38
src/V3TSP.h
|
|
@ -24,30 +24,30 @@
|
|||
#include "V3Error.h"
|
||||
|
||||
namespace V3TSP {
|
||||
// Perform a "Traveling Salesman Problem" optimizing sort
|
||||
// on any type you like -- so long as inherits from TspStateBase.
|
||||
// Perform a "Traveling Salesman Problem" optimizing sort
|
||||
// on any type you like -- so long as inherits from TspStateBase.
|
||||
|
||||
class TspStateBase {
|
||||
public:
|
||||
// This is the cost function that the TSP sort will minimize.
|
||||
// All costs in V3TSP are int, chosen to match the type of
|
||||
// V3GraphEdge::weight() which will reflect each edge's cost.
|
||||
virtual int cost(const TspStateBase* otherp) const = 0;
|
||||
class TspStateBase {
|
||||
public:
|
||||
// This is the cost function that the TSP sort will minimize.
|
||||
// All costs in V3TSP are int, chosen to match the type of
|
||||
// V3GraphEdge::weight() which will reflect each edge's cost.
|
||||
virtual int cost(const TspStateBase* otherp) const = 0;
|
||||
|
||||
// This operator< must place a meaningless, arbitrary, but
|
||||
// stable order on all TspStateBase's. It's used only to
|
||||
// key maps so that iteration is stable, without relying
|
||||
// on pointer values that could lead to nondeterminism.
|
||||
virtual bool operator<(const TspStateBase& otherp) const = 0;
|
||||
};
|
||||
// This operator< must place a meaningless, arbitrary, but
|
||||
// stable order on all TspStateBase's. It's used only to
|
||||
// key maps so that iteration is stable, without relying
|
||||
// on pointer values that could lead to nondeterminism.
|
||||
virtual bool operator<(const TspStateBase& otherp) const = 0;
|
||||
};
|
||||
|
||||
typedef std::vector<const TspStateBase*> StateVec;
|
||||
typedef std::vector<const TspStateBase*> StateVec;
|
||||
|
||||
// Given an unsorted set of TspState's, sort them to minimize
|
||||
// the transition cost for walking the sorted list.
|
||||
void tspSort(const StateVec& states, StateVec* resultp);
|
||||
// Given an unsorted set of TspState's, sort them to minimize
|
||||
// the transition cost for walking the sorted list.
|
||||
void tspSort(const StateVec& states, StateVec* resultp);
|
||||
|
||||
void selfTest();
|
||||
void selfTest();
|
||||
} // namespace V3TSP
|
||||
|
||||
#endif // Guard
|
||||
|
|
|
|||
|
|
@ -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] ... ]
|
||||
|
||||
//============================================================================
|
||||
|
|
|
|||
264
src/V3Trace.cpp
264
src/V3Trace.cpp
|
|
@ -60,22 +60,24 @@
|
|||
// Graph vertexes
|
||||
|
||||
class TraceActivityVertex : public V3GraphVertex {
|
||||
AstNode* m_insertp; // Insert before this statement
|
||||
vlsint32_t m_activityCode;
|
||||
bool m_activityCodeValid;
|
||||
bool m_slow; // If always slow, we can use the same code
|
||||
AstNode* m_insertp; // Insert before this statement
|
||||
vlsint32_t m_activityCode;
|
||||
bool m_activityCodeValid;
|
||||
bool m_slow; // If always slow, we can use the same code
|
||||
public:
|
||||
enum { ACTIVITY_NEVER =((1UL<<31) - 1) };
|
||||
enum { ACTIVITY_ALWAYS=((1UL<<31) - 2) };
|
||||
enum { ACTIVITY_SLOW=0 };
|
||||
enum { ACTIVITY_NEVER = ((1UL << 31) - 1) };
|
||||
enum { ACTIVITY_ALWAYS = ((1UL << 31) - 2) };
|
||||
enum { ACTIVITY_SLOW = 0 };
|
||||
TraceActivityVertex(V3Graph* graphp, AstNode* nodep, bool slow)
|
||||
: V3GraphVertex(graphp), m_insertp(nodep) {
|
||||
: V3GraphVertex(graphp)
|
||||
, m_insertp(nodep) {
|
||||
m_activityCode = 0;
|
||||
m_activityCodeValid = false;
|
||||
m_slow = slow;
|
||||
}
|
||||
TraceActivityVertex(V3Graph* graphp, vlsint32_t code)
|
||||
: V3GraphVertex(graphp), m_insertp(NULL) {
|
||||
: V3GraphVertex(graphp)
|
||||
, m_insertp(NULL) {
|
||||
m_activityCode = code;
|
||||
m_activityCodeValid = true;
|
||||
m_slow = false;
|
||||
|
|
@ -87,24 +89,33 @@ public:
|
|||
return m_insertp;
|
||||
}
|
||||
virtual string name() const {
|
||||
if (activityAlways()) return "*ALWAYS*";
|
||||
else return (string(slow()?"*SLOW* ":""))+insertp()->name();
|
||||
if (activityAlways()) {
|
||||
return "*ALWAYS*";
|
||||
} else {
|
||||
return (string(slow() ? "*SLOW* " : "")) + insertp()->name();
|
||||
}
|
||||
}
|
||||
virtual string dotColor() const { return slow()?"yellowGreen":"green"; }
|
||||
virtual string dotColor() const { return slow() ? "yellowGreen" : "green"; }
|
||||
bool activityCodeValid() const { return m_activityCodeValid; }
|
||||
vlsint32_t activityCode() const { return m_activityCode; }
|
||||
bool activityAlways() const { return activityCode()==ACTIVITY_ALWAYS; }
|
||||
void activityCode(vlsint32_t code) { m_activityCode = code; m_activityCodeValid = true;}
|
||||
bool activityAlways() const { return activityCode() == ACTIVITY_ALWAYS; }
|
||||
void activityCode(vlsint32_t code) {
|
||||
m_activityCode = code;
|
||||
m_activityCodeValid = true;
|
||||
}
|
||||
bool slow() const { return m_slow; }
|
||||
void slow(bool flag) { if (!flag) m_slow = false; }
|
||||
void slow(bool flag) {
|
||||
if (!flag) m_slow = false;
|
||||
}
|
||||
};
|
||||
|
||||
class TraceCFuncVertex : public V3GraphVertex {
|
||||
AstCFunc* m_nodep;
|
||||
|
||||
public:
|
||||
TraceCFuncVertex(V3Graph* graphp, AstCFunc* nodep)
|
||||
: V3GraphVertex(graphp), m_nodep(nodep) {
|
||||
}
|
||||
: V3GraphVertex(graphp)
|
||||
, m_nodep(nodep) {}
|
||||
virtual ~TraceCFuncVertex() {}
|
||||
// ACCESSORS
|
||||
AstCFunc* nodep() const { return m_nodep; }
|
||||
|
|
@ -115,10 +126,14 @@ public:
|
|||
|
||||
class TraceTraceVertex : public V3GraphVertex {
|
||||
AstTraceInc* m_nodep; // TRACEINC this represents
|
||||
TraceTraceVertex* m_duplicatep; // NULL, or other vertex with the real code() that duplicates this one
|
||||
// NULL, or other vertex with the real code() that duplicates this one
|
||||
TraceTraceVertex* m_duplicatep;
|
||||
|
||||
public:
|
||||
TraceTraceVertex(V3Graph* graphp, AstTraceInc* nodep)
|
||||
: V3GraphVertex(graphp), m_nodep(nodep), m_duplicatep(NULL) {}
|
||||
: V3GraphVertex(graphp)
|
||||
, m_nodep(nodep)
|
||||
, m_duplicatep(NULL) {}
|
||||
virtual ~TraceTraceVertex() {}
|
||||
// ACCESSORS
|
||||
AstTraceInc* nodep() const { return m_nodep; }
|
||||
|
|
@ -127,17 +142,18 @@ public:
|
|||
virtual FileLine* fileline() const { return nodep()->fileline(); }
|
||||
TraceTraceVertex* duplicatep() const { return m_duplicatep; }
|
||||
void duplicatep(TraceTraceVertex* dupp) {
|
||||
UASSERT_OBJ(!duplicatep(), nodep(),
|
||||
"Assigning duplicatep() to already duplicated node");
|
||||
UASSERT_OBJ(!duplicatep(), nodep(), "Assigning duplicatep() to already duplicated node");
|
||||
m_duplicatep = dupp;
|
||||
}
|
||||
};
|
||||
|
||||
class TraceVarVertex : public V3GraphVertex {
|
||||
AstVarScope* m_nodep;
|
||||
AstVarScope* m_nodep;
|
||||
|
||||
public:
|
||||
TraceVarVertex(V3Graph* graphp, AstVarScope* nodep)
|
||||
: V3GraphVertex(graphp), m_nodep(nodep) {}
|
||||
: V3GraphVertex(graphp)
|
||||
, m_nodep(nodep) {}
|
||||
virtual ~TraceVarVertex() {}
|
||||
// ACCESSORS
|
||||
AstVarScope* nodep() const { return m_nodep; }
|
||||
|
|
@ -160,31 +176,31 @@ private:
|
|||
// AstVarScope::user1() // V3GraphVertex* for this node
|
||||
// AstCCall::user2() // bool; walked next list for other ccalls
|
||||
// Ast*::user3() // TraceActivityVertex* for this node
|
||||
AstUser1InUse m_inuser1;
|
||||
AstUser2InUse m_inuser2;
|
||||
AstUser3InUse m_inuser3;
|
||||
//AstUser4InUse In V3Hashed
|
||||
AstUser1InUse m_inuser1;
|
||||
AstUser2InUse m_inuser2;
|
||||
AstUser3InUse m_inuser3;
|
||||
// AstUser4InUse In V3Hashed
|
||||
|
||||
// STATE
|
||||
AstNodeModule* m_topModp; // Module to add variables to
|
||||
AstScope* m_highScopep; // Scope to add variables to
|
||||
AstCFunc* m_funcp; // C function adding to graph
|
||||
AstTraceInc* m_tracep; // Trace function adding to graph
|
||||
AstCFunc* m_initFuncp; // Trace function we add statements to
|
||||
AstCFunc* m_fullFuncp; // Trace function we add statements to
|
||||
AstCFunc* m_fullSubFuncp; // Trace function we add statements to (under full)
|
||||
int m_fullSubStmts; // Statements under function being built
|
||||
AstCFunc* m_chgFuncp; // Trace function we add statements to
|
||||
AstCFunc* m_chgSubFuncp; // Trace function we add statements to (under full)
|
||||
AstNode* m_chgSubParentp;// Which node has call to m_chgSubFuncp
|
||||
int m_chgSubStmts; // Statements under function being built
|
||||
AstVarScope* m_activityVscp; // Activity variable
|
||||
uint32_t m_activityNumber; // Count of fields in activity variable
|
||||
uint32_t m_code; // Trace ident code# being assigned
|
||||
V3Graph m_graph; // Var/CFunc tracking
|
||||
AstNodeModule* m_topModp; // Module to add variables to
|
||||
AstScope* m_highScopep; // Scope to add variables to
|
||||
AstCFunc* m_funcp; // C function adding to graph
|
||||
AstTraceInc* m_tracep; // Trace function adding to graph
|
||||
AstCFunc* m_initFuncp; // Trace function we add statements to
|
||||
AstCFunc* m_fullFuncp; // Trace function we add statements to
|
||||
AstCFunc* m_fullSubFuncp; // Trace function we add statements to (under full)
|
||||
int m_fullSubStmts; // Statements under function being built
|
||||
AstCFunc* m_chgFuncp; // Trace function we add statements to
|
||||
AstCFunc* m_chgSubFuncp; // Trace function we add statements to (under full)
|
||||
AstNode* m_chgSubParentp; // Which node has call to m_chgSubFuncp
|
||||
int m_chgSubStmts; // Statements under function being built
|
||||
AstVarScope* m_activityVscp; // Activity variable
|
||||
uint32_t m_activityNumber; // Count of fields in activity variable
|
||||
uint32_t m_code; // Trace ident code# being assigned
|
||||
V3Graph m_graph; // Var/CFunc tracking
|
||||
TraceActivityVertex* m_alwaysVtxp; // "Always trace" vertex
|
||||
bool m_finding; // Pass one of algorithm?
|
||||
int m_funcNum; // Function number being built
|
||||
bool m_finding; // Pass one of algorithm?
|
||||
int m_funcNum; // Function number being built
|
||||
|
||||
VDouble0 m_statChgSigs; // Statistic tracking
|
||||
VDouble0 m_statUniqSigs; // Statistic tracking
|
||||
|
|
@ -194,11 +210,11 @@ private:
|
|||
VL_DEBUG_FUNC; // Declare debug()
|
||||
|
||||
void detectDuplicates() {
|
||||
UINFO(9,"Finding duplicates\n");
|
||||
UINFO(9, "Finding duplicates\n");
|
||||
// Note uses user4
|
||||
V3Hashed hashed; // Duplicate code detection
|
||||
// Hash all of the values the traceIncs need
|
||||
for (V3GraphVertex* itp = m_graph.verticesBeginp(); itp; itp=itp->verticesNextp()) {
|
||||
for (V3GraphVertex* itp = m_graph.verticesBeginp(); itp; itp = itp->verticesNextp()) {
|
||||
if (TraceTraceVertex* vvertexp = dynamic_cast<TraceTraceVertex*>(itp)) {
|
||||
AstTraceInc* nodep = vvertexp->nodep();
|
||||
if (nodep->valuep()) {
|
||||
|
|
@ -206,8 +222,8 @@ private:
|
|||
"Trace duplicate back needs consistency,"
|
||||
" so we can map duplicates back to TRACEINCs");
|
||||
hashed.hash(nodep->valuep());
|
||||
UINFO(8, " Hashed "<<std::hex<<hashed.nodeHash(nodep->valuep())
|
||||
<<" "<<nodep<<endl);
|
||||
UINFO(8, " Hashed " << std::hex << hashed.nodeHash(nodep->valuep()) << " "
|
||||
<< nodep << endl);
|
||||
|
||||
// Just keep one node in the map and point all duplicates to this node
|
||||
if (hashed.findDuplicate(nodep->valuep()) == hashed.end()) {
|
||||
|
|
@ -217,7 +233,7 @@ private:
|
|||
}
|
||||
}
|
||||
// Find if there are any duplicates
|
||||
for (V3GraphVertex* itp = m_graph.verticesBeginp(); itp; itp=itp->verticesNextp()) {
|
||||
for (V3GraphVertex* itp = m_graph.verticesBeginp(); itp; itp = itp->verticesNextp()) {
|
||||
if (TraceTraceVertex* vvertexp = dynamic_cast<TraceTraceVertex*>(itp)) {
|
||||
AstTraceInc* nodep = vvertexp->nodep();
|
||||
if (nodep->valuep() && !vvertexp->duplicatep()) {
|
||||
|
|
@ -228,8 +244,8 @@ private:
|
|||
UASSERT_OBJ(dupincp, nodep, "Trace duplicate of wrong type");
|
||||
TraceTraceVertex* dupvertexp
|
||||
= dynamic_cast<TraceTraceVertex*>(dupincp->user1u().toGraphVertex());
|
||||
UINFO(8," Orig "<<nodep<<endl);
|
||||
UINFO(8," dup "<<dupincp<<endl);
|
||||
UINFO(8, " Orig " << nodep << endl);
|
||||
UINFO(8, " dup " << dupincp << endl);
|
||||
// Mark the hashed node as the original and our
|
||||
// iterating node as duplicated
|
||||
vvertexp->duplicatep(dupvertexp);
|
||||
|
|
@ -242,7 +258,7 @@ private:
|
|||
|
||||
void graphSimplify() {
|
||||
// Remove all variable nodes
|
||||
for (V3GraphVertex* nextp, *itp = m_graph.verticesBeginp(); itp; itp=nextp) {
|
||||
for (V3GraphVertex *nextp, *itp = m_graph.verticesBeginp(); itp; itp = nextp) {
|
||||
nextp = itp->verticesNextp();
|
||||
if (TraceVarVertex* vvertexp = dynamic_cast<TraceVarVertex*>(itp)) {
|
||||
vvertexp->rerouteEdges(&m_graph);
|
||||
|
|
@ -253,7 +269,7 @@ private:
|
|||
// We do this twice, as then we have fewer edges to multiply out in the below expansion.
|
||||
m_graph.removeRedundantEdges(&V3GraphEdge::followAlwaysTrue);
|
||||
// Remove all Cfunc nodes
|
||||
for (V3GraphVertex* nextp, *itp = m_graph.verticesBeginp(); itp; itp=nextp) {
|
||||
for (V3GraphVertex *nextp, *itp = m_graph.verticesBeginp(); itp; itp = nextp) {
|
||||
nextp = itp->verticesNextp();
|
||||
if (TraceCFuncVertex* vvertexp = dynamic_cast<TraceCFuncVertex*>(itp)) {
|
||||
vvertexp->rerouteEdges(&m_graph);
|
||||
|
|
@ -265,10 +281,10 @@ private:
|
|||
m_graph.removeRedundantEdges(&V3GraphEdge::followAlwaysTrue);
|
||||
|
||||
// If there are any edges from a always, keep only the always
|
||||
for (V3GraphVertex* itp = m_graph.verticesBeginp(); itp; itp=itp->verticesNextp()) {
|
||||
for (V3GraphVertex* itp = m_graph.verticesBeginp(); itp; itp = itp->verticesNextp()) {
|
||||
if (TraceTraceVertex* vvertexp = dynamic_cast<TraceTraceVertex*>(itp)) {
|
||||
V3GraphEdge* alwaysEdgep = NULL;
|
||||
for (V3GraphEdge* edgep = vvertexp->inBeginp(); edgep; edgep=edgep->inNextp()) {
|
||||
for (V3GraphEdge* edgep = vvertexp->inBeginp(); edgep; edgep = edgep->inNextp()) {
|
||||
TraceActivityVertex* actVtxp
|
||||
= dynamic_cast<TraceActivityVertex*>(edgep->fromp());
|
||||
UASSERT_OBJ(actVtxp, vvertexp->nodep(),
|
||||
|
|
@ -279,21 +295,19 @@ private:
|
|||
}
|
||||
}
|
||||
if (alwaysEdgep) {
|
||||
for (V3GraphEdge* nextp, *edgep = vvertexp->inBeginp(); edgep; edgep=nextp) {
|
||||
for (V3GraphEdge *nextp, *edgep = vvertexp->inBeginp(); edgep; edgep = nextp) {
|
||||
nextp = edgep->inNextp();
|
||||
if (edgep!=alwaysEdgep) edgep->unlinkDelete();
|
||||
if (edgep != alwaysEdgep) edgep->unlinkDelete();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Activity points with no outputs can be removed
|
||||
for (V3GraphVertex* nextp, *itp = m_graph.verticesBeginp(); itp; itp=nextp) {
|
||||
for (V3GraphVertex *nextp, *itp = m_graph.verticesBeginp(); itp; itp = nextp) {
|
||||
nextp = itp->verticesNextp();
|
||||
if (TraceActivityVertex* vvertexp = dynamic_cast<TraceActivityVertex*>(itp)) {
|
||||
if (!vvertexp->outBeginp()) {
|
||||
vvertexp->unlinkDelete(&m_graph);
|
||||
}
|
||||
if (!vvertexp->outBeginp()) { vvertexp->unlinkDelete(&m_graph); }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -301,7 +315,7 @@ private:
|
|||
void assignActivity() {
|
||||
// Select activity numbers and put into each CFunc vertex
|
||||
m_activityNumber = 1; // Note 0 indicates "slow"
|
||||
for (V3GraphVertex* itp = m_graph.verticesBeginp(); itp; itp=itp->verticesNextp()) {
|
||||
for (V3GraphVertex* itp = m_graph.verticesBeginp(); itp; itp = itp->verticesNextp()) {
|
||||
if (TraceActivityVertex* vvertexp = dynamic_cast<TraceActivityVertex*>(itp)) {
|
||||
if (!vvertexp->activityCodeValid()) {
|
||||
if (vvertexp->slow()) {
|
||||
|
|
@ -328,14 +342,11 @@ private:
|
|||
= new AstBasicDType(m_chgFuncp->fileline(), VFlagLogicPacked(), 1);
|
||||
v3Global.rootp()->typeTablep()->addTypesp(newScalarDtp);
|
||||
AstNodeDType* newArrDtp = new AstUnpackArrayDType(
|
||||
m_chgFuncp->fileline(),
|
||||
newScalarDtp,
|
||||
new AstRange(m_chgFuncp->fileline(),
|
||||
VNumRange(m_activityNumber-1, 0, false)));
|
||||
m_chgFuncp->fileline(), newScalarDtp,
|
||||
new AstRange(m_chgFuncp->fileline(), VNumRange(m_activityNumber - 1, 0, false)));
|
||||
v3Global.rootp()->typeTablep()->addTypesp(newArrDtp);
|
||||
newvarp = new AstVar(m_chgFuncp->fileline(),
|
||||
AstVarType::MODULETEMP,
|
||||
"__Vm_traceActivity", newArrDtp);
|
||||
newvarp = new AstVar(m_chgFuncp->fileline(), AstVarType::MODULETEMP,
|
||||
"__Vm_traceActivity", newArrDtp);
|
||||
} else {
|
||||
// For tighter code; round to next word point.
|
||||
int activityBits = VL_WORDS_I(m_activityNumber) * VL_EDATASIZE;
|
||||
|
|
@ -348,14 +359,14 @@ private:
|
|||
m_activityVscp = newvscp;
|
||||
|
||||
// Insert activity setter
|
||||
for (V3GraphVertex* itp = m_graph.verticesBeginp(); itp; itp=itp->verticesNextp()) {
|
||||
for (V3GraphVertex* itp = m_graph.verticesBeginp(); itp; itp = itp->verticesNextp()) {
|
||||
if (TraceActivityVertex* vvertexp = dynamic_cast<TraceActivityVertex*>(itp)) {
|
||||
if (!vvertexp->activityAlways()) {
|
||||
FileLine* fl = vvertexp->insertp()->fileline();
|
||||
uint32_t acode = vvertexp->activityCode();
|
||||
vvertexp->insertp()->addNextHere
|
||||
(new AstAssign(fl, selectActivity(fl, acode, true),
|
||||
new AstConst(fl, AstConst::LogicTrue())));
|
||||
vvertexp->insertp()->addNextHere(
|
||||
new AstAssign(fl, selectActivity(fl, acode, true),
|
||||
new AstConst(fl, AstConst::LogicTrue())));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -363,31 +374,29 @@ private:
|
|||
|
||||
AstNode* selectActivity(FileLine* flp, uint32_t acode, bool lvalue) {
|
||||
if (v3Global.opt.mtasks()) {
|
||||
return new AstArraySel(
|
||||
flp, new AstVarRef(flp, m_activityVscp, lvalue), acode);
|
||||
return new AstArraySel(flp, new AstVarRef(flp, m_activityVscp, lvalue), acode);
|
||||
} else {
|
||||
return new AstSel(
|
||||
flp, new AstVarRef(flp, m_activityVscp, lvalue), acode, 1);
|
||||
return new AstSel(flp, new AstVarRef(flp, m_activityVscp, lvalue), acode, 1);
|
||||
}
|
||||
}
|
||||
|
||||
AstCFunc* newCFunc(AstCFuncType type, const string& name, AstCFunc* basep) {
|
||||
AstCFunc* funcp = new AstCFunc(basep->fileline(), name, basep->scopep());
|
||||
funcp->slow(basep->slow());
|
||||
funcp->argTypes(EmitCBaseVisitor::symClassVar()
|
||||
+", "+v3Global.opt.traceClassBase()+"* vcdp, uint32_t code");
|
||||
funcp->argTypes(EmitCBaseVisitor::symClassVar() + ", " + v3Global.opt.traceClassBase()
|
||||
+ "* vcdp, uint32_t code");
|
||||
funcp->funcType(type);
|
||||
funcp->symProlog(true);
|
||||
basep->addNext(funcp);
|
||||
UINFO(5," Newfunc "<<funcp<<endl);
|
||||
UINFO(5, " Newfunc " << funcp << endl);
|
||||
return funcp;
|
||||
}
|
||||
AstCFunc* newCFuncSub(AstCFunc* basep, AstNode* callfromp) {
|
||||
string name = basep->name()+"__"+cvtToStr(++m_funcNum);
|
||||
string name = basep->name() + "__" + cvtToStr(++m_funcNum);
|
||||
AstCFunc* funcp = NULL;
|
||||
if (basep->funcType()==AstCFuncType::TRACE_FULL) {
|
||||
if (basep->funcType() == AstCFuncType::TRACE_FULL) {
|
||||
funcp = newCFunc(AstCFuncType::TRACE_FULL_SUB, name, basep);
|
||||
} else if (basep->funcType()==AstCFuncType::TRACE_CHANGE) {
|
||||
} else if (basep->funcType() == AstCFuncType::TRACE_CHANGE) {
|
||||
funcp = newCFunc(AstCFuncType::TRACE_CHANGE_SUB, name, basep);
|
||||
} else {
|
||||
basep->v3fatalSrc("Strange base function type");
|
||||
|
|
@ -404,8 +413,7 @@ private:
|
|||
return funcp;
|
||||
}
|
||||
void addToChgSub(AstNode* underp, AstNode* stmtsp) {
|
||||
if (!m_chgSubFuncp
|
||||
|| (m_chgSubParentp != underp)
|
||||
if (!m_chgSubFuncp || (m_chgSubParentp != underp)
|
||||
|| (m_chgSubStmts && v3Global.opt.outputSplitCTrace()
|
||||
&& m_chgSubStmts > v3Global.opt.outputSplitCTrace())) {
|
||||
m_chgSubFuncp = newCFuncSub(m_chgFuncp, underp);
|
||||
|
|
@ -418,26 +426,27 @@ private:
|
|||
|
||||
void putTracesIntoTree() {
|
||||
// Form a sorted list of the traces we are interested in
|
||||
UINFO(9,"Making trees\n");
|
||||
UINFO(9, "Making trees\n");
|
||||
|
||||
typedef std::set<uint32_t> ActCodeSet; // All activity numbers applying to a given trace
|
||||
typedef std::multimap<ActCodeSet,TraceTraceVertex*> TraceVec; // For activity set, what traces apply
|
||||
typedef std::multimap<ActCodeSet, TraceTraceVertex*>
|
||||
TraceVec; // For activity set, what traces apply
|
||||
TraceVec traces;
|
||||
|
||||
// Form sort structure
|
||||
// If a trace doesn't have activity, it's constant, and we don't
|
||||
// need to track changes on it.
|
||||
for (V3GraphVertex* itp = m_graph.verticesBeginp(); itp; itp=itp->verticesNextp()) {
|
||||
for (V3GraphVertex* itp = m_graph.verticesBeginp(); itp; itp = itp->verticesNextp()) {
|
||||
if (TraceTraceVertex* vvertexp = dynamic_cast<TraceTraceVertex*>(itp)) {
|
||||
ActCodeSet actset;
|
||||
UINFO(9," Add to sort: "<<vvertexp<<endl);
|
||||
if (debug()>=9) vvertexp->nodep()->dumpTree(cout, "- trnode: ");
|
||||
for (V3GraphEdge* edgep = vvertexp->inBeginp(); edgep; edgep=edgep->inNextp()) {
|
||||
UINFO(9, " Add to sort: " << vvertexp << endl);
|
||||
if (debug() >= 9) vvertexp->nodep()->dumpTree(cout, "- trnode: ");
|
||||
for (V3GraphEdge* edgep = vvertexp->inBeginp(); edgep; edgep = edgep->inNextp()) {
|
||||
TraceActivityVertex* cfvertexp
|
||||
= dynamic_cast<TraceActivityVertex*>(edgep->fromp());
|
||||
UASSERT_OBJ(cfvertexp, vvertexp->nodep(),
|
||||
"Should have been function pointing to this trace");
|
||||
UINFO(9," Activity: "<<cfvertexp<<endl);
|
||||
UINFO(9, " Activity: " << cfvertexp << endl);
|
||||
if (cfvertexp->activityAlways()) {
|
||||
// If code 0, we always trace; ignore other codes
|
||||
actset.clear();
|
||||
|
|
@ -464,10 +473,10 @@ private:
|
|||
// Put TRACEs back into the tree
|
||||
const ActCodeSet* lastactp = NULL;
|
||||
AstNode* ifnodep = NULL;
|
||||
for (TraceVec::iterator it = traces.begin(); it!=traces.end(); ++it) {
|
||||
for (TraceVec::iterator it = traces.begin(); it != traces.end(); ++it) {
|
||||
const ActCodeSet& actset = it->first;
|
||||
TraceTraceVertex* vvertexp = it->second;
|
||||
UINFO(9," Done sort: "<<vvertexp<<endl);
|
||||
UINFO(9, " Done sort: " << vvertexp << endl);
|
||||
bool needChg = true;
|
||||
if (actset.find(TraceActivityVertex::ACTIVITY_NEVER) != actset.end()) {
|
||||
// No activity needed; it's a constant value or only set in initial block
|
||||
|
|
@ -476,7 +485,8 @@ private:
|
|||
AstNode* addp = assignTraceCode(vvertexp, vvertexp->nodep(), needChg);
|
||||
if (addp) { // Else no activity or duplicate
|
||||
if (actset.find(TraceActivityVertex::ACTIVITY_NEVER) != actset.end()) {
|
||||
vvertexp->nodep()->v3fatalSrc("If never, needChg=0 and shouldn't need to add.");
|
||||
vvertexp->nodep()->v3fatalSrc(
|
||||
"If never, needChg=0 and shouldn't need to add.");
|
||||
} else if (actset.find(TraceActivityVertex::ACTIVITY_ALWAYS) != actset.end()) {
|
||||
// Must always set it; add to base of function
|
||||
addToChgSub(m_chgFuncp, addp);
|
||||
|
|
@ -487,12 +497,14 @@ private:
|
|||
// Build a new IF statement
|
||||
FileLine* fl = addp->fileline();
|
||||
AstNode* condp = NULL;
|
||||
for (ActCodeSet::const_iterator csit = actset.begin();
|
||||
csit != actset.end(); ++csit) {
|
||||
for (ActCodeSet::const_iterator csit = actset.begin(); csit != actset.end();
|
||||
++csit) {
|
||||
uint32_t acode = *csit;
|
||||
AstNode* selp = selectActivity(fl, acode, false);
|
||||
if (condp) condp = new AstOr(fl, condp, selp);
|
||||
else condp = selp;
|
||||
if (condp)
|
||||
condp = new AstOr(fl, condp, selp);
|
||||
else
|
||||
condp = selp;
|
||||
}
|
||||
AstIf* ifp = new AstIf(fl, condp, NULL, NULL);
|
||||
ifp->branchPred(VBranchPred::BP_UNLIKELY);
|
||||
|
|
@ -517,9 +529,9 @@ private:
|
|||
m_chgFuncp->addFinalsp(clrp);
|
||||
}
|
||||
} else {
|
||||
AstNode* clrp = new AstAssign(fl, new AstVarRef(fl, m_activityVscp, true),
|
||||
new AstConst(fl, AstConst::WidthedValue(),
|
||||
m_activityVscp->width(), 0));
|
||||
AstNode* clrp = new AstAssign(
|
||||
fl, new AstVarRef(fl, m_activityVscp, true),
|
||||
new AstConst(fl, AstConst::WidthedValue(), m_activityVscp->width(), 0));
|
||||
m_fullFuncp->addFinalsp(clrp->cloneTree(true));
|
||||
m_chgFuncp->addFinalsp(clrp);
|
||||
}
|
||||
|
|
@ -539,13 +551,13 @@ private:
|
|||
// Assign trace code, add to tree, return node for change tree or null
|
||||
// Look for identical copies
|
||||
uint32_t codePreassigned = 0;
|
||||
//if (debug()>=9) nodep->dumpTree(cout, "- assnnode: ");
|
||||
// if (debug()>=9) nodep->dumpTree(cout, "- assnnode: ");
|
||||
// Find non-duplicated node; note some nodep's maybe null, as they were deleted below
|
||||
TraceTraceVertex* dupvertexp = vvertexp;
|
||||
if (dupvertexp->duplicatep()) {
|
||||
dupvertexp = dupvertexp->duplicatep();
|
||||
UINFO(9," dupOf "<<cvtToHex(dupvertexp)<<" "<<cvtToHex(dupvertexp->nodep())
|
||||
<<" "<<dupvertexp<<endl);
|
||||
UINFO(9, " dupOf " << cvtToHex(dupvertexp) << " " << cvtToHex(dupvertexp->nodep())
|
||||
<< " " << dupvertexp << endl);
|
||||
UASSERT_OBJ(!dupvertexp->duplicatep(), dupvertexp->nodep(),
|
||||
"Original node was marked as a duplicate");
|
||||
}
|
||||
|
|
@ -558,9 +570,9 @@ private:
|
|||
} else {
|
||||
assignDeclCode(nodep->declp());
|
||||
}
|
||||
UINFO(8," Created code="<<nodep->declp()->code()
|
||||
<<" "<<(codePreassigned?"[PREASS]":"")
|
||||
<<" "<<(needChg?"[CHG]":"")<<" "<<nodep<<endl);
|
||||
UINFO(8, " Created code=" << nodep->declp()->code() << " "
|
||||
<< (codePreassigned ? "[PREASS]" : "") << " "
|
||||
<< (needChg ? "[CHG]" : "") << " " << nodep << endl);
|
||||
|
||||
AstNode* incAddp = NULL;
|
||||
if (!codePreassigned) {
|
||||
|
|
@ -627,9 +639,9 @@ private:
|
|||
detectDuplicates();
|
||||
|
||||
// Simplify it
|
||||
if (debug()>=6) m_graph.dumpDotFilePrefixed("trace_pre");
|
||||
if (debug() >= 6) m_graph.dumpDotFilePrefixed("trace_pre");
|
||||
graphSimplify();
|
||||
if (debug()>=6) m_graph.dumpDotFilePrefixed("trace_opt");
|
||||
if (debug() >= 6) m_graph.dumpDotFilePrefixed("trace_opt");
|
||||
|
||||
// Create new TRACEINCs
|
||||
assignActivity();
|
||||
|
|
@ -646,15 +658,15 @@ private:
|
|||
iterateChildren(nodep);
|
||||
}
|
||||
virtual void visit(AstCCall* nodep) VL_OVERRIDE {
|
||||
UINFO(8," CCALL "<<nodep<<endl);
|
||||
UINFO(8, " CCALL " << nodep << endl);
|
||||
if (!m_finding && !nodep->user2()) {
|
||||
// See if there are other calls in same statement list;
|
||||
// If so, all funcs might share the same activity code
|
||||
TraceActivityVertex* activityVtxp = getActivityVertexp(nodep, nodep->funcp()->slow());
|
||||
for (AstNode* nextp=nodep; nextp; nextp=nextp->nextp()) {
|
||||
for (AstNode* nextp = nodep; nextp; nextp = nextp->nextp()) {
|
||||
if (AstCCall* ccallp = VN_CAST(nextp, CCall)) {
|
||||
ccallp->user2(true); // Processed
|
||||
UINFO(8," SubCCALL "<<ccallp<<endl);
|
||||
UINFO(8, " SubCCALL " << ccallp << endl);
|
||||
V3GraphVertex* ccallFuncVtxp = getCFuncVertexp(ccallp->funcp());
|
||||
activityVtxp->slow(ccallp->funcp()->slow());
|
||||
new V3GraphEdge(&m_graph, activityVtxp, ccallFuncVtxp, 1);
|
||||
|
|
@ -664,7 +676,7 @@ private:
|
|||
iterateChildren(nodep);
|
||||
}
|
||||
virtual void visit(AstCFunc* nodep) VL_OVERRIDE {
|
||||
UINFO(8," CFUNC "<<nodep<<endl);
|
||||
UINFO(8, " CFUNC " << nodep << endl);
|
||||
if (nodep->funcType() == AstCFuncType::TRACE_INIT) {
|
||||
m_initFuncp = nodep;
|
||||
} else if (nodep->funcType() == AstCFuncType::TRACE_FULL) {
|
||||
|
|
@ -673,12 +685,13 @@ private:
|
|||
m_chgFuncp = nodep;
|
||||
}
|
||||
V3GraphVertex* funcVtxp = getCFuncVertexp(nodep);
|
||||
if (!m_finding) { // If public, we need a unique activity code to allow for sets directly in this func
|
||||
if (nodep->funcPublic() || nodep->dpiExport()
|
||||
|| nodep == v3Global.rootp()->evalp()) {
|
||||
if (!m_finding) { // If public, we need a unique activity code to allow for sets directly
|
||||
// in this func
|
||||
if (nodep->funcPublic() || nodep->dpiExport() || nodep == v3Global.rootp()->evalp()) {
|
||||
// Need a non-null place to remember to later add a statement; make one
|
||||
if (!nodep->stmtsp()) nodep->addStmtsp(
|
||||
new AstComment(nodep->fileline(), "Tracing activity check", true));
|
||||
if (!nodep->stmtsp())
|
||||
nodep->addStmtsp(
|
||||
new AstComment(nodep->fileline(), "Tracing activity check", true));
|
||||
V3GraphVertex* activityVtxp = getActivityVertexp(nodep->stmtsp(), nodep->slow());
|
||||
new V3GraphEdge(&m_graph, activityVtxp, funcVtxp, 1);
|
||||
}
|
||||
|
|
@ -688,7 +701,7 @@ private:
|
|||
m_funcp = NULL;
|
||||
}
|
||||
virtual void visit(AstTraceInc* nodep) VL_OVERRIDE {
|
||||
UINFO(8," TRACE "<<nodep<<endl);
|
||||
UINFO(8, " TRACE " << nodep << endl);
|
||||
UASSERT_OBJ(!m_finding, nodep, "Traces should have been removed in prev step.");
|
||||
nodep->unlinkFrBack();
|
||||
|
||||
|
|
@ -715,8 +728,7 @@ private:
|
|||
|| nodep->varp()->isSigPublic()) { // Or ones user can change
|
||||
new V3GraphEdge(&m_graph, m_alwaysVtxp, traceVtxp, 1);
|
||||
}
|
||||
}
|
||||
else if (m_funcp && m_finding && nodep->lvalue()) {
|
||||
} else if (m_funcp && m_finding && nodep->lvalue()) {
|
||||
UASSERT_OBJ(nodep->varScopep(), nodep, "No var scope?");
|
||||
V3GraphVertex* funcVtxp = getCFuncVertexp(m_funcp);
|
||||
V3GraphVertex* varVtxp = nodep->varScopep()->user1u().toGraphVertex();
|
||||
|
|
@ -762,9 +774,7 @@ public:
|
|||
// Trace class functions
|
||||
|
||||
void V3Trace::traceAll(AstNetlist* nodep) {
|
||||
UINFO(2,__FUNCTION__<<": "<<endl);
|
||||
{
|
||||
TraceVisitor visitor(nodep);
|
||||
} // Destruct before checking
|
||||
UINFO(2, __FUNCTION__ << ": " << endl);
|
||||
{ TraceVisitor visitor(nodep); } // Destruct before checking
|
||||
V3Global::dumpCheckGlobalTree("trace", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -38,20 +38,20 @@ private:
|
|||
// NODE STATE
|
||||
|
||||
// STATE
|
||||
AstScope* m_scopetopp; // Current top scope
|
||||
AstCFunc* m_initFuncp; // Trace function being built
|
||||
AstCFunc* m_initSubFuncp; // Trace function being built (under m_init)
|
||||
int m_initSubStmts; // Number of statements in function
|
||||
AstCFunc* m_fullFuncp; // Trace function being built
|
||||
AstCFunc* m_chgFuncp; // Trace function being built
|
||||
int m_funcNum; // Function number being built
|
||||
AstVarScope* m_traVscp; // Signal being trace constructed
|
||||
AstNode* m_traValuep; // Signal being traced's value to trace in it
|
||||
string m_traShowname; // Signal being traced's component name
|
||||
bool m_interface; // Currently tracing an interface
|
||||
AstScope* m_scopetopp; // Current top scope
|
||||
AstCFunc* m_initFuncp; // Trace function being built
|
||||
AstCFunc* m_initSubFuncp; // Trace function being built (under m_init)
|
||||
int m_initSubStmts; // Number of statements in function
|
||||
AstCFunc* m_fullFuncp; // Trace function being built
|
||||
AstCFunc* m_chgFuncp; // Trace function being built
|
||||
int m_funcNum; // Function number being built
|
||||
AstVarScope* m_traVscp; // Signal being trace constructed
|
||||
AstNode* m_traValuep; // Signal being traced's value to trace in it
|
||||
string m_traShowname; // Signal being traced's component name
|
||||
bool m_interface; // Currently tracing an interface
|
||||
|
||||
VDouble0 m_statSigs; // Statistic tracking
|
||||
VDouble0 m_statIgnSigs; // Statistic tracking
|
||||
VDouble0 m_statSigs; // Statistic tracking
|
||||
VDouble0 m_statIgnSigs; // Statistic tracking
|
||||
|
||||
// METHODS
|
||||
VL_DEBUG_FUNC; // Declare debug()
|
||||
|
|
@ -62,16 +62,12 @@ private:
|
|||
AstVar* varp = nodep->varp();
|
||||
if (!varp->isTrace()) {
|
||||
return "Verilator trace_off";
|
||||
}
|
||||
else if (!nodep->isTrace()) {
|
||||
} else if (!nodep->isTrace()) {
|
||||
return "Verilator cell trace_off";
|
||||
}
|
||||
else if (!v3Global.opt.traceUnderscore()) {
|
||||
} else if (!v3Global.opt.traceUnderscore()) {
|
||||
string prettyName = varp->prettyName();
|
||||
if (!prettyName.empty() && prettyName[0] == '_')
|
||||
return "Leading underscore";
|
||||
if (prettyName.find("._") != string::npos)
|
||||
return "Inlined leading underscore";
|
||||
if (!prettyName.empty() && prettyName[0] == '_') return "Leading underscore";
|
||||
if (prettyName.find("._") != string::npos) return "Inlined leading underscore";
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
|
@ -79,14 +75,14 @@ private:
|
|||
AstCFunc* newCFunc(AstCFuncType type, const string& name, bool slow) {
|
||||
AstCFunc* funcp = new AstCFunc(m_scopetopp->fileline(), name, m_scopetopp);
|
||||
funcp->slow(slow);
|
||||
string argTypes(EmitCBaseVisitor::symClassVar()+", "+v3Global.opt.traceClassBase()
|
||||
+"* vcdp, uint32_t code");
|
||||
string argTypes(EmitCBaseVisitor::symClassVar() + ", " + v3Global.opt.traceClassBase()
|
||||
+ "* vcdp, uint32_t code");
|
||||
if (m_interface) argTypes += ", const char* scopep";
|
||||
funcp->argTypes(argTypes);
|
||||
funcp->funcType(type);
|
||||
funcp->symProlog(true);
|
||||
m_scopetopp->addActivep(funcp);
|
||||
UINFO(5," Newfunc "<<funcp<<endl);
|
||||
UINFO(5, " Newfunc " << funcp << endl);
|
||||
return funcp;
|
||||
}
|
||||
void callCFuncSub(AstCFunc* basep, AstCFunc* funcp, AstIntfRef* irp) {
|
||||
|
|
@ -96,10 +92,10 @@ private:
|
|||
basep->addStmtsp(callp);
|
||||
}
|
||||
AstCFunc* newCFuncSub(AstCFunc* basep) {
|
||||
string name = basep->name()+"__"+cvtToStr(++m_funcNum);
|
||||
string name = basep->name() + "__" + cvtToStr(++m_funcNum);
|
||||
AstCFunc* funcp = NULL;
|
||||
if (basep->funcType()==AstCFuncType::TRACE_INIT
|
||||
|| basep->funcType()==AstCFuncType::TRACE_INIT_SUB) {
|
||||
if (basep->funcType() == AstCFuncType::TRACE_INIT
|
||||
|| basep->funcType() == AstCFuncType::TRACE_INIT_SUB) {
|
||||
funcp = newCFunc(AstCFuncType::TRACE_INIT_SUB, name, basep->slow());
|
||||
} else {
|
||||
basep->v3fatalSrc("Strange base function type");
|
||||
|
|
@ -108,15 +104,19 @@ private:
|
|||
return funcp;
|
||||
}
|
||||
void addTraceDecl(const VNumRange& arrayRange,
|
||||
int widthOverride) { // If !=0, is packed struct/array where basicp size misreflects one element
|
||||
int widthOverride) { // If !=0, is packed struct/array where basicp size
|
||||
// misreflects one element
|
||||
VNumRange bitRange;
|
||||
AstBasicDType* bdtypep = m_traValuep->dtypep()->basicp();
|
||||
if (widthOverride) bitRange = VNumRange(widthOverride-1, 0, false);
|
||||
else if (bdtypep) bitRange = bdtypep->nrange();
|
||||
AstTraceDecl* declp = new AstTraceDecl(m_traVscp->fileline(), m_traShowname,
|
||||
m_traVscp->varp(), m_traValuep,
|
||||
bitRange, arrayRange, m_interface);
|
||||
UINFO(9,"Decl "<<declp<<endl);
|
||||
if (widthOverride) {
|
||||
bitRange = VNumRange(widthOverride - 1, 0, false);
|
||||
} else if (bdtypep) {
|
||||
bitRange = bdtypep->nrange();
|
||||
}
|
||||
AstTraceDecl* declp
|
||||
= new AstTraceDecl(m_traVscp->fileline(), m_traShowname, m_traVscp->varp(),
|
||||
m_traValuep, bitRange, arrayRange, m_interface);
|
||||
UINFO(9, "Decl " << declp << endl);
|
||||
|
||||
if (!m_interface && v3Global.opt.outputSplitCTrace()
|
||||
&& m_initSubStmts > v3Global.opt.outputSplitCTrace()) {
|
||||
|
|
@ -127,15 +127,14 @@ private:
|
|||
m_initSubFuncp->addStmtsp(declp);
|
||||
m_initSubStmts += EmitCBaseCounterVisitor(declp).count();
|
||||
|
||||
m_chgFuncp->addStmtsp(new AstTraceInc(m_traVscp->fileline(),
|
||||
declp, m_traValuep->cloneTree(true)));
|
||||
m_chgFuncp->addStmtsp(
|
||||
new AstTraceInc(m_traVscp->fileline(), declp, m_traValuep->cloneTree(true)));
|
||||
// The full version will get constructed in V3Trace
|
||||
}
|
||||
void addIgnore(const char* why) {
|
||||
++m_statIgnSigs;
|
||||
m_initSubFuncp->addStmtsp(
|
||||
new AstComment(m_traVscp->fileline(),
|
||||
"Tracing: "+m_traShowname+" // Ignored: "+why, true));
|
||||
m_initSubFuncp->addStmtsp(new AstComment(
|
||||
m_traVscp->fileline(), "Tracing: " + m_traShowname + " // Ignored: " + why, true));
|
||||
}
|
||||
|
||||
// VISITORS
|
||||
|
|
@ -144,7 +143,7 @@ private:
|
|||
// Make containers for TRACEDECLs first
|
||||
m_initFuncp = newCFunc(AstCFuncType::TRACE_INIT, "traceInitThis", true);
|
||||
m_fullFuncp = newCFunc(AstCFuncType::TRACE_FULL, "traceFullThis", true);
|
||||
m_chgFuncp = newCFunc(AstCFuncType::TRACE_CHANGE, "traceChgThis", false);
|
||||
m_chgFuncp = newCFunc(AstCFuncType::TRACE_CHANGE, "traceChgThis", false);
|
||||
//
|
||||
m_initSubFuncp = newCFuncSub(m_initFuncp);
|
||||
// And find variables
|
||||
|
|
@ -162,7 +161,7 @@ private:
|
|||
size_t lastDot = scopeName.find_last_of('.');
|
||||
UASSERT_OBJ(lastDot != string::npos, nodep,
|
||||
"Expected an interface scope name to have at least one dot");
|
||||
scopeName = scopeName.substr(0, lastDot+1);
|
||||
scopeName = scopeName.substr(0, lastDot + 1);
|
||||
size_t scopeLen = scopeName.length();
|
||||
|
||||
AstIntfRef* nextIrp = cellp->intfRefp();
|
||||
|
|
@ -195,9 +194,8 @@ private:
|
|||
// Generally this equation doesn't need updating, instead use
|
||||
// varp->isTrace() and/or vscIgnoreTrace.
|
||||
if ((!nodep->varp()->isTemp() || nodep->varp()->isTrace())
|
||||
&& !nodep->varp()->isClassMember()
|
||||
&& !nodep->varp()->isFuncLocal()) {
|
||||
UINFO(5, " vsc "<<nodep<<endl);
|
||||
&& !nodep->varp()->isClassMember() && !nodep->varp()->isFuncLocal()) {
|
||||
UINFO(5, " vsc " << nodep << endl);
|
||||
AstVar* varp = nodep->varp();
|
||||
AstScope* scopep = nodep->scopep();
|
||||
// Compute show name
|
||||
|
|
@ -217,8 +215,11 @@ private:
|
|||
addIgnore(vscIgnoreTrace(nodep));
|
||||
} else {
|
||||
++m_statSigs;
|
||||
if (nodep->valuep()) m_traValuep = nodep->valuep()->cloneTree(true);
|
||||
else m_traValuep = new AstVarRef(nodep->fileline(), nodep, false);
|
||||
if (nodep->valuep()) {
|
||||
m_traValuep = nodep->valuep()->cloneTree(true);
|
||||
} else {
|
||||
m_traValuep = new AstVarRef(nodep->fileline(), nodep, false);
|
||||
}
|
||||
{
|
||||
// Recurse into data type of the signal; the visitors will call addTraceDecl()
|
||||
iterate(varp->dtypep()->skipRefToEnump());
|
||||
|
|
@ -233,22 +234,20 @@ private:
|
|||
}
|
||||
// VISITORS - Data types when tracing
|
||||
virtual void visit(AstConstDType* nodep) VL_OVERRIDE {
|
||||
if (m_traVscp) {
|
||||
iterate(nodep->subDTypep()->skipRefToEnump());
|
||||
}
|
||||
if (m_traVscp) iterate(nodep->subDTypep()->skipRefToEnump());
|
||||
}
|
||||
virtual void visit(AstRefDType* nodep) VL_OVERRIDE {
|
||||
if (m_traVscp) {
|
||||
iterate(nodep->subDTypep()->skipRefToEnump());
|
||||
}
|
||||
if (m_traVscp) iterate(nodep->subDTypep()->skipRefToEnump());
|
||||
}
|
||||
virtual void visit(AstUnpackArrayDType* nodep) VL_OVERRIDE {
|
||||
// Note more specific dtypes above
|
||||
if (m_traVscp) {
|
||||
if (static_cast<int>(nodep->arrayUnpackedElements()) > v3Global.opt.traceMaxArray()) {
|
||||
addIgnore("Wide memory > --trace-max-array ents");
|
||||
} else if (VN_IS(nodep->subDTypep()->skipRefToEnump(), BasicDType) // Nothing lower than this array
|
||||
&& m_traVscp->dtypep()->skipRefToEnump() == nodep) { // Nothing above this array
|
||||
} else if (VN_IS(nodep->subDTypep()->skipRefToEnump(),
|
||||
BasicDType) // Nothing lower than this array
|
||||
&& m_traVscp->dtypep()->skipRefToEnump()
|
||||
== nodep) { // Nothing above this array
|
||||
// Simple 1-D array, use existing V3EmitC runtime loop rather than unrolling
|
||||
// This will put "(index)" at end of signal name for us
|
||||
if (m_traVscp->dtypep()->skipRefToEnump()->isString()) {
|
||||
|
|
@ -259,14 +258,13 @@ private:
|
|||
} else {
|
||||
// Unroll now, as have no other method to get right signal names
|
||||
AstNodeDType* subtypep = nodep->subDTypep()->skipRefToEnump();
|
||||
for (int i=nodep->lsb(); i<=nodep->msb(); ++i) {
|
||||
for (int i = nodep->lsb(); i <= nodep->msb(); ++i) {
|
||||
string oldShowname = m_traShowname;
|
||||
AstNode* oldValuep = m_traValuep;
|
||||
{
|
||||
m_traShowname += string("(")+cvtToStr(i)+string(")");
|
||||
m_traValuep = new AstArraySel(nodep->fileline(),
|
||||
m_traValuep->cloneTree(true),
|
||||
i - nodep->lsb());
|
||||
m_traShowname += string("(") + cvtToStr(i) + string(")");
|
||||
m_traValuep = new AstArraySel(
|
||||
nodep->fileline(), m_traValuep->cloneTree(true), i - nodep->lsb());
|
||||
|
||||
m_traValuep->dtypep(subtypep);
|
||||
iterate(subtypep);
|
||||
|
|
@ -287,13 +285,13 @@ private:
|
|||
addTraceDecl(VNumRange(), nodep->width());
|
||||
} else {
|
||||
AstNodeDType* subtypep = nodep->subDTypep()->skipRefToEnump();
|
||||
for (int i=nodep->lsb(); i<=nodep->msb(); ++i) {
|
||||
for (int i = nodep->lsb(); i <= nodep->msb(); ++i) {
|
||||
string oldShowname = m_traShowname;
|
||||
AstNode* oldValuep = m_traValuep;
|
||||
{
|
||||
m_traShowname += string("(")+cvtToStr(i)+string(")");
|
||||
m_traShowname += string("(") + cvtToStr(i) + string(")");
|
||||
m_traValuep = new AstSel(nodep->fileline(), m_traValuep->cloneTree(true),
|
||||
(i - nodep->lsb())*subtypep->width(),
|
||||
(i - nodep->lsb()) * subtypep->width(),
|
||||
subtypep->width());
|
||||
m_traValuep->dtypep(subtypep);
|
||||
iterate(subtypep);
|
||||
|
|
@ -316,17 +314,17 @@ private:
|
|||
if (!nodep->packed()) {
|
||||
addIgnore("Unsupported: Unpacked struct/union");
|
||||
} else {
|
||||
for (AstMemberDType* itemp = nodep->membersp();
|
||||
itemp; itemp=VN_CAST(itemp->nextp(), MemberDType)) {
|
||||
for (AstMemberDType* itemp = nodep->membersp(); itemp;
|
||||
itemp = VN_CAST(itemp->nextp(), MemberDType)) {
|
||||
AstNodeDType* subtypep = itemp->subDTypep()->skipRefToEnump();
|
||||
string oldShowname = m_traShowname;
|
||||
AstNode* oldValuep = m_traValuep;
|
||||
{
|
||||
m_traShowname += string(" ")+itemp->prettyName();
|
||||
m_traShowname += string(" ") + itemp->prettyName();
|
||||
if (VN_IS(nodep, StructDType)) {
|
||||
m_traValuep = new AstSel(nodep->fileline(),
|
||||
m_traValuep->cloneTree(true),
|
||||
itemp->lsb(), subtypep->width());
|
||||
m_traValuep
|
||||
= new AstSel(nodep->fileline(), m_traValuep->cloneTree(true),
|
||||
itemp->lsb(), subtypep->width());
|
||||
m_traValuep->dtypep(subtypep);
|
||||
iterate(subtypep);
|
||||
VL_DO_CLEAR(m_traValuep->deleteTree(), m_traValuep = NULL);
|
||||
|
|
@ -350,9 +348,7 @@ private:
|
|||
}
|
||||
}
|
||||
}
|
||||
virtual void visit(AstEnumDType* nodep) VL_OVERRIDE {
|
||||
iterate(nodep->skipRefp());
|
||||
}
|
||||
virtual void visit(AstEnumDType* nodep) VL_OVERRIDE { iterate(nodep->skipRefp()); }
|
||||
virtual void visit(AstNodeDType* nodep) VL_OVERRIDE {
|
||||
// Note more specific dtypes above
|
||||
if (!m_traVscp) return;
|
||||
|
|
@ -387,9 +383,7 @@ public:
|
|||
// Trace class functions
|
||||
|
||||
void V3TraceDecl::traceDeclAll(AstNetlist* nodep) {
|
||||
UINFO(2,__FUNCTION__<<": "<<endl);
|
||||
{
|
||||
TraceDeclVisitor visitor (nodep);
|
||||
} // Destruct before checking
|
||||
UINFO(2, __FUNCTION__ << ": " << endl);
|
||||
{ TraceDeclVisitor visitor(nodep); } // Destruct before checking
|
||||
V3Global::dumpCheckGlobalTree("tracedecl", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,9 +23,11 @@
|
|||
#include "V3Error.h"
|
||||
#include "V3Ast.h"
|
||||
|
||||
// clang-format off
|
||||
#ifndef _V3WIDTH_CPP_
|
||||
# error "V3WidthCommit for V3Width internal use only"
|
||||
#endif
|
||||
// clang-format on
|
||||
|
||||
//######################################################################
|
||||
|
||||
|
|
@ -55,9 +57,7 @@ public:
|
|||
// CONSTRUCTORS
|
||||
WidthRemoveVisitor() {}
|
||||
virtual ~WidthRemoveVisitor() {}
|
||||
AstNode* mainAcceptEdit(AstNode* nodep) {
|
||||
return iterateSubtreeReturnEdits(nodep);
|
||||
}
|
||||
AstNode* mainAcceptEdit(AstNode* nodep) { return iterateSubtreeReturnEdits(nodep); }
|
||||
};
|
||||
|
||||
//######################################################################
|
||||
|
|
@ -67,15 +67,14 @@ public:
|
|||
class WidthCommitVisitor : public AstNVisitor {
|
||||
// NODE STATE
|
||||
// AstVar::user1p -> bool, processed
|
||||
AstUser1InUse m_inuser1;
|
||||
AstUser1InUse m_inuser1;
|
||||
|
||||
public:
|
||||
// METHODS
|
||||
static AstConst* newIfConstCommitSize(AstConst* nodep) {
|
||||
if (((nodep->dtypep()->width() != nodep->num().width())
|
||||
|| !nodep->num().sized())
|
||||
if (((nodep->dtypep()->width() != nodep->num().width()) || !nodep->num().sized())
|
||||
&& !nodep->num().isString()) { // Need to force the number from unsized to sized
|
||||
V3Number num (nodep, nodep->dtypep()->width());
|
||||
V3Number num(nodep, nodep->dtypep()->width());
|
||||
num.opAssign(nodep->num());
|
||||
num.isSigned(nodep->isSigned());
|
||||
AstConst* newp = new AstConst(nodep->fileline(), num);
|
||||
|
|
@ -102,9 +101,12 @@ private:
|
|||
// Look for duplicate
|
||||
if (AstBasicDType* bdtypep = VN_CAST(nodep, BasicDType)) {
|
||||
AstBasicDType* newp = nodep->findInsertSameDType(bdtypep);
|
||||
if (newp != bdtypep && debug()>=9) {
|
||||
UINFO(9,"dtype replacement "); nodep->dumpSmall(cout);
|
||||
cout<<" ----> "; newp->dumpSmall(cout); cout<<endl;
|
||||
if (newp != bdtypep && debug() >= 9) {
|
||||
UINFO(9, "dtype replacement ");
|
||||
nodep->dumpSmall(cout);
|
||||
cout << " ----> ";
|
||||
newp->dumpSmall(cout);
|
||||
cout << endl;
|
||||
}
|
||||
return newp;
|
||||
}
|
||||
|
|
@ -116,16 +118,15 @@ private:
|
|||
iterate(nodep->dtypep()); // Do datatype first
|
||||
if (AstConst* newp = newIfConstCommitSize(nodep)) {
|
||||
nodep->replaceWith(newp);
|
||||
AstNode* oldp = nodep; nodep = newp;
|
||||
//if (debug()>4) oldp->dumpTree(cout, " fixConstSize_old: ");
|
||||
//if (debug()>4) newp->dumpTree(cout, " _new: ");
|
||||
AstNode* oldp = nodep;
|
||||
nodep = newp;
|
||||
// if (debug()>4) oldp->dumpTree(cout, " fixConstSize_old: ");
|
||||
// if (debug()>4) newp->dumpTree(cout, " _new: ");
|
||||
VL_DO_DANGLING(pushDeletep(oldp), oldp);
|
||||
}
|
||||
editDType(nodep);
|
||||
}
|
||||
virtual void visit(AstNodeDType* nodep) VL_OVERRIDE {
|
||||
visitIterateNodeDType(nodep);
|
||||
}
|
||||
virtual void visit(AstNodeDType* nodep) VL_OVERRIDE { visitIterateNodeDType(nodep); }
|
||||
virtual void visit(AstNodeUOrStructDType* nodep) VL_OVERRIDE {
|
||||
if (nodep->user1SetOnce()) return; // Process once
|
||||
visitIterateNodeDType(nodep);
|
||||
|
|
@ -158,6 +159,7 @@ private:
|
|||
iterateChildren(nodep);
|
||||
editDType(nodep);
|
||||
}
|
||||
|
||||
public:
|
||||
// CONSTRUCTORS
|
||||
explicit WidthCommitVisitor(AstNetlist* nodep) {
|
||||
|
|
|
|||
|
|
@ -47,9 +47,7 @@ private:
|
|||
v3fatal("Out of memory increasing buckets");
|
||||
}
|
||||
m_datap = newp;
|
||||
for (vluint64_t i = oldsize; i < m_dataSize; i += 64) {
|
||||
m_datap[i / 64] = 0;
|
||||
}
|
||||
for (vluint64_t i = oldsize; i < m_dataSize; i += 64) m_datap[i / 64] = 0;
|
||||
}
|
||||
|
||||
public:
|
||||
|
|
|
|||
|
|
@ -14,14 +14,16 @@
|
|||
//
|
||||
//*************************************************************************
|
||||
|
||||
// Cheat for speed and compile .cpp files into one object
|
||||
// clang-format off
|
||||
#include "config_build.h"
|
||||
#ifndef HAVE_CONFIG_BUILD
|
||||
# error "Something failed during ./configure as config_build.h is incomplete. Perhaps you used autoreconf, don't."
|
||||
#endif
|
||||
// clang-format on
|
||||
|
||||
#include "verilatedos.h"
|
||||
|
||||
// Cheat for speed and compile .cpp files into one object
|
||||
#define _V3ERROR_NO_GLOBAL_ 1
|
||||
#include "V3Error.cpp"
|
||||
#include "V3String.cpp"
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@ typedef std::set<string> VlStringSet;
|
|||
|
||||
class VlcOptions {
|
||||
// MEMBERS (general options)
|
||||
// clang-format off
|
||||
string m_annotateOut; // main switch: --annotate I<output_directory>
|
||||
bool m_annotateAll; // main switch: --annotate-all
|
||||
int m_annotateMin; // main switch: --annotate-min I<count>
|
||||
|
|
@ -41,6 +42,7 @@ class VlcOptions {
|
|||
bool m_rank; // main switch: --rank
|
||||
bool m_unlink; // main switch: --unlink
|
||||
string m_writeFile; // main switch: --write
|
||||
// clang-format on
|
||||
|
||||
private:
|
||||
// METHODS
|
||||
|
|
|
|||
|
|
@ -67,8 +67,7 @@ public:
|
|||
const string namestr = name();
|
||||
for (const char* cp = namestr.c_str(); *cp; ++cp) {
|
||||
if (*cp == '\001') {
|
||||
if (0 == strncmp(cp + 1, shortKey, shortLen)
|
||||
&& cp[shortLen + 1] == '\002') {
|
||||
if (0 == strncmp(cp + 1, shortKey, shortLen) && cp[shortLen + 1] == '\002') {
|
||||
cp += shortLen + 2; // Skip \001+short+\002
|
||||
const char* ep = cp;
|
||||
while (*ep && *ep != '\001') ++ep;
|
||||
|
|
@ -110,7 +109,8 @@ public:
|
|||
|
||||
public:
|
||||
// CONSTRUCTORS
|
||||
VlcPoints() : m_numPoints(0) {}
|
||||
VlcPoints()
|
||||
: m_numPoints(0) {}
|
||||
~VlcPoints() {}
|
||||
|
||||
// METHODS
|
||||
|
|
|
|||
|
|
@ -89,9 +89,7 @@ public:
|
|||
// METHODS
|
||||
void incCount(int lineno, int column, vluint64_t count, bool ok) {
|
||||
LinenoMap::iterator lit = m_lines.find(lineno);
|
||||
if (lit == m_lines.end()) {
|
||||
lit = m_lines.insert(make_pair(lineno, ColumnMap())).first;
|
||||
}
|
||||
if (lit == m_lines.end()) lit = m_lines.insert(make_pair(lineno, ColumnMap())).first;
|
||||
ColumnMap& cmap = lit->second;
|
||||
ColumnMap::iterator cit = cmap.find(column);
|
||||
if (cit == cmap.end()) {
|
||||
|
|
|
|||
|
|
@ -126,9 +126,7 @@ public:
|
|||
return testp;
|
||||
}
|
||||
void clearUser() {
|
||||
for (ByName::iterator it = m_tests.begin(); it != m_tests.end(); ++it) {
|
||||
(*it)->user(0);
|
||||
}
|
||||
for (ByName::iterator it = m_tests.begin(); it != m_tests.end(); ++it) (*it)->user(0);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -114,7 +114,10 @@ void VlcTop::rank() {
|
|||
// then hierarchically solve a small subset of tests, and take resulting
|
||||
// solution and move up to larger subset of tests. (Aka quick sort.)
|
||||
while (true) {
|
||||
if (debug()) { UINFO(9, "Left on iter" << nextrank << ": "); remaining.dump(); }
|
||||
if (debug()) {
|
||||
UINFO(9, "Left on iter" << nextrank << ": ");
|
||||
remaining.dump();
|
||||
}
|
||||
VlcTest* bestTestp = NULL;
|
||||
vluint64_t bestRemain = 0;
|
||||
for (std::vector<VlcTest*>::iterator it = bytime.begin(); it != bytime.end(); ++it) {
|
||||
|
|
@ -151,7 +154,8 @@ void VlcTop::annotateCalc() {
|
|||
string threshStr = point.thresh();
|
||||
unsigned thresh = (!threshStr.empty()) ? atoi(threshStr.c_str()) : opt.annotateMin();
|
||||
bool ok = (point.count() >= thresh);
|
||||
UINFO(9, "AnnoCalc count " << filename << " " << lineno << " " << point.count() << endl);
|
||||
UINFO(9,
|
||||
"AnnoCalc count " << filename << " " << lineno << " " << point.count() << endl);
|
||||
source.incCount(lineno, column, point.count(), ok);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -37,6 +37,7 @@
|
|||
// If set to "", this default is ignored and the user is expected
|
||||
// to set them at Verilator runtime.
|
||||
|
||||
// clang-format off
|
||||
#ifndef DEFENV_SYSTEMC
|
||||
# define DEFENV_SYSTEMC ""
|
||||
#endif
|
||||
|
|
@ -52,6 +53,7 @@
|
|||
#ifndef DEFENV_VERILATOR_ROOT
|
||||
# define DEFENV_VERILATOR_ROOT ""
|
||||
#endif
|
||||
// clang-format on
|
||||
|
||||
//**********************************************************************
|
||||
//**** Compile options
|
||||
|
|
|
|||
Loading…
Reference in New Issue