Compare commits

...
46 Commits
Author SHA1 Message Date
Wilson Snyder a8432ed4a4 Version bump 2012-03-07 22:50:13 -05:00
Wilson Snyder 04f910b747 Fix V3Tristate t_tri_select crash 2012-03-07 22:42:47 -05:00
Wilson Snyder 1c3de70155 Internals: Debug merge. No functional change 2012-03-07 21:48:02 -05:00
Wilson Snyder b73642f8a8 Report ENDLABEL on mismatching end labels, bug450. 2012-03-07 20:14:18 -05:00
Wilson Snyder 479b497528 Tests: Add new tests from Iztok Jeras, bug446, bug450. 2012-03-07 20:00:09 -05:00
Wilson Snyder 31b55d3844 Tests: Fix running different simulators simultaneously 2012-03-06 20:58:23 -05:00
Wilson Snyder dbf4e08d09 Tests 2012-03-06 20:12:47 -05:00
Wilson Snyder 274359e6ee Tests: Bit extraction from non-logic types 2012-03-04 17:17:57 -05:00
Wilson Snyder 8687dcbce1 Internals: Add isRanged, more debug. No functional change. 2012-03-04 16:18:41 -05:00
Wilson Snyder 03dfbdb7b1 Fix inheriting signed type across untyped parameters. 2012-03-03 21:03:34 -05:00
Wilson Snyder 3c8519f245 Fix inheriting real type across untyped parameters. 2012-03-03 16:29:06 -05:00
Wilson Snyder 4d2cc3ebdd Tests: New param value test 2012-03-03 15:44:56 -05:00
Wilson Snyder 6e2758ae26 Internals: Minor refactorings from dtype branch. No functional change. 2012-03-03 12:10:29 -05:00
Wilson Snyder 4637e06ad2 Fix backward widths in function output warning 2012-03-03 12:09:01 -05:00
Wilson Snyder 764399256c Internals: Rename gdb dump utilities, add fileline dump 2012-03-03 11:29:09 -05:00
Wilson Snyder f4ca4edc64 Debug: Add default .gdbinit file 2012-03-02 20:59:47 -05:00
Wilson Snyder 872a1216a7 Internals: Fix enum widthTotalBytes. 2012-03-02 06:58:19 -05:00
Wilson Snyder 8c75674591 Internals: V3Dead: Avoid iterating over vars we can't remove. 2012-02-29 23:05:11 -05:00
Wilson Snyder e6244ca204 Internals: Move dimension accessors from AstVar to AstNodeDType. 2012-02-28 21:33:17 -05:00
Wilson Snyder f540362e36 Fix expansion of back-slashed escaped macros, bug441. 2012-02-25 21:31:36 -05:00
Wilson Snyder 2be6699a6a Internals: Make covergroup parsing closer to normal types 2012-02-23 22:09:51 -05:00
Wilson Snyder 09c10492ab Fix hang on recursive substitution `defines, bug443. 2012-02-23 21:54:37 -05:00
Wilson Snyder c8e4b1fc84 Fix functions inside generate for block. 2012-02-21 22:23:06 -05:00
Wilson Snyder 0de7cece5b Fix hang when functions inside begin block. 2012-02-21 21:25:11 -05:00
Wilson Snyder a3413a6749 Merge branch 'master' of ssh://git-verilator-wsnyder/git/verilator 2012-02-21 08:03:07 -05:00
Wilson Snyder b104ab9491 Internals: AstRefDType points to type _below_ AstTyperef. No functional change 2012-02-21 07:27:17 -05:00
Wilson Snyder 269c5dce60 Internals: Use dtypeChgLogicBool(). No functional change. 2012-02-20 20:51:24 -05:00
Wilson Snyder a39c81c63f Internals: Remove width() on AstCaseItem. No functional change. 2012-02-20 16:48:52 -05:00
Wilson Snyder d699247269 Internals: In AstBasicDType avoid use of Range for constants. No functional change. 2012-02-20 11:48:31 -05:00
Wilson Snyder 7caafb4014 Internals: Use dtype functions; changes to integer to match spec 2012-02-20 09:55:20 -05:00
Wilson Snyder f1546abf09 Fix error when using UDPs without --bbox-unsup 2012-02-20 09:02:59 -05:00
Wilson Snyder 3083562f6f tests: Avoid massive make parallelism. 2012-02-17 21:40:52 -05:00
Wilson Snyder da2ee70462 Makefile: Print build done in right parallel spot 2012-02-16 20:39:13 -05:00
Wilson Snyder 7e9dda3c5e Fix false command not found warning in Makefiles. 2012-02-16 07:17:08 -05:00
Wilson Snyder 0b96f88875 Fix bisonpre documentation 2012-02-12 20:53:43 -05:00
Wilson Snyder f13ffe2098 Internals: Merge from VHDL branch. Minor stuff, no functional change. 2012-02-11 20:40:58 -05:00
Wilson Snyder bca5d26583 Backout ca927fe5; snps isn't supported in DC. 2012-02-10 22:36:19 -05:00
Wilson Snyder 660bc757f1 Tests: Remove debug 2012-02-04 20:00:36 -05:00
Wilson Snyder ca927fe587 Support snps directives 2012-02-02 10:26:45 -05:00
Wilson Snyder 9df8966f4a Support arrayed SystemC I/O pins. 2012-02-01 20:20:43 -05:00
Wilson Snyder 3429f41489 Typo 2012-01-29 18:26:39 -05:00
Wilson Snyder 0c7c4924ee Fix core dump with over 100 deep UNOPTFLAT, bug432. 2012-01-26 20:20:23 -05:00
Wilson Snyder 8f40d6617e For generated variables, opt towards 2-state so zero init 2012-01-26 08:29:55 -05:00
Wilson Snyder af9e85bda1 Fix memory delayed assignments from multiple clock domains. 2012-01-26 08:10:50 -05:00
Wilson Snyder 717f45d117 Devel version 2012-01-25 19:23:58 -05:00
Wilson Snyder 35c53865fb Check c style array 2012-01-25 19:23:41 -05:00
93 changed files with 2340 additions and 476 deletions
+23
View File
@@ -4,6 +4,29 @@ The contributors that suggested a given feature are shown in []. [by ...]
indicates the contributor was also the author of the fix; Thanks!
* Verilator 3.832 2012/03/07
*** Fix memory delayed assignments from multiple clock domains. [Andrew Ling]
*** Support arrayed SystemC I/O pins. [Christophe Joly]
*** Report MULTIDRIVEN on memories set in multiple clock domains.
*** Report ENDLABEL on mismatching end labels, bug450. [Iztok Jeras]
**** Fix expansion of back-slashed escaped macros, bug441. [Alberto Del Rio]
**** Fix inheriting real and signed type across untyped parameters.
**** Fix core dump with over 100 deep UNOPTFLAT, bug432. [Joe Eiler]
**** Fix false command not found warning in makefiles. [Ruben Diez]
**** Fix hang when functions inside begin block. [David Welch]
**** Fix hang on recursive substitution `defines, bug443. [Alex Solomatnikov]
* Verilator 3.831 2012/01/20
** Support SystemC 2.3.0 prerelease. This requires setting the new
+1
View File
@@ -1,5 +1,6 @@
^CVS/
/CVS/
\.gdbinit$
\.git/
\.svn/
\.(bak|old)/
+1 -1
View File
@@ -164,7 +164,7 @@ verilator_exe verilator_bin verilator_bin_dbg:
(cd src && $(MAKE) $(OBJCACHE_JOBS) )
.PHONY:msg_test
msg_test:
msg_test: all_nomsg
@echo "Build complete!"
@echo
@echo "Type 'make test' to test."
+16 -8
View File
@@ -905,9 +905,9 @@ Disable the specified warning message.
Disable all lint related warning messages, and all style warnings. This is
equivalent to "-Wno-CASEINCOMPLETE -Wno-CASEOVERLAP -Wno-CASEX
-Wno-CASEWITHX -Wno-CMPCONST -Wno-IMPLICIT -Wno-LITENDIAN -Wno-SYNCASYNCNET
-Wno-UNDRIVEN -Wno-UNSIGNED -Wno-UNUSED -Wno-WIDTH" plus the list shown for
Wno-style.
-Wno-CASEWITHX -Wno-CMPCONST -Wno-ENDLABEL -Wno-IMPLICIT -Wno-LITENDIAN
-Wno-SYNCASYNCNET -Wno-UNDRIVEN -Wno-UNSIGNED -Wno-UNUSED -Wno-WIDTH" plus
the list shown for Wno-style.
It is strongly recommended you cleanup your code rather than using this
option, it is only intended to be use when running test-cases of code
@@ -937,8 +937,8 @@ Enables the specified warning message.
Enable all lint related warning messages (note by default they are already
enabled), but do not affect style messages. This is equivalent to
"-Wwarn-CASEINCOMPLETE -Wwarn-CASEOVERLAP -Wwarn-CASEX -Wwarn-CASEWITHX
-Wwarn-CMPCONST -Wwarn-IMPLICIT -Wwarn-LITENDIAN -Wwarn-REALCVT
-Wwarn-UNSIGNED -Wwarn-WIDTH".
-Wwarn-CMPCONST -Wwarn-ENDLABEL -Wwarn-IMPLICIT -Wwarn-LITENDIAN
-Wwarn-REALCVT -Wwarn-UNSIGNED -Wwarn-WIDTH".
=item -Wwarn-style
@@ -1747,9 +1747,9 @@ assertion clocks.
=head2 Synthesis Directive Assertion Support
With the --assert switch, Verilator reads any "//synopsys full_case" or "//
synopsys parallel_case" directives. The same applies to any "// ambit
synthesis", "//cadence" or "//pragma" directives of the same form.
With the --assert switch, Verilator reads any "//synopsys full_case" or
"//synopsys parallel_case" directives. The same applies to any
"//ambit synthesis", "//cadence" or "//pragma" directives of the same form.
When these synthesis directives are discovered, Verilator will either
formally prove the directive to be true, or failing that, will insert the
@@ -2585,6 +2585,14 @@ designs should now be using the #(...) format to specify parameters.
Disabled by default as this is a code style warning; it will simulate
correctly.
=item ENDLABEL
Warns that a label attached to a "end"-something statement does not match
the label attached to the block start.
Ignoring this warning will only suppress the lint check, it will simulate
correctly.
=item GENCLK
Warns that the specified signal is generated, but is also being used as a
+1 -1
View File
@@ -193,5 +193,5 @@ C<verilator>
######################################################################
### Local Variables:
### compile-command: "$V4/bin/verilator_difftree $V4/test_c/obj_dir/V*_03_*.tree $V4N/test_c/obj_dir/V*_03_*.tree"
### compile-command: "$V4/bin/verilator_difftree {$V4D,$V4}/test_regress/obj_dir/t_EXAMPLE/V*_03_*.tree"
### End:
+1 -1
View File
@@ -4,7 +4,7 @@
# redistribute it and/or modify it under the terms of either the GNU Lesser
# General Public License Version 3 or the Perl Artistic License Version 2.0.
AC_INIT([Verilator],[3.831 2012-01-20])
AC_INIT([Verilator],[3.832 2012-03-07])
AC_CONFIG_HEADER(src/config_build.h)
AC_CONFIG_FILES(Makefile src/Makefile src/Makefile_obj include/verilated.mk)
+5
View File
@@ -247,6 +247,11 @@ what made a <e####> line in the tree dumps):
watch AstNode::s_editCntGbl==####
To print a node:
call nodep->dumpGdb() # aliased to "pn" in .gdbinit
call nodep->dumpTreeGdb() # aliased to "pnt" in .gdbinit
=head1 DISTRIBUTION
The latest version is available from L<http://www.veripool.org/>.
+23 -1
View File
@@ -13,6 +13,7 @@ use vars qw ($Debug);
# main
our $Opt_Stage = 0;
our $Opt_Jobs = calc_jobs();
autoflush STDOUT 1;
autoflush STDERR 1;
@@ -21,11 +22,13 @@ if (! GetOptions (
"debug" => sub { $Debug = 1; },
"<>" => sub { die "%Error: Unknown parameter: $_[0]\n"; },
"stage=i" => \$Opt_Stage,
"j=i" => \$Opt_Jobs,
)) {
die "%Error: Bad usage, try 'install_test --help'\n";
}
test();
exit(0);
#######################################################################
@@ -47,7 +50,7 @@ sub test {
run("/bin/rm -rf $blddir");
run("/bin/mkdir -p $blddir");
run("cd $blddir && $srcdir/configure --prefix $prefix");
run("cd $blddir && make -j");
run("cd $blddir && make -j $Opt_Jobs");
}
# Install it under the prefix
@@ -121,6 +124,16 @@ sub cleanenv {
#######################################################################
sub calc_jobs {
my $ok = eval "
use Unix::Processors;
return Unix::Processors->new->max_online;
";
$ok && !$@ or return 1;
print "driver.pl: Found $ok cores, using -j ",$ok+1,"\n" if $Debug;
return $ok + 1;
}
sub run {
# Run a system command, check errors
my $command = shift;
@@ -157,6 +170,15 @@ required.
Displays this message and program version and exits.
=item -j I<jobs>
Specify make -j flag. Defaults to number of cores + 1 if Perl's
Unix::Processors is installed, else 1.
=item -stage I<stage>
Runs a specific test stage (see the script).
=back
=head1 DISTRIBUTION
+20
View File
@@ -0,0 +1,20 @@
# DESCRIPTION: Verilator: GDB startup file with useful defines
#
# Copyright 2012-2012 by Wilson Snyder. This program is free software; you can
# redistribute it and/or modify it under the terms of either the GNU
# Lesser General Public License Version 3 or the Perl Artistic License
# Version 2.0.
define pn
call $arg0->dumpGdb()
end
document pn
Verilator: Print single AstNode NODEP
end
define pnt
call $arg0->dumpTreeGdb()
end
document pnt
Verilator: Print AstNode NODEP's tree
end
+1 -1
View File
@@ -27,7 +27,7 @@ config_srcdir = @srcdir@
ifeq ($(config_srcdir),.)
srcdir = ..
else # Run an experiment
ifeq ($(shell -e $(config_srcdir)/../Makefile_obj.in),)
ifeq ($(wildcard $(config_srcdir)/../Makefile_obj.in),)
srcdir = $(config_srcdir)
else
srcdir = $(config_srcdir)/..
+18 -1
View File
@@ -245,7 +245,7 @@ inline void AstNode::debugTreeChange(const char* prefix, int lineno, bool next)
// Called on all major tree changers.
// Only for use for those really nasty bugs relating to internals
// Note this may be null.
//if (debug()) cout<<"-treeChange: V3Ast.cpp:"<<lineno<<" Tree Change for "<<prefix<<": "<<(void*)this<<endl;
//if (debug()) cout<<"-treeChange: V3Ast.cpp:"<<lineno<<" Tree Change for "<<prefix<<": "<<(void*)this<<" <e"<<AstNode::s_editCntGbl<<">"<<endl;
//if (debug()) {
// cout<<"-treeChange: V3Ast.cpp:"<<lineno<<" Tree Change for "<<prefix<<endl;
// v3Global.rootp()->dumpTree(cout,"-treeChange: ");
@@ -719,6 +719,7 @@ void AstNode::deleteTree() {
if (!this) return;
UASSERT(m_backp==NULL,"Delete called on node with backlink still set\n");
this->debugTreeChange("-delTree: ", __LINE__, true);
this->editCountInc();
// MUST be depth first!
deleteTreeIter();
}
@@ -947,6 +948,22 @@ void AstNode::checkTree() {
}
}
void AstNode::dumpGdb() { // For GDB only
if (!this) { cout<<"This=NULL"<<endl; return; }
dumpGdbHeader();
cout<<" "; dump(cout); cout<<endl;
}
void AstNode::dumpTreeGdb() { // For GDB only
if (!this) { cout<<"This=NULL"<<endl; return; }
dumpGdbHeader();
dumpTree(cout);
}
void AstNode::dumpGdbHeader() const { // For GDB only
if (!this) { cout<<"This=NULL"<<endl; return; }
dumpPtrs(cout);
cout<<" Fileline = "<<fileline()<<endl;
}
void AstNode::dumpPtrs(ostream& os) const {
os<<"This="<<typeName()<<" "<<(void*)this;
os<<" back="<<(void*)backp();
+32 -9
View File
@@ -29,6 +29,7 @@
#include "V3Global.h"
#include <vector>
#include <cmath>
#include <map>
#include "V3Ast__gen_classes.h" // From ./astgen
// Things like:
@@ -36,6 +37,7 @@
// Hint class so we can choose constructors
class AstLogicPacked {};
class AstBitPacked {};
//######################################################################
@@ -289,11 +291,13 @@ public:
case INTEGER: return 32;
case LOGIC: return 1;
case LONGINT: return 64;
case DOUBLE: return 64;
case FLOAT: return 32;
case DOUBLE: return 64; // opaque
case FLOAT: return 32; // opaque
case SHORTINT: return 16;
case TIME: return 64;
case STRING: return 64; // Just the pointer, for today
case STRING: return 64; // opaque // Just the pointer, for today
case SCOPEPTR: return 0; // opaque
case CHARPTR: return 0; // opaque
default: return 0;
}
}
@@ -310,7 +314,7 @@ public:
bool isSloppy() const { // Don't be as anal about width warnings
return !(m_e==LOGIC || m_e==BIT);
}
bool isBitLogic() const { // Don't be as anal about width warnings
bool isBitLogic() const { // Bit/logic vector types; can form a packed array
return (m_e==LOGIC || m_e==BIT);
}
bool isDpiUnsupported() const {
@@ -331,7 +335,7 @@ public:
enum AstSignedState {
// This can't be in the fancy class as the lexer union will get upset
signedst_NOP=0, signedst_SIGNED=1, signedst_UNSIGNED=2
signedst_NOSIGNED=0, signedst_UNSIGNED=1, signedst_SIGNED=2
};
//######################################################################
@@ -860,16 +864,17 @@ public:
void numericFrom(AstNode* fromp) { numeric(fromp->numeric()); }
void numeric(AstNumeric flag) { m_numeric = (int)flag; if (flag.isDouble()) width(64,64); }
AstNumeric numeric() const { return AstNumeric(m_numeric); }
bool isDouble() const { return numeric().isDouble(); }
bool isSigned() const { return numeric().isSigned(); }
void isSigned(bool flag) { numeric(flag ? AstNumeric::SIGNED : AstNumeric::UNSIGNED); }
bool isUnsigned() const { return numeric().isUnsigned(); }
void didWidth(bool flag) { m_didWidth=flag; }
bool didWidth() const { return m_didWidth; }
bool didWidthAndSet() { if (didWidth()) return true; didWidth(true); return false;}
void doingWidth(bool flag) { m_doingWidth=flag; }
bool doingWidth() const { return m_doingWidth; }
bool isQuad() const { return (width()>VL_WORDSIZE && width()<=VL_QUADSIZE); }
bool isWide() const { return (width()>VL_QUADSIZE); }
bool isDouble() const;
bool isSigned() const;
AstNUser* user1p() const {
// Slows things down measurably, so disabled by default
@@ -933,12 +938,17 @@ public:
bool isAllOnesV(); // Verilog width rules apply
// METHODS - data type changes especially for initial creation
void dtypeChgBool() { numeric(AstNumeric::UNSIGNED); width(1,1); }
void dtypeChgLogicBool() { numeric(AstNumeric::UNSIGNED); width(1,1); }
void dtypeChgDouble() { numeric(AstNumeric::DOUBLE); }
void dtypeChgSigned32() { numeric(AstNumeric::SIGNED); width(VL_WORDSIZE,VL_WORDSIZE); }
void dtypeChgUInt32() { numeric(AstNumeric::UNSIGNED); width(VL_WORDSIZE,VL_WORDSIZE); }
void dtypeChgUInt64() { numeric(AstNumeric::UNSIGNED); width(VL_QUADSIZE,VL_QUADSIZE); }
// METHODS - dump and error
void v3errorEnd(ostringstream& str) const;
virtual void dump(ostream& str=cout);
void dumpGdb(); // For GDB only
void dumpGdbHeader() const;
// METHODS - Tree modifications
AstNode* addNext(AstNode* newp); // Returns this, adds to end of list
@@ -963,6 +973,7 @@ public:
void checkTree(); // User Interface version
void dumpPtrs(ostream& str=cout) const;
void dumpTree(ostream& str=cout, const string& indent=" ", int maxDepth=0);
void dumpTreeGdb(); // For GDB only
void dumpTreeAndNext(ostream& str=cout, const string& indent=" ", int maxDepth=0);
void dumpTreeFile(const string& filename, bool append=false);
@@ -1261,16 +1272,18 @@ private:
string m_name; // Name of variable
string m_hiername; // Scope converted into name-> for emitting
bool m_hierThis; // Hiername points to "this" function
void init();
public:
AstNodeVarRef(FileLine* fl, const string& name, bool lvalue)
: AstNodeMath(fl), m_lvalue(lvalue), m_varp(NULL), m_varScopep(NULL),
m_packagep(NULL), m_name(name), m_hierThis(false) {
init();
}
AstNodeVarRef(FileLine* fl, const string& name, AstVar* varp, bool lvalue)
: AstNodeMath(fl), m_lvalue(lvalue), m_varp(varp), m_varScopep(NULL),
m_packagep(NULL), m_name(name), m_hierThis(false) {
// May have varp==NULL
if (m_varp) widthSignedFrom((AstNode*)m_varp);
init();
}
ASTNODE_BASE_FUNCS(NodeVarRef)
virtual bool broken() const;
@@ -1318,10 +1331,15 @@ struct AstNodeDType : public AstNode {
AstNodeDType(FileLine* fl) : AstNode(fl) {}
ASTNODE_BASE_FUNCS(NodeDType)
// Accessors
virtual void dump(ostream& str);
virtual AstBasicDType* basicp() const = 0; // (Slow) recurse down to find basic data type
virtual AstNodeDType* skipRefp() const = 0; // recurses over typedefs to next non-typeref type
virtual int widthAlignBytes() const = 0; // (Slow) recurses - Structure alignment 1,2,4 or 8 bytes (arrays affect this)
virtual int widthTotalBytes() const = 0; // (Slow) recurses - Width in bytes rounding up 1,2,4,8,12,...
virtual bool maybePointedTo() const { return true; }
AstNodeDType* dtypeDimensionp(int depth);
pair<uint32_t,uint32_t> dimensions();
uint32_t arrayElements(); // 1, or total multiplication of all dimensions
};
struct AstNodeSel : public AstNodeBiop {
@@ -1497,10 +1515,15 @@ public:
//######################################################################
// Inline ACCESSORS
inline bool AstNode::isDouble() const { return numeric().isDouble(); }
inline bool AstNode::isSigned() const { return numeric().isSigned(); }
inline bool AstNode::isZero() { return (this->castConst() && this->castConst()->num().isEqZero()); }
inline bool AstNode::isNeqZero() { return (this->castConst() && this->castConst()->num().isNeqZero()); }
inline bool AstNode::isOne() { return (this->castConst() && this->castConst()->num().isEqOne()); }
inline bool AstNode::isAllOnes() { return (this->castConst() && this->castConst()->isEqAllOnes()); }
inline bool AstNode::isAllOnesV() { return (this->castConst() && this->castConst()->isEqAllOnesV()); }
inline void AstNodeVarRef::init() { if (m_varp) widthSignedFrom((AstNode*)m_varp); }
#endif // Guard
+25 -21
View File
@@ -245,7 +245,7 @@ string AstVar::scType() const {
}
}
AstNodeDType* AstVar::dtypeDimensionp(int dimension) const {
AstNodeDType* AstNodeDType::dtypeDimensionp(int dimension) {
// dimension passed from AstArraySel::dimension
// Dimension 0 means the VAR itself, 1 is the closest SEL to the AstVar,
// which is the lowest in the dtype list.
@@ -258,7 +258,7 @@ AstNodeDType* AstVar::dtypeDimensionp(int dimension) const {
// *or* VAR a (ARRAYSEL0 (ARRAYSEL1 (ARRAYSEL2 (ARRAYSEL3 (DT))))
// SEL1 needs to select from entire variable which is a pointer to ARRAYSEL0
int dim = 0;
for (AstNodeDType* dtypep=this->dtypep(); dtypep; ) {
for (AstNodeDType* dtypep=this; dtypep; ) {
dtypep = dtypep->skipRefp(); // Skip AstRefDType/AstTypedef, or return same node
if (AstArrayDType* adtypep = dtypep->castArrayDType()) {
if ((dim++)==dimension) {
@@ -269,7 +269,7 @@ AstNodeDType* AstVar::dtypeDimensionp(int dimension) const {
}
else if (AstBasicDType* adtypep = dtypep->castBasicDType()) {
// AstBasicDType - nothing below, return null
if (adtypep->rangep()) {
if (adtypep->isRanged()) {
if ((dim++) == dimension) {
return adtypep;
}
@@ -282,9 +282,9 @@ AstNodeDType* AstVar::dtypeDimensionp(int dimension) const {
return NULL;
}
uint32_t AstVar::arrayElements() const {
uint32_t AstNodeDType::arrayElements() {
uint32_t entries=1;
for (AstNodeDType* dtypep=this->dtypep(); dtypep; ) {
for (AstNodeDType* dtypep=this; dtypep; ) {
dtypep = dtypep->skipRefp(); // Skip AstRefDType/AstTypedef, or return same node
if (AstArrayDType* adtypep = dtypep->castArrayDType()) {
entries *= adtypep->elementsConst();
@@ -298,11 +298,11 @@ uint32_t AstVar::arrayElements() const {
return entries;
}
pair<uint32_t,uint32_t> AstVar::dimensions() const {
pair<uint32_t,uint32_t> AstNodeDType::dimensions() {
// How many array dimensions (packed,unpacked) does this Var have?
uint32_t packed = 0;
uint32_t unpacked = 0;
for (AstNodeDType* dtypep=this->dtypep(); dtypep; ) {
for (AstNodeDType* dtypep=this; dtypep; ) {
dtypep = dtypep->skipRefp(); // Skip AstRefDType/AstTypedef, or return same node
if (AstArrayDType* adtypep = dtypep->castArrayDType()) {
if (adtypep->isPacked()) packed += 1;
@@ -496,21 +496,21 @@ void AstWhile::addNextStmt(AstNode* newp, AstNode* belowp) {
//======================================================================
// Per-type Debugging
void AstNode::dump(ostream& os) {
os<<typeName()<<" "<<(void*)this
void AstNode::dump(ostream& str) {
str<<typeName()<<" "<<(void*)this
//<<" "<<(void*)this->m_backp
<<" <e"<<dec<<editCount()
<<((editCount()>=editCountLast())?"#>":">")
<<" {"<<fileline()->filenameLetters()<<dec<<fileline()->lineno()<<"}"
<<" "<<(isSigned()?"s":"")
<<(isDouble()?"d":"")
<<"w"<<(widthSized()?"":"u")<<width();
if (!widthSized()) os<<"/"<<widthMin();
if (name()!="") os<<" "<<AstNode::quoteName(name());
<<" <e"<<dec<<editCount()
<<((editCount()>=editCountLast())?"#>":">")
<<" {"<<fileline()->filenameLetters()<<dec<<fileline()->lineno()<<"}"
<<" "<<(isSigned()?"s":"")
<<(isDouble()?"d":"")
<<"w"<<(widthSized()?"":"u")<<width();
if (!widthSized()) str<<"/"<<widthMin();
if (name()!="") str<<" "<<AstNode::quoteName(name());
}
void AstArrayDType::dump(ostream& str) {
this->AstNode::dump(str);
this->AstNodeDType::dump(str);
if (isPacked()) str<<" [PACKED]";
}
void AstArraySel::dump(ostream& str) {
@@ -522,8 +522,9 @@ void AstAttrOf::dump(ostream& str) {
str<<" ["<<attrType().ascii()<<"]";
}
void AstBasicDType::dump(ostream& str) {
this->AstNode::dump(str);
str<<" ["<<keyword().ascii()<<"]";
this->AstNodeDType::dump(str);
str<<" kwd="<<keyword().ascii();
if (isRanged() && !rangep()) str<<" range=["<<msb()<<":"<<lsb()<<"]";
if (implicit()) str<<" [IMPLICIT]";
}
void AstCCast::dump(ostream& str) {
@@ -566,7 +567,7 @@ void AstRange::dump(ostream& str) {
if (littleEndian()) str<<" [LITTLE]";
}
void AstRefDType::dump(ostream& str) {
this->AstNode::dump(str);
this->AstNodeDType::dump(str);
if (defp()) { str<<" -> "; defp()->dump(str); }
else { str<<" -> UNLINKED"; }
}
@@ -580,6 +581,9 @@ void AstVarXRef::dump(ostream& str) {
else if (varp()) { varp()->dump(str); }
else { str<<"UNLINKED"; }
}
void AstNodeDType::dump(ostream& str) {
this->AstNode::dump(str);
}
void AstNodeModule::dump(ostream& str) {
this->AstNode::dump(str);
str<<" L"<<level();
+123 -83
View File
@@ -48,11 +48,14 @@ private:
public:
AstConst(FileLine* fl, const V3Number& num)
:AstNodeMath(fl)
,m_num(num) {
width(m_num.width(), m_num.sized()?0:m_num.widthMin());
numeric(m_num.isDouble() ? AstNumeric::DOUBLE
: m_num.isSigned() ? AstNumeric::SIGNED
: AstNumeric::UNSIGNED);
,m_num(num) {
if (m_num.isDouble()) {
dtypeChgDouble();
} else {
width(m_num.width(), m_num.sized()?0:m_num.widthMin());
numeric(m_num.isSigned() ? AstNumeric::SIGNED
: AstNumeric::UNSIGNED);
}
}
AstConst(FileLine* fl, uint32_t num)
:AstNodeMath(fl)
@@ -68,11 +71,11 @@ public:
class LogicFalse {};
AstConst(FileLine* fl, LogicFalse) // Shorthand const 0, know the dtype should be a logic of size 1
:AstNodeMath(fl)
,m_num(V3Number(fl,1,0)) { width(1,0); }
,m_num(V3Number(fl,1,0)) { dtypeChgLogicBool(); }
class LogicTrue {};
AstConst(FileLine* fl, LogicTrue) // Shorthand const 1, know the dtype should be a logic of size 1
:AstNodeMath(fl)
,m_num(V3Number(fl,1,1)) { width(1,0); }
,m_num(V3Number(fl,1,1)) { dtypeChgLogicBool(); }
ASTNODE_NODE_FUNCS(Const, CONST)
virtual string name() const { return num().ascii(); } // * = Value
@@ -212,7 +215,7 @@ public:
struct AstArrayDType : public AstNodeDType {
// Array data type, ie "some_dtype var_name [2:0]"
private:
bool m_packed;
bool m_packed;
public:
AstArrayDType(FileLine* fl, AstNodeDType* dtp, AstRange* rangep, bool isPacked=false)
: AstNodeDType(fl), m_packed(isPacked) {
@@ -241,33 +244,47 @@ public:
struct AstBasicDType : public AstNodeDType {
// Builtin atomic/vectored data type
// Children: RANGE (converted to constant in V3Width)
private:
AstBasicDTypeKwd m_keyword; // What keyword created it
bool m_implicit; // Implicitly declared
bool m_nosigned; // Implicit without sign
int m_msb; // MSB when no range attached
public:
AstBasicDType(FileLine* fl, AstBasicDTypeKwd kwd, AstSignedState signst=signedst_NOP)
AstBasicDType(FileLine* fl, AstBasicDTypeKwd kwd, AstSignedState signst=signedst_NOSIGNED)
: AstNodeDType(fl) {
init(kwd, signst, NULL);
init(kwd, signst, 0, NULL);
}
AstBasicDType(FileLine* fl, AstLogicPacked, int wantwidth)
: AstNodeDType(fl) {
init(AstBasicDTypeKwd::LOGIC, signedst_NOP,
((wantwidth > 1) ? new AstRange(fl, wantwidth-1, 0) : NULL));
init(AstBasicDTypeKwd::LOGIC, signedst_NOSIGNED, wantwidth, NULL);
}
AstBasicDType(FileLine* fl, AstBitPacked, int wantwidth)
: AstNodeDType(fl) {
init(AstBasicDTypeKwd::BIT, signedst_NOSIGNED, wantwidth, NULL);
}
// See also addRange in verilog.y
private:
void init(AstBasicDTypeKwd kwd, AstSignedState signst, AstRange* rangep) {
void init(AstBasicDTypeKwd kwd, AstSignedState signst, int wantwidth, AstRange* rangep) {
m_keyword = kwd;
m_msb = 0;
// Implicitness: // "parameter X" is implicit and sized from initial value, "parameter reg x" not
m_implicit = false;
m_nosigned = false;
if (keyword()==AstBasicDTypeKwd::LOGIC_IMPLICIT) {
if (!rangep) m_implicit = true; // Also cleared if range added later
if (!rangep && !wantwidth) m_implicit = true; // Also cleared if range added later
m_keyword = AstBasicDTypeKwd::LOGIC;
}
if (signst == signedst_NOP && keyword().isSigned()) signst = signedst_SIGNED;
if (signst == signedst_NOSIGNED) {
if (keyword().isSigned()) signst = signedst_SIGNED;
else m_nosigned = true;
}
if (keyword().isDouble()) dtypeChgDouble();
else setSignedState(signst);
if (!rangep) { // Set based on keyword properties
if (!rangep && wantwidth) { // Constant width
m_msb = wantwidth - 1;
width(wantwidth, wantwidth);
} else if (!rangep) { // Set based on keyword properties
// V3Width will pull from this width
if (keyword().width() > 1 && !isOpaque()) rangep = new AstRange(fileline(), keyword().width()-1, 0);
width(keyword().width(), keyword().width());
@@ -296,17 +313,21 @@ public:
virtual int widthTotalBytes() const; // (Slow) recurses - Width in bytes rounding up 1,2,4,8,12,...
AstBasicDTypeKwd keyword() const { return m_keyword; } // Avoid using - use isSomething accessors instead
bool isBitLogic() const { return keyword().isBitLogic(); }
bool isDouble() const { return keyword().isDouble(); }
bool isOpaque() const { return keyword().isOpaque(); }
bool isSloppy() const { return keyword().isSloppy(); }
bool isZeroInit() const { return keyword().isZeroInit(); }
int msb() const { if (!rangep()) return 0; return rangep()->msbConst(); }
bool isRanged() const { return rangep() || m_msb; }
int msb() const { if (!rangep()) return m_msb; return rangep()->msbConst(); }
int lsb() const { if (!rangep()) return 0; return rangep()->lsbConst(); }
int msbEndianed() const { if (!rangep()) return 0; return littleEndian()?rangep()->lsbConst():rangep()->msbConst(); }
int msbEndianed() const { if (!rangep()) return m_msb; return littleEndian()?rangep()->lsbConst():rangep()->msbConst(); }
int lsbEndianed() const { if (!rangep()) return 0; return littleEndian()?rangep()->msbConst():rangep()->lsbConst(); }
int msbMaxSelect() const { return (lsb()<0 ? msb()-lsb() : msb()); } // Maximum value a [] select may index
bool littleEndian() const { return (rangep() && rangep()->littleEndian()); }
bool implicit() const { return m_implicit; }
void implicit(bool flag) { m_implicit = flag; }
bool nosigned() const { return m_nosigned; }
void cvtRangeConst() {} // Convert to smaller represenation - disabled
};
struct AstConstDType : public AstNodeDType {
@@ -330,43 +351,43 @@ struct AstConstDType : public AstNodeDType {
struct AstRefDType : public AstNodeDType {
private:
AstTypedef* m_defp;
string m_name;
AstNodeDType* m_defp; // data type pointed to, BELOW the AstTypedef
string m_name; // Name of an AstTypedef
AstPackage* m_packagep; // Package hierarchy
public:
AstRefDType(FileLine* fl, const string& name)
: AstNodeDType(fl), m_defp(NULL), m_name(name), m_packagep(NULL) {}
AstRefDType(FileLine* fl, AstTypedef* defp)
: AstNodeDType(fl), m_defp(defp), m_name(defp->name()), m_packagep(NULL) {
AstRefDType(FileLine* fl, AstNodeDType* defp)
: AstNodeDType(fl), m_defp(defp), m_packagep(NULL) {
widthSignedFrom(defp);
}
ASTNODE_NODE_FUNCS(RefDType, REFDTYPE)
// METHODS
virtual bool broken() const { return m_defp && !m_defp->brokeExists(); }
virtual void cloneRelink() { if (m_defp && m_defp->clonep()) {
m_defp = m_defp->clonep()->castTypedef();
m_defp = m_defp->clonep()->castNodeDType();
}}
virtual V3Hash sameHash() const { return V3Hash(skipRefp()); }
virtual bool same(AstNode* samep) const {
return skipRefp()->sameTree(samep->castRefDType()->skipRefp()); }
virtual void dump(ostream& str=cout);
virtual string name() const { return m_name; }
virtual AstBasicDType* basicp() const { return defp() ? dtypep()->basicp() : NULL; }
virtual AstBasicDType* basicp() const { return defp() ? defp()->basicp() : NULL; }
virtual AstNodeDType* skipRefp() const {
// Skip past both the Ref and the Typedef
if (defp()) return defp()->dtypep()->skipRefp();
if (defp()) return defp()->skipRefp();
else { v3fatalSrc("Typedef not linked"); return NULL; }
}
virtual int widthAlignBytes() const { return dtypep()->widthAlignBytes(); }
virtual int widthTotalBytes() const { return dtypep()->widthTotalBytes(); }
virtual int widthAlignBytes() const { return dtypeSkipRefp()->widthAlignBytes(); }
virtual int widthTotalBytes() const { return dtypeSkipRefp()->widthTotalBytes(); }
void name(const string& flag) { m_name = flag; }
AstNodeDType* dtypep() const {
if (defp()) return defp()->dtypep();
if (defp()) return defp();
else { v3fatalSrc("Typedef not linked"); return NULL; }
}
AstNodeDType* dtypeSkipRefp() const { return dtypep()->skipRefp(); } // op1 = Range of variable
AstTypedef* defp() const { return m_defp; }
void defp(AstTypedef* nodep) { m_defp=nodep; }
AstNodeDType* dtypeSkipRefp() const { return defp()->skipRefp(); } // op1 = Range of variable
AstNodeDType* defp() const { return m_defp; }
void defp(AstNodeDType* nodep) { m_defp=nodep; }
AstPackage* packagep() const { return m_packagep; }
void packagep(AstPackage* nodep) { m_packagep=nodep; }
};
@@ -429,7 +450,7 @@ struct AstEnumDType : public AstNodeDType {
virtual AstBasicDType* basicp() const { return dtypep()->basicp(); } // (Slow) recurse down to find basic data type
virtual AstNodeDType* skipRefp() const { return dtypep()->skipRefp(); }
virtual int widthAlignBytes() const { return dtypep()->widthAlignBytes(); }
virtual int widthTotalBytes() const { return dtypep()->widthAlignBytes(); }
virtual int widthTotalBytes() const { return dtypep()->widthTotalBytes(); }
};
//######################################################################
@@ -440,14 +461,17 @@ struct AstArraySel : public AstNodeSel {
private:
unsigned m_start;
unsigned m_length;
void init(AstNode* fromp) {
if (fromp) widthSignedFrom(fromp);
}
public:
AstArraySel(FileLine* fl, AstNode* fromp, AstNode* bitp)
:AstNodeSel(fl, fromp, bitp), m_start(0), m_length(1) {
if (fromp) widthSignedFrom(fromp);
init(fromp);
}
AstArraySel(FileLine* fl, AstNode* fromp, int bit)
:AstNodeSel(fl, fromp, new AstConst(fl,bit)), m_start(0), m_length(1) {
if (fromp) widthSignedFrom(fromp);
init(fromp);
}
ASTNODE_NODE_FUNCS(ArraySel, ARRAYSEL)
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) {
@@ -476,7 +500,7 @@ struct AstWordSel : public AstNodeSel {
// Select a single word from a multi-word wide value
AstWordSel(FileLine* fl, AstNode* fromp, AstNode* bitp)
:AstNodeSel(fl, fromp, bitp) {
width(VL_WORDSIZE,VL_WORDSIZE); // Always used on, and returns word entities
dtypeChgUInt32(); // Always used on IData arrays so returns word entities
}
ASTNODE_NODE_FUNCS(WordSel, WORDSEL)
virtual void numberOperate(V3Number& out, const V3Number& from, const V3Number& bit) { V3ERROR_NA; }
@@ -535,7 +559,9 @@ struct AstSel : public AstNodeTriop {
// Children: varref|arraysel, math, constant math
AstSel(FileLine* fl, AstNode* fromp, AstNode* lsbp, AstNode* widthp)
:AstNodeTriop(fl, fromp, lsbp, widthp) {
if (widthp->castConst()) width(widthp->castConst()->toUInt(), widthp->castConst()->toUInt());
if (widthp->castConst()) {
width(widthp->castConst()->toUInt(), widthp->castConst()->toUInt());
}
}
AstSel(FileLine* fl, AstNode* fromp, int lsb, int bitwidth)
:AstNodeTriop(fl, fromp,
@@ -626,6 +652,14 @@ public:
setOp1p(new AstBasicDType(fl, AstLogicPacked(), wantwidth));
width(wantwidth,0);
}
AstVar(FileLine* fl, AstVarType type, const string& name, AstBitPacked, int wantwidth)
:AstNode(fl)
, m_name(name) {
init();
combineType(type);
setOp1p(new AstBasicDType(fl, AstBitPacked(), wantwidth));
width(wantwidth,0);
}
AstVar(FileLine* fl, AstVarType type, const string& name, AstVar* examplep)
:AstNode(fl)
, m_name(name) {
@@ -655,8 +689,6 @@ public:
AstNodeDType* dtypep() const { return op1p()->castNodeDType(); } // op1 = Range of variable
AstNodeDType* dtypeSkipRefp() const { return dtypep()->skipRefp(); } // op1 = Range of variable (Note don't need virtual - AstVar isn't a NodeDType)
AstBasicDType* basicp() const { return dtypep()->basicp(); } // (Slow) recurse down to find basic data type (Note don't need virtual - AstVar isn't a NodeDType)
AstNodeDType* dtypeDimensionp(int depth) const;
pair<uint32_t,uint32_t> dimensions() const;
AstNode* valuep() const { return op3p()->castNode(); } // op3 = Initial value that never changes (static const)
void valuep(AstNode* nodep) { setOp3p(nodep); } // It's valuep, not constp, as may be more complicated than an AstConst
void addAttrsp(AstNode* nodep) { addNOp4p(nodep); }
@@ -732,7 +764,6 @@ public:
bool attrScClocked() const { return m_scClocked; }
bool attrSFormat() const { return m_attrSFormat; }
bool attrIsolateAssign() const { return m_attrIsolateAssign; }
uint32_t arrayElements() const; // 1, or total multiplication of all dimensions
virtual string verilogKwd() const;
void propagateAttrFrom(AstVar* fromp) {
// This is getting connected to fromp; keep attributes
@@ -951,6 +982,14 @@ public:
setNOp1p(exprp);
if (exprp) widthSignedFrom(exprp);
}
AstPin(FileLine* fl, int pinNum, AstVarRef* varname, AstNode* exprp)
:AstNode(fl), m_svImplicit(false) {
m_name = varname->name();
m_pinNum = pinNum;
m_modVarp = NULL;
setNOp1p(exprp);
if (exprp) widthSignedFrom(exprp);
}
ASTNODE_NODE_FUNCS(Pin, PIN)
virtual void dump(ostream& str);
virtual bool broken() const { return (m_modVarp && !m_modVarp->brokeExists()); }
@@ -1280,7 +1319,7 @@ struct AstSenGate : public AstNodeSenItem {
// AND as applied to a sensitivity list and a gating expression
// Performing this gating is optional; it may be removed by later optimizations
AstSenGate(FileLine* fl, AstSenItem* sensesp, AstNode* rhsp) : AstNodeSenItem(fl) {
dtypeChgBool(); addOp1p(sensesp); setOp2p(rhsp);
dtypeChgLogicBool(); addOp1p(sensesp); setOp2p(rhsp);
}
ASTNODE_NODE_FUNCS(SenGate, SENGATE)
virtual string emitVerilog() { return "(%l) %f&& (%r)"; }
@@ -2176,7 +2215,8 @@ struct AstChangeXor : public AstNodeBiComAsv {
// Children: VARREF
AstChangeXor(FileLine* fl, AstNode* lhsp, AstNode* rhsp)
: AstNodeBiComAsv(fl, lhsp, rhsp) {
width(32,32); }
dtypeChgUInt32(); // Always used on, and returns word entities
}
ASTNODE_NODE_FUNCS(ChangeXor, CHANGEXOR)
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opChangeXor(lhs,rhs); }
virtual string emitVerilog() { return "%k(%l %f^ %r)"; }
@@ -2310,7 +2350,7 @@ public:
, m_showname(showname) {
widthSignedFrom(varp);
m_code = 0;
m_codeInc = varp->arrayElements() * varp->widthWords();
m_codeInc = varp->dtypep()->arrayElements() * varp->widthWords();
AstBasicDType* bdtypep = varp->basicp();
m_msb = bdtypep ? bdtypep->msbEndianed() : 0;
m_lsb = bdtypep ? bdtypep->lsbEndianed() : 0;
@@ -2326,8 +2366,8 @@ public:
ASTNODE_NODE_FUNCS(TraceDecl, TRACEDECL)
virtual string name() const { return m_showname; }
virtual bool maybePointedTo() const { return true; }
string showname() const { return m_showname; } // * = Var name
virtual bool same(AstNode* samep) const { return false; }
string showname() const { return m_showname; } // * = Var name
// Details on what we're tracing
uint32_t code() const { return m_code; }
void code(uint32_t code) { m_code=code; }
@@ -2434,7 +2474,7 @@ private:
bool m_dpiExport; // Is for dpiExport
public:
AstScopeName(FileLine* fl) : AstNodeMath(fl), m_dpiExport(false) {
width(64,64); }
dtypeChgUInt64(); }
ASTNODE_NODE_FUNCS(ScopeName, SCOPENAME)
virtual V3Hash sameHash() const { return V3Hash(); }
virtual bool same(AstNode* samep) const { return m_dpiExport==samep->castScopeName()->m_dpiExport; }
@@ -2495,7 +2535,7 @@ public:
struct AstTime : public AstNodeTermop {
AstTime(FileLine* fl) : AstNodeTermop(fl) {
width(64,64); }
dtypeChgUInt64(); }
ASTNODE_NODE_FUNCS(Time, TIME)
virtual string emitVerilog() { return "%f$time"; }
virtual string emitC() { return "VL_TIME_%nq()"; }
@@ -2571,7 +2611,7 @@ struct AstNegateD : public AstNodeUniop {
};
struct AstRedAnd : public AstNodeUniop {
AstRedAnd(FileLine* fl, AstNode* lhsp) : AstNodeUniop(fl, lhsp) {
dtypeChgBool(); }
dtypeChgLogicBool(); }
ASTNODE_NODE_FUNCS(RedAnd, REDAND)
virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.opRedAnd(lhs); }
virtual string emitVerilog() { return "%f(& %l)"; }
@@ -2581,7 +2621,7 @@ struct AstRedAnd : public AstNodeUniop {
};
struct AstRedOr : public AstNodeUniop {
AstRedOr(FileLine* fl, AstNode* lhsp) : AstNodeUniop(fl, lhsp) {
dtypeChgBool(); }
dtypeChgLogicBool(); }
ASTNODE_NODE_FUNCS(RedOr, REDOR)
virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.opRedOr(lhs); }
virtual string emitVerilog() { return "%f(| %l)"; }
@@ -2591,7 +2631,7 @@ struct AstRedOr : public AstNodeUniop {
};
struct AstRedXor : public AstNodeUniop {
AstRedXor(FileLine* fl, AstNode* lhsp) : AstNodeUniop(fl, lhsp) {
dtypeChgBool(); }
dtypeChgLogicBool(); }
ASTNODE_NODE_FUNCS(RedXor, REDXOR)
virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.opRedXor(lhs); }
virtual string emitVerilog() { return "%f(^ %l)"; }
@@ -2605,7 +2645,7 @@ struct AstRedXor : public AstNodeUniop {
struct AstRedXnor : public AstNodeUniop {
// AstRedXnors are replaced with AstRedXors in V3Const.
AstRedXnor(FileLine* fl, AstNode* lhsp) : AstNodeUniop(fl, lhsp) {
dtypeChgBool(); }
dtypeChgLogicBool(); }
ASTNODE_NODE_FUNCS(RedXnor, REDXNOR)
virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.opRedXnor(lhs); }
virtual string emitVerilog() { return "%f(~^ %l)"; }
@@ -2617,7 +2657,7 @@ struct AstRedXnor : public AstNodeUniop {
struct AstLogNot : public AstNodeUniop {
AstLogNot(FileLine* fl, AstNode* lhsp) : AstNodeUniop(fl, lhsp) {
dtypeChgBool(); }
dtypeChgLogicBool(); }
ASTNODE_NODE_FUNCS(LogNot, LOGNOT)
virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.opLogNot(lhs); }
virtual string emitVerilog() { return "%f(! %l)"; }
@@ -2689,7 +2729,7 @@ struct AstUnsigned : public AstNodeUniop {
struct AstRToIS : public AstNodeUniop {
// $rtoi(lhs)
AstRToIS(FileLine* fl, AstNode* lhsp) : AstNodeUniop(fl, lhsp) {
width(32,32); }
dtypeChgSigned32(); }
ASTNODE_NODE_FUNCS(RToIS, RTOIS)
virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.opRToIS(lhs); }
virtual string emitVerilog() { return "%f$rtoi(%l)"; }
@@ -2700,7 +2740,7 @@ struct AstRToIS : public AstNodeUniop {
};
struct AstRToIRoundS : public AstNodeUniop {
AstRToIRoundS(FileLine* fl, AstNode* lhsp) : AstNodeUniop(fl, lhsp) {
width(32,32); }
dtypeChgSigned32(); }
ASTNODE_NODE_FUNCS(RToIRoundS, RTOIROUNDS)
virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.opRToIRoundS(lhs); }
virtual string emitVerilog() { return "%f$rtoi_rounded(%l)"; }
@@ -2722,7 +2762,7 @@ struct AstIToRD : public AstNodeUniop {
};
struct AstRealToBits : public AstNodeUniop {
AstRealToBits(FileLine* fl, AstNode* lhsp) : AstNodeUniop(fl, lhsp) {
width(64,64); }
dtypeChgUInt64(); }
ASTNODE_NODE_FUNCS(RealToBits, REALTOBITS)
virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.opRealToBits(lhs); }
virtual string emitVerilog() { return "%f$realtobits(%l)"; }
@@ -2767,7 +2807,7 @@ struct AstCountOnes : public AstNodeUniop {
struct AstIsUnknown : public AstNodeUniop {
// True if any unknown bits
AstIsUnknown(FileLine* fl, AstNode* lhsp) : AstNodeUniop(fl, lhsp) {
dtypeChgBool(); }
dtypeChgLogicBool(); }
ASTNODE_NODE_FUNCS(IsUnknown, ISUNKNOWN)
virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.opIsUnknown(lhs); }
virtual string emitVerilog() { return "%f$isunknown(%l)"; }
@@ -2778,7 +2818,7 @@ struct AstIsUnknown : public AstNodeUniop {
struct AstOneHot : public AstNodeUniop {
// True if only single bit set in vector
AstOneHot(FileLine* fl, AstNode* lhsp) : AstNodeUniop(fl, lhsp) {
dtypeChgBool(); }
dtypeChgLogicBool(); }
ASTNODE_NODE_FUNCS(OneHot, ONEHOT)
virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.opOneHot(lhs); }
virtual string emitVerilog() { return "%f$onehot(%l)"; }
@@ -2790,7 +2830,7 @@ struct AstOneHot : public AstNodeUniop {
struct AstOneHot0 : public AstNodeUniop {
// True if only single bit, or no bits set in vector
AstOneHot0(FileLine* fl, AstNode* lhsp) : AstNodeUniop(fl, lhsp) {
dtypeChgBool(); }
dtypeChgLogicBool(); }
ASTNODE_NODE_FUNCS(OneHot0, ONEHOT0)
virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.opOneHot0(lhs); }
virtual string emitVerilog() { return "%f$onehot0(%l)"; }
@@ -2824,8 +2864,8 @@ public:
m_size=setwidth;
if (setwidth) { width(setwidth,setwidth); }
}
AstCCast(FileLine* fl, AstNode* lhsp, AstNode* widthFromp) : AstNodeUniop(fl, lhsp) {
if (widthFromp) { widthSignedFrom(widthFromp); }
AstCCast(FileLine* fl, AstNode* lhsp, AstNode* typeFromp) : AstNodeUniop(fl, lhsp) {
if (typeFromp) { widthSignedFrom(typeFromp); }
m_size=width();
}
ASTNODE_NODE_FUNCS(CCast, CCAST)
@@ -2844,7 +2884,7 @@ public:
struct AstCvtPackString : public AstNodeUniop {
// Convert to Verilator Packed Pack (aka Pack)
AstCvtPackString(FileLine* fl, AstNode* lhsp) : AstNodeUniop(fl, lhsp) {
width(64,64); } // Really, width should be dtypep -> STRING
dtypeChgUInt64(); } // Really, width should be dtypep -> STRING
ASTNODE_NODE_FUNCS(CvtPackString, CVTPACKSTRING)
virtual void numberOperate(V3Number& out, const V3Number& lhs) { V3ERROR_NA; }
virtual string emitVerilog() { return "%f$_CAST(%l)"; }
@@ -2969,7 +3009,7 @@ struct AstSqrtD : public AstNodeUniop {
struct AstLogOr : public AstNodeBiop {
AstLogOr(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiop(fl, lhsp, rhsp) {
dtypeChgBool(); }
dtypeChgLogicBool(); }
ASTNODE_NODE_FUNCS(LogOr, LOGOR)
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opLogOr(lhs,rhs); }
virtual string emitVerilog() { return "%k(%l %f|| %r)"; }
@@ -2982,7 +3022,7 @@ struct AstLogOr : public AstNodeBiop {
};
struct AstLogAnd : public AstNodeBiop {
AstLogAnd(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiop(fl, lhsp, rhsp) {
dtypeChgBool(); }
dtypeChgLogicBool(); }
ASTNODE_NODE_FUNCS(LogAnd, LOGAND)
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opLogAnd(lhs,rhs); }
virtual string emitVerilog() { return "%k(%l %f&& %r)"; }
@@ -2995,7 +3035,7 @@ struct AstLogAnd : public AstNodeBiop {
};
struct AstLogIf : public AstNodeBiop {
AstLogIf(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiop(fl, lhsp, rhsp) {
dtypeChgBool(); }
dtypeChgLogicBool(); }
ASTNODE_NODE_FUNCS(LogIf, LOGIF)
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { V3ERROR_NA; }
virtual string emitVerilog() { return "%k(%l %f-> %r)"; }
@@ -3008,7 +3048,7 @@ struct AstLogIf : public AstNodeBiop {
};
struct AstLogIff : public AstNodeBiCom {
AstLogIff(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiCom(fl, lhsp, rhsp) {
dtypeChgBool(); }
dtypeChgLogicBool(); }
ASTNODE_NODE_FUNCS(LogIff, LOGIFF)
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { V3ERROR_NA; }
virtual string emitVerilog() { return "%k(%l %f<-> %r)"; }
@@ -3069,7 +3109,7 @@ struct AstXnor : public AstNodeBiComAsv {
};
struct AstEq : public AstNodeBiCom {
AstEq(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiCom(fl, lhsp, rhsp) {
dtypeChgBool(); }
dtypeChgLogicBool(); }
ASTNODE_NODE_FUNCS(Eq, EQ)
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opEq(lhs,rhs); }
virtual string emitVerilog() { return "%k(%l %f== %r)"; }
@@ -3081,7 +3121,7 @@ struct AstEq : public AstNodeBiCom {
};
struct AstEqD : public AstNodeBiCom {
AstEqD(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiCom(fl, lhsp, rhsp) {
dtypeChgBool(); }
dtypeChgLogicBool(); }
ASTNODE_NODE_FUNCS(EqD, EQD)
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opEqD(lhs,rhs); }
virtual string emitVerilog() { return "%k(%l %f== %r)"; }
@@ -3095,7 +3135,7 @@ struct AstEqD : public AstNodeBiCom {
};
struct AstNeq : public AstNodeBiCom {
AstNeq(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiCom(fl, lhsp, rhsp) {
dtypeChgBool(); }
dtypeChgLogicBool(); }
ASTNODE_NODE_FUNCS(Neq, NEQ)
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opNeq(lhs,rhs); }
virtual string emitVerilog() { return "%k(%l %f!= %r)"; }
@@ -3107,7 +3147,7 @@ struct AstNeq : public AstNodeBiCom {
};
struct AstNeqD : public AstNodeBiCom {
AstNeqD(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiCom(fl, lhsp, rhsp) {
dtypeChgBool(); }
dtypeChgLogicBool(); }
ASTNODE_NODE_FUNCS(NeqD, NEQD)
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opNeqD(lhs,rhs); }
virtual string emitVerilog() { return "%k(%l %f!= %r)"; }
@@ -3121,7 +3161,7 @@ struct AstNeqD : public AstNodeBiCom {
};
struct AstLt : public AstNodeBiop {
AstLt(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiop(fl, lhsp, rhsp) {
dtypeChgBool(); }
dtypeChgLogicBool(); }
ASTNODE_NODE_FUNCS(Lt, LT)
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opLt(lhs,rhs); }
virtual string emitVerilog() { return "%k(%l %f< %r)"; }
@@ -3133,7 +3173,7 @@ struct AstLt : public AstNodeBiop {
};
struct AstLtD : public AstNodeBiop {
AstLtD(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiop(fl, lhsp, rhsp) {
dtypeChgBool(); }
dtypeChgLogicBool(); }
ASTNODE_NODE_FUNCS(LtD, LTD)
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opLtD(lhs,rhs); }
virtual string emitVerilog() { return "%k(%l %f< %r)"; }
@@ -3147,7 +3187,7 @@ struct AstLtD : public AstNodeBiop {
};
struct AstLtS : public AstNodeBiop {
AstLtS(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiop(fl, lhsp, rhsp) {
dtypeChgBool(); }
dtypeChgLogicBool(); }
ASTNODE_NODE_FUNCS(LtS, LTS)
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opLtS(lhs,rhs); }
virtual string emitVerilog() { return "%k(%l %f< %r)"; }
@@ -3160,7 +3200,7 @@ struct AstLtS : public AstNodeBiop {
};
struct AstGt : public AstNodeBiop {
AstGt(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiop(fl, lhsp, rhsp) {
dtypeChgBool(); }
dtypeChgLogicBool(); }
ASTNODE_NODE_FUNCS(Gt, GT)
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opGt(lhs,rhs); }
virtual string emitVerilog() { return "%k(%l %f> %r)"; }
@@ -3172,7 +3212,7 @@ struct AstGt : public AstNodeBiop {
};
struct AstGtD : public AstNodeBiop {
AstGtD(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiop(fl, lhsp, rhsp) {
dtypeChgBool(); }
dtypeChgLogicBool(); }
ASTNODE_NODE_FUNCS(GtD, GTD)
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opGtD(lhs,rhs); }
virtual string emitVerilog() { return "%k(%l %f> %r)"; }
@@ -3186,7 +3226,7 @@ struct AstGtD : public AstNodeBiop {
};
struct AstGtS : public AstNodeBiop {
AstGtS(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiop(fl, lhsp, rhsp) {
dtypeChgBool(); }
dtypeChgLogicBool(); }
ASTNODE_NODE_FUNCS(GtS, GTS)
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opGtS(lhs,rhs); }
virtual string emitVerilog() { return "%k(%l %f> %r)"; }
@@ -3199,7 +3239,7 @@ struct AstGtS : public AstNodeBiop {
};
struct AstGte : public AstNodeBiop {
AstGte(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiop(fl, lhsp, rhsp) {
dtypeChgBool(); }
dtypeChgLogicBool(); }
ASTNODE_NODE_FUNCS(Gte, GTE)
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opGte(lhs,rhs); }
virtual string emitVerilog() { return "%k(%l %f>= %r)"; }
@@ -3211,7 +3251,7 @@ struct AstGte : public AstNodeBiop {
};
struct AstGteD : public AstNodeBiop {
AstGteD(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiop(fl, lhsp, rhsp) {
dtypeChgBool(); }
dtypeChgLogicBool(); }
ASTNODE_NODE_FUNCS(GteD, GTED)
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opGteD(lhs,rhs); }
virtual string emitVerilog() { return "%k(%l %f>= %r)"; }
@@ -3225,7 +3265,7 @@ struct AstGteD : public AstNodeBiop {
};
struct AstGteS : public AstNodeBiop {
AstGteS(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiop(fl, lhsp, rhsp) {
dtypeChgBool(); }
dtypeChgLogicBool(); }
ASTNODE_NODE_FUNCS(GteS, GTES)
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opGteS(lhs,rhs); }
virtual string emitVerilog() { return "%k(%l %f>= %r)"; }
@@ -3238,7 +3278,7 @@ struct AstGteS : public AstNodeBiop {
};
struct AstLte : public AstNodeBiop {
AstLte(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiop(fl, lhsp, rhsp) {
dtypeChgBool(); }
dtypeChgLogicBool(); }
ASTNODE_NODE_FUNCS(Lte, LTE)
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opLte(lhs,rhs); }
virtual string emitVerilog() { return "%k(%l %f<= %r)"; }
@@ -3250,7 +3290,7 @@ struct AstLte : public AstNodeBiop {
};
struct AstLteD : public AstNodeBiop {
AstLteD(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiop(fl, lhsp, rhsp) {
dtypeChgBool(); }
dtypeChgLogicBool(); }
ASTNODE_NODE_FUNCS(LteD, LTED)
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opLteD(lhs,rhs); }
virtual string emitVerilog() { return "%k(%l %f<= %r)"; }
@@ -3264,7 +3304,7 @@ struct AstLteD : public AstNodeBiop {
};
struct AstLteS : public AstNodeBiop {
AstLteS(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiop(fl, lhsp, rhsp) {
dtypeChgBool(); }
dtypeChgLogicBool(); }
ASTNODE_NODE_FUNCS(LteS, LTES)
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opLteS(lhs,rhs); }
virtual string emitVerilog() { return "%k(%l %f<= %r)"; }
@@ -3515,7 +3555,7 @@ struct AstPowS : public AstNodeBiop {
};
struct AstEqCase : public AstNodeBiCom {
AstEqCase(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiCom(fl, lhsp, rhsp) {
dtypeChgBool(); }
dtypeChgLogicBool(); }
ASTNODE_NODE_FUNCS(EqCase, EQCASE)
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opCaseEq(lhs,rhs); }
virtual string emitVerilog() { return "%k(%l %f=== %r)"; }
@@ -3527,7 +3567,7 @@ struct AstEqCase : public AstNodeBiCom {
};
struct AstNeqCase : public AstNodeBiCom {
AstNeqCase(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiCom(fl, lhsp, rhsp) {
dtypeChgBool(); }
dtypeChgLogicBool(); }
ASTNODE_NODE_FUNCS(NeqCase, NEQCASE)
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opCaseNeq(lhs,rhs); }
virtual string emitVerilog() { return "%k(%l %f!== %r)"; }
@@ -3540,7 +3580,7 @@ struct AstNeqCase : public AstNodeBiCom {
struct AstEqWild : public AstNodeBiop {
// Note wildcard operator rhs differs from lhs
AstEqWild(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiop(fl, lhsp, rhsp) {
dtypeChgBool(); }
dtypeChgLogicBool(); }
ASTNODE_NODE_FUNCS(EqWild, EQWILD)
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opWildEq(lhs,rhs); }
virtual string emitVerilog() { return "%k(%l %f==? %r)"; }
@@ -3552,7 +3592,7 @@ struct AstEqWild : public AstNodeBiop {
};
struct AstNeqWild : public AstNodeBiop {
AstNeqWild(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiop(fl, lhsp, rhsp) {
dtypeChgBool(); }
dtypeChgLogicBool(); }
ASTNODE_NODE_FUNCS(NeqWild, NEQWILD)
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opWildNeq(lhs,rhs); }
virtual string emitVerilog() { return "%k(%l %f!=? %r)"; }
+80 -6
View File
@@ -45,9 +45,31 @@
//######################################################################
class BeginState {
private:
// NODE STATE
//Entire netlist:
// AstNodeFTask::user1 -> bool, 1=processed
AstUser1InUse m_inuser1;
bool m_anyFuncInBegin;
public:
BeginState() {
m_anyFuncInBegin = false;
}
~BeginState() {}
void userMarkChanged(AstNodeFTask* nodep) {
nodep->user1(true);
m_anyFuncInBegin = true;
}
bool anyFuncInBegin() const { return m_anyFuncInBegin; }
};
//######################################################################
class BeginVisitor : public AstNVisitor {
private:
// STATE
BeginState* m_statep; // Current global state
AstNodeModule* m_modp; // Current module
AstNodeFTask* m_ftaskp; // Current function/task
string m_namedScope; // Name of begin blocks above us
@@ -70,9 +92,27 @@ private:
m_modp = NULL;
}
virtual void visit(AstNodeFTask* nodep, AstNUser*) {
m_ftaskp = nodep;
nodep->iterateChildren(*this);
m_ftaskp = NULL;
UINFO(8," "<<nodep<<endl);
// Rename it
if (m_unnamedScope != "") {
nodep->name(m_unnamedScope+"__DOT__"+nodep->name());
UINFO(8," rename to "<<nodep->name()<<endl);
m_statep->userMarkChanged(nodep);
}
// BEGIN wrapping a function rename that function, but don't affect the inside function's variables
// We then restart with empty naming; so that any begin's inside the function will rename inside the function
// Process children
string oldScope = m_namedScope;
string oldUnnamed = m_unnamedScope;
{
m_namedScope = "";
m_unnamedScope = "";
m_ftaskp = nodep;
nodep->iterateChildren(*this);
m_ftaskp = NULL;
}
m_namedScope = oldScope;
m_unnamedScope = oldUnnamed;
}
virtual void visit(AstBegin* nodep, AstNUser*) {
// Begin blocks were only useful in variable creation, change names and delete
@@ -80,7 +120,7 @@ private:
string oldScope = m_namedScope;
string oldUnnamed = m_unnamedScope;
{
//UINFO(8,"nname "<<m_namedScope<<endl);
UINFO(8,"nname "<<m_namedScope<<endl);
if (nodep->name() != "") { // Else unneeded unnamed block
// Create data for dotted variable resolution
string dottedname = nodep->name() + "__DOT__"; // So always found
@@ -186,7 +226,8 @@ private:
}
public:
// CONSTUCTORS
BeginVisitor(AstNetlist* nodep) {
BeginVisitor(AstNetlist* nodep, BeginState* statep) {
m_statep = statep;
m_modp = NULL;
m_ftaskp = NULL;
m_repeatNum = 0;
@@ -196,10 +237,43 @@ public:
virtual ~BeginVisitor() {}
};
//######################################################################
class BeginRelinkVisitor : public AstNVisitor {
// Replace tasks with new pointer
private:
// NODE STATE
// Input:
// AstNodeFTask::user1p // Node replaced, rename it
// VISITORS
virtual void visit(AstNodeFTaskRef* nodep, AstNUser*) {
if (nodep->taskp()->user1()) { // It was converted
UINFO(9, " relinkFTask "<<nodep<<endl);
nodep->name(nodep->taskp()->name());
}
nodep->iterateChildren(*this);
}
//--------------------
virtual void visit(AstNode* nodep, AstNUser*) {
nodep->iterateChildren(*this);
}
public:
// CONSTUCTORS
BeginRelinkVisitor(AstNetlist* nodep, BeginState*) {
nodep->accept(*this);
}
virtual ~BeginRelinkVisitor() {}
};
//######################################################################
// Task class functions
void V3Begin::debeginAll(AstNetlist* nodep) {
UINFO(2,__FUNCTION__<<": "<<endl);
BeginVisitor bvisitor (nodep);
BeginState state;
{ BeginVisitor bvisitor (nodep,&state); }
if (state.anyFuncInBegin()) {
BeginRelinkVisitor brvisitor (nodep,&state);
}
}
+7 -1
View File
@@ -374,7 +374,7 @@ private:
if (m_warn
&& nodep->lsbp()->castConst()
&& nodep->widthp()->castConst()
&& (!bdtypep->rangep() || bdtypep->msb())) { // else it's non-resolvable parameterized
&& (!bdtypep->isRanged() || bdtypep->msb())) { // else it's non-resolvable parameterized
if (nodep->lsbp()->castConst()->num().isFourState()
|| nodep->widthp()->castConst()->num().isFourState()) {
nodep->v3error("Selection index is constantly unknown or tristated: "
@@ -1627,6 +1627,12 @@ private:
}
}
// Simplify
virtual void visit(AstBasicDType* nodep, AstNUser*) {
nodep->iterateChildren(*this);
nodep->cvtRangeConst();
}
//-----
// Jump elimination
+2 -2
View File
@@ -87,7 +87,7 @@ private:
if (prettyName.find("._") != string::npos)
return "Inlined leading underscore";
}
if ((nodep->width()*nodep->arrayElements()) > 256) return "Wide bus/array > 256 bits";
if ((nodep->width()*nodep->dtypep()->arrayElements()) > 256) return "Wide bus/array > 256 bits";
// We allow this, though tracing doesn't
// if (nodep->arrayp(1)) return "Unsupported: Multi-dimensional array";
return NULL;
@@ -193,7 +193,7 @@ private:
const ToggleEnt& above,
AstVar* varp, AstVar* chgVarp) { // Constant
if (AstBasicDType* bdtypep = dtypep->castBasicDType()) {
if (bdtypep->rangep()) {
if (bdtypep->isRanged()) {
for (int index_docs=bdtypep->lsb(); index_docs<bdtypep->msb()+1; index_docs++) {
int index_code = index_docs - bdtypep->lsb();
ToggleEnt newent (above.m_comment+string("[")+cvtToStr(index_docs)+"]",
+25 -10
View File
@@ -70,16 +70,16 @@ class DeadVisitor : public AstNVisitor {
private:
// NODE STATE
// Entire Netlist:
// AstNodeModule::user() -> int. Count of number of cells referencing this module.
// AstVar::user() -> int. Count of number of references
// AstVarScope::user() -> int. Count of number of references
// AstNodeModule::user1() -> int. Count of number of cells referencing this module.
// AstVar::user1() -> int. Count of number of references
// AstVarScope::user1() -> int. Count of number of references
AstUser1InUse m_inuser1;
// TYPES
typedef multimap<AstVarScope*,AstNodeAssign*> AssignMap;
// STATE
vector<AstVar*> m_varsp; // List of all encountered to avoid another loop through tree
vector<AstNode*> m_varEtcsp; // List of all encountered to avoid another loop through tree
vector<AstVarScope*> m_vscsp; // List of all encountered to avoid another loop through tree
AssignMap m_assignMap; // List of all simple assignments for each variable
bool m_elimUserVars; // Allow removal of user's vars
@@ -91,14 +91,18 @@ private:
if (VL_UNLIKELY(level < 0)) level = v3Global.opt.debugSrcLevel(__FILE__);
return level;
}
void checkAll(AstNode* nodep) {
}
// VISITORS
virtual void visit(AstCell* nodep, AstNUser*) {
nodep->iterateChildren(*this);
checkAll(nodep);
nodep->modp()->user1Inc();
}
virtual void visit(AstNodeVarRef* nodep, AstNUser*) {
nodep->iterateChildren(*this);
checkAll(nodep);
if (nodep->varScopep()) {
nodep->varScopep()->user1Inc();
nodep->varScopep()->varp()->user1Inc();
@@ -112,29 +116,38 @@ private:
}
virtual void visit(AstNodeFTaskRef* nodep, AstNUser*) {
nodep->iterateChildren(*this);
checkAll(nodep);
if (nodep->packagep()) {
nodep->packagep()->user1Inc();
}
}
virtual void visit(AstRefDType* nodep, AstNUser*) {
nodep->iterateChildren(*this);
checkAll(nodep);
if (nodep->packagep()) {
nodep->packagep()->user1Inc();
}
}
virtual void visit(AstEnumItemRef* nodep, AstNUser*) {
nodep->iterateChildren(*this);
checkAll(nodep);
if (nodep->packagep()) {
nodep->packagep()->user1Inc();
}
}
virtual void visit(AstVarScope* nodep, AstNUser*) {
nodep->iterateChildren(*this);
m_vscsp.push_back(nodep);
checkAll(nodep);
if (mightElim(nodep->varp())) {
m_vscsp.push_back(nodep);
}
}
virtual void visit(AstVar* nodep, AstNUser*) {
nodep->iterateChildren(*this);
m_varsp.push_back(nodep);
checkAll(nodep);
if (mightElim(nodep)) {
m_varEtcsp.push_back(nodep);
}
}
virtual void visit(AstNodeAssign* nodep, AstNUser*) {
@@ -150,12 +163,14 @@ private:
} else { // Track like any other statement
nodep->lhsp()->iterateAndNext(*this);
}
checkAll(nodep);
}
//-----
virtual void visit(AstNode* nodep, AstNUser*) {
if (nodep->isOutputter()) m_sideEffect=true;
nodep->iterateChildren(*this);
checkAll(nodep);
}
// METHODS
@@ -180,7 +195,7 @@ private:
}
}
}
bool canElim(AstVar* nodep) {
bool mightElim(AstVar* nodep) {
return (!nodep->isSigPublic() // Can't elim publics!
&& !nodep->isIO()
&& (nodep->isTemp() || nodep->isParam() || m_elimUserVars));
@@ -189,7 +204,7 @@ private:
// Delete any unused varscopes
for (vector<AstVarScope*>::iterator it = m_vscsp.begin(); it!=m_vscsp.end(); ++it) {
AstVarScope* vscp = *it;
if (vscp->user1() == 0 && canElim(vscp->varp())) {
if (vscp->user1() == 0) {
UINFO(4," Dead "<<vscp<<endl);
pair <AssignMap::iterator,AssignMap::iterator> eqrange = m_assignMap.equal_range(vscp);
for (AssignMap::iterator it = eqrange.first; it != eqrange.second; ++it) {
@@ -200,8 +215,8 @@ private:
vscp->unlinkFrBack()->deleteTree(); vscp=NULL;
}
}
for (vector<AstVar*>::iterator it = m_varsp.begin(); it!=m_varsp.end(); ++it) {
if ((*it)->user1() == 0 && canElim((*it))) {
for (vector<AstNode*>::iterator it = m_varEtcsp.begin(); it!=m_varEtcsp.end(); ++it) {
if ((*it)->user1() == 0) {
UINFO(4," Dead "<<(*it)<<endl);
(*it)->unlinkFrBack()->deleteTree(); (*it)=NULL;
}
+57 -40
View File
@@ -74,14 +74,15 @@ private:
// NODE STATE
// Cleared each module:
// AstVarScope::user1p() -> AstVarScope*. Points to temp var created.
// AstVarScope::user2p() -> AstActive*. Points to activity block of signal
// AstVarScope::user2p() -> AstActive*. Points to activity block of signal (valid when AstVarScope::user1p is valid)
// AstVarScope::user4p() -> AstAlwaysPost*. Post block for this variable
// AstVarScope::user5() -> VarUsage. Tracks delayed vs non-delayed usage
// AstVar::user2() -> bool. Set true if already made warning
// AstVar::user4() -> int. Vector number, for assignment creation
// AstVarRef::user2() -> bool. Set true if already processed
// AstAlwaysPost::user2() -> ActActive*. Points to activity block of signal (valid when AstAlwaysPost::user4p is valid)
// AstAlwaysPost::user4() -> AstIf*. Last IF (__Vdlyvset__) created under this AlwaysPost
// Cleared each scope:
// Cleared each scope/active:
// AstAssignDly::user3() -> AstVarScope*. __Vdlyvset__ created for this assign
// AstAlwaysPost::user3() -> AstVarScope*. __Vdlyvset__ last referenced in IF
AstUser1InUse m_inuser1;
@@ -132,8 +133,8 @@ private:
if (width==0) {
varp = new AstVar (oldvarscp->fileline(), AstVarType::BLOCKTEMP, name, oldvarscp->varp());
varp->widthSignedFrom(oldvarscp);
} else {
varp = new AstVar (oldvarscp->fileline(), AstVarType::BLOCKTEMP, name, AstLogicPacked(), width);
} else { // Used for vset and dimensions, so can zero init
varp = new AstVar (oldvarscp->fileline(), AstVarType::BLOCKTEMP, name, AstBitPacked(), width);
}
addmodp->addStmtp(varp);
m_modVarMap.insert(make_pair(make_pair(addmodp, name), varp));
@@ -144,6 +145,40 @@ private:
return varscp;
}
AstActive* createActivePost(AstVarRef* varrefp) {
AstActive* newactp = new AstActive (varrefp->fileline(), "sequentdly",
m_activep->sensesp());
m_activep->addNext(newactp);
return newactp;
}
void checkActivePost(AstVarRef* varrefp, AstActive* oldactivep) {
// Check for MULTIDRIVEN, and if so make new sentree that joins old & new sentree
if (!oldactivep) varrefp->v3fatalSrc("<= old dly assignment not put under sensitivity block");
if (oldactivep->sensesp() != m_activep->sensesp()) {
if (!varrefp->varp()->fileline()->warnIsOff(V3ErrorCode::MULTIDRIVEN)
&& !varrefp->varp()->user2()) {
varrefp->varp()->v3warn(MULTIDRIVEN,"Signal has multiple driving blocks: "<<varrefp->varp()->prettyName());
varrefp->v3warn(MULTIDRIVEN,"... Location of first driving block");
oldactivep->v3warn(MULTIDRIVEN,"... Location of other driving block");
varrefp->varp()->user2(true);
}
UINFO(4,"AssignDupDlyVar: "<<varrefp<<endl);
UINFO(4," Act: "<<m_activep<<endl);
UINFO(4," Act: "<<oldactivep<<endl);
// Make a new sensitivity list, which is the combination of both blocks
AstNodeSenItem* sena = m_activep->sensesp()->sensesp()->cloneTree(true);
AstNodeSenItem* senb = oldactivep->sensesp()->sensesp()->cloneTree(true);
AstSenTree* treep = new AstSenTree(m_activep->fileline(), sena);
if (senb) treep->addSensesp(senb);
if (AstSenTree* storep = oldactivep->sensesStorep()) {
storep->unlinkFrBack();
pushDeletep(storep);
}
oldactivep->sensesStorep(treep);
oldactivep->sensesp(treep);
}
}
AstNode* createDlyArray(AstAssignDly* nodep, AstNode* lhsp) {
// Create delayed assignment
// See top of this file for transformation
@@ -225,6 +260,7 @@ private:
//
//=== Setting/not setting boolean: __Vdlyvset__
AstVarScope* setvscp;
AstAssignPre* setinitp = NULL;
if (nodep->user3p()) {
// Simplistic optimization. If the previous statement in same scope was also a =>,
@@ -236,11 +272,9 @@ private:
} else { // Create new one
string setvarname = (string("__Vdlyvset__")+oldvarp->shortName()+"__v"+cvtToStr(modVecNum));
setvscp = createVarSc(varrefp->varScopep(), setvarname, 1);
AstAssignPre* setinitp
= new AstAssignPre (nodep->fileline(),
new AstVarRef(nodep->fileline(), setvscp, true),
new AstConst(nodep->fileline(), 0));
m_activep->addStmtsp(setinitp);
setinitp = new AstAssignPre (nodep->fileline(),
new AstVarRef(nodep->fileline(), setvscp, true),
new AstConst(nodep->fileline(), 0));
AstAssign* setassignp
= new AstAssign (nodep->fileline(),
new AstVarRef(nodep->fileline(), setvscp, true),
@@ -269,11 +303,18 @@ private:
UINFO(9," For "<<setvscp<<endl);
UINFO(9," & "<<varrefp<<endl);
AstAlwaysPost* finalp = varrefp->varScopep()->user4p()->castNode()->castAlwaysPost();
if (!finalp) {
if (finalp) {
AstActive* oldactivep = finalp->user2p()->castNode()->castActive();
checkActivePost(varrefp, oldactivep);
if (setinitp) oldactivep->addStmtsp(setinitp);
} else { // first time we've dealt with this memory
finalp = new AstAlwaysPost(nodep->fileline(), NULL/*sens*/, NULL/*body*/);
UINFO(9," Created "<<finalp<<endl);
m_activep->addStmtsp(finalp);
AstActive* newactp = createActivePost(varrefp);
newactp->addStmtsp(finalp);
varrefp->varScopep()->user4p(finalp);
finalp->user2p(newactp);
if (setinitp) newactp->addStmtsp(setinitp);
}
AstIf* postLogicp;
if (finalp->user3p()->castNode() == setvscp) {
@@ -292,7 +333,6 @@ private:
finalp->user4p(postLogicp); // and the associated IF, as we may be able to reuse it
}
postLogicp->addIfsp(new AstAssign(nodep->fileline(), selectsp, valreadp));
return newlhsp;
}
@@ -316,6 +356,7 @@ private:
m_activep = nodep;
bool oldinit = m_inInitial;
m_inInitial = nodep->hasInitial();
AstNode::user3ClearTree(); // Two sets to same variable in different actives must use different vars.
nodep->iterateChildren(*this);
m_inInitial = oldinit;
}
@@ -342,6 +383,7 @@ private:
m_inDly = false;
m_nextDlyp = NULL;
}
virtual void visit(AstVarRef* nodep, AstNUser*) {
if (!nodep->user2Inc()) { // Not done yet
if (m_inDly && nodep->lvalue()) {
@@ -354,30 +396,7 @@ private:
AstVarScope* dlyvscp = oldvscp->user1p()->castNode()->castVarScope();
if (dlyvscp) { // Multiple use of delayed variable
AstActive* oldactivep = dlyvscp->user2p()->castNode()->castActive();
if (!oldactivep) nodep->v3fatalSrc("<= old dly assignment not put under sensitivity block");
if (oldactivep->sensesp() != m_activep->sensesp()) {
if (!nodep->varp()->fileline()->warnIsOff(V3ErrorCode::MULTIDRIVEN)
&& !nodep->varp()->user2()) {
nodep->varp()->v3warn(MULTIDRIVEN,"Signal has multiple driving blocks: "<<nodep->varp()->prettyName());
nodep->v3warn(MULTIDRIVEN,"... Location of first driving block");
oldactivep->v3warn(MULTIDRIVEN,"... Location of other driving block");
nodep->varp()->user2(true);
}
UINFO(4,"AssignDupDlyVar: "<<nodep<<endl);
UINFO(4," Act: "<<m_activep<<endl);
UINFO(4," Act: "<<oldactivep<<endl);
// Make a new sensitivity list, which is the combination of both blocks
AstNodeSenItem* sena = m_activep->sensesp()->sensesp()->cloneTree(true);
AstNodeSenItem* senb = oldactivep->sensesp()->sensesp()->cloneTree(true);
AstSenTree* treep = new AstSenTree(m_activep->fileline(), sena);
if (senb) treep->addSensesp(senb);
if (AstSenTree* storep = oldactivep->sensesStorep()) {
storep->unlinkFrBack();
pushDeletep(storep);
}
oldactivep->sensesStorep(treep);
oldactivep->sensesp(treep);
}
checkActivePost(nodep, oldactivep);
}
if (!dlyvscp) { // First use of this delayed variable
string newvarname = (string("__Vdly__")+nodep->varp()->shortName());
@@ -393,12 +412,10 @@ private:
postp->lhsp()->user2(true); // Don't detect this assignment
oldvscp->user1p(dlyvscp); // So we can find it later
// Make new ACTIVE with identical sensitivity tree
AstActive* newactp = new AstActive (nodep->fileline(), "sequentdly",
m_activep->sensesp());
AstActive* newactp = createActivePost(nodep);
dlyvscp->user2p(newactp);
newactp->addStmtsp(prep); // Add to FRONT of statements
newactp->addStmtsp(postp);
m_activep->addNext(newactp);
dlyvscp->user2p(newactp);
}
AstVarRef* newrefp = new AstVarRef(nodep->fileline(), dlyvscp, true);
newrefp->user2(true); // No reason to do it again
+1
View File
@@ -68,6 +68,7 @@ private:
// Width, not widthMin, as we may be in middle of BITSEL expression which
// though it's one bit wide, needs the mask in the upper bits.
// (Someday we'll have a valid bitmask instead of widths....)
// See t_func_crc for an example test that requires this
AstLogicPacked(), nodep->width());
if (!m_funcp) nodep->v3fatalSrc("Deep expression not under a function");
m_funcp->addInitsp(varp);
+57 -27
View File
@@ -322,7 +322,7 @@ public:
AstVarRef* varrefp = nodep->memp()->castVarRef();
if (!varrefp) { nodep->v3error("Readmem loading non-variable"); }
else if (AstArrayDType* adtypep = varrefp->varp()->dtypeSkipRefp()->castArrayDType()) {
puts(cvtToStr(varrefp->varp()->arrayElements()));
puts(cvtToStr(varrefp->varp()->dtypep()->arrayElements()));
array_lsb = adtypep->lsb();
}
else {
@@ -677,10 +677,10 @@ class EmitCImp : EmitCStmts {
puts(" | (");
}
changep->lhsp()->iterateAndNext(*this);
if (changep->isWide()) puts("["+cvtToStr(word)+"]");
if (changep->lhsp()->isWide()) puts("["+cvtToStr(word)+"]");
puts(" ^ ");
changep->rhsp()->iterateAndNext(*this);
if (changep->isWide()) puts("["+cvtToStr(word)+"]");
if (changep->lhsp()->isWide()) puts("["+cvtToStr(word)+"]");
puts(")");
}
}
@@ -872,9 +872,6 @@ void EmitCStmts::emitVarDecl(AstVar* nodep, const string& prefixIfImp) {
if (nodep->isIO()) {
bool isArray = !nodep->dtypeSkipRefp()->castBasicDType();
if (nodep->isSc()) {
if (isArray) {
nodep->v3error("Unsupported: SystemC inputs and outputs must be simple data types; no arrays");
}
m_ctorVarsVec.push_back(nodep);
ofp()->putAlign(nodep->isStatic(), 4); // sc stuff is a structure, so bigger alignment
if (nodep->attrScClocked() && nodep->isInput()) {
@@ -889,6 +886,12 @@ void EmitCStmts::emitVarDecl(AstVar* nodep, const string& prefixIfImp) {
puts(">\t");
}
puts(nodep->name());
if (isArray) {
for (AstArrayDType* arrayp=nodep->dtypeSkipRefp()->castArrayDType(); arrayp;
arrayp = arrayp->dtypeSkipRefp()->castArrayDType()) {
puts("["+cvtToStr(arrayp->elementsConst())+"]");
}
}
puts(";\n");
} else { // C++ signals
ofp()->putAlign(nodep->isStatic(), nodep->dtypeSkipRefp()->widthAlignBytes(),
@@ -905,7 +908,8 @@ void EmitCStmts::emitVarDecl(AstVar* nodep, const string& prefixIfImp) {
if (isArray) {
if (nodep->isWide()) puts("W");
puts("("+nodep->name());
for (AstArrayDType* arrayp=nodep->dtypeSkipRefp()->castArrayDType(); arrayp; arrayp = arrayp->dtypeSkipRefp()->castArrayDType()) {
for (AstArrayDType* arrayp=nodep->dtypeSkipRefp()->castArrayDType(); arrayp;
arrayp = arrayp->dtypeSkipRefp()->castArrayDType()) {
puts("["+cvtToStr(arrayp->elementsConst())+"]");
}
puts(","+cvtToStr(basicp->msb())+","+cvtToStr(basicp->lsb()));
@@ -926,7 +930,8 @@ void EmitCStmts::emitVarDecl(AstVar* nodep, const string& prefixIfImp) {
// strings and other fundamental c types
puts(nodep->vlArgType(true,false));
// This isn't very robust and may need cleanup for other data types
for (AstArrayDType* arrayp=nodep->dtypeSkipRefp()->castArrayDType(); arrayp; arrayp = arrayp->dtypeSkipRefp()->castArrayDType()) {
for (AstArrayDType* arrayp=nodep->dtypeSkipRefp()->castArrayDType(); arrayp;
arrayp = arrayp->dtypeSkipRefp()->castArrayDType()) {
puts("["+cvtToStr(arrayp->elementsConst())+"]");
}
puts(";\n");
@@ -951,7 +956,8 @@ void EmitCStmts::emitVarDecl(AstVar* nodep, const string& prefixIfImp) {
if (prefixIfImp!="") { puts(prefixIfImp); puts("::"); }
puts(nodep->name());
// This isn't very robust and may need cleanup for other data types
for (AstArrayDType* arrayp=nodep->dtypeSkipRefp()->castArrayDType(); arrayp; arrayp = arrayp->dtypeSkipRefp()->castArrayDType()) {
for (AstArrayDType* arrayp=nodep->dtypeSkipRefp()->castArrayDType(); arrayp;
arrayp = arrayp->dtypeSkipRefp()->castArrayDType()) {
puts("["+cvtToStr(arrayp->elementsConst())+"]");
}
puts(","+cvtToStr(basicp->msb())+","+cvtToStr(basicp->lsb()));
@@ -961,22 +967,29 @@ void EmitCStmts::emitVarDecl(AstVar* nodep, const string& prefixIfImp) {
}
void EmitCStmts::emitVarCtors() {
ofp()->indentInc();
bool first = true;
for (vector<AstVar*>::iterator it = m_ctorVarsVec.begin(); it != m_ctorVarsVec.end(); ++it) {
if (first) {
first=false;
puts("\n");
puts("#if (SYSTEMC_VERSION>20011000)\n"); // SystemC 2.0.1 and newer
puts(" : ");
if (!m_ctorVarsVec.empty()) {
ofp()->indentInc();
puts("\n");
puts("#if (SYSTEMC_VERSION>20011000)\n"); // SystemC 2.0.1 and newer
bool first = true;
for (vector<AstVar*>::iterator it = m_ctorVarsVec.begin(); it != m_ctorVarsVec.end(); ++it) {
AstVar* varp = *it;
bool isArray = !varp->dtypeSkipRefp()->castBasicDType();
if (isArray) {
puts("// Skipping array: ");
puts(varp->name());
puts("\n");
} else {
if (first) { puts(" : "); first=false; }
else puts(", ");
if (ofp()->exceededWidth()) puts("\n ");
puts(varp->name());
puts("("); putsQuoted(varp->name()); puts(")");
}
}
else puts(", ");
if (ofp()->exceededWidth()) puts("\n ");
puts((*it)->name());
puts("("); putsQuoted((*it)->name()); puts(")");
puts ("\n#endif\n");
ofp()->indentDec();
}
if (!first) puts ("\n#endif\n");
ofp()->indentDec();
}
bool EmitCStmts::emitSimpleOk(AstNodeMath* nodep) {
@@ -1353,7 +1366,7 @@ void EmitCImp::emitVarResets(AstNodeModule* modp) {
puts(varp->name());
for (int v=0; v<vects; ++v) puts( "[__Vi"+cvtToStr(v)+"]");
if (zeroit) {
puts("= 0;\n");
puts(" = 0;\n");
} else {
puts(" = VL_RAND_RESET_");
emitIQW(varp);
@@ -1500,7 +1513,22 @@ void EmitCImp::emitSensitives() {
for (AstNode* nodep=m_modp->stmtsp(); nodep; nodep = nodep->nextp()) {
if (AstVar* varp = nodep->castVar()) {
if (varp->isInput() && (varp->isScSensitive() || varp->isUsedClock())) {
puts("sensitive << "+varp->name()+";\n");
int vects = 0;
// This isn't very robust and may need cleanup for other data types
for (AstArrayDType* arrayp=varp->dtypeSkipRefp()->castArrayDType(); arrayp;
arrayp = arrayp->dtypeSkipRefp()->castArrayDType()) {
int vecnum = vects++;
if (arrayp->msb() < arrayp->lsb()) varp->v3fatalSrc("Should have swapped msb & lsb earlier.");
string ivar = string("__Vi")+cvtToStr(vecnum);
// MSVC++ pre V7 doesn't support 'for (int ...)', so declare in sep block
puts("{ int __Vi"+cvtToStr(vecnum)+"="+cvtToStr(arrayp->lsb())+";");
puts(" for (; "+ivar+"<="+cvtToStr(arrayp->msb()));
puts("; ++"+ivar+") {\n");
}
puts("sensitive << "+varp->name());
for (int v=0; v<vects; ++v) puts( "[__Vi"+cvtToStr(v)+"]");
puts(";\n");
for (int v=0; v<vects; ++v) puts( "}}\n");
}
}
}
@@ -2062,7 +2090,8 @@ class EmitCTrace : EmitCStmts {
} else {
puts(",-1");
}
if (nodep->msbEndianed() || nodep->lsbEndianed()) {
if (!nodep->isDouble() // When float/double no longer have widths this can go
&& (nodep->msbEndianed() || nodep->lsbEndianed())) {
puts(","+cvtToStr(nodep->msbEndianed())+","+cvtToStr(nodep->lsbEndianed()));
}
puts(");");
@@ -2088,7 +2117,8 @@ class EmitCTrace : EmitCStmts {
+ ((arrayindex<0) ? 0 : (arrayindex*nodep->declp()->widthWords()))));
puts(",");
emitTraceValue(nodep, arrayindex);
if (nodep->declp()->msbEndianed() || nodep->declp()->lsbEndianed() || emitTraceIsScBv(nodep)) {
if (!nodep->isDouble() // When float/double no longer have widths this can go
&& (nodep->declp()->msbEndianed() || nodep->declp()->lsbEndianed() || emitTraceIsScBv(nodep))) {
puts(","+cvtToStr(nodep->declp()->widthMin()));
}
puts(");\n");
+3 -3
View File
@@ -453,9 +453,9 @@ void EmitCSyms::emitSymImp() {
string bounds;
if (AstBasicDType* basicp = varp->basicp()) {
// Range is always first, it's not in "C" order
if (basicp->rangep()) {
bounds += " ,"; bounds += cvtToStr(basicp->rangep()->msbConst());
bounds += ","; bounds += cvtToStr(basicp->rangep()->lsbConst());
if (basicp->isRanged()) {
bounds += " ,"; bounds += cvtToStr(basicp->msb());
bounds += ","; bounds += cvtToStr(basicp->lsb());
dim++;
}
for (AstNodeDType* dtypep=varp->dtypep(); dtypep; ) {
+1
View File
@@ -486,6 +486,7 @@ class EmitVBaseVisitor : public EmitCBaseVisitor {
if (nodep->isSigned()) putfs(nodep,"signed ");
putfs(nodep,nodep->prettyName());
if (nodep->rangep()) { puts(" "); nodep->rangep()->iterateAndNext(*this); puts(" "); }
else if (nodep->isRanged()) { puts(" ["); puts(cvtToStr(nodep->msb())); puts(":0] "); }
}
virtual void visit(AstConstDType* nodep, AstNUser*) {
putfs(nodep,"const ");
+3 -1
View File
@@ -69,6 +69,7 @@ public:
COMBDLY, // Combinatorial delayed assignment
DEFPARAM, // Style: Defparam
DECLFILENAME, // Declaration doesn't match filename
ENDLABEL, // End lable name mismatch
GENCLK, // Generated Clock
IFDEPTH, // If statements too deep
IMPERFECTSCH, // Imperfect schedule (disabled by default)
@@ -114,7 +115,7 @@ public:
"BLKANDNBLK", "BLKSEQ",
"CASEINCOMPLETE", "CASEOVERLAP", "CASEWITHX", "CASEX", "CDCRSTLOGIC", "CMPCONST",
"COMBDLY", "DEFPARAM", "DECLFILENAME",
"GENCLK",
"ENDLABEL", "GENCLK",
"IFDEPTH", "IMPERFECTSCH", "IMPLICIT", "IMPURE", "INCABSPATH",
"LITENDIAN", "MODDUP",
"MULTIDRIVEN",
@@ -141,6 +142,7 @@ public:
bool lintError() const { return ( m_e==CASEINCOMPLETE || m_e==CASEOVERLAP
|| m_e==CASEWITHX || m_e==CASEX
|| m_e==CMPCONST
|| m_e==ENDLABEL
|| m_e==IMPLICIT
|| m_e==LITENDIAN
|| m_e==REALCVT
+2 -1
View File
@@ -41,7 +41,8 @@ class AstNetlist;
class V3Global {
// Globals
AstNetlist* m_rootp; // Root of entire netlist
AstNetlist* m_rootp; // Root of entire netlist
int m_debugFileNumber; // Number to append to debug files created
bool m_assertDTypesResolved; // Tree should have dtypep()'s
bool m_assertWidthsMatch; // Tree should have width()==widthMin()
+3 -2
View File
@@ -344,8 +344,9 @@ private:
// When we hit ourself again, return the list of all loops
if (m_done) return;
m_callTrace.reserve(currentRank+10); // Leave slop for speed
m_callTrace[currentRank++] = vertexp;
// Can't just reserve(), unless we modify size() before setting array directly
while (m_callTrace.size() <= currentRank) m_callTrace.push_back(vertexp);
m_callTrace[currentRank++] = vertexp;
if (vertexp->user() == 1) {
for (unsigned i=0; i<currentRank; i++) {
+1 -1
View File
@@ -550,7 +550,7 @@ private:
defp = m_curVarsp->findIdUpward(nodep->name())->castTypedef();
}
if (!defp) { nodep->v3error("Can't find typedef: "<<nodep->prettyName()); }
nodep->defp(defp);
nodep->defp(defp->dtypep());
nodep->packagep(packageFor(defp));
}
nodep->iterateChildren(*this);
+6 -1
View File
@@ -498,7 +498,9 @@ private:
}
}
virtual void visit(AstNodeFTask* nodep, AstNUser*) {
m_statep->insertSym(m_cellVxp, nodep->name(), nodep);
if (!m_beginp) { // For now, we don't support xrefs into functions inside begin blocks
m_statep->insertSym(m_cellVxp, nodep->name(), nodep);
}
// No recursion, we don't want to pick up variables
}
virtual void visit(AstCFunc* nodep, AstNUser*) {
@@ -681,6 +683,9 @@ private:
} else if (!m_cellVxp) {
UINFO(9,"Dead module for "<<nodep<<endl);
nodep->taskp(NULL); // Module that is not in hierarchy. We'll be dead code eliminating it later.
} else if (nodep->dotted()=="" && nodep->taskp()) {
// V3Link should have setup the links
// Might be under a BEGIN we're not processing, so don't relink it
} else {
string baddot;
LinkDotBaseVertex* okVxp;
+1 -1
View File
@@ -139,7 +139,7 @@ private:
string name = string("__Vrepeat")+cvtToStr(m_repeatNum++);
// Spec says value is integral, if negative is ignored
AstVar* varp = new AstVar(nodep->fileline(), AstVarType::BLOCKTEMP, name,
AstLogicPacked(), 32);
AstBitPacked(), 32);
varp->numeric(AstNumeric::SIGNED);
varp->dtypep()->numeric(AstNumeric::SIGNED);
varp->usedLoopIdx(true);
-1
View File
@@ -275,7 +275,6 @@ private:
}
}
virtual void visit(AstVar* nodep, AstNUser*) {
cleanFileline(nodep);
m_varp = nodep;
+1 -1
View File
@@ -366,8 +366,8 @@ private:
}
}
}
nodep->unlinkFrBack(); pushDeletep(nodep); nodep=NULL;
}
nodep->unlinkFrBack(); pushDeletep(nodep); nodep=NULL;
}
virtual void visit(AstScCtor* nodep, AstNUser*) {
+16 -16
View File
@@ -55,8 +55,8 @@ struct V3OptionsImp {
set<string> m_incDirUserSet; // Include directories (for removing duplicates)
list<string> m_incDirFallbacks; // Include directories (ordered)
set<string> m_incDirFallbackSet; // Include directories (for removing duplicates)
list<string> m_libExts; // Library extensions (ordered)
set<string> m_libExtSet; // Library extensions (for removing duplicates)
list<string> m_libExtVs; // Library extensions (ordered)
set<string> m_libExtVSet; // Library extensions (for removing duplicates)
DirMap m_dirMap; // Directory listing
// ACCESSOR METHODS
@@ -76,10 +76,10 @@ struct V3OptionsImp {
}
}
}
void addLibExt(const string& libext) {
if (m_libExtSet.find(libext) == m_libExtSet.end()) {
m_libExtSet.insert(libext);
m_libExts.push_back(libext);
void addLibExtV(const string& libext) {
if (m_libExtVSet.find(libext) == m_libExtVSet.end()) {
m_libExtVSet.insert(libext);
m_libExtVs.push_back(libext);
}
}
V3OptionsImp() {}
@@ -91,8 +91,8 @@ void V3Options::addIncDirUser(const string& incdir) {
void V3Options::addIncDirFallback(const string& incdir) {
m_impp->addIncDirFallback(incdir);
}
void V3Options::addLibExt(const string& libext) {
m_impp->addLibExt(libext);
void V3Options::addLibExtV(const string& libext) {
m_impp->addLibExtV(libext);
}
void V3Options::addDefine(const string& defline) {
// Split +define+foo=value into the appropriate parts and parse
@@ -304,7 +304,7 @@ string V3Options::fileExists (const string& filename) {
}
string V3Options::filePathCheckOneDir(const string& modname, const string& dirname) {
for (list<string>::iterator extIter=m_impp->m_libExts.begin(); extIter!=m_impp->m_libExts.end(); ++extIter) {
for (list<string>::iterator extIter=m_impp->m_libExtVs.begin(); extIter!=m_impp->m_libExtVs.end(); ++extIter) {
string fn = filenameFromDirBase(dirname, modname+*extIter);
string exists = fileExists(fn);
if (exists!="") {
@@ -350,14 +350,14 @@ void V3Options::filePathLookedMsg(FileLine* fl, const string& modname) {
fl->v3error("Looked in:"<<endl);
for (list<string>::iterator dirIter=m_impp->m_incDirUsers.begin();
dirIter!=m_impp->m_incDirUsers.end(); ++dirIter) {
for (list<string>::iterator extIter=m_impp->m_libExts.begin(); extIter!=m_impp->m_libExts.end(); ++extIter) {
for (list<string>::iterator extIter=m_impp->m_libExtVs.begin(); extIter!=m_impp->m_libExtVs.end(); ++extIter) {
string fn = filenameFromDirBase(*dirIter,modname+*extIter);
fl->v3error(" "<<fn<<endl);
}
}
for (list<string>::iterator dirIter=m_impp->m_incDirFallbacks.begin();
dirIter!=m_impp->m_incDirFallbacks.end(); ++dirIter) {
for (list<string>::iterator extIter=m_impp->m_libExts.begin(); extIter!=m_impp->m_libExts.end(); ++extIter) {
for (list<string>::iterator extIter=m_impp->m_libExtVs.begin(); extIter!=m_impp->m_libExtVs.end(); ++extIter) {
string fn = filenameFromDirBase(*dirIter,modname+*extIter);
fl->v3error(" "<<fn<<endl);
}
@@ -685,10 +685,10 @@ void V3Options::parseOptsList(FileLine* fl, const string& optdir, int argc, char
string exts = string(sw+strlen("+libext+"));
string::size_type pos;
while ((pos=exts.find("+")) != string::npos) {
addLibExt (exts.substr(0,pos));
addLibExtV (exts.substr(0,pos));
exts = exts.substr(pos+1);
}
addLibExt (exts);
addLibExtV (exts);
}
else if ( !strcmp (sw, "+librescan")) { // NOP
}
@@ -1208,9 +1208,9 @@ V3Options::V3Options() {
optimize(true);
// Default +libext+
addLibExt(""); // So include "filename.v" will find the same file
addLibExt(".v");
addLibExt(".sv");
addLibExtV(""); // So include "filename.v" will find the same file
addLibExtV(".v");
addLibExtV(".sv");
// Default -I
addIncDirFallback("."); // Looks better than {long_cwd_path}/...
}
+1 -1
View File
@@ -183,7 +183,7 @@ class V3Options {
void addFuture(const string& flag);
void addIncDirUser(const string& incdir); // User requested
void addIncDirFallback(const string& incdir); // Low priority if not found otherwise
void addLibExt(const string& libext);
void addLibExtV(const string& libext);
void optimize(int level);
void showVersion(bool verbose);
void coverage(bool flag) { m_coverageLine = m_coverageToggle = m_coverageUser = flag; }
+1
View File
@@ -33,6 +33,7 @@
#include <cstdarg>
#include <unistd.h>
#include <fstream>
#include <sstream>
#include "V3Error.h"
#include "V3Global.h"
+1
View File
@@ -53,6 +53,7 @@ struct V3ParseBisonYYSType {
string* strp;
int cint;
double cdouble;
bool cbool;
V3UniqState uniqstate;
AstSignedState signstate;
V3ImportProperty iprop;
+18 -3
View File
@@ -34,6 +34,7 @@
//======================================================================
class V3PreLex;
class V3PreProcImp;
// Token codes
@@ -126,16 +127,23 @@ void yy_delete_buffer( YY_BUFFER_STATE b );
class VPreStream {
public:
FileLine* m_curFilelinep; // Current processing point (see also m_tokFilelinep)
V3PreLex* m_lexp; // Lexer, for resource tracking
deque<string> m_buffers; // Buffer of characters to process
int m_ignNewlines; // Ignore multiline newlines
bool m_eof; // "EOF" buffer
bool m_file; // Buffer is start of new file
int m_termState; // Termination fsm
VPreStream(FileLine* fl)
: m_curFilelinep(fl), m_ignNewlines(0),
VPreStream(FileLine* fl, V3PreLex* lexp)
: m_curFilelinep(fl), m_lexp(lexp),
m_ignNewlines(0),
m_eof(false), m_file(false), m_termState(0) {
lexStreamDepthAdd(1);
}
~VPreStream() {}
~VPreStream() {
lexStreamDepthAdd(-1);
}
private:
void lexStreamDepthAdd(int delta);
};
//======================================================================
@@ -145,6 +153,7 @@ class V3PreLex {
public: // Used only by V3PreLex.cpp and V3PreProc.cpp
V3PreProcImp* m_preimpp; // Preprocessor lexor belongs to
stack<VPreStream*> m_streampStack; // Stack of processing files
int m_streamDepth; // Depth of stream processing
YY_BUFFER_STATE m_bufferState; // Flex state
FileLine* m_tokFilelinep; // Starting position of current token
@@ -166,6 +175,7 @@ class V3PreLex {
// CONSTRUCTORS
V3PreLex(V3PreProcImp* preimpp, FileLine* filelinep) {
m_preimpp = preimpp;
m_streamDepth = 0;
m_keepComments = 0;
m_keepWhitespace = 1;
m_pedantic = false;
@@ -207,6 +217,9 @@ class V3PreLex {
void dumpSummary();
void dumpStack();
void unused();
// Called by VPreStream
void streamDepthAdd(int delta) { m_streamDepth += delta; }
int streamDepth() const { return m_streamDepth; }
/// Utility
static int debug();
static void debug(int level);
@@ -219,4 +232,6 @@ private:
void scanSwitchStream(VPreStream* streamp);
};
inline void VPreStream::lexStreamDepthAdd(int delta) { m_lexp->streamDepthAdd(delta); }
#endif // Guard
+22 -8
View File
@@ -81,6 +81,7 @@ quote [\"]
tickquote [`][\"]
backslash [\\]
/* Where we use symb/symbdef, we must also look for a `` join */
/* Note in the preprocessor \ESCaped is *not* always special; mantis1537/bug441 */
symb ([a-zA-Z_][a-zA-Z0-9_$]*|\\[^ \t\f\r\n]+)
symbdef ([a-zA-Z_][a-zA-Z0-9_$]*|\\[^ \t\f\r\n`]+)
word [a-zA-Z0-9_]+
@@ -432,7 +433,7 @@ string V3PreLex::endOfStream(bool& againr) {
void V3PreLex::initFirstBuffer(FileLine* filelinep) {
// Called from constructor to make first buffer
// yy_create_buffer also sets yy_fill_buffer=1 so reads from YY_INPUT
VPreStream* streamp = new VPreStream(filelinep);
VPreStream* streamp = new VPreStream(filelinep, this);
streamp->m_eof = true;
m_streampStack.push(streamp);
//
@@ -443,10 +444,16 @@ void V3PreLex::initFirstBuffer(FileLine* filelinep) {
void V3PreLex::scanNewFile(FileLine* filelinep) {
// Called on new open file. scanBytesBack will be called next.
VPreStream* streamp = new VPreStream(filelinep);
m_tokFilelinep = curFilelinep();
streamp->m_file = true;
scanSwitchStream(streamp);
if (streamDepth() > V3PreProc::DEFINE_RECURSION_LEVEL_MAX) {
// The recursive `include in VPreProcImp should trigger first
yyerrorf("Recursive `define or other nested inclusion");
curStreamp()->m_eof = true; // Fake it to stop recursion
} else {
VPreStream* streamp = new VPreStream(filelinep, this);
m_tokFilelinep = curFilelinep();
streamp->m_file = true;
scanSwitchStream(streamp);
}
}
void V3PreLex::scanBytes(const string& str) {
@@ -455,9 +462,16 @@ void V3PreLex::scanBytes(const string& str) {
// to take effect immediately, in the middle of the current buffer
// Also we don't use scan_bytes that would set yy_fill_buffer
// which would force Flex to bypass our YY_INPUT routine.
VPreStream* streamp = new VPreStream(curFilelinep());
streamp->m_buffers.push_front(str);
scanSwitchStream(streamp);
if (streamDepth() > V3PreProc::DEFINE_RECURSION_LEVEL_MAX) {
// More streams if recursive `define with complex insertion
// More buffers mostly if something internal goes funky
yyerrorf("Recursive `define or other nested inclusion");
curStreamp()->m_eof = true; // Fake it to stop recursion
} else {
VPreStream* streamp = new VPreStream(curFilelinep(), this);
streamp->m_buffers.push_front(str);
scanSwitchStream(streamp);
}
}
void V3PreLex::scanSwitchStream(VPreStream* streamp) {
+23 -11
View File
@@ -112,7 +112,7 @@ struct V3PreProcImp : public V3PreProc {
typedef std::map<string,V3Define> DefinesMap;
typedef V3InFilter::StrList StrList;
// debug() -> see V3PreShellImp::debug
// debug() -> see V3PreShellImp::debug; use --debugi-V3PreShell
// Defines list
DefinesMap m_defines; ///< Map of defines
@@ -628,16 +628,18 @@ string V3PreProcImp::defineSubst(V3DefineRef* refp) {
string argName;
string prev;
bool quote = false;
bool backslashesc = false; // In \.....{space} block
// Note we go through the loop once more at the NULL end-of-string
for (const char* cp=value.c_str(); (*cp) || argName!=""; cp=(*cp?cp+1:cp)) {
//cout << "CH "<<*cp<<" an "<<argName<<"\n";
if (!quote) {
if ( isalpha(*cp) || *cp=='_'
|| *cp=='$' // Won't replace system functions, since no $ in argValueByName
|| (argName!="" && (isdigit(*cp) || *cp=='$'))) {
argName += *cp;
continue;
}
//UINFO(4, "CH "<<*cp<<" an "<<argName<<endl);
if (!quote && *cp == '\\') { backslashesc = true; }
else if (isspace(*cp)) { backslashesc = false; }
// We don't check for quotes; some simulators expand even inside quotes
if ( isalpha(*cp) || *cp=='_'
|| *cp=='$' // Won't replace system functions, since no $ in argValueByName
|| (argName!="" && (isdigit(*cp) || *cp=='$'))) {
argName += *cp;
continue;
}
if (argName != "") {
// Found a possible variable substitution
@@ -654,7 +656,11 @@ string V3PreProcImp::defineSubst(V3DefineRef* refp) {
if (!quote) {
// Check for `` only after we've detected end-of-argname
if (cp[0]=='`' && cp[1]=='`') {
out += "``"; // `` must get removed later, as `FOO```BAR must pre-expand FOO and BAR
if (backslashesc) {
// Don't put out the ``, we're forming an escape which will not expand further later
} else {
out += "``"; // `` must get removed later, as `FOO```BAR must pre-expand FOO and BAR
}
cp++;
continue;
}
@@ -685,12 +691,18 @@ string V3PreProcImp::defineSubst(V3DefineRef* refp) {
continue;
}
}
if (cp[0]=='\\' && cp[1]) {
if (cp[0]=='\\' && cp[1]=='\"') {
out += cp[0]; // \{any} Put out literal next character
out += cp[1];
cp++;
continue;
}
else if (cp[0]=='\\') {
// Normally \{any} would put out literal next character
// Instead we allow "`define A(nm) \nm" to expand, per proposed mantis1537
out += cp[0];
continue;
}
if (*cp=='"') quote=!quote;
if (*cp) out += *cp;
}
+2
View File
@@ -50,6 +50,8 @@ public:
enum MiscConsts {
DEFINE_RECURSION_LEVEL_MAX = 1000, // How many `def substitutions before an error
INCLUDE_DEPTH_MAX = 500, // How many `includes deep before an error
STREAM_DEPTH_LEVEL_MAX = 2000, // How many streams deep (sometimes `def deep) before an error
// // Set more than DEFINE_RECURSION_LEVEL_MAX or INCLUDE_DEPTH_MAX
NEWLINES_VS_TICKLINE = 20 // Use `line in place of this many newlines
};
+2 -1
View File
@@ -204,6 +204,7 @@ private:
AstNRelinker replaceHandle;
nodep->unlinkFrBack(&replaceHandle);
AstNode* constzerop;
int m1value = nodep->widthMin()-1; // Constant of width-1; not changing dtype width
if (nodep->signedFlavor()) {
// Then over shifting gives the sign bit, not all zeros
// Note *NOT* clean output -- just like normal shift!
@@ -212,7 +213,7 @@ private:
new AstShiftR(nodep->fileline(),
nodep->lhsp()->cloneTree(false),
new AstConst(nodep->fileline(),
nodep->widthMin()-1),
m1value),
nodep->width()));
} else {
V3Number zeronum (nodep->fileline(), nodep->width(), 0);
+7 -5
View File
@@ -85,7 +85,7 @@ class SliceCloneVisitor : public AstNVisitor {
if (m_vecIdx == (int)m_selBits.size()) {
m_selBits.push_back(vector<unsigned>());
AstVar* varp = m_refp->varp();
pair<uint32_t,uint32_t> arrDim = varp->dimensions();
pair<uint32_t,uint32_t> arrDim = varp->dtypep()->dimensions();
uint32_t dimensions = arrDim.first + arrDim.second;
for (uint32_t i = 0; i < dimensions; ++i) {
m_selBits[m_vecIdx].push_back(0);
@@ -262,12 +262,13 @@ class SliceVisitor : public AstNVisitor {
AstArraySel* insertImplicit(AstNode* nodep, unsigned start, unsigned count) {
// Insert any implicit slices as explicit slices (ArraySel nodes).
// Return a new pointer to replace nodep() in the ArraySel.
UINFO(9," insertImplicit "<<nodep<<endl);
AstVarRef* refp = nodep->user1p()->castNode()->castVarRef();
if (!refp) nodep->v3fatalSrc("No VarRef in user1 of node "<<nodep);
AstVar* varp = refp->varp();
AstNode* topp = nodep;
for (unsigned i = start; i < start + count; ++i) {
AstNodeDType* dtypep = varp->dtypeDimensionp(i-1);
AstNodeDType* dtypep = varp->dtypep()->dtypeDimensionp(i-1);
AstArrayDType* adtypep = dtypep->castArrayDType();
if (!adtypep) nodep->v3fatalSrc("insertImplicit tried to expand an array without an ArrayDType");
vlsint32_t msb = adtypep->msb();
@@ -276,6 +277,7 @@ class SliceVisitor : public AstNVisitor {
// Below code assumes big bit endian; just works out if we swap
int x = msb; msb = lsb; lsb = x;
}
UINFO(9," ArraySel-child: "<<topp<<endl);
AstArraySel* newp = new AstArraySel(nodep->fileline(), topp, new AstConst(nodep->fileline(),lsb));
newp->user1p(refp);
newp->start(lsb);
@@ -303,7 +305,7 @@ class SliceVisitor : public AstNVisitor {
// The LHS/RHS of an Assign may be to a Var that is an array. In this
// case we need to create a slice accross the entire Var
if (m_assignp && !nodep->backp()->castArraySel()) {
pair<uint32_t,uint32_t> arrDim = nodep->varp()->dimensions();
pair<uint32_t,uint32_t> arrDim = nodep->varp()->dtypep()->dimensions();
uint32_t dimensions = arrDim.first + arrDim.second;
if (dimensions > 0) {
AstVarRef* clonep = nodep->cloneTree(false);
@@ -337,7 +339,7 @@ class SliceVisitor : public AstNVisitor {
if (nodep->user3()) return; // Prevent recursion on just created nodes
unsigned dim = explicitDimensions(nodep);
AstVarRef* refp = nodep->user1p()->castNode()->castVarRef();
pair<uint32_t,uint32_t> arrDim = refp->varp()->dimensions();
pair<uint32_t,uint32_t> arrDim = refp->varp()->dtypep()->dimensions();
uint32_t implicit = (arrDim.first + arrDim.second) - dim;
if (implicit > 0) {
AstArraySel* newp = insertImplicit(nodep->cloneTree(false), dim+1, implicit);
@@ -439,7 +441,7 @@ class SliceVisitor : public AstNVisitor {
nodep->iterateChildren(*this);
} else {
AstVarRef* refp = findVarRefRecurse(nodep->lhsp());
ArrayDimensions varDim = refp->varp()->dimensions();
ArrayDimensions varDim = refp->varp()->dtypep()->dimensions();
if ((int)(dim - varDim.second) < 0) {
// Unpacked dimensions are referenced first, make sure we have them all
nodep->v3error("Unary operator used across unpacked dimensions");
+13 -8
View File
@@ -182,19 +182,21 @@ private:
// Index into our table
AstVar* indexVarp = new AstVar (nodep->fileline(), AstVarType::BLOCKTEMP,
"__Vtableidx" + cvtToStr(m_modTables),
AstLogicPacked(), m_inWidth);
AstBitPacked(), m_inWidth);
m_modp->addStmtp(indexVarp);
AstVarScope* indexVscp = new AstVarScope (indexVarp->fileline(), m_scopep, indexVarp);
m_scopep->addVarp(indexVscp);
// Change it variable
FileLine* fl = nodep->fileline();
AstNodeDType* dtypep
= new AstArrayDType (fl,
new AstBasicDType(fl, AstBitPacked(), m_outVarps.size()),
new AstRange (fl, VL_MASK_I(m_inWidth), 0));
AstVar* chgVarp
= new AstVar (fl, AstVarType::MODULETEMP,
"__Vtablechg" + cvtToStr(m_modTables),
new AstArrayDType (fl,
new AstBasicDType(fl, AstLogicPacked(), m_outVarps.size()),
new AstRange (fl, VL_MASK_I(m_inWidth), 0)));
dtypep);
chgVarp->isConst(true);
chgVarp->valuep(new AstInitArray (nodep->fileline(), NULL));
m_modp->addStmtp(chgVarp);
@@ -233,12 +235,15 @@ private:
AstVarScope* outvscp = *it;
AstVar* outvarp = outvscp->varp();
FileLine* fl = nodep->fileline();
AstNodeDType* dtypep
= new AstArrayDType (fl,
// FUTURE: If support more types, below can use outvarp->dtype()
new AstBasicDType(fl, AstLogicPacked(), outvarp->width()),
new AstRange (fl, VL_MASK_I(m_inWidth), 0));
AstVar* tablevarp
= new AstVar (fl, AstVarType::MODULETEMP,
"__Vtable" + cvtToStr(m_modTables) +"_"+outvarp->name(),
new AstArrayDType (fl,
new AstBasicDType(fl, AstLogicPacked(), outvarp->width()),
new AstRange (fl, VL_MASK_I(m_inWidth), 0)));
dtypep);
tablevarp->isConst(true);
tablevarp->isStatic(true);
tablevarp->valuep(new AstInitArray (nodep->fileline(), NULL));
@@ -344,7 +349,7 @@ private:
AstVarScope* vsc2p= *it;
AstVar* var2p = vsc2p->varp();
if (var1p->width() == var2p->width()
&& var1p->arrayElements() == var2p->arrayElements()) {
&& var1p->dtypep()->arrayElements() == var2p->dtypep()->arrayElements()) {
AstNode* init1p = var1p->valuep()->castInitArray();
AstNode* init2p = var2p->valuep()->castInitArray();
if (init1p->sameTree(init2p)) {
+3 -5
View File
@@ -313,7 +313,7 @@ private:
if (!activityNumber) activityNumber++; // For simplicity, always create it
int activityBits = VL_WORDS_I(activityNumber)*VL_WORDSIZE; // For tighter code; round to next 32 bit point.
AstVar* newvarp = new AstVar (m_chgFuncp->fileline(), AstVarType::MODULETEMP,
"__Vm_traceActivity", AstLogicPacked(), activityBits);
"__Vm_traceActivity", AstBitPacked(), activityBits);
m_topModp->addStmtp(newvarp);
AstVarScope* newvscp = new AstVarScope(newvarp->fileline(), m_highScopep, newvarp);
m_highScopep->addVarp(newvscp);
@@ -328,8 +328,7 @@ private:
vvertexp->insertp()->addNextHere
(new AstAssign (fl,
new AstSel (fl, new AstVarRef(fl, m_activityVscp, true),
new AstConst(fl, acode),
new AstConst(fl, 1)),
acode, 1),
new AstConst (fl, AstConst::LogicTrue())));
}
}
@@ -452,8 +451,7 @@ private:
for (ActCodeSet::const_iterator csit = actset.begin(); csit!=actset.end(); ++csit) {
uint32_t acode = *csit;
AstNode* selp = new AstSel (fl, new AstVarRef(fl, m_activityVscp, false),
new AstConst(fl, acode),
new AstConst(fl, 1));
acode, 1);
if (condp) condp = new AstOr (fl, condp, selp);
else condp = selp;
}
+1 -1
View File
@@ -76,7 +76,7 @@ private:
return "Inlined leading underscore";
}
if ((int)nodep->width() > v3Global.opt.traceMaxWidth()) return "Wide bus > --trace-max-width bits";
if ((int)nodep->arrayElements() > v3Global.opt.traceMaxArray()) return "Wide memory > --trace-max-array ents";
if ((int)nodep->dtypep()->arrayElements() > v3Global.opt.traceMaxArray()) return "Wide memory > --trace-max-array ents";
if (!(nodep->dtypeSkipRefp()->castBasicDType()
|| (nodep->dtypeSkipRefp()->castArrayDType()
&& nodep->dtypeSkipRefp()->castArrayDType()->dtypeSkipRefp()->castBasicDType()))) {
+7 -3
View File
@@ -56,7 +56,6 @@
#include "V3Global.h"
#include "V3Tristate.h"
#include "V3Ast.h"
#include "V3Const.h"
#include "V3Stats.h"
#include "V3Inst.h"
@@ -441,7 +440,8 @@ private:
);
selp->replaceWith(new AstVarRef(refp->fileline(), newlhsp, true));
selp->deleteTree();
pushDeletep(selp); // Setting selp here or deleting immediately
// breaks the t_tri_select test, this probably indicates a problem
} else {
refp->varp(newlhsp); // assign the new var to the varref
refp->name(newlhsp->name());
@@ -571,7 +571,7 @@ private:
new AstVarRef(nodep->fileline(), enp, true));
AstVarRef *rp = findVarRef(pinp);
rp->replaceWith(new AstVarRef(nodep->fileline(), enp, true));
rp->deleteTree();
rp->deleteTree(); rp=NULL;
pinp->width(enp->width(),enp->width()); // minwidth==width
pinp->modVarp(enchildp);
m_cellp->addPinsp(pinp);
@@ -591,6 +591,9 @@ private:
public:
// CONSTUCTORS
TristateVisitor(AstNode* nodep) {
m_modp = NULL;
m_cellp = NULL;
m_unique = false;
nodep->accept(*this);
}
virtual ~TristateVisitor() { }
@@ -716,6 +719,7 @@ public:
m_modp = NULL;
m_cellp = NULL;
m_ftaskp = NULL;
m_state = CONVERT_VARS;
nodep->accept(*this);
}
virtual ~InoutVisitor() { }
+1 -1
View File
@@ -380,7 +380,7 @@ private:
int maxmsb = 0;
bool lvalue = false;
if (AstNodeVarRef* varrefp = basefromp->castNodeVarRef()) {
AstArrayDType* adtypep = varrefp->varp()->dtypeDimensionp(dimension)->castArrayDType();
AstArrayDType* adtypep = varrefp->varp()->dtypep()->dtypeDimensionp(dimension)->castArrayDType();
if (!adtypep) nodep->v3fatalSrc("ArraySel to type without array at same depth");
lvalue = varrefp->lvalue();
maxmsb = adtypep->elementsConst()-1;
+80 -88
View File
@@ -86,14 +86,19 @@ class WidthVP : public AstNUser {
// Parameters to pass down hierarchy with visit functions.
int m_width; // Expression width, for (2+2), it's 32 bits
int m_widthMin; // Minimum width, for (2+2), it's 2 bits, for 32'2+32'2 it's 32 bits
Stage m_stage; // If true, report errors
Stage m_stage; // If true, report errors
public:
WidthVP(int width, int widthMin, Stage stage) : m_width(width), m_widthMin(widthMin), m_stage(stage) {}
int width() const { return m_width; }
int widthMin() const { return m_widthMin?m_widthMin:m_width; }
bool prelim() const { return m_stage&1; }
bool final() const { return m_stage&2; }
char stageAscii() const { return "-PFB"[m_stage]; }
};
ostream& operator<<(ostream& str, const WidthVP* vup) {
str<<" VUP(w="<<vup->width()<<",wm="<<vup->widthMin()<<",s="<<vup->stageAscii()<<")";
return str;
}
//######################################################################
@@ -136,7 +141,7 @@ private:
virtual void visit(AstLogOr* nodep, AstNUser* vup) { visit_log_O1_LR1rus(nodep,vup); }
virtual void visit(AstLogIf* nodep, AstNUser* vup) { visit_log_O1_LR1rus(nodep,vup); } // Conversion from real not in IEEE, but a fallout
virtual void visit(AstLogIff* nodep, AstNUser* vup) { visit_log_O1_LR1rus(nodep,vup); } // Conversion from real not in IEEE, but a fallout
// Widths: 1 bit out, Any width lhs
virtual void visit(AstRedAnd* nodep, AstNUser* vup) { visit_red_O1_Lrus(nodep,vup,false); }
virtual void visit(AstRedOr* nodep, AstNUser* vup) { visit_red_O1_Lrus(nodep,vup,false); }
@@ -145,7 +150,7 @@ private:
virtual void visit(AstIsUnknown* nodep,AstNUser* vup) { visit_red_O1_Lrus(nodep,vup,true); } // Allow real
virtual void visit(AstOneHot* nodep,AstNUser* vup) { visit_red_O1_Lrus(nodep,vup,false); }
virtual void visit(AstOneHot0* nodep,AstNUser* vup) { visit_red_O1_Lrus(nodep,vup,false); }
// These have different node types, as they operate differently
// Must add to case statement below,
// Widths: 1 bit out, lhs width == rhs width. real if lhs|rhs real
@@ -199,7 +204,7 @@ private:
virtual void visit(AstNegate* nodep, AstNUser* vup) { visit_math_Orus_Dreplace(nodep,vup,true); }
// Unary never real
virtual void visit(AstNot* nodep, AstNUser* vup) { visit_math_Orus_Dreplace(nodep,vup,false); }
// Real: inputs and output real
virtual void visit(AstAddD* nodep, AstNUser* vup) { visit_math_Or_LRr(nodep,vup); }
virtual void visit(AstSubD* nodep, AstNUser* vup) { visit_math_Or_LRr(nodep,vup); }
@@ -215,18 +220,18 @@ private:
virtual void visit(AstLogD* nodep, AstNUser* vup) { visit_math_Or_Lr(nodep,vup); }
virtual void visit(AstLog10D* nodep, AstNUser* vup) { visit_math_Or_Lr(nodep,vup); }
virtual void visit(AstSqrtD* nodep, AstNUser* vup) { visit_math_Or_Lr(nodep,vup); }
// Widths: out signed/unsigned width = lhs width, input un|signed
// Widths: out signed/unsigned width = lhs width, input un|signed
virtual void visit(AstSigned* nodep, AstNUser* vup) { visit_Ous_Lus_Wforce(nodep,vup,AstNumeric::SIGNED); }
virtual void visit(AstUnsigned* nodep, AstNUser* vup) { visit_Ous_Lus_Wforce(nodep,vup,AstNumeric::UNSIGNED); }
// Widths: Output width from lhs, rhs<33 bits
// Signed: If lhs signed
virtual void visit(AstShiftL* nodep, AstNUser* vup) { visit_shift_Ous_Lus_Rus32(nodep,vup); }
virtual void visit(AstShiftR* nodep, AstNUser* vup) { visit_shift_Ous_Lus_Rus32(nodep,vup); }
// ShiftRS converts to ShiftR, but not vice-versa
virtual void visit(AstShiftRS* nodep, AstNUser* vup) { visit_shift_Ous_Lus_Rus32(nodep,vup); }
//========
// Widths: Output real, input integer signed
virtual void visit(AstBitsToRealD* nodep, AstNUser* vup) { visit_Or_Lu64(nodep,vup); }
@@ -235,15 +240,15 @@ private:
// Widths: Output integer signed, input real
virtual void visit(AstRToIS* nodep, AstNUser* vup) { visit_Os32_Lr(nodep,vup); }
virtual void visit(AstRToIRoundS* nodep, AstNUser* vup) { visit_Os32_Lr(nodep,vup); }
// Widths: Output integer unsigned, input real
virtual void visit(AstRealToBits* nodep, AstNUser* vup) { visit_Ou64_Lr(nodep,vup); }
// Widths: Constant, terminal
virtual void visit(AstTime* nodep, AstNUser*) { nodep->numeric(AstNumeric::UNSIGNED); nodep->width(64,64); }
virtual void visit(AstTime* nodep, AstNUser*) { nodep->dtypeChgUInt64(); }
virtual void visit(AstTimeD* nodep, AstNUser*) { nodep->dtypeChgDouble(); }
virtual void visit(AstTestPlusArgs* nodep, AstNUser*) { nodep->numeric(AstNumeric::UNSIGNED); nodep->width(32,32); }
virtual void visit(AstScopeName* nodep, AstNUser* vup) { nodep->width(64,1); } // A pointer, but not that it matters
virtual void visit(AstTestPlusArgs* nodep, AstNUser*) { nodep->dtypeChgSigned32(); }
virtual void visit(AstScopeName* nodep, AstNUser*) { nodep->dtypeChgUInt64(); } // A pointer, but not that it matters
// Special cases. So many....
virtual void visit(AstNodeCond* nodep, AstNUser* vup) {
@@ -280,7 +285,7 @@ private:
nodep->expr1p()->iterateAndNext(*this,WidthVP(width,mwidth,FINAL).p());
nodep->expr2p()->iterateAndNext(*this,WidthVP(width,mwidth,FINAL).p());
// Error report and change sizes for suboperands of this node.
widthCheckReduce(nodep,"Conditional Expression",nodep->condp(),1,0);
widthCheckReduce(nodep,"Conditional Test",nodep->condp(),1,0);
widthCheck(nodep,"Conditional True",nodep->expr1p(),width,mwidth);
widthCheck(nodep,"Conditional False",nodep->expr2p(),width,mwidth);
}
@@ -295,7 +300,7 @@ private:
checkCvtUS(nodep->rhsp());
nodep->width(nodep->lhsp()->width() + nodep->rhsp()->width(),
nodep->lhsp()->widthMin() + nodep->rhsp()->widthMin());
nodep->numeric(AstNumeric::UNSIGNED);
nodep->numeric(AstNumeric::UNSIGNED);
// Cleanup zero width Verilog2001 {x,{0{foo}}} now,
// otherwise having width(0) will cause later assertions to fire
if (AstReplicate* repp=nodep->lhsp()->castReplicate()) {
@@ -377,7 +382,7 @@ private:
AstConst* widthConstp = nodep->widthp()->castConst();
if (!widthConstp) {
nodep->v3error("Width of bit extract isn't a constant");
nodep->dtypeChgBool(); return;
nodep->dtypeChgLogicBool(); return;
}
int width = nodep->widthConst();
nodep->width(width,width);
@@ -405,7 +410,7 @@ private:
int frommsb = nodep->fromp()->width() - 1;
int fromlsb = 0;
AstNodeVarRef* varrp = nodep->fromp()->castNodeVarRef();
if (varrp && varrp->varp()->basicp()->rangep()) { // Selecting a bit from a multibit register
if (varrp && varrp->varp()->basicp()->isRanged()) { // Selecting a bit from a multibit register
frommsb = varrp->varp()->basicp()->msbMaxSelect(); // Corrected for negative lsb
fromlsb = varrp->varp()->basicp()->lsb();
}
@@ -457,7 +462,7 @@ private:
//
int frommsb;
int fromlsb;
AstNodeDType* ddtypep = varrp->varp()->dtypeDimensionp(dimension);
AstNodeDType* ddtypep = varrp->varp()->dtypep()->dtypeDimensionp(dimension);
if (AstArrayDType* adtypep = ddtypep->castArrayDType()) {
int outwidth = varrp->width(); // Width of variable
frommsb = adtypep->msb();
@@ -537,8 +542,7 @@ private:
}
virtual void visit(AstRand* nodep, AstNUser* vup) {
if (vup->c()->prelim()) {
nodep->numeric(AstNumeric::SIGNED); // Says the spec
nodep->width(32,32); // Says the spec
nodep->dtypeChgSigned32(); // Says the spec
}
}
virtual void visit(AstUCFunc* nodep, AstNUser* vup) {
@@ -558,8 +562,7 @@ private:
if (vup->c()->prelim()) {
nodep->lhsp()->iterateAndNext(*this,WidthVP(ANYSIZE,0,BOTH).p());
checkCvtUS(nodep->lhsp());
nodep->numeric(AstNumeric::UNSIGNED); // If want otherwise use a dpi import
nodep->width(32,32);
nodep->dtypeChgSigned32();
}
}
virtual void visit(AstPow* nodep, AstNUser* vup) {
@@ -615,6 +618,7 @@ private:
// But also cleanup array size
nodep->arrayp()->iterateAndNext(*this,WidthVP(ANYSIZE,0,BOTH).p());
nodep->widthFrom(nodep->dtypep());
UINFO(4,"dtWidthed "<<nodep<<endl);
}
virtual void visit(AstBasicDType* nodep, AstNUser* vup) {
if (nodep->rangep()) {
@@ -623,15 +627,18 @@ private:
}
// else width in node is correct; it was set based on keyword().width()
// at construction time. Ditto signed, so "unsigned byte" etc works right.
UINFO(4,"dtWidthed "<<nodep<<endl);
}
virtual void visit(AstConstDType* nodep, AstNUser* vup) {
nodep->iterateChildren(*this, vup);
nodep->widthFrom(nodep->dtypep());
UINFO(4,"dtWidthed "<<nodep<<endl);
}
virtual void visit(AstRefDType* nodep, AstNUser* vup) {
nodep->iterateChildren(*this, vup);
if (nodep->defp()) nodep->defp()->iterate(*this,vup);
nodep->widthSignedFrom(nodep->dtypeSkipRefp());
UINFO(4,"dtWidthed "<<nodep<<endl);
}
virtual void visit(AstTypedef* nodep, AstNUser* vup) {
nodep->iterateChildren(*this, vup);
@@ -693,16 +700,22 @@ private:
AstBasicDType* bdtypep = nodep->dtypep()->castBasicDType();
bool implicitParam = nodep->isParam() && bdtypep && bdtypep->implicit();
if (implicitParam) {
AstNumeric rs = AstNumeric::UNSIGNED;
int width=0;
AstNumeric rs = AstNumeric::UNSIGNED;
if (nodep->valuep()) {
nodep->valuep()->iterateAndNext(*this,WidthVP(width,0,PRELIM).p());
UINFO(9,"implicitParamPRELIMIV "<<nodep->valuep()<<endl);
// Although nodep will get a different width for parameters just below,
// we want the init numbers to retain their width/minwidth until parameters are replaced.
// This prevents width warnings at the location the parameter is substituted in
nodep->valuep()->iterateAndNext(*this,WidthVP(width,0,FINAL).p());
rs = nodep->numeric();
if (!rs.isDouble()) {
if (nodep->valuep()->isDouble()) {
nodep->dtypeChgDouble(); bdtypep=NULL;
nodep->dtypep()->dtypeChgDouble(); bdtypep=NULL;
nodep->valuep()->iterateAndNext(*this,WidthVP(width,0,FINAL).p());
} else {
nodep->valuep()->iterateAndNext(*this,WidthVP(width,0,FINAL).p());
if (bdtypep->nosigned()) rs = nodep->valuep()->numeric();
else rs = nodep->numeric();
if (nodep->valuep()->widthSized()) {
width = nodep->valuep()->width();
} else {
@@ -710,24 +723,20 @@ private:
width = 32;
}
}
}
// Parameter sizes can come from the thing they get assigned from
// They then "stick" to that width.
if (!width) width=32; // Or, if nothing, they're 32 bits.
// CLEANUP: If we have a TypeOf operator, or make dtype on every AstNode,
// this would be just a copy of the dtype into the var.
if (rs.isDouble()) {
AstBasicDType* newp = new AstBasicDType(nodep->fileline(), AstBasicDTypeKwd::DOUBLE);
bdtypep->replaceWith(newp);
bdtypep->deleteTree(); bdtypep=NULL;
UINFO(9,"implicitParamFromIV "<<nodep->valuep()<<endl);
//UINFO below will print variable nodep
} else {
// Or, if nothing assigned, they're 32 bits.
width=32;
}
if (!nodep->isDouble()) {
AstBasicDType* newp = new AstBasicDType(nodep->fileline(), AstLogicPacked(), width);
newp->implicit(true);
newp->numeric(rs); // SIGNED or UNSIGNED
bdtypep->replaceWith(newp);
bdtypep->deleteTree(); bdtypep=NULL;
nodep->dtypep()->iterateAndNext(*this,WidthVP(ANYSIZE,0,BOTH).p());
}
nodep->dtypep()->iterateAndNext(*this,WidthVP(ANYSIZE,0,BOTH).p());
}
else { // non param or sized param
nodep->dtypep()->iterateAndNext(*this,WidthVP(ANYSIZE,0,BOTH).p());
@@ -739,7 +748,7 @@ private:
// See above note about valuep()->...FINAL
nodep->widthSignedFrom(nodep->dtypep());
if (nodep->valuep()) {
if (implicitParam) {
if (implicitParam && !nodep->isDouble()) {
nodep->width(nodep->width(), nodep->valuep()->widthMin()); // Needed as mwidth might not equal width
}
widthCheck(nodep,"Initial value",nodep->valuep(),
@@ -829,7 +838,7 @@ private:
widthCheckReduce(nodep,"Disable",nodep->disablep(),1,1); // it's like an if() condition.
}
widthCheckReduce(nodep,"Property",nodep->propp(),1,1); // it's like an if() condition.
nodep->dtypeChgBool();
nodep->dtypeChgLogicBool();
}
//--------------------
@@ -840,47 +849,34 @@ private:
AstNodeCase* lastCasep = m_casep;
m_casep = nodep;
nodep->exprp()->iterateAndNext(*this,WidthVP(ANYSIZE,0,PRELIM).p());
for (AstCaseItem* nextp, *itemp = nodep->itemsp(); itemp; itemp=nextp) {
nextp = itemp->nextp()->castCaseItem(); // Prelim may cause the node to get replaced
itemp->iterate(*this,WidthVP(ANYSIZE,0,PRELIM).p()); itemp=NULL;
for (AstCaseItem* nextip, *itemp = nodep->itemsp(); itemp; itemp=nextip) {
nextip = itemp->nextp()->castCaseItem(); // Prelim may cause the node to get replaced
if (!m_casep->castGenCase()) itemp->bodysp()->iterateAndNext(*this);
for (AstNode* nextcp, *condp = itemp->condsp(); condp; condp=nextcp) {
nextcp = condp->nextp(); // Prelim may cause the node to get replaced
condp->iterate(*this,WidthVP(ANYSIZE,0,PRELIM).p()); condp=NULL;
}
}
// Take width as maximum across all items
int width = nodep->exprp()->width();
int mwidth = nodep->exprp()->widthMin();
for (AstCaseItem* itemp = nodep->itemsp(); itemp; itemp=itemp->nextp()->castCaseItem()) {
width = max(width,itemp->width());
mwidth = max(mwidth,itemp->widthMin());
for (AstNode* condp = itemp->condsp(); condp; condp=condp->nextp()) {
width = max(width,condp->width());
mwidth = max(mwidth,condp->widthMin());
}
}
// Apply width
nodep->exprp()->iterateAndNext(*this,WidthVP(width,mwidth,FINAL).p());
for (AstCaseItem* itemp = nodep->itemsp(); itemp; itemp=itemp->nextp()->castCaseItem()) {
itemp->iterate(*this,WidthVP(width,mwidth,FINAL).p());
for (AstNode* condp = itemp->condsp(); condp; condp=condp->nextp()) {
condp->iterate(*this,WidthVP(width,mwidth,FINAL).p());
widthCheck(nodep,"Case Item",condp,width,mwidth);
}
}
widthCheck(nodep,"Case expression",nodep->exprp(),width,mwidth);
m_casep = lastCasep;
}
virtual void visit(AstCaseItem* nodep, AstNUser* vup) {
// Same for both prelim() and final()
if (!m_casep->castGenCase()) nodep->bodysp()->iterateAndNext(*this);
if (!nodep->condsp()) {
// Else "default:" of the case, just return benign value
nodep->width(vup->c()->width(),vup->c()->widthMin());
} else {
// Need to look across multiple case values for one set of statements
int width = nodep->condsp()->width();
int mwidth = nodep->condsp()->widthMin();
for (AstNode* nextp, *condp = nodep->condsp(); condp; condp=nextp) {
nextp = condp->nextp(); // Prelim may cause the node to get replaced
condp->iterate(*this,vup); condp=NULL;
}
for (AstNode* condp = nodep->condsp(); condp; condp=condp->nextp()) {
width = max(width,condp->width());
mwidth = max(mwidth,condp->widthMin());
if (vup->c()->final()) {
widthCheck(nodep,"Case Item",condp,vup->c()->width(),vup->c()->widthMin());
}
}
nodep->width(width,mwidth);
}
}
virtual void visit(AstNodeFor* nodep, AstNUser*) {
// TOP LEVEL NODE
nodep->initsp()->iterateAndNext(*this);
@@ -1017,7 +1013,7 @@ private:
nodep->filep()->iterateAndNext(*this,WidthVP(32,32,BOTH).p());
nodep->strgp()->iterateAndNext(*this,WidthVP(ANYSIZE,0,BOTH).p());
if (vup->c()->prelim()) {
nodep->width(32,32);
nodep->dtypeChgSigned32(); // Spec says integer return
}
widthCheck(nodep,"file_descriptor",nodep->filep(),32,32);
}
@@ -1025,7 +1021,7 @@ private:
nodep->filep()->iterateAndNext(*this,WidthVP(32,32,BOTH).p());
nodep->exprsp()->iterateAndNext(*this,WidthVP(ANYSIZE,0,BOTH).p());
if (vup->c()->prelim()) {
nodep->width(32,32);
nodep->dtypeChgSigned32(); // Spec says integer return
}
widthCheck(nodep,"file_descriptor",nodep->filep(),32,32);
}
@@ -1033,7 +1029,7 @@ private:
nodep->fromp()->iterateAndNext(*this,WidthVP(ANYSIZE,0,BOTH).p());
nodep->exprsp()->iterateAndNext(*this,WidthVP(ANYSIZE,0,BOTH).p());
if (vup->c()->prelim()) {
nodep->width(32,32);
nodep->dtypeChgSigned32(); // Spec says integer return
}
}
virtual void visit(AstSysIgnore* nodep, AstNUser* vup) {
@@ -1041,8 +1037,7 @@ private:
}
virtual void visit(AstSystemF* nodep, AstNUser*) {
nodep->lhsp()->iterateAndNext(*this,WidthVP(ANYSIZE,0,BOTH).p());
nodep->numeric(AstNumeric::UNSIGNED);
nodep->width(32,32);
nodep->dtypeChgSigned32(); // Spec says integer return
}
virtual void visit(AstSystemT* nodep, AstNUser*) {
nodep->lhsp()->iterateAndNext(*this,WidthVP(ANYSIZE,0,BOTH).p());
@@ -1055,8 +1050,7 @@ private:
}
virtual void visit(AstValuePlusArgs* nodep, AstNUser* vup) {
nodep->exprsp()->iterateAndNext(*this,WidthVP(ANYSIZE,0,BOTH).p());
nodep->numeric(AstNumeric::UNSIGNED);
nodep->width(32,32);
nodep->dtypeChgSigned32(); // Spec says integer return
}
virtual void visit(AstUCStmt* nodep, AstNUser*) {
// TOP LEVEL NODE
@@ -1165,7 +1159,7 @@ private:
UINFO(5," FTASK "<<nodep<<endl);
if (nodep->doingWidth()) {
nodep->v3error("Unsupported: Recursive function or task call");
nodep->dtypeChgBool();
nodep->dtypeChgLogicBool();
nodep->didWidth(true);
return;
}
@@ -1259,9 +1253,9 @@ private:
if ((portp->isOutput() || portp->isInout())
&& pinp->width() != portp->width()) {
pinp->v3error("Unsupported: Function output argument '"<<portp->prettyName()<<"'"
<<" requires "<<pinp->width()
<<" requires "<<portp->width()
<<" bits, but connection's "<<pinp->prettyTypeName()
<<" generates "<<portp->width()<<" bits.");
<<" generates "<<pinp->width()<<" bits.");
// otherwise would need some mess to force both sides to proper size
// (get an ASSIGN with EXTEND on the lhs instead of rhs)
}
@@ -1320,8 +1314,7 @@ private:
if (vup->c()->prelim()) { // First stage evaluation
nodep->lhsp()->iterateAndNext(*this,WidthVP(ANYSIZE,0,BOTH).p());
checkCvtD(nodep->lhsp());
nodep->numeric(AstNumeric::SIGNED);
nodep->width(32,32);
nodep->dtypeChgSigned32();
}
}
void visit_Ou64_Lr(AstNodeUniop* nodep, AstNUser* vup) {
@@ -1330,8 +1323,7 @@ private:
if (vup->c()->prelim()) { // First stage evaluation
nodep->lhsp()->iterateAndNext(*this,WidthVP(ANYSIZE,0,BOTH).p());
checkCvtD(nodep->lhsp());
nodep->numeric(AstNumeric::UNSIGNED);
nodep->width(64,64);
nodep->dtypeChgUInt64();
}
}
@@ -1348,7 +1340,7 @@ private:
nodep->op1p()->iterateAndNext(*this,WidthVP(1,0,BOTH).p());
spliceCvtCmpD0(nodep->op1p());
}
nodep->dtypeChgBool();
nodep->dtypeChgLogicBool();
if (vup->c()->final()) {
widthCheckReduce(nodep,"LHS",nodep->op1p(),1,1);
}
@@ -1362,7 +1354,7 @@ private:
spliceCvtCmpD0(nodep->lhsp());
spliceCvtCmpD0(nodep->rhsp());
}
nodep->dtypeChgBool();
nodep->dtypeChgLogicBool();
if (vup->c()->final()) {
widthCheckReduce(nodep,"LHS",nodep->lhsp(),1,1);
widthCheckReduce(nodep,"RHS",nodep->rhsp(),1,1);
@@ -1377,14 +1369,14 @@ private:
nodep->lhsp()->iterateAndNext(*this,WidthVP(ANYSIZE,0,BOTH).p());
}
if (!realok) checkCvtUS(nodep->lhsp());
nodep->dtypeChgBool();
nodep->dtypeChgLogicBool();
}
void visit_cmp_O1_DSreplace(AstNodeBiop* nodep, AstNUser* vup) {
// CALLER: AstEq, AstGt, ..., AstLtS
// COMPARES
// Widths: 1 bit out, lhs width == rhs width
// Signed: if RHS&LHS signed, OPERATOR CHANGES to signed flavor
// Real: allowed on RHS, if RHS|LHS is real, both become real, and OPERATOR CHANGES
// Real: allowed on RHS, if RHS|LHS is real, both become real, and OPERATOR CHANGES
if (vup->c()->prelim()) {
nodep->lhsp()->iterateAndNext(*this,WidthVP(ANYSIZE,0,PRELIM).p());
nodep->rhsp()->iterateAndNext(*this,WidthVP(ANYSIZE,0,PRELIM).p());
@@ -1403,7 +1395,7 @@ private:
}
int width = max(nodep->lhsp()->width(), nodep->rhsp()->width());
int ewidth = max(nodep->lhsp()->widthMin(), nodep->rhsp()->widthMin());
nodep->dtypeChgBool();
nodep->dtypeChgLogicBool();
if (vup->c()->final()) {
nodep->lhsp()->iterateAndNext(*this,WidthVP(width,ewidth,FINAL).p());
nodep->rhsp()->iterateAndNext(*this,WidthVP(width,ewidth,FINAL).p());
@@ -1431,7 +1423,7 @@ private:
}
int width = max(nodep->lhsp()->width(), nodep->rhsp()->width());
int ewidth = max(nodep->lhsp()->widthMin(), nodep->rhsp()->widthMin());
nodep->dtypeChgBool();
nodep->dtypeChgLogicBool();
if (vup->c()->final()) {
nodep->lhsp()->iterateAndNext(*this,WidthVP(width,ewidth,FINAL).p());
nodep->rhsp()->iterateAndNext(*this,WidthVP(width,ewidth,FINAL).p());
+13 -12
View File
@@ -78,12 +78,12 @@ private:
// Perform error checks on the node
AstVar* varp = varFromBasefrom(basefromp);
//UINFO(9,"SCD\n"); if (debug()>=9) nodep->backp()->dumpTree(cout,"-selcheck: ");
AstNodeDType* ddtypep = varp->dtypeDimensionp(dimension);
AstNodeDType* ddtypep = varp->dtypep()->dtypeDimensionp(dimension);
if (AstArrayDType* adtypep = ddtypep->castArrayDType()) {
return adtypep;
}
else if (AstBasicDType* adtypep = ddtypep->castBasicDType()) {
if (!adtypep->rangep()) {
if (!adtypep->isRanged()) {
nodep->v3error("Illegal bit select; variable does not have a bit range, or bad dimension: "<<varp->prettyName());
return NULL;
}
@@ -110,13 +110,13 @@ private:
} else if (rhs > 0) {
AstNode* newp = new AstSub(lhsp->fileline(), lhsp,
new AstConst(lhsp->fileline(), AstConst::Unsized32(), rhs));
// We must make sure sub gets sign of original value
// We must make sure sub gets sign of original value, not from the constant
newp->numericFrom(lhsp);
return newp;
} else { // rhs < 0;
AstNode* newp = new AstAdd(lhsp->fileline(), lhsp,
new AstConst(lhsp->fileline(), AstConst::Unsized32(), -rhs));
// We must make sure sub gets sign of original value
// We must make sure sub gets sign of original value, not from the constant
newp->numericFrom(lhsp);
return newp;
}
@@ -144,14 +144,15 @@ private:
// Don't report WIDTH warnings etc here, as may be inside a generate branch that will be deleted
AstVar* varp = varFromBasefrom(basefromp);
// SUB #'s Not needed when LSB==0 and MSB>=0 (ie [0:-13] must still get added!)
if (!varp->basicp()->rangep()) {
// vector without range is ok, for example a INTEGER x; y = x[21:0];
if (!varp->basicp()->isRanged()) {
// vector without range, or 0 lsb is ok, for example a INTEGER x; y = x[21:0];
return underp;
} else {
if (!varp->basicp()->rangep()->msbp()->castConst()
|| !varp->basicp()->rangep()->lsbp()->castConst())
if (varp->basicp()->rangep()
&& (!varp->basicp()->rangep()->msbp()->castConst()
|| !varp->basicp()->rangep()->lsbp()->castConst()))
varp->v3fatalSrc("Non-constant variable range; errored earlier"); // in constifyParam(varp)
if (varp->basicp()->rangep()->littleEndian()) {
if (varp->basicp()->littleEndian()) {
// reg [1:3] was swapped to [3:1] (lsbEndianedp==3) and needs a SUB(3,under)
AstNode* newp = newSubNeg(varp->basicp()->msb(), underp);
return newp;
@@ -263,7 +264,7 @@ private:
}
} else if (AstBasicDType* adtypep = ddtypep->castBasicDType()) {
if (adtypep) {} // Unused
if (varp->basicp()->rangep() && varp->basicp()->rangep()->littleEndian()) {
if (varp->basicp()->littleEndian()) {
// Below code assumes big bit endian; just works out if we swap
int x = msb; msb = lsb; lsb = x;
}
@@ -308,7 +309,7 @@ private:
if (AstBasicDType* adtypep = ddtypep->castBasicDType()) {
AstSel* newp = NULL;
if (nodep->castSelPlus()) {
if (adtypep->rangep() && adtypep->rangep()->littleEndian()) {
if (adtypep->littleEndian()) {
// SELPLUS(from,lsb,width) -> SEL(from, (vector_msb-width+1)-sel, width)
newp = new AstSel (nodep->fileline(),
fromp,
@@ -322,7 +323,7 @@ private:
widthp);
}
} else if (nodep->castSelMinus()) {
if (adtypep->rangep() && adtypep->rangep()->littleEndian()) {
if (adtypep->littleEndian()) {
// SELMINUS(from,msb,width) -> SEL(from, msb-[bit])
newp = new AstSel (nodep->fileline(),
fromp,
+6 -2
View File
@@ -94,7 +94,11 @@ V3Global v3Global;
//######################################################################
// V3 Class -- top level
AstNetlist* V3Global::makeNetlist() { return new AstNetlist(); }
AstNetlist* V3Global::makeNetlist() {
AstNetlist* newp = new AstNetlist();
return newp;
}
void V3Global::checkTree() { rootp()->checkTree(); }
void V3Global::clear() {
@@ -488,7 +492,7 @@ void process () {
// Bits between widthMin() and width() are irrelevant, but may be non zero.
v3Global.assertWidthsMatch(false);
// Make all operations a multiple of 32 bits
// Make all math operations either 8, 16, 32 or 64 bits
V3Clean::cleanAll(v3Global.rootp());
v3Global.rootp()->dumpTreeFile(v3Global.debugFilename("clean.tree"));
+4 -4
View File
@@ -532,16 +532,16 @@ This switch causes the name.tab.c output to include a list of token names
in order by their token numbers; this is defined in the array yytname.
Also generated are #defines for YYNTOKENS, YYNNTS, YYNRULES, and YYNSTATES.
==item -t
==item --debug
=item -t
=item --debug
Passed to bison.
In the parser file, define the macro YYDEBUG to 1 if it is not already
defined, so that the debugging facilities are compiled.
==item -v
==item --verbose
=item -v
=item --verbose
Passed to bison.
+1 -1
View File
@@ -1017,7 +1017,7 @@ word [a-zA-Z0-9_]+
"`begin_keywords"[ \t]*\"1800-2005\" { yy_push_state(S05); PARSEP->pushBeginKeywords(YY_START); }
"`begin_keywords"[ \t]*\"1800-2009\" { yy_push_state(S09); PARSEP->pushBeginKeywords(YY_START); }
"`begin_keywords"[ \t]*\"1800+VAMS\" { yy_push_state(SA9); PARSEP->pushBeginKeywords(YY_START); }
"`end_keywords" { yy_pop_state(); if (!PARSEP->popBeginKeywords()) yyerrorf("`end_keywords when not inside `begin_keywords block"); }
"`end_keywords" { yy_pop_state(); if (!PARSEP->popBeginKeywords()) yyerrorf("`end_keywords when not inside `begin_keywords block"); }
/* Verilator */
"`systemc_ctor" { BEGIN SYSCCTOR; }
+36 -25
View File
@@ -96,6 +96,12 @@ public:
nodep->addNext(new AstStop(fileline));
return nodep;
}
void endLabel(FileLine* fl, AstNode* nodep, string* endnamep) { endLabel(fl, nodep->prettyName(), endnamep); }
void endLabel(FileLine* fl, string name, string* endnamep) {
if (fl && endnamep && *endnamep != "" && name != *endnamep) {
fl->v3warn(ENDLABEL,"End label '"<<*endnamep<<"' does not match begin label '"<<name<<"'");
}
}
void setDType(AstNodeDType* dtypep) {
if (m_varDTypep) { m_varDTypep->deleteTree(); m_varDTypep=NULL; } // It was cloned, so this is safe.
m_varDTypep = dtypep;
@@ -122,7 +128,7 @@ public:
// then [1:1] becomes the basicdtype range; everything else is arraying
// the final [5:5][4:4] will be passed in another call to createArray
AstRange* rangearraysp = NULL;
if (dtypep->rangep()) {
if (dtypep->isRanged()) {
rangearraysp = rangesp; // Already a range; everything is an array
} else {
AstRange* finalp = rangesp;
@@ -631,7 +637,8 @@ package_declaration: // ==IEEE: package_declaration
packageFront package_itemListE yENDPACKAGE endLabelE
{ $1->modTrace(v3Global.opt.trace() && $1->fileline()->tracingOn()); // Stash for implicit wires, etc
if ($2) $1->addStmtp($2);
SYMP->popScope($1); }
SYMP->popScope($1);
GRAMMARP->endLabel($<fl>4,$1,$4); }
;
packageFront<modulep>:
@@ -708,13 +715,15 @@ module_declaration: // ==IEEE: module_declaration
{ $1->modTrace(v3Global.opt.trace() && $1->fileline()->tracingOn()); // Stash for implicit wires, etc
if ($2) $1->addStmtp($2); if ($3) $1->addStmtp($3);
if ($5) $1->addStmtp($5);
SYMP->popScope($1); }
SYMP->popScope($1);
GRAMMARP->endLabel($<fl>7,$1,$7); }
| udpFront parameter_port_listE portsStarE ';'
module_itemListE yENDPRIMITIVE endLabelE
{ $1->modTrace(false); // Stash for implicit wires, etc
if ($2) $1->addStmtp($2); if ($3) $1->addStmtp($3);
if ($5) $1->addStmtp($5);
SYMP->popScope($1); }
SYMP->popScope($1);
GRAMMARP->endLabel($<fl>7,$1,$7); }
//
//UNSUP yEXTERN modFront parameter_port_listE portsStarE ';'
//UNSUP { UNSUP }
@@ -885,7 +894,8 @@ program_declaration: // IEEE: program_declaration + program_nonansi_header + pr
{ $1->modTrace(v3Global.opt.trace() && $1->fileline()->tracingOn()); // Stash for implicit wires, etc
if ($2) $1->addStmtp($2); if ($3) $1->addStmtp($3);
if ($5) $1->addStmtp($5);
SYMP->popScope($1); }
SYMP->popScope($1);
GRAMMARP->endLabel($<fl>7,$1,$7); }
//UNSUP yEXTERN pgmFront parameter_port_listE portsStarE ';'
//UNSUP { PARSEP->symPopScope(VAstType::PROGRAM); }
;
@@ -1093,7 +1103,7 @@ non_integer_type<bdtypep>: // ==IEEE: non_integer_type
;
signingE<signstate>: // IEEE: signing - plus empty
/*empty*/ { $$ = signedst_NOP; }
/*empty*/ { $$ = signedst_NOSIGNED; }
| signing { $$ = $1; }
;
@@ -1139,7 +1149,7 @@ data_type<dtypep>: // ==IEEE: data_type
// // IEEE: class_type
//UNSUP class_typeWithoutId { $$ = $1; }
// // IEEE: ps_covergroup_identifier
//UNSUP ps_covergroup_identifier { $$ = $1; }
// // we put covergroups under ps_type, so can ignore this
;
data_typeBasic<dtypep>: // IEEE: part of data_type
@@ -1154,7 +1164,8 @@ data_typeNoRef<dtypep>: // ==IEEE: data_type, excluding class_type etc referenc
//UNSUP { UNSUP }
//UNSUP yUNION taggedE packedSigningE '{' struct_union_memberList '}' packed_dimensionListE
//UNSUP { UNSUP }
| enumDecl { $$ = new AstDefImplicitDType($1->fileline(),"__typeimpenum"+cvtToStr(GRAMMARP->m_modTypeImpNum++),GRAMMARP->m_modp,$1); }
| enumDecl { $$ = new AstDefImplicitDType($1->fileline(),"__typeimpenum"+cvtToStr(GRAMMARP->m_modTypeImpNum++),
GRAMMARP->m_modp,$1); }
| ySTRING { $$ = new AstBasicDType($1,AstBasicDTypeKwd::STRING); }
| yCHANDLE { $$ = new AstBasicDType($1,AstBasicDTypeKwd::CHANDLE); }
//UNSUP yEVENT { UNSUP }
@@ -1250,7 +1261,9 @@ enum_base_typeE<dtypep>: // IEEE: enum_base_type
//
| integer_atom_type signingE { $1->setSignedState($2); $$ = $1; }
| integer_vector_type signingE rangeListE { $1->setSignedState($2); $$ = GRAMMARP->addRange($1,$3,false); }
| yaID__aTYPE rangeListE { $$ = GRAMMARP->createArray(new AstRefDType($<fl>1, *$1), $2, false); }
// // below can be idAny or yaID__aTYPE
// // IEEE requires a type, though no shift conflict if idAny
| idAny rangeListE { $$ = GRAMMARP->createArray(new AstRefDType($<fl>1, *$1), $2, false); }
;
enum_nameList<nodep>:
@@ -1450,10 +1463,10 @@ genTopBlock<nodep>:
genItemBegin<nodep>: // IEEE: part of generate_block
yBEGIN genItemList yEND { $$ = new AstBegin($1,"genblk",$2); }
| yBEGIN yEND { $$ = NULL; }
| id ':' yBEGIN genItemList yEND endLabelE { $$ = new AstBegin($2,*$1,$4); }
| id ':' yBEGIN yEND endLabelE { $$ = NULL; }
| yBEGIN ':' idAny genItemList yEND endLabelE { $$ = new AstBegin($2,*$3,$4); }
| yBEGIN ':' idAny yEND endLabelE { $$ = NULL; }
| id ':' yBEGIN genItemList yEND endLabelE { $$ = new AstBegin($2,*$1,$4); GRAMMARP->endLabel($<fl>6,*$1,$6); }
| id ':' yBEGIN yEND endLabelE { $$ = NULL; GRAMMARP->endLabel($<fl>5,*$1,$5); }
| yBEGIN ':' idAny genItemList yEND endLabelE { $$ = new AstBegin($2,*$3,$4); GRAMMARP->endLabel($<fl>6,*$3,$6); }
| yBEGIN ':' idAny yEND endLabelE { $$ = NULL; GRAMMARP->endLabel($<fl>5,*$3,$5); }
;
genItemList<nodep>:
@@ -1824,8 +1837,8 @@ stmtBlock<nodep>: // IEEE: statement + seq_block + par_block
seq_block<nodep>: // ==IEEE: seq_block
// // IEEE doesn't allow declarations in unnamed blocks, but several simulators do.
// // So need begin's even if unnamed to scope variables down
seq_blockFront blockDeclStmtList yEND endLabelE { $$=$1; $1->addStmtsp($2); SYMP->popScope($1); }
| seq_blockFront /**/ yEND endLabelE { $$=$1; SYMP->popScope($1); }
seq_blockFront blockDeclStmtList yEND endLabelE { $$=$1; $1->addStmtsp($2); SYMP->popScope($1); GRAMMARP->endLabel($<fl>4,$1,$4); }
| seq_blockFront /**/ yEND endLabelE { $$=$1; SYMP->popScope($1); GRAMMARP->endLabel($<fl>3,$1,$3); }
;
seq_blockFront<beginp>: // IEEE: part of par_block
@@ -2227,7 +2240,8 @@ list_of_argumentsE<nodep>: // IEEE: [list_of_arguments]
task_declaration<ftaskp>: // ==IEEE: task_declaration
yTASK lifetimeE taskId tfGuts yENDTASK endLabelE
{ $$ = $3; $$->addStmtsp($4); SYMP->popScope($$); }
{ $$ = $3; $$->addStmtsp($4); SYMP->popScope($$);
GRAMMARP->endLabel($<fl>6,$$,$6); }
;
task_prototype<ftaskp>: // ==IEEE: task_prototype
@@ -2237,7 +2251,8 @@ task_prototype<ftaskp>: // ==IEEE: task_prototype
function_declaration<ftaskp>: // IEEE: function_declaration + function_body_declaration
yFUNCTION lifetimeE funcId funcIsolateE tfGuts yENDFUNCTION endLabelE
{ $$ = $3; $3->attrIsolateAssign($4); $$->addStmtsp($5);
SYMP->popScope($$); }
SYMP->popScope($$);
GRAMMARP->endLabel($<fl>7,$$,$7); }
;
function_prototype<ftaskp>: // IEEE: function_prototype
@@ -3001,10 +3016,10 @@ strAsText<nodep>:
yaSTRING { $$ = GRAMMARP->createTextQuoted($<fl>1,*$1);}
;
endLabelE:
/* empty */ { }
| ':' idAny { }
//UNSUP ':' yNEW__ETC { }
endLabelE<strp>:
/* empty */ { $$ = NULL; $<fl>$=NULL; }
| ':' idAny { $$ = $2; $<fl>$=$<fl>2; }
//UNSUP ':' yNEW__ETC { $$ = $2; $<fl>$=$<fl>2; }
;
//************************************************
@@ -3321,7 +3336,3 @@ string V3ParseGrammar::deQuote(FileLine* fileline, string text) {
// --report=lookahead
// --report=itemset
// --graph
//
// Local Variables:
// compile-command: "cd obj_dbg ; /usr/bin/bison -y -d -v ../verilog.y ; cat y.output"
// End:
+1
View File
@@ -0,0 +1 @@
source ../src/.gdbinit
+5 -1
View File
@@ -42,7 +42,11 @@ ifeq ($(VM_SP_OR_SC),1)
LIBS += $(SC_LIBS)
endif
#Default compile, using normal make rules
#Default compile, pick up OBJCACHE
%.o: %.cpp
$(OBJCACHE) $(CXX) -c $(CPPFLAGS) $(CXXFLAGS) $<
#Default link, using normal make rules
#$(VM_PREFIX): $(VK_GLOBAL_OBJS) $(VK_OBJS)
# $(LINK) $(LDFLAGS) -g $^ $(LOADLIBES) $(LDLIBS) -o $@ $(LIBS) 2>&1 | c++filt
+58 -27
View File
@@ -278,7 +278,19 @@ sub new {
my $self = {@_};
$self->{name} ||= $2 if $self->{pl_filename} =~ m!^(.*/)?([^/]*)\.pl$!;
$self->{obj_dir} ||= "obj_dir/$self->{name}";
$self->{mode} = "";
$self->{mode} ||= "atsim" if $self->{atsim};
$self->{mode} ||= "ghdl" if $self->{ghdl};
$self->{mode} ||= "vcs" if $self->{vcs};
$self->{mode} ||= "vlt" if $self->{vlt};
$self->{mode} ||= "nc" if $self->{nc};
$self->{mode} ||= "iv" if $self->{iv};
# For backward compatibility, the verilator tests have no prefix
$self->{obj_dir} ||= ("obj_dir/".($self->{mode} eq 'vlt' ? "" : $self->{mode}."_")
."$self->{name}");
foreach my $dir (@::Test_Dirs) {
# t_dir used both absolutely and under obj_dir
if (-e "$dir/$self->{name}.pl") {
@@ -291,9 +303,9 @@ sub new {
}
}
$self->{t_dir} or die "%Error: Can't locate dir for $self->{name},";
$self = {
name => undef, # Set below, name of this test
mode => "",
pl_filename => undef, # Name of .pl file to get setup from
make_top_shell => 1, # Make a default __top.v file
make_main => 1, # Make __main.cpp
@@ -316,29 +328,29 @@ sub new {
atsim_flags => [split(/\s+/,"-c +sv +define+ATSIM"),
"+sv_dir+$self->{obj_dir}/.athdl_compile"],
atsim_flags2 => [], # Overridden in some sim files
atsimrun_flags => [],
atsim_run_flags => [],
# GHDL
ghdl => 0,
ghdl_work_dir => "$self->{obj_dir}/ghdl_compile",
ghdl_flags => [($::Debug?"-v":""),
"--workdir=$self->{obj_dir}/ghdl_compile", ],
ghdl_flags2 => [], # Overridden in some sim files
ghdlrun_flags => [],
ghdl_run_flags => [],
# IV
iv => 0,
iv_flags => [split(/\s+/,"+define+iverilog -o $self->{obj_dir}/simiv")],
iv_flags2 => [], # Overridden in some sim files
ivrun_flags => [],
iv_run_flags => [],
# VCS
vcs => 0,
vcs_flags => [split(/\s+/,"+vcs+lic+wait +cli -I +define+VCS+1 -q -sverilog -CFLAGS '-DVCS' ")],
vcs_flags2 => [], # Overridden in some sim files
vcsrun_flags => [split(/\s+/,"+vcs+lic_wait")],
vcs_run_flags => [split(/\s+/,"+vcs+lic_wait")],
# NC
nc => 0,
nc_flags => [split(/\s+/,"+licqueue +nowarn+LIBNOU +define+NC=1 -q +assert +sv -c ")],
nc_flags2 => [], # Overridden in some sim files
ncrun_flags => [split(/\s+/,"+licqueue -q +assert +sv -R")],
nc_run_flags => [split(/\s+/,"+licqueue -q +assert +sv -R")],
# Verilator
vlt => 0,
'v3' => 0,
@@ -352,12 +364,6 @@ sub new {
%$self};
bless $self, $class;
$self->{mode} ||= "atsim" if $self->{atsim};
$self->{mode} ||= "ghdl" if $self->{ghdl};
$self->{mode} ||= "vcs" if $self->{vcs};
$self->{mode} ||= "vlt" if $self->{vlt};
$self->{mode} ||= "nc" if $self->{nc};
$self->{mode} ||= "iv" if $self->{iv};
$self->{VM_PREFIX} ||= "V".$self->{name};
$self->{stats} ||= "$self->{obj_dir}/V".$self->{name}."__stats.txt";
$self->{status_filename} ||= "$self->{obj_dir}/V".$self->{name}.".status";
@@ -365,7 +371,18 @@ sub new {
$self->{coverage_filename} ||= "$self->{obj_dir}/vlt_coverage.pl";
$self->{vcd_filename} ||= "$self->{obj_dir}/sim.vcd";
$self->{main_filename} ||= "$self->{obj_dir}/$self->{VM_PREFIX}__main.cpp";
($self->{top_filename} = $self->{pl_filename}) =~ s/\.pl$/\.v/;
($self->{top_filename} = $self->{pl_filename}) =~ s/\.pl$//;
if (-e ($self->{top_filename}.".vhd")) { # If VHDL file exists
$self->{vhdl} = 1;
$self->{top_filename} .= ".vhd";
} else {
$self->{top_filename} .= ".v";
}
if (!$self->{make_top_shell}) {
$self->{top_shell_filename} = $self->{top_filename};
} else {
$self->{top_shell_filename} = "$self->{obj_dir}/$self->{VM_PREFIX}__top.v";
}
return $self;
}
@@ -631,6 +648,7 @@ sub execute {
my $self = (ref $_[0]? shift : $Self);
return 1 if $self->errors || $self->skips;
my %param = (%{$self}, @_); # Default arguments are from $self
# params may be expect or {tool}_expect
$self->oprint("Run\n");
my $run_env = $param{run_env};
@@ -640,44 +658,56 @@ sub execute {
$self->_run(logfile=>"$self->{obj_dir}/atsim_sim.log",
fails=>$param{fails},
cmd=>["echo q | ".$run_env."$self->{obj_dir}/athdl_sv",
@{$param{atsimrun_flags}},
@{$param{atsim_run_flags}},
@{$param{all_run_flags}},
]);
],
%param,
expect=>$param{atsim_run_expect}, # non-verilator expect isn't the same
);
}
elsif ($param{ghdl}) {
$self->_run(logfile=>"$self->{obj_dir}/ghdl_sim.log",
fails=>$param{fails},
cmd=>[$run_env."$self->{obj_dir}/simghdl",
@{$param{ghdlrun_flags}},
@{$param{ghdl_run_flags}},
@{$param{all_run_flags}},
]);
],
%param,
expect=>$param{ghdl_run_expect}, # non-verilator expect isn't the same
);
}
elsif ($param{iv}) {
$self->_run(logfile=>"$self->{obj_dir}/iv_sim.log",
fails=>$param{fails},
cmd=>[$run_env."$self->{obj_dir}/simiv",
@{$param{ivrun_flags}},
@{$param{iv_run_flags}},
@{$param{all_run_flags}},
]);
],
%param,
expect=>$param{iv_run_expect}, # non-verilator expect isn't the same
);
}
elsif ($param{nc}) {
$self->_run(logfile=>"$self->{obj_dir}/nc_sim.log",
fails=>$param{fails},
cmd=>["echo q | ".$run_env.($ENV{VERILATOR_NCVERILOG}||"ncverilog"),
@{$param{ncrun_flags}},
@{$param{nc_run_flags}},
@{$param{all_run_flags}},
]);
],
%param,
expect=>$param{nc_run_expect}, # non-verilator expect isn't the same
);
}
elsif ($param{vcs}) {
#my $fh = IO::File->new(">simv.key") or die "%Error: $! simv.key,";
#$fh->print("quit\n"); $fh->close;
$self->_run(logfile=>"$self->{obj_dir}/vcs_sim.log",
cmd=>["echo q | ".$run_env."./simv",
@{$param{vcsrun_flags}},
@{$param{vcs_run_flags}},
@{$param{all_run_flags}},
],
%param,
expect=>undef, # vcs expect isn't the same
expect=>$param{vcs_run_expect}, # non-verilator expect isn't the same
);
}
elsif ($param{vlt}
@@ -691,6 +721,7 @@ sub execute {
@{$param{all_run_flags}},
],
%param,
expect=>$param{expect}, # backward compatible name
);
}
else {
@@ -1170,7 +1201,7 @@ sub _sp_preproc {
sub _read_inputs_v {
my $self = shift;
my $filename = $self->{top_filename};
my $filename = $self->top_filename;
$filename = "$self->{t_dir}/$filename" if !-r $filename;
my $fh = IO::File->new("<$filename") or die "%Error: $! $filename,";
while (defined(my $line = $fh->getline)) {
@@ -1188,7 +1219,7 @@ sub _read_inputs_v {
sub _read_inputs_vhdl {
my $self = shift;
my $filename = $self->{top_filename};
my $filename = $self->top_filename;
$filename = "$self->{t_dir}/$filename" if !-r $filename;
my $fh = IO::File->new("<$filename") or die "%Error: $! $filename,";
while (defined(my $line = $fh->getline)) {
@@ -1456,7 +1487,7 @@ Displays this message and program version and exits.
=item --j #
Run number of parallel tests, or 0 to determine the count based on the
number of cores installed. Requires Parallel::Forker project.
number of cores installed. Requires Perl's Parallel::Forker package.
=item --optimize
+20
View File
@@ -0,0 +1,20 @@
#!/usr/bin/perl
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# Copyright 2003 by Wilson Snyder. This program is free software; you can
# redistribute it and/or modify it under the terms of either the GNU
# Lesser General Public License Version 3 or the Perl Artistic License
# Version 2.0.
$Self->{vlt} and $Self->skip("Verilator unsupported, bug355");
compile (
);
execute (
check_finished=>1,
);
ok(1);
1;
+119
View File
@@ -0,0 +1,119 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed into the Public Domain, for any use,
// without warranty, 2009 by Iztok Jeras.
module t (/*AUTOARG*/
// Inputs
clk
);
input clk;
// parameters for array sizes
localparam WA = 4; // address dimension size
localparam WB = 4; // bit dimension size
localparam NO = 10; // number of access events
// 2D packed arrays
logic [WA-1:0] [WB-1:0] array_bg; // big endian array
/* verilator lint_off LITENDIAN */
logic [0:WA-1] [0:WB-1] array_lt; // little endian array
/* verilator lint_on LITENDIAN */
integer cnt = 0;
// event counter
always @ (posedge clk) begin
cnt <= cnt + 1;
end
// finish report
always @ (posedge clk)
if ((cnt[30:2]==(NO-1)) && (cnt[1:0]==2'd3)) begin
$write("*-* All Finished *-*\n");
$finish;
end
// big endian
always @ (posedge clk)
if (cnt[1:0]==2'd0) begin
// initialize to defaults (all bits 1'bx)
if (cnt[30:2]==0) array_bg <= {WA{ {WB{1'bx}} }};
else if (cnt[30:2]==1) array_bg <= {WA{ {WB{1'bx}} }};
else if (cnt[30:2]==2) array_bg <= {WA{ {WB{1'bx}} }};
else if (cnt[30:2]==3) array_bg <= {WA{ {WB{1'bx}} }};
else if (cnt[30:2]==4) array_bg <= {WA{ {WB{1'bx}} }};
else if (cnt[30:2]==5) array_bg <= {WA{ {WB{1'bx}} }};
else if (cnt[30:2]==6) array_bg <= {WA{ {WB{1'bx}} }};
else if (cnt[30:2]==7) array_bg <= {WA{ {WB{1'bx}} }};
else if (cnt[30:2]==8) array_bg <= {WA{ {WB{1'bx}} }};
else if (cnt[30:2]==9) array_bg <= {WA{ {WB{1'bx}} }};
end else if (cnt[1:0]==2'd1) begin
// write data into whole or part of the array using literals
if (cnt[30:2]==0) begin end
else if (cnt[30:2]==1) array_bg = '{ 3 ,2 ,1, 0 };
else if (cnt[30:2]==2) array_bg = '{0:4, 1:5, 2:6, 3:7};
else if (cnt[30:2]==3) array_bg = '{default:13};
else if (cnt[30:2]==4) array_bg = '{2:15, default:13};
else if (cnt[30:2]==5) array_bg = '{WA { {WB/2 {2'b10}} }};
else if (cnt[30:2]==6) array_bg = '{WA { {3'b101, {WB/2-1{2'b10}}} }};
else if (cnt[30:2]==7) array_bg = '{WA { {WB/2-1{2'b10}} }};
else if (cnt[30:2]==8) array_bg [WA/2-1:0 ] = '{WA/2{ {WB/2 {2'b10}} }};
else if (cnt[30:2]==9) array_bg [WA -1:WA/2] = '{WA/2{ {WB/2 {2'b01}} }};
end else if (cnt[1:0]==2'd2) begin
// chack array agains expected value
if (cnt[30:2]==0) begin if (array_bg !== 16'bxxxxxxxxxxxxxxxx) begin $display("%b", array_bg); $stop(); end end
else if (cnt[30:2]==1) begin if (array_bg !== 16'b0011001000010000) begin $display("%b", array_bg); $stop(); end end
else if (cnt[30:2]==2) begin if (array_bg !== 16'b0111011001010100) begin $display("%b", array_bg); $stop(); end end
else if (cnt[30:2]==3) begin if (array_bg !== 16'b1101110111011101) begin $display("%b", array_bg); $stop(); end end
else if (cnt[30:2]==4) begin if (array_bg !== 16'b1101111111011101) begin $display("%b", array_bg); $stop(); end end
else if (cnt[30:2]==5) begin if (array_bg !== 16'b1010101010101010) begin $display("%b", array_bg); $stop(); end end
else if (cnt[30:2]==6) begin if (array_bg !== 16'b0110011001100110) begin $display("%b", array_bg); $stop(); end end
else if (cnt[30:2]==7) begin if (array_bg !== 16'b0010001000100010) begin $display("%b", array_bg); $stop(); end end
else if (cnt[30:2]==8) begin if (array_bg !== 16'b10101010xxxxxxxx) begin $display("%b", array_bg); $stop(); end end
else if (cnt[30:2]==9) begin if (array_bg !== 16'bxxxxxxxx10101010) begin $display("%b", array_bg); $stop(); end end
end
// little endian
always @ (posedge clk)
if (cnt[1:0]==2'd0) begin
// initialize to defaults (all bits 1'bx)
if (cnt[30:2]==0) array_lt <= {WA{ {WB{1'bx}} }};
else if (cnt[30:2]==1) array_lt <= {WA{ {WB{1'bx}} }};
else if (cnt[30:2]==2) array_lt <= {WA{ {WB{1'bx}} }};
else if (cnt[30:2]==3) array_lt <= {WA{ {WB{1'bx}} }};
else if (cnt[30:2]==4) array_lt <= {WA{ {WB{1'bx}} }};
else if (cnt[30:2]==5) array_lt <= {WA{ {WB{1'bx}} }};
else if (cnt[30:2]==6) array_lt <= {WA{ {WB{1'bx}} }};
else if (cnt[30:2]==7) array_lt <= {WA{ {WB{1'bx}} }};
else if (cnt[30:2]==8) array_lt <= {WA{ {WB{1'bx}} }};
else if (cnt[30:2]==9) array_lt <= {WA{ {WB{1'bx}} }};
end else if (cnt[1:0]==2'd1) begin
// write data into whole or part of the array using literals
if (cnt[30:2]==0) begin end
else if (cnt[30:2]==1) array_lt = '{ 3 ,2 ,1, 0 };
else if (cnt[30:2]==2) array_lt = '{3:4, 2:5, 1:6, 0:7};
else if (cnt[30:2]==3) array_lt = '{default:13};
else if (cnt[30:2]==4) array_lt = '{1:15, default:13};
else if (cnt[30:2]==5) array_lt = '{WA { {WB/2 {2'b10}} }};
else if (cnt[30:2]==6) array_lt = '{WA { {3'b101, {WB/2-1{2'b10}}} }};
else if (cnt[30:2]==7) array_lt = '{WA { {WB/2-1{2'b10}} }};
else if (cnt[30:2]==8) array_lt [0 :WA/2-1] = '{WA/2{ {WB/2 {2'b10}} }};
else if (cnt[30:2]==9) array_lt [WA/2:WA -1] = '{WA/2{ {WB/2 {2'b01}} }};
end else if (cnt[1:0]==2'd2) begin
// chack array agains expected value
if (cnt[30:2]==0) begin if (array_lt !== 16'bxxxxxxxxxxxxxxxx) begin $display("%b", array_lt); $stop(); end end
else if (cnt[30:2]==1) begin if (array_lt !== 16'b0011001000010000) begin $display("%b", array_lt); $stop(); end end
else if (cnt[30:2]==2) begin if (array_lt !== 16'b0111011001010100) begin $display("%b", array_lt); $stop(); end end
else if (cnt[30:2]==3) begin if (array_lt !== 16'b1101110111011101) begin $display("%b", array_lt); $stop(); end end
else if (cnt[30:2]==4) begin if (array_lt !== 16'b1101111111011101) begin $display("%b", array_lt); $stop(); end end
else if (cnt[30:2]==5) begin if (array_lt !== 16'b1010101010101010) begin $display("%b", array_lt); $stop(); end end
else if (cnt[30:2]==6) begin if (array_lt !== 16'b0110011001100110) begin $display("%b", array_lt); $stop(); end end
else if (cnt[30:2]==7) begin if (array_lt !== 16'b0010001000100010) begin $display("%b", array_lt); $stop(); end end
else if (cnt[30:2]==8) begin if (array_lt !== 16'b10101010xxxxxxxx) begin $display("%b", array_lt); $stop(); end end
else if (cnt[30:2]==9) begin if (array_lt !== 16'bxxxxxxxx10101010) begin $display("%b", array_lt); $stop(); end end
end
endmodule
+20
View File
@@ -0,0 +1,20 @@
#!/usr/bin/perl
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# Copyright 2003 by Wilson Snyder. This program is free software; you can
# redistribute it and/or modify it under the terms of either the GNU
# Lesser General Public License Version 3 or the Perl Artistic License
# Version 2.0.
$Self->{vlt} and $Self->skip("Verilator unsupported, bug448");
compile (
);
execute (
check_finished=>1,
);
ok(1);
1;
+143
View File
@@ -0,0 +1,143 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed into the Public Domain, for any use,
// without warranty, 2012 by Iztok Jeras.
module t (/*AUTOARG*/
// Inputs
clk
);
input clk;
// parameters for array sizes
localparam WA = 4;
localparam WB = 6;
localparam WC = 8;
// 2D packed arrays
logic [WA-1:0] [WB-1:0] [WC-1:0] array_bg; // big endian array
/* verilator lint_off LITENDIAN */
logic [0:WA-1] [0:WB-1] [0:WC-1] array_lt; // little endian array
/* verilator lint_on LITENDIAN */
integer cnt = 0;
integer slc = 0; // slice type
integer dim = 0; // dimension
integer wdt = 0; // width
// event counter
always @ (posedge clk) begin
cnt <= cnt + 1;
end
// finish report
always @ (posedge clk)
if ( (cnt[30:4]==3) && (cnt[3:2]==2'd3) && (cnt[1:0]==2'd3) ) begin
$write("*-* All Finished *-*\n");
$finish;
end
// calculation of dimention sizes
always @ (posedge clk)
begin
// slicing tipe counter
case (cnt[3:2])
2'd0 : begin slc = 0; end // full array
2'd1 : begin slc = 1; end // half array
2'd2 : begin slc = 2; end // single array element
default: begin slc = 0; end
endcase
// dimmension counter
case (cnt[1:0])
2'd0 : begin dim = 1; wdt = (slc==1) ? WA/2
: (slc==2) ? 1
: WA; end
2'd1 : begin dim = 2; wdt = WB; end
2'd2 : begin dim = 3; wdt = WC; end
default: begin dim = 0; wdt = 0; end
endcase
end
always @ (posedge clk)
if (cnt[30:4]==1) begin
// big endian
if (cnt[3:2]==0) begin
// full array
if ($dimensions (array_bg) != 3) $stop;
if ($bits (array_bg) != WA*WB*WC) $stop;
if ((dim>=1)&&(dim<=3)) begin
if ($left (array_bg, dim) != wdt-1) $stop;
if ($right (array_bg, dim) != 0 ) $stop;
if ($low (array_bg, dim) != 0 ) $stop;
if ($high (array_bg, dim) != wdt-1) $stop;
if ($increment (array_bg, dim) != 1 ) $stop;
if ($size (array_bg, dim) != wdt ) $stop;
end
end else if (cnt[3:2]==1) begin
// half array
if ($dimensions (array_bg[WA/2-1:0]) != 3) $stop;
if ($bits (array_bg[WA/2-1:0]) != WA/2*WB*WC) $stop;
if ((dim>=1)&&(dim<=3)) begin
if ($left (array_bg[WA/2-1:0], dim) != wdt-1) $stop;
if ($right (array_bg[WA/2-1:0], dim) != 0 ) $stop;
if ($low (array_bg[WA/2-1:0], dim) != 0 ) $stop;
if ($high (array_bg[WA/2-1:0], dim) != wdt-1) $stop;
if ($increment (array_bg[WA/2-1:0], dim) != 1 ) $stop;
if ($size (array_bg[WA/2-1:0], dim) != wdt ) $stop;
end
end else if (cnt[3:2]==2) begin
// single array element
if ($dimensions (array_bg[0]) != 2) $stop;
if ($bits (array_bg[0]) != WB*WC) $stop;
if ((dim>=2)&&(dim<=3)) begin
if ($left (array_bg[0], dim-1) != wdt-1) $stop;
if ($right (array_bg[0], dim-1) != 0 ) $stop;
if ($low (array_bg[0], dim-1) != 0 ) $stop;
if ($high (array_bg[0], dim-1) != wdt-1) $stop;
if ($increment (array_bg[0], dim-1) != 1 ) $stop;
if ($size (array_bg[0], dim-1) != wdt ) $stop;
end
end
end else if (cnt[30:4]==2) begin
// little endian
if (cnt[3:2]==0) begin
// full array
if ($dimensions (array_lt) != 3) $stop;
if ($bits (array_lt) != WA*WB*WC) $stop;
if ((dim>=1)&&(dim<=3)) begin
if ($left (array_lt, dim) != 0 ) $stop;
if ($right (array_lt, dim) != wdt-1) $stop;
if ($low (array_lt, dim) != 0 ) $stop;
if ($high (array_lt, dim) != wdt-1) $stop;
if ($increment (array_lt, dim) != -1 ) $stop;
if ($size (array_lt, dim) != wdt ) $stop;
end
end else if (cnt[3:2]==1) begin
// half array
if ($dimensions (array_lt[0:WA/2-1]) != 3) $stop;
if ($bits (array_lt[0:WA/2-1]) != WA/2*WB*WC) $stop;
if ((dim>=1)&&(dim<=3)) begin
if ($left (array_lt[0:WA/2-1], dim) != 0 ) $stop;
if ($right (array_lt[0:WA/2-1], dim) != wdt-1) $stop;
if ($low (array_lt[0:WA/2-1], dim) != 0 ) $stop;
if ($high (array_lt[0:WA/2-1], dim) != wdt-1) $stop;
if ($increment (array_lt[0:WA/2-1], dim) != -1 ) $stop;
if ($size (array_lt[0:WA/2-1], dim) != wdt ) $stop;
end
end else if (cnt[3:2]==2) begin
// single array element
if ($dimensions (array_lt[0]) != 2) $stop;
if ($bits (array_lt[0]) != WB*WC) $stop;
if ((dim>=2)&&(dim<=3)) begin
if ($left (array_lt[0], dim-1) != 0 ) $stop;
if ($right (array_lt[0], dim-1) != wdt-1) $stop;
if ($low (array_lt[0], dim-1) != 0 ) $stop;
if ($high (array_lt[0], dim-1) != wdt-1) $stop;
if ($increment (array_lt[0], dim-1) != -1 ) $stop;
if ($size (array_lt[0], dim-1) != wdt ) $stop;
end
end
end
endmodule
+20
View File
@@ -0,0 +1,20 @@
#!/usr/bin/perl
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# Copyright 2003 by Wilson Snyder. This program is free software; you can
# redistribute it and/or modify it under the terms of either the GNU
# Lesser General Public License Version 3 or the Perl Artistic License
# Version 2.0.
$Self->{vlt} and $Self->skip("Verilator unsupported, bug446");
compile (
);
execute (
check_finished=>1,
);
ok(1);
1;
+143
View File
@@ -0,0 +1,143 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed into the Public Domain, for any use,
// without warranty, 2012 by Iztok Jeras.
module t (/*AUTOARG*/
// Inputs
clk
);
input clk;
// parameters for array sizes
localparam WA = 8; // address dimension size
localparam WB = 8; // bit dimension size
localparam NO = 10; // number of access events
// 2D packed arrays
logic [WA-1:0] [WB-1:0] array_bg; // big endian array
/* verilator lint_off LITENDIAN */
logic [0:WA-1] [0:WB-1] array_lt; // little endian array
/* verilator lint_on LITENDIAN */
integer cnt = 0;
// event counter
always @ (posedge clk) begin
cnt <= cnt + 1;
end
// finish report
always @ (posedge clk)
if ((cnt[30:2]==NO) && (cnt[1:0]==2'd0)) begin
$write("*-* All Finished *-*\n");
$finish;
end
// big endian
always @ (posedge clk)
if (cnt[1:0]==2'd0) begin
// initialize to defaaults (all bits to x)
if (cnt[30:2]==0) array_bg <= {WA *WB{1'bx} };
else if (cnt[30:2]==1) array_bg <= {WA{ {WB{1'bx}} }};
else if (cnt[30:2]==2) array_bg <= {WA{ {WB{1'bx}} }};
else if (cnt[30:2]==3) array_bg <= {WA{ {WB{1'bx}} }};
else if (cnt[30:2]==4) array_bg <= {WA{ {WB{1'bx}} }};
else if (cnt[30:2]==5) array_bg <= {WA{ {WB{1'bx}} }};
else if (cnt[30:2]==6) array_bg <= {WA{ {WB{1'bx}} }};
else if (cnt[30:2]==7) array_bg <= {WA{ {WB{1'bx}} }};
else if (cnt[30:2]==8) array_bg <= {WA{ {WB{1'bx}} }};
else if (cnt[30:2]==9) array_bg <= {WA{ {WB{1'bx}} }};
end else if (cnt[1:0]==2'd1) begin
// write value to array
if (cnt[30:2]==0) begin end
else if (cnt[30:2]==1) array_bg = {WA *WB +0{1'b1}};
else if (cnt[30:2]==2) array_bg [WA/2-1:0 ] = {WA/2*WB +0{1'b1}};
else if (cnt[30:2]==3) array_bg [WA -1:WA/2] = {WA/2*WB +0{1'b1}};
else if (cnt[30:2]==4) array_bg [ 0 ] = {1 *WB +0{1'b1}};
else if (cnt[30:2]==5) array_bg [WA -1 ] = {1 *WB +0{1'b1}};
else if (cnt[30:2]==6) array_bg [ 0 ][WB/2-1:0 ] = {1 *WB/2+0{1'b1}};
else if (cnt[30:2]==7) array_bg [WA -1 ][WB -1:WB/2] = {1 *WB/2+0{1'b1}};
else if (cnt[30:2]==8) array_bg [ 0 ][ 0 ] = {1 *1 +0{1'b1}};
else if (cnt[30:2]==9) array_bg [WA -1 ][WB -1 ] = {1 *1 +0{1'b1}};
end else if (cnt[1:0]==2'd2) begin
// check array value
if (cnt[30:2]==0) begin if (array_bg !== 64'bxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx) $stop(); end
else if (cnt[30:2]==1) begin if (array_bg !== 64'b1111111111111111111111111111111111111111111111111111111111111111) $stop(); end
else if (cnt[30:2]==2) begin if (array_bg !== 64'bxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx11111111111111111111111111111111) $stop(); end
else if (cnt[30:2]==3) begin if (array_bg !== 64'b11111111111111111111111111111111xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx) $stop(); end
else if (cnt[30:2]==4) begin if (array_bg !== 64'bxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx11111111) $stop(); end
else if (cnt[30:2]==5) begin if (array_bg !== 64'b11111111xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx) $stop(); end
else if (cnt[30:2]==6) begin if (array_bg !== 64'bxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx1111) $stop(); end
else if (cnt[30:2]==7) begin if (array_bg !== 64'b1111xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx) $stop(); end
else if (cnt[30:2]==8) begin if (array_bg !== 64'bxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx1) $stop(); end
else if (cnt[30:2]==9) begin if (array_bg !== 64'b1xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx) $stop(); end
end else if (cnt[1:0]==2'd3) begin
// read value from array (not a very good test for now)
if (cnt[30:2]==0) begin if (array_bg !== {WA *WB {1'bx}}) $stop(); end
else if (cnt[30:2]==1) begin if (array_bg !== {WA *WB +0{1'b1}}) $stop(); end
else if (cnt[30:2]==2) begin if (array_bg [WA/2-1:0 ] !== {WA/2*WB +0{1'b1}}) $stop(); end
else if (cnt[30:2]==3) begin if (array_bg [WA -1:WA/2] !== {WA/2*WB +0{1'b1}}) $stop(); end
else if (cnt[30:2]==4) begin if (array_bg [ 0 ] !== {1 *WB +0{1'b1}}) $stop(); end
else if (cnt[30:2]==5) begin if (array_bg [WA -1 ] !== {1 *WB +0{1'b1}}) $stop(); end
else if (cnt[30:2]==6) begin if (array_bg [ 0 ][WB/2-1:0 ] !== {1 *WB/2+0{1'b1}}) $stop(); end
else if (cnt[30:2]==7) begin if (array_bg [WA -1 ][WB -1:WB/2] !== {1 *WB/2+0{1'b1}}) $stop(); end
else if (cnt[30:2]==8) begin if (array_bg [ 0 ][ 0 ] !== {1 *1 +0{1'b1}}) $stop(); end
else if (cnt[30:2]==9) begin if (array_bg [WA -1 ][WB -1 ] !== {1 *1 +0{1'b1}}) $stop(); end
end
// little endian
always @ (posedge clk)
if (cnt[1:0]==2'd0) begin
// initialize to defaaults (all bits to x)
if (cnt[30:2]==0) array_lt <= {WA *WB{1'bx} };
else if (cnt[30:2]==1) array_lt <= {WA{ {WB{1'bx}} }};
else if (cnt[30:2]==2) array_lt <= {WA{ {WB{1'bx}} }};
else if (cnt[30:2]==3) array_lt <= {WA{ {WB{1'bx}} }};
else if (cnt[30:2]==4) array_lt <= {WA{ {WB{1'bx}} }};
else if (cnt[30:2]==5) array_lt <= {WA{ {WB{1'bx}} }};
else if (cnt[30:2]==6) array_lt <= {WA{ {WB{1'bx}} }};
else if (cnt[30:2]==7) array_lt <= {WA{ {WB{1'bx}} }};
else if (cnt[30:2]==8) array_lt <= {WA{ {WB{1'bx}} }};
else if (cnt[30:2]==9) array_lt <= {WA{ {WB{1'bx}} }};
end else if (cnt[1:0]==2'd1) begin
// write value to array
if (cnt[30:2]==0) begin end
else if (cnt[30:2]==1) array_lt = {WA *WB +0{1'b1}};
else if (cnt[30:2]==2) array_lt [0 :WA/2-1] = {WA/2*WB +0{1'b1}};
else if (cnt[30:2]==3) array_lt [WA/2:WA -1] = {WA/2*WB +0{1'b1}};
else if (cnt[30:2]==4) array_lt [0 ] = {1 *WB +0{1'b1}};
else if (cnt[30:2]==5) array_lt [ WA -1] = {1 *WB +0{1'b1}};
else if (cnt[30:2]==6) array_lt [0 ][0 :WB/2-1] = {1 *WB/2+0{1'b1}};
else if (cnt[30:2]==7) array_lt [ WA -1][WB/2:WB -1] = {1 *WB/2+0{1'b1}};
else if (cnt[30:2]==8) array_lt [0 ][0 ] = {1 *1 +0{1'b1}};
else if (cnt[30:2]==9) array_lt [ WA -1][ WB -1] = {1 *1 +0{1'b1}};
end else if (cnt[1:0]==2'd2) begin
// check array value
if (cnt[30:2]==0) begin if (array_lt !== 64'bxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx) $stop(); end
else if (cnt[30:2]==1) begin if (array_lt !== 64'b1111111111111111111111111111111111111111111111111111111111111111) $stop(); end
else if (cnt[30:2]==2) begin if (array_lt !== 64'b11111111111111111111111111111111xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx) $stop(); end
else if (cnt[30:2]==3) begin if (array_lt !== 64'bxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx11111111111111111111111111111111) $stop(); end
else if (cnt[30:2]==4) begin if (array_lt !== 64'b11111111xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx) $stop(); end
else if (cnt[30:2]==5) begin if (array_lt !== 64'bxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx11111111) $stop(); end
else if (cnt[30:2]==6) begin if (array_lt !== 64'b1111xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx) $stop(); end
else if (cnt[30:2]==7) begin if (array_lt !== 64'bxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx1111) $stop(); end
else if (cnt[30:2]==8) begin if (array_lt !== 64'b1xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx) $stop(); end
else if (cnt[30:2]==9) begin if (array_lt !== 64'bxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx1) $stop(); end
end else if (cnt[1:0]==2'd3) begin
// read value from array (not a very good test for now)
if (cnt[30:2]==0) begin if (array_lt !== {WA *WB {1'bx}}) $stop(); end
else if (cnt[30:2]==1) begin if (array_lt !== {WA *WB +0{1'b1}}) $stop(); end
else if (cnt[30:2]==2) begin if (array_lt [0 :WA/2-1] !== {WA/2*WB +0{1'b1}}) $stop(); end
else if (cnt[30:2]==3) begin if (array_lt [WA/2:WA -1] !== {WA/2*WB +0{1'b1}}) $stop(); end
else if (cnt[30:2]==4) begin if (array_lt [0 ] !== {1 *WB +0{1'b1}}) $stop(); end
else if (cnt[30:2]==5) begin if (array_lt [ WA -1] !== {1 *WB +0{1'b1}}) $stop(); end
else if (cnt[30:2]==6) begin if (array_lt [0 ][0 :WB/2-1] !== {1 *WB/2+0{1'b1}}) $stop(); end
else if (cnt[30:2]==7) begin if (array_lt [ WA -1][WB/2:WB -1] !== {1 *WB/2+0{1'b1}}) $stop(); end
else if (cnt[30:2]==8) begin if (array_lt [0 ][0 ] !== {1 *1 +0{1'b1}}) $stop(); end
else if (cnt[30:2]==9) begin if (array_lt [ WA -1][ WB -1] !== {1 *1 +0{1'b1}}) $stop(); end
end
endmodule
+1 -1
View File
@@ -56,7 +56,7 @@ module sub (/*AUTOARG*/
);
input [23:0] in;
output reg [0:0] out1;
output reg [0:0] out1; // Note this tests a vector of 1 bit, which is different from a non-arrayed signal
parameter [1023:0] RANDOM = 1024'b101011010100011011100111101001000000101000001111111111100110000110011011010110011101000100110000110101111101000111100100010111001001110001010101000111000100010000010011100001100011110110110000101100011111000110111110010110011000011111111010101110001101010010001111110111100000110111101100110101110001110110000010000110101110111001111001100001101110001011100111001001110101001010000110101010100101111000010000010110100101110100110000110110101000100011101111100011000110011001100010010011001101100100101110010100110101001110011111110010000111001111000010001101100101101110111110001000010110010011100101001011111110011010110111110000110010011110001110110011010011010110011011111001110100010110100011100001011000101111000010011111010111001110110011101110101011111001100011000101000001000100111110010100111011101010101011001101000100000101111110010011010011010001111010001110000110010100011110110011001010000011001010010110111101010010011111111010001000101100010100100010011001100110000111111000001000000001001111101110000100101;
+18
View File
@@ -0,0 +1,18 @@
#!/usr/bin/perl
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# Copyright 2003 by Wilson Snyder. This program is free software; you can
# redistribute it and/or modify it under the terms of either the GNU
# Lesser General Public License Version 3 or the Perl Artistic License
# Version 2.0.
compile (
);
execute (
check_finished=>1,
);
ok(1);
1;
+33
View File
@@ -0,0 +1,33 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// Copyright 2012 by Wilson Snyder. This program is free software; you can
// redistribute it and/or modify it under the terms of either the GNU
// Lesser General Public License Version 3 or the Perl Artistic License
// Version 2.0.
module t (/*AUTOARG*/
// Inputs
clk
);
input clk;
genvar g;
logic [1:0] mask = 0;
generate
for (g=0; g<2; g++)
begin : picker
logic block_passed = 0; // Just for visualizing V3LinkDot debug
function [3:0] pick;
input [3:0] randnum;
pick = randnum+g[3:0];
endfunction
always @(posedge clk) begin
if (pick(3)!=3+g[3:0]) $stop;
else mask[g] = 1'b1;
if (mask == 2'b11) begin // All iterations must be finished
$write("*-* All Finished *-*\n");
$finish;
end
end
end
endgenerate
endmodule
+1 -1
View File
@@ -11,7 +11,7 @@ compile (
v_flags2 => ["--lint-only"],
fails=>1,
expect=>
q{%Error: t/t_func_wide_out_bad.v:\d+: Unsupported: Function output argument 'data' requires 4350 bits, but connection's VARREF 'msg' generates 4352 bits.
q{%Error: t/t_func_wide_out_bad.v:\d+: Unsupported: Function output argument 'data' requires 4352 bits, but connection's VARREF 'msg' generates 4350 bits.
%Error: Exiting due to.*},
);
+18
View File
@@ -0,0 +1,18 @@
#!/usr/bin/perl
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# Copyright 2003 by Wilson Snyder. This program is free software; you can
# redistribute it and/or modify it under the terms of either the GNU
# Lesser General Public License Version 3 or the Perl Artistic License
# Version 2.0.
compile (
);
execute (
check_finished=>1,
);
ok(1);
1;
+53
View File
@@ -0,0 +1,53 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed into the Public Domain, for any use,
// without warranty, 2012 by Iztok Jeras.
module t (/*AUTOARG*/
// Inputs
clk
);
input clk;
parameter SIZE = 8;
integer cnt = 0;
logic [SIZE-1:0] vld_for;
logic vld_if = 1'b0;
logic vld_else = 1'b0;
genvar i;
// event counter
always @ (posedge clk) begin
cnt <= cnt + 1;
end
// finish report
always @ (posedge clk)
if (cnt==SIZE) begin : if_cnt_finish
$write("*-* All Finished *-*\n");
$finish;
end : if_cnt_finish
generate
for (i=0; i<SIZE; i=i+1) begin : generate_for
always @ (posedge clk)
if (cnt == i) vld_for[i] <= 1'b1;
end : generate_for
endgenerate
generate
if (SIZE>0) begin : generate_if_if
always @ (posedge clk)
vld_if <= 1'b1;
end : generate_if_if
else begin : generate_if_else
always @ (posedge clk)
vld_else <= 1'b1;
end : generate_if_else
endgenerate
endmodule : t
+24
View File
@@ -0,0 +1,24 @@
#!/usr/bin/perl
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# Copyright 2003 by Wilson Snyder. This program is free software; you can
# redistribute it and/or modify it under the terms of either the GNU
# Lesser General Public License Version 3 or the Perl Artistic License
# Version 2.0.
compile (
v_flags2 => ["--lint-only"],
fails=>1,
expect=>
q{%Warning-ENDLABEL: t/t_hierarchy_identifier_bad.v:\d+: End label 'if_cnt_finish_bad' does not match begin label 'if_cnt_finish'
%Warning-ENDLABEL: Use .*
%Warning-ENDLABEL: t/t_hierarchy_identifier_bad.v:\d+: End label 'generate_for_bad' does not match begin label 'generate_for'
%Warning-ENDLABEL: t/t_hierarchy_identifier_bad.v:\d+: End label 'generate_if_if_bad' does not match begin label 'generate_if_if'
%Warning-ENDLABEL: t/t_hierarchy_identifier_bad.v:\d+: End label 'generate_if_else_bad' does not match begin label 'generate_if_else'
%Warning-ENDLABEL: t/t_hierarchy_identifier_bad.v:\d+: End label 't_bad' does not match begin label 't'
%Error: Exiting due to.*},
);
ok(1);
1;
@@ -0,0 +1,53 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed into the Public Domain, for any use,
// without warranty, 2012 by Iztok Jeras.
module t (/*AUTOARG*/
// Inputs
clk
);
input clk;
parameter SIZE = 8;
integer cnt = 0;
logic [SIZE-1:0] vld_for;
logic vld_if = 1'b0;
logic vld_else = 1'b0;
genvar i;
// event counter
always @ (posedge clk) begin
cnt <= cnt + 1;
end
// finish report
always @ (posedge clk)
if (cnt==SIZE) begin : if_cnt_finish
$write("*-* All Finished *-*\n");
$finish;
end : if_cnt_finish_bad
generate
for (i=0; i<SIZE; i=i+1) begin : generate_for
always @ (posedge clk)
if (cnt == i) vld_for[i] <= 1'b1;
end : generate_for_bad
endgenerate
generate
if (SIZE>0) begin : generate_if_if
always @ (posedge clk)
vld_if <= 1'b1;
end : generate_if_if_bad
else begin : generate_if_else
always @ (posedge clk)
vld_else <= 1'b1;
end : generate_if_else_bad
endgenerate
endmodule : t_bad
+30
View File
@@ -0,0 +1,30 @@
#!/usr/bin/perl
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# Copyright 2008 by Wilson Snyder. This program is free software; you can
# redistribute it and/or modify it under the terms of either the GNU
# Lesser General Public License Version 3 or the Perl Artistic License
# Version 2.0.
$Self->{vlt} or $Self->skip("Verilator only test");
compile (
v_flags2 => ["--lint-only"],
fails=>1,
verilator_make_gcc => 0,
make_top_shell => 0,
make_main => 0,
expect=>
'%Warning-MULTIDRIVEN: t/t_lint_multidriven_bad.v:\d+: Signal has multiple driving blocks: v.mem
%Warning-MULTIDRIVEN: Use ".*" and lint_on around source to disable this message.
%Warning-MULTIDRIVEN: t/t_lint_multidriven_bad.v:\d+: ... Location of first driving block
%Warning-MULTIDRIVEN: t/t_lint_multidriven_bad.v:\d+: ... Location of other driving block
%Warning-MULTIDRIVEN: t/t_lint_multidriven_bad.v:\d+: Signal has multiple driving blocks: out2
%Warning-MULTIDRIVEN: t/t_lint_multidriven_bad.v:\d+: ... Location of first driving block
%Warning-MULTIDRIVEN: t/t_lint_multidriven_bad.v:\d+: ... Location of other driving block
%Error: Exiting due to.*',
);
ok(1);
1;
+37
View File
@@ -0,0 +1,37 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed into the Public Domain, for any use,
// without warranty, 2012 by Wilson Snyder.
module t (/*AUTOARG*/
// Outputs
out, out2,
// Inputs
clk, a0, d0, d1
);
input clk;
input [1:0] a0;
input [7:0] d0;
input [7:0] d1;
output reg [31:0] out;
output reg [15:0] out2;
reg [7:0] mem [4];
always @(posedge clk) begin
mem[a0] <= d0;
end
always @(negedge clk) begin
mem[a0] <= d1;
end
assign out = {mem[3],mem[2],mem[1],mem[0]};
always @(posedge clk) begin
out2[7:0] <= d0;
end
always @(negedge clk) begin
out2[15:8] <= d0;
end
endmodule
+1 -1
View File
@@ -10,7 +10,7 @@ if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); di
$Self->{vlt} or $Self->skip("Verilator only test");
compile (
v_flags2 => ["--lint-only --bbox-sys -Wall -Wno-DECLFILENAME"],
v_flags2 => ["--lint-only --bbox-sys --bbox-unsup -Wall -Wno-DECLFILENAME"],
fails=>1,
verilator_make_gcc => 0,
make_top_shell => 0,
+89
View File
@@ -0,0 +1,89 @@
// This file ONLY is placed into the Public Domain, for any use,
// without warranty, 2008 by Lane Brooks
#if defined(T_MEM_MULTI_IO2_CC)
# include "Vt_mem_multi_io2_cc.h"
#elif defined(T_MEM_MULTI_IO2_SC)
# include "Vt_mem_multi_io2_sc.h"
#else
# error "Unknown test"
#endif
VM_PREFIX* tb = NULL;
bool pass = true;
double sc_time_stamp() {
return 0;
}
void check(const char* bus, int got, int exp) {
if (got != exp) {
VL_PRINTF("%%Error: Data mismatch on '%s', got=%x, exp=%x\n", bus, got, exp);
pass = false;
}
}
int main() {
Verilated::debug(0);
tb = new VM_PREFIX ("tb");
#ifdef SYSTEMC_VERSION
sc_signal<vluint32_t> i3;
sc_signal<vluint32_t> o3;
sc_signal<vluint32_t> i34[4];
sc_signal<vluint32_t> o34[4];
sc_signal<vluint32_t> i345[4][5];
sc_signal<vluint32_t> o345[4][5];
tb->i3(i3);
tb->o3(o3);
for (int i=0; i<4; i++) {
tb->i34[i](i34[i]);
tb->o34[i](o34[i]);
for (int j=0; j<5; j++) {
tb->i345[i][j](i345[i][j]);
tb->o345[i][j](o345[i][j]);
}
}
#endif
// loop through every possibility and check the result
#ifdef SYSTEMC_VERSION
sc_start(1,SC_NS);
# define ASSIGN(s,v) s.write(v)
# define READ(s) s.read()
#else
tb->eval();
# define ASSIGN(s,v) tb->s = (v)
# define READ(s) tb->s
#endif
ASSIGN(i3, 13);
for (int i=0; i<4; i++) {
ASSIGN(i34[i], i);
for (int j=0; j<5; j++) {
ASSIGN(i345[i][j], i*8 + j);
}
}
#ifdef SYSTEMC_VERSION
sc_start(1,SC_NS);
#else
tb->eval();
#endif
check("o3", READ(o3), 13);
for (int i=0; i<4; i++) {
check("o34", READ(o34[i]), i);
for (int j=0; j<5; j++) {
check("o345", READ(o345[i][j]), i*8 + j);
}
}
if (pass) {
VL_PRINTF("*-* All Finished *-*\n");
} else {
vl_fatal(__FILE__,__LINE__,"top", "Unexpected results from test\n");
}
return 0;
}
+37
View File
@@ -0,0 +1,37 @@
// This file ONLY is placed into the Public Domain, for any use,
// without warranty, 2008 by Lane Brooks
module t (/*AUTOARG*/
// Outputs
o3, o34, o345,
// Inputs
i3, i34, i345
);
input [15:0] i3;
output wire [15:0] o3;
input [15:0] i34 [3:0];
output wire [15:0] o34 [3:0];
input [15:0] i345 [3:0][4:0];
output wire [15:0] o345 [3:0][4:0];
sub sub (.*);
endmodule
module sub (/*AUTOARG*/
// Outputs
o3, o34, o345,
// Inputs
i3, i34, i345
);
input [15:0] i3;
output wire [15:0] o3;
input [15:0] i34 [3:0];
output wire [15:0] o34 [3:0];
input [15:0] i345 [3:0][4:0];
output wire [15:0] o345 [3:0][4:0];
assign o3 = i3;
assign o34 = i34;
assign o345 = i345;
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-2009 by Wilson Snyder. This program is free software; you can
# redistribute it and/or modify it under the terms of either the GNU
# Lesser General Public License Version 3 or the Perl Artistic License
# Version 2.0.
top_filename("t/t_mem_multi_io2.v");
$Self->{vlt} or $Self->skip("Verilator only test");
compile (
make_top_shell => 0,
make_main => 0,
verilator_flags2 => ["--exe $Self->{t_dir}/t_mem_multi_io2.cpp"],
);
execute (
check_finished=>1,
);
ok(1);
1;
+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-2009 by Wilson Snyder. This program is free software; you can
# redistribute it and/or modify it under the terms of either the GNU
# Lesser General Public License Version 3 or the Perl Artistic License
# Version 2.0.
top_filename("t/t_mem_multi_io2.v");
$Self->{vlt} or $Self->skip("Verilator only test");
compile (
make_top_shell => 0,
make_main => 0,
verilator_flags2 => ["--exe $Self->{t_dir}/t_mem_multi_io2.cpp --sc"],
);
execute (
check_finished=>1,
);
ok(1);
1;
-12
View File
@@ -1,12 +0,0 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed into the Public Domain, for any use,
// without warranty, 2005 by Wilson Snyder.
module t (/*AUTOARG*/
// Outputs
dim1
);
reg [1:0] dim1 [1:0];
output dim1; // Bad, can't output multi-dim
endmodule
+3
View File
@@ -26,6 +26,7 @@ module t (/*AUTOARG*/
integer i0,i1,i2;
integer imem[2:0][1:3];
reg [2:0] cstyle[2];
initial begin
for (i0=0; i0<3; i0=i0+1) begin
@@ -75,6 +76,8 @@ module t (/*AUTOARG*/
memn[index0][index1][index2] <= {~crc[6:0],crc[7]};
memw[index0][index1][index2] <= {~crc[7:0],crc};
//$write("Set memw[%d][%d][%d] <= %x\n",index0,index1,index2, {~crc[7:0],crc});
cstyle[cyc[0]] <= cyc[2:0];
if (cyc>20) if (cstyle[~cyc[0]] != (cyc[2:0]-3'b1)) $stop;
end
else if (cyc==90) begin
memn[0][1][3] <= memn[0][1][3] ^ 8'ha8;
+18
View File
@@ -0,0 +1,18 @@
#!/usr/bin/perl
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# Copyright 2003 by Wilson Snyder. This program is free software; you can
# redistribute it and/or modify it under the terms of either the GNU
# Lesser General Public License Version 3 or the Perl Artistic License
# Version 2.0.
compile (
);
execute (
check_finished=>1,
);
ok(1);
1;
+117
View File
@@ -0,0 +1,117 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed into the Public Domain, for any use,
// without warranty, 2012 by Wilson Snyder.
module t (/*AUTOARG*/
// Inputs
clk
);
input clk;
integer cyc=0;
reg [63:0] crc;
reg [63:0] sum;
// verilator lint_off MULTIDRIVEN
/*AUTOWIRE*/
// Beginning of automatic wires (for undeclared instantiated-module outputs)
wire [31:0] out; // From test of Test.v
wire [15:0] out2; // From test of Test.v
// End of automatics
// verilator lint_on MULTIDRIVEN
Test test (
.en (crc[21:20]),
.a1 (crc[19:18]),
.a0 (crc[17:16]),
.d1 (crc[15:8]),
.d0 (crc[7:0]),
/*AUTOINST*/
// Outputs
.out (out[31:0]),
.out2 (out2[15:0]),
// Inputs
.clk (clk));
// Aggregate outputs into a single result vector
wire [63:0] result = {out2, 16'h0, out};
// Test loop
`ifdef TEST_VERBOSE
always @ (negedge clk) begin
$write("[%0t] cyc==%0d crc=%x result=%x\n",$time, cyc, crc, result);
end
`endif
always @ (posedge clk) begin
`ifdef TEST_VERBOSE
$write("[%0t] cyc==%0d crc=%x result=%x\n",$time, cyc, crc, result);
`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;
test.clear();
end
else if (cyc<10) begin
sum <= 64'h0;
test.clear();
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'hc68a94a34ec970aa
if (sum !== `EXPECTED_SUM) $stop;
$write("*-* All Finished *-*\n");
$finish;
end
end
endmodule
module Test (/*AUTOARG*/
// Outputs
out, out2,
// Inputs
clk, en, a0, a1, d0, d1
);
input clk;
input [1:0] en;
input [1:0] a0;
input [1:0] a1;
input [7:0] d0;
input [7:0] d1;
output reg [31:0] out;
output reg [15:0] out2;
// verilator lint_off MULTIDRIVEN
reg [7:0] mem [4];
// verilator lint_on MULTIDRIVEN
task clear();
for (int i=0; i<4; ++i) mem[i] = 0;
endtask
always @(posedge clk) begin
if (en[0]) begin
mem[a0] <= d0;
out2[7:0] <= d0;
end
end
always @(negedge clk) begin
if (en[1]) begin
mem[a1] <= d1;
out2[15:8] <= d0;
end
end
assign out = {mem[3],mem[2],mem[1],mem[0]};
endmodule
+18
View File
@@ -0,0 +1,18 @@
#!/usr/bin/perl
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# Copyright 2003 by Wilson Snyder. This program is free software; you can
# redistribute it and/or modify it under the terms of either the GNU
# Lesser General Public License Version 3 or the Perl Artistic License
# Version 2.0.
compile (
);
execute (
check_finished=>1,
);
ok(1);
1;
+63
View File
@@ -0,0 +1,63 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// Copyright 2012 by Wilson Snyder. This program is free software; you can
// redistribute it and/or modify it under the terms of either the GNU
// Lesser General Public License Version 3 or the Perl Artistic License
// Version 2.0.
module t (/*AUTOARG*/);
`define ASSERT(x) initial if (!(x)) $stop
// See IEEE 6.20.2 on value parameters
localparam unsigned [63:0] UNSIGNED =64'h99934567_89abcdef;
localparam signed [63:0] SIGNED =64'sh99934567_89abcdef;
localparam real REAL=1.234;
`ASSERT(UNSIGNED > 0);
`ASSERT(SIGNED < 0);
// bullet 1
localparam A1_WIDE = UNSIGNED;
`ASSERT($bits(A1_WIDE)==64);
localparam A2_REAL = REAL;
`ASSERT(A2_REAL == 1.234);
localparam A3_SIGNED = SIGNED;
`ASSERT($bits(A3_SIGNED)==64 && A3_SIGNED < 0);
localparam A4_EXPR = (2'b01 + 2'b10);
`ASSERT($bits(A4_EXPR)==2 && A4_EXPR==2'b11);
// bullet 2
localparam [63:0] B_UNSIGNED = SIGNED;
`ASSERT($bits(B_UNSIGNED)==64 && B_UNSIGNED > 0);
// bullet 3
localparam signed C_SIGNED = UNSIGNED;
`ASSERT($bits(C_SIGNED)==64 && C_SIGNED < 0);
localparam unsigned C_UNSIGNED = SIGNED;
`ASSERT($bits(C_UNSIGNED)==64 && C_UNSIGNED > 0);
// bullet 4
// verilator lint_off WIDTH
localparam signed [59:0] D_SIGNED = UNSIGNED;
`ASSERT($bits(D_SIGNED)==60 && D_SIGNED < 0);
// verilator lint_on WIDTH
// verilator lint_off WIDTH
localparam unsigned [59:0] D_UNSIGNED = SIGNED;
`ASSERT($bits(D_UNSIGNED)==60 && D_UNSIGNED > 0);
// verilator lint_on WIDTH
// bullet 6
localparam UNSIZED = 23;
`ASSERT($bits(UNSIZED)>=32);
initial begin
$write("*-* All Finished *-*\n");
$finish;
end
endmodule
@@ -7,14 +7,17 @@ if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); di
# Lesser General Public License Version 3 or the Perl Artistic License
# Version 2.0.
$Self->{vlt} or $Self->skip("Verilator only test");
compile (
verilator_flags2 => ["-sp"],
fails=>$Self->{v3},
nc=>0,
v_flags2 => ["--lint-only"],
fails=>1,
expect=>
'%Error: t/t_mem_multi_io_bad.v:\d+: Unsupported: SystemC inputs and outputs must be simple data types; no arrays
'%Error: t/t_pp_circdef_bad.v:\d+: Recursive `define or other nested inclusion
.*
%Error: Exiting due to.*',
);
);
ok(1);
1;
+13
View File
@@ -0,0 +1,13 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed into the Public Domain, for any use,
// without warranty, 2011 by Wilson Snyder.
//
// bug445
`define WIDTH 12
`define SEL_NUM_BITS `WIDTH-`SEL_NUM_BITS +: `SEL_NUM_BITS
`define SEL_BITS `WIDTH-`SEL_NUM_BITS +: `SEL_NUM_BITS
`define ADDR_BITS 0 +: `WIDTH-`SEL_NUM_BITS
typedef logic [`SEL_NUM_BITS-1:0] d_t;
+84 -3
View File
@@ -137,7 +137,7 @@ firstline comma","line LLZZ firstline comma","line
`line 71 "t/t_preproc.v" 0
x y LLZZ "a" y
x y LLZZ "x" y
`line 74 "t/t_preproc.v" 0
@@ -398,7 +398,7 @@ x,y)--bee submacro has comma paren
$display("bits %d %d", $bits(foo), `10);
$display("10 %d %d", $bits(foo), 10);
`line 260 "t/t_preproc.v" 0
@@ -709,5 +709,86 @@ module a_b ; endmodule
integer foo;
module t;
`line 457 "t/t_preproc.v" 2
initial begin : \`LEX_CAT(a[0],_assignment)
`line 464 "t/t_preproc.v" 0
$write("GOT%%m='%m' EXP='%s'\n", "t.\\`LEX_CAT(a[0],_assignment) "); end
initial begin : \a[0]_assignment_a[1]
`line 471 "t/t_preproc.v" 0
$write("GOT%%m='%m' EXP='%s'\n", "t.\\a[0]_assignment_a[1] "); end
initial begin : \`CAT(pp,suffix) $write("GOT%%m='%m' EXP='%s'\n", "t.\\`CAT(pp,suffix) "); end
initial begin : \`CAT(ff,bb)
`line 485 "t/t_preproc.v" 0
$write("GOT%%m='%m' EXP='%s'\n", "t.\\`CAT(ff,bb) "); end
initial begin : \`zzz
`line 491 "t/t_preproc.v" 0
$write("GOT%%m='%m' EXP='%s'\n", "t.\\`zzz "); end
initial begin : \`FOO
`line 498 "t/t_preproc.v" 0
$write("GOT%%m='%m' OTHER_EXP='%s'\n OUR_EXP='%s'", "t.bar ","t.\\`FOO "); end
initial begin : \xx`FOO
`line 500 "t/t_preproc.v" 0
$write("GOT%%m='%m' EXP='%s'\n", "t.\\xx`FOO "); end
initial begin : \`UNKNOWN $write("GOT%%m='%m' EXP='%s'\n", "t.\\`UNKNOWN "); end
initial begin : \`DEF_NO_EXPAND $write("GOT%%m='%m' EXP='%s'\n", "t.\\`DEF_NO_EXPAND "); end
initial $write("GOT='%s' EXP='%s'\n", "foo bar baz", "foo bar baz");
initial $write("GOT='%s' EXP='%s'\n", "foo `A(bar) baz", "foo `A(bar) baz");
endmodule
`line 526 "t/t_preproc.v" 2
+71 -2
View File
@@ -69,7 +69,7 @@ Line_Preproc_Check `__LINE__
comma","line)
`define withquote(a, bar) a bar LLZZ "a" bar
`withquote( x , y)
`withquote( x , y) // Simulators disagree here; some substitute "a" others do not
`define noparam (a,b)
`noparam(a,b)
@@ -254,7 +254,7 @@ Not a \`define
//======================================================================
// bug191
`define bug191(bits) $display("bits %d %d", $bits(foo), `bits);
`define bug191(bits) $display("bits %d %d", $bits(foo), bits);
`bug191(10)
//======================================================================
@@ -453,3 +453,72 @@ module `Q1 ; endmodule
// bug311
integer/*NEED_SPACE*/foo;
//======================================================================
// bug441
module t;
//-----
// case provided
// note this does NOT escape as suggested in the mail
`define LEX_CAT(lexem1, lexem2) lexem1``lexem2
`define LEX_ESC(name) \name \
initial begin : `LEX_ESC( `LEX_CAT(a[0],_assignment) ) $write("GOT%%m='%m' EXP='%s'\n", "t.\\`LEX_CAT(a[0],_assignment) "); end
//-----
// SHOULD(simulator-dependant): Backslash doesn't prevent arguments from
// substituting and the \ staying in the expansion
// Note space after name is important so when substitute it has ending whitespace
`define ESC_CAT(name,name2) \name``_assignment_``name2 \
initial begin : `ESC_CAT( a[0],a[1] ) $write("GOT%%m='%m' EXP='%s'\n", "t.\\a[0]_assignment_a[1] "); end
`undef ESC_CAT
//-----
`define CAT(a,b) a``b
`define ESC(name) \`CAT(name,suffix)
// RULE: Ignoring backslash does NOT allow an additional expansion level
// (Because ESC gets expanded then the \ has it's normal escape meaning)
initial begin : `ESC(pp) $write("GOT%%m='%m' EXP='%s'\n", "t.\\`CAT(pp,suffix) "); end
`undef CAT `undef ESC
//-----
`define CAT(a,b) a``b
`define ESC(name) \name \
// Similar to above; \ does not allow expansion after substitution
initial begin : `ESC( `CAT(ff,bb) ) $write("GOT%%m='%m' EXP='%s'\n", "t.\\`CAT(ff,bb) "); end
`undef CAT `undef ESC
//-----
`define ESC(name) \name \
// MUST: Unknown macro with backslash escape stays as escaped symbol name
initial begin : `ESC( `zzz ) $write("GOT%%m='%m' EXP='%s'\n", "t.\\`zzz "); end
`undef ESC
//-----
`define FOO bar
`define ESC(name) \name \
// SHOULD(simulator-dependant): Known macro with backslash escape expands
initial begin : `ESC( `FOO ) $write("GOT%%m='%m' OTHER_EXP='%s'\n OUR_EXP='%s'", "t.bar ","t.\\`FOO "); end
// SHOULD(simulator-dependant): Prefix breaks the above
initial begin : `ESC( xx`FOO ) $write("GOT%%m='%m' EXP='%s'\n", "t.\\xx`FOO "); end
`undef FOO `undef ESC
//-----
// MUST: Unknown macro not under call with backslash escape doesn't expand
`undef UNKNOWN
initial begin : \`UNKNOWN $write("GOT%%m='%m' EXP='%s'\n", "t.\\`UNKNOWN "); end
//-----
// MUST: Unknown macro not under call doesn't expand
`define DEF_NO_EXPAND error_dont_expand
initial begin : \`DEF_NO_EXPAND $write("GOT%%m='%m' EXP='%s'\n", "t.\\`DEF_NO_EXPAND "); end
`undef DEF_NO_EXPAND
//-----
// bug441 derivative
// SHOULD(simulator-dependant): Quotes doesn't prevent arguments from expanding (like backslashes above)
`define STR(name) "foo name baz"
initial $write("GOT='%s' EXP='%s'\n", `STR(bar), "foo bar baz");
`undef STR
//-----
// RULE: Because there are quotes after substituting STR, the `A does NOT expand
`define STR(name) "foo name baz"
`define A(name) boo name hiss
initial $write("GOT='%s' EXP='%s'\n", `STR(`A(bar)), "foo `A(bar) baz");
`undef A `undef STR
endmodule
//======================================================================
+1 -1
View File
@@ -12,7 +12,7 @@ $Self->{vlt} or $Self->skip("Verilator only test");
compile (
make_top_shell => 0,
make_main => 0,
verilator_flags2 => ["--exe $Self->{t_dir}/$Self->{name}.cpp --debug"],
verilator_flags2 => ["--exe $Self->{t_dir}/$Self->{name}.cpp"],
);
execute (
+1 -1
View File
@@ -12,7 +12,7 @@ $Self->{vlt} or $Self->skip("Verilator only test");
compile (
make_top_shell => 0,
make_main => 0,
verilator_flags2 => ["--exe $Self->{t_dir}/$Self->{name}.cpp --debug"],
verilator_flags2 => ["--exe $Self->{t_dir}/$Self->{name}.cpp"],
);
execute (
+24
View File
@@ -0,0 +1,24 @@
#!/usr/bin/perl
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# Copyright 2003 by Wilson Snyder. This program is free software; you can
# redistribute it and/or modify it under the terms of either the GNU
# Lesser General Public License Version 3 or the Perl Artistic License
# Version 2.0.
top_filename("t/t_udp.v");
compile (
fails=>$Self->{vlt},
expect=>
'%Error: t/t_udp.v:\d+: Unsupported: Verilog 1995 UDP Tables. Use --bbox-unsup to ignore tables.
%Error: t/t_udp.v:\d+: Unsupported: Verilog 1995 UDP Tables. Use --bbox-unsup to ignore tables.
%Error: Exiting due to '
);
execute (
) if !$Self->{vlt};
ok(1);
1;
+57
View File
@@ -30,8 +30,10 @@ module t (/*AUTOARG*/);
// Declarations using var
var byte v_b;
`ifndef VCS
var [2:0] v_b3;
var signed [2:0] v_bs;
`endif
// verilator lint_off WIDTH
localparam p_implicit = {96{1'b1}};
@@ -44,11 +46,27 @@ module t (/*AUTOARG*/);
localparam reg p_reg = {96{1'b1}};
localparam bit p_bit = {96{1'b1}};
localparam logic p_logic = {96{1'b1}};
localparam reg [0:0] p_reg1 = {96{1'b1}};
localparam bit [0:0] p_bit1 = {96{1'b1}};
localparam logic [0:0] p_logic1= {96{1'b1}};
localparam reg [1:0] p_reg2 = {96{1'b1}};
localparam bit [1:0] p_bit2 = {96{1'b1}};
localparam logic [1:0] p_logic2= {96{1'b1}};
// verilator lint_on WIDTH
byte v_byte[2];
shortint v_shortint[2];
int v_int[2];
longint v_longint[2];
integer v_integer[2];
time v_time[2];
chandle v_chandle[2];
bit v_bit[2];
logic v_logic[2];
reg v_reg[2];
real v_real[2];
realtime v_realtime[2];
// We do this in two steps so we can check that initialization inside functions works properly
// verilator lint_off WIDTH
function f_implicit; reg lv_implicit; f_implicit = lv_implicit; endfunction
@@ -61,6 +79,9 @@ module t (/*AUTOARG*/);
function reg f_reg; reg lv_reg; f_reg = lv_reg; endfunction
function bit f_bit; bit lv_bit; f_bit = lv_bit; endfunction
function logic f_logic; logic lv_logic; f_logic = lv_logic; endfunction
function reg [0:0] f_reg1; reg [0:0] lv_reg1; f_reg1 = lv_reg1; endfunction
function bit [0:0] f_bit1; bit [0:0] lv_bit1; f_bit1 = lv_bit1; endfunction
function logic [0:0] f_logic1; logic [0:0] lv_logic1; f_logic1 = lv_logic1; endfunction
function reg [1:0] f_reg2; reg [1:0] lv_reg2; f_reg2 = lv_reg2; endfunction
function bit [1:0] f_bit2; bit [1:0] lv_bit2; f_bit2 = lv_bit2; endfunction
function logic [1:0] f_logic2; logic [1:0] lv_logic2; f_logic2 = lv_logic2; endfunction
@@ -107,26 +128,57 @@ module t (/*AUTOARG*/);
// verilator lint_on UNSIGNED
// Can't CHECK_ALL(d_chandle), as many operations not legal on chandles
`ifdef VERILATOR // else indeterminate
if ($bits(d_chandle) !== 64) $stop;
`endif
`define CHECK_P(name,nbits) \
if (name !== {(nbits){1'b1}}) begin $display("%%Error: Bad size for %s",`"name`"); $stop; end \
// name b
`CHECK_P(p_implicit ,96);
`CHECK_P(p_implicit[0] ,1 );
`CHECK_P(p_explicit ,90);
`CHECK_P(p_explicit[0] ,1 );
`CHECK_P(p_byte ,8 );
`CHECK_P(p_byte[0] ,1 );
`CHECK_P(p_shortint ,16);
`CHECK_P(p_shortint[0] ,1 );
`CHECK_P(p_int ,32);
`CHECK_P(p_int[0] ,1 );
`CHECK_P(p_longint ,64);
`CHECK_P(p_longint[0] ,1 );
`CHECK_P(p_integer ,32);
`CHECK_P(p_integer[0] ,1 );
`CHECK_P(p_bit ,1 );
`CHECK_P(p_logic ,1 );
`CHECK_P(p_reg ,1 );
`CHECK_P(p_bit1 ,1 );
`CHECK_P(p_logic1 ,1 );
`CHECK_P(p_reg1 ,1 );
`CHECK_P(p_bit1[0] ,1 );
`CHECK_P(p_logic1[0] ,1 );
`CHECK_P(p_reg1[0] ,1 );
`CHECK_P(p_bit2 ,2 );
`CHECK_P(p_logic2 ,2 );
`CHECK_P(p_reg2 ,2 );
`define CHECK_B(varname,nbits) \
if ($bits(varname) !== nbits) begin $display("%%Error: Bad size for %s",`"varname`"); $stop; end \
`CHECK_B(v_byte[1] ,8 );
`CHECK_B(v_shortint[1] ,16);
`CHECK_B(v_int[1] ,32);
`CHECK_B(v_longint[1] ,64);
`CHECK_B(v_integer[1] ,32);
`CHECK_B(v_time[1] ,64);
//`CHECK_B(v_chandle[1]
`CHECK_B(v_bit[1] ,1 );
`CHECK_B(v_logic[1] ,1 );
`CHECK_B(v_reg[1] ,1 );
//`CHECK_B(v_real[1] ,64); // $bits not allowed
//`CHECK_B(v_realtime[1] ,64); // $bits not allowed
`define CHECK_F(fname,nbits,zeroinit) \
if ($bits(fname()) !== nbits) begin $display("%%Error: Bad size for %s",`"fname`"); $stop; end \
@@ -139,10 +191,15 @@ module t (/*AUTOARG*/);
`CHECK_F(f_longint ,64,1'b1);
`CHECK_F(f_integer ,32,1'b0);
`CHECK_F(f_time ,64,1'b0);
`ifdef VERILATOR // else indeterminate
`CHECK_F(f_chandle ,64,1'b0);
`endif
`CHECK_F(f_bit ,1 ,1'b1);
`CHECK_F(f_logic ,1 ,1'b0);
`CHECK_F(f_reg ,1 ,1'b0);
`CHECK_F(f_bit1 ,1 ,1'b1);
`CHECK_F(f_logic1 ,1 ,1'b0);
`CHECK_F(f_reg1 ,1 ,1'b0);
`CHECK_F(f_bit2 ,2 ,1'b1);
`CHECK_F(f_logic2 ,2 ,1'b0);
`CHECK_F(f_reg2 ,2 ,1'b0);
+29
View File
@@ -0,0 +1,29 @@
#!/usr/bin/perl
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# Copyright 2003 by Wilson Snyder. This program is free software; you can
# redistribute it and/or modify it under the terms of either the GNU
# Lesser General Public License Version 3 or the Perl Artistic License
# Version 2.0.
$Self->{verilated_randReset} = 1; # allow checking if we initialize vars to zero only when needed
compile (
fails=>1,
expect=>
'%Error: t/t_var_types_bad.v:\d+: Illegal bit or array select; variable already selected, or bad dimension: d_bitz
%Error: t/t_var_types_bad.v:\d+: Illegal bit or array select; variable already selected, or bad dimension
%Error: t/t_var_types_bad.v:\d+: Illegal bit or array select; variable already selected, or bad dimension: d_logicz
%Error: t/t_var_types_bad.v:\d+: Illegal bit or array select; variable already selected, or bad dimension
%Error: t/t_var_types_bad.v:\d+: Illegal bit or array select; variable already selected, or bad dimension: d_regz
%Error: t/t_var_types_bad.v:\d+: Illegal bit or array select; variable already selected, or bad dimension
%Error: t/t_var_types_bad.v:\d+: Illegal bit or array select; variable already selected, or bad dimension: d_real
%Error: t/t_var_types_bad.v:\d+: Illegal bit or array select; variable already selected, or bad dimension
%Error: t/t_var_types_bad.v:\d+: Illegal bit or array select; variable already selected, or bad dimension: d_realtime
%Error: t/t_var_types_bad.v:\d+: Illegal bit or array select; variable already selected, or bad dimension
%Error: Exiting due to.*',
);
ok(1);
1;
+60
View File
@@ -0,0 +1,60 @@
// 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*/);
// IEEE: integer_atom_type
byte d_byte;
shortint d_shortint;
int d_int;
longint d_longint;
integer d_integer;
time d_time;
chandle d_chandle;
// IEEE: integer_atom_type
bit d_bit;
logic d_logic;
reg d_reg;
bit [0:0] d_bit1;
logic [0:0] d_logic1;
reg [0:0] d_reg1;
bit d_bitz;
logic d_logicz;
reg d_regz;
// IEEE: non_integer_type
//UNSUP shortreal d_shortreal;
real d_real;
realtime d_realtime;
initial begin
// below errors might cause spurious warnings
// verilator lint_off WIDTH
d_bitz[0] = 1'b1; // Illegal range
d_logicz[0] = 1'b1; // Illegal range
d_regz[0] = 1'b1; // Illegal range
`ifndef VERILATOR //UNSUPPORTED, it's just a 64 bit int right now
d_chandle[0] = 1'b1; // Illegal
`endif
d_real[0] = 1'b1; // Illegal
d_realtime[0] = 1'b1; // Illegal
// verilator lint_on WIDTH
d_byte[0] = 1'b1; // OK
d_shortint[0] = 1'b1; // OK
d_int[0] = 1'b1; // OK
d_longint[0] = 1'b1; // OK
d_integer[0] = 1'b1; // OK
d_time[0] = 1'b1; // OK
d_bit1[0] = 1'b1; // OK
d_logic1[0] = 1'b1; // OK
d_reg1[0] = 1'b1; // OK
end
endmodule
+1 -1
View File
@@ -75,7 +75,7 @@ obj_dir:
nosp:
@echo
@echo %Skip: SYSTERMPERL not in environment
@echo %Skip: SYSTEMPERL not in environment
@echo
######################################################################