mirror of
https://github.com/verilator/verilator.git
synced 2026-10-05 09:33:41 +02:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
344248cea0 | ||
|
|
2789e3dba5 | ||
|
|
cca759a41e | ||
|
|
4f7b3d8882 | ||
|
|
2b330b78b7 | ||
|
|
d47ca1912b | ||
|
|
cdf18c96f4 | ||
|
|
53acaa05b8 | ||
|
|
fb85679068 | ||
|
|
9558e14479 | ||
|
|
4af0af93bf | ||
|
|
df4bc950fe | ||
|
|
250394f72b | ||
|
|
d5e9e7cd2b | ||
|
|
9a96f621ef | ||
|
|
5d7ce096c6 | ||
|
|
c9f8109c06 | ||
|
|
a20b4f2864 | ||
|
|
44a19d2a0a | ||
|
|
02f3beb8db | ||
|
|
3269cc3d90 | ||
|
|
fb70a1f4ab | ||
|
|
df0aa483ce | ||
|
|
c83f12a55c | ||
|
|
9704f59566 | ||
|
|
2923893d34 | ||
|
|
890dab0742 | ||
|
|
607e26b041 | ||
|
|
ea75290f65 | ||
|
|
a176054118 | ||
|
|
9a697dc5f5 | ||
|
|
cfdb852843 | ||
|
|
2e67a91982 | ||
|
|
074ca9330d | ||
|
|
f0d7cdcb20 |
@@ -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
@@ -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
@@ -1633,6 +1633,6 @@ static inline WDataOutP VL_CONST_W_9X(int obits, WDataOutP o,
|
||||
|
||||
#undef _END
|
||||
|
||||
// Debugging
|
||||
//======================================================================
|
||||
|
||||
#endif /*_VERILATED_H_*/
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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__
|
||||
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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}");
|
||||
|
||||
@@ -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
@@ -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)) {
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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();
|
||||
|
||||
@@ -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
@@ -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}/...
|
||||
}
|
||||
|
||||
@@ -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; }
|
||||
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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());
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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
@@ -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
@@ -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,
|
||||
|
||||
Executable
+18
@@ -0,0 +1,18 @@
|
||||
#!/usr/bin/perl
|
||||
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
|
||||
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||
#
|
||||
# Copyright 2003 by Wilson Snyder. This program is free software; you can
|
||||
# redistribute it and/or modify it under the terms of either the GNU
|
||||
# Lesser General Public License Version 3 or the Perl Artistic License
|
||||
# Version 2.0.
|
||||
|
||||
compile (
|
||||
);
|
||||
|
||||
execute (
|
||||
check_finished=>1,
|
||||
);
|
||||
|
||||
ok(1);
|
||||
1;
|
||||
@@ -0,0 +1,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
|
||||
Executable
+24
@@ -0,0 +1,24 @@
|
||||
#!/usr/bin/perl
|
||||
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
|
||||
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||
#
|
||||
# Copyright 2003 by Wilson Snyder. This program is free software; you can
|
||||
# redistribute it and/or modify it under the terms of either the GNU
|
||||
# Lesser General Public License Version 3 or the Perl Artistic License
|
||||
# Version 2.0.
|
||||
|
||||
$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;
|
||||
@@ -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
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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); }
|
||||
|
||||
//======================================================================
|
||||
|
||||
Executable
+51
@@ -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;
|
||||
@@ -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
|
||||
@@ -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););
|
||||
}
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
Executable
+25
@@ -0,0 +1,25 @@
|
||||
#!/usr/bin/perl
|
||||
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
|
||||
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||
#
|
||||
# Copyright 2003 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;
|
||||
@@ -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
|
||||
Executable
+19
@@ -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;
|
||||
@@ -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
|
||||
@@ -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];
|
||||
|
||||
Executable
+16
@@ -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;
|
||||
@@ -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
|
||||
Executable
+22
@@ -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;
|
||||
@@ -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
|
||||
Executable
+18
@@ -0,0 +1,18 @@
|
||||
#!/usr/bin/perl
|
||||
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
|
||||
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||
#
|
||||
# Copyright 2003 by Wilson Snyder. This program is free software; you can
|
||||
# redistribute it and/or modify it under the terms of either the GNU
|
||||
# Lesser General Public License Version 3 or the Perl Artistic License
|
||||
# Version 2.0.
|
||||
|
||||
compile (
|
||||
);
|
||||
|
||||
execute (
|
||||
check_finished=>1,
|
||||
);
|
||||
|
||||
ok(1);
|
||||
1;
|
||||
@@ -0,0 +1,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
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user