Compare commits

...
26 Commits
Author SHA1 Message Date
Wilson Snyder eb072da81c Version bump 2009-03-28 10:30:35 -04:00
Wilson Snyder 38669d0a10 Add SYSTEMPERL_INCLUDE envvar to assist RPM builds. 2009-03-28 10:18:53 -04:00
Wilson Snyder 202a8bc3bb Internals: Use common wrapper for setenv 2009-03-28 09:15:13 -04:00
Wilson Snyder 45e8ed6b49 Internals: Cleanup what symbol lookups need to recurse up vs not. 2009-03-24 09:22:58 -04:00
Wilson Snyder 96692e8a5b Report errors when duplicate labels are used, bug72. 2009-03-23 14:57:15 -04:00
Wilson Snyder ecb08b0cf3 Internals: V3Link uses new common func to make symbol table 2009-03-23 13:52:36 -04:00
Wilson Snyder 71bdfd9710 Fix ASSIGN_SI errors with new --pins-bv 1 option 2009-03-13 22:58:55 -04:00
Wilson Snyder 193dcf38f4 Add --pins-bv option to use sc_bv for all ports. 2009-03-13 14:17:30 -04:00
Wilson Snyder 09091781cf Fix the SC_MODULE name() to not include __PVT__, for nicer coverage. 2009-03-12 14:07:38 -04:00
Wilson Snyder 023519c8f6 Version bump 2009-02-26 07:44:00 -05:00
Wilson Snyder d60d0a60c7 Support repeat and forever statements. 2009-02-25 22:06:59 -05:00
Wilson Snyder 8fe0c3dd84 Commentary in parser to match Verilog-Perl 2009-02-25 17:16:51 -05:00
Wilson Snyder 85419f01a9 Fix left associativity for ?: operators. 2009-02-07 20:54:09 -05:00
Wilson Snyder a199f4a849 Update Bison parser to track Verilog-Perl 3.110. No functional change 2009-01-28 15:27:41 -05:00
Wilson Snyder 290795a76b Commentary 2009-01-28 14:28:55 -05:00
Wilson Snyder c2cf2bc0ba Commentary 2009-01-26 18:36:59 -05:00
Wilson Snyder 2224918730 Fix error messages to consistently go to stderr. 2009-01-26 07:57:59 -05:00
Wilson Snyder c4e69daecd Add IEEE grammar comments; sync with Verilator-Perl parser 2009-01-24 21:36:14 -05:00
Wilson Snyder 9162e68d82 Commentary 2009-01-24 21:35:08 -05:00
Wilson Snyder 08f736ae33 bisonpre: Reconsile Verilog-Perl and Verilator bisonpre 2009-01-24 16:44:03 -05:00
Wilson Snyder 81092edab4 Commentary 2009-01-21 16:59:42 -05:00
Wilson Snyder 21b5a4e9e4 Add --debugi-<srcfile> option. 2009-01-21 16:56:50 -05:00
Wilson Snyder 057928b079 Fix VL_RANDom to better randomize bits. 2009-01-21 13:52:51 -05:00
Wilson Snyder 4beaa45199 Clock_enable is past experimental; bug50. 2009-01-20 07:24:57 -05:00
Wilson Snyder 8f88fa45f1 Make grammer names more closely track IEEE. No functional change. 2009-01-15 13:58:43 -05:00
Wilson Snyder 13e8176884 Fix compile issues with GCC 4.3, bug47. 2009-01-09 11:28:50 -05:00
98 changed files with 1770 additions and 610 deletions
+28 -4
View File
@@ -3,12 +3,36 @@ Revision history for Verilator
The contributors that suggested a given feature are shown in []. [by ...]
indicates the contributor was also the author of the fix; Thanks!
* Verilator 3.702 2009/03/28
*** Add --pins-bv option to use sc_bv for all ports. [Brian Small]
*** Add SYSTEMPERL_INCLUDE envvar to assist RPM builds. [Chitlesh Goorah]
**** Report errors when duplicate labels are used, bug72. [Vasu Kandadi]
**** Fix the SC_MODULE name() to not include __PVT__. [Bob Fredieu]
* Verilator 3.701 2009/02/26
** Support repeat and forever statements. [Jeremy Bennett]
*** Add --debugi-<srcfile> option, for internal debugging. [Dennis Muhlestein]
**** Fix compile issues with GCC 4.3, bug47. [Lane Brooks]
**** Fix VL_RANDom to better randomize bits. [Art Stamness]
**** Fix error messages to consistently go to stderr. [Jeremy Bennett]
**** Fix left associativity for ?: operators.
* Verilator 3.700 2009/01/08
** Add limited support for tristate inouts. Written by Lane Brooks.
This allows common pad ring and tristate-mux structures to be
Verilated. See the documentation for more information on supported
constructs.
** Add limited support for tristate inouts. Written by Lane Brooks,
under support by Ubixum Inc. This allows common pad ring and
tristate-mux structures to be Verilated. See the documentation for
more information on supported constructs.
** Add --coverage_toggle for toggle coverage analysis.
Running coverage now requires SystemPerl 1.301 or newer.
+52 -14
View File
@@ -188,6 +188,8 @@ descriptions in the next sections for more information.
-D<var>[=<value>] Set preprocessor define
--debug Enable debugging
--debug-check Enable debugging assertions
--debugi <level> Enable debugging at a specified level
--debugi-<srcfile> <level> Enable debugging a source file at a level
--dump-tree Enable dumping .tree files
-E Preprocess, but do not compile
--error-limit <value> Abort after this number of errors
@@ -210,6 +212,7 @@ descriptions in the next sections for more information.
-O<optimization-letter> Selectable optimizations
--output-split <bytes> Split .cpp files into pieces
--output-split-cfuncs <statements> Split .ccp functions
--pins-bv <bits> Specify types for top level ports
--prefix <topname> Name of top level class
--profile-cfuncs Name functions for profiling
--private Debugging; see docs
@@ -375,6 +378,12 @@ internal assertions, debugging messages, and intermediate form dump files.
Rarely needed. Enable internal debugging assertion checks, without
changing debug verbosity. Enabled automatically when --debug specified.
=item --debugi <level>
=item --debugi-<srcfile> <level>
Rarely needed - for developer use. Set internal debugging level globally
or on the specified source file to the specified level.
=item --dump-tree
Rarely needed. Enable writing .tree debug files. This is enabled with
@@ -451,9 +460,7 @@ the same as --prefix.
=item --no-pins64
Specifies SystemC outputs of 33-64 bits wide should use sc_bv's instead of
uint64_t's. Uint64's are faster, but sc_bvs were the default until
Verilator 3.671.
Backward compatible alias for "--pins-bv 33".
=item --no-skip-identical
@@ -499,6 +506,17 @@ worse with decreasing split values. Note that this option is stronger than
--output-split in the sense that --output-split will not split inside a
function.
=item --pins64
Backward compatible alias for "--pins-bv 65". Note that's a 65, not a 64.
=item --pins-bv I<width>
Specifies SystemC outputs of greater than or equal to I<width> bits wide
should use sc_bv's instead of uint32/uint64_t's. The default is "--pins-bv
65". Versions before Verilator 3.671 defaulted to "--pins-bv 33". The
more sc_bv is used, the worse for performance.
=item --prefix I<topname>
Specifies the name of the top level class and makefile. Defaults to V
@@ -633,6 +651,12 @@ will call a function to determine the value, this allows randomization of
all Xs to find reset bugs and is the slowest, but safest for finding reset
bugs in code.
If using -x-assign unique, you may want to seed your random number
generator such that each regression run gets a different randomization
sequence. Use the system's srand48() or for Windows srand() function to do
this. You'll probably also want to print any seeds selected, and code to
enable rerunning with that same seed so you can reproduce bugs.
=back
=head1 VERILOG ARGUMENTS
@@ -929,10 +953,18 @@ building the SystemC model.
=item SYSTEMPERL
Specifies the directory containing the Verilog-Perl distribution kit. This
is used to find the Verilog-Perl library and include files. If not
Specifies the directory containing the SystemPerl distribution kit. This
is used to find the SystemPerl library and include files. If not
specified, it will come from a default optionally specified at configure
time (before Verilator was compiled).
time (before Verilator was compiled). See also SYSTEMPERL_INCLUDE.
=item SYSTEMPERL_INCLUDE
Specifies the directory containing the Verilog-Perl include .cpp files,
from the src/ directory of the SystemPerl kit. If not specified, it will
be computed from the SYSTEMPERL environment variable if it is set, and if
SYSTEMPERL is not set SYSTEMPERL_INCLUDE will come from a default
optionally specified at configure time (before Verilator was compiled).
=item VCS_HOME
@@ -1249,11 +1281,11 @@ The Verilog code returns to the last language mode specified with
=item /*verilator clock_enable*/
Experimental use only. Used after a signal declaration to indicate the
signal is used to gate a clock, and the user takes responsibility for
insuring there are no races related to it. (Typically by adding a latch,
and running static timing analysis.) This will cause the clock gate to be
ignored in the scheduling algorithm, improving performance.
Used after a signal declaration to indicate the signal is used to gate a
clock, and the user takes responsibility for insuring there are no races
related to it. (Typically by adding a latch, and running static timing
analysis.) This will cause the clock gate to be ignored in the scheduling
algorithm, improving performance.
=item /*verilator coverage_block_off*/
@@ -1290,6 +1322,7 @@ this to the signal causing a false loop may clear up the problem.
IE, with the following
reg splitme /* verilator isolate_assignments*/;
// Note the placement of the semicolon above
always @* begin
if (....) begin
splitme = ....;
@@ -2143,7 +2176,7 @@ using --debug), see if your machine is paging; most likely you need to run
it on a machine with more memory. Verilator is a full 64 bit application
and may use more than 4GB, but about 1GB is the maximum typically needed.
=item How do I generate waveforms (traces) in C++ or SystemC?
=item How do I generate waveforms (traces) in C++?
See the next question for tracing in SystemPerl mode.
@@ -2162,7 +2195,7 @@ distribution.
You also need to compile SpTraceVcdC.cpp and add it to your link. This is
done for you if using the Verilator --exe flag.
=item How do I generate waveforms (traces) in SystemPerl?
=item How do I generate waveforms (traces) in SystemC/SystemPerl?
Add the --trace switch to Verilator, and make sure the SystemPerl package
is installed.
@@ -2172,6 +2205,10 @@ create a SpTraceFile object as you would create a normal SystemC trace
file. For an example, see the call to SpTraceFile in the
test_sp/sc_main.cpp file of the distribution.
Alternatively you may use the C++ trace mechanism described in the previous
question, however the timescale and timeprecision will not inherited from
your SystemC settings.
=item How do I view waveforms (traces)?
Verilator makes standard VCD (Value Change Dump) files. They are viewable
@@ -2349,7 +2386,8 @@ strips array bound checks where it believes them to be unnecessary.)
In the SYSTEMC example above, if you had in our.v:
input clk /*verilator public*/;
input clk /*verilator public*/;
// Note the placement of the semicolon above
From the sc_main.cpp file, you'd then:
+2 -2
View File
@@ -73,9 +73,9 @@ void vl_fatal (const char* filename, int linenum, const char* hier, const char*
IData VL_RAND32() {
#if defined(_WIN32) && !defined(__CYGWIN__)
// Windows doesn't have lrand48(), although Cygwin does.
return (rand()<<16) | rand();
return (rand()<<16) ^ rand();
#else
return (lrand48()<<16) | lrand48();
return (lrand48()<<16) ^ lrand48();
#endif
}
+26 -16
View File
@@ -359,35 +359,45 @@ static inline void VL_ASSIGNBIT_WO(int, int bit, WDataOutP owp, IData) {
//===================================================================
// SYSTEMC OPERATORS
// Copying verilog format to/from systemc integers and bit vectors.
#define VL_ASSIGN_IS(obits,vvar,svar) { (vvar) = VL_CLEAN_II((obits),(obits),(svar).read()); }
#define VL_ASSIGN_SI(obits,svar,vvar) { (svar).write(vvar); }
// Copying verilog format to systemc integers and bit vectors.
#define VL_ASSIGN_ISI(obits,vvar,svar) { (vvar) = VL_CLEAN_II((obits),(obits),(svar).read()); }
#define VL_ASSIGN_QSQ(obits,vvar,svar) { (vvar) = VL_CLEAN_QQ((obits),(obits),(svar).read()); }
#define VL_ASSIGN_ISW(obits,od,svar) { \
od = (svar.read().get_word(0)) & VL_MASK_I(obits); \
}
#define VL_ASSIGN_QSW(obits,od,svar) { \
od = (((QData)svar.read().get_word(1))<<VL_WORDSIZE | svar.read().get_word(0)) \
& VL_MASK_Q(obits); \
}
#define VL_ASSIGN_WSW(obits,owp,svar) { \
int words = VL_WORDS_I(obits); \
for (int i=0; i < words; i++) owp[i] = svar.read().get_word(i); \
owp[words-1] &= VL_MASK_I(obits); \
}
// Copying verilog format from systemc integers and bit vectors.
#define VL_ASSIGN_SII(obits,svar,vvar) { (svar).write(vvar); }
#define VL_ASSIGN_SQQ(obits,svar,vvar) { (svar).write(vvar); }
#define VL_ASSIGN_SQ(obits,svar,rd) { \
#define VL_ASSIGN_SWI(obits,svar,rd) { \
sc_bv<obits> _bvtemp; \
_bvtemp.set_word(0,rd); \
svar.write(_bvtemp); \
}
#define VL_ASSIGN_SWQ(obits,svar,rd) { \
sc_bv<obits> _bvtemp; \
_bvtemp.set_word(0,rd); \
_bvtemp.set_word(1,rd>>VL_WORDSIZE); \
svar.write(_bvtemp); \
}
#define VL_ASSIGN_QS(obits,od,svar) { \
od = (((QData)svar.read().get_word(1))<<VL_WORDSIZE | svar.read().get_word(0)) \
& VL_MASK_Q(obits); \
}
#define VL_ASSIGN_SW(obits,svar,rwp) { \
#define VL_ASSIGN_SWW(obits,svar,rwp) { \
sc_bv<obits> _bvtemp; \
for (int i=0; i < VL_WORDS_I(obits); i++) _bvtemp.set_word(i,rwp[i]); \
svar.write(_bvtemp); \
}
#define VL_ASSIGN_WS(obits,owp,svar) { \
int words = VL_WORDS_I(obits); \
for (int i=0; i < words; i++) owp[i] = svar.read().get_word(i); \
owp[words-1] &= VL_MASK_I(obits); \
}
//===================================================================
// Extending sizes
+6 -6
View File
@@ -89,8 +89,8 @@ endif
##### SystemPerl builds
ifeq ($(VM_SP),1)
CPPFLAGS += -I$(SYSTEMPERL)/src -DSYSTEMPERL
VPATH += $(SYSTEMPERL)/src
CPPFLAGS += -I$(SYSTEMPERL_INCLUDE) -DSYSTEMPERL
VPATH += $(SYSTEMPERL_INCLUDE)
LIBS += -lm -lstdc++
VK_CLASSES_SP = $(addsuffix .sp, $(VM_CLASSES))
@@ -110,8 +110,8 @@ endif
ifeq ($(VM_SC),1)
LIBS += -lm -lstdc++
ifeq ($(VM_TRACE),1)
CPPFLAGS += -I$(SYSTEMPERL)/src
VPATH += $(SYSTEMPERL)/src
CPPFLAGS += -I$(SYSTEMPERL_INCLUDE)
VPATH += $(SYSTEMPERL_INCLUDE)
endif
endif
@@ -121,8 +121,8 @@ endif
ifeq ($(VM_PCLI),1)
LIBS += -lm -lstdc++
ifeq ($(VM_TRACE),1)
CPPFLAGS += -I$(SYSTEMPERL)/src
VPATH += $(SYSTEMPERL)/src
CPPFLAGS += -I$(SYSTEMPERL_INCLUDE)
VPATH += $(SYSTEMPERL_INCLUDE)
endif
endif
+73
View File
@@ -0,0 +1,73 @@
#!/usr/bin/perl -w
######################################################################
#
# Copyright 2007-2009 by Wilson Snyder.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of either the GNU General Public License or the
# Perl Artistic License.
#
# This program 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.
#
# You should have received a copy of the Perl Artistic License
# along with this module; see the file COPYING. If not, see
# www.cpan.org
#
######################################################################
# DESCRIPTION: Diff bison files
use IO::File;
use strict;
my $Debug;
diff($ARGV[0],$ARGV[1]);
sub diff {
my $a=shift;
my $b=shift;
my $ta = "/tmp/bisondiff.$$.a";
my $tb = "/tmp/bisondiff.$$.b";
prep($a,$ta);
prep($b,$tb);
system("diff -u -w $ta $tb");
}
sub prep {
my $filename = shift;
my $wfilename = shift;
my $fh = IO::File->new("<$filename") or die "%Error: $! $filename";
my $fho = IO::File->new(">$wfilename") or die "%Error: $! writing $wfilename";
my %declared;
my %used;
my $body = 0;
my $rule = "";
my $skip = 1;
while (defined(my $line = $fh->getline)) {
if ($skip == 1) {
next if $line !~ /%token/;
$skip = 2;
}
# %type<foo>
$line =~ s/^(%\S+)<(\S+)>/$1/;
# rule<foo>
$line =~ s/^([a-zA-Z0-9_]+)<\S+>:/$1:/;
# Productions
$line =~ s/[ \t]{[^}]*?}/\t{}/g;
$fho->print($line);
}
}
# Local Variables:
# compile-command: "./bisondiff $WUP/Verilog/Parser/VParseBison.y ../src/verilog.y"
# End:
+3 -3
View File
@@ -42,8 +42,8 @@ foreach my $line (<STDIN>) {
$rule .= $line;
if ($line =~ m!^\s*;\s*$!) {
#print "Rule: $rule\n";
($rule =~ /^([a-zA-Z0-9_]+):(.*)$/) or die "%Error: No rule name: $1\n";
my $rulename = $1; my $preaction = $2;
($rule =~ /^([a-zA-Z0-9_]+)(<\S+>)?:(.*)$/) or die "%Error: No rule name: $1\n";
my $rulename = $1; my $preaction = $3;
$declared{$rulename} = $lineno;
$preaction =~ s/\{[^\}]*\}/ /g;
#print "RULEN $rulename PA $preaction\n" if $Debug;
@@ -62,5 +62,5 @@ foreach my $line (<STDIN>) {
}
# Local Variables:
# compile-command: "./bisonreader < verilog.y"
# compile-command: "./bisonreader < ../src/verilog.y"
# End:
+5 -4
View File
@@ -116,8 +116,9 @@ If you will be using SystemC, download and install Verilog-Perl,
If you will be using SystemC, download and install System-Perl,
@url{http://search.cpan.org/search?module=SystemC::Netlist}. Note
you'll need to set a @samp{SYSTEMPERL} environment variable to point
to the downloaded kit (not the installed files.) Also, make sure to
do a @code{make sc_patch}.
to the downloaded kit. Optionally also set @samp{SYSTEMPERL_INCLUDE}
to point to the installed headers. Also, make sure to do a @code{make
sc_patch}.
@item
@code{cd} to the Verilator directory containing this README.
@@ -128,8 +129,8 @@ Type @samp{./configure} to configure Verilator for your system.
If you are configuring Verilator to be part of a RPM or other
distribution package system, you may want to use the --enable-defenv
configure flag. This will take the current value of VERILATOR_ROOT,
SYSTEMC, SYSTEMC_ARCH, and SYSTEMPERL and build them as defaults into
the executable.
SYSTEMC, SYSTEMC_ARCH, SYSTEMPERL, and SYSTEMPERL_INCLUDE and build
them as defaults into the executable.
@item
Type @samp{make} to compile Verilator.
+7 -1
View File
@@ -81,12 +81,19 @@ CPPFLAGS += -W -Wall -Wno-unused-parameter -Wno-char-subscripts -Werror
#CPPFLAGS += -pedantic-errors
endif
ifneq ($(SYSTEMPERL),) # Intuit SYSTEMPERL_INCLUDE as it's new
SYSTEMPERL_INCLUDE ?= $(SYSTEMPERL)/src
#else if set, leave as-is.
#else if SYSTEMPERL="" don't set _INCLUDE so source will figure it out
endif
# Allow RPM builds to specify hardcoded data directories
# To do this:
ifeq ($(CFG_WITH_DEFENV),yes)
CPPFLAGS += -DDEFENV_SYSTEMC=\"$(SYSTEMC)\"
CPPFLAGS += -DDEFENV_SYSTEMC_ARCH=\"$(SYSTEMC_ARCH)\"
CPPFLAGS += -DDEFENV_SYSTEMPERL=\"$(SYSTEMPERL)\"
CPPFLAGS += -DDEFENV_SYSTEMPERL_INCLUDE=\"$(SYSTEMPERL_INCLUDE)\"
ifeq ($(VERILATOR_ROOT),) # Use what we're given, or intuit
CPPFLAGS += -DDEFENV_VERILATOR_ROOT=\"$(pkgdatadir)\"
else
@@ -280,4 +287,3 @@ DEPS := $(wildcard *.d)
ifneq ($(DEPS),)
include $(DEPS)
endif
+5 -1
View File
@@ -52,7 +52,11 @@
class ActiveBaseVisitor : public AstNVisitor {
protected:
//int debug() { return 9; }
static int debug() {
static int level = -1;
if (VL_UNLIKELY(level < 0)) level = v3Global.opt.debugSrcLevel(__FILE__);
return level;
}
};
class ActiveNamer : public ActiveBaseVisitor {
+7 -1
View File
@@ -56,7 +56,13 @@ private:
// STATE
AstTopScope* m_topscopep; // Top scope for adding sentrees under
SenTreeFinder m_finder; // Find global sentree's and add them
//int debug() { return 9; }
// METHODS
static int debug() {
static int level = -1;
if (VL_UNLIKELY(level < 0)) level = v3Global.opt.debugSrcLevel(__FILE__);
return level;
}
// VISITORS
virtual void visit(AstTopScope* nodep, AstNUser*) {
+6 -2
View File
@@ -48,9 +48,13 @@ private:
// Reset each assertion:
AstNodeSenItem* m_senip; // Last sensitivity
int debug() { return 0; }
// METHODS
static int debug() {
static int level = -1;
if (VL_UNLIKELY(level < 0)) level = v3Global.opt.debugSrcLevel(__FILE__);
return level;
}
AstSenTree* newSenTree(AstNode* nodep) {
// Create sentree based on clocked or default clock
// Return NULL for always
+7 -7
View File
@@ -51,11 +51,11 @@ bool AstVar::isSigPublic() const {
}
bool AstVar::isScQuad() const {
return (isSc()&&isQuad()&&v3Global.opt.pins64());
return (isSc() && isQuad() && !isScBv());
}
bool AstVar::isScWide() const {
return (isWide() || isSc()&&isQuad()&&!v3Global.opt.pins64());
bool AstVar::isScBv() const {
return (isSc() && width() >= v3Global.opt.pinsBv());
}
void AstVar::combineType(AstVarType type) {
@@ -108,7 +108,7 @@ string AstVar::cType() const {
return "bool";
} else if (widthMin() <= VL_WORDSIZE) {
return "uint32_t";
} else if (isScWide()) {
} else if (isWide()) {
return "uint32_t"; // []'s added later
} else {
return "uint64_t";
@@ -116,12 +116,12 @@ string AstVar::cType() const {
}
string AstVar::scType() const {
if (widthMin() == 1) {
if (isScBv()) {
return (string("sc_bv<")+cvtToStr(widthMin())+"> "); // Keep the space so don't get >>
} else if (widthMin() == 1) {
return "bool";
} else if (widthMin() <= VL_WORDSIZE) {
return "uint32_t";
} else if (isScWide()) {
return (string("sc_bv<")+cvtToStr(widthMin())+"> "); // Keep the space so don't get >>
} else {
return "uint64_t";
}
+16 -1
View File
@@ -341,7 +341,7 @@ public:
bool isUsedParam() const { return m_usedParam; }
bool isSc() const { return m_sc; }
bool isScQuad() const;
bool isScWide() const;
bool isScBv() const;
bool isScSensitive() const { return m_scSensitive; }
bool isSigPublic() const;
bool isSigModPublic() const { return m_sigModPublic; }
@@ -1408,6 +1408,21 @@ struct AstFor : public AstNodeFor {
ASTNODE_NODE_FUNCS(For, FOR)
};
struct AstRepeat : public AstNodeStmt {
AstRepeat(FileLine* fileline, AstNode* countp, AstNode* bodysp)
: AstNodeStmt(fileline) {
setOp2p(countp); addNOp3p(bodysp);
}
ASTNODE_NODE_FUNCS(Repeat, REPEAT)
AstNode* countp() const { return op2p()->castNode(); } // op2= condition to continue
AstNode* bodysp() const { return op3p()->castNode(); } // op3= body of loop
virtual bool isGateOptimizable() const { return false; }
virtual bool isPredictOptimizable() const { return false; }
virtual int instrCount() const { return instrCountBranch(); }
virtual V3Hash sameHash() const { return V3Hash(); }
virtual bool same(AstNode* samep) const { return true; }
};
struct AstWhile : public AstNodeStmt {
AstWhile(FileLine* fileline, AstNode* condp, AstNode* bodysp)
: AstNodeStmt(fileline) {
+42 -1
View File
@@ -47,11 +47,19 @@ private:
AstModule* m_modp; // Current module
AstNodeFTask* m_ftaskp; // Current function/task
string m_beginScope; // Name of begin blocks above us
//int debug() { return 9; }
int m_repeatNum; // Repeat counter
// METHODS
static int debug() {
static int level = -1;
if (VL_UNLIKELY(level < 0)) level = v3Global.opt.debugSrcLevel(__FILE__);
return level;
}
// VISITORS
virtual void visit(AstModule* nodep, AstNUser*) {
m_modp = nodep;
m_repeatNum = 0;
nodep->iterateChildren(*this);
m_modp = NULL;
}
@@ -130,6 +138,38 @@ private:
nodep->replaceWith(newp);
nodep->deleteTree(); nodep=NULL;
}
virtual void visit(AstRepeat* nodep, AstNUser*) {
// So later optimizations don't need to deal with them,
// REPEAT(count,body) -> loop=count,WHILE(loop>0) { body, loop-- }
// Note var can be signed or unsigned based on original number.
AstNode* countp = nodep->countp()->unlinkFrBackWithNext();
string name = string("__Vrepeat")+cvtToStr(m_repeatNum++);
AstVar* varp = new AstVar(nodep->fileline(), AstVarType::BLOCKTEMP, name,
new AstRange(nodep->fileline(), countp->width()-1, 0));
m_modp->addStmtp(varp);
AstNode* initsp = new AstAssign(nodep->fileline(), new AstVarRef(nodep->fileline(), varp, true),
countp);
AstNode* decp = new AstAssign(nodep->fileline(), new AstVarRef(nodep->fileline(), varp, true),
new AstSub(nodep->fileline(), new AstVarRef(nodep->fileline(), varp, false),
new AstConst(nodep->fileline(), 1)));
AstNode* condp;
if (countp->isSigned()) {
condp = new AstGtS(nodep->fileline(), new AstVarRef(nodep->fileline(), varp, false),
new AstConst(nodep->fileline(), 0));
} else {
condp = new AstGt (nodep->fileline(), new AstVarRef(nodep->fileline(), varp, false),
new AstConst(nodep->fileline(), 0));
}
AstNode* bodysp = nodep->bodysp(); if (bodysp) bodysp->unlinkFrBackWithNext();
bodysp = bodysp->addNext(decp);
AstNode* newp = new AstWhile(nodep->fileline(),
condp,
bodysp);
initsp = initsp->addNext(newp);
newp = initsp;
nodep->replaceWith(newp);
nodep->deleteTree(); nodep=NULL;
}
virtual void visit(AstScopeName* nodep, AstNUser*) {
// If there's a %m in the display text, we add a special node that will contain the name()
// Similar code in V3Inline
@@ -155,6 +195,7 @@ public:
BeginVisitor(AstNetlist* nodep) {
m_modp = NULL;
m_ftaskp = NULL;
m_repeatNum = 0;
nodep->accept(*this);
}
virtual ~BeginVisitor() {}
+6 -1
View File
@@ -43,9 +43,14 @@ private:
// STATE
int m_likely; // Excuses for branch likely taken
int m_unlikely; // Excuses for branch likely not taken
//int debug() { return 9; }
// METHODS
static int debug() {
static int level = -1;
if (VL_UNLIKELY(level < 0)) level = v3Global.opt.debugSrcLevel(__FILE__);
return level;
}
void reset() {
m_likely = false;
m_unlikely = false;
+3 -3
View File
@@ -129,9 +129,9 @@ public:
// Use only AstNode::dump instead of the virtual one, as there
// may be varp() and other cross links that are bad.
if (debug()) {
cout<<"%Error: LeakedNode"<<(it->first->backp()?"Back: ":": ");
((AstNode*)(it->first))->AstNode::dump(cout);
cout<<endl;
cerr<<"%Error: LeakedNode"<<(it->first->backp()?"Back: ":": ");
((AstNode*)(it->first))->AstNode::dump(cerr);
cerr<<endl;
V3Error::incErrors();
}
it->second |= FLAG_LEAKED;
+12 -3
View File
@@ -58,7 +58,12 @@
class CaseLintVisitor : public AstNVisitor {
private:
AstNodeCase* m_caseExprp; // Under a CASE value node, if so the relevant case statement
//int debug() { return 9; }
static int debug() {
static int level = -1;
if (VL_UNLIKELY(level < 0)) level = v3Global.opt.debugSrcLevel(__FILE__);
return level;
}
virtual void visit(AstNodeCase* nodep, AstNUser*) {
// Detect multiple defaults
@@ -130,9 +135,13 @@ private:
int m_caseNoOverlapsAllCovered; // Proven to be synopsys parallel_case compliant
AstNode* m_valueItem[1<<CASE_OVERLAP_WIDTH]; // For each possible value, the case branch we need
//int debug() { return 9; }
// METHODS
static int debug() {
static int level = -1;
if (VL_UNLIKELY(level < 0)) level = v3Global.opt.debugSrcLevel(__FILE__);
return level;
}
bool isCaseTreeFast(AstCase* nodep) {
int width = 0;
m_caseItems = 0;
+6 -1
View File
@@ -63,9 +63,14 @@ private:
AstUser1InUse m_inuser1;
// STATE
//int debug() { return 9; }
// METHODS
static int debug() {
static int level = -1;
if (VL_UNLIKELY(level < 0)) level = v3Global.opt.debugSrcLevel(__FILE__);
return level;
}
void insertCast(AstNode* nodep, int needsize) { // We'll insert ABOVE passed node
UINFO(4," NeedCast "<<nodep<<endl);
AstNRelinker relinkHandle;
+6 -1
View File
@@ -57,9 +57,14 @@ private:
AstModule* m_topModp; // Top module
AstScope* m_scopetopp; // Scope under TOPSCOPE
AstCFunc* m_chgFuncp; // Change function we're building
//int debug() { return 9; }
// METHODS
static int debug() {
static int level = -1;
if (VL_UNLIKELY(level < 0)) level = v3Global.opt.debugSrcLevel(__FILE__);
return level;
}
void genChangeDet(AstVarScope* vscp) {
#ifdef NEW_ORDERING
vscp->v3fatalSrc("Not applicable\n");
+10 -5
View File
@@ -50,14 +50,19 @@ private:
AstUser1InUse m_inuser1;
AstUser2InUse m_inuser2;
// STATE
AstModule* m_modp;
//int debug() { return 9; }
// ENUMS
// TYPES
enum CleanState { UNKNOWN, CLEAN, DIRTY };
// STATE
AstModule* m_modp;
// METHODS
static int debug() {
static int level = -1;
if (VL_UNLIKELY(level < 0)) level = v3Global.opt.debugSrcLevel(__FILE__);
return level;
}
// Width resetting
int cppWidth(AstNode* nodep) {
if (nodep->width()<=VL_WORDSIZE) return VL_WORDSIZE;
+5 -1
View File
@@ -52,7 +52,11 @@
class GaterBaseVisitor : public AstNVisitor {
protected:
//int debug() { return 9; }
static int debug() {
static int level = -1;
if (VL_UNLIKELY(level < 0)) level = v3Global.opt.debugSrcLevel(__FILE__);
return level;
}
};
//######################################################################
+6 -1
View File
@@ -71,9 +71,14 @@ private:
AstSenTree* m_lastSenp; // Last sensitivity match, so we can detect duplicates.
AstIf* m_lastIfp; // Last sensitivity if active to add more under
int m_stableNum; // Number of each untilstable
//int debug() { return 9; }
// METHODS
static int debug() {
static int level = -1;
if (VL_UNLIKELY(level < 0)) level = v3Global.opt.debugSrcLevel(__FILE__);
return level;
}
AstVarScope* getCreateLastClk(AstVarScope* vscp) {
if (vscp->user1p()) return ((AstVarScope*)vscp->user1p());
AstVar* varp = vscp->varp();
+7 -1
View File
@@ -58,8 +58,14 @@
class CombBaseVisitor : public AstNVisitor {
protected:
// STATE
//int debug() { return 9; }
// METHODS
static int debug() {
static int level = -1;
if (VL_UNLIKELY(level < 0)) level = v3Global.opt.debugSrcLevel(__FILE__);
return level;
}
virtual ~CombBaseVisitor() {}
//***** optimization levels
+7 -1
View File
@@ -30,6 +30,7 @@
#include <cstdarg>
#include <unistd.h>
#include <map>
#include <algorithm>
#include "V3Global.h"
#include "V3Const.h"
@@ -104,9 +105,14 @@ private:
bool m_expensive; // Enable computationally expensive optimizations
AstModule* m_modp; // Current module
AstNode* m_scopep; // Current scope
//int debug() { return 9; }
// METHODS
static int debug() {
static int level = -1;
if (VL_UNLIKELY(level < 0)) level = v3Global.opt.debugSrcLevel(__FILE__);
return level;
}
bool operandConst (AstNode* nodep) {
return (nodep->castConst());
}
+6 -2
View File
@@ -54,9 +54,13 @@ private:
FileMap m_fileps; // Column counts for each fileline
string m_beginHier; // AstBegin hier name for user coverage points
//int debug() { return 9; }
// METHODS
static int debug() {
static int level = -1;
if (VL_UNLIKELY(level < 0)) level = v3Global.opt.debugSrcLevel(__FILE__);
return level;
}
const char* varIgnoreToggle(AstVar* nodep) {
// Return true if this shouldn't be traced
// See also similar rule in V3TraceDecl::varIgnoreTrace
+6 -2
View File
@@ -53,9 +53,13 @@ private:
V3Double0 m_statToggleJoins; // Statistic tracking
//int debug() { return 9; }
// METHODS
static int debug() {
static int level = -1;
if (VL_UNLIKELY(level < 0)) level = v3Global.opt.debugSrcLevel(__FILE__);
return level;
}
void detectDuplicates() {
UINFO(9,"Finding duplicates\n");
// Note uses user4
+5 -1
View File
@@ -81,9 +81,13 @@ private:
AssignMap m_assignMap; // List of all simple assignments for each variable
bool m_elimUserVars; // Allow removal of user's vars
bool m_sideEffect; // Side effects discovered in assign RHS
//int debug() { return 9; }
// METHODS
static int debug() {
static int level = -1;
if (VL_UNLIKELY(level < 0)) level = v3Global.opt.debugSrcLevel(__FILE__);
return level;
}
// VISITORS
virtual void visit(AstCell* nodep, AstNUser*) {
+7 -2
View File
@@ -101,9 +101,14 @@ private:
VarMap m_modVarMap; // Table of new var names created under module
V3Double0 m_statSharedSet;// Statistic tracking
//static int debug() { return 9; }
// METHODS
static int debug() {
static int level = -1;
if (VL_UNLIKELY(level < 0)) level = v3Global.opt.debugSrcLevel(__FILE__);
return level;
}
void markVarUsage(AstVar* nodep, uint32_t flags) {
//UINFO(4," MVU "<<flags<<" "<<nodep<<endl);
nodep->user1( nodep->user1() | flags );
@@ -417,7 +422,7 @@ private:
}
virtual void visit(AstNodeFor* nodep, AstNUser*) {
nodep->v3fatalSrc("For statements should have been converted to while statements in V3Unroll\n");
nodep->v3fatalSrc("For statements should have been converted to while statements in V3Begin\n");
}
virtual void visit(AstWhile* nodep, AstNUser*) {
bool oldloop = m_inLoop;
+6 -2
View File
@@ -51,9 +51,13 @@ private:
int m_depth; // How deep in an expression
int m_maxdepth; // Maximum depth in an expression
//int debug() { return 9; }
// METHODS
static int debug() {
static int level = -1;
if (VL_UNLIKELY(level < 0)) level = v3Global.opt.debugSrcLevel(__FILE__);
return level;
}
void createDeepTemp(AstNode* nodep) {
UINFO(6," Deep "<<nodep<<endl);
//if (debug()>=9) nodep->dumpTree(cout,"deep:");
+6 -2
View File
@@ -48,9 +48,13 @@ private:
int m_depth; // How deep in an expression
int m_deepNum; // How many functions made
//int debug() { return 9; }
// METHODS
static int debug() {
static int level = -1;
if (VL_UNLIKELY(level < 0)) level = v3Global.opt.debugSrcLevel(__FILE__);
return level;
}
AstCFunc* createDeepFunc(AstNode* nodep) {
AstNRelinker relinkHandle;
nodep->unlinkFrBack(&relinkHandle);
+6 -1
View File
@@ -55,9 +55,14 @@ private:
AstScope* m_scopep; // Current scope
bool m_needThis; // Add thisp to function
FuncMmap m_modFuncs; // Name of public functions added
//int debug() { return 9; }
// METHODS
static int debug() {
static int level = -1;
if (VL_UNLIKELY(level < 0)) level = v3Global.opt.debugSrcLevel(__FILE__);
return level;
}
string descopedName(AstScope* scopep, bool& hierThisr, AstVar* varp=NULL) {
UASSERT(scopep, "Var/Func not scoped\n");
hierThisr = true;
+21 -14
View File
@@ -44,8 +44,14 @@ private:
vector<AstVar*> m_ctorVarsVec; // All variables in constructor order
int m_splitSize; // # of cfunc nodes placed into output file
int m_splitFilenum; // File number being created, 0 = primary
public:
//int debug() { return 9; }
// METHODS
static int debug() {
static int level = -1;
if (VL_UNLIKELY(level < 0)) level = v3Global.opt.debugSrcLevel(__FILE__);
return level;
}
// ACCESSORS
int splitFilenum() { return m_splitFilenum; }
@@ -69,6 +75,9 @@ public:
void emitIQW(AstNode* nodep) {
puts (nodep->isWide()?"W":(nodep->isQuad()?"Q":"I"));
}
void emitScIQW(AstVar* nodep) {
puts (nodep->isScBv()?"SW":(nodep->isScQuad()?"SQ":"SI"));
}
void emitOpName(AstNode* nodep, const string& format,
AstNode* lhsp, AstNode* rhsp, AstNode* thsp);
@@ -124,8 +133,7 @@ public:
} else if (nodep->lhsp()->castVarRef()
&& nodep->lhsp()->castVarRef()->varp()->isSc()) {
putbs("VL_ASSIGN_"); // Set a systemC variable
if (nodep->lhsp()->castVarRef()->varp()->isScQuad()) puts("SQ");
else puts("S");
emitScIQW(nodep->lhsp()->castVarRef()->varp());
emitIQW(nodep);
puts("(");
puts(cvtToStr(nodep->widthMin())+",");
@@ -134,8 +142,8 @@ public:
&& nodep->rhsp()->castVarRef()->varp()->isSc()) {
putbs("VL_ASSIGN_"); // Get a systemC variable
emitIQW(nodep);
if (nodep->rhsp()->castVarRef()->varp()->isScQuad()) puts("SQ(");
else puts("S(");
emitScIQW(nodep->rhsp()->castVarRef()->varp());
puts("(");
puts(cvtToStr(nodep->widthMin())+",");
nodep->lhsp()->iterateAndNext(*this); puts(", ");
} else if (nodep->isWide()
@@ -1406,7 +1414,7 @@ void EmitCStmts::emitVarList(AstNode* firstp, EisWhich which, const string& pref
int sigbytes = varp->widthAlignBytes();
if (varp->isUsedClock() && varp->widthMin()==1) sigbytes = 0;
else if (varp->arraysp()) sigbytes=7;
else if (varp->isScWide()) sigbytes=6;
else if (varp->isScBv()) sigbytes=6;
else if (sigbytes==8) sigbytes=5;
else if (sigbytes==4) sigbytes=4;
else if (sigbytes==2) sigbytes=2;
@@ -1538,7 +1546,7 @@ void EmitCImp::emitInt(AstModule* modp) {
if (!varp->initp()) nodep->v3fatalSrc("No init for a param?");
// These should be static const values, however microsloth VC++ doesn't
// support them. They also cause problems with GDB under GCC2.95.
if (varp->isScWide()) { // Unsupported for output
if (varp->isWide()) { // Unsupported for output
puts("// enum WData "+varp->name()+" //wide");
} else if (!varp->initp()->castConst()) { // Unsupported for output
puts("// enum IData "+varp->name()+" //not simple value");
@@ -1680,8 +1688,7 @@ void EmitCImp::main(AstModule* modp, bool slow, bool fast) {
string filenameNoExt = v3Global.opt.makeDir()+"/"+ modClassName(modp)+(m_fast ? "" : "__Slow");
if (debug()>=5) {
for (int i=0;i<modp->level();i++) { cout<<" "; }
UINFONL(0," Emitting "<<modClassName(modp)<<endl);
UINFO(0," Emitting "<<modClassName(modp)<<endl);
}
if (optSystemPerl()) {
@@ -1811,11 +1818,11 @@ class EmitCTrace : EmitCStmts {
puts("\n//======================\n\n");
}
bool emitTraceIsScWide(AstTraceInc* nodep) {
bool emitTraceIsScBv(AstTraceInc* nodep) {
AstVarRef* varrefp = nodep->valuep()->castVarRef();
if (!varrefp) return false;
AstVar* varp = varrefp->varp();
return varp->isSc() && varp->isScWide();
return varp->isSc() && varp->isScBv();
}
void emitTraceInitOne(AstTraceDecl* nodep) {
if (nodep->isWide()) {
@@ -1846,7 +1853,7 @@ class EmitCTrace : EmitCStmts {
string full = ((m_funcp->funcType() == AstCFuncType::TRACE_FULL
|| m_funcp->funcType() == AstCFuncType::TRACE_FULL_SUB)
? "full":"chg");
if (nodep->isWide() || emitTraceIsScWide(nodep)) {
if (nodep->isWide() || emitTraceIsScBv(nodep)) {
puts("vcdp->"+full+"Array");
} else if (nodep->isQuad()) {
puts("vcdp->"+full+"Quad ");
@@ -1868,7 +1875,7 @@ class EmitCTrace : EmitCStmts {
if (nodep->valuep()->castVarRef()) {
AstVarRef* varrefp = nodep->valuep()->castVarRef();
AstVar* varp = varrefp->varp();
if (emitTraceIsScWide(nodep)) puts("(uint32_t*)");
if (emitTraceIsScBv(nodep)) puts("(uint32_t*)");
puts("(");
varrefp->iterate(*this); // Put var name out
if (varp->arraysp()) {
@@ -1877,7 +1884,7 @@ class EmitCTrace : EmitCStmts {
else puts("["+cvtToStr(arrayindex)+"]");
}
if (varp->isSc()) puts(".read()");
if (emitTraceIsScWide(nodep)) puts(".get_datap()");
if (emitTraceIsScBv(nodep)) puts(".get_datap()");
puts(")");
} else {
puts("(");
+1 -3
View File
@@ -207,11 +207,9 @@ void EmitCSyms::emitImp() {
AstScope* scopep = it->first; AstModule* modp = it->second;
if (modp->isTop()) {
} else {
string arrow = scopep->name();
if (arrow.substr(0,4) == "TOP.") arrow.replace(0,4,".");
ofp()->printf("\t%c %-30s ", comma, scopep->nameDotless().c_str());
puts("(Verilated::catName(topp->name(),\"");
puts(arrow);
puts("."+scopep->prettyName());
puts("\"))\n");
comma=',';
}
+7 -1
View File
@@ -37,9 +37,14 @@
class EmitMkVisitor : public EmitCBaseVisitor {
public:
//int debug() { return 9; }
// METHODS
static int debug() {
static int level = -1;
if (VL_UNLIKELY(level < 0)) level = v3Global.opt.debugSrcLevel(__FILE__);
return level;
}
void emitClassMake() {
// Generate the makefile
V3OutMkFile of (v3Global.opt.makeDir()+"/"+ v3Global.opt.prefix() + "_classes.mk");
@@ -82,6 +87,7 @@ public:
of.puts("PERL = "+V3Options::getenvPERL()+"\n");
of.puts("VERILATOR_ROOT = "+V3Options::getenvVERILATOR_ROOT()+"\n");
of.puts("SYSTEMPERL = "+V3Options::getenvSYSTEMPERL()+"\n");
of.puts("SYSTEMPERL_INCLUDE = "+V3Options::getenvSYSTEMPERL_INCLUDE()+"\n");
of.puts("\n# Switches...\n");
of.puts(string("VM_SP = ")+(v3Global.opt.systemPerl()?"1":"0")+"\n");
+13 -1
View File
@@ -38,9 +38,14 @@
class EmitVBaseVisitor : public EmitCBaseVisitor {
// MEMBERS
bool m_suppressSemi;
//int debug() { return 9; }
// METHODS
static int debug() {
static int level = -1;
if (VL_UNLIKELY(level < 0)) level = v3Global.opt.debugSrcLevel(__FILE__);
return level;
}
virtual void puts(const string& str) = 0;
virtual void putbs(const string& str) = 0;
virtual void putsNoTracking(const string& str) = 0;
@@ -234,6 +239,13 @@ class EmitVBaseVisitor : public EmitCBaseVisitor {
nodep->bodysp()->iterateAndNext(*this);
puts("}\n");
}
virtual void visit(AstRepeat* nodep, AstNUser*) {
puts("repeat (");
nodep->countp()->iterateAndNext(*this);
puts(") {\n");
nodep->bodysp()->iterateAndNext(*this);
puts("}\n");
}
virtual void visit(AstWhile* nodep, AstNUser*) {
nodep->precondsp()->iterateAndNext(*this);
puts("while (");
+6 -2
View File
@@ -50,9 +50,13 @@ private:
// STATE
AstNode* m_stmtp; // Current statement
//int debug() { return 9; }
// METHODS
static int debug() {
static int level = -1;
if (VL_UNLIKELY(level < 0)) level = v3Global.opt.debugSrcLevel(__FILE__);
return level;
}
int longOrQuadWidth (AstNode* nodep) {
// Return 32 or 64...
return (nodep->width()+(VL_WORDSIZE-1)) & ~(VL_WORDSIZE-1);
+6 -2
View File
@@ -48,7 +48,11 @@ typedef list<AstNodeVarRef*> GateVarRefList;
class GateBaseVisitor : public AstNVisitor {
public:
//int debug() { return 9; }
static int debug() {
static int level = -1;
if (VL_UNLIKELY(level < 0)) level = v3Global.opt.debugSrcLevel(__FILE__);
return level;
}
};
//######################################################################
@@ -578,7 +582,7 @@ void GateVisitor::replaceAssigns() {
//if (debug()>9) {vscp->dumpTree(cout, "-vscDone: "); cout<<endl;}
if (!vscp->valuep()->castNodeMath()
|| vscp->valuep()->nextp()) {
vscp->dumpTree(cout, "vscStrange: ");
vscp->dumpTree(cerr, "vscStrange: ");
vscp->v3fatalSrc("Value of varscope not mathematical\n");
}
}
+5 -1
View File
@@ -38,7 +38,11 @@
class GenClkBaseVisitor : public AstNVisitor {
protected:
//static int debug() { return 9; }
static int debug() {
static int level = -1;
if (VL_UNLIKELY(level < 0)) level = v3Global.opt.debugSrcLevel(__FILE__);
return level;
}
};
//######################################################################
+1 -1
View File
@@ -228,7 +228,7 @@ void V3Graph::clearColors() {
void V3Graph::loopsVertexCb(V3GraphVertex* vertexp) {
// Needed here as V3GraphVertex<< isn't defined until later in header
cout<<"-Info-Loop: "<<(void*)(vertexp)<<" "<<vertexp<<endl;
cerr<<"-Info-Loop: "<<(void*)(vertexp)<<" "<<vertexp<<endl;
}
void V3Graph::dump(ostream& os) {
+1 -1
View File
@@ -106,7 +106,7 @@ private:
V3EdgeFuncP m_origEdgeFuncp; // Function that says we follow this edge (in original graph)
uint32_t m_placeStep; // Number that user() must be equal to to indicate processing
int debug() { return V3Graph::debug(); }
static int debug() { return V3Graph::debug(); }
// METHODS
void buildGraph (V3Graph* origGraphp);
+6 -2
View File
@@ -35,8 +35,12 @@
class V3GraphTest {
public:
// ***These tests only run with DEBUG ON***
//static int debug() { return 9; }
static int debug() { return 0; }
static int debug() {
static int level = -1;
// Note setting just --debug will not enable this, as we exit when we run the test
if (VL_UNLIKELY(level < 0)) level = v3Global.opt.debugSrcLevel(__FILE__, 0);
return level;
}
protected:
// MEMBERS
+5 -1
View File
@@ -53,7 +53,11 @@ private:
// STATE
V3Hash m_lowerHash; // Hash of the statement we're building
//int debug() { return 9; }
static int debug() {
static int level = -1;
if (VL_UNLIKELY(level < 0)) level = v3Global.opt.debugSrcLevel(__FILE__);
return level;
}
// METHODS
void hashNodeIterate(AstNode* nodep) {
+7 -1
View File
@@ -42,7 +42,7 @@ public:
private:
// MEMBERS
HashMmap m_hashMmap; // hashvalue -> nodes with that hash
int debug() { return 0; }
public:
// CONSTRUCTORS
V3Hashed();
@@ -51,7 +51,13 @@ public:
HashMmap& mmap() { return m_hashMmap; } // Return map for iteration
HashMmap::iterator begin() { return m_hashMmap.begin(); }
HashMmap::iterator end() { return m_hashMmap.end(); }
// METHODS
static int debug() {
static int level = -1;
if (VL_UNLIKELY(level < 0)) level = v3Global.opt.debugSrcLevel(__FILE__);
return level;
}
void clear() { m_hashMmap.clear(); }
void hashAndInsert(AstNode* nodep); // Hash the node, and insert into map
bool sameNodes(AstNode* node1p, AstNode* node2p); // After hashing, and tell if identical
+5 -1
View File
@@ -62,7 +62,11 @@ private:
AstCell* m_cellp; // Cell being cloned
V3Double0 m_statCells; // Statistic tracking
//int debug() { return 9; }
static int debug() {
static int level = -1;
if (VL_UNLIKELY(level < 0)) level = v3Global.opt.debugSrcLevel(__FILE__);
return level;
}
// VISITORS
virtual void visit(AstNetlist* nodep, AstNUser*) {
+10 -2
View File
@@ -53,7 +53,11 @@ private:
AstModule* m_modp; // Current module
AstCell* m_cellp; // Current cell
//int debug() { return 8; }
static int debug() {
static int level = -1;
if (VL_UNLIKELY(level < 0)) level = v3Global.opt.debugSrcLevel(__FILE__);
return level;
}
//int m_debug; int debug() { return m_debug; }
// VISITORS
@@ -147,7 +151,11 @@ private:
int m_instNum; // Current instantiation number
int m_instLsb; // Current instantiation number
//int debug() { return 9; }
static int debug() {
static int level = -1;
if (VL_UNLIKELY(level < 0)) level = v3Global.opt.debugSrcLevel(__FILE__);
return level;
}
// VISITORS
virtual void visit(AstCell* nodep, AstNUser*) {
+6 -1
View File
@@ -270,7 +270,6 @@ private:
// STATE
LifeState* m_statep; // Current state
bool m_sideEffect; // Side effects discovered in assign RHS
//static int debug() { return 9; }
// LIFE MAP
// For each basic block, we'll make a new map of what variables that if/else is changing
@@ -278,6 +277,12 @@ private:
LifeBlock* m_lifep; // Current active lifetime map for current scope
// METHODS
static int debug() {
static int level = -1;
if (VL_UNLIKELY(level < 0)) level = v3Global.opt.debugSrcLevel(__FILE__);
return level;
}
// VISITORS
virtual void visit(AstVarRef* nodep, AstNUser*) {
// Consumption/generation of a variable,
+5 -1
View File
@@ -44,7 +44,11 @@
class LifePostBaseVisitor : public AstNVisitor {
protected:
// static int debug() { return 9; }
static int debug() {
static int level = -1;
if (VL_UNLIKELY(level < 0)) level = v3Global.opt.debugSrcLevel(__FILE__);
return level;
}
};
//######################################################################
+103 -59
View File
@@ -29,6 +29,7 @@
#include "verilatedos.h"
#include <cstdio>
#include <cstdarg>
#include <cctype>
#include <unistd.h>
#include <map>
#include <algorithm>
@@ -49,10 +50,11 @@ private:
// AstModule::user1p() // V3SymTable* Module's Symbol table
// AstNodeFTask::user1p() // V3SymTable* Local Symbol table
// AstBegin::user1p() // V3SymTable* Local Symbol table
// AstVar::user1p() // V3SymTable* Table used to create this variable
// AstVar::user2p() // bool True if port set for this variable
// AstVar/Module::user3p() // V3SymTable* Table used to create this variable
AstUser1InUse m_inuser1;
AstUser2InUse m_inuser2;
AstUser3InUse m_inuser3;
// ENUMS
enum IdState { // Which loop through the tree
@@ -69,27 +71,84 @@ private:
V3SymTable* m_curVarsp; // Symbol table of variables and tasks under table we're inserting into
V3SymTable* m_cellVarsp; // Symbol table of variables under cell's module
int m_beginNum; // Begin block number, 0=none seen
bool m_inGenerate; // Inside a generate
vector<V3SymTable*> m_delSymps; // Symbol tables to delete
//int debug() { return 9; }
static int debug() {
static int level = -1;
if (VL_UNLIKELY(level < 0)) level = v3Global.opt.debugSrcLevel(__FILE__);
return level;
}
// METHODS
V3SymTable* symsFindNew(AstNode* nodep, V3SymTable* upperVarsp) {
// Find or create symbol table for this node
if (V3SymTable* symsp = nodep->user1p()->castSymTable()) {
return symsp;
} else {
V3SymTable* symsp = new V3SymTable(upperVarsp);
m_delSymps.push_back(symsp);
nodep->user1p(symsp);
return symsp;
}
}
void symsInsert(const string& name, AstNode* nodep) {
// Insert into symbol table, and remember what table the node is in
m_curVarsp->insert(name, nodep);
nodep->user3p(m_curVarsp);
}
void linkVarName (AstVarRef* nodep) {
if (!nodep->varp()) {
AstVar* varp = m_curVarsp->findIdName(nodep->name())->castVar();
AstVar* varp = m_curVarsp->findIdUpward(nodep->name())->castVar();
nodep->varp(varp);
}
}
const char* varTextType(AstNode* nodep) {
const char* nodeTextType(AstNode* nodep) {
const char* what = "node";
if (nodep->castVar()) what = "variable";
else if (nodep->castCell()) what = "cell";
else if (nodep->castTask()) what = "task";
else if (nodep->castFunc()) what = "function";
else if (nodep->castBegin()) what = "block";
return what;
}
string ucfirst(const string& text) {
string out = text;
out[0] = toupper(out[0]);
return out;
}
void findAndInsertAndCheck(AstNode* nodep, const string& name) {
// Lookup the given name under current symbol table
// Insert if not found
// Report error if there's a duplicate
//
// Note we only check for conflicts at the same level; it's ok if one block hides another
// We also wouldn't want to not insert it even though it's lower down
AstNode* foundp = m_curVarsp->findIdFlat(name);
if (!foundp) {
symsInsert(nodep->name(), nodep);
foundp = nodep;
} else if (nodep==foundp) { // Already inserted.
// Good.
} else if ((nodep->castBegin() || foundp->castBegin())
&& m_inGenerate) {
// Begin: ... blocks often replicate under genif/genfor, so simply suppress duplicate checks
// See t_gen_forif.v for an example.
} else if (nodep->type() == foundp->type()) {
nodep->v3error("Duplicate declaration of "<<nodeTextType(foundp)<<": "<<nodep->prettyName());
foundp->v3error("... Location of original declaration");
} else {
nodep->v3error("Unsupported in C: "<<ucfirst(nodeTextType(nodep))<<" has the same name as "
<<nodeTextType(foundp)<<": "<<nodep->prettyName());
foundp->v3error("... Location of original declaration");
}
}
void createImplicitVar (AstVarRef* forrefp, bool noWarn) {
// Create implicit after warning
linkVarName(forrefp);
@@ -111,9 +170,7 @@ private:
virtual void visit(AstNetlist* nodep, AstNUser*) {
// Look at all modules, and store pointers to all module names
for (AstModule* modp = v3Global.rootp()->modulesp(); modp; modp=modp->nextp()->castModule()) {
V3SymTable* symp = new V3SymTable(NULL);
m_delSymps.push_back(symp);
modp->user1p(symp);
symsFindNew(modp, NULL);
}
// And recurse...
m_idState = ID_FIND;
@@ -130,7 +187,7 @@ private:
UINFO(2,"Link Module: "<<nodep<<endl);
m_modp = nodep;
// This state must be save/restored in the cell visitor function
m_curVarsp = nodep->user1p()->castSymTable();
m_curVarsp = symsFindNew(nodep, NULL);
if (!m_curVarsp) nodep->v3fatalSrc("NULL");
m_cellVarsp = NULL;
m_paramNum = 0;
@@ -140,6 +197,18 @@ private:
m_curVarsp = NULL;
m_modp = NULL;
}
virtual void visit(AstGenerate* nodep, AstNUser*) {
// Begin: ... blocks often replicate under genif/genfor, so simply suppress duplicate checks
// See t_gen_forif.v for an example.
bool lastInGen = m_inGenerate;
{
m_inGenerate = true;
nodep->iterateChildren(*this);
}
m_inGenerate = lastInGen;
}
virtual void visit(AstVar* nodep, AstNUser*) {
// Var: Remember its name for later resolution
if (!m_curVarsp) nodep->v3fatalSrc("Var not under module??\n");
@@ -153,17 +222,17 @@ private:
nodep->trace(false);
}
// Find under either a task or the module's vars
AstNode* findidp = m_curVarsp->findIdName(nodep->name());
AstVar* findvarp = findidp->castVar();
AstNode* foundp = m_curVarsp->findIdUpward(nodep->name());
AstVar* findvarp = foundp->castVar();
bool ins=false;
if (!findidp) {
if (!foundp) {
ins=true;
} else if (!findvarp) {
nodep->v3error("Unsupported in C: Variable has same name as "
<<varTextType(findidp)<<": "<<nodep->prettyName());
<<nodeTextType(foundp)<<": "<<nodep->prettyName());
} else if (findvarp != nodep) {
UINFO(4,"DupVar: "<<nodep<<" ;; "<<findvarp<<endl);
if (findvarp->user1p() == m_curVarsp) { // Only when on same level
if (findvarp->user3p() == m_curVarsp) { // Only when on same level
if ((findvarp->isIO() && nodep->isSignal())
|| (findvarp->isSignal() && nodep->isIO())) {
findvarp->combineType(nodep);
@@ -184,11 +253,10 @@ private:
}
}
if (ins) {
m_curVarsp->insert(nodep->name(), nodep);
nodep->user1p(m_curVarsp);
symsInsert(nodep->name(), nodep);
if (nodep->isGParam()) {
m_paramNum++;
m_curVarsp->insert("__paramNumber"+cvtToStr(m_paramNum), nodep);
symsInsert("__paramNumber"+cvtToStr(m_paramNum), nodep);
}
}
}
@@ -220,13 +288,8 @@ private:
V3SymTable* upperVarsp = m_curVarsp;
{
// Create symbol table for the task's vars
if (V3SymTable* localVarsp = nodep->user1p()->castSymTable()) {
m_curVarsp = localVarsp;
} else {
m_curVarsp = new V3SymTable(upperVarsp);
m_delSymps.push_back(m_curVarsp);
nodep->user1p(m_curVarsp);
}
m_curVarsp = symsFindNew(nodep, upperVarsp);
// Convert the func's range to the output variable
// This should probably be done in the Parser instead, as then we could
// just attact normal signal attributes to it.
@@ -241,7 +304,7 @@ private:
newvarp->attrIsolateAssign(funcp->attrIsolateAssign());
funcp->addFvarp(newvarp);
// Explicit insert required, as the var name shadows the upper level's task name
m_curVarsp->insert(newvarp->name(), newvarp);
symsInsert(newvarp->name(), newvarp);
}
}
m_ftaskp = nodep;
@@ -250,16 +313,7 @@ private:
}
m_curVarsp = upperVarsp;
if (m_idState==ID_FIND) {
AstNode* findidp = m_curVarsp->findIdName(nodep->name());
AstNodeFTask* findtaskp = findidp->castNodeFTask();
if (!findidp) {
m_curVarsp->insert(nodep->name(), nodep);
} else if (!findtaskp) {
nodep->v3error("Unsupported in C: Task/function has same name as "
<<varTextType(findidp)<<": "<<nodep->prettyName());
} else if (findtaskp!=nodep) {
nodep->v3error("Duplicate declaration of task/function: "<<nodep->prettyName());
}
findAndInsertAndCheck(nodep, nodep->name());
}
}
virtual void visit(AstBegin* nodep, AstNUser*) {
@@ -273,18 +327,16 @@ private:
++m_beginNum;
nodep->name(nodep->name()+cvtToStr(m_beginNum));
}
// Check naming (we don't really care, but some tools do, so better to warn)
if (m_idState==ID_FIND) {
findAndInsertAndCheck(nodep, nodep->name());
}
// Recurse
int oldNum = m_beginNum;
m_beginNum = 0;
{
// Create symbol table for the task's vars
if (V3SymTable* localVarsp = nodep->user1p()->castSymTable()) {
m_curVarsp = localVarsp;
} else {
m_curVarsp = new V3SymTable(upperVarsp);
m_delSymps.push_back(m_curVarsp);
nodep->user1p(m_curVarsp);
}
m_curVarsp = symsFindNew(nodep, upperVarsp);
nodep->iterateChildren(*this);
}
m_curVarsp = upperVarsp;
@@ -294,7 +346,7 @@ private:
// NodeFTaskRef: Resolve its reference
if (m_idState==ID_RESOLVE && !nodep->taskp()) {
if (nodep->dotted() == "") {
AstNodeFTask* taskp = m_curVarsp->findIdName(nodep->name())->castNodeFTask();
AstNodeFTask* taskp = m_curVarsp->findIdUpward(nodep->name())->castNodeFTask();
if (!taskp) { nodep->v3error("Can't find definition of task/function: "<<nodep->prettyName()); }
nodep->taskp(taskp);
}
@@ -306,16 +358,7 @@ private:
// Cell: Resolve its filename. If necessary, parse it.
if (m_idState==ID_FIND) {
// Add to list of all cells, for error checking and defparam's
AstNode* findidp = m_curVarsp->findIdName(nodep->name());
AstCell* findcellp = findidp->castCell();
if (!findidp) {
m_curVarsp->insert(nodep->name(), nodep);
} else if (!findcellp) {
nodep->v3error("Unsupported in C: Cell has same name as "
<<varTextType(findidp)<<": "<<nodep->prettyName());
} else if (findcellp != nodep) {
nodep->v3error("Duplicate name of cell: "<<nodep->prettyName());
}
findAndInsertAndCheck(nodep, nodep->name());
}
if (!nodep->modp()) {
nodep->v3fatalSrc("Cell has unlinked module"); // V3LinkCell should have errored out
@@ -339,13 +382,13 @@ private:
if (m_idState==ID_PARAM) {
// Need to set pin numbers after varnames are created
// But before we do the final resolution based on names
AstVar* refp = m_curVarsp->findIdName(nodep->name())->castVar();
AstVar* refp = m_curVarsp->findIdFlat(nodep->name())->castVar();
if (!refp) {
nodep->v3error("Input/output/inout declaration not found for port: "<<nodep->prettyName());
} else if (!refp->isIO()) {
nodep->v3error("Pin is not a in/out/inout: "<<nodep->prettyName());
nodep->v3error("Pin is not an in/out/inout: "<<nodep->prettyName());
} else {
m_curVarsp->insert("__pinNumber"+cvtToStr(nodep->pinNum()), refp);
symsInsert("__pinNumber"+cvtToStr(nodep->pinNum()), refp);
refp->user2(true);
}
// Ports not needed any more
@@ -373,11 +416,11 @@ private:
// Pin: Link to submodule's pin
if (!m_cellVarsp) nodep->v3fatalSrc("Pin not under cell?\n");
if (m_idState==ID_RESOLVE && !nodep->modVarp()) {
AstVar* refp = m_cellVarsp->findIdName(nodep->name())->castVar();
AstVar* refp = m_cellVarsp->findIdFlat(nodep->name())->castVar();
if (!refp) {
nodep->v3error("Pin not found: "<<nodep->prettyName());
} else if (!refp->isIO() && !refp->isParam()) {
nodep->v3error("Pin is not a in/out/inout/param: "<<nodep->prettyName());
nodep->v3error("Pin is not an in/out/inout/param: "<<nodep->prettyName());
} else {
nodep->modVarp(refp);
}
@@ -403,8 +446,8 @@ private:
virtual void visit(AstDefParam* nodep, AstNUser*) {
nodep->iterateChildren(*this);
if (m_idState==ID_PARAM) {
AstNode* findidp = m_curVarsp->findIdName(nodep->path());
AstCell* cellp = findidp->castCell();
AstNode* foundp = m_curVarsp->findIdUpward(nodep->path());
AstCell* cellp = foundp->castCell();
if (!cellp) {
nodep->v3error("In defparam, cell "<<nodep->path()<<" never declared");
} else {
@@ -436,6 +479,7 @@ public:
m_ftaskp = NULL;
m_paramNum = 0;
m_beginNum = 0;
m_inGenerate = false;
//
rootp->accept(*this);
}
+12 -6
View File
@@ -96,7 +96,11 @@ private:
LinkCellsGraph m_graph; // Linked graph of all cell interconnects
LibraryVertex* m_libVertexp; // Vertex at root of all libraries
//int debug() { return 9; }
static int debug() {
static int level = -1;
if (VL_UNLIKELY(level < 0)) level = v3Global.opt.debugSrcLevel(__FILE__);
return level;
}
// METHODS
V3GraphVertex* vertex(AstModule* nodep) {
@@ -140,7 +144,9 @@ private:
// Cell: Resolve its filename. If necessary, parse it.
if (!nodep->modp()) {
UINFO(4,"Link Cell: "<<nodep<<endl);
AstModule* modp = m_mods.findIdName(nodep->modName())->castModule();
// Use findIdUpward instead of findIdFlat; it doesn't matter for now
// but we might support modules-under-modules someday.
AstModule* modp = m_mods.findIdUpward(nodep->modName())->castModule();
if (!modp) {
// Read-subfile
V3Read reader (v3Global.rootp());
@@ -149,7 +155,7 @@ private:
// We've read new modules, grab new pointers to their names
readModNames();
// Check again
modp = m_mods.findIdName(nodep->modName())->castModule();
modp = m_mods.findIdUpward(nodep->modName())->castModule();
if (!modp) {
nodep->v3error("Can't resolve module reference: "<<nodep->modName());
}
@@ -167,7 +173,7 @@ private:
V3SymTable ports; // Symbol table of all connected port names
for (AstPin* pinp = nodep->pinsp(); pinp; pinp=pinp->nextp()->castPin()) {
if (pinp->name()=="") pinp->v3error("Connect by position is illegal in .* connected cells");
if (!ports.findIdName(pinp->name())) {
if (!ports.findIdFlat(pinp->name())) {
ports.insert(pinp->name(), pinp);
}
}
@@ -175,7 +181,7 @@ private:
// and it's easier to do it now than in V3Link when we'd need to repeat steps.
for (AstNode* portnodep = nodep->modp()->stmtsp(); portnodep; portnodep=portnodep->nextp()) {
if (AstPort* portp = portnodep->castPort()) {
if (!ports.findIdName(portp->name())) {
if (!ports.findIdFlat(portp->name())) {
UINFO(9," need PORT "<<portp<<endl);
// Create any not already connected
AstPin* newp = new AstPin(nodep->fileline(),0,portp->name(),
@@ -210,7 +216,7 @@ private:
void readModNames() {
// Look at all modules, and store pointers to all module names
for (AstModule* nodep = v3Global.rootp()->modulesp(); nodep; nodep=nodep->nextp()->castModule()) {
AstNode* foundp = m_mods.findIdName(nodep->name());
AstNode* foundp = m_mods.findIdUpward(nodep->name());
if (foundp && foundp != nodep) {
nodep->v3error("Duplicate declaration of module: "<<nodep->prettyName());
foundp->v3error("... Location of original declaration");
+10 -3
View File
@@ -186,8 +186,12 @@ private:
bool m_forPrearray; // Compress cell__[array] refs
bool m_forScopeCreation; // Remove VarXRefs for V3Scope
public:
static int debug() { return V3Error::debugDefault(); }
// static int debug() { return 9; }
static int debug() {
static int level = -1;
if (VL_UNLIKELY(level < 0)) level = v3Global.opt.debugSrcLevel(__FILE__);
return level;
}
// CONSTRUCTORS
LinkDotState(bool forPrearray, bool forScopeCreation) {
@@ -356,7 +360,7 @@ public:
<<((cellVxp->symPrefix()=="") ? "" : cellVxp->symPrefix()+dotname)
<<" at "<<cellVxp
<<endl);
AstNode* nodep = cellVxp->syms().findIdName(cellVxp->symPrefix() + dotname); // Might be NULL
AstNode* nodep = cellVxp->syms().findIdFlat(cellVxp->symPrefix() + dotname); // Might be NULL
if (!nodep) baddot = dotname;
return nodep;
}
@@ -372,6 +376,7 @@ private:
LinkDotBaseVertex* m_inlineVxp; // Vertex for current module, possibly a fake inlined one
string m_scope; // Scope text
AstBegin* m_beginp; // Current Begin/end block
int debug() { return LinkDotState::debug(); }
// VISITs
@@ -518,6 +523,7 @@ private:
// STATE
LinkDotState* m_statep; // State to pass between visitors, including symbol table
LinkDotCellVertex* m_cellVxp; // Vertex for current module
int debug() { return LinkDotState::debug(); }
// VISITs
@@ -580,6 +586,7 @@ private:
// STATE
LinkDotState* m_statep; // State, including dotted symbol table
LinkDotCellVertex* m_cellVxp; // Vertex for current module
int debug() { return LinkDotState::debug(); }
// METHODS
+5 -2
View File
@@ -46,9 +46,12 @@ private:
bool m_setRefLvalue; // Set VarRefs to lvalues for pin assignments
AstNodeFTask* m_ftaskp; // Function or task we're inside
//int debug() { return 9; }
// METHODS
static int debug() {
static int level = -1;
if (VL_UNLIKELY(level < 0)) level = v3Global.opt.debugSrcLevel(__FILE__);
return level;
}
// VISITs
// Result handing
+6 -2
View File
@@ -55,9 +55,13 @@ private:
AstParseRefExp m_exp; // Type of data we're looking for
AstText* m_baseTextp; // Lowest TEXT node that needs replacement with varref
//int debug() { return 9; }
// METHODS
static int debug() {
static int level = -1;
if (VL_UNLIKELY(level < 0)) level = v3Global.opt.debugSrcLevel(__FILE__);
return level;
}
void checkExpected(AstNode* nodep) {
if (m_exp != AstParseRefExp::NONE) {
nodep->v3fatalSrc("Tree syntax error: Not expecting "<<nodep->type()<<" under a "<<nodep->backp()->type());
+13 -3
View File
@@ -58,9 +58,13 @@ private:
AstVAssert* m_assertp; // Current assertion
int m_senitemCvtNum; // Temporary signal counter
//int debug() { return 9; }
// METHODS
static int debug() {
static int level = -1;
if (VL_UNLIKELY(level < 0)) level = v3Global.opt.debugSrcLevel(__FILE__);
return level;
}
// VISITs
virtual void visit(AstModule* nodep, AstNUser*) {
// Module: Create sim table for entire module and iterate
@@ -484,7 +488,13 @@ class LinkBotupVisitor : public AstNVisitor {
private:
// STATE
AstModule* m_modp; // Current module
//int debug() { return 9; }
// METHODS
static int debug() {
static int level = -1;
if (VL_UNLIKELY(level < 0)) level = v3Global.opt.debugSrcLevel(__FILE__);
return level;
}
// VISITs
virtual void visit(AstNetlist* nodep, AstNUser*) {
+6 -1
View File
@@ -49,7 +49,12 @@ protected:
// AstVar::user2() -> VarFlags. Flag state
// AstVar::user4() -> AstVarRef*. First place signal set; must be first assignment
//int debug() { return 9; }
// METHODS
static int debug() {
static int level = -1;
if (VL_UNLIKELY(level < 0)) level = v3Global.opt.debugSrcLevel(__FILE__);
return level;
}
// TYPES
union VarFlags {
+6 -1
View File
@@ -53,7 +53,12 @@ private:
// STATE
AstModule* m_modp;
//int debug() { return 9; }
// METHODS
static int debug() {
static int level = -1;
if (VL_UNLIKELY(level < 0)) level = v3Global.opt.debugSrcLevel(__FILE__);
return level;
}
// VISITORS
virtual void visit(AstModule* nodep, AstNUser*) {
+89 -23
View File
@@ -303,23 +303,31 @@ void V3Options::unlinkRegexp(const string& dir, const string& regexp) {
//######################################################################
// Environment
string V3Options::getenvStr(const char* envvar, const char* defaultValue) {
if (const char* envvalue = getenv(envvar)) {
string V3Options::getenvStr(const string& envvar, const string& defaultValue) {
if (const char* envvalue = getenv(envvar.c_str())) {
return envvalue;
} else {
return defaultValue;
}
}
void V3Options::setenvStr(const string& envvar, const string& value, const string& why) {
if (why != "") {
UINFO(1,"export "<<envvar<<"="<<value<<" # "<<why<<endl);
} else {
UINFO(1,"export "<<envvar<<"="<<value<<endl);
}
setenv(envvar.c_str(),value.c_str(),true);
}
string V3Options::getenvSYSTEMC() {
string var = getenvStr("SYSTEMC","");
if (var == "" && string(DEFENV_SYSTEMC) != "") {
var = DEFENV_SYSTEMC;
UINFO(1,"export SYSTEMC="<<var<<" # Hardcoded at build time"<<endl);
setenv("SYSTEMC", var.c_str(), false);
setenvStr("SYSTEMC", var, "Hardcoded at build time");
}
// Only correct or check it if we really need the value
if ((v3Global.opt.systemPerl() || v3Global.opt.systemC())
&& !v3Global.opt.lintOnly()) {
if (v3Global.opt.usingSystemCLibs()) {
if (var == "") {
v3fatal("Need $SYSTEMC in environment\n"
"Probably System-C isn't installed, see http://www.systemc.org\n");
@@ -327,12 +335,12 @@ string V3Options::getenvSYSTEMC() {
}
return var;
}
string V3Options::getenvSYSTEMC_ARCH() {
string var = getenvStr("SYSTEMC_ARCH","");
if (var == "" && string(DEFENV_SYSTEMC_ARCH) != "") {
var = DEFENV_SYSTEMC_ARCH;
UINFO(1,"export SYSTEMC_ARCH="<<var<<" # Hardcoded at build time"<<endl);
setenv("SYSTEMC_ARCH", var.c_str(), false);
setenvStr("SYSTEMC_ARCH", var, "Hardcoded at build time");
}
if (var == "") {
struct utsname uts;
@@ -341,45 +349,73 @@ string V3Options::getenvSYSTEMC_ARCH() {
if (wildmatch(sysname.c_str(), "*solaris*")) { var = "gccsparcOS5"; }
else if (wildmatch(sysname.c_str(), "*cygwin*")) { var ="cygwin"; }
else { var = "linux"; }
UINFO(1,"export SYSTEMC_ARCH="<<var<<" # From sysname '"<<sysname<<"'"<<endl);
setenv("SYSTEMC_ARCH", var.c_str(), false);
setenvStr("SYSTEMC_ARCH", var,"From sysname '"+sysname+"'");
}
return var;
}
string V3Options::getenvSYSTEMPERL() {
// Must be careful to set SYSTEMPERL_INCLUDE first else we'd setenv
// SYSTEMPERL which would override a DEFENVed SYSTEMPERL_INCLUDE.
V3Options::getenvSYSTEMPERL_INCLUDE();
return V3Options::getenvSYSTEMPERLGuts();
}
string V3Options::getenvSYSTEMPERLGuts() {
// Get SYSTEMPERL when SYSTEMPERL_INCLUDE has already been tested
string var = getenvStr("SYSTEMPERL","");
if (var == "" && string(DEFENV_SYSTEMPERL) != "") {
var = DEFENV_SYSTEMPERL;
UINFO(1,"export SYSTEMPERL="<<var<<" # Hardcoded at build time"<<endl);
setenv("SYSTEMC_PERL", var.c_str(), false);
setenvStr("SYSTEMPERL", var, "Hardcoded at build time");
}
// Only correct or check it if we really need the value
if ((v3Global.opt.systemPerl() || v3Global.opt.trace()) && !v3Global.opt.lintOnly()) {
if (v3Global.opt.usingSystemPerlLibs()) {
if (var == "") {
string testdir = V3Options::getenvW() + "/hw/utils/perltools/SystemC"; // Hack for internal testing
if (V3Options::fileStatDir(testdir)) {
var = testdir;
UINFO(1,"export SYSTEMPERL="<<var<<endl);
setenv ("SYSTEMPERL", var.c_str(), false);
setenvStr ("SYSTEMPERL", var, "From W");
}
}
// Test for correctness in SYSTEMPERL_INCLUDE
}
return var;
}
string V3Options::getenvSYSTEMPERL_INCLUDE() {
string var = getenvStr("SYSTEMPERL_INCLUDE","");
if (var == "" && string(DEFENV_SYSTEMPERL_INCLUDE) != "") {
// Note if SYSTEMPERL is DEFENVed, then SYSTEMPERL_INCLUDE is also DEFENVed
// So we don't need to sweat testing SYSTEMPERL also
var = DEFENV_SYSTEMPERL_INCLUDE;
setenvStr("SYSTEMPERL_INCLUDE", var, "Hardcoded at build time");
}
// Only correct or check it if we really need the value
if (v3Global.opt.usingSystemPerlLibs()) {
if (var == "") {
string sp = V3Options::getenvSYSTEMPERLGuts();
var = sp+"/src";
setenvStr ("SYSTEMPERL_INCLUDE", var, "From $SYSTEMPERL/src");
}
// We warn about $SYSTEMPERL instead of _INCLUDE since that's more likely
// what users will want to set.
if (var == "") {
v3fatal("Need $SYSTEMPERL in environment for --sp or --trace\n"
"Probably System-Perl isn't installed, see http://www.veripool.org/systemperl\n");
}
if (var != ""
&& !V3Options::fileStatNormal(var+"/src/systemperl.h")) {
v3fatal("$SYSTEMPERL environment var doesn't seem to point to System-Perl kit\n");
&& !V3Options::fileStatNormal(var+"/systemperl.h")) {
v3fatal("Neither $SYSTEMPERL nor $SYSTEMPERL_INCLUDE environment vars to point to System-Perl kit: "<<var<<endl);
}
}
return var;
}
string V3Options::getenvVERILATOR_ROOT() {
string var = getenvStr("VERILATOR_ROOT","");
if (var == "" && string(DEFENV_VERILATOR_ROOT) != "") {
var = DEFENV_VERILATOR_ROOT;
UINFO(1,"export VERILATOR_ROOT="<<var<<" # Hardcoded at build time"<<endl);
setenv("VERILATOR_ROOT", var.c_str(), false);
setenvStr("VERILATOR_ROOT", var.c_str(), "Hardcoded at build time");
}
if (var == "") {
v3fatal("$VERILATOR_ROOT needs to be in environment\n");
@@ -532,7 +568,7 @@ void V3Options::parseOptsList(FileLine* fl, int argc, char** argv) {
shift;
} // + options
else if (argv[i][0]=='-') {
char *sw = argv[i];
const char *sw = argv[i];
bool flag = true;
// Allow gnu -- switches
if (sw[0]=='-' && sw[1]=='-') ++sw;
@@ -544,6 +580,11 @@ void V3Options::parseOptsList(FileLine* fl, int argc, char** argv) {
shift;
setDebugMode(atoi(argv[i]));
}
else if ( !strncmp (sw, "-debugi-", strlen("-debugi-"))) {
const char* src = sw+strlen("-debugi-");
shift;
setDebugSrcLevel(src, atoi(argv[i]));
}
else if ( !strcmp (sw, "-error-limit") ) {
shift;
m_inlineMult = atoi(argv[i]);
@@ -617,7 +658,8 @@ void V3Options::parseOptsList(FileLine* fl, int argc, char** argv) {
else if ( onoff (sw, "-inhibit-sim", flag/*ref*/)){ m_inhibitSim = flag; }
else if ( onoff (sw, "-l2name", flag/*ref*/) ) { m_l2Name = flag; }
else if ( onoff (sw, "-lint-only", flag/*ref*/) ) { m_lintOnly = flag; }
else if ( onoff (sw, "-pins64", flag/*ref*/) ) { m_pins64 = flag; }
else if ( !strcmp (sw, "-no-pins64") ) { m_pinsBv = 33; }
else if ( !strcmp (sw, "-pins64") ) { m_pinsBv = 65; }
else if ( !strcmp (sw, "-private") ) { m_public = false; }
else if ( onoff (sw, "-profile-cfuncs", flag/*ref*/) ) { m_profileCFuncs = flag; }
else if ( onoff (sw, "-psl", flag/*ref*/) ) { m_psl = flag; }
@@ -631,7 +673,7 @@ void V3Options::parseOptsList(FileLine* fl, int argc, char** argv) {
else if ( onoff (sw, "-underline-zero", flag/*ref*/) ) { m_underlineZero = flag; }
// Optimization
else if ( !strncmp (sw, "-O", 2) ) {
for (char* cp=sw+strlen("-O"); *cp; ++cp) {
for (const char* cp=sw+strlen("-O"); *cp; ++cp) {
flag = isupper(*cp);
switch (tolower(*cp)) {
case '0': optimize(0); break; // 0=all off
@@ -735,6 +777,9 @@ void V3Options::parseOptsList(FileLine* fl, int argc, char** argv) {
else if ( !strcmp (sw, "-mod-prefix") && (i+1)<argc ) {
shift; m_modPrefix = argv[i];
}
else if ( !strcmp (sw, "-pins-bv") && (i+1)<argc ) {
shift; m_pinsBv = atoi(argv[i]);
}
else if ( !strcmp (sw, "-prefix") && (i+1)<argc ) {
shift; m_prefix = argv[i];
if (m_modPrefix=="") m_modPrefix = m_prefix;
@@ -867,7 +912,7 @@ V3Options::V3Options() {
m_makeDepend = true;
m_makePhony = false;
m_outFormatOk = false;
m_pins64 = true;
m_pinsBv = 65;
m_profileCFuncs = false;
m_preprocOnly = false;
m_psl = false;
@@ -919,6 +964,27 @@ void V3Options::setDebugMode(int level) {
cout << "Starting "<<version()<<endl;
}
void V3Options::setDebugSrcLevel(const string& srcfile, int level) {
DebugSrcMap::iterator iter = m_debugSrcs.find(srcfile);
if (iter!=m_debugSrcs.end()) {
iter->second = level;
} else {
m_debugSrcs.insert(make_pair(srcfile,level));
}
}
int V3Options::debugSrcLevel(const string& srcfile_path, int default_level) {
// For simplicity, calling functions can just use __FILE__ for srcfile.
// That means though we need to cleanup the filename from ../Foo.cpp -> Foo
string srcfile = V3Options::filenameNonDirExt(srcfile_path);
DebugSrcMap::iterator iter = m_debugSrcs.find(srcfile);
if (iter!=m_debugSrcs.end()) {
return iter->second;
} else {
return default_level;
}
}
void V3Options::optimize(int level) {
// Set all optimizations to on/off
bool flag = level > 0;
+16 -4
View File
@@ -26,6 +26,7 @@
#include "verilatedos.h"
#include <string>
#include <vector>
#include <map>
#include <set>
#include "V3Global.h"
@@ -75,6 +76,9 @@ typedef vector<string> V3StringList;
typedef set<string> V3StringSet;
class V3Options {
// TYPES
typedef map<string,int> DebugSrcMap;
// MEMBERS (general options)
V3OptionsImp* m_impp; // Slow hidden options
@@ -82,6 +86,7 @@ class V3Options {
V3StringSet m_futures; // argument: -Wfuture- list
V3StringSet m_libraryFiles; // argument: Verilog -v files
V3StringList m_vFiles; // argument: Verilog files to read
DebugSrcMap m_debugSrcs; // argument: --debugi-<srcfile>=<level>
bool m_preprocOnly; // main switch: -E
bool m_makeDepend; // main switch: -MMD
@@ -99,7 +104,6 @@ class V3Options {
bool m_l2Name; // main switch: --l2name
bool m_lintOnly; // main switch: --lint-only
bool m_outFormatOk; // main switch: --cc, --sc or --sp was specified
bool m_pins64; // main switch: --pins64
bool m_profileCFuncs;// main switch: --profile-cfuncs
bool m_psl; // main switch: --psl
bool m_public; // main switch: --public
@@ -116,6 +120,7 @@ class V3Options {
int m_outputSplit; // main switch: --output-split
int m_outputSplitCFuncs;// main switch: --output-split-cfuncs
int m_outputSplitCTrace;// main switch: --output-split-ctrace
int m_pinsBv; // main switch: --pins-bv
int m_traceDepth; // main switch: --trace-depth
int m_unrollCount; // main switch: --unroll-count
int m_unrollStmts; // main switch: --unroll-stmts
@@ -163,13 +168,17 @@ class V3Options {
void coverage(bool flag) { m_coverageLine = m_coverageToggle = m_coverageUser = flag; }
bool onoff(const char* sw, const char* arg, bool& flag);
static bool wildmatchi(const char* s, const char* p);
static string getenvStr(const char* envvar, const char* defaultValue);
static string getenvStr(const string& envvar, const string& defaultValue);
static void setenvStr(const string& envvar, const string& value, const string& why);
static string getenvSYSTEMPERLGuts();
public:
// CREATORS
V3Options();
~V3Options();
void setDebugMode(int level);
void setDebugSrcLevel(const string& srcfile, int level);
int debugSrcLevel(const string& srcfile, int default_level=V3Error::debugDefault());
// METHODS
void addCppFile(const string& filename);
@@ -185,9 +194,11 @@ class V3Options {
string flags() const { return m_flags; }
bool systemC() const { return m_systemC; }
bool systemPerl() const { return m_systemPerl; }
bool usingSystemCLibs() const { return !lintOnly() && (systemPerl() || systemC()); }
bool usingSystemPerlLibs() const { return !lintOnly() && (systemPerl() || trace()); }
bool skipIdentical() const { return m_skipIdentical; }
bool stats() const { return m_stats; }
bool assertOn() const { return m_assert; } // assertOn as "assert" may be defined
bool assertOn() const { return m_assert; } // assertOn as __FILE__ may be defined
bool autoflush() const { return m_autoflush; }
bool coverage() const { return m_coverageLine || m_coverageToggle || m_coverageUser; }
bool coverageLine() const { return m_coverageLine; }
@@ -200,7 +211,6 @@ class V3Options {
bool traceDups() const { return m_traceDups; }
bool outFormatOk() const { return m_outFormatOk; }
bool keepTempFiles() const { return (V3Error::debugDefault()!=0); }
bool pins64() const { return m_pins64; }
bool profileCFuncs() const { return m_profileCFuncs; }
bool psl() const { return m_psl; }
bool allPublic() const { return m_public; }
@@ -214,6 +224,7 @@ class V3Options {
int outputSplit() const { return m_outputSplit; }
int outputSplitCFuncs() const { return m_outputSplitCFuncs; }
int outputSplitCTrace() const { return m_outputSplitCTrace; }
int pinsBv() const { return m_pinsBv; }
int traceDepth() const { return m_traceDepth; }
int unrollCount() const { return m_unrollCount; }
int unrollStmts() const { return m_unrollStmts; }
@@ -282,6 +293,7 @@ class V3Options {
static string getenvSYSTEMC();
static string getenvSYSTEMC_ARCH();
static string getenvSYSTEMPERL();
static string getenvSYSTEMPERL_INCLUDE();
static string getenvVERILATOR_ROOT();
static string getenvW() { return getenvStr("W",""); }
+8 -4
View File
@@ -121,10 +121,10 @@ class OrderMoveDomScope;
void OrderGraph::loopsVertexCb(V3GraphVertex* vertexp) {
if (debug()) cout<<"-Info-Loop: "<<vertexp<<" "<<endl;
if (OrderLogicVertex* vvertexp = dynamic_cast<OrderLogicVertex*>(vertexp)) {
cout<<V3Error::msgPrefix()<<" Example path: "<<vvertexp->nodep()->fileline()<<" "<<vvertexp->nodep()->typeName()<<endl;
cerr<<V3Error::msgPrefix()<<" Example path: "<<vvertexp->nodep()->fileline()<<" "<<vvertexp->nodep()->typeName()<<endl;
}
if (OrderVarVertex* vvertexp = dynamic_cast<OrderVarVertex*>(vertexp)) {
cout<<V3Error::msgPrefix()<<" Example path: "<<vvertexp->varScp()->fileline()<<" "<<vvertexp->varScp()->prettyName()<<endl;
cerr<<V3Error::msgPrefix()<<" Example path: "<<vvertexp->varScp()->fileline()<<" "<<vvertexp->varScp()->prettyName()<<endl;
}
};
@@ -254,8 +254,6 @@ private:
AstUser3InUse m_inuser3;
//AstUser4InUse m_inuser4; // Used only when building tree, so below
//int debug() { return 9; }
// STATE
OrderGraph m_graph; // Scoreboard of var usages/dependencies
SenTreeFinder m_finder; // Find global sentree's and add them
@@ -296,6 +294,12 @@ private:
enum VarUsage { VU_NONE=0, VU_CON=1, VU_GEN=2 };
// METHODS
static int debug() {
static int level = -1;
if (VL_UNLIKELY(level < 0)) level = v3Global.opt.debugSrcLevel(__FILE__);
return level;
}
void iterateNewStmt(AstNode* nodep) {
if (m_scopep) {
UINFO(4," STMT "<<nodep<<endl);
+7 -3
View File
@@ -70,9 +70,13 @@ private:
LongMap m_longMap; // Hash of very long names to unique identity number
int m_longId;
//int debug() { return 9; }
// METHODS
static int debug() {
static int level = -1;
if (VL_UNLIKELY(level < 0)) level = v3Global.opt.debugSrcLevel(__FILE__);
return level;
}
void makeSmallNames(AstModule* modp) {
vector<int> usedLetter; usedLetter.resize(256);
// Pass 1, assign first letter to each gparam's name
@@ -229,7 +233,7 @@ public:
void ParamVisitor::visit(AstCell* nodep, AstNUser*) {
// Cell: Check for parameters in the instantiation.
if (!nodep->modp()) { nodep->dumpTree(cout,"error:"); nodep->v3fatalSrc("Not linked?"); }
if (!nodep->modp()) { nodep->dumpTree(cerr,"error:"); nodep->v3fatalSrc("Not linked?"); }
if (nodep->paramsp()) {
UINFO(4,"De-parameterize: "<<nodep<<endl);
// Create new module name with _'s between the constants
+6 -2
View File
@@ -43,11 +43,15 @@ protected:
static V3PreShellImp s_preImp;
static V3PreProc* s_preprocp;
//int debug() { return 9; }
//---------------------------------------
// METHODS
static int debug() {
static int level = -1;
if (VL_UNLIKELY(level < 0)) level = v3Global.opt.debugSrcLevel(__FILE__);
return level;
}
void boot(char** env) {
// Create the implementation pointer
if (env) {}
+6 -2
View File
@@ -60,9 +60,13 @@ private:
AstTraceInc* m_inTracep; // Inside while loop, special statement additions
bool m_assignLhs; // Inside assignment lhs, don't breakup extracts
//int debug() { return 9; }
// METHODS
static int debug() {
static int level = -1;
if (VL_UNLIKELY(level < 0)) level = v3Global.opt.debugSrcLevel(__FILE__);
return level;
}
bool assignNoTemp(AstNodeAssign* nodep) {
return (nodep->lhsp()->castVarRef()
&& !nodep->lhsp()->castVarRef()->varp()->isSc()
+2
View File
@@ -51,6 +51,8 @@ class V3Read {
deque<V3Number*> m_numberps; // Created numbers for later cleanup
deque<FileLine> m_lintState; // Current lint state for save/restore
deque<string> m_ppBuffers; // Preprocessor->lex buffer of characters to process
// Options isn't visible, so not using debugSrcLevel
//int debug() { return 9; }
protected:
+12 -3
View File
@@ -56,7 +56,12 @@ private:
AstCell* m_aboveCellp; // Cell that instantiates this module
AstScope* m_aboveScopep; // Scope that instantiates this scope
//int debug() { return 9; }
// METHODS
static int debug() {
static int level = -1;
if (VL_UNLIKELY(level < 0)) level = v3Global.opt.debugSrcLevel(__FILE__);
return level;
}
// VISITORS
virtual void visit(AstNetlist* nodep, AstNUser*) {
@@ -250,9 +255,13 @@ private:
// STATE
AstScope* m_scopep; // Current scope we are building
//int debug() { return 9; }
// METHODS
static int debug() {
static int level = -1;
if (VL_UNLIKELY(level < 0)) level = v3Global.opt.debugSrcLevel(__FILE__);
return level;
}
// VISITORS
virtual void visit(AstScope* nodep, AstNUser*) {
// Want to ignore blocks under it
+7 -1
View File
@@ -55,8 +55,14 @@ private:
// STATE
AstTopScope* m_topscopep; // Top scope to add statement to
vector<AstSenTree*> m_treesp; // List of sensitive blocks, for folding
//int debug() { return 9; }
// VISITORS
static int debug() {
static int level = -1;
if (VL_UNLIKELY(level < 0)) level = v3Global.opt.debugSrcLevel(__FILE__);
return level;
}
virtual void visit(AstModule* nodep, AstNUser*) {
// Only do the top
if (nodep->isTop()) {
+6 -2
View File
@@ -235,9 +235,13 @@ private:
uint32_t m_stepNum; // Step number we need to ignore a edge in
V3Double0 m_statSplits; // Statistic tracking
//int debug() { return 9; }
// METHODS
static int debug() {
static int level = -1;
if (VL_UNLIKELY(level < 0)) level = v3Global.opt.debugSrcLevel(__FILE__);
return level;
}
void scoreboardClear() {
//VV***** We reset user1p() and user2p on each block!!!
m_inDly = false;
+5 -1
View File
@@ -44,7 +44,11 @@
class SplitAsBaseVisitor : public AstNVisitor {
public:
// METHODS
//int debug() { return 9; }
static int debug() {
static int level = -1;
if (VL_UNLIKELY(level < 0)) level = v3Global.opt.debugSrcLevel(__FILE__);
return level;
}
};
//######################################################################
+6 -2
View File
@@ -45,8 +45,11 @@
class SubstBaseVisitor : public AstNVisitor {
public:
static int debug() { return V3Error::debugDefault(); }
// static int debug() { return 9; }
static int debug() {
static int level = -1;
if (VL_UNLIKELY(level < 0)) level = v3Global.opt.debugSrcLevel(__FILE__);
return level;
}
};
//######################################################################
@@ -80,6 +83,7 @@ class SubstVarEntry {
SubstVarWord m_whole; // Data for whole vector used at once
vector<SubstVarWord> m_words; // Data for every word, if multi word variable
int debug() { return SubstBaseVisitor::debug(); }
public:
// CONSTRUCTORS
SubstVarEntry (AstVar* varp) { // Construction for when a var is used
+10 -2
View File
@@ -1,3 +1,4 @@
// -*- C++ -*-
//*************************************************************************
// DESCRIPTION: Verilator: Symbol table
//
@@ -55,13 +56,20 @@ class V3SymTable : public AstNUser {
m_idNameMap.insert(make_pair(name, nodep));
}
}
AstNode* findIdName(const string& name) {
AstNode* findIdFlat(const string& name) {
// Find identifier without looking upward through symbol hierarchy
//UINFO(9, " SymFind "<<this<<" '"<<name<<"' "<<endl);
// First, scan this begin/end block or module for the name
IdNameMap::iterator iter = m_idNameMap.find(name);
if (iter != m_idNameMap.end()) return (iter->second);
return NULL;
}
AstNode* findIdUpward(const string& name) {
// Find identifier looking upward through symbol hierarchy
// First, scan this begin/end block or module for the name
if (AstNode* nodep = findIdFlat(name)) return nodep;
// Then scan the upper begin/end block or module for the name
if (m_upperp) return m_upperp->findIdName(name);
if (m_upperp) return m_upperp->findIdUpward(name);
return NULL;
}
};
+5 -2
View File
@@ -54,8 +54,11 @@ class TableVisitor;
class TableBaseVisitor : public AstNVisitor {
public:
// Note level 8&9 include debugging each simulation value
// int debug() { return 7; }
// int debug() { return 9; }
static int debug() {
static int level = -1;
if (VL_UNLIKELY(level < 0)) level = v3Global.opt.debugSrcLevel(__FILE__);
return level;
}
};
//######################################################################
+6 -1
View File
@@ -314,9 +314,14 @@ private:
InsertMode m_insMode; // How to insert
AstNode* m_insStmtp; // Where to insert statement
int m_modNCalls; // Incrementing func # for making symbols
//int debug() { return 9; }
// METHODS
static int debug() {
static int level = -1;
if (VL_UNLIKELY(level < 0)) level = v3Global.opt.debugSrcLevel(__FILE__);
return level;
}
AstVarScope* createVarScope(AstVar* invarp, const string& name) {
// We could create under either the ref's scope or the ftask's scope.
// It shouldn't matter, as they are only local variables.
+6 -2
View File
@@ -189,9 +189,13 @@ private:
V3Double0 m_statUniqSigs; // Statistic tracking
V3Double0 m_statUniqCodes;// Statistic tracking
//int debug() { return 9; }
// METHODS
static int debug() {
static int level = -1;
if (VL_UNLIKELY(level < 0)) level = v3Global.opt.debugSrcLevel(__FILE__);
return level;
}
void detectDuplicates() {
UINFO(9,"Finding duplicates\n");
// Note uses user4
+6 -1
View File
@@ -54,9 +54,14 @@ private:
V3Double0 m_statSigs; // Statistic tracking
V3Double0 m_statIgnSigs; // Statistic tracking
//int debug() { return 9; }
// METHODS
static int debug() {
static int level = -1;
if (VL_UNLIKELY(level < 0)) level = v3Global.opt.debugSrcLevel(__FILE__);
return level;
}
const char* varIgnoreTrace(AstVar* nodep) {
// Return true if this shouldn't be traced
// See also similar rule in V3Coverage::varIgnoreToggle
+5 -1
View File
@@ -68,7 +68,11 @@ typedef std::map<AstVar*, RefVec*> VarMap;
class TristateBaseVisitor : public AstNVisitor {
public:
//int debug() { return 9; }
static int debug() {
static int level = -1;
if (VL_UNLIKELY(level < 0)) level = v3Global.opt.debugSrcLevel(__FILE__);
return level;
}
};
//######################################################################
+6 -1
View File
@@ -58,7 +58,12 @@ private:
bool m_constXCvt; // Convert X's
V3Double0 m_statUnkVars; // Statistic tracking
//int debug() { return 9; }
// METHODS
static int debug() {
static int level = -1;
if (VL_UNLIKELY(level < 0)) level = v3Global.opt.debugSrcLevel(__FILE__);
return level;
}
// VISITORS
virtual void visit(AstModule* nodep, AstNUser*) {
+7 -2
View File
@@ -59,7 +59,12 @@ private:
V3Double0 m_statLoops; // Statistic tracking
V3Double0 m_statIters; // Statistic tracking
//int debug() { return 9; }
// METHODS
static int debug() {
static int level = -1;
if (VL_UNLIKELY(level < 0)) level = v3Global.opt.debugSrcLevel(__FILE__);
return level;
}
// VISITORS
virtual void visit(AstModule* nodep, AstNUser*) {
@@ -339,7 +344,7 @@ private:
if (m_generate) { // Ignore for's when expanding genfor's
nodep->iterateChildren(*this);
} else {
nodep->v3error("V3Task should have removed standard FORs");
nodep->v3error("V3Begin should have removed standard FORs");
}
}
+18 -11
View File
@@ -81,15 +81,18 @@ private:
AstRange* m_cellRangep; // Range for arrayed instantiations, NULL for normal instantiations
AstNodeCase* m_casep; // Current case statement CaseItem is under
//int debug() { return 9; }
// CLASSES
#define ANYSIZE 0
// METHODS
// Naming: width_{output size rule}_{lhs rule}_{rhs rule}
static int debug() {
static int level = -1;
if (VL_UNLIKELY(level < 0)) level = v3Global.opt.debugSrcLevel(__FILE__);
return level;
}
// VISITORS
// Naming: width_{output size rule}_{lhs rule}_{rhs rule}
// Widths: 1 bit out, lhs 1 bit
void width_O1_L1(AstNode* nodep, AstNUser* vup);
virtual void visit(AstLogNot* nodep, AstNUser* vup) { width_O1_L1(nodep,vup); }
@@ -476,9 +479,9 @@ private:
nodep->sensesp()->iterateAndNext(*this);
if (nodep->disablep()) {
nodep->disablep()->iterateAndNext(*this,WidthVP(1,1,BOTH).p());
widthCheckReduce(nodep,"Disable",nodep->disablep(),1,1); // it's like a if() condition.
widthCheckReduce(nodep,"Disable",nodep->disablep(),1,1); // it's like an if() condition.
}
widthCheckReduce(nodep,"Property",nodep->propp(),1,1); // it's like a if() condition.
widthCheckReduce(nodep,"Property",nodep->propp(),1,1); // it's like an if() condition.
nodep->width(1,1);
}
@@ -533,14 +536,18 @@ private:
nodep->condp()->iterateAndNext(*this,WidthVP(1,1,BOTH).p());
if (!nodep->castGenFor()) nodep->bodysp()->iterateAndNext(*this);
nodep->incsp()->iterateAndNext(*this);
widthCheckReduce(nodep,"For Test Condition",nodep->condp(),1,1); // it's like a if() condition.
widthCheckReduce(nodep,"For Test Condition",nodep->condp(),1,1); // it's like an if() condition.
}
virtual void visit(AstRepeat* nodep, AstNUser*) {
nodep->countp()->iterateAndNext(*this,WidthVP(ANYSIZE,0,BOTH).p());
nodep->bodysp()->iterateAndNext(*this);
}
virtual void visit(AstWhile* nodep, AstNUser*) {
// TOP LEVEL NODE
nodep->precondsp()->iterateAndNext(*this);
nodep->condp()->iterateAndNext(*this,WidthVP(1,1,BOTH).p());
nodep->bodysp()->iterateAndNext(*this);
widthCheckReduce(nodep,"For Test Condition",nodep->condp(),1,1); // it's like a if() condition.
widthCheckReduce(nodep,"For Test Condition",nodep->condp(),1,1); // it's like an if() condition.
}
virtual void visit(AstNodeIf* nodep, AstNUser*) {
// TOP LEVEL NODE
@@ -550,7 +557,7 @@ private:
nodep->elsesp()->iterateAndNext(*this);
}
nodep->condp()->iterateAndNext(*this,WidthVP(1,1,BOTH).p());
widthCheckReduce(nodep,"If",nodep->condp(),1,1); // it's like a if() condition.
widthCheckReduce(nodep,"If",nodep->condp(),1,1); // it's like an if() condition.
//if (debug()) nodep->dumpTree(cout," IfPos: ");
}
virtual void visit(AstNodeAssign* nodep, AstNUser*) {
@@ -651,19 +658,19 @@ private:
// TOP LEVEL NODE
nodep->propp()->iterateAndNext(*this,WidthVP(1,1,BOTH).p());
nodep->stmtsp()->iterateChildren(*this,WidthVP(ANYSIZE,0,BOTH).p());
widthCheckReduce(nodep,"Property",nodep->propp(),1,1); // it's like a if() condition.
widthCheckReduce(nodep,"Property",nodep->propp(),1,1); // it's like an if() condition.
}
virtual void visit(AstPslAssert* nodep, AstNUser*) {
// TOP LEVEL NODE
nodep->propp()->iterateAndNext(*this,WidthVP(1,1,BOTH).p());
widthCheckReduce(nodep,"Property",nodep->propp(),1,1); // it's like a if() condition.
widthCheckReduce(nodep,"Property",nodep->propp(),1,1); // it's like an if() condition.
}
virtual void visit(AstVAssert* nodep, AstNUser*) {
// TOP LEVEL NODE
nodep->propp()->iterateAndNext(*this,WidthVP(1,1,BOTH).p());
nodep->passsp()->iterateAndNext(*this);
nodep->failsp()->iterateAndNext(*this);
widthCheckReduce(nodep,"Property",nodep->propp(),1,1); // it's like a if() condition.
widthCheckReduce(nodep,"Property",nodep->propp(),1,1); // it's like an if() condition.
}
virtual void visit(AstPin* nodep, AstNUser*) {
//if (debug()) nodep->dumpTree(cout,"- PinPre: ");
+1
View File
@@ -538,6 +538,7 @@ int main(int argc, char** argv, char** env) {
V3Options::getenvSYSTEMC();
V3Options::getenvSYSTEMC_ARCH();
V3Options::getenvSYSTEMPERL();
V3Options::getenvSYSTEMPERL_INCLUDE();
V3Error::abortIfErrors();
+52 -10
View File
@@ -9,7 +9,7 @@ use Pod::Usage;
use strict;
use vars qw ($Debug $VERSION);
$VERSION = '3.035';
$VERSION = '3.101';
#======================================================================
# main
@@ -45,8 +45,8 @@ if (! GetOptions (
die "%Error: Bad usage, try 'bisonpre --help'\n";
}
$Opt_Input or die "bisonpp: %Error: input file not specified\n";
$Opt_Output or die "bisonpp: %Error: --o option is required\n";
$Opt_Input or die "bisonpre: %Error: input file not specified\n";
$Opt_Output or die "bisonpre: %Error: --o option is required\n";
process();
@@ -63,7 +63,7 @@ sub parameter {
if (!defined $Opt_Input) {
$Opt_Input = $param;
} else {
die "bisonpp: %Error: Unknown parameter: $param\n";
die "bisonpre: %Error: Unknown parameter: $param\n";
}
}
@@ -91,7 +91,7 @@ sub process {
if ($status != 0) {
remove_outputs();
my $v = bison_version_check();
die "bisonpp: %Error: $Opt_Yacc version $v run failed due to errors\n";
die "bisonpre: %Error: $Opt_Yacc version $v run failed due to errors\n";
}
clean_output(tmp_prefix().".output",output_prefix().".output");
@@ -133,10 +133,10 @@ sub bison_version_check {
my $v = `$Opt_Yacc --version`;
if ($v && $v =~ /([0-9]+\.[0-9]+)/) {
my $v = $1;
($v >= 1.875) or die "bisonpp: %Error: '$Opt_Yacc' is version $v; version 1.875 or newer is required\n";
($v >= 1.875) or die "bisonpre: %Error: '$Opt_Yacc' is version $v; version 1.875 or newer is required\n";
return $v;
} else {
die "bisonpp: %Error: '$Opt_Yacc' is not installed, or not working\n";
die "bisonpre: %Error: '$Opt_Yacc' is not installed, or not working\n";
}
}
@@ -188,12 +188,50 @@ sub clean_input {
my @lines = $fh->getlines;
$fh->close;
# Find "rule<type>:"
# Find "%tokens<type>:"
my %tokens;
foreach my $line (@lines) {
if ($line =~ /^%token\s*<(\S+)>\s*(\S+)/) {
$tokens{$2} = $1;
}
}
# Replace BISONPRE_NOT(type,...) with expanded list
{
my @linesin = @lines; @lines=(); my $l=0;
foreach my $line (@linesin) {
if ($line =~ /BISONPRE_NOT/) {
($line =~ s/BISONPRE_NOT\((\S+)\)\s*({[^}]+})\s*$//)
or die "%Error: $filename:$l: Bad form of BISONPRE_NOT: $line\n";
my $endtok = $1; my $action = $2;
my @endtoks = split (/,/, $endtok);
map { $tokens{$_} or die "%Error: $filename:$l: Can't find definition for token: $_\n"
} @endtoks;
# Push it all onto one line to avoid error messages changing
my $bar = "";
tok:
foreach my $tok (sort keys %tokens) {
foreach (@endtoks) {
next tok if $tok eq $_;
}
if ($endtok ne $tok) {
$line .= "\t$bar $tok $action";
$bar = "|";
}
}
$line .= "\n";
}
push @lines, $line;
}
}
# Find "rule<type>:" and replace with just "rule:"
my %types;
{
my @linesin = @lines; @lines=(); my $l=0;
foreach my $line (@linesin) {
if ($line =~ s/^(\S+)<(\S+)>:/$1:/) {
# ^/ to prevent comments from matching
if ($line =~ s/^([^<\/ \t\n]+)<(\S+)>:/$1:/) {
$types{$2}{$1} = 1;
}
push @lines, $line;
@@ -268,7 +306,11 @@ This is expanded into %type declarations.
=item rule_label<type>:
This allows the label declaring a rule to also specify the type of the
rule. The type will be inserted where /*BISONPP_TYPES*/ is encountered.
rule. The type will be inserted where /*BISONPRE_TYPES*/ is encountered.
=item BISONPRE_NOT(token[, token...])
Create a rule that matches every token except for those specified.
=back
+4 -1
View File
@@ -24,7 +24,7 @@
//**********************************************************************
//**** Version and host name
#define DTVERSION "Verilator 3.700 2009/01/08"
#define DTVERSION "Verilator 3.702 2009/03/28"
//**********************************************************************
//**** Functions
@@ -73,6 +73,9 @@
#ifndef DEFENV_SYSTEMPERL
# define DEFENV_SYSTEMPERL ""
#endif
#ifndef DEFENV_SYSTEMPERL_INCLUDE
# define DEFENV_SYSTEMPERL_INCLUDE ""
#endif
#ifndef DEFENV_VERILATOR_ROOT
# define DEFENV_VERILATOR_ROOT ""
#endif
+2 -2
View File
@@ -199,6 +199,7 @@ escid \\[^ \t\f\r\n]+
"endspecify" {yylval.fileline = CRELINE(); return yENDSPECIFY;}
"endtask" {yylval.fileline = CRELINE(); return yENDTASK;}
"for" {yylval.fileline = CRELINE(); return yFOR;}
"forever" {yylval.fileline = CRELINE(); return yFOREVER;}
"function" {yylval.fileline = CRELINE(); return yFUNCTION;}
"if" {yylval.fileline = CRELINE(); return yIF;}
"initial" {yylval.fileline = CRELINE(); return yINITIAL;}
@@ -220,6 +221,7 @@ escid \\[^ \t\f\r\n]+
"pulldown" {yylval.fileline = CRELINE(); return yPULLDOWN;}
"pullup" {yylval.fileline = CRELINE(); return yPULLUP;}
"reg" {yylval.fileline = CRELINE(); return yREG;}
"repeat" {yylval.fileline = CRELINE(); return yREPEAT;}
"scalared" {yylval.fileline = CRELINE(); return ySCALARED;}
"specify" {yylval.fileline = CRELINE(); return ySPECIFY;}
"specparam" {yylval.fileline = CRELINE(); return yaTIMINGSPEC;}
@@ -252,7 +254,6 @@ escid \\[^ \t\f\r\n]+
"endtable" {yyerrorf("Unsupported: Verilog 1995 reserved word not implemented: %s",yytext);}
"event" {yyerrorf("Unsupported: Verilog 1995 reserved word not implemented: %s",yytext);}
"force" {yyerrorf("Unsupported: Verilog 1995 reserved word not implemented: %s",yytext);}
"forever" {yyerrorf("Unsupported: Verilog 1995 reserved word not implemented: %s",yytext);}
"fork" {yyerrorf("Unsupported: Verilog 1995 reserved word not implemented: %s",yytext);}
"highz0" {yyerrorf("Unsupported: Verilog 1995 reserved word not implemented: %s",yytext);}
"highz1" {yyerrorf("Unsupported: Verilog 1995 reserved word not implemented: %s",yytext);}
@@ -268,7 +269,6 @@ escid \\[^ \t\f\r\n]+
"real" {yyerrorf("Unsupported: Verilog 1995 reserved word not implemented: %s",yytext);}
"realtime" {yyerrorf("Unsupported: Verilog 1995 reserved word not implemented: %s",yytext);}
"release" {yyerrorf("Unsupported: Verilog 1995 reserved word not implemented: %s",yytext);}
"repeat" {yyerrorf("Unsupported: Verilog 1995 reserved word not implemented: %s",yytext);}
"rnmos" {yyerrorf("Unsupported: Verilog 1995 reserved word not implemented: %s",yytext);}
"rpmos" {yyerrorf("Unsupported: Verilog 1995 reserved word not implemented: %s",yytext);}
"rtran" {yyerrorf("Unsupported: Verilog 1995 reserved word not implemented: %s",yytext);}
+286 -271
View File
@@ -129,9 +129,13 @@ class AstSenTree;
AstVarRef* varrefp;
}
// When writing Bison patterns we use yTOKEN instead of "token",
// so Bison will error out on unknown "token"s.
// Generic lexer tokens, for example a number
// IEEE: real_number
%token<cdouble> yaFLOATNUM "FLOATING-POINT NUMBER"
// IEEE: identifier, class_identifier, class_variable_identifier,
// covergroup_variable_identifier, dynamic_array_variable_identifier,
// enum_identifier, interface_identifier, interface_instance_identifier,
@@ -153,6 +157,33 @@ class AstSenTree;
%token<strp> yaSCCTOR "`systemc_implementation BLOCK"
%token<strp> yaSCDTOR "`systemc_imp_header BLOCK"
%token<fileline> '!'
%token<fileline> '#'
%token<fileline> '%'
%token<fileline> '&'
%token<fileline> '('
%token<fileline> ')'
%token<fileline> '*'
%token<fileline> '+'
%token<fileline> ','
%token<fileline> '-'
%token<fileline> '.'
%token<fileline> '/'
%token<fileline> ':'
%token<fileline> ';'
%token<fileline> '<'
%token<fileline> '='
%token<fileline> '>'
%token<fileline> '?'
%token<fileline> '@'
%token<fileline> '['
%token<fileline> ']'
%token<fileline> '^'
%token<fileline> '{'
%token<fileline> '|'
%token<fileline> '}'
%token<fileline> '~'
// Specific keywords
// yKEYWORD means match "keyword"
// Other cases are yXX_KEYWORD where XX makes it unique,
@@ -187,6 +218,7 @@ class AstSenTree;
%token<fileline> yENDTASK "endtask"
%token<fileline> yFINAL "final"
%token<fileline> yFOR "for"
%token<fileline> yFOREVER "forever"
%token<fileline> yFUNCTION "function"
%token<fileline> yGENERATE "generate"
%token<fileline> yGENVAR "genvar"
@@ -213,6 +245,7 @@ class AstSenTree;
%token<fileline> yPULLDOWN "pulldown"
%token<fileline> yPULLUP "pullup"
%token<fileline> yREG "reg"
%token<fileline> yREPEAT "repeat"
%token<fileline> ySCALARED "scalared"
%token<fileline> ySIGNED "signed"
%token<fileline> ySPECIFY "specify"
@@ -335,37 +368,9 @@ class AstSenTree;
%token<fileline> yPSL_KET "}"
%token<fileline> yP_LOGIFF
%token<fileline> '!'
%token<fileline> '#'
%token<fileline> '%'
%token<fileline> '&'
%token<fileline> '('
%token<fileline> ')'
%token<fileline> '*'
%token<fileline> '+'
%token<fileline> ','
%token<fileline> '-'
%token<fileline> '.'
%token<fileline> '/'
%token<fileline> ':'
%token<fileline> ';'
%token<fileline> '<'
%token<fileline> '='
%token<fileline> '>'
%token<fileline> '?'
%token<fileline> '@'
%token<fileline> '['
%token<fileline> ']'
%token<fileline> '^'
%token<fileline> '{'
%token<fileline> '|'
%token<fileline> '}'
%token<fileline> '~'
// [* is not a operator, as "[ * ]" is legal
// [= and [-> could be repitition operators, but to match [* we don't add them.
// '( is not a operator, as "' (" is legal
// '{ could be an operator. More research needed.
//********************
// PSL op precedence
@@ -374,13 +379,11 @@ class AstSenTree;
%left<fileline> prPSLCLK
// Verilog op precedence
%left ':'
%left '?'
%right '?' ':'
%left yP_OROR
%left yP_ANDAND
%left '|' yP_NOR
%left '^'
%left yP_XNOR
%left '^' yP_XNOR
%left '&' yP_NAND
%left yP_EQUAL yP_NOTEQUAL yP_CASEEQUAL yP_CASENOTEQUAL yP_WILDEQUAL yP_WILDNOTEQUAL
%left '>' '<' yP_GTE yP_LTE
@@ -388,18 +391,11 @@ class AstSenTree;
%left '+' '-'
%left '*' '/' '%'
%left yP_POW
%left '{' '}'
%left<fileline> prUNARYARITH
%left<fileline> prREDUCTION
%left<fileline> prNEGATION
%left prUNARYARITH prREDUCTION prNEGATION
%nonassoc prLOWER_THAN_ELSE
%nonassoc yELSE
// Types are in same order as declarations.
// Naming:
// Trailing E indicates this type may have empty match
//BISONPRE_TYPES
// Blank lines for type insertion
// Blank lines for type insertion
@@ -419,63 +415,77 @@ class AstSenTree;
// Blank lines for type insertion
// Blank lines for type insertion
%start fileE
%start source_text
%%
//**********************************************************************
// Feedback to the Lexer
// Note we read a parenthesis ahead, so this may not change the lexer at the right point.
stateExitPsl: /* empty */ { V3Read::stateExitPsl(); }
stateExitPsl: // For PSL lexing, return from PSL state
/* empty */ { V3Read::stateExitPsl(); }
;
statePushVlg: /* empty */ { V3Read::statePushVlg(); }
statePushVlg: // For PSL lexing, escape current state into Verilog state
/* empty */ { V3Read::statePushVlg(); }
;
statePop: /* empty */ { V3Read::statePop(); }
statePop: // Return to previous lexing state
/* empty */ { V3Read::statePop(); }
;
//**********************************************************************
// Files
fileE: /* empty */ { }
| timeunitsDeclE file { }
source_text: // ==IEEE: source_text
/* empty */ { }
| timeunits_declarationE descriptionList { }
;
file: description { }
| file description { }
descriptionList: // IEEE: part of source_text
description { }
| descriptionList description { }
;
// IEEE: description
description: moduleDecl { }
description: // ==IEEE: description
module_declaration { }
// | interface_declaration { }
// | program_declaration { }
// | package_declaration { }
// | package_item { }
// | bind_directive { }
// unsupported // IEEE: config_declaration
| error { }
;
// IEEE: timeunits_declaration + empty
timeunitsDeclE: /*empty*/ { }
| yTIMEUNIT yaTIMENUM ';' { }
timeunits_declarationE: // IEEE: timeunits_declaration + empty
/*empty*/ { }
| yTIMEUNIT yaTIMENUM ';' { }
| yTIMEPRECISION yaTIMENUM ';' { }
| yTIMEUNIT yaTIMENUM ';' yTIMEPRECISION yaTIMENUM ';' { }
| yTIMEPRECISION yaTIMENUM ';' yTIMEUNIT yaTIMENUM ';' { }
| yTIMEUNIT yaTIMENUM ';' yTIMEPRECISION yaTIMENUM ';' { }
| yTIMEPRECISION yaTIMENUM ';' yTIMEUNIT yaTIMENUM ';' { }
;
//**********************************************************************
// Module headers
// IEEE: module_declaration:
moduleDecl: modHeader timeunitsDeclE modItemListE yENDMODULE endLabelE
module_declaration: // ==IEEE: module_declaration (incomplete)
modHeader timeunits_declarationE module_itemListE yENDMODULE endLabelE
{ if ($3) $1->addStmtp($3); }
;
modHeader<modulep>:
modHdr modParE modPortsE ';'
modHeader<modulep>: // IEEE: module_nonansi_header + module_ansi_header
modHdr parameter_port_listE modPortsStarE ';'
{ $1->modTrace(v3Global.opt.trace() && $1->fileline()->tracingOn()); // Stash for implicit wires, etc
if ($2) $1->addStmtp($2); if ($3) $1->addStmtp($3); }
;
modHdr<modulep>:
yMODULE yaID { $$ = new AstModule($1,*$2); $$->inLibrary(V3Read::inLibrary()||V3Read::inCellDefine());
$$->modTrace(v3Global.opt.trace());
V3Read::rootp()->addModulep($$); }
yMODULE lifetimeE yaID
{ $$ = new AstModule($1,*$3); $$->inLibrary(V3Read::inLibrary()||V3Read::inCellDefine());
$$->modTrace(v3Global.opt.trace());
V3Read::rootp()->addModulep($$); }
;
modParE<nodep>:
parameter_port_listE<nodep>: // IEEE: parameter_port_list + empty == parameter_value_assignment
/* empty */ { $$ = NULL; }
| '#' '(' ')' { $$ = NULL; }
| '#' '(' modParArgs ')' { $$ = $3; }
@@ -497,7 +507,7 @@ modParSecond<nodep>:
| param { $$ = $1; }
;
modPortsE<nodep>:
modPortsStarE<nodep>:
/* empty */ { $$ = NULL; }
| '(' ')' { $$ = NULL; }
| '(' {V3Parse::s_pinNum=1;} portList ')' { $$ = $3; }
@@ -553,19 +563,18 @@ regsigList<varp>:
;
portV2kDecl<nodep>:
varRESET portDirection v2kVarDeclE signingE regrangeE portV2kInit { $$ = $6; }
varRESET port_direction v2kVarDeclE signingE regrangeE portV2kInit { $$ = $6; }
;
// IEEE: port_declaration - plus ';'
portDecl<nodep>:
varRESET portDirection v2kVarDeclE signingE regrangeE regsigList ';' { $$ = $6; }
portDecl<nodep>: // IEEE: port_declaration - plus ';'
varRESET port_direction v2kVarDeclE signingE regrangeE regsigList ';' { $$ = $6; }
;
varDecl<nodep>:
varRESET varReg signingE regrangeE regsigList ';' { $$ = $5; }
| varRESET varGParam signingE regrangeE paramList ';' { $$ = $5; }
| varRESET varLParam signingE regrangeE paramList ';' { $$ = $5; }
| varRESET varNet signingE delayrange netSigList ';' { $$ = $5; }
| varRESET net_type signingE delayrange netSigList ';' { $$ = $5; }
| varRESET varGenVar signingE regsigList ';' { $$ = $4; }
;
@@ -573,10 +582,12 @@ modParDecl<nodep>:
varRESET varGParam signingE regrangeE param { $$ = $5; }
;
varRESET: /* empty */ { VARRESET(); }
varRESET:
/* empty */ { VARRESET(); }
;
varNet: ySUPPLY0 { VARDECL(SUPPLY0); }
net_type: // ==IEEE: net_type
ySUPPLY0 { VARDECL(SUPPLY0); }
| ySUPPLY1 { VARDECL(SUPPLY1); }
| yWIRE { VARDECL(WIRE); }
| yTRI { VARDECL(TRIWIRE); }
@@ -591,40 +602,44 @@ varReg: yREG { VARDECL(REG); }
| yINTEGER { VARDECL(INTEGER); }
;
//IEEE: port_direction
portDirection: yINPUT { VARIO(INPUT); }
port_direction: // ==IEEE: port_direction
yINPUT { VARIO(INPUT); }
| yOUTPUT { VARIO(OUTPUT); }
| yINOUT { VARIO(INOUT); }
// | yREF { VARIO(REF); }
;
// IEEE: signing - plus empty
signingE: /*empty*/ { }
signingE: // IEEE: signing - plus empty
/*empty*/ { }
| ySIGNED { VARSIGNED(true); }
| yUNSIGNED { VARSIGNED(false); }
;
v2kVarDeclE: /*empty*/ { }
| varNet { }
v2kVarDeclE:
/*empty*/ { }
| net_type { }
| varReg { }
;
//************************************************
// Module Items
modItemListE<nodep>:
module_itemListE<nodep>: // IEEE: Part of module_declaration
/* empty */ { $$ = NULL; }
| modItemList { $$ = $1; }
| module_itemList { $$ = $1; }
;
modItemList<nodep>:
modItem { $$ = $1; }
| modItemList modItem { $$ = $1->addNextNull($2); }
module_itemList<nodep>: // IEEE: Part of module_declaration
module_item { $$ = $1; }
| module_itemList module_item { $$ = $1->addNextNull($2); }
;
modItem<nodep>:
modOrGenItem { $$ = $1; }
| generateRegion { $$ = $1; }
module_item<nodep>: // ==IEEE: module_item
// // IEEE: non_port_module_item
generate_region { $$ = $1; }
| module_or_generate_item { $$ = $1; }
| specify_block { $$ = $1; }
// // Verilator specific
| yaSCHDR { $$ = new AstScHdr(CRELINE(),*$1); }
| yaSCINT { $$ = new AstScInt(CRELINE(),*$1); }
| yaSCIMP { $$ = new AstScImp(CRELINE(),*$1); }
@@ -634,38 +649,49 @@ modItem<nodep>:
| yVL_INLINE_MODULE { $$ = new AstPragma($1,AstPragmaType::INLINE_MODULE); }
| yVL_NO_INLINE_MODULE { $$ = new AstPragma($1,AstPragmaType::NO_INLINE_MODULE); }
| yVL_PUBLIC_MODULE { $$ = new AstPragma($1,AstPragmaType::PUBLIC_MODULE); }
| ySPECIFY specifyJunkList yENDSPECIFY { $$ = NULL; }
| ySPECIFY yENDSPECIFY { $$ = NULL; }
;
// IEEE: generate_region
generateRegion<nodep>:
generate_region<nodep>: // ==IEEE: generate_region
yGENERATE genTopBlock yENDGENERATE { $$ = new AstGenerate($1, $2); }
;
modOrGenItem<nodep>:
yALWAYS eventControlE stmtBlock { $$ = new AstAlways($1,$2,$3); }
| yFINAL stmtBlock { $$ = new AstFinal($1,$2); }
| yINITIAL stmtBlock { $$ = new AstInitial($1,$2); }
| yASSIGN delayE assignList ';' { $$ = $3; }
| yDEFPARAM defpList ';' { $$ = $2; }
// IEEE: module_or_generate_item + module_common_item + parameter_override
module_or_generate_item<nodep>:
// // IEEE: always_construct
yALWAYS event_controlE stmtBlock { $$ = new AstAlways($1,$2,$3); }
| continuous_assign { $$ = $1; }
| initial_construct { $$ = $1; }
| final_construct { $$ = $1; }
| yDEFPARAM list_of_defparam_assignments ';' { $$ = $2; }
| instDecl { $$ = $1; }
| taskDecl { $$ = $1; }
| funcDecl { $$ = $1; }
| task_declaration { $$ = $1; }
| function_declaration { $$ = $1; }
| gateDecl { $$ = $1; }
| portDecl { $$ = $1; }
| varDecl { $$ = $1; }
//No: | tableDecl // Unsupported
| pslStmt { $$ = $1; }
| concurrent_assertion_item { $$ = $1; } // IEEE puts in modItem; seems silly
| concurrent_assertion_item { $$ = $1; } // IEEE puts in module_item; seems silly
| clocking_declaration { $$ = $1; }
;
continuous_assign<nodep>: // IEEE: continuous_assign
yASSIGN delayE assignList ';' { $$ = $3; }
;
initial_construct<nodep>: // IEEE: initial_construct
yINITIAL stmtBlock { $$ = new AstInitial($1,$2); }
;
final_construct<nodep>: // IEEE: final_construct
yFINAL stmtBlock { $$ = new AstFinal($1,$2); }
;
//************************************************
// Generates
// Because genItemList includes variable declarations, we don't need beginNamed
genItemBlock<nodep>:
generate_block_or_null<nodep>: // IEEE: generate_block_or_null
genItem { $$ = new AstBegin(CRELINE(),"genblk",$1); }
| genItemBegin { $$ = $1; }
;
@@ -675,9 +701,11 @@ genTopBlock<nodep>:
| genItemBegin { $$ = $1; }
;
genItemBegin<nodep>:
genItemBegin<nodep>: // IEEE: part of generate_block
yBEGIN genItemList yEND { $$ = new AstBegin($1,"genblk",$2); }
| yBEGIN yEND { $$ = NULL; }
| yaID ':' yBEGIN genItemList yEND endLabelE { $$ = new AstBegin($2,*$1,$4); }
| yaID ':' yBEGIN yEND endLabelE { $$ = NULL; }
| yBEGIN ':' yaID genItemList yEND endLabelE { $$ = new AstBegin($2,*$3,$4); }
| yBEGIN ':' yaID yEND endLabelE { $$ = NULL; }
;
@@ -687,29 +715,39 @@ genItemList<nodep>:
| genItemList genItem { $$ = $1->addNextNull($2); }
;
genItem<nodep>:
modOrGenItem { $$ = $1; }
| yCASE '(' expr ')' genCaseListE yENDCASE { $$ = new AstGenCase($1,$3,$5); }
| yIF '(' expr ')' genItemBlock %prec prLOWER_THAN_ELSE { $$ = new AstGenIf($1,$3,$5,NULL); }
| yIF '(' expr ')' genItemBlock yELSE genItemBlock { $$ = new AstGenIf($1,$3,$5,$7); }
| yFOR '(' varRefBase '=' expr ';' expr ';' varRefBase '=' expr ')' genItemBlock
{ $$ = new AstGenFor($1, new AstAssign($4,$3,$5)
,$7, new AstAssign($10,$9,$11)
,$13);}
genItem<nodep>: // IEEE: module_or_interface_or_generate_item (INCOMPLETE)
module_or_generate_item { $$ = $1; }
| conditional_generate_construct {}
| loop_generate_construct {}
;
genCaseListE<nodep>:
conditional_generate_construct<nodep>: // ==IEEE: conditional_generate_construct
yCASE '(' expr ')' case_generate_itemListE yENDCASE { $$ = new AstGenCase($1,$3,$5); }
| yIF '(' expr ')' generate_block_or_null %prec prLOWER_THAN_ELSE { $$ = new AstGenIf($1,$3,$5,NULL); }
| yIF '(' expr ')' generate_block_or_null yELSE generate_block_or_null { $$ = new AstGenIf($1,$3,$5,$7); }
;
loop_generate_construct<nodep>: // ==IEEE: loop_generate_construct
yFOR '(' varRefBase '=' expr ';' expr ';' varRefBase '=' expr ')' generate_block_or_null
{ $$ = new AstGenFor($1, new AstAssign($4,$3,$5)
,$7, new AstAssign($10,$9,$11)
,$13);}
;
case_generate_itemListE<nodep>: // IEEE: [{ case_generate_itemList }]
/* empty */ { $$ = NULL; }
| genCaseList { $$ = $1; }
| case_generate_itemList { $$ = $1; }
;
genCaseList<nodep>:
caseCondList ':' genItemBlock { $$ = new AstCaseItem($2,$1,$3); }
| yDEFAULT ':' genItemBlock { $$ = new AstCaseItem($2,NULL,$3); }
| yDEFAULT genItemBlock { $$ = new AstCaseItem($1,NULL,$2); }
| genCaseList caseCondList ':' genItemBlock { $$ = $1;$1->addNext(new AstCaseItem($3,$2,$4)); }
| genCaseList yDEFAULT genItemBlock { $$ = $1;$1->addNext(new AstCaseItem($2,NULL,$3)); }
| genCaseList yDEFAULT ':' genItemBlock { $$ = $1;$1->addNext(new AstCaseItem($3,NULL,$4)); }
case_generate_itemList<nodep>: // IEEE: { case_generate_itemList }
case_generate_item { $$=$1; }
| case_generate_itemList case_generate_item { $$=$1; $1->addNext($2); }
;
case_generate_item<nodep>: // ==IEEE: case_generate_item
caseCondList ':' generate_block_or_null { $$ = new AstCaseItem($2,$1,$3); }
| yDEFAULT ':' generate_block_or_null { $$ = new AstCaseItem($2,NULL,$3); }
| yDEFAULT generate_block_or_null { $$ = new AstCaseItem($1,NULL,$2); }
;
//************************************************
@@ -722,14 +760,15 @@ assignList<nodep>:
assignOne<nodep>:
varRefDotBit '=' expr { $$ = new AstAssignW($2,$1,$3); }
| '{' concIdList '}' '=' expr { $$ = new AstAssignW($1,$2,$5); }
| '{' identifier_listLvalue '}' '=' expr { $$ = new AstAssignW($1,$2,$5); }
;
delayE: /* empty */ { }
| delay { } /* ignored */
delayE:
/* empty */ { }
| delay_control { } /* ignored */
;
delay<fileline>:
delay_control<fileline>: //== IEEE: delay_control
'#' dlyTerm { $$ = $1; } /* ignored */
| '#' '(' minTypMax ')' { $$ = $1; } /* ignored */
| '#' '(' minTypMax ',' minTypMax ')' { $$ = $1; } /* ignored */
@@ -743,8 +782,7 @@ dlyTerm<nodep>:
| yaTIMENUM { $$ = NULL; }
;
// IEEE: mintypmax_expression and constant_mintypmax_expression
minTypMax<nodep>:
minTypMax<nodep>: // IEEE: mintypmax_expression and constant_mintypmax_expression
dlyTerm { $$ = $1; } /* ignored */
| dlyTerm ':' dlyTerm ':' dlyTerm { $$ = $1; } /* ignored */
;
@@ -774,21 +812,26 @@ regSigId<varp>:
$$->addNext(new AstInitial($3,new AstAssign($3, new AstVarRef($3, *$1, true), $4))); }
;
sigId<varp>: yaID { $$ = V3Parse::createVariable(CRELINE(), *$1, NULL); }
sigId<varp>:
yaID { $$ = V3Parse::createVariable(CRELINE(), *$1, NULL); }
;
regsig<varp>: regSigId sigAttrListE {}
regsig<varp>:
regSigId sigAttrListE {}
;
sigAttrListE: /* empty */ {}
sigAttrListE:
/* empty */ {}
| sigAttrList {}
;
sigAttrList: sigAttr {}
sigAttrList:
sigAttr {}
| sigAttrList sigAttr {}
;
sigAttr: yVL_CLOCK { V3Parse::s_varAttrp->attrScClocked(true); }
sigAttr:
yVL_CLOCK { V3Parse::s_varAttrp->attrScClocked(true); }
| yVL_CLOCK_ENABLE { V3Parse::s_varAttrp->attrClockEn(true); }
| yVL_PUBLIC { V3Parse::s_varAttrp->sigPublic(true); V3Parse::s_varAttrp->sigModPublic(true); }
| yVL_PUBLIC_FLAT { V3Parse::s_varAttrp->sigPublic(true); }
@@ -800,7 +843,7 @@ rangeListE<rangep>:
| rangeList { $$ = $1; }
;
rangeList<rangep>:
rangeList<rangep>: // IEEE: packed_dimension + ...
anyrange { $$ = $1; }
| rangeList anyrange { $$ = $1; $1->addNext($2); }
;
@@ -838,13 +881,12 @@ paramList<varp>:
| paramList ',' param { $$ = $1; $1->addNext($3); }
;
// IEEE: list_of_defparam_assignments
defpList<nodep>:
defpOne { $$ = $1; }
| defpList ',' defpOne { $$ = $1->addNext($3); }
list_of_defparam_assignments<nodep>: //== IEEE: list_of_defparam_assignments
defparam_assignment { $$ = $1; }
| list_of_defparam_assignments ',' defparam_assignment { $$ = $1->addNext($3); }
;
defpOne<nodep>:
defparam_assignment<nodep>: // ==IEEE: defparam_assignment
yaID '.' yaID '=' expr { $$ = new AstDefParam($4,*$1,*$3,$5); }
;
@@ -853,6 +895,7 @@ defpOne<nodep>:
instDecl<nodep>:
yaID instparamListE {INSTPREP(*$1,$2);} instnameList ';' { $$ = $4; V3Parse::s_impliedDecl=false;}
;
instparamListE<pinp>:
/* empty */ { $$ = NULL; }
@@ -895,20 +938,19 @@ cellpinItemE<pinp>:
//************************************************
// EventControl lists
eventControlE<sentreep>:
event_controlE<sentreep>:
/* empty */ { $$ = NULL; }
| eventControl { $$ = $1; }
| event_control { $$ = $1; }
;
// IEEE: event_control
eventControl<sentreep>:
event_control<sentreep>: // ==IEEE: event_control
'@' '(' senList ')' { $$ = new AstSenTree($1,$3); }
| '@' senitemVar { $$ = new AstSenTree($1,$2); } /* For events only */
| '@' '(' '*' ')' { $$ = NULL; } /* Verilog 2001 */
| '@' '(' '*' ')' { $$ = NULL; }
| '@' '*' { $$ = NULL; } /* Verilog 2001 */
;
// IEEE: event_expression - split over several
senList<senitemp>:
senList<senitemp>: // IEEE: event_expression - split over several
senitem { $$ = $1; }
| senList yOR senitem { $$ = $1;$1->addNext($3); }
| senList ',' senitem { $$ = $1;$1->addNext($3); } /* Verilog 2001 */
@@ -924,7 +966,7 @@ senitemVar<senitemp>:
varRefDotBit { $$ = new AstSenItem(CRELINE(),AstEdgeType::ANYEDGE,$1); }
;
senitemEdge<senitemp>:
senitemEdge<senitemp>: // IEEE: part of event_expression
yPOSEDGE varRefDotBit { $$ = new AstSenItem($1,AstEdgeType::POSEDGE,$2); }
| yNEGEDGE varRefDotBit { $$ = new AstSenItem($1,AstEdgeType::NEGEDGE,$2); }
| yPOSEDGE '(' varRefDotBit ')' { $$ = new AstSenItem($1,AstEdgeType::POSEDGE,$3); }
@@ -934,7 +976,7 @@ senitemEdge<senitemp>:
//************************************************
// Statements
stmtBlock<nodep>:
stmtBlock<nodep>: // IEEE: statement + seq_block + par_block
stmt { $$ = $1; }
| yBEGIN stmtList yEND { $$ = $2; }
| yBEGIN yEND { $$ = NULL; }
@@ -952,19 +994,42 @@ stmtList<nodep>:
| stmtList stmtBlock { $$ = ($2==NULL)?($1):($1->addNext($2)); }
;
// IEEE: statement_or_null (may include more stuff, not analyzed)
// == function_statement_or_null
stmt<nodep>:
// // from _or_null
';' { $$ = NULL; }
| labeledStmt { $$ = $1; }
| yaID ':' labeledStmt { $$ = new AstBegin($2, *$1, $3); } /*S05 block creation rule*/
| delay stmtBlock { $$ = $2; $1->v3warn(STMTDLY,"Ignoring delay on this delayed statement.\n"); }
| varRefDotBit yP_LTE delayE expr ';' { $$ = new AstAssignDly($2,$1,$4); }
//
| delay_control stmtBlock { $$ = $2; $1->v3warn(STMTDLY,"Ignoring delay on this delayed statement.\n"); }
//
// // IEEE: operator_assignment
| varRefDotBit '=' delayE expr ';' { $$ = new AstAssign($2,$1,$4); }
| varRefDotBit '=' yD_FOPEN '(' expr ',' expr ')' ';' { $$ = new AstFOpen($3,$1,$5,$7); }
| '{' identifier_listLvalue '}' '=' delayE expr ';' { $$ = new AstAssign($4,$2,$6); }
//
// // IEEE: nonblocking_assignment
| varRefDotBit yP_LTE delayE expr ';' { $$ = new AstAssignDly($2,$1,$4); }
| '{' identifier_listLvalue '}' yP_LTE delayE expr ';' { $$ = new AstAssignDly($4,$2,$6); }
//
// // IEEE: procedural_continuous_assignment
| yASSIGN varRefDotBit '=' delayE expr ';' { $$ = new AstAssign($1,$2,$5); }
| '{' concIdList '}' yP_LTE delayE expr ';' { $$ = new AstAssignDly($4,$2,$6); }
| '{' concIdList '}' '=' delayE expr ';' { $$ = new AstAssign($4,$2,$6); }
//
// // IEEE: case_statement
| unique_priorityE caseStart caseAttrE case_itemListE yENDCASE { $$ = $2; if ($4) $2->addItemsp($4);
if ($1 == uniq_UNIQUE) $2->parallelPragma(true);
if ($1 == uniq_PRIORITY) $2->fullPragma(true); }
//
// // IEEE: conditional_statement
| unique_priorityE yIF '(' expr ')' stmtBlock %prec prLOWER_THAN_ELSE
{ $$ = new AstIf($2,$4,$6,NULL); }
| unique_priorityE yIF '(' expr ')' stmtBlock yELSE stmtBlock
{ $$ = new AstIf($2,$4,$6,$8); }
//
// // IEEE: subroutine_call_statement (INCOMPLETE)
| taskRef ';' { $$ = $1; }
//
| yD_C '(' cStrList ')' ';' { $$ = (v3Global.opt.ignc() ? NULL : new AstUCStmt($1,$3)); }
| yD_FCLOSE '(' varRefDotBit ')' ';' { $$ = new AstFClose($1, $3); }
| yD_FFLUSH ';' { $1->v3error("Unsupported: $fflush of all handles does not map to C++.\n"); }
@@ -975,9 +1040,7 @@ stmt<nodep>:
| yD_STOP parenE ';' { $$ = new AstStop($1); }
| yD_STOP '(' expr ')' ';' { $$ = new AstStop($1); }
| yVL_COVERAGE_BLOCK_OFF { $$ = new AstPragma($1,AstPragmaType::COVERAGE_BLOCK_OFF); }
| stateCaseForIf { $$ = $1; }
| taskRef ';' { $$ = $1; }
//
| yD_DISPLAY parenE ';' { $$ = new AstDisplay($1,AstDisplayType::DISPLAY,"", NULL,NULL); }
| yD_DISPLAY '(' yaSTRING commaEListE ')' ';' { $$ = new AstDisplay($1,AstDisplayType::DISPLAY,*$3,NULL,$4); }
| yD_WRITE '(' yaSTRING commaEListE ')' ';' { $$ = new AstDisplay($1,AstDisplayType::WRITE, *$3,NULL,$4); }
@@ -992,66 +1055,61 @@ stmt<nodep>:
| yD_FATAL parenE ';' { $$ = new AstDisplay($1,AstDisplayType::FATAL, "", NULL,NULL); $$->addNext(new AstStop($1)); }
| yD_FATAL '(' expr ')' ';' { $$ = new AstDisplay($1,AstDisplayType::FATAL, "", NULL,NULL); $$->addNext(new AstStop($1)); if ($3) $3->deleteTree(); }
| yD_FATAL '(' expr ',' yaSTRING commaEListE ')' ';' { $$ = new AstDisplay($1,AstDisplayType::FATAL, *$5,NULL,$6); $$->addNext(new AstStop($1)); if ($3) $3->deleteTree(); }
//
| yD_READMEMB '(' expr ',' varRefMem ')' ';' { $$ = new AstReadMem($1,false,$3,$5,NULL,NULL); }
| yD_READMEMB '(' expr ',' varRefMem ',' expr ')' ';' { $$ = new AstReadMem($1,false,$3,$5,$7,NULL); }
| yD_READMEMB '(' expr ',' varRefMem ',' expr ',' expr ')' ';' { $$ = new AstReadMem($1,false,$3,$5,$7,$9); }
| yD_READMEMH '(' expr ',' varRefMem ')' ';' { $$ = new AstReadMem($1,true, $3,$5,NULL,NULL); }
| yD_READMEMH '(' expr ',' varRefMem ',' expr ')' ';' { $$ = new AstReadMem($1,true, $3,$5,$7,NULL); }
| yD_READMEMH '(' expr ',' varRefMem ',' expr ',' expr ')' ';' { $$ = new AstReadMem($1,true, $3,$5,$7,$9); }
//
// // IEEE: loop_statement (INCOMPLETE)
| yFOREVER stmtBlock { $$ = new AstWhile($1,new AstConst($1,V3Number($1,1,1)),$2); }
| yREPEAT '(' expr ')' stmtBlock { $$ = new AstRepeat($1,$3,$5);}
| yWHILE '(' expr ')' stmtBlock { $$ = new AstWhile($1,$3,$5);}
| yFOR '(' varRefBase '=' expr ';' expr ';' varRefBase '=' expr ')' stmtBlock
{ $$ = new AstFor($1, new AstAssign($4,$3,$5)
,$7, new AstAssign($10,$9,$11)
,$13);}
| yDO stmtBlock yWHILE '(' expr ')' { $$ = $2->cloneTree(true); $$->addNext(new AstWhile($1,$5,$2));}
;
//************************************************
// Case/If
unique_priorityE<uniqstate>:
unique_priorityE<uniqstate>: // IEEE: unique_priority + empty
/*empty*/ { $$ = uniq_NONE; }
| yPRIORITY { $$ = uniq_PRIORITY; }
| yUNIQUE { $$ = uniq_UNIQUE; }
;
stateCaseForIf<nodep>:
unique_priorityE caseStmt caseAttrE caseListE yENDCASE { $$ = $2; if ($4) $2->addItemsp($4);
if ($1 == uniq_UNIQUE) $2->parallelPragma(true);
if ($1 == uniq_PRIORITY) $2->fullPragma(true); }
| unique_priorityE yIF '(' expr ')' stmtBlock %prec prLOWER_THAN_ELSE
{ $$ = new AstIf($2,$4,$6,NULL); }
| unique_priorityE yIF '(' expr ')' stmtBlock yELSE stmtBlock
{ $$ = new AstIf($2,$4,$6,$8); }
| yFOR '(' varRefBase '=' expr ';' expr ';' varRefBase '=' expr ')' stmtBlock
{ $$ = new AstFor($1, new AstAssign($4,$3,$5)
,$7, new AstAssign($10,$9,$11)
,$13);}
| yWHILE '(' expr ')' stmtBlock { $$ = new AstWhile($1,$3,$5);}
| yDO stmtBlock yWHILE '(' expr ')' { $$ = $2->cloneTree(true); $$->addNext(new AstWhile($1,$5,$2));}
;
caseStmt<casep>:
caseStart<casep>: // IEEE: part of case_statement
yCASE '(' expr ')' { $$ = V3Parse::s_caseAttrp = new AstCase($1,AstCaseType::CASE,$3,NULL); }
| yCASEX '(' expr ')' { $$ = V3Parse::s_caseAttrp = new AstCase($1,AstCaseType::CASEX,$3,NULL); $1->v3warn(CASEX,"Suggest casez (with ?'s) in place of casex (with X's)\n"); }
| yCASEZ '(' expr ')' { $$ = V3Parse::s_caseAttrp = new AstCase($1,AstCaseType::CASEZ,$3,NULL); }
| yCASEZ '(' expr ')' { $$ = V3Parse::s_caseAttrp = new AstCase($1,AstCaseType::CASEZ,$3,NULL); }
;
caseAttrE: /*empty*/ { }
caseAttrE:
/*empty*/ { }
| caseAttrE yVL_FULL_CASE { V3Parse::s_caseAttrp->fullPragma(true); }
| caseAttrE yVL_PARALLEL_CASE { V3Parse::s_caseAttrp->parallelPragma(true); }
;
caseListE<caseitemp>:
case_itemListE<caseitemp>: // IEEE: [ { case_item } ]
/* empty */ { $$ = NULL; }
| caseList { $$ = $1; }
| case_itemList { $$ = $1; }
;
caseList<caseitemp>:
case_itemList<caseitemp>: // IEEE: { case_item + ... }
caseCondList ':' stmtBlock { $$ = new AstCaseItem($2,$1,$3); }
| yDEFAULT ':' stmtBlock { $$ = new AstCaseItem($2,NULL,$3); }
| yDEFAULT stmtBlock { $$ = new AstCaseItem($1,NULL,$2); }
| caseList caseCondList ':' stmtBlock { $$ = $1;$1->addNext(new AstCaseItem($3,$2,$4)); }
| caseList yDEFAULT stmtBlock { $$ = $1;$1->addNext(new AstCaseItem($2,NULL,$3)); }
| caseList yDEFAULT ':' stmtBlock { $$ = $1;$1->addNext(new AstCaseItem($3,NULL,$4)); }
| case_itemList caseCondList ':' stmtBlock { $$ = $1;$1->addNext(new AstCaseItem($3,$2,$4)); }
| case_itemList yDEFAULT stmtBlock { $$ = $1;$1->addNext(new AstCaseItem($2,NULL,$3)); }
| case_itemList yDEFAULT ':' stmtBlock { $$ = $1;$1->addNext(new AstCaseItem($3,NULL,$4)); }
;
caseCondList<nodep>:
caseCondList<nodep>: // IEEE: part of case_item
expr { $$ = $1; }
| caseCondList ',' expr { $$ = $1;$1->addNext($3); }
;
@@ -1059,39 +1117,39 @@ caseCondList<nodep>:
//************************************************
// Functions/tasks
taskRef<nodep>:
taskRef<nodep>: // IEEE: part of tf_call
idDotted { $$ = new AstTaskRef(CRELINE(),new AstParseRef($1->fileline(), AstParseRefExp::TASK, $1),NULL);}
| idDotted '(' exprList ')' { $$ = new AstTaskRef(CRELINE(),new AstParseRef($1->fileline(), AstParseRefExp::TASK, $1),$3);}
;
funcRef<nodep>:
funcRef<nodep>: // IEEE: part of tf_call
idDotted '(' exprList ')' { $$ = new AstFuncRef($2,new AstParseRef($1->fileline(), AstParseRefExp::FUNC, $1), $3); }
;
taskDecl<nodep>:
yTASK lifetimeE yaID funcGuts yENDTASK endLabelE
task_declaration<nodep>: // ==IEEE: task_declaration
yTASK lifetimeE yaID tfGuts yENDTASK endLabelE
{ $$ = new AstTask ($1,*$3,$4);}
;
funcDecl<funcp>:
yFUNCTION lifetimeE funcTypeE yaID funcGuts yENDFUNCTION endLabelE { $$ = new AstFunc ($1,*$4,$5,$3); }
| yFUNCTION lifetimeE ySIGNED funcTypeE yaID funcGuts yENDFUNCTION endLabelE { $$ = new AstFunc ($1,*$5,$6,$4); $$->isSigned(true); }
| yFUNCTION lifetimeE funcTypeE yaID yVL_ISOLATE_ASSIGNMENTS funcGuts yENDFUNCTION endLabelE { $$ = new AstFunc ($1,*$4,$6,$3); $$->attrIsolateAssign(true);}
| yFUNCTION lifetimeE ySIGNED funcTypeE yaID yVL_ISOLATE_ASSIGNMENTS funcGuts yENDFUNCTION endLabelE { $$ = new AstFunc ($1,*$5,$7,$4); $$->attrIsolateAssign(true); $$->isSigned(true); }
function_declaration<funcp>: // IEEE: function_declaration + function_body_declaration
yFUNCTION lifetimeE funcTypeE yaID tfGuts yENDFUNCTION endLabelE { $$ = new AstFunc ($1,*$4,$5,$3); }
| yFUNCTION lifetimeE ySIGNED funcTypeE yaID tfGuts yENDFUNCTION endLabelE { $$ = new AstFunc ($1,*$5,$6,$4); $$->isSigned(true); }
| yFUNCTION lifetimeE funcTypeE yaID yVL_ISOLATE_ASSIGNMENTS tfGuts yENDFUNCTION endLabelE { $$ = new AstFunc ($1,*$4,$6,$3); $$->attrIsolateAssign(true);}
| yFUNCTION lifetimeE ySIGNED funcTypeE yaID yVL_ISOLATE_ASSIGNMENTS tfGuts yENDFUNCTION endLabelE { $$ = new AstFunc ($1,*$5,$7,$4); $$->attrIsolateAssign(true); $$->isSigned(true); }
;
// IEEE: lifetime - plus empty
lifetimeE: /* empty */ { }
lifetimeE: // IEEE: lifetime - plus empty
/* empty */ { }
| ySTATIC { $1->v3error("Unsupported: Static in this context\n"); }
| yAUTOMATIC { }
;
funcGuts<nodep>:
'(' {V3Parse::s_pinNum=1;} portV2kArgs ')' ';' funcBody { $$ = $3->addNextNull($6); }
| ';' funcBody { $$ = $2; }
tfGuts<nodep>:
'(' {V3Parse::s_pinNum=1;} portV2kArgs ')' ';' tfBody { $$ = $3->addNextNull($6); }
| ';' tfBody { $$ = $2; }
;
funcBody<nodep>:
tfBody<nodep>: // IEEE: part of function_body_declaration/task_body_declaration
funcVarList stmtBlock { $$ = $1;$1->addNextNull($2); }
| stmtBlock { $$ = $1; }
;
@@ -1114,7 +1172,8 @@ funcVar<nodep>:
| yVL_NO_INLINE_TASK { $$ = new AstPragma($1,AstPragmaType::NO_INLINE_TASK); }
;
parenE: /* empty */ { }
parenE:
/* empty */ { }
| '(' ')' { }
;
@@ -1155,7 +1214,7 @@ exprNoStr<nodep>:
| expr yP_POW expr { $$ = new AstPow ($2,$1,$3); }
| expr yP_MINUSGT expr { $$ = new AstLogIf ($2,$1,$3); }
| expr yP_LOGIFF expr { $$ = new AstLogIff ($2,$1,$3); }
//
| '-' expr %prec prUNARYARITH { $$ = new AstUnaryMin ($1,$2); }
| '+' expr %prec prUNARYARITH { $$ = $2; }
| '&' expr %prec prREDUCTION { $$ = new AstRedAnd ($1,$2); }
@@ -1166,13 +1225,15 @@ exprNoStr<nodep>:
| yP_NOR expr %prec prREDUCTION { $$ = new AstNot($1,new AstRedOr ($1,$2)); }
| '!' expr %prec prNEGATION { $$ = new AstLogNot ($1,$2); }
| '~' expr %prec prNEGATION { $$ = new AstNot ($1,$2); }
//
| expr '?' expr ':' expr { $$ = new AstCond($2,$1,$3,$5); }
| '(' expr ')' { $$ = $2; }
| '_' '(' statePushVlg expr statePop ')' { $$ = $4; } // Arbitrary Verilog inside PSL
//
// // IEEE: concatenation/constant_concatenation
| '{' cateList '}' { $$ = $2; }
| '{' constExpr '{' cateList '}' '}' { $$ = new AstReplicate($1,$4,$2); }
//
| yD_BITS '(' expr ')' { $$ = new AstAttrOf($1,AstAttrType::BITS,$3); }
| yD_C '(' cStrList ')' { $$ = (v3Global.opt.ignc() ? NULL : new AstUCFunc($1,$3)); }
| yD_CLOG2 '(' expr ')' { $$ = new AstCLog2($1,$3); }
@@ -1192,12 +1253,14 @@ exprNoStr<nodep>:
| yD_STIME { $$ = new AstSel($1,new AstTime($1),0,32); }
| yD_TIME { $$ = new AstTime($1); }
| yD_UNSIGNED '(' expr ')' { $$ = new AstUnsigned($1,$3); }
//
| funcRef { $$ = $1; }
//
| yaINTNUM { $$ = new AstConst(CRELINE(),*$1); }
//
| varRefDotBit { $$ = $1; }
//
| error ';' { $$ = NULL; }
;
// Generic expressions
@@ -1354,7 +1417,8 @@ gatePullup<pullp>: gateIdE instRangeE '(' varRefDotBit ')' { $$ = new AstPull ($
;
gatePulldown<pullp>: gateIdE instRangeE '(' varRefDotBit ')' { $$ = new AstPull ($3, $4, false); }
;
gateIdE: /*empty*/ {}
gateIdE:
/*empty*/ {}
| yaID {}
;
@@ -1378,71 +1442,19 @@ gateXorPinList<nodep>:
//************************************************
// Specify
specifyJunkList: specifyJunk {} /* ignored */
| specifyJunkList specifyJunk {} /* ignored */
specify_block<nodep>: // ==IEEE: specify_block
ySPECIFY specifyJunkList yENDSPECIFY { $$ = NULL; }
| ySPECIFY yENDSPECIFY { $$ = NULL; }
;
specifyJunk: dlyTerm {} /* ignored */
| ';' {}
| '!' {}
| '&' {}
| '(' {}
| ')' {}
| '*' {} | '/' {} | '%' {}
| '+' {} | '-' {}
| ',' {}
| ':' {}
| '$' {}
| '=' {}
| '>' {} | '<' {}
| '?' {}
| '^' {}
| '{' {} | '}' {}
| '[' {} | ']' {}
| '|' {}
| '~' {}
| '@' {}
| yIF {}
| yNEGEDGE {}
| yPOSEDGE {}
| yaSTRING {}
| yaTIMINGSPEC {}
| yP_ANDAND {} | yP_GTE {} | yP_LTE {}
| yP_EQUAL {} | yP_NOTEQUAL {}
| yP_CASEEQUAL {} | yP_CASENOTEQUAL {}
| yP_WILDEQUAL {} | yP_WILDNOTEQUAL {}
| yP_XNOR {} | yP_NOR {} | yP_NAND {}
| yP_OROR {}
| yP_SLEFT {} | yP_SRIGHT {} | yP_SSRIGHT {}
| yP_PLUSCOLON {} | yP_MINUSCOLON {}
| yP_POW {}
| yP_MINUSGT {}
| yP_LOGIFF {}
| yPSL_BRA {}
| yPSL_KET {}
| yP_ORMINUSGT {}
| yP_OREQGT {}
| yP_EQGT {} | yP_ASTGT {}
| yP_ANDANDAND {}
| yP_MINUSGTGT {}
| yP_POUNDPOUND {}
| yP_DOTSTAR {}
| yP_ATAT {}
| yP_COLONCOLON {}
| yP_COLONEQ {}
| yP_COLONDIV {}
| yP_PLUSEQ {} | yP_MINUSEQ {}
| yP_TIMESEQ {}
| yP_DIVEQ {} | yP_MODEQ {}
| yP_ANDEQ {} | yP_OREQ {}
| yP_XOREQ {}
| yP_SLEFTEQ {} | yP_SRIGHTEQ {} | yP_SSRIGHTEQ {}
specifyJunkList:
specifyJunk { } /* ignored */
| specifyJunkList specifyJunk { } /* ignored */
;
specifyJunk:
BISONPRE_NOT(ySPECIFY,yENDSPECIFY) { }
| ySPECIFY specifyJunk yENDSPECIFY { }
| error {}
;
@@ -1469,8 +1481,10 @@ idDotted<nodep>:
// we'll assume so and cleanup later.
idArrayed<nodep>:
yaID { $$ = new AstText(CRELINE(),*$1); }
// // IEEE: id + part_select_range/constant_part_select_range
| idArrayed '[' expr ']' { $$ = new AstSelBit($2,$1,$3); } // Or AstArraySel, don't know yet.
| idArrayed '[' constExpr ':' constExpr ']' { $$ = new AstSelExtract($2,$1,$3,$5); }
// // IEEE: id + indexed_range/constant_indexed_range
| idArrayed '[' expr yP_PLUSCOLON constExpr ']' { $$ = new AstSelPlus($2,$1,$3,$5); }
| idArrayed '[' expr yP_MINUSCOLON constExpr ']' { $$ = new AstSelMinus($2,$1,$3,$5); }
;
@@ -1488,12 +1502,13 @@ strAsText<nodep>:
yaSTRING { $$ = V3Parse::createTextQuoted(CRELINE(),*$1);}
;
concIdList<nodep>:
identifier_listLvalue<nodep>: // IEEE: identifier_list for lvalue only
varRefDotBit { $$ = $1; }
| concIdList ',' varRefDotBit { $$ = new AstConcat($2,$1,$3); }
| identifier_listLvalue ',' varRefDotBit { $$ = new AstConcat($2,$1,$3); }
;
endLabelE: /* empty */ { }
endLabelE:
/* empty */ { }
| ':' yaID { }
;
@@ -1509,7 +1524,7 @@ clocking_declaration<nodep>: // IEEE: clocking_declaration (INCOMPLETE)
{ $$ = new AstClocking($1, $5, NULL); }
;
concurrent_assertion_item<nodep>: // IEEE: concurrent_assertion_item (complete)
concurrent_assertion_item<nodep>: // IEEE: concurrent_assertion_item
concurrent_assertion_statement { $$ = $1; }
| yaID ':' concurrent_assertion_statement { $$ = new AstBegin($2,*$1,$3); }
;
@@ -1518,7 +1533,7 @@ concurrent_assertion_statement<nodep>: // IEEE: concurrent_assertion_statement
cover_property_statement { $$ = $1; }
;
cover_property_statement<nodep>: // IEEE: cover_property_statement (complete)
cover_property_statement<nodep>: // IEEE: cover_property_statement
yCOVER yPROPERTY '(' property_spec ')' stmtBlock { $$ = new AstPslCover($1,$4,$6); }
;
+1
View File
@@ -32,6 +32,7 @@ endif
# Needed by tracing routines
CPPFLAGS += -DVL_DEBUG=1
CPPFLAGS += -DVM_PREFIX=$(VM_PREFIX)
CPPFLAGS += $(CPPFLAGS_DRIVER)
CPPFLAGS += $(CPPFLAGS_ADD)
#######################################################################
+35 -19
View File
@@ -1,17 +1,5 @@
#!/usr/bin/perl -w
######################################################################
#
# This program is 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 General Public License or the
# Perl Artistic License.
#
# This program 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.
#
# See copyright, etc in below POD section.
######################################################################
require 5.006_001;
@@ -60,6 +48,9 @@ my $opt_gdb;
my $opt_jobs = 1;
my $opt_verbose;
my $Opt_Verilated_Debug;
our @Opt_Driver_Verilator_Flags;
Getopt::Long::config ("pass_through");
if (! GetOptions (
"help" => \&usage,
"debug" => \&debug,
@@ -75,7 +66,7 @@ if (! GetOptions (
"verbose!" => \$opt_verbose,
"<>" => \&parameter,
)) {
usage();
die "%Error: Bad usage, try '$0 --help'\n";
}
$opt_jobs = calc_jobs() if defined $opt_jobs && $opt_jobs==0;
@@ -155,14 +146,28 @@ sub usage {
sub debug {
$Debug = 1;
push @Opt_Driver_Verilator_Flags, "--debug";
}
our $_Parameter_Next_Level;
sub parameter {
my $param = shift;
if ($param =~ /\.pl/) {
if ($_Parameter_Next_Level) {
($param =~ /^(\d+)$/)
or die "%Error: Expected number following $_Parameter_Next_Level: $param\n";
push @Opt_Driver_Verilator_Flags, $param;
$_Parameter_Next_Level = undef;
}
elsif ($param =~ /\.pl/) {
push @opt_tests, $param;
} else {
die "%Error: Unknown parameter: $param\n";
}
elsif ($param =~ /^--debugi/) {
push @Opt_Driver_Verilator_Flags, $param;
$_Parameter_Next_Level = $param;
}
else {
warn "%Error: Unknown parameter: $param\n";
}
}
@@ -379,7 +384,7 @@ sub compile {
$opt_gdb="gdbrun" if defined $opt_gdb;
my @verilator_flags = @{$param{verilator_flags}};
unshift @verilator_flags, "--gdb $opt_gdb" if $opt_gdb;
unshift @verilator_flags, "--debug" if $::Debug;
unshift @verilator_flags, @Opt_Driver_Verilator_Flags;
unshift @verilator_flags, "--x-assign unique"; # More likely to be buggy
# unshift @verilator_flags, "--trace";
if (defined $opt_optimize) {
@@ -429,6 +434,7 @@ sub compile {
cmd=>["cd $self->{obj_dir} && ",
"make", "-f".getcwd()."/Makefile_obj",
"VM_PREFIX=$self->{VM_PREFIX}",
"CPPFLAGS_DRIVER=-D".uc($self->{name}),
($param{make_main}?"":"MAKE_MAIN=0"),
($param{benchmark}?"OPT_FAST=-O2":""),
"$self->{VM_PREFIX}", # bypass default rule, as we don't need archive
@@ -1057,12 +1063,22 @@ Command to use to invoke VCS.
=back
=head1 SEE ALSO
=head1 DISTRIBUTION
The latest version is available from L<http://www.veripool.org/>.
Copyright 2003-2009 by Wilson Snyder. Verilator is free software; you can
redistribute it and/or modify it under the terms of either the GNU Lesser
General Public License or the Perl Artistic License.
=head1 AUTHORS
Wilson Snyder <[email protected]>
=head1 SEE ALSO
L<verilator>
=cut
######################################################################
+19
View File
@@ -0,0 +1,19 @@
#!/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
# General Public License or the Perl Artistic License.
compile (
v_flags2 => ["--lint-only"],
fails=>1,
expect=>
'%Error: t/t_assert_dup_bad.v:\d+: Duplicate declaration of block: covlabel
%Error: t/t_assert_dup_bad.v:\d+: ... Location of original declaration
%Error: Exiting due to.*',
);
ok(1);
1;
+19
View File
@@ -0,0 +1,19 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed into the Public Domain, for any use,
// without warranty, 2007 by Wilson Snyder.
module t (/*AUTOARG*/
// Inputs
clk
);
input clk;
integer cyc = 0;
covlabel:
cover property (@(posedge clk) cyc==5);
covlabel: // Error: Duplicate block_identifier
cover property (@(posedge clk) cyc==5);
endmodule
+25
View File
@@ -0,0 +1,25 @@
#!/usr/bin/perl
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# Copyright 2003-2008 by Wilson Snyder. This program is free software; you can
# redistribute it and/or modify it under the terms of either the GNU
# General Public License or the Perl Artistic License.
compile (
v_flags2 => [$Self->{v3}?'--assert --sp --coverage-user':''],
);
execute (
check_finished=>1,
);
#if ($Self->{nc}) ... # See t_assert_cover.pl for NC version
# Allow old Perl format dump, or new binary dump
# Check that the hierarchy doesn't include __PVT__
# Otherwise our coverage reports would look really ugly
file_grep ($Self->{coverage_filename}, qr/(TOP\.v\.sub.*.cyc_eq_5)/);
ok(1);
1;
+59
View File
@@ -0,0 +1,59 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed into the Public Domain, for any use,
// without warranty, 2007 by Wilson Snyder.
module t (/*AUTOARG*/
// Inputs
clk
);
input clk;
reg toggle;
integer cyc; initial cyc=1;
Test suba (/*AUTOINST*/
// Inputs
.clk (clk),
.toggle (toggle),
.cyc (cyc[31:0]));
Test subb (/*AUTOINST*/
// Inputs
.clk (clk),
.toggle (toggle),
.cyc (cyc[31:0]));
Test subc (/*AUTOINST*/
// Inputs
.clk (clk),
.toggle (toggle),
.cyc (cyc[31:0]));
always @ (posedge clk) begin
if (cyc!=0) begin
cyc <= cyc + 1;
toggle <= !cyc[0];
if (cyc==9) begin
end
if (cyc==10) begin
$write("*-* All Finished *-*\n");
$finish;
end
end
end
endmodule
module Test
(
input clk,
input toggle,
input [31:0] cyc
);
// Don't flatten out these modules please:
// verilator no_inline_module
// Labeled cover
cyc_eq_5: cover property (@(posedge clk) cyc==5) $display("*COVER: Cyc==5");
endmodule
+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 by Wilson Snyder. This program is free software; you can
# redistribute it and/or modify it under the terms of either the GNU
# General Public License or the Perl Artistic License.
compile (
);
execute (
check_finished=>1,
);
ok(1);
1;
+170
View File
@@ -0,0 +1,170 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed into the Public Domain, for any use,
// without warranty, 2009 by Wilson Snyder.
module t (/*AUTOARG*/
// Inputs
clk
);
input clk;
integer cyc=0;
reg [63:0] crc;
reg [63:0] sum;
wire [1:0] a = crc[1 +: 2];
wire [1:0] b = crc[3 +: 2];
wire [1:0] c = crc[5 +: 2];
wire [1:0] d = crc[7 +: 2];
wire [1:0] e = crc[9 +: 2];
wire [1:0] f = crc[11+: 2];
wire [1:0] g = crc[13+: 2];
// left () [] :: .
// unary + - ! ~ & ~& | ~| ^ ~^ ^~ ++ -- (unary)
// left **
// left * / %
// left + - (binary)
// left << >> <<< >>>
// left < <= > >= inside dist
// left == != === !== ==? !=?
// left & (binary)
// left ^ ~^ ^~ (binary)
// left | (binary)
// left &&
// left ||
// left ? :
// right ->
// none = += -= *= /= %= &= ^= |= <<= >>= <<<= >>>= := :/ <=
// {} {{}} concatenation
wire [1:0] bnz = (b==2'b0) ? 2'b11 : b;
wire [1:0] cnz = (c==2'b0) ? 2'b11 : c;
wire [1:0] dnz = (d==2'b0) ? 2'b11 : d;
wire [1:0] enz = (e==2'b0) ? 2'b11 : e;
// verilator lint_off WIDTH
// Do a few in each group
wire [1:0] o1 = ~ a; // Can't get more than one reduction to parse
wire [1:0] o2 = ^ b; // Can't get more than one reduction to parse
`ifdef verilator
wire [1:0] o3 = a ** b ** c;
`else // A commercial simulator gets this wrong, so calc manually
wire [1:0] o3 = pow(pow(a,b),c);
`endif
wire [1:0] o4 = a * b / cnz % dnz * enz;
wire [1:0] o5 = a + b - c + d;
wire [1:0] o6 = a << b >> c <<< d >>> e <<< f;
wire [1:0] o7 = a < b <= c;
wire [1:0] o8 = a == b != c === d == e;
wire [1:0] o9 = a & b & c;
wire [1:0] o10 = a ^ b ~^ c ^~ d ^ a;
wire [1:0] o11 = a | b | c;
wire [1:0] o12 = a && b && c;
wire [1:0] o13 = a || b || c;
wire [1:0] o14 = a ? b ? c : d : e;
wire [1:0] o15 = a ? b : c ? d : e;
// Now cross each pair of groups
`ifdef verilator
wire [1:0] x1 = ~ a ** ~ b ** ~c;
wire [1:0] x2 = a ** b * c ** d;
`else
wire [1:0] x1 = pow(pow(~ a, ~ b), ~c);
wire [1:0] x2 = pow(a,b) * pow(c,d);
`endif
wire [1:0] x3 = a + b * c + d;
wire [1:0] x4 = a + b << c + d;
wire [1:0] x5 = a == b << c == d;
wire [1:0] x6 = a & b << c & d;
wire [1:0] x7 = a ^ b & c ^ d;
wire [1:0] x8 = a | b ^ c | d;
wire [1:0] x9 = a && b | c && d;
wire [1:0] x10 = a || b && c || d;
wire [1:0] x11 = a ? b || c : d ? e : f;
// verilator lint_on WIDTH
function [1:0] pow (input [1:0] x, input [1:0] y);
casez ({x,y})
4'b00_??: pow = 2'b00;
4'b01_00: pow = 2'b01;
4'b01_01: pow = 2'b01;
4'b01_10: pow = 2'b01;
4'b01_11: pow = 2'b01;
4'b10_00: pow = 2'b01;
4'b10_01: pow = 2'b10;
4'b10_10: pow = 2'b00;
4'b10_11: pow = 2'b00;
4'b11_00: pow = 2'b01;
4'b11_01: pow = 2'b11;
4'b11_10: pow = 2'b01;
4'b11_11: pow = 2'b11;
endcase
endfunction
// Aggregate outputs into a single result vector
wire [63:0] result = {12'h0,
x11,x10,x9,x8,x7,x6,x5,x4,x3,x2,x1,
o15,o14,o13,o12,o11,o10,o9,o8,o7,o6,o5,o4,o3,o2,o1};
// Test loop
always @ (posedge clk) begin
`ifdef TEST_VERBOSE
$write("[%0t] cyc==%0d crc=%x result=%x ",$time, cyc, crc, result);
$write(" %b",o1);
$write(" %b",o2);
$write(" %b",o3);
$write(" %b",o4);
$write(" %b",o5);
$write(" %b",o6);
$write(" %b",o7);
$write(" %b",o8);
$write(" %b",o9);
$write(" %b",o10);
$write(" %b",o11);
$write(" %b",o12);
$write(" %b",o13);
$write(" %b",o14);
$write(" %b",o15);
// Now cross each pair of groups
$write(" %b",x1);
$write(" %b",x2);
$write(" %b",x3);
$write(" %b",x4);
$write(" %b",x5);
$write(" %b",x6);
$write(" %b",x7);
$write(" %b",x8);
$write(" %b",x9);
$write(" %b",x10);
$write(" %b",x11);
$write("\n");
`endif
cyc <= cyc + 1;
crc <= {crc[62:0], crc[63]^crc[2]^crc[0]};
sum <= result ^ {sum[62:0],sum[63]^sum[2]^sum[0]};
if (cyc==0) begin
// Setup
crc <= 64'h5aef0c8d_d70a4497;
sum <= 64'h0;
end
else if (cyc<10) begin
sum <= 64'h0;
end
else if (cyc<90) begin
end
else if (cyc==99) begin
$write("[%0t] cyc==%0d crc=%x sum=%x\n",$time, cyc, crc, sum);
if (crc !== 64'hc77bb9b3784ea091) $stop;
// What checksum will we end up with (above print should match)
`define EXPECTED_SUM 64'h34b4e0b25bb03880
if (sum !== `EXPECTED_SUM) $stop;
$write("*-* All Finished *-*\n");
$finish;
end
end
endmodule
+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 by Wilson Snyder. This program is free software; you can
# redistribute it and/or modify it under the terms of either the GNU
# General Public License or the Perl Artistic License.
compile (
);
execute (
check_finished=>1,
);
ok(1);
1;
+33
View File
@@ -0,0 +1,33 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed into the Public Domain, for any use,
// without warranty, 2009 by Wilson Snyder.
module t (/*AUTOARG*/);
reg signed [2:0] negcnt;
integer times;
integer repeats;
initial begin
times = 0;
repeat (1) begin
repeat (0) $stop;
repeat (-1) $stop;
negcnt = 'sb111;
repeat (negcnt) $stop;
repeat (5) begin
repeat (2) begin
times = times + 1;
end
end
end
if (times != 10) $stop;
//
repeats = 0;
forever begin
$write("*-* All Finished *-*\n");
$finish;
end
end
endmodule
+8 -4
View File
@@ -9,12 +9,16 @@ if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); di
compile (
fails=>1,
expect=>
'%Error: t/t_var_bad_sameas.v:\d+: Unsupported in C: Cell has same name as variable: varfirst
%Error: t/t_var_bad_sameas.v:\d+: Unsupported in C: Task/function has same name as variable: varfirst
'%Error: t/t_var_bad_sameas.v:\d+: Unsupported in C: Cell has the same name as variable: varfirst
%Error: t/t_var_bad_sameas.v:\d+: ... Location of original declaration
%Error: t/t_var_bad_sameas.v:\d+: Unsupported in C: Task has the same name as variable: varfirst
%Error: t/t_var_bad_sameas.v:\d+: ... Location of original declaration
%Error: t/t_var_bad_sameas.v:\d+: Unsupported in C: Variable has same name as cell: cellfirst
%Error: t/t_var_bad_sameas.v:\d+: Unsupported in C: Task/function has same name as cell: cellfirst
%Error: t/t_var_bad_sameas.v:\d+: Unsupported in C: Task has the same name as cell: cellfirst
%Error: t/t_var_bad_sameas.v:\d+: ... Location of original declaration
%Error: t/t_var_bad_sameas.v:\d+: Unsupported in C: Variable has same name as task: taskfirst
%Error: t/t_var_bad_sameas.v:\d+: Unsupported in C: Cell has same name as task: taskfirst
%Error: t/t_var_bad_sameas.v:\d+: Unsupported in C: Cell has the same name as task: taskfirst
%Error: t/t_var_bad_sameas.v:\d+: ... Location of original declaration
%Error: Exiting due to.*',
);
+33
View File
@@ -0,0 +1,33 @@
#!/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
# General Public License or the Perl Artistic License.
top_filename("t/t_var_pinsizes.v");
compile (
v_flags2 => ["-sp -pins-bv 1 --exe $Self->{t_dir}/t_var_pinsizes.cpp"],
make_main => 0,
) if $Self->{v3};
if ($Self->{v3}) {
file_grep ("$Self->{obj_dir}/$Self->{VM_PREFIX}.sp", qr/sc_in<sc_bv<1>\s> \s+ i1;/x);
file_grep ("$Self->{obj_dir}/$Self->{VM_PREFIX}.sp", qr/sc_in<sc_bv<8>\s> \s+ i8;/x);
file_grep ("$Self->{obj_dir}/$Self->{VM_PREFIX}.sp", qr/sc_in<sc_bv<16>\s> \s+ i16;/x);
file_grep ("$Self->{obj_dir}/$Self->{VM_PREFIX}.sp", qr/sc_in<sc_bv<32>\s> \s+ i32;/x);
file_grep ("$Self->{obj_dir}/$Self->{VM_PREFIX}.sp", qr/sc_in<sc_bv<64>\s> \s+ i64;/x);
file_grep ("$Self->{obj_dir}/$Self->{VM_PREFIX}.sp", qr/sc_in<sc_bv<65>\s> \s+ i65;/x);
file_grep ("$Self->{obj_dir}/$Self->{VM_PREFIX}.sp", qr/sc_out<sc_bv<1>\s> \s+ o1;/x);
file_grep ("$Self->{obj_dir}/$Self->{VM_PREFIX}.sp", qr/sc_out<sc_bv<8>\s> \s+ o8;/x);
file_grep ("$Self->{obj_dir}/$Self->{VM_PREFIX}.sp", qr/sc_out<sc_bv<16>\s> \s+ o16;/x);
file_grep ("$Self->{obj_dir}/$Self->{VM_PREFIX}.sp", qr/sc_out<sc_bv<32>\s> \s+ o32;/x);
file_grep ("$Self->{obj_dir}/$Self->{VM_PREFIX}.sp", qr/sc_out<sc_bv<64>\s> \s+ o64;/x);
file_grep ("$Self->{obj_dir}/$Self->{VM_PREFIX}.sp", qr/sc_out<sc_bv<65>\s> \s+ o65;/x);
}
ok(1);
1;
+33
View File
@@ -0,0 +1,33 @@
#!/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
# General Public License or the Perl Artistic License.
top_filename("t/t_var_pinsizes.v");
compile (
v_flags2 => ["-sp -pins-bv 2 --exe $Self->{t_dir}/t_var_pinsizes.cpp"],
make_main => 0,
) if $Self->{v3};
if ($Self->{v3}) {
file_grep ("$Self->{obj_dir}/$Self->{VM_PREFIX}.sp", qr/sc_in<bool> \s+ i1;/x);
file_grep ("$Self->{obj_dir}/$Self->{VM_PREFIX}.sp", qr/sc_in<sc_bv<8>\s> \s+ i8;/x);
file_grep ("$Self->{obj_dir}/$Self->{VM_PREFIX}.sp", qr/sc_in<sc_bv<16>\s> \s+ i16;/x);
file_grep ("$Self->{obj_dir}/$Self->{VM_PREFIX}.sp", qr/sc_in<sc_bv<32>\s> \s+ i32;/x);
file_grep ("$Self->{obj_dir}/$Self->{VM_PREFIX}.sp", qr/sc_in<sc_bv<64>\s> \s+ i64;/x);
file_grep ("$Self->{obj_dir}/$Self->{VM_PREFIX}.sp", qr/sc_in<sc_bv<65>\s> \s+ i65;/x);
file_grep ("$Self->{obj_dir}/$Self->{VM_PREFIX}.sp", qr/sc_out<bool> \s+ o1;/x);
file_grep ("$Self->{obj_dir}/$Self->{VM_PREFIX}.sp", qr/sc_out<sc_bv<8>\s> \s+ o8;/x);
file_grep ("$Self->{obj_dir}/$Self->{VM_PREFIX}.sp", qr/sc_out<sc_bv<16>\s> \s+ o16;/x);
file_grep ("$Self->{obj_dir}/$Self->{VM_PREFIX}.sp", qr/sc_out<sc_bv<32>\s> \s+ o32;/x);
file_grep ("$Self->{obj_dir}/$Self->{VM_PREFIX}.sp", qr/sc_out<sc_bv<64>\s> \s+ o64;/x);
file_grep ("$Self->{obj_dir}/$Self->{VM_PREFIX}.sp", qr/sc_out<sc_bv<65>\s> \s+ o65;/x);
}
ok(1);
1;
+14 -14
View File
@@ -9,24 +9,24 @@ if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); di
top_filename("t/t_var_pinsizes.v");
compile (
v_flags2 => ['-sp -no-pins64'],
verilator_make_gcc => 0,
v_flags2 => ["-sp -no-pins64 --exe $Self->{t_dir}/t_var_pinsizes.cpp"],
make_main => 0,
) if $Self->{v3};
if ($Self->{v3}) {
file_grep ("$Self->{obj_dir}/Vt_var_pins_sc32.sp", qr/sc_in<bool> \s+ i1;/x);
file_grep ("$Self->{obj_dir}/Vt_var_pins_sc32.sp", qr/sc_in<uint32_t> \s+ i8;/x);
file_grep ("$Self->{obj_dir}/Vt_var_pins_sc32.sp", qr/sc_in<uint32_t> \s+ i16;/x);
file_grep ("$Self->{obj_dir}/Vt_var_pins_sc32.sp", qr/sc_in<uint32_t> \s+ i32;/x);
file_grep ("$Self->{obj_dir}/Vt_var_pins_sc32.sp", qr/sc_in<sc_bv<64>\s> \s+ i64;/x);
file_grep ("$Self->{obj_dir}/Vt_var_pins_sc32.sp", qr/sc_in<sc_bv<65>\s> \s+ i65;/x);
file_grep ("$Self->{obj_dir}/$Self->{VM_PREFIX}.sp", qr/sc_in<bool> \s+ i1;/x);
file_grep ("$Self->{obj_dir}/$Self->{VM_PREFIX}.sp", qr/sc_in<uint32_t> \s+ i8;/x);
file_grep ("$Self->{obj_dir}/$Self->{VM_PREFIX}.sp", qr/sc_in<uint32_t> \s+ i16;/x);
file_grep ("$Self->{obj_dir}/$Self->{VM_PREFIX}.sp", qr/sc_in<uint32_t> \s+ i32;/x);
file_grep ("$Self->{obj_dir}/$Self->{VM_PREFIX}.sp", qr/sc_in<sc_bv<64>\s> \s+ i64;/x);
file_grep ("$Self->{obj_dir}/$Self->{VM_PREFIX}.sp", qr/sc_in<sc_bv<65>\s> \s+ i65;/x);
file_grep ("$Self->{obj_dir}/Vt_var_pins_sc32.sp", qr/sc_out<bool> \s+ o1;/x);
file_grep ("$Self->{obj_dir}/Vt_var_pins_sc32.sp", qr/sc_out<uint32_t> \s+ o8;/x);
file_grep ("$Self->{obj_dir}/Vt_var_pins_sc32.sp", qr/sc_out<uint32_t> \s+ o16;/x);
file_grep ("$Self->{obj_dir}/Vt_var_pins_sc32.sp", qr/sc_out<uint32_t> \s+ o32;/x);
file_grep ("$Self->{obj_dir}/Vt_var_pins_sc32.sp", qr/sc_out<sc_bv<64>\s> \s+ o64;/x);
file_grep ("$Self->{obj_dir}/Vt_var_pins_sc32.sp", qr/sc_out<sc_bv<65>\s> \s+ o65;/x);
file_grep ("$Self->{obj_dir}/$Self->{VM_PREFIX}.sp", qr/sc_out<bool> \s+ o1;/x);
file_grep ("$Self->{obj_dir}/$Self->{VM_PREFIX}.sp", qr/sc_out<uint32_t> \s+ o8;/x);
file_grep ("$Self->{obj_dir}/$Self->{VM_PREFIX}.sp", qr/sc_out<uint32_t> \s+ o16;/x);
file_grep ("$Self->{obj_dir}/$Self->{VM_PREFIX}.sp", qr/sc_out<uint32_t> \s+ o32;/x);
file_grep ("$Self->{obj_dir}/$Self->{VM_PREFIX}.sp", qr/sc_out<sc_bv<64>\s> \s+ o64;/x);
file_grep ("$Self->{obj_dir}/$Self->{VM_PREFIX}.sp", qr/sc_out<sc_bv<65>\s> \s+ o65;/x);
}
ok(1);
+14 -14
View File
@@ -9,24 +9,24 @@ if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); di
top_filename("t/t_var_pinsizes.v");
compile (
v_flags2 => ['-sp -pins64'],
verilator_make_gcc => 0,
v_flags2 => ["-sp -pins64 --exe $Self->{t_dir}/t_var_pinsizes.cpp"],
make_main => 0,
) if $Self->{v3};
if ($Self->{v3}) {
file_grep ("$Self->{obj_dir}/Vt_var_pins_sc64.sp", qr/sc_in<bool> \s+ i1;/x);
file_grep ("$Self->{obj_dir}/Vt_var_pins_sc64.sp", qr/sc_in<uint32_t> \s+ i8;/x);
file_grep ("$Self->{obj_dir}/Vt_var_pins_sc64.sp", qr/sc_in<uint32_t> \s+ i16;/x);
file_grep ("$Self->{obj_dir}/Vt_var_pins_sc64.sp", qr/sc_in<uint32_t> \s+ i32;/x);
file_grep ("$Self->{obj_dir}/Vt_var_pins_sc64.sp", qr/sc_in<uint64_t> \s+ i64;/x);
file_grep ("$Self->{obj_dir}/Vt_var_pins_sc64.sp", qr/sc_in<sc_bv<65>\s> \s+ i65;/x);
file_grep ("$Self->{obj_dir}/$Self->{VM_PREFIX}.sp", qr/sc_in<bool> \s+ i1;/x);
file_grep ("$Self->{obj_dir}/$Self->{VM_PREFIX}.sp", qr/sc_in<uint32_t> \s+ i8;/x);
file_grep ("$Self->{obj_dir}/$Self->{VM_PREFIX}.sp", qr/sc_in<uint32_t> \s+ i16;/x);
file_grep ("$Self->{obj_dir}/$Self->{VM_PREFIX}.sp", qr/sc_in<uint32_t> \s+ i32;/x);
file_grep ("$Self->{obj_dir}/$Self->{VM_PREFIX}.sp", qr/sc_in<uint64_t> \s+ i64;/x);
file_grep ("$Self->{obj_dir}/$Self->{VM_PREFIX}.sp", qr/sc_in<sc_bv<65>\s> \s+ i65;/x);
file_grep ("$Self->{obj_dir}/Vt_var_pins_sc64.sp", qr/sc_out<bool> \s+ o1;/x);
file_grep ("$Self->{obj_dir}/Vt_var_pins_sc64.sp", qr/sc_out<uint32_t> \s+ o8;/x);
file_grep ("$Self->{obj_dir}/Vt_var_pins_sc64.sp", qr/sc_out<uint32_t> \s+ o16;/x);
file_grep ("$Self->{obj_dir}/Vt_var_pins_sc64.sp", qr/sc_out<uint32_t> \s+ o32;/x);
file_grep ("$Self->{obj_dir}/Vt_var_pins_sc64.sp", qr/sc_out<uint64_t> \s+ o64;/x);
file_grep ("$Self->{obj_dir}/Vt_var_pins_sc64.sp", qr/sc_out<sc_bv<65>\s> \s+ o65;/x);
file_grep ("$Self->{obj_dir}/$Self->{VM_PREFIX}.sp", qr/sc_out<bool> \s+ o1;/x);
file_grep ("$Self->{obj_dir}/$Self->{VM_PREFIX}.sp", qr/sc_out<uint32_t> \s+ o8;/x);
file_grep ("$Self->{obj_dir}/$Self->{VM_PREFIX}.sp", qr/sc_out<uint32_t> \s+ o16;/x);
file_grep ("$Self->{obj_dir}/$Self->{VM_PREFIX}.sp", qr/sc_out<uint32_t> \s+ o32;/x);
file_grep ("$Self->{obj_dir}/$Self->{VM_PREFIX}.sp", qr/sc_out<uint64_t> \s+ o64;/x);
file_grep ("$Self->{obj_dir}/$Self->{VM_PREFIX}.sp", qr/sc_out<sc_bv<65>\s> \s+ o65;/x);
}
ok(1);
+28
View File
@@ -0,0 +1,28 @@
#ifdef T_VAR_PINS_CC
# include "Vt_var_pins_cc.h"
#elif defined(T_VAR_PINS_SC1)
# include "Vt_var_pins_sc1.h"
#elif defined(T_VAR_PINS_SC2)
# include "Vt_var_pins_sc2.h"
#elif defined(T_VAR_PINS_SC32)
# include "Vt_var_pins_sc32.h"
#elif defined(T_VAR_PINS_SC64)
# include "Vt_var_pins_sc64.h"
#else
# error "Unknown test"
#endif
VM_PREFIX* tb = NULL;
double sc_time_stamp() {
return 0;
}
int main() {
Verilated::debug(0);
tb = new VM_PREFIX("tb");
cout << "*-* All Finished *-*" << endl;
tb->final();
return 0;
}