mirror of
https://github.com/verilator/verilator.git
synced 2026-10-03 08:33:21 +02:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a8432ed4a4 | ||
|
|
04f910b747 | ||
|
|
1c3de70155 | ||
|
|
b73642f8a8 | ||
|
|
479b497528 | ||
|
|
31b55d3844 | ||
|
|
dbf4e08d09 | ||
|
|
274359e6ee | ||
|
|
8687dcbce1 | ||
|
|
03dfbdb7b1 | ||
|
|
3c8519f245 | ||
|
|
4d2cc3ebdd | ||
|
|
6e2758ae26 | ||
|
|
4637e06ad2 | ||
|
|
764399256c | ||
|
|
f4ca4edc64 | ||
|
|
872a1216a7 | ||
|
|
8c75674591 | ||
|
|
e6244ca204 | ||
|
|
f540362e36 | ||
|
|
2be6699a6a | ||
|
|
09c10492ab | ||
|
|
c8e4b1fc84 | ||
|
|
0de7cece5b | ||
|
|
a3413a6749 | ||
|
|
b104ab9491 | ||
|
|
269c5dce60 | ||
|
|
a39c81c63f | ||
|
|
d699247269 | ||
|
|
7caafb4014 | ||
|
|
f1546abf09 | ||
|
|
3083562f6f | ||
|
|
da2ee70462 | ||
|
|
7e9dda3c5e | ||
|
|
0b96f88875 | ||
|
|
f13ffe2098 | ||
|
|
bca5d26583 | ||
|
|
660bc757f1 | ||
|
|
ca927fe587 | ||
|
|
9df8966f4a | ||
|
|
3429f41489 | ||
|
|
0c7c4924ee | ||
|
|
8f40d6617e | ||
|
|
af9e85bda1 | ||
|
|
717f45d117 | ||
|
|
35c53865fb |
@@ -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,5 +1,6 @@
|
||||
^CVS/
|
||||
/CVS/
|
||||
\.gdbinit$
|
||||
\.git/
|
||||
\.svn/
|
||||
\.(bak|old)/
|
||||
|
||||
+1
-1
@@ -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
@@ -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
|
||||
|
||||
@@ -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
@@ -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)
|
||||
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
|
||||
|
||||
@@ -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
@@ -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
@@ -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; ) {
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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);
|
||||
|
||||
@@ -275,7 +275,6 @@ private:
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
virtual void visit(AstVar* nodep, AstNUser*) {
|
||||
cleanFileline(nodep);
|
||||
m_varp = nodep;
|
||||
|
||||
@@ -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
@@ -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
@@ -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; }
|
||||
|
||||
@@ -33,6 +33,7 @@
|
||||
#include <cstdarg>
|
||||
#include <unistd.h>
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
|
||||
#include "V3Error.h"
|
||||
#include "V3Global.h"
|
||||
|
||||
@@ -53,6 +53,7 @@ struct V3ParseBisonYYSType {
|
||||
string* strp;
|
||||
int cint;
|
||||
double cdouble;
|
||||
bool cbool;
|
||||
V3UniqState uniqstate;
|
||||
AstSignedState signstate;
|
||||
V3ImportProperty iprop;
|
||||
|
||||
+18
-3
@@ -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
@@ -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
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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:
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
source ../src/.gdbinit
|
||||
@@ -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
@@ -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
|
||||
|
||||
|
||||
Executable
+20
@@ -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;
|
||||
@@ -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
|
||||
Executable
+20
@@ -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;
|
||||
@@ -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
|
||||
Executable
+20
@@ -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;
|
||||
@@ -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
|
||||
@@ -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;
|
||||
|
||||
|
||||
Executable
+18
@@ -0,0 +1,18 @@
|
||||
#!/usr/bin/perl
|
||||
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
|
||||
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||
#
|
||||
# Copyright 2003 by Wilson Snyder. This program is free software; you can
|
||||
# redistribute it and/or modify it under the terms of either the GNU
|
||||
# Lesser General Public License Version 3 or the Perl Artistic License
|
||||
# Version 2.0.
|
||||
|
||||
compile (
|
||||
);
|
||||
|
||||
execute (
|
||||
check_finished=>1,
|
||||
);
|
||||
|
||||
ok(1);
|
||||
1;
|
||||
@@ -0,0 +1,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
|
||||
@@ -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.*},
|
||||
);
|
||||
|
||||
|
||||
Executable
+18
@@ -0,0 +1,18 @@
|
||||
#!/usr/bin/perl
|
||||
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
|
||||
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||
#
|
||||
# Copyright 2003 by Wilson Snyder. This program is free software; you can
|
||||
# redistribute it and/or modify it under the terms of either the GNU
|
||||
# Lesser General Public License Version 3 or the Perl Artistic License
|
||||
# Version 2.0.
|
||||
|
||||
compile (
|
||||
);
|
||||
|
||||
execute (
|
||||
check_finished=>1,
|
||||
);
|
||||
|
||||
ok(1);
|
||||
1;
|
||||
@@ -0,0 +1,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
|
||||
Executable
+24
@@ -0,0 +1,24 @@
|
||||
#!/usr/bin/perl
|
||||
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
|
||||
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||
#
|
||||
# Copyright 2003 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
|
||||
Executable
+30
@@ -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;
|
||||
@@ -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
|
||||
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
|
||||
Executable
+25
@@ -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;
|
||||
Executable
+25
@@ -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;
|
||||
@@ -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
|
||||
@@ -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;
|
||||
|
||||
Executable
+18
@@ -0,0 +1,18 @@
|
||||
#!/usr/bin/perl
|
||||
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
|
||||
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||
#
|
||||
# Copyright 2003 by Wilson Snyder. This program is free software; you can
|
||||
# redistribute it and/or modify it under the terms of either the GNU
|
||||
# Lesser General Public License Version 3 or the Perl Artistic License
|
||||
# Version 2.0.
|
||||
|
||||
compile (
|
||||
);
|
||||
|
||||
execute (
|
||||
check_finished=>1,
|
||||
);
|
||||
|
||||
ok(1);
|
||||
1;
|
||||
@@ -0,0 +1,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
|
||||
Executable
+18
@@ -0,0 +1,18 @@
|
||||
#!/usr/bin/perl
|
||||
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
|
||||
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||
#
|
||||
# Copyright 2003 by Wilson Snyder. This program is free software; you can
|
||||
# redistribute it and/or modify it under the terms of either the GNU
|
||||
# Lesser General Public License Version 3 or the Perl Artistic License
|
||||
# Version 2.0.
|
||||
|
||||
compile (
|
||||
);
|
||||
|
||||
execute (
|
||||
check_finished=>1,
|
||||
);
|
||||
|
||||
ok(1);
|
||||
1;
|
||||
@@ -0,0 +1,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;
|
||||
|
||||
@@ -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;
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
//======================================================================
|
||||
|
||||
@@ -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 (
|
||||
|
||||
@@ -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 (
|
||||
|
||||
Executable
+24
@@ -0,0 +1,24 @@
|
||||
#!/usr/bin/perl
|
||||
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
|
||||
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||
#
|
||||
# Copyright 2003 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;
|
||||
@@ -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);
|
||||
|
||||
Executable
+29
@@ -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;
|
||||
@@ -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
@@ -75,7 +75,7 @@ obj_dir:
|
||||
|
||||
nosp:
|
||||
@echo
|
||||
@echo %Skip: SYSTERMPERL not in environment
|
||||
@echo %Skip: SYSTEMPERL not in environment
|
||||
@echo
|
||||
|
||||
######################################################################
|
||||
|
||||
Reference in New Issue
Block a user