mirror of
https://github.com/verilator/verilator.git
synced 2026-10-06 01:54:01 +02:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7c3c2af90b | ||
|
|
6dca9b4ba4 | ||
|
|
ede37bb9d8 | ||
|
|
4a1729eaab | ||
|
|
b1565f5b89 | ||
|
|
4fb8dcfd4e | ||
|
|
16d1f2b835 | ||
|
|
73594e5aa5 | ||
|
|
c0a365bd34 | ||
|
|
45940ff820 | ||
|
|
d545ae242c | ||
|
|
e862aaf2e1 | ||
|
|
30c3540086 | ||
|
|
663a084ca4 | ||
|
|
b4d9ccd9af | ||
|
|
98fff6a4ce | ||
|
|
4977a5e1d9 | ||
|
|
e4297486ef | ||
|
|
ad591767c9 |
@@ -3,6 +3,41 @@ Revision history for Verilator
|
|||||||
The contributors that suggested a given feature are shown in []. [by ...]
|
The contributors that suggested a given feature are shown in []. [by ...]
|
||||||
indicates the contributor was also the author of the fix; Thanks!
|
indicates the contributor was also the author of the fix; Thanks!
|
||||||
|
|
||||||
|
* Verilator 3.660 2008/03/23
|
||||||
|
|
||||||
|
*** Add support for hard-coding VERILATOR_ROOT etc in the executables,
|
||||||
|
to enable easier use of Verilator RPMs. [Gunter Dannoritzer]
|
||||||
|
|
||||||
|
*** Allow multiple .v files on command line. [Stefan Thiede]
|
||||||
|
|
||||||
|
*** Convert re-defining macro error to warning. [Stefan Thiede]
|
||||||
|
|
||||||
|
*** Add --error-limit option. [Stefan Thiede]
|
||||||
|
|
||||||
|
*** Allow __ in cell names by quoting them in C. [Stefan Thiede]
|
||||||
|
|
||||||
|
**** Fix genvar to be signed, so "< 0" works properly. [Niranjan Prabhu]
|
||||||
|
|
||||||
|
**** Fix assignments to inputs inside functions/tasks. [Patricio Kaplan]
|
||||||
|
|
||||||
|
**** Fix definitions in main file.v, referenced in library. [Stefan Thiede]
|
||||||
|
|
||||||
|
**** Fix undefined assigns to be implicit warnings. [Stefan Thiede]
|
||||||
|
|
||||||
|
* Verilator 3.658 2008/02/25
|
||||||
|
|
||||||
|
**** Fix unistd compile error in 3.657. [Patricio Kaplan, Jonathan Kimmitt]
|
||||||
|
|
||||||
|
* Verilator 3.657 2008/02/20
|
||||||
|
|
||||||
|
**** Fix assignments of {a,b,c} = {c,b,a}. [Jonathan Kimmitt]
|
||||||
|
|
||||||
|
**** Fix Perl warning with --lint-only. [by Ding Xiaoliang]
|
||||||
|
|
||||||
|
**** Avoid creating obj_dir with --lint-only. [Ding Xiaoliang]
|
||||||
|
|
||||||
|
**** Fix parsing of always @(*). [Patricio Kaplan]
|
||||||
|
|
||||||
* Verilator 3.656 2008/01/18
|
* Verilator 3.656 2008/01/18
|
||||||
|
|
||||||
**** Wide VL_CONST_W_#X functions are now made automatically. [Bernard Deadman]
|
**** Wide VL_CONST_W_#X functions are now made automatically. [Bernard Deadman]
|
||||||
|
|||||||
+18
-5
@@ -78,6 +78,7 @@ datadir = @datadir@
|
|||||||
infodir = @infodir@
|
infodir = @infodir@
|
||||||
|
|
||||||
# Directory in which to install package specific files
|
# Directory in which to install package specific files
|
||||||
|
# Generally ${prefix}/share/verilator
|
||||||
pkgdatadir = @pkgdatadir@
|
pkgdatadir = @pkgdatadir@
|
||||||
|
|
||||||
#### End of system configuration section. ####
|
#### End of system configuration section. ####
|
||||||
@@ -140,6 +141,7 @@ msg_test:
|
|||||||
@echo "Type 'make test' to test."
|
@echo "Type 'make test' to test."
|
||||||
@echo
|
@echo
|
||||||
|
|
||||||
|
.PHONY:test
|
||||||
ifeq ($(VERILATOR_AUTHOR_SITE),1) # Local... Else don't burden users
|
ifeq ($(VERILATOR_AUTHOR_SITE),1) # Local... Else don't burden users
|
||||||
test: test_vcs test_c test_sc test_sp test_verilated test_regress
|
test: test_vcs test_c test_sc test_sp test_verilated test_regress
|
||||||
else
|
else
|
||||||
@@ -203,21 +205,31 @@ README: readme.texi
|
|||||||
$(MAKEINFO) -I$(srcdir) $(srcdir)/readme.texi --output=$@ \
|
$(MAKEINFO) -I$(srcdir) $(srcdir)/readme.texi --output=$@ \
|
||||||
--no-headers --no-validate
|
--no-headers --no-validate
|
||||||
|
|
||||||
installdirs:
|
|
||||||
$(SHELL) ${srcdir}/mkinstalldirs $(bindir) $(infodir)
|
|
||||||
|
|
||||||
# See uninstall also
|
# See uninstall also
|
||||||
VL_INST_BIN_FILES = verilator
|
VL_INST_BIN_FILES = verilator verilator_bin verilator_bin_dbg
|
||||||
installbin:
|
installbin:
|
||||||
|
$(SHELL) ${srcdir}/mkinstalldirs $(bindir)
|
||||||
( cd bin ; $(INSTALL_PROGRAM) verilator $(bindir)/verilator )
|
( cd bin ; $(INSTALL_PROGRAM) verilator $(bindir)/verilator )
|
||||||
|
( $(INSTALL_PROGRAM) verilator_bin $(bindir)/verilator_bin )
|
||||||
|
( $(INSTALL_PROGRAM) verilator_bin_dbg $(bindir)/verilator_bin_dbg )
|
||||||
|
|
||||||
VL_INST_MAN_FILES = verilator.1
|
VL_INST_MAN_FILES = verilator.1
|
||||||
installman:
|
installman:
|
||||||
|
$(SHELL) ${srcdir}/mkinstalldirs $(mandir)
|
||||||
for p in $(VL_INST_MAN_FILES) ; do \
|
for p in $(VL_INST_MAN_FILES) ; do \
|
||||||
$(INSTALL_PROGRAM) $$p $(mandir)/man1/$$p; \
|
$(INSTALL_PROGRAM) $$p $(mandir)/man1/$$p; \
|
||||||
done
|
done
|
||||||
|
|
||||||
install: all_nomsg installdirs installbin installman install-msg
|
installdata:
|
||||||
|
$(SHELL) ${srcdir}/mkinstalldirs $(pkgdatadir)/examples
|
||||||
|
cp -r include $(pkgdatadir)
|
||||||
|
cp -r src $(pkgdatadir)
|
||||||
|
cp -r test_c $(pkgdatadir)/examples
|
||||||
|
cp -r test_sc $(pkgdatadir)/examples
|
||||||
|
cp -r test_sp $(pkgdatadir)/examples
|
||||||
|
|
||||||
|
VL_INST_DATA_FILES = verilator.1
|
||||||
|
install: all_nomsg installbin installman installdata install-msg
|
||||||
|
|
||||||
install-here: installman ftp
|
install-here: installman ftp
|
||||||
|
|
||||||
@@ -263,6 +275,7 @@ install-msg:
|
|||||||
uninstall:
|
uninstall:
|
||||||
-cd $(mandir)/man1 && rm -f $(VL_INST_MAN_FILES)
|
-cd $(mandir)/man1 && rm -f $(VL_INST_MAN_FILES)
|
||||||
-cd $(bindir) && rm -f $(VL_INST_BIN_FILES)
|
-cd $(bindir) && rm -f $(VL_INST_BIN_FILES)
|
||||||
|
-rm -f $(pkgdatadir)
|
||||||
|
|
||||||
# autoheader might not change config_build.h.in, so touch a stamp file.
|
# autoheader might not change config_build.h.in, so touch a stamp file.
|
||||||
IN_WILD := ${srcdir}/*.in ${srcdir}/*/*.in ${srcdir}/*/*/*.in \
|
IN_WILD := ${srcdir}/*.in ${srcdir}/*/*.in ${srcdir}/*/*/*.in \
|
||||||
|
|||||||
@@ -52,6 +52,10 @@ Usability:
|
|||||||
Better reporting of unopt problems, including what lines of code
|
Better reporting of unopt problems, including what lines of code
|
||||||
Report more errors (all of them?) before exiting [Eugene Weber]
|
Report more errors (all of them?) before exiting [Eugene Weber]
|
||||||
|
|
||||||
|
Internal Code:
|
||||||
|
Eliminate the AstNUser* passed to all visitors; its only needed in V3Width,
|
||||||
|
and removing it will speed up and simplify all the other code.
|
||||||
|
|
||||||
Performance:
|
Performance:
|
||||||
Constant propagation
|
Constant propagation
|
||||||
Extra cleaning AND: 1 & ((VARREF >> 1) | ((&VARREF >> 1) & VARREF))
|
Extra cleaning AND: 1 & ((VARREF >> 1) | ((&VARREF >> 1) & VARREF))
|
||||||
|
|||||||
+67
-70
@@ -34,27 +34,7 @@ use Config;
|
|||||||
use Cwd qw(abs_path getcwd);
|
use Cwd qw(abs_path getcwd);
|
||||||
|
|
||||||
use strict;
|
use strict;
|
||||||
use vars qw ($Debug %Vars $Opt $Opt_Make_Dir $Opt_Sp @Opt_Verilator_Sw
|
use vars qw ($Debug @Opt_Verilator_Sw);
|
||||||
$Opt_Trace
|
|
||||||
%Modules
|
|
||||||
);
|
|
||||||
|
|
||||||
#######################################################################
|
|
||||||
# Global constants -- Configuration info
|
|
||||||
|
|
||||||
# Where to find real executables
|
|
||||||
# We could find it by using $RealBin, but we require this path
|
|
||||||
# so that when the user runs make, they will have it and not get strange error.
|
|
||||||
$ENV{VERILATOR_ROOT} or die "%Error: verilator: VERILATOR_ROOT needs to be in environment\n";
|
|
||||||
print "export VERILATOR_ROOT=$ENV{VERILATOR_ROOT}\n" if $Debug;
|
|
||||||
|
|
||||||
# Read by verilator for populating makefile
|
|
||||||
if (!defined $ENV{SYSTEMC_ARCH}) {
|
|
||||||
$ENV{SYSTEMC_ARCH} ||= (($Config{osname} =~ /solaris/i && "gccsparcOS5")
|
|
||||||
|| ($Config{osname} =~ /cygwin/i && "cygwin")
|
|
||||||
|| "linux");
|
|
||||||
print "export SYSTEMC_ARCH=$ENV{SYSTEMC_ARCH}\n" if $Debug;
|
|
||||||
}
|
|
||||||
|
|
||||||
#######################################################################
|
#######################################################################
|
||||||
#######################################################################
|
#######################################################################
|
||||||
@@ -65,7 +45,6 @@ autoflush STDERR 1;
|
|||||||
|
|
||||||
$Debug = 0;
|
$Debug = 0;
|
||||||
my $opt_gdb;
|
my $opt_gdb;
|
||||||
$Opt_Sp = undef;
|
|
||||||
|
|
||||||
# No arguments can't do anything useful. Give help
|
# No arguments can't do anything useful. Give help
|
||||||
if ($#ARGV < 0) {
|
if ($#ARGV < 0) {
|
||||||
@@ -84,33 +63,15 @@ if (! GetOptions (
|
|||||||
# Major operating modes
|
# Major operating modes
|
||||||
"help" => \&usage,
|
"help" => \&usage,
|
||||||
"debug:s" => \&debug,
|
"debug:s" => \&debug,
|
||||||
"version!" => \&version,
|
# "version!" => \&version, # Also passthru'ed
|
||||||
# Switches
|
# Switches
|
||||||
"gdb=s" => \$opt_gdb, # Undocumented debugging
|
"gdb=s" => \$opt_gdb, # Undocumented debugging
|
||||||
"trace!" => \$Opt_Trace,
|
|
||||||
"sp!" => sub {$Opt_Sp = 'sp';},
|
|
||||||
"sc!" => sub {$Opt_Sp = 'sc';},
|
|
||||||
"cc!" => sub {$Opt_Sp = 0;},
|
|
||||||
#"ignc!" => ..., # Undocumented debugging, disable $c but don't complain
|
|
||||||
# Additional parameters
|
# Additional parameters
|
||||||
"<>" => sub {}, # Ignored
|
"<>" => sub {}, # Ignored
|
||||||
)) {
|
)) {
|
||||||
pod2usage(-exitstatus=>2, -verbose=>0);
|
pod2usage(-exitstatus=>2, -verbose=>0);
|
||||||
}
|
}
|
||||||
|
|
||||||
# Check configuration
|
|
||||||
if ($Opt_Sp) {
|
|
||||||
(defined $ENV{SYSTEMC}) or die "%Error: verilator: Need \$SYSTEMC in environment\nProbably System-C isn't installed, see http://www.systemc.org\n";
|
|
||||||
}
|
|
||||||
if ($Opt_Sp eq 'sp' || $Opt_Trace) {
|
|
||||||
if (!defined $ENV{SYSTEMPERL}) {
|
|
||||||
my $try = "$ENV{W}/hw/utils/perltools/SystemC";
|
|
||||||
$ENV{SYSTEMPERL} = $try if -d $try;
|
|
||||||
}
|
|
||||||
(defined $ENV{SYSTEMPERL}) or die "%Error: verilator: Need \$SYSTEMPERL in environment for --sp or --trace\nProbably System-Perl isn't installed, see http://www.veripool.com/systemperl.html\n";
|
|
||||||
(-d "$ENV{SYSTEMPERL}/src") or die "%Error: verilator: \$SYSTEMPERL environment var doesn't seem to point to System-Perl kit\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
# Determine runtime flags
|
# Determine runtime flags
|
||||||
my $vcmd =(($opt_gdb?"$opt_gdb ":"")
|
my $vcmd =(($opt_gdb?"$opt_gdb ":"")
|
||||||
.verilator_bin()
|
.verilator_bin()
|
||||||
@@ -123,7 +84,6 @@ run ($vcmd);
|
|||||||
#----------------------------------------------------------------------
|
#----------------------------------------------------------------------
|
||||||
|
|
||||||
sub usage {
|
sub usage {
|
||||||
bin_version();
|
|
||||||
print '$Revision$$Date$ ', "\n";
|
print '$Revision$$Date$ ', "\n";
|
||||||
pod2usage(-exitstatus=>2, -verbose=>2);
|
pod2usage(-exitstatus=>2, -verbose=>2);
|
||||||
}
|
}
|
||||||
@@ -134,23 +94,16 @@ sub debug {
|
|||||||
$Debug = $level||3;
|
$Debug = $level||3;
|
||||||
}
|
}
|
||||||
|
|
||||||
sub version {
|
|
||||||
bin_version();
|
|
||||||
exit (0);
|
|
||||||
}
|
|
||||||
|
|
||||||
sub bin_version {
|
|
||||||
($ENV{VERILATOR_ROOT}) or print "%Warning: Unknown rev: VERILATOR_ROOT undefined\n";
|
|
||||||
run (verilator_bin()." --version");
|
|
||||||
}
|
|
||||||
|
|
||||||
#######################################################################
|
#######################################################################
|
||||||
#######################################################################
|
#######################################################################
|
||||||
# Builds
|
# Builds
|
||||||
|
|
||||||
sub verilator_bin {
|
sub verilator_bin {
|
||||||
my $bin = "$ENV{VERILATOR_ROOT}/".($ENV{VERILATOR_BIN}||"verilator_bin");
|
my $bin = "";
|
||||||
if ($Debug && -x "${bin}_dbg") { $bin = "${bin}_dbg"; }
|
# Use VERILATOR_ROOT if defined, else assume verilator_bin is in the search path
|
||||||
|
$bin .= $ENV{VERILATOR_ROOT}."/" if defined($ENV{VERILATOR_ROOT});
|
||||||
|
$bin .= ($ENV{VERILATOR_BIN}||"verilator_bin");
|
||||||
|
if ($Debug) { $bin = "${bin}_dbg"; }
|
||||||
return $bin;
|
return $bin;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -165,8 +118,11 @@ sub run {
|
|||||||
system($command);
|
system($command);
|
||||||
my $status = $?;
|
my $status = $?;
|
||||||
if ($status) {
|
if ($status) {
|
||||||
|
if ($! =~ /no such file or directory/i) {
|
||||||
|
warn "%Error: verilator: Misinstalled, or VERILATOR_ROOT might need to be in environment\n";
|
||||||
|
}
|
||||||
if ($Debug) { # For easy rerunning
|
if ($Debug) { # For easy rerunning
|
||||||
warn "%Error: export VERILATOR_ROOT=$ENV{VERILATOR_ROOT}\n";
|
warn "%Error: export VERILATOR_ROOT=".($ENV{VERILATOR_ROOT}||"")."\n";
|
||||||
warn "%Error: $command\n";
|
warn "%Error: $command\n";
|
||||||
}
|
}
|
||||||
die "%Error: Command Failed $command\n";
|
die "%Error: Command Failed $command\n";
|
||||||
@@ -234,6 +190,7 @@ descriptions in the next sections for more information.
|
|||||||
--debug-check Enable debugging assertions
|
--debug-check Enable debugging assertions
|
||||||
--dump-tree Enable dumping .tree files
|
--dump-tree Enable dumping .tree files
|
||||||
-E Preprocess, but do not compile
|
-E Preprocess, but do not compile
|
||||||
|
--error-limit <value> Abort after this number of errors
|
||||||
--exe Link to create executable
|
--exe Link to create executable
|
||||||
-f <file> Parse options from a file
|
-f <file> Parse options from a file
|
||||||
--help Display this help.
|
--help Display this help.
|
||||||
@@ -392,6 +349,11 @@ Preprocess the source code, but do not compile, as with 'gcc -E'. Output
|
|||||||
is written to standard out. Beware of enabling debugging messages, as they
|
is written to standard out. Beware of enabling debugging messages, as they
|
||||||
will also go to standard out.
|
will also go to standard out.
|
||||||
|
|
||||||
|
=item --error-limit <value>
|
||||||
|
|
||||||
|
After this number of errors or warnings are encountered, exit. Defaults to
|
||||||
|
50.
|
||||||
|
|
||||||
=item --exe
|
=item --exe
|
||||||
|
|
||||||
Generate a executable. You will also need to pass additional .cpp files on
|
Generate a executable. You will also need to pass additional .cpp files on
|
||||||
@@ -434,7 +396,7 @@ to gcc -MP option.
|
|||||||
=item --Mdir I<directory>
|
=item --Mdir I<directory>
|
||||||
|
|
||||||
Specifies the name of the Make object directory. All generated files will
|
Specifies the name of the Make object directory. All generated files will
|
||||||
be placed in this directory.
|
be placed in this directory. If not specified, "obj_dir" is used.
|
||||||
|
|
||||||
=item --mod-prefix I<topname>
|
=item --mod-prefix I<topname>
|
||||||
|
|
||||||
@@ -489,8 +451,8 @@ the backward-compatible default of sc_bv's.
|
|||||||
|
|
||||||
=item --prefix I<topname>
|
=item --prefix I<topname>
|
||||||
|
|
||||||
Specifies the name of the top level class. Defaults to the name of the top
|
Specifies the name of the top level class. Defaults to the name of the first
|
||||||
level Verilog module.
|
Verilog file passed on the command line.
|
||||||
|
|
||||||
=item --profile-cfuncs
|
=item --profile-cfuncs
|
||||||
|
|
||||||
@@ -871,14 +833,16 @@ After running Make, the C++ compiler should produce the following:
|
|||||||
|
|
||||||
Required for SystemC output mode. If set, specifies the directory
|
Required for SystemC output mode. If set, specifies the directory
|
||||||
containing the SystemC distribution. This is used to find the SystemC
|
containing the SystemC distribution. This is used to find the SystemC
|
||||||
include files.
|
include files. If not specified, it will come from a default optionally
|
||||||
|
specified at configure time (before Verilator was compiled).
|
||||||
|
|
||||||
=item SYSTEMC_ARCH
|
=item SYSTEMC_ARCH
|
||||||
|
|
||||||
Specifies the architecture name used by the SystemC kit. This is the part
|
Specifies the architecture name used by the SystemC kit. This is the part
|
||||||
after the dash in the lib-{...} directory name created by a 'make' in the
|
after the dash in the lib-{...} directory name created by a 'make' in the
|
||||||
SystemC distribution. If not set, Verilator will try to intuit the proper
|
SystemC distribution. If not set, Verilator will try to intuit the proper
|
||||||
setting.
|
setting, or use the default optionally specified at configure time (before
|
||||||
|
Verilator was compiled). .
|
||||||
|
|
||||||
=item SYSTEMC_CXX_FLAGS
|
=item SYSTEMC_CXX_FLAGS
|
||||||
|
|
||||||
@@ -888,7 +852,9 @@ building the SystemC model.
|
|||||||
=item SYSTEMPERL
|
=item SYSTEMPERL
|
||||||
|
|
||||||
Specifies the directory containing the Verilog-Perl distribution kit. This
|
Specifies the directory containing the Verilog-Perl distribution kit. This
|
||||||
is used to find the Verilog-Perl library and include files.
|
is used to find the Verilog-Perl library and include files. If not
|
||||||
|
specified, it will come from a default optionally specified at configure
|
||||||
|
time (before Verilator was compiled).
|
||||||
|
|
||||||
=item VCS_HOME
|
=item VCS_HOME
|
||||||
|
|
||||||
@@ -904,7 +870,9 @@ for debugging and selecting between multiple operating system builds.
|
|||||||
=item VERILATOR_ROOT
|
=item VERILATOR_ROOT
|
||||||
|
|
||||||
Specifies the directory containing the distribution kit. This is used to
|
Specifies the directory containing the distribution kit. This is used to
|
||||||
find the executable, Perl library, and include files.
|
find the executable, Perl library, and include files. If not specified, it
|
||||||
|
will come from a default optionally specified at configure time (before
|
||||||
|
Verilator was compiled).
|
||||||
|
|
||||||
=back
|
=back
|
||||||
|
|
||||||
@@ -1733,6 +1701,23 @@ not really needed. The best solution is to insure that each module is in a
|
|||||||
unique file by the same name. Otherwise, make sure all library files are
|
unique file by the same name. Otherwise, make sure all library files are
|
||||||
read in as libraries with -v, instead of automatically with -y.
|
read in as libraries with -v, instead of automatically with -y.
|
||||||
|
|
||||||
|
=item REDEFMACRO
|
||||||
|
|
||||||
|
Warns that you have redefined the same macro with a different value, for
|
||||||
|
example:
|
||||||
|
|
||||||
|
`define MACRO def1
|
||||||
|
//...
|
||||||
|
`define MACRO otherdef
|
||||||
|
|
||||||
|
The best solution is to use a different name for the second macro. If this
|
||||||
|
is not possible, add a undef to indicate the code is overriding the value:
|
||||||
|
|
||||||
|
`define MACRO def1
|
||||||
|
//...
|
||||||
|
`undef MACRO
|
||||||
|
`define MACRO otherdef
|
||||||
|
|
||||||
=item STMTDLY
|
=item STMTDLY
|
||||||
|
|
||||||
Warns that you have a statement with a delayed time in front of it, for
|
Warns that you have a statement with a delayed time in front of it, for
|
||||||
@@ -1943,11 +1928,14 @@ Visual C++ Version 7 or newer, but this is not tested by the author.
|
|||||||
|
|
||||||
=item Can you provide binaries?
|
=item Can you provide binaries?
|
||||||
|
|
||||||
At this time I'd prefer to get patches out quickly than have to generate
|
Verilator is available as a RPM for SuSE and perhaps other systems; this is
|
||||||
myriad binaries for many different OS flavors. People have generally
|
done by porters and may slightly lag the primary distribution. If there
|
||||||
requested binaries when they are having problems with their C++
|
isn't a binary build for your distribution, how about you set one up?
|
||||||
compiler. Alas, binaries won't help this, as in the end a fully working C++
|
Please contact the authors for assistance.
|
||||||
compiler is required to compile the output of Verilator.
|
|
||||||
|
Note people sometimes request binaries when they are having problems with
|
||||||
|
their C++ compiler. Alas, binaries won't help this, as in the end a fully
|
||||||
|
working C++ compiler is required to compile the output of Verilator.
|
||||||
|
|
||||||
=item How can it be faster than (name-the-simulator)?
|
=item How can it be faster than (name-the-simulator)?
|
||||||
|
|
||||||
@@ -2030,15 +2018,24 @@ the "verilator" define for you, so just wrap the code in a ifndef region:
|
|||||||
|
|
||||||
=item Why do I get "unexpected `do'" or "unexpected `bit'" errors?
|
=item Why do I get "unexpected `do'" or "unexpected `bit'" errors?
|
||||||
|
|
||||||
Do, bit, ref, and other words are now SystemVerilog keywords. You should
|
Do, bit, ref, return, and other words are now SystemVerilog keywords. You
|
||||||
change your code to not use them to insure it works with newer tools.
|
should change your code to not use them to insure it works with newer
|
||||||
Alternatively, surround them by the Verilog 2005/SystemVerilog
|
tools. Alternatively, surround them by the Verilog 2005/SystemVerilog
|
||||||
begin_keywords pragma to indicate Verilog 2001 code.
|
begin_keywords pragma to indicate Verilog 2001 code.
|
||||||
|
|
||||||
`begin_keywords "1364-2001"
|
`begin_keywords "1364-2001"
|
||||||
integer bit; initial bit = 1;
|
integer bit; initial bit = 1;
|
||||||
`end_keywords
|
`end_keywords
|
||||||
|
|
||||||
|
If you want the whole file to be parsed as Verilog 2001, just create a
|
||||||
|
file with
|
||||||
|
|
||||||
|
`begin_keywords "1364-2001"
|
||||||
|
|
||||||
|
and add it before other Verilog files on the command line. (Note this will
|
||||||
|
also change the default for --prefix, so if you're not using --prefix, you
|
||||||
|
will now need to.)
|
||||||
|
|
||||||
=item How do I prevent my assertions from firing during reset?
|
=item How do I prevent my assertions from firing during reset?
|
||||||
|
|
||||||
Call Verilated::assertOn(false) before you first call the model, then turn
|
Call Verilated::assertOn(false) before you first call the model, then turn
|
||||||
|
|||||||
@@ -9,6 +9,10 @@ AC_INIT(src/Verilator.cpp)
|
|||||||
AC_CONFIG_HEADER(src/config_build.h)
|
AC_CONFIG_HEADER(src/config_build.h)
|
||||||
|
|
||||||
dnl Special Substitutions
|
dnl Special Substitutions
|
||||||
|
AC_ARG_ENABLE(defenv,
|
||||||
|
[AS_HELP_STRING([--enable-defenv], [hardcode default environment variables])],
|
||||||
|
CFG_WITH_DEFENV=1,)
|
||||||
|
AC_SUBST(CFG_WITH_DEFENV)
|
||||||
|
|
||||||
dnl Checks for programs.
|
dnl Checks for programs.
|
||||||
CXX=g++
|
CXX=g++
|
||||||
|
|||||||
@@ -126,6 +126,12 @@ do a @code{make sc_patch}.
|
|||||||
@item
|
@item
|
||||||
Type @samp{./configure} to configure Verilator for your system.
|
Type @samp{./configure} to configure Verilator for your system.
|
||||||
|
|
||||||
|
If you are configuring Verilator to be part of a RPM or other
|
||||||
|
distribution package system, you may want to use the --enable-defenv
|
||||||
|
configure flag. This will take the current value of VERILATOR_ROOT,
|
||||||
|
SYSTEMC, SYSTEMC_ARCH, and SYSTEMPERL and build them as defaults into
|
||||||
|
the executable.
|
||||||
|
|
||||||
@item
|
@item
|
||||||
Type @samp{make} to compile Verilator.
|
Type @samp{make} to compile Verilator.
|
||||||
|
|
||||||
|
|||||||
@@ -30,6 +30,14 @@ LINK = @CXX@
|
|||||||
|
|
||||||
LDFLAGS += @LDFLAGS@
|
LDFLAGS += @LDFLAGS@
|
||||||
|
|
||||||
|
CFG_WITH_DEFENV = @CFG_WITH_DEFENV@
|
||||||
|
|
||||||
|
prefix = @prefix@
|
||||||
|
|
||||||
|
# Directory in which to install package specific files
|
||||||
|
# Generally ${prefix}/share/verilator
|
||||||
|
pkgdatadir = @pkgdatadir@
|
||||||
|
|
||||||
#### End of system configuration section. ####
|
#### End of system configuration section. ####
|
||||||
|
|
||||||
VPATH += . $(srcdir)
|
VPATH += . $(srcdir)
|
||||||
@@ -70,6 +78,19 @@ CPPFLAGS += -W -Wall -Wno-unused-parameter -Wno-char-subscripts -Werror
|
|||||||
#CPPFLAGS += -pedantic-errors
|
#CPPFLAGS += -pedantic-errors
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
# Allow RPM builds to specify hardcoded data directories
|
||||||
|
# To do this:
|
||||||
|
ifneq ($(CFG_WITH_DEFENV),)
|
||||||
|
CPPFLAGS += -DDEFENV_SYSTEMC=\"$(SYSTEMC)\"
|
||||||
|
CPPFLAGS += -DDEFENV_SYSTEMC_ARCH=\"$(SYSTEMC_ARCH)\"
|
||||||
|
CPPFLAGS += -DDEFENV_SYSTEMPERL=\"$(SYSTEMPERL)\"
|
||||||
|
ifeq ($(VERILATOR_ROOT),) # Use what we're given, or intuit
|
||||||
|
CPPFLAGS += -DDEFENV_VERILATOR_ROOT=\"$(pkgdatadir)\"
|
||||||
|
else
|
||||||
|
CPPFLAGS += -DDEFENV_VERILATOR_ROOT=\"$(VERILATOR_ROOT)\"
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
|
||||||
HEADERS = $(wildcard V*.h v*.h)
|
HEADERS = $(wildcard V*.h v*.h)
|
||||||
|
|
||||||
ASTGEN = $(srcdir)/astgen
|
ASTGEN = $(srcdir)/astgen
|
||||||
|
|||||||
@@ -83,6 +83,20 @@ void AstNode::init() {
|
|||||||
m_user5Cnt = 0;
|
m_user5Cnt = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
string AstNode::encodeName(const string& namein) {
|
||||||
|
string name2 = namein;
|
||||||
|
string out;
|
||||||
|
for (string::iterator pos = name2.begin(); pos != name2.end(); pos++) {
|
||||||
|
if (pos[0]=='_' && pos[1]=='_') {
|
||||||
|
out += "__ULUL_";
|
||||||
|
pos++;
|
||||||
|
} else {
|
||||||
|
out += pos[0];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
string AstNode::shortName() const {
|
string AstNode::shortName() const {
|
||||||
string pretty = name();
|
string pretty = name();
|
||||||
string::size_type pos;
|
string::size_type pos;
|
||||||
@@ -114,6 +128,9 @@ string AstNode::prettyName(const string& namein) {
|
|||||||
while ((pos=pretty.find("__PVT__")) != string::npos) {
|
while ((pos=pretty.find("__PVT__")) != string::npos) {
|
||||||
pretty.replace(pos, 7, "");
|
pretty.replace(pos, 7, "");
|
||||||
}
|
}
|
||||||
|
while ((pos=pretty.find("__ULUL_")) != string::npos) {
|
||||||
|
pretty.replace(pos, 7, "");
|
||||||
|
}
|
||||||
return AstNode::dedotName(pretty);
|
return AstNode::dedotName(pretty);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -558,6 +558,7 @@ public:
|
|||||||
string shortName() const; // Name with __PVT__ removed for concatenating scopes
|
string shortName() const; // Name with __PVT__ removed for concatenating scopes
|
||||||
static string dedotName(const string& namein); // Name with dots removed
|
static string dedotName(const string& namein); // Name with dots removed
|
||||||
static string prettyName(const string& namein); // Name for printing out to the user
|
static string prettyName(const string& namein); // Name for printing out to the user
|
||||||
|
static string encodeName(const string& namein); // Encode user name into internal C representation
|
||||||
string prettyName() const { return prettyName(name()); }
|
string prettyName() const { return prettyName(name()); }
|
||||||
FileLine* fileline() const { return m_fileline; }
|
FileLine* fileline() const { return m_fileline; }
|
||||||
int width() const { return m_width; }
|
int width() const { return m_width; }
|
||||||
|
|||||||
+115
-11
@@ -39,11 +39,63 @@
|
|||||||
#include "V3Width.h"
|
#include "V3Width.h"
|
||||||
#include "V3Signed.h"
|
#include "V3Signed.h"
|
||||||
|
|
||||||
|
//######################################################################
|
||||||
|
// Utilities
|
||||||
|
|
||||||
|
class ConstVarMarkVisitor : public AstNVisitor {
|
||||||
|
// NODE STATE
|
||||||
|
// AstVar::userp -> bool, Var marked, 0=not set yet
|
||||||
|
private:
|
||||||
|
// VISITORS
|
||||||
|
virtual void visit(AstVarRef* nodep, AstNUser*) {
|
||||||
|
if (nodep->varp()) nodep->varp()->user(1);
|
||||||
|
}
|
||||||
|
virtual void visit(AstNode* nodep, AstNUser*) {
|
||||||
|
nodep->iterateChildren(*this);
|
||||||
|
}
|
||||||
|
public:
|
||||||
|
// CONSTUCTORS
|
||||||
|
ConstVarMarkVisitor(AstNode* nodep) {
|
||||||
|
AstNode::userClearTree();
|
||||||
|
nodep->iterateAndNext(*this, NULL);
|
||||||
|
}
|
||||||
|
virtual ~ConstVarMarkVisitor() {}
|
||||||
|
};
|
||||||
|
|
||||||
|
class ConstVarFindVisitor : public AstNVisitor {
|
||||||
|
// NODE STATE
|
||||||
|
// AstVar::userp -> bool, input from ConstVarMarkVisitor
|
||||||
|
// MEMBERS
|
||||||
|
bool m_found;
|
||||||
|
private:
|
||||||
|
// VISITORS
|
||||||
|
virtual void visit(AstVarRef* nodep, AstNUser*) {
|
||||||
|
if (nodep->varp() && nodep->varp()->user()) m_found = true;
|
||||||
|
}
|
||||||
|
virtual void visit(AstNode* nodep, AstNUser*) {
|
||||||
|
nodep->iterateChildren(*this);
|
||||||
|
}
|
||||||
|
public:
|
||||||
|
// CONSTUCTORS
|
||||||
|
ConstVarFindVisitor(AstNode* nodep) {
|
||||||
|
m_found = false;
|
||||||
|
nodep->iterateAndNext(*this, NULL);
|
||||||
|
}
|
||||||
|
virtual ~ConstVarFindVisitor() {}
|
||||||
|
// METHODS
|
||||||
|
bool found() const { return m_found; }
|
||||||
|
};
|
||||||
|
|
||||||
//######################################################################
|
//######################################################################
|
||||||
// Const state, as a visitor of each AstNode
|
// Const state, as a visitor of each AstNode
|
||||||
|
|
||||||
class ConstVisitor : public AstNVisitor {
|
class ConstVisitor : public AstNVisitor {
|
||||||
private:
|
private:
|
||||||
|
// NODE STATE
|
||||||
|
// ** only when m_warn is set. If state is needed other times,
|
||||||
|
// ** must track down everywhere V3Const is called and make sure no overlaps.
|
||||||
|
// AstVar::userp -> Used by ConstVarMarkVisitor/ConstVarFindVisitor
|
||||||
|
|
||||||
// STATE
|
// STATE
|
||||||
bool m_params; // If true, propogate parameterized and true numbers only
|
bool m_params; // If true, propogate parameterized and true numbers only
|
||||||
bool m_required; // If true, must become a constant
|
bool m_required; // If true, must become a constant
|
||||||
@@ -494,10 +546,26 @@ private:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (!m_cpp && nodep->lhsp()->castConcat()) {
|
else if (!m_cpp && nodep->lhsp()->castConcat()) {
|
||||||
UINFO(4," ASSI "<<nodep<<endl);
|
bool need_temp = false;
|
||||||
|
if (m_warn && !nodep->castAssignDly()) { // Is same var on LHS and RHS?
|
||||||
|
ConstVarMarkVisitor mark(nodep->lhsp());
|
||||||
|
ConstVarFindVisitor find(nodep->rhsp());
|
||||||
|
if (find.found()) need_temp = true;
|
||||||
|
}
|
||||||
|
if (need_temp) {
|
||||||
|
// The first time we constify, there may be the same variable on the LHS
|
||||||
|
// and RHS. In that case, we must use temporaries, or {a,b}={b,a} will break.
|
||||||
|
UINFO(4," ASSITEMP "<<nodep<<endl);
|
||||||
|
// ASSIGN(CONCAT(lc1,lc2),rhs) -> ASSIGN(temp1,SEL(rhs,{size})),
|
||||||
|
// ASSIGN(temp2,SEL(newrhs,{size}))
|
||||||
|
// ASSIGN(lc1,temp1),
|
||||||
|
// ASSIGN(lc2,temp2)
|
||||||
|
} else {
|
||||||
|
UINFO(4," ASSI "<<nodep<<endl);
|
||||||
|
// ASSIGN(CONCAT(lc1,lc2),rhs) -> ASSIGN(lc1,SEL(rhs,{size})),
|
||||||
|
// ASSIGN(lc2,SEL(newrhs,{size}))
|
||||||
|
}
|
||||||
if (debug()>=9) nodep->dumpTree(cout," Ass_old: ");
|
if (debug()>=9) nodep->dumpTree(cout," Ass_old: ");
|
||||||
// ASSIGN(CONCAT(lc1,lc2),rhs) -> ASSIGN(lc1,SEL(rhs,{size})),
|
|
||||||
// ASSIGN(lc2,SEL(newrhs,{size}))
|
|
||||||
// Unlink the stuff
|
// Unlink the stuff
|
||||||
AstNode* lc1p = nodep->lhsp()->castConcat()->lhsp()->unlinkFrBack();
|
AstNode* lc1p = nodep->lhsp()->castConcat()->lhsp()->unlinkFrBack();
|
||||||
AstNode* lc2p = nodep->lhsp()->castConcat()->rhsp()->unlinkFrBack();
|
AstNode* lc2p = nodep->lhsp()->castConcat()->rhsp()->unlinkFrBack();
|
||||||
@@ -517,14 +585,50 @@ private:
|
|||||||
sel2p->width(msb2-lsb2+1,msb2-lsb2+1);
|
sel2p->width(msb2-lsb2+1,msb2-lsb2+1);
|
||||||
// Make new assigns of same flavor as old one
|
// Make new assigns of same flavor as old one
|
||||||
//*** Not cloneTree; just one node.
|
//*** Not cloneTree; just one node.
|
||||||
AstNodeAssign* asn1p=nodep->cloneType(lc1p, sel1p)->castNodeAssign();
|
AstNode* newp = NULL;
|
||||||
AstNodeAssign* asn2p=nodep->cloneType(lc2p, sel2p)->castNodeAssign();
|
if (!need_temp) {
|
||||||
asn1p->width(msb1-lsb1+1,msb1-lsb1+1);
|
AstNodeAssign* asn1ap=nodep->cloneType(lc1p, sel1p)->castNodeAssign();
|
||||||
asn2p->width(msb2-lsb2+1,msb2-lsb2+1);
|
AstNodeAssign* asn2ap=nodep->cloneType(lc2p, sel2p)->castNodeAssign();
|
||||||
nodep->addNextHere(asn1p);
|
asn1ap->width(msb1-lsb1+1,msb1-lsb1+1);
|
||||||
nodep->addNextHere(asn2p);
|
asn2ap->width(msb2-lsb2+1,msb2-lsb2+1);
|
||||||
if (debug()>=9) asn1p->dumpTree(cout," _new: ");
|
newp = newp->addNext(asn1ap);
|
||||||
if (debug()>=9) asn2p->dumpTree(cout," _new: ");
|
newp = newp->addNext(asn2ap);
|
||||||
|
} else {
|
||||||
|
if (!m_modp) nodep->v3fatalSrc("Not under module");
|
||||||
|
// We could create just one temp variable, but we'll get better optimization
|
||||||
|
// if we make one per term.
|
||||||
|
string name1 = ((string)"__Vconcswap__"+cvtToStr(m_modp->varNumGetInc()));
|
||||||
|
string name2 = ((string)"__Vconcswap__"+cvtToStr(m_modp->varNumGetInc()));
|
||||||
|
AstVar* temp1p = new AstVar(sel1p->fileline(), AstVarType::BLOCKTEMP, name1,
|
||||||
|
new AstRange(sel1p->fileline(), msb1-lsb1, 0));
|
||||||
|
AstVar* temp2p = new AstVar(sel2p->fileline(), AstVarType::BLOCKTEMP, name2,
|
||||||
|
new AstRange(sel2p->fileline(), msb2-lsb2, 0));
|
||||||
|
m_modp->addStmtp(temp1p);
|
||||||
|
m_modp->addStmtp(temp2p);
|
||||||
|
AstNodeAssign* asn1ap=nodep->cloneType
|
||||||
|
(new AstVarRef(sel1p->fileline(), temp1p, true),
|
||||||
|
sel1p)->castNodeAssign();
|
||||||
|
AstNodeAssign* asn2ap=nodep->cloneType
|
||||||
|
(new AstVarRef(sel2p->fileline(), temp2p, true),
|
||||||
|
sel2p)->castNodeAssign();
|
||||||
|
AstNodeAssign* asn1bp=nodep->cloneType
|
||||||
|
(lc1p, new AstVarRef(sel1p->fileline(), temp1p, false))
|
||||||
|
->castNodeAssign();
|
||||||
|
AstNodeAssign* asn2bp=nodep->cloneType
|
||||||
|
(lc2p, new AstVarRef(sel2p->fileline(), temp2p, false))
|
||||||
|
->castNodeAssign();
|
||||||
|
asn1ap->width(msb1-lsb1+1,msb1-lsb1+1);
|
||||||
|
asn1bp->width(msb1-lsb1+1,msb1-lsb1+1);
|
||||||
|
asn2ap->width(msb2-lsb2+1,msb2-lsb2+1);
|
||||||
|
asn2bp->width(msb2-lsb2+1,msb2-lsb2+1);
|
||||||
|
// This order matters
|
||||||
|
newp = newp->addNext(asn1ap);
|
||||||
|
newp = newp->addNext(asn2ap);
|
||||||
|
newp = newp->addNext(asn1bp);
|
||||||
|
newp = newp->addNext(asn2bp);
|
||||||
|
}
|
||||||
|
if (debug()>=9) newp->dumpTreeAndNext(cout," _new: ");
|
||||||
|
nodep->addNextHere(newp);
|
||||||
// Cleanup
|
// Cleanup
|
||||||
nodep->unlinkFrBack()->deleteTree(); nodep=NULL;
|
nodep->unlinkFrBack()->deleteTree(); nodep=NULL;
|
||||||
conp->deleteTree(); conp=NULL;
|
conp->deleteTree(); conp=NULL;
|
||||||
|
|||||||
+4
-4
@@ -79,16 +79,16 @@ public:
|
|||||||
of.puts("default: "+v3Global.opt.prefix()+"__ALL.a\n");
|
of.puts("default: "+v3Global.opt.prefix()+"__ALL.a\n");
|
||||||
}
|
}
|
||||||
of.puts("\n# Constants...\n");
|
of.puts("\n# Constants...\n");
|
||||||
of.puts("PERL = "+V3Options::getenvStr("PERL","perl")+"\n");
|
of.puts("PERL = "+V3Options::getenvPERL()+"\n");
|
||||||
of.puts("VERILATOR_ROOT = "+V3Options::getenvStr("VERILATOR_ROOT","")+"\n");
|
of.puts("VERILATOR_ROOT = "+V3Options::getenvVERILATOR_ROOT()+"\n");
|
||||||
of.puts("SYSTEMPERL = "+V3Options::getenvStr("SYSTEMPERL","")+"\n");
|
of.puts("SYSTEMPERL = "+V3Options::getenvSYSTEMPERL()+"\n");
|
||||||
|
|
||||||
of.puts("\n# Switches...\n");
|
of.puts("\n# Switches...\n");
|
||||||
of.puts(string("VM_SP = ")+(v3Global.opt.systemPerl()?"1":"0")+"\n");
|
of.puts(string("VM_SP = ")+(v3Global.opt.systemPerl()?"1":"0")+"\n");
|
||||||
of.puts(string("VM_SC = ")+((v3Global.opt.systemC()&&!v3Global.opt.systemPerl())?"1":"0")+"\n");
|
of.puts(string("VM_SC = ")+((v3Global.opt.systemC()&&!v3Global.opt.systemPerl())?"1":"0")+"\n");
|
||||||
of.puts(string("VM_SP_OR_SC = ")+(v3Global.opt.systemC()?"1":"0")+"\n");
|
of.puts(string("VM_SP_OR_SC = ")+(v3Global.opt.systemC()?"1":"0")+"\n");
|
||||||
of.puts(string("VM_PCLI = ")+(v3Global.opt.systemC()?"0":"1")+"\n");
|
of.puts(string("VM_PCLI = ")+(v3Global.opt.systemC()?"0":"1")+"\n");
|
||||||
of.puts(string("VM_SC_TARGET_ARCH = ")+V3Options::getenvStr("SYSTEMC_ARCH","")+"\n");
|
of.puts(string("VM_SC_TARGET_ARCH = ")+V3Options::getenvSYSTEMC_ARCH()+"\n");
|
||||||
|
|
||||||
of.puts("\n# Vars...\n");
|
of.puts("\n# Vars...\n");
|
||||||
of.puts(string("VM_PREFIX = ")+v3Global.opt.prefix()+"\n");
|
of.puts(string("VM_PREFIX = ")+v3Global.opt.prefix()+"\n");
|
||||||
|
|||||||
+2
-2
@@ -243,8 +243,8 @@ void V3Error::incWarnings() {
|
|||||||
|
|
||||||
void V3Error::incErrors() {
|
void V3Error::incErrors() {
|
||||||
s_errCount++;
|
s_errCount++;
|
||||||
if (errorCount() == MAX_ERRORS) { // Not >= as would otherwise recurse
|
if (errorCount() == v3Global.opt.errorLimit()) { // Not >= as would otherwise recurse
|
||||||
v3fatal ("Exiting due to too many errors encountered\n");
|
v3fatal ("Exiting due to too many errors encountered; --error-limit="<<errorCount()<<endl);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+2
-1
@@ -53,6 +53,7 @@ public:
|
|||||||
IMPLICIT, // Implicit wire
|
IMPLICIT, // Implicit wire
|
||||||
IMPURE, // Impure function not being inlined
|
IMPURE, // Impure function not being inlined
|
||||||
MULTIDRIVEN, // Driven from multiple blocks
|
MULTIDRIVEN, // Driven from multiple blocks
|
||||||
|
REDEFMACRO, // Redefining existing define macro
|
||||||
UNDRIVEN, // No drivers
|
UNDRIVEN, // No drivers
|
||||||
UNOPT, // Unoptimizable block
|
UNOPT, // Unoptimizable block
|
||||||
UNOPTFLAT, // Unoptimizable block after flattening
|
UNOPTFLAT, // Unoptimizable block after flattening
|
||||||
@@ -78,7 +79,7 @@ public:
|
|||||||
"BLKANDNBLK",
|
"BLKANDNBLK",
|
||||||
"CASEINCOMPLETE", "CASEOVERLAP", "CASEX", "CMPCONST",
|
"CASEINCOMPLETE", "CASEOVERLAP", "CASEX", "CMPCONST",
|
||||||
"COMBDLY", "STMTDLY", "GENCLK", "IMPLICIT", "IMPURE",
|
"COMBDLY", "STMTDLY", "GENCLK", "IMPLICIT", "IMPURE",
|
||||||
"MULTIDRIVEN",
|
"MULTIDRIVEN", "REDEFMACRO",
|
||||||
"UNDRIVEN", "UNOPT", "UNOPTFLAT", "UNSIGNED", "UNUSED",
|
"UNDRIVEN", "UNOPT", "UNOPTFLAT", "UNSIGNED", "UNUSED",
|
||||||
"VARHIDDEN", "WIDTH",
|
"VARHIDDEN", "WIDTH",
|
||||||
" MAX"
|
" MAX"
|
||||||
|
|||||||
@@ -23,6 +23,7 @@
|
|||||||
#include "verilatedos.h"
|
#include "verilatedos.h"
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
|
#include <sys/types.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <iomanip>
|
#include <iomanip>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
@@ -232,6 +233,14 @@ bool V3File::checkTimes(const string& filename, const string& cmdline) {
|
|||||||
return dependImp.checkTimes(filename, cmdline);
|
return dependImp.checkTimes(filename, cmdline);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void V3File::createMakeDir() {
|
||||||
|
static bool created = false;
|
||||||
|
if (!created) {
|
||||||
|
created = true;
|
||||||
|
mkdir(v3Global.opt.makeDir().c_str(), 0777);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//######################################################################
|
//######################################################################
|
||||||
// V3OutFile: A class for printing to a file, with automatic indentation of C++ code.
|
// V3OutFile: A class for printing to a file, with automatic indentation of C++ code.
|
||||||
|
|
||||||
|
|||||||
@@ -46,6 +46,7 @@ public:
|
|||||||
return new_ofstream_nodepend (filename, append);
|
return new_ofstream_nodepend (filename, append);
|
||||||
}
|
}
|
||||||
static ofstream* new_ofstream_nodepend(const string& filename, bool append=false) {
|
static ofstream* new_ofstream_nodepend(const string& filename, bool append=false) {
|
||||||
|
if (filename != "/dev/null") createMakeDir();
|
||||||
if (append) {
|
if (append) {
|
||||||
return new ofstream(filename.c_str(), ios::app);
|
return new ofstream(filename.c_str(), ios::app);
|
||||||
} else {
|
} else {
|
||||||
@@ -53,15 +54,20 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
static FILE* new_fopen_w(const string& filename) {
|
static FILE* new_fopen_w(const string& filename) {
|
||||||
|
if (filename != "/dev/null") createMakeDir();
|
||||||
addTgtDepend(filename);
|
addTgtDepend(filename);
|
||||||
return fopen(filename.c_str(),"w");
|
return fopen(filename.c_str(),"w");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Dependencies
|
// Dependencies
|
||||||
static void addSrcDepend(const string& filename);
|
static void addSrcDepend(const string& filename);
|
||||||
static void addTgtDepend(const string& filename);
|
static void addTgtDepend(const string& filename);
|
||||||
static void writeDepend(const string& filename);
|
static void writeDepend(const string& filename);
|
||||||
static void writeTimes(const string& filename, const string& cmdline);
|
static void writeTimes(const string& filename, const string& cmdline);
|
||||||
static bool checkTimes(const string& filename, const string& cmdline);
|
static bool checkTimes(const string& filename, const string& cmdline);
|
||||||
|
|
||||||
|
// Directory utilities
|
||||||
|
static void createMakeDir();
|
||||||
};
|
};
|
||||||
|
|
||||||
//============================================================================
|
//============================================================================
|
||||||
|
|||||||
@@ -480,3 +480,97 @@ public:
|
|||||||
void DfaGraph::dfaReduce() {
|
void DfaGraph::dfaReduce() {
|
||||||
DfaGraphReduce (this, &V3GraphEdge::followAlwaysTrue);
|
DfaGraphReduce (this, &V3GraphEdge::followAlwaysTrue);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//######################################################################
|
||||||
|
//######################################################################
|
||||||
|
// Algorithms - complement a DFA
|
||||||
|
//
|
||||||
|
// The traditional algorithm is to make a rejecting state, add edges to
|
||||||
|
// reject from all missing values, then swap accept and reject. Rather
|
||||||
|
// than swap at the end, it's faster if we swap up front, then do the edge
|
||||||
|
// changes.
|
||||||
|
//
|
||||||
|
// 1. Since we didn't log rejecting states, make a temp state (this will be
|
||||||
|
// the old accept, and new reject).
|
||||||
|
//
|
||||||
|
// 2. All vertexes except start/accept get edges to NEW accept for any
|
||||||
|
// non-existing case. Weedely we don't have a nice way of representing
|
||||||
|
// this so we just create a edge for each case and mark it "complemented."
|
||||||
|
//
|
||||||
|
// 3. Delete temp vertex (old accept/new reject) and related edges.
|
||||||
|
// The user's old accept is now the new accept. This is imporant as
|
||||||
|
// we want the virtual type of it to be intact.
|
||||||
|
|
||||||
|
class DfaGraphComplement : GraphAlg {
|
||||||
|
private:
|
||||||
|
// MEMBERS
|
||||||
|
DfaVertex* m_tempNewerReject;
|
||||||
|
|
||||||
|
// METHODS
|
||||||
|
int debug() { return 9; }
|
||||||
|
DfaGraph* graphp() { return static_cast<DfaGraph*>(m_graphp); }
|
||||||
|
|
||||||
|
void add_complement_edges() {
|
||||||
|
// Find accepting vertex
|
||||||
|
DfaVertex* acceptp = NULL;
|
||||||
|
for (V3GraphVertex* vertexp = m_graphp->verticesBeginp(); vertexp; vertexp=vertexp->verticesNextp()) {
|
||||||
|
if (DfaVertex* vvertexp = dynamic_cast<DfaVertex*>(vertexp)) {
|
||||||
|
if (vvertexp->accepting()) {
|
||||||
|
acceptp = vvertexp;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!acceptp) v3fatalSrc("No accepting vertex in DFA\n");
|
||||||
|
|
||||||
|
// Remap edges
|
||||||
|
for (V3GraphVertex* vertexp = m_graphp->verticesBeginp(); vertexp; vertexp=vertexp->verticesNextp()) {
|
||||||
|
if (DfaVertex* vvertexp = dynamic_cast<DfaVertex*>(vertexp)) {
|
||||||
|
//UINFO(9, " on vertex "<<vvertexp->name()<<endl);
|
||||||
|
if (!vvertexp->accepting() && vvertexp != m_tempNewerReject) {
|
||||||
|
for (V3GraphEdge* nextp, *edgep = vertexp->outBeginp(); edgep; edgep=nextp) {
|
||||||
|
nextp = edgep->outNextp();
|
||||||
|
if (!edgep->user()) { // Not processed
|
||||||
|
// Old edges to accept now go to new reject
|
||||||
|
DfaEdge* vedgep = static_cast<DfaEdge*>(edgep);
|
||||||
|
DfaVertex* tovertexp = static_cast<DfaVertex*>(edgep->top());
|
||||||
|
if (tovertexp->accepting()) {
|
||||||
|
new DfaEdge(graphp(), vvertexp, m_tempNewerReject, vedgep);
|
||||||
|
edgep->unlinkDelete(); edgep=NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// NOT of all values goes to accept
|
||||||
|
// We make a edge for each value to OR, IE
|
||||||
|
// edge(complemented,a) edge(complemented,b) means !(a | b)
|
||||||
|
if (!tovertexp->accepting()) { // Note we must include edges moved above to reject
|
||||||
|
DfaEdge* newp = new DfaEdge (graphp(), vvertexp, acceptp, vedgep);
|
||||||
|
newp->complement(!newp->complement());
|
||||||
|
newp->user(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public:
|
||||||
|
DfaGraphComplement(V3Graph* dfagraphp, V3EdgeFuncP edgeFuncp)
|
||||||
|
: GraphAlg(dfagraphp, edgeFuncp) {
|
||||||
|
if (debug()>=6) m_graphp->dumpDotFilePrefixed("comp_in");
|
||||||
|
|
||||||
|
// Vertex::m_user begin: 1 indicates new edge, no more processing
|
||||||
|
m_graphp->userClearEdges();
|
||||||
|
|
||||||
|
m_tempNewerReject = new DfaVertex(graphp());
|
||||||
|
add_complement_edges();
|
||||||
|
if (debug()>=6) m_graphp->dumpDotFilePrefixed("comp_preswap");
|
||||||
|
|
||||||
|
m_tempNewerReject->unlinkDelete(graphp()); m_tempNewerReject=NULL;
|
||||||
|
if (debug()>=6) m_graphp->dumpDotFilePrefixed("comp_out");
|
||||||
|
}
|
||||||
|
~DfaGraphComplement() {}
|
||||||
|
};
|
||||||
|
|
||||||
|
void DfaGraph::dfaComplement() {
|
||||||
|
DfaGraphComplement (this, &V3GraphEdge::followAlwaysTrue);
|
||||||
|
}
|
||||||
|
|||||||
+24
-6
@@ -43,7 +43,9 @@ class DfaEdge;
|
|||||||
/// or epsilon, represented as a empty list of inputs.
|
/// or epsilon, represented as a empty list of inputs.
|
||||||
///
|
///
|
||||||
/// We're only looking for matches, so the only accepting states are
|
/// We're only looking for matches, so the only accepting states are
|
||||||
/// at the end of the transformations.
|
/// at the end of the transformations. (If we want the complement, we
|
||||||
|
/// call complement and the algorithm makes a REJECT state, then flips
|
||||||
|
/// accept and reject for you.)
|
||||||
///
|
///
|
||||||
/// Common transforms:
|
/// Common transforms:
|
||||||
///
|
///
|
||||||
@@ -51,8 +53,8 @@ class DfaEdge;
|
|||||||
///
|
///
|
||||||
/// "L": ...->[ON_L]-->DfaVtx-->[epsilon]-->DfaVtx(ACCEPT)
|
/// "L": ...->[ON_L]-->DfaVtx-->[epsilon]-->DfaVtx(ACCEPT)
|
||||||
///
|
///
|
||||||
/// "LR": ...->[ON_L]-->DfaVtx-->[epsilon]-->DfaVtx()
|
/// "LR": ...->[ON_L]-->DfaVtx-->[epsilon]-->DfaVtx(ACCEPT)
|
||||||
/// ->[ON_R]-->DfaVtx-->[epsilon]-->DfaVtx(ACCEPT)
|
/// ->[ON_R]-->DfaVtx-->[epsilon]-/
|
||||||
///
|
///
|
||||||
/// "L|R": ...->DfaVtx-->[epsilon]-->DfaVtx-->[ON_L]-->DfaVtx()->[epsilon]-->DfaVtx(ACCEPT)
|
/// "L|R": ...->DfaVtx-->[epsilon]-->DfaVtx-->[ON_L]-->DfaVtx()->[epsilon]-->DfaVtx(ACCEPT)
|
||||||
/// \->[epsilon]-->DfaVtx-->[ON_R]-->DfaVtx()->[epsilon]-/
|
/// \->[epsilon]-->DfaVtx-->[ON_R]-->DfaVtx()->[epsilon]-/
|
||||||
@@ -76,6 +78,9 @@ public:
|
|||||||
|
|
||||||
/// Simplify a DFA automata
|
/// Simplify a DFA automata
|
||||||
void dfaReduce();
|
void dfaReduce();
|
||||||
|
|
||||||
|
/// Complement result (must already be dfa)
|
||||||
|
void dfaComplement();
|
||||||
};
|
};
|
||||||
|
|
||||||
//=============================================================================
|
//=============================================================================
|
||||||
@@ -113,20 +118,33 @@ typedef AstNUser* DfaInput;
|
|||||||
|
|
||||||
class DfaEdge : public V3GraphEdge {
|
class DfaEdge : public V3GraphEdge {
|
||||||
DfaInput m_input;
|
DfaInput m_input;
|
||||||
|
bool m_complement; // Invert value when doing compare
|
||||||
public:
|
public:
|
||||||
static DfaInput EPSILON() { return NULL; }
|
static DfaInput EPSILON() { return NULL; }
|
||||||
static DfaInput NA() { return AstNUser::fromInt(1); } // as in not-applicable
|
static DfaInput NA() { return AstNUser::fromInt(1); } // as in not-applicable
|
||||||
// CONSTRUCTORS
|
// CONSTRUCTORS
|
||||||
DfaEdge(DfaGraph* graphp, DfaVertex* fromp, DfaVertex* top, DfaInput input)
|
DfaEdge(DfaGraph* graphp, DfaVertex* fromp, DfaVertex* top, DfaInput input)
|
||||||
: V3GraphEdge(graphp, fromp, top, 1)
|
: V3GraphEdge(graphp, fromp, top, 1)
|
||||||
, m_input(input) {}
|
, m_input(input), m_complement(false) {}
|
||||||
|
DfaEdge(DfaGraph* graphp, DfaVertex* fromp, DfaVertex* top, const DfaEdge* copyfrom)
|
||||||
|
: V3GraphEdge(graphp, fromp, top, copyfrom->weight())
|
||||||
|
, m_input(copyfrom->input()), m_complement(copyfrom->complement()) {}
|
||||||
virtual ~DfaEdge() {}
|
virtual ~DfaEdge() {}
|
||||||
// METHODS
|
// METHODS
|
||||||
virtual string dotColor() const { return na()?"yellow":epsilon()?"green":"black"; }
|
virtual string dotColor() const {
|
||||||
virtual string dotLabel() const { return na()?"":epsilon()?"e":cvtToStr((void*)(input())); }
|
return (na() ? "yellow"
|
||||||
|
: epsilon() ? "green"
|
||||||
|
: "black"); }
|
||||||
|
virtual string dotLabel() const {
|
||||||
|
return (na() ? ""
|
||||||
|
: epsilon() ? "e"
|
||||||
|
: complement() ? ("not "+cvtToStr((void*)(input())))
|
||||||
|
: cvtToStr((void*)(input()))); }
|
||||||
virtual string dotStyle() const { return (na()||cutable())?"dashed":""; }
|
virtual string dotStyle() const { return (na()||cutable())?"dashed":""; }
|
||||||
bool epsilon() const { return input()==EPSILON(); }
|
bool epsilon() const { return input()==EPSILON(); }
|
||||||
bool na() const { return input()==NA(); }
|
bool na() const { return input()==NA(); }
|
||||||
|
bool complement() const { return m_complement; }
|
||||||
|
void complement(bool value) { m_complement=value; }
|
||||||
DfaInput input() const { return m_input; }
|
DfaInput input() const { return m_input; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -309,6 +309,12 @@ public:
|
|||||||
gp->nfaToDfa();
|
gp->nfaToDfa();
|
||||||
dump();
|
dump();
|
||||||
gp->dfaReduce();
|
gp->dfaReduce();
|
||||||
|
dump();
|
||||||
|
|
||||||
|
gp->dfaComplement();
|
||||||
|
dump();
|
||||||
|
gp->dfaReduce();
|
||||||
|
dump();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
+4
-4
@@ -381,10 +381,10 @@ private:
|
|||||||
|
|
||||||
virtual void visit(AstAssignW* nodep, AstNUser*) {
|
virtual void visit(AstAssignW* nodep, AstNUser*) {
|
||||||
// Deal with implicit definitions
|
// Deal with implicit definitions
|
||||||
if (nodep->allowImplicit()) {
|
// We used to nodep->allowImplicit() here, but it turns out
|
||||||
if (AstVarRef* forrefp = nodep->lhsp()->castVarRef()) {
|
// normal "assigns" can also make implicit wires. Yuk.
|
||||||
createImplicitVar(forrefp, false);
|
if (AstVarRef* forrefp = nodep->lhsp()->castVarRef()) {
|
||||||
}
|
createImplicitVar(forrefp, false);
|
||||||
}
|
}
|
||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildren(*this);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -127,9 +127,6 @@ private:
|
|||||||
// Module: Pick up modnames, so we can resolve cells later
|
// Module: Pick up modnames, so we can resolve cells later
|
||||||
m_modp = nodep;
|
m_modp = nodep;
|
||||||
UINFO(2,"Link Module: "<<nodep<<endl);
|
UINFO(2,"Link Module: "<<nodep<<endl);
|
||||||
if (nodep->name().find("__") != string::npos) {
|
|
||||||
nodep->v3error("Unsupported: Double underscores (__) in module names reserved for internal use: "<<nodep->prettyName());
|
|
||||||
}
|
|
||||||
if (nodep->inLibrary()) {
|
if (nodep->inLibrary()) {
|
||||||
if (!m_libVertexp) m_libVertexp = new LibraryVertex(&m_graph);
|
if (!m_libVertexp) m_libVertexp = new LibraryVertex(&m_graph);
|
||||||
new V3GraphEdge(&m_graph, m_libVertexp, vertex(nodep), 1, false);
|
new V3GraphEdge(&m_graph, m_libVertexp, vertex(nodep), 1, false);
|
||||||
|
|||||||
+10
-1
@@ -45,6 +45,7 @@ private:
|
|||||||
|
|
||||||
// STATE
|
// STATE
|
||||||
bool m_setRefLvalue; // Set VarRefs to lvalues for pin assignments
|
bool m_setRefLvalue; // Set VarRefs to lvalues for pin assignments
|
||||||
|
AstNodeFTask* m_ftaskp; // Function or task we're inside
|
||||||
|
|
||||||
//int debug() { return 9; }
|
//int debug() { return 9; }
|
||||||
|
|
||||||
@@ -59,7 +60,9 @@ private:
|
|||||||
}
|
}
|
||||||
if (nodep->varp()) {
|
if (nodep->varp()) {
|
||||||
if (nodep->lvalue() && nodep->varp()->isInOnly()) {
|
if (nodep->lvalue() && nodep->varp()->isInOnly()) {
|
||||||
nodep->v3error("Assigning to input variable: "<<nodep->prettyName());
|
if (!m_ftaskp) {
|
||||||
|
nodep->v3error("Assigning to input variable: "<<nodep->prettyName());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildren(*this);
|
||||||
@@ -150,6 +153,11 @@ private:
|
|||||||
}
|
}
|
||||||
m_setRefLvalue = last_setRefLvalue;
|
m_setRefLvalue = last_setRefLvalue;
|
||||||
}
|
}
|
||||||
|
virtual void visit(AstNodeFTask* nodep, AstNUser*) {
|
||||||
|
m_ftaskp = nodep;
|
||||||
|
nodep->iterateChildren(*this);
|
||||||
|
m_ftaskp = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
virtual void visit(AstNode* nodep, AstNUser*) {
|
virtual void visit(AstNode* nodep, AstNUser*) {
|
||||||
// Default: Just iterate
|
// Default: Just iterate
|
||||||
@@ -160,6 +168,7 @@ public:
|
|||||||
// CONSTUCTORS
|
// CONSTUCTORS
|
||||||
LinkLValueVisitor(AstNetlist* rootp) {
|
LinkLValueVisitor(AstNetlist* rootp) {
|
||||||
m_setRefLvalue = false;
|
m_setRefLvalue = false;
|
||||||
|
m_ftaskp = NULL;
|
||||||
rootp->accept(*this);
|
rootp->accept(*this);
|
||||||
}
|
}
|
||||||
virtual ~LinkLValueVisitor() {}
|
virtual ~LinkLValueVisitor() {}
|
||||||
|
|||||||
+171
-4
@@ -23,7 +23,10 @@
|
|||||||
#include "verilatedos.h"
|
#include "verilatedos.h"
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
|
#include <sys/utsname.h>
|
||||||
|
#include <ctype.h>
|
||||||
#include <dirent.h>
|
#include <dirent.h>
|
||||||
|
#include <unistd.h>
|
||||||
#include <set>
|
#include <set>
|
||||||
#include <list>
|
#include <list>
|
||||||
#include <map>
|
#include <map>
|
||||||
@@ -97,6 +100,11 @@ void V3Options::addLibraryFile(const string& filename) {
|
|||||||
m_libraryFiles.insert(filename);
|
m_libraryFiles.insert(filename);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
void V3Options::addVFile(const string& filename) {
|
||||||
|
if (m_vFiles.find(filename) == m_vFiles.end()) {
|
||||||
|
m_vFiles.insert(filename);
|
||||||
|
}
|
||||||
|
}
|
||||||
void V3Options::addArg(const string& arg) {
|
void V3Options::addArg(const string& arg) {
|
||||||
m_impp->m_allArgs.push_back(arg);
|
m_impp->m_allArgs.push_back(arg);
|
||||||
}
|
}
|
||||||
@@ -146,6 +154,14 @@ string V3Options::filenameNonExt (const string& filename) {
|
|||||||
return base;
|
return base;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool V3Options::fileStatDir(const string& filename) {
|
||||||
|
struct stat m_stat; // Stat information
|
||||||
|
int err = stat(filename.c_str(), &m_stat);
|
||||||
|
if (err!=0) return false;
|
||||||
|
if (!S_ISDIR(m_stat.st_mode)) return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool V3Options::fileStatNormal(const string& filename) {
|
bool V3Options::fileStatNormal(const string& filename) {
|
||||||
struct stat m_stat; // Stat information
|
struct stat m_stat; // Stat information
|
||||||
int err = stat(filename.c_str(), &m_stat);
|
int err = stat(filename.c_str(), &m_stat);
|
||||||
@@ -226,6 +242,153 @@ string V3Options::filePath (FileLine* fl, const string& modname, const string& e
|
|||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void V3Options::unlinkRegexp(const string& dir, const string& regexp) {
|
||||||
|
if (DIR* dirp = opendir(dir.c_str())) {
|
||||||
|
while (struct dirent* direntp = readdir(dirp)) {
|
||||||
|
if (wildmatch(direntp->d_name, regexp.c_str())) {
|
||||||
|
string fullname = dir + "/" + string(direntp->d_name);
|
||||||
|
unlink (fullname.c_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
closedir(dirp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//######################################################################
|
||||||
|
// Environment
|
||||||
|
|
||||||
|
string V3Options::getenvStr(const char* envvar, const char* defaultValue) {
|
||||||
|
if (const char* envvalue = getenv(envvar)) {
|
||||||
|
return envvalue;
|
||||||
|
} else {
|
||||||
|
return defaultValue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
string V3Options::getenvSYSTEMC() {
|
||||||
|
string var = getenvStr("SYSTEMC","");
|
||||||
|
if (var == "" && string(DEFENV_SYSTEMC) != "") {
|
||||||
|
var = DEFENV_SYSTEMC;
|
||||||
|
UINFO(1,"export SYSTEMC="<<var<<" # Hardcoded at build time"<<endl);
|
||||||
|
setenv("SYSTEMC", var.c_str(), false);
|
||||||
|
}
|
||||||
|
// Only correct or check it if we really need the value
|
||||||
|
if ((v3Global.opt.systemPerl() || v3Global.opt.systemC())
|
||||||
|
&& !v3Global.opt.lintOnly()) {
|
||||||
|
if (var == "") {
|
||||||
|
v3fatal("Need $SYSTEMC in environment\n"
|
||||||
|
"Probably System-C isn't installed, see http://www.systemc.org\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return var;
|
||||||
|
}
|
||||||
|
string V3Options::getenvSYSTEMC_ARCH() {
|
||||||
|
string var = getenvStr("SYSTEMC_ARCH","");
|
||||||
|
if (var == "" && string(DEFENV_SYSTEMC_ARCH) != "") {
|
||||||
|
var = DEFENV_SYSTEMC_ARCH;
|
||||||
|
UINFO(1,"export SYSTEMC_ARCH="<<var<<" # Hardcoded at build time"<<endl);
|
||||||
|
setenv("SYSTEMC_ARCH", var.c_str(), false);
|
||||||
|
}
|
||||||
|
if (var == "") {
|
||||||
|
struct utsname uts;
|
||||||
|
uname(&uts);
|
||||||
|
string sysname = downcase(uts.sysname); // aka 'uname -s'
|
||||||
|
if (wildmatch(sysname.c_str(), "*solaris*")) { var = "gccsparcOS5"; }
|
||||||
|
else if (wildmatch(sysname.c_str(), "*cygwin*")) { var ="cygwin"; }
|
||||||
|
else { var = "linux"; }
|
||||||
|
UINFO(1,"export SYSTEMC_ARCH="<<var<<" # From sysname '"<<sysname<<"'"<<endl);
|
||||||
|
setenv("SYSTEMC_ARCH", var.c_str(), false);
|
||||||
|
}
|
||||||
|
return var;
|
||||||
|
}
|
||||||
|
string V3Options::getenvSYSTEMPERL() {
|
||||||
|
string var = getenvStr("SYSTEMPERL","");
|
||||||
|
if (var == "" && string(DEFENV_SYSTEMPERL) != "") {
|
||||||
|
var = DEFENV_SYSTEMPERL;
|
||||||
|
UINFO(1,"export SYSTEMPERL="<<var<<" # Hardcoded at build time"<<endl);
|
||||||
|
setenv("SYSTEMC_PERL", var.c_str(), false);
|
||||||
|
}
|
||||||
|
// Only correct or check it if we really need the value
|
||||||
|
if ((v3Global.opt.systemPerl() || v3Global.opt.trace()) && !v3Global.opt.lintOnly()) {
|
||||||
|
if (var == "") {
|
||||||
|
string testdir = V3Options::getenvW() + "/hw/utils/perltools/SystemC"; // Hack for internal testing
|
||||||
|
if (V3Options::fileStatDir(testdir)) {
|
||||||
|
var = testdir;
|
||||||
|
UINFO(1,"export SYSTEMPERL="<<var<<endl);
|
||||||
|
setenv ("SYSTEMPERL", var.c_str(), false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (var == "") {
|
||||||
|
v3fatal("Need $SYSTEMPERL in environment for --sp or --trace\n"
|
||||||
|
"Probably System-Perl isn't installed, see http://www.veripool.com/systemperl.html\n");
|
||||||
|
}
|
||||||
|
if (var != ""
|
||||||
|
&& !V3Options::fileStatNormal(var+"/src/systemperl.h")) {
|
||||||
|
v3fatal("$SYSTEMPERL environment var doesn't seem to point to System-Perl kit\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return var;
|
||||||
|
}
|
||||||
|
string V3Options::getenvVERILATOR_ROOT() {
|
||||||
|
string var = getenvStr("VERILATOR_ROOT","");
|
||||||
|
if (var == "" && string(DEFENV_VERILATOR_ROOT) != "") {
|
||||||
|
var = DEFENV_VERILATOR_ROOT;
|
||||||
|
UINFO(1,"export VERILATOR_ROOT="<<var<<" # Hardcoded at build time"<<endl);
|
||||||
|
setenv("VERILATOR_ROOT", var.c_str(), false);
|
||||||
|
}
|
||||||
|
if (var == "") {
|
||||||
|
v3fatal("$VERILATOR_ROOT needs to be in environment\n");
|
||||||
|
}
|
||||||
|
return var;
|
||||||
|
}
|
||||||
|
|
||||||
|
//######################################################################
|
||||||
|
// Wildcard
|
||||||
|
|
||||||
|
// Double procedures, inlined, unrolls loop much better
|
||||||
|
inline bool V3Options::wildmatchi(const char* s, const char* p) {
|
||||||
|
for ( ; *p; s++, p++) {
|
||||||
|
if (*p!='*') {
|
||||||
|
if (((*s)!=(*p)) && *p != '?')
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// Trailing star matches everything.
|
||||||
|
if (!*++p) return true;
|
||||||
|
while (wildmatch(s, p) == false)
|
||||||
|
if (*++s == '\0')
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return(*s == '\0' || *s == '[');
|
||||||
|
}
|
||||||
|
|
||||||
|
bool V3Options::wildmatch(const char* s, const char* p) {
|
||||||
|
for ( ; *p; s++, p++) {
|
||||||
|
if (*p!='*') {
|
||||||
|
if (((*s)!=(*p)) && *p != '?')
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// Trailing star matches everything.
|
||||||
|
if (!*++p) return true;
|
||||||
|
while (wildmatchi(s, p) == false)
|
||||||
|
if (*++s == '\0')
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return(*s == '\0' || *s == '[');
|
||||||
|
}
|
||||||
|
|
||||||
|
string V3Options::downcase(const string& str) {
|
||||||
|
string out = str;
|
||||||
|
for (string::iterator pos = out.begin(); pos != out.end(); pos++) {
|
||||||
|
*pos = tolower(*pos);
|
||||||
|
}
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
//######################################################################
|
//######################################################################
|
||||||
// V3 Options accessors
|
// V3 Options accessors
|
||||||
|
|
||||||
@@ -261,12 +424,12 @@ void V3Options::parseOpts (FileLine* fl, int argc, char** argv) {
|
|||||||
|
|
||||||
// Default certain options and error check
|
// Default certain options and error check
|
||||||
// Detailed error, since this is what we often get when run with minimal arguments
|
// Detailed error, since this is what we often get when run with minimal arguments
|
||||||
if (top()=="") {
|
if (vFiles().empty()) {
|
||||||
v3fatal("verilator: No Input Verilog file specified on command line, see verilator --help for more information\n");
|
v3fatal("verilator: No Input Verilog file specified on command line, see verilator --help for more information\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Default prefix to the filename
|
// Default prefix to the filename
|
||||||
if (prefix()=="") m_prefix = string("V")+filenameNonExt(top());
|
if (prefix()=="") m_prefix = string("V")+filenameNonExt(*(vFiles().begin()));
|
||||||
if (modPrefix()=="") m_modPrefix = prefix();
|
if (modPrefix()=="") m_modPrefix = prefix();
|
||||||
|
|
||||||
// Find files in makedir
|
// Find files in makedir
|
||||||
@@ -343,6 +506,10 @@ void V3Options::parseOptsList(FileLine* fl, int argc, char** argv) {
|
|||||||
cout <<endl;
|
cout <<endl;
|
||||||
exit(0);
|
exit(0);
|
||||||
}
|
}
|
||||||
|
else if ( !strcmp (sw, "-error-limit") ) {
|
||||||
|
shift;
|
||||||
|
m_inlineMult = atoi(argv[i]);
|
||||||
|
}
|
||||||
else if ( !strcmp (sw, "-inline-mult") ) {
|
else if ( !strcmp (sw, "-inline-mult") ) {
|
||||||
shift;
|
shift;
|
||||||
m_inlineMult = atoi(argv[i]);
|
m_inlineMult = atoi(argv[i]);
|
||||||
@@ -513,8 +680,7 @@ void V3Options::parseOptsList(FileLine* fl, int argc, char** argv) {
|
|||||||
|| filename.find(".sp") != string::npos) {
|
|| filename.find(".sp") != string::npos) {
|
||||||
V3Options::addCppFile(argv[i]);
|
V3Options::addCppFile(argv[i]);
|
||||||
} else {
|
} else {
|
||||||
if (m_top!="") fl->v3fatal ("Top filename specified twice: "<<m_top<<" and "<<filename);
|
V3Options::addVFile(argv[i]);
|
||||||
m_top = filename;
|
|
||||||
}
|
}
|
||||||
shift;
|
shift;
|
||||||
}
|
}
|
||||||
@@ -608,6 +774,7 @@ V3Options::V3Options() {
|
|||||||
m_traceDups = false;
|
m_traceDups = false;
|
||||||
m_underlineZero = false;
|
m_underlineZero = false;
|
||||||
|
|
||||||
|
m_errorLimit = 50;
|
||||||
m_inlineMult = 2000;
|
m_inlineMult = 2000;
|
||||||
m_outputSplit = 0;
|
m_outputSplit = 0;
|
||||||
m_outputSplitCFuncs = 0;
|
m_outputSplitCFuncs = 0;
|
||||||
|
|||||||
+25
-11
@@ -41,8 +41,9 @@ class V3Options {
|
|||||||
// MEMBERS (general options)
|
// MEMBERS (general options)
|
||||||
V3OptionsImp* m_impp; // Slow hidden options
|
V3OptionsImp* m_impp; // Slow hidden options
|
||||||
|
|
||||||
V3StringSet m_cppFiles; // C++ files to link against
|
V3StringSet m_cppFiles; // argument: C++ files to link against
|
||||||
V3StringSet m_libraryFiles; // Verilog -v files
|
V3StringSet m_libraryFiles; // argument: Verilog -v files
|
||||||
|
V3StringSet m_vFiles; // argument: Verilog files to read
|
||||||
|
|
||||||
bool m_preprocOnly; // main switch: -E
|
bool m_preprocOnly; // main switch: -E
|
||||||
bool m_makeDepend; // main switch: -MMD
|
bool m_makeDepend; // main switch: -MMD
|
||||||
@@ -70,6 +71,7 @@ class V3Options {
|
|||||||
bool m_traceDups; // main switch: --trace-dups
|
bool m_traceDups; // main switch: --trace-dups
|
||||||
bool m_underlineZero;// main switch: --underline-zero
|
bool m_underlineZero;// main switch: --underline-zero
|
||||||
|
|
||||||
|
int m_errorLimit; // main switch: --error-limit
|
||||||
int m_inlineMult; // main switch: --inline-mult
|
int m_inlineMult; // main switch: --inline-mult
|
||||||
int m_outputSplit; // main switch: --output-split
|
int m_outputSplit; // main switch: --output-split
|
||||||
int m_outputSplitCFuncs;// main switch: --output-split-cfuncs
|
int m_outputSplitCFuncs;// main switch: --output-split-cfuncs
|
||||||
@@ -82,7 +84,6 @@ class V3Options {
|
|||||||
|
|
||||||
string m_bin; // main switch: --bin {binary}
|
string m_bin; // main switch: --bin {binary}
|
||||||
string m_flags; // main switch: -f {name}
|
string m_flags; // main switch: -f {name}
|
||||||
string m_top; // main switch: Top .v file name
|
|
||||||
string m_makeDir; // main switch: -Mdir
|
string m_makeDir; // main switch: -Mdir
|
||||||
string m_prefix; // main switch: --prefix
|
string m_prefix; // main switch: --prefix
|
||||||
string m_modPrefix; // main switch: --mod-prefix
|
string m_modPrefix; // main switch: --mod-prefix
|
||||||
@@ -115,6 +116,8 @@ class V3Options {
|
|||||||
void optimize(int level);
|
void optimize(int level);
|
||||||
void coverage(bool flag) { m_coverageLine = m_coverageUser = flag; }
|
void coverage(bool flag) { m_coverageLine = m_coverageUser = flag; }
|
||||||
bool onoff(const char* sw, const char* arg, bool& flag);
|
bool onoff(const char* sw, const char* arg, bool& flag);
|
||||||
|
static bool wildmatchi(const char* s, const char* p);
|
||||||
|
static string getenvStr(const char* envvar, const char* defaultValue);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// CREATORS
|
// CREATORS
|
||||||
@@ -125,9 +128,9 @@ class V3Options {
|
|||||||
// METHODS
|
// METHODS
|
||||||
void addCppFile(const string& filename);
|
void addCppFile(const string& filename);
|
||||||
void addLibraryFile(const string& filename);
|
void addLibraryFile(const string& filename);
|
||||||
|
void addVFile(const string& filename);
|
||||||
|
|
||||||
// ACCESSORS (options)
|
// ACCESSORS (options)
|
||||||
const string& top() const { return m_top; }
|
|
||||||
bool preprocOnly() const { return m_preprocOnly; }
|
bool preprocOnly() const { return m_preprocOnly; }
|
||||||
bool makeDepend() const { return m_makeDepend; }
|
bool makeDepend() const { return m_makeDepend; }
|
||||||
bool makePhony() const { return m_makePhony; }
|
bool makePhony() const { return m_makePhony; }
|
||||||
@@ -158,6 +161,7 @@ class V3Options {
|
|||||||
bool ignc() const { return m_ignc; }
|
bool ignc() const { return m_ignc; }
|
||||||
bool inhibitSim() const { return m_inhibitSim; }
|
bool inhibitSim() const { return m_inhibitSim; }
|
||||||
|
|
||||||
|
int errorLimit() const { return m_errorLimit; }
|
||||||
int inlineMult() const { return m_inlineMult; }
|
int inlineMult() const { return m_inlineMult; }
|
||||||
int outputSplit() const { return m_outputSplit; }
|
int outputSplit() const { return m_outputSplit; }
|
||||||
int outputSplitCFuncs() const { return m_outputSplitCFuncs; }
|
int outputSplitCFuncs() const { return m_outputSplitCFuncs; }
|
||||||
@@ -174,6 +178,7 @@ class V3Options {
|
|||||||
string xAssign() const { return m_xAssign; }
|
string xAssign() const { return m_xAssign; }
|
||||||
const V3StringSet& cppFiles() const { return m_cppFiles; }
|
const V3StringSet& cppFiles() const { return m_cppFiles; }
|
||||||
const V3StringSet& libraryFiles() const { return m_libraryFiles; }
|
const V3StringSet& libraryFiles() const { return m_libraryFiles; }
|
||||||
|
const V3StringSet& vFiles() const { return m_vFiles; }
|
||||||
|
|
||||||
|
|
||||||
// ACCESSORS (optimization options)
|
// ACCESSORS (optimization options)
|
||||||
@@ -203,23 +208,32 @@ class V3Options {
|
|||||||
void parseOptsList (FileLine* fl, int argc, char** argv);
|
void parseOptsList (FileLine* fl, int argc, char** argv);
|
||||||
void parseOptsFile (FileLine* fl, const string& filename);
|
void parseOptsFile (FileLine* fl, const string& filename);
|
||||||
|
|
||||||
|
// METHODS (generic string utilities)
|
||||||
|
static bool wildmatch(const char* s, const char* p);
|
||||||
|
static string downcase(const string& str);
|
||||||
|
|
||||||
// METHODS (generic file utilities)
|
// METHODS (generic file utilities)
|
||||||
static string filenameFromDirBase (const string& dir, const string& basename);
|
static string filenameFromDirBase (const string& dir, const string& basename);
|
||||||
static string filenameNonDir (const string& filename); ///< Return non-directory part of filename
|
static string filenameNonDir (const string& filename); ///< Return non-directory part of filename
|
||||||
static string filenameNonExt (const string& filename); ///< Return non-extensioned (no .) part of filename
|
static string filenameNonExt (const string& filename); ///< Return non-extensioned (no .) part of filename
|
||||||
static string filenameNonDirExt (const string& filename) { return filenameNonExt(filenameNonDir(filename)); } ///< Return basename of filename
|
static string filenameNonDirExt (const string& filename) { return filenameNonExt(filenameNonDir(filename)); } ///< Return basename of filename
|
||||||
static string filenameDir (const string& filename); ///< Return directory part of filename
|
static string filenameDir (const string& filename); ///< Return directory part of filename
|
||||||
static string getenvStr(const char* envvar, const char* defaultValue) {
|
static void unlinkRegexp(const string& dir, const string& regexp);
|
||||||
if (const char* envvalue = getenv(envvar)) {
|
|
||||||
return envvalue;
|
// METHODS (environment)
|
||||||
} else {
|
// Most of these may be built into the executable with --enable-defenv,
|
||||||
return defaultValue;
|
// see the README. If adding new variables, also see src/Makefile_obj.in
|
||||||
}
|
static string getenvPERL() { return getenvStr("PERL","perl"); }
|
||||||
}
|
static string getenvSYSTEMC();
|
||||||
|
static string getenvSYSTEMC_ARCH();
|
||||||
|
static string getenvSYSTEMPERL();
|
||||||
|
static string getenvVERILATOR_ROOT();
|
||||||
|
static string getenvW() { return getenvStr("W",""); }
|
||||||
|
|
||||||
// METHODS (file utilities using these options)
|
// METHODS (file utilities using these options)
|
||||||
string fileExists (const string& filename);
|
string fileExists (const string& filename);
|
||||||
string filePath (FileLine* fl, const string& modname, const string& errmsg);
|
string filePath (FileLine* fl, const string& modname, const string& errmsg);
|
||||||
|
static bool fileStatDir (const string& filename);
|
||||||
static bool fileStatNormal (const string& filename);
|
static bool fileStatNormal (const string& filename);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
+2
-2
@@ -207,8 +207,8 @@ void V3PreProcImp::define(FileLine* fl, const string& name, const string& value,
|
|||||||
UINFO(4,"DEFINE '"<<name<<"' as '"<<value<<"' params '"<<params<<"'"<<endl);
|
UINFO(4,"DEFINE '"<<name<<"' as '"<<value<<"' params '"<<params<<"'"<<endl);
|
||||||
if (defExists(name)) {
|
if (defExists(name)) {
|
||||||
if (!(defValue(name)==value && defParams(name)==params)) { // Duplicate defs are OK
|
if (!(defValue(name)==value && defParams(name)==params)) { // Duplicate defs are OK
|
||||||
fl->v3error("Define already exists: "<<name);
|
fl->v3warn(REDEFMACRO,"Redefining existing define: "<<name<<", with different value: "<<value<<" "<<params);
|
||||||
defFileline(name)->v3error("Previous definition is here.");
|
defFileline(name)->v3warn(REDEFMACRO,"Previous definition is here, with value: "<<defValue(name)<<" "<<defParams(name));
|
||||||
}
|
}
|
||||||
undef(name);
|
undef(name);
|
||||||
}
|
}
|
||||||
|
|||||||
+5
-27
@@ -33,6 +33,7 @@
|
|||||||
#include "V3PreShell.h"
|
#include "V3PreShell.h"
|
||||||
#include "V3PreProc.h"
|
#include "V3PreProc.h"
|
||||||
#include "V3File.h"
|
#include "V3File.h"
|
||||||
|
#include "V3Read.h"
|
||||||
|
|
||||||
//######################################################################
|
//######################################################################
|
||||||
|
|
||||||
@@ -64,38 +65,15 @@ protected:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void preproc (FileLine* fl, const string& modname, const string& vppFilename) {
|
void preproc (FileLine* fl, const string& modname, V3Read* readerp) {
|
||||||
// Preprocess the given module, putting output in vppFilename
|
// Preprocess the given module, putting output in vppFilename
|
||||||
unlink(vppFilename.c_str());
|
|
||||||
UINFONL(1," Preprocessing "<<modname<<endl);
|
UINFONL(1," Preprocessing "<<modname<<endl);
|
||||||
|
|
||||||
// Open
|
|
||||||
ofstream* ofp = NULL;
|
|
||||||
ostream* osp;
|
|
||||||
if (v3Global.opt.preprocOnly()) {
|
|
||||||
osp = &cout;
|
|
||||||
} else if (!v3Global.opt.keepTempFiles()) { // Must match unlink rule in V3Read.cpp
|
|
||||||
osp = ofp = V3File::new_ofstream_nodepend(vppFilename);
|
|
||||||
} else {
|
|
||||||
osp = ofp = V3File::new_ofstream(vppFilename);
|
|
||||||
}
|
|
||||||
if (osp->fail()) {
|
|
||||||
fl->v3error("Cannot write preprocessor output: "+vppFilename);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Preprocess
|
// Preprocess
|
||||||
preprocOpen(fl, modname, "Cannot find file containing module: ");
|
preprocOpen(fl, modname, "Cannot find file containing module: ");
|
||||||
while (!s_preprocp->isEof()) {
|
while (!s_preprocp->isEof()) {
|
||||||
string line = s_preprocp->getline();
|
string line = s_preprocp->getline();
|
||||||
*osp << line;
|
readerp->ppPushText(line);
|
||||||
}
|
|
||||||
|
|
||||||
// Close
|
|
||||||
if (ofp) {
|
|
||||||
ofp->close();
|
|
||||||
delete ofp;
|
|
||||||
osp = ofp = NULL;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -129,8 +107,8 @@ V3PreProc* V3PreShellImp::s_preprocp = NULL;
|
|||||||
void V3PreShell::boot(char** env) {
|
void V3PreShell::boot(char** env) {
|
||||||
V3PreShellImp::s_preImp.boot(env);
|
V3PreShellImp::s_preImp.boot(env);
|
||||||
}
|
}
|
||||||
void V3PreShell::preproc(FileLine* fl, const string& modname, const string& vppFilename) {
|
void V3PreShell::preproc(FileLine* fl, const string& modname, V3Read* readerp) {
|
||||||
V3PreShellImp::s_preImp.preproc(fl, modname, vppFilename);
|
V3PreShellImp::s_preImp.preproc(fl, modname, readerp);
|
||||||
}
|
}
|
||||||
void V3PreShell::preprocInclude(FileLine* fl, const string& modname) {
|
void V3PreShell::preprocInclude(FileLine* fl, const string& modname) {
|
||||||
V3PreShellImp::s_preImp.preprocInclude(fl, modname);
|
V3PreShellImp::s_preImp.preprocInclude(fl, modname);
|
||||||
|
|||||||
+3
-1
@@ -26,13 +26,15 @@
|
|||||||
#include "verilatedos.h"
|
#include "verilatedos.h"
|
||||||
#include "V3Error.h"
|
#include "V3Error.h"
|
||||||
|
|
||||||
|
class V3Read;
|
||||||
|
|
||||||
//============================================================================
|
//============================================================================
|
||||||
|
|
||||||
class V3PreShell {
|
class V3PreShell {
|
||||||
// Static class for calling preprocessor
|
// Static class for calling preprocessor
|
||||||
public:
|
public:
|
||||||
static void boot(char** env);
|
static void boot(char** env);
|
||||||
static void preproc(FileLine* fileline, const string& module, const string& vppFilename);
|
static void preproc(FileLine* fileline, const string& module, V3Read* readerp);
|
||||||
static void preprocInclude(FileLine* fileline, const string& module);
|
static void preprocInclude(FileLine* fileline, const string& module);
|
||||||
static string dependFiles() { return ""; } // Perl only
|
static string dependFiles() { return ""; } // Perl only
|
||||||
static void define(const string& name, const string& value);
|
static void define(const string& name, const string& value);
|
||||||
|
|||||||
+55
-22
@@ -57,7 +57,7 @@ extern int yydebug;
|
|||||||
class V3Lexer : public V3LexerBase {
|
class V3Lexer : public V3LexerBase {
|
||||||
public:
|
public:
|
||||||
// CONSTRUCTORS
|
// CONSTRUCTORS
|
||||||
V3Lexer(std::istream* arg_yyin) : V3LexerBase(arg_yyin) {}
|
V3Lexer() : V3LexerBase(NULL) {}
|
||||||
~V3Lexer() {}
|
~V3Lexer() {}
|
||||||
// METHODS
|
// METHODS
|
||||||
void stateExitPsl() {
|
void stateExitPsl() {
|
||||||
@@ -91,6 +91,29 @@ V3Read::~V3Read() {
|
|||||||
parserClear();
|
parserClear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int V3Read::ppInputToLex(char* buf, int max_size) {
|
||||||
|
int got = 0;
|
||||||
|
while (got < max_size // Haven't got enough
|
||||||
|
&& !m_ppBuffers.empty()) { // And something buffered
|
||||||
|
string front = m_ppBuffers.front(); m_ppBuffers.pop_front();
|
||||||
|
int len = front.length();
|
||||||
|
if (len > (max_size-got)) { // Front string too big
|
||||||
|
string remainder = front.substr(max_size-got);
|
||||||
|
front = front.substr(0, max_size-got);
|
||||||
|
m_ppBuffers.push_front(remainder); // Put back remainder for next time
|
||||||
|
len = (max_size-got);
|
||||||
|
}
|
||||||
|
strncpy(buf+got, front.c_str(), len);
|
||||||
|
got += len;
|
||||||
|
}
|
||||||
|
if (debug()>=9) {
|
||||||
|
string out = string(buf,got);
|
||||||
|
cout<<" inputToLex got="<<got<<" '"<<out<<"'"<<endl;
|
||||||
|
}
|
||||||
|
// Note returns 0 at EOF
|
||||||
|
return got;
|
||||||
|
}
|
||||||
|
|
||||||
void V3Read::readFile(FileLine* fileline, const string& modfilename, bool inLibrary) {
|
void V3Read::readFile(FileLine* fileline, const string& modfilename, bool inLibrary) {
|
||||||
string modname = V3Options::filenameNonExt(modfilename);
|
string modname = V3Options::filenameNonExt(modfilename);
|
||||||
|
|
||||||
@@ -98,42 +121,52 @@ void V3Read::readFile(FileLine* fileline, const string& modfilename, bool inLibr
|
|||||||
m_fileline = new FileLine(fileline);
|
m_fileline = new FileLine(fileline);
|
||||||
m_inLibrary = inLibrary;
|
m_inLibrary = inLibrary;
|
||||||
|
|
||||||
// Read it
|
// Preprocess into m_ppBuffer
|
||||||
string vppfilename = v3Global.opt.makeDir()+"/"+v3Global.opt.prefix()+"_"+modname+".vpp";
|
V3PreShell::preproc(fileline, modfilename, this);
|
||||||
V3PreShell::preproc(fileline, modfilename, vppfilename);
|
|
||||||
|
|
||||||
if (!v3Global.opt.preprocOnly()) {
|
if (v3Global.opt.preprocOnly() || v3Global.opt.keepTempFiles()) {
|
||||||
lexFile (vppfilename, modfilename);
|
// Create output file with all the preprocessor output we buffered up
|
||||||
|
string vppfilename = v3Global.opt.makeDir()+"/"+v3Global.opt.prefix()+"_"+modname+".vpp";
|
||||||
|
ofstream* ofp = NULL;
|
||||||
|
ostream* osp;
|
||||||
|
if (v3Global.opt.preprocOnly()) {
|
||||||
|
osp = &cout;
|
||||||
|
} else {
|
||||||
|
osp = ofp = V3File::new_ofstream(vppfilename);
|
||||||
|
}
|
||||||
|
if (osp->fail()) {
|
||||||
|
fileline->v3error("Cannot write preprocessor output: "+vppfilename);
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
for (deque<string>::iterator it = m_ppBuffers.begin(); it!=m_ppBuffers.end(); ++it) {
|
||||||
|
*osp << *it;
|
||||||
|
}
|
||||||
|
if (ofp) {
|
||||||
|
ofp->close();
|
||||||
|
delete ofp; ofp = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!v3Global.opt.keepTempFiles()) { // Must match new_ofstream_nodepend rule in V3PreShell.cpp
|
// Parse it
|
||||||
unlink (vppfilename.c_str());
|
if (!v3Global.opt.preprocOnly()) {
|
||||||
|
lexFile (modfilename);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void V3Read::lexFile(const string& vppfilename, const string& modname) {
|
void V3Read::lexFile(const string& modname) {
|
||||||
// Open the preprocess output
|
|
||||||
// Don't track a input dependency, as we created the file ourselves
|
|
||||||
ifstream* fsp = V3File::new_ifstream_nodepend(vppfilename);
|
|
||||||
if (fsp->fail()) {
|
|
||||||
m_fileline->v3fatal("Module "<<modname<<" isn't found, or preprocessor errors in "<<vppfilename);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Prepare for lexing
|
// Prepare for lexing
|
||||||
UINFO(3,"Lexing "<<vppfilename<<endl);
|
UINFO(3,"Lexing "<<modname<<endl);
|
||||||
V3Read::s_readp = this;
|
V3Read::s_readp = this;
|
||||||
V3Read::fileline()->warnResetDefault(); // Reenable warnings on each file
|
V3Read::fileline()->warnResetDefault(); // Reenable warnings on each file
|
||||||
if (m_lexerp) delete m_lexerp; // Restart from clean slate.
|
if (m_lexerp) delete m_lexerp; // Restart from clean slate.
|
||||||
m_lexerp = new V3Lexer(fsp);
|
m_lexerp = new V3Lexer();
|
||||||
// if (debug()) { m_lexerp->set_debug(~0); }
|
// if (debug()) { m_lexerp->set_debug(~0); }
|
||||||
// if (debug()) yydebug = 1;
|
// if (debug()) yydebug = 1;
|
||||||
UINFO(4,"Lexing Done "<<vppfilename<<endl);
|
UINFO(4,"Lexing Done "<<modname<<endl);
|
||||||
|
|
||||||
// Lex it
|
// Lex it
|
||||||
if (yyparse()) v3fatal("Cannot continue\n");
|
if (yyparse()) v3fatal("Cannot continue\n");
|
||||||
|
|
||||||
// Cleanup
|
|
||||||
fsp->close(); delete fsp; fsp = NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//======================================================================
|
//======================================================================
|
||||||
|
|||||||
+7
-1
@@ -45,6 +45,7 @@ class V3Read {
|
|||||||
deque<string*> m_stringps; // Created strings for later cleanup
|
deque<string*> m_stringps; // Created strings for later cleanup
|
||||||
deque<V3Number*> m_numberps; // Created numbers for later cleanup
|
deque<V3Number*> m_numberps; // Created numbers for later cleanup
|
||||||
deque<FileLine> m_lintState; // Current lint state for save/restore
|
deque<FileLine> m_lintState; // Current lint state for save/restore
|
||||||
|
deque<string> m_ppBuffers; // Preprocessor->lex buffer of characters to process
|
||||||
//int debug() { return 9; }
|
//int debug() { return 9; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
@@ -52,6 +53,7 @@ protected:
|
|||||||
friend class V3Lexer;
|
friend class V3Lexer;
|
||||||
friend class V3LexerBase;
|
friend class V3LexerBase;
|
||||||
friend class FileLine;
|
friend class FileLine;
|
||||||
|
friend class V3PreShellImp;
|
||||||
int yylexThis();
|
int yylexThis();
|
||||||
static bool optPsl();
|
static bool optPsl();
|
||||||
static void ppline (const char* text);
|
static void ppline (const char* text);
|
||||||
@@ -64,6 +66,9 @@ protected:
|
|||||||
static bool popBeginKeywords() { if (s_readp->m_inBeginKwd) { s_readp->m_inBeginKwd--; return true; } else return false; }
|
static bool popBeginKeywords() { if (s_readp->m_inBeginKwd) { s_readp->m_inBeginKwd--; return true; } else return false; }
|
||||||
static int lastVerilogState() { return s_readp->m_lastVerilogState; }
|
static int lastVerilogState() { return s_readp->m_lastVerilogState; }
|
||||||
|
|
||||||
|
void ppPushText(const string& text) { m_ppBuffers.push_back(text); }
|
||||||
|
int ppInputToLex(char* buf, int max_size);
|
||||||
|
|
||||||
public: // But for internal use only
|
public: // But for internal use only
|
||||||
static string* newString(const string& text) {
|
static string* newString(const string& text) {
|
||||||
// Allocate a string, remembering it so we can reclaim storage at lex end
|
// Allocate a string, remembering it so we can reclaim storage at lex end
|
||||||
@@ -100,6 +105,7 @@ public: // But for internal use only
|
|||||||
static void statePushVlg(); // Parser -> lexer communication
|
static void statePushVlg(); // Parser -> lexer communication
|
||||||
static void statePop(); // Parser -> lexer communication
|
static void statePop(); // Parser -> lexer communication
|
||||||
static int stateVerilogRecent(); // Parser -> lexer communication
|
static int stateVerilogRecent(); // Parser -> lexer communication
|
||||||
|
static int flexPpInputToLex(char* buf, int max_size) { return s_readp->ppInputToLex(buf,max_size); }
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// CREATORS
|
// CREATORS
|
||||||
@@ -118,7 +124,7 @@ public:
|
|||||||
void readFile(FileLine* fileline, const string& modname, bool inLibrary);
|
void readFile(FileLine* fileline, const string& modname, bool inLibrary);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void lexFile(const string& vppfilename, const string& modname);
|
void lexFile(const string& modname);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // Guard
|
#endif // Guard
|
||||||
|
|||||||
+17
-9
@@ -90,14 +90,21 @@ V3Global v3Global;
|
|||||||
|
|
||||||
void V3Global::readFiles() {
|
void V3Global::readFiles() {
|
||||||
V3Read reader (m_rootp);
|
V3Read reader (m_rootp);
|
||||||
|
// Read top module
|
||||||
|
for (V3StringSet::iterator it = v3Global.opt.vFiles().begin();
|
||||||
|
it != v3Global.opt.vFiles().end(); ++it) {
|
||||||
|
string filename = *it;
|
||||||
|
reader.readFile(new FileLine("CommandLine",0), filename, false);
|
||||||
|
}
|
||||||
|
|
||||||
// Read libraries
|
// Read libraries
|
||||||
|
// To be compatible with other simulators,
|
||||||
|
// this needs to be done after the top file is read
|
||||||
for (V3StringSet::iterator it = v3Global.opt.libraryFiles().begin();
|
for (V3StringSet::iterator it = v3Global.opt.libraryFiles().begin();
|
||||||
it != v3Global.opt.libraryFiles().end(); ++it) {
|
it != v3Global.opt.libraryFiles().end(); ++it) {
|
||||||
string filename = *it;
|
string filename = *it;
|
||||||
reader.readFile(new FileLine("CommandLine",0), filename, true);
|
reader.readFile(new FileLine("CommandLine",0), filename, true);
|
||||||
}
|
}
|
||||||
// Read top module
|
|
||||||
reader.readFile(new FileLine("CommandLine",0), opt.top(), false);
|
|
||||||
V3Error::abortIfErrors();
|
V3Error::abortIfErrors();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -464,6 +471,7 @@ void process () {
|
|||||||
V3EmitC::emitcSyms();
|
V3EmitC::emitcSyms();
|
||||||
V3EmitC::emitcTrace();
|
V3EmitC::emitcTrace();
|
||||||
}
|
}
|
||||||
|
// Unfortunately we have some lint checks in emitc.
|
||||||
V3EmitC::emitc();
|
V3EmitC::emitc();
|
||||||
|
|
||||||
// Statistics
|
// Statistics
|
||||||
@@ -502,6 +510,10 @@ int main(int argc, char** argv, char** env) {
|
|||||||
if (!v3Global.opt.outFormatOk() && !v3Global.opt.preprocOnly() && !v3Global.opt.lintOnly()) {
|
if (!v3Global.opt.outFormatOk() && !v3Global.opt.preprocOnly() && !v3Global.opt.lintOnly()) {
|
||||||
v3fatal("verilator: Need --cc, --sc, --sp, --lint-only or --E option");
|
v3fatal("verilator: Need --cc, --sc, --sp, --lint-only or --E option");
|
||||||
}
|
}
|
||||||
|
// Check enviornment
|
||||||
|
V3Options::getenvSYSTEMC();
|
||||||
|
V3Options::getenvSYSTEMC_ARCH();
|
||||||
|
V3Options::getenvSYSTEMPERL();
|
||||||
|
|
||||||
V3Error::abortIfErrors();
|
V3Error::abortIfErrors();
|
||||||
|
|
||||||
@@ -521,13 +533,9 @@ int main(int argc, char** argv, char** env) {
|
|||||||
//--FRONTEND------------------
|
//--FRONTEND------------------
|
||||||
|
|
||||||
// Cleanup
|
// Cleanup
|
||||||
mkdir(v3Global.opt.makeDir().c_str(), 0777);
|
V3Options::unlinkRegexp(v3Global.opt.makeDir(), v3Global.opt.prefix()+"_*.tree");
|
||||||
string cleanFilename = "/bin/rm -rf "+v3Global.opt.makeDir()+"/"+v3Global.opt.prefix()+"_*.tree";
|
V3Options::unlinkRegexp(v3Global.opt.makeDir(), v3Global.opt.prefix()+"_*.dot");
|
||||||
system(cleanFilename.c_str());
|
V3Options::unlinkRegexp(v3Global.opt.makeDir(), v3Global.opt.prefix()+"_*.txt");
|
||||||
cleanFilename = "/bin/rm -rf "+v3Global.opt.makeDir()+"/"+v3Global.opt.prefix()+"_*.dot";
|
|
||||||
system(cleanFilename.c_str());
|
|
||||||
cleanFilename = "/bin/rm -rf "+v3Global.opt.makeDir()+"/"+v3Global.opt.prefix()+"_*.txt";
|
|
||||||
system(cleanFilename.c_str());
|
|
||||||
|
|
||||||
// Read first filename
|
// Read first filename
|
||||||
v3Global.readFiles();
|
v3Global.readFiles();
|
||||||
|
|||||||
+21
-1
@@ -24,7 +24,7 @@
|
|||||||
//**********************************************************************
|
//**********************************************************************
|
||||||
//**** Version and host name
|
//**** Version and host name
|
||||||
|
|
||||||
#define DTVERSION "Verilator 3.656 2008/01/18"
|
#define DTVERSION "Verilator 3.660 2008/03/23"
|
||||||
|
|
||||||
//**********************************************************************
|
//**********************************************************************
|
||||||
//**** Functions
|
//**** Functions
|
||||||
@@ -57,6 +57,26 @@
|
|||||||
// Set define if we have header: <inttypes.h>
|
// Set define if we have header: <inttypes.h>
|
||||||
#define HAVE_INTTYPES_H 0
|
#define HAVE_INTTYPES_H 0
|
||||||
|
|
||||||
|
//**********************************************************************
|
||||||
|
//**** Default environment
|
||||||
|
|
||||||
|
// Set defines to defaults for environment variables
|
||||||
|
// If set to "", this default is ignored and the user is expected
|
||||||
|
// to set them at Verilator runtime.
|
||||||
|
|
||||||
|
#ifndef DEFENV_SYSTEMC
|
||||||
|
# define DEFENV_SYSTEMC ""
|
||||||
|
#endif
|
||||||
|
#ifndef DEFENV_SYSTEMC_ARCH
|
||||||
|
# define DEFENV_SYSTEMC_ARCH ""
|
||||||
|
#endif
|
||||||
|
#ifndef DEFENV_SYSTEMPERL
|
||||||
|
# define DEFENV_SYSTEMPERL ""
|
||||||
|
#endif
|
||||||
|
#ifndef DEFENV_VERILATOR_ROOT
|
||||||
|
# define DEFENV_VERILATOR_ROOT ""
|
||||||
|
#endif
|
||||||
|
|
||||||
//**********************************************************************
|
//**********************************************************************
|
||||||
//**** Compile options
|
//**** Compile options
|
||||||
|
|
||||||
|
|||||||
+11
-4
@@ -33,6 +33,9 @@ extern void yyerrorf(const char* format, ...);
|
|||||||
|
|
||||||
#define STATE_VERILOG_RECENT S05 // State name for most recent Verilog Version
|
#define STATE_VERILOG_RECENT S05 // State name for most recent Verilog Version
|
||||||
|
|
||||||
|
#define YY_INPUT(buf,result,max_size) \
|
||||||
|
result = V3Read::flexPpInputToLex(buf,max_size);
|
||||||
|
|
||||||
//======================================================================
|
//======================================================================
|
||||||
|
|
||||||
#define NEXTLINE() {V3Read::incLineno();}
|
#define NEXTLINE() {V3Read::incLineno();}
|
||||||
@@ -631,14 +634,18 @@ escid \\[^ \t\f\r\n]+
|
|||||||
if (!isalnum(yytext[i]))
|
if (!isalnum(yytext[i]))
|
||||||
yytext[i] = '_';
|
yytext[i] = '_';
|
||||||
if (isalpha(yytext[1])) {
|
if (isalpha(yytext[1])) {
|
||||||
yylval.strp = V3Read::newString(yytext+1); // +1 to skip the backslash
|
yylval.strp = V3Read::newString(
|
||||||
|
AstNode::encodeName(
|
||||||
|
string(yytext+1))); // +1 to skip the backslash
|
||||||
} else {
|
} else {
|
||||||
yylval.strp = V3Read::newString(yytext); // Need _ as "6..." isn't legal ID
|
yylval.strp = V3Read::newString(
|
||||||
|
AstNode::encodeName(
|
||||||
|
yytext)); // Need _ as "6..." isn't legal ID
|
||||||
}
|
}
|
||||||
return yaID;
|
return yaID;
|
||||||
}
|
}
|
||||||
|
|
||||||
{id} { yylval.strp = V3Read::newString(yytext);
|
{id} { yylval.strp = V3Read::newString(AstNode::encodeName(string(yytext)));
|
||||||
return yaID;
|
return yaID;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -698,7 +705,7 @@ escid \\[^ \t\f\r\n]+
|
|||||||
/************************************************************************/
|
/************************************************************************/
|
||||||
/* Attributes */
|
/* Attributes */
|
||||||
<V95,V01,V05,S05>{
|
<V95,V01,V05,S05>{
|
||||||
"(*" { yymore(); yy_push_state(ATTRMODE); }
|
"(*"/{ws}*[^)] { yymore(); yy_push_state(ATTRMODE); } // Doesn't match (*)
|
||||||
}
|
}
|
||||||
|
|
||||||
/************************************************************************/
|
/************************************************************************/
|
||||||
|
|||||||
+11
-8
@@ -526,15 +526,15 @@ regsigList: regsig { $$ = $1; }
|
|||||||
| regsigList ',' regsig { $$ = $1;$1->addNext($3); }
|
| regsigList ',' regsig { $$ = $1;$1->addNext($3); }
|
||||||
;
|
;
|
||||||
|
|
||||||
portV2kDecl: varRESET varInput signingE v2kNetDeclE regrangeE portV2kSig { $$ = $6; }
|
portV2kDecl: varRESET varInput v2kNetDeclE signingE regrangeE portV2kSig { $$ = $6; }
|
||||||
| varRESET varInout signingE v2kNetDeclE regrangeE portV2kSig { $$ = $6; }
|
| varRESET varInout v2kNetDeclE signingE regrangeE portV2kSig { $$ = $6; }
|
||||||
| varRESET varOutput signingE v2kVarDeclE regrangeE portV2kSig { $$ = $6; }
|
| varRESET varOutput v2kVarDeclE signingE regrangeE portV2kSig { $$ = $6; }
|
||||||
;
|
;
|
||||||
|
|
||||||
// IEEE: port_declaration - plus ';'
|
// IEEE: port_declaration - plus ';'
|
||||||
portDecl: varRESET varInput signingE v2kVarDeclE regrangeE sigList ';' { $$ = $6; }
|
portDecl: varRESET varInput v2kVarDeclE signingE regrangeE sigList ';' { $$ = $6; }
|
||||||
| varRESET varInout signingE v2kVarDeclE regrangeE sigList ';' { $$ = $6; }
|
| varRESET varInout v2kVarDeclE signingE regrangeE sigList ';' { $$ = $6; }
|
||||||
| varRESET varOutput signingE v2kVarDeclE regrangeE sigList ';' { $$ = $6; }
|
| varRESET varOutput v2kVarDeclE signingE regrangeE sigList ';' { $$ = $6; }
|
||||||
;
|
;
|
||||||
|
|
||||||
varDecl: varRESET varReg signingE regrangeE regsigList ';' { $$ = $5; }
|
varDecl: varRESET varReg signingE regrangeE regsigList ';' { $$ = $5; }
|
||||||
@@ -838,7 +838,7 @@ eventControlE: /* empty */ { $$ = NULL; }
|
|||||||
// IEEE: event_control
|
// IEEE: event_control
|
||||||
eventControl: '@' '(' senList ')' { $$ = new AstSenTree($1,$3); }
|
eventControl: '@' '(' senList ')' { $$ = new AstSenTree($1,$3); }
|
||||||
| '@' senitemVar { $$ = new AstSenTree($1,$2); } /* For events only */
|
| '@' senitemVar { $$ = new AstSenTree($1,$2); } /* For events only */
|
||||||
| '@' '(' '*' ')' { $$ = NULL; $2->v3error("Use @*. always @ (*) to be depreciated in Verilog 2005.\n"); }
|
| '@' '(' '*' ')' { $$ = NULL; } /* Verilog 2001 */
|
||||||
| '@' '*' { $$ = NULL; } /* Verilog 2001 */
|
| '@' '*' { $$ = NULL; } /* Verilog 2001 */
|
||||||
;
|
;
|
||||||
|
|
||||||
@@ -1403,7 +1403,10 @@ AstVar* V3Parse::createVariable(FileLine* fileline, string name, AstRange* array
|
|||||||
rangep->cloneTree(false),
|
rangep->cloneTree(false),
|
||||||
arrayp);
|
arrayp);
|
||||||
nodep->isSigned(V3Parse::s_varSigned);
|
nodep->isSigned(V3Parse::s_varSigned);
|
||||||
if (type == AstVarType::INTEGER || V3Parse::s_varDecl == AstVarType::INTEGER) nodep->isSigned(true);
|
if (type == AstVarType::INTEGER || V3Parse::s_varDecl == AstVarType::INTEGER
|
||||||
|
|| type == AstVarType::GENVAR) {
|
||||||
|
nodep->isSigned(true);
|
||||||
|
}
|
||||||
if (V3Parse::s_varDecl != AstVarType::UNKNOWN) nodep->combineType(V3Parse::s_varDecl);
|
if (V3Parse::s_varDecl != AstVarType::UNKNOWN) nodep->combineType(V3Parse::s_varDecl);
|
||||||
if (V3Parse::s_varIO != AstVarType::UNKNOWN) nodep->combineType(V3Parse::s_varIO);
|
if (V3Parse::s_varIO != AstVarType::UNKNOWN) nodep->combineType(V3Parse::s_varIO);
|
||||||
|
|
||||||
|
|||||||
@@ -39,6 +39,7 @@ endif
|
|||||||
|
|
||||||
######################################################################
|
######################################################################
|
||||||
|
|
||||||
|
.PHONY: test
|
||||||
test:
|
test:
|
||||||
$(PERL) driver.pl $(DRIVER_FLAGS) $(PRODUCTS)
|
$(PERL) driver.pl $(DRIVER_FLAGS) $(PRODUCTS)
|
||||||
|
|
||||||
|
|||||||
@@ -443,7 +443,8 @@ sub sc_or_sp {
|
|||||||
|
|
||||||
sub _run {
|
sub _run {
|
||||||
my $self = (ref $_[0]? shift : $Last_Self);
|
my $self = (ref $_[0]? shift : $Last_Self);
|
||||||
my %param = (@_);
|
my %param = (tee=>1,
|
||||||
|
@_);
|
||||||
my $command = join(' ',@{$param{cmd}});
|
my $command = join(' ',@{$param{cmd}});
|
||||||
print "\t$command\n";
|
print "\t$command\n";
|
||||||
|
|
||||||
@@ -451,7 +452,11 @@ sub _run {
|
|||||||
open(SAVEOUT, ">&STDOUT") or die "%Error: Can't dup stdout";
|
open(SAVEOUT, ">&STDOUT") or die "%Error: Can't dup stdout";
|
||||||
open(SAVEERR, ">&STDERR") or die "%Error: Can't dup stderr";
|
open(SAVEERR, ">&STDERR") or die "%Error: Can't dup stderr";
|
||||||
if (0) {close(SAVEOUT); close(SAVEERR);} # Prevent unused warning
|
if (0) {close(SAVEOUT); close(SAVEERR);} # Prevent unused warning
|
||||||
open(STDOUT, "|tee $param{logfile}") or die "%Error: Can't redirect stdout";
|
if ($param{tee}) {
|
||||||
|
open(STDOUT, "|tee $param{logfile}") or die "%Error: Can't redirect stdout";
|
||||||
|
} else {
|
||||||
|
open(STDOUT, ">$param{logfile}") or die "%Error: Can't open $param{logfile}";
|
||||||
|
}
|
||||||
open(STDERR, ">&STDOUT") or die "%Error: Can't dup stdout";
|
open(STDERR, ">&STDOUT") or die "%Error: Can't dup stdout";
|
||||||
autoflush STDOUT 1;
|
autoflush STDOUT 1;
|
||||||
autoflush STDERR 1;
|
autoflush STDERR 1;
|
||||||
|
|||||||
@@ -14,7 +14,7 @@
|
|||||||
// please note it here, otherwise:**
|
// please note it here, otherwise:**
|
||||||
//
|
//
|
||||||
// This file ONLY is placed into the Public Domain, for any use,
|
// This file ONLY is placed into the Public Domain, for any use,
|
||||||
// without warranty, 2007 by Wilson Snyder.
|
// without warranty, 2008 by Wilson Snyder.
|
||||||
|
|
||||||
module t (/*AUTOARG*/
|
module t (/*AUTOARG*/
|
||||||
// Inputs
|
// Inputs
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// $Id:$
|
// $Id$
|
||||||
// DESCRIPTION: Verilator: Verilog Test module
|
// DESCRIPTION: Verilator: Verilog Test module
|
||||||
//
|
//
|
||||||
// This file ONLY is placed into the Public Domain, for any use,
|
// This file ONLY is placed into the Public Domain, for any use,
|
||||||
@@ -14,7 +14,7 @@ module t (/*AUTOARG*/
|
|||||||
|
|
||||||
reg [31:0] a, b, c;
|
reg [31:0] a, b, c;
|
||||||
|
|
||||||
always @ (/*AS*/a or b) begin
|
always @ (*) begin // Test Verilog 2001 (*)
|
||||||
// verilator lint_off COMBDLY
|
// verilator lint_off COMBDLY
|
||||||
c <= a | b;
|
c <= a | b;
|
||||||
// verilator lint_on COMBDLY
|
// verilator lint_on COMBDLY
|
||||||
|
|||||||
Executable
+18
@@ -0,0 +1,18 @@
|
|||||||
|
#!/usr/bin/perl
|
||||||
|
if (!$::Driver) { use FindBin; exec("./driver.pl", @ARGV, $0); die; }
|
||||||
|
# $Id$
|
||||||
|
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||||
|
#
|
||||||
|
# Copyright 2003 by Wilson Snyder. This program is free software; you can
|
||||||
|
# redistribute it and/or modify it under the terms of either the GNU
|
||||||
|
# General Public License or the Perl Artistic License.
|
||||||
|
|
||||||
|
compile (
|
||||||
|
);
|
||||||
|
|
||||||
|
execute (
|
||||||
|
check_finished=>1,
|
||||||
|
);
|
||||||
|
|
||||||
|
ok(1);
|
||||||
|
1;
|
||||||
@@ -0,0 +1,56 @@
|
|||||||
|
// $Id$
|
||||||
|
// DESCRIPTION: Verilator: Verilog Test module
|
||||||
|
//
|
||||||
|
// This file ONLY is placed into the Public Domain, for any use,
|
||||||
|
// without warranty, 2003-2008 by Wilson Snyder.
|
||||||
|
|
||||||
|
module t (clk);
|
||||||
|
input clk;
|
||||||
|
|
||||||
|
integer cyc; initial cyc=1;
|
||||||
|
integer sum;
|
||||||
|
integer cpre;
|
||||||
|
always @ (posedge clk) begin
|
||||||
|
if (cyc!=0) begin
|
||||||
|
cpre = cyc;
|
||||||
|
cyc <= cyc + 1;
|
||||||
|
if (cyc==1) begin
|
||||||
|
if (mlog2(32'd0) != 32'd0) $stop;
|
||||||
|
if (mlog2(32'd1) != 32'd0) $stop;
|
||||||
|
if (mlog2(32'd3) != 32'd2) $stop;
|
||||||
|
sum <= 32'd0;
|
||||||
|
end
|
||||||
|
else if (cyc<90) begin
|
||||||
|
// (cyc) so if we trash the variable things will get upset.
|
||||||
|
sum <= mlog2(cyc) + sum * 32'd42;
|
||||||
|
if (cpre != cyc) $stop;
|
||||||
|
end
|
||||||
|
else if (cyc==90) begin
|
||||||
|
if (sum !== 32'h0f12bb51) $stop;
|
||||||
|
$write("*-* All Finished *-*\n");
|
||||||
|
$finish;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function integer mlog2;
|
||||||
|
input [31:0] value;
|
||||||
|
integer i;
|
||||||
|
begin
|
||||||
|
if(value < 32'd1) begin
|
||||||
|
mlog2 = 0;
|
||||||
|
end
|
||||||
|
else begin
|
||||||
|
value = value - 32'd1;
|
||||||
|
mlog2 = 0;
|
||||||
|
for(i=0;i<32;i=i+1) begin
|
||||||
|
if(value > 32'd0) begin
|
||||||
|
mlog2 = mlog2 + 1;
|
||||||
|
end
|
||||||
|
value = value >> 1;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
endmodule
|
||||||
Executable
+18
@@ -0,0 +1,18 @@
|
|||||||
|
#!/usr/bin/perl
|
||||||
|
if (!$::Driver) { use FindBin; exec("./driver.pl", @ARGV, $0); die; }
|
||||||
|
# $Id$
|
||||||
|
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||||
|
#
|
||||||
|
# Copyright 2003 by Wilson Snyder. This program is free software; you can
|
||||||
|
# redistribute it and/or modify it under the terms of either the GNU
|
||||||
|
# General Public License or the Perl Artistic License.
|
||||||
|
|
||||||
|
compile (
|
||||||
|
);
|
||||||
|
|
||||||
|
execute (
|
||||||
|
check_finished=>1,
|
||||||
|
);
|
||||||
|
|
||||||
|
ok(1);
|
||||||
|
1;
|
||||||
@@ -0,0 +1,85 @@
|
|||||||
|
// $Id$
|
||||||
|
// DESCRIPTION: Verilator: Verilog Test module
|
||||||
|
//
|
||||||
|
// This file ONLY is placed into the Public Domain, for any use,
|
||||||
|
// without warranty, 2007 by Wilson Snyder.
|
||||||
|
|
||||||
|
module t (/*AUTOARG*/
|
||||||
|
// Inputs
|
||||||
|
clk
|
||||||
|
);
|
||||||
|
input clk;
|
||||||
|
|
||||||
|
wire b;
|
||||||
|
reg reset;
|
||||||
|
integer cyc=0;
|
||||||
|
|
||||||
|
Testit testit (/*AUTOINST*/
|
||||||
|
// Outputs
|
||||||
|
.b (b),
|
||||||
|
// Inputs
|
||||||
|
.clk (clk),
|
||||||
|
.reset (reset));
|
||||||
|
|
||||||
|
always @ (posedge clk) begin
|
||||||
|
cyc <= cyc + 1;
|
||||||
|
if (cyc==0) begin
|
||||||
|
reset <= 1'b0;
|
||||||
|
end
|
||||||
|
else if (cyc<10) begin
|
||||||
|
reset <= 1'b1;
|
||||||
|
end
|
||||||
|
else if (cyc<90) begin
|
||||||
|
reset <= 1'b0;
|
||||||
|
end
|
||||||
|
else if (cyc==99) begin
|
||||||
|
$write("*-* All Finished *-*\n");
|
||||||
|
$finish;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
module Testit (clk, reset, b);
|
||||||
|
input clk;
|
||||||
|
input reset;
|
||||||
|
output b;
|
||||||
|
|
||||||
|
wire [0:0] c;
|
||||||
|
wire my_sig;
|
||||||
|
wire [0:0] d;
|
||||||
|
|
||||||
|
genvar i;
|
||||||
|
generate
|
||||||
|
for(i = 0; i >= 0; i = i-1) begin: fnxtclk1
|
||||||
|
fnxtclk fnxtclk1
|
||||||
|
(.u(c[i]),
|
||||||
|
.reset(reset),
|
||||||
|
.clk(clk),
|
||||||
|
.w(d[i]) );
|
||||||
|
end
|
||||||
|
endgenerate
|
||||||
|
|
||||||
|
assign b = d[0];
|
||||||
|
assign c[0] = my_sig;
|
||||||
|
assign my_sig = 1'b1;
|
||||||
|
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
module fnxtclk (u, reset, clk, w );
|
||||||
|
input u;
|
||||||
|
input reset;
|
||||||
|
input clk;
|
||||||
|
output reg w;
|
||||||
|
|
||||||
|
always @ (posedge clk or posedge reset) begin
|
||||||
|
if (reset == 1'b1) begin
|
||||||
|
w <= 1'b0;
|
||||||
|
end
|
||||||
|
else begin
|
||||||
|
w <= u;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
endmodule
|
||||||
|
|
||||||
Executable
+20
@@ -0,0 +1,20 @@
|
|||||||
|
#!/usr/bin/perl
|
||||||
|
if (!$::Driver) { use FindBin; exec("./driver.pl", @ARGV, $0); die; }
|
||||||
|
# $Id$
|
||||||
|
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||||
|
#
|
||||||
|
# Copyright 2003-2007 by Wilson Snyder. This program is free software; you can
|
||||||
|
# redistribute it and/or modify it under the terms of either the GNU
|
||||||
|
# General Public License or the Perl Artistic License.
|
||||||
|
|
||||||
|
$Last_Self->_run(fails=>1,
|
||||||
|
cmd=>["perl","../bin/verilator",
|
||||||
|
"--help"],
|
||||||
|
logfile=>"obj_dir/t_help.log",
|
||||||
|
tee=>0,
|
||||||
|
) if $Last_Self->{v3};
|
||||||
|
|
||||||
|
file_grep ("obj_dir/t_help.log", qr/DISTRIBUTION/i);
|
||||||
|
|
||||||
|
ok(1);
|
||||||
|
1;
|
||||||
Executable
+16
@@ -0,0 +1,16 @@
|
|||||||
|
#!/usr/bin/perl
|
||||||
|
if (!$::Driver) { use FindBin; exec("./driver.pl", @ARGV, $0); die; }
|
||||||
|
# $Id$
|
||||||
|
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||||
|
#
|
||||||
|
# Copyright 2003 by Wilson Snyder. This program is free software; you can
|
||||||
|
# redistribute it and/or modify it under the terms of either the GNU
|
||||||
|
# General Public License or the Perl Artistic License.
|
||||||
|
|
||||||
|
compile (
|
||||||
|
v_flags2 => ["-Wno-IMPLICIT"],
|
||||||
|
) if $Last_Self->{v3};
|
||||||
|
|
||||||
|
ok(1);
|
||||||
|
1;
|
||||||
|
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
// $Id$
|
||||||
|
// DESCRIPTION: Verilator: Verilog Test module
|
||||||
|
//
|
||||||
|
// This file ONLY is placed into the Public Domain, for any use,
|
||||||
|
// without warranty, 2008 by Wilson Snyder.
|
||||||
|
|
||||||
|
module t (a,z);
|
||||||
|
input a;
|
||||||
|
output z;
|
||||||
|
|
||||||
|
assign b = 1'b1;
|
||||||
|
|
||||||
|
or OR0 (nt0, a, b);
|
||||||
|
|
||||||
|
assign z = nt0;
|
||||||
|
endmodule
|
||||||
Executable
+24
@@ -0,0 +1,24 @@
|
|||||||
|
#!/usr/bin/perl
|
||||||
|
if (!$::Driver) { use FindBin; exec("./driver.pl", @ARGV, $0); die; }
|
||||||
|
# $Id$
|
||||||
|
# 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
|
||||||
|
# General Public License or the Perl Artistic License.
|
||||||
|
|
||||||
|
top_filename("t/t_lint_implicit.v");
|
||||||
|
|
||||||
|
compile (
|
||||||
|
v_flags2 => ["--lint-only"],
|
||||||
|
fails=>1,
|
||||||
|
expect=>
|
||||||
|
'%Warning-IMPLICIT: t/t_lint_implicit.v:\d+: Signal definition not found, creating implicitly: b
|
||||||
|
%Warning-IMPLICIT: Use .* to disable this message.
|
||||||
|
%Warning-IMPLICIT: t/t_lint_implicit.v:\d+: Signal definition not found, creating implicitly: nt0
|
||||||
|
%Error: Exiting due to.*',
|
||||||
|
) if $Last_Self->{v3};
|
||||||
|
|
||||||
|
ok(1);
|
||||||
|
1;
|
||||||
|
|
||||||
@@ -15,21 +15,24 @@ module t (/*AUTOARG*/
|
|||||||
reg [63:0] crc;
|
reg [63:0] crc;
|
||||||
reg [63:0] sum;
|
reg [63:0] sum;
|
||||||
|
|
||||||
reg [31:0] out1;
|
wire [31:0] out1;
|
||||||
sub sub (.in1(crc[15:0]), .in2(crc[31:16]), .out1(out1));
|
wire [31:0] out2;
|
||||||
|
sub sub (.in1(crc[15:0]), .in2(crc[31:16]), .out1(out1), .out2);
|
||||||
|
|
||||||
always @ (posedge clk) begin
|
always @ (posedge clk) begin
|
||||||
//$write("[%0t] cyc==%0d crc=%x sum=%x out=%x\n",$time, cyc, crc, sum, out1);
|
`ifdef TEST_VERBOSE
|
||||||
|
$write("[%0t] cyc==%0d crc=%x sum=%x out=%x %x\n",$time, cyc, crc, sum, out1, out2);
|
||||||
|
`endif
|
||||||
cyc <= cyc + 1;
|
cyc <= cyc + 1;
|
||||||
crc <= {crc[62:0], crc[63]^crc[2]^crc[0]};
|
crc <= {crc[62:0], crc[63]^crc[2]^crc[0]};
|
||||||
sum <= {sum[62:0], sum[63]^sum[2]^sum[0]} ^ {32'h0,out1};
|
sum <= {sum[62:0], sum[63]^sum[2]^sum[0]} ^ {out2,out1};
|
||||||
if (cyc==1) begin
|
if (cyc==1) begin
|
||||||
// Setup
|
// Setup
|
||||||
crc <= 64'h00000000_00000097;
|
crc <= 64'h00000000_00000097;
|
||||||
sum <= 64'h0;
|
sum <= 64'h0;
|
||||||
end
|
end
|
||||||
else if (cyc==90) begin
|
else if (cyc==90) begin
|
||||||
if (sum !== 64'hc1f743ad62c2c04d) $stop;
|
if (sum !== 64'he396068aba3898a2) $stop;
|
||||||
end
|
end
|
||||||
else if (cyc==91) begin
|
else if (cyc==91) begin
|
||||||
end
|
end
|
||||||
@@ -49,18 +52,20 @@ endmodule
|
|||||||
|
|
||||||
module sub (/*AUTOARG*/
|
module sub (/*AUTOARG*/
|
||||||
// Outputs
|
// Outputs
|
||||||
out1,
|
out1, out2,
|
||||||
// Inputs
|
// Inputs
|
||||||
in1, in2
|
in1, in2
|
||||||
);
|
);
|
||||||
|
|
||||||
input [15:0] in1;
|
input [15:0] in1;
|
||||||
input [15:0] in2;
|
input [15:0] in2;
|
||||||
output reg [31:0] out1;
|
output reg signed [31:0] out1;
|
||||||
|
output reg unsigned [31:0] out2;
|
||||||
|
|
||||||
always @* begin
|
always @* begin
|
||||||
// verilator lint_off WIDTH
|
// verilator lint_off WIDTH
|
||||||
out1 = $signed(in1) * $signed(in2);
|
out1 = $signed(in1) * $signed(in2);
|
||||||
|
out2 = $unsigned(in1) * $unsigned(in2);
|
||||||
// verilator lint_on WIDTH
|
// verilator lint_on WIDTH
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
Executable
+18
@@ -0,0 +1,18 @@
|
|||||||
|
#!/usr/bin/perl
|
||||||
|
if (!$::Driver) { use FindBin; exec("./driver.pl", @ARGV, $0); die; }
|
||||||
|
# $Id$
|
||||||
|
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||||
|
#
|
||||||
|
# Copyright 2003 by Wilson Snyder. This program is free software; you can
|
||||||
|
# redistribute it and/or modify it under the terms of either the GNU
|
||||||
|
# General Public License or the Perl Artistic License.
|
||||||
|
|
||||||
|
compile (
|
||||||
|
);
|
||||||
|
|
||||||
|
execute (
|
||||||
|
check_finished=>1,
|
||||||
|
);
|
||||||
|
|
||||||
|
ok(1);
|
||||||
|
1;
|
||||||
@@ -0,0 +1,165 @@
|
|||||||
|
// $Id$
|
||||||
|
// DESCRIPTION: Verilator: Verilog Test module
|
||||||
|
//
|
||||||
|
// This file ONLY is placed into the Public Domain, for any use,
|
||||||
|
// without warranty, 2008 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 [31:0] Operand1 = crc[31:0];
|
||||||
|
wire [15:0] Operand2 = crc[47:32];
|
||||||
|
wire Unsigned = crc[48];
|
||||||
|
reg rst;
|
||||||
|
|
||||||
|
parameter wl = 16;
|
||||||
|
|
||||||
|
/*AUTOWIRE*/
|
||||||
|
// Beginning of automatic wires (for undeclared instantiated-module outputs)
|
||||||
|
wire [wl-1:0] Quotient; // From test of Test.v
|
||||||
|
wire [wl-1:0] Remainder; // From test of Test.v
|
||||||
|
// End of automatics
|
||||||
|
|
||||||
|
Test test (/*AUTOINST*/
|
||||||
|
// Outputs
|
||||||
|
.Quotient (Quotient[wl-1:0]),
|
||||||
|
.Remainder (Remainder[wl-1:0]),
|
||||||
|
// Inputs
|
||||||
|
.Operand1 (Operand1[wl*2-1:0]),
|
||||||
|
.Operand2 (Operand2[wl-1:0]),
|
||||||
|
.clk (clk),
|
||||||
|
.rst (rst),
|
||||||
|
.Unsigned (Unsigned));
|
||||||
|
|
||||||
|
// Aggregate outputs into a single result vector
|
||||||
|
wire [63:0] result = {32'h0, Quotient, Remainder};
|
||||||
|
|
||||||
|
// What checksum will we end up with
|
||||||
|
`define EXPECTED_SUM 64'h98d41f89a8be5693
|
||||||
|
|
||||||
|
// Test loop
|
||||||
|
always @ (posedge clk) begin
|
||||||
|
`ifdef TEST_VERBOSE
|
||||||
|
$write("[%0t] cyc==%0d crc=%x result=%x it=%x\n",$time, cyc, crc, result, test.Iteration);
|
||||||
|
`endif
|
||||||
|
cyc <= cyc + 1;
|
||||||
|
if (cyc < 20 || test.Iteration==4'd15) begin
|
||||||
|
crc <= {crc[62:0], crc[63]^crc[2]^crc[0]};
|
||||||
|
end
|
||||||
|
sum <= result ^ {sum[62:0],sum[63]^sum[2]^sum[0]};
|
||||||
|
if (cyc==0) begin
|
||||||
|
// Setup
|
||||||
|
crc <= 64'h5aef0c8d_d70a4497;
|
||||||
|
rst <= 1'b1;
|
||||||
|
end
|
||||||
|
else if (cyc<20) begin
|
||||||
|
sum <= 64'h0;
|
||||||
|
rst <= 1'b0;
|
||||||
|
end
|
||||||
|
else if (cyc<90) begin
|
||||||
|
end
|
||||||
|
else if (cyc==99) begin
|
||||||
|
$write("[%0t] cyc==%0d crc=%x sum=%x\n",$time, cyc, crc, sum);
|
||||||
|
if (crc !== 64'h8dd70a44972ad809) $stop;
|
||||||
|
if (sum !== `EXPECTED_SUM) $stop;
|
||||||
|
$write("*-* All Finished *-*\n");
|
||||||
|
$finish;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
module Test(clk, rst, Operand1, Operand2, Unsigned, Quotient, Remainder);
|
||||||
|
|
||||||
|
parameter wl = 16;
|
||||||
|
|
||||||
|
input [wl*2-1:0] Operand1;
|
||||||
|
input [wl-1:0] Operand2;
|
||||||
|
input clk, rst, Unsigned;
|
||||||
|
output [wl-1:0] Quotient, Remainder;
|
||||||
|
|
||||||
|
reg Cy, Overflow, Sign1, Sign2, Zero, Negative;
|
||||||
|
reg [wl-1:0] ah,al,Quotient, Remainder;
|
||||||
|
reg [3:0] Iteration;
|
||||||
|
reg [wl-1:0] sub_quot,op;
|
||||||
|
reg ah_ext;
|
||||||
|
|
||||||
|
reg [1:0] a,b,c,d,e;
|
||||||
|
|
||||||
|
always @(posedge clk) begin
|
||||||
|
if (!rst) begin
|
||||||
|
{a,b,c,d,e} = Operand1[9:0];
|
||||||
|
{a,b,c,d,e} = {e,d,c,b,a};
|
||||||
|
if (a != Operand1[1:0]) $stop;
|
||||||
|
if (b != Operand1[3:2]) $stop;
|
||||||
|
if (c != Operand1[5:4]) $stop;
|
||||||
|
if (d != Operand1[7:6]) $stop;
|
||||||
|
if (e != Operand1[9:8]) $stop;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
always @(posedge clk) begin
|
||||||
|
if (rst) begin
|
||||||
|
Iteration <= 0;
|
||||||
|
Quotient <= 0;
|
||||||
|
Remainder <= 0;
|
||||||
|
end
|
||||||
|
else begin
|
||||||
|
if (Iteration == 0) begin
|
||||||
|
{ah,al} = Operand1;
|
||||||
|
op = Operand2;
|
||||||
|
Cy = 0;
|
||||||
|
Overflow = 0;
|
||||||
|
Sign1 = (~Unsigned)&ah[wl-1];
|
||||||
|
Sign2 = (~Unsigned)&(ah[wl-1]^op[wl-1]);
|
||||||
|
if (Sign1) {ah,al} = -{ah,al};
|
||||||
|
end
|
||||||
|
`define BUG1
|
||||||
|
`ifdef BUG1
|
||||||
|
{ah_ext,ah,al} = {ah,al,Cy};
|
||||||
|
`else
|
||||||
|
ah_ext = ah[15];
|
||||||
|
ah[15:1] = ah[14:0];
|
||||||
|
ah[0] = al[15];
|
||||||
|
al[15:1] = al[14:0];
|
||||||
|
al[0] = Cy;
|
||||||
|
`endif
|
||||||
|
`ifdef TEST_VERBOSE
|
||||||
|
$display("%x %x %x %x %x %x %x %x %x",
|
||||||
|
Iteration, ah, al, Quotient, Remainder, Overflow, ah_ext, sub_quot, Cy);
|
||||||
|
`endif
|
||||||
|
{Cy,sub_quot} = (~Unsigned)&op[wl-1]? {ah_ext,ah}+op : {ah_ext,ah} - {1'b1,op};
|
||||||
|
if (Cy)
|
||||||
|
begin
|
||||||
|
{ah_ext,ah} = {1'b0,sub_quot};
|
||||||
|
end
|
||||||
|
if (Iteration != 15 )
|
||||||
|
begin
|
||||||
|
if (ah_ext) Overflow = 1;
|
||||||
|
end
|
||||||
|
else
|
||||||
|
begin
|
||||||
|
if (al[14] && ~Unsigned) Overflow = 1;
|
||||||
|
Quotient <= Sign2 ? -{al[14:0],Cy} : {al[14:0],Cy};
|
||||||
|
Remainder <= Sign1 ? -ah : ah;
|
||||||
|
if (Overflow)
|
||||||
|
begin
|
||||||
|
Quotient <= Sign2 ? 16'h8001 : {Unsigned,{15{1'b1}}};
|
||||||
|
Remainder <= Unsigned ? 16'hffff : 16'h8000;
|
||||||
|
Zero = 1;
|
||||||
|
Negative = 1;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
Iteration <= Iteration + 1; // Count number of times this instruction is repeated
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
endmodule
|
||||||
Executable
+16
@@ -0,0 +1,16 @@
|
|||||||
|
#!/usr/bin/perl
|
||||||
|
if (!$::Driver) { use FindBin; exec("./driver.pl", @ARGV, $0); die; }
|
||||||
|
# $Id$
|
||||||
|
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||||
|
#
|
||||||
|
# Copyright 2003 by Wilson Snyder. This program is free software; you can
|
||||||
|
# redistribute it and/or modify it under the terms of either the GNU
|
||||||
|
# General Public License or the Perl Artistic License.
|
||||||
|
|
||||||
|
compile (
|
||||||
|
v_flags2 => ["-Wno-REDEFMACRO"],
|
||||||
|
) if $Last_Self->{v3};
|
||||||
|
|
||||||
|
ok(1);
|
||||||
|
1;
|
||||||
|
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
// $Id$
|
||||||
|
// DESCRIPTION: Verilator: Verilog Test module
|
||||||
|
//
|
||||||
|
// This file ONLY is placed into the Public Domain, for any use,
|
||||||
|
// without warranty, 2008 by Wilson Snyder.
|
||||||
|
|
||||||
|
module t;
|
||||||
|
|
||||||
|
`define DUP fred
|
||||||
|
`define DUP barney
|
||||||
|
|
||||||
|
`define DUPP paramed(x) (x)
|
||||||
|
`define DUPP paramed(x,z) (x*z)
|
||||||
|
|
||||||
|
initial $stop; // Should have failed
|
||||||
|
|
||||||
|
endmodule
|
||||||
Executable
+26
@@ -0,0 +1,26 @@
|
|||||||
|
#!/usr/bin/perl
|
||||||
|
if (!$::Driver) { use FindBin; exec("./driver.pl", @ARGV, $0); die; }
|
||||||
|
# $Id$
|
||||||
|
# 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
|
||||||
|
# General Public License or the Perl Artistic License.
|
||||||
|
|
||||||
|
top_filename("t/t_pp_dupdef.v");
|
||||||
|
|
||||||
|
compile (
|
||||||
|
v_flags2 => ["--lint-only"],
|
||||||
|
fails=>1,
|
||||||
|
expect=>
|
||||||
|
'%Warning-REDEFMACRO: t/t_pp_dupdef.v:\d+: Redefining existing define: DUP, with different value: barney
|
||||||
|
%Warning-REDEFMACRO: Use .* to disable this message.
|
||||||
|
%Warning-REDEFMACRO: t/t_pp_dupdef.v:\d+: Previous definition is here, with value: fred
|
||||||
|
%Warning-REDEFMACRO: t/t_pp_dupdef.v:\d+: Redefining existing define: DUPP, with different value: .*
|
||||||
|
%Warning-REDEFMACRO: t/t_pp_dupdef.v:\d+: Previous definition is here, with value: .*
|
||||||
|
%Error: Exiting due to.*',
|
||||||
|
) if $Last_Self->{v3};
|
||||||
|
|
||||||
|
ok(1);
|
||||||
|
1;
|
||||||
|
|
||||||
Executable
+20
@@ -0,0 +1,20 @@
|
|||||||
|
#!/usr/bin/perl
|
||||||
|
if (!$::Driver) { use FindBin; exec("./driver.pl", @ARGV, $0); die; }
|
||||||
|
# $Id$
|
||||||
|
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||||
|
#
|
||||||
|
# Copyright 2003 by Wilson Snyder. This program is free software; you can
|
||||||
|
# redistribute it and/or modify it under the terms of either the GNU
|
||||||
|
# General Public License or the Perl Artistic License.
|
||||||
|
|
||||||
|
compile (
|
||||||
|
v_flags2 => ['-v', 't/t_pp_lib_library.v'],
|
||||||
|
);
|
||||||
|
|
||||||
|
execute (
|
||||||
|
check_finished=>1,
|
||||||
|
);
|
||||||
|
|
||||||
|
ok(1);
|
||||||
|
1;
|
||||||
|
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
// $Id$
|
||||||
|
// DESCRIPTION: Verilator: Verilog Test module
|
||||||
|
//
|
||||||
|
// This file ONLY is placed into the Public Domain, for any use,
|
||||||
|
// without warranty, 2008 by Wilson Snyder.
|
||||||
|
|
||||||
|
`include "t_pp_lib_inc.v"
|
||||||
|
module t();
|
||||||
|
wire [`WIDTH-1:0] a;
|
||||||
|
library_cell n1(a);
|
||||||
|
endmodule
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
// $Id$
|
||||||
|
// DESCRIPTION: Verilator: Verilog Test module
|
||||||
|
//
|
||||||
|
// This file ONLY is placed into the Public Domain, for any use,
|
||||||
|
// without warranty, 2008 by Wilson Snyder.
|
||||||
|
|
||||||
|
`define WIDTH 10
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
// $Id$
|
||||||
|
// DESCRIPTION: Verilator: Verilog Test module
|
||||||
|
//
|
||||||
|
// This file ONLY is placed into the Public Domain, for any use,
|
||||||
|
// without warranty, 2008 by Wilson Snyder.
|
||||||
|
|
||||||
|
module library_cell(a);
|
||||||
|
input [`WIDTH-1:0] a;
|
||||||
|
initial begin
|
||||||
|
$write("*-* All Finished *-*\n");
|
||||||
|
$finish;
|
||||||
|
end
|
||||||
|
endmodule
|
||||||
@@ -8,7 +8,7 @@ if (!$::Driver) { use FindBin; exec("./driver.pl", @ARGV, $0); die; }
|
|||||||
# General Public License or the Perl Artistic License.
|
# General Public License or the Perl Artistic License.
|
||||||
|
|
||||||
compile (
|
compile (
|
||||||
v_flags2 => ["--lint-only"],
|
v_flags2 => ["--lint-only --Mdir obj_lint_only"],
|
||||||
fails=>1,
|
fails=>1,
|
||||||
expect=>
|
expect=>
|
||||||
'%Error: t/t_var_in_assign_bad.v:\d+: Assigning to input variable: value
|
'%Error: t/t_var_in_assign_bad.v:\d+: Assigning to input variable: value
|
||||||
@@ -16,5 +16,6 @@ compile (
|
|||||||
%Error: Exiting due to.*',
|
%Error: Exiting due to.*',
|
||||||
) if $Last_Self->{v3};
|
) if $Last_Self->{v3};
|
||||||
|
|
||||||
|
(!-d "obj_lint_only") or $Last_Self->error("%Error: lint-only shouldn't make output directory");
|
||||||
ok(1);
|
ok(1);
|
||||||
1;
|
1;
|
||||||
|
|||||||
Reference in New Issue
Block a user