Merge from master.

This commit is contained in:
Wilson Snyder 2020-02-09 17:39:23 -05:00
commit 1c3b8229b4
54 changed files with 301 additions and 160 deletions

15
Changes
View File

@ -3,7 +3,10 @@ Revision history for Verilator
The contributors that suggested a given feature are shown in []. Thanks!
* Verilator 4.027 devel
* Verilator 4.029 devel
* Verilator 4.028 2020-02-08
** Support attributes (public, isolate_assignments, etc.) in configuration files.
@ -25,6 +28,8 @@ The contributors that suggested a given feature are shown in []. Thanks!
**** Support enum.next(k) with constant k > 1, #2125. [Tobias Rosenkranz]
**** Support parameter access from arrays of interfaces, #2155. [Todd Strader]
**** Add parameter values in XML. #2110. [Pieter Kapsenberg]
**** Add loc column location in XML (replaces fl), #2122. [Pieter Kapsenberg]
@ -41,6 +46,8 @@ The contributors that suggested a given feature are shown in []. Thanks!
**** Fix WIDTH warning on </<= of narrower value, #2141. [agrobman]
**** Fix OpenSolaris issues, #2154. [brancoliticus]
* Verilator 4.026 2020-01-11
@ -168,10 +175,10 @@ The contributors that suggested a given feature are shown in []. Thanks!
* Verilator 4.020 2019-10-06
*** Support $fseek, $ftell, $frewind, #1496. [Howard Su]
*** Add --public-flat-rw, #1511. [Stefan Wallentowitz]
*** Support $fseek, $ftell, $frewind, #1496. [Howard Su]
*** Support vpiModule, #1469. [Stefan Wallentowitz]
**** Make Syms file honor --output-split-cfuncs, #1499. [Todd Strader]
@ -192,6 +199,8 @@ The contributors that suggested a given feature are shown in []. Thanks!
**** Fix case statements with strings, #1536. [Philipp Wagner]
**** Fix some coverage lost when multithreaded, #2151.
* Verilator 4.018 2019-08-29

View File

@ -19,14 +19,15 @@
\.codacy\.yml
\.travis\.yml
/build/
/obj_dir/
/obj_dbg/
/obj_dir/
/obj_dist/
/obj_iv/
/obj_nc/
/obj_opt/
/obj_vcs/
/obj_vlt/
/obj_vltmt/
/obj_dist/
/INCA_libs/
/cov_work/
/logs/

View File

@ -6,7 +6,7 @@
#AC_INIT([Verilator],[#.### YYYY-MM-DD])
#AC_INIT([Verilator],[#.### devel])
AC_INIT([Verilator],[4.027 devel],
AC_INIT([Verilator],[4.029 devel],
[https://verilator.org],
[verilator],[https://verilator.org])
# When releasing, also update header of Changes file

View File

@ -1832,7 +1832,7 @@ void VL_READMEM_N(bool hex, // Hex format, else binary
QData end // Last row address to read
) VL_MT_SAFE {
QData addr_max = array_lsb + depth - 1;
if (start < array_lsb) start = array_lsb;
if (start < static_cast<QData>(array_lsb)) start = array_lsb;
QData addr_end = end;
if (addr_end > addr_max) addr_end = addr_max;
@ -1883,7 +1883,7 @@ void VL_WRITEMEM_N(bool hex, // Hex format, else binary
QData end // Last address to write, or ~0 when not specified
) VL_MT_SAFE {
QData addr_max = array_lsb + depth - 1;
if (start < array_lsb) start = array_lsb;
if (start < static_cast<QData>(array_lsb)) start = array_lsb;
if (end > addr_max) end = addr_max;
VlWriteMem wmem(hex, bits, filename, start, end);
@ -2396,9 +2396,9 @@ VerilatedVar* VerilatedScope::varFind(const char* namep) const VL_MT_SAFE_POSTIN
void* VerilatedScope::exportFindNullError(int funcnum) VL_MT_SAFE {
// Slowpath - Called only when find has failed
std::string msg = (std::string("Testbench C called '")
+VerilatedImp::exportName(funcnum)
+"' but scope wasn't set, perhaps due to dpi import call without 'context'");
std::string msg = (std::string("Testbench C called '") + VerilatedImp::exportName(funcnum)
+ "' but scope wasn't set, perhaps due to dpi import call without "
+ "'context', or missing svSetScope. See IEEE 1800-2017 35.5.3.");
VL_FATAL_MT("unknown", 0, "", msg.c_str());
return NULL;
}

View File

@ -20,6 +20,7 @@
//=============================================================================
// SPDIFF_OFF
#define __STDC_LIMIT_MACROS // UINT64_MAX
#include "verilatedos.h"
#include "verilated.h"
#include "verilated_fst_c.h"
@ -47,6 +48,7 @@
#if defined(_WIN32) && !defined(__MINGW32__) && !defined(__CYGWIN__)
# include <io.h>
#else
# include <stdint.h>
# include <unistd.h>
#endif

View File

@ -1993,7 +1993,7 @@ PLI_INT32 vpi_chk_error(p_vpi_error_info error_info_p) {
}
if (!_error_info_p) return 0; // no error occured
return _error_info_p->level; // return error severity level
};
}
PLI_INT32 vpi_free_object(vpiHandle object) {
VerilatedVpiImp::assertOneCheck();

View File

@ -111,7 +111,7 @@ public:
"UNSIGNED", "SIGNED", "NOSIGN"
};
return names[m_e];
};
}
inline AstNumeric() : m_e(UNSIGNED) {}
// cppcheck-suppress noExplicitConstructor
inline AstNumeric(en _e) : m_e(_e) {}
@ -346,7 +346,7 @@ public:
"VAR_NO_CLOCKER"
};
return names[m_e];
};
}
inline AstAttrType() : m_e(ILLEGAL) {}
// cppcheck-suppress noExplicitConstructor
inline AstAttrType(en _e) : m_e(_e) {}
@ -391,7 +391,7 @@ public:
" MAX"
};
return names[m_e];
};
}
const char* dpiType() const {
static const char* const names[] = {
"%E-unk",
@ -404,7 +404,7 @@ public:
" MAX"
};
return names[m_e];
};
}
static void selfTest() {
UASSERT(0==strcmp(AstBasicDTypeKwd(_ENUM_MAX).ascii(), " MAX"), "SelfTest: Enum mismatch");
UASSERT(0==strcmp(AstBasicDTypeKwd(_ENUM_MAX).dpiType(), " MAX"), "SelfTest: Enum mismatch");
@ -1025,14 +1025,14 @@ protected:
clearcnt(id, cntGblRef, userBusyRef); // Includes a checkUse for us
userBusyRef = false;
}
static void clearcnt(int id, uint32_t& cntGblRef, bool& userBusyRef) {
static void clearcnt(int id, uint32_t& cntGblRef, const bool& userBusyRef) {
UASSERT_STATIC(userBusyRef, "Clear of User"+cvtToStr(id)+"() not under AstUserInUse");
// If this really fires and is real (after 2^32 edits???)
// we could just walk the tree and clear manually
++cntGblRef;
UASSERT_STATIC(cntGblRef, "User*() overflowed!");
}
static void checkcnt(int id, uint32_t&, bool& userBusyRef) {
static void checkcnt(int id, uint32_t&, const bool& userBusyRef) {
UASSERT_STATIC(userBusyRef, "Check of User"+cvtToStr(id)+"() failed, not under AstUserInUse");
}
};
@ -1197,7 +1197,7 @@ public:
explicit V3Hash(VNUser u) { m_both = u.toInt(); }
V3Hash operator+= (const V3Hash& rh) {
setBoth(depth()+rh.depth(), (hshval()*31+rh.hshval()));
return *this; };
return *this; }
// Creating from raw data (sameHash functions)
V3Hash() { setBoth(1, 0); }
// cppcheck-suppress noExplicitConstructor

