diff --git a/Changes b/Changes index 4a99d0189..21cb7b1d3 100644 --- a/Changes +++ b/Changes @@ -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 (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(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; } diff --git a/include/verilated_fst_c.cpp b/include/verilated_fst_c.cpp index 976e171e7..2e2533cbc 100644 --- a/include/verilated_fst_c.cpp +++ b/include/verilated_fst_c.cpp @@ -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 #else +# include # include #endif diff --git a/include/verilated_vpi.cpp b/include/verilated_vpi.cpp index 1de5908c0..d22c1c807 100644 --- a/include/verilated_vpi.cpp +++ b/include/verilated_vpi.cpp @@ -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(); diff --git a/src/V3Ast.h b/src/V3Ast.h index 79fc039df..4af07e190 100644 --- a/src/V3Ast.h +++ b/src/V3Ast.h @@ -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 diff --git a/src/V3AstNodes.cpp b/src/V3AstNodes.cpp index 1ac50e7bf..835758651 100644 --- a/src/V3AstNodes.cpp +++ b/src/V3AstNodes.cpp @@ -630,7 +630,7 @@ std::pair 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; diff --git a/src/V3AstNodes.h b/src/V3AstNodes.h index 04bd1b04e..dcba2822f 100644 --- a/src/V3AstNodes.h +++ b/src/V3AstNodes.h @@ -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); } } diff --git a/src/V3CUse.cpp b/src/V3CUse.cpp index 72ed029ac..f13ed23d0 100644 --- a/src/V3CUse.cpp +++ b/src/V3CUse.cpp @@ -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); } diff --git a/src/V3Config.cpp b/src/V3Config.cpp index 0528ca921..b1f0b0237 100644 --- a/src/V3Config.cpp +++ b/src/V3Config.cpp @@ -41,9 +41,9 @@ template 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; } diff --git a/src/V3Const.cpp b/src/V3Const.cpp index 2ae16580a..5ba0db8a2 100644 --- a/src/V3Const.cpp +++ b/src/V3Const.cpp @@ -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: "< "<__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"); + 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"); + 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));\n"); + puts( "uint32_t* count32p = reinterpret_cast(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"); } diff --git a/src/V3EmitCSyms.cpp b/src/V3EmitCSyms.cpp index 214fff4fd..6cdc1c635 100644 --- a/src/V3EmitCSyms.cpp +++ b/src/V3EmitCSyms.cpp @@ -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"); + puts(" __Vcoverage["); + puts(cvtToStr(m_coverBins)); + puts("];\n"); } if (!m_scopeNames.empty()) { // Scope names diff --git a/src/V3EmitMk.cpp b/src/V3EmitMk.cpp index ad7d91386..284e02bc4 100644 --- a/src/V3EmitMk.cpp +++ b/src/V3EmitMk.cpp @@ -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"); diff --git a/src/V3FileLine.cpp b/src/V3FileLine.cpp index d27440602..7dad8ea66 100644 --- a/src/V3FileLine.cpp +++ b/src/V3FileLine.cpp @@ -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) diff --git a/src/V3FileLine.h b/src/V3FileLine.h index 44ccb7ab9..dc9643d26 100644 --- a/src/V3FileLine.h +++ b/src/V3FileLine.h @@ -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); diff --git a/src/V3Gate.cpp b/src/V3Gate.cpp index f4db76775..7ecacc26a 100644 --- a/src/V3Gate.cpp +++ b/src/V3Gate.cpp @@ -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 "<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(edgep->top()); diff --git a/src/V3Graph.h b/src/V3Graph.h index c57aa3923..14c757494 100644 --- a/src/V3Graph.h +++ b/src/V3Graph.h @@ -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; } diff --git a/src/V3GraphDfa.cpp b/src/V3GraphDfa.cpp index 1716f8657..81af99039 100644 --- a/src/V3GraphDfa.cpp +++ b/src/V3GraphDfa.cpp @@ -599,6 +599,7 @@ public: if (debug()>=6) m_graphp->dumpDotFilePrefixed("comp_out"); } ~DfaGraphComplement() {} + VL_UNCOPYABLE(DfaGraphComplement); }; void DfaGraph::dfaComplement() { diff --git a/src/V3GraphDfa.h b/src/V3GraphDfa.h index 21009ef57..193279631 100644 --- a/src/V3GraphDfa.h +++ b/src/V3GraphDfa.h @@ -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*) diff --git a/src/V3GraphPathChecker.h b/src/V3GraphPathChecker.h index 2d248363b..7b6024eee 100644 --- a/src/V3GraphPathChecker.h +++ b/src/V3GraphPathChecker.h @@ -42,8 +42,8 @@ class GraphPathChecker : GraphAlg { public: // CONSTRUCTORS - GraphPathChecker(const V3Graph* graphp, - V3EdgeFuncP edgeFuncp = V3GraphEdge::followAlwaysTrue); + explicit GraphPathChecker(const V3Graph* graphp, + V3EdgeFuncP edgeFuncp = V3GraphEdge::followAlwaysTrue); ~GraphPathChecker(); // METHODS diff --git a/src/V3GraphStream.h b/src/V3GraphStream.h index a1bd9a1bb..b949b0418 100644 --- a/src/V3GraphStream.h +++ b/src/V3GraphStream.h @@ -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. diff --git a/src/V3Inline.cpp b/src/V3Inline.cpp index 68843c59c..dd32eda44 100644 --- a/src/V3Inline.cpp +++ b/src/V3Inline.cpp @@ -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); diff --git a/src/V3LangCode.h b/src/V3LangCode.h index ab4509e97..c66d4b76d 100644 --- a/src/V3LangCode.h +++ b/src/V3LangCode.h @@ -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; } diff --git a/src/V3LinkCells.cpp b/src/V3LinkCells.cpp index 1a49d5855..8e4ea4b29 100644 --- a/src/V3LinkCells.cpp +++ b/src/V3LinkCells.cpp @@ -385,9 +385,7 @@ private: <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. diff --git a/src/V3LinkDot.cpp b/src/V3LinkDot.cpp index 30d88d6a8..c7a045d1d 100644 --- a/src/V3LinkDot.cpp +++ b/src/V3LinkDot.cpp @@ -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) { diff --git a/src/V3Number.cpp b/src/V3Number.cpp index 00a043c68..b5900bc51 100644 --- a/src/V3Number.cpp +++ b/src/V3Number.cpp @@ -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; bitwidth(); 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 diff --git a/src/V3Number.h b/src/V3Number.h index 73a2f4907..a53e886ca 100644 --- a/src/V3Number.h +++ b/src/V3Number.h @@ -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(); } diff --git a/src/V3Options.cpp b/src/V3Options.cpp index 7b3cc7735..eb56d87b2 100644 --- a/src/V3Options.cpp +++ b/src/V3Options.cpp @@ -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 diff --git a/src/V3Order.cpp b/src/V3Order.cpp index 3cd4d6782..f594320b9 100644 --- a/src/V3Order.cpp +++ b/src/V3Order.cpp @@ -127,7 +127,7 @@ void OrderGraph::loopsVertexCb(V3GraphVertex* vertexp) { <<" Example path: " <varScp()->prettyName()<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 "<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()) { diff --git a/src/V3Partition.cpp b/src/V3Partition.cpp index e6fbc3cfd..f742fdad2 100644 --- a/src/V3Partition.cpp +++ b/src/V3Partition.cpp @@ -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) { diff --git a/src/V3PreProc.cpp b/src/V3PreProc.cpp index f49464eae..102ca4cef 100644 --- a/src/V3PreProc.cpp +++ b/src/V3PreProc.cpp @@ -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 m_states; ///< Current state of parser int m_off; ///< If non-zero, ifdef level is turned off, don't dump text diff --git a/src/V3PreProc.h b/src/V3PreProc.h index b7cb47103..9e09dfe93 100644 --- a/src/V3PreProc.h +++ b/src/V3PreProc.h @@ -102,8 +102,8 @@ public: protected: // CONSTRUCTORS V3PreProc() { - m_debug=0; - }; + m_debug = 0; + } void configure(FileLine* fl); public: static V3PreProc* createPreProc(FileLine* fl); diff --git a/src/V3Scoreboard.h b/src/V3Scoreboard.h index db6362929..8fd72dcd5 100644 --- a/src/V3Scoreboard.h +++ b/src/V3Scoreboard.h @@ -505,6 +505,6 @@ private: namespace V3ScoreboardBase { void selfTest(); -}; +} #endif // Guard diff --git a/src/V3Simulate.h b/src/V3Simulate.h index f97876d6b..86b934e7a 100644 --- a/src/V3Simulate.h +++ b/src/V3Simulate.h @@ -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; diff --git a/src/V3Stats.cpp b/src/V3Stats.cpp index 064ed353f..27562f72f 100644 --- a/src/V3Stats.cpp +++ b/src/V3Stats.cpp @@ -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); diff --git a/src/V3SymTable.h b/src/V3SymTable.h index da7185397..b0a504caa 100644 --- a/src/V3SymTable.h +++ b/src/V3SymTable.h @@ -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); } diff --git a/src/V3Task.cpp b/src/V3Task.cpp index 72cb3c9e4..ac9d669c2 100644 --- a/src/V3Task.cpp +++ b/src/V3Task.cpp @@ -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); } diff --git a/src/V3Trace.cpp b/src/V3Trace.cpp index 864010e45..aa6f67756 100644 --- a/src/V3Trace.cpp +++ b/src/V3Trace.cpp @@ -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 diff --git a/src/V3Unroll.cpp b/src/V3Unroll.cpp index 25408ef5b..73e8c5dd6 100644 --- a/src/V3Unroll.cpp +++ b/src/V3Unroll.cpp @@ -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()) {} diff --git a/src/V3Width.cpp b/src/V3Width.cpp index 8c18da24c..512bb9676 100644 --- a/src/V3Width.cpp +++ b/src/V3Width.cpp @@ -1138,9 +1138,9 @@ private: default: nodep->v3error("Unhandled attribute type"); } } else { - std::pair dim + std::pair 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 "<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); } } } diff --git a/src/V3WidthSel.cpp b/src/V3WidthSel.cpp index d6e866185..ae3e4946d 100644 --- a/src/V3WidthSel.cpp +++ b/src/V3WidthSel.cpp @@ -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(); diff --git a/src/VlcMain.cpp b/src/VlcMain.cpp index aa1247fa2..99e018446 100644 --- a/src/VlcMain.cpp +++ b/src/VlcMain.cpp @@ -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() { diff --git a/src/astgen b/src/astgen index ed42a54bf..ad1d5ed45 100644 --- a/src/astgen +++ b/src/astgen @@ -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(); } diff --git a/src/cppcheck_filtered b/src/cppcheck_filtered index 6bc699092..1f962ea58 100755 --- a/src/cppcheck_filtered +++ b/src/cppcheck_filtered @@ -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!; diff --git a/src/verilog.y b/src/verilog.y index 875564aa3..acfcf0329 100644 --- a/src/verilog.y +++ b/src/verilog.y @@ -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 '"<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 '"<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"); diff --git a/test_regress/t/t_dpi_export_context_bad.cpp b/test_regress/t/t_dpi_export_context_bad.cpp new file mode 100644 index 000000000..135bc7d3c --- /dev/null +++ b/test_regress/t/t_dpi_export_context_bad.cpp @@ -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 +#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; +} diff --git a/test_regress/t/t_dpi_export_context_bad.out b/test_regress/t/t_dpi_export_context_bad.out new file mode 100644 index 000000000..dc2091af3 --- /dev/null +++ b/test_regress/t/t_dpi_export_context_bad.out @@ -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... diff --git a/test_regress/t/t_dpi_export_context_bad.pl b/test_regress/t/t_dpi_export_context_bad.pl new file mode 100755 index 000000000..72e2ef077 --- /dev/null +++ b/test_regress/t/t_dpi_export_context_bad.pl @@ -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; diff --git a/test_regress/t/t_dpi_export_context_bad.v b/test_regress/t/t_dpi_export_context_bad.v new file mode 100644 index 000000000..ec52623af --- /dev/null +++ b/test_regress/t/t_dpi_export_context_bad.v @@ -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 diff --git a/test_regress/t/t_interface_parameter_access.v b/test_regress/t/t_interface_parameter_access.v index 40f363153..f21948da8 100644 --- a/test_regress/t/t_interface_parameter_access.v +++ b/test_regress/t/t_interface_parameter_access.v @@ -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;