Compare commits

...
35 Commits
Author SHA1 Message Date
Wilson Snyder 344248cea0 Version bump 2011-06-28 20:52:04 -04:00
Wilson Snyder 2789e3dba5 Fix 96 bit DPI input/outputs, bug359 2011-06-28 20:45:50 -04:00
Wilson Snyder cca759a41e Tests: Example embedding 2011-05-22 08:43:36 -04:00
Wilson Snyder 4f7b3d8882 Fix out of memory on slice syntax error, bug354. 2011-05-21 08:19:33 -04:00
Wilson Snyder 2b330b78b7 Support bit vectors > 64 bits wide in DPI import and exports. 2011-05-20 21:33:31 -04:00
Wilson Snyder d47ca1912b tests: Fix invocation scripts for new site standard 2011-05-20 20:47:15 -04:00
Wilson Snyder cdf18c96f4 driver: Allow getting verilator flags in tests 2011-05-19 21:25:23 -04:00
Wilson Snyder 53acaa05b8 Commentary 2011-05-18 07:10:12 -04:00
Wilson Snyder fb85679068 Fix DPI bit vector compile errors, bug347. 2011-05-12 07:35:28 -04:00
Wilson Snyder 9558e14479 Fix DPI undeclared svBitVecVal compile error, bug346. Additional change. 2011-05-12 06:59:13 -04:00
Wilson Snyder 4af0af93bf Fix DPI undeclared svBitVecVal compile error, bug346. 2011-05-12 06:32:29 -04:00
Wilson Snyder df4bc950fe Cleanup trailing whitespace 2011-05-09 23:58:38 -04:00
Wilson Snyder 250394f72b Fix compiler warnings on SPARC, bug288 2011-05-09 23:49:17 -04:00
Wilson Snyder d5e9e7cd2b Remove dead code 2011-04-19 19:02:03 -05:00
Wilson Snyder 9a96f621ef Fix CDCRSTLOGIC report showing endpoint flops without resets. 2011-04-18 10:47:02 -04:00
Wilson Snyder 5d7ce096c6 Fix error on enum references to other packages, bug339. 2011-04-13 19:34:14 -04:00
Wilson Snyder c9f8109c06 Pre-version 2011-04-13 19:33:58 -04:00
Wilson Snyder a20b4f2864 Version bump 2011-04-06 07:33:44 -04:00
Wilson Snyder 44a19d2a0a Fix missing test files 2011-04-06 07:33:32 -04:00
Wilson Snyder 02f3beb8db Add V3Number rotate functions; unused as yet 2011-03-30 21:31:29 -04:00
Wilson Snyder 3269cc3d90 Add +libext+.sv default 2011-03-30 21:30:36 -04:00
Wilson Snyder fb70a1f4ab Add --Wno-fatal to turn off abort on warnings. 2011-03-22 18:09:39 -04:00
Wilson Snyder df0aa483ce Support ${...} and $(...) env variables in .vc files 2011-03-21 12:25:31 -04:00
Wilson Snyder c83f12a55c Support simple cast operators, bug335. 2011-03-17 22:25:49 -04:00
Wilson Snyder 9704f59566 Internals: Rename AstCast to AstCCast 2011-03-17 21:09:52 -04:00
Wilson Snyder 2923893d34 Support loop unrolling on width mismatches, bug 333 2011-03-12 07:45:04 -05:00
Wilson Snyder 890dab0742 Write logfile on each failure 2011-03-12 07:44:29 -05:00
Wilson Snyder 607e26b041 Commentary 2011-03-08 06:49:45 -05:00
Wilson Snyder ea75290f65 Add error on circular parameter definitions, bug329 2011-03-07 20:44:19 -05:00
Wilson Snyder a176054118 Add --trace-max-width and --trace-max-array, bug 319. 2011-02-23 21:58:27 -05:00
Wilson Snyder 9a697dc5f5 Accelerate bit-selected inversions. 2011-02-23 21:36:38 -05:00
Wilson Snyder cfdb852843 Fix concatenates and vectored bufif1, bug326. 2011-02-23 21:21:59 -05:00
Wilson Snyder 2e67a91982 Support $bits(data_type), bug327. 2011-02-23 19:04:15 -05:00
Wilson Snyder 074ca9330d Make width violation on function outputs a fatal error 2011-02-18 20:52:26 -05:00
Wilson Snyder f0d7cdcb20 Commentary 2011-02-18 07:11:03 -05:00
65 changed files with 1759 additions and 264 deletions
+36
View File
@@ -3,6 +3,42 @@ Revision history for Verilator
The contributors that suggested a given feature are shown in []. [by ...]
indicates the contributor was also the author of the fix; Thanks!
* Verilator 3.813 2011/06/28
*** Support bit vectors > 64 bits wide in DPI import and exports.
*** Fix out of memory on slice syntax error, bug354. [Alex Solomatnikov]
**** Fix error on enum references to other packages, bug339. [Alex Solomatnikov]
**** Fix DPI undeclared svBitVecVal compile error, bug346. [Chandan Egbert]
**** Fix DPI bit vector compile errors, bug347, bug359. [Chandan Egbert]
**** Fix CDCRSTLOGIC report showing endpoint flops without resets.
**** Fix compiler warnings on SPARC, bug288. [Ahmed El-Mahmoudy]
* Verilator 3.812 2011/04/06
*** Add --trace-max-width and --trace-max-array, bug319. [Alex Solomatnikov]
*** Add --Wno-fatal to turn off abort on warnings. [by Stefan Wallentowitz]
**** Support ${...} and $(...) env vars in .vc files. [by Stefan Wallentowitz]
**** Support $bits(data_type), bug327. [Alex Solomatnikov]
**** Support loop unrolling on width mismatches, bug333. [Joe Eiler]
**** Support simple cast operators, bug335. [Alex Solomatnikov]
**** Accelerate bit-selected inversions.
**** Add error on circular parameter definitions, bug329. [Alex Solomatnikov]
**** Fix concatenates and vectored bufif1, bug326. [Iztok Jeras]
* Verilator 3.811 2011/02/14
**** Report errors on duplicated or empty pins, bug321. [Christian Leber]
+102 -33
View File
@@ -252,7 +252,7 @@ descriptions in the next sections for more information.
--exe Link to create executable
-F <file> Parse options from a file, relatively
-f <file> Parse options from a file
--gdbbt Run Verilator under GDB for backtrace
--gdbbt Run Verilator under GDB for backtrace
--help Display this help
-I<dir> Directory to search for includes
--if-depth <value> Tune IFDEPTH warning
@@ -292,6 +292,8 @@ descriptions in the next sections for more information.
--top-module <topname> Name of top level input module
--trace Enable waveform creation
--trace-depth <levels> Depth of tracing
--trace-max-array <bits> Maximum bit width for tracing
--trace-max-width <depth> Maximum array depth for tracing
--trace-underscore Enable tracing of _signals
-U<var> Undefine preprocessor define
--unroll-count <loops> Tune maximum loop iterations
@@ -304,6 +306,7 @@ descriptions in the next sections for more information.
-Wno-<message> Disable warning
-Wno-lint Disable all lint warnings
-Wno-style Disable all style warnings
-Wno-fatal Disable fatal exit on warnings
-x-assign <mode> Initially assign Xs to this value
-y <dir> Directory to search for modules
@@ -534,14 +537,18 @@ the command line that implement the main loop for your simulation.
Read the specified file, and act as if all text inside it was specified as
command line parameters. Any relative paths are relative to the directory
containing the specified file. Note -F is fairly standard across Verilog
tools.
containing the specified file. See also -f. Note -F is fairly standard
across Verilog tools.
=item -f I<file>
Read the specified file, and act as if all text inside it was specified as
command line parameters. Any relative paths are relative to the current
directory. Note -f is fairly standard across Verilog tools.
directory. See also -F. Note -f is fairly standard across Verilog tools.
The file may contain // comments which are ignored to the end of the line.
Any $VAR, $(VAR), or ${VAR} will be replaced with the specified environment
variable.
=item --gdbbt
@@ -610,7 +617,7 @@ appropriate `begin_keywords.
Specify the extensions that should be used for finding modules. If for
example module I<x> is referenced, look in I<x>.I<ext>. Note +libext+ is
fairly standard across Verilog tools.
fairly standard across Verilog tools. Defaults to .v and .sv.
=item --lint-only
@@ -816,6 +823,18 @@ Specify the number of levels deep to enable tracing, for example
entire model. Using a small number will decrease visibility, but greatly
improve runtime and trace file size.
=item --trace-max-array I<bits>
Rarely needed. Specify the maximum array depth of a signal that may be
traced. Defaults to 32, as tracing large arrays may greatly slow traced
simulations.
=item --trace-max-width I<depth>
Rarely needed. Specify the maximum bit width of a signal that may be
traced. Defaults to 256, as tracing large vectors may greatly slow traced
simulations.
=item --trace-underscore
Enable tracing of signals that start with an underscore. Normally, these
@@ -865,11 +884,11 @@ example C<-Werror-NOUNOPTFLAT>.
=item -Wfuture-I<message>
Suppress unknown Verilator comments or warning messages with the given
message code. This is used to allow code written with pragmas for a later
version of Verilator to run under a older version; add -Wfuture- arguments
for each message code or comment that the new version supports which the
older version does not support.
Rarely needed. Suppress unknown Verilator comments or warning messages
with the given message code. This is used to allow code written with
pragmas for a later version of Verilator to run under a older version; add
-Wfuture- arguments for each message code or comment that the new version
supports which the older version does not support.
=item -Wno-I<message>
@@ -894,6 +913,14 @@ already disabled). This is equivalent to "-Wno-DECLFILENAME -Wno-DEFPARAM
-Wno-INCABSPATH -Wno-SYNCASYNCNET -Wno-UNDRIVEN -Wno-UNUSED
-Wno-VARHIDDEN".
=item -Wno-fatal
When warnings are detected, print them, but do not exit the simulator.
Having warning messages in builds is sloppy. It is strongly recommended
you cleanup your code, use inline lint_off, or use -Wno-... flags rather
than using this option.
=item -Wwarn-I<message>
Enables the specified warning message.
@@ -954,7 +981,7 @@ We'll compile this example into C++.
cat <<EOF >our.v
module our;
initial begin \$display("Hello World"); \$finish; end
initial begin $display("Hello World"); $finish; end
endmodule
EOF
@@ -976,7 +1003,7 @@ your operating system (as an RPM), first you need to point to the kit:
export PATH=$VERILATOR_ROOT/bin:$PATH
Now we run Verilator on our little example.
verilator -Wall --cc our.v --exe sim_main.cpp
We can see the source code under the "obj_dir" directory. See the FILES
@@ -1019,7 +1046,7 @@ This is an example similar to the above, but using SystemPerl.
module our (clk);
input clk; // Clock is required to get initial activation
always @ (posedge clk)
begin \$display("Hello World"); \$finish; end
begin $display("Hello World"); $finish; end
endmodule
EOF
@@ -1410,6 +1437,38 @@ The /*verilator sformat*/ indicates that this function accepts a $display
like format specifier followed by any number of arguments to satisfy the
format.
=head2 DPI Context Functions
Verilator supports IEEE DPI Context Functions. Context imports pass the
simulator context, including calling scope name, and filename and line
number to the C code. For example, in Verilog:
import "DPI-C" context function int dpic_line();
initial $display("This is line %d, again, line %d\n", `line, dpic_line());
This will call C++ code which may then use the svGet* functions to read
information, in this case the line number of the Verilog statement that
invoked the dpic_line function:
int dpic_line() {
// Get a scope: svScope scope = svGetScope();
const char* scopenamep = svGetNameFromScope(scope);
assert(scopenamep);
const char* filenamep = "";
int lineno = 0;
if (svGetCallerInfo(&filenamep, &lineno)) {
printf("dpic_line called from scope %s on line %d\n",
scopenamep, lineno);
return lineno;
} else {
return 0;
}
}
See the IEEE Standard for more information.
=head2 DPI Header Isolation
Verilator places the IEEE standard header files such as svdpi.h into a
@@ -1421,7 +1480,7 @@ svdpi.h and similar standard files with different contents, the vltstd
directory should not be included to prevent picking up incompatible
definitions.
=head2 Public Functions
=head2 Public Functions
Instead of DPI exporting, there's also Verilator public functions, which
are slightly faster, but less compatible.
@@ -2080,7 +2139,7 @@ of the form:
inout driver;
wire driver = (enable) ? output_value : 1'bz;
Will be converted to
input driver__in; // Value being driven in from "external" drivers
@@ -2189,6 +2248,11 @@ Increment/decrement can only be used as standalone statements or in for
loops. They cannot be used as side effect operators inside more complicate
expressions ("a = b++;").
=item cast operator
Casting is supported only between simple scalar types, signed and unsigned,
not arrays nor structs.
=item chandle
Treated as a "longint"; does not yet warn about operations that are
@@ -3232,25 +3296,30 @@ Brooks, Duane Galbi, Paul Wasson, and Wilson Snyder. Major testers include
Jeff Dutton, Ralf Karge, David Hewson, Wim Michiels, and Gene Weber.
Some of the people who have provided ideas and feedback for Verilator
include David Addison, Hans Van Antwerpen, Vasu Arasanipalai, Jens Arm, J
include: David Addison, Hans Van Antwerpen, Vasu Arasanipalai, Jens Arm, J
Baxter, Jeremy Bennett, David Black, Gregg Bouchard, Christopher Boumenot,
Byron Bradley, Bryan Brady, Lane Brooks, John Brownlee, Lawrence Butcher,
Chris Candler, Lauren Carlson, Donal Casey, Robert A. Clark, Allan
Cochrane, Gunter Dannoritzer, Bernard Deadman, John Deroo, John Dickol,
Danny Ding, Alex Duller, Jeff Dutton, Robert Farrell, Eugen Fekete, Andrea
Foletto, Bob Fredieu, Shankar Giri, Sam Gladstone, Chitlesh Goorah, Thomas
Hawkins, David Hewson, Jae Hossell, Ben Jackson, Mike Kagen, Guy-Armand
Kamendje, Vasu Kandadi, Patricio Kaplan, Ralf Karge, Dan Katz, Sol Katzman,
Jonathan Kimmitt, Gernot Koch, Soon Koh, Steve Kolecki, Steve Lang,
Stephane Laurent, Charlie Lind, Dan Lussier, Fred Ma, Duraid Madina, Mark
Marshall, Wim Michiels, Dennis Muhlestein, John Murphy, Richard Myers,
Dimitris Nalbantis, Paul Nitza, Pete Nixon, Lisa Noack, Mark Nodine,
Andreas Olofsson, Niranjan Prabhu, Oleg Rodionov, John Sanguinetti, Mike
Shinkarovsky, Rafael Shirakawa, Rodney Sinclair, Brian Small, Art Stamness,
John Stroebel, Emerson Suguimoto, Renga Sundararajan, Stefan Thiede, Gary
Thomas, Steve Tong, Holger Waechtler, Shawn Wang, Greg Waters, Eugene
Weber, Leon Wildman, Gerald Williams, Jeff Winston, Johan Wouters, and Ding
Xiaoliang.
Nick Bowler, Byron Bradley, Bryan Brady, Lane Brooks, John Brownlee,
Lawrence Butcher, Chris Candler, Lauren Carlson, Donal Casey, Terry Chen,
Robert A. Clark, Allan Cochrane, Gunter Dannoritzer, Ashutosh Das, Bernard
Deadman, John Deroo, John Dickol, Danny Ding, Ivan Djordjevic, Alex Duller,
Jeff Dutton, Chandan Egbert, Joe Eiler, Ahmed El-Mahmoudy, Robert Farrell,
Eugen Fekete, Andrea Foletto, Bob Fredieu, Shankar Giri, Sam Gladstone,
Amir Gonnen, Chitlesh Goorah, Neil Hamilton, Thomas Hawkins, David Hewson,
Jae Hossell, Ben Jackson, Iztok Jeras, Mike Kagen, Guy-Armand Kamendje,
Vasu Kandadi, Patricio Kaplan, Ralf Karge, Dan Katz, Sol Katzman, Jonathan
Kimmitt, Gernot Koch, Soon Koh, Steve Kolecki, Steve Lang, Stephane
Laurent, Christian Leber, Charlie Lind, Paul Liu, Dan Lussier, Fred Ma,
Duraid Madina, Mark Marshall, Jason McMullan, Wim Michiels, Dennis
Muhlestein, John Murphy, Richard Myers, Dimitris Nalbantis, Paul Nitza,
Pete Nixon, Lisa Noack, Mark Nodine, Andreas Olofsson, Brad Parker, Dominic
Plunkett, Niranjan Prabhu, Usha Priyadharshini, Oleg Rodionov, John
Sanguinetti, Salman Sheikh, Mike Shinkarovsky, Rafael Shirakawa, Jeffrey
Short, Rodney Sinclair, Brian Small, Alex Solomatnikov, Art Stamness, John
Stroebel, Emerson Suguimoto, Gene Sullivan, Renga Sundararajan, Stefan
Thiede, Gary Thomas, Steve Tong, Holger Waechtler, Stefan Wallentowitz,
Shawn Wang, Greg Waters, Eugene Weber, David Welch, Leon Wildman, Gerald
Williams, Trevor Williams, Jeff Winston, Joshua Wise, Johan Wouters, and
Ding Xiaoliang.
Thanks all.
+1 -1
View File
@@ -1633,6 +1633,6 @@ static inline WDataOutP VL_CONST_W_9X(int obits, WDataOutP o,
#undef _END
// Debugging
//======================================================================
#endif /*_VERILATED_H_*/
+1
View File
@@ -25,6 +25,7 @@
#define _VERILATED_DPI_CPP_
#include "verilatedos.h"
#include "verilated_dpi.h"
#include "verilated_imp.h"
// On MSVC++ we need svdpi.h to declare exports, not imports
+64
View File
@@ -0,0 +1,64 @@
// -*- C++ -*-
//*************************************************************************
//
// Copyright 2003-2011 by Wilson Snyder. This program is free software; you can
// redistribute it and/or modify it under the terms of either the GNU
// Lesser General Public License Version 3 or the Perl Artistic License.
// Version 2.0.
//
// Verilator is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
//*************************************************************************
///
/// \file
/// \brief Verilator: Common include for all Verilated C files that use DPI
///
/// This file is included automatically by Verilator at the top of
/// all C++ files it generates where DPI is used. It contains
/// DPI interface functions required by the Verilated code.
///
/// Code available from: http://www.veripool.org/verilator
///
//*************************************************************************
#ifndef _VERILATED_DPI_H_
#define _VERILATED_DPI_H_ 1 ///< Header Guard
#include "verilated.h" // Presumed done by caller
#include "svdpi.h"
//===================================================================
// SETTING OPERATORS
/// Return svBitVecVal from WData
static inline void VL_SET_W_SVBV(int obits, WDataOutP owp, svBitVecVal* lwp) {
int words = VL_WORDS_I(obits);
for (int i=0; i<words-1; i++) owp[i]=lwp[i];
owp[words-1] = lwp[words-1] & VL_MASK_I(obits);
}
static inline void VL_SET_SVBV_W(int obits, svBitVecVal* owp, WDataInP lwp) {
int words = VL_WORDS_I(obits);
for (int i=0; i<words-1; i++) owp[i]=lwp[i];
owp[words-1] = lwp[words-1] & VL_MASK_I(obits);
}
static inline void VL_SET_W_SVLV(int obits, WDataOutP owp, svLogicVecVal* lwp) {
// Note we ignore X/Z in svLogicVecVal
int words = VL_WORDS_I(obits);
for (int i=0; i<words-1; i++) owp[i]=lwp[i].aval;
owp[words-1] = lwp[words-1].aval & VL_MASK_I(obits);
}
static inline void VL_SET_SVLV_W(int obits, svLogicVecVal* owp, WDataInP lwp) {
// Note we don't create X/Z in svLogicVecVal
int words = VL_WORDS_I(obits);
for (int i=0; i<words; i++) owp[i].bval=0;
for (int i=0; i<words-1; i++) owp[i].aval=lwp[i];
owp[words-1].aval = lwp[words-1] & VL_MASK_I(obits);
}
//======================================================================
#endif // _VERILATED_DPI_H_
+1 -13
View File
@@ -8,21 +8,9 @@ use strict;
#======================================================================
# main
delete $ENV{MODULE_VERSION};
_setup_modules();
module('add','axiom-athdl');
eval `modulecmd perl add axiom-athdl`;
exec('atsim',@ARGV);
#######################################################################
# Modules package
sub _setup_modules {
# Load the 'module' command into the environment
my $init = "$ENV{MODULESHOME}/init/perl";
(-f $init) or die "%Error: Script not found: $init,";
require $init;
}
#######################################################################
__END__
+1 -13
View File
@@ -8,21 +8,9 @@ use strict;
#======================================================================
# main
delete $ENV{MODULE_VERSION};
_setup_modules();
module('add','cadence-ius');
eval `modulecmd perl add cds-ius`;
exec('iccr',@ARGV);
#######################################################################
# Modules package
sub _setup_modules {
# Load the 'module' command into the environment
my $init = "$ENV{MODULESHOME}/init/perl";
(-f $init) or die "%Error: Script not found: $init,";
require $init;
}
#######################################################################
__END__
+1 -13
View File
@@ -8,21 +8,9 @@ use strict;
#======================================================================
# main
delete $ENV{MODULE_VERSION};
_setup_modules();
module('add','cadence-ius');
eval `modulecmd perl add cds-ius`;
exec('ncverilog',@ARGV);
#######################################################################
# Modules package
sub _setup_modules {
# Load the 'module' command into the environment
my $init = "$ENV{MODULESHOME}/init/perl";
(-f $init) or die "%Error: Script not found: $init,";
require $init;
}
#######################################################################
__END__
+1 -13
View File
@@ -8,21 +8,9 @@ use strict;
#======================================================================
# main
delete $ENV{MODULE_VERSION};
_setup_modules();
module('add','synopsys-vcs');
eval `modulecmd perl add synopsys-vcs`;
exec('vcs',@ARGV);
#######################################################################
# Modules package
sub _setup_modules {
# Load the 'module' command into the environment
my $init = "$ENV{MODULESHOME}/init/perl";
(-f $init) or die "%Error: Script not found: $init,";
require $init;
}
#######################################################################
__END__
+1
View File
@@ -976,6 +976,7 @@ struct AstNodeUniop : public AstNodeMath {
setOp1p(lhsp); }
ASTNODE_BASE_FUNCS(NodeUniop)
AstNode* lhsp() const { return op1p()->castNode(); }
void lhsp(AstNode* nodep) { return setOp1p(nodep); }
// METHODS
virtual void numberOperate(V3Number& out, const V3Number& lhs) = 0; // Set out to evaluation of a AstConst'ed lhs
virtual bool cleanLhs() = 0;
+1 -2
View File
@@ -202,7 +202,6 @@ string AstVar::dpiArgType(bool named, bool forReturn) const {
if (forReturn) named=false;
string arg;
if (!basicp()) arg = "UNKNOWN";
if (isWide()) v3error("Unsupported: DPI functions with vectored outputs > 32-bits");
if (basicp()->isBitLogic()) {
if (widthMin() == 1) {
arg = "unsigned char";
@@ -522,7 +521,7 @@ void AstBasicDType::dump(ostream& str) {
str<<" ["<<keyword().ascii()<<"]";
if (implicit()) str<<" [IMPLICIT]";
}
void AstCast::dump(ostream& str) {
void AstCCast::dump(ostream& str) {
this->AstNode::dump(str);
str<<" sz"<<size();
}
+46 -8
View File
@@ -364,9 +364,10 @@ public:
struct AstEnumItemRef : public AstNodeMath {
private:
AstEnumItem* m_itemp; // [AfterLink] Pointer to item
AstPackage* m_packagep; // Package hierarchy
public:
AstEnumItemRef(FileLine* fl, AstEnumItem* itemp)
: AstNodeMath(fl), m_itemp(itemp) {
AstEnumItemRef(FileLine* fl, AstEnumItem* itemp, AstPackage* packagep)
: AstNodeMath(fl), m_itemp(itemp), m_packagep(packagep) {
if (m_itemp) widthSignedFrom(m_itemp);
}
ASTNODE_NODE_FUNCS(EnumItemRef, ENUMITEMREF)
@@ -381,6 +382,8 @@ public:
virtual string emitVerilog() { V3ERROR_NA; return ""; } // Implemented specially
virtual string emitC() { V3ERROR_NA; return ""; }
virtual bool cleanOut() { return true; }
AstPackage* packagep() const { return m_packagep; }
void packagep(AstPackage* nodep) { m_packagep=nodep; }
};
struct AstEnumDType : public AstNodeDType {
@@ -559,6 +562,8 @@ private:
bool m_attrClockEn:1;// User clock enable attribute
bool m_attrIsolateAssign:1;// User isolate_assignments attribute
bool m_attrSFormat:1;// User sformat attribute
bool m_didSigning:1; // V3Signed completed; can skip iteration
bool m_didWidth:1; // V3Width completed; can skip iteration
bool m_fileDescr:1; // File descriptor
bool m_isConst:1; // Table contains constant data
bool m_isStatic:1; // Static variable
@@ -572,6 +577,7 @@ private:
m_sigPublic=false; m_sigModPublic=false; m_sigUserRdPublic=false; m_sigUserRWPublic=false;
m_funcLocal=false; m_funcReturn=false;
m_attrClockEn=false; m_attrIsolateAssign=false; m_attrSFormat=false;
m_didSigning=false; m_didWidth=false;
m_fileDescr=false; m_isConst=false; m_isStatic=false;
m_trace=false;
}
@@ -634,6 +640,10 @@ public:
void attrScClocked(bool flag) { m_scClocked = flag; }
void attrIsolateAssign(bool flag) { m_attrIsolateAssign = flag; }
void attrSFormat(bool flag) { m_attrSFormat = flag; }
void didSigning(bool flag) { m_didSigning=flag; }
bool didSigning() const { return m_didSigning; }
void didWidth(bool flag) { m_didWidth=flag; }
bool didWidth() const { return m_didWidth; }
void usedClock(bool flag) { m_usedClock = flag; }
void usedParam(bool flag) { m_usedParam = flag; }
void usedLoopIdx(bool flag) { m_usedLoopIdx = flag; }
@@ -2615,27 +2625,42 @@ struct AstOneHot0 : public AstNodeUniop {
virtual int instrCount() const { return widthInstrs()*3; }
};
struct AstCast : public AstNodeUniop {
// Cast to appropriate data type
struct AstCast : public AstNode {
// Cast to appropriate data type - note lhsp is value, to match AstTypedef, AstCCast, etc
AstCast(FileLine* fl, AstNode* lhsp, AstNodeDType* dtypep) : AstNode(fl) {
setOp1p(lhsp); setOp2p(dtypep);
if (dtypep) { widthSignedFrom(dtypep); }
}
ASTNODE_NODE_FUNCS(Cast, CAST)
virtual string emitVerilog() { return "((%r)'(%l))"; }
virtual string emitC() { V3ERROR_NA; return ""; }
virtual bool cleanOut() { V3ERROR_NA; return true;} virtual bool cleanLhs() {return true;}
virtual bool sizeMattersLhs() {return false;}
AstNode* lhsp() const { return op1p(); }
AstNodeDType* dtypep() const { return op2p()->castNodeDType(); }
};
struct AstCCast : public AstNodeUniop {
// Cast to C-based data type
private:
int m_size;
public:
AstCast(FileLine* fl, AstNode* lhsp, int setwidth) : AstNodeUniop(fl, lhsp) {
AstCCast(FileLine* fl, AstNode* lhsp, int setwidth) : AstNodeUniop(fl, lhsp) {
m_size=setwidth;
if (setwidth) { width(setwidth,setwidth); }
}
AstCast(FileLine* fl, AstNode* lhsp, AstNode* widthFromp) : AstNodeUniop(fl, lhsp) {
AstCCast(FileLine* fl, AstNode* lhsp, AstNode* widthFromp) : AstNodeUniop(fl, lhsp) {
if (widthFromp) { widthSignedFrom(widthFromp); }
m_size=width();
}
ASTNODE_NODE_FUNCS(Cast, CAST)
ASTNODE_NODE_FUNCS(CCast, CCAST)
virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.opAssign(lhs); }
virtual string emitVerilog() { return "%f$_CAST(%l)"; }
virtual string emitC() { return "VL_CAST_%nq%lq(%nw,%lw, %P, %li)"; }
virtual bool cleanOut() {return true;} virtual bool cleanLhs() {return true;}
virtual bool sizeMattersLhs() {return false;} // Special cased in V3Cast
virtual V3Hash sameHash() const { return V3Hash(size()); }
virtual bool same(AstNode* samep) const { return size()==samep->castCast()->size(); }
virtual bool same(AstNode* samep) const { return size()==samep->castCCast()->size(); }
virtual void dump(ostream& str=cout);
//
int size() const { return m_size; }
@@ -3152,6 +3177,19 @@ struct AstReplicate : public AstNodeBiop {
virtual bool sizeMattersLhs() {return false;} virtual bool sizeMattersRhs() {return false;}
virtual int instrCount() const { return widthInstrs()*2; }
};
struct AstBufIf1 : public AstNodeBiop {
// lhs is enable, rhs is data to drive
AstBufIf1(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiop(fl, lhsp, rhsp) {
if (lhsp) widthSignedFrom(lhsp); }
ASTNODE_NODE_FUNCS(BufIf1, BUFIF1)
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opBufIf1(lhs,rhs); }
virtual string emitVerilog() { return "bufif(%r,%l)"; }
virtual string emitC() { V3ERROR_NA; return "";} // Lclean || Rclean
virtual string emitSimpleOperator() { V3ERROR_NA; return false;} // Lclean || Rclean
virtual bool cleanOut() {V3ERROR_NA; return "";} // Lclean || Rclean
virtual bool cleanLhs() {return false;} virtual bool cleanRhs() {return false;}
virtual bool sizeMattersLhs() {return false;} virtual bool sizeMattersRhs() {return false;}
};
struct AstFGetS : public AstNodeBiop {
AstFGetS(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiop(fl, lhsp, rhsp) {}
ASTNODE_NODE_FUNCS(FGetS, FGETS)
+5 -5
View File
@@ -77,7 +77,7 @@ private:
AstNRelinker relinkHandle;
nodep->unlinkFrBack(&relinkHandle);
//
AstCast* castp = new AstCast (nodep->fileline(), nodep, needsize);
AstCCast* castp = new AstCCast (nodep->fileline(), nodep, needsize);
castp->width(needsize, nodep->widthMin());
relinkHandle.relink(castp);
//if (debug()>8) castp->dumpTree(cout,"-castins: ");
@@ -97,13 +97,13 @@ private:
insertCast(nodep, castSize(nodep->backp()));
}
}
void insureLower32Cast(AstCast* nodep) {
void insureLower32Cast(AstCCast* nodep) {
// If we have uint64 = CAST(uint64(x)) then the upcasting
// really needs to be CAST(uint64(CAST(uint32(x))).
// Otherwise a (uint64)(a>b) would return wrong value, as
// less than has undeterministic signedness.
if (nodep->isQuad() && !nodep->lhsp()->isQuad()
&& !nodep->lhsp()->castCast()) {
&& !nodep->lhsp()->castCCast()) {
insertCast(nodep->lhsp(), VL_WORDSIZE);
}
}
@@ -130,7 +130,7 @@ private:
if (nodep->sizeMattersRhs()) insureCast(nodep->rhsp());
if (nodep->sizeMattersThs()) insureCast(nodep->thsp());
}
virtual void visit(AstCast* nodep, AstNUser*) {
virtual void visit(AstCCast* nodep, AstNUser*) {
nodep->iterateChildren(*this);
insureLower32Cast(nodep);
nodep->user1(1);
@@ -149,7 +149,7 @@ private:
}
virtual void visit(AstVarRef* nodep, AstNUser*) {
if (!nodep->lvalue()
&& !nodep->backp()->castCast()
&& !nodep->backp()->castCCast()
&& nodep->backp()->castNodeMath()
&& nodep->backp()->width()
&& castSize(nodep) != castSize(nodep->varp())) {
+19 -5
View File
@@ -46,6 +46,8 @@
#include "V3EmitV.h"
#include "V3File.h"
#define CDC_WEIGHT_ASYNC 0x1000 // Weight for edges that feed async logic
//######################################################################
class CdcBaseVisitor : public AstNVisitor {
@@ -314,7 +316,9 @@ private:
UINFO(3,__FUNCTION__<<": "<<endl);
//if (debug()>6) m_graph.dump();
if (debug()>6) m_graph.dumpDotFilePrefixed("cdc_pre");
m_graph.removeRedundantEdgesSum(&V3GraphEdge::followAlwaysTrue);
//
m_graph.removeRedundantEdges(&V3GraphEdge::followAlwaysTrue); // This will MAX across edge weights
//
m_graph.dumpDotFilePrefixed("cdc_simp");
//
analyzeReset();
@@ -411,12 +415,15 @@ private:
CdcEitherVertex* eToVertexp = (CdcEitherVertex*)edgep->top();
if (!eToVertexp) targetp = eToVertexp;
if (CdcLogicVertex* vvertexp = dynamic_cast<CdcLogicVertex*>(eToVertexp)) {
if (vvertexp->isFlop()) {
if (vvertexp->isFlop() // IE the target flop that is upsetting us
&& edgep->weight() >= CDC_WEIGHT_ASYNC) { // And this signal feeds an async reset line
targetp = eToVertexp;
//UINFO(9," targetasync "<<targetp->name()<<" "<<" from "<<vertexp->name()<<endl);
break;
}
} // else it might be random logic that's not relevant
}
//UINFO(9," finalflop "<<targetp->name()<<" "<<targetp->nodep()->fileline()<<endl);
warnAndFile(markp->nodep(),V3ErrorCode::CDCRSTLOGIC,"Logic in path that feeds async reset, via signal: "+nodep->prettyName());
dumpAsyncRecurse(targetp, "", " ",0);
}
@@ -618,8 +625,9 @@ private:
if (!varscp) nodep->v3fatalSrc("Var didn't get varscoped in V3Scope.cpp\n");
CdcVarVertex* varvertexp = makeVarVertex(varscp);
UINFO(5," VARREF to "<<varscp<<endl);
// We use weight of one; if we ref the var more than once, when we simplify,
// the weight will increase
// We use weight of one for normal edges,
// Weight of CDC_WEIGHT_ASYNC to indicate feeds async (for reporting)
// When simplify we'll take the MAX weight
if (nodep->lvalue()) {
new V3GraphEdge(&m_graph, m_logicVertexp, varvertexp, 1);
if (m_inDly) {
@@ -628,7 +636,13 @@ private:
varvertexp->srcDomainSet(true);
}
} else {
new V3GraphEdge(&m_graph, varvertexp, m_logicVertexp, 1);
if (varvertexp->cntAsyncRst()) {
//UINFO(9," edgeasync "<<varvertexp->name()<<" to "<<m_logicVertexp<<endl);
new V3GraphEdge(&m_graph, varvertexp, m_logicVertexp, CDC_WEIGHT_ASYNC);
} else {
//UINFO(9," edgena "<<varvertexp->name()<<" to "<<m_logicVertexp<<endl);
new V3GraphEdge(&m_graph, varvertexp, m_logicVertexp, 1);
}
}
}
}
+110 -8
View File
@@ -290,13 +290,61 @@ private:
// SEL(EXTEND(any,width,...),(width-1),0) -> ...
// Since select's return unsigned, this is always an extend
AstExtend* extendp = nodep->fromp()->castExtend();
return (m_doV
&& extendp
&& nodep->lsbp()->castConst()
&& nodep->widthp()->castConst()
&& nodep->lsbConst()==0
&& (int)nodep->widthConst()==extendp->lhsp()->width()
);
if (!(m_doV
&& extendp
&& nodep->lsbp()->castConst()
&& nodep->widthp()->castConst()
&& nodep->lsbConst()==0
&& (int)nodep->widthConst()==extendp->lhsp()->width()
)) return false;
replaceWChild(nodep, extendp->lhsp()); nodep=NULL;
return true;
}
bool operandSelBiLower(AstSel* nodep) {
// SEL(ADD(a,b),(width-1),0) -> ADD(SEL(a),SEL(b))
// Add or any operation which doesn't care if we discard top bits
AstNodeBiop* bip = nodep->fromp()->castNodeBiop();
if (!(m_doV
&& bip
&& nodep->lsbp()->castConst()
&& nodep->widthp()->castConst()
&& nodep->lsbConst()==0
)) return false;
if (debug()>=9) nodep->dumpTree(cout,"SEL(BI)-in:");
AstNode* bilhsp = bip->lhsp()->unlinkFrBack();
AstNode* birhsp = bip->rhsp()->unlinkFrBack();
bip->lhsp(new AstSel(nodep->fileline(), bilhsp, 0, nodep->widthConst()));
bip->rhsp(new AstSel(nodep->fileline(), birhsp, 0, nodep->widthConst()));
if (debug()>=9) bip->dumpTree(cout,"SEL(BI)-ou:");
replaceWChild(nodep, bip); nodep=NULL;
return true;
}
bool operandBiExtendConst(AstNodeBiop* nodep) {
// Loop unrolling likes standalone compares
// EQ(EXTEND(xx{width3}), const{width32}) -> EQ(xx{3},const{3})
// Beware that the constant must have zero bits (+ 1 if signed) or compare
// would be incorrect
AstExtend* extendp = nodep->lhsp()->castExtend();
if (!extendp) return false;
AstNode* smallerp = extendp->lhsp();
int subsize = smallerp->width();
AstConst* constp = nodep->rhsp()->castConst();
if (!constp) return false;
if (!constp->num().isBitsZero(constp->width()-1, subsize)) return false;
//
if (debug()>=9) nodep->dumpTree(cout,"BI(EXTEND)-in:");
smallerp->unlinkFrBack();
extendp->unlinkFrBack()->deleteTree(); // aka nodep->lhsp.
nodep->lhsp(smallerp);
constp->unlinkFrBack();
V3Number num (constp->fileline(), subsize);
num.opAssign(constp->num());
nodep->rhsp(new AstConst(constp->fileline(), num));
constp->deleteTree(); constp=NULL;
if (debug()>=9) nodep->dumpTree(cout,"BI(EXTEND)-ou:");
return true;
}
AstNode* afterComment(AstNode* nodep) {
@@ -1061,6 +1109,38 @@ private:
nodep->replaceWith(newp); nodep->deleteTree(); nodep=NULL;
}
void replaceSelIntoBiop(AstSel* nodep) {
// SEL(BUFIF1(a,b),1,bit) => BUFIF1(SEL(a,1,bit),SEL(b,1,bit))
AstNodeBiop* fromp = nodep->fromp()->unlinkFrBack()->castNodeBiop();
if (!fromp) nodep->v3fatalSrc("Called on non biop");
AstNode* lsbp = nodep->lsbp()->unlinkFrBack();
AstNode* widthp = nodep->widthp()->unlinkFrBack();
//
AstNode* bilhsp = fromp->lhsp()->unlinkFrBack();
AstNode* birhsp = fromp->rhsp()->unlinkFrBack();
//
fromp->lhsp(new AstSel(nodep->fileline(),
bilhsp, lsbp->cloneTree(true), widthp->cloneTree(true)));
fromp->rhsp(new AstSel(nodep->fileline(),
birhsp, lsbp, widthp));
fromp->widthSignedFrom(nodep);
nodep->replaceWith(fromp); nodep->deleteTree(); nodep=NULL;
}
void replaceSelIntoUniop(AstSel* nodep) {
// SEL(NOT(a),1,bit) => NOT(SEL(a,bit))
AstNodeUniop* fromp = nodep->fromp()->unlinkFrBack()->castNodeUniop();
if (!fromp) nodep->v3fatalSrc("Called on non biop");
AstNode* lsbp = nodep->lsbp()->unlinkFrBack();
AstNode* widthp = nodep->widthp()->unlinkFrBack();
//
AstNode* bilhsp = fromp->lhsp()->unlinkFrBack();
//
fromp->lhsp(new AstSel(nodep->fileline(),
bilhsp, lsbp->cloneTree(true), widthp->cloneTree(true)));
fromp->widthSignedFrom(nodep);
nodep->replaceWith(fromp); nodep->deleteTree(); nodep=NULL;
}
virtual void visit(AstVarRef* nodep, AstNUser*) {
nodep->iterateChildren(*this);
if (!nodep->varp()) nodep->v3fatalSrc("Not linked");
@@ -1684,6 +1764,13 @@ private:
TREEOP ("AstShiftL{operandShiftShift(nodep)}", "replaceShiftShift(nodep)");
TREEOP ("AstShiftR{operandShiftShift(nodep)}", "replaceShiftShift(nodep)");
TREEOP ("AstWordSel{operandWordOOB(nodep)}", "replaceZero(nodep)");
// Compress out EXTENDs to appease loop unroller
TREEOPV("AstEq {$lhsp.castExtend,operandBiExtendConst(nodep)}", "DONE");
TREEOPV("AstNeq {$lhsp.castExtend,operandBiExtendConst(nodep)}", "DONE");
TREEOPV("AstGt {$lhsp.castExtend,operandBiExtendConst(nodep)}", "DONE");
TREEOPV("AstGte {$lhsp.castExtend,operandBiExtendConst(nodep)}", "DONE");
TREEOPV("AstLt {$lhsp.castExtend,operandBiExtendConst(nodep)}", "DONE");
TREEOPV("AstLte {$lhsp.castExtend,operandBiExtendConst(nodep)}", "DONE");
// Identical operands on both sides
// AstLogAnd/AstLogOr already converted to AstAnd/AstOr for these rules
// AstAdd->ShiftL(#,1) but uncommon
@@ -1761,12 +1848,27 @@ private:
TREEOPV("AstReplicate{$lhsp, $rhsp.isOne, $lhsp->width()==nodep->width()}", "replaceWLhs(nodep)"); // {1{lhs}}->lhs
// Next rule because AUTOINST puts the width of bits in
// to pins, even when the widths are exactly the same across the hierarchy.
TREEOPV("AstSel{operandSelExtend(nodep)}", "replaceWChild(nodep, nodep->fromp()->castExtend()->lhsp())");
TREEOPV("AstSel{operandSelExtend(nodep)}", "DONE");
TREEOPV("AstSel{operandSelFull(nodep)}", "replaceWChild(nodep, nodep->fromp())");
TREEOPV("AstSel{$fromp.castSel}", "replaceSelSel(nodep)");
TREEOPV("AstSel{$fromp.castAdd, operandSelBiLower(nodep)}", "DONE");
TREEOPV("AstSel{$fromp.castAnd, operandSelBiLower(nodep)}", "DONE");
TREEOPV("AstSel{$fromp.castOr, operandSelBiLower(nodep)}", "DONE");
TREEOPV("AstSel{$fromp.castSub, operandSelBiLower(nodep)}", "DONE");
TREEOPV("AstSel{$fromp.castXnor,operandSelBiLower(nodep)}", "DONE");
TREEOPV("AstSel{$fromp.castXor, operandSelBiLower(nodep)}", "DONE");
TREEOPC("AstSel{$fromp.castConst, $lsbp.castConst, $widthp.castConst, }", "replaceConst(nodep)");
TREEOPV("AstSel{$fromp.castConcat, $lsbp.castConst, $widthp.castConst, }", "replaceSelConcat(nodep)");
TREEOPV("AstSel{$fromp.castReplicate, $lsbp.castConst, $widthp.isOne, }", "replaceSelReplicate(nodep)");
// V3Tristate requires selects below BufIf1.
// Also do additional operators that are bit-independent, but only definite
// win if bit select is a constant (otherwise we may need to compute bit index several times)
TREEOPV("AstSel{$fromp.castBufIf1}", "replaceSelIntoBiop(nodep)");
TREEOPV("AstSel{$fromp.castNot}", "replaceSelIntoUniop(nodep)");
TREEOPV("AstSel{$fromp.castAnd,$lhsp.castConst}", "replaceSelIntoUniop(nodep)");
TREEOPV("AstSel{$fromp.castOr,$lhsp.castConst}", "replaceSelIntoUniop(nodep)");
TREEOPV("AstSel{$fromp.castXor,$lhsp.castConst}", "replaceSelIntoUniop(nodep)");
TREEOPV("AstSel{$fromp.castXnor,$lhsp.castConst}", "replaceSelIntoUniop(nodep)");
// Conversions
TREEOPV("AstRedXnor{$lhsp}", "AstNot{AstRedXor{$lhsp}}"); // Just eliminate XNOR's
TREEOPV("AstLogIf {$lhsp, $rhsp}", "AstLogOr{AstLogNot{$lhsp},$rhsp}");
+6
View File
@@ -122,6 +122,12 @@ private:
nodep->packagep()->user1Inc();
}
}
virtual void visit(AstEnumItemRef* nodep, AstNUser*) {
nodep->iterateChildren(*this);
if (nodep->packagep()) {
nodep->packagep()->user1Inc();
}
}
virtual void visit(AstVarScope* nodep, AstNUser*) {
nodep->iterateChildren(*this);
m_vscsp.push_back(nodep);
+11 -3
View File
@@ -127,6 +127,7 @@ public:
nodep->lhsp()->iterateAndNext(*this); puts(", ");
} else if (nodep->isWide()
&& nodep->lhsp()->castVarRef()
&& !nodep->rhsp()->castCMath()
&& !nodep->rhsp()->castVarRef()
&& !nodep->rhsp()->castArraySel()) {
// Wide functions assign into the array directly, don't need separate assign statement
@@ -475,7 +476,7 @@ public:
}
visit(nodep->castNodeBiop(), vup);
}
virtual void visit(AstCast* nodep, AstNUser*) {
virtual void visit(AstCCast* nodep, AstNUser*) {
// Extending a value of the same word width is just a NOP.
if (nodep->size()>VL_WORDSIZE) {
puts("(QData)(");
@@ -1619,7 +1620,12 @@ void EmitCImp::emitInt(AstNodeModule* modp) {
if (v3Global.needHInlines()) { // Set by V3EmitCInlines; should have been called before us
puts("#include \""+topClassName()+"__Inlines.h\"\n");
}
// No __Dpi.h needed, we've shimmed it all into the interface
if (v3Global.dpi()) {
// do this before including our main .h file so that any references to
// types defined in svdpi.h are available
puts("#include \""+ topClassName() +"__Dpi.h\"\n");
puts("\n");
}
// Declare foreign instances up front to make C++ happy
puts("class "+symClassName()+";\n");
@@ -1797,8 +1803,10 @@ void EmitCImp::emitImp(AstNodeModule* modp) {
// Us
puts("#include \""+ symClassName() +".h\"\n");
if (v3Global.dpi()) {
puts("#include \""+ topClassName() +"__Dpi.h\"\n");
puts("\n");
puts("#include \"verilated_dpi.h\"\n");
}
if (optSystemPerl() && (splitFilenum() || !m_fast)) {
+2
View File
@@ -519,6 +519,8 @@ void EmitCSyms::emitDpiHdr() {
puts("// Manually include this file where DPI .c import functions are declared to insure\n");
puts("// the C functions match the expectations of the DPI imports.\n");
puts("\n");
puts("#include \"svdpi.h\"\n");
puts("\n");
puts("#ifdef __cplusplus\n");
puts("extern \"C\" {\n");
puts("#endif\n");
+1 -1
View File
@@ -309,7 +309,7 @@ void V3Error::abortIfErrors() {
}
void V3Error::abortIfWarnings() {
if (errorOrWarnCount()) {
if (v3Global.opt.warnFatal() ? errorOrWarnCount() : errorCount()) {
v3fatal ("Exiting due to "<<dec<<errorOrWarnCount()<<" warning(s)\n");
}
}
+20 -20
View File
@@ -127,18 +127,18 @@ private:
} else if (nodep->isQuad() && word==0) {
AstNode* quadfromp = nodep->cloneTree(true);
quadfromp->width(VL_QUADSIZE,quadfromp->widthMin());
return new AstCast (nodep->fileline(),
quadfromp,
VL_WORDSIZE);
return new AstCCast (nodep->fileline(),
quadfromp,
VL_WORDSIZE);
} else if (nodep->isQuad() && word==1) {
AstNode* quadfromp = nodep->cloneTree(true);
quadfromp->width(VL_QUADSIZE,quadfromp->widthMin());
return new AstCast (nodep->fileline(),
new AstShiftR (nodep->fileline(),
quadfromp,
new AstConst (nodep->fileline(), VL_WORDSIZE),
VL_WORDSIZE),
VL_WORDSIZE);
return new AstCCast (nodep->fileline(),
new AstShiftR (nodep->fileline(),
quadfromp,
new AstConst (nodep->fileline(), VL_WORDSIZE),
VL_WORDSIZE),
VL_WORDSIZE);
} else if (!nodep->isWide() && !nodep->isQuad() && word==0) {
return nodep->cloneTree(true);
} else { // Out of bounds
@@ -324,7 +324,7 @@ private:
nodep->v3fatalSrc("extending larger thing into smaller?");
} else {
UINFO(8," EXTEND(q<-l) "<<nodep<<endl);
newp = new AstCast (nodep->fileline(), lhsp, nodep);
newp = new AstCCast (nodep->fileline(), lhsp, nodep);
}
} else { // Long
if (lhsp->isQuad() || lhsp->isWide()) {
@@ -366,7 +366,7 @@ private:
AstNode* lowwordp = new AstWordSel (nodep->fromp()->fileline(),
nodep->fromp()->cloneTree(true),
newSelBitWord(nodep->lsbp(), 0));
if (nodep->isQuad() && !lowwordp->isQuad()) lowwordp = new AstCast(nodep->fileline(), lowwordp, nodep);
if (nodep->isQuad() && !lowwordp->isQuad()) lowwordp = new AstCCast(nodep->fileline(), lowwordp, nodep);
AstNode* lowp = new AstShiftR (nodep->fileline(),
lowwordp,
newSelBitBit(nodep->lsbp()),
@@ -379,7 +379,7 @@ private:
new AstWordSel (nodep->fromp()->fileline(),
nodep->fromp()->cloneTree(true),
newSelBitWord(nodep->lsbp(), 1));
if (nodep->isQuad() && !midwordp->isQuad()) midwordp = new AstCast(nodep->fileline(), midwordp, nodep);
if (nodep->isQuad() && !midwordp->isQuad()) midwordp = new AstCCast(nodep->fileline(), midwordp, nodep);
// If we're selecting bit zero, then all 32 bits in word 1 get shifted << by 32 bits
// else we need to form the lower word, so we << by 31 or less
// nbitsfromlow <= (lsb==0) ? 64-bitbit(lsb) : 32-bitbit(lsb)
@@ -417,7 +417,7 @@ private:
new AstWordSel (nodep->fromp()->fileline(),
nodep->fromp()->cloneTree(true),
newSelBitWord(nodep->lsbp(), 2));
if (nodep->isQuad() && !hiwordp->isQuad()) hiwordp = new AstCast(nodep->fileline(), hiwordp, nodep);
if (nodep->isQuad() && !hiwordp->isQuad()) hiwordp = new AstCCast(nodep->fileline(), hiwordp, nodep);
AstNode* himayp =
new AstShiftL (nodep->fileline(),
hiwordp,
@@ -445,14 +445,14 @@ private:
UINFO(8," SEL->SHIFT "<<nodep<<endl);
AstNode* fromp = nodep->fromp()->unlinkFrBack();
AstNode* lsbp = nodep->lsbp()->unlinkFrBack();
if (nodep->isQuad() && !fromp->isQuad()) fromp = new AstCast(nodep->fileline(), fromp, nodep);
if (nodep->isQuad() && !fromp->isQuad()) fromp = new AstCCast(nodep->fileline(), fromp, nodep);
AstNode* newp = new AstShiftR (nodep->fileline(),
fromp,
dropCondBound(lsbp),
nodep->width());
newp->widthSignedFrom(nodep);
if (!nodep->isQuad() && fromp->isQuad()) {
newp = new AstCast (newp->fileline(), newp, nodep);
newp = new AstCCast (newp->fileline(), newp, nodep);
}
newp->widthSignedFrom(nodep);
replaceWithDelete(nodep,newp); nodep=NULL;
@@ -546,7 +546,7 @@ private:
destp->deleteTree(); destp=NULL;
} else {
UINFO(8," ASSIGNSEL(const,narrow) "<<nodep<<endl);
if (destp->isQuad() && !rhsp->isQuad()) rhsp = new AstCast(nodep->fileline(), rhsp, nodep);
if (destp->isQuad() && !rhsp->isQuad()) rhsp = new AstCCast(nodep->fileline(), rhsp, nodep);
AstNode* oldvalp = destp->cloneTree(true);
fixCloneLvalue(oldvalp);
if (!ones) oldvalp = new AstAnd (lhsp->fileline(),
@@ -620,7 +620,7 @@ private:
V3Number maskwidth (nodep->fileline(), destp->widthMin());
for (int bit=0; bit<(int)lhsp->widthConst(); bit++) maskwidth.setBit(bit,1);
if (destp->isQuad() && !rhsp->isQuad()) rhsp = new AstCast(nodep->fileline(), rhsp, nodep);
if (destp->isQuad() && !rhsp->isQuad()) rhsp = new AstCCast(nodep->fileline(), rhsp, nodep);
if (!ones)
oldvalp = new AstAnd (lhsp->fileline(),
new AstNot (lhsp->fileline(),
@@ -655,8 +655,8 @@ private:
AstNode* lhsp = nodep->lhsp()->unlinkFrBack();
AstNode* rhsp = nodep->rhsp()->unlinkFrBack();
int rhsshift = rhsp->widthMin();
if (nodep->isQuad() && !lhsp->isQuad()) lhsp = new AstCast(nodep->fileline(), lhsp, nodep);
if (nodep->isQuad() && !rhsp->isQuad()) rhsp = new AstCast(nodep->fileline(), rhsp, nodep);
if (nodep->isQuad() && !lhsp->isQuad()) lhsp = new AstCCast(nodep->fileline(), lhsp, nodep);
if (nodep->isQuad() && !rhsp->isQuad()) rhsp = new AstCCast(nodep->fileline(), rhsp, nodep);
AstNode* newp = new AstOr (nodep->fileline(),
new AstShiftL (nodep->fileline(),
lhsp,
@@ -703,7 +703,7 @@ private:
AstConst* constp = nodep->rhsp()->castConst();
if (!constp) nodep->v3fatalSrc("Replication value isn't a constant. Checked earlier!");
uint32_t times = constp->toUInt();
if (nodep->isQuad() && !lhsp->isQuad()) lhsp = new AstCast(nodep->fileline(), lhsp, nodep);
if (nodep->isQuad() && !lhsp->isQuad()) lhsp = new AstCCast(nodep->fileline(), lhsp, nodep);
newp = lhsp->cloneTree(true);
for (unsigned repnum=1; repnum<times; repnum++) {
int rhsshift = repnum*lhswidth;
+1 -1
View File
@@ -184,7 +184,7 @@ private:
// user2p is either a const or a var.
AstConst* exprconstp = nodep->user2p()->castNode()->castConst();
AstVarRef* exprvarrefp = nodep->user2p()->castNode()->castVarRef();
UINFO(1,"connectto: "<<nodep->user2p()->castNode()<<endl);
UINFO(8,"connectto: "<<nodep->user2p()->castNode()<<endl);
if (!exprconstp && !exprvarrefp) {
nodep->v3fatalSrc("Unknown interconnect type; pinReconnectSimple should have cleared up\n");
}
+1 -1
View File
@@ -134,7 +134,7 @@ private:
nodep->packagep(packageFor(varp));
}
else if (AstEnumItem* valuep = foundp->castEnumItem()) {
AstNode* newp = new AstEnumItemRef(nodep->fileline(), valuep);
AstNode* newp = new AstEnumItemRef(nodep->fileline(), valuep, packageFor(valuep));
nodep->replaceWith(newp);
nodep->deleteTree(); nodep=NULL;
return true; // Edited
+49 -1
View File
@@ -555,6 +555,12 @@ bool V3Number::isNeqZero() const {
}
return false;
}
bool V3Number::isBitsZero(int msb, int lsb) const {
for (int i=lsb; i<=msb; i++) {
if (VL_UNLIKELY(!bitIs0(i))) return false;
}
return true;
}
bool V3Number::isEqOne() const {
if (m_value[0]!=1 || m_valueX[0]) return false;
for (int i=1; i<words(); i++) {
@@ -1005,6 +1011,30 @@ V3Number& V3Number::opLteS (const V3Number& lhs, const V3Number& rhs) {
return opGteS(rhs,lhs);
}
V3Number& V3Number::opRotR (const V3Number& lhs, const V3Number& rhs) {
// L(lhs) bit return
if (rhs.isFourState()) return setAllBitsX();
setZero();
uint32_t rhsval = rhs.toUInt();
for (int bit=0; bit<this->width(); bit++) {
setBit(bit,lhs.bitIs((bit + rhsval) % this->width()));
}
return *this;
}
V3Number& V3Number::opRotL (const V3Number& lhs, const V3Number& rhs) {
// L(lhs) bit return
if (rhs.isFourState()) return setAllBitsX();
setZero();
uint32_t rhsval = rhs.toUInt();
for (int bit=0; bit<this->width(); bit++) {
if (bit >= (int)rhsval) {
setBit(bit,lhs.bitIs((bit - rhsval) % this->width()));
}
}
return *this;
}
V3Number& V3Number::opShiftR (const V3Number& lhs, const V3Number& rhs) {
// L(lhs) bit return
if (rhs.isFourState()) return setAllBitsX();
@@ -1032,8 +1062,8 @@ V3Number& V3Number::opShiftRS (const V3Number& lhs, const V3Number& rhs) {
V3Number& V3Number::opShiftL (const V3Number& lhs, const V3Number& rhs) {
// L(lhs) bit return
if (rhs.isFourState()) return setAllBitsX();
uint32_t rhsval = rhs.toUInt();
setZero();
uint32_t rhsval = rhs.toUInt();
for (int bit=0; bit<this->width(); bit++) {
if (bit >= (int)rhsval) {
setBit(bit,lhs.bitIs(bit - rhsval));
@@ -1045,6 +1075,15 @@ V3Number& V3Number::opShiftL (const V3Number& lhs, const V3Number& rhs) {
//======================================================================
// Ops - Arithmetic
V3Number& V3Number::opAbsS (const V3Number& lhs) {
// op i, L(lhs) bit return
if (lhs.isFourState()) return setAllBitsX();
if (lhs.isNegative()) {
return opUnaryMin(lhs);
} else {
return opAssign(lhs);
}
}
V3Number& V3Number::opUnaryMin (const V3Number& lhs) {
// op i, L(lhs) bit return
if (lhs.isFourState()) return setAllBitsX();
@@ -1318,6 +1357,15 @@ V3Number& V3Number::opPowS (const V3Number& lhs, const V3Number& rhs) {
return setAllBitsX();
}
V3Number& V3Number::opBufIf1 (const V3Number& ens, const V3Number& if1s) {
setZero();
for(int bit=0; bit<this->width(); bit++) {
if (ens.bitIs1(bit)) { setBit(bit, if1s.bitIs(bit)); }
else setBit(bit,'z');
}
return *this;
}
V3Number& V3Number::opAssign (const V3Number& lhs) {
// Note may be a width change during the assign
setZero();
+5
View File
@@ -138,6 +138,7 @@ public:
bool isAllZ() const { for(int i=0;i<width();i++) { if(!bitIsZ(i)){return false;} } return true; }
bool isEqZero() const;
bool isNeqZero() const;
bool isBitsZero(int msb, int lsb) const;
bool isEqOne() const;
bool isEqAllOnes(int optwidth=0) const;
bool isCaseEq(const V3Number& rhsp) const; // operator==
@@ -195,11 +196,13 @@ public:
V3Number& opCaseNeq (const V3Number& lhs, const V3Number& rhs);
V3Number& opWildEq (const V3Number& lhs, const V3Number& rhs);
V3Number& opWildNeq (const V3Number& lhs, const V3Number& rhs);
V3Number& opBufIf1 (const V3Number& lhs, const V3Number& rhs);
// "standard" math
V3Number& opNot (const V3Number& lhs);
V3Number& opLogNot (const V3Number& lhs);
V3Number& opLogAnd (const V3Number& lhs, const V3Number& rhs);
V3Number& opLogOr (const V3Number& lhs, const V3Number& rhs);
V3Number& opAbsS (const V3Number& lhs);
V3Number& opUnaryMin(const V3Number& lhs);
V3Number& opAdd (const V3Number& lhs, const V3Number& rhs);
V3Number& opSub (const V3Number& lhs, const V3Number& rhs);
@@ -216,6 +219,8 @@ public:
V3Number& opXor (const V3Number& lhs, const V3Number& rhs);
V3Number& opXnor (const V3Number& lhs, const V3Number& rhs);
V3Number& opOr (const V3Number& lhs, const V3Number& rhs);
V3Number& opRotR (const V3Number& lhs, const V3Number& rhs);
V3Number& opRotL (const V3Number& lhs, const V3Number& rhs);
V3Number& opShiftR (const V3Number& lhs, const V3Number& rhs);
V3Number& opShiftRS (const V3Number& lhs, const V3Number& rhs); // Arithmetic w/carry
V3Number& opShiftL (const V3Number& lhs, const V3Number& rhs);
+35 -4
View File
@@ -194,18 +194,33 @@ string V3Options::filenameNonExt (const string& filename) {
string V3Options::filenameSubstitute (const string& filename) {
string out;
enum { NONE, PAREN, CURLY } brackets = NONE;
for (string::size_type pos = 0; pos < filename.length(); ++pos) {
if (filename[pos] == '$') {
if ((filename[pos] == '$') && (pos+1 < filename.length())) {
switch (filename[pos+1]) {
case '{': brackets = CURLY; break;
case '(': brackets = PAREN; break;
default: brackets = NONE; break;
}
if (brackets != NONE) pos = pos+1;
string::size_type endpos = pos+1;
while ((endpos+1) < filename.length()
&& (isalnum(filename[endpos+1]) || filename[endpos+1]=='_'))
while (((endpos+1) < filename.length()) &&
(((brackets==NONE) && (isalnum(filename[endpos+1]) || filename[endpos+1]=='_')) ||
((brackets==CURLY) && (filename[endpos+1]!='}')) ||
((brackets==PAREN) && (filename[endpos+1]!=')'))))
++endpos;
// Catch bracket errors
if (((brackets==CURLY) && (filename[endpos+1]!='}')) ||
((brackets==PAREN) && (filename[endpos+1]!=')'))) {
v3fatal("Unmatched brackets in variable substitution in file: "+filename);
}
string envvar = filename.substr(pos+1,endpos-pos);
const char* envvalue = NULL;
if (envvar != "") envvalue = getenv(envvar.c_str());
if (envvalue) {
out += envvalue;
pos = endpos;
if (brackets==NONE) pos = endpos;
else pos = endpos+1;
} else {
out += filename[pos]; // *pos == '$'
}
@@ -214,6 +229,7 @@ string V3Options::filenameSubstitute (const string& filename) {
}
}
return out;
}
bool V3Options::filenameIsRel(const string& filename) {
@@ -756,6 +772,14 @@ void V3Options::parseOptsList(FileLine* fl, const string& optdir, int argc, char
shift;
m_traceDepth = atoi(argv[i]);
}
else if ( !strcmp (sw, "-trace-max-array") && (i+1)<argc ) {
shift;
m_traceMaxArray = atoi(argv[i]);
}
else if ( !strcmp (sw, "-trace-max-width") && (i+1)<argc ) {
shift;
m_traceMaxWidth = atoi(argv[i]);
}
else if ( !strncmp (sw, "-U", 2)) {
V3PreShell::undef (string (sw+strlen("-U")));
}
@@ -807,6 +831,9 @@ void V3Options::parseOptsList(FileLine* fl, const string& optdir, int argc, char
else if (!strcmp (sw, "-Wno-style")) {
FileLine::globalWarnStyleOff(true);
}
else if (!strcmp (sw, "-Wno-fatal")) {
m_warnFatal = false;
}
else {
string msg = sw+strlen("-Wno-");
if (!(FileLine::globalWarnOff(msg, true))) {
@@ -1056,6 +1083,7 @@ V3Options::V3Options() {
m_makeDepend = true;
m_makePhony = false;
m_outFormatOk = false;
m_warnFatal = true;
m_pinsBv = 65;
m_profileCFuncs = false;
m_preprocOnly = false;
@@ -1077,6 +1105,8 @@ V3Options::V3Options() {
m_outputSplitCFuncs = 0;
m_outputSplitCTrace = 0;
m_traceDepth = 0;
m_traceMaxArray = 32;
m_traceMaxWidth = 256;
m_unrollCount = 64;
m_unrollStmts = 30000;
@@ -1095,6 +1125,7 @@ V3Options::V3Options() {
// Default +libext+
addLibExt(""); // So include "filename.v" will find the same file
addLibExt(".v");
addLibExt(".sv");
// Default -I
addIncDir("."); // Looks better than {long_cwd_path}/...
}
+6
View File
@@ -113,6 +113,7 @@ class V3Options {
bool m_l2Name; // main switch: --l2name
bool m_lintOnly; // main switch: --lint-only
bool m_outFormatOk; // main switch: --cc, --sc or --sp was specified
bool m_warnFatal; // main switch: --warnFatal
bool m_pinsUint8; // main switch: --pins-uint8
bool m_profileCFuncs;// main switch: --profile-cfuncs
bool m_psl; // main switch: --psl
@@ -134,6 +135,8 @@ class V3Options {
int m_outputSplitCTrace;// main switch: --output-split-ctrace
int m_pinsBv; // main switch: --pins-bv
int m_traceDepth; // main switch: --trace-depth
int m_traceMaxArray;// main switch: --trace-max-array
int m_traceMaxWidth;// main switch: --trace-max-width
int m_unrollCount; // main switch: --unroll-count
int m_unrollStmts; // main switch: --unroll-stmts
@@ -238,6 +241,7 @@ class V3Options {
bool traceUnderscore() const { return m_traceUnderscore; }
bool outFormatOk() const { return m_outFormatOk; }
bool keepTempFiles() const { return (V3Error::debugDefault()!=0); }
bool warnFatal() const { return m_warnFatal; }
bool pinsUint8() const { return m_pinsUint8; }
bool profileCFuncs() const { return m_profileCFuncs; }
bool psl() const { return m_psl; }
@@ -255,6 +259,8 @@ class V3Options {
int outputSplitCTrace() const { return m_outputSplitCTrace; }
int pinsBv() const { return m_pinsBv; }
int traceDepth() const { return m_traceDepth; }
int traceMaxArray() const { return m_traceMaxArray; }
int traceMaxWidth() const { return m_traceMaxWidth; }
int unrollCount() const { return m_unrollCount; }
int unrollStmts() const { return m_unrollStmts; }
+9
View File
@@ -98,6 +98,7 @@ private:
virtual void visit(AstLogOr* nodep, AstNUser*) { signed_Ou_Ix(nodep); }
virtual void visit(AstLogIf* nodep, AstNUser*) { signed_Ou_Ix(nodep); }
virtual void visit(AstLogIff* nodep, AstNUser*) { signed_Ou_Ix(nodep); }
virtual void visit(AstBufIf1* nodep, AstNUser*) { signed_Ou_Ix(nodep); }
// ... These shouldn't matter, just make unsigned
virtual void visit(AstScopeName* nodep, AstNUser*) { signed_Ou_Ix(nodep); }
virtual void visit(AstText* nodep, AstNUser*) { signed_Ou_Ix(nodep); }
@@ -148,6 +149,9 @@ private:
// Inherit from others
virtual void visit(AstVar* nodep, AstNUser*) {
// Avoid recursion; can't use user() as they're all full, and anyhow this is often called
if (nodep->didSigning()) return;
nodep->didSigning(true);
nodep->iterateChildren(*this);
nodep->signedFrom(nodep->dtypep());
}
@@ -159,6 +163,11 @@ private:
nodep->itemp()->iterate(*this);
nodep->signedFrom(nodep->itemp());
}
virtual void visit(AstCast* nodep, AstNUser*) {
nodep->lhsp()->iterate(*this);
nodep->dtypep()->iterate(*this);
nodep->signedFrom(nodep->dtypep());
}
virtual void visit(AstConst* nodep, AstNUser*) {
// The node got setup with the signed state of the node.
// However a later operation may have changed the node->signed w/o changing
+8 -4
View File
@@ -53,6 +53,7 @@ class SliceCloneVisitor : public AstNVisitor {
// Inputs:
// AstArraySel::user1p() -> AstVarRef. The VarRef that the final ArraySel points to
// AstNodeAssign::user2() -> int. The number of clones needed for this assign
// AstArraySel::user3() -> bool. Error detected
// ENUMS
enum RedOp { // The type of unary operation to be expanded
@@ -221,6 +222,7 @@ class SliceVisitor : public AstNVisitor {
// AstNode::user2() -> int. The number of clones needed for this node
AstUser1InUse m_inuser1;
AstUser2InUse m_inuser2;
AstUser3InUse m_inuser3;
// TYPEDEFS
typedef pair<uint32_t, uint32_t> ArrayDimensions; // Array Dimensions (packed, unpacked)
@@ -328,11 +330,11 @@ class SliceVisitor : public AstNVisitor {
m_assignp->v3error("Unsupported: Assignment between a constant and an array slice");
m_assignError = true;
}
nodep->iterateChildren(*this);
}
virtual void visit(AstArraySel* nodep, AstNUser*) {
if (!m_assignp) return;
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();
@@ -340,16 +342,18 @@ class SliceVisitor : public AstNVisitor {
if (implicit > 0) {
AstArraySel* newp = insertImplicit(nodep->cloneTree(false), dim+1, implicit);
nodep->replaceWith(newp); nodep = newp;
nodep->user3(true);
}
int clones = countClones(nodep);
if (m_assignp->user2() > 0 && m_assignp->user2() != clones) {
m_assignp->v3error("Slices of arrays in assignments must have the same unpacked dimensions");
} else if (m_assignp->user2() == 0 && !m_assignError) {
if (m_extend && clones > 1) {
} else if (!m_assignp->user2()) {
if (m_extend && clones > 1 && !m_assignError) {
m_assignp->v3error("Unsupported: Assignment between packed arrays of different dimensions");
m_assignError = true;
}
if (clones > 1 && !refp->lvalue() && refp->varp() == m_lhsVarRefp->varp() && !m_assignp->castAssignDly()) {
if (clones > 1 && !refp->lvalue() && refp->varp() == m_lhsVarRefp->varp()
&& !m_assignp->castAssignDly() && !m_assignError) {
// LHS Var != RHS Var for a non-delayed assignment
m_assignp->v3error("Unsupported: Slices in a non-delayed assignment with the same Var on both sides");
m_assignError = true;
+1 -1
View File
@@ -304,7 +304,7 @@ private:
if (debug()>5) nodep->dumpTree(cout," substw_old: ");
AstNode* newp = substp->cloneTree(true);
if (!nodep->isQuad() && newp->isQuad()) {
newp = new AstCast (newp->fileline(), newp, nodep);
newp = new AstCCast (newp->fileline(), newp, nodep);
}
if (debug()>5) newp->dumpTree(cout," w_new: ");
nodep->replaceWith(newp);
+12 -5
View File
@@ -587,8 +587,12 @@ private:
// Someday we'll have better type support, and this can make variables and casts.
// But for now, we'll just text-bash it.
if (bitvec) {
// We only support quads, so don't need to sweat longer stuff
stmt += "VL_SET_WQ("+portp->name()+toSuffix+", "+portp->name()+frSuffix+")";
if (portp->isWide()) {
stmt += ("VL_SET_SVBV_W("+cvtToStr(portp->width())
+", "+portp->name()+toSuffix+", "+portp->name()+frSuffix+")");
} else {
stmt += "VL_SET_WQ("+portp->name()+toSuffix+", "+portp->name()+frSuffix+")";
}
} else {
if (isPtr) stmt += "*"; // DPI outputs are pointers
stmt += portp->name()+toSuffix+" = ";
@@ -605,7 +609,7 @@ private:
return new AstCStmt(portp->fileline(), stmt);
}
AstNode* createAssignDpiToInternal(AstVarScope* portvscp, const string& frName) {
AstNode* createAssignDpiToInternal(AstVarScope* portvscp, const string& frName, bool cvt) {
// Create assignment from DPI temporary into internal format
AstVar* portp = portvscp->varp();
string stmt;
@@ -614,6 +618,9 @@ private:
stmt += "VL_CVT_VP_Q(";
ket += ")";
}
if (!cvt
&& portp->basicp() && portp->basicp()->isBitLogic() && portp->widthMin() != 1 && !portp->isWide())
stmt += "*"; // it's a svBitVecVal, which other code won't think is arrayed (as WData aren't), but really is
stmt += frName;
stmt += ket;
// Use a AstCMath, as we want V3Clean to mask off bits that don't make sense.
@@ -680,7 +687,7 @@ private:
argnodesp = argnodesp->addNextNull(refp);
if (portp->isInput()) {
dpip->addStmtsp(createAssignDpiToInternal(outvscp, portp->name()));
dpip->addStmtsp(createAssignDpiToInternal(outvscp, portp->name(), false));
}
}
}
@@ -795,7 +802,7 @@ private:
if (AstVar* portp = stmtp->castVar()) {
if (portp->isIO() && (portp->isOutput() || portp->isFuncReturn())) {
AstVarScope* portvscp = portp->user2p()->castNode()->castVarScope(); // Remembered when we created it earlier
cfuncp->addStmtsp(createAssignDpiToInternal(portvscp,portp->name()+"__Vcvt"));
cfuncp->addStmtsp(createAssignDpiToInternal(portvscp,portp->name()+"__Vcvt",true));
}
}
}
+2 -2
View File
@@ -75,8 +75,8 @@ private:
if (prettyName.find("._") != string::npos)
return "Inlined leading underscore";
}
if (nodep->width() > 256) return "Wide bus > 256 bits";
if (nodep->arrayElements() > 32) return "Wide memory > 32 ents";
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 (!(nodep->dtypeSkipRefp()->castBasicDType()
|| (nodep->dtypeSkipRefp()->castArrayDType()
&& nodep->dtypeSkipRefp()->castArrayDType()->dtypeSkipRefp()->castBasicDType()))) {
+38 -7
View File
@@ -159,8 +159,8 @@ private:
// assign x = (OE) ? 'hz : y;
// see if this a COND and separate out the __en logic from the output logic if it is
if (nodep->rhsp()->castCond()) {
AstCond* condp = nodep->rhsp()->castCond();
if (AstCond* condp = nodep->rhsp()->castCond()) {
//if (debug()>=9) nodep->dumpTree(cout,"- cond-in: ");
AstNode* oep = condp->condp();
AstNode* expr1p = condp->expr1p();
AstNode* expr2p = condp->expr2p();
@@ -192,17 +192,44 @@ private:
// replace the old assign logic with the new one
AstAssignW* newassp = new AstAssignW(nodep->fileline(), outp,outrhsp);
//if (debug()>=9) newassp->dumpTreeAndNext(cout,"- cond-out: ");
nodep->replaceWith(newassp);
nodep->deleteTree(); nodep=NULL;
newassp->iterateChildren(*this);
} else {
}
// How about a tri gate?
else if (AstBufIf1* bufp = nodep->rhsp()->castBufIf1()) {
//if (debug()>=9) nodep->dumpTree(cout,"- tri-in : ");
AstNode* enrhsp = bufp->lhsp()->unlinkFrBack();
AstNode* outrhsp = bufp->rhsp()->unlinkFrBack();
AstNode* outp = nodep->lhsp()->unlinkFrBack();;
AstVarRef* outrefp = NULL;
if (outp->castVarRef()) {
outrefp = outp->castVarRef();
} else if (outp->castSel()) {
outrefp = outp->castSel()->fromp()->castVarRef();
} else {
nodep->v3error("Can't find LHS varref");
}
createEnableVar(outp, outrefp, enrhsp, outrhsp->width());
// replace the old assign logic with the new one
AstAssignW* newassp = new AstAssignW(nodep->fileline(), outp,outrhsp);
//if (debug()>=9) newassp->dumpTreeAndNext(cout,"- tri-out: ");
nodep->replaceWith(newassp);
nodep->deleteTree(); nodep=NULL;
newassp->iterateChildren(*this);
}
else {
nodep->iterateChildren(*this);
}
}
AstVar* createEnableVar(AstNode* outp, AstVarRef* outrefp, AstNode* enrhsp, int width, string suffix="") {
// this function creates an __en Var that cooresponds to
// this function creates an __en Var that corresponds to
// the outp and outrefp and creates an assignw to enrhsp
AstVar* enp = new AstVar (outrefp->varp()->fileline(),
AstVarType::MODULETEMP,
@@ -218,10 +245,14 @@ private:
enrhsp->v3error("Don't know how to deal with selection logic wider than 1 bit");
}
}
AstNode* newassp = new AstAssignW (enp->fileline(),
new AstVarRef (enp->fileline(), enp, true),
enrhsp);
if (debug()>=9) enp->dumpTreeAndNext(cout,"- cev-out: ");
if (debug()>=9) newassp->dumpTreeAndNext(cout,"- cev-out: ");
m_modp->addStmtp(enp);
m_modp->addStmtp(new AstAssignW (enp->fileline(),
new AstVarRef (enp->fileline(), enp, true),
enrhsp));
m_modp->addStmtp(newassp);
outrefp->user1p(enp); // put __en signal into varref for later usage
outrefp->varp()->user1p(enp); // put __en signal into var as well in the event this is a single lhs driver and this needs passed up one level
+2 -1
View File
@@ -187,8 +187,9 @@ private:
UINFO(8," In Numbers: for (v="<<valInit<<"; v<"<<valStop<<"; v=v+"<<valInc<<")\n");
//
if (!m_generate) {
UINFO(8, " ~Iters: "<<((valStop - valInit)/valInc)<<" c="<<unrollCount()<<endl);
int loops = ((valStop - valInit)/valInc);
if (loops < 0) { loops += (1ULL<<constStopp->width()); } // Will roll around
UINFO(8, " ~Iters: "<<loops<<" c="<<unrollCount()<<endl);
if (loops > unrollCount())
return cantUnroll(nodep, "too many iterations");
+47 -31
View File
@@ -143,6 +143,7 @@ private:
virtual void visit(AstOr* nodep, AstNUser* vup) { width_Omax_L_Rlhs(nodep,vup); }
virtual void visit(AstXnor* nodep, AstNUser* vup) { width_Omax_L_Rlhs(nodep,vup); }
virtual void visit(AstXor* nodep, AstNUser* vup) { width_Omax_L_Rlhs(nodep,vup); }
virtual void visit(AstBufIf1* nodep, AstNUser* vup) { width_Omax_L_Rlhs(nodep,vup); }
// Multiple possible reasonable division width conversions. Just keep our code simple, they aren't common.
virtual void visit(AstModDiv* nodep, AstNUser* vup) { width_Omax_L_Rlhs(nodep,vup); }
virtual void visit(AstModDivS* nodep, AstNUser* vup) { width_Omax_L_Rlhs(nodep,vup); }
@@ -389,47 +390,20 @@ private:
// Just a quick check as after V3Param these nodes instead are AstSel's
AstNode* selp = V3Width::widthSelNoIterEdit(nodep); if (selp!=nodep) { nodep=NULL; selp->iterate(*this,vup); return; }
nodep->v3fatalSrc("AstSelBit should disappear after widthSel");
if (vup->c()->prelim()) {
nodep->lhsp()->iterateAndNext(*this,WidthVP(ANYSIZE,0,BOTH).p()); // from
nodep->rhsp()->iterateAndNext(*this,WidthVP(ANYSIZE,0,BOTH).p()); // bit
}
}
virtual void visit(AstSelExtract* nodep, AstNUser* vup) {
// Just a quick check as after V3Param these nodes instead are AstSel's
AstNode* selp = V3Width::widthSelNoIterEdit(nodep); if (selp!=nodep) { nodep=NULL; selp->iterate(*this,vup); return; }
nodep->v3fatalSrc("AstSelExtract should disappear after widthSel");
if (vup->c()->prelim()) {
nodep->fromp()->iterateAndNext(*this,WidthVP(ANYSIZE,0,BOTH).p());
nodep->msbp()->iterateAndNext(*this,WidthVP(ANYSIZE,0,BOTH).p());
nodep->lsbp()->iterateAndNext(*this,WidthVP(ANYSIZE,0,BOTH).p());
}
}
virtual void visit(AstSelPlus* nodep, AstNUser* vup) {
AstNode* selp = V3Width::widthSelNoIterEdit(nodep); if (selp!=nodep) { nodep=NULL; selp->iterate(*this,vup); return; }
nodep->v3fatalSrc("AstSelPlus should disappear after widthSel");
if (vup->c()->prelim()) {
nodep->fromp()->iterateAndNext(*this,WidthVP(ANYSIZE,0,BOTH).p());
nodep->bitp()->iterateAndNext(*this,WidthVP(ANYSIZE,0,BOTH).p());
nodep->widthp()->iterateAndNext(*this,WidthVP(ANYSIZE,0,BOTH).p());
if (AstConst* constp = nodep->widthp()->castConst()) {
int width = constp->toSInt();
nodep->width(width,width);
}
}
}
virtual void visit(AstSelMinus* nodep, AstNUser* vup) {
AstNode* selp = V3Width::widthSelNoIterEdit(nodep); if (selp!=nodep) { nodep=NULL; selp->iterate(*this,vup); return; }
nodep->v3fatalSrc("AstSelMinus should disappear after widthSel");
if (vup->c()->prelim()) {
nodep->fromp()->iterateAndNext(*this,WidthVP(ANYSIZE,0,BOTH).p());
nodep->bitp()->iterateAndNext(*this,WidthVP(ANYSIZE,0,BOTH).p());
nodep->widthp()->iterateAndNext(*this,WidthVP(ANYSIZE,0,BOTH).p());
if (AstConst* constp = nodep->widthp()->castConst()) {
int width = constp->toSInt();
nodep->width(width,width);
}
}
}
virtual void visit(AstExtend* nodep, AstNUser* vup) {
@@ -523,11 +497,41 @@ private:
nodep->iterateChildren(*this, vup);
nodep->widthFrom(nodep->dtypep()->skipRefp());
}
virtual void visit(AstCast* nodep, AstNUser* vup) {
nodep->lhsp()->iterateAndNext(*this,WidthVP(ANYSIZE,0,BOTH).p());
nodep->dtypep()->iterateAndNext(*this,WidthVP(ANYSIZE,0,BOTH).p());
// When more general casts are supported, the cast elimination will be done later.
// For now, replace it ASAP, so widthing can propagate easily
// The cast may change signing, but we don't know the sign yet. Make it so.
// Note we don't sign lhsp() that would make the algorithm O(n^2) if lots of casting.
V3Width::widthParamsEdit(nodep->dtypep()); // MAY CHANGE dtypep()
AstBasicDType* basicp = nodep->dtypep()->basicp(); if (!basicp) nodep->v3fatalSrc("Unimplemented: Casting non-simple data type");
nodep->widthSignedFrom(basicp);
widthCheck(nodep,"Cast",nodep->lhsp(),nodep->width(),nodep->width(),true);
AstNode* newp = nodep->lhsp()->unlinkFrBack();
if (basicp->isSigned()) {
newp = new AstSigned(nodep->fileline(), newp);
} else {
newp = new AstUnsigned(nodep->fileline(), newp);
}
nodep->replaceWith(newp);
}
virtual void visit(AstVar* nodep, AstNUser* vup) {
//if (debug()) nodep->dumpTree(cout," InitPre: ");
// Must have deterministic constant width
// We can't skip this step when width()!=0, as creating a AstVar
// with non-constant range gets size 1, not size 0.
// with non-constant range gets size 1, not size 0. So use didWidth().
if (nodep->didWidth()) { // Early exit if have circular parameter definition
if (!nodep->width()) {
if (!nodep->valuep()) nodep->v3fatalSrc("circular, but without value");
nodep->v3error("Variable's initial value is circular: "<<nodep->prettyName());
pushDeletep(nodep->valuep()->unlinkFrBack());
nodep->valuep(new AstConst(nodep->fileline(), 1));
} else {
return;
}
}
nodep->didWidth(true);
int width=1; int mwidth=1;
// Parameters if implicit untyped inherit from what they are assigned to
AstBasicDType* bdtypep = nodep->dtypep()->castBasicDType();
@@ -585,6 +589,7 @@ private:
}
virtual void visit(AstEnumDType* nodep, AstNUser* vup) {
UINFO(5," ENUMDTYPE "<<nodep<<endl);
nodep->dtypep()->iterateAndNext(*this,WidthVP(ANYSIZE,0,BOTH).p());
nodep->widthFrom(nodep->dtypep());
// Assign widths
@@ -615,6 +620,7 @@ private:
}
}
virtual void visit(AstEnumItem* nodep, AstNUser* vup) {
UINFO(5," ENUMITEM "<<nodep<<endl);
int width = vup->c()->width();
int mwidth = vup->c()->widthMin();
nodep->width(width, mwidth);
@@ -626,12 +632,13 @@ private:
virtual void visit(AstEnumItemRef* nodep, AstNUser* vup) {
if (nodep->itemp()->width()==0) {
// We need to do the whole enum en-mass
AstNode* enump = nodep;
AstNode* enump = nodep->itemp();
if (!enump) nodep->v3fatalSrc("EnumItemRef not linked");
for (; enump; enump=enump->backp()) {
if (enump->castEnumDType()) break;
}
if (!enump) nodep->v3fatalSrc("EnumItem not under a Enum");
enump->iterate(*this);
if (!enump) nodep->v3fatalSrc("EnumItemRef can't deref back to a Enum");
enump->iterate(*this,vup);
}
nodep->widthFrom(nodep->itemp()->valuep());
}
@@ -1007,6 +1014,15 @@ private:
} else {
// Do PRELIM again, because above accept may have exited early due to node replacement
pinp->accept(*this,WidthVP(portp->width(),portp->widthMin(),BOTH).p());
if ((portp->isOutput() || portp->isInout())
&& pinp->width() != portp->width()) {
pinp->v3error("Unsupported: Function output argument '"<<portp->prettyName()<<"'"
<<" requires "<<pinp->width()
<<" bits, but connection's "<<pinp->prettyTypeName()
<<" generates "<<portp->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)
}
if (portp->basicp() && !portp->basicp()->isOpaque()) {
widthCheck(nodep,"Function Argument",pinp,portp->width(),portp->widthMin());
}
+2
View File
@@ -630,6 +630,8 @@ int main(int argc, char** argv, char** env) {
V3File::writeTimes(v3Global.opt.makeDir()+"/"+v3Global.opt.prefix()+"__verFiles.dat", argString);
}
// Final writing shouldn't throw warnings, but...
V3Error::abortIfWarnings();
#ifdef VL_LEAK_CHECKS
// Cleanup memory for valgrind leak analysis
v3Global.clear();
+1 -1
View File
@@ -25,7 +25,7 @@
//**********************************************************************
//**** Version and host name
#define DTVERSION "Verilator 3.811 2011/02/14"
#define DTVERSION "Verilator 3.813 2011/06/28"
//**********************************************************************
//**** Functions
+61 -20
View File
@@ -833,7 +833,7 @@ port<nodep>: // ==IEEE: port
| portDirNetE /*implicit*/ portSig variable_dimensionListE sigAttrListE '=' constExpr
{ $$=$2; /*VARDTYPE-same*/ AstVar* vp=VARDONEP($$,$3,$4); $$->addNextNull(vp); vp->valuep($6); }
;
portDirNetE: // IEEE: part of port, optional net type and/or direction
/* empty */ { }
// // Per spec, if direction given default the nettype.
@@ -842,12 +842,12 @@ portDirNetE: // IEEE: part of port, optional net type and/or direction
| port_direction net_type { VARDECL(PORT); VARDTYPE(NULL/*default_nettype*/); } // net_type calls VARNET
| net_type { } // net_type calls VARNET
;
port_declNetE: // IEEE: part of port_declaration, optional net type
/* empty */ { }
| net_type { } // net_type calls VARNET
;
portSig<nodep>:
id/*port*/ { $$ = new AstPort($<fl>1,PINNUMINC(),*$1); }
| idSVKwd { $$ = new AstPort($<fl>1,PINNUMINC(),*$1); }
@@ -1078,6 +1078,31 @@ signing<signstate>: // ==IEEE: signing
//************************************************
// Data Types
casting_type<dtypep>: // IEEE: casting_type
simple_type { $$ = $1; }
// // IEEE: constant_primary
// // In expr:cast this is expanded to just "expr"
//
// // IEEE: signing
//See where casting_type used
//^^ ySIGNED { $$ = new AstSigned($1,$3); }
//^^ yUNSIGNED { $$ = new AstUnsigned($1,$3); }
//UNSUP ySTRING { $$ = $1; }
//UNSUP yCONST__ETC/*then `*/ { $$ = $1; }
;
simple_type<dtypep>: // ==IEEE: simple_type
// // IEEE: integer_type
integer_atom_type { $$ = $1; }
| integer_vector_type { $$ = $1; }
//UNSUP non_integer_type { $$ = $1; }
// // IEEE: ps_type_identifier
// // IEEE: ps_parameter_identifier (presumably a PARAMETER TYPE)
| ps_type { $$ = $1; }
// // { generate_block_identifer ... } '.'
// // Need to determine if generate_block_identifier can be lex-detected
;
data_type<dtypep>: // ==IEEE: data_type
// // This expansion also replicated elsewhere, IE data_type__AndID
data_typeNoRef { $$ = $1; }
@@ -2115,6 +2140,7 @@ system_f_call<nodep>: // IEEE: system_tf_call (as func)
| yaD_DPI '(' exprList ')' { $$ = new AstFuncRef($2,*$1,$3); }
//
| yD_BITS '(' expr ')' { $$ = new AstAttrOf($1,AstAttrType::EXPR_BITS,$3); }
| yD_BITS '(' data_type ')' { $$ = new AstAttrOf($1,AstAttrType::EXPR_BITS,$3); }
| yD_C '(' cStrList ')' { $$ = (v3Global.opt.ignc() ? NULL : new AstUCFunc($1,$3)); }
| yD_CLOG2 '(' expr ')' { $$ = new AstCLog2($1,$3); }
| yD_COUNTONES '(' expr ')' { $$ = new AstCountOnes($1,$3); }
@@ -2454,7 +2480,10 @@ expr<nodep>: // IEEE: part of expression/constant_expression/primary
| '_' '(' statePushVlg expr statePop ')' { $$ = $4; } // Arbitrary Verilog inside PSL
//
// // IEEE: cast/constant_cast
//UNSUP casting_type yP_TICK '(' expr ')' { UNSUP }
| casting_type yP_TICK '(' expr ')' { $$ = new AstCast($2,$4,$1); }
// // expanded from casting_type
| ySIGNED yP_TICK '(' expr ')' { $$ = new AstSigned($1,$4); }
| yUNSIGNED yP_TICK '(' expr ')' { $$ = new AstUnsigned($1,$4); }
// // Spec only allows primary with addition of a type reference
// // We'll be more general, and later assert LHS was a type.
//UNSUP ~l~expr yP_TICK '(' expr ')' { UNSUP }
@@ -2681,46 +2710,58 @@ gateUnsupList<nodep>:
;
gateBuf<nodep>:
gateIdE instRangeE '(' idClassSel ',' expr ')' { $$ = new AstAssignW ($3,$4,$6); }
gateIdE instRangeE '(' variable_lvalue ',' expr ')'
{ $$ = new AstAssignW ($3,$4,$6); }
;
gateBufif0<nodep>:
gateIdE instRangeE '(' idClassSel ',' expr ',' expr ')' { $$ = new AstAssignW ($3,$4,new AstCond($3,$8, new AstConst($3,V3Number($3,"1'bz")), $6)); }
gateIdE instRangeE '(' variable_lvalue ',' expr ',' expr ')'
{ $$ = new AstAssignW ($3,$4,new AstBufIf1($3,new AstNot($3,$8),$6)); }
;
gateBufif1<nodep>:
gateIdE instRangeE '(' idClassSel ',' expr ',' expr ')' { $$ = new AstAssignW ($3,$4,new AstCond($3,$8, $6, new AstConst($3,V3Number($3,"1'bz")))); }
gateIdE instRangeE '(' variable_lvalue ',' expr ',' expr ')'
{ $$ = new AstAssignW ($3,$4,new AstBufIf1($3,$8,$6)); }
;
gateNot<nodep>:
gateIdE instRangeE '(' idClassSel ',' expr ')' { $$ = new AstAssignW ($3,$4,new AstNot($5,$6)); }
gateIdE instRangeE '(' variable_lvalue ',' expr ')'
{ $$ = new AstAssignW ($3,$4,new AstNot($5,$6)); }
;
gateNotif0<nodep>:
gateIdE instRangeE '(' idClassSel ',' expr ',' expr ')' { $$ = new AstAssignW ($3,$4,new AstCond($3,$8, new AstConst($3,V3Number($3,"1'bz")), new AstNot($3, $6))); }
gateIdE instRangeE '(' variable_lvalue ',' expr ',' expr ')'
{ $$ = new AstAssignW ($3,$4,new AstBufIf1($3,new AstNot($3,$8), new AstNot($3, $6))); }
;
gateNotif1<nodep>:
gateIdE instRangeE '(' idClassSel ',' expr ',' expr ')' { $$ = new AstAssignW ($3,$4,new AstCond($3,$8, new AstNot($3,$6), new AstConst($3,V3Number($3,"1'bz")))); }
gateIdE instRangeE '(' variable_lvalue ',' expr ',' expr ')'
{ $$ = new AstAssignW ($3,$4,new AstBufIf1($3,$8, new AstNot($3,$6))); }
;
gateAnd<nodep>:
gateIdE instRangeE '(' idClassSel ',' gateAndPinList ')' { $$ = new AstAssignW ($3,$4,$6); }
gateIdE instRangeE '(' variable_lvalue ',' gateAndPinList ')'
{ $$ = new AstAssignW ($3,$4,$6); }
;
gateNand<nodep>:
gateIdE instRangeE '(' idClassSel ',' gateAndPinList ')' { $$ = new AstAssignW ($3,$4,new AstNot($5,$6)); }
gateIdE instRangeE '(' variable_lvalue ',' gateAndPinList ')'
{ $$ = new AstAssignW ($3,$4,new AstNot($5,$6)); }
;
gateOr<nodep>:
gateIdE instRangeE '(' idClassSel ',' gateOrPinList ')' { $$ = new AstAssignW ($3,$4,$6); }
gateIdE instRangeE '(' variable_lvalue ',' gateOrPinList ')'
{ $$ = new AstAssignW ($3,$4,$6); }
;
gateNor<nodep>:
gateIdE instRangeE '(' idClassSel ',' gateOrPinList ')' { $$ = new AstAssignW ($3,$4,new AstNot($5,$6)); }
gateIdE instRangeE '(' variable_lvalue ',' gateOrPinList ')'
{ $$ = new AstAssignW ($3,$4,new AstNot($5,$6)); }
;
gateXor<nodep>:
gateIdE instRangeE '(' idClassSel ',' gateXorPinList ')' { $$ = new AstAssignW ($3,$4,$6); }
gateIdE instRangeE '(' variable_lvalue ',' gateXorPinList ')'
{ $$ = new AstAssignW ($3,$4,$6); }
;
gateXnor<nodep>:
gateIdE instRangeE '(' idClassSel ',' gateXorPinList ')' { $$ = new AstAssignW ($3,$4,new AstNot($5,$6)); }
gateIdE instRangeE '(' variable_lvalue ',' gateXorPinList ')'
{ $$ = new AstAssignW ($3,$4,new AstNot($5,$6)); }
;
gatePullup<nodep>:
gateIdE instRangeE '(' idClassSel ')' { $$ = new AstPull ($3, $4, true); }
gateIdE instRangeE '(' variable_lvalue ')' { $$ = new AstPull ($3, $4, true); }
;
gatePulldown<nodep>:
gateIdE instRangeE '(' idClassSel ')' { $$ = new AstPull ($3, $4, false); }
gateIdE instRangeE '(' variable_lvalue ')' { $$ = new AstPull ($3, $4, false); }
;
gateUnsup<nodep>:
gateIdE instRangeE '(' gateUnsupPinList ')' { $$ = new AstImplicit ($3,$4); }
@@ -2797,7 +2838,7 @@ junkToSemiList:
junkToSemi { } /* ignored */
| junkToSemiList junkToSemi { } /* ignored */
;
junkToSemi:
BISONPRE_NOT(';',yENDSPECIFY,yENDMODULE) { }
| error {}
@@ -3068,7 +3109,7 @@ vltOffFront<errcodeen>:
int V3ParseImp::bisonParse() {
if (PARSEP->debugBison()>=9) yydebug = 1;
return yyparse();
return yyparse();
}
const char* V3ParseImp::tokenName(int token) {
+51 -36
View File
@@ -110,8 +110,8 @@ if ($#opt_tests<0) {
}
mkdir "obj_dir";
mkdir "logs";
our $Log_Filename = "obj_dir/driver_".strftime("%Y%m%d_%H%M%S.log", localtime);
my $leftcnt=0; my $okcnt=0; my $failcnt=0; my $skcnt=0;
my @fails;
@@ -161,6 +161,7 @@ sub one_test {
push @fails, "\t\tmake$j && test_regress/"
.$test->{pl_filename}." ".join(' ',@Orig_ARGV_Sw)."\n";
$failcnt++;
report(\@fails, $Log_Filename);
if ($opt_stop) { die "%Error: --stop and errors found\n"; }
}
$leftcnt--;
@@ -170,7 +171,7 @@ sub one_test {
}
report(\@fails, undef);
report(\@fails, "obj_dir/driver_".strftime("%Y%m%d_%H%M%S.log", localtime));
report(\@fails, $Log_Filename);
exit(10) if $failcnt;
@@ -303,8 +304,9 @@ sub new {
ivrun_flags => [],
# VCS
vcs => 0,
vcs_flags => [split(/\s+/,"+cli -I +define+VCS+1 -q -sverilog -CFLAGS '-DVCS' ")],
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")],
# NC
nc => 0,
nc_flags => [split(/\s+/,"+licqueue +nowarn+LIBNOU +define+NC=1 -q +assert +sv -c ")],
@@ -408,11 +410,10 @@ sub read_status {
#----------------------------------------------------------------------
# Methods invoked by tests
sub compile {
sub compile_vlt_flags {
my $self = (ref $_[0]? shift : $Self);
my %param = (%{$self}, @_); # Default arguments are from $self
return 1 if $self->errors || $self->skips;
$self->oprint("Compile\n");
my $checkflags = join(' ',@{$param{v_flags}},
@{$param{v_flags2}},
@@ -423,6 +424,48 @@ sub compile {
$self->{trace} = 1 if ($opt_trace || $checkflags =~ /-trace\b/);
$self->{coverage} = 1 if ($checkflags =~ /-coverage\b/);
$opt_gdb="gdbrun" if defined $opt_gdb;
my @verilator_flags = @{$param{verilator_flags}};
unshift @verilator_flags, "--gdb $opt_gdb" if $opt_gdb;
unshift @verilator_flags, "--gdbbt" if $opt_gdbbt;
unshift @verilator_flags, @Opt_Driver_Verilator_Flags;
unshift @verilator_flags, "--x-assign unique"; # More likely to be buggy
unshift @verilator_flags, "--trace" if $opt_trace;
if (defined $opt_optimize) {
my $letters = "";
if ($opt_optimize =~ /[a-zA-Z]/) {
$letters = $opt_optimize;
} else { # Randomly turn on/off different optimizations
foreach my $l ('a'..'z') {
$letters .= ((rand() > 0.5) ? $l : uc $l);
}
unshift @verilator_flags, "--trace" if rand() > 0.5;
unshift @verilator_flags, "--coverage" if rand() > 0.5;
}
unshift @verilator_flags, "--O".$letters;
}
my @cmdargs = ("perl","../bin/verilator",
"--prefix ".$param{VM_PREFIX},
@verilator_flags,
@{$param{verilator_flags2}},
@{$param{v_flags}},
@{$param{v_flags2}},
$param{top_filename},
@{$param{v_other_filenames}},
($param{stdout_filename}?"> ".$param{stdout_filename}:""),
);
return @cmdargs;
}
sub compile {
my $self = (ref $_[0]? shift : $Self);
my %param = (%{$self}, @_); # Default arguments are from $self
return 1 if $self->errors || $self->skips;
$self->oprint("Compile\n");
compile_vlt_flags(%param);
if ($param{atsim}) {
$self->_make_top();
$self->_run(logfile=>"$self->{obj_dir}/atsim_compile.log",
@@ -482,37 +525,8 @@ sub compile {
cmd=>\@cmd);
}
if ($param{vlt}) {
$opt_gdb="gdbrun" if defined $opt_gdb;
my @verilator_flags = @{$param{verilator_flags}};
unshift @verilator_flags, "--gdb $opt_gdb" if $opt_gdb;
unshift @verilator_flags, "--gdbbt" if $opt_gdbbt;
unshift @verilator_flags, @Opt_Driver_Verilator_Flags;
unshift @verilator_flags, "--x-assign unique"; # More likely to be buggy
unshift @verilator_flags, "--trace" if $opt_trace;
if (defined $opt_optimize) {
my $letters = "";
if ($opt_optimize =~ /[a-zA-Z]/) {
$letters = $opt_optimize;
} else { # Randomly turn on/off different optimizations
foreach my $l ('a'..'z') {
$letters .= ((rand() > 0.5) ? $l : uc $l);
}
unshift @verilator_flags, "--trace" if rand() > 0.5;
unshift @verilator_flags, "--coverage" if rand() > 0.5;
}
unshift @verilator_flags, "--O".$letters;
}
my @cmdargs = $self->compile_vlt_flags(%param);
my @vlargs = ("perl","../bin/verilator",
"--prefix ".$self->{VM_PREFIX},
@verilator_flags,
@{$param{verilator_flags2}},
@{$param{v_flags}},
@{$param{v_flags2}},
$param{top_filename},
@{$param{v_other_filenames}},
($param{stdout_filename}?"> ".$param{stdout_filename}:""),
);
if ($self->sc_or_sp && !defined $ENV{SYSTEMC}) {
$self->skip("Test requires SystemC; ignore error since not installed\n");
return 1;
@@ -525,7 +539,7 @@ sub compile {
$self->_run(logfile=>"$self->{obj_dir}/vlt_compile.log",
fails=>$param{fails},
expect=>$param{expect},
cmd=>\@vlargs);
cmd=>\@cmdargs);
return 1 if $self->errors || $self->skips;
if (!$param{fails} && $param{verilator_make_gcc}) {
@@ -590,6 +604,7 @@ sub execute {
#$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{all_run_flags}},
],
%param,
+18
View File
@@ -0,0 +1,18 @@
#!/usr/bin/perl
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# Copyright 2003 by Wilson Snyder. This program is free software; you can
# redistribute it and/or modify it under the terms of either the GNU
# Lesser General Public License Version 3 or the Perl Artistic License
# Version 2.0.
compile (
);
execute (
check_finished=>1,
);
ok(1);
1;
+26
View File
@@ -0,0 +1,26 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed into the Public Domain, for any use,
// without warranty, 2011 by Wilson Snyder.
module t;
typedef logic [3:0] mc_t;
typedef mc_t tocast_t;
mc_t o;
initial begin
if (4'shf > 4'sh0) $stop;
if (signed'(4'hf) > 4'sh0) $stop;
if (4'hf < 4'h0) $stop;
if (unsigned'(4'shf) < 4'h0) $stop;
o = tocast_t'(4'b1);
if (o != 4'b1) $stop;
$write("*-* All Finished *-*\n");
$finish;
end
endmodule
+24
View File
@@ -0,0 +1,24 @@
#!/usr/bin/perl
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# Copyright 2003 by Wilson Snyder. This program is free software; you can
# redistribute it and/or modify it under the terms of either the GNU
# Lesser General Public License Version 3 or the Perl Artistic License
# Version 2.0.
$Self->{vl_time_multiplier} = 1000;
compile (
);
execute (
check_finished=>1,
expect=> quotemeta(
'[1000.000] cyc==99 crc=2961926edde3e5c6018be970cdbf327b72b5f3c5eab42995891005eec8767e5fdf03051edbe9d222ee756ee34d8d6c83ee877aad65c487140ac87d26c636a66214b4a69acad924c568cc8e8c79f97d07a6eedf91011919d0e3cdda5215ee58c942f6c4dea48b3f38abc77bf47e4f6d6a859fcc5b5d46ec9d2f6a5bf7b978b1ba7ca15d0713a2eb06ade1570c4e3a12db687625eef8dfebcb4095ab4bdffe79c1298f609307a5ef773a6432b855e3e54deb88ca342bf5a7fecc5f2f3e165a59cdb9179718a2d11c9d55f14d69f40b01e41fcb7335a8872a6ba7876ec684d6a3af0b82aa31cca6e26340a2589cf7bf886faa8d23844596dc71233c7025c5250a968b770ab72db90b03d8c045fb8848159df544a3a3bf063269be0aa11d5507f5c8b328b760a6df9e3fbe276faad8eadee126443ad3f99d595b12d0ae514b20693298a58642a07718f9ab7ea8c66575f7f8d0e3ba77d992235b3d5a4e015a7ff9b97a8c4f48ebdbfc2365e6bca4dd3ba6bfc7e850f7c8e2842c717a1d85a977a033f564fc
[1000.000] cyc==99 crc=001010010110000110010010011011101101110111100011111001011100011000000001100010111110100101110000110011011011111100110010011110110111001010110101111100111100010111101010101101000010100110010101100010010001000000000101111011101100100001110110011111100101111111011111000000110000010100011110110110111110100111010010001000101110111001110101011011101110001101001101100011010110110010000011111011101000011101111010101011010110010111000100100001110001010000001010110010000111110100100110110001100011011010100110011000100001010010110100101001101001101011001010110110010010010011000101011010001100110010001110100011000111100111111001011111010000011110100110111011101101111110010001000000010001100100011001110100001110001111001101110110100101001000010101111011100101100011001001010000101111011011000100110111101010010010001011001111110011100010101011110001110111101111110100011111100100111101101101011010101000010110011111110011000101101101011101010001101110110010011101001011110110101001011011111101111011100101111000101100011011101001111100101000010101110100000111000100111010001011101011000001101010110111100001010101110000110001001110001110100001001011011011011010000111011000100101111011101111100011011111111010111100101101000000100101011010101101001011110111111111111001111001110000010010100110001111011000001001001100000111101001011110111101110111001110100110010000110010101110000101010111100011111001010100110111101011100010001100101000110100001010111111010110100111111111101100110001011111001011110011111000010110010110100101100111001101101110010001011110010111000110001010001011010001000111001001110101010101111100010100110101101001111101000000101100000001111001000001111111001011011100110011010110101000100001110010101001101011101001111000011101101110110001101000010011010110101000111010111100001011100000101010101000110001110011001010011011100010011000110100000010100010010110001001110011110111101111111000100001101111101010101000110100100011100001000100010110010110110111000111000100100011001111000111000000100101110001010010010100001010100101101000101101110111000010101011011100101101101110010000101100000011110110001100000001000101111110111000100001001000000101011001110111110101010001001010001110100011101111110000011000110010011010011011111000001010101000010001110101010101000001111111010111001000101100110010100010110111011000001010011011011111100111100011111110111110001001110110111110101010110110001110101011011110111000010010011001000100001110101101001111111001100111010101100101011011000100101101000010101110010100010100101100100000011010010011001010011000101001011000011001000010101000000111011100011000111110011010101101111110101010001100011001100101011101011111011111111000110100001110001110111010011101111101100110010010001000110101101100111101010110100100111000000001010110100111111111111001101110010111101010001100010011110100100011101011110110111111110000100011011001011110011010111100101001001101110100111011101001101011111111000111111010000101000011110111110010001110001010000100001011000111000101111010000111011000010110101001011101111010000000110011111101010110010011111100'
),
);
ok(1);
1;
+33
View File
@@ -0,0 +1,33 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed into the Public Domain, for any use,
// without warranty, 2011 by Wilson Snyder.
module t (/*AUTOARG*/
// Inputs
clk
);
input clk;
integer cyc=0;
reg [4095:0] crc;
// Test loop
always @ (posedge clk) begin
cyc <= cyc + 1;
crc <= {crc[4094:0], crc[63]^crc[2]^crc[0]}; // not a good crc :)
if (cyc==0) begin
// Setup
crc <= 4096'h9f51804b5275c7b6ab9907144a58649bb778f9718062fa5c336fcc9edcad7cf17aad0a656244017bb21d9f97f7c0c147b6fa7488bb9d5bb8d3635b20fba1deab597121c502b21f49b18da998852d29a6b2b649315a3323a31e7e5f41e9bbb7e44046467438f37694857b963250bdb137a922cfce2af1defd1f93db5aa167f316d751bb274bda96fdee5e2c6eb21886633246b165341f0594c27697b06b62b1ad05ebe3c08909a54272de651296dcdd3d1774fc432d22210d8f6afa50b02cf23336f8cc3a0a2ebfd1a3a60366a1b66ef346e0379116d68caa01279ac2772d1f3cd76d2cbbc68ada6f83ec2441b2679b405486df8aa734ea1729b40c3f82210e8e42823eb3fd6ca77ee19f285741c4e8bac1ab7855c3138e84b6da1d897bbe37faf2d0256ad2f7ff9e704a63d824c1e97bddce990cae1578f9537ae2328d0afd69ffb317cbcf859696736e45e5c628b44727557c535a7d02c07907f2dccd6a21ca9ae9e1dbb1a135a8ebc2e0aa8c7329b898d02896273defe21beaa348e11165b71c48cf1c09714942a5a2ddc2adcb6e42c0f630117ee21205677d5128e8efc18c9a6f82a8475541fd722cca2dd829b7e78fef89dbeab63ab7b849910eb4fe675656c4b42b9452c81a4ca6296190a81dc63e6adfaa31995d7dfe3438ee9df66488d6cf569380569ffe6e5ea313d23af6ff08d979af29374ee9aff1fa143df238a1;
end
else if (cyc==99) begin
$write("[%0t] cyc==%0d crc=%x%x%x%x\n",$time, cyc, crc[4095:3072], crc[2071:2048], crc[2047:1024], crc[1023:0]);
$write("[%0t] cyc==%0d crc=%b%b%b%b\n",$time, cyc, crc[4095:3072], crc[2071:2048], crc[2047:1024], crc[1023:0]);
//Unsupported: $write("[%0t] cyc==%0d crc=%x\n",$time, cyc, crc);
if (crc != 4096'h2961926edde3e5c6018be970cdbf327b72b5f3c5eab42995891005eec8767e5fdf03051edbe9d222ee756ee34d8d6c83ee877aad65c487140ac87d26c636a66214b4a69acad924c568cc8e8c79f97d07a6eedf91011919d0e3cdda5215ee58c942f6c4dea48b3f38abc77bf47e4f6d6a859fcc5b5d46ec9d2f6a5bf7b978b1bac862198cc91ac594d07c165309da5ec1ad8ac6b417af8f0224269509cb79944a5b7374f45dd3f10cb48884363dabe942c0b3c8ccdbe330e828baff468e980d9a86d9bbcd1b80de445b5a32a8049e6b09dcb47cf35db4b2ef1a2b69be0fb09106c99e6d01521b7e2a9cd3a85ca6d030fe08843a390a08facff5b29dfb867ca15d0713a2eb06ade1570c4e3a12db687625eef8dfebcb4095ab4bdffe79c1298f609307a5ef773a6432b855e3e54deb88ca342bf5a7fecc5f2f3e165a59cdb9179718a2d11c9d55f14d69f40b01e41fcb7335a8872a6ba7876ec684d6a3af0b82aa31cca6e26340a2589cf7bf886faa8d23844596dc71233c7025c5250a968b770ab72db90b03d8c045fb8848159df544a3a3bf063269be0aa11d5507f5c8b328b760a6df9e3fbe276faad8eadee126443ad3f99d595b12d0ae514b20693298a58642a07718f9ab7ea8c66575f7f8d0e3ba77d992235b3d5a4e015a7ff9b97a8c4f48ebdbfc2365e6bca4dd3ba6bfc7e850f7c8e2842c717a1d85a977a033f564fc
) $stop;
$write("*-* All Finished *-*\n");
$finish;
end
end
endmodule
+7
View File
@@ -23,6 +23,7 @@ module t;
function int dpix_int123(); dpix_int123 = 32'h123; endfunction
export "DPI-C" function dpix_f_bit;
export "DPI-C" function dpix_f_bit15;
export "DPI-C" function dpix_f_int;
export "DPI-C" function dpix_f_byte;
export "DPI-C" function dpix_f_shortint;
@@ -30,12 +31,18 @@ module t;
export "DPI-C" function dpix_f_chandle;
function bit dpix_f_bit (bit i); dpix_f_bit = ~i; endfunction
function bit [14:0] dpix_f_bit15 (bit [14:0] i); dpix_f_bit15 = ~i; endfunction
function int dpix_f_int (int i); dpix_f_int = ~i; endfunction
function byte dpix_f_byte (byte i); dpix_f_byte = ~i; endfunction
function shortint dpix_f_shortint(shortint i); dpix_f_shortint = ~i; endfunction
function longint dpix_f_longint (longint i); dpix_f_longint = ~i; endfunction
function chandle dpix_f_chandle (chandle i); dpix_f_chandle = i; endfunction
export "DPI-C" task dpix_t_bit95;
task dpix_t_bit95(input bit [94:0] i, output bit [94:0] o); o = ~i; endtask
export "DPI-C" task dpix_t_bit96;
task dpix_t_bit96(input bit [95:0] i, output bit [95:0] o); o = ~i; endtask
int lineno;
initial begin
+20
View File
@@ -123,8 +123,11 @@ int dpix_run_tests() {
CHECK_RESULT (int, o, 0x458UL);
#endif
svBitVecVal vec10[1] = {0x10};
CHECK_RESULT (int, dpix_f_bit(1), 0x0);
CHECK_RESULT (int, dpix_f_bit(0), 0x1);
CHECK_RESULT (int, dpix_f_bit15(vec10) & 0x7fUL, 0x6f);
// Simulators disagree over the next three's sign extension unless we mask the upper bits
CHECK_RESULT (int, dpix_f_int(1) & 0xffffffffUL, 0xfffffffeUL);
CHECK_RESULT (int, dpix_f_byte(1) & 0xffUL, 0xfe);
@@ -133,6 +136,23 @@ int dpix_run_tests() {
CHECK_RESULT (unsigned long long, dpix_f_longint(1), 0xfffffffffffffffeULL);
CHECK_RESULT (void*, dpix_f_chandle((void*)(12345)), (void*)(12345));
{
svBitVecVal i_vec95[3] = {0x72912312,0xab782a12,0x8a413bd9};
svBitVecVal o_vec95[3] = {0,0,0};
dpix_t_bit95(i_vec95, o_vec95);
CHECK_RESULT(int, o_vec95[0], ~i_vec95[0]);
CHECK_RESULT(int, o_vec95[1], ~i_vec95[1]);
CHECK_RESULT(int, o_vec95[2], (~i_vec95[2])&0x7fffffffUL);
}
{
svBitVecVal i_vec96[3] = {0xf2912312,0xab782a12,0x8a413bd9};
svBitVecVal o_vec96[3] = {0,0,0};
dpix_t_bit96(i_vec96, o_vec96);
CHECK_RESULT(int, o_vec96[0], ~i_vec96[0]);
CHECK_RESULT(int, o_vec96[1], ~i_vec96[1]);
CHECK_RESULT(int, o_vec96[2], ~i_vec96[2]);
}
if (int bad=check_sub("top.t.a",1)) return bad;
if (int bad=check_sub("top.t.b",2)) return bad;
+8
View File
@@ -59,6 +59,8 @@ module t ();
`ifndef NO_SHORTREAL
import "DPI-C" pure function void dpii_v_shortreal(input shortreal i, output shortreal o);
`endif
import "DPI-C" pure function void dpii_v_bit95 (input bit [95-1:0] i, output bit [95-1:0] o);
import "DPI-C" pure function void dpii_v_bit96 (input bit [96-1:0] i, output bit [96-1:0] o);
import "DPI-C" pure function int dpii_f_strlen (input string i);
@@ -82,6 +84,8 @@ module t ();
bit [31:0] i_b32, o_b32;
bit [32:0] i_b33, o_b33;
bit [63:0] i_b64, o_b64;
bit [94:0] i_b95, o_b95;
bit [95:0] i_b96, o_b96;
int i_i, o_i;
byte i_y, o_y;
@@ -111,6 +115,8 @@ module t ();
i_b32 = {1'b1,wide[32-2:0]};
i_b33 = {1'b1,wide[33-2:0]};
i_b64 = {1'b1,wide[64-2:0]};
i_b95 = {1'b1,wide[95-2:0]};
i_b96 = {1'b1,wide[96-2:0]};
i_i = {1'b1,wide[32-2:0]};
i_y = {1'b1,wide[8-2:0]};
@@ -159,6 +165,8 @@ module t ();
`ifndef NO_SHORTREAL
dpii_v_shortreal(i_f,o_f); if (o_f != i_f+1.5) $stop;
`endif
dpii_v_bit95 (i_b95,o_b95); if (o_b95 !== ~i_b95) $stop;
dpii_v_bit96 (i_b96,o_b96); if (o_b96 !== ~i_b96) $stop;
if (dpii_f_strlen ("")!=0) $stop;
if (dpii_f_strlen ("s")!=1) $stop;
+20 -8
View File
@@ -33,13 +33,14 @@
extern "C" {
extern unsigned char dpii_f_bit (unsigned char i);
extern svBitVecVal dpii_f_bit8 (const svBitVecVal *i);
extern svBitVecVal dpii_f_bit9 (const svBitVecVal *i);
extern svBitVecVal dpii_f_bit16 (const svBitVecVal *i);
extern svBitVecVal dpii_f_bit17 (const svBitVecVal *i);
extern svBitVecVal dpii_f_bit32 (const svBitVecVal *i);
extern long long dpii_f_bit33 (const svBitVecVal *i);
extern long long dpii_f_bit64 (const svBitVecVal *i);
extern svBitVecVal dpii_f_bit8 (const svBitVecVal* i);
extern svBitVecVal dpii_f_bit9 (const svBitVecVal* i);
extern svBitVecVal dpii_f_bit16 (const svBitVecVal* i);
extern svBitVecVal dpii_f_bit17 (const svBitVecVal* i);
extern svBitVecVal dpii_f_bit32 (const svBitVecVal* i);
extern long long dpii_f_bit33 (const svBitVecVal* i);
extern long long dpii_f_bit64 (const svBitVecVal* i);
extern long long dpii_f_bit95 (const svBitVecVal* i, svBitVecVal* o);
extern int dpii_f_int (int i);
extern char dpii_f_byte (char i);
extern short int dpii_f_shortint(short int i);
@@ -49,7 +50,7 @@ extern "C" {
extern double dpii_f_real (double i);
extern float dpii_f_shortreal(float i);
extern void dpii_v_bit (unsigned char i, unsigned char *o);
extern void dpii_v_bit (unsigned char i, unsigned char* o);
extern void dpii_v_int (int i, int *o);
extern void dpii_v_byte (char i, char *o);
extern void dpii_v_shortint (short int i, short int *o);
@@ -100,6 +101,17 @@ void dpii_v_string (const char* i, const char** o) { *o = i; }
void dpii_v_real (double i, double* o) { *o = i + 1.5; }
void dpii_v_shortreal(float i, float* o) { *o = i + 1.5; }
void dpii_v_bit95(const svBitVecVal* i, svBitVecVal* o) {
o[0] = ~i[0];
o[1] = ~i[1];
o[2] = SV_MASK(95-64) & ~i[2];
}
void dpii_v_bit96(const svBitVecVal* i, svBitVecVal* o) {
o[0] = ~i[0];
o[1] = ~i[1];
o[2] = ~i[2];
}
int dpii_f_strlen (const char* i) { return strlen(i); }
//======================================================================
+51
View File
@@ -0,0 +1,51 @@
#!/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.
use File::Spec;
my $self = $Self;
my $child_dir = "$Self->{obj_dir}_child";
mkdir $child_dir;
# Compile the child
{
my @cmdargs = $Self->compile_vlt_flags
(VM_PREFIX => "$Self->{VM_PREFIX}_child",
top_filename => "$Self->{name}_child.v",
verilator_flags => ["-cc", "-Mdir", "${child_dir}", "--debug-check"],
);
$Self->_run(logfile=>"${child_dir}/vlt_compile.log",
cmd=>\@cmdargs);
$Self->_run(logfile=>"${child_dir}/vlt_gcc.log",
cmd=>["cd ${child_dir} && ",
"make", "-f".getcwd()."/Makefile_obj",
"CPPFLAGS_DRIVER=-D".uc($self->{name}),
($opt_verbose ? "CPPFLAGS_DRIVER2=-DTEST_VERBOSE=1":""),
"MAKE_MAIN=0",
"VM_PREFIX=$self->{VM_PREFIX}_child",
"V$self->{name}_child__ALL.a", # bypass default rule, make archive
($param{make_flags}||""),
]);
}
# Compile the parent (might be with other than verilator)
compile (
v_flags2 => [File::Spec->rel2abs("${child_dir}/V$self->{name}_child__ALL.a"),
# TODO would be nice to have this in embedded archive
"t/t_embed1_c.cpp"],
);
execute (
check_finished=>1,
);
ok(1);
1;
+109
View File
@@ -0,0 +1,109 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed into the Public Domain, for any use,
// without warranty, 2011 by Wilson Snyder.
module t (/*AUTOARG*/
// Inputs
clk
);
input clk;
integer cyc=0;
reg [63:0] crc;
reg [63:0] sum;
// Take CRC data and apply to testblock inputs
wire bit_in = crc[0];
wire [30:0] vec_in = crc[31:1];
wire [123:0] wide_in = {crc[59:0],~crc[63:0]};
/*AUTOWIRE*/
// Beginning of automatic wires (for undeclared instantiated-module outputs)
wire exp_bit_out; // From reference of t_embed1_child.v
wire exp_did_init_out; // From reference of t_embed1_child.v
wire [30:0] exp_vec_out; // From reference of t_embed1_child.v
wire [123:0] exp_wide_out; // From reference of t_embed1_child.v
wire got_bit_out; // From test of t_embed1_wrap.v
wire got_did_init_out; // From test of t_embed1_wrap.v
wire [30:0] got_vec_out; // From test of t_embed1_wrap.v
wire [123:0] got_wide_out; // From test of t_embed1_wrap.v
// End of automatics
// A non-embedded master
/* t_embed1_child AUTO_TEMPLATE(
.\(.*_out\) (exp_\1[]),
.is_ref (1'b1));
*/
t_embed1_child reference
(/*AUTOINST*/
// Outputs
.bit_out (exp_bit_out), // Templated
.vec_out (exp_vec_out[30:0]), // Templated
.wide_out (exp_wide_out[123:0]), // Templated
.did_init_out (exp_did_init_out), // Templated
// Inputs
.clk (clk),
.bit_in (bit_in),
.vec_in (vec_in[30:0]),
.wide_in (wide_in[123:0]),
.is_ref (1'b1)); // Templated
// The embeded comparison
/* t_embed1_wrap AUTO_TEMPLATE(
.\(.*_out\) (got_\1[]),
.is_ref (1'b0));
*/
t_embed1_wrap test
(/*AUTOINST*/
// Outputs
.bit_out (got_bit_out), // Templated
.vec_out (got_vec_out[30:0]), // Templated
.wide_out (got_wide_out[123:0]), // Templated
.did_init_out (got_did_init_out), // Templated
// Inputs
.clk (clk),
.bit_in (bit_in),
.vec_in (vec_in[30:0]),
.wide_in (wide_in[123:0]),
.is_ref (1'b0)); // Templated
// Aggregate outputs into a single result vector
wire [63:0] result = {60'h0,
got_wide_out !== exp_wide_out,
got_vec_out !== exp_vec_out,
got_bit_out !== exp_bit_out,
got_did_init_out !== exp_did_init_out};
// Test loop
always @ (posedge clk) begin
`ifdef TEST_VERBOSE
$write("[%0t] cyc==%0d crc=%x result=%x gv=%x ev=%x\n",$time, cyc, crc, result,
got_vec_out, exp_vec_out);
`endif
cyc <= cyc + 1;
crc <= {crc[62:0], crc[63]^crc[2]^crc[0]};
if (cyc==0) begin
// Setup
crc <= 64'h5aef0c8d_d70a4497;
end
else if (cyc<10) begin
end
else if (cyc<90) begin
if (result != 64'h0) begin
$display("Bit mismatch, result=%x\n", result);
$stop;
end
end
else if (cyc==99) begin
$write("[%0t] cyc==%0d crc=%x sum=%x\n",$time, cyc, crc, sum);
if (crc !== 64'hc77bb9b3784ea091) $stop;
//Child prints this: $write("*-* All Finished *-*\n");
$finish;
end
end
endmodule
+123
View File
@@ -0,0 +1,123 @@
// -*- C++ -*-
//*************************************************************************
//
// Copyright 2011-2011 by Wilson Snyder. This program is free software; you can
// redistribute it and/or modify it under the terms of either the GNU
// Lesser General Public License Version 3 or the Perl Artistic License.
// Version 2.0.
//
// Verilator is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
//*************************************************************************
#include <cstdio>
#include "svdpi.h"
#include "../t_embed1_child/Vt_embed1_child.h"
//======================================================================
#if defined(VERILATOR)
# include "Vt_embed1__Dpi.h"
#elif defined(VCS)
# include "../vc_hdrs.h"
#elif defined(CADENCE)
# define NEED_EXTERNS
#else
# error "Unknown simulator for DPI test"
#endif
#include "verilated.h"
#ifdef NEED_EXTERNS
extern "C" {
extern void t_embed_child_initial();
extern void t_embed_child_final();
extern void t_embed_child_eval();
extern void t_embed_child_io_eval(); // TODO real function params here
}
#endif
//======================================================================
extern int T_Embed_Child_Unique;
int T_Embed_Child_Unique = 0; // Address used for uniqueness
Vt_embed1_child* __get_modelp() {
svScope scope = svGetScope();
if (!scope) {
vl_fatal(__FILE__,__LINE__,__FILE__,"svGetScope failed");
return NULL;
}
void* __modelp = svGetUserData(scope, &T_Embed_Child_Unique);
if (!__modelp) {
// Create the model
const char* scopenamep = svGetNameFromScope(scope);
if (!scopenamep) vl_fatal(__FILE__,__LINE__,__FILE__,"svGetNameFromScope failed");
__modelp = new Vt_embed1_child(scopenamep);
if (svPutUserData(scope, &T_Embed_Child_Unique, __modelp)) {
vl_fatal(__FILE__,__LINE__,__FILE__,"svPutUserData failed");
}
}
return (Vt_embed1_child*)(__modelp);
}
void t_embed_child_initial() {
VL_DEBUG_IF(VL_PRINTF(" t_embed1_child_initial\n"); );
Vt_embed1_child* __modelp = __get_modelp();
__modelp->eval();
}
void t_embed_child_final() {
VL_DEBUG_IF(VL_PRINTF(" t_embed1_child_final\n"); );
Vt_embed1_child* __modelp = __get_modelp();
__modelp->final();
}
void t_embed_child_eval() {
VL_DEBUG_IF(VL_PRINTF(" t_embed1_child_eval\n"); );
Vt_embed1_child* __modelp = __get_modelp();
__modelp->eval();
}
void t_embed_child_io_eval (unsigned char clk,
unsigned char bit_in,
const svBitVecVal* vec_in,
const svBitVecVal* wide_in,
unsigned char is_ref,
unsigned char* bit_out,
svBitVecVal* vec_out,
svBitVecVal* wide_out,
unsigned char* did_init_out) {
VL_DEBUG_IF(VL_PRINTF(" t_embed1_child_io_eval\n"); );
Vt_embed1_child* __modelp = __get_modelp();
VL_DEBUG_IF(VL_PRINTF("[%0ld] in clk=%x b=%x V=%x R=%x\n",
VL_TIME_Q(), clk, bit_in, vec_in[0], is_ref););
__modelp->clk = clk;
__modelp->bit_in = bit_in;
__modelp->vec_in = vec_in[0];
__modelp->wide_in[0] = wide_in[0];
__modelp->wide_in[1] = wide_in[1];
__modelp->wide_in[2] = wide_in[2];
__modelp->wide_in[3] = wide_in[3];
__modelp->is_ref = is_ref;
//
__modelp->eval();
// TODO maybe we should look at a "change detect" to know if we need to copy
// out the variables; can return this value to the caller verilog code too
//
*bit_out = __modelp->bit_out;
vec_out[0] = __modelp->vec_out;
wide_out[0] = __modelp->wide_out[0];
wide_out[1] = __modelp->wide_out[1];
wide_out[2] = __modelp->wide_out[2];
wide_out[3] = __modelp->wide_out[3];
*did_init_out = __modelp->did_init_out;
VL_DEBUG_IF(VL_PRINTF("[%0ld] out b=%x V=%x DI=%x\n",
VL_TIME_Q(), *bit_out, *vec_out, *did_init_out););
}
+45
View File
@@ -0,0 +1,45 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed into the Public Domain, for any use,
// without warranty, 2011 by Wilson Snyder.
module t_embed1_child (/*AUTOARG*/
// Outputs
bit_out, vec_out, wide_out, did_init_out,
// Inputs
clk, bit_in, vec_in, wide_in, is_ref
);
input clk;
input bit_in;
output bit_out;
input [30:0] vec_in;
output [30:0] vec_out;
input [123:0] wide_in;
output [123:0] wide_out;
output did_init_out;
input is_ref;
reg did_init; initial did_init = 0;
initial begin
did_init = 1;
end
reg did_final; initial did_final = 0;
final begin
did_final = 1;
if (!is_ref) $write("*-* All Finished *-*\n");
//$finish is in parent
end
// Note async use!
wire bit_out = bit_in;
wire did_init_out = did_init;
always @ (posedge clk) begin
vec_out <= vec_in;
wide_out <= wide_in;
end
endmodule
+90
View File
@@ -0,0 +1,90 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed into the Public Domain, for any use,
// without warranty, 2011 by Wilson Snyder.
module t_embed1_wrap (/*AUTOARG*/
// Outputs
bit_out, vec_out, wide_out, did_init_out,
// Inputs
clk, bit_in, vec_in, wide_in, is_ref
);
/*AUTOINOUTMODULE("t_embed1_child")*/
// Beginning of automatic in/out/inouts (from specific module)
output bit_out;
output [30:0] vec_out;
output [123:0] wide_out;
output did_init_out;
input clk;
input bit_in;
input [30:0] vec_in;
input [123:0] wide_in;
input is_ref;
// End of automatics
`ifdef verilator
// Import $t_embed_child__initial etc as a DPI function
`endif
//TODO would like __'s as in {PREFIX}__initial but presently illegal for users to do this
import "DPI-C" context function void t_embed_child_initial();
import "DPI-C" context function void t_embed_child_final();
import "DPI-C" context function void t_embed_child_eval();
import "DPI-C" context function void t_embed_child_io_eval
(
//TODO we support bit, but not logic
input bit clk,
input bit bit_in,
input bit [30:0] vec_in,
input bit [123:0] wide_in,
input bit is_ref,
output bit bit_out,
output bit [30:0] vec_out,
output bit [123:0] wide_out,
output bit did_init_out);
initial begin
// Load all values
t_embed_child_initial();
end
// Only if system verilog, and if a "final" block in the code
final begin
t_embed_child_final();
end
bit _temp_bit_out;
bit _temp_did_init_out;
bit [30:0] _temp_vec_out;
bit [123:0] _temp_wide_out;
always @* begin
t_embed_child_io_eval(
clk,
bit_in,
vec_in,
wide_in,
is_ref,
_temp_bit_out,
_temp_vec_out,
_temp_wide_out,
_temp_did_init_out
);
// TODO might eliminate these temporaries
bit_out = _temp_bit_out;
did_init_out = _temp_did_init_out;
end
// Send all variables every cycle,
// or have a sensitivity routine for each?
// How to make sure we call eval at end of variable changes?
// #0 (though not verilator compatible!)
// TODO for now, we know what changes when
always @ (posedge clk) begin
vec_out <= _temp_vec_out;
wide_out <= _temp_wide_out;
end
endmodule
+12
View File
@@ -3,6 +3,13 @@
// This file ONLY is placed into the Public Domain, for any use,
// without warranty, 2009 by Wilson Snyder.
typedef enum logic [4:0]
{
BIT0 = 5'd0,
BIT1 = 5'd1,
BIT2 = 5'd2
} three_t;
module t (/*AUTOARG*/);
localparam FIVE = 5;
@@ -48,6 +55,11 @@ module t (/*AUTOARG*/);
if (three != 3'b111) $stop;
if ($bits(sized_based_on_enum) != 8) $stop;
if ($bits(three_t) != 3) $stop;
if (FIVE[BIT0] != 1'b1) $stop;
if (FIVE[BIT1] != 1'b0) $stop;
if (FIVE[BIT2] != 1'b1) $stop;
$write("*-* All Finished *-*\n");
$finish;
+2 -2
View File
@@ -1,6 +1,6 @@
// Test that environment substitutions work
-f $VERILATOR_ROOT/test_regress/t/t_flag_f__2.vc
// Env var with .v file
$VERILATOR_ROOT/test_regress/t/t_flag_f__3.v
// Env var with .v file, and parens
${VERILATOR_ROOT}/test_regress/t/t_flag_f__3.v
// Test -f
-F $VERILATOR_ROOT/test_regress/t/tsub/t_flag_f_tsub.vc
+25
View File
@@ -0,0 +1,25 @@
#!/usr/bin/perl
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# Copyright 2003 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_flag_wfatal.v");
compile (
v_flags2 => ["--lint-only -Wno-fatal"],
fails=>0,
verilator_make_gcc => 0,
make_top_shell => 0,
make_main => 0,
expect=>
q{%Warning-WIDTH: t/t_flag_wfatal.v:\d+: Operator ASSIGNW expects 4 bits on the Assign RHS, but Assign RHS.s CONST '6'h2e' generates 6 bits.
%Warning-WIDTH: Use .* and lint_on around source to disable this message.
},
) if $Self->{v3};
ok(1);
1;
+11
View File
@@ -0,0 +1,11 @@
// 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*/);
// Width error below
wire [3:0] foo = 6'h2e;
endmodule
+19
View File
@@ -0,0 +1,19 @@
#!/usr/bin/perl
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# Copyright 2003 by Wilson Snyder. This program is free software; you can
# redistribute it and/or modify it under the terms of either the GNU
# Lesser General Public License Version 3 or the Perl Artistic License
# Version 2.0.
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.
%Error: Exiting due to.*},
);
ok(1);
1;
+29
View File
@@ -0,0 +1,29 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed into the Public Domain, for any use,
// without warranty, 2003 by Wilson Snyder.
module t ();
parameter MSG_PORT_WIDTH = 4350;
localparam PAYLOAD_MAX_BITS = 4352;
reg [MSG_PORT_WIDTH-1:0] msg;
initial begin
// Operator TASKREF 'func' expects 4352 bits on the Function Argument, but Function Argument's VARREF 'msg' generates 4350 bits.
// verilator lint_off WIDTH
func(msg);
// verilator lint_on WIDTH
if (msg !== {MSG_PORT_WIDTH{1'b1}}) $stop;
$write("*-* All Finished *-*\n");
$finish;
end
function integer func (output bit [PAYLOAD_MAX_BITS-1:0] data);
/*verilator no_inline_task*/
data = {PAYLOAD_MAX_BITS{1'b1}};
return (1);
endfunction
endmodule
+1 -1
View File
@@ -62,7 +62,7 @@ module t (/*AUTOARG*/
// We never read past bounds, or get unspecific results
// We also never read lowest indexes, as writing outside of range may corrupt them
if (index0>=0+1 && index0<=2 && index1>=1+1 && index1<=3 && index2>=2+1 && index2<=5) begin
if (index0>=0+1 && index0<=2 && index1>=1+1 /*&& index1<=3 CMPCONST*/ && index2>=2+1 && index2<=5) begin
narrow <= ({narrow[6:0], narrow[7]^narrow[0]}
^ {memn[index0][index1][index2]});
wread = memw[index0][index1][index2];
+16
View File
@@ -0,0 +1,16 @@
#!/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,
) if $Self->{v3};
ok(1);
1;
+118
View File
@@ -0,0 +1,118 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed into the Public Domain, for any use,
// without warranty, 2011 by Wilson Snyder.
//
// bug354
typedef logic [5:0] data_t;
module t (/*AUTOARG*/
// Inputs
clk
);
input clk;
integer cyc=0;
reg [63:0] crc;
reg [63:0] sum;
// Take CRC data and apply to testblock inputs
wire rst;
data_t iii_in = crc[5:0];
data_t jjj_in = crc[11:6];
data_t iii_out;
data_t jjj_out;
logic [1:0] ctl0 = crc[63:62];
aaa aaa (.*);
// Aggregate outputs into a single result vector
wire [63:0] result = {64'h0};
// Test loop
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;
rst <= 1'b0;
end
else if (cyc<10) begin
sum <= 64'h0;
rst <= 1'b1;
end
else if (cyc<90) begin
rst <= 1'b0;
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'h4afe43fb79d7b71e
if (sum !== `EXPECTED_SUM) $stop;
$write("*-* All Finished *-*\n");
$finish;
end
end
endmodule
module bbb
(
output data_t ggg_out[1:0],
input data_t ggg_in [1:0],
input [1:0] [1:0] ctl,
input logic clk,
input logic rst
);
genvar i;
generate
for (i=0; i<2; i++) begin: PPP
always_ff @(posedge clk) begin
if (rst) begin
ggg_out[i] <= 6'b0;
end
else begin
if (ctl[i][0]) begin
if (ctl[i][1]) begin
ggg_out[i] <= ~ggg_in[i];
end else begin
ggg_out[i] <= ggg_in[i];
end
end
end
end
end
endgenerate
endmodule
module aaa
(
input data_t iii_in,
input data_t jjj_in,
input [1:0] ctl0,
output data_t iii_out,
output data_t jjj_out,
input logic clk,
input logic rst
);
// Below is a bug; {} concat isn't used to make arrays
bbb bbb (
.ggg_in ({jjj_in, iii_in}),
.ggg_out ({jjj_out, iii_out}),
.ctl ({{1'b1,ctl0[1]}, {1'b0,ctl0[0]}}),
.*);
endmodule
+22
View File
@@ -0,0 +1,22 @@
#!/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.
compile (
v_flags2 => ["--lint-only"],
fails=>1,
verilator_make_gcc => 0,
make_top_shell => 0,
make_main => 0,
expect=>
'%Error: t/t_param_circ_bad.v:\d+: Variable\'s initial value is circular: X
%Error: Exiting due to.*',
) if $Self->{v3};
ok(1);
1;
+12
View File
@@ -0,0 +1,12 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed into the Public Domain, for any use,
// without warranty, 2011 by Wilson Snyder.
module t (/*AUTOARG*/);
sub sub ();
endmodule
module sub #(parameter WIDTH=X, parameter X=WIDTH)
();
endmodule
+18
View File
@@ -0,0 +1,18 @@
#!/usr/bin/perl
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# Copyright 2003 by Wilson Snyder. This program is free software; you can
# redistribute it and/or modify it under the terms of either the GNU
# Lesser General Public License Version 3 or the Perl Artistic License
# Version 2.0.
compile (
);
execute (
check_finished=>1,
);
ok(1);
1;
+116
View File
@@ -0,0 +1,116 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed into the Public Domain, for any use,
// without warranty, 2011 by Wilson Snyder.
module t (/*AUTOARG*/
// Inputs
clk
);
input clk;
integer cyc=0;
reg [63:0] crc;
reg [63:0] sum;
parameter DW = 4;
wire [3:0] drv_a = crc[3:0];
wire [3:0] drv_b = crc[7:4];
wire [3:0] drv_e = crc[19:16];
/*AUTOWIRE*/
// Beginning of automatic wires (for undeclared instantiated-module outputs)
wire [DW-1:0] drv; // To/From test1 of Test1.v
wire [DW-1:0] drv2; // From test2 of Test2.v
// End of automatics
Test1 test1 (/*AUTOINST*/
// Inouts
.drv (drv[DW-1:0]),
// Inputs
.drv_a (drv_a[DW-1:0]),
.drv_b (drv_b[DW-1:0]),
.drv_e (drv_e[DW-1:0]));
Test2 test2 (/*AUTOINST*/
// Outputs
.drv2 (drv2[DW-1:0]),
// Inputs
.drv_a (drv_a[DW-1:0]),
.drv_b (drv_b[DW-1:0]),
.drv_e (drv_e[DW-1:0]));
// Aggregate outputs into a single result vector
wire [63:0] result = {60'h0, drv};
// Test loop
always @ (posedge clk) begin
`ifdef TEST_VERBOSE
$write("[%0t] cyc==%0d crc=%x drv=%x %x (%b??%b:%b)\n",$time, cyc, crc, drv, drv2, drv_e,drv_a,drv_b);
`endif
cyc <= cyc + 1;
crc <= {crc[62:0], crc[63]^crc[2]^crc[0]};
sum <= result ^ {sum[62:0],sum[63]^sum[2]^sum[0]};
if (cyc==0) begin
// Setup
crc <= 64'h5aef0c8d_d70a4497;
sum <= 64'h0;
end
else if (cyc<10) begin
sum <= 64'h0;
end
else if (cyc<90) begin
if (drv2 != drv) $stop;
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'hd95d216c5a2945d0
if (sum !== `EXPECTED_SUM) $stop;
$write("*-* All Finished *-*\n");
$finish;
end
end
endmodule
module Test1 #(
parameter DW = 4
)(
input wire [DW-1:0] drv_a,
input wire [DW-1:0] drv_b,
input wire [DW-1:0] drv_e,
inout wire [DW-1:0] drv
);
wire drv_0, drv_1, drv_2, drv_3;
bufif1 bufa0 (drv_0, drv_a[0], drv_e[0]);
bufif1 bufb0 (drv_0, drv_b[0], ~drv_e[0]);
bufif1 bufa1 (drv_1, drv_a[1], drv_e[1]);
bufif1 bufb1 (drv_1, drv_b[1], ~drv_e[1]);
bufif1 bufa2 (drv_2, drv_a[2], drv_e[2]);
bufif1 bufb2 (drv_2, drv_b[2], ~drv_e[2]);
bufif1 bufa3 (drv_3, drv_a[3], drv_e[3]);
bufif1 bufb3 (drv_3, drv_b[3], ~drv_e[3]);
assign drv = {drv_3,drv_2,drv_1,drv_0};
endmodule
module Test2 #(
parameter DW = 4
)(
input wire [DW-1:0] drv_a,
input wire [DW-1:0] drv_b,
input wire [DW-1:0] drv_e,
inout wire [DW-1:0] drv2
);
wire [DW-1:0] drv_all;
bufif1 bufa [DW-1:0] (drv_all, drv_a, drv_e);
// Below ~= bufif1 bufb [DW-1:0] (drv_all, drv_b, ~drv_e);
bufif1 bufb [DW-1:0] ({drv_all[3], drv_all[2], drv_all[1], drv_all[0]},
{drv_b[3], drv_b[2], drv_b[1], drv_b[0]},
{~drv_e[3], ~drv_e[2], ~drv_e[1], ~drv_e[0]});
assign drv2 = drv_all;
endmodule
+23
View File
@@ -118,6 +118,29 @@ module t (/*AUTOARG*/
if (total != -28) $stop;
end
//===
10: begin
// mostly cover a small index
total = 0;
for (i3=0; i3<3'd7; i3=i3+3'd1) begin
total = total - {29'd0,i3} -1;
dly_to_insure_was_unrolled[i3[0]] <= 0;
end
if (total != -28) $stop;
end
//===
11: begin
// width violation on <, causes extend
total = 0;
for (i3=3'd0; i3<7; i3=i3+1) begin
total = total - {29'd0,i3} -1;
dly_to_insure_was_unrolled[i3[0]] <= 0;
end
if (total != -28) $stop;
end
//===
// width violation on <, causes extend signed
// Unsupported as yet
//===
19: begin
$write("*-* All Finished *-*\n");
$finish;