View File

@ -630,7 +630,7 @@ std::pair<uint32_t,uint32_t> AstNodeDType::dimensions(bool includeBasic) {
else if (const AstBasicDType* adtypep = VN_CAST(dtypep, BasicDType)) {
if (includeBasic && (adtypep->isRanged() || adtypep->isString())) packed++;
}
else if (const AstStructDType* sdtypep = VN_CAST(dtypep, StructDType)) {
else if (VN_IS(dtypep, StructDType)) {
packed++;
}
break;

View File

@ -996,7 +996,7 @@ public:
class AstVoidDType : public AstNodeDType {
// For e.g. a function returning void
public:
AstVoidDType(FileLine* fl)
explicit AstVoidDType(FileLine* fl)
: ASTGEN_SUPER(fl) { dtypep(this); }
ASTNODE_NODE_FUNCS(VoidDType)
virtual void dumpSmall(std::ostream& str) const;
@ -1404,7 +1404,8 @@ public:
}
AstCMethodHard(FileLine* fl, AstNode* fromp, const string& name, AstNode* pinsp)
: ASTGEN_SUPER(fl, false)
, m_name(name) {
, m_name(name)
, m_pure(false) {
setOp1p(fromp);
addNOp2p(pinsp);
}
@ -2419,7 +2420,7 @@ public:
class AstUnbounded : public AstNode {
// A $ in the parser, used for unbounded and queues
public:
AstUnbounded(FileLine* fl)
explicit AstUnbounded(FileLine* fl)
: ASTGEN_SUPER(fl) {}
ASTNODE_NODE_FUNCS(Unbounded)
virtual string emitVerilog() { return "$"; }
@ -3615,7 +3616,7 @@ public:
class AstReturn : public AstNodeStmt {
public:
AstReturn(FileLine* fl, AstNode* lhsp = NULL)
explicit AstReturn(FileLine* fl, AstNode* lhsp = NULL)
: ASTGEN_SUPER(fl) {
setNOp1p(lhsp);
}
@ -3916,7 +3917,7 @@ class AstNew : public AstNodeMath {
// Parents: math|stmt
// Children: varref|arraysel, math
public:
AstNew(FileLine* fl)
explicit AstNew(FileLine* fl)
: ASTGEN_SUPER(fl) {
dtypep(NULL); // V3Width will resolve
}
@ -6471,9 +6472,10 @@ class AstTextBlock : public AstNodeSimpleText {
private:
bool m_commas; // Comma separate emitted children
public:
AstTextBlock(FileLine* fl, const string& textp="", bool tracking=false,
bool commas=false)
: ASTGEN_SUPER(fl, textp, tracking), m_commas(commas) {}
explicit AstTextBlock(FileLine* fl, const string& textp = "", bool tracking = false,
bool commas = false)
: ASTGEN_SUPER(fl, textp, tracking)
, m_commas(commas) {}
ASTNODE_NODE_FUNCS(TextBlock)
void commas(bool flag) { m_commas = flag; }
bool commas() const { return m_commas; }
@ -6840,7 +6842,7 @@ public:
dtypeFrom(exprsp);
}
AstCMath(FileLine* fl, const string& textStmt, int setwidth, bool cleanOut=true)
: ASTGEN_SUPER(fl), m_cleanOut(cleanOut) {
: ASTGEN_SUPER(fl), m_cleanOut(cleanOut), m_pure(true) {
addNOp1p(new AstText(fl, textStmt, true));
if (setwidth) { dtypeSetLogicSized(setwidth, AstNumeric::UNSIGNED); }
}

View File

@ -115,11 +115,11 @@ public:
void V3CUse::cUseAll(AstNetlist* nodep) {
UINFO(2, __FUNCTION__ << ": " << endl);
// Call visitor separately for each module, so visitor state is cleared
for (AstNodeModule* nodep = v3Global.rootp()->modulesp(); nodep;
nodep = VN_CAST(nodep->nextp(), NodeModule)) {
for (AstNodeModule* modp = v3Global.rootp()->modulesp(); modp;
modp = VN_CAST(modp->nextp(), NodeModule)) {
// Insert under this module; someday we should e.g. make Ast
// for each output file and put under that
CUseVisitor visitor(nodep);
CUseVisitor visitor(modp);
}
V3Global::dumpCheckGlobalTree("cuse", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
}

View File

@ -41,9 +41,9 @@ template <typename T> class V3ConfigWildcardResolver {
Map m_mapWildcard; // Wildcard strings to entities
Map m_mapResolved; // Resolved strings to converged entities
typename Map::iterator m_last; // Last access, will probably hit again
public:
V3ConfigWildcardResolver() { m_last = m_mapResolved.end(); }
V3ConfigWildcardResolver() {}
~V3ConfigWildcardResolver() {}
/// Update into maps from other
void update(const V3ConfigWildcardResolver& other) {
@ -63,10 +63,6 @@ public:
}
// Access an entity and resolve wildcards that match it
T* resolve(const string& name) {
// Lookup if recently accessed matches
if (VL_LIKELY(m_last != m_mapResolved.end()) && VL_LIKELY(m_last->first == name)) {
return &m_last->second;
}
// Lookup if it was resolved before, typically not
typename Map::iterator it = m_mapResolved.find(name);
if (VL_UNLIKELY(it != m_mapResolved.end())) { return &it->second; }

View File

@ -2087,7 +2087,7 @@ private:
default: // Most operators, just move to next argument
if (argp) {
AstNode* nextp = argp->nextp();
if (argp && VN_IS(argp, Const)) { // Convert it
if (VN_IS(argp, Const)) { // Convert it
string out = VN_CAST(argp, Const)->num().displayed(nodep, fmt);
UINFO(9," DispConst: "<<fmt<<" -> "<<out
<<" for "<<argp<<endl);

View File

@ -382,9 +382,15 @@ public:
puts(");\n");
}
virtual void visit(AstCoverInc* nodep) VL_OVERRIDE {
puts("++(vlSymsp->__Vcoverage[");
puts(cvtToStr(nodep->declp()->dataDeclThisp()->binNum()));
puts("]);\n");
if (v3Global.opt.threads()) {
puts("vlSymsp->__Vcoverage[");
puts(cvtToStr(nodep->declp()->dataDeclThisp()->binNum()));
puts("].fetch_add(1, std::memory_order_relaxed);\n");
} else {
puts("++(vlSymsp->__Vcoverage[");
puts(cvtToStr(nodep->declp()->dataDeclThisp()->binNum()));
puts("]);\n");
}
}
virtual void visit(AstCReturn* nodep) VL_OVERRIDE {
puts("return (");
@ -1074,6 +1080,7 @@ class EmitCImp : EmitCStmts {
// METHODS
void doubleOrDetect(AstChangeDet* changep, bool& gotOne) {
// cppcheck-suppress variableScope
static int s_addDoubleOr = 10; // Determined experimentally as best
if (!changep->rhsp()) {
if (!gotOne) gotOne = true;
@ -1447,7 +1454,8 @@ class EmitCImp : EmitCStmts {
puts(emitVarResetRecurse(varp, dtypep, 0, ""));
}
}
string emitVarResetRecurse(AstVar* varp, AstNodeDType* dtypep, int depth, string suffix) {
string emitVarResetRecurse(AstVar* varp, AstNodeDType* dtypep, int depth,
const string& suffix) {
dtypep = dtypep->skipRefp();
AstBasicDType* basicp = dtypep->basicp();
// Returns string to do resetting, empty to do nothing (which caller should handle)
@ -1953,7 +1961,9 @@ void EmitCImp::emitCoverageDecl(AstNodeModule* modp) {
if (v3Global.opt.coverage()) {
ofp()->putsPrivate(true);
putsDecoration("// Coverage\n");
puts("void __vlCoverInsert(uint32_t* countp, bool enable, const char* filenamep, int lineno, int column,\n");
puts("void __vlCoverInsert(");
puts(v3Global.opt.threads() ? "std::atomic<uint32_t>" : "uint32_t");
puts("* countp, bool enable, const char* filenamep, int lineno, int column,\n");
puts( "const char* hierp, const char* pagep, const char* commentp);\n");
}
}
@ -2068,14 +2078,22 @@ void EmitCImp::emitCoverageImp(AstNodeModule* modp) {
puts("\n// Coverage\n");
// Rather than putting out VL_COVER_INSERT calls directly, we do it via this function
// This gets around gcc slowness constructing all of the template arguments.
puts("void " + prefixNameProtect(m_modp)
+ "::__vlCoverInsert(uint32_t* countp, bool enable,"
+ " const char* filenamep, int lineno, int column,\n");
puts("void " + prefixNameProtect(m_modp) + "::__vlCoverInsert(");
puts(v3Global.opt.threads() ? "std::atomic<uint32_t>" : "uint32_t");
puts("* countp, bool enable, const char* filenamep, int lineno, int column,\n");
puts( "const char* hierp, const char* pagep, const char* commentp) {\n");
puts( "static uint32_t fake_zero_count = 0;\n"); // static doesn't need save-restore as constant
puts( "if (!enable) countp = &fake_zero_count;\n"); // Used for second++ instantiation of identical bin
puts( "*countp = 0;\n");
puts( "VL_COVER_INSERT(countp,");
if (v3Global.opt.threads()) {
puts( "assert(sizeof(uint32_t) == sizeof(std::atomic<uint32_t>));\n");
puts( "uint32_t* count32p = reinterpret_cast<uint32_t*>(countp);\n");
} else {
puts( "uint32_t* count32p = countp;\n");
}
// static doesn't need save-restore as is constant
puts( "static uint32_t fake_zero_count = 0;\n");
// Used for second++ instantiation of identical bin
puts( "if (!enable) count32p = &fake_zero_count;\n");
puts( "*count32p = 0;\n");
puts("VL_COVER_INSERT(count32p,");
puts( " \"filename\",filenamep,");
puts( " \"lineno\",lineno,");
puts( " \"column\",column,\n");
@ -2644,8 +2662,10 @@ void EmitCImp::emitInt(AstNodeModule* modp) {
if (!did) {
did = true;
putsDecoration("// CELLS\n");
if (modp->isTop()) puts("// Public to allow access to /*verilator_public*/ items;\n");
if (modp->isTop()) puts("// otherwise the application code can consider these internals.\n");
if (modp->isTop()) {
puts("// Public to allow access to /*verilator_public*/ items;\n");
puts("// otherwise the application code can consider these internals.\n");
}
}
puts(prefixNameProtect(cellp->modp()) + "* " + cellp->nameProtect() + ";\n");
}

View File

@ -437,7 +437,10 @@ void EmitCSyms::emitSymHdr() {
if (m_coverBins) {
puts("\n// COVERAGE\n");
puts("uint32_t __Vcoverage["); puts(cvtToStr(m_coverBins)); puts("];\n");
puts(v3Global.opt.threads() ? "std::atomic<uint32_t>" : "uint32_t");
puts(" __Vcoverage[");
puts(cvtToStr(m_coverBins));
puts("];\n");
}
if (!m_scopeNames.empty()) { // Scope names

View File

@ -189,7 +189,7 @@ public:
string cppfile = *it;
of.puts("\t"+V3Os::filenameNonExt(cppfile)+" \\\n");
string dir = V3Os::filenameDir(cppfile);
if (dirs.find(dir) == dirs.end()) dirs.insert(dir);
dirs.insert(dir);
}
of.puts("\n");

View File

@ -120,6 +120,7 @@ void VFileContent::pushText(const string& text) {
string VFileContent::getLine(int lineno) const {
// Return error text rather than asserting so the user isn't left without a message
// cppcheck-suppress negativeContainerIndex
if (VL_UNCOVERABLE(lineno < 0 || lineno >= (int)m_lines.size())) {
if (debug() || v3Global.opt.debugCheck()) {
return ("%Error-internal-contents-bad-ct"+cvtToStr(m_id)

View File

@ -119,7 +119,7 @@ private:
return *defFilelinep;
}
public:
FileLine(const string& filename) {
explicit FileLine(const string& filename) {
m_lastLineno = m_firstLineno = 0;
m_lastColumn = m_firstColumn = 0;
m_filenameno = singleton().nameToNumber(filename);

View File

@ -453,9 +453,11 @@ private:
UASSERT_OBJ(varscp, nodep, "Var didn't get varscoped in V3Scope.cpp");
GateVarVertex* vvertexp = makeVarVertex(varscp);
UINFO(5," VARREF to "<<varscp<<endl);
if (m_inSenItem) vvertexp->setIsClock();
// For SYNCASYNCNET
if (m_inSenItem) varscp->user2(true);
if (m_inSenItem) {
vvertexp->setIsClock();
// For SYNCASYNCNET
varscp->user2(true);
}
else if (m_activep && m_activep->hasClocked() && !nodep->lvalue()) {
if (varscp->user2()) {
if (!vvertexp->rstAsyncNodep()) vvertexp->rstAsyncNodep(nodep);
@ -712,7 +714,7 @@ bool GateVisitor::elimLogicOkOutputs(GateLogicVertex* consumeVertexp,
for (GateVarRefList::const_iterator it = rhsVarRefs.begin();
it != rhsVarRefs.end(); ++it) {
AstVarScope* vscp = (*it)->varScopep();
if (varscopes.find(vscp) == varscopes.end()) varscopes.insert(vscp);
varscopes.insert(vscp);
}
for (V3GraphEdge* edgep = consumeVertexp->outBeginp(); edgep; edgep = edgep->outNextp()) {
GateVarVertex* consVVertexp = dynamic_cast<GateVarVertex*>(edgep->top());

View File

@ -65,7 +65,7 @@ public:
const char* ascii() const {
static const char* const names[] = { "FORWARD", "REVERSE" };
return names[m_e];
};
}
// METHODS unique to this class
GraphWay invert() const { return m_e == FORWARD ? REVERSE : FORWARD; }
bool forward() const { return m_e == FORWARD; }

View File

@ -599,6 +599,7 @@ public:
if (debug()>=6) m_graphp->dumpDotFilePrefixed("comp_out");
}
~DfaGraphComplement() {}
VL_UNCOPYABLE(DfaGraphComplement);
};
void DfaGraph::dfaComplement() {

View File

@ -89,7 +89,7 @@ class DfaVertex : public V3GraphVertex {
bool m_accepting; // Accepting state?
public:
// CONSTRUCTORS
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) {}
using V3GraphVertex::clone; // We are overriding, not overloading clone(V3Graph*)

View File

@ -42,8 +42,8 @@ class GraphPathChecker : GraphAlg<const V3Graph> {
public:
// CONSTRUCTORS
GraphPathChecker(const V3Graph* graphp,
V3EdgeFuncP edgeFuncp = V3GraphEdge::followAlwaysTrue);
explicit GraphPathChecker(const V3Graph* graphp,
V3EdgeFuncP edgeFuncp = V3GraphEdge::followAlwaysTrue);
~GraphPathChecker();
// METHODS

View File

@ -95,9 +95,9 @@ private:
public:
// CONSTRUCTORS
GraphStream(const V3Graph* graphp,
GraphWay way = GraphWay::FORWARD,
const T_Compare& lessThan = T_Compare())
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
// sensitive to its lessThan at all, so it doesn't matter.

View File

@ -178,10 +178,10 @@ private:
// update user4 (statement count) to reflect that:
int statements = modp->user4();
LocalInstanceMap& localsr = m_instances[modp];
for (LocalInstanceMap::iterator it = localsr.begin(); it != localsr.end(); ++it) {
AstNodeModule* childp = it->first;
for (LocalInstanceMap::iterator iti = localsr.begin(); iti != localsr.end(); ++iti) {
AstNodeModule* childp = iti->first;
if (childp->user1()) { // inlining child
statements += (childp->user4() * it->second);
statements += (childp->user4() * iti->second);
}
}
modp->user4(statements);

View File

@ -59,7 +59,7 @@ public:
"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; }

View File

@ -385,9 +385,7 @@ private:
<<pinp->prettyNameQ());
}
}
if (ports.find(pinp->name()) == ports.end()) {
ports.insert(pinp->name());
}
ports.insert(pinp->name());
}
// We search ports, rather than in/out declarations as they aren't resolved yet,
// and it's easier to do it now than in V3LinkDot when we'd need to repeat steps.

View File

@ -2070,11 +2070,21 @@ private:
refp->varp(varp);
m_ds.m_dotText = "";
if (m_ds.m_unresolved && m_ds.m_unlinkedScope) {
newp = new AstUnlinkedRef(nodep->fileline(), VN_CAST(refp, VarXRef),
refp->name(),
m_ds.m_unlinkedScope->unlinkFrBack());
m_ds.m_unlinkedScope = NULL;
m_ds.m_unresolved = false;
string dotted = refp->dotted();
size_t pos = dotted.find("__BRA__??__KET__");
// Arrays of interfaces all have the same parameters
if (pos != string::npos && varp->isParam()
&& VN_IS(m_ds.m_unlinkedScope, CellArrayRef)) {
refp->dotted(dotted.substr(0, pos));
newp = refp;
} else {
newp = new AstUnlinkedRef(nodep->fileline(),
VN_CAST(refp, VarXRef),
refp->name(),
m_ds.m_unlinkedScope->unlinkFrBack());
m_ds.m_unlinkedScope = NULL;
m_ds.m_unresolved = false;
}
} else {
newp = refp;
}
@ -2241,7 +2251,6 @@ private:
}
}
} else {
string baddot;
VSymEnt* foundp = m_statep->findSymPrefixed(dotSymp, nodep->name(), baddot);
AstVarScope* vscp = foundp ? VN_CAST(foundp->nodep(), VarScope) : NULL;
if (!vscp) {

View File

@ -1540,8 +1540,8 @@ V3Number& V3Number::opShiftRS(const V3Number& lhs, const V3Number& rhs, uint32_t
if (rhs.isFourState()) return setAllBitsX();
setZero();
for (int bit=32; bit<rhs.width(); bit++) {
for (int bit=0; bit<this->width(); bit++) {
setBit(bit, lhs.bitIs(lbits-1)); // 0/1/X/Z
for (int sbit = 0; sbit < this->width(); sbit++) {
setBit(sbit, lhs.bitIs(lbits - 1)); // 0/1/X/Z
}
if (rhs.bitIs1(lbits-1)) setAllBits1(); // -1 else 0
return *this; // shift of over 2^32 must be -1/0

View File

@ -151,7 +151,7 @@ public:
V3Number(VerilogStringLiteral, AstNode* nodep, const string& str);
class String {};
V3Number(String, AstNode* nodep, const string& value) { init(nodep, 0); setString(value); }
V3Number(const V3Number* nump, int width = 1) {
explicit V3Number(const V3Number* nump, int width = 1) {
init(NULL, width);
m_fileline = nump->fileline();
}

View File

@ -182,9 +182,7 @@ void V3Options::checkParameters() {
}
void V3Options::addCppFile(const string& filename) {
if (m_cppFiles.find(filename) == m_cppFiles.end()) {
m_cppFiles.insert(filename);
}
m_cppFiles.insert(filename);
}
void V3Options::addCFlags(const string& filename) {
m_cFlags.push_back(filename);
@ -193,9 +191,7 @@ void V3Options::addLdLibs(const string& filename) {
m_ldLibs.push_back(filename);
}
void V3Options::addFuture(const string& flag) {
if (m_futures.find(flag) == m_futures.end()) {
m_futures.insert(flag);
}
m_futures.insert(flag);
}
bool V3Options::isFuture(const string& flag) const {
return m_futures.find(flag) != m_futures.end();
@ -204,25 +200,19 @@ bool V3Options::isLibraryFile(const string& filename) const {
return m_libraryFiles.find(filename) != m_libraryFiles.end();
}
void V3Options::addLibraryFile(const string& filename) {
if (m_libraryFiles.find(filename) == m_libraryFiles.end()) {
m_libraryFiles.insert(filename);
}
m_libraryFiles.insert(filename);
}
bool V3Options::isClocker(const string& signame) const {
return m_clockers.find(signame) != m_clockers.end();
}
void V3Options::addClocker(const string& signame) {
if (m_clockers.find(signame) == m_clockers.end()) {
m_clockers.insert(signame);
}
m_clockers.insert(signame);
}
bool V3Options::isNoClocker(const string& signame) const {
return m_noClockers.find(signame) != m_noClockers.end();
}
void V3Options::addNoClocker(const string& signame) {
if (m_noClockers.find(signame) == m_noClockers.end()) {
m_noClockers.insert(signame);
}
m_noClockers.insert(signame);
}
void V3Options::addVFile(const string& filename) {
// We use a list for v files, because it's legal to have includes

View File

@ -127,7 +127,7 @@ void OrderGraph::loopsVertexCb(V3GraphVertex* vertexp) {
<<" Example path: "
<<vvertexp->varScp()->prettyName()<<endl;
}
};
}
//######################################################################

View File

@ -228,9 +228,9 @@ private:
// Hitting a cell adds to the appropriate level of this level-sorted list,
// so since cells originally exist top->bottom we process in top->bottom order too.
while (!m_todoModps.empty()) {
LevelModMap::iterator it = m_todoModps.begin();
AstNodeModule* nodep = it->second;
m_todoModps.erase(it);
LevelModMap::iterator itm = m_todoModps.begin();
AstNodeModule* nodep = itm->second;
m_todoModps.erase(itm);
if (!nodep->user5SetOnce()) { // Process once; note clone() must clear so we do it again
m_modp = nodep;
UINFO(4," MOD "<<nodep<<endl);
@ -355,9 +355,16 @@ private:
if (VN_IS(backp, Var)
&& VN_CAST(backp, Var)->isIfaceRef()
&& VN_CAST(backp, Var)->childDTypep()
&& VN_CAST(VN_CAST(backp, Var)->childDTypep(), IfaceRefDType)) {
&& (VN_CAST(VN_CAST(backp, Var)->childDTypep(), IfaceRefDType)
|| (VN_CAST(VN_CAST(backp, Var)->childDTypep(), UnpackArrayDType)
&& VN_CAST(VN_CAST(backp, Var)->childDTypep()->getChildDTypep(),
IfaceRefDType)))) {
AstIfaceRefDType* ifacerefp
= VN_CAST(VN_CAST(backp, Var)->childDTypep(), IfaceRefDType);
if (!ifacerefp) {
ifacerefp = VN_CAST(VN_CAST(backp, Var)->childDTypep()->getChildDTypep(),
IfaceRefDType);
}
// Interfaces passed in on the port map have ifaces
if (AstIface* ifacep = ifacerefp->ifacep()) {
if (dotted == backp->name()) {

View File

@ -573,7 +573,7 @@ public:
edges.erase(relativep);
}
bool hasRelative(GraphWay way, LogicMTask* relativep) {
EdgeSet& edges = m_edges[way];
const EdgeSet& edges = m_edges[way];
return edges.has(relativep);
}
void checkRelativesCp(GraphWay way) const {
@ -1584,7 +1584,7 @@ private:
}
UASSERT_OBJ(found, ap, "Sibling not found");
}
};
}
static const GraphWay* s_shortestWaywardCpInclusiveWay;
static int shortestWaywardCpInclusive(const void* vap, const void* vbp) {

View File

@ -135,7 +135,7 @@ public:
"ps_DEFFORM", "ps_DEFVALUE", "ps_DEFPAREN", "ps_DEFARG",
"ps_INCNAME", "ps_ERRORNAME", "ps_JOIN", "ps_STRIFY"};
return states[s];
};
}
std::stack<ProcState> m_states; ///< Current state of parser
int m_off; ///< If non-zero, ifdef level is turned off, don't dump text

View File

@ -102,8 +102,8 @@ public:
protected:
// CONSTRUCTORS
V3PreProc() {
m_debug=0;
};
m_debug = 0;
}
void configure(FileLine* fl);
public:
static V3PreProc* createPreProc(FileLine* fl);

View File

@ -505,6 +505,6 @@ private:
namespace V3ScoreboardBase {
void selfTest();
};
}
#endif // Guard

View File

@ -993,8 +993,8 @@ private:
clearOptimizable(nodep, "Argument for $display like statement is not constant");
break;
}
string format = string("%") + pos[0];
result += constp->num().displayed(nodep, format);
string pformat = string("%") + pos[0];
result += constp->num().displayed(nodep, pformat);
} else {
switch (tolower(pos[0])) {
case '%': result += "%"; break;

View File

@ -204,7 +204,7 @@ private:
if (m_fast && nodep->evalp()) {
m_instrs = 0;
m_counting = true;
if (nodep->evalp()) iterateChildrenConst(nodep->evalp());
iterateChildrenConst(nodep->evalp());
m_counting = false;
}
allNodes(nodep);

View File

@ -163,9 +163,9 @@ public:
// Suggest alternative symbol candidates without looking upward through symbol hierarchy
for (IdNameMap::const_iterator it = m_idNameMap.begin();
it != m_idNameMap.end(); ++it) {
const AstNode* nodep = it->second->nodep();
if (nodep && (!matcherp || matcherp->nodeMatch(nodep))) {
spellerp->pushCandidate(nodep->prettyName());
const AstNode* itemp = it->second->nodep();
if (itemp && (!matcherp || matcherp->nodeMatch(itemp))) {
spellerp->pushCandidate(itemp->prettyName());
}
}
}
@ -249,9 +249,9 @@ public:
if (prettyName=="") prettyName = lookp->prettyName();
string scopes;
for (IdNameMap::iterator it = m_idNameMap.begin(); it!=m_idNameMap.end(); ++it) {
AstNode* nodep = it->second->nodep();
if (VN_IS(nodep, Cell)
|| (VN_IS(nodep, Module) && VN_CAST(nodep, Module)->isTop())) {
AstNode* itemp = it->second->nodep();
if (VN_IS(itemp, Cell)
|| (VN_IS(itemp, Module) && VN_CAST(itemp, Module)->isTop())) {
if (scopes != "") scopes += ", ";
scopes += AstNode::prettyName(it->first);
}

View File

@ -415,12 +415,12 @@ private:
// Even if it's referencing a varref, we still make a temporary
// Else task(x,x,x) might produce incorrect results
AstVarScope* outvscp
AstVarScope* tempvscp
= createVarScope(portp, namePrefix+"__"+portp->shortName());
portp->user2p(outvscp);
AstAssign* assp = new AstAssign(pinp->fileline(),
pinp,
new AstVarRef(outvscp->fileline(), outvscp, false));
portp->user2p(tempvscp);
AstAssign* assp
= new AstAssign(pinp->fileline(), pinp,
new AstVarRef(tempvscp->fileline(), tempvscp, false));
assp->fileline()->modifyWarnOff(V3ErrorCode::BLKSEQ, true); // Ok if in <= block
// Put assignment BEHIND of all other statements
beginp->addNext(assp);
@ -469,7 +469,7 @@ private:
// Iteration requires a back, so put under temporary node
{
AstBegin* tempp = new AstBegin(beginp->fileline(), "[EditWrapper]", beginp);
TaskRelinkVisitor visit (tempp);
TaskRelinkVisitor visitor(tempp);
tempp->stmtsp()->unlinkFrBackWithNext();
VL_DO_DANGLING(tempp->deleteTree(), tempp);
}
@ -1073,7 +1073,7 @@ private:
// Iteration requires a back, so put under temporary node
{
AstBegin* tempp = new AstBegin(cfuncp->fileline(), "[EditWrapper]", cfuncp);
TaskRelinkVisitor visit (tempp);
TaskRelinkVisitor visitor(tempp);
tempp->stmtsp()->unlinkFrBackWithNext();
VL_DO_DANGLING(tempp->deleteTree(), tempp);
}

View File

@ -449,9 +449,7 @@ private:
break;
} else {
uint32_t acode = cfvertexp->activityCode();
if (actset.find(acode) == actset.end()) {
actset.insert(acode);
}
actset.insert(acode);
}
}
// If a trace doesn't have activity, it's constant, and we

View File

@ -388,6 +388,7 @@ private:
// Grab assignment
AstNode* incp = NULL; // Should be last statement
if (nodep->incsp()) V3Const::constifyEdit(nodep->incsp());
// cppcheck-suppress duplicateCondition
if (nodep->incsp()) incp = nodep->incsp();
else {
for (incp = nodep->bodysp(); incp && incp->nextp(); incp = incp->nextp()) {}

View File

@ -1138,9 +1138,9 @@ private:
default: nodep->v3error("Unhandled attribute type");
}
} else {
std::pair<uint32_t, uint32_t> dim
std::pair<uint32_t, uint32_t> dimp
= nodep->fromp()->dtypep()->skipRefp()->dimensions(true);
uint32_t msbdim = dim.first + dim.second;
uint32_t msbdim = dimp.first + dimp.second;
if (!nodep->dimp() || msbdim < 1) {
int dim = 1;
AstConst* newp = dimensionValue(nodep->fileline(), nodep->fromp()->dtypep(),
@ -2291,7 +2291,6 @@ private:
userIterateChildren(nodep, WidthVP(SELF, BOTH).p());
AstClassRefDType* refp = VN_CAST(m_vup->dtypeNullp(), ClassRefDType);
if (!refp) { // e.g. int a = new;
if (refp) UINFO(1, "Got refp "<<refp<<endl);
nodep->v3error("new() not expected in this context");
return;
}
@ -2454,9 +2453,9 @@ private:
if (VN_IS(valuep, Const)) {
// Forming a AstConcat will cause problems with
// unsized (uncommitted sized) constants
if (AstNode* newp = WidthCommitVisitor::newIfConstCommitSize(VN_CAST(valuep, Const))) {
if (AstNode* newccp = WidthCommitVisitor::newIfConstCommitSize(VN_CAST(valuep, Const))) {
VL_DO_DANGLING(pushDeletep(valuep), valuep);
valuep = newp;
valuep = newccp;
}
}
if (!newp) newp = valuep;
@ -2574,9 +2573,10 @@ private:
if (VN_IS(valuep, Const)) {
// Forming a AstConcat will cause problems with
// unsized (uncommitted sized) constants
if (AstNode* newp = WidthCommitVisitor::newIfConstCommitSize(VN_CAST(valuep, Const))) {
if (AstNode* newccp
= WidthCommitVisitor::newIfConstCommitSize(VN_CAST(valuep, Const))) {
VL_DO_DANGLING(pushDeletep(valuep), valuep);
valuep = newp;
valuep = newccp;
}
}
{ // Packed. Convert to concat for now.
@ -3675,9 +3675,9 @@ private:
if (shiftp && shiftp->num().mostSetBitP1() <= 32) {
// If (number)<<96'h1, then make it into (number)<<32'h1
V3Number num (shiftp, 32, 0); num.opAssign(shiftp->num());
AstNode* shiftp = nodep->rhsp();
nodep->rhsp()->replaceWith(new AstConst(shiftp->fileline(), num));
VL_DO_DANGLING(shiftp->deleteTree(), shiftp);
AstNode* shiftrhsp = nodep->rhsp();
nodep->rhsp()->replaceWith(new AstConst(shiftrhsp->fileline(), num));
VL_DO_DANGLING(shiftrhsp->deleteTree(), shiftrhsp);
}
}
}

View File

@ -91,9 +91,9 @@ private:
if (const AstNodeArrayDType* adtypep = VN_CAST(ddtypep, NodeArrayDType)) {
fromRange = adtypep->declRange();
}
else if (const AstAssocArrayDType* adtypep = VN_CAST(ddtypep, AssocArrayDType)) {
else if (VN_IS(ddtypep, AssocArrayDType)) {
}
else if (const AstQueueDType* adtypep = VN_CAST(ddtypep, QueueDType)) {
else if (VN_IS(ddtypep, QueueDType)) {
}
else if (const AstNodeUOrStructDType* adtypep = VN_CAST(ddtypep, NodeUOrStructDType)) {
fromRange = adtypep->declRange();

View File

@ -42,9 +42,7 @@
// VlcOptions
void VlcOptions::addReadFile(const string& filename) {
if (m_readFiles.find(filename) == m_readFiles.end()) {
m_readFiles.insert(filename);
}
m_readFiles.insert(filename);
}
string VlcOptions::version() {

View File

@ -352,7 +352,7 @@ sub write_types {
printf $fh " \"_ENUM_END\"\n";
printf $fh " };\n";
printf $fh " return names[m_e];\n";
printf $fh " };\n";
printf $fh " }\n";
$fh->close();
}

View File

@ -137,6 +137,9 @@ sub _suppress {
return undef if $filename eq "*";
# Cleanup for e.g. ../V3AstNodes.h
$filename = "src/$1" if $filename =~ m!^\.\./(.*)!;
# Specific suppressions
return 1 if $id eq "missingInclude" && $filename =~ m!systemc.h!;
return 1 if $id eq "missingInclude" && $filename =~ m!svdpi.h!;

View File

@ -114,12 +114,14 @@ public:
if (!rangep) return exprp;
else return new AstGatePin(rangep->fileline(), exprp, rangep->cloneTree(true));
}
void endLabel(FileLine* fl, AstNode* nodep, string* endnamep) { endLabel(fl, nodep->prettyName(), endnamep); }
void endLabel(FileLine* fl, string name, string* endnamep) {
if (fl && endnamep && *endnamep != "" && name != *endnamep
&& name != AstNode::prettyName(*endnamep)) {
fl->v3warn(ENDLABEL,"End label '"<<*endnamep<<"' does not match begin label '"<<name<<"'");
}
void endLabel(FileLine* fl, AstNode* nodep, string* endnamep) {
endLabel(fl, nodep->prettyName(), endnamep);
}
void endLabel(FileLine* fl, const string& name, string* endnamep) {
if (fl && endnamep && *endnamep != "" && name != *endnamep
&& name != AstNode::prettyName(*endnamep)) {
fl->v3warn(ENDLABEL,"End label '"<<*endnamep<<"' does not match begin label '"<<name<<"'");
}
}
void setVarDecl(AstVarType type) { m_varDecl = type; }
void setDType(AstNodeDType* dtypep) {

View File

@ -1498,10 +1498,9 @@ sub _run {
# Read the log file a couple of times to allow for NFS delays
if ($param{check_finished} || $param{expect}) {
my $tries = $self->tries;
for (my $try=$tries-1; $try>=0; $try--) {
sleep 1 if ($try!=$tries-1);
my $moretry = $try!=0;
for (my $try = $self->tries - 1; $try >= 0; $try--) {
sleep 1 if ($try != $self->tries - 1);
my $moretry = $try != 0;
my $fh = IO::File->new("<$param{logfile}");
next if !$fh && $moretry;
@ -1949,11 +1948,10 @@ sub files_identical {
my $fn1_is_logfile = shift;
return 1 if $self->errors || $self->skips || $self->unsupporteds;
my $tries = $self->tries;
try:
for (my $try=$tries-1; $try>=0; $try--) {
sleep 1 if ($try!=$tries-1);
my $moretry = $try!=0;
for (my $try = $self->tries - 1; $try >= 0; $try--) {
sleep 1 if ($try != $self->tries - 1);
my $moretry = $try != 0;
my $f1 = IO::File->new("<$fn1");
my $f2 = IO::File->new("<$fn2");

View File

@ -0,0 +1,45 @@
// -*- mode: C++; c-file-style: "cc-mode" -*-
//
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed into the Public Domain, for any use,
// without warranty, 2010 by Wilson Snyder.
#include <verilated.h>
#include VM_PREFIX_INCLUDE
//======================================================================
#if defined(VERILATOR)
# include "Vt_dpi_export_context_bad__Dpi.h"
#elif defined(VCS)
# include "../vc_hdrs.h"
#elif defined(CADENCE)
# define NEED_EXTERNS
#else
# error "Unknown simulator for DPI test"
#endif
#ifdef NEED_EXTERNS
extern "C" {
extern void dpix_task();
}
#endif
//======================================================================
unsigned int main_time = 0;
double sc_time_stamp() { return main_time; }
VM_PREFIX* topp = NULL;
int main(int argc, char* argv[]) {
topp = new VM_PREFIX;
Verilated::debug(0);
topp->eval();
dpix_task(); // Missing svSetScope
return 1;
}

View File

@ -0,0 +1,2 @@
%Error: unknown:0: Testbench C called 'dpix_task' but scope wasn't set, perhaps due to dpi import call without 'context', or missing svSetScope. See IEEE 1800-2017 35.5.3.
Aborting...

View File

@ -0,0 +1,23 @@
#!/usr/bin/perl
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# Copyright 2003 by Wilson Snyder. This program is free software; you can
# redistribute it and/or modify it under the terms of either the GNU
# Lesser General Public License Version 3 or the Perl Artistic License
# Version 2.0.
scenarios(simulator => 1);
compile(
v_flags2 => ["--exe $Self->{t_dir}/t_dpi_export_context_bad.cpp"],
make_main => 0,
);
execute(
fails => 1,
expect_filename => $Self->{golden_filename},
);
ok(1);
1;

View File

@ -0,0 +1,13 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// Copyright 2020 by Wilson Snyder. This program is free software; you can
// redistribute it and/or modify it under the terms of either the GNU
// Lesser General Public License Version 3 or the Perl Artistic License
// Version 2.0.
module t;
export "DPI-C" task dpix_task;
task dpix_task();
$write("Hello in %m\n");
endtask
endmodule

View File

@ -34,14 +34,17 @@ module t (/*AUTOARG*/
input clk;
test_if #( .FOO (identity(5)) ) the_interface ();
test_if #( .FOO (identity(7)) ) array_interface [1:0] ();
testmod testmod_i (.clk (clk),
.intf (the_interface),
.intf_no_mp (the_interface)
.intf_no_mp (the_interface),
.intf_array (array_interface)
);
localparam THE_TOP_FOO = the_interface.FOO;
localparam THE_TOP_FOO_BITS = $bits({the_interface.FOO, the_interface.FOO});
localparam THE_ARRAY_FOO = array_interface[0].FOO;
initial begin
if (THE_TOP_FOO != 5) begin
@ -52,6 +55,10 @@ module t (/*AUTOARG*/
$display("%%Error: THE_TOP_FOO_BITS = %0d", THE_TOP_FOO_BITS);
$stop;
end
if (THE_ARRAY_FOO != 7) begin
$display("%%Error: THE_ARRAY_FOO = %0d", THE_ARRAY_FOO);
$stop;
end
end
endmodule
@ -61,11 +68,13 @@ module testmod
(
input clk,
test_if.mp intf,
test_if intf_no_mp
test_if intf_no_mp,
test_if.mp intf_array [1:0]
);
localparam THE_FOO = intf.FOO;
localparam THE_OTHER_FOO = intf_no_mp.FOO;
localparam THE_ARRAY_FOO = intf_array[0].FOO;
always @(posedge clk) begin
if (THE_FOO != 5) begin
@ -76,6 +85,10 @@ module testmod
$display("%%Error: THE_OTHER_FOO = %0d", THE_OTHER_FOO);
$stop;
end
if (THE_ARRAY_FOO != 7) begin
$display("%%Error: THE_ARRAY_FOO = %0d", THE_ARRAY_FOO);
$stop;
end
if (intf.FOO != 5) begin
$display("%%Error: intf.FOO = %0d", intf.FOO);
$stop;
@ -84,6 +97,10 @@ module testmod
$display("%%Error: intf_no_mp.FOO = %0d", intf_no_mp.FOO);
$stop;
end
if (intf_array[0].FOO != 7) begin
$display("%%Error: intf_array[0].FOO = %0d", intf_array[0].FOO);
$stop;
end
// if (i.getFoo() != 5) begin
// $display("%%Error: i.getFoo() = %0d", i.getFoo());
// $stop;