Compare commits

...
58 Commits
Author SHA1 Message Date
Wilson Snyder bcadb0b3b3 Version bump 2013-02-04 22:12:21 -05:00
Wilson Snyder 0df561f873 Fix whole slices of arrays, bug609. 2013-02-04 22:11:10 -05:00
Wilson Snyder 238fc24684 Remove slow sync() call for NFS flushing. 2013-02-04 21:21:55 -05:00
Wilson Snyder 936855c81c Fix elimination, bug610 _2 test. 2013-02-03 14:13:16 -05:00
Jeremy Bennett 61ad9d4651 Commentary, bug610.
Signed-off-by: Wilson Snyder <[email protected]>
2013-02-03 13:29:37 -05:00
Wilson Snyder f07f6a26a8 cppcheck fixes 2013-02-03 13:27:37 -05:00
Wilson Snyder 4a5a56f8ef Tests: Fix t_vpi_var uninitialized 2013-02-03 12:21:48 -05:00
Wilson Snyder 7d44bba95c Better packed-array misconnect error message 2013-02-02 19:22:02 -05:00
Wilson Snyder 6e6f1045b8 Fix per-bit array output connection error, bug414. 2013-02-02 18:33:10 -05:00
Wilson Snyder 5dd3221759 Fix complete selection of array ports 2013-02-02 16:52:08 -05:00
Wilson Snyder 09edb467f6 Fix CDC report causing out-of-memory 2013-02-02 15:40:59 -05:00
Wilson Snyder ffb187ae15 Fix enums in sensitivity lists 2013-02-02 14:37:18 -05:00
Wilson Snyder b4a8be07f3 Fix enum items under packages. 2013-02-02 14:11:50 -05:00
Wilson Snyder 4968a2abc5 Support inside expressions. 2013-02-02 12:55:48 -05:00
Wilson Snyder 91159da30d Fix enums with X values. Test in next commit. 2013-02-02 12:43:28 -05:00
Wilson Snyder c9ad61b4fb Support wires with data types, bug608. 2013-02-02 09:33:04 -05:00
Wilson Snyder 3f0dcd8c0e Tests: Redo check macro. 2013-02-02 09:28:45 -05:00
Wilson Snyder e1eb41fe77 Fix segfault on multidimensional dotted arrays, bug607. 2013-01-25 21:27:19 -05:00
Wilson Snyder 498ab23355 Commentary 2013-01-20 13:00:02 -05:00
Wilson Snyder 5d6a053f98 Fix internal error on array pin mismatch, bug393. 2013-01-20 12:59:27 -05:00
Wilson Snyder 929aeebf12 Support , and related functions, bug448. 2013-01-20 12:19:22 -05:00
Wilson Snyder 00bd947385 Tests: Additional unsupported iface tests 2013-01-19 14:40:35 -05:00
Wilson Snyder d4ef86afc0 Fix signed/unsigned parameter misconversion, bug606. 2013-01-18 21:35:43 -05:00
Wilson Snyder 1856cad816 Maintain little endian indication for multidimensional arrays 2013-01-17 23:21:07 -05:00
Wilson Snyder 91e2d1d2a0 Tests: Make struct test pass. 2013-01-17 22:45:35 -05:00
Wilson Snyder f29f30dce0 Fix struct +: slices, bug605. 2013-01-17 21:48:35 -05:00
Wilson Snyder e7ba6ef492 Support VPI product info, warning calls, etc, bug588. 2013-01-17 21:40:37 -05:00
Wilson Snyder de4016dcff Internals: Ast classes create declRange(). 2013-01-17 20:41:45 -05:00
Wilson Snyder bbeb382cbb Internals: Rename range lo/hi to match IEEE. 2013-01-17 20:29:20 -05:00
Wilson Snyder 385c166830 Fix package logic var compile error. 2013-01-17 19:04:36 -05:00
Wilson Snyder 410e6ff203 Fix DECLFILENAME warning on . 2013-01-17 18:38:51 -05:00
Jeremy Bennett 8b47c4e307 Fix loosing logic/bit difference and -x-initial-edge fallout, bug604.
Signed-off-by: Wilson Snyder <[email protected]>
2013-01-17 07:16:19 -05:00
Wilson Snyder 6d1b42bedb Fix implicit one bit parameter selection, bug603. 2013-01-16 20:58:48 -05:00
Wilson Snyder f0a4bd28b6 Comment about -x-initial-edge and logic/bit. 2013-01-16 20:47:22 -05:00
Wilson Snyder 2879684f21 Define SYSTEMVERILOG, SV_COV_START and other IEEE mandated predefines. 2013-01-16 19:11:56 -05:00
Wilson Snyder 0437d0abea Fix pin width mismatch error, bug595. 2013-01-15 19:26:35 -05:00
Wilson Snyder 0286f588bf Tests: bind by modname 2013-01-15 19:23:46 -05:00
Wilson Snyder 042fb76837 Tests 2013-01-14 23:39:56 -05:00
Wilson Snyder 795e66eac9 Support bind, to module names only, bug602. 2013-01-14 23:19:44 -05:00
Wilson Snyder aae0615ffd Commentary 2013-01-14 21:51:02 -05:00
Wilson Snyder 8127a79cb1 Fix nested packed arrays and structs, bug600.
IMPORTANT: 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.
2013-01-14 21:49:22 -05:00
Wilson Snyder 057ca497dd tests: Fix Xs on vector data 2013-01-14 21:38:16 -05:00
Wilson Snyder 66b1611649 In debug, show node dump after errors. 2013-01-14 21:37:55 -05:00
Wilson Snyder 7f5220a6ca Internals: Fix marking of packed vs unpacked wires. 2013-01-13 22:18:57 -05:00
Wilson Snyder e41e26717b Commentary 2013-01-13 19:51:15 -05:00
Wilson Snyder 7a8184d206 Internals: Remove dimension and use only dtypes for V3Width. 2013-01-13 15:21:38 -05:00
Wilson Snyder 13bf2f19ac Internals: Have V3Unknown/Const use only dtypes for selects. 2013-01-13 14:54:12 -05:00
Wilson Snyder 1d5ebfd0b1 Internals: Have V3WidthSel use only dtypes for select promotion. 2013-01-13 14:49:53 -05:00
Wilson Snyder dfc11da2ce Internals: Dump array bounds in tree file. 2013-01-13 14:30:56 -05:00
Wilson Snyder 191af2e87b Internals: Make SelPlus consistent with other branches. No functional change intended. 2013-01-13 11:30:05 -05:00
Wilson Snyder 0985b82760 Commentary 2013-01-13 09:48:12 -05:00
Wilson Snyder 26f4b5a69a Stats: Count only unpacked 2013-01-12 16:26:26 -05:00
Wilson Snyder 5c7a6e278f Internals: Split into packed and unpacked array types 2013-01-12 16:19:25 -05:00
Wilson Snyder ae1ab8aaaa Fix array slice selection of msb==lsb. 2013-01-12 15:34:09 -05:00
Wilson Snyder 18c25d1b6f Commentary 2013-01-12 14:51:16 -05:00
Wilson Snyder 5888a2c399 Internals: Move V3WidthSel::range into V3Width. No functional change intended. 2013-01-12 14:23:56 -05:00
Wilson Snyder c00603704e Commentary 2013-01-11 07:05:25 -05:00
Wilson Snyder 786bc4b04f devel release 2013-01-09 22:27:36 -05:00
133 changed files with 4213 additions and 797 deletions
+35 -1
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -1 +1,2 @@
verilated.mk verilated.mk
verilated_config.h
+9 -3
View File
@@ -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);
+17
View File
@@ -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.
+28
View File
@@ -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@"
-3
View File
@@ -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;
} }
+2
View File
@@ -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) {
+3 -3
View File
@@ -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
+1
View File
@@ -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) {
+331
View File
@@ -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
View File
File diff suppressed because it is too large Load Diff
+1
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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);
+1
View File
@@ -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
View File
@@ -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
View File
@@ -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;
} }
+3 -2
View File
@@ -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
View File
@@ -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;
+10
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
+20
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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;
} }
} }
+1 -1
View File
@@ -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 (
); );
+121 -93
View File
@@ -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
-2
View File
@@ -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 (
); );
+4 -4
View File
@@ -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
+3 -5
View File
@@ -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;
+18
View File
@@ -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;
+92
View File
@@ -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
+2 -3
View File
@@ -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);
+18
View File
@@ -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;
+32
View File
@@ -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
+18
View File
@@ -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;
+44
View File
@@ -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
+18
View File
@@ -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;
+42
View File
@@ -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
+1 -1
View File
@@ -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);
+1 -1
View File
@@ -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;
+18
View File
@@ -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;
+69
View File
@@ -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 -4
View File
@@ -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;
+1 -3
View File
@@ -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.*',
); );
+18
View File
@@ -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;
+41
View File
@@ -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
+18
View File
@@ -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;
+15
View File
@@ -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
+18
View File
@@ -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;
+48
View File
@@ -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
+3 -3
View File
@@ -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;
+21
View File
@@ -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;
+68
View File
@@ -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
+24
View File
@@ -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;
+21
View File
@@ -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;
+70
View File
@@ -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
+24
View File
@@ -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;
+17
View File
@@ -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;
+22
View File
@@ -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
+1 -1
View File
@@ -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;
+2
View File
@@ -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;
+2
View File
@@ -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;
+5 -9
View File
@@ -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.*},
); );
+2
View File
@@ -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
+2
View File
@@ -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;
+5 -5
View File
@@ -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
+18
View File
@@ -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;
+1 -4
View File
@@ -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.*',
); );
+1 -1
View File
@@ -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