Merge from master.
This commit is contained in:
commit
1c3b8229b4
15
Changes
15
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 </<= 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
|
||||
|
||||
|
|
|
|||
|
|
@ -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/
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
14
src/V3Ast.h
14
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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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); }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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; }
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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());
|
||||
|
|
|
|||
|
|
@ -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; }
|
||||
|
|
|
|||
|
|
@ -599,6 +599,7 @@ public:
|
|||
if (debug()>=6) m_graphp->dumpDotFilePrefixed("comp_out");
|
||||
}
|
||||
~DfaGraphComplement() {}
|
||||
VL_UNCOPYABLE(DfaGraphComplement);
|
||||
};
|
||||
|
||||
void DfaGraph::dfaComplement() {
|
||||
|
|
|
|||
|
|
@ -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*)
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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; }
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -127,7 +127,7 @@ void OrderGraph::loopsVertexCb(V3GraphVertex* vertexp) {
|
|||
<<" Example path: "
|
||||
<<vvertexp->varScp()->prettyName()<<endl;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
//######################################################################
|
||||
|
||||
|
|
|
|||
|
|
@ -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()) {
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -102,8 +102,8 @@ public:
|
|||
protected:
|
||||
// CONSTRUCTORS
|
||||
V3PreProc() {
|
||||
m_debug=0;
|
||||
};
|
||||
m_debug = 0;
|
||||
}
|
||||
void configure(FileLine* fl);
|
||||
public:
|
||||
static V3PreProc* createPreProc(FileLine* fl);
|
||||
|
|
|
|||
|
|
@ -505,6 +505,6 @@ private:
|
|||
|
||||
namespace V3ScoreboardBase {
|
||||
void selfTest();
|
||||
};
|
||||
}
|
||||
|
||||
#endif // Guard
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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()) {}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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() {
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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!;
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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...
|
||||
|
|
@ -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;
|
||||
|
|
@ -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
|
||||
|
|
@ -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;
|
||||
|
|
|
|||
Loading…
Reference in New Issue