Merge branch 'master' into develop-v5

This commit is contained in:
Geza Lore 2022-09-15 10:25:30 +01:00
commit 27031ed688
103 changed files with 1819 additions and 408 deletions

View File

@ -11,7 +11,7 @@ on:
jobs:
Test:
name: "'docs/CONTRIBUTORS' was signed"
runs-on: ubuntu-20.04
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v2
- run: test_regress/t/t_dist_contributors.pl

18
Changes
View File

@ -24,9 +24,21 @@ Verilator 5.001 devel
Verilator 4.227 devel
==========================
**Announcement:**
* The next release is anticipated primere Verilator Version 5. Please
consider beta-testing the github 'develop-v5' branch, which will soon
merge into the github 'master' branch (#3383).
**Minor:**
Fix crash in gate optimization of circular logic (#3543). [Bill Flynn]
* Support IEEE constant signal strengths (#3601). [Ryszard Rozak/Antmicro]
* Add --main to generate main() C++ (previously was experimental only).
* Fix thread saftey in SystemC VL_ASSIGN_SBW/WSB (#3494) (#3513). [Mladen Slijepcevic]
* Fix crash in gate optimization of circular logic (#3543). [Bill Flynn]
* Fix arguments in non-static method call (#3547) (#3582). [Gustav Svensk]
* Fix default --mod-prefix when --prefix is repeated (#3603). [Geza Lore]
* Fix typedef'ed class conversion to boolean (#3616). [Aleksander Kiryk]
Verilator 4.226 2022-08-31
@ -46,7 +58,7 @@ Verilator 4.226 2022-08-31
* Fix incorrect tristate logic (#3399) [shareefj, Vighnesh Iyer]
* Fix incorrect bit op tree optimization (#3470). [algrobman]
* Fix bisonpre for MSYS2 (#3471).
* Fix max memory usage (#3483). [Kamil Rakoczy]
* Fix max memory usage (#3483). [Kamil Rakoczy/Antmicro]
* Fix empty string arguments to display (#3484). [Grulfen]
* Fix table misoptimizing away display (#3488). [Stefan Post]
* Fix unique_ptr memory header for MinGW64 (#3493).
@ -57,7 +69,7 @@ Verilator 4.226 2022-08-31
* Fix segfault exporting non-existant package (#3535).
* Fix void-cast queue pop_front or pop_back (#3542) (#3364). [Drew Ranck]
* Fix case statement comparing string literal (#3544). [Gustav Svensk]
* Fix === with some tristate constants (#3551). [Ryszard Rozak]
* Fix === with some tristate constants (#3551). [Ryszard Rozak/Antmicro]
* Fix converting subclasses to string (#3552). [Arkadiusz Kozdra/Antmicro]
* Fix --hierarchical with order-based pin connections (#3583) (#3585). [Kelin9298]

View File

@ -391,10 +391,10 @@ yapf:
FLAKE8 = flake8
FLAKE8_FLAGS = \
--extend-exclude=fastcov.py \
--ignore=E123,E129,E251,E501,W503,W504,E701
--ignore=E123,E129,E251,E402,E501,W503,W504,E701
PYLINT = pylint
PYLINT_FLAGS = --disable=R0801
PYLINT_FLAGS = --score=n --disable=R0801
lint-py:
-$(FLAKE8) $(FLAKE8_FLAGS) $(PY_PROGRAMS)

View File

@ -28,7 +28,7 @@ Welcome to Verilator
- |Logo|
* - |verilator multithreaded performance|
- **Fast**
* Outperforms many commercial simulators
* Outperforms many closed-source commercial simulators
* Single- and multi-threaded output models
* - **Widely Used**
* Wide industry and academic deployment
@ -55,20 +55,19 @@ performing lint checks, and optionally inserting assertion checks and
coverage-analysis points. It outputs single- or multi-threaded .cpp and .h
files, the "Verilated" code.
The user writes a little C++/SystemC wrapper file, which instantiates the
"Verilated" model of the user's top level module. These C++/SystemC files
are then compiled by a C++ compiler (gcc/clang/MSVC++). Executing the
resulting executable performs the design simulation. Verilator also
supports linking Verilated generated libraries, optionally encrypted, into
other simulators.
These Verilated C++/SystemC files are then compiled by a C++ compiler
(gcc/clang/MSVC++), optionally along with a user's own C++/SystemC wrapper
file to instantiate the Verilated model. Executing the resulting executable
performs the design simulation. Verilator also supports linking Verilated
generated libraries, optionally encrypted, into other simulators.
Verilator may not be the best choice if you are expecting a full featured
replacement for Incisive, ModelSim/Questa, VCS or another commercial
Verilog simulator, or if you are looking for a behavioral Verilog simulator
e.g. for a quick class project (we recommend `Icarus Verilog`_ for this.)
However, if you are looking for a path to migrate SystemVerilog to C++ or
SystemC, or your team is comfortable writing just a touch of C++ code,
Verilator is the tool for you.
replacement for a closed-source Verilog simulator, need SDF annotation,
mixed-signal simulation, or are doing a quick class project (we recommend
`Icarus Verilog`_ for classwork.) However, if you are looking for a path
to migrate SystemVerilog to C++/SystemC, or want high speed simulation of
synthesizable designs containing limited verification constructs, Verilator
is the tool for you.
Performance
@ -85,9 +84,11 @@ multithreading (yielding 200-1000x total over interpreted simulators).
Verilator has typically similar or better performance versus the
closed-source Verilog simulators (Carbon Design Systems Carbonator,
Modelsim, Cadence Incisive/NC-Verilog, Synopsys VCS, VTOC, and Pragmatic
CVer/CVC). But, Verilator is open-sourced, so you can spend on computes
rather than licenses. Thus Verilator gives you the best cycles/dollar.
Modelsim/Questa, Cadence Incisive/NC-Verilog, Synopsys VCS, VTOC, and
Pragmatic CVer/CVC). But, Verilator is open-sourced, so you can spend on
computes rather than licenses. Thus Verilator gives you the best
cycles/dollar.
Installation & Documentation
============================

View File

@ -344,6 +344,7 @@ detailed descriptions of these arguments.
--main Generate a main C++ file
--make <build-tool> Generate scripts for specified build tool
-MAKEFLAGS <flags> Arguments to pass to make during --build
--main Generate C++ main()
--max-num-width <value> Maximum number width (default: 64K)
--Mdir <directory> Name of output object directory
--MMD Create .d dependency files

View File

@ -38,7 +38,7 @@ def diff_dir(a, b):
anyfile = False
for base in sorted(files.keys()):
if (not 'a' in files[base]) or (not 'b' in files[base]):
if ('a' not in files[base]) or ('b' not in files[base]):
continue
a = files[base]['a']
b = files[base]['b']

View File

@ -149,7 +149,8 @@ def report():
for thread in Threads:
# Make potentially multiple characters per column
for start in Threads[thread]:
if not Threads[thread][start]: continue
if not Threads[thread][start]:
continue
cpu = Threads[thread][start]['cpu']
elapsed = Threads[thread][start]['end'] - start
if cpu not in Global['cpus']:

View File

@ -19,6 +19,10 @@ set -x
cd $(dirname "$0")/..
# Avoid occasional cpan failures "Issued certificate has expired."
export PERL_LWP_SSL_VERIFY_HOSTNAME=0
echo "check_certificate = off" >> ~/.wgetrc
fatal() {
echo "ERROR: $(basename "$0"): $1" >&2; exit 1;
}

View File

@ -82,6 +82,7 @@ Michael Killough
Michaël Lefebvre
Mike Popoloski
Miodrag Milanović
Mladen Slijepcevic
Morten Borup Petersen
Mostafa Gamal
Nandu Raj

View File

@ -716,6 +716,15 @@ Summary:
(e.g. ``-MAKEFLAGS -l -MAKEFLAGS -k``). Use of this option should not be
required for simple builds using the host toolchain.
.. option:: --main
Generates a top-level C++ main() file that supports parsing arguments,
but does not drive any inputs. This is sufficient to use for top-level
SystemVerilog designs that has no inputs, and does not need the C++ to
do any time advancement.
Implies :vlopt:`--cc` if no other output mode was provided.
.. option:: --max-num-width <value>
Set the maximum number literal width (e.g. in 1024'd22 this it the

View File

@ -7,9 +7,9 @@
Simulating (Verilated-Model Runtime)
************************************
This section describes items related to simulating, that using a Verilated
model's executable. For the runtime arguments to a simulated model, see
:ref:`Simulation Runtime Arguments`.
This section describes items related to simulating, that is, the use of a
Verilated model's executable. For the runtime arguments to a simulated
model, see :ref:`Simulation Runtime Arguments`.
.. _Benchmarking & Optimization:

View File

@ -32,7 +32,7 @@ int main(int argc, char** argv, char** env) {
// When tracing, the contents of the secret module will not be seen
VerilatedVcdC* tfp = nullptr;
const char* flag = contextp->commandArgsPlusMatch("trace");
if (flag && 0 == strcmp(flag, "+trace")) {
if (flag && 0 == std::strcmp(flag, "+trace")) {
contextp->traceEverOn(true);
VL_PRINTF("Enabling waves into logs/vlt_dump.vcd...\n");
tfp = new VerilatedVcdC;

View File

@ -89,7 +89,7 @@ int sc_main(int argc, char* argv[]) {
// and if at run time passed the +trace argument, turn on tracing
VerilatedVcdSc* tfp = nullptr;
const char* flag = Verilated::commandArgsPlusMatch("trace");
if (flag && 0 == strcmp(flag, "+trace")) {
if (flag && 0 == std::strcmp(flag, "+trace")) {
cout << "Enabling waves into logs/vlt_dump.vcd...\n";
tfp = new VerilatedVcdSc;
top->trace(tfp, 99); // Trace 99 levels of hierarchy

View File

@ -448,10 +448,17 @@ static inline void VL_ASSIGNBIT_WO(int bit, WDataOutP owp) VL_MT_SAFE {
{ \
const int words = VL_WORDS_I(obits); \
sc_biguint<(obits)> _butemp = (svar).read(); \
for (int i = 0; i < words; ++i) { \
int msb = ((i + 1) * VL_IDATASIZE) - 1; \
msb = (msb >= (obits)) ? ((obits)-1) : msb; \
(owp)[i] = _butemp.range(msb, i * VL_IDATASIZE).to_uint(); \
uint32_t* chunk = _butemp.get_raw(); \
int32_t lsb = 0; \
while (lsb < obits - BITS_PER_DIGIT) { \
const uint32_t data = *chunk; \
++chunk; \
_vl_insert_WI(owp.data(), data, lsb + BITS_PER_DIGIT - 1, lsb); \
lsb += BITS_PER_DIGIT; \
} \
if (lsb < obits) { \
const uint32_t msb_data = *chunk; \
_vl_insert_WI(owp.data(), msb_data, obits - 1, lsb); \
} \
(owp)[words - 1] &= VL_MASK_E(obits); \
}
@ -492,13 +499,23 @@ static inline void VL_ASSIGNBIT_WO(int bit, WDataOutP owp) VL_MT_SAFE {
{ (svar).write(rd); }
#define VL_ASSIGN_SBQ(obits, svar, rd) \
{ (svar).write(rd); }
#define VL_SC_BITS_PER_DIGIT 30 // This comes from sc_nbdefs.h BITS_PER_DIGIT
#define VL_ASSIGN_SBW(obits, svar, rwp) \
{ \
sc_biguint<(obits)> _butemp; \
for (int i = 0; i < VL_WORDS_I(obits); ++i) { \
int msb = ((i + 1) * VL_IDATASIZE) - 1; \
msb = (msb >= (obits)) ? ((obits)-1) : msb; \
_butemp.range(msb, i* VL_IDATASIZE) = (rwp)[i]; \
int32_t lsb = 0; \
uint32_t* chunk = _butemp.get_raw(); \
while (lsb + VL_SC_BITS_PER_DIGIT < (obits)) { \
static_assert(std::is_same<IData, EData>::value, "IData and EData missmatch"); \
const uint32_t data = VL_SEL_IWII(lsb + VL_SC_BITS_PER_DIGIT + 1, (rwp).data(), lsb, \
VL_SC_BITS_PER_DIGIT); \
*chunk = data & VL_MASK_E(VL_SC_BITS_PER_DIGIT); \
++chunk; \
lsb += VL_SC_BITS_PER_DIGIT; \
} \
if (lsb < (obits)) { \
const uint32_t msb_data = VL_SEL_IWII((obits) + 1, (rwp).data(), lsb, (obits)-lsb); \
*chunk = msb_data & VL_MASK_E((obits)-lsb); \
} \
(svar).write(_butemp); \
}

View File

@ -165,22 +165,22 @@ string AstNode::prettyName(const string& namein) {
continue;
}
if (pos[0] == '_' && pos[1] == '_') { // Short-circuit
if (0 == strncmp(pos, "__BRA__", 7)) {
if (0 == std::strncmp(pos, "__BRA__", 7)) {
pretty += "[";
pos += 7;
continue;
}
if (0 == strncmp(pos, "__KET__", 7)) {
if (0 == std::strncmp(pos, "__KET__", 7)) {
pretty += "]";
pos += 7;
continue;
}
if (0 == strncmp(pos, "__DOT__", 7)) {
if (0 == std::strncmp(pos, "__DOT__", 7)) {
pretty += ".";
pos += 7;
continue;
}
if (0 == strncmp(pos, "__PVT__", 7)) {
if (0 == std::strncmp(pos, "__PVT__", 7)) {
pretty += "";
pos += 7;
continue;

View File

@ -517,8 +517,9 @@ public:
return names[m_e];
}
static void selfTest() {
UASSERT(0 == strcmp(VBasicDTypeKwd(_ENUM_MAX).ascii(), " MAX"), "SelfTest: Enum mismatch");
UASSERT(0 == strcmp(VBasicDTypeKwd(_ENUM_MAX).dpiType(), " MAX"),
UASSERT(0 == std::strcmp(VBasicDTypeKwd(_ENUM_MAX).ascii(), " MAX"),
"SelfTest: Enum mismatch");
UASSERT(0 == std::strcmp(VBasicDTypeKwd(_ENUM_MAX).dpiType(), " MAX"),
"SelfTest: Enum mismatch");
}
inline VBasicDTypeKwd()
@ -786,6 +787,10 @@ public:
return (m_e == WIRE || m_e == WREAL || m_e == IMPLICITWIRE || m_e == TRIWIRE || m_e == TRI0
|| m_e == TRI1 || m_e == PORT || m_e == SUPPLY0 || m_e == SUPPLY1 || m_e == VAR);
}
bool isNet() const {
return (m_e == WIRE || m_e == IMPLICITWIRE || m_e == TRIWIRE || m_e == TRI0 || m_e == TRI1
|| m_e == SUPPLY0 || m_e == SUPPLY1);
}
bool isContAssignable() const { // In Verilog, always ok in SystemVerilog
return (m_e == SUPPLY0 || m_e == SUPPLY1 || m_e == WIRE || m_e == WREAL
|| m_e == IMPLICITWIRE || m_e == TRIWIRE || m_e == TRI0 || m_e == TRI1
@ -1029,6 +1034,32 @@ inline std::ostream& operator<<(std::ostream& os, const VParseRefExp& rhs) {
return os << rhs.ascii();
}
//######################################################################
class VStrength final {
public:
enum en : uint8_t { HIGHZ, SMALL, MEDIUM, WEAK, LARGE, PULL, STRONG, SUPPLY };
enum en m_e;
inline VStrength(en strengthLevel)
: m_e(strengthLevel) {}
explicit inline VStrength(int _e)
: m_e(static_cast<en>(_e)) {} // Need () or GCC 4.8 false warning
operator en() const { return m_e; }
const char* ascii() const {
static const char* const names[]
= {"highz", "small", "medium", "weak", "large", "pull", "strong", "supply"};
return names[m_e];
}
};
inline bool operator==(const VStrength& lhs, const VStrength& rhs) { return lhs.m_e == rhs.m_e; }
inline bool operator==(const VStrength& lhs, VStrength::en rhs) { return lhs.m_e == rhs; }
inline bool operator==(VStrength::en lhs, const VStrength& rhs) { return lhs == rhs.m_e; }
inline std::ostream& operator<<(std::ostream& os, const VStrength& rhs) {
return os << rhs.ascii();
}
//######################################################################
// VNumRange - Structure containing numeric range information
// See also AstRange, which is a symbolic version of this

View File

@ -1834,6 +1834,10 @@ void AstSenItem::dump(std::ostream& str) const {
this->AstNode::dump(str);
str << " [" << edgeType().ascii() << "]";
}
void AstStrengthSpec::dump(std::ostream& str) const {
this->AstNode::dump(str);
str << " (" << m_s0.ascii() << ", " << m_s1.ascii() << ")";
}
void AstParseRef::dump(std::ostream& str) const {
this->AstNode::dump(str);
str << " [" << expect().ascii() << "]";

View File

@ -290,6 +290,23 @@ public:
virtual bool same(const AstNode* /*samep*/) const override { return true; }
};
class AstStrengthSpec final : public AstNode {
private:
VStrength m_s0; // Drive 0 strength
VStrength m_s1; // Drive 1 strength
public:
AstStrengthSpec(FileLine* fl, VStrength s0, VStrength s1)
: ASTGEN_SUPER_StrengthSpec(fl)
, m_s0{s0}
, m_s1{s1} {}
ASTNODE_NODE_FUNCS(StrengthSpec)
VStrength strength0() { return m_s0; }
VStrength strength1() { return m_s1; }
virtual void dump(std::ostream& str) const override;
};
class AstGatePin final : public AstNodeMath {
// Possibly expand a gate primitive input pin value to match the range of the gate primitive
public:
@ -2098,6 +2115,7 @@ private:
bool m_isRand : 1; // Random variable
bool m_isConst : 1; // Table contains constant data
bool m_isContinuously : 1; // Ever assigned continuously (for force/release)
bool m_hasStrengthAssignment : 1; // Is on LHS of assignment with strength specifier
bool m_isStatic : 1; // Static C variable (for Verilog see instead isAutomatic)
bool m_isPulldown : 1; // Tri0
bool m_isPullup : 1; // Tri1
@ -2139,6 +2157,7 @@ private:
m_isRand = false;
m_isConst = false;
m_isContinuously = false;
m_hasStrengthAssignment = false;
m_isStatic = false;
m_isPulldown = false;
m_isPullup = false;
@ -2303,6 +2322,8 @@ public:
void isIfaceParent(bool flag) { m_isIfaceParent = flag; }
void funcLocal(bool flag) { m_funcLocal = flag; }
void funcReturn(bool flag) { m_funcReturn = flag; }
void hasStrengthAssignment(bool flag) { m_hasStrengthAssignment = flag; }
bool hasStrengthAssignment() { return m_hasStrengthAssignment; }
void isDpiOpenArray(bool flag) { m_isDpiOpenArray = flag; }
bool isDpiOpenArray() const { return m_isDpiOpenArray; }
bool isHideLocal() const { return m_isHideLocal; }
@ -2340,6 +2361,7 @@ public:
bool isIfaceRef() const { return (varType() == VVarType::IFACEREF); }
bool isIfaceParent() const { return m_isIfaceParent; }
bool isSignal() const { return varType().isSignal(); }
bool isNet() const { return varType().isNet(); }
bool isTemp() const { return varType().isTemp(); }
bool isToggleCoverable() const {
return ((isIO() || isSignal())
@ -3648,6 +3670,8 @@ public:
AstAssignW(FileLine* fl, AstNode* lhsp, AstNode* rhsp, AstNode* timingControlp = nullptr)
: ASTGEN_SUPER_AssignW(fl, lhsp, rhsp, timingControlp) {}
ASTNODE_NODE_FUNCS(AssignW)
AstStrengthSpec* strengthSpecp() const { return VN_AS(op4p(), StrengthSpec); }
void strengthSpecp(AstStrengthSpec* const strengthSpecp) { setOp4p((AstNode*)strengthSpecp); }
virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override {
AstNode* const controlp = timingControlp() ? timingControlp()->cloneTree(false) : nullptr;
return new AstAssignW(this->fileline(), lhsp, rhsp, controlp);

View File

@ -86,7 +86,7 @@ private:
string::size_type pos;
while ((pos = dottedname.find("__DOT__")) != string::npos) {
const string ident = dottedname.substr(0, pos);
dottedname = dottedname.substr(pos + strlen("__DOT__"));
dottedname = dottedname.substr(pos + std::strlen("__DOT__"));
if (nodep->name() != "") {
m_displayScope = dot(m_displayScope, ident);
m_namedScope = dot(m_namedScope, ident);

View File

@ -2872,6 +2872,7 @@ private:
if (m_wremove && !m_params && m_doNConst && m_modp && operandConst(nodep->rhsp())
&& !VN_AS(nodep->rhsp(), Const)->num().isFourState()
&& varrefp // Don't do messes with BITREFs/ARRAYREFs
&& !varrefp->varp()->hasStrengthAssignment() // Strengths are resolved in V3Tristate
&& !varrefp->varp()->valuep() // Not already constified
&& !varrefp->varScopep()) { // Not scoped (or each scope may have different initial
// value)

View File

@ -57,11 +57,11 @@ string EmitCBaseVisitor::funcNameProtect(const AstCFunc* nodep, const AstNodeMod
return name;
}
AstCFile* EmitCBaseVisitor::newCFile(const string& filename, bool slow, bool source) {
AstCFile* EmitCBaseVisitor::newCFile(const string& filename, bool slow, bool source, bool add) {
AstCFile* const cfilep = new AstCFile(v3Global.rootp()->fileline(), filename);
cfilep->slow(slow);
cfilep->source(source);
v3Global.rootp()->addFilesp(cfilep);
if (add) v3Global.rootp()->addFilesp(cfilep);
return cfilep;
}

View File

@ -100,7 +100,7 @@ public:
&& (varp->basicp() && !varp->basicp()->isOpaque()); // Aggregates can't be anon
}
static AstCFile* newCFile(const string& filename, bool slow, bool source);
static AstCFile* newCFile(const string& filename, bool slow, bool source, bool add = true);
string cFuncArgs(const AstCFunc* nodep);
void emitCFuncHeader(const AstCFunc* funcp, const AstNodeModule* modp, bool withScope);
void emitCFuncDecl(const AstCFunc* funcp, const AstNodeModule* modp, bool cLinkage = false);

View File

@ -36,18 +36,20 @@ constexpr int EMITC_NUM_CONSTW = 8;
class EmitCLazyDecls final : public VNVisitor {
// NODE STATE/TYPES
// AstNode::user2() -> bool. Already emitted decl for symbols.
const VNUser2InUse m_inuser2;
// None allowed to support threaded emitting
// MEMBERS
std::unordered_set<string> m_emittedManually; // Set of names already declared manually.
EmitCBaseVisitor& m_emitter; // For access to file output
bool m_needsBlankLine = false; // Emit blank line if any declarations were emitted (cosmetic)
std::set<AstNode*> m_emitted; // -> in set. Already emitted decl for symbols.
// METHODS
bool declaredOnce(AstNode* nodep) { return m_emitted.insert(nodep).second; }
void lazyDeclare(AstCFunc* funcp) {
// Already declared in this compilation unit
if (funcp->user2SetOnce()) return;
if (!declaredOnce(funcp)) return;
// Check if this kind of function is lazily declared
if (!(funcp->isMethod() && funcp->isLoose()) && !funcp->dpiImportPrototype()) return;
// Already declared manually
@ -58,7 +60,7 @@ class EmitCLazyDecls final : public VNVisitor {
}
void lazyDeclareConstPoolVar(AstVar* varp) {
if (varp->user2SetOnce()) return; // Already declared
if (!declaredOnce(varp)) return; // Already declared
const string nameProtect
= m_emitter.topClassName() + "__ConstPool__" + varp->nameProtect();
m_emitter.puts("extern const ");
@ -106,8 +108,8 @@ public:
m_emitter.puts(suffix);
m_emitter.ensureNewLine();
}
void declared(AstCFunc* nodep) { nodep->user2SetOnce(); }
void reset() { AstNode::user2ClearTree(); }
void declared(AstCFunc* nodep) { m_emitted.insert(nodep); }
void reset() { m_emitted.clear(); }
};
//######################################################################

View File

@ -148,6 +148,7 @@ class EmitCImp final : EmitCFunc {
const std::set<string>* m_requiredHeadersp; // Header files required by output file
std::string m_subFileName; // substring added to output filenames
V3UniqueNames m_uniqueNames; // For generating unique file names
std::deque<AstCFile*>& m_cfilesr; // cfiles generated by this emit
// METHODS
void openNextOutputFile(const std::set<string>& headers, const string& subFileName) {
@ -160,7 +161,8 @@ class EmitCImp final : EmitCFunc {
// Unfortunately we have some lint checks here, so we can't just skip processing.
// We should move them to a different stage.
const string filename = VL_DEV_NULL;
newCFile(filename, /* slow: */ m_slow, /* source: */ true);
m_cfilesr.push_back(
newCFile(filename, /* slow: */ m_slow, /* source: */ true, /* add */ false));
m_ofp = new V3OutCFile(filename);
} else {
string filename = v3Global.opt.makeDir() + "/" + prefixNameProtect(m_fileModp);
@ -170,7 +172,8 @@ class EmitCImp final : EmitCFunc {
}
if (m_slow) filename += "__Slow";
filename += ".cpp";
newCFile(filename, /* slow: */ m_slow, /* source: */ true);
m_cfilesr.push_back(
newCFile(filename, /* slow: */ m_slow, /* source: */ true, /* add */ false));
m_ofp = v3Global.opt.systemC() ? new V3OutScFile(filename) : new V3OutCFile(filename);
}
@ -527,9 +530,10 @@ class EmitCImp final : EmitCFunc {
EmitCFunc::visit(nodep);
}
explicit EmitCImp(const AstNodeModule* modp, bool slow)
explicit EmitCImp(const AstNodeModule* modp, bool slow, std::deque<AstCFile*>& cfilesr)
: m_fileModp{modp}
, m_slow{slow} {
, m_slow{slow}
, m_cfilesr{cfilesr} {
UINFO(5, " Emitting implementation of " << prefixNameProtect(modp) << endl);
m_modp = modp;
@ -548,7 +552,9 @@ class EmitCImp final : EmitCFunc {
virtual ~EmitCImp() override = default;
public:
static void main(const AstNodeModule* modp, bool slow) { EmitCImp{modp, slow}; }
static void main(const AstNodeModule* modp, bool slow, std::deque<AstCFile*>& cfilesr) {
EmitCImp{modp, slow, cfilesr};
}
};
//######################################################################
@ -556,14 +562,14 @@ public:
class EmitCTrace final : EmitCFunc {
// NODE STATE/TYPES
// Cleared on netlist
// AstNode::user1() -> int. Enum number
const VNUser1InUse m_inuser1;
// None allowed to support threaded emitting
// MEMBERS
const bool m_slow; // Making slow file
int m_enumNum = 0; // Enumeration number (whole netlist)
V3UniqueNames m_uniqueNames; // For generating unique file names
std::unordered_map<AstNode*, int> m_enumNumMap; // EnumDType to enumeration number
std::deque<AstCFile*>& m_cfilesr; // cfiles generated by this emit
// METHODS
void openNextOutputFile() {
@ -578,8 +584,9 @@ class EmitCTrace final : EmitCFunc {
if (m_slow) filename += "__Slow";
filename += ".cpp";
AstCFile* const cfilep = newCFile(filename, m_slow, true /*source*/);
AstCFile* const cfilep = newCFile(filename, m_slow, true /*source*/, false /*add*/);
cfilep->support(true);
m_cfilesr.push_back(cfilep);
if (optSystemC()) {
m_ofp = new V3OutScFile(filename);
@ -715,10 +722,10 @@ class EmitCTrace final : EmitCFunc {
// Skip over refs-to-refs, but stop before final ref so can get data type name
// Alternatively back in V3Width we could push enum names from upper typedefs
if (AstEnumDType* const enump = VN_CAST(nodep->skipRefToEnump(), EnumDType)) {
int enumNum = enump->user1();
int enumNum = m_enumNumMap[enump];
if (!enumNum) {
enumNum = ++m_enumNum;
enump->user1(enumNum);
m_enumNumMap[enump] = enumNum;
int nvals = 0;
puts("{\n");
puts("const char* " + protect("__VenumItemNames") + "[]\n");
@ -868,8 +875,9 @@ class EmitCTrace final : EmitCFunc {
}
}
explicit EmitCTrace(AstNodeModule* modp, bool slow)
: m_slow{slow} {
explicit EmitCTrace(AstNodeModule* modp, bool slow, std::deque<AstCFile*>& cfilesr)
: m_slow{slow}
, m_cfilesr{cfilesr} {
m_modp = modp;
// Open output file
openNextOutputFile();
@ -883,7 +891,9 @@ class EmitCTrace final : EmitCFunc {
virtual ~EmitCTrace() override = default;
public:
static void main(AstNodeModule* modp, bool slow) { EmitCTrace{modp, slow}; }
static void main(AstNodeModule* modp, bool slow, std::deque<AstCFile*>& cfilesr) {
EmitCTrace{modp, slow, cfilesr};
}
};
//######################################################################
@ -893,19 +903,27 @@ void V3EmitC::emitcImp() {
UINFO(2, __FUNCTION__ << ": " << endl);
// Make parent module pointers available.
const EmitCParentModule emitCParentModule;
std::list<std::deque<AstCFile*>> cfiles;
// Process each module in turn
for (const AstNode* nodep = v3Global.rootp()->modulesp(); nodep; nodep = nodep->nextp()) {
if (VN_IS(nodep, Class)) continue; // Imped with ClassPackage
const AstNodeModule* const modp = VN_AS(nodep, NodeModule);
EmitCImp::main(modp, /* slow: */ true);
EmitCImp::main(modp, /* slow: */ false);
cfiles.emplace_back();
EmitCImp::main(modp, /* slow: */ true, cfiles.back());
cfiles.emplace_back();
EmitCImp::main(modp, /* slow: */ false, cfiles.back());
}
// Emit trace routines (currently they can only exist in the top module)
if (v3Global.opt.trace() && !v3Global.opt.lintOnly()) {
EmitCTrace::main(v3Global.rootp()->topModulep(), /* slow: */ true);
EmitCTrace::main(v3Global.rootp()->topModulep(), /* slow: */ false);
cfiles.emplace_back();
EmitCTrace::main(v3Global.rootp()->topModulep(), /* slow: */ true, cfiles.back());
cfiles.emplace_back();
EmitCTrace::main(v3Global.rootp()->topModulep(), /* slow: */ false, cfiles.back());
}
for (const auto& collr : cfiles) {
for (const auto cfilep : collr) v3Global.rootp()->addFilesp(cfilep);
}
}

View File

@ -555,7 +555,7 @@ class EmitCModel final : public EmitCFunc {
// Some hackery to locate handle__V for trace_init_task
// Considered a pragma on the handle, but that still doesn't help us attach it here
string handle = funcp->name();
const size_t wr_len = strlen("__Vdpiimwrap_");
const size_t wr_len = std::strlen("__Vdpiimwrap_");
UASSERT_OBJ(handle.substr(0, wr_len) == "__Vdpiimwrap_", funcp,
"Strange trace_init_task function name");
handle = "vlSymsp->TOP." + handle.substr(wr_len);

View File

@ -211,7 +211,7 @@ class EmitCSyms final : EmitCBaseVisitor {
const string::size_type dpos = whole.rfind("__DOT__");
if (dpos != string::npos) {
scpName = whole.substr(0, dpos);
varBase = whole.substr(dpos + strlen("__DOT__"));
varBase = whole.substr(dpos + std::strlen("__DOT__"));
} else {
varBase = whole;
}

View File

@ -94,7 +94,7 @@ class V3FileDependImp final {
const string fn = filename();
const int err = stat(fn.c_str(), &m_stat);
if (err != 0) {
memset(&m_stat, 0, sizeof(m_stat));
std::memset(&m_stat, 0, sizeof(m_stat));
m_stat.st_mtime = 1;
m_exists = false;
// Not an error... This can occur due to `line directives in the .vpp files
@ -389,7 +389,7 @@ private:
if (!m_pidExited && waitpid(m_pid, &m_pidStatus, hang ? 0 : WNOHANG)) {
UINFO(1, "--pipe-filter: Exited, status "
<< m_pidStatus << " exit=" << WEXITSTATUS(m_pidStatus) << " err"
<< strerror(errno) << endl);
<< std::strerror(errno) << endl);
m_readEof = true;
m_pidExited = true;
}
@ -495,7 +495,7 @@ private:
constexpr int P_WR = 1;
if (pipe(fd_stdin) != 0 || pipe(fd_stdout) != 0) {
v3fatal("--pipe-filter: Can't pipe: " << strerror(errno));
v3fatal("--pipe-filter: Can't pipe: " << std::strerror(errno));
}
if (fd_stdin[P_RD] <= 2 || fd_stdin[P_WR] <= 2 || fd_stdout[P_RD] <= 2
|| fd_stdout[P_WR] <= 2) {
@ -507,7 +507,7 @@ private:
UINFO(1, "--pipe-filter: /bin/sh -c " << command << endl);
const pid_t pid = fork();
if (pid < 0) v3fatal("--pipe-filter: fork failed: " << strerror(errno));
if (pid < 0) v3fatal("--pipe-filter: fork failed: " << std::strerror(errno));
if (pid == 0) { // Child
UINFO(6, "In child\n");
close(fd_stdin[P_WR]);
@ -518,7 +518,7 @@ private:
execl("/bin/sh", "sh", "-c", command.c_str(), static_cast<char*>(nullptr));
// Don't use v3fatal, we don't share the common structures any more
fprintf(stderr, "--pipe-filter: exec failed: %s\n", strerror(errno));
fprintf(stderr, "--pipe-filter: exec failed: %s\n", std::strerror(errno));
_exit(1);
} else { // Parent
UINFO(6, "In parent, child pid " << pid << " stdin " << fd_stdin[P_WR] << "->"

View File

@ -224,7 +224,7 @@ private:
std::size_t len = strlen(str);
std::size_t availableBytes = WRITE_BUFFER_SIZE_BYTES - m_usedBytes;
while (VL_UNLIKELY(len >= availableBytes)) {
memcpy(m_bufferp->data() + m_usedBytes, str, availableBytes);
std::memcpy(m_bufferp->data() + m_usedBytes, str, availableBytes);
m_usedBytes = WRITE_BUFFER_SIZE_BYTES;
writeBlock();
str += availableBytes;
@ -232,7 +232,7 @@ private:
availableBytes = WRITE_BUFFER_SIZE_BYTES;
}
if (len > 0) {
memcpy(m_bufferp->data() + m_usedBytes, str, len);
std::memcpy(m_bufferp->data() + m_usedBytes, str, len);
m_usedBytes += len;
}
}

View File

@ -185,7 +185,7 @@ void FileLine::lineDirective(const char* textp, int& enterExitRef) {
const char* const ln = textp;
while (*textp && !isspace(*textp)) textp++;
if (isdigit(*ln)) {
lineno(atoi(ln));
lineno(std::atoi(ln));
} else {
fail = true;
}
@ -207,7 +207,7 @@ void FileLine::lineDirective(const char* textp, int& enterExitRef) {
// Grab level
while (*textp && (isspace(*textp) || *textp == '"')) textp++;
if (isdigit(*textp)) {
enterExitRef = atoi(textp);
enterExitRef = std::atoi(textp);
if (enterExitRef >= 3) fail = true;
} else {
enterExitRef = 0;

View File

@ -919,7 +919,7 @@ class LinkDotFindVisitor final : public VNVisitor {
string::size_type pos;
if ((pos = dottedname.rfind("__DOT__")) != string::npos) {
const string dotted = dottedname.substr(0, pos);
const string ident = dottedname.substr(pos + strlen("__DOT__"));
const string ident = dottedname.substr(pos + std::strlen("__DOT__"));
string baddot;
VSymEnt* okSymp;
aboveSymp = m_statep->findDotted(nodep->fileline(), aboveSymp, dotted, baddot, okSymp);

View File

@ -37,6 +37,7 @@ private:
// STATE
bool m_setContinuously = false; // Set that var has some continuous assignment
bool m_setStrengthSpecified = false; // Set that var has assignment with strength specified.
VAccess m_setRefLvalue; // Set VarRefs to lvalues for pin assignments
AstNodeFTask* m_ftaskp = nullptr; // Function or task we're inside
@ -51,6 +52,9 @@ private:
if (nodep->varp()) {
if (nodep->access().isWriteOrRW() && m_setContinuously) {
nodep->varp()->isContinuously(true);
// Strength may only be specified in continuous assignment,
// so it is needed to check only if m_setContinuously is true
if (m_setStrengthSpecified) nodep->varp()->hasStrengthAssignment(true);
}
if (nodep->access().isWriteOrRW() && !m_ftaskp && nodep->varp()->isReadOnly()) {
nodep->v3warn(ASSIGNIN,
@ -78,9 +82,13 @@ private:
{
m_setRefLvalue = VAccess::WRITE;
m_setContinuously = VN_IS(nodep, AssignW) || VN_IS(nodep, AssignAlias);
if (AstAssignW* assignwp = VN_CAST(nodep, AssignW)) {
if (assignwp->strengthSpecp()) m_setStrengthSpecified = true;
}
iterateAndNextNull(nodep->lhsp());
m_setRefLvalue = VAccess::NOCHANGE;
m_setContinuously = false;
m_setStrengthSpecified = false;
iterateAndNextNull(nodep->rhsp());
}
}

View File

@ -156,14 +156,15 @@ void V3Number::V3NumberCreate(AstNode* nodep, const char* sourcep, FileLine* fl)
}
value_startp = cp;
if (atoi(widthn.c_str())) {
if (atoi(widthn.c_str()) < 0 || atoi(widthn.c_str()) > v3Global.opt.maxNumWidth()) {
if (std::atoi(widthn.c_str())) {
if (std::atoi(widthn.c_str()) < 0
|| std::atoi(widthn.c_str()) > v3Global.opt.maxNumWidth()) {
// atoi might convert large number to negative, so can't tell which
v3error("Unsupported: Width of number exceeds implementation limit: "
<< sourcep << " (IEEE 1800-2017 6.9.1)");
width(v3Global.opt.maxNumWidth(), true);
} else {
width(atoi(widthn.c_str()), true);
width(std::atoi(widthn.c_str()), true);
}
}
} else {
@ -278,7 +279,8 @@ void V3Number::V3NumberCreate(AstNode* nodep, const char* sourcep, FileLine* fl)
}
} else {
// Convert bin/octal number to hex
for (const char* cp = value_startp + strlen(value_startp) - 1; cp >= value_startp; cp--) {
for (const char* cp = value_startp + std::strlen(value_startp) - 1; cp >= value_startp;
cp--) {
if (*cp != '_' && *cp != '0' && obit >= width()) {
v3error("Too many digits for " << width() << " bit number: " << sourcep);
break;
@ -698,7 +700,7 @@ string V3Number::displayed(FileLine* fl, const string& vformat) const {
if (fmtsize != "0") str += ' ';
}
}
const size_t fmtsizen = static_cast<size_t>(atoi(fmtsize.c_str()));
const size_t fmtsizen = static_cast<size_t>(std::atoi(fmtsize.c_str()));
str = displayPad(fmtsizen, ' ', left, str);
return str;
}
@ -747,7 +749,7 @@ string V3Number::displayed(FileLine* fl, const string& vformat) const {
}
const bool zeropad = fmtsize.length() > 0 && fmtsize[0] == '0';
// fmtsize might have changed since we parsed the %fmtsize
const size_t fmtsizen = static_cast<size_t>(atoi(fmtsize.c_str()));
const size_t fmtsizen = static_cast<size_t>(std::atoi(fmtsize.c_str()));
str = displayPad(fmtsizen, (zeropad ? '0' : ' '), left, str);
return str;
}
@ -802,7 +804,7 @@ string V3Number::displayed(FileLine* fl, const string& vformat) const {
return str;
}
case '@': { // Packed string
const size_t fmtsizen = static_cast<size_t>(atoi(fmtsize.c_str()));
const size_t fmtsizen = static_cast<size_t>(std::atoi(fmtsize.c_str()));
str = displayPad(fmtsizen, ' ', left, toString());
return str;
}

View File

@ -130,8 +130,8 @@ V3OptionParser::ActionIfs* V3OptionParser::find(const char* optp) {
for (auto&& act : m_pimpl->m_options) {
if (act.second->isFOnOffAllowed()) { // Find starts with "-fno"
if (const char* const nop
= VString::startsWith(optp, "-fno-") ? (optp + strlen("-fno-")) : nullptr) {
if (act.first.substr(strlen("-f"), std::string::npos)
= VString::startsWith(optp, "-fno-") ? (optp + std::strlen("-fno-")) : nullptr) {
if (act.first.substr(std::strlen("-f"), std::string::npos)
== nop) { // [-f]opt = [-fno-]opt
return act.second.get();
}
@ -139,7 +139,7 @@ V3OptionParser::ActionIfs* V3OptionParser::find(const char* optp) {
}
if (act.second->isOnOffAllowed()) { // Find starts with "-no"
if (const char* const nop
= VString::startsWith(optp, "-no") ? (optp + strlen("-no")) : nullptr) {
= VString::startsWith(optp, "-no") ? (optp + std::strlen("-no")) : nullptr) {
if (act.first == nop || act.first == (std::string{"-"} + nop)) {
return act.second.get();
}
@ -206,7 +206,7 @@ void V3OptionParser::finalize() {
m_pimpl->m_spellCheck.pushCandidate(opt.first);
if (opt.second->isFOnOffAllowed()) {
m_pimpl->m_spellCheck.pushCandidate(
"-fno-" + opt.first.substr(strlen("-f"), std::string::npos));
"-fno-" + opt.first.substr(std::strlen("-f"), std::string::npos));
}
if (opt.second->isOnOffAllowed()) m_pimpl->m_spellCheck.pushCandidate("-no" + opt.first);
}

View File

@ -435,6 +435,11 @@ string V3Options::allArgsStringForHierBlock(bool forTop) const {
return out;
}
void V3Options::ccSet() { // --cc
m_outFormatOk = true;
m_systemC = false;
}
//######################################################################
// File searching
@ -727,9 +732,10 @@ bool V3Options::coroutineSupport() {
// V3 Options notification methods
void V3Options::notify() {
FileLine* const cmdfl = new FileLine(FileLine::commandLineFilename());
// Notify that all arguments have been passed and final modification can be made.
FileLine* const cmdfl = new FileLine{FileLine::commandLineFilename()};
if (!outFormatOk() && v3Global.opt.main()) ccSet(); // --main implies --cc if not provided
if (!outFormatOk() && !cdc() && !dpiHdrOnly() && !lintOnly() && !preprocOnly() && !xmlOnly()) {
v3fatal("verilator: Need --cc, --sc, --cdc, --dpi-hdr-only, --lint-only, "
"--xml-only or --E option");
@ -910,8 +916,8 @@ void V3Options::parseOpts(FileLine* fl, int argc, char** argv) {
//======================================================================
bool V3Options::suffixed(const string& sw, const char* arg) {
if (strlen(arg) > sw.length()) return false;
return (0 == strcmp(sw.c_str() + sw.length() - strlen(arg), arg));
if (std::strlen(arg) > sw.length()) return false;
return (0 == std::strcmp(sw.c_str() + sw.length() - std::strlen(arg), arg));
}
void V3Options::parseOptsList(FileLine* fl, const string& optdir, int argc, char** argv) {
@ -1010,10 +1016,7 @@ void V3Options::parseOptsList(FileLine* fl, const string& optdir, int argc, char
DECL_OPTION("-build", Set, &m_build);
DECL_OPTION("-CFLAGS", CbVal, callStrSetter(&V3Options::addCFlags));
DECL_OPTION("-cc", CbCall, [this]() {
m_outFormatOk = true;
m_systemC = false;
});
DECL_OPTION("-cc", CbCall, [this]() { ccSet(); });
DECL_OPTION("-cdc", OnOff, &m_cdc);
DECL_OPTION("-clk", CbVal, callStrSetter(&V3Options::addClocker));
DECL_OPTION("-no-clk", CbVal, callStrSetter(&V3Options::addNoClocker));
@ -1024,15 +1027,15 @@ void V3Options::parseOptsList(FileLine* fl, const string& optdir, int argc, char
DECL_OPTION("-comp-limit-parens", Set, &m_compLimitParens).undocumented();
DECL_OPTION("-comp-limit-syms", CbVal, [](int val) { VName::maxLength(val); }).undocumented();
DECL_OPTION("-compiler", CbVal, [this, fl](const char* valp) {
if (!strcmp(valp, "clang")) {
if (!std::strcmp(valp, "clang")) {
m_compLimitBlocks = 80; // limit unknown
m_compLimitMembers = 64; // soft limit, has slowdown bug as of clang++ 3.8
m_compLimitParens = 240; // controlled by -fbracket-depth, which defaults to 256
} else if (!strcmp(valp, "gcc")) {
} else if (!std::strcmp(valp, "gcc")) {
m_compLimitBlocks = 0; // Bug free
m_compLimitMembers = 64; // soft limit, has slowdown bug as of g++ 7.1
m_compLimitParens = 240; // Unlimited, but generate same code as for clang
} else if (!strcmp(valp, "msvc")) {
} else if (!std::strcmp(valp, "msvc")) {
m_compLimitBlocks = 80; // 128, but allow some room
m_compLimitMembers = 0; // probably ok, and AFAIK doesn't support anon structs
m_compLimitParens = 80; // 128, but allow some room
@ -1183,11 +1186,11 @@ void V3Options::parseOptsList(FileLine* fl, const string& optdir, int argc, char
m_makeDir = valp;
addIncDirFallback(m_makeDir); // Need to find generated files there too
});
DECL_OPTION("-main", OnOff, &m_main).undocumented(); // Future
DECL_OPTION("-main", OnOff, &m_main);
DECL_OPTION("-make", CbVal, [this, fl](const char* valp) {
if (!strcmp(valp, "cmake")) {
if (!std::strcmp(valp, "cmake")) {
m_cmake = true;
} else if (!strcmp(valp, "gmake")) {
} else if (!std::strcmp(valp, "gmake")) {
m_gmake = true;
} else {
fl->v3fatal("Unknown --make system specified: '" << valp << "'");
@ -1280,10 +1283,7 @@ void V3Options::parseOptsList(FileLine* fl, const string& optdir, int argc, char
DECL_OPTION("-pins-uint8", OnOff, &m_pinsUint8);
DECL_OPTION("-pipe-filter", Set, &m_pipeFilter);
DECL_OPTION("-pp-comments", OnOff, &m_ppComments);
DECL_OPTION("-prefix", CbVal, [this](const char* valp) {
m_prefix = valp;
if (m_modPrefix == "") m_modPrefix = m_prefix;
});
DECL_OPTION("-prefix", Set, &m_prefix);
DECL_OPTION("-private", CbCall, [this]() { m_public = false; });
DECL_OPTION("-prof-c", OnOff, &m_profC);
DECL_OPTION("-prof-cfuncs", CbCall, [this]() { m_profC = m_profCFuncs = true; });
@ -1339,13 +1339,13 @@ void V3Options::parseOptsList(FileLine* fl, const string& optdir, int argc, char
if (m_threads < 0) fl->v3fatal("--threads must be >= 0: " << valp);
});
DECL_OPTION("-threads-dpi", CbVal, [this, fl](const char* valp) {
if (!strcmp(valp, "all")) {
if (!std::strcmp(valp, "all")) {
m_threadsDpiPure = true;
m_threadsDpiUnpure = true;
} else if (!strcmp(valp, "none")) {
} else if (!std::strcmp(valp, "none")) {
m_threadsDpiPure = false;
m_threadsDpiUnpure = false;
} else if (!strcmp(valp, "pure")) {
} else if (!std::strcmp(valp, "pure")) {
m_threadsDpiPure = true;
m_threadsDpiUnpure = false;
} else {
@ -1481,13 +1481,13 @@ void V3Options::parseOptsList(FileLine* fl, const string& optdir, int argc, char
DECL_OPTION("-waiver-output", Set, &m_waiverOutput);
DECL_OPTION("-x-assign", CbVal, [this, fl](const char* valp) {
if (!strcmp(valp, "0")) {
if (!std::strcmp(valp, "0")) {
m_xAssign = "0";
} else if (!strcmp(valp, "1")) {
} else if (!std::strcmp(valp, "1")) {
m_xAssign = "1";
} else if (!strcmp(valp, "fast")) {
} else if (!std::strcmp(valp, "fast")) {
m_xAssign = "fast";
} else if (!strcmp(valp, "unique")) {
} else if (!std::strcmp(valp, "unique")) {
m_xAssign = "unique";
} else {
fl->v3fatal("Unknown setting for --x-assign: '"
@ -1496,11 +1496,11 @@ void V3Options::parseOptsList(FileLine* fl, const string& optdir, int argc, char
}
});
DECL_OPTION("-x-initial", CbVal, [this, fl](const char* valp) {
if (!strcmp(valp, "0")) {
if (!std::strcmp(valp, "0")) {
m_xInitial = "0";
} else if (!strcmp(valp, "fast")) {
} else if (!std::strcmp(valp, "fast")) {
m_xInitial = "fast";
} else if (!strcmp(valp, "unique")) {
} else if (!std::strcmp(valp, "unique")) {
m_xInitial = "unique";
} else {
fl->v3fatal("Unknown setting for --x-initial: '"
@ -1522,11 +1522,12 @@ void V3Options::parseOptsList(FileLine* fl, const string& optdir, int argc, char
for (int i = 0; i < argc;) {
UINFO(9, " Option: " << argv[i] << endl);
if (!strcmp(argv[i], "-j") || !strcmp(argv[i], "--j")) { // Allow gnu -- switches
if (!std::strcmp(argv[i], "-j")
|| !std::strcmp(argv[i], "--j")) { // Allow gnu -- switches
++i;
m_buildJobs = 0; // Unlimited parallelism
if (i < argc && isdigit(argv[i][0])) {
m_buildJobs = atoi(argv[i]);
m_buildJobs = std::atoi(argv[i]);
if (m_buildJobs <= 0) {
fl->v3error("-j accepts positive integer, but '" << argv[i] << "' is passed");
}

View File

@ -410,8 +410,9 @@ public:
void addNoClocker(const string& signame);
void addVFile(const string& filename);
void addForceInc(const string& filename);
void notify();
bool available() const { return m_available; }
void ccSet();
void notify();
// ACCESSORS (options)
bool preprocOnly() const { return m_preprocOnly; }

View File

@ -347,7 +347,7 @@ int V3Os::system(const string& command) {
const int ret = ::system(command.c_str());
if (VL_UNCOVERABLE(ret == -1)) {
v3fatal("Failed to execute command:" // LCOV_EXCL_LINE
<< command << " " << strerror(errno));
<< command << " " << std::strerror(errno));
return -1; // LCOV_EXCL_LINE
} else {
UASSERT(WIFEXITED(ret), "system(" << command << ") returned unexpected value of " << ret);

View File

@ -84,9 +84,13 @@ AstArg* V3ParseGrammar::argWrapList(AstNode* nodep) {
}
AstNode* V3ParseGrammar::createSupplyExpr(FileLine* fileline, const string& name, int value) {
return new AstAssignW(
fileline, new AstVarRef(fileline, name, VAccess::WRITE),
new AstConst(fileline, AstConst::StringToParse(), (value ? "'1" : "'0")));
AstAssignW* assignp
= new AstAssignW{fileline, new AstVarRef{fileline, name, VAccess::WRITE},
new AstConst{fileline, AstConst::StringToParse{}, (value ? "'1" : "'0")}};
AstStrengthSpec* strengthSpecp
= new AstStrengthSpec{fileline, VStrength::SUPPLY, VStrength::SUPPLY};
assignp->strengthSpecp(strengthSpecp);
return assignp;
}
AstRange* V3ParseGrammar::scrubRange(AstNodeRange* nrangep) {

View File

@ -150,8 +150,8 @@ void V3ParseImp::lexVerilatorCmtLint(FileLine* fl, const char* textp, bool warnO
void V3ParseImp::lexVerilatorCmtBad(FileLine* fl, const char* textp) {
string cmtparse = textp;
if (cmtparse.substr(0, strlen("/*verilator")) == "/*verilator") {
cmtparse.replace(0, strlen("/*verilator"), "");
if (cmtparse.substr(0, std::strlen("/*verilator")) == "/*verilator") {
cmtparse.replace(0, std::strlen("/*verilator"), "");
}
while (isspace(cmtparse[0])) cmtparse.replace(0, 1, "");
string cmtname;
@ -178,14 +178,14 @@ void V3ParseImp::lexErrorPreprocDirective(FileLine* fl, const char* textp) {
}
string V3ParseImp::lexParseTag(const char* textp) {
string tmp = textp + strlen("/*verilator tag ");
string tmp = textp + std::strlen("/*verilator tag ");
string::size_type pos;
if ((pos = tmp.rfind("*/")) != string::npos) tmp.erase(pos);
return tmp;
}
double V3ParseImp::lexParseTimenum(const char* textp) {
const size_t length = strlen(textp);
const size_t length = std::strlen(textp);
char* const strgp = new char[length + 1];
char* dp = strgp;
const char* sp = textp;
@ -234,7 +234,7 @@ size_t V3ParseImp::ppInputToLex(char* buf, size_t max_size) {
m_ppBuffers.push_front(remainder); // Put back remainder for next time
len = (max_size - got);
}
memcpy(buf + got, front.c_str(), len);
std::memcpy(buf + got, front.c_str(), len);
got += len;
}
if (debug() >= 9) {
@ -398,8 +398,7 @@ void V3ParseImp::tokenPipeline() {
const int nexttok = nexttokp->token;
yylval = curValue;
// Now potentially munge the current token
if (token == '('
&& (nexttok == ygenSTRENGTH || nexttok == ySUPPLY0 || nexttok == ySUPPLY1)) {
if (token == '(' && isStrengthToken(nexttok)) {
token = yP_PAR__STRENGTH;
} else if (token == ':') {
if (nexttok == yBEGIN) {
@ -483,6 +482,12 @@ void V3ParseImp::tokenPipeline() {
// effectively returns yylval
}
bool V3ParseImp::isStrengthToken(int tok) {
return tok == ygenSTRENGTH || tok == ySUPPLY0 || tok == ySUPPLY1 || tok == ySTRONG0
|| tok == ySTRONG1 || tok == yPULL0 || tok == yPULL1 || tok == yWEAK0 || tok == yWEAK1
|| tok == yHIGHZ0 || tok == yHIGHZ1;
}
void V3ParseImp::tokenPipelineSym() {
// If an id, change the type based on symbol table
// Note above sometimes converts yGLOBAL to a yaID__LEX

View File

@ -121,6 +121,7 @@ struct V3ParseBisonYYSType {
V3ErrorCode::en errcodeen;
VAttrType::en attrtypeen;
VLifetime::en lifetime;
VStrength::en strength;
#include "V3Ast__gen_yystype.h"
};
@ -216,6 +217,7 @@ public:
}
int lexKwdLastState() const { return m_lexKwdLast; }
static const char* tokenName(int tok);
static bool isStrengthToken(int tok);
void ppPushText(const string& text) {
m_ppBuffers.push_back(text);

View File

@ -126,7 +126,7 @@ bom [\357\273\277]
if (LEXP->m_protBytes > 0) {
LEXP->curFilelinep()->v3warn(BADSTDPRAGMA, "multiple `pragma protected encoding sections");
}
res = sscanf(yytext + strlen("encoding"), " = (enctype = \"%15[A-Za-z0-9]\", line_length = %d, bytes = %d)", &enctype[0], &LEXP->m_protLength, &LEXP->m_protBytes);
res = sscanf(yytext + std::strlen("encoding"), " = (enctype = \"%15[A-Za-z0-9]\", line_length = %d, bytes = %d)", &enctype[0], &LEXP->m_protLength, &LEXP->m_protBytes);
if (res == 0)
LEXP->curFilelinep()->v3warn(BADSTDPRAGMA, "`pragma protected encoding must have an \"enctype\" field");
LEXP->m_encType = !VL_STRCASECMP(enctype, "uuencode") ? Enctype::UUENCODE :
@ -242,7 +242,7 @@ bom [\357\273\277]
<INITIAL,STRIFY>"`__LINE__" { FL_FWDC;
static char buf[25];
VL_SNPRINTF(buf, 25, "%d", LEXP->curFilelinep()->lastLineno());
yytext = buf; yyleng = strlen(yytext);
yytext = buf; yyleng = std::strlen(yytext);
return VP_TEXT; }
/* Pass-through strings */

View File

@ -395,7 +395,7 @@ string V3PreProcImp::commentCleanup(const string& text) {
}
bool V3PreProcImp::commentTokenMatch(string& cmdr, const char* strg) {
int len = strlen(strg);
int len = std::strlen(strg);
if (VString::startsWith(cmdr, strg) && (cmdr[len] == '\0' || isspace(cmdr[len]))) {
if (isspace(cmdr[len])) len++;
cmdr = cmdr.substr(len);
@ -425,27 +425,27 @@ void V3PreProcImp::comment(const string& text) {
bool synth = false;
bool vlcomment = false;
if ((cp[0] == 'v' || cp[0] == 'V') && VString::startsWith(cp + 1, "erilator")) {
cp += strlen("verilator");
cp += std::strlen("verilator");
if (*cp == '_') {
fileline()->v3error("Extra underscore in meta-comment;"
" use /*verilator {...}*/ not /*verilator_{...}*/");
}
vlcomment = true;
} else if (VString::startsWith(cp, "synopsys")) {
cp += strlen("synopsys");
cp += std::strlen("synopsys");
synth = true;
if (*cp == '_') {
fileline()->v3error("Extra underscore in meta-comment;"
" use /*synopsys {...}*/ not /*synopsys_{...}*/");
}
} else if (VString::startsWith(cp, "cadence")) {
cp += strlen("cadence");
cp += std::strlen("cadence");
synth = true;
} else if (VString::startsWith(cp, "pragma")) {
cp += strlen("pragma");
cp += std::strlen("pragma");
synth = true;
} else if (VString::startsWith(cp, "ambit synthesis")) {
cp += strlen("ambit synthesis");
cp += std::strlen("ambit synthesis");
synth = true;
} else {
return;
@ -478,7 +478,7 @@ void V3PreProcImp::comment(const string& text) {
string::size_type pos;
if ((pos = cmd.find("public_flat_rw")) != string::npos) {
// "/*verilator public_flat_rw @(foo) */" -> "/*verilator public_flat_rw*/ @(foo)"
cmd = cmd.substr(pos + strlen("public_flat_rw"));
cmd = cmd.substr(pos + std::strlen("public_flat_rw"));
while (isspace(cmd[0])) cmd = cmd.substr(1);
if (!printed) insertUnreadback("/*verilator public_flat_rw*/ " + cmd + " /**/");
} else {
@ -1593,7 +1593,7 @@ string V3PreProcImp::getline() {
if (isEof()) return "";
const char* rtnp;
bool gotEof = false;
while (nullptr == (rtnp = strchr(m_lineChars.c_str(), '\n')) && !gotEof) {
while (nullptr == (rtnp = std::strchr(m_lineChars.c_str(), '\n')) && !gotEof) {
string buf;
const int tok = getFinalToken(buf /*ref*/);
if (debug() >= 5) {

View File

@ -150,7 +150,7 @@ double VString::parseDouble(const string& str, bool* successp) {
char* endp = strgp;
const double d = strtod(strgp, &endp);
const size_t parsed_len = endp - strgp;
if (parsed_len != strlen(strgp)) {
if (parsed_len != std::strlen(strgp)) {
if (successp) *successp = false;
}
VL_DO_DANGLING(delete[] strgp, strgp);
@ -402,7 +402,7 @@ void VHashSha256::selfTest() {
string VName::dehash(const string& in) {
static const char VHSH[] = "__Vhsh";
static const size_t DOT_LEN = strlen("__DOT__");
static const size_t DOT_LEN = std::strlen("__DOT__");
std::string dehashed;
// Need to split 'in' into components separated by __DOT__, 'last_dot_pos'

View File

@ -359,6 +359,13 @@ private:
}
virtual void visit(AstVar*) override {}
virtual void visit(AstConst*) override {}
virtual void visit(AstModule* nodep) override {
++m_ops;
if (!nodep->isSubstOptimizable()) m_ops = SUBST_MAX_OPS_NA;
iterateChildren(nodep);
// Reduce peak memory usage by reclaiming the edited AstNodes
doDeletes();
}
virtual void visit(AstNode* nodep) override {
m_ops++;
if (!nodep->isSubstOptimizable()) m_ops = SUBST_MAX_OPS_NA;

View File

@ -55,6 +55,33 @@
// duplicating vars and logic that is common between each instance of a
// module.
//
//
// Another thing done in this phase is signal strength handling.
// Currently they are only supported in assignments and only in case when the strongest assignment
// has constant with all bits equal on the RHS. It is the case when they can be statically
// resolved.
//
// Static resolution is done in the following way:
// - The assignment of value 0 (size may be greater than 1), that has greatest strength (the
// one corresponding to 0) of all other assignments of 0, has to be found.
// - The same is done for value '1 and strength corresponding to value 1.
// - The greater of these two strengths is chosen. If they are equal the one that corresponds
// to 1 is taken as the greatest.
// - All assignments, that have strengths weaker or equal to the one that was found before, are
// removed. They are the assignments with constants on the RHS and also all assignments that have
// both strengths non-greater that the one was found, because they are weaker no matter what is on
// RHS.
//
// All assignments that are stronger than the one with strongest constant are left as they are.
//
// There is a possible problem with equally strong assignments, because multiple assignments with
// the same strength, but different values should result in x value, but these values are
// unsupported.
//
// Singal strength can also be used in simple logic gates parsed as assignments (see verilog.y),
// but these gates are then either removed (if they are weaker than the strongest constant) or
// handled as the gates witout signal strengths are handled now. In other words, gate with greater
// strength won't properly overwrite weaker driver.
//*************************************************************************
#include "config_build.h"
@ -340,6 +367,8 @@ class TristateVisitor final : public TristateBaseVisitor {
// TYPES
using RefVec = std::vector<AstVarRef*>;
using VarMap = std::unordered_map<AstVar*, RefVec*>;
using Assigns = std::vector<AstAssignW*>;
using VarToAssignsMap = std::map<AstVar*, Assigns>;
enum : uint8_t {
U2_GRAPHING = 1, // bit[0] if did m_graphing visit
U2_NONGRAPH = 2, // bit[1] if did !m_graphing visit
@ -352,6 +381,7 @@ class TristateVisitor final : public TristateBaseVisitor {
AstNodeModule* m_modp = nullptr; // Current module
AstCell* m_cellp = nullptr; // current cell
VarMap m_lhsmap; // Tristate left-hand-side driver map
VarToAssignsMap m_assigns; // Assigns in current module
int m_unique = 0;
bool m_alhs = false; // On LHS of assignment
const AstNode* m_logicp = nullptr; // Current logic being built
@ -636,6 +666,117 @@ class TristateVisitor final : public TristateBaseVisitor {
nodep->addStmtp(assp);
}
void addToAssignmentList(AstAssignW* nodep) {
if (AstVarRef* const varRefp = VN_CAST(nodep->lhsp(), VarRef)) {
if (varRefp->varp()->isNet()) {
m_assigns[varRefp->varp()].push_back(nodep);
} else if (nodep->strengthSpecp()) {
if (!varRefp->varp()->isNet())
nodep->v3warn(E_UNSUPPORTED, "Unsupported: Signal strengths are unsupported "
"on the following variable type: "
<< varRefp->varp()->varType());
nodep->strengthSpecp()->unlinkFrBack()->deleteTree();
}
} else if (nodep->strengthSpecp()) {
nodep->v3warn(E_UNSUPPORTED,
"Unsupported: Assignments with signal strength with LHS of type: "
<< nodep->lhsp()->prettyTypeName());
}
}
uint8_t getStrength(AstAssignW* const nodep, bool value) {
if (AstStrengthSpec* const strengthSpec = nodep->strengthSpecp()) {
return value ? strengthSpec->strength1() : strengthSpec->strength0();
}
return VStrength::STRONG; // default strength is strong
}
bool assignmentOfValueOnAllBits(AstAssignW* const nodep, bool value) {
if (AstConst* const constp = VN_CAST(nodep->rhsp(), Const)) {
const V3Number num = constp->num();
return value ? num.isEqAllOnes() : num.isEqZero();
}
return false;
}
AstAssignW* getStrongestAssignmentOfValue(const Assigns& assigns, bool value) {
auto maxIt = std::max_element(
assigns.begin(), assigns.end(), [&](AstAssignW* ap, AstAssignW* bp) {
bool valuesOnRhsA = assignmentOfValueOnAllBits(ap, value);
bool valuesOnRhsB = assignmentOfValueOnAllBits(bp, value);
if (!valuesOnRhsA) return valuesOnRhsB;
if (!valuesOnRhsB) return false;
return getStrength(ap, value) < getStrength(bp, value);
});
// If not all assignments have const with all bits equal to value on the RHS,
// std::max_element will return one of them anyway, so it has to be checked before
// returning
return assignmentOfValueOnAllBits(*maxIt, value) ? *maxIt : nullptr;
}
void removeWeakerAssignments(Assigns& assigns) {
// Weaker assignments are these assignments that can't change the final value of the net.
// If the value of the RHS is known, only strength corresponding to its value is taken into
// account. Assignments of constants that have bits both 0 and 1 are skipped here, because
// it would involve handling parts of bits separately.
// First, the strongest assignment, that has value on the RHS consisting of only 1 or only
// 0, has to be found.
AstAssignW* const strongest0p = getStrongestAssignmentOfValue(assigns, 0);
AstAssignW* const strongest1p = getStrongestAssignmentOfValue(assigns, 1);
AstAssignW* strongestp = nullptr;
uint8_t greatestKnownStrength = 0;
const auto getIfStrongest = [&](AstAssignW* const strongestCandidatep, bool value) {
if (!strongestCandidatep) return;
uint8_t strength = getStrength(strongestCandidatep, value);
if (strength >= greatestKnownStrength) {
greatestKnownStrength = strength;
strongestp = strongestCandidatep;
}
};
getIfStrongest(strongest0p, 0);
getIfStrongest(strongest1p, 1);
if (strongestp) {
// Then all weaker assignments can be safely removed.
// Assignments of the same strength are also removed, because duplicates aren't needed.
// One problem is with 2 assignments of different values and equal strengths. It should
// result in assignment of x value, but these values aren't supported now.
auto removedIt
= std::remove_if(assigns.begin(), assigns.end(), [&](AstAssignW* assignp) {
if (assignp == strongestp) return false;
const uint8_t strength0 = getStrength(assignp, 0);
const uint8_t strength1 = getStrength(assignp, 1);
const bool toRemove = (strength0 <= greatestKnownStrength
&& strength1 <= greatestKnownStrength)
|| (strength0 <= greatestKnownStrength
&& assignmentOfValueOnAllBits(assignp, 0))
|| (strength1 <= greatestKnownStrength
&& assignmentOfValueOnAllBits(assignp, 1));
if (toRemove) {
// Don't propagate tristate if its assignment is removed.
TristateVertex* const vertexp
= reinterpret_cast<TristateVertex*>(assignp->rhsp()->user5p());
if (vertexp) vertexp->isTristate(false);
VL_DO_DANGLING(pushDeletep(assignp->unlinkFrBack()), assignp);
return true;
}
return false;
});
assigns.erase(removedIt, assigns.end());
}
}
void resolveMultipleNetAssignments() {
for (auto& varpAssigns : m_assigns) {
if (varpAssigns.second.size() > 1) {
// first the static resolution is tried
removeWeakerAssignments(varpAssigns.second);
}
}
}
// VISITORS
virtual void visit(AstConst* nodep) override {
UINFO(9, dbgState() << nodep << endl);
@ -889,6 +1030,8 @@ class TristateVisitor final : public TristateBaseVisitor {
void visitAssign(AstNodeAssign* nodep) {
if (m_graphing) {
if (AstAssignW* assignWp = VN_CAST(nodep, AssignW)) addToAssignmentList(assignWp);
if (nodep->user2() & U2_GRAPHING) return;
VL_RESTORER(m_logicp);
m_logicp = nodep;
@ -1373,6 +1516,7 @@ class TristateVisitor final : public TristateBaseVisitor {
VL_RESTORER(m_graphing);
VL_RESTORER(m_unique);
VL_RESTORER(m_lhsmap);
VL_RESTORER(m_assigns);
// Not preserved, needs pointer instead: TristateGraph origTgraph = m_tgraph;
UASSERT_OBJ(m_tgraph.empty(), nodep, "Unsupported: NodeModule under NodeModule");
{
@ -1382,6 +1526,7 @@ class TristateVisitor final : public TristateBaseVisitor {
m_unique = 0;
m_logicp = nullptr;
m_lhsmap.clear();
m_assigns.clear();
m_modp = nodep;
// Walk the graph, finding all variables and tristate constructs
{
@ -1389,6 +1534,8 @@ class TristateVisitor final : public TristateBaseVisitor {
iterateChildren(nodep);
m_graphing = false;
}
// resolve multiple net assignments and signal strengths
resolveMultipleNetAssignments();
// Use graph to find tristate signals
m_tgraph.graphWalk(nodep);
// Build the LHS drivers map for this module

View File

@ -6,9 +6,10 @@
//
//*************************************************************************
//
// 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.
// Copyright 2020-2022 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.
// SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
//
//*************************************************************************

View File

@ -538,7 +538,7 @@ private:
|| VN_IS(vdtypep, DynArrayDType) //
|| VN_IS(vdtypep, QueueDType)) {
nodep->v3warn(E_UNSUPPORTED, "Unsupported: Concatenation to form "
<< vdtypep->prettyDTypeNameQ() << "data type");
<< vdtypep->prettyDTypeNameQ() << " data type");
}
iterateCheckSizedSelf(nodep, "LHS", nodep->lhsp(), SELF, BOTH);
@ -3256,6 +3256,7 @@ private:
nodep->dtypeFrom(ftaskp);
nodep->classOrPackagep(classp);
if (VN_IS(ftaskp, Task)) nodep->makeStatement();
processFTaskRefArgs(nodep);
}
return;
}
@ -5910,7 +5911,8 @@ private:
"Node has no type"); // Perhaps forgot to do a prelim visit on it?
//
// For DOUBLE under a logical op, add implied test against zero, never a warning
if (underp && underp->isDouble()) {
AstNodeDType* const underVDTypep = underp ? underp->dtypep()->skipRefp() : nullptr;
if (underp && underVDTypep->isDouble()) {
UINFO(6, " spliceCvtCmpD0: " << underp << endl);
VNRelinker linker;
underp->unlinkFrBack(&linker);
@ -5918,13 +5920,12 @@ private:
= new AstNeqD(nodep->fileline(), underp,
new AstConst(nodep->fileline(), AstConst::RealDouble(), 0.0));
linker.relink(newp);
} else if (VN_IS(underp->dtypep(), ClassRefDType)
|| (VN_IS(underp->dtypep(), BasicDType)
&& VN_AS(underp->dtypep(), BasicDType)->keyword()
== VBasicDTypeKwd::CHANDLE)) {
} else if (VN_IS(underVDTypep, ClassRefDType)
|| (VN_IS(underVDTypep, BasicDType)
&& VN_AS(underVDTypep, BasicDType)->keyword() == VBasicDTypeKwd::CHANDLE)) {
// Allow warning-free "if (handle)"
VL_DO_DANGLING(fixWidthReduce(underp), underp); // Changed
} else if (!underp->dtypep()->basicp()) {
} else if (!underVDTypep->basicp()) {
nodep->v3error("Logical operator " << nodep->prettyTypeName()
<< " expects a non-complex data type on the "
<< side << ".");
@ -6065,7 +6066,7 @@ private:
}
if ((VN_IS(nodep, Add) && underp->width() == 1 && underp->isOne())
|| (VN_IS(nodep, Sub) && underp->width() == 1 && underp->isOne()
&& 0 == strcmp(side, "RHS"))) {
&& 0 == std::strcmp(side, "RHS"))) {
// "foo + 1'b1", or "foo - 1'b1" are very common, people assume
// they extend correctly
warnOn = false;

View File

@ -8,9 +8,125 @@ import re
import sys
# from pprint import pprint, pformat
Types = []
Classes = {}
Children = {}
class Node:
def __init__(self, name, superClass):
self._name = name
self._superClass = superClass
self._subClasses = [] # Initially list, but tuple after completion
self._allSuperClasses = None # Computed on demand after completion
self._allSubClasses = None # Computed on demand after completion
self._typeId = None # Concrete type identifier number for leaf classes
self._typeIdMin = None # Lowest type identifier number for class
self._typeIdMax = None # Highest type identifier number for class
@property
def name(self):
return self._name
@property
def superClass(self):
return self._superClass
@property
def isCompleted(self):
return isinstance(self._subClasses, tuple)
# Pre completion methods
def addSubClass(self, subClass):
assert not self.isCompleted
self._subClasses.append(subClass)
# Computes derived properties over entire class hierarchy.
# No more changes to the hierarchy are allowed once this was called
def complete(self, typeId=0):
assert not self.isCompleted
# Sort sub-classes and convert to tuple, which marks completion
self._subClasses = tuple(sorted(self._subClasses,
key=lambda _: _.name))
# Leaves
if self.isLeaf:
self._typeId = typeId
return typeId + 1
# Non-leaves
for subClass in self._subClasses:
typeId = subClass.complete(typeId)
return typeId
# Post completion methods
@property
def subClasses(self):
assert self.isCompleted
return self._subClasses
@property
def isRoot(self):
assert self.isCompleted
return self.superClass is None
@property
def isLeaf(self):
assert self.isCompleted
return not self.subClasses
@property
def allSuperClasses(self):
assert self.isCompleted
if self._allSuperClasses is None:
if self.superClass is None:
self._allSuperClasses = ()
else:
self._allSuperClasses = self.superClass.allSuperClasses + (
self.superClass, )
return self._allSuperClasses
@property
def allSubClasses(self):
assert self.isCompleted
if self._allSubClasses is None:
if self.isLeaf:
self._allSubClasses = ()
else:
self._allSubClasses = self.subClasses + tuple(
_ for subClass in self.subClasses
for _ in subClass.allSubClasses)
return self._allSubClasses
@property
def typeId(self):
assert self.isCompleted
assert self.isLeaf
return self._typeId
@property
def typeIdMin(self):
assert self.isCompleted
if self.isLeaf:
return self.typeId
if self._typeIdMin is None:
self._typeIdMin = min(_.typeIdMin for _ in self.allSubClasses)
return self._typeIdMin
@property
def typeIdMax(self):
assert self.isCompleted
if self.isLeaf:
return self.typeId
if self._typeIdMax is None:
self._typeIdMax = max(_.typeIdMax for _ in self.allSubClasses)
return self._typeIdMax
def isSubClassOf(self, other):
assert self.isCompleted
if self is other:
return True
return self in other.allSubClasses
Nodes = {}
SortedNodes = None
ClassRefs = {}
Stages = {}
@ -111,7 +227,7 @@ class Cpt:
self.error("Can't parse from function: " + func)
typen = match.group(1)
subnodes = match.group(2)
if not subclasses_of(typen):
if Nodes[typen].isRoot:
self.error("Unknown AstNode typen: " + typen + ": in " + func)
mif = ""
@ -166,7 +282,7 @@ class Cpt:
elif match_skip:
typen = match_skip.group(1)
self.tree_skip_visit[typen] = 1
if typen not in Classes:
if typen not in Nodes:
self.error("Unknown node type: " + typen)
else:
@ -296,12 +412,13 @@ class Cpt:
self.print(
" // Bottom class up, as more simple transforms are generally better\n"
)
for typen in sorted(Classes.keys()):
for node in SortedNodes:
out_for_type_sc = []
out_for_type = []
bases = subclasses_of(typen)
bases.append(typen)
for base in bases:
classes = list(node.allSuperClasses)
classes.append(node)
for base in classes:
base = base.name
if base not in self.treeop:
continue
for typefunc in self.treeop[base]:
@ -328,23 +445,23 @@ class Cpt:
if len(out_for_type_sc) > 0: # Short-circuited types
self.print(
" // Generated by astgen with short-circuiting\n" +
" virtual void visit(Ast" + typen +
" virtual void visit(Ast" + node.name +
"* nodep) override {\n" +
" iterateAndNextNull(nodep->lhsp());\n" +
"".join(out_for_type_sc))
if out_for_type[0]:
self.print(" iterateAndNextNull(nodep->rhsp());\n")
if is_subclass_of(typen, "NodeTriop"):
if node.isSubClassOf(Nodes["NodeTriop"]):
self.print(
" iterateAndNextNull(nodep->thsp());\n")
self.print("".join(out_for_type) + " }\n")
elif len(out_for_type) > 0: # Other types with something to print
skip = typen in self.tree_skip_visit
skip = node.name in self.tree_skip_visit
gen = "Gen" if skip else ""
override = "" if skip else " override"
self.print(
" // Generated by astgen\n" + " virtual void visit" +
gen + "(Ast" + typen + "* nodep)" + override + " {\n" +
gen + "(Ast" + node.name + "* nodep)" + override + " {\n" +
("" if skip else " iterateChildren(nodep);\n") +
''.join(out_for_type) + " }\n")
@ -368,11 +485,13 @@ def read_types(filename):
if re.search(r'Ast', supern) or classn == "AstNode":
classn = re.sub(r'^Ast', '', classn)
supern = re.sub(r'^Ast', '', supern)
Classes[classn] = supern
if supern != '':
if supern not in Children:
Children[supern] = {}
Children[supern][classn] = 1
if supern:
superClass = Nodes[supern]
node = Node(classn, superClass)
Nodes[supern].addSubClass(node)
else:
node = Node(classn, None)
Nodes[classn] = node
def read_stages(filename):
@ -424,37 +543,6 @@ def open_file(filename):
return fh
def subclasses_of(typen):
cllist = []
subclass = Classes[typen]
while True:
if subclass not in Classes:
break
cllist.append(subclass)
subclass = Classes[subclass]
cllist.reverse()
return cllist
def children_of(typen):
cllist = []
todo = []
todo.append(typen)
while len(todo) != 0:
subclass = todo.pop(0)
if subclass in Children:
for child in sorted(Children[subclass].keys()):
todo.append(child)
cllist.append(child)
return cllist
def is_subclass_of(typen, what):
return typen == what or (typen in children_of(what))
# ---------------------------------------------------------------------
@ -468,20 +556,19 @@ def write_report(filename):
fh.write(" " + classn + "\n")
fh.write("\nClasses:\n")
for typen in sorted(Classes.keys()):
fh.write(" class Ast%-17s\n" % typen)
for node in SortedNodes:
fh.write(" class Ast%-17s\n" % node.name)
fh.write(" parent: ")
for subclass in subclasses_of(typen):
if subclass != 'Node':
fh.write("Ast%-12s " % subclass)
for superClass in node.allSuperClasses:
if not superClass.isRoot:
fh.write("Ast%-12s " % superClass.name)
fh.write("\n")
fh.write(" childs: ")
for subclass in children_of(typen):
if subclass != 'Node':
fh.write("Ast%-12s " % subclass)
for subClass in node.allSubClasses:
fh.write("Ast%-12s " % subClass.name)
fh.write("\n")
if ("Ast" + typen) in ClassRefs: # pylint: disable=superfluous-parens
refs = ClassRefs["Ast" + typen]
if ("Ast" + node.name) in ClassRefs: # pylint: disable=superfluous-parens
refs = ClassRefs["Ast" + node.name]
fh.write(" newed: ")
for stage in sorted(refs['newed'].keys(),
key=lambda val: Stages[val]
@ -500,27 +587,27 @@ def write_report(filename):
def write_classes(filename):
with open_file(filename) as fh:
fh.write("class AstNode;\n")
for typen in sorted(Classes.keys()):
fh.write("class Ast%-17s // " % (typen + ";"))
for subclass in subclasses_of(typen):
fh.write("Ast%-12s " % subclass)
for node in SortedNodes:
fh.write("class Ast%-17s // " % (node.name + ";"))
for superClass in node.allSuperClasses:
fh.write("Ast%-12s " % superClass.name)
fh.write("\n")
def write_visitor_decls(filename):
with open_file(filename) as fh:
for typen in sorted(Classes.keys()):
if typen != "Node":
fh.write("virtual void visit(Ast" + typen + "*);\n")
for node in SortedNodes:
if not node.isRoot:
fh.write("virtual void visit(Ast" + node.name + "*);\n")
def write_visitor_defns(filename):
with open_file(filename) as fh:
for typen in sorted(Classes.keys()):
if typen != "Node":
base = Classes[typen]
fh.write("void VNVisitor::visit(Ast" + typen +
"* nodep) { visit(static_cast<Ast" + base +
for node in SortedNodes:
base = node.superClass
if base is not None:
fh.write("void VNVisitor::visit(Ast" + node.name +
"* nodep) { visit(static_cast<Ast" + base.name +
"*>(nodep)); }\n")
@ -528,75 +615,51 @@ def write_impl(filename):
with open_file(filename) as fh:
fh.write("\n")
fh.write("// For internal use. They assume argument is not nullptr.\n")
for typen in sorted(Classes.keys()):
for node in SortedNodes:
fh.write("template<> inline bool AstNode::privateTypeTest<Ast" +
typen + ">(const AstNode* nodep) { ")
if typen == "Node":
node.name + ">(const AstNode* nodep) { ")
if node.isRoot:
fh.write("return true; ")
else:
fh.write("return ")
if re.search(r'^Node', typen):
if not node.isLeaf:
fh.write(
"static_cast<int>(nodep->type()) >= static_cast<int>(VNType::first"
+ typen + ") && ")
+ node.name + ") && ")
fh.write(
"static_cast<int>(nodep->type()) <= static_cast<int>(VNType::last"
+ typen + "); ")
+ node.name + "); ")
else:
fh.write("nodep->type() == VNType::at" + typen + "; ")
fh.write("nodep->type() == VNType::at" + node.name + "; ")
fh.write("}\n")
def write_type_enum(fh, typen, idx, processed, kind, indent):
# Skip this if it has already been processed
if typen in processed:
return idx
# Mark processed
processed[typen] = 1
# The last used index
last = None
if not re.match(r'^Node', typen):
last = idx
if kind == "concrete-enum":
fh.write(" " * (indent * 4) + "at" + typen + " = " + str(idx) +
",\n")
elif kind == "concrete-ascii":
fh.write(" " * (indent * 4) + "\"" + typen.upper() + "\",\n")
idx += 1
elif kind == "abstract-enum":
fh.write(" " * (indent * 4) + "first" + typen + " = " + str(idx) +
",\n")
if typen in Children:
for child in sorted(Children[typen].keys()):
(idx, last) = write_type_enum(fh, child, idx, processed, kind,
indent)
if re.match(r'^Node', typen) and kind == "abstract-enum":
fh.write(" " * (indent * 4) + "last" + typen + " = " + str(last) +
",\n")
return [idx, last]
def write_types(filename):
with open_file(filename) as fh:
fh.write(" enum en : uint16_t {\n")
(final, ignored) = write_type_enum( # pylint: disable=W0612
fh, "Node", 0, {}, "concrete-enum", 2)
fh.write(" _ENUM_END = " + str(final) + "\n")
for node in sorted(filter(lambda _: _.isLeaf, SortedNodes),
key=lambda _: _.typeId):
fh.write(" at" + node.name + " = " + str(node.typeId) +
",\n")
fh.write(" _ENUM_END = " + str(Nodes["Node"].typeIdMax + 1) +
"\n")
fh.write(" };\n")
fh.write(" enum bounds : uint16_t {\n")
write_type_enum(fh, "Node", 0, {}, "abstract-enum", 2)
for node in sorted(filter(lambda _: not _.isLeaf, SortedNodes),
key=lambda _: _.typeIdMin):
fh.write(" first" + node.name + " = " +
str(node.typeIdMin) + ",\n")
fh.write(" last" + node.name + " = " + str(node.typeIdMax) +
",\n")
fh.write(" _BOUNDS_END\n")
fh.write(" };\n")
fh.write(" const char* ascii() const {\n")
fh.write(" static const char* const names[_ENUM_END + 1] = {\n")
write_type_enum(fh, "Node", 0, {}, "concrete-ascii", 3)
for node in sorted(filter(lambda _: _.isLeaf, SortedNodes),
key=lambda _: _.typeId):
fh.write(" \"" + node.name.upper() + "\",\n")
fh.write(" \"_ENUM_END\"\n")
fh.write(" };\n")
fh.write(" return names[m_e];\n")
@ -605,45 +668,21 @@ def write_types(filename):
def write_yystype(filename):
with open_file(filename) as fh:
for typen in sorted(Classes.keys()):
fh.write("Ast{t}* {m}p;\n".format(t=typen,
m=typen[0].lower() + typen[1:]))
for node in SortedNodes:
fh.write("Ast{t}* {m}p;\n".format(t=node.name,
m=node.name[0].lower() +
node.name[1:]))
def write_macros(filename):
with open_file(filename) as fh:
typen = "None"
base = "None"
in_filename = "V3AstNodes.h"
ifile = Args.I + "/" + in_filename
with open(ifile) as ifh:
for (lineno, line) in enumerate(ifh, 1):
# Drop expanded macro definitions - but keep empty line so compiler
# message locations are accurate
line = re.sub(r'^\s*#(define|undef)\s+ASTGEN_.*$', '', line)
# Track current node type and base class
match = re.search(
r'\s*class\s*Ast(\S+)\s*(final|VL_NOT_FINAL)?\s*:\s*(public)?\s*(AstNode\S*)',
line)
if match:
typen = match.group(1)
base = match.group(4)
if not typen.startswith("Node"):
macro = "#define ASTGEN_SUPER_{t}(...) {b}(VNType::at{t}, __VA_ARGS__)\n" \
.format(b=base, t=typen)
fh.write(macro)
match = re.search(r"ASTGEN_SUPER_(\w+)", line)
if match:
if typen != match.group(1):
print((
"V3AstNodes.h:{l} ERROR: class Ast{t} calls wrong superclass "
+
"constructor macro (should call ASTGEN_SUPER_{t})"
).format(l=lineno, t=typen))
sys.exit(1)
for node in SortedNodes:
# Only care about leaf classes
if not node.isLeaf:
continue
fh.write(
"#define ASTGEN_SUPER_{t}(...) Ast{b}(VNType::at{t}, __VA_ARGS__)\n"
.format(t=node.name, b=node.superClass.name))
######################################################################
@ -673,19 +712,24 @@ Args = parser.parse_args()
read_types(Args.I + "/V3Ast.h")
read_types(Args.I + "/V3AstNodes.h")
for typen in sorted(Classes.keys()):
# Compute derived properties over the whole AstNode hierarchy
Nodes["Node"].complete()
SortedNodes = tuple(map(lambda _: Nodes[_], sorted(Nodes.keys())))
for node in SortedNodes:
# Check all leaves are not AstNode* and non-leaves are AstNode*
children = children_of(typen)
if re.match(r'^Node', typen):
if len(children) == 0:
if re.match(r'^Node', node.name):
if node.isLeaf:
sys.exit(
"%Error: Final AstNode subclasses must not be named AstNode*: Ast"
+ typen)
+ node.name)
else:
if len(children) != 0:
if not node.isLeaf:
sys.exit(
"%Error: Non-final AstNode subclasses must be named AstNode*: Ast"
+ typen)
+ node.name)
read_stages(Args.I + "/Verilator.cpp")

View File

@ -327,8 +327,8 @@ vnum {vnum1}|{vnum2}|{vnum3}|{vnum4}|{vnum5}
"forever" { FL; return yFOREVER; }
"fork" { FL; return yFORK; }
"function" { FL; return yFUNCTION; }
"highz0" { FL; return ygenSTRENGTH; }
"highz1" { FL; return ygenSTRENGTH; }
"highz0" { FL; return yHIGHZ0; }
"highz1" { FL; return yHIGHZ1; }
"if" { FL; return yIF; }
"initial" { FL; return yINITIAL; }
"inout" { FL; return yINOUT; }
@ -352,8 +352,8 @@ vnum {vnum1}|{vnum2}|{vnum3}|{vnum4}|{vnum5}
"pmos" { FL; return yPMOS; }
"posedge" { FL; return yPOSEDGE; }
"primitive" { FL; return yPRIMITIVE; }
"pull0" { FL; return ygenSTRENGTH; }
"pull1" { FL; return ygenSTRENGTH; }
"pull0" { FL; return yPULL0; }
"pull1" { FL; return yPULL1; }
"pulldown" { FL; return yPULLDOWN; }
"pullup" { FL; return yPULLUP; }
"rcmos" { FL; return yRCMOS; }
@ -371,8 +371,8 @@ vnum {vnum1}|{vnum2}|{vnum3}|{vnum4}|{vnum5}
"small" { FL; return ygenSTRENGTH; }
"specify" { FL; return ySPECIFY; }
"specparam" { FL; return ySPECPARAM; }
"strong0" { FL; return ygenSTRENGTH; }
"strong1" { FL; return ygenSTRENGTH; }
"strong0" { FL; return ySTRONG0; }
"strong1" { FL; return ySTRONG1; }
"supply0" { FL; return ySUPPLY0; }
"supply1" { FL; return ySUPPLY1; }
"table" { FL; yy_push_state(TABLE); return yTABLE; }
@ -390,8 +390,8 @@ vnum {vnum1}|{vnum2}|{vnum3}|{vnum4}|{vnum5}
"vectored" { FL; return yVECTORED; }
"wait" { FL; return yWAIT; }
"wand" { FL; return yWAND; }
"weak0" { FL; return ygenSTRENGTH; }
"weak1" { FL; return ygenSTRENGTH; }
"weak0" { FL; return yWEAK0; }
"weak1" { FL; return yWEAK1; }
"while" { FL; return yWHILE; }
"wire" { FL; return yWIRE; }
"wor" { FL; return yWOR; }
@ -1008,7 +1008,7 @@ vnum {vnum1}|{vnum2}|{vnum3}|{vnum4}|{vnum5}
return yaT_RESETALL; } // Rest handled by preproc
"`suppress_faults" { FL_FWD; FL_BRK; } // Verilog-XL compatibility
"`timescale"{ws}+[^\n\r]* { FL; PARSEP->lexTimescaleParse(yylval.fl,
yytext + strlen("`timescale"));
yytext + std::strlen("`timescale"));
FL_BRK; }
"`unconnected_drive"{ws}+"pull0" { FL; return yaT_UNCONNECTED_PULL0; }
"`unconnected_drive"{ws}+"pull1" { FL; return yaT_UNCONNECTED_PULL1; }

View File

@ -58,6 +58,13 @@
assignp->timingControlp(nodep == assignsp ? delayp : delayp->cloneTree(false)); \
} \
}
#define STRENGTHUNSUP(nodep) \
{ \
if (nodep) { \
BBUNSUP((nodep->fileline()), "Unsupported: Strength specifier on this gate type"); \
nodep->deleteTree(); \
} \
}
//======================================================================
// Statics (for here only)
@ -79,6 +86,7 @@ public:
AstNodeDType* m_varDTypep = nullptr; // Pointer to data type for next signal declaration
AstNodeDType* m_memDTypep = nullptr; // Pointer to data type for next member declaration
AstNode* m_netDelayp = nullptr; // Pointer to delay for next signal declaration
AstStrengthSpec* m_netStrengthp = nullptr; // Pointer to strength for next net declaration
AstNodeModule* m_modp = nullptr; // Last module for timeunits
bool m_pinAnsi = false; // In ANSI port list
FileLine* m_instModuleFl = nullptr; // Fileline of module referenced for instantiations
@ -183,6 +191,7 @@ public:
m_varDTypep = dtypep;
}
void setNetDelay(AstNode* netDelayp) { m_netDelayp = netDelayp; }
void setNetStrength(AstStrengthSpec* netStrengthp) { m_netStrengthp = netStrengthp; }
void pinPush() {
m_pinStack.push(m_pinNum);
m_pinNum = 1;
@ -302,6 +311,16 @@ int V3ParseGrammar::s_modTypeImpNum = 0;
if (nodep) nodep->deleteTree(); \
}
#define APPLY_STRENGTH_TO_LIST(beginp, strengthSpecNodep, typeToCast) \
{ \
if (AstStrengthSpec* specp = VN_CAST(strengthSpecNodep, StrengthSpec)) { \
for (auto* nodep = beginp; nodep; nodep = nodep->nextp()) { \
auto* const assignp = VN_AS(nodep, typeToCast); \
assignp->strengthSpecp(nodep == beginp ? specp : specp->cloneTree(false)); \
} \
} \
}
static void ERRSVKWD(FileLine* fileline, const string& tokname) {
static int toldonce = 0;
fileline->v3error(
@ -557,6 +576,8 @@ BISONPRE_VERSION(3.7,%define api.header.include {"V3ParseBison.h"})
%token<fl> yGLOBAL__CLOCKING "global-then-clocking"
%token<fl> yGLOBAL__ETC "global"
%token<fl> yGLOBAL__LEX "global-in-lex"
%token<fl> yHIGHZ0 "highz0"
%token<fl> yHIGHZ1 "highz1"
%token<fl> yIF "if"
%token<fl> yIFF "iff"
//UNSUP %token<fl> yIGNORE_BINS "ignore_bins"
@ -611,6 +632,8 @@ BISONPRE_VERSION(3.7,%define api.header.include {"V3ParseBison.h"})
%token<fl> yPROGRAM "program"
%token<fl> yPROPERTY "property"
%token<fl> yPROTECTED "protected"
%token<fl> yPULL0 "pull0"
%token<fl> yPULL1 "pull1"
%token<fl> yPULLDOWN "pulldown"
%token<fl> yPULLUP "pullup"
%token<fl> yPURE "pure"
@ -648,6 +671,8 @@ BISONPRE_VERSION(3.7,%define api.header.include {"V3ParseBison.h"})
%token<fl> ySTATIC__LEX "static-in-lex"
%token<fl> ySTRING "string"
//UNSUP %token<fl> ySTRONG "strong"
%token<fl> ySTRONG0 "strong0"
%token<fl> ySTRONG1 "strong1"
%token<fl> ySTRUCT "struct"
%token<fl> ySUPER "super"
%token<fl> ySUPPLY0 "supply0"
@ -701,6 +726,8 @@ BISONPRE_VERSION(3.7,%define api.header.include {"V3ParseBison.h"})
//UNSUP %token<fl> yWAIT_ORDER "wait_order"
%token<fl> yWAND "wand"
//UNSUP %token<fl> yWEAK "weak"
%token<fl> yWEAK0 "weak0"
%token<fl> yWEAK1 "weak1"
%token<fl> yWHILE "while"
//UNSUP %token<fl> yWILDCARD "wildcard"
%token<fl> yWIRE "wire"
@ -1731,11 +1758,18 @@ parameter_port_declarationTypeFrontE: // IEEE: parameter_port_declaration w/o as
;
net_declaration<nodep>: // IEEE: net_declaration - excluding implict
net_declarationFront netSigList ';' { $$ = $2; }
net_declarationFront netSigList ';'
{ $$ = $2;
if (GRAMMARP->m_netStrengthp) {
VL_DO_CLEAR(delete GRAMMARP->m_netStrengthp, GRAMMARP->m_netStrengthp = nullptr);
}}
;
net_declarationFront: // IEEE: beginning of net_declaration
net_declRESET net_type strengthSpecE net_scalaredE net_dataTypeE { VARDTYPE_NDECL($5); }
net_declRESET net_type driveStrengthE net_scalaredE net_dataTypeE
{ VARDTYPE_NDECL($5);
GRAMMARP->setNetStrength(VN_CAST($3, StrengthSpec));
}
//UNSUP net_declRESET yINTERCONNECT signingE rangeListE { VARNET($2); VARDTYPE(x); }
;
@ -2441,10 +2475,11 @@ module_common_item<nodep>: // ==IEEE: module_common_item
;
continuous_assign<nodep>: // IEEE: continuous_assign
yASSIGN strengthSpecE delay_controlE assignList ';'
yASSIGN driveStrengthE delay_controlE assignList ';'
{
$$ = $4;
PUT_DLYS_IN_ASSIGNS($3, $$);
APPLY_STRENGTH_TO_LIST($4, $2, AssignW);
PUT_DLYS_IN_ASSIGNS($3, $4);
}
;
@ -2733,6 +2768,7 @@ netSig<varp>: // IEEE: net_decl_assignment - one element from
| netId sigAttrListE '=' expr
{ $$ = VARDONEA($<fl>1, *$1, nullptr, $2);
auto* const assignp = new AstAssignW{$3, new AstVarRef{$<fl>1, *$1, VAccess::WRITE}, $4};
if (GRAMMARP->m_netStrengthp) assignp->strengthSpecp(GRAMMARP->m_netStrengthp->cloneTree(false));
if ($$->delayp()) assignp->timingControlp($$->delayp()->unlinkFrBack()); // IEEE 1800-2017 10.3.3
$$->addNext(assignp); }
| netId variable_dimensionList sigAttrListE
@ -4715,22 +4751,22 @@ stream_expressionOrDataType<nodep>: // IEEE: from streaming_concatenation
// Gate declarations
gateDecl<nodep>:
yBUF delay_controlE gateBufList ';' { $$ = $3; PUT_DLYS_IN_ASSIGNS($2, $3); }
| yBUFIF0 delay_controlE gateBufif0List ';' { $$ = $3; PUT_DLYS_IN_ASSIGNS($2, $3); }
| yBUFIF1 delay_controlE gateBufif1List ';' { $$ = $3; PUT_DLYS_IN_ASSIGNS($2, $3); }
| yNOT delay_controlE gateNotList ';' { $$ = $3; PUT_DLYS_IN_ASSIGNS($2, $3); }
| yNOTIF0 delay_controlE gateNotif0List ';' { $$ = $3; PUT_DLYS_IN_ASSIGNS($2, $3); }
| yNOTIF1 delay_controlE gateNotif1List ';' { $$ = $3; PUT_DLYS_IN_ASSIGNS($2, $3); }
| yAND delay_controlE gateAndList ';' { $$ = $3; PUT_DLYS_IN_ASSIGNS($2, $3); }
| yNAND delay_controlE gateNandList ';' { $$ = $3; PUT_DLYS_IN_ASSIGNS($2, $3); }
| yOR delay_controlE gateOrList ';' { $$ = $3; PUT_DLYS_IN_ASSIGNS($2, $3); }
| yNOR delay_controlE gateNorList ';' { $$ = $3; PUT_DLYS_IN_ASSIGNS($2, $3); }
| yXOR delay_controlE gateXorList ';' { $$ = $3; PUT_DLYS_IN_ASSIGNS($2, $3); }
| yXNOR delay_controlE gateXnorList ';' { $$ = $3; PUT_DLYS_IN_ASSIGNS($2, $3); }
| yPULLUP delay_controlE gatePullupList ';' { $$ = $3; PUT_DLYS_IN_ASSIGNS($2, $3); }
yBUF driveStrengthE delay_controlE gateBufList ';' { $$ = $4; STRENGTHUNSUP($2); PUT_DLYS_IN_ASSIGNS($3, $4); }
| yBUFIF0 driveStrengthE delay_controlE gateBufif0List ';' { $$ = $4; STRENGTHUNSUP($2); PUT_DLYS_IN_ASSIGNS($3, $4); }
| yBUFIF1 driveStrengthE delay_controlE gateBufif1List ';' { $$ = $4; STRENGTHUNSUP($2); PUT_DLYS_IN_ASSIGNS($3, $4); }
| yNOT driveStrengthE delay_controlE gateNotList ';' { $$ = $4; APPLY_STRENGTH_TO_LIST($4, $2, AssignW); PUT_DLYS_IN_ASSIGNS($3, $4); }
| yNOTIF0 driveStrengthE delay_controlE gateNotif0List ';' { $$ = $4; STRENGTHUNSUP($2); PUT_DLYS_IN_ASSIGNS($3, $4); }
| yNOTIF1 driveStrengthE delay_controlE gateNotif1List ';' { $$ = $4; STRENGTHUNSUP($2); PUT_DLYS_IN_ASSIGNS($3, $4); }
| yAND driveStrengthE delay_controlE gateAndList ';' { $$ = $4; APPLY_STRENGTH_TO_LIST($4, $2, AssignW); PUT_DLYS_IN_ASSIGNS($3, $4); }
| yNAND driveStrengthE delay_controlE gateNandList ';' { $$ = $4; APPLY_STRENGTH_TO_LIST($4, $2, AssignW); PUT_DLYS_IN_ASSIGNS($3, $4); }
| yOR driveStrengthE delay_controlE gateOrList ';' { $$ = $4; APPLY_STRENGTH_TO_LIST($4, $2, AssignW); PUT_DLYS_IN_ASSIGNS($3, $4); }
| yNOR driveStrengthE delay_controlE gateNorList ';' { $$ = $4; APPLY_STRENGTH_TO_LIST($4, $2, AssignW); PUT_DLYS_IN_ASSIGNS($3, $4); }
| yXOR driveStrengthE delay_controlE gateXorList ';' { $$ = $4; APPLY_STRENGTH_TO_LIST($4, $2, AssignW); PUT_DLYS_IN_ASSIGNS($3, $4); }
| yXNOR driveStrengthE delay_controlE gateXnorList ';' { $$ = $4; APPLY_STRENGTH_TO_LIST($4, $2, AssignW); PUT_DLYS_IN_ASSIGNS($3, $4); }
| yPULLUP delay_controlE gatePullupList ';' { $$ = $3; PUT_DLYS_IN_ASSIGNS($2, $3); }
| yPULLDOWN delay_controlE gatePulldownList ';' { $$ = $3; PUT_DLYS_IN_ASSIGNS($2, $3); }
| yNMOS delay_controlE gateBufif1List ';' { $$ = $3; PUT_DLYS_IN_ASSIGNS($2, $3); } // ~=bufif1, as don't have strengths yet
| yPMOS delay_controlE gateBufif0List ';' { $$ = $3; PUT_DLYS_IN_ASSIGNS($2, $3); } // ~=bufif0, as don't have strengths yet
| yNMOS delay_controlE gateBufif1List ';' { $$ = $3; PUT_DLYS_IN_ASSIGNS($2, $3); }
| yPMOS delay_controlE gateBufif0List ';' { $$ = $3; PUT_DLYS_IN_ASSIGNS($2, $3); }
//
| yTRAN delay_controlE gateUnsupList ';' { $$ = $3; GATEUNSUP($3,"tran"); } // Unsupported
| yRCMOS delay_controlE gateUnsupList ';' { $$ = $3; GATEUNSUP($3,"rcmos"); } // Unsupported
@ -4898,21 +4934,33 @@ gatePinExpr<nodep>:
expr { $$ = GRAMMARP->createGatePin($1); }
;
// This list is also hardcoded in VParseLex.l
strength: // IEEE: strength0+strength1 - plus HIGHZ/SMALL/MEDIUM/LARGE
ygenSTRENGTH { BBUNSUP($1, "Unsupported: Verilog 1995 strength specifiers"); }
| ySUPPLY0 { BBUNSUP($1, "Unsupported: Verilog 1995 strength specifiers"); }
| ySUPPLY1 { BBUNSUP($1, "Unsupported: Verilog 1995 strength specifiers"); }
strength0<strength>:
ySUPPLY0 { $$ = VStrength::SUPPLY; }
| ySTRONG0 { $$ = VStrength::STRONG; }
| yPULL0 { $$ = VStrength::PULL; }
| yWEAK0 { $$ = VStrength::WEAK; }
;
strengthSpecE: // IEEE: drive_strength + pullup_strength + pulldown_strength + charge_strength - plus empty
/* empty */ { }
| strengthSpec { }
strength1<strength>:
ySUPPLY1 { $$ = VStrength::SUPPLY; }
| ySTRONG1 { $$ = VStrength::STRONG; }
| yPULL1 { $$ = VStrength::PULL; }
| yWEAK1 { $$ = VStrength::WEAK; }
;
strengthSpec: // IEEE: drive_strength + pullup_strength + pulldown_strength + charge_strength - plus empty
yP_PAR__STRENGTH strength ')' { }
| yP_PAR__STRENGTH strength ',' strength ')' { }
driveStrengthE<nodep>:
/* empty */ { $$ = nullptr; }
| driveStrength { $$ = $1; }
;
driveStrength<nodep>:
yP_PAR__STRENGTH strength0 ',' strength1 ')' { $$ = new AstStrengthSpec{$1, $2, $4}; }
| yP_PAR__STRENGTH strength1 ',' strength0 ')' { $$ = new AstStrengthSpec{$1, $4, $2}; }
| yP_PAR__STRENGTH strength0 ',' yHIGHZ1 ')' { BBUNSUP($<fl>4, "Unsupported: highz strength"); }
| yP_PAR__STRENGTH strength1 ',' yHIGHZ0 ')' { BBUNSUP($<fl>4, "Unsupported: highz strength"); }
| yP_PAR__STRENGTH yHIGHZ0 ',' strength1 ')' { BBUNSUP($<fl>2, "Unsupported: highz strength"); }
| yP_PAR__STRENGTH yHIGHZ1 ',' strength0 ')' { BBUNSUP($<fl>2, "Unsupported: highz strength"); }
;
//************************************************

View File

@ -1856,7 +1856,7 @@ sub _make_main {
if ($self->{savable}) {
$fh->print(" const char* save_time_strp = contextp->commandArgsPlusMatch(\"save_time=\");\n");
$fh->print(" unsigned int save_time = !save_time_strp[0] ? 0 : atoi(save_time_strp+strlen(\"+save_time=\"));\n");
$fh->print(" unsigned int save_time = !save_time_strp[0] ? 0 : std::atoi(save_time_strp + std::strlen(\"+save_time=\"));\n");
$fh->print(" const char* save_restore_strp = contextp->commandArgsPlusMatch(\"save_restore=\");\n");
$fh->print(" unsigned int save_restore = !save_restore_strp[0] ? 0 : 1;\n");
}

View File

@ -34,7 +34,7 @@ static const bool verbose = false;
#define TEST_CHECK_EQ(got, exp) TEST_CHECK(got, exp, ((got) == (exp)));
#define TEST_CHECK_NE(got, exp) TEST_CHECK(got, exp, ((got) != (exp)));
#define TEST_CHECK_CSTR(got, exp) TEST_CHECK(got, exp, 0 == strcmp((got), (exp)));
#define TEST_CHECK_CSTR(got, exp) TEST_CHECK(got, exp, 0 == std::strcmp((got), (exp)));
#define TEST_CHECK_HEX_EQ(got, exp) \
do { \

View File

@ -28,13 +28,13 @@ private:
public:
TestSimulator() {
vpi_get_vlog_info(&m_info);
if (0 == strcmp(m_info.product, "Verilator")) {
if (0 == std::strcmp(m_info.product, "Verilator")) {
m_simulators.verilator = true;
} else if (0 == strcmp(m_info.product, "Verilator")) {
} else if (0 == std::strcmp(m_info.product, "Verilator")) {
m_simulators.icarus = true;
} else if (0
== strncmp(m_info.product, "Chronologic Simulation VCS",
strlen("Chronologic Simulation VCS"))) {
std::strlen("Chronologic Simulation VCS"))) {
m_simulators.vcs = true;
} else {
printf("%%Warning: %s:%d: Unknown simulator in TestSimulator.h: %s\n", __FILE__,

View File

@ -13,7 +13,7 @@
// please note it here, otherwise:**
//
// This file ONLY is placed under the Creative Commons Public Domain, for
// any use, without warranty, 2022 by ____YOUR_NAME_HERE____.
// any use, without warranty, 2022 by Wilson Snyder.
// SPDX-License-Identifier: CC0-1.0
module t(/*AUTOARG*/

View File

@ -12,14 +12,20 @@ class Cls;
endclass : Cls
module t (/*AUTOARG*/);
typedef Cls Cls2;
initial begin
Cls c;
Cls2 c2;
if (c != null) $stop;
if (c) $stop;
if (c2) $stop;
$display("Display: null = \"%p\"", c); // null
c = new;
c2 = new;
if (c == null) $stop;
if (!c) $stop;
if (!c2) $stop;
$display("Display: newed = \"%p\"", c); // '{imembera:0, imemberb:0}
c.imembera = 10;
c.imemberb = 20;

View File

@ -0,0 +1,21 @@
#!/usr/bin/env 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.
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
scenarios(simulator => 1);
compile(
);
execute(
check_finished => 1,
);
ok(1);
1;

View File

@ -0,0 +1,28 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed under the Creative Commons Public Domain, for
// any use, without warranty, 2022 by Wilson Snyder.
// SPDX-License-Identifier: CC0-1.0
module t;
class T;
function automatic void print_str(input string a_string);
$display(a_string);
endfunction
static function automatic void static_print_str(input string a_string);
$display(a_string);
endfunction
endclass
initial begin
T t_c = new;
t_c.print_str("function though member");
t_c.static_print_str("static function through member");
T::static_print_str("static function through class");
$write("*-* All Finished *-*\n");
$finish;
end
endmodule

View File

@ -168,10 +168,10 @@ void i_string(const char** x) {
static int n = 0;
printf("i_string %d\n", n);
if (n++ % 2 == 0) {
if (strcmp(*x, "Hello") != 0) stop();
if (std::strcmp(*x, "Hello") != 0) stop();
*x = "Good";
} else {
if (strcmp(*x, "World") != 0) stop();
if (std::strcmp(*x, "World") != 0) stop();
*x = "Bye";
}
}
@ -296,10 +296,10 @@ void i_string_t(const char** x) {
static int n = 0;
printf("i_string_t %d\n", n);
if (n++ % 2 == 0) {
if (strcmp(*x, "World") != 0) stop();
if (std::strcmp(*x, "World") != 0) stop();
*x = "Bye";
} else {
if (strcmp(*x, "Hello") != 0) stop();
if (std::strcmp(*x, "Hello") != 0) stop();
*x = "Good";
}
}
@ -962,10 +962,10 @@ void check_exports() {
e_string(&x_string);
if ((n % 2) == 0) {
if (x_chandle) stop();
if (strcmp(x_string, "Hello") != 0) stop();
if (std::strcmp(x_string, "Hello") != 0) stop();
} else {
if (x_chandle) stop();
if (strcmp(x_string, "World") != 0) stop();
if (std::strcmp(x_string, "World") != 0) stop();
}
x_bit = n % 2;
@ -1045,10 +1045,10 @@ void check_exports() {
e_string_t(&x_string_t);
if ((n % 2) == 0) {
if (x_chandle_t != NULL) stop();
if (strcmp(x_string_t, "World") != 0) stop();
if (std::strcmp(x_string_t, "World") != 0) stop();
} else {
if (x_chandle_t != NULL) stop();
if (strcmp(x_string_t, "Hello") != 0) stop();
if (std::strcmp(x_string_t, "Hello") != 0) stop();
}
x_bit_t = n % 2;

View File

@ -155,9 +155,9 @@ void i_string(const char* i) {
static int n = 0;
printf("i_string %d\n", n);
if (n++ % 2 == 0) {
if (strcmp(i, "World") != 0) stop();
if (std::strcmp(i, "World") != 0) stop();
} else {
if (strcmp(i, "Hello") != 0) stop();
if (std::strcmp(i, "Hello") != 0) stop();
}
}
@ -266,9 +266,9 @@ void i_string_t(const char* i) {
static int n = 0;
printf("i_string_t %d\n", n);
if (n++ % 2 == 0) {
if (strcmp(i, "World") != 0) stop();
if (std::strcmp(i, "World") != 0) stop();
} else {
if (strcmp(i, "Hello") != 0) stop();
if (std::strcmp(i, "Hello") != 0) stop();
}
}

View File

@ -711,9 +711,9 @@ void check_exports() {
e_string(&x_string);
if ((n % 2) == 0) {
if (strcmp(x_string, "Hello") != 0) stop();
if (std::strcmp(x_string, "Hello") != 0) stop();
} else {
if (strcmp(x_string, "World") != 0) stop();
if (std::strcmp(x_string, "World") != 0) stop();
}
e_bit(&x_bit);
@ -772,9 +772,9 @@ void check_exports() {
e_string_t(&x_string_t);
if ((n % 2) == 0) {
if (strcmp(x_string_t, "Hello") != 0) stop();
if (std::strcmp(x_string_t, "Hello") != 0) stop();
} else {
if (strcmp(x_string_t, "World") != 0) stop();
if (std::strcmp(x_string_t, "World") != 0) stop();
}
e_bit_t(&x_bit_t);

View File

@ -115,9 +115,10 @@ int dpix_run_tests() {
#ifndef CADENCE // Unimplemented; how hard is it?
printf("svDpiVersion: %s\n", svDpiVersion());
CHECK_RESULT(
bool,
strcmp(svDpiVersion(), "1800-2005") == 0 || strcmp(svDpiVersion(), "P1800-2005") == 0, 1);
CHECK_RESULT(bool,
std::strcmp(svDpiVersion(), "1800-2005") == 0
|| std::strcmp(svDpiVersion(), "P1800-2005") == 0,
1);
#endif
CHECK_RESULT(int, dpix_int123(), 0x123);

View File

@ -303,9 +303,9 @@ void check_exports() {
#endif
if (e_chandle()) stop();
if ((n % 2) == 0) {
if (strcmp(e_string(), "Hello") != 0) stop();
if (std::strcmp(e_string(), "Hello") != 0) stop();
} else {
if (strcmp(e_string(), "World") != 0) stop();
if (std::strcmp(e_string(), "World") != 0) stop();
}
if (e_bit() != (n % 2)) stop();
if (e_logic() != !(n % 2)) stop();
@ -327,9 +327,9 @@ void check_exports() {
#endif
if (e_chandle_t()) stop();
if ((n % 2) == 0) {
if (strcmp(e_string_t(), "Hello") != 0) stop();
if (std::strcmp(e_string_t(), "Hello") != 0) stop();
} else {
if (strcmp(e_string_t(), "World") != 0) stop();
if (std::strcmp(e_string_t(), "World") != 0) stop();
}
if (e_bit_t() != (n % 2)) stop();
if (e_logic_t() != !(n % 2)) stop();

View File

@ -39,5 +39,5 @@ extern int dpii_string(const char* s);
int dpii_string(const char* s) {
printf("dpii_string: %s\n", s);
return strlen(s);
return std::strlen(s);
}

View File

@ -60,9 +60,9 @@ void mon_scope_name(const char* namep) {
#ifdef TEST_VERBOSE
VL_PRINTF("- mon_scope_name('%s', \"%s\");\n", modp, namep);
#endif
if (strcmp(namep, "t.sub"))
if (std::strcmp(namep, "t.sub"))
vl_fatal(__FILE__, __LINE__, "", (std::string{"Unexp scope name "} + namep).c_str());
if (strcmp(modp, "t.sub"))
if (std::strcmp(modp, "t.sub"))
vl_fatal(__FILE__, __LINE__, "", (std::string{"Unexp dpiscope name "} + modp).c_str());
}

View File

@ -11,6 +11,9 @@ if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); di
scenarios(simulator => 1);
compile(
verilator_flags => [# Custom as don't want -cc
"-Mdir $Self->{obj_dir}",
"--debug-check", ],
verilator_flags2 => ['--exe --build --main'],
verilator_make_cmake => 0,
verilator_make_gmake => 0,

49
test_regress/t/t_flag_prefix.pl Executable file
View File

@ -0,0 +1,49 @@
#!/usr/bin/env perl
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# Copyright 2022 by Geza Lore. 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.
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
scenarios(vlt => 1);
compile(
verilator_flags2 => ["--prefix t_flag_prefix", # should be overridden
"--prefix Vprefix",
"--exe", "--main", "--stats", "--build"],
verilator_make_cmake => 0,
verilator_make_gmake => 0,
make_main => 0,
);
execute(
check_finished => 1,
executable => "$Self->{obj_dir}/Vprefix",
);
sub check_files {
foreach my $path (glob("$Self->{obj_dir}/*")) {
my $filename = substr $path, ((length $Self->{obj_dir}) + 1);
next if ($filename =~ /^.*\.log$/);
if ($filename =~ /t_flag_prefix/) {
error("bad filename $filename");
next;
}
next if ($filename =~ /^(.*\.(o|a)|Vprefix)$/);
my $fh = IO::File->new("<$path") or error("$! $filenme");
while (defined(my $line = $fh->getline)) {
$line =~ s/--prefix V?t_flag_prefix//g;
$line =~ s/obj_vlt\/t_flag_prefix//g;
$line =~ s/t\/t_flag_prefix\.v//g;
error("bad line in $filename: $line") if $line =~ /t_flag_prefix/;
}
}
}
check_files();
ok(1);
1;

35
test_regress/t/t_flag_prefix.v Executable file
View File

@ -0,0 +1,35 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed under the Creative Commons Public Domain, for
// any use, without warranty, 2022 by Geza Lore.
// SPDX-License-Identifier: CC0-1.0
module t;
sub sub();
endmodule
module sub;
// no_inline_module, so it goes into separate file
/* verilator no_inline_module */
// Goes into const pool which is separate file
wire bit [255:0] C = {32'h1111_1111,
32'h2222_2222,
32'h3333_3333,
32'h4444_4444,
32'h5555_5555,
32'h6666_6666,
32'h7777_7777,
32'h8888_8888};
initial begin
// Note: Base index via $c to prevent optimization
$display("0x%32x", C[$c(0*32)+:32]);
$display("0x%32x", C[$c(2*32)+:32]);
$display("0x%32x", C[$c(4*32)+:32]);
$display("0x%32x", C[$c(6*32)+:32]);
$write("*-* All Finished *-*\n");
$finish;
end
endmodule

View File

@ -1,4 +1,6 @@
%Error: t/t_mailbox.v:20:4: Can't find typedef: 'mailbox'
20 | mailbox m;
20 | mailbox #(int) m;
| ^~~~~~~
%Error: Exiting due to
%Error: Internal Error: t/t_mailbox.v:20:14: ../V3LinkDot.cpp:#: Pin not under instance?
20 | mailbox #(int) m;
| ^~~

View File

@ -17,7 +17,7 @@
// endclass
module t(/*AUTOARG*/);
mailbox m;
mailbox #(int) m;
int msg;
int out;

View File

@ -0,0 +1,6 @@
%Error: t/t_mailbox.v:20:4: Can't find typedef: 'mailbox'
20 | mailbox #(int) m;
| ^~~~~~~
%Error: Internal Error: t/t_mailbox.v:20:14: ../V3LinkDot.cpp:#: Pin not under instance?
20 | mailbox #(int) m;
| ^~~

22
test_regress/t/t_mailbox_bad.pl Executable file
View File

@ -0,0 +1,22 @@
#!/usr/bin/env perl
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# Copyright 2022 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.
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
scenarios(vlt => 1);
top_filename("t_mailbox.v");
lint(
verilator_flags2 => ["--xml-only"],
fails => 1,
expect_filename => $Self->{golden_filename},
);
ok(1);
1;

View File

@ -0,0 +1,17 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed under the Creative Commons Public Domain, for
// any use, without warranty, 2022 by Wilson Snyder.
// SPDX-License-Identifier: CC0-1.0
module t(/*AUTOARG*/);
mailbox #(int) m;
initial begin
m = new(4);
if (m.bad_method() != 0) $stop;
$write("*-* All Finished *-*\n");
$finish;
end
endmodule

View File

@ -6,16 +6,16 @@
// Methods defined by IEEE:
// class process;
// enum state { FINISHED, RUNNING, WAITING, SUSPENDED, KILLED };
// enum state { FINISHED, RUNNING, WAITING, SUSPENDED, KILLED }; // UVM uses KILLED, FINISHED
// static function process self();
// function state status();
// function void kill();
// task await(); // Warn as unsupported (no UVM library use)
// function void suspend(); // Warn as unsupported (no UVM library use)
// function void resume(); // Warn as unsupported (no UVM library use)
// function void srandom( int seed ); // Just ignore?
// function string get_randstate(); // Just ignore?
// function void set_randstate( string state ); // Just ignore?
// function void srandom( int seed ); // Operate on all proceses for now?
// function string get_randstate(); // Operate on all proceses for now?
// function void set_randstate( string state ); // Operate on all proceses for now?
// endclass
module t(/*AUTOARG*/);

View File

@ -0,0 +1,10 @@
%Error: t/t_process.v:22:4: Can't find typedef: 'process'
22 | process p;
| ^~~~~~~
%Error-UNSUPPORTED: t/t_process.v:26:20: Unsupported: 'process'
26 | p = process::self();
| ^~~~
... For error description see https://verilator.org/warn/UNSUPPORTED?v=latest
%Error: Internal Error: t/t_process.v:26:11: ../V3LinkDot.cpp:#: Bad package link
26 | p = process::self();
| ^~~~~~~

22
test_regress/t/t_process_bad.pl Executable file
View File

@ -0,0 +1,22 @@
#!/usr/bin/env perl
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# Copyright 2022 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.
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
scenarios(vlt => 1);
top_filename("t_process.v");
lint(
verilator_flags2 => ["--xml-only"],
fails => 1,
expect_filename => $Self->{golden_filename},
);
ok(1);
1;

View File

@ -0,0 +1,20 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed under the Creative Commons Public Domain, for
// any use, without warranty, 2022 by Wilson Snyder.
// SPDX-License-Identifier: CC0-1.0
module t(/*AUTOARG*/);
process p;
initial begin
if (p != null) $stop;
p = process::self();
if (p.bad_method() != 0) $stop;
p.bad_method_2();
$write("*-* All Finished *-*\n");
$finish;
end
endmodule

View File

@ -15,7 +15,7 @@ int sc_main(int argc, char* argv[]) {
/* We expect to find clk in here. */
for (int i = 0; i < ch.size(); ++i) {
if (!strcmp(ch[i]->basename(), "clk")) found = true;
if (!std::strcmp(ch[i]->basename(), "clk")) found = true;
}
if (found) {

View File

@ -100,7 +100,7 @@ int main(int argc, char** argv, char** env) {
#endif
// Clear out the data
memset(varData, 0, (varBits + 7) / 8);
std::memset(varData, 0, (varBits + 7) / 8);
}
}

View File

@ -1,4 +1,7 @@
%Error: t/t_semaphore.v:17:4: Can't find typedef: 'semaphore'
17 | semaphore s;
| ^~~~~~~~~
%Error: t/t_semaphore.v:18:4: Can't find typedef: 'semaphore'
18 | semaphore s2;
| ^~~~~~~~~
%Error: Exiting due to

View File

@ -13,8 +13,9 @@
// endclass
module t(/*AUTOARG*/);
//From UVM:
// From UVM:
semaphore s;
semaphore s2;
int msg;
initial begin
@ -30,6 +31,7 @@ module t(/*AUTOARG*/);
s.put(2);
if (s.try_get(2) <= 0) $stop;
`ifndef VERILATOR
fork
begin
#10; // So later then get() starts below
@ -42,6 +44,10 @@ module t(/*AUTOARG*/);
s.get();
end
join
`endif
s2 = new;
if (s2.try_get() != 0) $stop;
$write("*-* All Finished *-*\n");
$finish;

View File

@ -0,0 +1,7 @@
%Error: t/t_semaphore.v:17:4: Can't find typedef: 'semaphore'
17 | semaphore s;
| ^~~~~~~~~
%Error: t/t_semaphore.v:18:4: Can't find typedef: 'semaphore'
18 | semaphore s2;
| ^~~~~~~~~
%Error: Exiting due to

View File

@ -0,0 +1,22 @@
#!/usr/bin/env perl
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# Copyright 2022 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.
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
scenarios(vlt => 1);
top_filename("t_semaphore.v");
lint(
verilator_flags2 => ["--xml-only"],
fails => 1,
expect_filename => $Self->{golden_filename},
);
ok(1);
1;

View File

@ -0,0 +1,17 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed under the Creative Commons Public Domain, for
// any use, without warranty, 2022 by Wilson Snyder.
// SPDX-License-Identifier: CC0-1.0
module t(/*AUTOARG*/);
semaphore s;
initial begin
s = new(4);
if (s.bad_method() != 0) $stop;
$write("*-* All Finished *-*\n");
$finish;
end
endmodule

View File

@ -0,0 +1,21 @@
#!/usr/bin/env perl
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# Copyright 2022 by Antmicro Ltd. 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.
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
scenarios(simulator => 1);
compile(
);
execute(
check_finished => 1,
);
ok(1);
1;

View File

@ -0,0 +1,38 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed under the Creative Commons Public Domain, for
// any use, without warranty, 2022 by Antmicro Ltd.
// SPDX-License-Identifier: CC0-1.0
module t (/*AUTOARG*/);
wire a;
assign (weak0, weak1) a = 1;
assign (weak0, supply1) a = 1;
assign (strong0, strong1) a = 0;
wire (weak0, weak1) b = 1;
assign (strong0, strong1) b = 0;
wire [1:0] c;
assign (weak0, supply1) c = '1;
assign (supply0, pull1) c = '1;
assign (strong0, strong1) c = '0;
supply0 d;
assign (strong0, strong1) d = 1;
wire (supply0, supply1) e = 'z;
assign (weak0, weak1) e = 1;
always begin
if (a && !b && c === '1 && !d && e) begin
$write("*-* All Finished *-*\n");
$finish;
end
else begin
$write("Error: a = %b, b = %b, c = %b, d = %b, e = %b ", a, b, c, d, e);
$write("expected: a = 1, b = 0, c = 11, d = 0, e = 1\n");
$stop;
end
end
endmodule

View File

@ -0,0 +1,5 @@
%Error-UNSUPPORTED: t/t_strength_bufif1.v:9:11: Unsupported: Strength specifier on this gate type
9 | bufif1 (strong0, strong1) (a, 1'b1, 1'b1);
| ^
... For error description see https://verilator.org/warn/UNSUPPORTED?v=latest
%Error: Exiting due to

View File

@ -0,0 +1,19 @@
#!/usr/bin/env perl
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# Copyright 2022 by Antmicro Ltd. 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.
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
scenarios(vlt => 1);
lint(
fails => $Self->{vlt_all},
expect_filename => $Self->{golden_filename},
);
ok(1);
1;

View File

@ -0,0 +1,17 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed under the Creative Commons Public Domain, for
// any use, without warranty, 2022 by Antmicro Ltd.
// SPDX-License-Identifier: CC0-1.0
module t (/*AUTOARG*/);
wire a;
bufif1 (strong0, strong1) (a, 1'b1, 1'b1);
always begin
if (a) begin
$write("*-* All Finished *-*\n");
$finish;
end
end
endmodule

View File

@ -0,0 +1,14 @@
%Error-UNSUPPORTED: t/t_strength_highz.v:8:17: Unsupported: highz strength
8 | wire (weak0, highz1) a = 1;
| ^~~~~~
... For error description see https://verilator.org/warn/UNSUPPORTED?v=latest
%Error-UNSUPPORTED: t/t_strength_highz.v:9:19: Unsupported: highz strength
9 | wire (strong1, highz0) b = 0;
| ^~~~~~
%Error-UNSUPPORTED: t/t_strength_highz.v:10:10: Unsupported: highz strength
10 | wire (highz0, pull1) c = 0;
| ^~~~~~
%Error-UNSUPPORTED: t/t_strength_highz.v:11:10: Unsupported: highz strength
11 | wire (highz1, supply0) d = 1;
| ^~~~~~
%Error: Exiting due to

View File

@ -0,0 +1,19 @@
#!/usr/bin/env 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.
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
scenarios(vlt => 1);
lint(
fails => $Self->{vlt_all},
expect_filename => $Self->{golden_filename},
);
ok(1);
1;

View File

@ -0,0 +1,19 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed under the Creative Commons Public Domain, for
// any use, without warranty, 2022 by Antmicro Ltd.
// SPDX-License-Identifier: CC0-1.0
module t (/*AUTOARG*/);
wire (weak0, highz1) a = 1;
wire (strong1, highz0) b = 0;
wire (highz0, pull1) c = 0;
wire (highz1, supply0) d = 1;
always begin
if (a === 1'bz && b === 1'bz && c === 1'bz && d === 1'bz) begin
$write("*-* All Finished *-*\n");
$finish;
end
end
endmodule

View File

@ -0,0 +1,4 @@
%Error: t/t_strength_strong1_strong1_bad.v:8:19: syntax error, unexpected strong1
8 | wire (strong1, strong1) a = 1;
| ^~~~~~~
%Error: Exiting due to

View File

@ -0,0 +1,19 @@
#!/usr/bin/env perl
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# Copyright 2022 by Antmicro Ltd. 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.
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
scenarios(linter => 1);
lint(
fails => 1,
expect_filename => $Self->{golden_filename},
);
ok(1);
1;

View File

@ -0,0 +1,13 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed under the Creative Commons Public Domain, for
// any use, without warranty, 2022 by Antmicro Ltd.
// SPDX-License-Identifier: CC0-1.0
module t (/*AUTOARG*/);
wire (strong1, strong1) a = 1;
initial begin
$stop;
end
endmodule

View File

@ -0,0 +1,220 @@
// -*- mode: C++; c-file-style: "cc-mode" -*-
//
// This file ONLY is placed into the Public Domain, for any use,
// without warranty, 2022 by Wilson Snyder.
// SPDX-License-Identifier: CC0-1.0
#include VM_PREFIX_INCLUDE
VM_PREFIX* tb = nullptr;
bool pass = true;
double sc_time_stamp() { return 0; }
void compare_signals(const sc_signal<sc_bv<256>>& ls, const sc_signal<sc_bv<256>>& rs) {
if (ls.read() != rs.read()) {
pass &= false;
VL_PRINTF("%%Error: Data missmatch in signals %s and %s\n", ls.name(), rs.name());
}
}
void compareWls(int obits, WDataInP const lwp, WDataInP const rwp) {
const int words = VL_WORDS_I(obits);
bool same = true;
for (int i = 0; (i < (words - 1)); ++i) {
if (lwp[i] != rwp[i]) { same = false; }
}
if ((lwp[words - 1] & VL_MASK_E(obits)) != (rwp[words - 1] & VL_MASK_E(obits))) {
same = false;
}
if (!same) {
pass &= false;
VL_PRINTF("%%Error: There is a difference in VlWide variable %d bits wide\n", obits);
}
}
// old macro which is correct but has MT issue with range
#define VL_ASSIGN_SBW_MT_ISSUE(obits, svar, rwp) \
{ \
sc_biguint<(obits)> _butemp; \
for (int i = 0; i < VL_WORDS_I(obits); ++i) { \
int msb = ((i + 1) * VL_IDATASIZE) - 1; \
msb = (msb >= (obits)) ? ((obits)-1) : msb; \
_butemp.range(msb, i* VL_IDATASIZE) = (rwp)[i]; \
} \
(svar).write(_butemp); \
}
#ifdef SYSTEMC_VERSION
int sc_main(int, char**)
#else
int main()
#endif
{
Verilated::debug(0);
tb = new VM_PREFIX("tb");
VlWide<8> /*255:0*/ input_var;
VlWide<8> /*255:0*/ out_var;
// msb is always set to F not to be false positive on checking equality
input_var.m_storage[0] = 0xF2341234;
input_var.m_storage[1] = 0xFEADBEEF;
input_var.m_storage[2] = 0xF5A5A5A5;
input_var.m_storage[3] = 0xF1B2C3D4;
input_var.m_storage[4] = 0xFFFFFFFF;
input_var.m_storage[5] = 0xFAAABBBB;
input_var.m_storage[6] = 0xF000AAAA;
input_var.m_storage[7] = 0xF0101010;
#ifdef SYSTEMC_VERSION
// clang-format off
sc_signal<sc_bv<256>> SC_NAMED(i_29_s), SC_NAMED(i_29_old_s), SC_NAMED(o_29_s), SC_NAMED(o_29_old_s),
SC_NAMED(i_30_s), SC_NAMED(i_30_old_s), SC_NAMED(o_30_s), SC_NAMED(o_30_old_s),
SC_NAMED(i_31_s), SC_NAMED(i_31_old_s), SC_NAMED(o_31_s), SC_NAMED(o_31_old_s),
SC_NAMED(i_32_s), SC_NAMED(i_32_old_s), SC_NAMED(o_32_s), SC_NAMED(o_32_old_s),
SC_NAMED(i_59_s), SC_NAMED(i_59_old_s), SC_NAMED(o_59_s), SC_NAMED(o_59_old_s),
SC_NAMED(i_60_s), SC_NAMED(i_60_old_s), SC_NAMED(o_60_s), SC_NAMED(o_60_old_s),
SC_NAMED(i_62_s), SC_NAMED(i_62_old_s), SC_NAMED(o_62_s), SC_NAMED(o_62_old_s),
SC_NAMED(i_64_s), SC_NAMED(i_64_old_s), SC_NAMED(o_64_s), SC_NAMED(o_64_old_s),
SC_NAMED(i_119_s), SC_NAMED(i_119_old_s), SC_NAMED(o_119_s), SC_NAMED(o_119_old_s),
SC_NAMED(i_120_s), SC_NAMED(i_120_old_s), SC_NAMED(o_120_s), SC_NAMED(o_120_old_s),
SC_NAMED(i_121_s), SC_NAMED(i_121_old_s), SC_NAMED(o_121_s), SC_NAMED(o_121_old_s),
SC_NAMED(i_127_s), SC_NAMED(i_127_old_s), SC_NAMED(o_127_s), SC_NAMED(o_127_old_s),
SC_NAMED(i_128_s), SC_NAMED(i_128_old_s), SC_NAMED(o_128_s), SC_NAMED(o_128_old_s),
SC_NAMED(i_255_s), SC_NAMED(i_255_old_s), SC_NAMED(o_255_s), SC_NAMED(o_255_old_s),
SC_NAMED(i_256_s), SC_NAMED(i_256_old_s), SC_NAMED(o_256_s), SC_NAMED(o_256_old_s);
tb->i_29(i_29_s); tb->i_29_old(i_29_old_s); tb->o_29(o_29_s); tb->o_29_old(o_29_old_s);
tb->i_30(i_30_s); tb->i_30_old(i_30_old_s); tb->o_30(o_30_s); tb->o_30_old(o_30_old_s);
tb->i_31(i_31_s); tb->i_31_old(i_31_old_s); tb->o_31(o_31_s); tb->o_31_old(o_31_old_s);
tb->i_32(i_32_s); tb->i_32_old(i_32_old_s); tb->o_32(o_32_s); tb->o_32_old(o_32_old_s);
tb->i_59(i_59_s); tb->i_59_old(i_59_old_s); tb->o_59(o_59_s); tb->o_59_old(o_59_old_s);
tb->i_60(i_60_s); tb->i_60_old(i_60_old_s); tb->o_60(o_60_s); tb->o_60_old(o_60_old_s);
tb->i_62(i_62_s); tb->i_62_old(i_62_old_s); tb->o_62(o_62_s); tb->o_62_old(o_62_old_s);
tb->i_64(i_64_s); tb->i_64_old(i_64_old_s); tb->o_64(o_64_s); tb->o_64_old(o_64_old_s);
tb->i_119(i_119_s); tb->i_119_old(i_119_old_s); tb->o_119(o_119_s); tb->o_119_old(o_119_old_s);
tb->i_120(i_120_s); tb->i_120_old(i_120_old_s); tb->o_120(o_120_s); tb->o_120_old(o_120_old_s);
tb->i_121(i_121_s); tb->i_121_old(i_121_old_s); tb->o_121(o_121_s); tb->o_121_old(o_121_old_s);
tb->i_127(i_127_s); tb->i_127_old(i_127_old_s); tb->o_127(o_127_s); tb->o_127_old(o_127_old_s);
tb->i_128(i_128_s); tb->i_128_old(i_128_old_s); tb->o_128(o_128_s); tb->o_128_old(o_128_old_s);
tb->i_255(i_255_s); tb->i_255_old(i_255_old_s); tb->o_255(o_255_s); tb->o_255_old(o_255_old_s);
tb->i_256(i_256_s); tb->i_256_old(i_256_old_s); tb->o_256(o_256_s); tb->o_256_old(o_256_old_s);
// clang-format on
#endif
// clang-format off
#ifdef SYSTEMC_VERSION
sc_start(1, SC_NS);
#else
tb->eval();
#endif
// This testcase is testing multi-thread safe VL_ASSIGN_SBW and VL_ASSIGN_WSB macros.
// Testbench is assigning different number of bits from VlWide input_var variable to different inputs.
// Values around multiple of 30 (i.e. BITS_PER_DIGIT defined in SystemC sc_nbdefs.h) are tested with the special care, since
// it is the value by which the data_ptr of sc_biguint underlying data type is increased by (and not expected 32, as width of uint32_t).
// Correctness of the output is compared against the 'old' macro, which is correct but has multi-threaded issue since it's using range function.
// Second part is testing VL_ASSIGN_WSB in a reverse way, it is reading signals from the previous test,
// and comparing the output with (fraction) of VlWide input_var variable.
// clang-format on
VL_ASSIGN_SBW(29, i_29_s, input_var);
VL_ASSIGN_SBW_MT_ISSUE(29, i_29_old_s, input_var);
VL_ASSIGN_SBW(30, i_30_s, input_var);
VL_ASSIGN_SBW_MT_ISSUE(30, i_30_old_s, input_var);
VL_ASSIGN_SBW(31, i_31_s, input_var);
VL_ASSIGN_SBW_MT_ISSUE(31, i_31_old_s, input_var);
VL_ASSIGN_SBW(32, i_32_s, input_var);
VL_ASSIGN_SBW_MT_ISSUE(32, i_32_old_s, input_var);
VL_ASSIGN_SBW(59, i_59_s, input_var);
VL_ASSIGN_SBW_MT_ISSUE(59, i_59_old_s, input_var);
VL_ASSIGN_SBW(60, i_60_s, input_var);
VL_ASSIGN_SBW_MT_ISSUE(60, i_60_old_s, input_var);
VL_ASSIGN_SBW(62, i_62_s, input_var);
VL_ASSIGN_SBW_MT_ISSUE(62, i_62_old_s, input_var);
VL_ASSIGN_SBW(64, i_64_s, input_var);
VL_ASSIGN_SBW_MT_ISSUE(64, i_64_old_s, input_var);
VL_ASSIGN_SBW(119, i_119_s, input_var);
VL_ASSIGN_SBW_MT_ISSUE(119, i_119_old_s, input_var);
VL_ASSIGN_SBW(120, i_120_s, input_var);
VL_ASSIGN_SBW_MT_ISSUE(120, i_120_old_s, input_var);
VL_ASSIGN_SBW(121, i_121_s, input_var);
VL_ASSIGN_SBW_MT_ISSUE(121, i_121_old_s, input_var);
VL_ASSIGN_SBW(127, i_127_s, input_var);
VL_ASSIGN_SBW_MT_ISSUE(127, i_127_old_s, input_var);
VL_ASSIGN_SBW(128, i_128_s, input_var);
VL_ASSIGN_SBW_MT_ISSUE(128, i_128_old_s, input_var);
VL_ASSIGN_SBW(255, i_255_s, input_var);
VL_ASSIGN_SBW_MT_ISSUE(255, i_255_old_s, input_var);
VL_ASSIGN_SBW(256, i_256_s, input_var);
VL_ASSIGN_SBW_MT_ISSUE(256, i_256_old_s, input_var);
#ifdef SYSTEMC_VERSION
sc_start(1, SC_NS);
#else
tb->eval();
#endif
compare_signals(o_29_s, o_29_old_s);
compare_signals(o_30_s, o_30_old_s);
compare_signals(o_31_s, o_31_old_s);
compare_signals(o_32_s, o_32_old_s);
compare_signals(o_59_s, o_59_old_s);
compare_signals(o_60_s, o_60_old_s);
compare_signals(o_62_s, o_62_old_s);
compare_signals(o_64_s, o_64_old_s);
compare_signals(o_119_s, o_119_old_s);
compare_signals(o_120_s, o_120_old_s);
compare_signals(o_121_s, o_121_old_s);
compare_signals(o_127_s, o_127_old_s);
compare_signals(o_128_s, o_128_old_s);
compare_signals(o_255_s, o_255_old_s);
compare_signals(o_256_s, o_256_old_s);
////////////////////////////////
VL_ASSIGN_WSB(29, out_var, o_29_s);
compareWls(29, input_var.data(), out_var.data());
VL_ASSIGN_WSB(30, out_var, o_30_s);
compareWls(30, input_var.data(), out_var.data());
VL_ASSIGN_WSB(31, out_var, o_31_s);
compareWls(31, input_var.data(), out_var.data());
VL_ASSIGN_WSB(32, out_var, o_32_s);
compareWls(32, input_var.data(), out_var.data());
VL_ASSIGN_WSB(59, out_var, o_59_s);
compareWls(59, input_var.data(), out_var.data());
VL_ASSIGN_WSB(60, out_var, o_60_s);
compareWls(60, input_var.data(), out_var.data());
VL_ASSIGN_WSB(62, out_var, o_62_s);
compareWls(62, input_var.data(), out_var.data());
VL_ASSIGN_WSB(64, out_var, o_64_s);
compareWls(64, input_var.data(), out_var.data());
VL_ASSIGN_WSB(119, out_var, o_119_s);
compareWls(119, input_var.data(), out_var.data());
VL_ASSIGN_WSB(120, out_var, o_120_s);
compareWls(120, input_var.data(), out_var.data());
VL_ASSIGN_WSB(121, out_var, o_121_s);
compareWls(121, input_var.data(), out_var.data());
VL_ASSIGN_WSB(127, out_var, o_127_s);
compareWls(127, input_var.data(), out_var.data());
VL_ASSIGN_WSB(128, out_var, o_128_s);
compareWls(128, input_var.data(), out_var.data());
VL_ASSIGN_WSB(255, out_var, o_255_s);
compareWls(255, input_var.data(), out_var.data());
VL_ASSIGN_WSB(256, out_var, o_256_s);
compareWls(256, input_var.data(), out_var.data());
tb->final();
VL_DO_DANGLING(delete tb, tb);
if (pass) {
VL_PRINTF("*-* All Finished *-*\n");
} else {
vl_fatal(__FILE__, __LINE__, "top", "Unexpected results from test\n");
}
return 0;
}

24
test_regress/t/t_var_sc_bv.pl Executable file
View File

@ -0,0 +1,24 @@
#!/usr/bin/env perl
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# Copyright 2003-2009 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.
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
scenarios(vlt_all => 1);
compile(
make_top_shell => 0,
make_main => 0,
verilator_flags2 => ["--exe $Self->{t_dir}/t_var_sc_bv.cpp --sc -fno-inline"],
);
execute(
check_finished => 1,
);
ok(1);
1;

View File

@ -0,0 +1,246 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed into the Public Domain, for any use,
// without warranty, 2008 by Lane Brooks.
// SPDX-License-Identifier: CC0-1.0
module t (/*AUTOARG*/
// Outputs
o_29,o_29_old,
o_30,o_30_old,
o_31,o_31_old,
o_32,o_32_old,
o_59,o_59_old,
o_60,o_60_old,
o_62,o_62_old,
o_64,o_64_old,
o_119,o_119_old,
o_120,o_120_old,
o_121,o_121_old,
o_127,o_127_old,
o_128,o_128_old,
o_255,o_255_old,
o_256,o_256_old,
// Inputs
i_29,i_29_old,
i_30,i_30_old,
i_31,i_31_old,
i_32,i_32_old,
i_59,i_59_old,
i_60,i_60_old,
i_62,i_62_old,
i_64,i_64_old,
i_119,i_119_old,
i_120,i_120_old,
i_121,i_121_old,
i_127,i_127_old,
i_128,i_128_old,
i_255,i_255_old,
i_256,i_256_old
);
input [255:0] i_29;
output wire [255:0] o_29;
input [255:0] i_29_old;
output wire [255:0] o_29_old;
input [255:0] i_30;
output wire [255:0] o_30;
input [255:0] i_30_old;
output wire [255:0] o_30_old;
input [255:0] i_31;
output wire [255:0] o_31;
input [255:0] i_31_old;
output wire [255:0] o_31_old;
input [255:0] i_32;
output wire [255:0] o_32;
input [255:0] i_32_old;
output wire [255:0] o_32_old;
input [255:0] i_59;
output wire [255:0] o_59;
input [255:0] i_59_old;
output wire [255:0] o_59_old;
input [255:0] i_60;
output wire [255:0] o_60;
input [255:0] i_60_old;
output wire [255:0] o_60_old;
input [255:0] i_62;
output wire [255:0] o_62;
input [255:0] i_62_old;
output wire [255:0] o_62_old;
input [255:0] i_64;
output wire [255:0] o_64;
input [255:0] i_64_old;
output wire [255:0] o_64_old;
input [255:0] i_119;
output wire [255:0] o_119;
input [255:0] i_119_old;
output wire [255:0] o_119_old;
input [255:0] i_120;
output wire [255:0] o_120;
input [255:0] i_120_old;
output wire [255:0] o_120_old;
input [255:0] i_121;
output wire [255:0] o_121;
input [255:0] i_121_old;
output wire [255:0] o_121_old;
input [255:0] i_127;
output wire [255:0] o_127;
input [255:0] i_127_old;
output wire [255:0] o_127_old;
input [255:0] i_128;
output wire [255:0] o_128;
input [255:0] i_128_old;
output wire [255:0] o_128_old;
input [255:0] i_255;
output wire [255:0] o_255;
input [255:0] i_255_old;
output wire [255:0] o_255_old;
input [255:0] i_256;
output wire [255:0] o_256;
input [255:0] i_256_old;
output wire [255:0] o_256_old;
sub sub (.*);
endmodule
module sub (/*AUTOARG*/
// Outputs
o_29,o_29_old,
o_30,o_30_old,
o_31,o_31_old,
o_32,o_32_old,
o_59,o_59_old,
o_60,o_60_old,
o_62,o_62_old,
o_64,o_64_old,
o_119,o_119_old,
o_120,o_120_old,
o_121,o_121_old,
o_127,o_127_old,
o_128,o_128_old,
o_255,o_255_old,
o_256,o_256_old,
// Inputs
i_29,i_29_old,
i_30,i_30_old,
i_31,i_31_old,
i_32,i_32_old,
i_59,i_59_old,
i_60,i_60_old,
i_62,i_62_old,
i_64,i_64_old,
i_119,i_119_old,
i_120,i_120_old,
i_121,i_121_old,
i_127,i_127_old,
i_128,i_128_old,
i_255,i_255_old,
i_256,i_256_old
);
input [255:0] i_29;
output wire [255:0] o_29;
input [255:0] i_29_old;
output wire [255:0] o_29_old;
input [255:0] i_30;
output wire [255:0] o_30;
input [255:0] i_30_old;
output wire [255:0] o_30_old;
input [255:0] i_31;
output wire [255:0] o_31;
input [255:0] i_31_old;
output wire [255:0] o_31_old;
input [255:0] i_32;
output wire [255:0] o_32;
input [255:0] i_32_old;
output wire [255:0] o_32_old;
input [255:0] i_59;
output wire [255:0] o_59;
input [255:0] i_59_old;
output wire [255:0] o_59_old;
input [255:0] i_60;
output wire [255:0] o_60;
input [255:0] i_60_old;
output wire [255:0] o_60_old;
input [255:0] i_62;
output wire [255:0] o_62;
input [255:0] i_62_old;
output wire [255:0] o_62_old;
input [255:0] i_64;
output wire [255:0] o_64;
input [255:0] i_64_old;
output wire [255:0] o_64_old;
input [255:0] i_119;
output wire [255:0] o_119;
input [255:0] i_119_old;
output wire [255:0] o_119_old;
input [255:0] i_120;
output wire [255:0] o_120;
input [255:0] i_120_old;
output wire [255:0] o_120_old;
input [255:0] i_121;
output wire [255:0] o_121;
input [255:0] i_121_old;
output wire [255:0] o_121_old;
input [255:0] i_127;
output wire [255:0] o_127;
input [255:0] i_127_old;
output wire [255:0] o_127_old;
input [255:0] i_128;
output wire [255:0] o_128;
input [255:0] i_128_old;
output wire [255:0] o_128_old;
input [255:0] i_255;
output wire [255:0] o_255;
input [255:0] i_255_old;
output wire [255:0] o_255_old;
input [255:0] i_256;
output wire [255:0] o_256;
input [255:0] i_256_old;
output wire [255:0] o_256_old;
assign o_29 = i_29;
assign o_29_old = i_29_old;
assign o_30 = i_30;
assign o_30_old = i_30_old;
assign o_31 = i_31;
assign o_31_old = i_31_old;
assign o_32 = i_32;
assign o_32_old = i_32_old;
assign o_59 = i_59;
assign o_59_old = i_59_old;
assign o_60 = i_60;
assign o_60_old = i_60_old;
assign o_62 = i_62;
assign o_62_old = i_62_old;
assign o_64 = i_64;
assign o_64_old = i_64_old;
assign o_119 = i_119;
assign o_119_old = i_119_old;
assign o_120 = i_120;
assign o_120_old = i_120_old;
assign o_121 = i_121;
assign o_121_old = i_121_old;
assign o_127 = i_127;
assign o_127_old = i_127_old;
assign o_128 = i_128;
assign o_128_old = i_128_old;
assign o_255 = i_255;
assign o_255_old = i_255_old;
assign o_256 = i_256;
assign o_256_old = i_256_old;
endmodule

View File

@ -71,7 +71,7 @@
}
#define CHECK_RESULT_CSTR(got, exp) \
if (strcmp((got), (exp))) { \
if (std::strcmp((got), (exp))) { \
printf("%%Error: %s:%d: GOT = '%s' EXP = '%s'\n", FILENM, __LINE__, \
(got) ? (got) : "<null>", (exp) ? (exp) : "<null>"); \
return __LINE__; \

View File

@ -61,7 +61,7 @@
}
#define CHECK_RESULT_CSTR(got, exp) \
if (strcmp((got), (exp))) { \
if (std::strcmp((got), (exp))) { \
printf("%%Error: %s:%d: GOT = '%s' EXP = '%s'\n", FILENM, __LINE__, \
(got) ? (got) : "<null>", (exp) ? (exp) : "<null>"); \
return __LINE__; \
@ -100,7 +100,7 @@ int mon_check() {
CHECK_RESULT_NZ(t_name);
// Icarus reports the top most module as "top"
if (strcmp(t_name, "top") == 0) {
if (std::strcmp(t_name, "top") == 0) {
it = vpi_iterate(vpiModule, topmod);
CHECK_RESULT_NZ(it);
CHECK_RESULT(vpi_get(vpiType, it), vpiModule);
@ -129,7 +129,7 @@ int mon_check() {
CHECK_RESULT_NZ(mod3);
const char* mod_c_name = vpi_get_str(vpiName, mod3);
if (strcmp(mod_c_name, "mod_b") == 0) {
if (std::strcmp(mod_c_name, "mod_b") == 0) {
// Full visibility in other simulators, skip mod_b
TestVpiHandle mod4 = vpi_scan(it3);
CHECK_RESULT_NZ(mod4);

View File

@ -71,7 +71,7 @@
}
#define CHECK_RESULT_CSTR(got, exp) \
if (strcmp((got), (exp))) { \
if (std::strcmp((got), (exp))) { \
printf("%%Error: %s:%d: GOT = '%s' EXP = '%s'\n", FILENM, __LINE__, \
(got) ? (got) : "<null>", (exp) ? (exp) : "<null>"); \
return __LINE__; \

View File

@ -66,7 +66,7 @@ unsigned int callback_count = 0;
}
#define CHECK_RESULT_CSTR(got, exp) \
if (strcmp((got), (exp))) { \
if (std::strcmp((got), (exp))) { \
printf("%%Error: %s:%d: GOT = '%s' EXP = '%s'\n", FILENM, __LINE__, \
(got) ? (got) : "<null>", (exp) ? (exp) : "<null>"); \
return __LINE__; \

Some files were not shown because too many files have changed in this diff Show More