Merge branch 'master' into develop-v5
This commit is contained in:
commit
27031ed688
|
|
@ -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
18
Changes
|
|
@ -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]
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
33
README.rst
33
README.rst
|
|
@ -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
|
||||
============================
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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']
|
||||
|
|
|
|||
|
|
@ -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']:
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -82,6 +82,7 @@ Michael Killough
|
|||
Michaël Lefebvre
|
||||
Mike Popoloski
|
||||
Miodrag Milanović
|
||||
Mladen Slijepcevic
|
||||
Morten Borup Petersen
|
||||
Mostafa Gamal
|
||||
Nandu Raj
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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); \
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
35
src/V3Ast.h
35
src/V3Ast.h
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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() << "]";
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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(); }
|
||||
};
|
||||
|
||||
//######################################################################
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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] << "->"
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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());
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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; }
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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'
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
//
|
||||
//*************************************************************************
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
362
src/astgen
362
src/astgen
|
|
@ -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")
|
||||
|
||||
|
|
|
|||
|
|
@ -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; }
|
||||
|
|
|
|||
108
src/verilog.y
108
src/verilog.y
|
|
@ -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"); }
|
||||
;
|
||||
|
||||
//************************************************
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 { \
|
||||
|
|
|
|||
|
|
@ -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__,
|
||||
|
|
|
|||
|
|
@ -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*/
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
@ -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
|
||||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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());
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
@ -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
|
||||
|
|
@ -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;
|
||||
| ^~~
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@
|
|||
// endclass
|
||||
|
||||
module t(/*AUTOARG*/);
|
||||
mailbox m;
|
||||
mailbox #(int) m;
|
||||
int msg;
|
||||
int out;
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
| ^~~
|
||||
|
|
@ -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;
|
||||
|
|
@ -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
|
||||
|
|
@ -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*/);
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
| ^~~~~~~
|
||||
|
|
@ -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;
|
||||
|
|
@ -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
|
||||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -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;
|
||||
|
|
@ -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
|
||||
|
|
@ -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;
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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;
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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;
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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;
|
||||
|
|
@ -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
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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;
|
||||
|
|
@ -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
|
||||
|
|
@ -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__; \
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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__; \
|
||||
|
|
|
|||
|
|
@ -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
Loading…
Reference in New Issue