mirror of
https://github.com/verilator/verilator.git
synced 2026-10-06 01:54:01 +02:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
bcadb0b3b3 | ||
|
|
0df561f873 | ||
|
|
238fc24684 | ||
|
|
936855c81c | ||
|
|
61ad9d4651 | ||
|
|
f07f6a26a8 | ||
|
|
4a5a56f8ef | ||
|
|
7d44bba95c | ||
|
|
6e6f1045b8 | ||
|
|
5dd3221759 | ||
|
|
09edb467f6 | ||
|
|
ffb187ae15 | ||
|
|
b4a8be07f3 | ||
|
|
4968a2abc5 | ||
|
|
91159da30d | ||
|
|
c9ad61b4fb | ||
|
|
3f0dcd8c0e | ||
|
|
e1eb41fe77 | ||
|
|
498ab23355 | ||
|
|
5d6a053f98 | ||
|
|
929aeebf12 | ||
|
|
00bd947385 | ||
|
|
d4ef86afc0 | ||
|
|
1856cad816 | ||
|
|
91e2d1d2a0 | ||
|
|
f29f30dce0 | ||
|
|
e7ba6ef492 | ||
|
|
de4016dcff | ||
|
|
bbeb382cbb | ||
|
|
385c166830 | ||
|
|
410e6ff203 | ||
|
|
8b47c4e307 | ||
|
|
6d1b42bedb | ||
|
|
f0a4bd28b6 | ||
|
|
2879684f21 | ||
|
|
0437d0abea | ||
|
|
0286f588bf | ||
|
|
042fb76837 | ||
|
|
795e66eac9 | ||
|
|
aae0615ffd | ||
|
|
8127a79cb1 | ||
|
|
057ca497dd | ||
|
|
66b1611649 | ||
|
|
7f5220a6ca | ||
|
|
e41e26717b | ||
|
|
7a8184d206 | ||
|
|
13bf2f19ac | ||
|
|
1d5ebfd0b1 | ||
|
|
dfc11da2ce | ||
|
|
191af2e87b | ||
|
|
0985b82760 | ||
|
|
26f4b5a69a | ||
|
|
5c7a6e278f | ||
|
|
ae1ab8aaaa | ||
|
|
18c25d1b6f | ||
|
|
5888a2c399 | ||
|
|
c00603704e | ||
|
|
786bc4b04f |
@@ -3,6 +3,40 @@ Revision history for Verilator
|
|||||||
The contributors that suggested a given feature are shown in []. [by ...]
|
The contributors that suggested a given feature are shown in []. [by ...]
|
||||||
indicates the contributor was also the author of the fix; Thanks!
|
indicates the contributor was also the author of the fix; Thanks!
|
||||||
|
|
||||||
|
* Verilator 3.845 2013/02/04
|
||||||
|
|
||||||
|
*** Fix nested packed arrays and struct, bug600. [Jeremy Bennett]
|
||||||
|
Packed arrays are now represented as a single linear vector in
|
||||||
|
Verilated models. This may affect packed arrays that are public or
|
||||||
|
accessed via the VPI.
|
||||||
|
|
||||||
|
*** Support wires with data types, bug608. [Ed Lander]
|
||||||
|
|
||||||
|
*** Support bind, to module names only, bug602. [Ed Lander]
|
||||||
|
|
||||||
|
*** Support VPI product info, warning calls, etc, bug588. [Rick Porter]
|
||||||
|
|
||||||
|
*** Support $left, $right and related functions, bug448. [Iztok Jeras]
|
||||||
|
|
||||||
|
*** Support inside expressions.
|
||||||
|
|
||||||
|
*** Define SYSTEMVERILOG, SV_COV_START and other IEEE mandated predefines.
|
||||||
|
|
||||||
|
**** Fix pin width mismatch error, bug595. [Alex Solomatnikov]
|
||||||
|
|
||||||
|
**** Fix implicit one bit parameter selection, bug603. [Jeremy Bennett]
|
||||||
|
|
||||||
|
**** Fix signed/unsigned parameter misconversion, bug606. [Jeremy Bennett]
|
||||||
|
|
||||||
|
**** Fix segfault on multidimensional dotted arrays, bug607. [Jie Xu]
|
||||||
|
|
||||||
|
**** Fix per-bit array output connection error, bug414. [Jan Egil Ruud]
|
||||||
|
|
||||||
|
**** Fix package logic var compile error.
|
||||||
|
|
||||||
|
**** Fix enums with X values.
|
||||||
|
|
||||||
|
|
||||||
* Verilator 3.844 2013/01/09
|
* Verilator 3.844 2013/01/09
|
||||||
|
|
||||||
*** Support "unsigned int" DPI import functions, msg966. [Alex Lee]
|
*** Support "unsigned int" DPI import functions, msg966. [Alex Lee]
|
||||||
@@ -13,7 +47,7 @@ indicates the contributor was also the author of the fix; Thanks!
|
|||||||
|
|
||||||
**** Fix task inlining under $display and case, bug589, bug598. [Holger Waechtler]
|
**** Fix task inlining under $display and case, bug589, bug598. [Holger Waechtler]
|
||||||
|
|
||||||
**** Fix package import of non-localparam parameter, bug591. [Jeremy Bennett]
|
**** Fix package import of non-localparam parameter, bug474, bug591. [Jeremy Bennett]
|
||||||
|
|
||||||
**** Fix package import of package imports, partial bug592. [Jeremy Bennett]
|
**** Fix package import of package imports, partial bug592. [Jeremy Bennett]
|
||||||
|
|
||||||
|
|||||||
+6
-3
@@ -398,14 +398,17 @@ endif
|
|||||||
# VERILATOR_AUTHOR_SITE
|
# VERILATOR_AUTHOR_SITE
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
# Use --xml flag to see the cppcheck code to use for suppression
|
||||||
CPPCHECK = cppcheck
|
CPPCHECK = cppcheck
|
||||||
CPPCHECK_FLAGS = --enable=all --inline-suppr --suppress=unusedScopedObject
|
CPPCHECK_FLAGS = --enable=all --inline-suppr --suppress=unusedScopedObject --suppress=cstyleCast
|
||||||
|
CPPCHECK_FLAGS += --xml
|
||||||
CPPCHECK_CPP = $(wildcard $(srcdir)/include/*.cpp $(srcdir)/src/*.cpp)
|
CPPCHECK_CPP = $(wildcard $(srcdir)/include/*.cpp $(srcdir)/src/*.cpp)
|
||||||
CPPCHECK_DEP = $(subst .cpp,.cppcheck,$(CPPCHECK_CPP))
|
CPPCHECK_DEP = $(subst .cpp,.cppcheck,$(CPPCHECK_CPP))
|
||||||
|
CPPCHECK_INC = -I$(srcdir)/include -I$(srcdir)/src/obj_dbg -I$(srcdir)/src
|
||||||
|
|
||||||
cppcheck: $(CPPCHECK_DEP)
|
cppcheck: $(CPPCHECK_DEP)
|
||||||
%.cppcheck: %.cpp
|
%.cppcheck: %.cpp
|
||||||
$(CPPCHECK) $(CPPCHECK_FLAGS) -DVL_DEBUG=1 -I$(srcdir)/include -I$(srcdir)/src $<
|
$(CPPCHECK) $(CPPCHECK_FLAGS) -DVL_DEBUG=1 $(CPPCHECK_INC) $<
|
||||||
|
|
||||||
ftp: info
|
ftp: info
|
||||||
|
|
||||||
@@ -455,7 +458,7 @@ clean mostlyclean distclean maintainer-clean::
|
|||||||
|
|
||||||
distclean maintainer-clean::
|
distclean maintainer-clean::
|
||||||
rm -f Makefile config.status config.cache config.log verilator_bin* TAGS
|
rm -f Makefile config.status config.cache config.log verilator_bin* TAGS
|
||||||
rm -f include/verilated.mk
|
rm -f include/verilated.mk include/verilated_config.h
|
||||||
|
|
||||||
TAGFILES=${srcdir}/*/*.cpp ${srcdir}/*/*.h ${srcdir}/*/*.in \
|
TAGFILES=${srcdir}/*/*.cpp ${srcdir}/*/*.h ${srcdir}/*/*.in \
|
||||||
${srcdir}/*.in ${srcdir}/*.pod
|
${srcdir}/*.in ${srcdir}/*.pod
|
||||||
|
|||||||
+27
-4
@@ -202,9 +202,8 @@ Verilator - Convert Verilog code to C++/SystemC
|
|||||||
|
|
||||||
verilator --help
|
verilator --help
|
||||||
verilator --version
|
verilator --version
|
||||||
verilator --cc [options] [top_level.v] [opt_c_files.cpp/c/cc/a/o/so]
|
verilator --cc [options] [top_level.v]... [opt_c_files.cpp/c/cc/a/o/so]
|
||||||
verilator --sc [options] [top_level.v] [opt_c_files.cpp/c/cc/a/o/so]
|
verilator --sc [options] [top_level.v]... [opt_c_files.cpp/c/cc/a/o/so]
|
||||||
verilator --sp [options] [top_level.v] [opt_c_files.cpp/c/cc/a/o/so]
|
|
||||||
verilator --lint-only [top_level.v]...
|
verilator --lint-only [top_level.v]...
|
||||||
|
|
||||||
=head1 DESCRIPTION
|
=head1 DESCRIPTION
|
||||||
@@ -1321,7 +1320,8 @@ OPT_FAST and OPT_SLOW affect. For best results, use OPT="-O2", and link
|
|||||||
with "-static". Nearly the same results can be had with much better
|
with "-static". Nearly the same results can be had with much better
|
||||||
compile times with OPT_FAST="-O1 -fstrict-aliasing". Higher optimization
|
compile times with OPT_FAST="-O1 -fstrict-aliasing". Higher optimization
|
||||||
such as "-O3" may help, but gcc compile times may be excessive under O3 on
|
such as "-O3" may help, but gcc compile times may be excessive under O3 on
|
||||||
even medium sized designs.
|
even medium sized designs. Alternatively, some larger designs report
|
||||||
|
better performance using "-Os".
|
||||||
|
|
||||||
Unfortunately, using the optimizer with SystemC files can result in
|
Unfortunately, using the optimizer with SystemC files can result in
|
||||||
compiles taking several minutes. (The SystemC libraries have many little
|
compiles taking several minutes. (The SystemC libraries have many little
|
||||||
@@ -2070,6 +2070,11 @@ functions, the Verilog signals must be declared with /*verilator public*/.
|
|||||||
See also the public task feature; writing an accessor may result in cleaner
|
See also the public task feature; writing an accessor may result in cleaner
|
||||||
code.
|
code.
|
||||||
|
|
||||||
|
=item `SYSTEMVERILOG
|
||||||
|
|
||||||
|
The SYSTEMVERILOG, SV_COV_START and related standard defines are set by
|
||||||
|
default when --language is 1800-*.
|
||||||
|
|
||||||
=item `VERILATOR
|
=item `VERILATOR
|
||||||
|
|
||||||
=item `verilator
|
=item `verilator
|
||||||
@@ -2327,6 +2332,11 @@ always @* to reduce missing activity items. Avoid putting $displays in
|
|||||||
combo blocks, as they may print multiple times when not desired, even on
|
combo blocks, as they may print multiple times when not desired, even on
|
||||||
compliant simulators as event ordering is not specified.
|
compliant simulators as event ordering is not specified.
|
||||||
|
|
||||||
|
=head2 Bind
|
||||||
|
|
||||||
|
Verilator only supports "bind" to a target module name, not an instance
|
||||||
|
path.
|
||||||
|
|
||||||
=head2 Dotted cross-hierarchy references
|
=head2 Dotted cross-hierarchy references
|
||||||
|
|
||||||
Verilator supports dotted references to variables, functions and tasks in
|
Verilator supports dotted references to variables, functions and tasks in
|
||||||
@@ -2548,6 +2558,11 @@ the disable statement itself is inside. This was commonly used to provide
|
|||||||
loop break and continue functionality before SystemVerilog added the break
|
loop break and continue functionality before SystemVerilog added the break
|
||||||
and continue keywords.
|
and continue keywords.
|
||||||
|
|
||||||
|
=item inside
|
||||||
|
|
||||||
|
Inside expressions may not include unpacked array traversal or $ as an
|
||||||
|
upper bound. Case inside and case matches are also unsupported.
|
||||||
|
|
||||||
=item priority if, unique if
|
=item priority if, unique if
|
||||||
|
|
||||||
Priority and unique if's are treated as normal ifs and not asserted to be
|
Priority and unique if's are treated as normal ifs and not asserted to be
|
||||||
@@ -2822,6 +2837,14 @@ designs should now be using the #(...) format to specify parameters.
|
|||||||
Disabled by default as this is a code style warning; it will simulate
|
Disabled by default as this is a code style warning; it will simulate
|
||||||
correctly.
|
correctly.
|
||||||
|
|
||||||
|
=item DETECTARRAY
|
||||||
|
|
||||||
|
Error when Verilator tries to deal with a combinatorial loop that could not be
|
||||||
|
flattened, and which involves a structure. This typically ocurrs when
|
||||||
|
-Wno-UNOPTFLAT has been used to override an UNOPTFLAT warning (see below).
|
||||||
|
|
||||||
|
The solution is to break the loop, as described for UNOPTFLAT.
|
||||||
|
|
||||||
=item ENDLABEL
|
=item ENDLABEL
|
||||||
|
|
||||||
Warns that a label attached to a "end"-something statement does not match
|
Warns that a label attached to a "end"-something statement does not match
|
||||||
|
|||||||
+2
-2
@@ -6,9 +6,9 @@
|
|||||||
|
|
||||||
#AC_INIT([Verilator],[#.### YYYY-MM-DD])
|
#AC_INIT([Verilator],[#.### YYYY-MM-DD])
|
||||||
#AC_INIT([Verilator],[#.### devel])
|
#AC_INIT([Verilator],[#.### devel])
|
||||||
AC_INIT([Verilator],[3.844 2013-01-09])
|
AC_INIT([Verilator],[3.845 2013-02-04])
|
||||||
AC_CONFIG_HEADER(src/config_build.h)
|
AC_CONFIG_HEADER(src/config_build.h)
|
||||||
AC_CONFIG_FILES(Makefile src/Makefile src/Makefile_obj include/verilated.mk)
|
AC_CONFIG_FILES(Makefile src/Makefile src/Makefile_obj include/verilated.mk include/verilated_config.h)
|
||||||
|
|
||||||
AC_MSG_RESULT([configuring for $PACKAGE_STRING])
|
AC_MSG_RESULT([configuring for $PACKAGE_STRING])
|
||||||
|
|
||||||
|
|||||||
@@ -1 +1,2 @@
|
|||||||
verilated.mk
|
verilated.mk
|
||||||
|
verilated_config.h
|
||||||
|
|||||||
@@ -40,6 +40,7 @@ Verilated::Serialized Verilated::s_s;
|
|||||||
VL_THREAD const VerilatedScope* Verilated::t_dpiScopep = NULL;
|
VL_THREAD const VerilatedScope* Verilated::t_dpiScopep = NULL;
|
||||||
VL_THREAD const char* Verilated::t_dpiFilename = "";
|
VL_THREAD const char* Verilated::t_dpiFilename = "";
|
||||||
VL_THREAD int Verilated::t_dpiLineno = 0;
|
VL_THREAD int Verilated::t_dpiLineno = 0;
|
||||||
|
struct Verilated::CommandArgValues Verilated::s_args = {0, NULL};
|
||||||
|
|
||||||
VerilatedImp VerilatedImp::s_s;
|
VerilatedImp VerilatedImp::s_s;
|
||||||
|
|
||||||
@@ -86,6 +87,7 @@ Verilated::Serialized::Serialized() {
|
|||||||
s_calcUnusedSigs = false;
|
s_calcUnusedSigs = false;
|
||||||
s_gotFinish = false;
|
s_gotFinish = false;
|
||||||
s_assertOn = true;
|
s_assertOn = true;
|
||||||
|
s_fatalOnVpiError = true; // retains old default behaviour
|
||||||
}
|
}
|
||||||
|
|
||||||
//===========================================================================
|
//===========================================================================
|
||||||
@@ -601,7 +603,7 @@ IData _vl_vsscanf(FILE* fp, // If a fscanf
|
|||||||
_vl_vsss_read(fp,floc,fromp, tmp, "0123456789+-xXzZ?_");
|
_vl_vsss_read(fp,floc,fromp, tmp, "0123456789+-xXzZ?_");
|
||||||
if (!tmp[0]) goto done;
|
if (!tmp[0]) goto done;
|
||||||
vlsint64_t ld;
|
vlsint64_t ld;
|
||||||
sscanf(tmp,"%" VL_PRI64 "d",&ld);
|
sscanf(tmp,"%30" VL_PRI64 "d",&ld);
|
||||||
VL_SET_WQ(owp,ld);
|
VL_SET_WQ(owp,ld);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -622,7 +624,7 @@ IData _vl_vsscanf(FILE* fp, // If a fscanf
|
|||||||
_vl_vsss_read(fp,floc,fromp, tmp, "0123456789+-xXzZ?_");
|
_vl_vsss_read(fp,floc,fromp, tmp, "0123456789+-xXzZ?_");
|
||||||
if (!tmp[0]) goto done;
|
if (!tmp[0]) goto done;
|
||||||
QData ld;
|
QData ld;
|
||||||
sscanf(tmp,"%" VL_PRI64 "u",&ld);
|
sscanf(tmp,"%30" VL_PRI64 "u",&ld);
|
||||||
VL_SET_WQ(owp,ld);
|
VL_SET_WQ(owp,ld);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -975,7 +977,7 @@ IData VL_VALUEPLUSARGS_IW(int rbits, const char* prefixp, char fmt, WDataOutP rw
|
|||||||
break;
|
break;
|
||||||
case 'd':
|
case 'd':
|
||||||
vlsint64_t ld;
|
vlsint64_t ld;
|
||||||
sscanf(dp,"%" VL_PRI64 "d",&ld);
|
sscanf(dp,"%30" VL_PRI64 "d",&ld);
|
||||||
VL_SET_WQ(rwp,ld);
|
VL_SET_WQ(rwp,ld);
|
||||||
break;
|
break;
|
||||||
case 'b':
|
case 'b':
|
||||||
@@ -1064,6 +1066,8 @@ void Verilated::flushCb(VerilatedVoidCb cb) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Verilated::commandArgs(int argc, const char** argv) {
|
void Verilated::commandArgs(int argc, const char** argv) {
|
||||||
|
s_args.argc = argc;
|
||||||
|
s_args.argv = argv;
|
||||||
VerilatedImp::commandArgs(argc,argv);
|
VerilatedImp::commandArgs(argc,argv);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1097,6 +1101,7 @@ VerilatedModule::~VerilatedModule() {
|
|||||||
//======================================================================
|
//======================================================================
|
||||||
// VerilatedVar:: Methods
|
// VerilatedVar:: Methods
|
||||||
|
|
||||||
|
// cppcheck-suppress unusedFunction // Used by applications
|
||||||
vluint32_t VerilatedVar::entSize() const {
|
vluint32_t VerilatedVar::entSize() const {
|
||||||
vluint32_t size = 1;
|
vluint32_t size = 1;
|
||||||
switch (vltype()) {
|
switch (vltype()) {
|
||||||
@@ -1193,6 +1198,7 @@ void VerilatedScope::varInsert(int finalize, const char* namep, void* datap,
|
|||||||
m_varsp->insert(make_pair(namep,var));
|
m_varsp->insert(make_pair(namep,var));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// cppcheck-suppress unusedFunction // Used by applications
|
||||||
VerilatedVar* VerilatedScope::varFind(const char* namep) const {
|
VerilatedVar* VerilatedScope::varFind(const char* namep) const {
|
||||||
if (VL_LIKELY(m_varsp)) {
|
if (VL_LIKELY(m_varsp)) {
|
||||||
VerilatedVarNameMap::iterator it = m_varsp->find(namep);
|
VerilatedVarNameMap::iterator it = m_varsp->find(namep);
|
||||||
|
|||||||
@@ -28,6 +28,7 @@
|
|||||||
#ifndef _VERILATED_H_
|
#ifndef _VERILATED_H_
|
||||||
#define _VERILATED_H_ 1 ///< Header Guard
|
#define _VERILATED_H_ 1 ///< Header Guard
|
||||||
|
|
||||||
|
#include "verilated_config.h"
|
||||||
#include "verilatedos.h"
|
#include "verilatedos.h"
|
||||||
|
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
@@ -229,6 +230,7 @@ private:
|
|||||||
bool s_calcUnusedSigs; ///< Waves file on, need all signals calculated
|
bool s_calcUnusedSigs; ///< Waves file on, need all signals calculated
|
||||||
bool s_gotFinish; ///< A $finish statement executed
|
bool s_gotFinish; ///< A $finish statement executed
|
||||||
bool s_assertOn; ///< Assertions are enabled
|
bool s_assertOn; ///< Assertions are enabled
|
||||||
|
bool s_fatalOnVpiError; ///< Stop on vpi error/unsupported
|
||||||
Serialized();
|
Serialized();
|
||||||
} s_s;
|
} s_s;
|
||||||
|
|
||||||
@@ -236,6 +238,13 @@ private:
|
|||||||
static VL_THREAD const char* t_dpiFilename; ///< DPI context filename
|
static VL_THREAD const char* t_dpiFilename; ///< DPI context filename
|
||||||
static VL_THREAD int t_dpiLineno; ///< DPI context line number
|
static VL_THREAD int t_dpiLineno; ///< DPI context line number
|
||||||
|
|
||||||
|
// no need to be save-restored (serialized) the
|
||||||
|
// assumption is that the restore is allowed to pass different arguments
|
||||||
|
static struct CommandArgValues {
|
||||||
|
int argc;
|
||||||
|
const char** argv;
|
||||||
|
} s_args;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
// METHODS - User called
|
// METHODS - User called
|
||||||
@@ -268,6 +277,9 @@ public:
|
|||||||
/// Enable/disable assertions
|
/// Enable/disable assertions
|
||||||
static void assertOn(bool flag) { s_s.s_assertOn=flag; }
|
static void assertOn(bool flag) { s_s.s_assertOn=flag; }
|
||||||
static bool assertOn() { return s_s.s_assertOn; }
|
static bool assertOn() { return s_s.s_assertOn; }
|
||||||
|
/// Enable/disable vpi fatal
|
||||||
|
static void fatalOnVpiError(bool flag) { s_s.s_fatalOnVpiError=flag; }
|
||||||
|
static bool fatalOnVpiError() { return s_s.s_fatalOnVpiError; }
|
||||||
/// Flush callback for VCD waves
|
/// Flush callback for VCD waves
|
||||||
static void flushCb(VerilatedVoidCb cb);
|
static void flushCb(VerilatedVoidCb cb);
|
||||||
static void flushCall() { if (s_flushCb) (*s_flushCb)(); }
|
static void flushCall() { if (s_flushCb) (*s_flushCb)(); }
|
||||||
@@ -275,8 +287,13 @@ public:
|
|||||||
/// Record command line arguments, for retrieval by $test$plusargs/$value$plusargs
|
/// Record command line arguments, for retrieval by $test$plusargs/$value$plusargs
|
||||||
static void commandArgs(int argc, const char** argv);
|
static void commandArgs(int argc, const char** argv);
|
||||||
static void commandArgs(int argc, char** argv) { commandArgs(argc,(const char**)argv); }
|
static void commandArgs(int argc, char** argv) { commandArgs(argc,(const char**)argv); }
|
||||||
|
static CommandArgValues* getCommandArgs() {return &s_args;}
|
||||||
static const char* commandArgsPlusMatch(const char* prefixp);
|
static const char* commandArgsPlusMatch(const char* prefixp);
|
||||||
|
|
||||||
|
/// Produce name & version for (at least) VPI
|
||||||
|
static const char* productName() { return VERILATOR_PRODUCT; }
|
||||||
|
static const char* productVersion() { return VERILATOR_VERSION; }
|
||||||
|
|
||||||
/// For debugging, print text list of all scope names with
|
/// For debugging, print text list of all scope names with
|
||||||
/// dpiImport/Export context. This function may change in future
|
/// dpiImport/Export context. This function may change in future
|
||||||
/// releases - contact the authors before production use.
|
/// releases - contact the authors before production use.
|
||||||
|
|||||||
@@ -0,0 +1,28 @@
|
|||||||
|
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
||||||
|
//*************************************************************************
|
||||||
|
//
|
||||||
|
// Copyright 2003-2012 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.
|
||||||
|
//
|
||||||
|
// Verilator is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
//*************************************************************************
|
||||||
|
///
|
||||||
|
/// \file
|
||||||
|
/// \brief Verilator: Auto version information include for all Verilated C files
|
||||||
|
///
|
||||||
|
/// Code available from: http://www.veripool.org/verilator
|
||||||
|
///
|
||||||
|
//*************************************************************************
|
||||||
|
|
||||||
|
|
||||||
|
///**** Product and Version name
|
||||||
|
|
||||||
|
// Autoconf substitutes this with the strings from AC_INIT.
|
||||||
|
#define VERILATOR_PRODUCT "@PACKAGE_NAME@"
|
||||||
|
#define VERILATOR_VERSION "@PACKAGE_VERSION@"
|
||||||
@@ -104,9 +104,6 @@ int svHigh(const svOpenArrayHandle h, int d) {
|
|||||||
int svIncrement(const svOpenArrayHandle h, int d) {
|
int svIncrement(const svOpenArrayHandle h, int d) {
|
||||||
_VL_SVDPI_UNIMP(); return 0;
|
_VL_SVDPI_UNIMP(); return 0;
|
||||||
}
|
}
|
||||||
int svLength(const svOpenArrayHandle h, int d) {
|
|
||||||
_VL_SVDPI_UNIMP(); return 0;
|
|
||||||
}
|
|
||||||
int svDimensions(const svOpenArrayHandle h) {
|
int svDimensions(const svOpenArrayHandle h) {
|
||||||
_VL_SVDPI_UNIMP(); return 0;
|
_VL_SVDPI_UNIMP(); return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -116,6 +116,7 @@ void VerilatedSave::open (const char* filenamep) {
|
|||||||
if (filenamep[0]=='|') {
|
if (filenamep[0]=='|') {
|
||||||
assert(0); // Not supported yet.
|
assert(0); // Not supported yet.
|
||||||
} else {
|
} else {
|
||||||
|
// cppcheck-suppress duplicateExpression
|
||||||
m_fd = ::open (filenamep, O_CREAT|O_WRONLY|O_TRUNC|O_LARGEFILE|O_NONBLOCK
|
m_fd = ::open (filenamep, O_CREAT|O_WRONLY|O_TRUNC|O_LARGEFILE|O_NONBLOCK
|
||||||
, 0666);
|
, 0666);
|
||||||
if (m_fd<0) {
|
if (m_fd<0) {
|
||||||
@@ -137,6 +138,7 @@ void VerilatedRestore::open (const char* filenamep) {
|
|||||||
if (filenamep[0]=='|') {
|
if (filenamep[0]=='|') {
|
||||||
assert(0); // Not supported yet.
|
assert(0); // Not supported yet.
|
||||||
} else {
|
} else {
|
||||||
|
// cppcheck-suppress duplicateExpression
|
||||||
m_fd = ::open (filenamep, O_CREAT|O_RDONLY|O_LARGEFILE
|
m_fd = ::open (filenamep, O_CREAT|O_RDONLY|O_LARGEFILE
|
||||||
, 0666);
|
, 0666);
|
||||||
if (m_fd<0) {
|
if (m_fd<0) {
|
||||||
|
|||||||
@@ -109,7 +109,7 @@ protected:
|
|||||||
void trailer();
|
void trailer();
|
||||||
public:
|
public:
|
||||||
// CREATORS
|
// CREATORS
|
||||||
VerilatedDeserialize() {}
|
VerilatedDeserialize() { m_endp = NULL; }
|
||||||
virtual ~VerilatedDeserialize() { close(); }
|
virtual ~VerilatedDeserialize() { close(); }
|
||||||
// METHODS
|
// METHODS
|
||||||
inline VerilatedDeserialize& read (void* __restrict datap, size_t size) {
|
inline VerilatedDeserialize& read (void* __restrict datap, size_t size) {
|
||||||
@@ -146,7 +146,7 @@ private:
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
// CREATORS
|
// CREATORS
|
||||||
VerilatedSave() {}
|
VerilatedSave() { m_fd=-1; }
|
||||||
virtual ~VerilatedSave() { close(); }
|
virtual ~VerilatedSave() { close(); }
|
||||||
// METHODS
|
// METHODS
|
||||||
void open(const char* filenamep); ///< Open the file; call isOpen() to see if errors
|
void open(const char* filenamep); ///< Open the file; call isOpen() to see if errors
|
||||||
@@ -164,7 +164,7 @@ private:
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
// CREATORS
|
// CREATORS
|
||||||
VerilatedRestore() {}
|
VerilatedRestore() { m_fd=-1; }
|
||||||
virtual ~VerilatedRestore() { close(); }
|
virtual ~VerilatedRestore() { close(); }
|
||||||
|
|
||||||
// METHODS
|
// METHODS
|
||||||
|
|||||||
@@ -141,6 +141,7 @@ void VerilatedVcd::openNext (bool incFilename) {
|
|||||||
if (m_filename[0]=='|') {
|
if (m_filename[0]=='|') {
|
||||||
assert(0); // Not supported yet.
|
assert(0); // Not supported yet.
|
||||||
} else {
|
} else {
|
||||||
|
// cppcheck-suppress duplicateExpression
|
||||||
m_fd = ::open (m_filename.c_str(), O_CREAT|O_WRONLY|O_TRUNC|O_LARGEFILE|O_NONBLOCK
|
m_fd = ::open (m_filename.c_str(), O_CREAT|O_WRONLY|O_TRUNC|O_LARGEFILE|O_NONBLOCK
|
||||||
, 0666);
|
, 0666);
|
||||||
if (m_fd<0) {
|
if (m_fd<0) {
|
||||||
|
|||||||
@@ -31,3 +31,334 @@ VerilatedVpi VerilatedVpi::s_s; // Singleton
|
|||||||
vluint8_t* VerilatedVpio::s_freeHead = NULL;
|
vluint8_t* VerilatedVpio::s_freeHead = NULL;
|
||||||
|
|
||||||
//======================================================================
|
//======================================================================
|
||||||
|
|
||||||
|
const char* VerilatedVpiError::strFromVpiVal(PLI_INT32 vpiVal) {
|
||||||
|
static const char *names[] = {
|
||||||
|
"*undefined*",
|
||||||
|
"vpiBinStrVal",
|
||||||
|
"vpiOctStrVal",
|
||||||
|
"vpiDecStrVal",
|
||||||
|
"vpiHexStrVal",
|
||||||
|
"vpiScalarVal",
|
||||||
|
"vpiIntVal",
|
||||||
|
"vpiRealVal",
|
||||||
|
"vpiStringVal",
|
||||||
|
"vpiVectorVal",
|
||||||
|
"vpiStrengthVal",
|
||||||
|
"vpiTimeVal",
|
||||||
|
"vpiObjTypeVal",
|
||||||
|
"vpiSuppressVal",
|
||||||
|
"vpiShortIntVal",
|
||||||
|
"vpiLongIntVal",
|
||||||
|
"vpiShortRealVal",
|
||||||
|
"vpiRawTwoStateVal",
|
||||||
|
"vpiRawFourStateVal",
|
||||||
|
};
|
||||||
|
if (vpiVal < 0) return names[0];
|
||||||
|
return names[(vpiVal<=vpiRawFourStateVal)?vpiVal:0];
|
||||||
|
}
|
||||||
|
const char* VerilatedVpiError::strFromVpiObjType(PLI_INT32 vpiVal) {
|
||||||
|
static const char *names[] = {
|
||||||
|
"*undefined*",
|
||||||
|
"vpiAlways",
|
||||||
|
"vpiAssignStmt",
|
||||||
|
"vpiAssignment",
|
||||||
|
"vpiBegin",
|
||||||
|
"vpiCase",
|
||||||
|
"vpiCaseItem",
|
||||||
|
"vpiConstant",
|
||||||
|
"vpiContAssign",
|
||||||
|
"vpiDeassign",
|
||||||
|
"vpiDefParam",
|
||||||
|
"vpiDelayControl",
|
||||||
|
"vpiDisable",
|
||||||
|
"vpiEventControl",
|
||||||
|
"vpiEventStmt",
|
||||||
|
"vpiFor",
|
||||||
|
"vpiForce",
|
||||||
|
"vpiForever",
|
||||||
|
"vpiFork",
|
||||||
|
"vpiFuncCall",
|
||||||
|
"vpiFunction",
|
||||||
|
"vpiGate",
|
||||||
|
"vpiIf",
|
||||||
|
"vpiIfElse",
|
||||||
|
"vpiInitial",
|
||||||
|
"vpiIntegerVar",
|
||||||
|
"vpiInterModPath",
|
||||||
|
"vpiIterator",
|
||||||
|
"vpiIODecl",
|
||||||
|
"vpiMemory",
|
||||||
|
"vpiMemoryWord",
|
||||||
|
"vpiModPath",
|
||||||
|
"vpiModule",
|
||||||
|
"vpiNamedBegin",
|
||||||
|
"vpiNamedEvent",
|
||||||
|
"vpiNamedFork",
|
||||||
|
"vpiNet",
|
||||||
|
"vpiNetBit",
|
||||||
|
"vpiNullStmt",
|
||||||
|
"vpiOperation",
|
||||||
|
"vpiParamAssign",
|
||||||
|
"vpiParameter",
|
||||||
|
"vpiPartSelect",
|
||||||
|
"vpiPathTerm",
|
||||||
|
"vpiPort",
|
||||||
|
"vpiPortBit",
|
||||||
|
"vpiPrimTerm",
|
||||||
|
"vpiRealVar",
|
||||||
|
"vpiReg",
|
||||||
|
"vpiRegBit",
|
||||||
|
"vpiRelease",
|
||||||
|
"vpiRepeat",
|
||||||
|
"vpiRepeatControl",
|
||||||
|
"vpiSchedEvent",
|
||||||
|
"vpiSpecParam",
|
||||||
|
"vpiSwitch",
|
||||||
|
"vpiSysFuncCall",
|
||||||
|
"vpiSysTaskCall",
|
||||||
|
"vpiTableEntry",
|
||||||
|
"vpiTask",
|
||||||
|
"vpiTaskCall",
|
||||||
|
"vpiTchk",
|
||||||
|
"vpiTchkTerm",
|
||||||
|
"vpiTimeVar",
|
||||||
|
"vpiTimeQueue",
|
||||||
|
"vpiUdp",
|
||||||
|
"vpiUdpDefn",
|
||||||
|
"vpiUserSystf",
|
||||||
|
"vpiVarSelect",
|
||||||
|
"vpiWait",
|
||||||
|
"vpiWhile",
|
||||||
|
"*undefined*",
|
||||||
|
"*undefined*",
|
||||||
|
"*undefined*",
|
||||||
|
"*undefined*",
|
||||||
|
"*undefined*",
|
||||||
|
"*undefined*",
|
||||||
|
"*undefined*",
|
||||||
|
"*undefined*",
|
||||||
|
"*undefined*",
|
||||||
|
"*undefined*",
|
||||||
|
"*undefined*",
|
||||||
|
"*undefined*",
|
||||||
|
"*undefined*",
|
||||||
|
"*undefined*",
|
||||||
|
"*undefined*",
|
||||||
|
"*undefined*",
|
||||||
|
"*undefined*",
|
||||||
|
"*undefined*",
|
||||||
|
"*undefined*",
|
||||||
|
"*undefined*",
|
||||||
|
"*undefined*",
|
||||||
|
"*undefined*",
|
||||||
|
"*undefined*",
|
||||||
|
"*undefined*",
|
||||||
|
"*undefined*",
|
||||||
|
"*undefined*",
|
||||||
|
"*undefined*",
|
||||||
|
"*undefined*",
|
||||||
|
"*undefined*",
|
||||||
|
"*undefined*",
|
||||||
|
"*undefined*",
|
||||||
|
"*undefined*",
|
||||||
|
"*undefined*",
|
||||||
|
"*undefined*",
|
||||||
|
"vpiAttribute",
|
||||||
|
"vpiBitSelect",
|
||||||
|
"vpiCallback",
|
||||||
|
"vpiDelayTerm",
|
||||||
|
"vpiDelayDevice",
|
||||||
|
"vpiFrame",
|
||||||
|
"vpiGateArray",
|
||||||
|
"vpiModuleArray",
|
||||||
|
"vpiPrimitiveArray",
|
||||||
|
"vpiNetArray",
|
||||||
|
"vpiRange",
|
||||||
|
"vpiRegArray",
|
||||||
|
"vpiSwitchArray",
|
||||||
|
"vpiUdpArray",
|
||||||
|
"*undefined*",
|
||||||
|
"*undefined*",
|
||||||
|
"*undefined*",
|
||||||
|
"*undefined*",
|
||||||
|
"*undefined*",
|
||||||
|
"*undefined*",
|
||||||
|
"*undefined*",
|
||||||
|
"*undefined*",
|
||||||
|
"*undefined*",
|
||||||
|
"vpiContAssignBit",
|
||||||
|
"vpiNamedEventArray",
|
||||||
|
"vpiIndexedPartSelect",
|
||||||
|
"*undefined*",
|
||||||
|
"*undefined*",
|
||||||
|
"vpiGenScopeArray",
|
||||||
|
"vpiGenScope",
|
||||||
|
"vpiGenVar"
|
||||||
|
};
|
||||||
|
if (vpiVal < 0) return names[0];
|
||||||
|
return names[(vpiVal<=vpiGenVar)?vpiVal:0];
|
||||||
|
}
|
||||||
|
const char* VerilatedVpiError::strFromVpiMethod(PLI_INT32 vpiVal) {
|
||||||
|
static const char *names[] = {
|
||||||
|
"vpiCondition",
|
||||||
|
"vpiDelay",
|
||||||
|
"vpiElseStmt",
|
||||||
|
"vpiForIncStmt",
|
||||||
|
"vpiForInitStmt",
|
||||||
|
"vpiHighConn",
|
||||||
|
"vpiLhs",
|
||||||
|
"vpiIndex",
|
||||||
|
"vpiLeftRange",
|
||||||
|
"vpiLowConn",
|
||||||
|
"vpiParent",
|
||||||
|
"vpiRhs",
|
||||||
|
"vpiRightRange",
|
||||||
|
"vpiScope",
|
||||||
|
"vpiSysTfCall",
|
||||||
|
"vpiTchkDataTerm",
|
||||||
|
"vpiTchkNotifier",
|
||||||
|
"vpiTchkRefTerm",
|
||||||
|
"vpiArgument",
|
||||||
|
"vpiBit",
|
||||||
|
"vpiDriver",
|
||||||
|
"vpiInternalScope",
|
||||||
|
"vpiLoad",
|
||||||
|
"vpiModDataPathIn",
|
||||||
|
"vpiModPathIn",
|
||||||
|
"vpiModPathOut",
|
||||||
|
"vpiOperand",
|
||||||
|
"vpiPortInst",
|
||||||
|
"vpiProcess",
|
||||||
|
"vpiVariables",
|
||||||
|
"vpiUse",
|
||||||
|
"vpiExpr",
|
||||||
|
"vpiPrimitive",
|
||||||
|
"vpiStmt"
|
||||||
|
};
|
||||||
|
if (vpiVal>vpiStmt || vpiVal<vpiCondition) {
|
||||||
|
return "*undefined*";
|
||||||
|
}
|
||||||
|
return names[vpiVal-vpiCondition];
|
||||||
|
}
|
||||||
|
const char* VerilatedVpiError::strFromVpiCallbackReason(PLI_INT32 vpiVal) {
|
||||||
|
static const char *names[] = {
|
||||||
|
"*undefined*",
|
||||||
|
"cbValueChange",
|
||||||
|
"cbStmt",
|
||||||
|
"cbForce",
|
||||||
|
"cbRelease",
|
||||||
|
"cbAtStartOfSimTime",
|
||||||
|
"cbReadWriteSynch",
|
||||||
|
"cbReadOnlySynch",
|
||||||
|
"cbNextSimTime",
|
||||||
|
"cbAfterDelay",
|
||||||
|
"cbEndOfCompile",
|
||||||
|
"cbStartOfSimulation",
|
||||||
|
"cbEndOfSimulation",
|
||||||
|
"cbError",
|
||||||
|
"cbTchkViolation",
|
||||||
|
"cbStartOfSave",
|
||||||
|
"cbEndOfSave",
|
||||||
|
"cbStartOfRestart",
|
||||||
|
"cbEndOfRestart",
|
||||||
|
"cbStartOfReset",
|
||||||
|
"cbEndOfReset",
|
||||||
|
"cbEnterInteractive",
|
||||||
|
"cbExitInteractive",
|
||||||
|
"cbInteractiveScopeChange",
|
||||||
|
"cbUnresolvedSystf",
|
||||||
|
"cbAssign",
|
||||||
|
"cbDeassign",
|
||||||
|
"cbDisable",
|
||||||
|
"cbPLIError",
|
||||||
|
"cbSignal",
|
||||||
|
"cbNBASynch",
|
||||||
|
"cbAtEndOfSimTime"
|
||||||
|
};
|
||||||
|
if (vpiVal < 0) return names[0];
|
||||||
|
return names[(vpiVal<=cbAtEndOfSimTime)?vpiVal:0];
|
||||||
|
}
|
||||||
|
const char* VerilatedVpiError::strFromVpiProp(PLI_INT32 vpiVal) {
|
||||||
|
static const char *names[] = {
|
||||||
|
"*undefined or other*",
|
||||||
|
"vpiType",
|
||||||
|
"vpiName",
|
||||||
|
"vpiFullName",
|
||||||
|
"vpiSize",
|
||||||
|
"vpiFile",
|
||||||
|
"vpiLineNo",
|
||||||
|
"vpiTopModule",
|
||||||
|
"vpiCellInstance",
|
||||||
|
"vpiDefName",
|
||||||
|
"vpiProtected",
|
||||||
|
"vpiTimeUnit",
|
||||||
|
"vpiTimePrecision",
|
||||||
|
"vpiDefNetType",
|
||||||
|
"vpiUnconnDrive",
|
||||||
|
"vpiDefFile",
|
||||||
|
"vpiDefLineNo",
|
||||||
|
"vpiScalar",
|
||||||
|
"vpiVector",
|
||||||
|
"vpiExplicitName",
|
||||||
|
"vpiDirection",
|
||||||
|
"vpiConnByName",
|
||||||
|
"vpiNetType",
|
||||||
|
"vpiExplicitScalared",
|
||||||
|
"vpiExplicitVectored",
|
||||||
|
"vpiExpanded",
|
||||||
|
"vpiImplicitDecl",
|
||||||
|
"vpiChargeStrength",
|
||||||
|
"vpiArray",
|
||||||
|
"vpiPortIndex",
|
||||||
|
"vpiTermIndex",
|
||||||
|
"vpiStrength0",
|
||||||
|
"vpiStrength1",
|
||||||
|
"vpiPrimType",
|
||||||
|
"vpiPolarity",
|
||||||
|
"vpiDataPolarity",
|
||||||
|
"vpiEdge",
|
||||||
|
"vpiPathType",
|
||||||
|
"vpiTchkType",
|
||||||
|
"vpiOpType",
|
||||||
|
"vpiConstType",
|
||||||
|
"vpiBlocking",
|
||||||
|
"vpiCaseType",
|
||||||
|
"vpiFuncType",
|
||||||
|
"vpiNetDeclAssign",
|
||||||
|
"vpiUserDefn",
|
||||||
|
"vpiScheduled",
|
||||||
|
"*undefined*",
|
||||||
|
"*undefined*",
|
||||||
|
"vpiActive",
|
||||||
|
"vpiAutomatic",
|
||||||
|
"vpiCell",
|
||||||
|
"vpiConfig",
|
||||||
|
"vpiConstantSelect",
|
||||||
|
"vpiDecompile",
|
||||||
|
"vpiDefAttribute",
|
||||||
|
"vpiDelayType",
|
||||||
|
"vpiIteratorType",
|
||||||
|
"vpiLibrary",
|
||||||
|
"*undefined*",
|
||||||
|
"vpiOffset",
|
||||||
|
"vpiResolvedNetType",
|
||||||
|
"vpiSaveRestartID",
|
||||||
|
"vpiSaveRestartLocation",
|
||||||
|
"vpiValid",
|
||||||
|
"vpiSigned",
|
||||||
|
"vpiStop",
|
||||||
|
"vpiFinish",
|
||||||
|
"vpiReset",
|
||||||
|
"vpiSetInteractiveScope",
|
||||||
|
"vpiLocalParam",
|
||||||
|
"vpiModPathHasIfNone",
|
||||||
|
"vpiIndexedPartSelectType",
|
||||||
|
"vpiIsMemory",
|
||||||
|
"vpiIsProtected"
|
||||||
|
};
|
||||||
|
if (vpiVal == vpiUndefined) {
|
||||||
|
return "vpiUndefined";
|
||||||
|
}
|
||||||
|
return names[(vpiVal<=vpiIsProtected)?vpiVal:0];
|
||||||
|
}
|
||||||
|
|||||||
+613
-98
File diff suppressed because it is too large
Load Diff
@@ -62,6 +62,7 @@ private:
|
|||||||
nodep->displayType(AstDisplayType::DT_WRITE);
|
nodep->displayType(AstDisplayType::DT_WRITE);
|
||||||
nodep->fmtp()->text(assertDisplayMessage(nodep, prefix, nodep->fmtp()->text()));
|
nodep->fmtp()->text(assertDisplayMessage(nodep, prefix, nodep->fmtp()->text()));
|
||||||
AstNode* timesp = nodep->fmtp()->exprsp(); if (timesp) timesp->unlinkFrBack();
|
AstNode* timesp = nodep->fmtp()->exprsp(); if (timesp) timesp->unlinkFrBack();
|
||||||
|
// cppcheck-suppress nullPointer
|
||||||
timesp = timesp->addNext(new AstTime(nodep->fileline()));
|
timesp = timesp->addNext(new AstTime(nodep->fileline()));
|
||||||
nodep->fmtp()->exprsp(timesp);
|
nodep->fmtp()->exprsp(timesp);
|
||||||
if (!nodep->fmtp()->scopeNamep() && nodep->fmtp()->formatScopeTracking()) {
|
if (!nodep->fmtp()->scopeNamep() && nodep->fmtp()->formatScopeTracking()) {
|
||||||
|
|||||||
+7
-3
@@ -764,6 +764,7 @@ void AstNode::iterateAndNext(AstNVisitor& v, AstNUser* vup) {
|
|||||||
while (nodep) {
|
while (nodep) {
|
||||||
AstNode* niterp = nodep; // This address may get stomped via m_iterpp if the node is edited
|
AstNode* niterp = nodep; // This address may get stomped via m_iterpp if the node is edited
|
||||||
ASTNODE_PREFETCH(nodep->m_nextp);
|
ASTNODE_PREFETCH(nodep->m_nextp);
|
||||||
|
// cppcheck-suppress nullPointer
|
||||||
niterp->m_iterpp = &niterp;
|
niterp->m_iterpp = &niterp;
|
||||||
niterp->accept(v, vup);
|
niterp->accept(v, vup);
|
||||||
// accept may do a replaceNode and change niterp on us...
|
// accept may do a replaceNode and change niterp on us...
|
||||||
@@ -1041,7 +1042,7 @@ void AstNode::v3errorEnd(ostringstream& str) const {
|
|||||||
nsstr<<str.str();
|
nsstr<<str.str();
|
||||||
if (debug()) {
|
if (debug()) {
|
||||||
nsstr<<endl;
|
nsstr<<endl;
|
||||||
nsstr<<"-node: "<<this<<endl;
|
nsstr<<"-node: "; ((AstNode*)this)->dump(nsstr); nsstr<<endl;
|
||||||
}
|
}
|
||||||
m_fileline->v3errorEnd(nsstr);
|
m_fileline->v3errorEnd(nsstr);
|
||||||
} else {
|
} else {
|
||||||
@@ -1067,8 +1068,7 @@ void AstNode::dtypeChgWidth(int width, int widthMin) {
|
|||||||
dtypeChgWidthSigned(width, widthMin, dtypep()->numeric());
|
dtypeChgWidthSigned(width, widthMin, dtypep()->numeric());
|
||||||
}
|
}
|
||||||
|
|
||||||
void AstNode::dtypeChgWidthSigned(int width, int widthMin, bool issigned) {
|
void AstNode::dtypeChgWidthSigned(int width, int widthMin, AstNumeric numeric) {
|
||||||
AstNumeric numeric = issigned ? AstNumeric::SIGNED : AstNumeric::UNSIGNED;
|
|
||||||
if (!dtypep()) {
|
if (!dtypep()) {
|
||||||
// We allow dtypep() to be null, as before/during widthing dtypes are not resolved
|
// We allow dtypep() to be null, as before/during widthing dtypes are not resolved
|
||||||
dtypeSetLogicSized(width, widthMin, numeric);
|
dtypeSetLogicSized(width, widthMin, numeric);
|
||||||
@@ -1099,6 +1099,10 @@ AstNodeDType* AstNode::findLogicDType(int width, int widthMin, AstNumeric numeri
|
|||||||
return v3Global.rootp()->typeTablep()
|
return v3Global.rootp()->typeTablep()
|
||||||
->findLogicBitDType(fileline(), AstBasicDTypeKwd::LOGIC, width, widthMin, numeric);
|
->findLogicBitDType(fileline(), AstBasicDTypeKwd::LOGIC, width, widthMin, numeric);
|
||||||
}
|
}
|
||||||
|
AstNodeDType* AstNode::findLogicRangeDType(VNumRange range, int widthMin, AstNumeric numeric) const {
|
||||||
|
return v3Global.rootp()->typeTablep()
|
||||||
|
->findLogicBitDType(fileline(), AstBasicDTypeKwd::LOGIC, range, widthMin, numeric);
|
||||||
|
}
|
||||||
AstBasicDType* AstNode::findInsertSameDType(AstBasicDType* nodep) {
|
AstBasicDType* AstNode::findInsertSameDType(AstBasicDType* nodep) {
|
||||||
return v3Global.rootp()->typeTablep()
|
return v3Global.rootp()->typeTablep()
|
||||||
->findInsertSameDType(nodep);
|
->findInsertSameDType(nodep);
|
||||||
|
|||||||
+100
-24
@@ -47,6 +47,7 @@ public:
|
|||||||
// enum en {...};
|
// enum en {...};
|
||||||
// const char* ascii() const {...};
|
// const char* ascii() const {...};
|
||||||
enum en m_e;
|
enum en m_e;
|
||||||
|
// cppcheck-suppress uninitVar // responsiblity of each subclass
|
||||||
inline AstType () {}
|
inline AstType () {}
|
||||||
inline AstType (en _e) : m_e(_e) {}
|
inline AstType (en _e) : m_e(_e) {}
|
||||||
explicit inline AstType (int _e) : m_e(static_cast<en>(_e)) {}
|
explicit inline AstType (int _e) : m_e(static_cast<en>(_e)) {}
|
||||||
@@ -219,7 +220,16 @@ class AstAttrType {
|
|||||||
public:
|
public:
|
||||||
enum en {
|
enum en {
|
||||||
ILLEGAL,
|
ILLEGAL,
|
||||||
EXPR_BITS, // V3Const converts to constant
|
//
|
||||||
|
DIM_BITS, // V3Const converts to constant
|
||||||
|
DIM_DIMENSIONS, // V3Width converts to constant
|
||||||
|
DIM_HIGH, // V3Width processes
|
||||||
|
DIM_INCREMENT, // V3Width processes
|
||||||
|
DIM_LEFT, // V3Width processes
|
||||||
|
DIM_LOW, // V3Width processes
|
||||||
|
DIM_RIGHT, // V3Width processes
|
||||||
|
DIM_SIZE, // V3Width processes
|
||||||
|
DIM_UNPK_DIMENSIONS, // V3Width converts to constant
|
||||||
//
|
//
|
||||||
MEMBER_BASE, // V3LinkResolve creates for AstPreSel, V3LinkParam removes
|
MEMBER_BASE, // V3LinkResolve creates for AstPreSel, V3LinkParam removes
|
||||||
//
|
//
|
||||||
@@ -237,7 +247,10 @@ public:
|
|||||||
enum en m_e;
|
enum en m_e;
|
||||||
const char* ascii() const {
|
const char* ascii() const {
|
||||||
static const char* names[] = {
|
static const char* names[] = {
|
||||||
"%E-AT", "EXPR_BITS", "MEMBER_BASE",
|
"%E-AT",
|
||||||
|
"DIM_BITS", "DIM_DIMENSIONS", "DIM_HIGH", "DIM_INCREMENT", "DIM_LEFT",
|
||||||
|
"DIM_LOW", "DIM_RIGHT", "DIM_SIZE", "DIM_UNPK_DIMENSIONS",
|
||||||
|
"MEMBER_BASE",
|
||||||
"VAR_BASE", "VAR_CLOCK", "VAR_CLOCK_ENABLE", "VAR_PUBLIC",
|
"VAR_BASE", "VAR_CLOCK", "VAR_CLOCK_ENABLE", "VAR_PUBLIC",
|
||||||
"VAR_PUBLIC_FLAT", "VAR_PUBLIC_FLAT_RD","VAR_PUBLIC_FLAT_RW",
|
"VAR_PUBLIC_FLAT", "VAR_PUBLIC_FLAT_RD","VAR_PUBLIC_FLAT_RW",
|
||||||
"VAR_ISOLATE_ASSIGNMENTS", "VAR_SC_BV", "VAR_SFORMAT"
|
"VAR_ISOLATE_ASSIGNMENTS", "VAR_SC_BV", "VAR_SFORMAT"
|
||||||
@@ -527,8 +540,8 @@ public:
|
|||||||
// See also AstRange, which is a symbolic version of this
|
// See also AstRange, which is a symbolic version of this
|
||||||
|
|
||||||
struct VNumRange {
|
struct VNumRange {
|
||||||
int m_msb; // MSB, MSB always >= LSB
|
int m_hi; // HI part, HI always >= LO
|
||||||
int m_lsb; // LSB
|
int m_lo; // LO
|
||||||
union {
|
union {
|
||||||
int mu_flags;
|
int mu_flags;
|
||||||
struct {
|
struct {
|
||||||
@@ -537,33 +550,38 @@ struct VNumRange {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
inline bool operator== (const VNumRange& rhs) const {
|
inline bool operator== (const VNumRange& rhs) const {
|
||||||
return m_msb == rhs.m_msb
|
return m_hi == rhs.m_hi
|
||||||
&& m_lsb == rhs.m_lsb
|
&& m_lo == rhs.m_lo
|
||||||
&& mu_flags == rhs.mu_flags; }
|
&& mu_flags == rhs.mu_flags; }
|
||||||
inline bool operator< (const VNumRange& rhs) const {
|
inline bool operator< (const VNumRange& rhs) const {
|
||||||
if ( (m_msb < rhs.m_msb)) return true;
|
if ( (m_hi < rhs.m_hi)) return true;
|
||||||
if (!(m_msb == rhs.m_msb)) return false; // lhs > rhs
|
if (!(m_hi == rhs.m_hi)) return false; // lhs > rhs
|
||||||
if ( (m_lsb < rhs.m_lsb)) return true;
|
if ( (m_lo < rhs.m_lo)) return true;
|
||||||
if (!(m_lsb == rhs.m_lsb)) return false; // lhs > rhs
|
if (!(m_lo == rhs.m_lo)) return false; // lhs > rhs
|
||||||
if ( (mu_flags < rhs.mu_flags)) return true;
|
if ( (mu_flags < rhs.mu_flags)) return true;
|
||||||
if (!(mu_flags == rhs.mu_flags)) return false; // lhs > rhs
|
if (!(mu_flags == rhs.mu_flags)) return false; // lhs > rhs
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
//
|
//
|
||||||
VNumRange() : m_msb(0), m_lsb(0), mu_flags(0) {}
|
VNumRange() : m_hi(0), m_lo(0), mu_flags(0) {}
|
||||||
|
VNumRange(int hi, int lo, bool littleEndian)
|
||||||
|
: m_hi(0), m_lo(0), mu_flags(0)
|
||||||
|
{ init(hi,lo,littleEndian); }
|
||||||
~VNumRange() {}
|
~VNumRange() {}
|
||||||
// MEMBERS
|
// MEMBERS
|
||||||
void init(int msb, int lsb, bool littleEndian) {
|
void init(int hi, int lo, bool littleEndian) {
|
||||||
m_msb=msb; m_lsb=lsb; mu_flags=0; m_ranged=true; m_littleEndian=littleEndian;
|
m_hi=hi; m_lo=lo; mu_flags=0; m_ranged=true; m_littleEndian=littleEndian;
|
||||||
}
|
}
|
||||||
int msb() const { return m_msb; }
|
int hi() const { return m_hi; }
|
||||||
int lsb() const { return m_lsb; }
|
int lo() const { return m_lo; }
|
||||||
int left() const { return littleEndian()?lsb():msb(); } // How to show a declaration
|
int left() const { return littleEndian()?lo():hi(); } // How to show a declaration
|
||||||
int right() const { return littleEndian()?msb():lsb(); }
|
int right() const { return littleEndian()?hi():lo(); }
|
||||||
|
int elements() const { return hi()-lo()+1; }
|
||||||
bool ranged() const { return m_ranged; }
|
bool ranged() const { return m_ranged; }
|
||||||
bool littleEndian() const { return m_littleEndian; }
|
bool littleEndian() const { return m_littleEndian; }
|
||||||
|
int hiMaxSelect() const { return (lo()<0 ? hi()-lo() : hi()); } // Maximum value a [] select may index
|
||||||
bool representableByWidth() const // Could be represented by just width=1, or [width-1:0]
|
bool representableByWidth() const // Could be represented by just width=1, or [width-1:0]
|
||||||
{ return (!m_ranged || (m_lsb==0 && m_msb>=1 && !m_littleEndian)); }
|
{ return (!m_ranged || (m_lo==0 && m_hi>=1 && !m_littleEndian)); }
|
||||||
};
|
};
|
||||||
|
|
||||||
//######################################################################
|
//######################################################################
|
||||||
@@ -765,7 +783,7 @@ protected:
|
|||||||
RelinkWhatEn m_chg;
|
RelinkWhatEn m_chg;
|
||||||
AstNode** m_iterpp;
|
AstNode** m_iterpp;
|
||||||
public:
|
public:
|
||||||
AstNRelinker() { m_backp=NULL; m_chg=RELINK_BAD; m_iterpp=NULL;}
|
AstNRelinker() { m_oldp=NULL; m_backp=NULL; m_chg=RELINK_BAD; m_iterpp=NULL;}
|
||||||
void relink(AstNode* newp);
|
void relink(AstNode* newp);
|
||||||
AstNode* oldp() const { return m_oldp; }
|
AstNode* oldp() const { return m_oldp; }
|
||||||
void dump(ostream& str=cout) const;
|
void dump(ostream& str=cout) const;
|
||||||
@@ -1057,7 +1075,7 @@ public:
|
|||||||
void dtypeFrom(AstNode* fromp) { if (fromp) { dtypep(fromp->dtypep()); }}
|
void dtypeFrom(AstNode* fromp) { if (fromp) { dtypep(fromp->dtypep()); }}
|
||||||
void dtypeChgSigned(bool flag=true);
|
void dtypeChgSigned(bool flag=true);
|
||||||
void dtypeChgWidth(int width, int widthMin);
|
void dtypeChgWidth(int width, int widthMin);
|
||||||
void dtypeChgWidthSigned(int width, int widthMin, bool issigned);
|
void dtypeChgWidthSigned(int width, int widthMin, AstNumeric numeric);
|
||||||
void dtypeSetBitSized(int width, int widthMin, AstNumeric numeric) { dtypep(findBitDType(width,widthMin,numeric)); }
|
void dtypeSetBitSized(int width, int widthMin, AstNumeric numeric) { dtypep(findBitDType(width,widthMin,numeric)); }
|
||||||
void dtypeSetLogicSized(int width, int widthMin, AstNumeric numeric) { dtypep(findLogicDType(width,widthMin,numeric)); }
|
void dtypeSetLogicSized(int width, int widthMin, AstNumeric numeric) { dtypep(findLogicDType(width,widthMin,numeric)); }
|
||||||
void dtypeSetLogicBool() { dtypep(findLogicBoolDType()); }
|
void dtypeSetLogicBool() { dtypep(findLogicBoolDType()); }
|
||||||
@@ -1074,6 +1092,7 @@ public:
|
|||||||
AstNodeDType* findUInt64DType() { return findBasicDType(AstBasicDTypeKwd::UINT64); } // Twostate
|
AstNodeDType* findUInt64DType() { return findBasicDType(AstBasicDTypeKwd::UINT64); } // Twostate
|
||||||
AstNodeDType* findBitDType(int width, int widthMin, AstNumeric numeric) const;
|
AstNodeDType* findBitDType(int width, int widthMin, AstNumeric numeric) const;
|
||||||
AstNodeDType* findLogicDType(int width, int widthMin, AstNumeric numeric) const;
|
AstNodeDType* findLogicDType(int width, int widthMin, AstNumeric numeric) const;
|
||||||
|
AstNodeDType* findLogicRangeDType(VNumRange range, int widthMin, AstNumeric numeric) const;
|
||||||
AstNodeDType* findBasicDType(AstBasicDTypeKwd kwd) const;
|
AstNodeDType* findBasicDType(AstBasicDTypeKwd kwd) const;
|
||||||
AstBasicDType* findInsertSameDType(AstBasicDType* nodep);
|
AstBasicDType* findInsertSameDType(AstBasicDType* nodep);
|
||||||
|
|
||||||
@@ -1498,7 +1517,7 @@ public:
|
|||||||
//
|
//
|
||||||
// Changing the width may confuse the data type resolution, so must clear TypeTable cache after use.
|
// Changing the width may confuse the data type resolution, so must clear TypeTable cache after use.
|
||||||
void widthForce(int width, int sized) { m_width=width; m_widthMin=sized; }
|
void widthForce(int width, int sized) { m_width=width; m_widthMin=sized; }
|
||||||
// For backward compatibility AstArrayDType and others inherit width and signing from the subDType/base type
|
// For backward compatibility inherit width and signing from the subDType/base type
|
||||||
void widthFromSub(AstNodeDType* nodep) { m_width=nodep->m_width; m_widthMin=nodep->m_widthMin; m_numeric=nodep->m_numeric; }
|
void widthFromSub(AstNodeDType* nodep) { m_width=nodep->m_width; m_widthMin=nodep->m_widthMin; m_numeric=nodep->m_numeric; }
|
||||||
//
|
//
|
||||||
int width() const { return m_width; }
|
int width() const { return m_width; }
|
||||||
@@ -1514,8 +1533,8 @@ public:
|
|||||||
bool generic() const { return m_generic; }
|
bool generic() const { return m_generic; }
|
||||||
void generic(bool flag) { m_generic = flag; }
|
void generic(bool flag) { m_generic = flag; }
|
||||||
AstNodeDType* dtypeDimensionp(int depth);
|
AstNodeDType* dtypeDimensionp(int depth);
|
||||||
pair<uint32_t,uint32_t> dimensions();
|
pair<uint32_t,uint32_t> dimensions(bool includeBasic);
|
||||||
uint32_t arrayElements(); // 1, or total multiplication of all dimensions
|
uint32_t arrayUnpackedElements(); // 1, or total multiplication of all dimensions
|
||||||
static int uniqueNumInc() { return ++s_uniqueNum; }
|
static int uniqueNumInc() { return ++s_uniqueNum; }
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -1551,6 +1570,54 @@ public:
|
|||||||
MemberNameMap::const_iterator it = m_members.find(name);
|
MemberNameMap::const_iterator it = m_members.find(name);
|
||||||
return (it==m_members.end()) ? NULL : it->second;
|
return (it==m_members.end()) ? NULL : it->second;
|
||||||
}
|
}
|
||||||
|
int lsb() const { return 0; }
|
||||||
|
int msb() const { return dtypep()->width()-1; } // Packed classes look like arrays
|
||||||
|
VNumRange declRange() const { return VNumRange(msb(), lsb(), false); }
|
||||||
|
};
|
||||||
|
|
||||||
|
struct AstNodeArrayDType : public AstNodeDType {
|
||||||
|
// Array data type, ie "some_dtype var_name [2:0]"
|
||||||
|
// Children: DTYPE (moved to refDTypep() in V3Width)
|
||||||
|
// Children: RANGE (array bounds)
|
||||||
|
private:
|
||||||
|
AstNodeDType* m_refDTypep; // Elements of this type (after widthing)
|
||||||
|
AstNode* rangenp() const { return op2p(); } // op2 = Array(s) of variable
|
||||||
|
public:
|
||||||
|
AstNodeArrayDType(FileLine* fl) : AstNodeDType(fl) {
|
||||||
|
m_refDTypep = NULL;
|
||||||
|
}
|
||||||
|
ASTNODE_BASE_FUNCS(NodeArrayDType)
|
||||||
|
virtual void dump(ostream& str);
|
||||||
|
virtual void dumpSmall(ostream& str);
|
||||||
|
virtual bool broken() const { return !((m_refDTypep && !childDTypep() && m_refDTypep->brokeExists())
|
||||||
|
|| (!m_refDTypep && childDTypep())); }
|
||||||
|
virtual void cloneRelink() { if (m_refDTypep && m_refDTypep->clonep()) {
|
||||||
|
m_refDTypep = m_refDTypep->clonep()->castNodeDType();
|
||||||
|
}}
|
||||||
|
virtual bool same(AstNode* samep) const {
|
||||||
|
AstNodeArrayDType* sp = samep->castNodeArrayDType();
|
||||||
|
return (msb()==sp->msb()
|
||||||
|
&& subDTypep()==sp->subDTypep()
|
||||||
|
&& rangenp()->sameTree(sp->rangenp())); } // HashedDT doesn't recurse, so need to check children
|
||||||
|
virtual V3Hash sameHash() const { return V3Hash(V3Hash(m_refDTypep),V3Hash(msb()),V3Hash(lsb())); }
|
||||||
|
AstNodeDType* getChildDTypep() const { return childDTypep(); }
|
||||||
|
AstNodeDType* childDTypep() const { return op1p()->castNodeDType(); } // op1 = Range of variable
|
||||||
|
void childDTypep(AstNodeDType* nodep) { setOp1p(nodep); }
|
||||||
|
AstNodeDType* subDTypep() const { return m_refDTypep ? m_refDTypep : childDTypep(); }
|
||||||
|
void refDTypep(AstNodeDType* nodep) { m_refDTypep = nodep; }
|
||||||
|
virtual AstNodeDType* virtRefDTypep() const { return m_refDTypep; }
|
||||||
|
virtual void virtRefDTypep(AstNodeDType* nodep) { refDTypep(nodep); }
|
||||||
|
AstRange* rangep() const { return op2p()->castRange(); } // op2 = Array(s) of variable
|
||||||
|
void rangep(AstRange* nodep);
|
||||||
|
// METHODS
|
||||||
|
virtual AstBasicDType* basicp() const { return subDTypep()->basicp(); } // (Slow) recurse down to find basic data type
|
||||||
|
virtual AstNodeDType* skipRefp() const { return (AstNodeDType*)this; }
|
||||||
|
virtual int widthAlignBytes() const { return subDTypep()->widthAlignBytes(); }
|
||||||
|
virtual int widthTotalBytes() const { return elementsConst() * subDTypep()->widthTotalBytes(); }
|
||||||
|
int msb() const;
|
||||||
|
int lsb() const;
|
||||||
|
int elementsConst() const;
|
||||||
|
VNumRange declRange() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct AstNodeSel : public AstNodeBiop {
|
struct AstNodeSel : public AstNodeBiop {
|
||||||
@@ -1684,13 +1751,14 @@ private:
|
|||||||
bool m_modTrace:1; // Tracing this module
|
bool m_modTrace:1; // Tracing this module
|
||||||
bool m_inLibrary:1; // From a library, no error if not used, never top level
|
bool m_inLibrary:1; // From a library, no error if not used, never top level
|
||||||
bool m_dead:1; // LinkDot believes is dead; will remove in Dead visitors
|
bool m_dead:1; // LinkDot believes is dead; will remove in Dead visitors
|
||||||
|
bool m_internal:1; // Internally created
|
||||||
int m_level; // 1=top module, 2=cell off top module, ...
|
int m_level; // 1=top module, 2=cell off top module, ...
|
||||||
int m_varNum; // Incrementing variable number
|
int m_varNum; // Incrementing variable number
|
||||||
public:
|
public:
|
||||||
AstNodeModule(FileLine* fl, const string& name)
|
AstNodeModule(FileLine* fl, const string& name)
|
||||||
: AstNode (fl)
|
: AstNode (fl)
|
||||||
,m_name(name), m_origName(name)
|
,m_name(name), m_origName(name)
|
||||||
,m_modPublic(false), m_modTrace(false), m_inLibrary(false), m_dead(false)
|
,m_modPublic(false), m_modTrace(false), m_inLibrary(false), m_dead(false), m_internal(false)
|
||||||
,m_level(0), m_varNum(0) { }
|
,m_level(0), m_varNum(0) { }
|
||||||
ASTNODE_BASE_FUNCS(NodeModule)
|
ASTNODE_BASE_FUNCS(NodeModule)
|
||||||
virtual void dump(ostream& str);
|
virtual void dump(ostream& str);
|
||||||
@@ -1717,6 +1785,8 @@ public:
|
|||||||
bool modTrace() const { return m_modTrace; }
|
bool modTrace() const { return m_modTrace; }
|
||||||
void dead(bool flag) { m_dead = flag; }
|
void dead(bool flag) { m_dead = flag; }
|
||||||
bool dead() const { return m_dead; }
|
bool dead() const { return m_dead; }
|
||||||
|
void internal(bool flag) { m_internal = flag; }
|
||||||
|
bool internal() const { return m_internal; }
|
||||||
};
|
};
|
||||||
|
|
||||||
//######################################################################
|
//######################################################################
|
||||||
@@ -1745,4 +1815,10 @@ inline bool AstNode::isAllOnesV() { return (this->castConst() && this->castConst
|
|||||||
|
|
||||||
inline void AstNodeVarRef::init() { if (m_varp) dtypep(m_varp->dtypep()); }
|
inline void AstNodeVarRef::init() { if (m_varp) dtypep(m_varp->dtypep()); }
|
||||||
|
|
||||||
|
inline void AstNodeArrayDType::rangep(AstRange* nodep) { setOp2p(nodep); }
|
||||||
|
inline int AstNodeArrayDType::msb() const { return rangep()->msbConst(); }
|
||||||
|
inline int AstNodeArrayDType::lsb() const { return rangep()->lsbConst(); }
|
||||||
|
inline int AstNodeArrayDType::elementsConst() const { return rangep()->elementsConst(); }
|
||||||
|
inline VNumRange AstNodeArrayDType::declRange() const { return VNumRange(msb(), lsb(), rangep()->littleEndian()); }
|
||||||
|
|
||||||
#endif // Guard
|
#endif // Guard
|
||||||
|
|||||||
+40
-30
@@ -307,10 +307,12 @@ AstNodeDType* AstNodeDType::dtypeDimensionp(int dimension) {
|
|||||||
// DECL: VAR a (ARRAYSEL0 (ARRAYSEL1 (ARRAYSEL2 (DT RANGE3))))
|
// DECL: VAR a (ARRAYSEL0 (ARRAYSEL1 (ARRAYSEL2 (DT RANGE3))))
|
||||||
// *or* VAR a (ARRAYSEL0 (ARRAYSEL1 (ARRAYSEL2 (ARRAYSEL3 (DT))))
|
// *or* VAR a (ARRAYSEL0 (ARRAYSEL1 (ARRAYSEL2 (ARRAYSEL3 (DT))))
|
||||||
// SEL1 needs to select from entire variable which is a pointer to ARRAYSEL0
|
// SEL1 needs to select from entire variable which is a pointer to ARRAYSEL0
|
||||||
|
// TODO this function should be removed in favor of recursing the dtype(),
|
||||||
|
// as that allows for more complicated data types.
|
||||||
int dim = 0;
|
int dim = 0;
|
||||||
for (AstNodeDType* dtypep=this; dtypep; ) {
|
for (AstNodeDType* dtypep=this; dtypep; ) {
|
||||||
dtypep = dtypep->skipRefp(); // Skip AstRefDType/AstTypedef, or return same node
|
dtypep = dtypep->skipRefp(); // Skip AstRefDType/AstTypedef, or return same node
|
||||||
if (AstArrayDType* adtypep = dtypep->castArrayDType()) {
|
if (AstNodeArrayDType* adtypep = dtypep->castNodeArrayDType()) {
|
||||||
if ((dim++)==dimension) {
|
if ((dim++)==dimension) {
|
||||||
return dtypep;
|
return dtypep;
|
||||||
}
|
}
|
||||||
@@ -340,11 +342,11 @@ AstNodeDType* AstNodeDType::dtypeDimensionp(int dimension) {
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t AstNodeDType::arrayElements() {
|
uint32_t AstNodeDType::arrayUnpackedElements() {
|
||||||
uint32_t entries=1;
|
uint32_t entries=1;
|
||||||
for (AstNodeDType* dtypep=this; dtypep; ) {
|
for (AstNodeDType* dtypep=this; dtypep; ) {
|
||||||
dtypep = dtypep->skipRefp(); // Skip AstRefDType/AstTypedef, or return same node
|
dtypep = dtypep->skipRefp(); // Skip AstRefDType/AstTypedef, or return same node
|
||||||
if (AstArrayDType* adtypep = dtypep->castArrayDType()) {
|
if (AstUnpackArrayDType* adtypep = dtypep->castUnpackArrayDType()) {
|
||||||
entries *= adtypep->elementsConst();
|
entries *= adtypep->elementsConst();
|
||||||
dtypep = adtypep->subDTypep();
|
dtypep = adtypep->subDTypep();
|
||||||
}
|
}
|
||||||
@@ -356,21 +358,22 @@ uint32_t AstNodeDType::arrayElements() {
|
|||||||
return entries;
|
return entries;
|
||||||
}
|
}
|
||||||
|
|
||||||
pair<uint32_t,uint32_t> AstNodeDType::dimensions() {
|
pair<uint32_t,uint32_t> AstNodeDType::dimensions(bool includeBasic) {
|
||||||
// How many array dimensions (packed,unpacked) does this Var have?
|
// How many array dimensions (packed,unpacked) does this Var have?
|
||||||
uint32_t packed = 0;
|
uint32_t packed = 0;
|
||||||
uint32_t unpacked = 0;
|
uint32_t unpacked = 0;
|
||||||
for (AstNodeDType* dtypep=this; dtypep; ) {
|
for (AstNodeDType* dtypep=this; dtypep; ) {
|
||||||
dtypep = dtypep->skipRefp(); // Skip AstRefDType/AstTypedef, or return same node
|
dtypep = dtypep->skipRefp(); // Skip AstRefDType/AstTypedef, or return same node
|
||||||
if (AstArrayDType* adtypep = dtypep->castArrayDType()) {
|
if (AstNodeArrayDType* adtypep = dtypep->castNodeArrayDType()) {
|
||||||
if (adtypep->isPacked()) packed += 1;
|
if (adtypep->castPackArrayDType()) packed++;
|
||||||
else unpacked += 1;
|
else unpacked++;
|
||||||
dtypep = adtypep->subDTypep();
|
dtypep = adtypep->subDTypep();
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
else {
|
else if (AstBasicDType* adtypep = dtypep->castBasicDType()) {
|
||||||
// AstBasicDType - nothing below, 1
|
if (includeBasic && adtypep->isRanged()) packed++;
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
return make_pair(packed, unpacked);
|
return make_pair(packed, unpacked);
|
||||||
}
|
}
|
||||||
@@ -384,26 +387,12 @@ int AstNodeDType::widthPow2() const {
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Special operators
|
|
||||||
int AstArraySel::dimension(AstNode* nodep) {
|
|
||||||
// How many dimensions is this reference from the base variable?
|
|
||||||
// nodep is typically the fromp() of a select; thus the first select
|
|
||||||
// is selecting from the entire variable type - effectively dimension 0.
|
|
||||||
// Dimension passed to AstVar::dtypeDimensionp; see comments there
|
|
||||||
int dim = 0;
|
|
||||||
while (nodep) {
|
|
||||||
if (nodep->castNodeSel()) { dim++; nodep=nodep->castNodeSel()->fromp(); continue; }
|
|
||||||
if (nodep->castNodePreSel()) { dim++; nodep=nodep->castNodePreSel()->fromp(); continue; }
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return dim;
|
|
||||||
}
|
|
||||||
AstNode* AstArraySel::baseFromp(AstNode* nodep) { ///< What is the base variable (or const) this dereferences?
|
AstNode* AstArraySel::baseFromp(AstNode* nodep) { ///< What is the base variable (or const) this dereferences?
|
||||||
// Else AstArraySel etc; search for the base
|
// Else AstArraySel etc; search for the base
|
||||||
while (nodep) {
|
while (nodep) {
|
||||||
if (nodep->castArraySel()) { nodep=nodep->castArraySel()->fromp(); continue; }
|
if (nodep->castArraySel()) { nodep=nodep->castArraySel()->fromp(); continue; }
|
||||||
else if (nodep->castSel()) { nodep=nodep->castSel()->fromp(); continue; }
|
else if (nodep->castSel()) { nodep=nodep->castSel()->fromp(); continue; }
|
||||||
// AstNodeSelPre stashes the associated variable under a ATTROF of AstAttrType::VAR_BASE/MEMBER_BASE so it isn't constified
|
// AstNodeSelPre stashes the associated variable under an ATTROF of AstAttrType::VAR_BASE/MEMBER_BASE so it isn't constified
|
||||||
else if (nodep->castAttrOf()) { nodep=nodep->castAttrOf()->fromp(); continue; }
|
else if (nodep->castAttrOf()) { nodep=nodep->castAttrOf()->fromp(); continue; }
|
||||||
else if (nodep->castNodePreSel()) {
|
else if (nodep->castNodePreSel()) {
|
||||||
if (nodep->castNodePreSel()->attrp()) {
|
if (nodep->castNodePreSel()->attrp()) {
|
||||||
@@ -555,7 +544,7 @@ AstBasicDType* AstTypeTable::findLogicBitDType(FileLine* fl, AstBasicDTypeKwd kw
|
|||||||
LogicMap::const_iterator it = mapr.find(widths);
|
LogicMap::const_iterator it = mapr.find(widths);
|
||||||
if (it != mapr.end()) return it->second;
|
if (it != mapr.end()) return it->second;
|
||||||
//
|
//
|
||||||
AstBasicDType* new1p = new AstBasicDType(fl, AstBasicDTypeKwd::BIT, numeric, width, widthMin);
|
AstBasicDType* new1p = new AstBasicDType(fl, kwd, numeric, width, widthMin);
|
||||||
// Because the detailed map doesn't update this map,
|
// Because the detailed map doesn't update this map,
|
||||||
// check the detailed map for this same node, and if found update this map
|
// check the detailed map for this same node, and if found update this map
|
||||||
// Also adds this new node to the detailed map
|
// Also adds this new node to the detailed map
|
||||||
@@ -567,6 +556,15 @@ AstBasicDType* AstTypeTable::findLogicBitDType(FileLine* fl, AstBasicDTypeKwd kw
|
|||||||
return newp;
|
return newp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
AstBasicDType* AstTypeTable::findLogicBitDType(FileLine* fl, AstBasicDTypeKwd kwd,
|
||||||
|
VNumRange range, int widthMin, AstNumeric numeric) {
|
||||||
|
AstBasicDType* new1p = new AstBasicDType(fl, kwd, numeric, range, widthMin);
|
||||||
|
AstBasicDType* newp = findInsertSameDType(new1p);
|
||||||
|
if (newp != new1p) new1p->deleteTree();
|
||||||
|
else addTypesp(newp);
|
||||||
|
return newp;
|
||||||
|
}
|
||||||
|
|
||||||
AstBasicDType* AstTypeTable::findInsertSameDType(AstBasicDType* nodep) {
|
AstBasicDType* AstTypeTable::findInsertSameDType(AstBasicDType* nodep) {
|
||||||
VBasicTypeKey key (nodep->width(), nodep->widthMin(), nodep->numeric(),
|
VBasicTypeKey key (nodep->width(), nodep->widthMin(), nodep->numeric(),
|
||||||
nodep->keyword(), nodep->nrange());
|
nodep->keyword(), nodep->nrange());
|
||||||
@@ -667,10 +665,6 @@ void AstNode::dump(ostream& str) {
|
|||||||
if (name()!="") str<<" "<<AstNode::quoteName(name());
|
if (name()!="") str<<" "<<AstNode::quoteName(name());
|
||||||
}
|
}
|
||||||
|
|
||||||
void AstArrayDType::dump(ostream& str) {
|
|
||||||
this->AstNodeDType::dump(str);
|
|
||||||
if (isPacked()) str<<" [PACKED]";
|
|
||||||
}
|
|
||||||
void AstArraySel::dump(ostream& str) {
|
void AstArraySel::dump(ostream& str) {
|
||||||
this->AstNode::dump(str);
|
this->AstNode::dump(str);
|
||||||
str<<" [start:"<<start()<<"] [length:"<<length()<<"]";
|
str<<" [start:"<<start()<<"] [length:"<<length()<<"]";
|
||||||
@@ -750,6 +744,15 @@ void AstNodeDType::dumpSmall(ostream& str) {
|
|||||||
if (!widthSized()) str<<"/"<<widthMin();
|
if (!widthSized()) str<<"/"<<widthMin();
|
||||||
str<<")";
|
str<<")";
|
||||||
}
|
}
|
||||||
|
void AstNodeArrayDType::dumpSmall(ostream& str) {
|
||||||
|
this->AstNodeDType::dumpSmall(str);
|
||||||
|
if (castPackArrayDType()) str<<"p"; else str<<"u";
|
||||||
|
str<<"["<<declRange().left()<<":"<<declRange().right()<<"]";
|
||||||
|
}
|
||||||
|
void AstNodeArrayDType::dump(ostream& str) {
|
||||||
|
this->AstNodeDType::dump(str);
|
||||||
|
str<<" ["<<declRange().left()<<":"<<declRange().right()<<"]";
|
||||||
|
}
|
||||||
void AstNodeModule::dump(ostream& str) {
|
void AstNodeModule::dump(ostream& str) {
|
||||||
this->AstNode::dump(str);
|
this->AstNode::dump(str);
|
||||||
str<<" L"<<level();
|
str<<" L"<<level();
|
||||||
@@ -761,6 +764,13 @@ void AstPackageImport::dump(ostream& str) {
|
|||||||
this->AstNode::dump(str);
|
this->AstNode::dump(str);
|
||||||
str<<" -> "<<packagep();
|
str<<" -> "<<packagep();
|
||||||
}
|
}
|
||||||
|
void AstSel::dump(ostream& str) {
|
||||||
|
this->AstNode::dump(str);
|
||||||
|
if (declRange().ranged()) {
|
||||||
|
str<<" decl["<<declRange().left()<<":"<<declRange().right()<<"]";
|
||||||
|
if (declElWidth()!=1) str<<"/"<<declElWidth();
|
||||||
|
}
|
||||||
|
}
|
||||||
void AstTypeTable::dump(ostream& str) {
|
void AstTypeTable::dump(ostream& str) {
|
||||||
this->AstNode::dump(str);
|
this->AstNode::dump(str);
|
||||||
for (int i=0; i<(int)(AstBasicDTypeKwd::_ENUM_MAX); ++i) {
|
for (int i=0; i<(int)(AstBasicDTypeKwd::_ENUM_MAX); ++i) {
|
||||||
|
|||||||
+134
-52
@@ -65,6 +65,11 @@ public:
|
|||||||
:AstNodeMath(fl)
|
:AstNodeMath(fl)
|
||||||
,m_num(V3Number(fl,32,num)) { m_num.width(32,false); dtypeSetLogicSized(32,m_num.widthMin(),
|
,m_num(V3Number(fl,32,num)) { m_num.width(32,false); dtypeSetLogicSized(32,m_num.widthMin(),
|
||||||
AstNumeric::UNSIGNED); }
|
AstNumeric::UNSIGNED); }
|
||||||
|
class Signed32 {}; // for creator type-overload selection
|
||||||
|
AstConst(FileLine* fl, Signed32, int32_t num) // Signed 32-bit integer of specified value
|
||||||
|
:AstNodeMath(fl)
|
||||||
|
,m_num(V3Number(fl,32,num)) { m_num.width(32,32); dtypeSetLogicSized(32,m_num.widthMin(),
|
||||||
|
AstNumeric::SIGNED); }
|
||||||
class RealDouble {}; // for creator type-overload selection
|
class RealDouble {}; // for creator type-overload selection
|
||||||
AstConst(FileLine* fl, RealDouble, double num)
|
AstConst(FileLine* fl, RealDouble, double num)
|
||||||
:AstNodeMath(fl)
|
:AstNodeMath(fl)
|
||||||
@@ -137,6 +142,11 @@ public:
|
|||||||
m_littleEndian = false;
|
m_littleEndian = false;
|
||||||
setOp2p(new AstConst(fl,msb)); setOp3p(new AstConst(fl,lsb));
|
setOp2p(new AstConst(fl,msb)); setOp3p(new AstConst(fl,lsb));
|
||||||
}
|
}
|
||||||
|
AstRange(FileLine* fl, VNumRange range)
|
||||||
|
:AstNode(fl) {
|
||||||
|
m_littleEndian = range.littleEndian();
|
||||||
|
setOp2p(new AstConst(fl,range.hi())); setOp3p(new AstConst(fl,range.lo()));
|
||||||
|
}
|
||||||
ASTNODE_NODE_FUNCS(Range, RANGE)
|
ASTNODE_NODE_FUNCS(Range, RANGE)
|
||||||
AstNode* msbp() const { return op2p()->castNode(); } // op2 = Msb expression
|
AstNode* msbp() const { return op2p()->castNode(); } // op2 = Msb expression
|
||||||
AstNode* lsbp() const { return op3p()->castNode(); } // op3 = Lsb expression
|
AstNode* lsbp() const { return op3p()->castNode(); } // op3 = Lsb expression
|
||||||
@@ -223,62 +233,54 @@ public:
|
|||||||
void name(const string& flag) { m_name = flag; }
|
void name(const string& flag) { m_name = flag; }
|
||||||
};
|
};
|
||||||
|
|
||||||
struct AstArrayDType : public AstNodeDType {
|
struct AstPackArrayDType : public AstNodeArrayDType {
|
||||||
// Array data type, ie "some_dtype var_name [2:0]"
|
// Array data type, ie "some_dtype var_name [2:0]"
|
||||||
// Children: DTYPE (moved to refDTypep() in V3Width)
|
// Children: DTYPE (moved to refDTypep() in V3Width)
|
||||||
// Children: RANGE (array bounds)
|
// Children: RANGE (array bounds)
|
||||||
private:
|
|
||||||
AstNodeDType* m_refDTypep; // Elements of this type (after widthing)
|
|
||||||
bool m_packed;
|
|
||||||
public:
|
public:
|
||||||
AstArrayDType(FileLine* fl, VFlagChildDType, AstNodeDType* dtp, AstRange* rangep, bool isPacked=false)
|
AstPackArrayDType(FileLine* fl, VFlagChildDType, AstNodeDType* dtp, AstRange* rangep)
|
||||||
: AstNodeDType(fl), m_packed(isPacked) {
|
: AstNodeArrayDType(fl) {
|
||||||
childDTypep(dtp); // Only for parser
|
childDTypep(dtp); // Only for parser
|
||||||
refDTypep(NULL);
|
refDTypep(NULL);
|
||||||
setOp2p(rangep);
|
setOp2p(rangep);
|
||||||
dtypep(NULL); // V3Width will resolve
|
dtypep(NULL); // V3Width will resolve
|
||||||
|
// For backward compatibility AstNodeArrayDType and others inherit width and signing from the subDType/base type
|
||||||
widthFromSub(subDTypep());
|
widthFromSub(subDTypep());
|
||||||
}
|
}
|
||||||
AstArrayDType(FileLine* fl, AstNodeDType* dtp, AstRange* rangep, bool isPacked=false)
|
AstPackArrayDType(FileLine* fl, AstNodeDType* dtp, AstRange* rangep)
|
||||||
: AstNodeDType(fl), m_packed(isPacked) {
|
: AstNodeArrayDType(fl) {
|
||||||
refDTypep(dtp);
|
refDTypep(dtp);
|
||||||
setOp2p(rangep);
|
setOp2p(rangep);
|
||||||
dtypep(this);
|
dtypep(this);
|
||||||
|
// For backward compatibility AstNodeArrayDType and others inherit width and signing from the subDType/base type
|
||||||
widthFromSub(subDTypep());
|
widthFromSub(subDTypep());
|
||||||
}
|
}
|
||||||
ASTNODE_NODE_FUNCS(ArrayDType, ARRAYDTYPE)
|
ASTNODE_NODE_FUNCS(PackArrayDType, PACKARRAYDTYPE)
|
||||||
virtual void dump(ostream& str);
|
};
|
||||||
virtual bool broken() const { return !((m_refDTypep && !childDTypep() && m_refDTypep->brokeExists())
|
|
||||||
|| (!m_refDTypep && childDTypep())); }
|
struct AstUnpackArrayDType : public AstNodeArrayDType {
|
||||||
virtual void cloneRelink() { if (m_refDTypep && m_refDTypep->clonep()) {
|
// Array data type, ie "some_dtype var_name [2:0]"
|
||||||
m_refDTypep = m_refDTypep->clonep()->castNodeDType();
|
// Children: DTYPE (moved to refDTypep() in V3Width)
|
||||||
}}
|
// Children: RANGE (array bounds)
|
||||||
virtual bool same(AstNode* samep) const {
|
public:
|
||||||
AstArrayDType* sp = samep->castArrayDType();
|
AstUnpackArrayDType(FileLine* fl, VFlagChildDType, AstNodeDType* dtp, AstRange* rangep)
|
||||||
return (m_packed==sp->m_packed
|
: AstNodeArrayDType(fl) {
|
||||||
&& msb()==sp->msb()
|
childDTypep(dtp); // Only for parser
|
||||||
&& subDTypep()==sp->subDTypep()
|
refDTypep(NULL);
|
||||||
&& rangep()->sameTree(sp->rangep())); } // HashedDT doesn't recurse, so need to check children
|
setOp2p(rangep);
|
||||||
virtual V3Hash sameHash() const { return V3Hash(V3Hash(m_refDTypep),V3Hash(msb()),V3Hash(lsb())); }
|
dtypep(NULL); // V3Width will resolve
|
||||||
AstNodeDType* getChildDTypep() const { return childDTypep(); }
|
// For backward compatibility AstNodeArrayDType and others inherit width and signing from the subDType/base type
|
||||||
AstNodeDType* childDTypep() const { return op1p()->castNodeDType(); } // op1 = Range of variable
|
widthFromSub(subDTypep());
|
||||||
void childDTypep(AstNodeDType* nodep) { setOp1p(nodep); }
|
}
|
||||||
AstNodeDType* subDTypep() const { return m_refDTypep ? m_refDTypep : childDTypep(); }
|
AstUnpackArrayDType(FileLine* fl, AstNodeDType* dtp, AstRange* rangep)
|
||||||
void refDTypep(AstNodeDType* nodep) { m_refDTypep = nodep; }
|
: AstNodeArrayDType(fl) {
|
||||||
virtual AstNodeDType* virtRefDTypep() const { return m_refDTypep; }
|
refDTypep(dtp);
|
||||||
virtual void virtRefDTypep(AstNodeDType* nodep) { refDTypep(nodep); }
|
setOp2p(rangep);
|
||||||
AstRange* rangep() const { return op2p()->castRange(); } // op2 = Array(s) of variable
|
dtypep(this);
|
||||||
void rangep(AstRange* nodep) { setOp2p(nodep); }
|
// For backward compatibility AstNodeArrayDType and others inherit width and signing from the subDType/base type
|
||||||
// METHODS
|
widthFromSub(subDTypep());
|
||||||
virtual AstBasicDType* basicp() const { return subDTypep()->basicp(); } // (Slow) recurse down to find basic data type
|
}
|
||||||
virtual AstNodeDType* skipRefp() const { return (AstNodeDType*)this; }
|
ASTNODE_NODE_FUNCS(UnpackArrayDType, UNPACKARRAYDTYPE)
|
||||||
virtual int widthAlignBytes() const { return subDTypep()->widthAlignBytes(); }
|
|
||||||
virtual int widthTotalBytes() const { return elementsConst() * subDTypep()->widthTotalBytes(); }
|
|
||||||
int msb() const { return rangep()->msbConst(); }
|
|
||||||
int lsb() const { return rangep()->lsbConst(); }
|
|
||||||
int elementsConst() const { return rangep()->elementsConst(); }
|
|
||||||
int msbMaxSelect() const { return (lsb()<0 ? msb()-lsb() : msb()); } // Maximum value a [] select may index
|
|
||||||
bool isPacked() const { return m_packed; }
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct AstBasicDType : public AstNodeDType {
|
struct AstBasicDType : public AstNodeDType {
|
||||||
@@ -310,6 +312,11 @@ public:
|
|||||||
: AstNodeDType(fl) {
|
: AstNodeDType(fl) {
|
||||||
init(kwd, numer, wantwidth, widthmin, NULL);
|
init(kwd, numer, wantwidth, widthmin, NULL);
|
||||||
}
|
}
|
||||||
|
AstBasicDType(FileLine* fl, AstBasicDTypeKwd kwd, AstNumeric numer, VNumRange range, int widthmin)
|
||||||
|
: AstNodeDType(fl) {
|
||||||
|
init(kwd, numer, range.elements(), widthmin, NULL);
|
||||||
|
m.m_nrange = range; // as init() presumes lsb==0, but range.lsb() might not be
|
||||||
|
}
|
||||||
// See also addRange in verilog.y
|
// See also addRange in verilog.y
|
||||||
private:
|
private:
|
||||||
void init(AstBasicDTypeKwd kwd, AstNumeric numer,
|
void init(AstBasicDTypeKwd kwd, AstNumeric numer,
|
||||||
@@ -346,7 +353,7 @@ private:
|
|||||||
public:
|
public:
|
||||||
ASTNODE_NODE_FUNCS(BasicDType, BASICDTYPE)
|
ASTNODE_NODE_FUNCS(BasicDType, BASICDTYPE)
|
||||||
virtual void dump(ostream& str);
|
virtual void dump(ostream& str);
|
||||||
virtual V3Hash sameHash() const { return V3Hash(V3Hash(m.m_keyword), V3Hash(m.m_nrange.msb())); }
|
virtual V3Hash sameHash() const { return V3Hash(V3Hash(m.m_keyword), V3Hash(m.m_nrange.hi())); }
|
||||||
virtual bool same(AstNode* samep) const { // width/widthMin/numeric compared elsewhere
|
virtual bool same(AstNode* samep) const { // width/widthMin/numeric compared elsewhere
|
||||||
return samep->castBasicDType()->m == m; }
|
return samep->castBasicDType()->m == m; }
|
||||||
virtual string name() const { return m.m_keyword.ascii(); }
|
virtual string name() const { return m.m_keyword.ascii(); }
|
||||||
@@ -371,13 +378,13 @@ public:
|
|||||||
bool isZeroInit() const { return keyword().isZeroInit(); }
|
bool isZeroInit() const { return keyword().isZeroInit(); }
|
||||||
bool isRanged() const { return rangep() || m.m_nrange.ranged(); }
|
bool isRanged() const { return rangep() || m.m_nrange.ranged(); }
|
||||||
const VNumRange& nrange() const { return m.m_nrange; } // Generally the msb/lsb/etc funcs should be used instead
|
const VNumRange& nrange() const { return m.m_nrange; } // Generally the msb/lsb/etc funcs should be used instead
|
||||||
int msb() const { return (rangep() ? rangep()->msbConst() : m.m_nrange.msb()); }
|
int msb() const { return (rangep() ? rangep()->msbConst() : m.m_nrange.hi()); }
|
||||||
int lsb() const { return (rangep() ? rangep()->lsbConst() : m.m_nrange.lsb()); }
|
int lsb() const { return (rangep() ? rangep()->lsbConst() : m.m_nrange.lo()); }
|
||||||
int left() const { return littleEndian()?lsb():msb(); } // How to show a declaration
|
int left() const { return littleEndian()?lsb():msb(); } // How to show a declaration
|
||||||
int right() const { return littleEndian()?msb():lsb(); }
|
int right() const { return littleEndian()?msb():lsb(); }
|
||||||
int msbMaxSelect() const { return (lsb()<0 ? msb()-lsb() : msb()); } // Maximum value a [] select may index
|
|
||||||
bool littleEndian() const { return (rangep() ? rangep()->littleEndian() : m.m_nrange.littleEndian()); }
|
bool littleEndian() const { return (rangep() ? rangep()->littleEndian() : m.m_nrange.littleEndian()); }
|
||||||
bool implicit() const { return keyword() == AstBasicDTypeKwd::LOGIC_IMPLICIT; }
|
bool implicit() const { return keyword() == AstBasicDTypeKwd::LOGIC_IMPLICIT; }
|
||||||
|
VNumRange declRange() const { return isRanged() ? VNumRange(msb(), lsb(), littleEndian()) : VNumRange(); }
|
||||||
void cvtRangeConst() { // Convert to smaller represenation
|
void cvtRangeConst() { // Convert to smaller represenation
|
||||||
if (rangep() && rangep()->msbp()->castConst() && rangep()->lsbp()->castConst()) {
|
if (rangep() && rangep()->msbp()->castConst() && rangep()->lsbp()->castConst()) {
|
||||||
m.m_nrange.init(rangep()->msbConst(), rangep()->lsbConst(),
|
m.m_nrange.init(rangep()->msbConst(), rangep()->lsbConst(),
|
||||||
@@ -626,9 +633,9 @@ private:
|
|||||||
unsigned m_start;
|
unsigned m_start;
|
||||||
unsigned m_length;
|
unsigned m_length;
|
||||||
void init(AstNode* fromp) {
|
void init(AstNode* fromp) {
|
||||||
if (fromp && fromp->dtypep()->castArrayDType()) {
|
if (fromp && fromp->dtypep()->castNodeArrayDType()) {
|
||||||
// Strip off array to find what array references
|
// Strip off array to find what array references
|
||||||
dtypeFrom(fromp->dtypep()->castArrayDType()->subDTypep());
|
dtypeFrom(fromp->dtypep()->castNodeArrayDType()->subDTypep());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
public:
|
public:
|
||||||
@@ -658,7 +665,6 @@ public:
|
|||||||
void start(unsigned start) { m_start = start; }
|
void start(unsigned start) { m_start = start; }
|
||||||
unsigned start() const { return m_start; }
|
unsigned start() const { return m_start; }
|
||||||
// Special operators
|
// Special operators
|
||||||
static int dimension(AstNode* nodep); ///< How many dimensions is this reference from the base variable?
|
|
||||||
static AstNode* baseFromp(AstNode* nodep); ///< What is the base variable (or const) this dereferences?
|
static AstNode* baseFromp(AstNode* nodep); ///< What is the base variable (or const) this dereferences?
|
||||||
virtual void dump(ostream& str);
|
virtual void dump(ostream& str);
|
||||||
};
|
};
|
||||||
@@ -724,8 +730,15 @@ struct AstSel : public AstNodeTriop {
|
|||||||
// Multiple bit range extraction
|
// Multiple bit range extraction
|
||||||
// Parents: math|stmt
|
// Parents: math|stmt
|
||||||
// Children: varref|arraysel, math, constant math
|
// Children: varref|arraysel, math, constant math
|
||||||
|
// Tempting to have an lvalue() style method here as LHS selects are quite
|
||||||
|
// different, but that doesn't play well with V3Inst and bidirects which don't know direction
|
||||||
|
private:
|
||||||
|
VNumRange m_declRange; // Range of the 'from' array if isRanged() is set, else invalid
|
||||||
|
int m_declElWidth; // If a packed array, the number of bits per element
|
||||||
|
public:
|
||||||
AstSel(FileLine* fl, AstNode* fromp, AstNode* lsbp, AstNode* widthp)
|
AstSel(FileLine* fl, AstNode* fromp, AstNode* lsbp, AstNode* widthp)
|
||||||
:AstNodeTriop(fl, fromp, lsbp, widthp) {
|
:AstNodeTriop(fl, fromp, lsbp, widthp) {
|
||||||
|
m_declElWidth = 1;
|
||||||
if (widthp->castConst()) {
|
if (widthp->castConst()) {
|
||||||
dtypeSetLogicSized(widthp->castConst()->toUInt(),
|
dtypeSetLogicSized(widthp->castConst()->toUInt(),
|
||||||
widthp->castConst()->toUInt(),
|
widthp->castConst()->toUInt(),
|
||||||
@@ -735,9 +748,11 @@ struct AstSel : public AstNodeTriop {
|
|||||||
AstSel(FileLine* fl, AstNode* fromp, int lsb, int bitwidth)
|
AstSel(FileLine* fl, AstNode* fromp, int lsb, int bitwidth)
|
||||||
:AstNodeTriop(fl, fromp,
|
:AstNodeTriop(fl, fromp,
|
||||||
new AstConst(fl,lsb), new AstConst(fl,bitwidth)) {
|
new AstConst(fl,lsb), new AstConst(fl,bitwidth)) {
|
||||||
|
m_declElWidth = 1;
|
||||||
dtypeSetLogicSized(bitwidth,bitwidth,AstNumeric::UNSIGNED);
|
dtypeSetLogicSized(bitwidth,bitwidth,AstNumeric::UNSIGNED);
|
||||||
}
|
}
|
||||||
ASTNODE_NODE_FUNCS(Sel, SEL)
|
ASTNODE_NODE_FUNCS(Sel, SEL)
|
||||||
|
virtual void dump(ostream& str);
|
||||||
virtual void numberOperate(V3Number& out, const V3Number& from, const V3Number& bit, const V3Number& width) {
|
virtual void numberOperate(V3Number& out, const V3Number& from, const V3Number& bit, const V3Number& width) {
|
||||||
out.opSel(from, bit.toUInt()+width.toUInt()-1, bit.toUInt()); }
|
out.opSel(from, bit.toUInt()+width.toUInt()-1, bit.toUInt()); }
|
||||||
virtual string emitVerilog() { V3ERROR_NA; return ""; } // Implemented specially
|
virtual string emitVerilog() { V3ERROR_NA; return ""; } // Implemented specially
|
||||||
@@ -759,6 +774,10 @@ struct AstSel : public AstNodeTriop {
|
|||||||
int widthConst() const { return widthp()->castConst()->toSInt(); }
|
int widthConst() const { return widthp()->castConst()->toSInt(); }
|
||||||
int lsbConst() const { return lsbp()->castConst()->toSInt(); }
|
int lsbConst() const { return lsbp()->castConst()->toSInt(); }
|
||||||
int msbConst() const { return lsbConst()+widthConst()-1; }
|
int msbConst() const { return lsbConst()+widthConst()-1; }
|
||||||
|
VNumRange& declRange() { return m_declRange; }
|
||||||
|
void declRange(const VNumRange& flag) { m_declRange = flag; }
|
||||||
|
int declElWidth() const { return m_declElWidth; }
|
||||||
|
void declElWidth(int flag) { m_declElWidth = flag; }
|
||||||
};
|
};
|
||||||
|
|
||||||
struct AstMemberSel : public AstNodeMath {
|
struct AstMemberSel : public AstNodeMath {
|
||||||
@@ -1279,7 +1298,7 @@ private:
|
|||||||
string m_name; // Cell name
|
string m_name; // Cell name
|
||||||
string m_origName; // Original name before dot addition
|
string m_origName; // Original name before dot addition
|
||||||
string m_modName; // Module the cell instances
|
string m_modName; // Module the cell instances
|
||||||
AstNodeModule* m_modp; // [AfterLink] Pointer to module instanced
|
AstNodeModule* m_modp; // [AfterLink] Pointer to module instanced
|
||||||
public:
|
public:
|
||||||
AstCell(FileLine* fl, const string& instName, const string& modName,
|
AstCell(FileLine* fl, const string& instName, const string& modName,
|
||||||
AstPin* pinsp, AstPin* paramsp, AstRange* rangep)
|
AstPin* pinsp, AstPin* paramsp, AstRange* rangep)
|
||||||
@@ -1327,6 +1346,25 @@ public:
|
|||||||
virtual void name(const string& name) { m_name = name; }
|
virtual void name(const string& name) { m_name = name; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct AstBind : public AstNode {
|
||||||
|
// Parents: MODULE
|
||||||
|
// Children: CELL
|
||||||
|
private:
|
||||||
|
string m_name; // Binding to name
|
||||||
|
public:
|
||||||
|
AstBind(FileLine* fl, const string& name, AstNode* cellsp)
|
||||||
|
: AstNode(fl)
|
||||||
|
, m_name(name) {
|
||||||
|
if (!cellsp->castCell()) cellsp->v3fatalSrc("Only cells allowed to be bound");
|
||||||
|
addNOp1p(cellsp);
|
||||||
|
}
|
||||||
|
ASTNODE_NODE_FUNCS(Bind, BIND)
|
||||||
|
// ACCESSORS
|
||||||
|
virtual string name() const { return m_name; } // * = Bind Target name
|
||||||
|
virtual void name(const string& name) { m_name = name; }
|
||||||
|
AstNode* cellsp() const { return op1p(); } // op1= cells
|
||||||
|
};
|
||||||
|
|
||||||
struct AstPort : public AstNode {
|
struct AstPort : public AstNode {
|
||||||
// A port (in/out/inout) on a module
|
// A port (in/out/inout) on a module
|
||||||
private:
|
private:
|
||||||
@@ -2519,6 +2557,33 @@ struct AstFinal : public AstNode {
|
|||||||
AstNode* bodysp() const { return op1p()->castNode(); } // op1 = Expressions to evaluate
|
AstNode* bodysp() const { return op1p()->castNode(); } // op1 = Expressions to evaluate
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct AstInside : public AstNodeMath {
|
||||||
|
AstInside(FileLine* fl, AstNode* exprp, AstNode* itemsp)
|
||||||
|
: AstNodeMath(fl) {
|
||||||
|
addOp1p(exprp); addOp2p(itemsp);
|
||||||
|
dtypeSetLogicBool();
|
||||||
|
}
|
||||||
|
ASTNODE_NODE_FUNCS(Inside, INSIDE)
|
||||||
|
AstNode* exprp() const { return op1p()->castNode(); } // op1 = LHS expression to compare with
|
||||||
|
AstNode* itemsp() const { return op2p()->castNode(); } // op2 = RHS, possibly a list of expr or AstInsideRange
|
||||||
|
virtual string emitVerilog() { return "%l inside { %r }"; }
|
||||||
|
virtual string emitC() { V3ERROR_NA; return ""; }
|
||||||
|
virtual bool cleanOut() { return false; } // NA
|
||||||
|
};
|
||||||
|
|
||||||
|
struct AstInsideRange : public AstNodeMath {
|
||||||
|
AstInsideRange(FileLine* fl, AstNode* lhsp, AstNode* rhsp)
|
||||||
|
: AstNodeMath(fl) {
|
||||||
|
addOp1p(lhsp); addOp2p(rhsp);
|
||||||
|
}
|
||||||
|
ASTNODE_NODE_FUNCS(InsideRange, INSIDERANGE)
|
||||||
|
AstNode* lhsp() const { return op1p()->castNode(); } // op1 = LHS
|
||||||
|
AstNode* rhsp() const { return op2p()->castNode(); } // op2 = RHS
|
||||||
|
virtual string emitVerilog() { return "[%l:%r]"; }
|
||||||
|
virtual string emitC() { V3ERROR_NA; return ""; }
|
||||||
|
virtual bool cleanOut() { return false; } // NA
|
||||||
|
};
|
||||||
|
|
||||||
struct AstInitArray : public AstNode {
|
struct AstInitArray : public AstNode {
|
||||||
// Set a var to a large list of values
|
// Set a var to a large list of values
|
||||||
// The values must be in sorted order, and not exceed the size of the var's array.
|
// The values must be in sorted order, and not exceed the size of the var's array.
|
||||||
@@ -2600,11 +2665,11 @@ public:
|
|||||||
, m_showname(showname) {
|
, m_showname(showname) {
|
||||||
dtypeFrom(varp);
|
dtypeFrom(varp);
|
||||||
m_code = 0;
|
m_code = 0;
|
||||||
m_codeInc = varp->dtypep()->arrayElements() * varp->dtypep()->widthWords();
|
m_codeInc = varp->dtypep()->arrayUnpackedElements() * varp->dtypep()->widthWords();
|
||||||
AstBasicDType* bdtypep = varp->basicp();
|
AstBasicDType* bdtypep = varp->basicp();
|
||||||
m_left = bdtypep ? bdtypep->left() : 0;
|
m_left = bdtypep ? bdtypep->left() : 0;
|
||||||
m_right = bdtypep ? bdtypep->right() : 0;
|
m_right = bdtypep ? bdtypep->right() : 0;
|
||||||
if (AstArrayDType* adtypep = varp->dtypeSkipRefp()->castArrayDType()) {
|
if (AstUnpackArrayDType* adtypep = varp->dtypeSkipRefp()->castUnpackArrayDType()) {
|
||||||
m_arrayLsb = adtypep->lsb();
|
m_arrayLsb = adtypep->lsb();
|
||||||
m_arrayMsb = adtypep->msb();
|
m_arrayMsb = adtypep->msb();
|
||||||
} else {
|
} else {
|
||||||
@@ -2708,12 +2773,14 @@ private:
|
|||||||
// Return a value of a attribute, for example a LSB or array LSB of a signal
|
// Return a value of a attribute, for example a LSB or array LSB of a signal
|
||||||
AstAttrType m_attrType; // What sort of extraction
|
AstAttrType m_attrType; // What sort of extraction
|
||||||
public:
|
public:
|
||||||
AstAttrOf(FileLine* fl, AstAttrType attrtype, AstNode* fromp=NULL)
|
AstAttrOf(FileLine* fl, AstAttrType attrtype, AstNode* fromp=NULL, AstNode* dimp=NULL)
|
||||||
: AstNode(fl) {
|
: AstNode(fl) {
|
||||||
setNOp1p(fromp);
|
setNOp1p(fromp);
|
||||||
|
setNOp2p(dimp);
|
||||||
m_attrType = attrtype; }
|
m_attrType = attrtype; }
|
||||||
ASTNODE_NODE_FUNCS(AttrOf, ATTROF)
|
ASTNODE_NODE_FUNCS(AttrOf, ATTROF)
|
||||||
AstNode* fromp() const { return op1p(); }
|
AstNode* fromp() const { return op1p(); }
|
||||||
|
AstNode* dimp() const { return op2p(); }
|
||||||
AstAttrType attrType() const { return m_attrType; }
|
AstAttrType attrType() const { return m_attrType; }
|
||||||
virtual void dump(ostream& str=cout);
|
virtual void dump(ostream& str=cout);
|
||||||
};
|
};
|
||||||
@@ -4459,6 +4526,8 @@ public:
|
|||||||
AstBasicDType* findBasicDType(FileLine* fl, AstBasicDTypeKwd kwd);
|
AstBasicDType* findBasicDType(FileLine* fl, AstBasicDTypeKwd kwd);
|
||||||
AstBasicDType* findLogicBitDType(FileLine* fl, AstBasicDTypeKwd kwd,
|
AstBasicDType* findLogicBitDType(FileLine* fl, AstBasicDTypeKwd kwd,
|
||||||
int width, int widthMin, AstNumeric numeric);
|
int width, int widthMin, AstNumeric numeric);
|
||||||
|
AstBasicDType* findLogicBitDType(FileLine* fl, AstBasicDTypeKwd kwd,
|
||||||
|
VNumRange range, int widthMin, AstNumeric numeric);
|
||||||
AstBasicDType* findInsertSameDType(AstBasicDType* nodep);
|
AstBasicDType* findInsertSameDType(AstBasicDType* nodep);
|
||||||
void clearCache();
|
void clearCache();
|
||||||
void repairCache();
|
void repairCache();
|
||||||
@@ -4474,11 +4543,14 @@ struct AstNetlist : public AstNode {
|
|||||||
// Children: MODULEs & CFILEs
|
// Children: MODULEs & CFILEs
|
||||||
private:
|
private:
|
||||||
AstTypeTable* m_typeTablep; // Reference to top type table, for faster lookup
|
AstTypeTable* m_typeTablep; // Reference to top type table, for faster lookup
|
||||||
|
AstPackage* m_dollarUnitPkgp;
|
||||||
public:
|
public:
|
||||||
AstNetlist() : AstNode(new FileLine("AstRoot",0)) {
|
AstNetlist() : AstNode(new FileLine("AstRoot",0)) {
|
||||||
m_typeTablep = NULL;
|
m_typeTablep = NULL;
|
||||||
|
m_dollarUnitPkgp = NULL;
|
||||||
}
|
}
|
||||||
ASTNODE_NODE_FUNCS(Netlist, NETLIST)
|
ASTNODE_NODE_FUNCS(Netlist, NETLIST)
|
||||||
|
virtual bool broken() const { return (m_dollarUnitPkgp && !m_dollarUnitPkgp->brokeExists()); }
|
||||||
AstNodeModule* modulesp() const { return op1p()->castNodeModule();} // op1 = List of modules
|
AstNodeModule* modulesp() const { return op1p()->castNodeModule();} // op1 = List of modules
|
||||||
AstNodeModule* topModulep() const { return op1p()->castNodeModule(); } // * = Top module in hierarchy (first one added, for now)
|
AstNodeModule* topModulep() const { return op1p()->castNodeModule(); } // * = Top module in hierarchy (first one added, for now)
|
||||||
void addModulep(AstNodeModule* modulep) { addOp1p(modulep); }
|
void addModulep(AstNodeModule* modulep) { addOp1p(modulep); }
|
||||||
@@ -4488,6 +4560,16 @@ public:
|
|||||||
void addMiscsp(AstNode* nodep) { addOp3p(nodep); }
|
void addMiscsp(AstNode* nodep) { addOp3p(nodep); }
|
||||||
AstTypeTable* typeTablep() { return m_typeTablep; }
|
AstTypeTable* typeTablep() { return m_typeTablep; }
|
||||||
void addTypeTablep(AstTypeTable* nodep) { m_typeTablep = nodep; addMiscsp(nodep); }
|
void addTypeTablep(AstTypeTable* nodep) { m_typeTablep = nodep; addMiscsp(nodep); }
|
||||||
|
AstPackage* dollarUnitPkgp() const { return m_dollarUnitPkgp; }
|
||||||
|
AstPackage* dollarUnitPkgAddp() {
|
||||||
|
if (!m_dollarUnitPkgp) {
|
||||||
|
m_dollarUnitPkgp = new AstPackage(fileline(), AstPackage::dollarUnitName());
|
||||||
|
m_dollarUnitPkgp->inLibrary(true); // packages are always libraries; don't want to make them a "top"
|
||||||
|
m_dollarUnitPkgp->modTrace(false); // may reconsider later
|
||||||
|
m_dollarUnitPkgp->internal(true);
|
||||||
|
addModulep(m_dollarUnitPkgp);
|
||||||
|
}
|
||||||
|
return m_dollarUnitPkgp; }
|
||||||
};
|
};
|
||||||
|
|
||||||
//######################################################################
|
//######################################################################
|
||||||
|
|||||||
+1
-1
@@ -153,7 +153,7 @@ private:
|
|||||||
AstNode* addsp = NULL;
|
AstNode* addsp = NULL;
|
||||||
if (AstNode* stmtsp = nodep->stmtsp()) {
|
if (AstNode* stmtsp = nodep->stmtsp()) {
|
||||||
stmtsp->unlinkFrBackWithNext();
|
stmtsp->unlinkFrBackWithNext();
|
||||||
addsp = addsp->addNextNull(stmtsp);
|
if (addsp) { addsp = addsp->addNextNull(stmtsp); } else { addsp = stmtsp; }
|
||||||
}
|
}
|
||||||
if (addsp) {
|
if (addsp) {
|
||||||
nodep->replaceWith(addsp);
|
nodep->replaceWith(addsp);
|
||||||
|
|||||||
+1
-1
@@ -86,7 +86,7 @@ private:
|
|||||||
#endif
|
#endif
|
||||||
AstVar* varp = vscp->varp();
|
AstVar* varp = vscp->varp();
|
||||||
vscp->v3warn(IMPERFECTSCH,"Imperfect scheduling of variable: "<<vscp);
|
vscp->v3warn(IMPERFECTSCH,"Imperfect scheduling of variable: "<<vscp);
|
||||||
AstArrayDType* arrayp = varp->dtypeSkipRefp()->castArrayDType();
|
AstUnpackArrayDType* arrayp = varp->dtypeSkipRefp()->castUnpackArrayDType();
|
||||||
bool isArray = arrayp;
|
bool isArray = arrayp;
|
||||||
int msb = isArray ? arrayp->msb() : 0;
|
int msb = isArray ? arrayp->msb() : 0;
|
||||||
int lsb = isArray ? arrayp->lsb() : 0;
|
int lsb = isArray ? arrayp->lsb() : 0;
|
||||||
|
|||||||
+34
-26
@@ -370,37 +370,40 @@ private:
|
|||||||
|
|
||||||
// Extraction checks
|
// Extraction checks
|
||||||
bool warnSelect(AstSel* nodep) {
|
bool warnSelect(AstSel* nodep) {
|
||||||
AstNode* basefromp = AstArraySel::baseFromp(nodep);
|
|
||||||
if (m_doGenerate) {
|
if (m_doGenerate) {
|
||||||
// Never checked yet
|
// Never checked yet
|
||||||
V3Width::widthParamsEdit(nodep);
|
V3Width::widthParamsEdit(nodep);
|
||||||
nodep->iterateChildren(*this); // May need "constifying"
|
nodep->iterateChildren(*this); // May need "constifying"
|
||||||
}
|
}
|
||||||
if (AstNodeVarRef* varrefp = basefromp->castNodeVarRef()) {
|
// Find range of dtype we are selecting from
|
||||||
AstVar* varp = varrefp->varp();
|
// Similar code in V3Unknown::AstSel
|
||||||
if (!varp->dtypep()) varp->v3fatalSrc("Data type lost");
|
bool doit = true;
|
||||||
AstBasicDType* bdtypep = varp->basicp(); if (!bdtypep) varp->v3fatalSrc("Select of non-selectable type");
|
if (m_warn
|
||||||
if (m_warn
|
&& nodep->lsbp()->castConst()
|
||||||
&& nodep->lsbp()->castConst()
|
&& nodep->widthp()->castConst()
|
||||||
&& nodep->widthp()->castConst()
|
&& doit) {
|
||||||
&& (!bdtypep->isRanged() || bdtypep->msb())) { // else it's non-resolvable parameterized
|
int maxDeclBit = nodep->declRange().hiMaxSelect()*nodep->declElWidth() + (nodep->declElWidth()-1);
|
||||||
if (nodep->lsbp()->castConst()->num().isFourState()
|
if (nodep->lsbp()->castConst()->num().isFourState()
|
||||||
|| nodep->widthp()->castConst()->num().isFourState()) {
|
|| nodep->widthp()->castConst()->num().isFourState()) {
|
||||||
nodep->v3error("Selection index is constantly unknown or tristated: "
|
nodep->v3error("Selection index is constantly unknown or tristated: "
|
||||||
"lsb="<<nodep->lsbp()->name()<<" width="<<nodep->widthp()->name());
|
"lsb="<<nodep->lsbp()->name()<<" width="<<nodep->widthp()->name());
|
||||||
// Replacing nodep will make a mess above, so we replace the offender
|
// Replacing nodep will make a mess above, so we replace the offender
|
||||||
replaceZero(nodep->lsbp());
|
replaceZero(nodep->lsbp());
|
||||||
}
|
}
|
||||||
else if ((nodep->msbConst() > bdtypep->msbMaxSelect())
|
else if (nodep->declRange().ranged()
|
||||||
|| (nodep->lsbConst() > bdtypep->msbMaxSelect())) {
|
&& (nodep->msbConst() > maxDeclBit
|
||||||
// See also warning in V3Width
|
|| nodep->lsbConst() > maxDeclBit)) {
|
||||||
nodep->v3warn(SELRANGE, "Selection index out of range: "
|
// See also warning in V3Width
|
||||||
<<nodep->msbConst()<<":"<<nodep->lsbConst()
|
// Must adjust by element width as declRange() is in number of elements
|
||||||
<<" outside "<<bdtypep->msbMaxSelect()<<":0"
|
nodep->v3warn(SELRANGE, "Selection index out of range: "
|
||||||
<<(bdtypep->lsb()>=0 ? ""
|
<<(nodep->msbConst()/nodep->declElWidth())
|
||||||
:" (adjusted +"+cvtToStr(-bdtypep->lsb())+" to account for negative lsb)"));
|
<<":"<<(nodep->lsbConst()/nodep->declElWidth())
|
||||||
// Don't replace with zero, we'll do it later
|
<<" outside "<<nodep->declRange().hiMaxSelect()<<":0"
|
||||||
}
|
<<(nodep->declRange().lo()>=0 ? ""
|
||||||
|
:(" (adjusted +"+cvtToStr(-nodep->declRange().lo())
|
||||||
|
+" to account for negative lsb)")));
|
||||||
|
UINFO(1," Related Raw index is "<<nodep->msbConst()<<":"<<nodep->lsbConst()<<endl);
|
||||||
|
// Don't replace with zero, we'll do it later
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false; // Not a transform, so NOP
|
return false; // Not a transform, so NOP
|
||||||
@@ -1270,6 +1273,7 @@ private:
|
|||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildren(*this);
|
||||||
if (m_doNConst
|
if (m_doNConst
|
||||||
&& (nodep->sensp()->castConst()
|
&& (nodep->sensp()->castConst()
|
||||||
|
|| nodep->sensp()->castEnumItemRef()
|
||||||
|| (nodep->varrefp() && nodep->varrefp()->varp()->isParam()))) {
|
|| (nodep->varrefp() && nodep->varrefp()->varp()->isParam()))) {
|
||||||
// Constants in sensitivity lists may be removed (we'll simplify later)
|
// Constants in sensitivity lists may be removed (we'll simplify later)
|
||||||
if (nodep->isClocked()) { // A constant can never get a pos/negexge
|
if (nodep->isClocked()) { // A constant can never get a pos/negexge
|
||||||
@@ -1298,6 +1302,9 @@ private:
|
|||||||
if (!senvarp) sensp->v3fatalSrc("Non-varref sensitivity variable");
|
if (!senvarp) sensp->v3fatalSrc("Non-varref sensitivity variable");
|
||||||
sensp->replaceWith(senvarp);
|
sensp->replaceWith(senvarp);
|
||||||
sensp->deleteTree(); sensp=NULL;
|
sensp->deleteTree(); sensp=NULL;
|
||||||
|
} else if (!m_doNConst // Deal with later when doNConst missing
|
||||||
|
&& (nodep->sensp()->castEnumItemRef()
|
||||||
|
|| nodep->sensp()->castConst())) {
|
||||||
} else {
|
} else {
|
||||||
if (nodep->hasVar() && !nodep->varrefp()) nodep->v3fatalSrc("Null sensitivity variable");
|
if (nodep->hasVar() && !nodep->varrefp()) nodep->v3fatalSrc("Null sensitivity variable");
|
||||||
}
|
}
|
||||||
@@ -1397,6 +1404,7 @@ private:
|
|||||||
for (AstNodeSenItem* nextp, * senp = nodep->sensesp()->castNodeSenItem();
|
for (AstNodeSenItem* nextp, * senp = nodep->sensesp()->castNodeSenItem();
|
||||||
senp; senp=nextp) {
|
senp; senp=nextp) {
|
||||||
nextp=senp->nextp()->castNodeSenItem();
|
nextp=senp->nextp()->castNodeSenItem();
|
||||||
|
// cppcheck-suppress unassignedVariable // cppcheck bug
|
||||||
SenItemCmp cmp;
|
SenItemCmp cmp;
|
||||||
if (nextp && !cmp(senp, nextp)) {
|
if (nextp && !cmp(senp, nextp)) {
|
||||||
// Something's out of order, sort it
|
// Something's out of order, sort it
|
||||||
|
|||||||
+2
-2
@@ -86,7 +86,7 @@ private:
|
|||||||
if (prettyName.find("._") != string::npos)
|
if (prettyName.find("._") != string::npos)
|
||||||
return "Inlined leading underscore";
|
return "Inlined leading underscore";
|
||||||
}
|
}
|
||||||
if ((nodep->width()*nodep->dtypep()->arrayElements()) > 256) return "Wide bus/array > 256 bits";
|
if ((nodep->width()*nodep->dtypep()->arrayUnpackedElements()) > 256) return "Wide bus/array > 256 bits";
|
||||||
// We allow this, though tracing doesn't
|
// We allow this, though tracing doesn't
|
||||||
// if (nodep->arrayp(1)) return "Unsupported: Multi-dimensional array";
|
// if (nodep->arrayp(1)) return "Unsupported: Multi-dimensional array";
|
||||||
return NULL;
|
return NULL;
|
||||||
@@ -209,7 +209,7 @@ private:
|
|||||||
varp, chgVarp);
|
varp, chgVarp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (AstArrayDType* adtypep = dtypep->castArrayDType()) {
|
else if (AstUnpackArrayDType* adtypep = dtypep->castUnpackArrayDType()) {
|
||||||
for (int index_docs=adtypep->lsb(); index_docs<=adtypep->msb()+1; ++index_docs) {
|
for (int index_docs=adtypep->lsb(); index_docs<=adtypep->msb()+1; ++index_docs) {
|
||||||
int index_code = index_docs - adtypep->lsb();
|
int index_code = index_docs - adtypep->lsb();
|
||||||
ToggleEnt newent (above.m_comment+string("[")+cvtToStr(index_docs)+"]",
|
ToggleEnt newent (above.m_comment+string("[")+cvtToStr(index_docs)+"]",
|
||||||
|
|||||||
+1
-1
@@ -206,7 +206,7 @@ private:
|
|||||||
AstNodeModule* nextmodp;
|
AstNodeModule* nextmodp;
|
||||||
for (AstNodeModule* modp = v3Global.rootp()->modulesp(); modp; modp=nextmodp) {
|
for (AstNodeModule* modp = v3Global.rootp()->modulesp(); modp; modp=nextmodp) {
|
||||||
nextmodp = modp->nextp()->castNodeModule();
|
nextmodp = modp->nextp()->castNodeModule();
|
||||||
if (modp->level()>2 && modp->user1()==0) {
|
if (modp->level()>2 && modp->user1()==0 && !modp->internal()) {
|
||||||
// > 2 because L1 is the wrapper, L2 is the top user module
|
// > 2 because L1 is the wrapper, L2 is the top user module
|
||||||
UINFO(4," Dead module "<<modp<<endl);
|
UINFO(4," Dead module "<<modp<<endl);
|
||||||
// And its children may now be killable too; correct counts
|
// And its children may now be killable too; correct counts
|
||||||
|
|||||||
+33
-33
@@ -321,12 +321,12 @@ public:
|
|||||||
{
|
{
|
||||||
AstVarRef* varrefp = nodep->memp()->castVarRef();
|
AstVarRef* varrefp = nodep->memp()->castVarRef();
|
||||||
if (!varrefp) { nodep->v3error("Readmem loading non-variable"); }
|
if (!varrefp) { nodep->v3error("Readmem loading non-variable"); }
|
||||||
else if (AstArrayDType* adtypep = varrefp->varp()->dtypeSkipRefp()->castArrayDType()) {
|
else if (AstUnpackArrayDType* adtypep = varrefp->varp()->dtypeSkipRefp()->castUnpackArrayDType()) {
|
||||||
puts(cvtToStr(varrefp->varp()->dtypep()->arrayElements()));
|
puts(cvtToStr(varrefp->varp()->dtypep()->arrayUnpackedElements()));
|
||||||
array_lsb = adtypep->lsb();
|
array_lsb = adtypep->lsb();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
nodep->v3error("Readmem loading non-arrayed variable");
|
nodep->v3error("Readmem loading other than unpacked-array variable");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
putbs(", ");
|
putbs(", ");
|
||||||
@@ -889,8 +889,8 @@ void EmitCStmts::emitVarDecl(AstVar* nodep, const string& prefixIfImp) {
|
|||||||
}
|
}
|
||||||
puts(nodep->name());
|
puts(nodep->name());
|
||||||
if (isArray) {
|
if (isArray) {
|
||||||
for (AstArrayDType* arrayp=nodep->dtypeSkipRefp()->castArrayDType(); arrayp;
|
for (AstUnpackArrayDType* arrayp=nodep->dtypeSkipRefp()->castUnpackArrayDType(); arrayp;
|
||||||
arrayp = arrayp->subDTypep()->skipRefp()->castArrayDType()) {
|
arrayp = arrayp->subDTypep()->skipRefp()->castUnpackArrayDType()) {
|
||||||
puts("["+cvtToStr(arrayp->elementsConst())+"]");
|
puts("["+cvtToStr(arrayp->elementsConst())+"]");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -910,8 +910,8 @@ void EmitCStmts::emitVarDecl(AstVar* nodep, const string& prefixIfImp) {
|
|||||||
if (isArray) {
|
if (isArray) {
|
||||||
if (nodep->isWide()) puts("W");
|
if (nodep->isWide()) puts("W");
|
||||||
puts("("+nodep->name());
|
puts("("+nodep->name());
|
||||||
for (AstArrayDType* arrayp=nodep->dtypeSkipRefp()->castArrayDType(); arrayp;
|
for (AstUnpackArrayDType* arrayp=nodep->dtypeSkipRefp()->castUnpackArrayDType(); arrayp;
|
||||||
arrayp = arrayp->subDTypep()->skipRefp()->castArrayDType()) {
|
arrayp = arrayp->subDTypep()->skipRefp()->castUnpackArrayDType()) {
|
||||||
puts("["+cvtToStr(arrayp->elementsConst())+"]");
|
puts("["+cvtToStr(arrayp->elementsConst())+"]");
|
||||||
}
|
}
|
||||||
puts(","+cvtToStr(basicp->msb())+","+cvtToStr(basicp->lsb()));
|
puts(","+cvtToStr(basicp->msb())+","+cvtToStr(basicp->lsb()));
|
||||||
@@ -932,8 +932,8 @@ void EmitCStmts::emitVarDecl(AstVar* nodep, const string& prefixIfImp) {
|
|||||||
// strings and other fundamental c types
|
// strings and other fundamental c types
|
||||||
puts(nodep->vlArgType(true,false));
|
puts(nodep->vlArgType(true,false));
|
||||||
// This isn't very robust and may need cleanup for other data types
|
// This isn't very robust and may need cleanup for other data types
|
||||||
for (AstArrayDType* arrayp=nodep->dtypeSkipRefp()->castArrayDType(); arrayp;
|
for (AstUnpackArrayDType* arrayp=nodep->dtypeSkipRefp()->castUnpackArrayDType(); arrayp;
|
||||||
arrayp = arrayp->subDTypep()->skipRefp()->castArrayDType()) {
|
arrayp = arrayp->subDTypep()->skipRefp()->castUnpackArrayDType()) {
|
||||||
puts("["+cvtToStr(arrayp->elementsConst())+"]");
|
puts("["+cvtToStr(arrayp->elementsConst())+"]");
|
||||||
}
|
}
|
||||||
puts(";\n");
|
puts(";\n");
|
||||||
@@ -958,12 +958,13 @@ void EmitCStmts::emitVarDecl(AstVar* nodep, const string& prefixIfImp) {
|
|||||||
if (prefixIfImp!="") { puts(prefixIfImp); puts("::"); }
|
if (prefixIfImp!="") { puts(prefixIfImp); puts("::"); }
|
||||||
puts(nodep->name());
|
puts(nodep->name());
|
||||||
// This isn't very robust and may need cleanup for other data types
|
// This isn't very robust and may need cleanup for other data types
|
||||||
for (AstArrayDType* arrayp=nodep->dtypeSkipRefp()->castArrayDType(); arrayp;
|
for (AstUnpackArrayDType* arrayp=nodep->dtypeSkipRefp()->castUnpackArrayDType(); arrayp;
|
||||||
arrayp = arrayp->subDTypep()->skipRefp()->castArrayDType()) {
|
arrayp = arrayp->subDTypep()->skipRefp()->castUnpackArrayDType()) {
|
||||||
puts("["+cvtToStr(arrayp->elementsConst())+"]");
|
puts("["+cvtToStr(arrayp->elementsConst())+"]");
|
||||||
}
|
}
|
||||||
puts(","+cvtToStr(basicp->msb())+","+cvtToStr(basicp->lsb()));
|
// If it's a packed struct/array then nodep->width is the whole thing, msb/lsb is just lowest dimension
|
||||||
if (basicp->isWide()) puts(","+cvtToStr(basicp->widthWords()));
|
puts(","+cvtToStr(basicp->lsb()+nodep->width())+","+cvtToStr(basicp->lsb()));
|
||||||
|
if (nodep->isWide()) puts(","+cvtToStr(nodep->widthWords()));
|
||||||
puts(");\n");
|
puts(");\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1328,7 +1329,7 @@ void EmitCImp::emitVarResets(AstNodeModule* modp) {
|
|||||||
}
|
}
|
||||||
else if (AstInitArray* initarp = varp->valuep()->castInitArray()) {
|
else if (AstInitArray* initarp = varp->valuep()->castInitArray()) {
|
||||||
AstConst* constsp = initarp->initsp()->castConst();
|
AstConst* constsp = initarp->initsp()->castConst();
|
||||||
if (AstArrayDType* arrayp = varp->dtypeSkipRefp()->castArrayDType()) {
|
if (AstUnpackArrayDType* arrayp = varp->dtypeSkipRefp()->castUnpackArrayDType()) {
|
||||||
for (int i=0; i<arrayp->elementsConst(); i++) {
|
for (int i=0; i<arrayp->elementsConst(); i++) {
|
||||||
if (!constsp) initarp->v3fatalSrc("Not enough values in array initalizement");
|
if (!constsp) initarp->v3fatalSrc("Not enough values in array initalizement");
|
||||||
emitSetVarConstant(varp->name()+"["+cvtToStr(i)+"]", constsp);
|
emitSetVarConstant(varp->name()+"["+cvtToStr(i)+"]", constsp);
|
||||||
@@ -1341,8 +1342,8 @@ void EmitCImp::emitVarResets(AstNodeModule* modp) {
|
|||||||
else {
|
else {
|
||||||
int vects = 0;
|
int vects = 0;
|
||||||
// This isn't very robust and may need cleanup for other data types
|
// This isn't very robust and may need cleanup for other data types
|
||||||
for (AstArrayDType* arrayp=varp->dtypeSkipRefp()->castArrayDType(); arrayp;
|
for (AstUnpackArrayDType* arrayp=varp->dtypeSkipRefp()->castUnpackArrayDType(); arrayp;
|
||||||
arrayp = arrayp->subDTypep()->skipRefp()->castArrayDType()) {
|
arrayp = arrayp->subDTypep()->skipRefp()->castUnpackArrayDType()) {
|
||||||
int vecnum = vects++;
|
int vecnum = vects++;
|
||||||
if (arrayp->msb() < arrayp->lsb()) varp->v3fatalSrc("Should have swapped msb & lsb earlier.");
|
if (arrayp->msb() < arrayp->lsb()) varp->v3fatalSrc("Should have swapped msb & lsb earlier.");
|
||||||
string ivar = string("__Vi")+cvtToStr(vecnum);
|
string ivar = string("__Vi")+cvtToStr(vecnum);
|
||||||
@@ -1367,17 +1368,16 @@ void EmitCImp::emitVarResets(AstNodeModule* modp) {
|
|||||||
} else {
|
} else {
|
||||||
puts(varp->name());
|
puts(varp->name());
|
||||||
for (int v=0; v<vects; ++v) puts( "[__Vi"+cvtToStr(v)+"]");
|
for (int v=0; v<vects; ++v) puts( "[__Vi"+cvtToStr(v)+"]");
|
||||||
if (zeroit) {
|
// If --x-initial-edge is set, we want to force an initial
|
||||||
// We want to force an initial edge on uninitialized clocks (from 'X' to
|
// edge on uninitialized clocks (from 'X' to whatever the
|
||||||
// whatever the first value is). Since the class is instantiated before
|
// first value is). Since the class is instantiated before
|
||||||
// initial blocks are evaluated, this should not clash with any initial
|
// initial blocks are evaluated, this should not clash
|
||||||
// block settings. Clocks are always BIT datatypes, so zeroit is true.
|
// with any initial block settings.
|
||||||
if (v3Global.opt.xInitialEdge()
|
if (zeroit || (v3Global.opt.xInitialEdge() && varp->isUsedClock())) {
|
||||||
&& (0 == varp->name().find("__Vclklast__"))) {
|
puts(" = 0;\n");
|
||||||
puts(" = 1;\n");
|
} else if (v3Global.opt.xInitialEdge()
|
||||||
} else {
|
&& (0 == varp->name().find("__Vclklast__"))) {
|
||||||
puts(" = 0;\n");
|
puts(" = 1;\n");
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
puts(" = VL_RAND_RESET_");
|
puts(" = VL_RAND_RESET_");
|
||||||
emitIQW(varp);
|
emitIQW(varp);
|
||||||
@@ -1508,8 +1508,8 @@ void EmitCImp::emitSavableImp(AstNodeModule* modp) {
|
|||||||
else {
|
else {
|
||||||
int vects = 0;
|
int vects = 0;
|
||||||
// This isn't very robust and may need cleanup for other data types
|
// This isn't very robust and may need cleanup for other data types
|
||||||
for (AstArrayDType* arrayp=varp->dtypeSkipRefp()->castArrayDType(); arrayp;
|
for (AstUnpackArrayDType* arrayp=varp->dtypeSkipRefp()->castUnpackArrayDType(); arrayp;
|
||||||
arrayp = arrayp->subDTypep()->skipRefp()->castArrayDType()) {
|
arrayp = arrayp->subDTypep()->skipRefp()->castUnpackArrayDType()) {
|
||||||
int vecnum = vects++;
|
int vecnum = vects++;
|
||||||
if (arrayp->msb() < arrayp->lsb()) varp->v3fatalSrc("Should have swapped msb & lsb earlier.");
|
if (arrayp->msb() < arrayp->lsb()) varp->v3fatalSrc("Should have swapped msb & lsb earlier.");
|
||||||
string ivar = string("__Vi")+cvtToStr(vecnum);
|
string ivar = string("__Vi")+cvtToStr(vecnum);
|
||||||
@@ -1599,8 +1599,8 @@ void EmitCImp::emitSensitives() {
|
|||||||
if (varp->isInput() && (varp->isScSensitive() || varp->isUsedClock())) {
|
if (varp->isInput() && (varp->isScSensitive() || varp->isUsedClock())) {
|
||||||
int vects = 0;
|
int vects = 0;
|
||||||
// This isn't very robust and may need cleanup for other data types
|
// This isn't very robust and may need cleanup for other data types
|
||||||
for (AstArrayDType* arrayp=varp->dtypeSkipRefp()->castArrayDType(); arrayp;
|
for (AstUnpackArrayDType* arrayp=varp->dtypeSkipRefp()->castUnpackArrayDType(); arrayp;
|
||||||
arrayp = arrayp->subDTypep()->skipRefp()->castArrayDType()) {
|
arrayp = arrayp->subDTypep()->skipRefp()->castUnpackArrayDType()) {
|
||||||
int vecnum = vects++;
|
int vecnum = vects++;
|
||||||
if (arrayp->msb() < arrayp->lsb()) varp->v3fatalSrc("Should have swapped msb & lsb earlier.");
|
if (arrayp->msb() < arrayp->lsb()) varp->v3fatalSrc("Should have swapped msb & lsb earlier.");
|
||||||
string ivar = string("__Vi")+cvtToStr(vecnum);
|
string ivar = string("__Vi")+cvtToStr(vecnum);
|
||||||
@@ -1697,7 +1697,7 @@ void EmitCStmts::emitVarList(AstNode* firstp, EisWhich which, const string& pref
|
|||||||
int sigbytes = varp->dtypeSkipRefp()->widthAlignBytes();
|
int sigbytes = varp->dtypeSkipRefp()->widthAlignBytes();
|
||||||
int sortbytes = sortmax-1;
|
int sortbytes = sortmax-1;
|
||||||
if (varp->isUsedClock() && varp->widthMin()==1) sortbytes = 0;
|
if (varp->isUsedClock() && varp->widthMin()==1) sortbytes = 0;
|
||||||
else if (varp->dtypeSkipRefp()->castArrayDType()) sortbytes=8;
|
else if (varp->dtypeSkipRefp()->castUnpackArrayDType()) sortbytes=8;
|
||||||
else if (varp->basicp() && varp->basicp()->isOpaque()) sortbytes=7;
|
else if (varp->basicp() && varp->basicp()->isOpaque()) sortbytes=7;
|
||||||
else if (varp->isScBv()) sortbytes=6;
|
else if (varp->isScBv()) sortbytes=6;
|
||||||
else if (sigbytes==8) sortbytes=5;
|
else if (sigbytes==8) sortbytes=5;
|
||||||
@@ -2234,7 +2234,7 @@ class EmitCTrace : EmitCStmts {
|
|||||||
if (emitTraceIsScBv(nodep)) puts("VL_SC_BV_DATAP(");
|
if (emitTraceIsScBv(nodep)) puts("VL_SC_BV_DATAP(");
|
||||||
varrefp->iterate(*this); // Put var name out
|
varrefp->iterate(*this); // Put var name out
|
||||||
// Tracing only supports 1D arrays
|
// Tracing only supports 1D arrays
|
||||||
if (varp->dtypeSkipRefp()->castArrayDType()) {
|
if (varp->dtypeSkipRefp()->castUnpackArrayDType()) {
|
||||||
if (arrayindex==-2) puts("[i]");
|
if (arrayindex==-2) puts("[i]");
|
||||||
else if (arrayindex==-1) puts("[0]");
|
else if (arrayindex==-1) puts("[0]");
|
||||||
else puts("["+cvtToStr(arrayindex)+"]");
|
else puts("["+cvtToStr(arrayindex)+"]");
|
||||||
|
|||||||
+8
-7
@@ -454,29 +454,30 @@ void EmitCSyms::emitSymImp() {
|
|||||||
AstScope* scopep = it->second.m_scopep;
|
AstScope* scopep = it->second.m_scopep;
|
||||||
AstVar* varp = it->second.m_varp;
|
AstVar* varp = it->second.m_varp;
|
||||||
//
|
//
|
||||||
int dim=0;
|
int pdim=0;
|
||||||
|
int udim=0;
|
||||||
string bounds;
|
string bounds;
|
||||||
if (AstBasicDType* basicp = varp->basicp()) {
|
if (AstBasicDType* basicp = varp->basicp()) {
|
||||||
// Range is always first, it's not in "C" order
|
// Range is always first, it's not in "C" order
|
||||||
if (basicp->isRanged()) {
|
if (basicp->isRanged()) {
|
||||||
bounds += " ,"; bounds += cvtToStr(basicp->msb());
|
bounds += " ,"; bounds += cvtToStr(basicp->msb());
|
||||||
bounds += ","; bounds += cvtToStr(basicp->lsb());
|
bounds += ","; bounds += cvtToStr(basicp->lsb());
|
||||||
dim++;
|
pdim++;
|
||||||
}
|
}
|
||||||
for (AstNodeDType* dtypep=varp->dtypep(); dtypep; ) {
|
for (AstNodeDType* dtypep=varp->dtypep(); dtypep; ) {
|
||||||
dtypep = dtypep->skipRefp(); // Skip AstRefDType/AstTypedef, or return same node
|
dtypep = dtypep->skipRefp(); // Skip AstRefDType/AstTypedef, or return same node
|
||||||
if (AstArrayDType* adtypep = dtypep->castArrayDType()) {
|
if (AstNodeArrayDType* adtypep = dtypep->castNodeArrayDType()) {
|
||||||
bounds += " ,"; bounds += cvtToStr(adtypep->msb());
|
bounds += " ,"; bounds += cvtToStr(adtypep->msb());
|
||||||
bounds += ","; bounds += cvtToStr(adtypep->lsb());
|
bounds += ","; bounds += cvtToStr(adtypep->lsb());
|
||||||
dim++;
|
if (dtypep->castPackArrayDType()) pdim++; else udim++;
|
||||||
dtypep = adtypep->subDTypep();
|
dtypep = adtypep->subDTypep();
|
||||||
}
|
}
|
||||||
else break; // AstBasicDType - nothing below, 1
|
else break; // AstBasicDType - nothing below, 1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//
|
//
|
||||||
if (dim>2) {
|
if (pdim>1 || udim>1) {
|
||||||
puts("//UNSUP "); // VerilatedImp can't deal with >2d arrays
|
puts("//UNSUP "); // VerilatedImp can't deal with >2d or packed arrays
|
||||||
}
|
}
|
||||||
puts("__Vscope_"+it->second.m_scopeName+".varInsert(__Vfinal,");
|
puts("__Vscope_"+it->second.m_scopeName+".varInsert(__Vfinal,");
|
||||||
putsQuoted(it->second.m_varBasePretty);
|
putsQuoted(it->second.m_varBasePretty);
|
||||||
@@ -496,7 +497,7 @@ void EmitCSyms::emitSymImp() {
|
|||||||
if (varp->isSigUserRWPublic()) puts("|VLVF_PUB_RW");
|
if (varp->isSigUserRWPublic()) puts("|VLVF_PUB_RW");
|
||||||
else if (varp->isSigUserRdPublic()) puts("|VLVF_PUB_RD");
|
else if (varp->isSigUserRdPublic()) puts("|VLVF_PUB_RD");
|
||||||
puts(",");
|
puts(",");
|
||||||
puts(cvtToStr(dim));
|
puts(cvtToStr(pdim+udim));
|
||||||
puts(bounds);
|
puts(bounds);
|
||||||
puts(");\n");
|
puts(");\n");
|
||||||
}
|
}
|
||||||
|
|||||||
+8
-4
@@ -440,6 +440,10 @@ class EmitVBaseVisitor : public EmitCBaseVisitor {
|
|||||||
virtual void visit(AstAttrOf* nodep, AstNUser*) {
|
virtual void visit(AstAttrOf* nodep, AstNUser*) {
|
||||||
putfs(nodep,"$_ATTROF(");
|
putfs(nodep,"$_ATTROF(");
|
||||||
nodep->fromp()->iterateAndNext(*this);
|
nodep->fromp()->iterateAndNext(*this);
|
||||||
|
if (nodep->dimp()) {
|
||||||
|
putbs(",");
|
||||||
|
nodep->dimp()->iterateAndNext(*this);
|
||||||
|
}
|
||||||
puts(")");
|
puts(")");
|
||||||
}
|
}
|
||||||
virtual void visit(AstNodeCond* nodep, AstNUser*) {
|
virtual void visit(AstNodeCond* nodep, AstNUser*) {
|
||||||
@@ -495,10 +499,10 @@ class EmitVBaseVisitor : public EmitCBaseVisitor {
|
|||||||
}
|
}
|
||||||
virtual void visit(AstConstDType* nodep, AstNUser*) {
|
virtual void visit(AstConstDType* nodep, AstNUser*) {
|
||||||
putfs(nodep,"const ");
|
putfs(nodep,"const ");
|
||||||
nodep->subDTypep()->iterateAndNext(*this);
|
nodep->subDTypep()->accept(*this);
|
||||||
}
|
}
|
||||||
virtual void visit(AstArrayDType* nodep, AstNUser*) {
|
virtual void visit(AstNodeArrayDType* nodep, AstNUser*) {
|
||||||
nodep->subDTypep()->iterateAndNext(*this);
|
nodep->subDTypep()->accept(*this);
|
||||||
nodep->rangep()->iterateAndNext(*this);
|
nodep->rangep()->iterateAndNext(*this);
|
||||||
}
|
}
|
||||||
virtual void visit(AstNodeClassDType* nodep, AstNUser*) {
|
virtual void visit(AstNodeClassDType* nodep, AstNUser*) {
|
||||||
@@ -509,7 +513,7 @@ class EmitVBaseVisitor : public EmitCBaseVisitor {
|
|||||||
puts("}");
|
puts("}");
|
||||||
}
|
}
|
||||||
virtual void visit(AstMemberDType* nodep, AstNUser*) {
|
virtual void visit(AstMemberDType* nodep, AstNUser*) {
|
||||||
nodep->subDTypep()->iterateAndNext(*this);
|
nodep->subDTypep()->accept(*this);
|
||||||
puts(" ");
|
puts(" ");
|
||||||
puts(nodep->name());
|
puts(nodep->name());
|
||||||
puts("}");
|
puts("}");
|
||||||
|
|||||||
+1
-1
@@ -294,7 +294,7 @@ protected:
|
|||||||
int nameToNumber(const string& filename);
|
int nameToNumber(const string& filename);
|
||||||
const string numberToName(int filenameno) const { return m_names[filenameno]; }
|
const string numberToName(int filenameno) const { return m_names[filenameno]; }
|
||||||
const V3LangCode numberToLang(int filenameno) const { return m_languages[filenameno]; }
|
const V3LangCode numberToLang(int filenameno) const { return m_languages[filenameno]; }
|
||||||
void numberToLang(int filenameno, const V3LangCode l) { m_languages[filenameno] = l; }
|
void numberToLang(int filenameno, const V3LangCode& l) { m_languages[filenameno] = l; }
|
||||||
void clear() { m_namemap.clear(); m_names.clear(); m_languages.clear(); }
|
void clear() { m_namemap.clear(); m_names.clear(); m_languages.clear(); }
|
||||||
void fileNameNumMapDumpXml(ostream& os);
|
void fileNameNumMapDumpXml(ostream& os);
|
||||||
static const string filenameLetters(int fileno);
|
static const string filenameLetters(int fileno);
|
||||||
|
|||||||
+1
-3
@@ -162,13 +162,11 @@ inline void V3FileDependImp::writeTimes(const string& filename, const string& cm
|
|||||||
*ofp<<"# DESCR"<<"IPTION: Verilator output: Timestamp data for --skip-identical. Delete at will."<<endl;
|
*ofp<<"# DESCR"<<"IPTION: Verilator output: Timestamp data for --skip-identical. Delete at will."<<endl;
|
||||||
*ofp<<"C \""<<cmdline<<"\""<<endl;
|
*ofp<<"C \""<<cmdline<<"\""<<endl;
|
||||||
|
|
||||||
#ifndef _WIN32
|
|
||||||
sync(); // Push files so sizes look correct
|
|
||||||
#endif
|
|
||||||
for (set<DependFile>::iterator iter=m_filenameList.begin();
|
for (set<DependFile>::iterator iter=m_filenameList.begin();
|
||||||
iter!=m_filenameList.end(); ++iter) {
|
iter!=m_filenameList.end(); ++iter) {
|
||||||
// Read stats of files we create after we're done making them (execpt for this file, of course)
|
// Read stats of files we create after we're done making them (execpt for this file, of course)
|
||||||
DependFile* dfp = (DependFile*)&(*iter);
|
DependFile* dfp = (DependFile*)&(*iter);
|
||||||
|
V3Options::fileNfsFlush(dfp->filename());
|
||||||
dfp->loadStats();
|
dfp->loadStats();
|
||||||
off_t showSize = iter->size();
|
off_t showSize = iter->size();
|
||||||
if (dfp->filename() == filename) showSize=0; // We're writing it, so need to ignore it
|
if (dfp->filename() == filename) showSize=0; // We're writing it, so need to ignore it
|
||||||
|
|||||||
+1
-1
@@ -198,6 +198,7 @@ private:
|
|||||||
AstNode* exprp = nodep->exprp()->unlinkFrBack();
|
AstNode* exprp = nodep->exprp()->unlinkFrBack();
|
||||||
bool inputPin = nodep->modVarp()->isInput();
|
bool inputPin = nodep->modVarp()->isInput();
|
||||||
if (!inputPin && !exprp->castVarRef()
|
if (!inputPin && !exprp->castVarRef()
|
||||||
|
&& !exprp->castConcat() // V3Const will collapse the SEL with the one we're about to make
|
||||||
&& !exprp->castSel()) { // V3Const will collapse the SEL with the one we're about to make
|
&& !exprp->castSel()) { // V3Const will collapse the SEL with the one we're about to make
|
||||||
nodep->v3error("Unsupported: Per-bit array instantiations with output connections to non-wires.");
|
nodep->v3error("Unsupported: Per-bit array instantiations with output connections to non-wires.");
|
||||||
// Note spec allows more complicated matches such as slices and such
|
// Note spec allows more complicated matches such as slices and such
|
||||||
@@ -291,7 +292,6 @@ AstAssignW* V3Inst::pinReconnectSimple(AstPin* pinp, AstCell* cellp, AstNodeModu
|
|||||||
pinp->exprp(new AstVarRef (pinexprp->fileline(), newvarp, true));
|
pinp->exprp(new AstVarRef (pinexprp->fileline(), newvarp, true));
|
||||||
} else {
|
} else {
|
||||||
// V3 width should have range/extended to make the widths correct
|
// V3 width should have range/extended to make the widths correct
|
||||||
if (pinexprp->width() != pinVarp->width()) pinp->v3fatalSrc("Input pin width mismatch");
|
|
||||||
assignp = new AstAssignW (pinp->fileline(),
|
assignp = new AstAssignW (pinp->fileline(),
|
||||||
new AstVarRef(pinp->fileline(), newvarp, true),
|
new AstVarRef(pinp->fileline(), newvarp, true),
|
||||||
pinexprp);
|
pinexprp);
|
||||||
|
|||||||
@@ -57,6 +57,7 @@ public:
|
|||||||
return names[m_e];
|
return names[m_e];
|
||||||
};
|
};
|
||||||
static V3LangCode mostRecent() { return V3LangCode(L1800_2009); }
|
static V3LangCode mostRecent() { return V3LangCode(L1800_2009); }
|
||||||
|
bool systemVerilog() const { return m_e == L1800_2005 || m_e == L1800_2009; }
|
||||||
bool legal() const { return m_e != L_ERROR; }
|
bool legal() const { return m_e != L_ERROR; }
|
||||||
//
|
//
|
||||||
enum en m_e;
|
enum en m_e;
|
||||||
|
|||||||
+47
-17
@@ -90,6 +90,7 @@ private:
|
|||||||
// NODE STATE
|
// NODE STATE
|
||||||
// Entire netlist:
|
// Entire netlist:
|
||||||
// AstNodeModule::user1p() // V3GraphVertex* Vertex describing this module
|
// AstNodeModule::user1p() // V3GraphVertex* Vertex describing this module
|
||||||
|
// AstCell::user1() // bool Did it.
|
||||||
// Allocated across all readFiles in V3Global::readFiles:
|
// Allocated across all readFiles in V3Global::readFiles:
|
||||||
// AstNode::user4p() // VSymEnt* Package and typedef symbol names
|
// AstNode::user4p() // VSymEnt* Package and typedef symbol names
|
||||||
AstUser1InUse m_inuser1;
|
AstUser1InUse m_inuser1;
|
||||||
@@ -121,6 +122,26 @@ private:
|
|||||||
return (nodep->user1p()->castGraphVertex());
|
return (nodep->user1p()->castGraphVertex());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
AstNodeModule* resolveModule(AstNode* nodep, const string& modName) {
|
||||||
|
AstNodeModule* modp = m_mods.rootp()->findIdFallback(modName)->nodep()->castNodeModule();
|
||||||
|
if (!modp) {
|
||||||
|
// Read-subfile
|
||||||
|
// If file not found, make AstNotFoundModule, rather than error out.
|
||||||
|
// We'll throw the error when we know the module will really be needed.
|
||||||
|
V3Parse parser (v3Global.rootp(), m_filterp, m_parseSymp);
|
||||||
|
parser.parseFile(nodep->fileline(), modName, false, "");
|
||||||
|
V3Error::abortIfErrors();
|
||||||
|
// We've read new modules, grab new pointers to their names
|
||||||
|
readModNames();
|
||||||
|
// Check again
|
||||||
|
modp = m_mods.rootp()->findIdFallback(modName)->nodep()->castNodeModule();
|
||||||
|
if (!modp) {
|
||||||
|
nodep->v3error("Can't resolve module reference: "<<modName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return modp;
|
||||||
|
}
|
||||||
|
|
||||||
// VISITs
|
// VISITs
|
||||||
virtual void visit(AstNetlist* nodep, AstNUser*) {
|
virtual void visit(AstNetlist* nodep, AstNUser*) {
|
||||||
AstNode::user1ClearTree();
|
AstNode::user1ClearTree();
|
||||||
@@ -158,7 +179,8 @@ private:
|
|||||||
m_modp = nodep;
|
m_modp = nodep;
|
||||||
UINFO(2,"Link Module: "<<nodep<<endl);
|
UINFO(2,"Link Module: "<<nodep<<endl);
|
||||||
if (nodep->fileline()->filebasenameNoExt() != nodep->prettyName()
|
if (nodep->fileline()->filebasenameNoExt() != nodep->prettyName()
|
||||||
&& !v3Global.opt.isLibraryFile(nodep->fileline()->filename())) {
|
&& !v3Global.opt.isLibraryFile(nodep->fileline()->filename())
|
||||||
|
&& !nodep->internal()) {
|
||||||
// We only complain once per file, otherwise library-like files have a huge mess of warnings
|
// We only complain once per file, otherwise library-like files have a huge mess of warnings
|
||||||
if (m_declfnWarned.find(nodep->fileline()->filename()) == m_declfnWarned.end()) {
|
if (m_declfnWarned.find(nodep->fileline()->filename()) == m_declfnWarned.end()) {
|
||||||
m_declfnWarned.insert(nodep->fileline()->filename());
|
m_declfnWarned.insert(nodep->fileline()->filename());
|
||||||
@@ -180,6 +202,7 @@ private:
|
|||||||
if (!m_libVertexp) m_libVertexp = new LibraryVertex(&m_graph);
|
if (!m_libVertexp) m_libVertexp = new LibraryVertex(&m_graph);
|
||||||
new V3GraphEdge(&m_graph, m_libVertexp, vertex(nodep), 1, false);
|
new V3GraphEdge(&m_graph, m_libVertexp, vertex(nodep), 1, false);
|
||||||
}
|
}
|
||||||
|
// Note AstBind also has iteration on cells
|
||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildren(*this);
|
||||||
nodep->checkTree();
|
nodep->checkTree();
|
||||||
m_modp = NULL;
|
m_modp = NULL;
|
||||||
@@ -192,28 +215,35 @@ private:
|
|||||||
new V3GraphEdge(&m_graph, vertex(m_modp), vertex(nodep->packagep()), 1, false);
|
new V3GraphEdge(&m_graph, vertex(m_modp), vertex(nodep->packagep()), 1, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virtual void visit(AstBind* nodep, AstNUser*) {
|
||||||
|
// Bind: Has cells underneath that need to be put into the new module, and cells which need resolution
|
||||||
|
// TODO this doesn't allow bind to dotted hier names, that would require
|
||||||
|
// this move to post param, which would mean we do not auto-read modules
|
||||||
|
// and means we cannot compute module levels until later.
|
||||||
|
UINFO(4,"Link Bind: "<<nodep<<endl);
|
||||||
|
AstNodeModule* modp = resolveModule(nodep,nodep->name());
|
||||||
|
if (modp) {
|
||||||
|
AstNode* cellsp = nodep->cellsp()->unlinkFrBackWithNext();
|
||||||
|
// Module may have already linked, so need to pick up these new cells
|
||||||
|
AstNodeModule* oldModp = m_modp;
|
||||||
|
{
|
||||||
|
m_modp = modp;
|
||||||
|
modp->addStmtp(cellsp); // Important that this adds to end, as next iterate assumes does all cells
|
||||||
|
cellsp->iterateAndNext(*this);
|
||||||
|
}
|
||||||
|
m_modp = oldModp;
|
||||||
|
}
|
||||||
|
pushDeletep(nodep->unlinkFrBack());
|
||||||
|
}
|
||||||
|
|
||||||
virtual void visit(AstCell* nodep, AstNUser*) {
|
virtual void visit(AstCell* nodep, AstNUser*) {
|
||||||
// Cell: Resolve its filename. If necessary, parse it.
|
// Cell: Resolve its filename. If necessary, parse it.
|
||||||
|
if (nodep->user1SetOnce()) return; // AstBind and AstNodeModule may call a cell twice
|
||||||
if (!nodep->modp()) {
|
if (!nodep->modp()) {
|
||||||
UINFO(4,"Link Cell: "<<nodep<<endl);
|
UINFO(4,"Link Cell: "<<nodep<<endl);
|
||||||
// Use findIdFallback instead of findIdFlat; it doesn't matter for now
|
// Use findIdFallback instead of findIdFlat; it doesn't matter for now
|
||||||
// but we might support modules-under-modules someday.
|
// but we might support modules-under-modules someday.
|
||||||
AstNodeModule* modp = m_mods.rootp()->findIdFallback(nodep->modName())->nodep()->castNodeModule();
|
AstNodeModule* modp = resolveModule(nodep,nodep->modName());
|
||||||
if (!modp) {
|
|
||||||
// Read-subfile
|
|
||||||
// If file not found, make AstNotFoundModule, rather than error out.
|
|
||||||
// We'll throw the error when we know the module will really be needed.
|
|
||||||
V3Parse parser (v3Global.rootp(), m_filterp, m_parseSymp);
|
|
||||||
parser.parseFile(nodep->fileline(), nodep->modName(), false, "");
|
|
||||||
V3Error::abortIfErrors();
|
|
||||||
// We've read new modules, grab new pointers to their names
|
|
||||||
readModNames();
|
|
||||||
// Check again
|
|
||||||
modp = m_mods.rootp()->findIdFallback(nodep->modName())->nodep()->castNodeModule();
|
|
||||||
if (!modp) {
|
|
||||||
nodep->v3error("Can't resolve module reference: "<<nodep->modName());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (modp) {
|
if (modp) {
|
||||||
nodep->modp(modp);
|
nodep->modp(modp);
|
||||||
// Track module depths, so can sort list from parent down to children
|
// Track module depths, so can sort list from parent down to children
|
||||||
|
|||||||
+9
-3
@@ -103,6 +103,7 @@ public:
|
|||||||
if (!diddump && v3Global.opt.dumpTree()) {
|
if (!diddump && v3Global.opt.dumpTree()) {
|
||||||
diddump = true;
|
diddump = true;
|
||||||
m_syms.dumpFilePrefixed("linkdot-preerr");
|
m_syms.dumpFilePrefixed("linkdot-preerr");
|
||||||
|
v3Global.rootp()->dumpTreeFile(v3Global.debugFilename("linkdot-preerr.tree"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -660,7 +661,7 @@ private:
|
|||||||
// Find under either a task or the module's vars
|
// Find under either a task or the module's vars
|
||||||
VSymEnt* foundp = m_curSymp->findIdFallback(nodep->name());
|
VSymEnt* foundp = m_curSymp->findIdFallback(nodep->name());
|
||||||
if (!foundp && m_modSymp && nodep->name() == m_modSymp->nodep()->name()) foundp = m_modSymp; // Conflicts with modname?
|
if (!foundp && m_modSymp && nodep->name() == m_modSymp->nodep()->name()) foundp = m_modSymp; // Conflicts with modname?
|
||||||
AstVar* findvarp = foundp->nodep()->castVar();
|
AstVar* findvarp = foundp ? foundp->nodep()->castVar() : NULL;
|
||||||
bool ins=false;
|
bool ins=false;
|
||||||
if (!foundp) {
|
if (!foundp) {
|
||||||
ins=true;
|
ins=true;
|
||||||
@@ -729,7 +730,7 @@ private:
|
|||||||
// Find under either a task or the module's vars
|
// Find under either a task or the module's vars
|
||||||
VSymEnt* foundp = m_curSymp->findIdFallback(nodep->name());
|
VSymEnt* foundp = m_curSymp->findIdFallback(nodep->name());
|
||||||
if (!foundp && m_modSymp && nodep->name() == m_modSymp->nodep()->name()) foundp = m_modSymp; // Conflicts with modname?
|
if (!foundp && m_modSymp && nodep->name() == m_modSymp->nodep()->name()) foundp = m_modSymp; // Conflicts with modname?
|
||||||
AstEnumItem* findvarp = foundp->nodep()->castEnumItem();
|
AstEnumItem* findvarp = foundp ? foundp->nodep()->castEnumItem() : NULL;
|
||||||
bool ins=false;
|
bool ins=false;
|
||||||
if (!foundp) {
|
if (!foundp) {
|
||||||
ins=true;
|
ins=true;
|
||||||
@@ -1445,6 +1446,10 @@ private:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
virtual void visit(AstEnumItemRef* nodep, AstNUser*) {
|
||||||
|
// EnumItemRef may be under a dot. Should already be resolved.
|
||||||
|
nodep->iterateChildren(*this);
|
||||||
|
}
|
||||||
virtual void visit(AstVar* nodep, AstNUser*) {
|
virtual void visit(AstVar* nodep, AstNUser*) {
|
||||||
checkNoDot(nodep);
|
checkNoDot(nodep);
|
||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildren(*this);
|
||||||
@@ -1498,7 +1503,7 @@ private:
|
|||||||
VSymEnt* foundp = NULL;
|
VSymEnt* foundp = NULL;
|
||||||
AstNodeFTask* taskp = NULL;
|
AstNodeFTask* taskp = NULL;
|
||||||
foundp = m_statep->findSymPrefixed(dotSymp, nodep->name(), baddot);
|
foundp = m_statep->findSymPrefixed(dotSymp, nodep->name(), baddot);
|
||||||
taskp = foundp->nodep()->castNodeFTask(); // Maybe NULL
|
taskp = foundp ? foundp->nodep()->castNodeFTask() : NULL; // Maybe NULL
|
||||||
if (taskp) {
|
if (taskp) {
|
||||||
nodep->taskp(taskp);
|
nodep->taskp(taskp);
|
||||||
nodep->packagep(foundp->packagep());
|
nodep->packagep(foundp->packagep());
|
||||||
@@ -1563,6 +1568,7 @@ private:
|
|||||||
m_ds.init(m_curSymp);
|
m_ds.init(m_curSymp);
|
||||||
nodep->rhsp()->iterateAndNext(*this);
|
nodep->rhsp()->iterateAndNext(*this);
|
||||||
nodep->thsp()->iterateAndNext(*this);
|
nodep->thsp()->iterateAndNext(*this);
|
||||||
|
nodep->attrp()->iterateAndNext(*this);
|
||||||
}
|
}
|
||||||
m_ds = lastStates;
|
m_ds = lastStates;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -183,7 +183,8 @@ private:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!nodep->sensp()->castNodeVarRef()) {
|
if (!nodep->sensp()->castNodeVarRef()
|
||||||
|
&& !nodep->sensp()->castEnumItemRef()) { // V3Const will cleanup
|
||||||
if (debug()) nodep->dumpTree(cout,"-tree: ");
|
if (debug()) nodep->dumpTree(cout,"-tree: ");
|
||||||
nodep->v3error("Unsupported: Complex statement in sensitivity list");
|
nodep->v3error("Unsupported: Complex statement in sensitivity list");
|
||||||
}
|
}
|
||||||
@@ -203,7 +204,7 @@ private:
|
|||||||
if (AstNodeVarRef* varrefp = basefromp->castNodeVarRef()) { // Maybe varxref - so need to clone
|
if (AstNodeVarRef* varrefp = basefromp->castNodeVarRef()) { // Maybe varxref - so need to clone
|
||||||
nodep->attrp(new AstAttrOf(nodep->fileline(), AstAttrType::VAR_BASE,
|
nodep->attrp(new AstAttrOf(nodep->fileline(), AstAttrType::VAR_BASE,
|
||||||
varrefp->cloneTree(false)));
|
varrefp->cloneTree(false)));
|
||||||
} else if (AstMemberSel* fromp = nodep->fromp()->castMemberSel()) {
|
} else if (AstMemberSel* fromp = basefromp->castMemberSel()) {
|
||||||
nodep->attrp(new AstAttrOf(nodep->fileline(), AstAttrType::MEMBER_BASE,
|
nodep->attrp(new AstAttrOf(nodep->fileline(), AstAttrType::MEMBER_BASE,
|
||||||
fromp->cloneTree(false)));
|
fromp->cloneTree(false)));
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
+3
-3
@@ -79,7 +79,7 @@ public:
|
|||||||
void pushBack (V3List<T>& listr, T newp) {
|
void pushBack (V3List<T>& listr, T newp) {
|
||||||
// "this" must be a element inside of *newp
|
// "this" must be a element inside of *newp
|
||||||
// cppcheck-suppress thisSubtraction
|
// cppcheck-suppress thisSubtraction
|
||||||
size_t offset = (vluint8_t*)(this) - (vluint8_t*)(newp);
|
size_t offset = (size_t)(vluint8_t*)(this) - (size_t)(vluint8_t*)(newp);
|
||||||
m_nextp = NULL;
|
m_nextp = NULL;
|
||||||
if (!listr.m_headp) listr.m_headp = newp;
|
if (!listr.m_headp) listr.m_headp = newp;
|
||||||
m_prevp = listr.m_tailp;
|
m_prevp = listr.m_tailp;
|
||||||
@@ -89,7 +89,7 @@ public:
|
|||||||
void pushFront (V3List<T>& listr, T newp) {
|
void pushFront (V3List<T>& listr, T newp) {
|
||||||
// "this" must be a element inside of *newp
|
// "this" must be a element inside of *newp
|
||||||
// cppcheck-suppress thisSubtraction
|
// cppcheck-suppress thisSubtraction
|
||||||
size_t offset = (vluint8_t*)(this) - (vluint8_t*)(newp);
|
size_t offset = (size_t)(vluint8_t*)(this) - (size_t)(vluint8_t*)(newp);
|
||||||
m_nextp = listr.m_headp;
|
m_nextp = listr.m_headp;
|
||||||
if (m_nextp) baseToListEnt(m_nextp,offset)->m_prevp = newp;
|
if (m_nextp) baseToListEnt(m_nextp,offset)->m_prevp = newp;
|
||||||
listr.m_headp = newp;
|
listr.m_headp = newp;
|
||||||
@@ -100,7 +100,7 @@ public:
|
|||||||
void unlink (V3List<T>& listr, T oldp) {
|
void unlink (V3List<T>& listr, T oldp) {
|
||||||
// "this" must be a element inside of *oldp
|
// "this" must be a element inside of *oldp
|
||||||
// cppcheck-suppress thisSubtraction
|
// cppcheck-suppress thisSubtraction
|
||||||
size_t offset = (vluint8_t*)(this) - (vluint8_t*)(oldp);
|
size_t offset = (size_t)(vluint8_t*)(this) - (size_t)(vluint8_t*)(oldp);
|
||||||
if (m_nextp) baseToListEnt(m_nextp,offset)->m_prevp = m_prevp;
|
if (m_nextp) baseToListEnt(m_nextp,offset)->m_prevp = m_prevp;
|
||||||
else listr.m_tailp = m_prevp;
|
else listr.m_tailp = m_prevp;
|
||||||
if (m_prevp) baseToListEnt(m_prevp,offset)->m_nextp = m_nextp;
|
if (m_prevp) baseToListEnt(m_prevp,offset)->m_nextp = m_nextp;
|
||||||
|
|||||||
@@ -625,6 +625,16 @@ bool V3Number::isLt(const V3Number& rhs) const {
|
|||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
bool V3Number::isLtXZ(const V3Number& rhs) const {
|
||||||
|
// Include X/Z in comparisons for sort ordering
|
||||||
|
for (int bit=0; bit<max(this->width(),rhs.width()); bit++) {
|
||||||
|
if (this->bitIs1(bit) && rhs.bitIs0(bit)) { return 1; }
|
||||||
|
if (rhs.bitIs1(bit) && this->bitIs0(bit)) { return 0; }
|
||||||
|
if (this->bitIsXZ(bit)) { return 1; }
|
||||||
|
if (rhs.bitIsXZ(bit)) { return 0; }
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
int V3Number::widthMin() const {
|
int V3Number::widthMin() const {
|
||||||
for(int bit=width()-1; bit>0; bit--) {
|
for(int bit=width()-1; bit>0; bit--) {
|
||||||
|
|||||||
+2
-1
@@ -166,6 +166,7 @@ public:
|
|||||||
bool isEqAllOnes(int optwidth=0) const;
|
bool isEqAllOnes(int optwidth=0) const;
|
||||||
bool isCaseEq(const V3Number& rhsp) const; // operator==
|
bool isCaseEq(const V3Number& rhsp) const; // operator==
|
||||||
bool isLt(const V3Number& rhsp) const; // operator<
|
bool isLt(const V3Number& rhsp) const; // operator<
|
||||||
|
bool isLtXZ(const V3Number& rhsp) const; // operator< with XZ compared
|
||||||
void isSigned(bool ssigned) { m_signed=ssigned; }
|
void isSigned(bool ssigned) { m_signed=ssigned; }
|
||||||
bool isUnknown() const;
|
bool isUnknown() const;
|
||||||
uint32_t toUInt() const;
|
uint32_t toUInt() const;
|
||||||
@@ -180,7 +181,7 @@ public:
|
|||||||
uint32_t mostSetBitP1() const; // Highest bit set plus one, IE for 16 return 5, for 0 return 0.
|
uint32_t mostSetBitP1() const; // Highest bit set plus one, IE for 16 return 5, for 0 return 0.
|
||||||
|
|
||||||
// Operators
|
// Operators
|
||||||
bool operator<(const V3Number& rhs) const { return isLt(rhs); }
|
bool operator<(const V3Number& rhs) const { return isLtXZ(rhs); }
|
||||||
|
|
||||||
// STATICS
|
// STATICS
|
||||||
static int log2b(uint32_t num);
|
static int log2b(uint32_t num);
|
||||||
|
|||||||
+15
-3
@@ -28,6 +28,7 @@
|
|||||||
#include <cctype>
|
#include <cctype>
|
||||||
#include <dirent.h>
|
#include <dirent.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
#include <fcntl.h>
|
||||||
#include <set>
|
#include <set>
|
||||||
#include <list>
|
#include <list>
|
||||||
#include <map>
|
#include <map>
|
||||||
@@ -77,7 +78,7 @@ struct V3OptionsImp {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void addLangExt(const string &langext, const V3LangCode lc) {
|
void addLangExt(const string& langext, const V3LangCode& lc) {
|
||||||
// New language extension replaces any pre-existing one.
|
// New language extension replaces any pre-existing one.
|
||||||
(void)m_langExts.erase(langext);
|
(void)m_langExts.erase(langext);
|
||||||
m_langExts[langext] = lc;
|
m_langExts[langext] = lc;
|
||||||
@@ -98,7 +99,7 @@ void V3Options::addIncDirUser(const string& incdir) {
|
|||||||
void V3Options::addIncDirFallback(const string& incdir) {
|
void V3Options::addIncDirFallback(const string& incdir) {
|
||||||
m_impp->addIncDirFallback(incdir);
|
m_impp->addIncDirFallback(incdir);
|
||||||
}
|
}
|
||||||
void V3Options::addLangExt(const string &langext, const V3LangCode lc) {
|
void V3Options::addLangExt(const string& langext, const V3LangCode& lc) {
|
||||||
m_impp->addLangExt(langext, lc);
|
m_impp->addLangExt(langext, lc);
|
||||||
}
|
}
|
||||||
void V3Options::addLibExtV(const string& libext) {
|
void V3Options::addLibExtV(const string& libext) {
|
||||||
@@ -277,6 +278,17 @@ bool V3Options::fileStatNormal(const string& filename) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void V3Options::fileNfsFlush(const string& filename) {
|
||||||
|
// NFS caches stat() calls so to get up-to-date information must
|
||||||
|
// do a open or opendir on the filename.
|
||||||
|
// Faster to just try both rather than check if a file is a dir.
|
||||||
|
if (DIR* dirp = opendir(filename.c_str())) {
|
||||||
|
closedir(dirp);
|
||||||
|
} else if (int fd = ::open(filename.c_str(), O_RDONLY)) {
|
||||||
|
if (fd>0) ::close(fd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
string V3Options::fileExists (const string& filename) {
|
string V3Options::fileExists (const string& filename) {
|
||||||
// Surprisingly, for VCS and other simulators, this process
|
// Surprisingly, for VCS and other simulators, this process
|
||||||
// is quite slow; presumably because of re-reading each directory
|
// is quite slow; presumably because of re-reading each directory
|
||||||
@@ -1117,7 +1129,7 @@ string V3Options::parseFileArg(const string& optdir, const string& relfilename)
|
|||||||
//! Utility to see if we have a language extension argument and if so add it.
|
//! Utility to see if we have a language extension argument and if so add it.
|
||||||
bool V3Options::parseLangExt (const char* swp, //!< argument text
|
bool V3Options::parseLangExt (const char* swp, //!< argument text
|
||||||
const char* langswp, //!< option to match
|
const char* langswp, //!< option to match
|
||||||
const V3LangCode lc) { //!< language code
|
const V3LangCode& lc) { //!< language code
|
||||||
int len = strlen(langswp);
|
int len = strlen(langswp);
|
||||||
if (!strncmp(swp, langswp, len)) {
|
if (!strncmp(swp, langswp, len)) {
|
||||||
addLangExt(swp + len, lc);
|
addLangExt(swp + len, lc);
|
||||||
|
|||||||
+4
-2
@@ -36,6 +36,7 @@
|
|||||||
|
|
||||||
class V3OptionsImp;
|
class V3OptionsImp;
|
||||||
class FileLine;
|
class FileLine;
|
||||||
|
struct stat;
|
||||||
|
|
||||||
typedef vector<string> V3StringList;
|
typedef vector<string> V3StringList;
|
||||||
typedef set<string> V3StringSet;
|
typedef set<string> V3StringSet;
|
||||||
@@ -150,7 +151,7 @@ class V3Options {
|
|||||||
void addFuture(const string& flag);
|
void addFuture(const string& flag);
|
||||||
void addIncDirUser(const string& incdir); // User requested
|
void addIncDirUser(const string& incdir); // User requested
|
||||||
void addIncDirFallback(const string& incdir); // Low priority if not found otherwise
|
void addIncDirFallback(const string& incdir); // Low priority if not found otherwise
|
||||||
void addLangExt(const string &langext, const V3LangCode lc);
|
void addLangExt(const string& langext, const V3LangCode& lc);
|
||||||
void addLibExtV(const string& libext);
|
void addLibExtV(const string& libext);
|
||||||
void optimize(int level);
|
void optimize(int level);
|
||||||
void showVersion(bool verbose);
|
void showVersion(bool verbose);
|
||||||
@@ -158,7 +159,7 @@ class V3Options {
|
|||||||
bool onoff(const char* sw, const char* arg, bool& flag);
|
bool onoff(const char* sw, const char* arg, bool& flag);
|
||||||
bool suffixed(const char* sw, const char* arg);
|
bool suffixed(const char* sw, const char* arg);
|
||||||
string parseFileArg(const string& optdir, const string& relfilename);
|
string parseFileArg(const string& optdir, const string& relfilename);
|
||||||
bool parseLangExt(const char* swp, const char* langswp, const V3LangCode lc);
|
bool parseLangExt(const char* swp, const char* langswp, const V3LangCode& lc);
|
||||||
string filePathCheckOneDir(const string& modname, const string& dirname);
|
string filePathCheckOneDir(const string& modname, const string& dirname);
|
||||||
|
|
||||||
static string getenvStr(const string& envvar, const string& defaultValue);
|
static string getenvStr(const string& envvar, const string& defaultValue);
|
||||||
@@ -321,6 +322,7 @@ class V3Options {
|
|||||||
V3LangCode fileLanguage(const string &filename);
|
V3LangCode fileLanguage(const string &filename);
|
||||||
static bool fileStatDir (const string& filename);
|
static bool fileStatDir (const string& filename);
|
||||||
static bool fileStatNormal (const string& filename);
|
static bool fileStatNormal (const string& filename);
|
||||||
|
static void fileNfsFlush(const string& filename);
|
||||||
|
|
||||||
// METHODS (other OS)
|
// METHODS (other OS)
|
||||||
static void throwSigsegv();
|
static void throwSigsegv();
|
||||||
|
|||||||
+5
-4
@@ -94,8 +94,8 @@ private:
|
|||||||
if (varp->isGParam()) {
|
if (varp->isGParam()) {
|
||||||
char ch = varp->name()[0];
|
char ch = varp->name()[0];
|
||||||
ch = toupper(ch); if (ch<'A' || ch>'Z') ch='Z';
|
ch = toupper(ch); if (ch<'A' || ch>'Z') ch='Z';
|
||||||
varp->user4(usedLetter[ch]*256 + ch);
|
varp->user4(usedLetter[static_cast<int>(ch)]*256 + ch);
|
||||||
usedLetter[ch]++;
|
usedLetter[static_cast<int>(ch)]++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -324,13 +324,13 @@ void ParamVisitor::visit(AstCell* nodep, AstNUser*) {
|
|||||||
if (nodep->paramsp()) {
|
if (nodep->paramsp()) {
|
||||||
UINFO(4,"De-parameterize: "<<nodep<<endl);
|
UINFO(4,"De-parameterize: "<<nodep<<endl);
|
||||||
// Create new module name with _'s between the constants
|
// Create new module name with _'s between the constants
|
||||||
if (debug()>9) nodep->dumpTree(cout,"cell:\t");
|
if (debug()>=10) nodep->dumpTree(cout,"-cell:\t");
|
||||||
// Evaluate all module constants
|
// Evaluate all module constants
|
||||||
V3Const::constifyParamsEdit(nodep);
|
V3Const::constifyParamsEdit(nodep);
|
||||||
|
|
||||||
// Make sure constification worked
|
// Make sure constification worked
|
||||||
// Must be a separate loop, as constant conversion may have changed some pointers.
|
// Must be a separate loop, as constant conversion may have changed some pointers.
|
||||||
//if (debug()) nodep->dumpTree(cout,"cel2:\t");
|
//if (debug()) nodep->dumpTree(cout,"-cel2:\t");
|
||||||
string longname = nodep->modp()->name();
|
string longname = nodep->modp()->name();
|
||||||
bool any_overrides = false;
|
bool any_overrides = false;
|
||||||
longname += "_";
|
longname += "_";
|
||||||
@@ -442,6 +442,7 @@ void ParamVisitor::visit(AstCell* nodep, AstNUser*) {
|
|||||||
// Delete the parameters from the cell; they're not relevant any longer.
|
// Delete the parameters from the cell; they're not relevant any longer.
|
||||||
nodep->paramsp()->unlinkFrBackWithNext()->deleteTree();
|
nodep->paramsp()->unlinkFrBackWithNext()->deleteTree();
|
||||||
UINFO(8," Done with "<<nodep<<endl);
|
UINFO(8," Done with "<<nodep<<endl);
|
||||||
|
//if (debug()>=10) v3Global.rootp()->dumpTreeFile(v3Global.debugFilename("param-out.tree"));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Now remember to process the child module at the end of the module
|
// Now remember to process the child module at the end of the module
|
||||||
|
|||||||
@@ -70,6 +70,26 @@ protected:
|
|||||||
s_preprocp->defineCmdLine(prefl,"verilator3", "1"); // LEAK_OK
|
s_preprocp->defineCmdLine(prefl,"verilator3", "1"); // LEAK_OK
|
||||||
s_preprocp->defineCmdLine(prefl,"systemc_clock", "/*verilator systemc_clock*/"); // LEAK_OK
|
s_preprocp->defineCmdLine(prefl,"systemc_clock", "/*verilator systemc_clock*/"); // LEAK_OK
|
||||||
s_preprocp->defineCmdLine(prefl,"coverage_block_off", "/*verilator coverage_block_off*/"); // LEAK_OK
|
s_preprocp->defineCmdLine(prefl,"coverage_block_off", "/*verilator coverage_block_off*/"); // LEAK_OK
|
||||||
|
if (prefl->language().systemVerilog()) {
|
||||||
|
// Synthesis compatibility
|
||||||
|
s_preprocp->defineCmdLine(prefl,"SYSTEMVERILOG", "1"); // LEAK_OK
|
||||||
|
// IEEE predefined
|
||||||
|
s_preprocp->defineCmdLine(prefl,"SV_COV_START", "0");
|
||||||
|
s_preprocp->defineCmdLine(prefl,"SV_COV_STOP", "1");
|
||||||
|
s_preprocp->defineCmdLine(prefl,"SV_COV_RESET", "2");
|
||||||
|
s_preprocp->defineCmdLine(prefl,"SV_COV_CHECK", "3");
|
||||||
|
s_preprocp->defineCmdLine(prefl,"SV_COV_MODULE", "10");
|
||||||
|
s_preprocp->defineCmdLine(prefl,"SV_COV_HIER", "11");
|
||||||
|
s_preprocp->defineCmdLine(prefl,"SV_COV_ASSERTION", "20");
|
||||||
|
s_preprocp->defineCmdLine(prefl,"SV_COV_FSM_STATE", "21");
|
||||||
|
s_preprocp->defineCmdLine(prefl,"SV_COV_STATEMENT", "22");
|
||||||
|
s_preprocp->defineCmdLine(prefl,"SV_COV_TOGGLE", "23");
|
||||||
|
s_preprocp->defineCmdLine(prefl,"SV_COV_OVERFLOW", "-2");
|
||||||
|
s_preprocp->defineCmdLine(prefl,"SV_COV_ERROR", "-1");
|
||||||
|
s_preprocp->defineCmdLine(prefl,"SV_COV_NOCOV", "0");
|
||||||
|
s_preprocp->defineCmdLine(prefl,"SV_COV_OK", "1");
|
||||||
|
s_preprocp->defineCmdLine(prefl,"SV_COV_PARTIAL", "2");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+8
-2
@@ -46,8 +46,10 @@ private:
|
|||||||
// NODE STATE
|
// NODE STATE
|
||||||
// AstVar::user1p -> AstVarScope replacement for this variable
|
// AstVar::user1p -> AstVarScope replacement for this variable
|
||||||
// AstTask::user2p -> AstTask*. Replacement task
|
// AstTask::user2p -> AstTask*. Replacement task
|
||||||
|
// AstVar::user3p -> AstVarScope for packages
|
||||||
AstUser1InUse m_inuser1;
|
AstUser1InUse m_inuser1;
|
||||||
AstUser2InUse m_inuser2;
|
AstUser2InUse m_inuser2;
|
||||||
|
AstUser3InUse m_inuser3;
|
||||||
|
|
||||||
// STATE, inside processing a single module
|
// STATE, inside processing a single module
|
||||||
AstNodeModule* m_modp; // Current module
|
AstNodeModule* m_modp; // Current module
|
||||||
@@ -201,10 +203,12 @@ private:
|
|||||||
}
|
}
|
||||||
virtual void visit(AstVar* nodep, AstNUser*) {
|
virtual void visit(AstVar* nodep, AstNUser*) {
|
||||||
// Make new scope variable
|
// Make new scope variable
|
||||||
if (!nodep->user1p()) {
|
if (m_modp->castPackage()
|
||||||
|
? !nodep->user3p() : !nodep->user1p()) {
|
||||||
AstVarScope* varscp = new AstVarScope(nodep->fileline(), m_scopep, nodep);
|
AstVarScope* varscp = new AstVarScope(nodep->fileline(), m_scopep, nodep);
|
||||||
UINFO(6," New scope "<<varscp<<endl);
|
UINFO(6," New scope "<<varscp<<endl);
|
||||||
nodep->user1p(varscp);
|
nodep->user1p(varscp);
|
||||||
|
if (m_modp->castPackage()) nodep->user3p(varscp);
|
||||||
m_scopep->addVarp(varscp);
|
m_scopep->addVarp(varscp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -212,7 +216,9 @@ private:
|
|||||||
// VarRef needs to point to VarScope
|
// VarRef needs to point to VarScope
|
||||||
// Make sure variable has made user1p.
|
// Make sure variable has made user1p.
|
||||||
nodep->varp()->accept(*this);
|
nodep->varp()->accept(*this);
|
||||||
AstVarScope* varscp = (AstVarScope*)nodep->varp()->user1p();
|
AstVarScope* varscp = nodep->packagep()
|
||||||
|
? (AstVarScope*)nodep->varp()->user3p()
|
||||||
|
: (AstVarScope*)nodep->varp()->user1p();
|
||||||
if (!varscp) nodep->v3fatalSrc("Can't locate varref scope");
|
if (!varscp) nodep->v3fatalSrc("Can't locate varref scope");
|
||||||
nodep->varScopep(varscp);
|
nodep->varScopep(varscp);
|
||||||
}
|
}
|
||||||
|
|||||||
+14
-13
@@ -76,8 +76,8 @@ class SliceCloneVisitor : public AstNVisitor {
|
|||||||
if (m_vecIdx == (int)m_selBits.size()) {
|
if (m_vecIdx == (int)m_selBits.size()) {
|
||||||
m_selBits.push_back(vector<unsigned>());
|
m_selBits.push_back(vector<unsigned>());
|
||||||
AstVar* varp = m_refp->varp();
|
AstVar* varp = m_refp->varp();
|
||||||
pair<uint32_t,uint32_t> arrDim = varp->dtypep()->dimensions();
|
pair<uint32_t,uint32_t> arrDim = varp->dtypep()->dimensions(false);
|
||||||
uint32_t dimensions = arrDim.first + arrDim.second;
|
uint32_t dimensions = arrDim.second;
|
||||||
for (uint32_t i = 0; i < dimensions; ++i) {
|
for (uint32_t i = 0; i < dimensions; ++i) {
|
||||||
m_selBits[m_vecIdx].push_back(0);
|
m_selBits[m_vecIdx].push_back(0);
|
||||||
}
|
}
|
||||||
@@ -233,6 +233,7 @@ class SliceVisitor : public AstNVisitor {
|
|||||||
if (!selp) {
|
if (!selp) {
|
||||||
nodep->user1p(fromp->castVarRef());
|
nodep->user1p(fromp->castVarRef());
|
||||||
selp = NULL;
|
selp = NULL;
|
||||||
|
break;
|
||||||
} else {
|
} else {
|
||||||
fromp = selp->fromp();
|
fromp = selp->fromp();
|
||||||
if (fromp) ++dim;
|
if (fromp) ++dim;
|
||||||
@@ -252,7 +253,7 @@ class SliceVisitor : public AstNVisitor {
|
|||||||
AstNode* topp = nodep;
|
AstNode* topp = nodep;
|
||||||
for (unsigned i = start; i < start + count; ++i) {
|
for (unsigned i = start; i < start + count; ++i) {
|
||||||
AstNodeDType* dtypep = varp->dtypep()->dtypeDimensionp(i-1);
|
AstNodeDType* dtypep = varp->dtypep()->dtypeDimensionp(i-1);
|
||||||
AstArrayDType* adtypep = dtypep->castArrayDType();
|
AstUnpackArrayDType* adtypep = dtypep->castUnpackArrayDType();
|
||||||
if (!adtypep) nodep->v3fatalSrc("insertImplicit tried to expand an array without an ArrayDType");
|
if (!adtypep) nodep->v3fatalSrc("insertImplicit tried to expand an array without an ArrayDType");
|
||||||
vlsint32_t msb = adtypep->msb();
|
vlsint32_t msb = adtypep->msb();
|
||||||
vlsint32_t lsb = adtypep->lsb();
|
vlsint32_t lsb = adtypep->lsb();
|
||||||
@@ -291,8 +292,8 @@ class SliceVisitor : public AstNVisitor {
|
|||||||
// The LHS/RHS of an Assign may be to a Var that is an array. In this
|
// The LHS/RHS of an Assign may be to a Var that is an array. In this
|
||||||
// case we need to create a slice accross the entire Var
|
// case we need to create a slice accross the entire Var
|
||||||
if (m_assignp && !nodep->backp()->castArraySel()) {
|
if (m_assignp && !nodep->backp()->castArraySel()) {
|
||||||
pair<uint32_t,uint32_t> arrDim = nodep->varp()->dtypep()->dimensions();
|
pair<uint32_t,uint32_t> arrDim = nodep->varp()->dtypep()->dimensions(false);
|
||||||
uint32_t dimensions = arrDim.first + arrDim.second;
|
uint32_t dimensions = arrDim.second; // unpacked only
|
||||||
if (dimensions > 0) {
|
if (dimensions > 0) {
|
||||||
AstVarRef* clonep = nodep->cloneTree(false);
|
AstVarRef* clonep = nodep->cloneTree(false);
|
||||||
clonep->user1p(nodep);
|
clonep->user1p(nodep);
|
||||||
@@ -306,7 +307,7 @@ class SliceVisitor : public AstNVisitor {
|
|||||||
virtual void visit(AstExtend* nodep, AstNUser*) {
|
virtual void visit(AstExtend* nodep, AstNUser*) {
|
||||||
m_extend = true;
|
m_extend = true;
|
||||||
if (m_assignp && m_assignp->user2() > 1 && !m_assignError) {
|
if (m_assignp && m_assignp->user2() > 1 && !m_assignError) {
|
||||||
m_assignp->v3error("Unsupported: Assignment between packed arrays of different dimensions");
|
m_assignp->v3error("Unsupported: Assignment between unpacked arrays of different dimensions");
|
||||||
m_assignError = true;
|
m_assignError = true;
|
||||||
}
|
}
|
||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildren(*this);
|
||||||
@@ -325,8 +326,8 @@ class SliceVisitor : public AstNVisitor {
|
|||||||
if (nodep->user3()) return; // Prevent recursion on just created nodes
|
if (nodep->user3()) return; // Prevent recursion on just created nodes
|
||||||
unsigned dim = explicitDimensions(nodep);
|
unsigned dim = explicitDimensions(nodep);
|
||||||
AstVarRef* refp = nodep->user1p()->castNode()->castVarRef();
|
AstVarRef* refp = nodep->user1p()->castNode()->castVarRef();
|
||||||
pair<uint32_t,uint32_t> arrDim = refp->varp()->dtypep()->dimensions();
|
pair<uint32_t,uint32_t> arrDim = refp->varp()->dtypep()->dimensions(false);
|
||||||
uint32_t implicit = (arrDim.first + arrDim.second) - dim;
|
uint32_t implicit = (arrDim.second) - dim;
|
||||||
if (implicit > 0) {
|
if (implicit > 0) {
|
||||||
AstArraySel* newp = insertImplicit(nodep->cloneTree(false), dim+1, implicit);
|
AstArraySel* newp = insertImplicit(nodep->cloneTree(false), dim+1, implicit);
|
||||||
nodep->replaceWith(newp); nodep = newp;
|
nodep->replaceWith(newp); nodep = newp;
|
||||||
@@ -337,7 +338,7 @@ class SliceVisitor : public AstNVisitor {
|
|||||||
m_assignp->v3error("Slices of arrays in assignments must have the same unpacked dimensions");
|
m_assignp->v3error("Slices of arrays in assignments must have the same unpacked dimensions");
|
||||||
} else if (!m_assignp->user2()) {
|
} else if (!m_assignp->user2()) {
|
||||||
if (m_extend && clones > 1 && !m_assignError) {
|
if (m_extend && clones > 1 && !m_assignError) {
|
||||||
m_assignp->v3error("Unsupported: Assignment between packed arrays of different dimensions");
|
m_assignp->v3error("Unsupported: Assignment between unpacked arrays of different dimensions");
|
||||||
m_assignError = true;
|
m_assignError = true;
|
||||||
}
|
}
|
||||||
if (clones > 1 && !refp->lvalue() && refp->varp() == m_lhsVarRefp->varp()
|
if (clones > 1 && !refp->lvalue() && refp->varp() == m_lhsVarRefp->varp()
|
||||||
@@ -353,7 +354,7 @@ class SliceVisitor : public AstNVisitor {
|
|||||||
virtual void visit(AstSel* nodep, AstNUser*) {
|
virtual void visit(AstSel* nodep, AstNUser*) {
|
||||||
m_extend = true;
|
m_extend = true;
|
||||||
if (m_assignp && m_assignp->user2() > 1 && !m_assignError) {
|
if (m_assignp && m_assignp->user2() > 1 && !m_assignError) {
|
||||||
m_assignp->v3error("Unsupported: Assignment between packed arrays of different dimensions");
|
m_assignp->v3error("Unsupported: Assignment between unpacked arrays of different dimensions");
|
||||||
m_assignError = true;
|
m_assignError = true;
|
||||||
}
|
}
|
||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildren(*this);
|
||||||
@@ -427,13 +428,13 @@ class SliceVisitor : public AstNVisitor {
|
|||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildren(*this);
|
||||||
} else {
|
} else {
|
||||||
AstVarRef* refp = findVarRefRecurse(nodep->lhsp());
|
AstVarRef* refp = findVarRefRecurse(nodep->lhsp());
|
||||||
ArrayDimensions varDim = refp->varp()->dtypep()->dimensions();
|
ArrayDimensions varDim = refp->varp()->dtypep()->dimensions(false);
|
||||||
if ((int)(dim - varDim.second) < 0) {
|
if ((int)(dim - varDim.second) < 0) {
|
||||||
// Unpacked dimensions are referenced first, make sure we have them all
|
// Unpacked dimensions are referenced first, make sure we have them all
|
||||||
nodep->v3error("Unary operator used across unpacked dimensions");
|
nodep->v3error("Unary operator used across unpacked dimensions");
|
||||||
} else if ((int)(dim - (varDim.first + varDim.second)) < 0) {
|
} else if ((int)(dim - (varDim.second)) < 0) {
|
||||||
// Implicit packed dimensions are allowed, make them explicit
|
// Implicit packed dimensions are allowed, make them explicit
|
||||||
uint32_t newDim = (varDim.first + varDim.second) - dim;
|
uint32_t newDim = (varDim.second) - dim;
|
||||||
AstNode* clonep = nodep->lhsp()->cloneTree(false);
|
AstNode* clonep = nodep->lhsp()->cloneTree(false);
|
||||||
clonep->user1p(refp);
|
clonep->user1p(refp);
|
||||||
AstNode* newp = insertImplicit(clonep, dim+1, newDim);
|
AstNode* newp = insertImplicit(clonep, dim+1, newDim);
|
||||||
|
|||||||
+2
-2
@@ -93,7 +93,7 @@ private:
|
|||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildren(*this);
|
||||||
if (m_counting && nodep->dtypep()) {
|
if (m_counting && nodep->dtypep()) {
|
||||||
if (nodep->isUsedClock()) ++m_statVarClock;
|
if (nodep->isUsedClock()) ++m_statVarClock;
|
||||||
if (nodep->dtypeSkipRefp()->castArrayDType()) ++m_statVarArray;
|
if (nodep->dtypeSkipRefp()->castUnpackArrayDType()) ++m_statVarArray;
|
||||||
else m_statVarBytes += nodep->dtypeSkipRefp()->widthTotalBytes();
|
else m_statVarBytes += nodep->dtypeSkipRefp()->widthTotalBytes();
|
||||||
if (int(m_statVarWidths.size()) <= nodep->width()) {
|
if (int(m_statVarWidths.size()) <= nodep->width()) {
|
||||||
m_statVarWidths.resize(nodep->width()+5);
|
m_statVarWidths.resize(nodep->width()+5);
|
||||||
@@ -197,7 +197,7 @@ public:
|
|||||||
V3Stats::addStat(m_stage, "Instruction count, TOTAL", m_statInstr);
|
V3Stats::addStat(m_stage, "Instruction count, TOTAL", m_statInstr);
|
||||||
V3Stats::addStat(m_stage, "Instruction count, fast", m_statInstrFast);
|
V3Stats::addStat(m_stage, "Instruction count, fast", m_statInstrFast);
|
||||||
// Vars
|
// Vars
|
||||||
V3Stats::addStat(m_stage, "Vars, arrayed", m_statVarArray);
|
V3Stats::addStat(m_stage, "Vars, unpacked arrayed", m_statVarArray);
|
||||||
V3Stats::addStat(m_stage, "Vars, clock attribute", m_statVarClock);
|
V3Stats::addStat(m_stage, "Vars, clock attribute", m_statVarClock);
|
||||||
V3Stats::addStat(m_stage, "Var space, non-arrays, bytes", m_statVarBytes);
|
V3Stats::addStat(m_stage, "Var space, non-arrays, bytes", m_statVarBytes);
|
||||||
if (m_statVarScpBytes) {
|
if (m_statVarScpBytes) {
|
||||||
|
|||||||
+2
-2
@@ -225,10 +225,10 @@ public:
|
|||||||
VSymMap doneSyms;
|
VSymMap doneSyms;
|
||||||
os<<"SymEnt Dump:\n";
|
os<<"SymEnt Dump:\n";
|
||||||
m_symRootp->dumpIterate(os, doneSyms, indent, 9999, "$root");
|
m_symRootp->dumpIterate(os, doneSyms, indent, 9999, "$root");
|
||||||
bool first = false;
|
bool first = true;
|
||||||
for (SymStack::iterator it = m_symsp.begin(); it != m_symsp.end(); ++it) {
|
for (SymStack::iterator it = m_symsp.begin(); it != m_symsp.end(); ++it) {
|
||||||
if (doneSyms.find(*it) == doneSyms.end()) {
|
if (doneSyms.find(*it) == doneSyms.end()) {
|
||||||
if (!first++) os<<"%%Warning: SymEnt Orphans:\n";
|
if (first) { first=false; os<<"%%Warning: SymEnt Orphans:\n"; }
|
||||||
(*it)->dumpIterate(os, doneSyms, indent, 9999, "Orphan");
|
(*it)->dumpIterate(os, doneSyms, indent, 9999, "Orphan");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+8
-7
@@ -189,10 +189,10 @@ private:
|
|||||||
// Change it variable
|
// Change it variable
|
||||||
FileLine* fl = nodep->fileline();
|
FileLine* fl = nodep->fileline();
|
||||||
AstNodeDType* dtypep
|
AstNodeDType* dtypep
|
||||||
= new AstArrayDType (fl,
|
= new AstUnpackArrayDType (fl,
|
||||||
nodep->findBitDType(m_outVarps.size(),
|
nodep->findBitDType(m_outVarps.size(),
|
||||||
m_outVarps.size(), AstNumeric::UNSIGNED),
|
m_outVarps.size(), AstNumeric::UNSIGNED),
|
||||||
new AstRange (fl, VL_MASK_I(m_inWidth), 0), false);
|
new AstRange (fl, VL_MASK_I(m_inWidth), 0));
|
||||||
v3Global.rootp()->typeTablep()->addTypesp(dtypep);
|
v3Global.rootp()->typeTablep()->addTypesp(dtypep);
|
||||||
AstVar* chgVarp
|
AstVar* chgVarp
|
||||||
= new AstVar (fl, AstVarType::MODULETEMP,
|
= new AstVar (fl, AstVarType::MODULETEMP,
|
||||||
@@ -237,8 +237,8 @@ private:
|
|||||||
AstVar* outvarp = outvscp->varp();
|
AstVar* outvarp = outvscp->varp();
|
||||||
FileLine* fl = nodep->fileline();
|
FileLine* fl = nodep->fileline();
|
||||||
AstNodeDType* dtypep
|
AstNodeDType* dtypep
|
||||||
= new AstArrayDType (fl, outvarp->dtypep(),
|
= new AstUnpackArrayDType (fl, outvarp->dtypep(),
|
||||||
new AstRange (fl, VL_MASK_I(m_inWidth), 0), false);
|
new AstRange (fl, VL_MASK_I(m_inWidth), 0));
|
||||||
v3Global.rootp()->typeTablep()->addTypesp(dtypep);
|
v3Global.rootp()->typeTablep()->addTypesp(dtypep);
|
||||||
AstVar* tablevarp
|
AstVar* tablevarp
|
||||||
= new AstVar (fl, AstVarType::MODULETEMP,
|
= new AstVar (fl, AstVarType::MODULETEMP,
|
||||||
@@ -349,7 +349,8 @@ private:
|
|||||||
AstVarScope* vsc2p= *it;
|
AstVarScope* vsc2p= *it;
|
||||||
AstVar* var2p = vsc2p->varp();
|
AstVar* var2p = vsc2p->varp();
|
||||||
if (var1p->width() == var2p->width()
|
if (var1p->width() == var2p->width()
|
||||||
&& var1p->dtypep()->arrayElements() == var2p->dtypep()->arrayElements()) {
|
&& (var1p->dtypep()->arrayUnpackedElements()
|
||||||
|
== var2p->dtypep()->arrayUnpackedElements())) {
|
||||||
AstNode* init1p = var1p->valuep()->castInitArray();
|
AstNode* init1p = var1p->valuep()->castInitArray();
|
||||||
AstNode* init2p = var2p->valuep()->castInitArray();
|
AstNode* init2p = var2p->valuep()->castInitArray();
|
||||||
if (init1p->sameTree(init2p)) {
|
if (init1p->sameTree(init2p)) {
|
||||||
|
|||||||
+3
-3
@@ -75,10 +75,10 @@ private:
|
|||||||
return "Inlined leading underscore";
|
return "Inlined leading underscore";
|
||||||
}
|
}
|
||||||
if ((int)nodep->width() > v3Global.opt.traceMaxWidth()) return "Wide bus > --trace-max-width bits";
|
if ((int)nodep->width() > v3Global.opt.traceMaxWidth()) return "Wide bus > --trace-max-width bits";
|
||||||
if ((int)nodep->dtypep()->arrayElements() > v3Global.opt.traceMaxArray()) return "Wide memory > --trace-max-array ents";
|
if ((int)nodep->dtypep()->arrayUnpackedElements() > v3Global.opt.traceMaxArray()) return "Wide memory > --trace-max-array ents";
|
||||||
if (!(nodep->dtypeSkipRefp()->castBasicDType()
|
if (!(nodep->dtypeSkipRefp()->castBasicDType()
|
||||||
|| (nodep->dtypeSkipRefp()->castArrayDType()
|
|| (nodep->dtypeSkipRefp()->castUnpackArrayDType()
|
||||||
&& (nodep->dtypeSkipRefp()->castArrayDType()->subDTypep()
|
&& (nodep->dtypeSkipRefp()->castUnpackArrayDType()->subDTypep()
|
||||||
->skipRefp()->castBasicDType())))) {
|
->skipRefp()->castBasicDType())))) {
|
||||||
return "Unsupported: Multi-dimensional array";
|
return "Unsupported: Multi-dimensional array";
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -508,7 +508,7 @@ class TristateVisitor : public TristateBaseVisitor {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_statTriSigs++;
|
++m_statTriSigs;
|
||||||
m_tgraph.didProcess(invarp);
|
m_tgraph.didProcess(invarp);
|
||||||
UINFO(8, " TRISTATE EXPANDING:" << invarp << endl);
|
UINFO(8, " TRISTATE EXPANDING:" << invarp << endl);
|
||||||
|
|
||||||
|
|||||||
+21
-14
@@ -168,6 +168,11 @@ private:
|
|||||||
m_constXCvt = true;
|
m_constXCvt = true;
|
||||||
nodep->bodysp()->iterateAndNext(*this);
|
nodep->bodysp()->iterateAndNext(*this);
|
||||||
}
|
}
|
||||||
|
virtual void visit(AstNodeDType* nodep, AstNUser*) {
|
||||||
|
m_constXCvt = false; // Avoid loosing the X's in casex
|
||||||
|
nodep->iterateChildren(*this);
|
||||||
|
m_constXCvt = true;
|
||||||
|
}
|
||||||
void visitEqNeqCase(AstNodeBiop* nodep) {
|
void visitEqNeqCase(AstNodeBiop* nodep) {
|
||||||
UINFO(4," N/EQCASE->EQ "<<nodep<<endl);
|
UINFO(4," N/EQCASE->EQ "<<nodep<<endl);
|
||||||
V3Const::constifyEdit(nodep->lhsp()); // lhsp may change
|
V3Const::constifyEdit(nodep->lhsp()); // lhsp may change
|
||||||
@@ -283,6 +288,7 @@ private:
|
|||||||
} else {
|
} else {
|
||||||
// Make a Vxrand variable
|
// Make a Vxrand variable
|
||||||
// We use the special XTEMP type so it doesn't break pure functions
|
// We use the special XTEMP type so it doesn't break pure functions
|
||||||
|
if (!m_modp) nodep->v3fatalSrc("X number not under module");
|
||||||
string newvarname = ((string)"__Vxrand"
|
string newvarname = ((string)"__Vxrand"
|
||||||
+cvtToStr(m_modp->varNumGetInc()));
|
+cvtToStr(m_modp->varNumGetInc()));
|
||||||
AstVar* newvarp
|
AstVar* newvarp
|
||||||
@@ -323,16 +329,14 @@ private:
|
|||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildren(*this);
|
||||||
if (!nodep->user1SetOnce()) {
|
if (!nodep->user1SetOnce()) {
|
||||||
// Guard against reading/writing past end of bit vector array
|
// Guard against reading/writing past end of bit vector array
|
||||||
int maxmsb = 0;
|
|
||||||
bool lvalue = false;
|
|
||||||
AstNode* basefromp = AstArraySel::baseFromp(nodep);
|
AstNode* basefromp = AstArraySel::baseFromp(nodep);
|
||||||
|
bool lvalue = false;
|
||||||
if (AstNodeVarRef* varrefp = basefromp->castNodeVarRef()) {
|
if (AstNodeVarRef* varrefp = basefromp->castNodeVarRef()) {
|
||||||
lvalue = varrefp->lvalue();
|
lvalue = varrefp->lvalue();
|
||||||
maxmsb = (varrefp->varp()->width()-1);
|
|
||||||
} else {
|
|
||||||
// If it's a PARAMETER[bit], then basefromp may be a constant instead of a varrefp
|
|
||||||
maxmsb = basefromp->width()-1;
|
|
||||||
}
|
}
|
||||||
|
// Find range of dtype we are selecting from
|
||||||
|
// Similar code in V3Const::warnSelect
|
||||||
|
int maxmsb = nodep->fromp()->dtypep()->width()-1;
|
||||||
int maxlsb = maxmsb - nodep->width() + 1;
|
int maxlsb = maxmsb - nodep->width() + 1;
|
||||||
if (debug()>=9) nodep->dumpTree(cout,"sel_old: ");
|
if (debug()>=9) nodep->dumpTree(cout,"sel_old: ");
|
||||||
V3Number maxlsbnum (nodep->fileline(), nodep->lsbp()->width(), maxlsb);
|
V3Number maxlsbnum (nodep->fileline(), nodep->lsbp()->width(), maxlsb);
|
||||||
@@ -375,22 +379,25 @@ private:
|
|||||||
if (debug()==9) nodep->dumpTree(cout,"-in: ");
|
if (debug()==9) nodep->dumpTree(cout,"-in: ");
|
||||||
// Guard against reading/writing past end of arrays
|
// Guard against reading/writing past end of arrays
|
||||||
AstNode* basefromp = AstArraySel::baseFromp(nodep->fromp());
|
AstNode* basefromp = AstArraySel::baseFromp(nodep->fromp());
|
||||||
int dimension = AstArraySel::dimension(nodep->fromp());
|
|
||||||
int maxmsb = 0;
|
|
||||||
bool lvalue = false;
|
bool lvalue = false;
|
||||||
if (AstNodeVarRef* varrefp = basefromp->castNodeVarRef()) {
|
if (AstNodeVarRef* varrefp = basefromp->castNodeVarRef()) {
|
||||||
AstArrayDType* adtypep = varrefp->varp()->dtypep()->dtypeDimensionp(dimension)->castArrayDType();
|
|
||||||
if (!adtypep) nodep->v3fatalSrc("ArraySel to type without array at same depth");
|
|
||||||
lvalue = varrefp->lvalue();
|
lvalue = varrefp->lvalue();
|
||||||
maxmsb = adtypep->elementsConst()-1;
|
} else if (basefromp->castConst()) {
|
||||||
} else if (AstConst* lhconstp = basefromp->castConst()) {
|
|
||||||
// If it's a PARAMETER[bit], then basefromp may be a constant instead of a varrefp
|
// If it's a PARAMETER[bit], then basefromp may be a constant instead of a varrefp
|
||||||
maxmsb = lhconstp->width();
|
|
||||||
} else {
|
} else {
|
||||||
nodep->v3fatalSrc("No VarRef or Const under ArraySel\n");
|
nodep->v3fatalSrc("No VarRef or Const under ArraySel\n");
|
||||||
}
|
}
|
||||||
|
// Find range of dtype we are selecting from
|
||||||
|
int declElements = -1;
|
||||||
|
AstNodeDType* dtypep = nodep->fromp()->dtypep()->skipRefp();
|
||||||
|
if (!dtypep) nodep->v3fatalSrc("Select of non-selectable type");
|
||||||
|
if (AstNodeArrayDType* adtypep = dtypep->castNodeArrayDType()) {
|
||||||
|
declElements = adtypep->elementsConst();
|
||||||
|
} else {
|
||||||
|
nodep->v3error("Select from non-array "<<dtypep->prettyTypeName());
|
||||||
|
}
|
||||||
if (debug()>=9) nodep->dumpTree(cout,"arraysel_old: ");
|
if (debug()>=9) nodep->dumpTree(cout,"arraysel_old: ");
|
||||||
V3Number widthnum (nodep->fileline(), nodep->bitp()->width(), maxmsb);
|
V3Number widthnum (nodep->fileline(), nodep->bitp()->width(), declElements-1);
|
||||||
|
|
||||||
// See if the condition is constant true
|
// See if the condition is constant true
|
||||||
AstNode* condp = new AstLte (nodep->fileline(),
|
AstNode* condp = new AstLte (nodep->fileline(),
|
||||||
|
|||||||
+286
-49
@@ -115,12 +115,12 @@ private:
|
|||||||
// STATE
|
// STATE
|
||||||
bool m_paramsOnly; // Computing parameter value; limit operation
|
bool m_paramsOnly; // Computing parameter value; limit operation
|
||||||
AstRange* m_cellRangep; // Range for arrayed instantiations, NULL for normal instantiations
|
AstRange* m_cellRangep; // Range for arrayed instantiations, NULL for normal instantiations
|
||||||
AstNodeCase* m_casep; // Current case statement CaseItem is under
|
|
||||||
AstFunc* m_funcp; // Current function
|
AstFunc* m_funcp; // Current function
|
||||||
AstInitial* m_initialp; // Current initial block
|
AstInitial* m_initialp; // Current initial block
|
||||||
AstAttrOf* m_attrp; // Current attribute
|
AstAttrOf* m_attrp; // Current attribute
|
||||||
AstNodeDType* m_assDTypep; // Assign LHS data type for assignment pattern
|
AstNodeDType* m_assDTypep; // Assign LHS data type for assignment pattern
|
||||||
bool m_doGenerate; // Do errors later inside generate statement
|
bool m_doGenerate; // Do errors later inside generate statement
|
||||||
|
int m_dtTables; // Number of created data type tables
|
||||||
|
|
||||||
// CLASSES
|
// CLASSES
|
||||||
#define ANYSIZE 0
|
#define ANYSIZE 0
|
||||||
@@ -359,10 +359,25 @@ private:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
virtual void visit(AstRange* nodep, AstNUser* vup) {
|
virtual void visit(AstRange* nodep, AstNUser* vup) {
|
||||||
// If there's an edit, then processes the edit'ee (can't just rely on iterateChildren because sometimes we for(...) here ourself
|
|
||||||
// Real: Not allowed
|
// Real: Not allowed
|
||||||
// Signed: unsigned output, input either
|
// Signed: unsigned output, input either
|
||||||
AstNode* selp = V3Width::widthSelNoIterEdit(nodep); if (selp!=nodep) { nodep=NULL; selp->iterate(*this,vup); return; }
|
// Convert all range values to constants
|
||||||
|
UINFO(6,"RANGE "<<nodep<<endl);
|
||||||
|
V3Const::constifyParamsEdit(nodep->msbp()); // May relink pointed to node
|
||||||
|
V3Const::constifyParamsEdit(nodep->lsbp()); // May relink pointed to node
|
||||||
|
checkConstantOrReplace(nodep->msbp(), "MSB of bit range isn't a constant");
|
||||||
|
checkConstantOrReplace(nodep->lsbp(), "LSB of bit range isn't a constant");
|
||||||
|
int msb = nodep->msbConst();
|
||||||
|
int lsb = nodep->lsbConst();
|
||||||
|
if (msb<lsb) {
|
||||||
|
// Little endian bits are legal, just remember to swap
|
||||||
|
// Warning is in V3Width to avoid false warnings when in "off" generate if's
|
||||||
|
nodep->littleEndian(!nodep->littleEndian());
|
||||||
|
// Internally we'll always have msb() be the greater number
|
||||||
|
// We only need to correct when doing [] AstSel extraction,
|
||||||
|
// and when tracing the vector.
|
||||||
|
nodep->msbp()->swapWith(nodep->lsbp());
|
||||||
|
}
|
||||||
if (vup->c()->prelim()) {
|
if (vup->c()->prelim()) {
|
||||||
nodep->msbp()->iterateAndNext(*this,WidthVP(ANYSIZE,0,BOTH).p());
|
nodep->msbp()->iterateAndNext(*this,WidthVP(ANYSIZE,0,BOTH).p());
|
||||||
nodep->lsbp()->iterateAndNext(*this,WidthVP(ANYSIZE,0,BOTH).p());
|
nodep->lsbp()->iterateAndNext(*this,WidthVP(ANYSIZE,0,BOTH).p());
|
||||||
@@ -395,7 +410,7 @@ private:
|
|||||||
nodep->dtypeSetLogicBool(); return;
|
nodep->dtypeSetLogicBool(); return;
|
||||||
}
|
}
|
||||||
int width = nodep->widthConst();
|
int width = nodep->widthConst();
|
||||||
nodep->dtypeSetLogicSized(width,width,AstNumeric::UNSIGNED);
|
if (!nodep->dtypep()) nodep->v3fatalSrc("dtype wasn't set") // by V3WidthSel
|
||||||
if (nodep->lsbp()->castConst()
|
if (nodep->lsbp()->castConst()
|
||||||
&& nodep->msbConst() < nodep->lsbConst()) {
|
&& nodep->msbConst() < nodep->lsbConst()) {
|
||||||
nodep->v3error("Unsupported: MSB < LSB of bit extract: "
|
nodep->v3error("Unsupported: MSB < LSB of bit extract: "
|
||||||
@@ -415,31 +430,29 @@ private:
|
|||||||
}
|
}
|
||||||
// Check bit indexes.
|
// Check bit indexes.
|
||||||
// What is the MSB? We want the true MSB, not one starting at 0,
|
// What is the MSB? We want the true MSB, not one starting at 0,
|
||||||
// because a 4 bit index is required to look at a one-bit variable[15:15]
|
// because a 4 bit index is required to look at a one-bit variable[15:15] and 5 bits for [15:-2]
|
||||||
int frommsb = nodep->fromp()->width() - 1;
|
int frommsb = nodep->fromp()->width() - 1;
|
||||||
int fromlsb = 0;
|
int fromlsb = 0;
|
||||||
AstNodeVarRef* varrp = nodep->fromp()->castNodeVarRef();
|
int elw = nodep->declElWidth(); // Must adjust to tell user bit ranges
|
||||||
if (varrp
|
if (nodep->declRange().ranged()) {
|
||||||
&& varrp->varp()->basicp()
|
frommsb = nodep->declRange().hiMaxSelect()*elw + (elw-1); // Corrected for negative lsb
|
||||||
&& varrp->varp()->basicp()->isRanged()) { // Selecting a bit from a multibit register
|
fromlsb = nodep->declRange().lo()*elw;
|
||||||
frommsb = varrp->varp()->basicp()->msbMaxSelect(); // Corrected for negative lsb
|
} else {
|
||||||
fromlsb = varrp->varp()->basicp()->lsb();
|
//nodep->v3fatalSrc("Should have been declRanged in V3WidthSel");
|
||||||
}
|
}
|
||||||
int selwidth = V3Number::log2b(frommsb+1-1)+1; // Width to address a bit
|
int selwidth = V3Number::log2b(frommsb+1-1)+1; // Width to address a bit
|
||||||
nodep->fromp()->iterateAndNext(*this,WidthVP(selwidth,selwidth,FINAL).p());
|
nodep->fromp()->iterateAndNext(*this,WidthVP(selwidth,selwidth,FINAL).p());
|
||||||
nodep->lsbp()->iterateAndNext(*this,WidthVP(ANYSIZE,0,FINAL).p());
|
nodep->lsbp()->iterateAndNext(*this,WidthVP(ANYSIZE,0,FINAL).p());
|
||||||
if (widthBad(nodep->lsbp(),selwidth,selwidth)
|
if (widthBad(nodep->lsbp(),selwidth,selwidth)
|
||||||
&& nodep->lsbp()->width()!=32) {
|
&& nodep->lsbp()->width()!=32) {
|
||||||
nodep->v3warn(WIDTH,"Bit extraction of var["<<frommsb<<":"<<fromlsb<<"] requires "
|
|
||||||
<<selwidth<<" bit index, not "
|
|
||||||
<<nodep->lsbp()->width()
|
|
||||||
<<(nodep->lsbp()->width()!=nodep->lsbp()->widthMin()
|
|
||||||
?" or "+cvtToStr(nodep->lsbp()->widthMin()):"")
|
|
||||||
<<" bits.");
|
|
||||||
if (!nodep->fileline()->warnIsOff(V3ErrorCode::WIDTH)) {
|
if (!nodep->fileline()->warnIsOff(V3ErrorCode::WIDTH)) {
|
||||||
|
nodep->v3warn(WIDTH,"Bit extraction of var["<<(frommsb/elw)<<":"<<(fromlsb/elw)<<"] requires "
|
||||||
|
<<(selwidth/elw)<<" bit index, not "
|
||||||
|
<<(nodep->lsbp()->width()/elw)
|
||||||
|
<<(nodep->lsbp()->width()!=nodep->lsbp()->widthMin()
|
||||||
|
?" or "+cvtToStr(nodep->lsbp()->widthMin()/elw):"")
|
||||||
|
<<" bits.");
|
||||||
UINFO(1," Related node: "<<nodep<<endl);
|
UINFO(1," Related node: "<<nodep<<endl);
|
||||||
if (varrp) UINFO(1," Related var: "<<varrp->varp()<<endl);
|
|
||||||
if (varrp) UINFO(1," Related dtype: "<<varrp->varp()->dtypep()<<endl);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (nodep->lsbp()->castConst() && nodep->msbConst() > frommsb) {
|
if (nodep->lsbp()->castConst() && nodep->msbConst() > frommsb) {
|
||||||
@@ -458,8 +471,6 @@ private:
|
|||||||
<<nodep->msbConst()<<":"<<nodep->lsbConst()
|
<<nodep->msbConst()<<":"<<nodep->lsbConst()
|
||||||
<<" outside "<<frommsb<<":"<<fromlsb);
|
<<" outside "<<frommsb<<":"<<fromlsb);
|
||||||
UINFO(1," Related node: "<<nodep<<endl);
|
UINFO(1," Related node: "<<nodep<<endl);
|
||||||
if (varrp) UINFO(1," Related var: "<<varrp->varp()<<endl);
|
|
||||||
if (varrp) UINFO(1," Related dtype: "<<varrp->varp()->dtypep()<<endl);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// iterate FINAL is two blocks above
|
// iterate FINAL is two blocks above
|
||||||
@@ -482,15 +493,11 @@ private:
|
|||||||
checkCvtUS(nodep->bitp());
|
checkCvtUS(nodep->bitp());
|
||||||
//
|
//
|
||||||
nodep->fromp()->iterateAndNext(*this,WidthVP(ANYSIZE,0,PRELIM).p());
|
nodep->fromp()->iterateAndNext(*this,WidthVP(ANYSIZE,0,PRELIM).p());
|
||||||
AstNode* basefromp = AstArraySel::baseFromp(nodep->fromp());
|
|
||||||
int dimension = AstArraySel::dimension(nodep->fromp());
|
|
||||||
AstNodeVarRef* varrp = basefromp->castNodeVarRef();
|
|
||||||
if (!varrp) nodep->v3fatalSrc("No VarRef found under ArraySel(s)");
|
|
||||||
//
|
//
|
||||||
int frommsb;
|
int frommsb;
|
||||||
int fromlsb;
|
int fromlsb;
|
||||||
AstNodeDType* ddtypep = varrp->varp()->dtypep()->dtypeDimensionp(dimension);
|
AstNodeDType* fromDtp = nodep->fromp()->dtypep()->skipRefp();
|
||||||
if (AstArrayDType* adtypep = ddtypep->castArrayDType()) {
|
if (AstUnpackArrayDType* adtypep = fromDtp->castUnpackArrayDType()) {
|
||||||
frommsb = adtypep->msb();
|
frommsb = adtypep->msb();
|
||||||
fromlsb = adtypep->lsb();
|
fromlsb = adtypep->lsb();
|
||||||
if (fromlsb>frommsb) {int t=frommsb; frommsb=fromlsb; fromlsb=t; }
|
if (fromlsb>frommsb) {int t=frommsb; frommsb=fromlsb; fromlsb=t; }
|
||||||
@@ -499,6 +506,8 @@ private:
|
|||||||
nodep->dtypeFrom(adtypep->subDTypep()); // Need to strip off array reference
|
nodep->dtypeFrom(adtypep->subDTypep()); // Need to strip off array reference
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
// Note PackArrayDType doesn't use an ArraySel but a normal Sel.
|
||||||
|
UINFO(1," Related dtype: "<<fromDtp<<endl);
|
||||||
nodep->v3fatalSrc("Array reference exceeds dimension of array");
|
nodep->v3fatalSrc("Array reference exceeds dimension of array");
|
||||||
frommsb = fromlsb = 0;
|
frommsb = fromlsb = 0;
|
||||||
}
|
}
|
||||||
@@ -514,8 +523,7 @@ private:
|
|||||||
<<" bits.");
|
<<" bits.");
|
||||||
if (!nodep->fileline()->warnIsOff(V3ErrorCode::WIDTH)) {
|
if (!nodep->fileline()->warnIsOff(V3ErrorCode::WIDTH)) {
|
||||||
UINFO(1," Related node: "<<nodep<<endl);
|
UINFO(1," Related node: "<<nodep<<endl);
|
||||||
if (varrp) UINFO(1," Related var: "<<varrp->varp()<<endl);
|
UINFO(1," Related dtype: "<<nodep->dtypep()<<endl);
|
||||||
if (varrp) UINFO(1," Related depth: "<<dimension<<" dtype: "<<ddtypep<<endl);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
widthCheck(nodep,"Extract Range",nodep->bitp(),selwidth,selwidth,true);
|
widthCheck(nodep,"Extract Range",nodep->bitp(),selwidth,selwidth,true);
|
||||||
@@ -524,22 +532,34 @@ private:
|
|||||||
|
|
||||||
virtual void visit(AstSelBit* nodep, AstNUser* vup) {
|
virtual void visit(AstSelBit* nodep, AstNUser* vup) {
|
||||||
// Just a quick check as after V3Param these nodes instead are AstSel's
|
// Just a quick check as after V3Param these nodes instead are AstSel's
|
||||||
|
nodep->fromp()->iterateAndNext(*this,WidthVP(0,0,PRELIM).p()); //FINAL in AstSel
|
||||||
|
nodep->rhsp()->iterateAndNext(*this,WidthVP(0,0,PRELIM).p()); //FINAL in AstSel
|
||||||
|
nodep->thsp()->iterateAndNext(*this,WidthVP(0,0,PRELIM).p()); //FINAL in AstSel
|
||||||
nodep->attrp()->iterateAndNext(*this,WidthVP(0,0,FINAL).p());
|
nodep->attrp()->iterateAndNext(*this,WidthVP(0,0,FINAL).p());
|
||||||
AstNode* selp = V3Width::widthSelNoIterEdit(nodep); if (selp!=nodep) { nodep=NULL; selp->iterate(*this,vup); return; }
|
AstNode* selp = V3Width::widthSelNoIterEdit(nodep); if (selp!=nodep) { nodep=NULL; selp->iterate(*this,vup); return; }
|
||||||
nodep->v3fatalSrc("AstSelBit should disappear after widthSel");
|
nodep->v3fatalSrc("AstSelBit should disappear after widthSel");
|
||||||
}
|
}
|
||||||
virtual void visit(AstSelExtract* nodep, AstNUser* vup) {
|
virtual void visit(AstSelExtract* nodep, AstNUser* vup) {
|
||||||
// Just a quick check as after V3Param these nodes instead are AstSel's
|
// Just a quick check as after V3Param these nodes instead are AstSel's
|
||||||
|
nodep->fromp()->iterateAndNext(*this,WidthVP(0,0,PRELIM).p()); //FINAL in AstSel
|
||||||
|
nodep->rhsp()->iterateAndNext(*this,WidthVP(0,0,PRELIM).p()); //FINAL in AstSel
|
||||||
|
nodep->thsp()->iterateAndNext(*this,WidthVP(0,0,PRELIM).p()); //FINAL in AstSel
|
||||||
nodep->attrp()->iterateAndNext(*this,WidthVP(0,0,FINAL).p());
|
nodep->attrp()->iterateAndNext(*this,WidthVP(0,0,FINAL).p());
|
||||||
AstNode* selp = V3Width::widthSelNoIterEdit(nodep); if (selp!=nodep) { nodep=NULL; selp->iterate(*this,vup); return; }
|
AstNode* selp = V3Width::widthSelNoIterEdit(nodep); if (selp!=nodep) { nodep=NULL; selp->iterate(*this,vup); return; }
|
||||||
nodep->v3fatalSrc("AstSelExtract should disappear after widthSel");
|
nodep->v3fatalSrc("AstSelExtract should disappear after widthSel");
|
||||||
}
|
}
|
||||||
virtual void visit(AstSelPlus* nodep, AstNUser* vup) {
|
virtual void visit(AstSelPlus* nodep, AstNUser* vup) {
|
||||||
|
nodep->fromp()->iterateAndNext(*this,WidthVP(0,0,PRELIM).p()); //FINAL in AstSel
|
||||||
|
nodep->rhsp()->iterateAndNext(*this,WidthVP(0,0,PRELIM).p()); //FINAL in AstSel
|
||||||
|
nodep->thsp()->iterateAndNext(*this,WidthVP(0,0,PRELIM).p()); //FINAL in AstSel
|
||||||
nodep->attrp()->iterateAndNext(*this,WidthVP(0,0,FINAL).p());
|
nodep->attrp()->iterateAndNext(*this,WidthVP(0,0,FINAL).p());
|
||||||
AstNode* selp = V3Width::widthSelNoIterEdit(nodep); if (selp!=nodep) { nodep=NULL; selp->iterate(*this,vup); return; }
|
AstNode* selp = V3Width::widthSelNoIterEdit(nodep); if (selp!=nodep) { nodep=NULL; selp->iterate(*this,vup); return; }
|
||||||
nodep->v3fatalSrc("AstSelPlus should disappear after widthSel");
|
nodep->v3fatalSrc("AstSelPlus should disappear after widthSel");
|
||||||
}
|
}
|
||||||
virtual void visit(AstSelMinus* nodep, AstNUser* vup) {
|
virtual void visit(AstSelMinus* nodep, AstNUser* vup) {
|
||||||
|
nodep->fromp()->iterateAndNext(*this,WidthVP(0,0,PRELIM).p()); //FINAL in AstSel
|
||||||
|
nodep->rhsp()->iterateAndNext(*this,WidthVP(0,0,PRELIM).p()); //FINAL in AstSel
|
||||||
|
nodep->thsp()->iterateAndNext(*this,WidthVP(0,0,PRELIM).p()); //FINAL in AstSel
|
||||||
nodep->attrp()->iterateAndNext(*this,WidthVP(0,0,FINAL).p());
|
nodep->attrp()->iterateAndNext(*this,WidthVP(0,0,FINAL).p());
|
||||||
AstNode* selp = V3Width::widthSelNoIterEdit(nodep); if (selp!=nodep) { nodep=NULL; selp->iterate(*this,vup); return; }
|
AstNode* selp = V3Width::widthSelNoIterEdit(nodep); if (selp!=nodep) { nodep=NULL; selp->iterate(*this,vup); return; }
|
||||||
nodep->v3fatalSrc("AstSelMinus should disappear after widthSel");
|
nodep->v3fatalSrc("AstSelMinus should disappear after widthSel");
|
||||||
@@ -635,14 +655,41 @@ private:
|
|||||||
m_attrp = nodep;
|
m_attrp = nodep;
|
||||||
nodep->fromp()->iterateAndNext(*this,WidthVP(ANYSIZE,0,BOTH).p());
|
nodep->fromp()->iterateAndNext(*this,WidthVP(ANYSIZE,0,BOTH).p());
|
||||||
// Don't iterate children, don't want to lose VarRef.
|
// Don't iterate children, don't want to lose VarRef.
|
||||||
if (nodep->attrType()==AstAttrType::EXPR_BITS) {
|
if (nodep->attrType()==AstAttrType::VAR_BASE) {
|
||||||
if (!nodep->fromp() || !nodep->fromp()->widthMin()) nodep->v3fatalSrc("Unsized expression");
|
|
||||||
V3Number num (nodep->fileline(), 32, nodep->fromp()->width());
|
|
||||||
nodep->replaceWith(new AstConst(nodep->fileline(), num)); nodep->deleteTree(); nodep=NULL;
|
|
||||||
} else if (nodep->attrType()==AstAttrType::VAR_BASE) {
|
|
||||||
// Soon to be handled in V3LinkWidth SEL generation, under attrp() and newSubLsbOf
|
// Soon to be handled in V3LinkWidth SEL generation, under attrp() and newSubLsbOf
|
||||||
} else if (nodep->attrType()==AstAttrType::MEMBER_BASE) {
|
} else if (nodep->attrType()==AstAttrType::MEMBER_BASE) {
|
||||||
// Soon to be handled in V3LinkWidth SEL generation, under attrp() and newSubLsbOf
|
// Soon to be handled in V3LinkWidth SEL generation, under attrp() and newSubLsbOf
|
||||||
|
} else if (nodep->attrType()==AstAttrType::DIM_DIMENSIONS
|
||||||
|
|| nodep->attrType()==AstAttrType::DIM_UNPK_DIMENSIONS) {
|
||||||
|
if (!nodep->fromp() || !nodep->fromp()->dtypep()) nodep->v3fatalSrc("Unsized expression");
|
||||||
|
pair<uint32_t,uint32_t> dim = nodep->fromp()->dtypep()->dimensions(true);
|
||||||
|
int val = (nodep->attrType()==AstAttrType::DIM_UNPK_DIMENSIONS
|
||||||
|
? dim.second : (dim.first+dim.second));
|
||||||
|
nodep->replaceWith(new AstConst(nodep->fileline(), AstConst::Signed32(), val)); nodep->deleteTree(); nodep=NULL;
|
||||||
|
} else if (nodep->attrType()==AstAttrType::DIM_BITS
|
||||||
|
|| nodep->attrType()==AstAttrType::DIM_HIGH
|
||||||
|
|| nodep->attrType()==AstAttrType::DIM_INCREMENT
|
||||||
|
|| nodep->attrType()==AstAttrType::DIM_LEFT
|
||||||
|
|| nodep->attrType()==AstAttrType::DIM_LOW
|
||||||
|
|| nodep->attrType()==AstAttrType::DIM_RIGHT
|
||||||
|
|| nodep->attrType()==AstAttrType::DIM_SIZE) {
|
||||||
|
if (!nodep->fromp() || !nodep->fromp()->dtypep()) nodep->v3fatalSrc("Unsized expression");
|
||||||
|
pair<uint32_t,uint32_t> dim = nodep->fromp()->dtypep()->skipRefp()->dimensions(true);
|
||||||
|
uint32_t maxdim = dim.first+dim.second;
|
||||||
|
if (!nodep->dimp() || nodep->dimp()->castConst() || maxdim<1) {
|
||||||
|
int dim = !nodep->dimp() ? 1 : nodep->dimp()->castConst()->toSInt();
|
||||||
|
int val = dimensionValue(nodep->fromp()->dtypep(), nodep->attrType(), dim);
|
||||||
|
nodep->replaceWith(new AstConst(nodep->fileline(), AstConst::Signed32(), val)); nodep->deleteTree(); nodep=NULL;
|
||||||
|
}
|
||||||
|
else { // Need a runtime lookup table. Yuk.
|
||||||
|
if (!nodep->fromp() || !nodep->fromp()->dtypep()) nodep->v3fatalSrc("Unsized expression");
|
||||||
|
AstVar* varp = dimensionVarp(nodep->fromp()->dtypep(), nodep->attrType());
|
||||||
|
AstNode* dimp = nodep->dimp()->unlinkFrBack();
|
||||||
|
AstVarRef* varrefp = new AstVarRef(nodep->fileline(), varp, false);
|
||||||
|
varrefp->packagep(v3Global.rootp()->dollarUnitPkgAddp());
|
||||||
|
AstNode* newp = new AstArraySel(nodep->fileline(), varrefp, dimp);
|
||||||
|
nodep->replaceWith(newp); nodep->deleteTree(); nodep=NULL;
|
||||||
|
}
|
||||||
} else { // Everything else resolved earlier
|
} else { // Everything else resolved earlier
|
||||||
nodep->dtypeSetLogicSized(32,1,AstNumeric::UNSIGNED); // Approximation, unsized 32
|
nodep->dtypeSetLogicSized(32,1,AstNumeric::UNSIGNED); // Approximation, unsized 32
|
||||||
UINFO(1,"Missing ATTR type case node: "<<nodep<<endl);
|
UINFO(1,"Missing ATTR type case node: "<<nodep<<endl);
|
||||||
@@ -655,7 +702,7 @@ private:
|
|||||||
}
|
}
|
||||||
|
|
||||||
// DTYPES
|
// DTYPES
|
||||||
virtual void visit(AstArrayDType* nodep, AstNUser*) {
|
virtual void visit(AstNodeArrayDType* nodep, AstNUser*) {
|
||||||
if (nodep->didWidthAndSet()) return; // This node is a dtype & not both PRELIMed+FINALed
|
if (nodep->didWidthAndSet()) return; // This node is a dtype & not both PRELIMed+FINALed
|
||||||
if (nodep->childDTypep()) nodep->refDTypep(moveChildDTypeEdit(nodep));
|
if (nodep->childDTypep()) nodep->refDTypep(moveChildDTypeEdit(nodep));
|
||||||
// Iterate into subDTypep() to resolve that type and update pointer.
|
// Iterate into subDTypep() to resolve that type and update pointer.
|
||||||
@@ -663,7 +710,13 @@ private:
|
|||||||
// Cleanup array size
|
// Cleanup array size
|
||||||
nodep->rangep()->iterateAndNext(*this,WidthVP(ANYSIZE,0,BOTH).p());
|
nodep->rangep()->iterateAndNext(*this,WidthVP(ANYSIZE,0,BOTH).p());
|
||||||
nodep->dtypep(nodep); // The array itself, not subDtype
|
nodep->dtypep(nodep); // The array itself, not subDtype
|
||||||
nodep->widthFromSub(nodep->subDTypep());
|
if (nodep->castUnpackArrayDType()) {
|
||||||
|
// Historically array elements have width of the ref type not the full array
|
||||||
|
nodep->widthFromSub(nodep->subDTypep());
|
||||||
|
} else {
|
||||||
|
int width = nodep->subDTypep()->width() * nodep->rangep()->elementsConst();
|
||||||
|
nodep->widthForce(width,width);
|
||||||
|
}
|
||||||
UINFO(4,"dtWidthed "<<nodep<<endl);
|
UINFO(4,"dtWidthed "<<nodep<<endl);
|
||||||
}
|
}
|
||||||
virtual void visit(AstBasicDType* nodep, AstNUser*) {
|
virtual void visit(AstBasicDType* nodep, AstNUser*) {
|
||||||
@@ -772,7 +825,7 @@ private:
|
|||||||
nodep->dtypep(iterateEditDTypep(nodep, nodep->dtypep()));
|
nodep->dtypep(iterateEditDTypep(nodep, nodep->dtypep()));
|
||||||
if (!nodep->dtypep()) nodep->v3fatalSrc("No dtype determined for var");
|
if (!nodep->dtypep()) nodep->v3fatalSrc("No dtype determined for var");
|
||||||
if (nodep->isIO() && !(nodep->dtypeSkipRefp()->castBasicDType()
|
if (nodep->isIO() && !(nodep->dtypeSkipRefp()->castBasicDType()
|
||||||
|| nodep->dtypeSkipRefp()->castArrayDType()
|
|| nodep->dtypeSkipRefp()->castNodeArrayDType()
|
||||||
|| nodep->dtypeSkipRefp()->castNodeClassDType())) {
|
|| nodep->dtypeSkipRefp()->castNodeClassDType())) {
|
||||||
nodep->v3error("Unsupported: Inputs and outputs must be simple data types");
|
nodep->v3error("Unsupported: Inputs and outputs must be simple data types");
|
||||||
}
|
}
|
||||||
@@ -784,8 +837,8 @@ private:
|
|||||||
bool didchk = false;
|
bool didchk = false;
|
||||||
bool implicitParam = nodep->isParam() && bdtypep && bdtypep->implicit();
|
bool implicitParam = nodep->isParam() && bdtypep && bdtypep->implicit();
|
||||||
if (implicitParam) {
|
if (implicitParam) {
|
||||||
int width=0;
|
|
||||||
if (nodep->valuep()) {
|
if (nodep->valuep()) {
|
||||||
|
int width=0;
|
||||||
nodep->valuep()->iterateAndNext(*this,WidthVP(width,0,PRELIM).p());
|
nodep->valuep()->iterateAndNext(*this,WidthVP(width,0,PRELIM).p());
|
||||||
UINFO(9,"implicitParamPRELIMIV "<<nodep->valuep()<<endl);
|
UINFO(9,"implicitParamPRELIMIV "<<nodep->valuep()<<endl);
|
||||||
// Although nodep will get a different width for parameters just below,
|
// Although nodep will get a different width for parameters just below,
|
||||||
@@ -807,7 +860,19 @@ private:
|
|||||||
width = 32;
|
width = 32;
|
||||||
}
|
}
|
||||||
// Can't just inherit valuep()->dtypep() as mwidth might not equal width
|
// Can't just inherit valuep()->dtypep() as mwidth might not equal width
|
||||||
nodep->dtypeChgWidthSigned(width, nodep->valuep()->widthMin(),issigned);
|
if (width==1) {
|
||||||
|
// one bit parameter is same as "parameter [0] foo", not "parameter logic foo"
|
||||||
|
// as you can extract "foo[0]" from a parameter but not a wire
|
||||||
|
nodep->dtypeChgWidthSigned(width, nodep->valuep()->widthMin(),
|
||||||
|
issigned?AstNumeric::SIGNED : AstNumeric::UNSIGNED);
|
||||||
|
nodep->dtypep(nodep->findLogicRangeDType
|
||||||
|
(VNumRange(0,0,false),
|
||||||
|
nodep->valuep()->widthMin(),
|
||||||
|
issigned?AstNumeric::SIGNED : AstNumeric::UNSIGNED));
|
||||||
|
} else {
|
||||||
|
nodep->dtypeChgWidthSigned(width, nodep->valuep()->widthMin(),
|
||||||
|
issigned?AstNumeric::SIGNED : AstNumeric::UNSIGNED);
|
||||||
|
}
|
||||||
didchk = true;
|
didchk = true;
|
||||||
nodep->valuep()->iterateAndNext(*this,WidthVP(width,nodep->widthMin(),FINAL).p());
|
nodep->valuep()->iterateAndNext(*this,WidthVP(width,nodep->widthMin(),FINAL).p());
|
||||||
}
|
}
|
||||||
@@ -824,7 +889,9 @@ private:
|
|||||||
if (nodep->valuep()) {
|
if (nodep->valuep()) {
|
||||||
//if (debug()) nodep->dumpTree(cout," final: ");
|
//if (debug()) nodep->dumpTree(cout," final: ");
|
||||||
if (!didchk) nodep->valuep()->iterateAndNext(*this,WidthVP(nodep->dtypep()->width(),0,BOTH).p());
|
if (!didchk) nodep->valuep()->iterateAndNext(*this,WidthVP(nodep->dtypep()->width(),0,BOTH).p());
|
||||||
widthCheck(nodep,"Initial value",nodep->valuep(),nodep->width(),nodep->widthMin());
|
if (!nodep->valuep()->castInitArray()) { // No dtype at present, perhaps TODO
|
||||||
|
widthCheck(nodep,"Initial value",nodep->valuep(),nodep->width(),nodep->widthMin());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
UINFO(4,"varWidthed "<<nodep<<endl);
|
UINFO(4,"varWidthed "<<nodep<<endl);
|
||||||
//if (debug()) nodep->dumpTree(cout," InitOut: ");
|
//if (debug()) nodep->dumpTree(cout," InitOut: ");
|
||||||
@@ -925,6 +992,63 @@ private:
|
|||||||
}
|
}
|
||||||
nodep->dtypeFrom(nodep->itemp());
|
nodep->dtypeFrom(nodep->itemp());
|
||||||
}
|
}
|
||||||
|
virtual void visit(AstInitArray* nodep, AstNUser* vup) {
|
||||||
|
// Should be correct by construction, so we'll just loop through all types
|
||||||
|
nodep->iterateChildren(*this, vup);
|
||||||
|
}
|
||||||
|
virtual void visit(AstInside* nodep, AstNUser* vup) {
|
||||||
|
nodep->exprp()->iterateAndNext(*this,WidthVP(ANYSIZE,0,PRELIM).p());
|
||||||
|
for (AstNode* nextip, *itemp = nodep->itemsp(); itemp; itemp=nextip) {
|
||||||
|
nextip = itemp->nextp(); // Prelim may cause the node to get replaced
|
||||||
|
itemp->iterate(*this,WidthVP(ANYSIZE,0,PRELIM).p()); itemp=NULL;
|
||||||
|
}
|
||||||
|
// Take width as maximum across all items
|
||||||
|
int width = nodep->exprp()->width();
|
||||||
|
int mwidth = nodep->exprp()->widthMin();
|
||||||
|
for (AstNode* itemp = nodep->itemsp(); itemp; itemp=itemp->nextp()) {
|
||||||
|
width = max(width,itemp->width());
|
||||||
|
mwidth = max(mwidth,itemp->widthMin());
|
||||||
|
}
|
||||||
|
// Apply width
|
||||||
|
nodep->exprp()->iterateAndNext(*this,WidthVP(width,mwidth,FINAL).p());
|
||||||
|
for (AstNode* itemp = nodep->itemsp(); itemp; itemp=itemp->nextp()) {
|
||||||
|
widthCheck(nodep,"Inside Item",itemp,width,mwidth);
|
||||||
|
}
|
||||||
|
widthCheck(nodep,"Inside expression",nodep->exprp(),width,mwidth);
|
||||||
|
nodep->dtypeSetLogicBool();
|
||||||
|
if (debug()>=9) nodep->dumpTree(cout,"-inside-in: ");
|
||||||
|
// Now rip out the inside and replace with simple math
|
||||||
|
AstNode* newp = NULL;
|
||||||
|
for (AstNode* nextip, *itemp = nodep->itemsp(); itemp; itemp=nextip) {
|
||||||
|
nextip = itemp->nextp(); // Will be unlinking
|
||||||
|
AstNode* inewp;
|
||||||
|
if (AstInsideRange* irangep = itemp->castInsideRange()) {
|
||||||
|
inewp = new AstAnd(itemp->fileline(),
|
||||||
|
new AstGte(itemp->fileline(),
|
||||||
|
nodep->exprp()->cloneTree(true),
|
||||||
|
irangep->lhsp()->unlinkFrBack()),
|
||||||
|
new AstLte(itemp->fileline(),
|
||||||
|
nodep->exprp()->cloneTree(true),
|
||||||
|
irangep->rhsp()->unlinkFrBack()));
|
||||||
|
} else {
|
||||||
|
inewp = new AstEqWild(itemp->fileline(),
|
||||||
|
nodep->exprp()->cloneTree(true),
|
||||||
|
itemp->unlinkFrBack());
|
||||||
|
}
|
||||||
|
if (newp) newp = new AstOr(nodep->fileline(), newp, inewp);
|
||||||
|
else newp = inewp;
|
||||||
|
}
|
||||||
|
if (!newp) newp = new AstConst(nodep->fileline(), AstConst::LogicFalse());
|
||||||
|
if (debug()>=9) newp->dumpTree(cout,"-inside-out: ");
|
||||||
|
nodep->replaceWith(newp); pushDeletep(nodep); nodep=NULL;
|
||||||
|
}
|
||||||
|
virtual void visit(AstInsideRange* nodep, AstNUser* vup) {
|
||||||
|
// Just do each side; AstInside will rip these nodes out later
|
||||||
|
nodep->lhsp()->iterateAndNext(*this,vup);
|
||||||
|
nodep->rhsp()->iterateAndNext(*this,vup);
|
||||||
|
nodep->dtypeFrom(nodep->lhsp());
|
||||||
|
}
|
||||||
|
|
||||||
virtual void visit(AstNodeClassDType* nodep, AstNUser* vup) {
|
virtual void visit(AstNodeClassDType* nodep, AstNUser* vup) {
|
||||||
if (nodep->didWidthAndSet()) return; // This node is a dtype & not both PRELIMed+FINALed
|
if (nodep->didWidthAndSet()) return; // This node is a dtype & not both PRELIMed+FINALed
|
||||||
UINFO(5," NODECLASS "<<nodep<<endl);
|
UINFO(5," NODECLASS "<<nodep<<endl);
|
||||||
@@ -1142,12 +1266,10 @@ private:
|
|||||||
|
|
||||||
virtual void visit(AstNodeCase* nodep, AstNUser*) {
|
virtual void visit(AstNodeCase* nodep, AstNUser*) {
|
||||||
// TOP LEVEL NODE
|
// TOP LEVEL NODE
|
||||||
AstNodeCase* lastCasep = m_casep;
|
|
||||||
m_casep = nodep;
|
|
||||||
nodep->exprp()->iterateAndNext(*this,WidthVP(ANYSIZE,0,PRELIM).p());
|
nodep->exprp()->iterateAndNext(*this,WidthVP(ANYSIZE,0,PRELIM).p());
|
||||||
for (AstCaseItem* nextip, *itemp = nodep->itemsp(); itemp; itemp=nextip) {
|
for (AstCaseItem* nextip, *itemp = nodep->itemsp(); itemp; itemp=nextip) {
|
||||||
nextip = itemp->nextp()->castCaseItem(); // Prelim may cause the node to get replaced
|
nextip = itemp->nextp()->castCaseItem(); // Prelim may cause the node to get replaced
|
||||||
if (!m_casep->castGenCase()) itemp->bodysp()->iterateAndNext(*this);
|
if (!nodep->castGenCase()) itemp->bodysp()->iterateAndNext(*this);
|
||||||
for (AstNode* nextcp, *condp = itemp->condsp(); condp; condp=nextcp) {
|
for (AstNode* nextcp, *condp = itemp->condsp(); condp; condp=nextcp) {
|
||||||
nextcp = condp->nextp(); // Prelim may cause the node to get replaced
|
nextcp = condp->nextp(); // Prelim may cause the node to get replaced
|
||||||
condp->iterate(*this,WidthVP(ANYSIZE,0,PRELIM).p()); condp=NULL;
|
condp->iterate(*this,WidthVP(ANYSIZE,0,PRELIM).p()); condp=NULL;
|
||||||
@@ -1171,7 +1293,6 @@ private:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
widthCheck(nodep,"Case expression",nodep->exprp(),width,mwidth);
|
widthCheck(nodep,"Case expression",nodep->exprp(),width,mwidth);
|
||||||
m_casep = lastCasep;
|
|
||||||
}
|
}
|
||||||
virtual void visit(AstNodeFor* nodep, AstNUser*) {
|
virtual void visit(AstNodeFor* nodep, AstNUser*) {
|
||||||
// TOP LEVEL NODE
|
// TOP LEVEL NODE
|
||||||
@@ -1210,11 +1331,13 @@ private:
|
|||||||
//if (debug()) nodep->dumpTree(cout," AssignPre: ");
|
//if (debug()) nodep->dumpTree(cout," AssignPre: ");
|
||||||
AstNodeDType* oldAssDTypep = m_assDTypep;
|
AstNodeDType* oldAssDTypep = m_assDTypep;
|
||||||
{
|
{
|
||||||
|
//if (debug()) nodep->dumpTree(cout,"- assin: ");
|
||||||
nodep->lhsp()->iterateAndNext(*this,WidthVP(ANYSIZE,0,BOTH).p());
|
nodep->lhsp()->iterateAndNext(*this,WidthVP(ANYSIZE,0,BOTH).p());
|
||||||
if (!nodep->lhsp()->dtypep()) nodep->v3fatalSrc("How can LHS be untyped?");
|
if (!nodep->lhsp()->dtypep()) nodep->v3fatalSrc("How can LHS be untyped?");
|
||||||
if (!nodep->lhsp()->dtypep()->widthSized()) nodep->v3fatalSrc("How can LHS be unsized?");
|
if (!nodep->lhsp()->dtypep()->widthSized()) nodep->v3fatalSrc("How can LHS be unsized?");
|
||||||
m_assDTypep = nodep->lhsp()->dtypep();
|
m_assDTypep = nodep->lhsp()->dtypep();
|
||||||
nodep->rhsp()->iterateAndNext(*this,WidthVP(ANYSIZE,0,PRELIM).p());
|
nodep->rhsp()->iterateAndNext(*this,WidthVP(ANYSIZE,0,PRELIM).p());
|
||||||
|
//if (debug()) nodep->dumpTree(cout,"- assign: ");
|
||||||
if (!nodep->lhsp()->isDouble() && nodep->rhsp()->isDouble()) {
|
if (!nodep->lhsp()->isDouble() && nodep->rhsp()->isDouble()) {
|
||||||
spliceCvtS(nodep->rhsp(), false); // Round RHS
|
spliceCvtS(nodep->rhsp(), false); // Round RHS
|
||||||
} else if (nodep->lhsp()->isDouble() && !nodep->rhsp()->isDouble()) {
|
} else if (nodep->lhsp()->isDouble() && !nodep->rhsp()->isDouble()) {
|
||||||
@@ -1345,8 +1468,8 @@ private:
|
|||||||
virtual void visit(AstReadMem* nodep, AstNUser*) {
|
virtual void visit(AstReadMem* nodep, AstNUser*) {
|
||||||
nodep->filenamep()->iterateAndNext(*this,WidthVP(ANYSIZE,0,BOTH).p());
|
nodep->filenamep()->iterateAndNext(*this,WidthVP(ANYSIZE,0,BOTH).p());
|
||||||
nodep->memp()->iterateAndNext(*this,WidthVP(ANYSIZE,0,BOTH).p());
|
nodep->memp()->iterateAndNext(*this,WidthVP(ANYSIZE,0,BOTH).p());
|
||||||
if (!nodep->memp()->dtypep()->skipRefp()->castArrayDType()) {
|
if (!nodep->memp()->dtypep()->skipRefp()->castUnpackArrayDType()) {
|
||||||
nodep->memp()->v3error("Unsupported: $readmem into non-array");
|
nodep->memp()->v3error("Unsupported: $readmem into other than unpacked array");
|
||||||
}
|
}
|
||||||
nodep->lsbp()->iterateAndNext(*this,WidthVP(ANYSIZE,0,BOTH).p());
|
nodep->lsbp()->iterateAndNext(*this,WidthVP(ANYSIZE,0,BOTH).p());
|
||||||
nodep->msbp()->iterateAndNext(*this,WidthVP(ANYSIZE,0,BOTH).p());
|
nodep->msbp()->iterateAndNext(*this,WidthVP(ANYSIZE,0,BOTH).p());
|
||||||
@@ -1424,6 +1547,16 @@ private:
|
|||||||
// otherwise would need some mess to force both sides to proper size
|
// otherwise would need some mess to force both sides to proper size
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// TODO Simple dtype checking, should be a more general check
|
||||||
|
bool hiArray = nodep->exprp()->dtypep()->skipRefp()->castUnpackArrayDType();
|
||||||
|
bool loArray = nodep->modVarp()->dtypep()->skipRefp()->castUnpackArrayDType();
|
||||||
|
if (loArray != hiArray) {
|
||||||
|
nodep->v3error("Illegal port connection '"<<nodep->prettyName()<<"',"
|
||||||
|
<<" mismatch between port which is"<<(hiArray?"":" not")<<" an array,"
|
||||||
|
<<" and expression which is"<<(loArray?"":" not")<<" an array.");
|
||||||
|
UINFO(1," Related lo: "<<nodep->exprp()->dtypep()->skipRefp()<<endl);
|
||||||
|
UINFO(1," Related hi: "<<nodep->modVarp()->dtypep()->skipRefp()<<endl);
|
||||||
|
}
|
||||||
if (inputPin) {
|
if (inputPin) {
|
||||||
// input pin is lhs, expr is rhs; resize expr to match
|
// input pin is lhs, expr is rhs; resize expr to match
|
||||||
awidth = pinwidth;
|
awidth = pinwidth;
|
||||||
@@ -1863,7 +1996,8 @@ private:
|
|||||||
int width = max(vup->c()->width(), max(nodep->lhsp()->width(), nodep->rhsp()->width()));
|
int width = max(vup->c()->width(), max(nodep->lhsp()->width(), nodep->rhsp()->width()));
|
||||||
int mwidth = max(vup->c()->widthMin(), max(nodep->lhsp()->widthMin(), nodep->rhsp()->widthMin()));
|
int mwidth = max(vup->c()->widthMin(), max(nodep->lhsp()->widthMin(), nodep->rhsp()->widthMin()));
|
||||||
bool expSigned = (nodep->lhsp()->isSigned() && nodep->rhsp()->isSigned());
|
bool expSigned = (nodep->lhsp()->isSigned() && nodep->rhsp()->isSigned());
|
||||||
nodep->dtypeChgWidthSigned(width,mwidth,expSigned);
|
nodep->dtypeChgWidthSigned(width,mwidth,
|
||||||
|
expSigned?AstNumeric::SIGNED : AstNumeric::UNSIGNED);
|
||||||
if (vup->c()->final()) {
|
if (vup->c()->final()) {
|
||||||
// Final call, so make sure children check their sizes
|
// Final call, so make sure children check their sizes
|
||||||
nodep->lhsp()->iterateAndNext(*this,WidthVP(width,mwidth,FINAL).p());
|
nodep->lhsp()->iterateAndNext(*this,WidthVP(width,mwidth,FINAL).p());
|
||||||
@@ -2034,7 +2168,8 @@ private:
|
|||||||
linker.relink(newp);
|
linker.relink(newp);
|
||||||
nodep=newp;
|
nodep=newp;
|
||||||
}
|
}
|
||||||
nodep->dtypeChgWidthSigned(expWidth,expWidth,expSigned);
|
nodep->dtypeChgWidthSigned(expWidth,expWidth,
|
||||||
|
expSigned?AstNumeric::SIGNED : AstNumeric::UNSIGNED);
|
||||||
UINFO(4," _new: "<<nodep<<endl);
|
UINFO(4," _new: "<<nodep<<endl);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2330,6 +2465,99 @@ private:
|
|||||||
return nodep;
|
return nodep;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int dimensionValue(AstNodeDType* nodep, AstAttrType attrType, int dim) {
|
||||||
|
// Return the dimension value for the specified attribute and constant dimension
|
||||||
|
AstNodeDType* dtypep = nodep->skipRefp();
|
||||||
|
VNumRange declRange; // ranged() set false
|
||||||
|
for (int i = 1; i <= dim; ++i) {
|
||||||
|
//UINFO(9, " dim at "<<dim<<" "<<dtypep<<endl);
|
||||||
|
declRange = VNumRange(); // ranged() set false
|
||||||
|
if (AstNodeArrayDType* adtypep = dtypep->castNodeArrayDType()) {
|
||||||
|
declRange = adtypep->declRange();
|
||||||
|
if (i<dim) dtypep = adtypep->subDTypep()->skipRefp();
|
||||||
|
continue;
|
||||||
|
} else if (AstNodeClassDType* adtypep = dtypep->castNodeClassDType()) {
|
||||||
|
declRange = adtypep->declRange();
|
||||||
|
if (adtypep) {} // UNUSED
|
||||||
|
break; // Sub elements don't look like arrays and can't iterate into
|
||||||
|
} else if (AstBasicDType* adtypep = dtypep->castBasicDType()) {
|
||||||
|
if (adtypep->isRanged()) declRange = adtypep->declRange();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
int val = 0;
|
||||||
|
if (attrType==AstAttrType::DIM_BITS) {
|
||||||
|
int bits = 1;
|
||||||
|
while (dtypep) {
|
||||||
|
//UINFO(9, " bits at "<<bits<<" "<<dtypep<<endl);
|
||||||
|
if (AstNodeArrayDType* adtypep = dtypep->castNodeArrayDType()) {
|
||||||
|
bits *= adtypep->declRange().elements();
|
||||||
|
dtypep = adtypep->subDTypep()->skipRefp();
|
||||||
|
continue;
|
||||||
|
} else if (AstNodeClassDType* adtypep = dtypep->castNodeClassDType()) {
|
||||||
|
bits *= adtypep->width();
|
||||||
|
break;
|
||||||
|
} else if (AstBasicDType* adtypep = dtypep->castBasicDType()) {
|
||||||
|
bits *= adtypep->width();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (dim == 0) {
|
||||||
|
val = 0;
|
||||||
|
} else if (dim == 1 && !declRange.ranged() && bits==1) { // $bits should be sane for non-arrays
|
||||||
|
val = nodep->width();
|
||||||
|
} else {
|
||||||
|
val = bits;
|
||||||
|
}
|
||||||
|
} else if (attrType==AstAttrType::DIM_HIGH) {
|
||||||
|
val = !declRange.ranged() ? 0 : declRange.hi();
|
||||||
|
} else if (attrType==AstAttrType::DIM_LEFT) {
|
||||||
|
val = !declRange.ranged() ? 0 : declRange.left();
|
||||||
|
} else if (attrType==AstAttrType::DIM_LOW) {
|
||||||
|
val = !declRange.ranged() ? 0 : declRange.lo();
|
||||||
|
} else if (attrType==AstAttrType::DIM_RIGHT) {
|
||||||
|
val = !declRange.ranged() ? 0 : declRange.right();
|
||||||
|
} else if (attrType==AstAttrType::DIM_INCREMENT) {
|
||||||
|
val = (declRange.ranged() && declRange.littleEndian()) ? -1 : 1;
|
||||||
|
} else if (attrType==AstAttrType::DIM_SIZE) {
|
||||||
|
val = !declRange.ranged() ? 0 : declRange.elements();
|
||||||
|
} else {
|
||||||
|
nodep->v3fatalSrc("Missing DIM ATTR type case");
|
||||||
|
}
|
||||||
|
UINFO(9," $dimension "<<attrType.ascii()<<"("<<((void*)dtypep)<<","<<dim<<")="<<val<<endl);
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
AstVar* dimensionVarp(AstNodeDType* nodep, AstAttrType attrType) {
|
||||||
|
// Return a variable table which has specified dimension properties for this variable
|
||||||
|
pair<uint32_t,uint32_t> dim = nodep->skipRefp()->dimensions(true);
|
||||||
|
uint32_t maxdim = dim.first+dim.second;
|
||||||
|
//
|
||||||
|
AstInitArray* initp = new AstInitArray (nodep->fileline(), NULL);
|
||||||
|
AstNodeDType* vardtypep = new AstUnpackArrayDType(nodep->fileline(),
|
||||||
|
nodep->findSigned32DType(),
|
||||||
|
new AstRange(nodep->fileline(), maxdim, 0));
|
||||||
|
v3Global.rootp()->typeTablep()->addTypesp(vardtypep);
|
||||||
|
AstVar* varp = new AstVar (nodep->fileline(), AstVarType::MODULETEMP,
|
||||||
|
"__Vdimtable" + cvtToStr(m_dtTables++),
|
||||||
|
vardtypep);
|
||||||
|
varp->isConst(true);
|
||||||
|
varp->isStatic(true);
|
||||||
|
varp->valuep(initp);
|
||||||
|
// Add to root, as don't know module we are in, and aids later structure sharing
|
||||||
|
v3Global.rootp()->dollarUnitPkgAddp()->addStmtp(varp);
|
||||||
|
// Element 0 is a non-index and has speced values
|
||||||
|
initp->addInitsp(new AstConst(nodep->fileline(), AstConst::Signed32(),
|
||||||
|
dimensionValue(nodep, attrType, 0)));
|
||||||
|
for (unsigned i=1; i<maxdim+1; ++i) {
|
||||||
|
initp->addInitsp(new AstConst(nodep->fileline(), AstConst::Signed32(),
|
||||||
|
dimensionValue(nodep, attrType, i)));
|
||||||
|
}
|
||||||
|
varp->iterate(*this); // May have already done $unit so must do this var
|
||||||
|
return varp;
|
||||||
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------
|
//----------------------------------------------------------------------
|
||||||
// METHODS - special type detection
|
// METHODS - special type detection
|
||||||
bool backRequiresUnsigned(AstNode* nodep) {
|
bool backRequiresUnsigned(AstNode* nodep) {
|
||||||
@@ -2337,6 +2565,15 @@ private:
|
|||||||
// index is NOT wide enough, you do not sign extend, but always zero extend.
|
// index is NOT wide enough, you do not sign extend, but always zero extend.
|
||||||
return (nodep->castArraySel() || nodep->castSel());
|
return (nodep->castArraySel() || nodep->castSel());
|
||||||
}
|
}
|
||||||
|
void checkConstantOrReplace(AstNode* nodep, const string& message) {
|
||||||
|
// See also V3WidthSel::checkConstantOrReplace
|
||||||
|
// Note can't call V3Const::constifyParam(nodep) here, as constify may change nodep on us!
|
||||||
|
if (!nodep->castConst()) {
|
||||||
|
nodep->v3error(message);
|
||||||
|
nodep->replaceWith(new AstConst(nodep->fileline(), AstConst::Unsized32(), 1));
|
||||||
|
pushDeletep(nodep); nodep=NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// CONSTUCTORS
|
// CONSTUCTORS
|
||||||
@@ -2345,12 +2582,12 @@ public:
|
|||||||
// // don't wish to trigger errors
|
// // don't wish to trigger errors
|
||||||
m_paramsOnly = paramsOnly;
|
m_paramsOnly = paramsOnly;
|
||||||
m_cellRangep = NULL;
|
m_cellRangep = NULL;
|
||||||
m_casep = NULL;
|
|
||||||
m_funcp = NULL;
|
m_funcp = NULL;
|
||||||
m_initialp = NULL;
|
m_initialp = NULL;
|
||||||
m_attrp = NULL;
|
m_attrp = NULL;
|
||||||
m_assDTypep = NULL;
|
m_assDTypep = NULL;
|
||||||
m_doGenerate = doGenerate;
|
m_doGenerate = doGenerate;
|
||||||
|
m_dtTables = 0;
|
||||||
}
|
}
|
||||||
AstNode* mainAcceptEdit(AstNode* nodep) {
|
AstNode* mainAcceptEdit(AstNode* nodep) {
|
||||||
return nodep->acceptSubtreeReturnEdits(*this, WidthVP(ANYSIZE,0,BOTH).p());
|
return nodep->acceptSubtreeReturnEdits(*this, WidthVP(ANYSIZE,0,BOTH).p());
|
||||||
|
|||||||
+171
-138
@@ -51,11 +51,6 @@ private:
|
|||||||
// complicated GenCase/GenFor/Cell/Function call logic that all depends
|
// complicated GenCase/GenFor/Cell/Function call logic that all depends
|
||||||
// on if widthing top-down or just for parameters.
|
// on if widthing top-down or just for parameters.
|
||||||
#define iterateChildren DO_NOT_iterateChildern_IN_V3WidthSel
|
#define iterateChildren DO_NOT_iterateChildern_IN_V3WidthSel
|
||||||
//
|
|
||||||
// NODE STATE
|
|
||||||
// isBelowSeled() used insead of userp, as we're out of
|
|
||||||
// non-conflicting users, and having a persistent variable means this
|
|
||||||
// code can be skipped during most later stage constification calls.
|
|
||||||
|
|
||||||
// METHODS
|
// METHODS
|
||||||
static int debug() {
|
static int debug() {
|
||||||
@@ -65,6 +60,7 @@ private:
|
|||||||
}
|
}
|
||||||
|
|
||||||
void checkConstantOrReplace(AstNode* nodep, const string& message) {
|
void checkConstantOrReplace(AstNode* nodep, const string& message) {
|
||||||
|
// See also V3Width::checkConstantOrReplace
|
||||||
// Note can't call V3Const::constifyParam(nodep) here, as constify may change nodep on us!
|
// Note can't call V3Const::constifyParam(nodep) here, as constify may change nodep on us!
|
||||||
if (!nodep->castConst()) {
|
if (!nodep->castConst()) {
|
||||||
nodep->v3error(message);
|
nodep->v3error(message);
|
||||||
@@ -73,32 +69,53 @@ private:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
AstNodeDType* dtypeForExtractp(AstNode* nodep, AstNode* basefromp, int dimension, bool rangedSelect) {
|
// RETURN TYPE
|
||||||
// Perform error checks on the node
|
struct FromData {
|
||||||
AstNode* errp;
|
AstNode* m_errp; // Node that was found, for error reporting if not known type
|
||||||
AstNodeDType* bfdtypep = baseDTypeFrom(basefromp, errp/*ref*/);
|
AstNodeDType* m_dtypep; // Data type for the 'from' slice
|
||||||
//UINFO(9,"SCD\n"); if (debug()>=9) bfdtypep->dumpTree(cout,"-dtfexvar: ");
|
VNumRange m_fromRange; // Numeric range bounds for the 'from' slice
|
||||||
// This may be called on dotted variables before we've completed widthing of the dotted var.
|
FromData(AstNode* errp, AstNodeDType* dtypep, VNumRange fromRange)
|
||||||
AstNodeDType* ddtypep = bfdtypep;
|
{ m_errp=errp; m_dtypep=dtypep; m_fromRange=fromRange; }
|
||||||
ddtypep = ddtypep->dtypeDimensionp(dimension);
|
~FromData() {}
|
||||||
if (debug()>=9 &&ddtypep) ddtypep->dumpTree(cout,"-ddtypep: ");
|
};
|
||||||
if (AstArrayDType* adtypep = ddtypep->castArrayDType()) {
|
FromData fromDataForArray(AstNode* nodep, AstNode* basefromp, bool rangedSelect) {
|
||||||
return adtypep;
|
// What is the data type and information for this SEL-ish's from()?
|
||||||
|
UINFO(9," fromData start ddtypep = "<<basefromp<<endl);
|
||||||
|
VNumRange fromRange; // constructs to isRanged(false)
|
||||||
|
while (basefromp) {
|
||||||
|
if (basefromp->castAttrOf()) {
|
||||||
|
basefromp = basefromp->castAttrOf()->fromp();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (!basefromp || !basefromp->dtypep()) nodep->v3fatalSrc("Select with no from dtype");
|
||||||
|
AstNodeDType* ddtypep = basefromp->dtypep()->skipRefp();
|
||||||
|
AstNode* errp = ddtypep;
|
||||||
|
UINFO(9," fromData.ddtypep = "<<ddtypep<<endl);
|
||||||
|
if (AstNodeArrayDType* adtypep = ddtypep->castNodeArrayDType()) {
|
||||||
|
fromRange = adtypep->declRange();
|
||||||
}
|
}
|
||||||
else if (AstNodeClassDType* adtypep = ddtypep->castNodeClassDType()) {
|
else if (AstNodeClassDType* adtypep = ddtypep->castNodeClassDType()) {
|
||||||
return adtypep;
|
fromRange = adtypep->declRange();
|
||||||
}
|
}
|
||||||
else if (AstBasicDType* adtypep = ddtypep->castBasicDType()) {
|
else if (AstBasicDType* adtypep = ddtypep->castBasicDType()) {
|
||||||
if (!adtypep->isRanged()) {
|
if (adtypep->isRanged()) {
|
||||||
nodep->v3error("Illegal bit select; variable does not have a bit range, or bad dimension: "<<errp->prettyName());
|
if (adtypep->rangep()
|
||||||
return NULL;
|
&& (!adtypep->rangep()->msbp()->castConst()
|
||||||
|
|| !adtypep->rangep()->lsbp()->castConst()))
|
||||||
|
nodep->v3fatalSrc("Non-constant variable range; errored earlier"); // in constifyParam(bfdtypep)
|
||||||
|
fromRange = adtypep->declRange();
|
||||||
|
} else {
|
||||||
|
nodep->v3error("Illegal bit or array select; type does not have a bit range, or bad dimension: type is "
|
||||||
|
<<errp->prettyName());
|
||||||
}
|
}
|
||||||
return adtypep;
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
nodep->v3error("Illegal bit or array select; variable already selected, or bad dimension: "<<errp->prettyName());
|
nodep->v3error("Illegal bit or array select; type already selected, or bad dimension: type is "
|
||||||
|
<<errp->prettyName());
|
||||||
}
|
}
|
||||||
return NULL;
|
return FromData(errp,ddtypep,fromRange);
|
||||||
}
|
}
|
||||||
|
|
||||||
AstNode* newSubNeg(AstNode* lhsp, vlsint32_t rhs) {
|
AstNode* newSubNeg(AstNode* lhsp, vlsint32_t rhs) {
|
||||||
@@ -137,47 +154,22 @@ private:
|
|||||||
return newp;
|
return newp;
|
||||||
}
|
}
|
||||||
|
|
||||||
AstNodeDType* baseDTypeFrom(AstNode* basefromp, AstNode*& errpr) {
|
AstNode* newSubLsbOf(AstNode* underp, VNumRange fromRange) {
|
||||||
errpr = basefromp;
|
|
||||||
if (AstNodeVarRef* varrefp = basefromp->castNodeVarRef()) {
|
|
||||||
AstVar* varp = varrefp->varp(); if (!varp) { varrefp->v3fatalSrc("Signal not linked"); return NULL; }
|
|
||||||
errpr = varp;
|
|
||||||
AstNodeDType* bfdtypep = varp->subDTypep();
|
|
||||||
if (!bfdtypep) basefromp->v3fatalSrc("No datatype found for variable in select");
|
|
||||||
return bfdtypep;
|
|
||||||
} else if (AstMemberSel* selp = basefromp->castMemberSel()) {
|
|
||||||
errpr = selp;
|
|
||||||
AstNodeDType* bfdtypep = selp->dtypep();
|
|
||||||
if (!bfdtypep) basefromp->v3fatalSrc("No datatype found for variable in select");
|
|
||||||
return bfdtypep;
|
|
||||||
} else {
|
|
||||||
basefromp->v3fatalSrc("Bit/array selection of non-variable");
|
|
||||||
}
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
AstNode* newSubLsbOf(AstNode* underp, AstNode* basefromp) {
|
|
||||||
// Account for a variable's LSB in bit selections
|
// Account for a variable's LSB in bit selections
|
||||||
// Will likely become SUB(underp, lsb_of_signal)
|
// Will likely become SUB(underp, lsb_of_signal)
|
||||||
// Don't report WIDTH warnings etc here, as may be inside a generate branch that will be deleted
|
// Don't report WIDTH warnings etc here, as may be inside a generate branch that will be deleted
|
||||||
AstNode* errp;
|
|
||||||
AstNodeDType* bfdtypep = baseDTypeFrom(basefromp, errp/*ref*/);
|
|
||||||
// SUB #'s Not needed when LSB==0 and MSB>=0 (ie [0:-13] must still get added!)
|
// SUB #'s Not needed when LSB==0 and MSB>=0 (ie [0:-13] must still get added!)
|
||||||
if (!bfdtypep->basicp()->isRanged()) {
|
if (!fromRange.ranged()) {
|
||||||
// vector without range, or 0 lsb is ok, for example a INTEGER x; y = x[21:0];
|
// vector without range, or 0 lsb is ok, for example a INTEGER x; y = x[21:0];
|
||||||
return underp;
|
return underp;
|
||||||
} else {
|
} else {
|
||||||
if (bfdtypep->basicp()->rangep()
|
if (fromRange.littleEndian()) {
|
||||||
&& (!bfdtypep->basicp()->rangep()->msbp()->castConst()
|
|
||||||
|| !bfdtypep->basicp()->rangep()->lsbp()->castConst()))
|
|
||||||
bfdtypep->v3fatalSrc("Non-constant variable range; errored earlier"); // in constifyParam(bfdtypep)
|
|
||||||
if (bfdtypep->basicp()->littleEndian()) {
|
|
||||||
// reg [1:3] was swapped to [3:1] (lsbEndianedp==3) and needs a SUB(3,under)
|
// reg [1:3] was swapped to [3:1] (lsbEndianedp==3) and needs a SUB(3,under)
|
||||||
AstNode* newp = newSubNeg(bfdtypep->basicp()->msb(), underp);
|
AstNode* newp = newSubNeg(fromRange.hi(), underp);
|
||||||
return newp;
|
return newp;
|
||||||
} else {
|
} else {
|
||||||
// reg [3:1] needs a SUB(under,1)
|
// reg [3:1] needs a SUB(under,1)
|
||||||
AstNode* newp = newSubNeg(underp, bfdtypep->basicp()->lsb());
|
AstNode* newp = newSubNeg(underp, fromRange.lo());
|
||||||
return newp;
|
return newp;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -186,118 +178,146 @@ private:
|
|||||||
// VISITORS
|
// VISITORS
|
||||||
// If adding new visitors, insure V3Width's visit(TYPE) calls into here
|
// If adding new visitors, insure V3Width's visit(TYPE) calls into here
|
||||||
|
|
||||||
virtual void visit(AstRange* nodep, AstNUser*) {
|
|
||||||
// Convert all range values to constants
|
|
||||||
UINFO(6,"RANGE "<<nodep<<endl);
|
|
||||||
V3Const::constifyParamsEdit(nodep->msbp()); // May relink pointed to node
|
|
||||||
V3Const::constifyParamsEdit(nodep->lsbp()); // May relink pointed to node
|
|
||||||
checkConstantOrReplace(nodep->msbp(), "MSB of bit range isn't a constant");
|
|
||||||
checkConstantOrReplace(nodep->lsbp(), "LSB of bit range isn't a constant");
|
|
||||||
int msb = nodep->msbConst();
|
|
||||||
int lsb = nodep->lsbConst();
|
|
||||||
if (msb<lsb) {
|
|
||||||
// If it's an array, ok to have either ordering, we'll just correct
|
|
||||||
// So, see if we're sitting under a variable's arrayp.
|
|
||||||
AstNode* huntbackp = nodep;
|
|
||||||
while (huntbackp->backp()->castRange()) huntbackp=huntbackp->backp();
|
|
||||||
if (huntbackp->backp()->castArrayDType()) {
|
|
||||||
} else {
|
|
||||||
// Little endian bits are legal, just remember to swap
|
|
||||||
// Warning is in V3Width to avoid false warnings when in "off" generate if's
|
|
||||||
nodep->littleEndian(!nodep->littleEndian());
|
|
||||||
}
|
|
||||||
// Internally we'll always have msb() be the greater number
|
|
||||||
// We only need to correct when doing [] AstSel extraction,
|
|
||||||
// and when tracing the vector.
|
|
||||||
nodep->msbp()->swapWith(nodep->lsbp());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual void visit(AstSelBit* nodep, AstNUser*) {
|
virtual void visit(AstSelBit* nodep, AstNUser*) {
|
||||||
|
// Select of a non-width specified part of an array, i.e. "array[2]"
|
||||||
|
// This select style has a lsb and msb (no user specified width)
|
||||||
UINFO(6,"SELBIT "<<nodep<<endl);
|
UINFO(6,"SELBIT "<<nodep<<endl);
|
||||||
if (debug()>=9) nodep->backp()->dumpTree(cout,"-vsbin(-1): ");
|
if (debug()>=9) nodep->backp()->dumpTree(cout,"--SELBT0: ");
|
||||||
// lhsp/rhsp do not need to be constant
|
// lhsp/rhsp do not need to be constant
|
||||||
AstNode* basefromp = AstArraySel::baseFromp(nodep->attrp());
|
|
||||||
int dimension = AstArraySel::dimension(nodep->fromp()); // Not attrp as need hierarchy
|
|
||||||
AstNodeDType* ddtypep = dtypeForExtractp(nodep, basefromp, dimension, false);
|
|
||||||
AstNode* fromp = nodep->lhsp()->unlinkFrBack();
|
AstNode* fromp = nodep->lhsp()->unlinkFrBack();
|
||||||
AstNode* rhsp = nodep->rhsp()->unlinkFrBack(); // bit we're extracting
|
AstNode* rhsp = nodep->rhsp()->unlinkFrBack(); // bit we're extracting
|
||||||
if (debug()>=9) ddtypep->dumpTree(cout,"-ddtypep: ");
|
if (debug()>=9) nodep->dumpTree(cout,"--SELBT2: ");
|
||||||
if (debug()>=9) nodep->dumpTree(cout,"-vsbmd: ");
|
FromData fromdata = fromDataForArray(nodep, fromp, false);
|
||||||
if (AstArrayDType* adtypep = ddtypep->castArrayDType()) {
|
AstNodeDType* ddtypep = fromdata.m_dtypep;
|
||||||
|
VNumRange fromRange = fromdata.m_fromRange;
|
||||||
|
UINFO(6," ddtypep "<<ddtypep<<endl);
|
||||||
|
if (AstUnpackArrayDType* adtypep = ddtypep->castUnpackArrayDType()) {
|
||||||
// SELBIT(array, index) -> ARRAYSEL(array, index)
|
// SELBIT(array, index) -> ARRAYSEL(array, index)
|
||||||
AstNode* subp = rhsp;
|
AstNode* subp = rhsp;
|
||||||
if (adtypep->lsb()!=0 || adtypep->msb()<0) {
|
if (fromRange.lo()!=0 || fromRange.hi()<0) {
|
||||||
subp = newSubNeg (subp, adtypep->lsb());
|
subp = newSubNeg (subp, fromRange.lo());
|
||||||
}
|
}
|
||||||
AstArraySel* newp = new AstArraySel (nodep->fileline(),
|
AstArraySel* newp = new AstArraySel (nodep->fileline(),
|
||||||
fromp, subp);
|
fromp, subp);
|
||||||
UINFO(6," newd"<<dimension<<" "<<newp<<endl);
|
newp->dtypeFrom(adtypep->subDTypep()); // Need to strip off array reference
|
||||||
|
if (debug()>=9) newp->dumpTree(cout,"--SELBTn: ");
|
||||||
nodep->replaceWith(newp); pushDeletep(nodep); nodep=NULL;
|
nodep->replaceWith(newp); pushDeletep(nodep); nodep=NULL;
|
||||||
}
|
}
|
||||||
else if (AstBasicDType* adtypep = ddtypep->castBasicDType()) {
|
else if (AstPackArrayDType* adtypep = ddtypep->castPackArrayDType()) {
|
||||||
if (adtypep) {} // unused
|
// SELBIT(array, index) -> SEL(array, index*width-of-subindex, width-of-subindex)
|
||||||
|
AstNode* subp = rhsp;
|
||||||
|
if (fromRange.lo()!=0 || fromRange.hi()<0) {
|
||||||
|
subp = newSubNeg (subp, fromRange.lo());
|
||||||
|
}
|
||||||
|
if (!fromRange.elements() || (adtypep->width() % fromRange.elements())!=0)
|
||||||
|
adtypep->v3fatalSrc("Array extraction with width miscomputed "
|
||||||
|
<<adtypep->width()<<"/"<<fromRange.elements());
|
||||||
|
int elwidth = adtypep->width() / fromRange.elements();
|
||||||
|
AstSel* newp = new AstSel (nodep->fileline(),
|
||||||
|
fromp,
|
||||||
|
new AstMul(nodep->fileline(),
|
||||||
|
new AstConst(nodep->fileline(),AstConst::Unsized32(),elwidth),
|
||||||
|
newSubLsbOf(rhsp, fromRange)),
|
||||||
|
new AstConst (nodep->fileline(),AstConst::Unsized32(),elwidth));
|
||||||
|
newp->declRange(fromRange);
|
||||||
|
newp->declElWidth(elwidth);
|
||||||
|
newp->dtypeFrom(adtypep->subDTypep()); // Need to strip off array reference
|
||||||
|
if (debug()>=9) newp->dumpTree(cout,"--SELBTn: ");
|
||||||
|
nodep->replaceWith(newp); pushDeletep(nodep); nodep=NULL;
|
||||||
|
}
|
||||||
|
else if (ddtypep->castBasicDType()) {
|
||||||
// SELBIT(range, index) -> SEL(array, index, 1)
|
// SELBIT(range, index) -> SEL(array, index, 1)
|
||||||
AstSel* newp = new AstSel (nodep->fileline(),
|
AstSel* newp = new AstSel (nodep->fileline(),
|
||||||
fromp,
|
fromp,
|
||||||
newSubLsbOf(rhsp, basefromp),
|
newSubLsbOf(rhsp, fromRange),
|
||||||
// Unsized so width from user
|
// Unsized so width from user
|
||||||
new AstConst (nodep->fileline(),AstConst::Unsized32(),1));
|
new AstConst (nodep->fileline(),AstConst::Unsized32(),1));
|
||||||
UINFO(6," new "<<newp<<endl); if (debug()>=9) newp->dumpTree(cout,"-vsbnw: ");
|
newp->declRange(fromRange);
|
||||||
|
UINFO(6," new "<<newp<<endl);
|
||||||
|
if (debug()>=9) newp->dumpTree(cout,"--SELBTn: ");
|
||||||
nodep->replaceWith(newp); pushDeletep(nodep); nodep=NULL;
|
nodep->replaceWith(newp); pushDeletep(nodep); nodep=NULL;
|
||||||
}
|
}
|
||||||
else if (AstNodeClassDType* adtypep = ddtypep->castNodeClassDType()) {
|
else if (ddtypep->castNodeClassDType()) { // It's packed, so a bit from the packed struct
|
||||||
if (adtypep) {} // unused
|
|
||||||
// SELBIT(range, index) -> SEL(array, index, 1)
|
// SELBIT(range, index) -> SEL(array, index, 1)
|
||||||
AstSel* newp = new AstSel (nodep->fileline(),
|
AstSel* newp = new AstSel (nodep->fileline(),
|
||||||
fromp,
|
fromp,
|
||||||
newSubLsbOf(rhsp, basefromp),
|
newSubLsbOf(rhsp, fromRange),
|
||||||
// Unsized so width from user
|
// Unsized so width from user
|
||||||
new AstConst (nodep->fileline(),AstConst::Unsized32(),1));
|
new AstConst (nodep->fileline(),AstConst::Unsized32(),1));
|
||||||
UINFO(6," new "<<newp<<endl); if (debug()>=9) newp->dumpTree(cout,"-vsbnw: ");
|
newp->declRange(fromRange);
|
||||||
|
UINFO(6," new "<<newp<<endl);
|
||||||
|
if (debug()>=9) newp->dumpTree(cout,"--SELBTn: ");
|
||||||
nodep->replaceWith(newp); pushDeletep(nodep); nodep=NULL;
|
nodep->replaceWith(newp); pushDeletep(nodep); nodep=NULL;
|
||||||
}
|
}
|
||||||
else { // NULL=bad extract, or unknown node type
|
else { // NULL=bad extract, or unknown node type
|
||||||
nodep->v3error("Illegal bit or array select; variable already selected, or bad dimension");
|
nodep->v3error("Illegal bit or array select; type already selected, or bad dimension: type is"
|
||||||
|
<<fromdata.m_errp->prettyName());
|
||||||
// How to recover? We'll strip a dimension.
|
// How to recover? We'll strip a dimension.
|
||||||
nodep->replaceWith(fromp); pushDeletep(nodep); nodep=NULL;
|
nodep->replaceWith(fromp); pushDeletep(nodep); nodep=NULL;
|
||||||
}
|
}
|
||||||
if (!rhsp->backp()) pushDeletep(rhsp); rhsp=NULL;
|
if (!rhsp->backp()) pushDeletep(rhsp); rhsp=NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void visit(AstSelExtract* nodep, AstNUser*) {
|
virtual void visit(AstSelExtract* nodep, AstNUser*) {
|
||||||
|
// Select of a range specified part of an array, i.e. "array[2:3]"
|
||||||
// SELEXTRACT(from,msb,lsb) -> SEL(from, lsb, 1+msb-lsb)
|
// SELEXTRACT(from,msb,lsb) -> SEL(from, lsb, 1+msb-lsb)
|
||||||
|
// This select style has a (msb or lsb) and width
|
||||||
UINFO(6,"SELEXTRACT "<<nodep<<endl);
|
UINFO(6,"SELEXTRACT "<<nodep<<endl);
|
||||||
//if (debug()>=9) nodep->dumpTree(cout,"--SLEX0: ");
|
//if (debug()>=9) nodep->dumpTree(cout,"--SELEX0: ");
|
||||||
// Below 2 lines may change nodep->widthp()
|
// Below 2 lines may change nodep->widthp()
|
||||||
V3Const::constifyParamsEdit(nodep->lsbp()); // May relink pointed to node
|
V3Const::constifyParamsEdit(nodep->lsbp()); // May relink pointed to node
|
||||||
V3Const::constifyParamsEdit(nodep->msbp()); // May relink pointed to node
|
V3Const::constifyParamsEdit(nodep->msbp()); // May relink pointed to node
|
||||||
//if (debug()>=9) nodep->dumpTree(cout,"--SLEX3: ");
|
//if (debug()>=9) nodep->dumpTree(cout,"--SELEX3: ");
|
||||||
checkConstantOrReplace(nodep->lsbp(), "First value of [a:b] isn't a constant, maybe you want +: or -:");
|
checkConstantOrReplace(nodep->lsbp(), "First value of [a:b] isn't a constant, maybe you want +: or -:");
|
||||||
checkConstantOrReplace(nodep->msbp(), "Second value of [a:b] isn't a constant, maybe you want +: or -:");
|
checkConstantOrReplace(nodep->msbp(), "Second value of [a:b] isn't a constant, maybe you want +: or -:");
|
||||||
AstNode* basefromp = AstArraySel::baseFromp(nodep->attrp());
|
|
||||||
int dimension = AstArraySel::dimension(nodep->fromp()); // Not attrp as need hierarchy
|
|
||||||
AstNode* fromp = nodep->lhsp()->unlinkFrBack();
|
AstNode* fromp = nodep->lhsp()->unlinkFrBack();
|
||||||
AstNode* msbp = nodep->rhsp()->unlinkFrBack();
|
AstNode* msbp = nodep->rhsp()->unlinkFrBack();
|
||||||
AstNode* lsbp = nodep->thsp()->unlinkFrBack();
|
AstNode* lsbp = nodep->thsp()->unlinkFrBack();
|
||||||
AstNode* errp;
|
|
||||||
AstNodeDType* bfdtypep = baseDTypeFrom(basefromp, errp/*ref*/);
|
|
||||||
vlsint32_t msb = msbp->castConst()->toSInt();
|
vlsint32_t msb = msbp->castConst()->toSInt();
|
||||||
vlsint32_t lsb = lsbp->castConst()->toSInt();
|
vlsint32_t lsb = lsbp->castConst()->toSInt();
|
||||||
AstNodeDType* ddtypep = dtypeForExtractp(nodep, basefromp, dimension, msb!=lsb);
|
FromData fromdata = fromDataForArray(nodep, fromp, false);
|
||||||
if (AstArrayDType* adtypep = ddtypep->castArrayDType()) {
|
AstNodeDType* ddtypep = fromdata.m_dtypep;
|
||||||
if (adtypep) {}
|
VNumRange fromRange = fromdata.m_fromRange;
|
||||||
if (msb!=lsb) {
|
if (ddtypep->castUnpackArrayDType()) {
|
||||||
|
// Slice extraction
|
||||||
|
if (fromRange.elements() == (msb-lsb+1)
|
||||||
|
&& fromRange.lo() == lsb) { // Extracting whole of original array
|
||||||
|
nodep->replaceWith(fromp); pushDeletep(nodep); nodep=NULL;
|
||||||
|
} else {
|
||||||
|
// TODO when unpacked arrays fully supported probably need new data type here
|
||||||
AstArraySel* newp = new AstArraySel (nodep->fileline(), fromp, lsbp);
|
AstArraySel* newp = new AstArraySel (nodep->fileline(), fromp, lsbp);
|
||||||
newp->start(lsb);
|
newp->start(lsb);
|
||||||
newp->length((msb - lsb) + 1);
|
newp->length((msb - lsb) + 1);
|
||||||
nodep->replaceWith(newp); pushDeletep(nodep); nodep=NULL;
|
nodep->replaceWith(newp); pushDeletep(nodep); nodep=NULL;
|
||||||
} else {
|
|
||||||
nodep->v3error("Illegal bit select; can't bit extract from arrayed dimension: "<<errp->prettyName());
|
|
||||||
}
|
}
|
||||||
} else if (AstBasicDType* adtypep = ddtypep->castBasicDType()) {
|
}
|
||||||
if (adtypep) {} // Unused
|
else if (AstPackArrayDType* adtypep = ddtypep->castPackArrayDType()) {
|
||||||
if (bfdtypep->basicp()->littleEndian()) {
|
// SELEXTRACT(array, msb, lsb) -> SEL(array, lsb*width-of-subindex, width-of-subindex*(msb-lsb))
|
||||||
|
if (!fromRange.elements() || (adtypep->width() % fromRange.elements())!=0)
|
||||||
|
adtypep->v3fatalSrc("Array extraction with width miscomputed "
|
||||||
|
<<adtypep->width()<<"/"<<fromRange.elements());
|
||||||
|
int elwidth = adtypep->width() / fromRange.elements();
|
||||||
|
AstSel* newp = new AstSel (nodep->fileline(),
|
||||||
|
fromp,
|
||||||
|
new AstConst(nodep->fileline(),AstConst::Unsized32(),lsb*elwidth),
|
||||||
|
new AstConst(nodep->fileline(),AstConst::Unsized32(),(msb-lsb+1)*elwidth));
|
||||||
|
newp->declRange(fromRange);
|
||||||
|
newp->declElWidth(elwidth);
|
||||||
|
if (fromRange.elements() == (msb-lsb+1) // Extracting whole of original array
|
||||||
|
&& fromRange.lo() == lsb) {
|
||||||
|
newp->dtypeFrom(adtypep);
|
||||||
|
} else {
|
||||||
|
// Need a slice data type, which is an array of the extracted type, but with (presumably) different size
|
||||||
|
AstNodeDType* vardtypep = new AstPackArrayDType(nodep->fileline(),
|
||||||
|
adtypep->subDTypep(), // Need to strip off array reference
|
||||||
|
new AstRange(nodep->fileline(), fromRange));
|
||||||
|
v3Global.rootp()->typeTablep()->addTypesp(vardtypep);
|
||||||
|
newp->dtypeFrom(vardtypep);
|
||||||
|
}
|
||||||
|
if (debug()>=9) newp->dumpTree(cout,"--EXTBTn: ");
|
||||||
|
nodep->replaceWith(newp); pushDeletep(nodep); nodep=NULL;
|
||||||
|
}
|
||||||
|
else if (ddtypep->castBasicDType()) {
|
||||||
|
if (fromRange.littleEndian()) {
|
||||||
// Below code assumes big bit endian; just works out if we swap
|
// Below code assumes big bit endian; just works out if we swap
|
||||||
int x = msb; msb = lsb; lsb = x;
|
int x = msb; msb = lsb; lsb = x;
|
||||||
}
|
}
|
||||||
@@ -309,13 +329,14 @@ private:
|
|||||||
msb +1-lsb);
|
msb +1-lsb);
|
||||||
AstSel* newp = new AstSel (nodep->fileline(),
|
AstSel* newp = new AstSel (nodep->fileline(),
|
||||||
fromp,
|
fromp,
|
||||||
newSubLsbOf(lsbp, basefromp),
|
newSubLsbOf(lsbp, fromRange),
|
||||||
widthp);
|
widthp);
|
||||||
|
newp->declRange(fromRange);
|
||||||
UINFO(6," new "<<newp<<endl);
|
UINFO(6," new "<<newp<<endl);
|
||||||
//if (debug()>=9) newp->dumpTree(cout,"--SLEXnew: ");
|
//if (debug()>=9) newp->dumpTree(cout,"--SELEXnew: ");
|
||||||
nodep->replaceWith(newp); pushDeletep(nodep); nodep=NULL;
|
nodep->replaceWith(newp); pushDeletep(nodep); nodep=NULL;
|
||||||
} else if (AstNodeClassDType* adtypep = ddtypep->castNodeClassDType()) {
|
}
|
||||||
if (adtypep) {} // Unused
|
else if (ddtypep->castNodeClassDType()) {
|
||||||
// Classes aren't little endian
|
// Classes aren't little endian
|
||||||
if (lsb > msb) {
|
if (lsb > msb) {
|
||||||
nodep->v3error("["<<msb<<":"<<lsb<<"] Range extract has backward bit ordering, perhaps you wanted ["<<lsb<<":"<<msb<<"]");
|
nodep->v3error("["<<msb<<":"<<lsb<<"] Range extract has backward bit ordering, perhaps you wanted ["<<lsb<<":"<<msb<<"]");
|
||||||
@@ -325,14 +346,17 @@ private:
|
|||||||
msb +1-lsb);
|
msb +1-lsb);
|
||||||
AstSel* newp = new AstSel (nodep->fileline(),
|
AstSel* newp = new AstSel (nodep->fileline(),
|
||||||
fromp,
|
fromp,
|
||||||
newSubLsbOf(lsbp, basefromp),
|
newSubLsbOf(lsbp, fromRange),
|
||||||
widthp);
|
widthp);
|
||||||
|
newp->declRange(fromRange);
|
||||||
UINFO(6," new "<<newp<<endl);
|
UINFO(6," new "<<newp<<endl);
|
||||||
//if (debug()>=9) newp->dumpTree(cout,"--SLEXnew: ");
|
//if (debug()>=9) newp->dumpTree(cout,"--SELEXnew: ");
|
||||||
nodep->replaceWith(newp); pushDeletep(nodep); nodep=NULL;
|
nodep->replaceWith(newp); pushDeletep(nodep); nodep=NULL;
|
||||||
}
|
}
|
||||||
else { // NULL=bad extract, or unknown node type
|
else { // NULL=bad extract, or unknown node type
|
||||||
nodep->v3error("Illegal range select; variable already selected, or bad dimension");
|
nodep->v3error("Illegal range select; type already selected, or bad dimension: type is "
|
||||||
|
<<fromdata.m_errp->prettyName());
|
||||||
|
UINFO(1," Related ddtype: "<<ddtypep<<endl);
|
||||||
// How to recover? We'll strip a dimension.
|
// How to recover? We'll strip a dimension.
|
||||||
nodep->replaceWith(fromp); pushDeletep(nodep); nodep=NULL;
|
nodep->replaceWith(fromp); pushDeletep(nodep); nodep=NULL;
|
||||||
}
|
}
|
||||||
@@ -343,65 +367,73 @@ private:
|
|||||||
}
|
}
|
||||||
|
|
||||||
void replaceSelPlusMinus(AstNodePreSel* nodep) {
|
void replaceSelPlusMinus(AstNodePreSel* nodep) {
|
||||||
|
// Select of a range specified with +: or -:, i.e. "array[2+:3], [2-:3]"
|
||||||
|
// This select style has a lsb and width
|
||||||
UINFO(6,"SELPLUS/MINUS "<<nodep<<endl);
|
UINFO(6,"SELPLUS/MINUS "<<nodep<<endl);
|
||||||
// Below 2 lines may change nodep->widthp()
|
// Below 2 lines may change nodep->widthp()
|
||||||
|
if (debug()>=9) nodep->dumpTree(cout,"--SELPM0: ");
|
||||||
V3Const::constifyParamsEdit(nodep->thsp()); // May relink pointed to node
|
V3Const::constifyParamsEdit(nodep->thsp()); // May relink pointed to node
|
||||||
checkConstantOrReplace(nodep->thsp(), "Width of :+ or :- bit extract isn't a constant");
|
checkConstantOrReplace(nodep->thsp(), "Width of :+ or :- bit extract isn't a constant");
|
||||||
|
if (debug()>=9) nodep->dumpTree(cout,"--SELPM3: ");
|
||||||
// Now replace it with an AstSel
|
// Now replace it with an AstSel
|
||||||
AstNode* basefromp = AstArraySel::baseFromp(nodep->attrp());
|
|
||||||
int dimension = AstArraySel::dimension(nodep->fromp()); // Not attrp as need hierarchy
|
|
||||||
AstNode* fromp = nodep->lhsp()->unlinkFrBack();
|
AstNode* fromp = nodep->lhsp()->unlinkFrBack();
|
||||||
AstNode* rhsp = nodep->rhsp()->unlinkFrBack();
|
AstNode* rhsp = nodep->rhsp()->unlinkFrBack();
|
||||||
AstNode* widthp = nodep->thsp()->unlinkFrBack();
|
AstNode* widthp = nodep->thsp()->unlinkFrBack();
|
||||||
int width = widthp->castConst()->toSInt();
|
int width = widthp->castConst()->toSInt();
|
||||||
if (width > (1<<28)) nodep->v3error("Width of :+ or :- is huge; vector of over 1billion bits: "<<widthp->prettyName());
|
if (width > (1<<28)) nodep->v3error("Width of :+ or :- is huge; vector of over 1billion bits: "<<widthp->prettyName());
|
||||||
if (width<0) nodep->v3error("Width of :+ or :- is < 0: "<<widthp->prettyName());
|
if (width<0) nodep->v3error("Width of :+ or :- is < 0: "<<widthp->prettyName());
|
||||||
AstNodeDType* ddtypep = dtypeForExtractp(nodep, basefromp, dimension, width!=1);
|
FromData fromdata = fromDataForArray(nodep, fromp, width!=1);
|
||||||
if (AstBasicDType* adtypep = ddtypep->castBasicDType()) {
|
AstNodeDType* ddtypep = fromdata.m_dtypep;
|
||||||
|
VNumRange fromRange = fromdata.m_fromRange;
|
||||||
|
if (ddtypep->castBasicDType()
|
||||||
|
|| (ddtypep->castNodeClassDType()
|
||||||
|
&& ddtypep->castNodeClassDType()->packed())) {
|
||||||
AstSel* newp = NULL;
|
AstSel* newp = NULL;
|
||||||
if (nodep->castSelPlus()) {
|
if (nodep->castSelPlus()) {
|
||||||
if (adtypep->littleEndian()) {
|
if (fromRange.littleEndian()) {
|
||||||
// SELPLUS(from,lsb,width) -> SEL(from, (vector_msb-width+1)-sel, width)
|
// SELPLUS(from,lsb,width) -> SEL(from, (vector_msb-width+1)-sel, width)
|
||||||
newp = new AstSel (nodep->fileline(),
|
newp = new AstSel (nodep->fileline(),
|
||||||
fromp,
|
fromp,
|
||||||
newSubNeg((adtypep->msb()-width+1), rhsp),
|
newSubNeg((fromRange.hi()-width+1), rhsp),
|
||||||
widthp);
|
widthp);
|
||||||
} else {
|
} else {
|
||||||
// SELPLUS(from,lsb,width) -> SEL(from, lsb-vector_lsb, width)
|
// SELPLUS(from,lsb,width) -> SEL(from, lsb-vector_lsb, width)
|
||||||
newp = new AstSel (nodep->fileline(),
|
newp = new AstSel (nodep->fileline(),
|
||||||
fromp,
|
fromp,
|
||||||
newSubLsbOf(rhsp, basefromp),
|
newSubNeg(rhsp, fromRange.lo()),
|
||||||
widthp);
|
widthp);
|
||||||
}
|
}
|
||||||
} else if (nodep->castSelMinus()) {
|
} else if (nodep->castSelMinus()) {
|
||||||
if (adtypep->littleEndian()) {
|
if (fromRange.littleEndian()) {
|
||||||
// SELMINUS(from,msb,width) -> SEL(from, msb-[bit])
|
// SELMINUS(from,msb,width) -> SEL(from, msb-[bit])
|
||||||
newp = new AstSel (nodep->fileline(),
|
newp = new AstSel (nodep->fileline(),
|
||||||
fromp,
|
fromp,
|
||||||
newSubNeg(adtypep->msb(), rhsp),
|
newSubNeg(fromRange.hi(), rhsp),
|
||||||
widthp);
|
widthp);
|
||||||
} else {
|
} else {
|
||||||
// SELMINUS(from,msb,width) -> SEL(from, msb-(width-1)-lsb#)
|
// SELMINUS(from,msb,width) -> SEL(from, msb-(width-1)-lsb#)
|
||||||
newp = new AstSel (nodep->fileline(),
|
newp = new AstSel (nodep->fileline(),
|
||||||
fromp,
|
fromp,
|
||||||
newSubNeg(rhsp, adtypep->lsb()+(width-1)),
|
newSubNeg(rhsp, fromRange.lo()+(width-1)),
|
||||||
widthp);
|
widthp);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
nodep->v3fatalSrc("Bad Case");
|
nodep->v3fatalSrc("Bad Case");
|
||||||
}
|
}
|
||||||
|
newp->declRange(fromRange);
|
||||||
UINFO(6," new "<<newp<<endl);
|
UINFO(6," new "<<newp<<endl);
|
||||||
nodep->replaceWith(newp); pushDeletep(nodep); nodep=NULL;
|
nodep->replaceWith(newp); pushDeletep(nodep); nodep=NULL;
|
||||||
// delete whataver we didn't use in reconstruction
|
|
||||||
if (!fromp->backp()) pushDeletep(fromp); fromp=NULL;
|
|
||||||
if (!rhsp->backp()) pushDeletep(rhsp); rhsp=NULL;
|
|
||||||
if (!widthp->backp()) pushDeletep(widthp); widthp=NULL;
|
|
||||||
}
|
}
|
||||||
else { // NULL=bad extract, or unknown node type
|
else { // NULL=bad extract, or unknown node type
|
||||||
nodep->v3error("Illegal +: or -: select; variable already selected, or bad dimension");
|
nodep->v3error("Illegal +: or -: select; type already selected, or bad dimension: type is "
|
||||||
|
<<fromdata.m_errp->prettyTypeName());
|
||||||
// How to recover? We'll strip a dimension.
|
// How to recover? We'll strip a dimension.
|
||||||
nodep->replaceWith(fromp); pushDeletep(nodep); nodep=NULL;
|
nodep->replaceWith(fromp); pushDeletep(nodep); nodep=NULL;
|
||||||
}
|
}
|
||||||
|
// delete whataver we didn't use in reconstruction
|
||||||
|
if (!fromp->backp()) pushDeletep(fromp); fromp=NULL;
|
||||||
|
if (!rhsp->backp()) pushDeletep(rhsp); rhsp=NULL;
|
||||||
|
if (!widthp->backp()) pushDeletep(widthp); widthp=NULL;
|
||||||
}
|
}
|
||||||
virtual void visit(AstSelPlus* nodep, AstNUser*) {
|
virtual void visit(AstSelPlus* nodep, AstNUser*) {
|
||||||
replaceSelPlusMinus(nodep);
|
replaceSelPlusMinus(nodep);
|
||||||
@@ -415,6 +447,7 @@ private:
|
|||||||
// Default
|
// Default
|
||||||
virtual void visit(AstNode* nodep, AstNUser*) {
|
virtual void visit(AstNode* nodep, AstNUser*) {
|
||||||
// See notes above; we never iterate
|
// See notes above; we never iterate
|
||||||
|
nodep->v3fatalSrc("Shouldn't iterate in V3WidthSel");
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|||||||
+10
-2
@@ -386,18 +386,27 @@ word [a-zA-Z0-9_]+
|
|||||||
"$bits" { FL; return yD_BITS; }
|
"$bits" { FL; return yD_BITS; }
|
||||||
"$clog2" { FL; return yD_CLOG2; }
|
"$clog2" { FL; return yD_CLOG2; }
|
||||||
"$countones" { FL; return yD_COUNTONES; }
|
"$countones" { FL; return yD_COUNTONES; }
|
||||||
|
"$dimensions" { FL; return yD_DIMENSIONS; }
|
||||||
"$error" { FL; return yD_ERROR; }
|
"$error" { FL; return yD_ERROR; }
|
||||||
"$fatal" { FL; return yD_FATAL; }
|
"$fatal" { FL; return yD_FATAL; }
|
||||||
|
"$high" { FL; return yD_HIGH; }
|
||||||
|
"$increment" { FL; return yD_INCREMENT; }
|
||||||
"$info" { FL; return yD_INFO; }
|
"$info" { FL; return yD_INFO; }
|
||||||
"$isunknown" { FL; return yD_ISUNKNOWN; }
|
"$isunknown" { FL; return yD_ISUNKNOWN; }
|
||||||
|
"$left" { FL; return yD_LEFT; }
|
||||||
|
"$low" { FL; return yD_LOW; }
|
||||||
"$onehot" { FL; return yD_ONEHOT; }
|
"$onehot" { FL; return yD_ONEHOT; }
|
||||||
"$onehot0" { FL; return yD_ONEHOT0; }
|
"$onehot0" { FL; return yD_ONEHOT0; }
|
||||||
|
"$right" { FL; return yD_RIGHT; }
|
||||||
|
"$size" { FL; return yD_SIZE; }
|
||||||
|
"$unpacked_dimensions" { FL; return yD_UNPACKED_DIMENSIONS; }
|
||||||
"$warning" { FL; return yD_WARNING; }
|
"$warning" { FL; return yD_WARNING; }
|
||||||
/* SV2005 Keywords */
|
/* SV2005 Keywords */
|
||||||
"$unit" { FL; return yD_UNIT; } /* Yes, a keyword, not task */
|
"$unit" { FL; return yD_UNIT; } /* Yes, a keyword, not task */
|
||||||
"always_comb" { FL; return yALWAYS; }
|
"always_comb" { FL; return yALWAYS; }
|
||||||
"always_ff" { FL; return yALWAYS; }
|
"always_ff" { FL; return yALWAYS; }
|
||||||
"always_latch" { FL; return yALWAYS; }
|
"always_latch" { FL; return yALWAYS; }
|
||||||
|
"bind" { FL; return yBIND; }
|
||||||
"bit" { FL; return yBIT; }
|
"bit" { FL; return yBIT; }
|
||||||
"break" { FL; return yBREAK; }
|
"break" { FL; return yBREAK; }
|
||||||
"byte" { FL; return yBYTE; }
|
"byte" { FL; return yBYTE; }
|
||||||
@@ -415,6 +424,7 @@ word [a-zA-Z0-9_]+
|
|||||||
"final" { FL; return yFINAL; }
|
"final" { FL; return yFINAL; }
|
||||||
"iff" { FL; return yIFF; }
|
"iff" { FL; return yIFF; }
|
||||||
"import" { FL; return yIMPORT; }
|
"import" { FL; return yIMPORT; }
|
||||||
|
"inside" { FL; return yINSIDE; }
|
||||||
"int" { FL; return yINT; }
|
"int" { FL; return yINT; }
|
||||||
"logic" { FL; return yLOGIC; }
|
"logic" { FL; return yLOGIC; }
|
||||||
"longint" { FL; return yLONGINT; }
|
"longint" { FL; return yLONGINT; }
|
||||||
@@ -440,7 +450,6 @@ word [a-zA-Z0-9_]+
|
|||||||
/* Note assert_strobe was in SystemVerilog 3.1, but removed for SystemVerilog 2005 */
|
/* Note assert_strobe was in SystemVerilog 3.1, but removed for SystemVerilog 2005 */
|
||||||
"$root" { yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented: %s",yytext); }
|
"$root" { yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented: %s",yytext); }
|
||||||
"alias" { yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented: %s",yytext); }
|
"alias" { yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented: %s",yytext); }
|
||||||
"bind" { yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented: %s",yytext); }
|
|
||||||
"bins" { yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented: %s",yytext); }
|
"bins" { yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented: %s",yytext); }
|
||||||
"binsof" { yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented: %s",yytext); }
|
"binsof" { yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented: %s",yytext); }
|
||||||
"class" { yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented: %s",yytext); }
|
"class" { yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented: %s",yytext); }
|
||||||
@@ -461,7 +470,6 @@ word [a-zA-Z0-9_]+
|
|||||||
"forkjoin" { yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented: %s",yytext); }
|
"forkjoin" { yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented: %s",yytext); }
|
||||||
"ignore_bins" { yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented: %s",yytext); }
|
"ignore_bins" { yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented: %s",yytext); }
|
||||||
"illegal_bins" { yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented: %s",yytext); }
|
"illegal_bins" { yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented: %s",yytext); }
|
||||||
"inside" { yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented: %s",yytext); }
|
|
||||||
"interface" { yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented: %s",yytext); }
|
"interface" { yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented: %s",yytext); }
|
||||||
"intersect" { yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented: %s",yytext); }
|
"intersect" { yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented: %s",yytext); }
|
||||||
"join_any" { yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented: %s",yytext); }
|
"join_any" { yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented: %s",yytext); }
|
||||||
|
|||||||
+126
-49
@@ -63,7 +63,6 @@ public:
|
|||||||
AstPin* m_instParamp; // Parameters for instantiations
|
AstPin* m_instParamp; // Parameters for instantiations
|
||||||
AstNodeModule* m_modp; // Module
|
AstNodeModule* m_modp; // Module
|
||||||
int m_modTypeImpNum; // Implicit type number, incremented each module
|
int m_modTypeImpNum; // Implicit type number, incremented each module
|
||||||
int m_uniqueAttr; // Bitmask of unique/priority keywords
|
|
||||||
|
|
||||||
// CONSTRUCTORS
|
// CONSTRUCTORS
|
||||||
V3ParseGrammar() {
|
V3ParseGrammar() {
|
||||||
@@ -112,11 +111,8 @@ public:
|
|||||||
// Find one made earlier?
|
// Find one made earlier?
|
||||||
AstPackage* pkgp = SYMP->symRootp()->findIdFlat(AstPackage::dollarUnitName())->nodep()->castPackage();
|
AstPackage* pkgp = SYMP->symRootp()->findIdFlat(AstPackage::dollarUnitName())->nodep()->castPackage();
|
||||||
if (!pkgp) {
|
if (!pkgp) {
|
||||||
pkgp = new AstPackage(fl, AstPackage::dollarUnitName());
|
pkgp = PARSEP->rootp()->dollarUnitPkgAddp();
|
||||||
pkgp->inLibrary(true); // packages are always libraries; don't want to make them a "top"
|
|
||||||
pkgp->modTrace(false); // may reconsider later
|
|
||||||
GRAMMARP->m_modp = pkgp; GRAMMARP->m_modTypeImpNum = 0;
|
GRAMMARP->m_modp = pkgp; GRAMMARP->m_modTypeImpNum = 0;
|
||||||
PARSEP->rootp()->addModulep(pkgp);
|
|
||||||
SYMP->reinsert(pkgp, SYMP->symRootp()); // Don't push/pop scope as they're global
|
SYMP->reinsert(pkgp, SYMP->symRootp()); // Don't push/pop scope as they're global
|
||||||
}
|
}
|
||||||
return pkgp;
|
return pkgp;
|
||||||
@@ -282,6 +278,7 @@ class AstSenTree;
|
|||||||
%token<fl> yASSIGN "assign"
|
%token<fl> yASSIGN "assign"
|
||||||
%token<fl> yAUTOMATIC "automatic"
|
%token<fl> yAUTOMATIC "automatic"
|
||||||
%token<fl> yBEGIN "begin"
|
%token<fl> yBEGIN "begin"
|
||||||
|
%token<fl> yBIND "bind"
|
||||||
%token<fl> yBIT "bit"
|
%token<fl> yBIT "bit"
|
||||||
%token<fl> yBREAK "break"
|
%token<fl> yBREAK "break"
|
||||||
%token<fl> yBUF "buf"
|
%token<fl> yBUF "buf"
|
||||||
@@ -334,6 +331,7 @@ class AstSenTree;
|
|||||||
%token<fl> yINITIAL "initial"
|
%token<fl> yINITIAL "initial"
|
||||||
%token<fl> yINOUT "inout"
|
%token<fl> yINOUT "inout"
|
||||||
%token<fl> yINPUT "input"
|
%token<fl> yINPUT "input"
|
||||||
|
%token<fl> yINSIDE "inside"
|
||||||
%token<fl> yINT "int"
|
%token<fl> yINT "int"
|
||||||
%token<fl> yINTEGER "integer"
|
%token<fl> yINTEGER "integer"
|
||||||
%token<fl> yLOCALPARAM "localparam"
|
%token<fl> yLOCALPARAM "localparam"
|
||||||
@@ -416,6 +414,7 @@ class AstSenTree;
|
|||||||
%token<fl> yD_CEIL "$ceil"
|
%token<fl> yD_CEIL "$ceil"
|
||||||
%token<fl> yD_CLOG2 "$clog2"
|
%token<fl> yD_CLOG2 "$clog2"
|
||||||
%token<fl> yD_COUNTONES "$countones"
|
%token<fl> yD_COUNTONES "$countones"
|
||||||
|
%token<fl> yD_DIMENSIONS "$dimensions"
|
||||||
%token<fl> yD_DISPLAY "$display"
|
%token<fl> yD_DISPLAY "$display"
|
||||||
%token<fl> yD_ERROR "$error"
|
%token<fl> yD_ERROR "$error"
|
||||||
%token<fl> yD_EXP "$exp"
|
%token<fl> yD_EXP "$exp"
|
||||||
@@ -431,11 +430,15 @@ class AstSenTree;
|
|||||||
%token<fl> yD_FOPEN "$fopen"
|
%token<fl> yD_FOPEN "$fopen"
|
||||||
%token<fl> yD_FSCANF "$fscanf"
|
%token<fl> yD_FSCANF "$fscanf"
|
||||||
%token<fl> yD_FWRITE "$fwrite"
|
%token<fl> yD_FWRITE "$fwrite"
|
||||||
|
%token<fl> yD_HIGH "$high"
|
||||||
|
%token<fl> yD_INCREMENT "$increment"
|
||||||
%token<fl> yD_INFO "$info"
|
%token<fl> yD_INFO "$info"
|
||||||
%token<fl> yD_ISUNKNOWN "$isunknown"
|
%token<fl> yD_ISUNKNOWN "$isunknown"
|
||||||
%token<fl> yD_ITOR "$itor"
|
%token<fl> yD_ITOR "$itor"
|
||||||
|
%token<fl> yD_LEFT "$left"
|
||||||
%token<fl> yD_LN "$ln"
|
%token<fl> yD_LN "$ln"
|
||||||
%token<fl> yD_LOG10 "$log10"
|
%token<fl> yD_LOG10 "$log10"
|
||||||
|
%token<fl> yD_LOW "$low"
|
||||||
%token<fl> yD_ONEHOT "$onehot"
|
%token<fl> yD_ONEHOT "$onehot"
|
||||||
%token<fl> yD_ONEHOT0 "$onehot0"
|
%token<fl> yD_ONEHOT0 "$onehot0"
|
||||||
%token<fl> yD_POW "$pow"
|
%token<fl> yD_POW "$pow"
|
||||||
@@ -444,9 +447,11 @@ class AstSenTree;
|
|||||||
%token<fl> yD_READMEMH "$readmemh"
|
%token<fl> yD_READMEMH "$readmemh"
|
||||||
%token<fl> yD_REALTIME "$realtime"
|
%token<fl> yD_REALTIME "$realtime"
|
||||||
%token<fl> yD_REALTOBITS "$realtobits"
|
%token<fl> yD_REALTOBITS "$realtobits"
|
||||||
|
%token<fl> yD_RIGHT "$right"
|
||||||
%token<fl> yD_RTOI "$rtoi"
|
%token<fl> yD_RTOI "$rtoi"
|
||||||
%token<fl> yD_SFORMAT "$sformat"
|
%token<fl> yD_SFORMAT "$sformat"
|
||||||
%token<fl> yD_SIGNED "$signed"
|
%token<fl> yD_SIGNED "$signed"
|
||||||
|
%token<fl> yD_SIZE "$size"
|
||||||
%token<fl> yD_SQRT "$sqrt"
|
%token<fl> yD_SQRT "$sqrt"
|
||||||
%token<fl> yD_SSCANF "$sscanf"
|
%token<fl> yD_SSCANF "$sscanf"
|
||||||
%token<fl> yD_STIME "$stime"
|
%token<fl> yD_STIME "$stime"
|
||||||
@@ -456,6 +461,7 @@ class AstSenTree;
|
|||||||
%token<fl> yD_TESTPLUSARGS "$test$plusargs"
|
%token<fl> yD_TESTPLUSARGS "$test$plusargs"
|
||||||
%token<fl> yD_TIME "$time"
|
%token<fl> yD_TIME "$time"
|
||||||
%token<fl> yD_UNIT "$unit"
|
%token<fl> yD_UNIT "$unit"
|
||||||
|
%token<fl> yD_UNPACKED_DIMENSIONS "$unpacked_dimensions"
|
||||||
%token<fl> yD_UNSIGNED "$unsigned"
|
%token<fl> yD_UNSIGNED "$unsigned"
|
||||||
%token<fl> yD_VALUEPLUSARGS "$value$plusargs"
|
%token<fl> yD_VALUEPLUSARGS "$value$plusargs"
|
||||||
%token<fl> yD_WARNING "$warning"
|
%token<fl> yD_WARNING "$warning"
|
||||||
@@ -551,7 +557,7 @@ class AstSenTree;
|
|||||||
// PSL op precedence
|
// PSL op precedence
|
||||||
%right yP_MINUSGT yP_LOGIFF
|
%right yP_MINUSGT yP_LOGIFF
|
||||||
%right yP_ORMINUSGT yP_OREQGT
|
%right yP_ORMINUSGT yP_OREQGT
|
||||||
%left<fl> prPSLCLK
|
%left<fl> prPSLCLK
|
||||||
|
|
||||||
// Verilog op precedence
|
// Verilog op precedence
|
||||||
%right '?' ':'
|
%right '?' ':'
|
||||||
@@ -561,7 +567,7 @@ class AstSenTree;
|
|||||||
%left '^' yP_XNOR
|
%left '^' yP_XNOR
|
||||||
%left '&' yP_NAND
|
%left '&' yP_NAND
|
||||||
%left yP_EQUAL yP_NOTEQUAL yP_CASEEQUAL yP_CASENOTEQUAL yP_WILDEQUAL yP_WILDNOTEQUAL
|
%left yP_EQUAL yP_NOTEQUAL yP_CASEEQUAL yP_CASENOTEQUAL yP_WILDEQUAL yP_WILDNOTEQUAL
|
||||||
%left '>' '<' yP_GTE yP_LTE yP_LTE__IGNORE
|
%left '>' '<' yP_GTE yP_LTE yP_LTE__IGNORE yINSIDE
|
||||||
%left yP_SLEFT yP_SRIGHT yP_SSRIGHT
|
%left yP_SLEFT yP_SRIGHT yP_SSRIGHT
|
||||||
%left '+' '-'
|
%left '+' '-'
|
||||||
%left '*' '/' '%'
|
%left '*' '/' '%'
|
||||||
@@ -887,7 +893,7 @@ port<nodep>: // ==IEEE: port
|
|||||||
| portDirNetE yVAR implicit_typeE portSig variable_dimensionListE sigAttrListE
|
| portDirNetE yVAR implicit_typeE portSig variable_dimensionListE sigAttrListE
|
||||||
{ $$=$4; VARDTYPE($3); $$->addNextNull(VARDONEP($$,$5,$6)); }
|
{ $$=$4; VARDTYPE($3); $$->addNextNull(VARDONEP($$,$5,$6)); }
|
||||||
| portDirNetE signingE rangeList portSig variable_dimensionListE sigAttrListE
|
| portDirNetE signingE rangeList portSig variable_dimensionListE sigAttrListE
|
||||||
{ $$=$4; VARDTYPE(GRAMMARP->addRange(new AstBasicDType($3->fileline(), LOGIC_IMPLICIT, $2), $3,false)); $$->addNextNull(VARDONEP($$,$5,$6)); }
|
{ $$=$4; VARDTYPE(GRAMMARP->addRange(new AstBasicDType($3->fileline(), LOGIC_IMPLICIT, $2), $3,true)); $$->addNextNull(VARDONEP($$,$5,$6)); }
|
||||||
| portDirNetE /*implicit*/ portSig variable_dimensionListE sigAttrListE
|
| portDirNetE /*implicit*/ portSig variable_dimensionListE sigAttrListE
|
||||||
{ $$=$2; /*VARDTYPE-same*/ $$->addNextNull(VARDONEP($$,$3,$4)); }
|
{ $$=$2; /*VARDTYPE-same*/ $$->addNextNull(VARDONEP($$,$3,$4)); }
|
||||||
//
|
//
|
||||||
@@ -1036,13 +1042,30 @@ net_declaration<nodep>: // IEEE: net_declaration - excluding implict
|
|||||||
;
|
;
|
||||||
|
|
||||||
net_declarationFront: // IEEE: beginning of net_declaration
|
net_declarationFront: // IEEE: beginning of net_declaration
|
||||||
net_declRESET net_type strengthSpecE signingE delayrange { VARDTYPE($5); $5->basicp()->setSignedState($4); }
|
net_declRESET net_type strengthSpecE net_scalaredE net_dataType { VARDTYPE($5); }
|
||||||
;
|
;
|
||||||
|
|
||||||
net_declRESET:
|
net_declRESET:
|
||||||
/* empty */ { VARRESET_NONLIST(UNKNOWN); }
|
/* empty */ { VARRESET_NONLIST(UNKNOWN); }
|
||||||
;
|
;
|
||||||
|
|
||||||
|
net_scalaredE:
|
||||||
|
/* empty */ { }
|
||||||
|
//UNSUP: ySCALARED/yVECTORED ignored
|
||||||
|
| ySCALARED { }
|
||||||
|
| yVECTORED { }
|
||||||
|
;
|
||||||
|
|
||||||
|
net_dataType<dtypep>:
|
||||||
|
// // If there's a SV data type there shouldn't be a delay on this wire
|
||||||
|
// // Otherwise #(...) can't be determined to be a delay or parameters
|
||||||
|
// // Submit this as a footnote to the committee
|
||||||
|
var_data_type { $$ = $1; }
|
||||||
|
| signingE rangeList delayE { $$ = GRAMMARP->addRange(new AstBasicDType($2->fileline(), LOGIC, $1),$2,true); } // not implicit
|
||||||
|
| signing { $$ = new AstBasicDType($<fl>1, LOGIC, $1); } // not implicit
|
||||||
|
| /*implicit*/ delayE { $$ = new AstBasicDType(CRELINE(), LOGIC); } // not implicit
|
||||||
|
;
|
||||||
|
|
||||||
net_type: // ==IEEE: net_type
|
net_type: // ==IEEE: net_type
|
||||||
ySUPPLY0 { VARDECL(SUPPLY0); }
|
ySUPPLY0 { VARDECL(SUPPLY0); }
|
||||||
| ySUPPLY1 { VARDECL(SUPPLY1); }
|
| ySUPPLY1 { VARDECL(SUPPLY1); }
|
||||||
@@ -1097,7 +1120,7 @@ port_declaration<nodep>: // ==IEEE: port_declaration
|
|||||||
list_of_variable_decl_assignments { $$ = $6; }
|
list_of_variable_decl_assignments { $$ = $6; }
|
||||||
| port_directionReset port_declNetE yVAR implicit_typeE { VARDTYPE($4); }
|
| port_directionReset port_declNetE yVAR implicit_typeE { VARDTYPE($4); }
|
||||||
list_of_variable_decl_assignments { $$ = $6; }
|
list_of_variable_decl_assignments { $$ = $6; }
|
||||||
| port_directionReset port_declNetE signingE rangeList { VARDTYPE(GRAMMARP->addRange(new AstBasicDType($4->fileline(), LOGIC_IMPLICIT, $3),$4,false)); }
|
| port_directionReset port_declNetE signingE rangeList { VARDTYPE(GRAMMARP->addRange(new AstBasicDType($4->fileline(), LOGIC_IMPLICIT, $3),$4,true)); }
|
||||||
list_of_variable_decl_assignments { $$ = $6; }
|
list_of_variable_decl_assignments { $$ = $6; }
|
||||||
| port_directionReset port_declNetE signing { VARDTYPE(new AstBasicDType($<fl>3, LOGIC_IMPLICIT, $3)); }
|
| port_directionReset port_declNetE signing { VARDTYPE(new AstBasicDType($<fl>3, LOGIC_IMPLICIT, $3)); }
|
||||||
list_of_variable_decl_assignments { $$ = $5; }
|
list_of_variable_decl_assignments { $$ = $5; }
|
||||||
@@ -1197,7 +1220,7 @@ data_typeBasic<dtypep>: // IEEE: part of data_type
|
|||||||
data_typeNoRef<dtypep>: // ==IEEE: data_type, excluding class_type etc references
|
data_typeNoRef<dtypep>: // ==IEEE: data_type, excluding class_type etc references
|
||||||
data_typeBasic { $$ = $1; }
|
data_typeBasic { $$ = $1; }
|
||||||
| struct_unionDecl packed_dimensionListE { $$ = GRAMMARP->createArray(new AstDefImplicitDType($1->fileline(),"__typeimpsu"+cvtToStr(GRAMMARP->m_modTypeImpNum++),
|
| struct_unionDecl packed_dimensionListE { $$ = GRAMMARP->createArray(new AstDefImplicitDType($1->fileline(),"__typeimpsu"+cvtToStr(GRAMMARP->m_modTypeImpNum++),
|
||||||
GRAMMARP->m_modp,VFlagChildDType(),$1),$2,false); }
|
GRAMMARP->m_modp,VFlagChildDType(),$1),$2,true); }
|
||||||
| enumDecl { $$ = new AstDefImplicitDType($1->fileline(),"__typeimpenum"+cvtToStr(GRAMMARP->m_modTypeImpNum++),
|
| enumDecl { $$ = new AstDefImplicitDType($1->fileline(),"__typeimpenum"+cvtToStr(GRAMMARP->m_modTypeImpNum++),
|
||||||
GRAMMARP->m_modp,VFlagChildDType(),$1); }
|
GRAMMARP->m_modp,VFlagChildDType(),$1); }
|
||||||
| ySTRING { $$ = new AstBasicDType($1,AstBasicDTypeKwd::STRING); }
|
| ySTRING { $$ = new AstBasicDType($1,AstBasicDTypeKwd::STRING); }
|
||||||
@@ -1211,11 +1234,17 @@ data_typeNoRef<dtypep>: // ==IEEE: data_type, excluding class_type etc referenc
|
|||||||
// // IEEE: ps_covergroup: see data_type above
|
// // IEEE: ps_covergroup: see data_type above
|
||||||
;
|
;
|
||||||
|
|
||||||
data_type_or_void<dtypep>: // ==IEEE: data_type_or_void
|
data_type_or_void<dtypep>: // ==IEEE: data_type_or_void
|
||||||
data_type { $$=$1; }
|
data_type { $$ = $1; }
|
||||||
//UNSUP yVOID { UNSUP } // No yTAGGED structures
|
//UNSUP yVOID { UNSUP } // No yTAGGED structures
|
||||||
;
|
;
|
||||||
|
|
||||||
|
var_data_type<dtypep>: // ==IEEE: var_data_type
|
||||||
|
data_type { $$ = $1; }
|
||||||
|
| yVAR data_type { $$ = $2; }
|
||||||
|
| yVAR implicit_typeE { $$ = $2; }
|
||||||
|
;
|
||||||
|
|
||||||
struct_unionDecl<classp>: // IEEE: part of data_type
|
struct_unionDecl<classp>: // IEEE: part of data_type
|
||||||
// // packedSigningE is NOP for unpacked
|
// // packedSigningE is NOP for unpacked
|
||||||
ySTRUCT packedSigningE '{' { $<classp>$ = new AstStructDType($1, $2); SYMP->pushNew($<classp>$); }
|
ySTRUCT packedSigningE '{' { $<classp>$ = new AstStructDType($1, $2); SYMP->pushNew($<classp>$); }
|
||||||
@@ -1362,14 +1391,15 @@ enum_base_typeE<dtypep>: // IEEE: enum_base_type
|
|||||||
/* empty */ { $$ = new AstBasicDType(CRELINE(),AstBasicDTypeKwd::INT); }
|
/* empty */ { $$ = new AstBasicDType(CRELINE(),AstBasicDTypeKwd::INT); }
|
||||||
// // Not in spec, but obviously "enum [1:0]" should work
|
// // Not in spec, but obviously "enum [1:0]" should work
|
||||||
// // implicit_type expanded, without empty
|
// // implicit_type expanded, without empty
|
||||||
| signingE rangeList { $$ = GRAMMARP->addRange(new AstBasicDType($2->fileline(), LOGIC_IMPLICIT, $1),$2,false); }
|
// // Note enum base types are always packed data types
|
||||||
|
| signingE rangeList { $$ = GRAMMARP->addRange(new AstBasicDType($2->fileline(), LOGIC_IMPLICIT, $1),$2,true); }
|
||||||
| signing { $$ = new AstBasicDType($<fl>1, LOGIC_IMPLICIT, $1); }
|
| signing { $$ = new AstBasicDType($<fl>1, LOGIC_IMPLICIT, $1); }
|
||||||
//
|
//
|
||||||
| integer_atom_type signingE { $1->setSignedState($2); $$ = $1; }
|
| integer_atom_type signingE { $1->setSignedState($2); $$ = $1; }
|
||||||
| integer_vector_type signingE rangeListE { $1->setSignedState($2); $$ = GRAMMARP->addRange($1,$3,false); }
|
| integer_vector_type signingE rangeListE { $1->setSignedState($2); $$ = GRAMMARP->addRange($1,$3,true); }
|
||||||
// // below can be idAny or yaID__aTYPE
|
// // below can be idAny or yaID__aTYPE
|
||||||
// // IEEE requires a type, though no shift conflict if idAny
|
// // IEEE requires a type, though no shift conflict if idAny
|
||||||
| idAny rangeListE { $$ = GRAMMARP->createArray(new AstRefDType($<fl>1, *$1), $2, false); }
|
| idAny rangeListE { $$ = GRAMMARP->createArray(new AstRefDType($<fl>1, *$1), $2, true); }
|
||||||
;
|
;
|
||||||
|
|
||||||
enum_nameList<nodep>:
|
enum_nameList<nodep>:
|
||||||
@@ -1419,12 +1449,12 @@ data_declarationVarFront: // IEEE: part of data_declaration
|
|||||||
// // implicit_type expanded into /*empty*/ or "signingE rangeList"
|
// // implicit_type expanded into /*empty*/ or "signingE rangeList"
|
||||||
/**/ yVAR lifetimeE data_type { VARRESET_NONLIST(VAR); VARDTYPE($3); }
|
/**/ yVAR lifetimeE data_type { VARRESET_NONLIST(VAR); VARDTYPE($3); }
|
||||||
| /**/ yVAR lifetimeE { VARRESET_NONLIST(VAR); VARDTYPE(new AstBasicDType($<fl>1, LOGIC_IMPLICIT)); }
|
| /**/ yVAR lifetimeE { VARRESET_NONLIST(VAR); VARDTYPE(new AstBasicDType($<fl>1, LOGIC_IMPLICIT)); }
|
||||||
| /**/ yVAR lifetimeE signingE rangeList { /*VARRESET-in-ddVar*/ VARDTYPE(GRAMMARP->addRange(new AstBasicDType($<fl>1, LOGIC_IMPLICIT, $3), $4,false)); }
|
| /**/ yVAR lifetimeE signingE rangeList { /*VARRESET-in-ddVar*/ VARDTYPE(GRAMMARP->addRange(new AstBasicDType($<fl>1, LOGIC_IMPLICIT, $3), $4,true)); }
|
||||||
//
|
//
|
||||||
// // implicit_type expanded into /*empty*/ or "signingE rangeList"
|
// // implicit_type expanded into /*empty*/ or "signingE rangeList"
|
||||||
| yCONST__ETC yVAR lifetimeE data_type { VARRESET_NONLIST(VAR); VARDTYPE(new AstConstDType($<fl>1, VFlagChildDType(), $4)); }
|
| yCONST__ETC yVAR lifetimeE data_type { VARRESET_NONLIST(VAR); VARDTYPE(new AstConstDType($<fl>1, VFlagChildDType(), $4)); }
|
||||||
| yCONST__ETC yVAR lifetimeE { VARRESET_NONLIST(VAR); VARDTYPE(new AstConstDType($<fl>1, VFlagChildDType(), new AstBasicDType($<fl>2, LOGIC_IMPLICIT))); }
|
| yCONST__ETC yVAR lifetimeE { VARRESET_NONLIST(VAR); VARDTYPE(new AstConstDType($<fl>1, VFlagChildDType(), new AstBasicDType($<fl>2, LOGIC_IMPLICIT))); }
|
||||||
| yCONST__ETC yVAR lifetimeE signingE rangeList { VARRESET_NONLIST(VAR); VARDTYPE(new AstConstDType($<fl>1, VFlagChildDType(), GRAMMARP->addRange(new AstBasicDType($<fl>2, LOGIC_IMPLICIT, $4), $5,false))); }
|
| yCONST__ETC yVAR lifetimeE signingE rangeList { VARRESET_NONLIST(VAR); VARDTYPE(new AstConstDType($<fl>1, VFlagChildDType(), GRAMMARP->addRange(new AstBasicDType($<fl>2, LOGIC_IMPLICIT, $4), $5,true))); }
|
||||||
//
|
//
|
||||||
// // Expanded: "constE lifetimeE data_type"
|
// // Expanded: "constE lifetimeE data_type"
|
||||||
| /**/ data_type { VARRESET_NONLIST(VAR); VARDTYPE($1); }
|
| /**/ data_type { VARRESET_NONLIST(VAR); VARDTYPE($1); }
|
||||||
@@ -1436,7 +1466,7 @@ data_declarationVarFront: // IEEE: part of data_declaration
|
|||||||
implicit_typeE<dtypep>: // IEEE: part of *data_type_or_implicit
|
implicit_typeE<dtypep>: // IEEE: part of *data_type_or_implicit
|
||||||
// // Also expanded in data_declaration
|
// // Also expanded in data_declaration
|
||||||
/* empty */ { $$ = NULL; }
|
/* empty */ { $$ = NULL; }
|
||||||
| signingE rangeList { $$ = GRAMMARP->addRange(new AstBasicDType($2->fileline(), LOGIC_IMPLICIT, $1),$2,false); }
|
| signingE rangeList { $$ = GRAMMARP->addRange(new AstBasicDType($2->fileline(), LOGIC_IMPLICIT, $1),$2,true); }
|
||||||
| signing { $$ = new AstBasicDType($<fl>1, LOGIC_IMPLICIT, $1); }
|
| signing { $$ = new AstBasicDType($<fl>1, LOGIC_IMPLICIT, $1); }
|
||||||
;
|
;
|
||||||
|
|
||||||
@@ -1511,7 +1541,7 @@ module_common_item<nodep>: // ==IEEE: module_common_item
|
|||||||
// // + module_instantiation from module_or_generate_item
|
// // + module_instantiation from module_or_generate_item
|
||||||
| etcInst { $$ = $1; }
|
| etcInst { $$ = $1; }
|
||||||
| concurrent_assertion_item { $$ = $1; }
|
| concurrent_assertion_item { $$ = $1; }
|
||||||
//UNSUP bind_directive { $$ = $1; }
|
| bind_directive { $$ = $1; }
|
||||||
| continuous_assign { $$ = $1; }
|
| continuous_assign { $$ = $1; }
|
||||||
// // IEEE: net_alias
|
// // IEEE: net_alias
|
||||||
//UNSUP yALIAS variable_lvalue aliasEqList ';' { UNSUP }
|
//UNSUP yALIAS variable_lvalue aliasEqList ';' { UNSUP }
|
||||||
@@ -1548,6 +1578,31 @@ module_or_generate_item_declaration<nodep>: // ==IEEE: module_or_generate_item_d
|
|||||||
//UNSUP yDEFAULT yCLOCKING idAny/*new-clocking_identifier*/ ';' { $$ = $1; }
|
//UNSUP yDEFAULT yCLOCKING idAny/*new-clocking_identifier*/ ';' { $$ = $1; }
|
||||||
;
|
;
|
||||||
|
|
||||||
|
bind_directive<nodep>: // ==IEEE: bind_directive + bind_target_scope
|
||||||
|
// // ';' - Note IEEE grammar is wrong, includes extra ';' - it's already in module_instantiation
|
||||||
|
// // We merged the rules - id may be a bind_target_instance or module_identifier or interface_identifier
|
||||||
|
yBIND bind_target_instance bind_instantiation { $$ = new AstBind($<fl>1,*$2,$3); }
|
||||||
|
| yBIND bind_target_instance ':' bind_target_instance_list bind_instantiation { $$=NULL; $1->v3error("Unsupported: Bind with instance list"); }
|
||||||
|
;
|
||||||
|
|
||||||
|
bind_target_instance_list: // ==IEEE: bind_target_instance_list
|
||||||
|
bind_target_instance { }
|
||||||
|
| bind_target_instance_list ',' bind_target_instance { }
|
||||||
|
;
|
||||||
|
|
||||||
|
bind_target_instance<strp>: // ==IEEE: bind_target_instance
|
||||||
|
//UNSUP hierarchical_identifierBit { }
|
||||||
|
idAny { $$ = $1; }
|
||||||
|
;
|
||||||
|
|
||||||
|
bind_instantiation<nodep>: // ==IEEE: bind_instantiation
|
||||||
|
// // IEEE: program_instantiation
|
||||||
|
// // IEEE: + module_instantiation
|
||||||
|
// // IEEE: + interface_instantiation
|
||||||
|
// // Need to get an AstBind instead of AstCell, so have special rules
|
||||||
|
instDecl { $$ = $1; }
|
||||||
|
;
|
||||||
|
|
||||||
//************************************************
|
//************************************************
|
||||||
// Generates
|
// Generates
|
||||||
//
|
//
|
||||||
@@ -1768,11 +1823,6 @@ rangeList<rangep>: // IEEE: {packed_dimension}
|
|||||||
| rangeList anyrange { $$ = $1; $1->addNext($2); }
|
| rangeList anyrange { $$ = $1; $1->addNext($2); }
|
||||||
;
|
;
|
||||||
|
|
||||||
wirerangeE<dtypep>:
|
|
||||||
/* empty */ { $$ = new AstBasicDType(CRELINE(), LOGIC); } // not implicit
|
|
||||||
| rangeList { $$ = GRAMMARP->addRange(new AstBasicDType($1->fileline(), LOGIC),$1,false); } // not implicit
|
|
||||||
;
|
|
||||||
|
|
||||||
// IEEE: select
|
// IEEE: select
|
||||||
// Merged into more general idArray
|
// Merged into more general idArray
|
||||||
|
|
||||||
@@ -1795,13 +1845,6 @@ packed_dimension<rangep>: // ==IEEE: packed_dimension
|
|||||||
//UNSUP '[' ']' { UNSUP }
|
//UNSUP '[' ']' { UNSUP }
|
||||||
;
|
;
|
||||||
|
|
||||||
delayrange<dtypep>:
|
|
||||||
wirerangeE delayE { $$ = $1; }
|
|
||||||
| ySCALARED wirerangeE delayE { $$ = $2; }
|
|
||||||
| yVECTORED wirerangeE delayE { $$ = $2; }
|
|
||||||
//UNSUP: ySCALARED/yVECTORED ignored
|
|
||||||
;
|
|
||||||
|
|
||||||
//************************************************
|
//************************************************
|
||||||
// Parameters
|
// Parameters
|
||||||
|
|
||||||
@@ -2202,6 +2245,20 @@ case_itemList<caseitemp>: // IEEE: { case_item + ... }
|
|||||||
| case_itemList yDEFAULT ':' stmtBlock { $$ = $1;$1->addNext(new AstCaseItem($3,NULL,$4)); }
|
| case_itemList yDEFAULT ':' stmtBlock { $$ = $1;$1->addNext(new AstCaseItem($3,NULL,$4)); }
|
||||||
;
|
;
|
||||||
|
|
||||||
|
open_range_list<nodep>: // ==IEEE: open_range_list + open_value_range
|
||||||
|
open_value_range { $$ = $1; }
|
||||||
|
| open_range_list ',' open_value_range { $$ = $1;$1->addNext($3); }
|
||||||
|
;
|
||||||
|
|
||||||
|
open_value_range<nodep>: // ==IEEE: open_value_range
|
||||||
|
value_range { $$ = $1; }
|
||||||
|
;
|
||||||
|
|
||||||
|
value_range<nodep>: // ==IEEE: value_range
|
||||||
|
expr { $$ = $1; }
|
||||||
|
| '[' expr ':' expr ']' { $$ = new AstInsideRange($3,$2,$4); }
|
||||||
|
;
|
||||||
|
|
||||||
caseCondList<nodep>: // IEEE: part of case_item
|
caseCondList<nodep>: // IEEE: part of case_item
|
||||||
expr { $$ = $1; }
|
expr { $$ = $1; }
|
||||||
| caseCondList ',' expr { $$ = $1;$1->addNext($3); }
|
| caseCondList ',' expr { $$ = $1;$1->addNext($3); }
|
||||||
@@ -2385,39 +2442,55 @@ system_f_call<nodep>: // IEEE: system_tf_call (as func)
|
|||||||
| yaD_DPI parenE { $$ = new AstFuncRef($<fl>1,*$1,NULL); }
|
| yaD_DPI parenE { $$ = new AstFuncRef($<fl>1,*$1,NULL); }
|
||||||
| yaD_DPI '(' exprList ')' { $$ = new AstFuncRef($2,*$1,$3); }
|
| yaD_DPI '(' exprList ')' { $$ = new AstFuncRef($2,*$1,$3); }
|
||||||
//
|
//
|
||||||
| yD_CEIL '(' expr ')' { $$ = new AstCeilD($1,$3); }
|
| yD_BITS '(' data_type ')' { $$ = new AstAttrOf($1,AstAttrType::DIM_BITS,$3); }
|
||||||
| yD_EXP '(' expr ')' { $$ = new AstExpD($1,$3); }
|
| yD_BITS '(' data_type ',' expr ')' { $$ = new AstAttrOf($1,AstAttrType::DIM_BITS,$3,$5); }
|
||||||
| yD_FLOOR '(' expr ')' { $$ = new AstFloorD($1,$3); }
|
| yD_BITS '(' expr ')' { $$ = new AstAttrOf($1,AstAttrType::DIM_BITS,$3); }
|
||||||
| yD_LN '(' expr ')' { $$ = new AstLogD($1,$3); }
|
| yD_BITS '(' expr ',' expr ')' { $$ = new AstAttrOf($1,AstAttrType::DIM_BITS,$3,$5); }
|
||||||
| yD_LOG10 '(' expr ')' { $$ = new AstLog10D($1,$3); }
|
|
||||||
| yD_POW '(' expr ',' expr ')' { $$ = new AstPowD($1,$3,$5); }
|
|
||||||
| yD_SQRT '(' expr ')' { $$ = new AstSqrtD($1,$3); }
|
|
||||||
| yD_BITS '(' expr ')' { $$ = new AstAttrOf($1,AstAttrType::EXPR_BITS,$3); }
|
|
||||||
| yD_BITS '(' data_type ')' { $$ = new AstAttrOf($1,AstAttrType::EXPR_BITS,$3); }
|
|
||||||
| yD_BITSTOREAL '(' expr ')' { $$ = new AstBitsToRealD($1,$3); }
|
| yD_BITSTOREAL '(' expr ')' { $$ = new AstBitsToRealD($1,$3); }
|
||||||
| yD_C '(' cStrList ')' { $$ = (v3Global.opt.ignc() ? NULL : new AstUCFunc($1,$3)); }
|
| yD_C '(' cStrList ')' { $$ = (v3Global.opt.ignc() ? NULL : new AstUCFunc($1,$3)); }
|
||||||
|
| yD_CEIL '(' expr ')' { $$ = new AstCeilD($1,$3); }
|
||||||
| yD_CLOG2 '(' expr ')' { $$ = new AstCLog2($1,$3); }
|
| yD_CLOG2 '(' expr ')' { $$ = new AstCLog2($1,$3); }
|
||||||
| yD_COUNTONES '(' expr ')' { $$ = new AstCountOnes($1,$3); }
|
| yD_COUNTONES '(' expr ')' { $$ = new AstCountOnes($1,$3); }
|
||||||
|
| yD_DIMENSIONS '(' expr ')' { $$ = new AstAttrOf($1,AstAttrType::DIM_DIMENSIONS,$3); }
|
||||||
|
| yD_EXP '(' expr ')' { $$ = new AstExpD($1,$3); }
|
||||||
| yD_FEOF '(' expr ')' { $$ = new AstFEof($1,$3); }
|
| yD_FEOF '(' expr ')' { $$ = new AstFEof($1,$3); }
|
||||||
| yD_FGETC '(' expr ')' { $$ = new AstFGetC($1,$3); }
|
| yD_FGETC '(' expr ')' { $$ = new AstFGetC($1,$3); }
|
||||||
| yD_FGETS '(' idClassSel ',' expr ')' { $$ = new AstFGetS($1,$3,$5); }
|
| yD_FGETS '(' idClassSel ',' expr ')' { $$ = new AstFGetS($1,$3,$5); }
|
||||||
|
| yD_FLOOR '(' expr ')' { $$ = new AstFloorD($1,$3); }
|
||||||
| yD_FSCANF '(' expr ',' str commaVRDListE ')' { $$ = new AstFScanF($1,*$5,$3,$6); }
|
| yD_FSCANF '(' expr ',' str commaVRDListE ')' { $$ = new AstFScanF($1,*$5,$3,$6); }
|
||||||
| yD_SSCANF '(' expr ',' str commaVRDListE ')' { $$ = new AstSScanF($1,*$5,$3,$6); }
|
| yD_HIGH '(' expr ')' { $$ = new AstAttrOf($1,AstAttrType::DIM_HIGH,$3,NULL); }
|
||||||
| yD_SYSTEM '(' expr ')' { $$ = new AstSystemF($1,$3); }
|
| yD_HIGH '(' expr ',' expr ')' { $$ = new AstAttrOf($1,AstAttrType::DIM_HIGH,$3,$5); }
|
||||||
|
| yD_INCREMENT '(' expr ')' { $$ = new AstAttrOf($1,AstAttrType::DIM_INCREMENT,$3,NULL); }
|
||||||
|
| yD_INCREMENT '(' expr ',' expr ')' { $$ = new AstAttrOf($1,AstAttrType::DIM_INCREMENT,$3,$5); }
|
||||||
| yD_ISUNKNOWN '(' expr ')' { $$ = new AstIsUnknown($1,$3); }
|
| yD_ISUNKNOWN '(' expr ')' { $$ = new AstIsUnknown($1,$3); }
|
||||||
| yD_ITOR '(' expr ')' { $$ = new AstIToRD($1,$3); }
|
| yD_ITOR '(' expr ')' { $$ = new AstIToRD($1,$3); }
|
||||||
|
| yD_LEFT '(' expr ')' { $$ = new AstAttrOf($1,AstAttrType::DIM_LEFT,$3,NULL); }
|
||||||
|
| yD_LEFT '(' expr ',' expr ')' { $$ = new AstAttrOf($1,AstAttrType::DIM_LEFT,$3,$5); }
|
||||||
|
| yD_LN '(' expr ')' { $$ = new AstLogD($1,$3); }
|
||||||
|
| yD_LOG10 '(' expr ')' { $$ = new AstLog10D($1,$3); }
|
||||||
|
| yD_LOW '(' expr ')' { $$ = new AstAttrOf($1,AstAttrType::DIM_LOW,$3,NULL); }
|
||||||
|
| yD_LOW '(' expr ',' expr ')' { $$ = new AstAttrOf($1,AstAttrType::DIM_LOW,$3,$5); }
|
||||||
| yD_ONEHOT '(' expr ')' { $$ = new AstOneHot($1,$3); }
|
| yD_ONEHOT '(' expr ')' { $$ = new AstOneHot($1,$3); }
|
||||||
| yD_ONEHOT0 '(' expr ')' { $$ = new AstOneHot0($1,$3); }
|
| yD_ONEHOT0 '(' expr ')' { $$ = new AstOneHot0($1,$3); }
|
||||||
|
| yD_POW '(' expr ',' expr ')' { $$ = new AstPowD($1,$3,$5); }
|
||||||
| yD_RANDOM '(' expr ')' { $1->v3error("Unsupported: Seeding $random doesn't map to C++, use $c(\"srand\")"); }
|
| yD_RANDOM '(' expr ')' { $1->v3error("Unsupported: Seeding $random doesn't map to C++, use $c(\"srand\")"); }
|
||||||
| yD_RANDOM parenE { $$ = new AstRand($1); }
|
| yD_RANDOM parenE { $$ = new AstRand($1); }
|
||||||
| yD_REALTIME parenE { $$ = new AstTimeD($1); }
|
| yD_REALTIME parenE { $$ = new AstTimeD($1); }
|
||||||
| yD_REALTOBITS '(' expr ')' { $$ = new AstRealToBits($1,$3); }
|
| yD_REALTOBITS '(' expr ')' { $$ = new AstRealToBits($1,$3); }
|
||||||
|
| yD_RIGHT '(' expr ')' { $$ = new AstAttrOf($1,AstAttrType::DIM_RIGHT,$3,NULL); }
|
||||||
|
| yD_RIGHT '(' expr ',' expr ')' { $$ = new AstAttrOf($1,AstAttrType::DIM_RIGHT,$3,$5); }
|
||||||
| yD_RTOI '(' expr ')' { $$ = new AstRToIS($1,$3); }
|
| yD_RTOI '(' expr ')' { $$ = new AstRToIS($1,$3); }
|
||||||
//| yD_SFORMATF '(' str commaEListE ')' { $$ = new AstSFormatF($1,*$3,false,$4); } // Have AST, just need testing and debug
|
//| yD_SFORMATF '(' str commaEListE ')' { $$ = new AstSFormatF($1,*$3,false,$4); } // Have AST, just need testing and debug
|
||||||
| yD_SIGNED '(' expr ')' { $$ = new AstSigned($1,$3); }
|
| yD_SIGNED '(' expr ')' { $$ = new AstSigned($1,$3); }
|
||||||
|
| yD_SIZE '(' expr ')' { $$ = new AstAttrOf($1,AstAttrType::DIM_SIZE,$3,NULL); }
|
||||||
|
| yD_SIZE '(' expr ',' expr ')' { $$ = new AstAttrOf($1,AstAttrType::DIM_SIZE,$3,$5); }
|
||||||
|
| yD_SQRT '(' expr ')' { $$ = new AstSqrtD($1,$3); }
|
||||||
|
| yD_SSCANF '(' expr ',' str commaVRDListE ')' { $$ = new AstSScanF($1,*$5,$3,$6); }
|
||||||
| yD_STIME parenE { $$ = new AstSel($1,new AstTime($1),0,32); }
|
| yD_STIME parenE { $$ = new AstSel($1,new AstTime($1),0,32); }
|
||||||
| yD_TIME parenE { $$ = new AstTime($1); }
|
| yD_SYSTEM '(' expr ')' { $$ = new AstSystemF($1,$3); }
|
||||||
| yD_TESTPLUSARGS '(' str ')' { $$ = new AstTestPlusArgs($1,*$3); }
|
| yD_TESTPLUSARGS '(' str ')' { $$ = new AstTestPlusArgs($1,*$3); }
|
||||||
|
| yD_TIME parenE { $$ = new AstTime($1); }
|
||||||
|
| yD_UNPACKED_DIMENSIONS '(' expr ')' { $$ = new AstAttrOf($1,AstAttrType::DIM_UNPK_DIMENSIONS,$3); }
|
||||||
| yD_UNSIGNED '(' expr ')' { $$ = new AstUnsigned($1,$3); }
|
| yD_UNSIGNED '(' expr ')' { $$ = new AstUnsigned($1,$3); }
|
||||||
| yD_VALUEPLUSARGS '(' str ',' expr ')' { $$ = new AstValuePlusArgs($1,*$3,$5); }
|
| yD_VALUEPLUSARGS '(' str ',' expr ')' { $$ = new AstValuePlusArgs($1,*$3,$5); }
|
||||||
;
|
;
|
||||||
@@ -2480,7 +2553,7 @@ funcId<ftaskp>: // IEEE: function_data_type_or_implicit + part of function_bod
|
|||||||
SYMP->pushNewUnder($$, NULL); }
|
SYMP->pushNewUnder($$, NULL); }
|
||||||
| signingE rangeList tfIdScoped
|
| signingE rangeList tfIdScoped
|
||||||
{ $$ = new AstFunc ($<fl>3,*$<strp>3,NULL,
|
{ $$ = new AstFunc ($<fl>3,*$<strp>3,NULL,
|
||||||
GRAMMARP->addRange(new AstBasicDType($<fl>3, LOGIC_IMPLICIT, $1), $2,false));
|
GRAMMARP->addRange(new AstBasicDType($<fl>3, LOGIC_IMPLICIT, $1), $2,true));
|
||||||
SYMP->pushNewUnder($$, NULL); }
|
SYMP->pushNewUnder($$, NULL); }
|
||||||
| signing tfIdScoped
|
| signing tfIdScoped
|
||||||
{ $$ = new AstFunc ($<fl>2,*$<strp>2,NULL,
|
{ $$ = new AstFunc ($<fl>2,*$<strp>2,NULL,
|
||||||
@@ -2550,14 +2623,14 @@ tf_port_item<nodep>: // ==IEEE: tf_port_item
|
|||||||
|
|
||||||
tf_port_itemFront: // IEEE: part of tf_port_item, which has the data type
|
tf_port_itemFront: // IEEE: part of tf_port_item, which has the data type
|
||||||
data_type { VARDTYPE($1); }
|
data_type { VARDTYPE($1); }
|
||||||
| signingE rangeList { VARDTYPE(GRAMMARP->addRange(new AstBasicDType($2->fileline(), LOGIC_IMPLICIT, $1), $2, false)); }
|
| signingE rangeList { VARDTYPE(GRAMMARP->addRange(new AstBasicDType($2->fileline(), LOGIC_IMPLICIT, $1), $2, true)); }
|
||||||
| signing { VARDTYPE(new AstBasicDType($<fl>1, LOGIC_IMPLICIT, $1)); }
|
| signing { VARDTYPE(new AstBasicDType($<fl>1, LOGIC_IMPLICIT, $1)); }
|
||||||
| yVAR data_type { VARDTYPE($2); }
|
| yVAR data_type { VARDTYPE($2); }
|
||||||
| yVAR implicit_typeE { VARDTYPE($2); }
|
| yVAR implicit_typeE { VARDTYPE($2); }
|
||||||
//
|
//
|
||||||
| tf_port_itemDir /*implicit*/ { VARDTYPE(NULL); /*default_nettype-see spec*/ }
|
| tf_port_itemDir /*implicit*/ { VARDTYPE(NULL); /*default_nettype-see spec*/ }
|
||||||
| tf_port_itemDir data_type { VARDTYPE($2); }
|
| tf_port_itemDir data_type { VARDTYPE($2); }
|
||||||
| tf_port_itemDir signingE rangeList { VARDTYPE(GRAMMARP->addRange(new AstBasicDType($3->fileline(), LOGIC_IMPLICIT, $2),$3,false)); }
|
| tf_port_itemDir signingE rangeList { VARDTYPE(GRAMMARP->addRange(new AstBasicDType($3->fileline(), LOGIC_IMPLICIT, $2),$3,true)); }
|
||||||
| tf_port_itemDir signing { VARDTYPE(new AstBasicDType($<fl>2, LOGIC_IMPLICIT, $2)); }
|
| tf_port_itemDir signing { VARDTYPE(new AstBasicDType($<fl>2, LOGIC_IMPLICIT, $2)); }
|
||||||
| tf_port_itemDir yVAR data_type { VARDTYPE($3); }
|
| tf_port_itemDir yVAR data_type { VARDTYPE($3); }
|
||||||
| tf_port_itemDir yVAR implicit_typeE { VARDTYPE($3); }
|
| tf_port_itemDir yVAR implicit_typeE { VARDTYPE($3); }
|
||||||
@@ -2698,7 +2771,7 @@ expr<nodep>: // IEEE: part of expression/constant_expression/primary
|
|||||||
| ~l~expr '?' ~r~expr ':' ~r~expr { $$ = new AstCond($2,$1,$3,$5); }
|
| ~l~expr '?' ~r~expr ':' ~r~expr { $$ = new AstCond($2,$1,$3,$5); }
|
||||||
//
|
//
|
||||||
// // IEEE: inside_expression
|
// // IEEE: inside_expression
|
||||||
//UNSUP ~l~expr yINSIDE '{' open_range_list '}' { UNSUP }
|
| ~l~expr yINSIDE '{' open_range_list '}' { $$ = new AstInside($2,$1,$4); }
|
||||||
//
|
//
|
||||||
// // IEEE: tagged_union_expression
|
// // IEEE: tagged_union_expression
|
||||||
//UNSUP yTAGGED id/*member*/ %prec prTAGGED { UNSUP }
|
//UNSUP yTAGGED id/*member*/ %prec prTAGGED { UNSUP }
|
||||||
@@ -3433,7 +3506,11 @@ AstNodeDType* V3ParseGrammar::createArray(AstNodeDType* basep, AstRange* rangep,
|
|||||||
while (rangep) {
|
while (rangep) {
|
||||||
AstRange* prevp = rangep->backp()->castRange();
|
AstRange* prevp = rangep->backp()->castRange();
|
||||||
if (prevp) rangep->unlinkFrBack();
|
if (prevp) rangep->unlinkFrBack();
|
||||||
arrayp = new AstArrayDType(rangep->fileline(), VFlagChildDType(), arrayp, rangep, isPacked);
|
if (isPacked) {
|
||||||
|
arrayp = new AstPackArrayDType(rangep->fileline(), VFlagChildDType(), arrayp, rangep);
|
||||||
|
} else {
|
||||||
|
arrayp = new AstUnpackArrayDType(rangep->fileline(), VFlagChildDType(), arrayp, rangep);
|
||||||
|
}
|
||||||
rangep = prevp;
|
rangep = prevp;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,7 +13,7 @@
|
|||||||
// please note it here, otherwise:**
|
// please note it here, otherwise:**
|
||||||
//
|
//
|
||||||
// This file ONLY is placed into the Public Domain, for any use,
|
// This file ONLY is placed into the Public Domain, for any use,
|
||||||
// without warranty, 2012 by Wilson Snyder.
|
// without warranty, 2013 by ____YOUR_NAME_HERE____.
|
||||||
|
|
||||||
module t (/*AUTOARG*/
|
module t (/*AUTOARG*/
|
||||||
// Inputs
|
// Inputs
|
||||||
|
|||||||
@@ -7,8 +7,6 @@ if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); di
|
|||||||
# Lesser General Public License Version 3 or the Perl Artistic License
|
# Lesser General Public License Version 3 or the Perl Artistic License
|
||||||
# Version 2.0.
|
# Version 2.0.
|
||||||
|
|
||||||
$Self->{vlt} and $Self->unsupported("Verilator unsupported, bug448");
|
|
||||||
|
|
||||||
compile (
|
compile (
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@@ -10,22 +10,40 @@ module t (/*AUTOARG*/
|
|||||||
|
|
||||||
input clk;
|
input clk;
|
||||||
|
|
||||||
|
`define checkh(gotv,expv) do if ((gotv) !== (expv)) begin $write("%%Error: %s:%0d: got='h%x exp='h%x\n", `__FILE__,`__LINE__, (gotv), (expv)); $stop; end while(0);
|
||||||
|
|
||||||
// parameters for array sizes
|
// parameters for array sizes
|
||||||
localparam WA = 4;
|
localparam WA = 4;
|
||||||
localparam WB = 6;
|
localparam WB = 6;
|
||||||
localparam WC = 8;
|
localparam WC = 8;
|
||||||
|
|
||||||
// 2D packed arrays
|
// 2D packed arrays
|
||||||
logic [WA-1:0] [WB-1:0] [WC-1:0] array_bg; // big endian array
|
logic [WA+1:2] [WB+1:2] [WC+1:2] array_bg; // big endian array
|
||||||
/* verilator lint_off LITENDIAN */
|
/* verilator lint_off LITENDIAN */
|
||||||
logic [0:WA-1] [0:WB-1] [0:WC-1] array_lt; // little endian array
|
logic [2:WA+1] [2:WB+1] [2:WC+1] array_lt; // little endian array
|
||||||
/* verilator lint_on LITENDIAN */
|
/* verilator lint_on LITENDIAN */
|
||||||
|
|
||||||
|
logic [1:0] array_unpk [3:2][1:0];
|
||||||
|
|
||||||
integer cnt = 0;
|
integer cnt = 0;
|
||||||
integer slc = 0; // slice type
|
integer slc = 0; // slice type
|
||||||
integer dim = 0; // dimension
|
integer dim = 0; // dimension
|
||||||
integer wdt = 0; // width
|
integer wdt = 0; // width
|
||||||
|
|
||||||
|
initial begin
|
||||||
|
`checkh($dimensions (array_unpk), 3);
|
||||||
|
`ifndef VCS
|
||||||
|
`checkh($unpacked_dimensions (array_unpk), 2); // IEEE 2009
|
||||||
|
`endif
|
||||||
|
`checkh($bits (array_unpk), 2*2*2);
|
||||||
|
`checkh($low (array_unpk), 2);
|
||||||
|
`checkh($high (array_unpk), 3);
|
||||||
|
`checkh($left (array_unpk), 3);
|
||||||
|
`checkh($right(array_unpk), 2);
|
||||||
|
`checkh($increment(array_unpk), 1);
|
||||||
|
`checkh($size (array_unpk), 2);
|
||||||
|
end
|
||||||
|
|
||||||
// event counter
|
// event counter
|
||||||
always @ (posedge clk) begin
|
always @ (posedge clk) begin
|
||||||
cnt <= cnt + 1;
|
cnt <= cnt + 1;
|
||||||
@@ -38,104 +56,114 @@ module t (/*AUTOARG*/
|
|||||||
$finish;
|
$finish;
|
||||||
end
|
end
|
||||||
|
|
||||||
|
integer slc_next;
|
||||||
|
|
||||||
// calculation of dimention sizes
|
// calculation of dimention sizes
|
||||||
always @ (posedge clk)
|
always @ (posedge clk) begin
|
||||||
begin
|
// slicing type counter
|
||||||
// slicing tipe counter
|
|
||||||
case (cnt[3:2])
|
case (cnt[3:2])
|
||||||
2'd0 : begin slc <= 0; end // full array
|
2'd0 : begin slc_next = 0; end // full array
|
||||||
2'd1 : begin slc <= 1; end // half array
|
2'd1 : begin slc_next = 1; end // single array element
|
||||||
2'd2 : begin slc <= 2; end // single array element
|
2'd2 : begin slc_next = 2; end // half array
|
||||||
default: begin slc <= 0; end
|
default: begin slc_next = 0; end
|
||||||
endcase
|
endcase
|
||||||
// dimmension counter
|
slc <= slc_next;
|
||||||
|
// dimension counter
|
||||||
case (cnt[1:0])
|
case (cnt[1:0])
|
||||||
2'd0 : begin dim <= 1; wdt = (slc==1) ? WA/2 : (slc==2) ? 1 : WA; end
|
2'd0 : begin dim <= 1; wdt <= (slc_next==1) ? WA/2 : (slc_next==2) ? WA/2 : WA; end
|
||||||
2'd1 : begin dim <= 2; wdt = WB; end
|
2'd1 : begin dim <= 2; wdt <= WB; end
|
||||||
2'd2 : begin dim <= 3; wdt = WC; end
|
2'd2 : begin dim <= 3; wdt <= WC; end
|
||||||
default: begin dim <= 0; wdt = 0; end
|
default: begin dim <= 0; wdt <= 0; end
|
||||||
endcase
|
endcase
|
||||||
end
|
end
|
||||||
|
|
||||||
always @ (posedge clk)
|
always @ (posedge clk) begin
|
||||||
if (cnt[30:4]==1) begin
|
`ifdef TEST_VERBOSE
|
||||||
// big endian
|
$write("cnt[30:4]=%0d slc=%0d dim=%0d wdt=%0d\n", cnt[30:4], slc, dim, wdt);
|
||||||
if (cnt[3:2]==0) begin
|
`endif
|
||||||
// full array
|
if (cnt[30:4]==1) begin
|
||||||
if ($dimensions (array_bg) != 3) $stop;
|
// big endian
|
||||||
if ($bits (array_bg) != WA*WB*WC) $stop;
|
if (slc==0) begin
|
||||||
if ((dim>=1)&&(dim<=3)) begin
|
// full array
|
||||||
if ($left (array_bg, dim) != wdt-1) $stop;
|
`checkh($dimensions (array_bg), 3);
|
||||||
if ($right (array_bg, dim) != 0 ) $stop;
|
`checkh($bits (array_bg), WA*WB*WC);
|
||||||
if ($low (array_bg, dim) != 0 ) $stop;
|
if ((dim>=1)&&(dim<=3)) begin
|
||||||
if ($high (array_bg, dim) != wdt-1) $stop;
|
`checkh($left (array_bg, dim), wdt+1);
|
||||||
if ($increment (array_bg, dim) != 1 ) $stop;
|
`checkh($right (array_bg, dim), 2 );
|
||||||
if ($size (array_bg, dim) != wdt ) $stop;
|
`checkh($low (array_bg, dim), 2 );
|
||||||
end
|
`checkh($high (array_bg, dim), wdt+1);
|
||||||
end else if (cnt[3:2]==1) begin
|
`checkh($increment (array_bg, dim), 1 );
|
||||||
// half array
|
`checkh($size (array_bg, dim), wdt );
|
||||||
if ($dimensions (array_bg[WA/2-1:0]) != 3) $stop;
|
end
|
||||||
if ($bits (array_bg[WA/2-1:0]) != WA/2*WB*WC) $stop;
|
end else if (slc==1) begin
|
||||||
if ((dim>=1)&&(dim<=3)) begin
|
// single array element
|
||||||
if ($left (array_bg[WA/2-1:0], dim) != wdt-1) $stop;
|
`checkh($dimensions (array_bg[2]), 2);
|
||||||
if ($right (array_bg[WA/2-1:0], dim) != 0 ) $stop;
|
`checkh($bits (array_bg[2]), WB*WC);
|
||||||
if ($low (array_bg[WA/2-1:0], dim) != 0 ) $stop;
|
if ((dim>=2)&&(dim<=3)) begin
|
||||||
if ($high (array_bg[WA/2-1:0], dim) != wdt-1) $stop;
|
`checkh($left (array_bg[2], dim-1), wdt+1);
|
||||||
if ($increment (array_bg[WA/2-1:0], dim) != 1 ) $stop;
|
`checkh($right (array_bg[2], dim-1), 2 );
|
||||||
if ($size (array_bg[WA/2-1:0], dim) != wdt ) $stop;
|
`checkh($low (array_bg[2], dim-1), 2 );
|
||||||
end
|
`checkh($high (array_bg[2], dim-1), wdt+1);
|
||||||
end else if (cnt[3:2]==2) begin
|
`checkh($increment (array_bg[2], dim-1), 1 );
|
||||||
// single array element
|
`checkh($size (array_bg[2], dim-1), wdt );
|
||||||
if ($dimensions (array_bg[0]) != 2) $stop;
|
end
|
||||||
if ($bits (array_bg[0]) != WB*WC) $stop;
|
`ifndef VERILATOR // Unsupported slices don't maintain size correctly
|
||||||
if ((dim>=2)&&(dim<=3)) begin
|
end else if (slc==2) begin
|
||||||
if ($left (array_bg[0], dim-1) != wdt-1) $stop;
|
// half array
|
||||||
if ($right (array_bg[0], dim-1) != 0 ) $stop;
|
`checkh($dimensions (array_bg[WA/2+1:2]), 3);
|
||||||
if ($low (array_bg[0], dim-1) != 0 ) $stop;
|
`checkh($bits (array_bg[WA/2+1:2]), WA/2*WB*WC);
|
||||||
if ($high (array_bg[0], dim-1) != wdt-1) $stop;
|
if ((dim>=1)&&(dim<=3)) begin
|
||||||
if ($increment (array_bg[0], dim-1) != 1 ) $stop;
|
`checkh($left (array_bg[WA/2+1:2], dim), wdt+1);
|
||||||
if ($size (array_bg[0], dim-1) != wdt ) $stop;
|
`checkh($right (array_bg[WA/2+1:2], dim), 2 );
|
||||||
end
|
`checkh($low (array_bg[WA/2+1:2], dim), 2 );
|
||||||
end
|
`checkh($high (array_bg[WA/2+1:2], dim), wdt+1);
|
||||||
end else if (cnt[30:4]==2) begin
|
`checkh($increment (array_bg[WA/2+1:2], dim), 1 );
|
||||||
// little endian
|
`checkh($size (array_bg[WA/2+1:2], dim), wdt);
|
||||||
if (cnt[3:2]==0) begin
|
end
|
||||||
// full array
|
`endif
|
||||||
if ($dimensions (array_lt) != 3) $stop;
|
end
|
||||||
if ($bits (array_lt) != WA*WB*WC) $stop;
|
end else if (cnt[30:4]==2) begin
|
||||||
if ((dim>=1)&&(dim<=3)) begin
|
// little endian
|
||||||
if ($left (array_lt, dim) != 0 ) $stop;
|
if (slc==0) begin
|
||||||
if ($right (array_lt, dim) != wdt-1) $stop;
|
// full array
|
||||||
if ($low (array_lt, dim) != 0 ) $stop;
|
`checkh($dimensions (array_lt), 3);
|
||||||
if ($high (array_lt, dim) != wdt-1) $stop;
|
`checkh($bits (array_lt), WA*WB*WC);
|
||||||
if ($increment (array_lt, dim) != -1 ) $stop;
|
if ((dim>=1)&&(dim<=3)) begin
|
||||||
if ($size (array_lt, dim) != wdt ) $stop;
|
`checkh($left (array_lt, dim), 2 );
|
||||||
end
|
`checkh($right (array_lt, dim), wdt+1);
|
||||||
end else if (cnt[3:2]==1) begin
|
`checkh($low (array_lt, dim), 2 );
|
||||||
// half array
|
`checkh($high (array_lt, dim), wdt+1);
|
||||||
if ($dimensions (array_lt[0:WA/2-1]) != 3) $stop;
|
`checkh($increment (array_lt, dim), -1 );
|
||||||
if ($bits (array_lt[0:WA/2-1]) != WA/2*WB*WC) $stop;
|
`checkh($size (array_lt, dim), wdt );
|
||||||
if ((dim>=1)&&(dim<=3)) begin
|
end
|
||||||
if ($left (array_lt[0:WA/2-1], dim) != 0 ) $stop;
|
end else if (slc==1) begin
|
||||||
if ($right (array_lt[0:WA/2-1], dim) != wdt-1) $stop;
|
// single array element
|
||||||
if ($low (array_lt[0:WA/2-1], dim) != 0 ) $stop;
|
`checkh($dimensions (array_lt[2]), 2);
|
||||||
if ($high (array_lt[0:WA/2-1], dim) != wdt-1) $stop;
|
`checkh($bits (array_lt[2]), WB*WC);
|
||||||
if ($increment (array_lt[0:WA/2-1], dim) != -1 ) $stop;
|
if ((dim>=2)&&(dim<=3)) begin
|
||||||
if ($size (array_lt[0:WA/2-1], dim) != wdt ) $stop;
|
`checkh($left (array_lt[2], dim-1), 2 );
|
||||||
end
|
`checkh($right (array_lt[2], dim-1), wdt+1);
|
||||||
end else if (cnt[3:2]==2) begin
|
`checkh($low (array_lt[2], dim-1), 2 );
|
||||||
// single array element
|
`checkh($high (array_lt[2], dim-1), wdt+1);
|
||||||
if ($dimensions (array_lt[0]) != 2) $stop;
|
`checkh($increment (array_lt[2], dim-1), -1 );
|
||||||
if ($bits (array_lt[0]) != WB*WC) $stop;
|
`checkh($size (array_lt[2], dim-1), wdt );
|
||||||
if ((dim>=2)&&(dim<=3)) begin
|
end
|
||||||
if ($left (array_lt[0], dim-1) != 0 ) $stop;
|
`ifndef VERILATOR // Unsupported slices don't maintain size correctly
|
||||||
if ($right (array_lt[0], dim-1) != wdt-1) $stop;
|
end else if (slc==2) begin
|
||||||
if ($low (array_lt[0], dim-1) != 0 ) $stop;
|
// half array
|
||||||
if ($high (array_lt[0], dim-1) != wdt-1) $stop;
|
`checkh($dimensions (array_lt[2:WA/2+1]), 3);
|
||||||
if ($increment (array_lt[0], dim-1) != -1 ) $stop;
|
`checkh($bits (array_lt[2:WA/2+1]), WA/2*WB*WC);
|
||||||
if ($size (array_lt[0], dim-1) != wdt ) $stop;
|
if ((dim>=1)&&(dim<=3)) begin
|
||||||
end
|
`checkh($left (array_lt[2:WA/2+1], dim), 2 );
|
||||||
|
`checkh($right (array_lt[2:WA/2+1], dim), wdt+1);
|
||||||
|
`checkh($low (array_lt[2:WA/2+1], dim), 2 );
|
||||||
|
`checkh($high (array_lt[2:WA/2+1], dim), wdt+1);
|
||||||
|
`checkh($increment (array_lt[2:WA/2+1], dim), -1 );
|
||||||
|
`checkh($size (array_lt[2:WA/2+1], dim), wdt );
|
||||||
|
end
|
||||||
|
`endif
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
endmodule
|
endmodule
|
||||||
|
|||||||
@@ -7,8 +7,6 @@ if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); di
|
|||||||
# Lesser General Public License Version 3 or the Perl Artistic License
|
# Lesser General Public License Version 3 or the Perl Artistic License
|
||||||
# Version 2.0.
|
# Version 2.0.
|
||||||
|
|
||||||
$Self->{vlt} and $Self->unsupported("Verilator unsupported, bug448");
|
|
||||||
|
|
||||||
compile (
|
compile (
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@@ -39,7 +39,9 @@ module array_test
|
|||||||
|
|
||||||
input clk;
|
input clk;
|
||||||
|
|
||||||
|
// verilator lint_off LITENDIAN
|
||||||
reg [7:0] a [LEFT:RIGHT];
|
reg [7:0] a [LEFT:RIGHT];
|
||||||
|
// verilator lint_on LITENDIAN
|
||||||
|
|
||||||
integer l;
|
integer l;
|
||||||
integer r;
|
integer r;
|
||||||
@@ -54,10 +56,8 @@ module array_test
|
|||||||
$write ("$left (a) = %d, $right (a) = %d, $size (a) = %d\n", l, r, s);
|
$write ("$left (a) = %d, $right (a) = %d, $size (a) = %d\n", l, r, s);
|
||||||
`endif
|
`endif
|
||||||
|
|
||||||
if ((l == LEFT) && (r == RIGHT) && (s == (RIGHT - LEFT + 1))) begin
|
if ((l != LEFT) || (r != RIGHT) || (s != (RIGHT - LEFT + 1))) $stop;
|
||||||
$write("*-* All Finished *-*\n");
|
$write("*-* All Finished *-*\n");
|
||||||
end
|
|
||||||
|
|
||||||
$finish;
|
$finish;
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -7,14 +7,12 @@ if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); di
|
|||||||
# Lesser General Public License Version 3 or the Perl Artistic License
|
# Lesser General Public License Version 3 or the Perl Artistic License
|
||||||
# Version 2.0.
|
# Version 2.0.
|
||||||
|
|
||||||
$Self->{vlt} and $Self->unsupported("Verilator unsupported, bind");
|
|
||||||
|
|
||||||
compile (
|
compile (
|
||||||
);
|
);
|
||||||
|
|
||||||
execute (
|
execute (
|
||||||
check_finished=>1,
|
check_finished=>1,
|
||||||
);
|
);
|
||||||
|
|
||||||
ok(1);
|
ok(1);
|
||||||
1;
|
1;
|
||||||
|
|||||||
Executable
+18
@@ -0,0 +1,18 @@
|
|||||||
|
#!/usr/bin/perl
|
||||||
|
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
|
||||||
|
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||||
|
#
|
||||||
|
# Copyright 2003 by Wilson Snyder. This program is free software; you can
|
||||||
|
# redistribute it and/or modify it under the terms of either the GNU
|
||||||
|
# Lesser General Public License Version 3 or the Perl Artistic License
|
||||||
|
# Version 2.0.
|
||||||
|
|
||||||
|
compile (
|
||||||
|
);
|
||||||
|
|
||||||
|
execute (
|
||||||
|
check_finished=>1,
|
||||||
|
);
|
||||||
|
|
||||||
|
ok(1);
|
||||||
|
1;
|
||||||
@@ -0,0 +1,92 @@
|
|||||||
|
// DESCRIPTION: Verilator: Verilog Test module
|
||||||
|
//
|
||||||
|
// This file ONLY is placed into the Public Domain, for any use,
|
||||||
|
// without warranty, 2013 by Ed Lander.
|
||||||
|
|
||||||
|
// verilator lint_off WIDTH
|
||||||
|
|
||||||
|
`define checkh(gotv,expv) do if ((gotv) !== (expv)) begin $write("%%Error: %s:%0d: got='h%x exp='h%x\n", `__FILE__,`__LINE__, (gotv), (expv)); $stop; end while(0);
|
||||||
|
|
||||||
|
module t (/*AUTOARG*/
|
||||||
|
// Inputs
|
||||||
|
clk
|
||||||
|
);
|
||||||
|
input clk;
|
||||||
|
reg [7:0] p1;
|
||||||
|
reg [7:0] p2;
|
||||||
|
reg [7:0] p3;
|
||||||
|
|
||||||
|
initial begin
|
||||||
|
p1 = 8'h01;
|
||||||
|
p2 = 8'h02;
|
||||||
|
p3 = 8'h03;
|
||||||
|
end
|
||||||
|
|
||||||
|
parameter int param1 = 8'h11;
|
||||||
|
parameter int param2 = 8'h12;
|
||||||
|
parameter int param3 = 8'h13;
|
||||||
|
|
||||||
|
targetmod i_targetmod (/*AUTOINST*/
|
||||||
|
// Inputs
|
||||||
|
.clk (clk));
|
||||||
|
|
||||||
|
//Binding i_targetmod to mycheck --instantiates i_mycheck inside i_targetmod
|
||||||
|
//param1 not over-riden (as mycheck) (=> 0x31)
|
||||||
|
//param2 explicitly bound to targetmod value (=> 0x22)
|
||||||
|
//param3 explicitly bound to top value (=> 0x13)
|
||||||
|
//p1 implictly bound (.*), takes value from targetmod (=> 0x04)
|
||||||
|
//p2 explictly bound to targetmod (=> 0x05)
|
||||||
|
//p3 explictly bound to top (=> 0x03)
|
||||||
|
|
||||||
|
// Alternative unsupported form is i_targetmod
|
||||||
|
bind targetmod mycheck
|
||||||
|
#(
|
||||||
|
.param2(param2),
|
||||||
|
.param3(param3)
|
||||||
|
)
|
||||||
|
i_mycheck (.p2(p2), .p3(p3), .*);
|
||||||
|
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
module targetmod (input clk);
|
||||||
|
reg [7:0] p1;
|
||||||
|
reg [7:0] p2;
|
||||||
|
reg [7:0] p3;
|
||||||
|
|
||||||
|
parameter int param1 = 8'h21;
|
||||||
|
parameter int param2 = 8'h22;
|
||||||
|
parameter int param3 = 8'h23;
|
||||||
|
|
||||||
|
initial begin
|
||||||
|
p1 = 8'h04;
|
||||||
|
p2 = 8'h05;
|
||||||
|
p3 = 8'h06;
|
||||||
|
end
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
module mycheck (/*AUTOARG*/
|
||||||
|
// Inputs
|
||||||
|
clk, p1, p2, p3
|
||||||
|
);
|
||||||
|
|
||||||
|
input clk;
|
||||||
|
input [7:0] p1;
|
||||||
|
input [7:0] p2;
|
||||||
|
input [7:0] p3;
|
||||||
|
|
||||||
|
parameter int param1 = 8'h31;
|
||||||
|
parameter int param2 = 8'h32;
|
||||||
|
parameter int param3 = 8'h33;
|
||||||
|
|
||||||
|
always @ (posedge clk) begin
|
||||||
|
`checkh(param1,8'h31);
|
||||||
|
`checkh(param2,8'h22);
|
||||||
|
`checkh(param3,8'h23);
|
||||||
|
`checkh(p1,8'h04);
|
||||||
|
`checkh(p2,8'h05);
|
||||||
|
`checkh(p3,8'h06);
|
||||||
|
$write("*-* All Finished *-*\n");
|
||||||
|
$finish;
|
||||||
|
end
|
||||||
|
endmodule
|
||||||
|
|
||||||
@@ -11,9 +11,8 @@ compile (
|
|||||||
v_flags2 => ["--lint-only"],
|
v_flags2 => ["--lint-only"],
|
||||||
fails=>1,
|
fails=>1,
|
||||||
expect=>
|
expect=>
|
||||||
'%Error: t/t_bitsel_const_bad.v:\d+: Illegal bit or array select; variable already selected, or bad dimension: b
|
'%Error: t/t_bitsel_const_bad.v:\d+: Illegal bit or array select; type does not have a bit range, or bad dimension: type is logic
|
||||||
.*
|
.*%Error: Exiting due to.*',
|
||||||
%Error: Exiting due to.*',
|
|
||||||
);
|
);
|
||||||
|
|
||||||
ok(1);
|
ok(1);
|
||||||
|
|||||||
Executable
+18
@@ -0,0 +1,18 @@
|
|||||||
|
#!/usr/bin/perl
|
||||||
|
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
|
||||||
|
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||||
|
#
|
||||||
|
# Copyright 2003 by Wilson Snyder. This program is free software; you can
|
||||||
|
# redistribute it and/or modify it under the terms of either the GNU
|
||||||
|
# Lesser General Public License Version 3 or the Perl Artistic License
|
||||||
|
# Version 2.0.
|
||||||
|
|
||||||
|
compile (
|
||||||
|
);
|
||||||
|
|
||||||
|
execute (
|
||||||
|
check_finished=>1,
|
||||||
|
);
|
||||||
|
|
||||||
|
ok(1);
|
||||||
|
1;
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
// DESCRIPTION: Verilator: Verilog Test module
|
||||||
|
//
|
||||||
|
// A test case for struct signal bit selection.
|
||||||
|
//
|
||||||
|
// This test is to check that bit selection of multi-dimensional signal inside
|
||||||
|
// of a struct works.
|
||||||
|
//
|
||||||
|
// This file ONLY is placed into the Public Domain, for any use,
|
||||||
|
// without warranty, 2012 by Jie Xu.
|
||||||
|
|
||||||
|
module t(/*AUTOARG*/
|
||||||
|
// Inputs
|
||||||
|
clk
|
||||||
|
);
|
||||||
|
|
||||||
|
input clk;
|
||||||
|
typedef struct packed {
|
||||||
|
logic [1:0][15:0] channel;
|
||||||
|
logic others;
|
||||||
|
} buss_t;
|
||||||
|
|
||||||
|
buss_t b;
|
||||||
|
reg [7:0] a;
|
||||||
|
|
||||||
|
initial begin
|
||||||
|
b = {16'h8765,16'h4321,1'b1};
|
||||||
|
a = b.channel[0][8+:8];
|
||||||
|
if (a != 8'h43) $stop;
|
||||||
|
$write("*-* All Finished *-*\n");
|
||||||
|
$finish;
|
||||||
|
end
|
||||||
|
endmodule
|
||||||
Executable
+18
@@ -0,0 +1,18 @@
|
|||||||
|
#!/usr/bin/perl
|
||||||
|
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
|
||||||
|
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||||
|
#
|
||||||
|
# Copyright 2003 by Wilson Snyder. This program is free software; you can
|
||||||
|
# redistribute it and/or modify it under the terms of either the GNU
|
||||||
|
# Lesser General Public License Version 3 or the Perl Artistic License
|
||||||
|
# Version 2.0.
|
||||||
|
|
||||||
|
compile (
|
||||||
|
);
|
||||||
|
|
||||||
|
execute (
|
||||||
|
check_finished=>1,
|
||||||
|
);
|
||||||
|
|
||||||
|
ok(1);
|
||||||
|
1;
|
||||||
@@ -0,0 +1,44 @@
|
|||||||
|
// DESCRIPTION: Verilator: Verilog Test module
|
||||||
|
//
|
||||||
|
// This file ONLY is placed into the Public Domain, for any use,
|
||||||
|
// without warranty, 2013 by Wilson Snyder.
|
||||||
|
|
||||||
|
module t (/*AUTOARG*/);
|
||||||
|
|
||||||
|
typedef struct packed {
|
||||||
|
logic [3:2] a;
|
||||||
|
logic [5:4][3:2] b;
|
||||||
|
} ab_t;
|
||||||
|
typedef ab_t [7:6] c_t; // array of structs
|
||||||
|
typedef struct packed {
|
||||||
|
c_t [17:16] d;
|
||||||
|
} e_t;
|
||||||
|
|
||||||
|
`define checkb(gotv,expv) do if ((gotv) !== (expv)) begin $write("%%Error: %s:%0d: got='b%x exp='b%x\n", `__FILE__,`__LINE__, (gotv), (expv)); $stop; end while(0);
|
||||||
|
`define checkh(gotv,expv) do if ((gotv) !== (expv)) begin $write("%%Error: %s:%0d: got='h%x exp='h%x\n", `__FILE__,`__LINE__, (gotv), (expv)); $stop; end while(0);
|
||||||
|
|
||||||
|
initial begin
|
||||||
|
e_t e;
|
||||||
|
`checkh($bits(ab_t),6);
|
||||||
|
`checkh($bits(c_t),12);
|
||||||
|
`checkh($bits(e_t),24);
|
||||||
|
`checkh($bits(e), 24);
|
||||||
|
`checkh($bits(e.d[17]),12);
|
||||||
|
`checkh($bits(e.d[16][6]),6);
|
||||||
|
`checkh($bits(e.d[16][6].b[5]),2);
|
||||||
|
`checkh($bits(e.d[16][6].b[5][2]), 1);
|
||||||
|
//
|
||||||
|
e = 24'b101101010111010110101010;
|
||||||
|
`checkb(e, 24'b101101010111010110101010);
|
||||||
|
e.d[17] = 12'b111110011011;
|
||||||
|
`checkb(e, 24'b111110011011010110101010);
|
||||||
|
e.d[16][6] = 6'b010101;
|
||||||
|
`checkb(e, 24'b111110011011010110010101);
|
||||||
|
e.d[16][6].b[5] = 2'b10;
|
||||||
|
`checkb(e, 24'b111110011011010110011001);
|
||||||
|
e.d[16][6].b[5][2] = 1'b1;
|
||||||
|
//
|
||||||
|
$write("*-* All Finished *-*\n");
|
||||||
|
$finish;
|
||||||
|
end
|
||||||
|
endmodule
|
||||||
Executable
+18
@@ -0,0 +1,18 @@
|
|||||||
|
#!/usr/bin/perl
|
||||||
|
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
|
||||||
|
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||||
|
#
|
||||||
|
# Copyright 2003 by Wilson Snyder. This program is free software; you can
|
||||||
|
# redistribute it and/or modify it under the terms of either the GNU
|
||||||
|
# Lesser General Public License Version 3 or the Perl Artistic License
|
||||||
|
# Version 2.0.
|
||||||
|
|
||||||
|
compile (
|
||||||
|
);
|
||||||
|
|
||||||
|
execute (
|
||||||
|
check_finished=>1,
|
||||||
|
);
|
||||||
|
|
||||||
|
ok(1);
|
||||||
|
1;
|
||||||
@@ -0,0 +1,42 @@
|
|||||||
|
// DESCRIPTION: Verilator: Verilog Test module
|
||||||
|
//
|
||||||
|
// A test case for struct signal bit selection.
|
||||||
|
//
|
||||||
|
// This test is to check that bit selection of multi-dimensional signal inside
|
||||||
|
// of a packed struct works. Currently +: and -: blow up with packed structs.
|
||||||
|
//
|
||||||
|
// This file ONLY is placed into the Public Domain, for any use, without
|
||||||
|
// warranty, 2013 by Jie Xu.
|
||||||
|
|
||||||
|
module t(/*AUTOARG*/
|
||||||
|
// Inputs
|
||||||
|
clk
|
||||||
|
);
|
||||||
|
|
||||||
|
input clk;
|
||||||
|
typedef struct packed {
|
||||||
|
logic [15:0] channel;
|
||||||
|
logic [15:0] others;
|
||||||
|
} buss_t;
|
||||||
|
|
||||||
|
buss_t b;
|
||||||
|
|
||||||
|
reg [7:0] a;
|
||||||
|
reg [7:0] c;
|
||||||
|
reg [7:0] d;
|
||||||
|
|
||||||
|
initial begin
|
||||||
|
b = {16'h8765,16'h4321};
|
||||||
|
a = b[19:12]; // This works
|
||||||
|
c = b[8+:8]; // This fails
|
||||||
|
d = b[11-:8]; // This fails
|
||||||
|
if ((a == 8'h54) && (c == 8'h43) && (d == 8'h32)) begin
|
||||||
|
$write("*-* All Finished *-*\n");
|
||||||
|
$finish;
|
||||||
|
end
|
||||||
|
else begin
|
||||||
|
$stop;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
endmodule
|
||||||
@@ -18,7 +18,7 @@ execute (
|
|||||||
# Read the input .v file and do any CHECK_COVER requests
|
# Read the input .v file and do any CHECK_COVER requests
|
||||||
inline_checks();
|
inline_checks();
|
||||||
|
|
||||||
file_grep ($Self->{stats}, qr/Coverage, Toggle points joined\s+(\d+)/i, 24)
|
file_grep ($Self->{stats}, qr/Coverage, Toggle points joined\s+(\d+)/i, 25)
|
||||||
if $Self->{vlt};
|
if $Self->{vlt};
|
||||||
|
|
||||||
ok(1);
|
ok(1);
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ reg covfok;
|
|||||||
reg [15:0] xwieqw;
|
reg [15:0] xwieqw;
|
||||||
reg [2:0] ofnjjt;
|
reg [2:0] ofnjjt;
|
||||||
|
|
||||||
reg [37:0] hdsejo[0:1];
|
reg [37:0] hdsejo[1:0];
|
||||||
|
|
||||||
reg wxxzgd, tceppr, ratebp, fjizkr, iwwrnq;
|
reg wxxzgd, tceppr, ratebp, fjizkr, iwwrnq;
|
||||||
reg vrqrih, ryyjxy;
|
reg vrqrih, ryyjxy;
|
||||||
|
|||||||
Executable
+18
@@ -0,0 +1,18 @@
|
|||||||
|
#!/usr/bin/perl
|
||||||
|
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
|
||||||
|
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||||
|
#
|
||||||
|
# Copyright 2003 by Wilson Snyder. This program is free software; you can
|
||||||
|
# redistribute it and/or modify it under the terms of either the GNU
|
||||||
|
# Lesser General Public License Version 3 or the Perl Artistic License
|
||||||
|
# Version 2.0.
|
||||||
|
|
||||||
|
compile (
|
||||||
|
);
|
||||||
|
|
||||||
|
execute (
|
||||||
|
check_finished=>1,
|
||||||
|
);
|
||||||
|
|
||||||
|
ok(1);
|
||||||
|
1;
|
||||||
@@ -0,0 +1,69 @@
|
|||||||
|
// DESCRIPTION::Verilog Test module
|
||||||
|
//
|
||||||
|
// This file ONLY is placed into the Public Domain, for any use,
|
||||||
|
// without warranty, 2013 by Wilson Snyder.
|
||||||
|
|
||||||
|
module t;
|
||||||
|
|
||||||
|
`define checkh(gotv,expv) do if ((gotv) !== (expv)) begin $write("%%Error: %s:%0d: got='h%x exp='h%x\n", `__FILE__,`__LINE__, (gotv), (expv)); $stop; end while(0);
|
||||||
|
|
||||||
|
typedef enum logic [1:0]
|
||||||
|
{ ZERO = 2'd0,
|
||||||
|
ONE = 2'd1,
|
||||||
|
TWO = 2'd2,
|
||||||
|
THREE = 2'd3,
|
||||||
|
XXX = 2'dx
|
||||||
|
} num_t;
|
||||||
|
|
||||||
|
function automatic logic is_odd;
|
||||||
|
input en;
|
||||||
|
input num_t number;
|
||||||
|
case (en)
|
||||||
|
1'b1: begin
|
||||||
|
unique if (number inside {ONE, THREE})
|
||||||
|
is_odd = 1'b1;
|
||||||
|
else if (number inside {ZERO, TWO})
|
||||||
|
is_odd = 1'b0;
|
||||||
|
else
|
||||||
|
is_odd = 1'bx;
|
||||||
|
end
|
||||||
|
1'b0: is_odd = 1'bx;
|
||||||
|
default: is_odd = 1'bx;
|
||||||
|
endcase
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
initial begin
|
||||||
|
`checkh ((4'd4 inside {4'd1,4'd5}), 1'b0);
|
||||||
|
`checkh ((4'd4 inside {4'd1,4'd4}), 1'b1);
|
||||||
|
//
|
||||||
|
`checkh ((4'b1011 inside {4'b1001}), 1'b0);
|
||||||
|
`checkh ((4'b1011 inside {4'b1xx1}), 1'b1); // Uses ==?
|
||||||
|
`checkh ((4'b1001 inside {4'b1xx1}), 1'b1); // Uses ==?
|
||||||
|
`checkh ((4'b1001 inside {4'b1??1}), 1'b1);
|
||||||
|
`ifndef VERILATOR
|
||||||
|
`checkh ((4'b1z11 inside {4'b11?1, 4'b1011}),1'bx);
|
||||||
|
`endif
|
||||||
|
// Range
|
||||||
|
`checkh ((4'd4 inside {[4'd5:4'd3], [4'd10:4'd8]}), 1'b0); // If left of colon < never matches
|
||||||
|
`checkh ((4'd3 inside {[4'd1:4'd2], [4'd3:4'd5]}), 1'b1);
|
||||||
|
`checkh ((4'd4 inside {[4'd1:4'd2], [4'd3:4'd5]}), 1'b1);
|
||||||
|
`checkh ((4'd5 inside {[4'd1:4'd2], [4'd3:4'd5]}), 1'b1);
|
||||||
|
//
|
||||||
|
// Unsupported $ bound
|
||||||
|
//
|
||||||
|
// Unsupported if unpacked array, elements tranversed
|
||||||
|
//int unpackedarray [$] = '{8,9};
|
||||||
|
//( expr inside {2, 3, unpackedarray}) // { 2,3,8,9}
|
||||||
|
//
|
||||||
|
`checkh (is_odd(1'b1, ZERO), 1'd0);
|
||||||
|
`checkh (is_odd(1'b1, ONE), 1'd1);
|
||||||
|
`checkh (is_odd(1'b1, TWO), 1'd0);
|
||||||
|
`checkh (is_odd(1'b1, THREE),1'd1);
|
||||||
|
`ifndef VERILATOR
|
||||||
|
`checkh (is_odd(1'b1, XXX), 1'dx);
|
||||||
|
`endif
|
||||||
|
//
|
||||||
|
$write("*-* All Finished *-*\n");
|
||||||
|
$finish;
|
||||||
|
end
|
||||||
|
endmodule
|
||||||
@@ -9,8 +9,8 @@ module t (/*AUTOARG*/
|
|||||||
);
|
);
|
||||||
input clk;
|
input clk;
|
||||||
|
|
||||||
wire [17:10] bitout;
|
wire [19:10] bitout;
|
||||||
wire [27:24] short_bitout;
|
wire [29:24] short_bitout;
|
||||||
wire [7:0] allbits;
|
wire [7:0] allbits;
|
||||||
wire [15:0] twobits;
|
wire [15:0] twobits;
|
||||||
|
|
||||||
@@ -37,6 +37,11 @@ module t (/*AUTOARG*/
|
|||||||
.twobits (twobits),
|
.twobits (twobits),
|
||||||
.bitout (bitout[17:10]));
|
.bitout (bitout[17:10]));
|
||||||
|
|
||||||
|
sub
|
||||||
|
i_sub6 [7:4] (.allbits (allbits),
|
||||||
|
.twobits (twobits[15:8]),
|
||||||
|
.bitout ({bitout[18+:2],short_bitout[28+:2]}));
|
||||||
|
|
||||||
integer cyc=0;
|
integer cyc=0;
|
||||||
reg [63:0] crc;
|
reg [63:0] crc;
|
||||||
reg [63:0] sum;
|
reg [63:0] sum;
|
||||||
@@ -44,7 +49,7 @@ module t (/*AUTOARG*/
|
|||||||
// Signals under test
|
// Signals under test
|
||||||
assign allbits = crc[7:0];
|
assign allbits = crc[7:0];
|
||||||
assign twobits = crc[15:0];
|
assign twobits = crc[15:0];
|
||||||
wire [63:0] result = {52'h0, short_bitout, bitout};
|
wire [63:0] result = {48'h0, short_bitout, bitout};
|
||||||
|
|
||||||
// Test loop
|
// Test loop
|
||||||
always @ (posedge clk) begin
|
always @ (posedge clk) begin
|
||||||
@@ -68,7 +73,7 @@ module t (/*AUTOARG*/
|
|||||||
$write("[%0t] cyc==%0d crc=%x sum=%x\n",$time, cyc, crc, sum);
|
$write("[%0t] cyc==%0d crc=%x sum=%x\n",$time, cyc, crc, sum);
|
||||||
if (crc !== 64'hc77bb9b3784ea091) $stop;
|
if (crc !== 64'hc77bb9b3784ea091) $stop;
|
||||||
// What checksum will we end up with (above print should match)
|
// What checksum will we end up with (above print should match)
|
||||||
`define EXPECTED_SUM 64'h0bf9559ce1f98425
|
`define EXPECTED_SUM 64'ha1da9ff8082a4ff6
|
||||||
if (sum !== `EXPECTED_SUM) $stop;
|
if (sum !== `EXPECTED_SUM) $stop;
|
||||||
$write("*-* All Finished *-*\n");
|
$write("*-* All Finished *-*\n");
|
||||||
$finish;
|
$finish;
|
||||||
|
|||||||
@@ -7,13 +7,11 @@ if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); di
|
|||||||
# Lesser General Public License Version 3 or the Perl Artistic License
|
# Lesser General Public License Version 3 or the Perl Artistic License
|
||||||
# Version 2.0.
|
# Version 2.0.
|
||||||
|
|
||||||
$Self->{vlt} and $Self->unsupported("Verilator unsupported, bug595");
|
|
||||||
|
|
||||||
compile (
|
compile (
|
||||||
verilator_flags2 => ["--lint-only"],
|
verilator_flags2 => ["--lint-only"],
|
||||||
fails=>1,
|
fails=>1,
|
||||||
expect=>
|
expect=>
|
||||||
'TBD
|
'%Error: t/t_inst_misarray_bad.v:\d+: Illegal port connection \'foo\', mismatch between port which is not an array, and expression which is an array.
|
||||||
%Error: Exiting due to.*',
|
%Error: Exiting due to.*',
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
Executable
+18
@@ -0,0 +1,18 @@
|
|||||||
|
#!/usr/bin/perl
|
||||||
|
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
|
||||||
|
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||||
|
#
|
||||||
|
# Copyright 2003 by Wilson Snyder. This program is free software; you can
|
||||||
|
# redistribute it and/or modify it under the terms of either the GNU
|
||||||
|
# Lesser General Public License Version 3 or the Perl Artistic License
|
||||||
|
# Version 2.0.
|
||||||
|
|
||||||
|
compile (
|
||||||
|
);
|
||||||
|
|
||||||
|
execute (
|
||||||
|
check_finished=>1,
|
||||||
|
);
|
||||||
|
|
||||||
|
ok(1);
|
||||||
|
1;
|
||||||
@@ -0,0 +1,41 @@
|
|||||||
|
// DESCRIPTION: Verilator: Verilog Test module
|
||||||
|
//
|
||||||
|
// This file ONLY is placed into the Public Domain, for any use,
|
||||||
|
// without warranty, 2013 by Alex Solomatnikov.
|
||||||
|
|
||||||
|
//bug595
|
||||||
|
|
||||||
|
module t (/*AUTOARG*/
|
||||||
|
// Inputs
|
||||||
|
clk
|
||||||
|
);
|
||||||
|
input clk;
|
||||||
|
|
||||||
|
logic [6-1:0] foo; initial foo = 20;
|
||||||
|
|
||||||
|
dut #(.W(6)) udut(.clk(clk),
|
||||||
|
.foo(foo-16));
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
module dut
|
||||||
|
#(parameter W = 1)
|
||||||
|
(input logic clk,
|
||||||
|
input logic [W-1:0] foo);
|
||||||
|
|
||||||
|
genvar i;
|
||||||
|
generate
|
||||||
|
for (i = 0; i < W; i++) begin
|
||||||
|
suba ua(.clk(clk), .foo(foo[i]));
|
||||||
|
end
|
||||||
|
endgenerate
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
module suba
|
||||||
|
(input logic clk,
|
||||||
|
input logic foo);
|
||||||
|
|
||||||
|
always @(posedge clk) begin
|
||||||
|
$write("*-* All Finished *-*\n");
|
||||||
|
$finish;
|
||||||
|
end
|
||||||
|
endmodule
|
||||||
Executable
+18
@@ -0,0 +1,18 @@
|
|||||||
|
#!/usr/bin/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.
|
||||||
|
|
||||||
|
compile (
|
||||||
|
v_flags2 => ["--lint-only --Wall -Wno-DECLFILENAME"],
|
||||||
|
verilator_make_gcc => 0,
|
||||||
|
make_top_shell => 0,
|
||||||
|
make_main => 0,
|
||||||
|
);
|
||||||
|
|
||||||
|
ok(1);
|
||||||
|
1;
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
// DESCRIPTION: Verilator: Verilog Test module
|
||||||
|
//
|
||||||
|
// This file ONLY is placed into the Public Domain, for any use,
|
||||||
|
// without warranty, 2012 by Wilson Snyder.
|
||||||
|
|
||||||
|
module t (/*AUTOARG*/);
|
||||||
|
wire ok = 1'b0;
|
||||||
|
// verilator lint_off PINNOCONNECT
|
||||||
|
sub sub (.ok(ok), .nc());
|
||||||
|
// verilator lint_on PINNOCONNECT
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
module sub (input ok, input nc);
|
||||||
|
initial if (ok&&nc) begin end // No unused warning
|
||||||
|
endmodule
|
||||||
Executable
+18
@@ -0,0 +1,18 @@
|
|||||||
|
#!/usr/bin/perl
|
||||||
|
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
|
||||||
|
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||||
|
#
|
||||||
|
# Copyright 2003 by Wilson Snyder. This program is free software; you can
|
||||||
|
# redistribute it and/or modify it under the terms of either the GNU
|
||||||
|
# Lesser General Public License Version 3 or the Perl Artistic License
|
||||||
|
# Version 2.0.
|
||||||
|
|
||||||
|
compile (
|
||||||
|
);
|
||||||
|
|
||||||
|
execute (
|
||||||
|
check_finished=>1,
|
||||||
|
);
|
||||||
|
|
||||||
|
ok(1);
|
||||||
|
1;
|
||||||
@@ -0,0 +1,48 @@
|
|||||||
|
// DESCRIPTION: Verilator: Verilog Test module
|
||||||
|
//
|
||||||
|
// This file ONLY is placed into the Public Domain, for any use,
|
||||||
|
// without warranty, 2013 by Alex Solomatnikov.
|
||||||
|
|
||||||
|
module t (/*AUTOARG*/
|
||||||
|
// Inputs
|
||||||
|
clk
|
||||||
|
);
|
||||||
|
input clk;
|
||||||
|
|
||||||
|
logic [6-1:0] foo[4-1:0];
|
||||||
|
|
||||||
|
//initial $display("%m: %p\n", foo);
|
||||||
|
//initial $display("%m: %p\n", foo[3:0]); // VCS not supported %p with slice
|
||||||
|
//logic [6-1:0] foo2[4-1:0][5:6];
|
||||||
|
//initial $display("%m: %p\n", foo2[3:0][5:6]); // This is not legal
|
||||||
|
|
||||||
|
dut #(.W(6),
|
||||||
|
.D(4)) udut(.clk(clk),
|
||||||
|
.foo(foo[4-1:0]));
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
module dut
|
||||||
|
#(parameter W = 1,
|
||||||
|
parameter D = 1)
|
||||||
|
(input logic clk,
|
||||||
|
input logic [W-1:0] foo[D-1:0]);
|
||||||
|
|
||||||
|
genvar i, j;
|
||||||
|
generate
|
||||||
|
for (j = 0; j < D; j++) begin
|
||||||
|
for (i = 0; i < W; i++) begin
|
||||||
|
suba ua(.clk(clk), .foo(foo[j][i]));
|
||||||
|
end
|
||||||
|
end
|
||||||
|
endgenerate
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
module suba
|
||||||
|
(input logic clk,
|
||||||
|
input logic foo);
|
||||||
|
|
||||||
|
always @(posedge clk) begin
|
||||||
|
$write("*-* All Finished *-*\n");
|
||||||
|
$finish;
|
||||||
|
end
|
||||||
|
endmodule
|
||||||
@@ -10,11 +10,11 @@ if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); di
|
|||||||
$Self->{vlt} and $Self->unsupported("Verilator unsupported, bug102");
|
$Self->{vlt} and $Self->unsupported("Verilator unsupported, bug102");
|
||||||
|
|
||||||
compile (
|
compile (
|
||||||
);
|
);
|
||||||
|
|
||||||
execute (
|
execute (
|
||||||
check_finished=>1,
|
check_finished=>1,
|
||||||
);
|
);
|
||||||
|
|
||||||
ok(1);
|
ok(1);
|
||||||
1;
|
1;
|
||||||
|
|||||||
Executable
+21
@@ -0,0 +1,21 @@
|
|||||||
|
#!/usr/bin/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.
|
||||||
|
|
||||||
|
$Self->{vlt} and $Self->unsupported("Verilator unsupported, bug102");
|
||||||
|
|
||||||
|
compile (
|
||||||
|
v_flags => []
|
||||||
|
);
|
||||||
|
|
||||||
|
execute (
|
||||||
|
check_finished=>1,
|
||||||
|
);
|
||||||
|
|
||||||
|
ok(1);
|
||||||
|
1;
|
||||||
@@ -0,0 +1,68 @@
|
|||||||
|
// DESCRIPTION: Verilator: Verilog Test module
|
||||||
|
//
|
||||||
|
// This file ONLY is placed into the Public Domain, for any use,
|
||||||
|
// without warranty, 2010 by Wilson Snyder.
|
||||||
|
|
||||||
|
interface counter_io;
|
||||||
|
logic [3:0] value;
|
||||||
|
logic reset;
|
||||||
|
endinterface
|
||||||
|
|
||||||
|
module t (/*AUTOARG*/
|
||||||
|
// Inputs
|
||||||
|
clk
|
||||||
|
);
|
||||||
|
|
||||||
|
input clk;
|
||||||
|
integer cyc=1;
|
||||||
|
|
||||||
|
counter_io c1_data();
|
||||||
|
counter_io c2_data();
|
||||||
|
|
||||||
|
counter c1 (.clkm(clk),
|
||||||
|
.c_data(c1_data),
|
||||||
|
.i_value(4'h1));
|
||||||
|
counter c2 (.clkm(clk),
|
||||||
|
.c_data(c2_data),
|
||||||
|
.i_value(4'h2));
|
||||||
|
|
||||||
|
initial begin
|
||||||
|
c1_data.value = 4'h4;
|
||||||
|
c2_data.value = 4'h5;
|
||||||
|
end
|
||||||
|
|
||||||
|
always @ (posedge clk) begin
|
||||||
|
cyc <= cyc + 1;
|
||||||
|
if (cyc<2) begin
|
||||||
|
c1_data.reset <= 1;
|
||||||
|
c2_data.reset <= 1;
|
||||||
|
end
|
||||||
|
if (cyc==2) begin
|
||||||
|
c1_data.reset <= 0;
|
||||||
|
c2_data.reset <= 0;
|
||||||
|
end
|
||||||
|
if (cyc==20) begin
|
||||||
|
$write("[%0t] c1 cyc%0d: %0x %0x\n", $time, cyc, c1_data.value, c1_data.reset);
|
||||||
|
$write("[%0t] c2 cyc%0d: %0x %0x\n", $time, cyc, c2_data.value, c2_data.reset);
|
||||||
|
if (c1_data.value != 2) $stop;
|
||||||
|
if (c2_data.value != 3) $stop;
|
||||||
|
$write("*-* All Finished *-*\n");
|
||||||
|
$finish;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
module counter
|
||||||
|
(
|
||||||
|
input clkm,
|
||||||
|
counter_io c_data,
|
||||||
|
input logic [3:0] i_value
|
||||||
|
);
|
||||||
|
|
||||||
|
always @ (posedge clkm) begin
|
||||||
|
if (c_data.reset)
|
||||||
|
c_data.value <= i_value;
|
||||||
|
else
|
||||||
|
c_data.value <= c_data.value + 1;
|
||||||
|
end
|
||||||
|
endmodule : counter
|
||||||
Executable
+24
@@ -0,0 +1,24 @@
|
|||||||
|
#!/usr/bin/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.
|
||||||
|
|
||||||
|
$Self->{vlt} and $Self->unsupported("Verilator unsupported, bug102");
|
||||||
|
|
||||||
|
top_filename("t/t_interface.v");
|
||||||
|
|
||||||
|
compile (
|
||||||
|
# Avoid inlining so we find bugs in the non-inliner connection code
|
||||||
|
v_flags => ["-Oi"],
|
||||||
|
);
|
||||||
|
|
||||||
|
execute (
|
||||||
|
check_finished=>1,
|
||||||
|
);
|
||||||
|
|
||||||
|
ok(1);
|
||||||
|
1;
|
||||||
Executable
+21
@@ -0,0 +1,21 @@
|
|||||||
|
#!/usr/bin/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.
|
||||||
|
|
||||||
|
$Self->{vlt} and $Self->unsupported("Verilator unsupported, bug102");
|
||||||
|
|
||||||
|
compile (
|
||||||
|
v_flags => [],
|
||||||
|
);
|
||||||
|
|
||||||
|
execute (
|
||||||
|
check_finished=>1,
|
||||||
|
);
|
||||||
|
|
||||||
|
ok(1);
|
||||||
|
1;
|
||||||
@@ -0,0 +1,70 @@
|
|||||||
|
// DESCRIPTION: Verilator: Verilog Test module
|
||||||
|
//
|
||||||
|
// This file ONLY is placed into the Public Domain, for any use,
|
||||||
|
// without warranty, 2010 by Wilson Snyder.
|
||||||
|
|
||||||
|
interface counter_io;
|
||||||
|
logic [3:0] value;
|
||||||
|
logic reset;
|
||||||
|
modport counter_side (input reset, output value);
|
||||||
|
modport core_side (output reset, input value);
|
||||||
|
endinterface
|
||||||
|
|
||||||
|
module t (/*AUTOARG*/
|
||||||
|
// Inputs
|
||||||
|
clk
|
||||||
|
);
|
||||||
|
|
||||||
|
input clk;
|
||||||
|
integer cyc=1;
|
||||||
|
|
||||||
|
counter_io c1_data();
|
||||||
|
counter_io c2_data();
|
||||||
|
|
||||||
|
counter c1 (.clkm(clk),
|
||||||
|
.c_data(c1_data),
|
||||||
|
.i_value(4'h1));
|
||||||
|
counter c2 (.clkm(clk),
|
||||||
|
.c_data(c2_data.counter_side),
|
||||||
|
.i_value(4'h2));
|
||||||
|
|
||||||
|
initial begin
|
||||||
|
c1_data.value = 4'h4;
|
||||||
|
c2_data.value = 4'h5;
|
||||||
|
end
|
||||||
|
|
||||||
|
always @ (posedge clk) begin
|
||||||
|
cyc <= cyc + 1;
|
||||||
|
if (cyc<2) begin
|
||||||
|
c1_data.reset <= 1;
|
||||||
|
c2_data.reset <= 1;
|
||||||
|
end
|
||||||
|
if (cyc==2) begin
|
||||||
|
c1_data.reset <= 0;
|
||||||
|
c2_data.reset <= 0;
|
||||||
|
end
|
||||||
|
if (cyc==20) begin
|
||||||
|
$write("[%0t] c1 cyc%0d: %0x %0x\n", $time, cyc, c1_data.value, c1_data.reset);
|
||||||
|
$write("[%0t] c2 cyc%0d: %0x %0x\n", $time, cyc, c2_data.value, c2_data.reset);
|
||||||
|
if (c1_data.value != 2) $stop;
|
||||||
|
if (c2_data.value != 3) $stop;
|
||||||
|
$write("*-* All Finished *-*\n");
|
||||||
|
$finish;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
module counter
|
||||||
|
(
|
||||||
|
input clkm,
|
||||||
|
counter_io c_data,
|
||||||
|
input logic [3:0] i_value
|
||||||
|
);
|
||||||
|
|
||||||
|
always @ (posedge clkm) begin
|
||||||
|
if (c_data.reset)
|
||||||
|
c_data.value <= i_value;
|
||||||
|
else
|
||||||
|
c_data.value <= c_data.value + 1;
|
||||||
|
end
|
||||||
|
endmodule : counter
|
||||||
Executable
+24
@@ -0,0 +1,24 @@
|
|||||||
|
#!/usr/bin/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.
|
||||||
|
|
||||||
|
$Self->{vlt} and $Self->unsupported("Verilator unsupported, bug102");
|
||||||
|
|
||||||
|
top_filename("t/t_interface_modport.v");
|
||||||
|
|
||||||
|
compile (
|
||||||
|
# Avoid inlining so we find bugs in the non-inliner connection code
|
||||||
|
v_flags => ["-Oi"],
|
||||||
|
);
|
||||||
|
|
||||||
|
execute (
|
||||||
|
check_finished=>1,
|
||||||
|
);
|
||||||
|
|
||||||
|
ok(1);
|
||||||
|
1;
|
||||||
Executable
+17
@@ -0,0 +1,17 @@
|
|||||||
|
#!/usr/bin/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.
|
||||||
|
|
||||||
|
$Self->{vlt} and $Self->unsupported("Verilator unsupported, bug102");
|
||||||
|
|
||||||
|
compile (
|
||||||
|
v_flags => ["--lint-only"]
|
||||||
|
);
|
||||||
|
|
||||||
|
ok(1);
|
||||||
|
1;
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
// DESCRIPTION: Verilator: Verilog Test module
|
||||||
|
//
|
||||||
|
// This file ONLY is placed into the Public Domain, for any use,
|
||||||
|
// without warranty, 2010 by Wilson Snyder.
|
||||||
|
|
||||||
|
interface counter_io;
|
||||||
|
logic [3:0] value;
|
||||||
|
logic reset;
|
||||||
|
modport counter_side (input reset, output value);
|
||||||
|
modport core_side (output reset, input value);
|
||||||
|
endinterface
|
||||||
|
|
||||||
|
module t (/*AUTOARG*/
|
||||||
|
// Inputs
|
||||||
|
clk,
|
||||||
|
counter_io.counter_side c_data
|
||||||
|
);
|
||||||
|
|
||||||
|
input clk;
|
||||||
|
integer cyc=1;
|
||||||
|
|
||||||
|
endmodule
|
||||||
@@ -65,7 +65,7 @@ module reg_1r1w
|
|||||||
|
|
||||||
output [WIDTH-1:0] data_out;
|
output [WIDTH-1:0] data_out;
|
||||||
|
|
||||||
reg [WIDTH-1:0] array [0:DEPTH-1];
|
reg [WIDTH-1:0] array [DEPTH-1:0];
|
||||||
reg [ADRWID-1:0] ra_r, wa_r;
|
reg [ADRWID-1:0] ra_r, wa_r;
|
||||||
reg [WIDTH-1:0] data_in_r;
|
reg [WIDTH-1:0] data_in_r;
|
||||||
reg wr_r;
|
reg wr_r;
|
||||||
|
|||||||
@@ -88,7 +88,9 @@ module fifo (/*AUTOARG*/
|
|||||||
reg [65:0] outData;
|
reg [65:0] outData;
|
||||||
|
|
||||||
// verilator lint_off VARHIDDEN
|
// verilator lint_off VARHIDDEN
|
||||||
|
// verilator lint_off LITENDIAN
|
||||||
reg [65:0] fifo[0:fifoDepth-1];
|
reg [65:0] fifo[0:fifoDepth-1];
|
||||||
|
// verilator lint_on LITENDIAN
|
||||||
// verilator lint_on VARHIDDEN
|
// verilator lint_on VARHIDDEN
|
||||||
|
|
||||||
//reg [65:0] temp;
|
//reg [65:0] temp;
|
||||||
|
|||||||
@@ -11,11 +11,13 @@ module t (/*AUTOARG*/
|
|||||||
input clk;
|
input clk;
|
||||||
integer _mode; initial _mode = 0;
|
integer _mode; initial _mode = 0;
|
||||||
|
|
||||||
|
// verilator lint_off LITENDIAN
|
||||||
reg [7:0] mem_narrow [0:31]; //surefire lint_off_line RD_WRT WRTWRT NBAJAM
|
reg [7:0] mem_narrow [0:31]; //surefire lint_off_line RD_WRT WRTWRT NBAJAM
|
||||||
reg [77:0] mem_wide [1024:0]; //surefire lint_off_line RD_WRT WRTWRT NBAJAM
|
reg [77:0] mem_wide [1024:0]; //surefire lint_off_line RD_WRT WRTWRT NBAJAM
|
||||||
reg [7:0] mem_dly_narrow [0:1]; //surefire lint_off_line RD_WRT WRTWRT NBAJAM
|
reg [7:0] mem_dly_narrow [0:1]; //surefire lint_off_line RD_WRT WRTWRT NBAJAM
|
||||||
reg [77:0] mem_dly_wide [1:0]; //surefire lint_off_line RD_WRT WRTWRT NBAJAM
|
reg [77:0] mem_dly_wide [1:0]; //surefire lint_off_line RD_WRT WRTWRT NBAJAM
|
||||||
reg [34:0] vec_wide;
|
reg [34:0] vec_wide;
|
||||||
|
// verilator lint_on LITENDIAN
|
||||||
|
|
||||||
reg [31:0] wrd0 [15:0];
|
reg [31:0] wrd0 [15:0];
|
||||||
wire [3:0] sel = 4'h3;
|
wire [3:0] sel = 4'h3;
|
||||||
|
|||||||
@@ -11,15 +11,11 @@ compile (
|
|||||||
fails=>$Self->{v3},
|
fails=>$Self->{v3},
|
||||||
nc=>0, # Need to get it not to give the prompt
|
nc=>0, # Need to get it not to give the prompt
|
||||||
expect=>
|
expect=>
|
||||||
q{%Error: t/t_mem_multi_ref_bad.v:\d+: Illegal bit or array select; variable already selected, or bad dimension: dimn
|
q{%Error: t/t_mem_multi_ref_bad.v:\d+: Illegal bit or array select; type does not have a bit range, or bad dimension: type is (bit|logic)
|
||||||
.*%Error: t/t_mem_multi_ref_bad.v:\d+: Illegal range select; variable already selected, or bad dimension
|
.*%Error: t/t_mem_multi_ref_bad.v:\d+: Illegal bit or array select; type does not have a bit range, or bad dimension: type is (bit|logic)
|
||||||
.*%Error: t/t_mem_multi_ref_bad.v:\d+: Illegal bit or array select; variable already selected, or bad dimension: dim0
|
.*%Error: t/t_mem_multi_ref_bad.v:\d+: Illegal bit or array select; type does not have a bit range, or bad dimension: type is (bit|logic)
|
||||||
.*%Error: t/t_mem_multi_ref_bad.v:\d+: Illegal bit or array select; variable already selected, or bad dimension
|
.*%Error: t/t_mem_multi_ref_bad.v:\d+: Illegal \+: or -: select; type already selected, or bad dimension: type is UNPACKARRAYDTYPE
|
||||||
.*%Error: t/t_mem_multi_ref_bad.v:\d+: Illegal bit or array select; variable already selected, or bad dimension: dim1
|
.*%Error: t/t_mem_multi_ref_bad.v:\d+: Illegal bit or array select; type does not have a bit range, or bad dimension: type is logic
|
||||||
.*%Error: t/t_mem_multi_ref_bad.v:\d+: Illegal bit or array select; variable already selected, or bad dimension
|
|
||||||
.*%Error: t/t_mem_multi_ref_bad.v:\d+: Illegal \+: or -: select; variable already selected, or bad dimension
|
|
||||||
.*%Error: t/t_mem_multi_ref_bad.v:\d+: Illegal bit or array select; variable already selected, or bad dimension: dim0nv
|
|
||||||
.*%Error: t/t_mem_multi_ref_bad.v:\d+: Illegal bit or array select; variable already selected, or bad dimension
|
|
||||||
.*%Error: Exiting due to.*},
|
.*%Error: Exiting due to.*},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ module t (/*AUTOARG*/
|
|||||||
|
|
||||||
input clk;
|
input clk;
|
||||||
|
|
||||||
|
// verilator lint_off LITENDIAN
|
||||||
// verilator lint_off BLKANDNBLK
|
// verilator lint_off BLKANDNBLK
|
||||||
// 3 3 4
|
// 3 3 4
|
||||||
reg [71:0] memw [2:0][1:3][5:2];
|
reg [71:0] memw [2:0][1:3][5:2];
|
||||||
@@ -27,6 +28,7 @@ module t (/*AUTOARG*/
|
|||||||
|
|
||||||
integer imem[2:0][1:3];
|
integer imem[2:0][1:3];
|
||||||
reg [2:0] cstyle[2];
|
reg [2:0] cstyle[2];
|
||||||
|
// verilator lint_on LITENDIAN
|
||||||
|
|
||||||
initial begin
|
initial begin
|
||||||
for (i0=0; i0<3; i0=i0+1) begin
|
for (i0=0; i0<3; i0=i0+1) begin
|
||||||
|
|||||||
@@ -10,7 +10,9 @@ module t (/*AUTOARG*/
|
|||||||
|
|
||||||
input clk;
|
input clk;
|
||||||
|
|
||||||
|
// verilator lint_off LITENDIAN
|
||||||
wire [7:0] array [2:0][1:3];
|
wire [7:0] array [2:0][1:3];
|
||||||
|
// verilator lint_on LITENDIAN
|
||||||
|
|
||||||
integer cyc; initial cyc=0;
|
integer cyc; initial cyc=0;
|
||||||
integer i0,i1,i2;
|
integer i0,i1,i2;
|
||||||
|
|||||||
@@ -92,8 +92,8 @@ module t (/*AUTOARG*/
|
|||||||
end
|
end
|
||||||
|
|
||||||
// Test for mixed implicit/explicit dimensions and all implicit packed
|
// Test for mixed implicit/explicit dimensions and all implicit packed
|
||||||
logic [3:0][7:0][1:0] vld [1:0][1:0];
|
bit [3:0][7:0][1:0] vld [1:0][1:0];
|
||||||
logic [3:0][7:0][1:0] vld2;
|
bit [3:0][7:0][1:0] vld2;
|
||||||
|
|
||||||
// There are specific nodes for Or, Xor, Xnor and And
|
// There are specific nodes for Or, Xor, Xnor and And
|
||||||
logic vld_or;
|
logic vld_or;
|
||||||
@@ -118,12 +118,12 @@ module t (/*AUTOARG*/
|
|||||||
|
|
||||||
// Bit reductions should be cloned, other unary operations should clone the
|
// Bit reductions should be cloned, other unary operations should clone the
|
||||||
// entire assign.
|
// entire assign.
|
||||||
logic [3:0][7:0][1:0] not_lhs;
|
bit [3:0][7:0][1:0] not_lhs;
|
||||||
logic [3:0][7:0][1:0] not_rhs;
|
bit [3:0][7:0][1:0] not_rhs;
|
||||||
assign not_lhs = ~not_rhs;
|
assign not_lhs = ~not_rhs;
|
||||||
|
|
||||||
// Test an AstNodeUniop that shouldn't be expanded
|
// Test an AstNodeUniop that shouldn't be expanded
|
||||||
logic [3:0][7:0][1:0] vld2_inv;
|
bit [3:0][7:0][1:0] vld2_inv;
|
||||||
assign vld2_inv = ~vld2;
|
assign vld2_inv = ~vld2;
|
||||||
|
|
||||||
initial begin
|
initial begin
|
||||||
|
|||||||
Executable
+18
@@ -0,0 +1,18 @@
|
|||||||
|
#!/usr/bin/perl
|
||||||
|
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
|
||||||
|
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||||
|
#
|
||||||
|
# Copyright 2010 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.
|
||||||
|
|
||||||
|
compile (
|
||||||
|
);
|
||||||
|
|
||||||
|
execute (
|
||||||
|
check_finished=>1,
|
||||||
|
);
|
||||||
|
|
||||||
|
ok(1);
|
||||||
|
1;
|
||||||
@@ -24,7 +24,9 @@ module t (/*AUTOARG*/
|
|||||||
cyc <= cyc + 1;
|
cyc <= cyc + 1;
|
||||||
arr_c <= arr_c + 1;
|
arr_c <= arr_c + 1;
|
||||||
arr2 <= arr2 + 1;
|
arr2 <= arr2 + 1;
|
||||||
|
`ifdef TEST_VERBOSE
|
||||||
$write("cyc%0d c:%0x a0:%0x a1:%0x a2:%0x a3:%0x\n", cyc, arr_c, arr[0], arr[1], arr[2], arr[3]);
|
$write("cyc%0d c:%0x a0:%0x a1:%0x a2:%0x a3:%0x\n", cyc, arr_c, arr[0], arr[1], arr[2], arr[3]);
|
||||||
|
`endif
|
||||||
if (cyc==99) begin
|
if (cyc==99) begin
|
||||||
$write("*-* All Finished *-*\n");
|
$write("*-* All Finished *-*\n");
|
||||||
$finish;
|
$finish;
|
||||||
@@ -13,10 +13,7 @@ compile (
|
|||||||
verilator_flags2 => ["--lint-only"],
|
verilator_flags2 => ["--lint-only"],
|
||||||
fails=>1,
|
fails=>1,
|
||||||
expect=>
|
expect=>
|
||||||
'%Error: t/t_mem_packed_bad.v:\d+: Unsupported: Assignment between packed arrays of different dimensions
|
'%Error: t/t_mem_packed_bad.v:\d+: Unsupported: Assignment between unpacked arrays of different dimensions
|
||||||
%Error: t/t_mem_packed_bad.v:\d+: Unsupported: Assignment between packed arrays of different dimensions
|
|
||||||
%Error: t/t_mem_packed_bad.v:\d+: Unsupported: Assignment between packed arrays of different dimensions
|
|
||||||
%Error: t/t_mem_packed_bad.v:\d+: Unsupported: Assignment between packed arrays of different dimensions
|
|
||||||
%Error: Exiting due to.*',
|
%Error: Exiting due to.*',
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ module t (/*AUTOARG*/
|
|||||||
|
|
||||||
/* verilator lint_off WIDTH */
|
/* verilator lint_off WIDTH */
|
||||||
always @ (posedge clk) begin
|
always @ (posedge clk) begin
|
||||||
// LHS is a 2D packed array, RHS is 1D packed or Const. Unsupported.
|
// LHS is a 2D packed array, RHS is 1D packed or Const. Allowed now.
|
||||||
ch01 <= {{2{28'd4}}};
|
ch01 <= {{2{28'd4}}};
|
||||||
ch02 <= {{2{cyc}}};
|
ch02 <= {{2{cyc}}};
|
||||||
ch03 <= 56'd0;
|
ch03 <= 56'd0;
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user