mirror of
https://github.com/verilator/verilator.git
synced 2026-10-05 17:43:31 +02:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
813d62005d | ||
|
|
411de9bddf | ||
|
|
bd28945374 | ||
|
|
1e4c3751e1 | ||
|
|
5b6f47cd0f | ||
|
|
bec8c5bf4c | ||
|
|
15495bb200 | ||
|
|
999f278971 | ||
|
|
7ca1d35a4e | ||
|
|
2117fe414e | ||
|
|
7d8c51181d | ||
|
|
c30211cb27 | ||
|
|
901da118e5 | ||
|
|
f11757e43a | ||
|
|
3f143317a6 | ||
|
|
45d7312dfc | ||
|
|
26774eb045 | ||
|
|
6789d247e2 | ||
|
|
462bc3d707 | ||
|
|
e1755ea6a8 | ||
|
|
b4a7e4697e | ||
|
|
cd61b1d045 | ||
|
|
24dc36ba4c | ||
|
|
e8e4f1777d | ||
|
|
ae38a26af3 | ||
|
|
8ee94dd7aa | ||
|
|
e741a29d36 | ||
|
|
be1d275151 | ||
|
|
31c9e26e2e | ||
|
|
20ed1ada03 | ||
|
|
891214fa72 | ||
|
|
e819e285e2 | ||
|
|
171c175e54 | ||
|
|
675cbce8cb | ||
|
|
4f1398f773 | ||
|
|
ae89e399a3 | ||
|
|
2c9716c64c | ||
|
|
bc58245abf | ||
|
|
8c4aa8517e | ||
|
|
c0b7a54bb9 | ||
|
|
6b32bb635d | ||
|
|
691de22ae3 | ||
|
|
e64b2d3372 | ||
|
|
e190af9d87 | ||
|
|
8d14463b18 | ||
|
|
04977ef721 | ||
|
|
d84e6875c5 | ||
|
|
80678ae7bc | ||
|
|
482bdab0e0 | ||
|
|
b2623b9841 | ||
|
|
9ae40d64f0 | ||
|
|
cef097b7b7 | ||
|
|
b840334ad2 |
@@ -1,7 +1,58 @@
|
||||
Revision history for Verilator
|
||||
|
||||
The contributors that suggested a given feature are shown in []. [by ...]
|
||||
indicates the contributor was also the author of the fix; Thanks!
|
||||
The contributors that suggested a given feature are shown in []. Thanks!
|
||||
|
||||
|
||||
* Verilator 3.888 2016-10-14
|
||||
|
||||
** Support foreach, bug1078. [Xuan Guo]
|
||||
|
||||
*** Add --no-decoration to remove output comments, msg2015. [Frederic Requin]
|
||||
|
||||
*** If VM_PARALLEL_BUILDS=1, use OPT_FAST and OPT_SLOW. [Frederic Requin]
|
||||
Set VM_DEFAULT_RULES=0 for old behavior.
|
||||
|
||||
**** Add error on DPI functions > 32 bits, msg1995. [Elliot Mednick]
|
||||
|
||||
**** Fix SystemC compiles with VPI, bug1081. [Arthur Kahlich]
|
||||
|
||||
**** Fix error on wide numbers that represent shifts, msg1991, bug1088. [Mandy Xu]
|
||||
|
||||
**** Improve Verilation performance on internal strings, msg1975. [Johan Bjork]
|
||||
|
||||
**** Improve Verilation performance on trace duplicates, bug1090. [Johan Bjork]
|
||||
|
||||
|
||||
* Verilator 3.886 2016-07-30
|
||||
|
||||
**** Fix enum values of 11-16 bits wide using .next/.prev, bug1062. [Brian Flachs]
|
||||
|
||||
**** Fix false warnings on non-power-2 enums using .next/.prev.
|
||||
|
||||
**** Fix comparison of unpacked arrays, bug1071. [Andrew Bardsley]
|
||||
|
||||
**** Fix compiler warning in GCC 6. [David Horton]
|
||||
|
||||
|
||||
* Verilator 3.884 2016-05-18
|
||||
|
||||
** Support parameter type, bug376. [Alan Hunter, et al]
|
||||
|
||||
** Support command-line -G/+pvalue param overrides, bug1045. [Stefan Wallentowitz]
|
||||
|
||||
*** The default l2 scope name is now the same as the top-level module, bug1050.
|
||||
Use "--l2-name v" for the historical behavior.
|
||||
|
||||
*** Add --l2-name option for controlling "v" naming.
|
||||
|
||||
**** Fix --output-split of constructors, bug1035. [Johan Bjork]
|
||||
|
||||
**** Fix removal of empty packages, modules and cells, bug1034. [Johan Bjork]
|
||||
|
||||
**** Fix core dump on Arch Linux/GCC 6.1.1, bug1058. [Jannis Harder]
|
||||
|
||||
**** Fix $value$plusargs to string, msg1890. [Frederic Requin]
|
||||
|
||||
|
||||
* Verilator 3.882 2016-03-01
|
||||
|
||||
@@ -2711,5 +2762,5 @@ Version 2.0.
|
||||
|
||||
Local variables:
|
||||
mode: outline
|
||||
paragraph-separate: "[ \f\n]*$"
|
||||
paragraph-separate: "[ \f\n]*$"
|
||||
end:
|
||||
|
||||
+226
-154
@@ -19,8 +19,8 @@ require 5.006_001;
|
||||
use warnings;
|
||||
BEGIN {
|
||||
if ($ENV{DIRPROJECT} && $ENV{DIRPROJECT_PERL_BOOT}) {
|
||||
# Magic to allow author testing of perl packages in local directory
|
||||
require $ENV{DIRPROJECT}."/".$ENV{DIRPROJECT_PERL_BOOT};
|
||||
# Magic to allow author testing of perl packages in local directory
|
||||
require $ENV{DIRPROJECT}."/".$ENV{DIRPROJECT_PERL_BOOT};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -54,22 +54,33 @@ push @ARGV, (split ' ',$ENV{VERILATOR_TEST_FLAGS}||"");
|
||||
# We sneak a look at the flags so we can do some pre-environment checks
|
||||
# All flags will hit verilator...
|
||||
foreach my $sw (@ARGV) {
|
||||
$sw = "'$sw'" if $sw =~ m![^---a-zA-Z0-9_/\\:.+]!;
|
||||
# Some special treatment for parameters to allow verilog literals for numbers
|
||||
if ((substr($sw, 0, 2) eq "-G") || (substr($sw, 0, 8) eq "-pvalue+")) {
|
||||
# If there is a single quote in the parameter put it double quotes ,
|
||||
# else just put it in double quotes
|
||||
if ($sw =~ m![\']!) {
|
||||
$sw = "\"$sw\"";
|
||||
} else {
|
||||
$sw = "'$sw'";
|
||||
}
|
||||
} else {
|
||||
$sw = "'$sw'" if $sw =~ m![^---a-zA-Z0-9_/\\:.+]!;
|
||||
}
|
||||
push @Opt_Verilator_Sw, $sw;
|
||||
}
|
||||
|
||||
Getopt::Long::config ("no_auto_abbrev","pass_through");
|
||||
if (! GetOptions (
|
||||
# Major operating modes
|
||||
"help" => \&usage,
|
||||
"debug:s" => \&debug,
|
||||
# "version!" => \&version, # Also passthru'ed
|
||||
# Switches
|
||||
"gdb!" => \$opt_gdb,
|
||||
"gdbbt!" => \$opt_gdbbt,
|
||||
# Additional parameters
|
||||
"<>" => sub {}, # Ignored
|
||||
)) {
|
||||
# Major operating modes
|
||||
"help" => \&usage,
|
||||
"debug:s" => \&debug,
|
||||
# "version!" => \&version, # Also passthru'ed
|
||||
# Switches
|
||||
"gdb!" => \$opt_gdb,
|
||||
"gdbbt!" => \$opt_gdbbt,
|
||||
# Additional parameters
|
||||
"<>" => sub {}, # Ignored
|
||||
)) {
|
||||
pod2usage(-exitstatus=>2, -verbose=>0);
|
||||
}
|
||||
|
||||
@@ -81,22 +92,22 @@ if ($opt_gdbbt && !gdb_works()) {
|
||||
if ($opt_gdb) {
|
||||
# Generic GDB interactive
|
||||
run (("gdb"||$ENV{VERILATOR_GDB})
|
||||
." ".verilator_bin()
|
||||
." -ex 'run ".join(' ',@Opt_Verilator_Sw)."'"
|
||||
." -ex 'set width 0'"
|
||||
." -ex 'bt'");
|
||||
." ".verilator_bin()
|
||||
." -ex 'run ".join(' ',@Opt_Verilator_Sw)."'"
|
||||
." -ex 'set width 0'"
|
||||
." -ex 'bt'");
|
||||
} elsif ($opt_gdbbt && $Debug) {
|
||||
# Run under GDB to get gdbbt
|
||||
run ("gdb"
|
||||
." ".verilator_bin()
|
||||
." --batch --quiet --return-child-result"
|
||||
." -ex 'run ".join(' ',@Opt_Verilator_Sw)."'"
|
||||
." -ex 'set width 0'"
|
||||
." -ex 'bt'");
|
||||
." ".verilator_bin()
|
||||
." --batch --quiet --return-child-result"
|
||||
." -ex 'run ".join(' ',@Opt_Verilator_Sw)."'"
|
||||
." -ex 'set width 0'"
|
||||
." -ex 'bt'");
|
||||
} else {
|
||||
# Normal, non gdb
|
||||
run (verilator_bin()
|
||||
." ".join(' ',@Opt_Verilator_Sw));
|
||||
." ".join(' ',@Opt_Verilator_Sw));
|
||||
}
|
||||
|
||||
#----------------------------------------------------------------------
|
||||
@@ -119,23 +130,23 @@ sub verilator_bin {
|
||||
my $bin = "";
|
||||
# Use VERILATOR_ROOT if defined, else assume verilator_bin is in the search path
|
||||
my $basename = ($ENV{VERILATOR_BIN}
|
||||
|| ($Debug ? "verilator_bin_dbg" : "verilator_bin"));
|
||||
|| ($Debug ? "verilator_bin_dbg" : "verilator_bin"));
|
||||
if (defined($ENV{VERILATOR_ROOT})) {
|
||||
my $dir = $ENV{VERILATOR_ROOT};
|
||||
if (-x "$dir/bin/$basename") { # From a "make install" into VERILATOR_ROOT
|
||||
$bin = "$dir/bin/$basename";
|
||||
} else {
|
||||
$bin = "$dir/$basename"; # From pointing to kit directory
|
||||
}
|
||||
my $dir = $ENV{VERILATOR_ROOT};
|
||||
if (-x "$dir/bin/$basename") { # From a "make install" into VERILATOR_ROOT
|
||||
$bin = "$dir/bin/$basename";
|
||||
} else {
|
||||
$bin = "$dir/$basename"; # From pointing to kit directory
|
||||
}
|
||||
} else {
|
||||
if (-x "$RealBin/$basename") {
|
||||
$bin = "$RealBin/$basename"; # From path/to/verilator with verilator_bin installed
|
||||
} else {
|
||||
$bin = $basename; # Find in PATH
|
||||
}
|
||||
# Note we don't look under bin/$basename which would be right if running
|
||||
# in the kit dir. Running that would likely break, since
|
||||
# VERILATOR_ROOT wouldn't be set and Verilator won't find internal files.
|
||||
if (-x "$RealBin/$basename") {
|
||||
$bin = "$RealBin/$basename"; # From path/to/verilator with verilator_bin installed
|
||||
} else {
|
||||
$bin = $basename; # Find in PATH
|
||||
}
|
||||
# Note we don't look under bin/$basename which would be right if running
|
||||
# in the kit dir. Running that would likely break, since
|
||||
# VERILATOR_ROOT wouldn't be set and Verilator won't find internal files.
|
||||
}
|
||||
return $bin;
|
||||
}
|
||||
@@ -147,10 +158,10 @@ sub verilator_bin {
|
||||
sub gdb_works {
|
||||
$! = undef; # Cleanup -x
|
||||
system("gdb /bin/echo"
|
||||
." --batch-silent --quiet --return-child-result"
|
||||
." -ex 'run -n'" # `echo -n`
|
||||
." -ex 'set width 0'"
|
||||
." -ex 'bt'");
|
||||
." --batch-silent --quiet --return-child-result"
|
||||
." -ex 'run -n'" # `echo -n`
|
||||
." -ex 'set width 0'"
|
||||
." -ex 'bt'");
|
||||
my $status = $?;
|
||||
return $status==0;
|
||||
}
|
||||
@@ -163,23 +174,23 @@ sub run {
|
||||
system($command);
|
||||
my $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
|
||||
warn "%Error: export VERILATOR_ROOT=".($ENV{VERILATOR_ROOT}||"")."\n";
|
||||
warn "%Error: $command\n";
|
||||
}
|
||||
if ($status & 127) {
|
||||
if (($status & 127) == 8 || ($status & 127) == 11) { # SIGFPA or SIGSEGV
|
||||
warn "%Error: Verilator internal fault, sorry. Consider trying --debug --gdbbt\n" if !$Debug;
|
||||
} elsif (($status & 127) == 6) { # SIGABRT
|
||||
warn "%Error: Verilator aborted. Consider trying --debug --gdbbt\n" if !$Debug;
|
||||
} else {
|
||||
warn "%Error: Verilator threw signal $status. Consider trying --debug --gdbbt\n" if !$Debug;
|
||||
}
|
||||
}
|
||||
die "%Error: Command Failed $command\n";
|
||||
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
|
||||
warn "%Error: export VERILATOR_ROOT=".($ENV{VERILATOR_ROOT}||"")."\n";
|
||||
warn "%Error: $command\n";
|
||||
}
|
||||
if ($status & 127) {
|
||||
if (($status & 127) == 8 || ($status & 127) == 11) { # SIGFPA or SIGSEGV
|
||||
warn "%Error: Verilator internal fault, sorry. Consider trying --debug --gdbbt\n" if !$Debug;
|
||||
} elsif (($status & 127) == 6) { # SIGABRT
|
||||
warn "%Error: Verilator aborted. Consider trying --debug --gdbbt\n" if !$Debug;
|
||||
} else {
|
||||
warn "%Error: Verilator threw signal $status. Consider trying --debug --gdbbt\n" if !$Debug;
|
||||
}
|
||||
}
|
||||
die "%Error: Command Failed $command\n";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -269,6 +280,7 @@ descriptions in the next sections for more information.
|
||||
--exe Link to create executable
|
||||
-F <file> Parse options from a file, relatively
|
||||
-f <file> Parse options from a file
|
||||
-G<name>=<value> Overwrite toplevel parameter
|
||||
--gdb Run Verilator under GDB interactively
|
||||
--gdbbt Run Verilator under GDB for backtrace
|
||||
--help Display this help
|
||||
@@ -279,6 +291,7 @@ descriptions in the next sections for more information.
|
||||
--inline-mult <value> Tune module inlining
|
||||
-LDFLAGS <flags> Linker pre-object flags for makefile
|
||||
-LDLIBS <flags> Linker library flags for makefile
|
||||
--l2-name <value> Verilog scope name of the top module
|
||||
--language <lang> Default language standard to parse
|
||||
+libext+<ext>+[ext]... Extensions for finding modules
|
||||
--lint-only Lint, but do not make output
|
||||
@@ -287,6 +300,7 @@ descriptions in the next sections for more information.
|
||||
--Mdir <directory> Name of output object directory
|
||||
--mod-prefix <topname> Name to prepend to lower classes
|
||||
--no-clk <signal-name> Prevent marking specified signal as clock
|
||||
--no-decoration Disable comments and symbol decorations
|
||||
--no-pins64 Don't use vluint64_t's for 33-64 bit sigs
|
||||
--no-skip-identical Disable skipping identical output
|
||||
+notimingchecks Ignored
|
||||
@@ -308,8 +322,9 @@ descriptions in the next sections for more information.
|
||||
--profile-cfuncs Name functions for profiling
|
||||
--private Debugging; see docs
|
||||
--public Debugging; see docs
|
||||
-pvalue+<name>=<value> Overwrite toplevel parameter
|
||||
--report-unoptflat Extra diagnostics for UNOPTFLAT
|
||||
--savable Enable model save-restore
|
||||
--savable Enable model save-restore
|
||||
--sc Create SystemC output
|
||||
--stats Create statistics file
|
||||
--stats-vars Provide statistics on variables
|
||||
@@ -479,7 +494,7 @@ RTL file to mark the signal directly.
|
||||
|
||||
=item --compiler I<compiler-name>
|
||||
|
||||
Enables tunings and work-arounds for the specified C++ compiler.
|
||||
Enables tunings and workarounds for the specified C++ compiler.
|
||||
|
||||
=over 4
|
||||
|
||||
@@ -592,8 +607,8 @@ alias for GCC compatibility.
|
||||
=item --debug
|
||||
|
||||
Select the debug built image of Verilator (if available), and enable more
|
||||
internal assertions (equivelent to C<--debug-check>), debugging messages
|
||||
(equivelent to C<--debugi 4>), and intermediate form dump files (equivilent
|
||||
internal assertions (equivalent to C<--debug-check>), debugging messages
|
||||
(equivalent to C<--debugi 4>), and intermediate form dump files (equivalent
|
||||
to C<--dump-treei 3>).
|
||||
|
||||
=item --debug-check
|
||||
@@ -688,6 +703,35 @@ The file may contain // comments which are ignored to the end of the line.
|
||||
Any $VAR, $(VAR), or ${VAR} will be replaced with the specified environment
|
||||
variable.
|
||||
|
||||
=item -GI<name>=I<value>
|
||||
|
||||
Overwrites the given parameter of the toplevel module. The value is limited
|
||||
to basic data literals:
|
||||
|
||||
=over 4
|
||||
|
||||
=item Verilog integer literals
|
||||
|
||||
The standard verilog integer literals are supported, so values like 32'h8,
|
||||
2'b00, 4 etc. are allowed. Care must be taken that the single quote (I') is
|
||||
properly escaped in an interactive shell, e.g., as -GWIDTH=8\'hx.
|
||||
|
||||
=item C integer literals
|
||||
|
||||
It is also possible to use C integer notation, including hexadecimal (0x..),
|
||||
octal (0..) or binary (0b..) notation.
|
||||
|
||||
=item Double literals
|
||||
|
||||
Double literals must contain a dot (.) and/or an exponent (e).
|
||||
|
||||
=item Strings
|
||||
|
||||
String must in double quotes ("). On the command line it is required to escape
|
||||
them properly, e.g. as -GSTR="\"My String\"" or -GSTR='"My String"'.
|
||||
|
||||
=back
|
||||
|
||||
=item --gdb
|
||||
|
||||
Run Verilator underneath an interactive GDB (or VERILATOR_GDB environment
|
||||
@@ -743,9 +787,19 @@ called LDLIBS as that's the Makefile variable it controls. (In Make,
|
||||
LDFLAGS is before the first object, LDLIBS after. -L libraries need to be
|
||||
in the Make variable LDLIBS, not LDFLAGS.)
|
||||
|
||||
=item --l2-name I<value>
|
||||
|
||||
Instead of using the module name when showing Verilog scope, use the name
|
||||
provided. This allows simplifying some Verilator-embedded modeling
|
||||
methodologies. Default is an l2-name matching the top module. The default
|
||||
before 3.884 was "--l2-name v"
|
||||
|
||||
For example, the program "module t; initial $display("%m"); endmodule" will
|
||||
show by default "t". With "--l2-name v" it will print "v".
|
||||
|
||||
=item --language I<value>
|
||||
|
||||
A synonym for C<--default-langauge>, for compatibility with other tools and
|
||||
A synonym for C<--default-language>, for compatibility with other tools and
|
||||
earlier versions of Verilator.
|
||||
|
||||
=item +libext+I<ext>+I<ext>...
|
||||
@@ -790,6 +844,13 @@ the same as --prefix.
|
||||
|
||||
Prevent the specified signal from being marked as clock. See C<--clk>.
|
||||
|
||||
=item --no-decoration
|
||||
|
||||
When creating output Verilated code, minimize comments, whitespace, symbol
|
||||
names and other decorative items, at the cost of greatly reduced
|
||||
readability. This may assist C++ compile times. This will not typically
|
||||
change the ultimate model's performance, but may in some cases.
|
||||
|
||||
=item --no-pins64
|
||||
|
||||
Backward compatible alias for "--pins-bv 33".
|
||||
@@ -873,9 +934,10 @@ Backward compatible alias for "--pins-bv 65". Note that's a 65, not a 64.
|
||||
|
||||
Specifies SystemC inputs/outputs of greater than or equal to I<width> bits
|
||||
wide should use sc_bv's instead of uint32/vluint64_t's. The default is
|
||||
"--pins-bv 65". Versions before Verilator 3.671 defaulted to "--pins-bv
|
||||
33". The more sc_bv is used, the worse for performance. Use the
|
||||
"/*verilator sc_bv*/" attribute to select specific ports to be sc_bv.
|
||||
"--pins-bv 65", and the value must be less than or equal to 65. Versions
|
||||
before Verilator 3.671 defaulted to "--pins-bv 33". The more sc_bv is
|
||||
used, the worse for performance. Use the "/*verilator sc_bv*/" attribute
|
||||
to select specific ports to be sc_bv.
|
||||
|
||||
=item --pins-sc-uint
|
||||
|
||||
@@ -946,6 +1008,11 @@ inlining. This will also turn off inlining as if all modules had a
|
||||
/*verilator public_module*/, unless the module specifically enabled it with
|
||||
/*verilator inline_module*/.
|
||||
|
||||
=item -pvalue+I<name>=I<value>
|
||||
|
||||
Overwrites the given parameter(s) of the toplevel module. See -G for a
|
||||
detailed description.
|
||||
|
||||
=item --report-unoptflat
|
||||
|
||||
Extra diagnostics for UNOPTFLAT warnings. This includes for each loop, the
|
||||
@@ -1269,7 +1336,7 @@ We'll compile this example into C++.
|
||||
#include "Vour.h"
|
||||
#include "verilated.h"
|
||||
int main(int argc, char **argv, char **env) {
|
||||
Verilated::commandArgs(argc, argv);
|
||||
Verilated::commandArgs(argc, argv);
|
||||
Vour* top = new Vour;
|
||||
while (!Verilated::gotFinish()) { top->eval(); }
|
||||
delete top;
|
||||
@@ -1294,8 +1361,7 @@ section below for descriptions of some of the files that were created.
|
||||
|
||||
We then can compile it
|
||||
|
||||
cd obj_dir
|
||||
make -j -f Vour.mk Vour
|
||||
make -j -C obj_dir -f Vour.mk Vour
|
||||
|
||||
(Verilator included a default compile rule and link rule, since we used
|
||||
--exe and passed a .cpp file on the Verilator command line. You can also
|
||||
@@ -1303,7 +1369,6 @@ write your own compile rules, as we'll show in the SYSTEMC section.)
|
||||
|
||||
And now we run it
|
||||
|
||||
cd ..
|
||||
obj_dir/Vour
|
||||
|
||||
And we get as output
|
||||
@@ -1312,8 +1377,9 @@ And we get as output
|
||||
- our.v:2: Verilog $finish
|
||||
|
||||
Really, you're better off writing a Makefile to do all this for you. Then,
|
||||
when your source changes it will automatically run all of these steps. See
|
||||
the test_c directory in the distribution for an example.
|
||||
when your source changes it will automatically run all of these steps; to
|
||||
aid this Verilator can create a makefile dependency file. See the test_c
|
||||
directory in the distribution for an example.
|
||||
|
||||
|
||||
=head1 EXAMPLE SYSTEMC EXECUTION
|
||||
@@ -1334,13 +1400,13 @@ This is an example similar to the above, but using SystemC.
|
||||
cat <<EOF >sc_main.cpp
|
||||
#include "Vour.h"
|
||||
int sc_main(int argc, char **argv) {
|
||||
Verilated::commandArgs(argc, argv);
|
||||
Verilated::commandArgs(argc, argv);
|
||||
sc_clock clk ("clk",10, 0.5, 3, true);
|
||||
Vour* top;
|
||||
top = new Vour("top"); // SP_CELL (top, Vour);
|
||||
top->clk(clk); // SP_PIN (top, clk, clk);
|
||||
while (!Verilated::gotFinish()) { sc_start(1, SC_NS); }
|
||||
delete top;
|
||||
delete top;
|
||||
exit(0);
|
||||
}
|
||||
EOF
|
||||
@@ -1357,6 +1423,7 @@ Now we run Verilator on our little example.
|
||||
|
||||
We then can compile it
|
||||
|
||||
cd obj_dir
|
||||
make -j -f Vour.mk Vour__ALL.a
|
||||
make -j -f Vour.mk ../sc_main.o verilated.o
|
||||
|
||||
@@ -1462,42 +1529,42 @@ All output files are placed in the output directory name specified with the
|
||||
|
||||
Verilator creates the following files in the output directory:
|
||||
|
||||
{prefix}.mk // Make include file for compiling
|
||||
{prefix}_classes.mk // Make include file with class names
|
||||
{prefix}.mk // Make include file for compiling
|
||||
{prefix}_classes.mk // Make include file with class names
|
||||
|
||||
For -cc and -sc mode, it also creates:
|
||||
|
||||
{prefix}.cpp // Top level C++ file
|
||||
{prefix}.h // Top level header
|
||||
{prefix}{each_verilog_module}.cpp // Lower level internal C++ files
|
||||
{prefix}{each_verilog_module}.h // Lower level internal header files
|
||||
{prefix}.cpp // Top level C++ file
|
||||
{prefix}.h // Top level header
|
||||
{prefix}{each_verilog_module}.cpp // Lower level internal C++ files
|
||||
{prefix}{each_verilog_module}.h // Lower level internal header files
|
||||
|
||||
In certain optimization modes, it also creates:
|
||||
|
||||
{prefix}__Dpi.h // DPI import and export declarations
|
||||
{prefix}__Inlines.h // Inline support functions
|
||||
{prefix}__Slow.cpp // Constructors and infrequent routines
|
||||
{prefix}__Syms.cpp // Global symbol table C++
|
||||
{prefix}__Syms.h // Global symbol table header
|
||||
{prefix}__Trace.cpp // Wave file generation code (--trace)
|
||||
{prefix}__cdc.txt // Clock Domain Crossing checks (--cdc)
|
||||
{prefix}__stats.txt // Statistics (--stats)
|
||||
{prefix}__Dpi.h // DPI import and export declarations
|
||||
{prefix}__Inlines.h // Inline support functions
|
||||
{prefix}__Slow.cpp // Constructors and infrequent routines
|
||||
{prefix}__Syms.cpp // Global symbol table C++
|
||||
{prefix}__Syms.h // Global symbol table header
|
||||
{prefix}__Trace.cpp // Wave file generation code (--trace)
|
||||
{prefix}__cdc.txt // Clock Domain Crossing checks (--cdc)
|
||||
{prefix}__stats.txt // Statistics (--stats)
|
||||
|
||||
It also creates internal files that can be mostly ignored:
|
||||
|
||||
{each_verilog_module}.vpp // Post-processed verilog (--debug)
|
||||
{prefix}.flags_vbin // Verilator dependencies
|
||||
{prefix}.flags_vpp // Pre-processor dependencies
|
||||
{prefix}__verFiles.dat // Timestamps for skip-identical
|
||||
{prefix}{misc}.d // Make dependencies (-MMD)
|
||||
{prefix}{misc}.dot // Debugging graph files (--debug)
|
||||
{prefix}{misc}.tree // Debugging files (--debug)
|
||||
{each_verilog_module}.vpp // Post-processed verilog (--debug)
|
||||
{prefix}.flags_vbin // Verilator dependencies
|
||||
{prefix}.flags_vpp // Pre-processor dependencies
|
||||
{prefix}__verFiles.dat // Timestamps for skip-identical
|
||||
{prefix}{misc}.d // Make dependencies (-MMD)
|
||||
{prefix}{misc}.dot // Debugging graph files (--debug)
|
||||
{prefix}{misc}.tree // Debugging files (--debug)
|
||||
|
||||
After running Make, the C++ compiler should produce the following:
|
||||
|
||||
{prefix} // Final executable (w/--exe argument)
|
||||
{prefix}__ALL.a // Library of all Verilated objects
|
||||
{prefix}{misc}.o // Intermediate objects
|
||||
{prefix} // Final executable (w/--exe argument)
|
||||
{prefix}__ALL.a // Library of all Verilated objects
|
||||
{prefix}{misc}.o // Intermediate objects
|
||||
|
||||
|
||||
=head1 ENVIRONMENT
|
||||
@@ -1592,46 +1659,47 @@ simulation executable.
|
||||
The user must write the top level of the simulation. Here's a simple
|
||||
example:
|
||||
|
||||
#include <verilated.h> // Defines common routines
|
||||
#include "Vtop.h" // From Verilating "top.v"
|
||||
#include <verilated.h> // Defines common routines
|
||||
#include <iostream> // Need std::cout
|
||||
#include "Vtop.h" // From Verilating "top.v"
|
||||
|
||||
Vtop *top; // Instantiation of module
|
||||
Vtop *top; // Instantiation of module
|
||||
|
||||
vluint64_t main_time = 0; // Current simulation time
|
||||
// This is a 64-bit integer to reduce wrap over issues and
|
||||
// allow modulus. You can also use a double, if you wish.
|
||||
vluint64_t main_time = 0; // Current simulation time
|
||||
// This is a 64-bit integer to reduce wrap over issues and
|
||||
// allow modulus. You can also use a double, if you wish.
|
||||
|
||||
double sc_time_stamp () { // Called by $time in Verilog
|
||||
return main_time; // converts to double, to match
|
||||
// what SystemC does
|
||||
}
|
||||
double sc_time_stamp () { // Called by $time in Verilog
|
||||
return main_time; // converts to double, to match
|
||||
// what SystemC does
|
||||
}
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
Verilated::commandArgs(argc, argv); // Remember args
|
||||
int main(int argc, char** argv) {
|
||||
Verilated::commandArgs(argc, argv); // Remember args
|
||||
|
||||
top = new Vtop; // Create instance
|
||||
top = new Vtop; // Create instance
|
||||
|
||||
top->reset_l = 0; // Set some inputs
|
||||
top->reset_l = 0; // Set some inputs
|
||||
|
||||
while (!Verilated::gotFinish()) {
|
||||
if (main_time > 10) {
|
||||
top->reset_l = 1; // Deassert reset
|
||||
}
|
||||
if ((main_time % 10) == 1) {
|
||||
top->clk = 1; // Toggle clock
|
||||
}
|
||||
if ((main_time % 10) == 6) {
|
||||
top->clk = 0;
|
||||
}
|
||||
top->eval(); // Evaluate model
|
||||
cout << top->out << endl; // Read a output
|
||||
main_time++; // Time passes...
|
||||
}
|
||||
while (!Verilated::gotFinish()) {
|
||||
if (main_time > 10) {
|
||||
top->reset_l = 1; // Deassert reset
|
||||
}
|
||||
if ((main_time % 10) == 1) {
|
||||
top->clk = 1; // Toggle clock
|
||||
}
|
||||
if ((main_time % 10) == 6) {
|
||||
top->clk = 0;
|
||||
}
|
||||
top->eval(); // Evaluate model
|
||||
cout << top->out << endl; // Read a output
|
||||
main_time++; // Time passes...
|
||||
}
|
||||
|
||||
top->final(); // Done simulating
|
||||
// // (Though this example doesn't get here)
|
||||
delete top;
|
||||
}
|
||||
top->final(); // Done simulating
|
||||
// // (Though this example doesn't get here)
|
||||
delete top;
|
||||
}
|
||||
|
||||
Note signals are read and written as member variables of the lower module.
|
||||
You call the eval() method to evaluate the model. When the simulation is
|
||||
@@ -1847,7 +1915,7 @@ accesses the above would be:
|
||||
if (!vh1) { error... }
|
||||
const char* name = vpi_get_str(vpiName, vh1);
|
||||
printf("Module name: %s\n"); // Prints "readme"
|
||||
|
||||
|
||||
s_vpi_value v;
|
||||
v.format = vpiIntVal;
|
||||
vpi_get_value(vh1, &v);
|
||||
@@ -1861,8 +1929,8 @@ VerilatedVpi::callValueCbs().
|
||||
...
|
||||
while (time passes) {
|
||||
...
|
||||
topp->eval();
|
||||
VerilatedVpi::callValueCbs();
|
||||
topp->eval();
|
||||
VerilatedVpi::callValueCbs();
|
||||
}
|
||||
|
||||
|
||||
@@ -1906,10 +1974,10 @@ underneath NC:
|
||||
|
||||
cd obj_dir
|
||||
ncsc_run \
|
||||
sc_main.cpp \
|
||||
Vour__ALLcls.cpp \
|
||||
Vour__ALLsup.cpp \
|
||||
verilated.cpp
|
||||
sc_main.cpp \
|
||||
Vour__ALLcls.cpp \
|
||||
Vour__ALLsup.cpp \
|
||||
verilated.cpp
|
||||
|
||||
For larger designs you'll want to automate this using makefiles, which pull
|
||||
the names of the .cpp files to compile in from the make variables generated
|
||||
@@ -2426,12 +2494,12 @@ such as $stop, $finish and $display. That is, you cannot use hierarchical
|
||||
references, events or similar features of the Verilog language. It also
|
||||
simulates as Synopsys's Design Compiler would; namely a block of the form:
|
||||
|
||||
always @ (x) y = x & z;
|
||||
always @ (x) y = x & z;
|
||||
|
||||
This will recompute y when there is even a potential for change in x or a
|
||||
change in z, that is when the flops computing x or z evaluate (which is
|
||||
what Design Compiler will synthesize.) A compliant simulator would only
|
||||
calculate y if x changes. Use verilog-mode's /*AS*/ or Verilog 2001's
|
||||
calculate y if x changes. Use Verilog-Mode's /*AS*/ or Verilog 2001's
|
||||
always @* to reduce missing activity items. Avoid putting $displays in
|
||||
combo blocks, as they may print multiple times when not desired, even on
|
||||
compliant simulators as event ordering is not specified.
|
||||
@@ -2514,7 +2582,7 @@ variables are initialized to a random value.
|
||||
Event driven simulators will generally trigger an edge on a transition from X
|
||||
to 1 (C<posedge>) or X to 0 (C<negedge>). However, by default, since clocks
|
||||
are initialized to zero, Verilator will not trigger an initial negedge. Some
|
||||
code (particulary for reset) may rely on X->0 triggering an edge. Verilator
|
||||
code (particularly for reset) may rely on X->0 triggering an edge. Verilator
|
||||
provides a switch (see --x-initial-edge) to enable this behavior. Comparing
|
||||
runs with and without this switch will find such problems.
|
||||
|
||||
@@ -2567,7 +2635,7 @@ clock_enable*/ attribute.
|
||||
=head2 Ranges must be big-bit-endian
|
||||
|
||||
Bit ranges must be numbered with the MSB being numbered greater or the same
|
||||
as the LSB. Little-bit-endian busses [0:15] are not supported as they
|
||||
as the LSB. Little-bit-endian buses [0:15] are not supported as they
|
||||
aren't easily made compatible with C++.
|
||||
|
||||
=head2 Gate Primitives
|
||||
@@ -2766,13 +2834,17 @@ when displaying all times, model wide.
|
||||
|
||||
=head1 ERRORS AND WARNINGS
|
||||
|
||||
Warnings may be disabled in two ways. First, when the warning is
|
||||
Warnings may be disabled in three ways. First, when the warning is
|
||||
printed it will include a warning code. Simply surround the offending
|
||||
line with a warn_off/warn_on pair:
|
||||
|
||||
// verilator lint_off UNSIGNED
|
||||
if (`DEF_THAT_IS_EQ_ZERO <= 3) $stop;
|
||||
// verilator lint_on UNSIGNED
|
||||
// verilator lint_off UNSIGNED
|
||||
if (`DEF_THAT_IS_EQ_ZERO <= 3) $stop;
|
||||
// verilator lint_on UNSIGNED
|
||||
|
||||
Second, warnings may be disabled using a configuration file with a lint_off
|
||||
command. This is useful when a script is suppressing warnings and the
|
||||
Verilog source should not be changed.
|
||||
|
||||
Warnings may also be globally disabled by invoking Verilator with the
|
||||
C<-Wno-I<warning>> switch. This should be avoided, as it removes all
|
||||
@@ -2866,10 +2938,10 @@ were used, the simulator would have to copy large arrays every cycle. (In
|
||||
smaller loops, loop unrolling allows the delayed assignment to work, though
|
||||
it's a bit slower than a non-delayed assignment.) Here's an example
|
||||
|
||||
always @ (posedge clk)
|
||||
always @ (posedge clk)
|
||||
if (~reset_l) begin
|
||||
for (i=0; i<`ARRAY_SIZE; i++) begin
|
||||
array[i] = 0; // Non-delayed for verilator
|
||||
array[i] = 0; // Non-delayed for verilator
|
||||
end
|
||||
|
||||
This message is only seen on large or complicated loops because Verilator
|
||||
@@ -3327,9 +3399,9 @@ A recommended style for unused nets is to put at the bottom of a file code
|
||||
similar to the following:
|
||||
|
||||
wire _unused_ok = &{1'b0,
|
||||
sig_not_used_a,
|
||||
sig_not_used_yet_b, // To be fixed
|
||||
1'b0};
|
||||
sig_not_used_a,
|
||||
sig_not_used_yet_b, // To be fixed
|
||||
1'b0};
|
||||
|
||||
The reduction AND and constant zeros mean the net will always be zero, so
|
||||
won't use simulation time. The redundant leading and trailing zeros avoid
|
||||
@@ -3366,11 +3438,11 @@ unwidthed. Verilator considers zero to be any width needed.
|
||||
|
||||
Concatenate leading zeros when doing arithmetic. In the statement
|
||||
|
||||
wire [5:0] plus_one = from[5:0] + 6'd1 + carry[0];
|
||||
wire [5:0] plus_one = from[5:0] + 6'd1 + carry[0];
|
||||
|
||||
The best fix, which clarifies intent and will also make all tools happy is:
|
||||
|
||||
wire [5:0] plus_one = from[5:0] + 6'd1 + {5'd0,carry[0]};
|
||||
wire [5:0] plus_one = from[5:0] + 6'd1 + {5'd0,carry[0]};
|
||||
|
||||
Ignoring this warning will only suppress the lint check, it will simulate
|
||||
correctly.
|
||||
@@ -3568,7 +3640,7 @@ trace file if you want all data to land in the same output file.
|
||||
tfp->open ("obj_dir/t_trace_ena_cc/simx.vcd");
|
||||
...
|
||||
sc_start(1);
|
||||
...
|
||||
...
|
||||
tfp->close();
|
||||
}
|
||||
|
||||
|
||||
+2
-1
@@ -6,7 +6,7 @@
|
||||
|
||||
#AC_INIT([Verilator],[#.### YYYY-MM-DD])
|
||||
#AC_INIT([Verilator],[#.### devel])
|
||||
AC_INIT([Verilator],[3.882 2016-03-01])
|
||||
AC_INIT([Verilator],[3.888 2016-10-14])
|
||||
# When releasing, also update header of Changes file
|
||||
|
||||
AC_CONFIG_HEADER(src/config_build.h)
|
||||
@@ -132,6 +132,7 @@ _MY_CXX_CHECK_OPT(CFG_CXXFLAGS_SRC,-Wno-unused-parameter)
|
||||
_MY_CXX_CHECK_OPT(CFG_CXXFLAGS_SRC,-Wno-char-subscripts)
|
||||
_MY_CXX_CHECK_OPT(CFG_CXXFLAGS_SRC,-Wno-undefined-bool-conversion)
|
||||
_MY_CXX_CHECK_OPT(CFG_CXXFLAGS_SRC,-Qunused-arguments)
|
||||
_MY_CXX_CHECK_OPT(CFG_CXXFLAGS_SRC,-fno-delete-null-pointer-checks)
|
||||
AC_SUBST(CFG_CXXFLAGS_SRC)
|
||||
|
||||
# Flags for compiling Verilator parser
|
||||
|
||||
+11
-2
@@ -961,7 +961,8 @@ void VL_READMEM_W(bool hex, int width, int depth, int array_lsb, int fnwords,
|
||||
}
|
||||
|
||||
void VL_READMEM_N(bool hex, int width, int depth, int array_lsb, int fnwords,
|
||||
const string& ofilenamep, void* memp, IData start, IData end) {
|
||||
const string& ofilenamep, void* memp, IData start, IData end) {
|
||||
if (fnwords) {}
|
||||
FILE* fp = fopen(ofilenamep.c_str(), "r");
|
||||
if (VL_UNLIKELY(!fp)) {
|
||||
// We don't report the Verilog source filename as it slow to have to pass it down
|
||||
@@ -1076,6 +1077,14 @@ IData VL_TESTPLUSARGS_I(const char* formatp) {
|
||||
else return 1;
|
||||
}
|
||||
|
||||
IData VL_VALUEPLUSARGS_IN(int, const char* prefixp, char, string& ldr) {
|
||||
const string& match = VerilatedImp::argPlusMatch(prefixp);
|
||||
const char* dp = match.c_str() + 1 /*leading + */ + strlen(prefixp);
|
||||
if (match == "") return 0;
|
||||
ldr = string(dp);
|
||||
return 1;
|
||||
}
|
||||
|
||||
IData VL_VALUEPLUSARGS_IW(int rbits, const char* prefixp, char fmt, WDataOutP rwp) {
|
||||
const string& match = VerilatedImp::argPlusMatch(prefixp);
|
||||
const char* dp = match.c_str() + 1 /*leading + */ + strlen(prefixp);
|
||||
@@ -1217,7 +1226,7 @@ VerilatedModule::VerilatedModule(const char* namep)
|
||||
}
|
||||
|
||||
VerilatedModule::~VerilatedModule() {
|
||||
if (m_namep) free((void*)m_namep); m_namep=NULL;
|
||||
if (m_namep) { free((void*)m_namep); m_namep=NULL; }
|
||||
}
|
||||
|
||||
//======================================================================
|
||||
|
||||
@@ -288,6 +288,7 @@ public:
|
||||
/// Record command line arguments, for retrieval by $test$plusargs/$value$plusargs
|
||||
static void commandArgs(int argc, const char** argv);
|
||||
static void commandArgs(int argc, char** argv) { commandArgs(argc,(const char**)argv); }
|
||||
static void commandArgsAdd(int argc, const char** argv);
|
||||
static CommandArgValues* getCommandArgs() {return &s_args;}
|
||||
/// Match plusargs with a given prefix. Returns static char* valid only for a single call
|
||||
static const char* commandArgsPlusMatch(const char* prefixp);
|
||||
|
||||
+15
-15
@@ -43,8 +43,9 @@ VK_CPPFLAGS_ALWAYS += \
|
||||
-I$(VERILATOR_ROOT)/include \
|
||||
-I$(VERILATOR_ROOT)/include/vltstd \
|
||||
-DVL_PRINTF=printf \
|
||||
-DVM_TRACE=$(VM_TRACE) \
|
||||
-DVM_COVERAGE=$(VM_COVERAGE) \
|
||||
-DVM_SC=$(VM_SC) \
|
||||
-DVM_TRACE=$(VM_TRACE) \
|
||||
$(CFG_CXXFLAGS_NO_UNUSED) \
|
||||
|
||||
ifeq ($(CFG_WITH_CCWARN),yes) # Local... Else don't burden users
|
||||
@@ -123,19 +124,10 @@ else
|
||||
preproc:
|
||||
endif
|
||||
|
||||
#######################################################################
|
||||
##### SystemC w/o SystemPerl builds
|
||||
|
||||
ifeq ($(VM_SC),1)
|
||||
LIBS += -lm -lstdc++
|
||||
endif
|
||||
|
||||
#######################################################################
|
||||
##### C/H builds
|
||||
|
||||
ifeq ($(VM_PCLI),1)
|
||||
LIBS += -lm -lstdc++
|
||||
endif
|
||||
LIBS += -lm -lstdc++
|
||||
|
||||
#######################################################################
|
||||
# Overall Objects Linking
|
||||
@@ -171,16 +163,24 @@ $(VM_PREFIX)__ALL.a: $(VK_OBJS)
|
||||
######################################################################
|
||||
### Compile rules
|
||||
|
||||
#Default rule embedded in make: (Not defined so user makefiles can override it)
|
||||
#.cpp.o:
|
||||
# $(CXX) $(CXXFLAGS) $(CPPFLAGS) -c -o $@ $<
|
||||
|
||||
ifneq ($(VM_DEFAULT_RULES),0)
|
||||
$(VM_PREFIX)__ALLsup.o: $(VM_PREFIX)__ALLsup.cpp
|
||||
$(OBJCACHE) $(CXX) $(CXXFLAGS) $(CPPFLAGS) $(OPT_SLOW) -c -o $@ $<
|
||||
|
||||
$(VM_PREFIX)__ALLcls.o: $(VM_PREFIX)__ALLcls.cpp
|
||||
$(OBJCACHE) $(CXX) $(CXXFLAGS) $(CPPFLAGS) $(OPT_FAST) -c -o $@ $<
|
||||
|
||||
$(VM_PREFIX)%__Slow.o: $(VM_PREFIX)%__Slow.cpp
|
||||
$(OBJCACHE) $(CXX) $(CXXFLAGS) $(CPPFLAGS) $(OPT_SLOW) -c -o $@ $<
|
||||
|
||||
$(VM_PREFIX)%.o: $(VM_PREFIX)%.cpp
|
||||
$(OBJCACHE) $(CXX) $(CXXFLAGS) $(CPPFLAGS) $(OPT_FAST) -c -o $@ $<
|
||||
endif
|
||||
|
||||
#Default rule embedded in make:
|
||||
#.cpp.o:
|
||||
# $(CXX) $(CXXFLAGS) $(CPPFLAGS) -c -o $@ $<
|
||||
|
||||
######################################################################
|
||||
### Debugging
|
||||
|
||||
|
||||
@@ -66,5 +66,6 @@ extern void VL_READMEM_N(bool hex, int width, int depth, int array_lsb, int fnwo
|
||||
extern IData VL_SSCANF_INX(int lbits, const string& ld, const char* formatp, ...);
|
||||
extern void VL_SFORMAT_X(int obits_ignored, string &output, const char* formatp, ...);
|
||||
extern string VL_SFORMATF_NX(const char* formatp, ...);
|
||||
extern IData VL_VALUEPLUSARGS_IN(int rbits, const char* prefixp, char fmt, string& ldr);
|
||||
|
||||
#endif // Guard
|
||||
|
||||
@@ -92,7 +92,11 @@ public: // But only for verilated*.cpp
|
||||
|
||||
// METHODS - arguments
|
||||
static void commandArgs(int argc, const char** argv) {
|
||||
s_s.m_argVec.clear();
|
||||
s_s.m_argVec.clear(); // Always clear
|
||||
commandArgsAdd(argc, argv);
|
||||
}
|
||||
static void commandArgsAdd(int argc, const char** argv) {
|
||||
if (!s_s.m_argVecLoaded) s_s.m_argVec.clear();
|
||||
for (int i=0; i<argc; i++) s_s.m_argVec.push_back(argv[i]);
|
||||
s_s.m_argVecLoaded = true; // Can't just test later for empty vector, no arguments is ok
|
||||
}
|
||||
|
||||
@@ -26,6 +26,9 @@
|
||||
//=========================================================================
|
||||
|
||||
|
||||
#if VM_SC
|
||||
# include "verilated_sc.h"
|
||||
#endif
|
||||
#include "verilated.h"
|
||||
#include "verilated_vpi.h"
|
||||
|
||||
|
||||
@@ -99,6 +99,8 @@ CPPFLAGS += -MP # Only works on recent GCC versions
|
||||
ifeq ($(CFG_WITH_CCWARN),yes) # Local... Else don't burden users
|
||||
CPPFLAGS += -W -Wall $(CFG_CXXFLAGS_SRC) -Werror
|
||||
#CPPFLAGS += -pedantic-errors
|
||||
else
|
||||
CPPFLAGS += $(CFG_CXXFLAGS_SRC)
|
||||
endif
|
||||
CPPFLAGSWALL = $(CPPFLAGS)
|
||||
CPPFLAGSPARSER = $(CPPFLAGS) $(CFG_CXXFLAGS_PARSER)
|
||||
@@ -235,6 +237,7 @@ RAW_OBJS = \
|
||||
V3Undriven.o \
|
||||
V3Unknown.o \
|
||||
V3Unroll.o \
|
||||
V3VarResets.o \
|
||||
V3Width.o \
|
||||
V3WidthSel.o \
|
||||
|
||||
|
||||
+39
-30
@@ -166,44 +166,53 @@ string AstNode::vcdName(const string& namein) {
|
||||
}
|
||||
|
||||
string AstNode::prettyName(const string& namein) {
|
||||
// This function is somewhat hot, so we short-circuit some compares
|
||||
string pretty;
|
||||
pretty = "";
|
||||
pretty.reserve(namein.length());
|
||||
for (const char* pos = namein.c_str(); *pos; ) {
|
||||
if (0==strncmp(pos,"__BRA__",7)) {
|
||||
pretty += "[";
|
||||
pos += 7;
|
||||
}
|
||||
else if (0==strncmp(pos,"__KET__",7)) {
|
||||
pretty += "]";
|
||||
pos += 7;
|
||||
}
|
||||
else if (0==strncmp(pos,"__DOT__",7)) {
|
||||
pretty += ".";
|
||||
pos += 7;
|
||||
}
|
||||
else if (0==strncmp(pos,"->",2)) {
|
||||
if (pos[0]=='-' && pos[1]=='>') { // ->
|
||||
pretty += ".";
|
||||
pos += 2;
|
||||
continue;
|
||||
}
|
||||
else if (0==strncmp(pos,"__PVT__",7)) {
|
||||
pretty += "";
|
||||
pos += 7;
|
||||
}
|
||||
else if (pos[0]=='_' && pos[1]=='_' && pos[2]=='0'
|
||||
&& isxdigit(pos[3]) && isxdigit(pos[4])) {
|
||||
char value = 0;
|
||||
value += 16*(isdigit(pos[3]) ? (pos[3]-'0') : (tolower(pos[3])-'a'+10));
|
||||
value += (isdigit(pos[4]) ? (pos[4]-'0') : (tolower(pos[4])-'a'+10));
|
||||
pretty += value;
|
||||
pos += 5;
|
||||
}
|
||||
else {
|
||||
pretty += pos[0];
|
||||
++pos;
|
||||
if (pos[0]=='_' && pos[1]=='_') { // Short-circuit
|
||||
if (0==strncmp(pos,"__BRA__",7)) {
|
||||
pretty += "[";
|
||||
pos += 7;
|
||||
continue;
|
||||
}
|
||||
if (0==strncmp(pos,"__KET__",7)) {
|
||||
pretty += "]";
|
||||
pos += 7;
|
||||
continue;
|
||||
}
|
||||
if (0==strncmp(pos,"__DOT__",7)) {
|
||||
pretty += ".";
|
||||
pos += 7;
|
||||
continue;
|
||||
}
|
||||
if (0==strncmp(pos,"__PVT__",7)) {
|
||||
pretty += "";
|
||||
pos += 7;
|
||||
continue;
|
||||
}
|
||||
if (pos[0]=='_' && pos[1]=='_' && pos[2]=='0'
|
||||
&& isxdigit(pos[3]) && isxdigit(pos[4])) {
|
||||
char value = 0;
|
||||
value += 16*(isdigit(pos[3]) ? (pos[3]-'0') : (tolower(pos[3])-'a'+10));
|
||||
value += (isdigit(pos[4]) ? (pos[4]-'0') : (tolower(pos[4])-'a'+10));
|
||||
pretty += value;
|
||||
pos += 5;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
// Default
|
||||
pretty += pos[0];
|
||||
++pos;
|
||||
}
|
||||
if (pretty.substr(0,4) == "TOP.") pretty.replace(0,4,"");
|
||||
if (pretty.substr(0,5) == "TOP->") pretty.replace(0,5,"");
|
||||
if (pretty[0]=='T' && pretty.substr(0,4) == "TOP.") pretty.replace(0,4,"");
|
||||
if (pretty[0]=='T' && pretty.substr(0,5) == "TOP->") pretty.replace(0,5,"");
|
||||
return pretty;
|
||||
}
|
||||
|
||||
|
||||
+8
-5
@@ -514,6 +514,7 @@ public:
|
||||
inline AstVarAttrClocker (en _e) : m_e(_e) {}
|
||||
explicit inline AstVarAttrClocker (int _e) : m_e(static_cast<en>(_e)) {}
|
||||
operator en () const { return m_e; }
|
||||
bool unknown() const { return m_e==CLOCKER_UNKNOWN; }
|
||||
AstVarAttrClocker invert() const {
|
||||
if (m_e==CLOCKER_YES) return CLOCKER_NO;
|
||||
else if (m_e==CLOCKER_NO) return CLOCKER_YES;
|
||||
@@ -1118,7 +1119,7 @@ public:
|
||||
void user1p(void* userp) { m_user1p=(AstNUser*)(userp); m_user1Cnt=AstUser1InUse::s_userCntGbl; }
|
||||
int user1() const { return user1p()->castInt(); }
|
||||
void user1(int val) { user1p(AstNUser::fromInt(val)); }
|
||||
int user1Inc() { int v=user1(); user1(v+1); return v; }
|
||||
int user1Inc(int val=1) { int v=user1(); user1(v+val); return v; }
|
||||
int user1SetOnce() { int v=user1(); if (!v) user1(1); return v; } // Better for cache than user1Inc()
|
||||
static void user1ClearTree() { AstUser1InUse::clear(); } // Clear userp()'s across the entire tree
|
||||
|
||||
@@ -1128,7 +1129,7 @@ public:
|
||||
void user2p(void* userp) { m_user2p=(AstNUser*)(userp); m_user2Cnt=AstUser2InUse::s_userCntGbl; }
|
||||
int user2() const { return user2p()->castInt(); }
|
||||
void user2(int val) { user2p(AstNUser::fromInt(val)); }
|
||||
int user2Inc() { int v=user2(); user2(v+1); return v; }
|
||||
int user2Inc(int val=1) { int v=user2(); user2(v+val); return v; }
|
||||
int user2SetOnce() { int v=user2(); if (!v) user2(1); return v; }
|
||||
static void user2ClearTree() { AstUser2InUse::clear(); }
|
||||
|
||||
@@ -1138,7 +1139,7 @@ public:
|
||||
void user3p(void* userp) { m_user3p=(AstNUser*)(userp); m_user3Cnt=AstUser3InUse::s_userCntGbl; }
|
||||
int user3() const { return user3p()->castInt(); }
|
||||
void user3(int val) { user3p(AstNUser::fromInt(val)); }
|
||||
int user3Inc() { int v=user3(); user3(v+1); return v; }
|
||||
int user3Inc(int val=1) { int v=user3(); user3(v+val); return v; }
|
||||
int user3SetOnce() { int v=user3(); if (!v) user3(1); return v; }
|
||||
static void user3ClearTree() { AstUser3InUse::clear(); }
|
||||
|
||||
@@ -1148,7 +1149,7 @@ public:
|
||||
void user4p(void* userp) { m_user4p=(AstNUser*)(userp); m_user4Cnt=AstUser4InUse::s_userCntGbl; }
|
||||
int user4() const { return user4p()->castInt(); }
|
||||
void user4(int val) { user4p(AstNUser::fromInt(val)); }
|
||||
int user4Inc() { int v=user4(); user4(v+1); return v; }
|
||||
int user4Inc(int val=1) { int v=user4(); user4(v+val); return v; }
|
||||
int user4SetOnce() { int v=user4(); if (!v) user4(1); return v; }
|
||||
static void user4ClearTree() { AstUser4InUse::clear(); }
|
||||
|
||||
@@ -1158,7 +1159,7 @@ public:
|
||||
void user5p(void* userp) { m_user5p=(AstNUser*)(userp); m_user5Cnt=AstUser5InUse::s_userCntGbl; }
|
||||
int user5() const { return user5p()->castInt(); }
|
||||
void user5(int val) { user5p(AstNUser::fromInt(val)); }
|
||||
int user5Inc() { int v=user5(); user5(v+1); return v; }
|
||||
int user5Inc(int val=1) { int v=user5(); user5(v+val); return v; }
|
||||
int user5SetOnce() { int v=user5(); if (!v) user5(1); return v; }
|
||||
static void user5ClearTree() { AstUser5InUse::clear(); }
|
||||
|
||||
@@ -1349,6 +1350,8 @@ public:
|
||||
: AstNodeMath(fl) {
|
||||
setOp1p(lhs); setOp2p(rhs); }
|
||||
ASTNODE_BASE_FUNCS(NodeBiop)
|
||||
virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp)=0; // Clone single node, just get same type back.
|
||||
// ACCESSORS
|
||||
AstNode* lhsp() const { return op1p()->castNode(); }
|
||||
AstNode* rhsp() const { return op2p()->castNode(); }
|
||||
void lhsp(AstNode* nodep) { return setOp1p(nodep); }
|
||||
|
||||
@@ -977,6 +977,7 @@ void AstVar::dump(ostream& str) {
|
||||
if (attrFileDescr()) str<<" [aFD]";
|
||||
if (isFuncReturn()) str<<" [FUNCRTN]";
|
||||
else if (isFuncLocal()) str<<" [FUNC]";
|
||||
if (!attrClocker().unknown()) str<<" ["<<attrClocker().ascii()<<"] ";
|
||||
str<<" "<<varType();
|
||||
}
|
||||
void AstSenTree::dump(ostream& str) {
|
||||
|
||||
+180
-7
@@ -158,6 +158,39 @@ public:
|
||||
//######################################################################
|
||||
//==== Data Types
|
||||
|
||||
class AstParamTypeDType : public AstNodeDType {
|
||||
// Parents: MODULE
|
||||
// A parameter type statement; much like a var or typedef
|
||||
private:
|
||||
AstVarType m_varType; // Type of variable (for localparam vs. param)
|
||||
string m_name; // Name of variable
|
||||
public:
|
||||
AstParamTypeDType(FileLine* fl, AstVarType type, const string& name, VFlagChildDType, AstNodeDType* dtp)
|
||||
: AstNodeDType(fl), m_varType(type), m_name(name) {
|
||||
childDTypep(dtp); // Only for parser
|
||||
dtypep(NULL); // V3Width will resolve
|
||||
}
|
||||
ASTNODE_NODE_FUNCS(ParamTypeDType, PARAMTYPEDTYPE)
|
||||
AstNodeDType* getChildDTypep() const { return childDTypep(); }
|
||||
AstNodeDType* childDTypep() const { return op1p()->castNodeDType(); } // op1 = Type assigning to
|
||||
void childDTypep(AstNodeDType* nodep) { setOp1p(nodep); }
|
||||
AstNodeDType* subDTypep() const { return dtypep() ? dtypep() : childDTypep(); }
|
||||
virtual AstBasicDType* basicp() const { return subDTypep()->basicp(); } // (Slow) recurse down to find basic data type
|
||||
virtual AstNodeDType* skipRefp() const { return subDTypep()->skipRefp(); }
|
||||
virtual AstNodeDType* skipRefToConstp() const { return subDTypep()->skipRefToConstp(); }
|
||||
virtual AstNodeDType* skipRefToEnump() const { return subDTypep()->skipRefToEnump(); }
|
||||
virtual int widthAlignBytes() const { return dtypep()->widthAlignBytes(); }
|
||||
virtual int widthTotalBytes() const { return dtypep()->widthTotalBytes(); }
|
||||
// METHODS
|
||||
virtual string name() const { return m_name; }
|
||||
virtual bool maybePointedTo() const { return true; }
|
||||
virtual bool hasDType() const { return true; }
|
||||
void name(const string& flag) { m_name = flag; }
|
||||
AstVarType varType() const { return m_varType; } // * = Type of variable
|
||||
bool isParam() const { return true; }
|
||||
bool isGParam() const { return (varType()==AstVarType::GPARAM); }
|
||||
};
|
||||
|
||||
class AstTypedef : public AstNode {
|
||||
private:
|
||||
string m_name;
|
||||
@@ -689,6 +722,24 @@ public:
|
||||
virtual int widthTotalBytes() const { return subDTypep()->widthTotalBytes(); }
|
||||
};
|
||||
|
||||
class AstParseTypeDType : public AstNodeDType {
|
||||
// Parents: VAR
|
||||
// During parsing, this indicates the type of a parameter is a "parameter type"
|
||||
// e.g. the data type is a container of any data type
|
||||
public:
|
||||
AstParseTypeDType(FileLine* fl)
|
||||
: AstNodeDType(fl) {}
|
||||
ASTNODE_NODE_FUNCS(ParseTypeDType, PARSETYPEDTYPE)
|
||||
AstNodeDType* dtypep() const { return NULL; }
|
||||
// METHODS
|
||||
virtual AstBasicDType* basicp() const { return NULL; }
|
||||
virtual AstNodeDType* skipRefp() const { return NULL; }
|
||||
virtual AstNodeDType* skipRefToConstp() const { return (AstNodeDType*)this; }
|
||||
virtual AstNodeDType* skipRefToEnump() const { return (AstNodeDType*)this; }
|
||||
virtual int widthAlignBytes() const { return 0; }
|
||||
virtual int widthTotalBytes() const { return 0; }
|
||||
};
|
||||
|
||||
//######################################################################
|
||||
|
||||
class AstArraySel : public AstNodeSel {
|
||||
@@ -713,6 +764,7 @@ public:
|
||||
init(fromp);
|
||||
}
|
||||
ASTNODE_NODE_FUNCS(ArraySel, ARRAYSEL)
|
||||
virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { return new AstArraySel(this->fileline(), lhsp, rhsp); }
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) {
|
||||
V3ERROR_NA; /* How can from be a const? */ }
|
||||
virtual string emitVerilog() { return "%k(%l%f[%r])"; }
|
||||
@@ -742,6 +794,7 @@ public:
|
||||
dtypeSetUInt32(); // Always used on IData arrays so returns word entities
|
||||
}
|
||||
ASTNODE_NODE_FUNCS(WordSel, WORDSEL)
|
||||
virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { return new AstWordSel(this->fileline(), lhsp, rhsp); }
|
||||
virtual void numberOperate(V3Number& out, const V3Number& from, const V3Number& bit) { V3ERROR_NA; }
|
||||
virtual string emitVerilog() { return "%k(%l%f[%r])"; }
|
||||
virtual string emitC() { return "%li[%ri]"; } // Not %k, as usually it's a small constant rhsp
|
||||
@@ -1333,6 +1386,7 @@ private:
|
||||
int m_pinNum; // Pin number
|
||||
string m_name; // Pin name, or "" for number based interconnect
|
||||
AstVar* m_modVarp; // Input/output this pin connects to on submodule.
|
||||
AstParamTypeDType* m_modPTypep; // Param type this pin connects to on submodule.
|
||||
bool m_param; // Pin connects to parameter
|
||||
bool m_svImplicit; // Pin is SystemVerilog .name'ed
|
||||
public:
|
||||
@@ -1341,6 +1395,7 @@ public:
|
||||
,m_name(name), m_param(false), m_svImplicit(false) {
|
||||
m_pinNum = pinNum;
|
||||
m_modVarp = NULL;
|
||||
m_modPTypep = NULL;
|
||||
setNOp1p(exprp);
|
||||
}
|
||||
AstPin(FileLine* fl, int pinNum, AstVarRef* varname, AstNode* exprp)
|
||||
@@ -1348,11 +1403,15 @@ public:
|
||||
m_name = varname->name();
|
||||
m_pinNum = pinNum;
|
||||
m_modVarp = NULL;
|
||||
m_modPTypep = NULL;
|
||||
setNOp1p(exprp);
|
||||
}
|
||||
ASTNODE_NODE_FUNCS(Pin, PIN)
|
||||
virtual void dump(ostream& str);
|
||||
virtual const char* broken() const { BROKEN_RTN(m_modVarp && !m_modVarp->brokeExists()); return NULL; }
|
||||
virtual const char* broken() const {
|
||||
BROKEN_RTN(m_modVarp && !m_modVarp->brokeExists());
|
||||
BROKEN_RTN(m_modPTypep && !m_modPTypep->brokeExists());
|
||||
return NULL; }
|
||||
virtual string name() const { return m_name; } // * = Pin name, ""=go by number
|
||||
virtual void name(const string& name) { m_name = name; }
|
||||
virtual string prettyOperatorName() const { return modVarp()
|
||||
@@ -1363,7 +1422,9 @@ public:
|
||||
void exprp(AstNode* nodep) { addOp1p(nodep); }
|
||||
AstNode* exprp() const { return op1p()->castNode(); } // op1 = Expression connected to pin, NULL if unconnected
|
||||
AstVar* modVarp() const { return m_modVarp; } // [After Link] Pointer to variable
|
||||
void modVarp(AstVar* varp) { m_modVarp=varp; }
|
||||
void modVarp(AstVar* nodep) { m_modVarp=nodep; }
|
||||
AstParamTypeDType* modPTypep() const { return m_modPTypep; } // [After Link] Pointer to variable
|
||||
void modPTypep(AstParamTypeDType* nodep) { m_modPTypep=nodep; }
|
||||
bool param() const { return m_param; }
|
||||
void param(bool flag) { m_param=flag; }
|
||||
bool svImplicit() const { return m_svImplicit; }
|
||||
@@ -2616,6 +2677,23 @@ public:
|
||||
ASTNODE_NODE_FUNCS(GenFor, GENFOR)
|
||||
};
|
||||
|
||||
class AstForeach : public AstNodeStmt {
|
||||
public:
|
||||
AstForeach(FileLine* fileline, AstNode* arrayp, AstNode* varsp,
|
||||
AstNode* bodysp)
|
||||
: AstNodeStmt(fileline) {
|
||||
setOp1p(arrayp); addNOp2p(varsp); addNOp4p(bodysp);
|
||||
}
|
||||
ASTNODE_NODE_FUNCS(Foreach, FOREACH)
|
||||
AstNode* arrayp() const { return op1p()->castNode(); } // op1= array
|
||||
AstNode* varsp() const { return op2p()->castNode(); } // op2= variable index list
|
||||
AstNode* bodysp() const { return op4p()->castNode(); } // op4= body of loop
|
||||
virtual bool isGateOptimizable() const { return false; }
|
||||
virtual int instrCount() const { return instrCountBranch(); }
|
||||
virtual V3Hash sameHash() const { return V3Hash(); }
|
||||
virtual bool same(AstNode* samep) const { return true; }
|
||||
};
|
||||
|
||||
class AstRepeat : public AstNodeStmt {
|
||||
public:
|
||||
AstRepeat(FileLine* fileline, AstNode* countp, AstNode* bodysp)
|
||||
@@ -2804,6 +2882,7 @@ public:
|
||||
dtypeSetUInt32(); // Always used on, and returns word entities
|
||||
}
|
||||
ASTNODE_NODE_FUNCS(ChangeXor, CHANGEXOR)
|
||||
virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { return new AstChangeXor(this->fileline(), lhsp, rhsp); }
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opChangeXor(lhs,rhs); }
|
||||
virtual string emitVerilog() { return "%k(%l %f^ %r)"; }
|
||||
virtual string emitC() { return "VL_CHANGEXOR_%li(%lw, %P, %li, %ri)"; }
|
||||
@@ -2922,20 +3001,37 @@ class AstInitArray : public AstNode {
|
||||
// Set a var to a large list of values
|
||||
// The values must be in sorted order, and not exceed the size of the var's array.
|
||||
// The first value on the initsp() list is for the lo() index of the array.
|
||||
// If default is specified, the vector may be sparse, and not provide each value.
|
||||
// Parents: ASTVAR::init()
|
||||
// Children: CONSTs...
|
||||
deque<uint32_t> m_indices; // Which array index each entry in the list is for (if defaultp)
|
||||
public:
|
||||
AstInitArray(FileLine* fl, AstNodeArrayDType* newDTypep, AstNode* initsp)
|
||||
AstInitArray(FileLine* fl, AstNodeArrayDType* newDTypep, AstNode* defaultp)
|
||||
: AstNode(fl) {
|
||||
dtypep(newDTypep);
|
||||
addNOp1p(initsp);
|
||||
addNOp1p(defaultp);
|
||||
}
|
||||
ASTNODE_NODE_FUNCS(InitArray, INITARRAY)
|
||||
AstNode* initsp() const { return op1p()->castNode(); } // op1 = Initial value expressions
|
||||
void addInitsp(AstNode* newp) { addOp1p(newp); }
|
||||
AstNode* defaultp() const { return op1p()->castNode(); } // op1 = Default if sparse
|
||||
void defaultp(AstNode* newp) { setOp1p(newp); }
|
||||
AstNode* initsp() const { return op2p()->castNode(); } // op2 = Initial value expressions
|
||||
void addValuep(AstNode* newp) { addIndexValuep(m_indices.size(), newp); }
|
||||
void addIndexValuep(uint32_t index, AstNode* newp) {
|
||||
// Must insert in sorted order
|
||||
if (!m_indices.empty()) UASSERT(index > m_indices.back(), "InitArray adding index <= previous index");
|
||||
m_indices.push_back(index);
|
||||
addOp2p(newp); }
|
||||
void addFrontValuep(AstNode* newp) { // Add to front of list, e.g. index 0.
|
||||
// e.g. 0:100, 1:101 when addFront(200), get 0:200, 1:100, 2:101
|
||||
initsp()->addHereThisAsNext(newp);
|
||||
m_indices.push_back(m_indices.size());
|
||||
}
|
||||
int posIndex(int listPos) {
|
||||
UASSERT (listPos < (int)m_indices.size(), "InitArray past end of indices list");
|
||||
return m_indices[listPos]; }
|
||||
virtual bool hasDType() const { return true; }
|
||||
virtual V3Hash sameHash() const { return V3Hash(); }
|
||||
virtual bool same(AstNode* samep) const { return true; }
|
||||
virtual bool same(AstNode* samep) const { return m_indices==samep->castInitArray()->m_indices; }
|
||||
};
|
||||
|
||||
class AstPragma : public AstNode {
|
||||
@@ -3747,6 +3843,7 @@ public:
|
||||
AstLogOr(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiop(fl, lhsp, rhsp) {
|
||||
dtypeSetLogicBool(); }
|
||||
ASTNODE_NODE_FUNCS(LogOr, LOGOR)
|
||||
virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { return new AstLogOr(this->fileline(), lhsp, rhsp); }
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opLogOr(lhs,rhs); }
|
||||
virtual string emitVerilog() { return "%k(%l %f|| %r)"; }
|
||||
virtual string emitC() { return "VL_LOGOR_%nq%lq%rq(%nw,%lw,%rw, %P, %li, %ri)"; }
|
||||
@@ -3761,6 +3858,7 @@ public:
|
||||
AstLogAnd(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiop(fl, lhsp, rhsp) {
|
||||
dtypeSetLogicBool(); }
|
||||
ASTNODE_NODE_FUNCS(LogAnd, LOGAND)
|
||||
virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { return new AstLogAnd(this->fileline(), lhsp, rhsp); }
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opLogAnd(lhs,rhs); }
|
||||
virtual string emitVerilog() { return "%k(%l %f&& %r)"; }
|
||||
virtual string emitC() { return "VL_LOGAND_%nq%lq%rq(%nw,%lw,%rw, %P, %li, %ri)"; }
|
||||
@@ -3775,6 +3873,7 @@ public:
|
||||
AstLogIf(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiop(fl, lhsp, rhsp) {
|
||||
dtypeSetLogicBool(); }
|
||||
ASTNODE_NODE_FUNCS(LogIf, LOGIF)
|
||||
virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { return new AstLogIf(this->fileline(), lhsp, rhsp); }
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opLogIf(lhs,rhs); }
|
||||
virtual string emitVerilog() { return "%k(%l %f-> %r)"; }
|
||||
virtual string emitC() { return "VL_LOGIF_%nq%lq%rq(%nw,%lw,%rw, %P, %li, %ri)"; }
|
||||
@@ -3789,6 +3888,7 @@ public:
|
||||
AstLogIff(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiCom(fl, lhsp, rhsp) {
|
||||
dtypeSetLogicBool(); }
|
||||
ASTNODE_NODE_FUNCS(LogIff, LOGIFF)
|
||||
virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { return new AstLogIff(this->fileline(), lhsp, rhsp); }
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opLogIff(lhs,rhs); }
|
||||
virtual string emitVerilog() { return "%k(%l %f<-> %r)"; }
|
||||
virtual string emitC() { return "VL_LOGIFF_%nq%lq%rq(%nw,%lw,%rw, %P, %li, %ri)"; }
|
||||
@@ -3803,6 +3903,7 @@ public:
|
||||
AstOr(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiComAsv(fl, lhsp, rhsp) {
|
||||
dtypeFrom(lhsp); }
|
||||
ASTNODE_NODE_FUNCS(Or, OR)
|
||||
virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { return new AstOr(this->fileline(), lhsp, rhsp); }
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opOr(lhs,rhs); }
|
||||
virtual string emitVerilog() { return "%k(%l %f| %r)"; }
|
||||
virtual string emitC() { return "VL_OR_%lq(%lW, %P, %li, %ri)"; }
|
||||
@@ -3816,6 +3917,7 @@ public:
|
||||
AstAnd(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiComAsv(fl, lhsp, rhsp) {
|
||||
dtypeFrom(lhsp); }
|
||||
ASTNODE_NODE_FUNCS(And, AND)
|
||||
virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { return new AstAnd(this->fileline(), lhsp, rhsp); }
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opAnd(lhs,rhs); }
|
||||
virtual string emitVerilog() { return "%k(%l %f& %r)"; }
|
||||
virtual string emitC() { return "VL_AND_%lq(%lW, %P, %li, %ri)"; }
|
||||
@@ -3829,6 +3931,7 @@ public:
|
||||
AstXor(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiComAsv(fl, lhsp, rhsp) {
|
||||
dtypeFrom(lhsp); }
|
||||
ASTNODE_NODE_FUNCS(Xor, XOR)
|
||||
virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { return new AstXor(this->fileline(), lhsp, rhsp); }
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opXor(lhs,rhs); }
|
||||
virtual string emitVerilog() { return "%k(%l %f^ %r)"; }
|
||||
virtual string emitC() { return "VL_XOR_%lq(%lW, %P, %li, %ri)"; }
|
||||
@@ -3842,6 +3945,7 @@ public:
|
||||
AstXnor(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiComAsv(fl, lhsp, rhsp) {
|
||||
dtypeFrom(lhsp); }
|
||||
ASTNODE_NODE_FUNCS(Xnor, XNOR)
|
||||
virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { return new AstXnor(this->fileline(), lhsp, rhsp); }
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opXnor(lhs,rhs); }
|
||||
virtual string emitVerilog() { return "%k(%l %f^ ~ %r)"; }
|
||||
virtual string emitC() { return "VL_XNOR_%lq(%lW, %P, %li, %ri)"; }
|
||||
@@ -3855,6 +3959,7 @@ public:
|
||||
AstEq(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiCom(fl, lhsp, rhsp) {
|
||||
dtypeSetLogicBool(); }
|
||||
ASTNODE_NODE_FUNCS(Eq, EQ)
|
||||
virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { return new AstEq(this->fileline(), lhsp, rhsp); }
|
||||
static AstNodeBiop* newTyped(FileLine* fl, AstNode* lhsp, AstNode* rhsp); // Return AstEq/AstEqD
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opEq(lhs,rhs); }
|
||||
virtual string emitVerilog() { return "%k(%l %f== %r)"; }
|
||||
@@ -3869,6 +3974,7 @@ public:
|
||||
AstEqD(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiCom(fl, lhsp, rhsp) {
|
||||
dtypeSetLogicBool(); }
|
||||
ASTNODE_NODE_FUNCS(EqD, EQD)
|
||||
virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { return new AstEqD(this->fileline(), lhsp, rhsp); }
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opEqD(lhs,rhs); }
|
||||
virtual string emitVerilog() { return "%k(%l %f== %r)"; }
|
||||
virtual string emitC() { V3ERROR_NA; return ""; }
|
||||
@@ -3884,6 +3990,7 @@ public:
|
||||
AstEqN(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiCom(fl, lhsp, rhsp) {
|
||||
dtypeSetLogicBool(); }
|
||||
ASTNODE_NODE_FUNCS(EqN, EQN)
|
||||
virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { return new AstEqN(this->fileline(), lhsp, rhsp); }
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opEqN(lhs,rhs); }
|
||||
virtual string emitVerilog() { return "%k(%l %f== %r)"; }
|
||||
virtual string emitC() { V3ERROR_NA; return ""; }
|
||||
@@ -3899,6 +4006,7 @@ public:
|
||||
AstNeq(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiCom(fl, lhsp, rhsp) {
|
||||
dtypeSetLogicBool(); }
|
||||
ASTNODE_NODE_FUNCS(Neq, NEQ)
|
||||
virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { return new AstNeq(this->fileline(), lhsp, rhsp); }
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opNeq(lhs,rhs); }
|
||||
virtual string emitVerilog() { return "%k(%l %f!= %r)"; }
|
||||
virtual string emitC() { return "VL_NEQ_%lq(%lW, %P, %li, %ri)"; }
|
||||
@@ -3912,6 +4020,7 @@ public:
|
||||
AstNeqD(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiCom(fl, lhsp, rhsp) {
|
||||
dtypeSetLogicBool(); }
|
||||
ASTNODE_NODE_FUNCS(NeqD, NEQD)
|
||||
virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { return new AstNeqD(this->fileline(), lhsp, rhsp); }
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opNeqD(lhs,rhs); }
|
||||
virtual string emitVerilog() { return "%k(%l %f!= %r)"; }
|
||||
virtual string emitC() { V3ERROR_NA; return ""; }
|
||||
@@ -3927,6 +4036,7 @@ public:
|
||||
AstNeqN(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiCom(fl, lhsp, rhsp) {
|
||||
dtypeSetLogicBool(); }
|
||||
ASTNODE_NODE_FUNCS(NeqN, NEQN)
|
||||
virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { return new AstNeqN(this->fileline(), lhsp, rhsp); }
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opNeqN(lhs,rhs); }
|
||||
virtual string emitVerilog() { return "%k(%l %f!= %r)"; }
|
||||
virtual string emitC() { V3ERROR_NA; return ""; }
|
||||
@@ -3942,6 +4052,7 @@ public:
|
||||
AstLt(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiop(fl, lhsp, rhsp) {
|
||||
dtypeSetLogicBool(); }
|
||||
ASTNODE_NODE_FUNCS(Lt, LT)
|
||||
virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { return new AstLt(this->fileline(), lhsp, rhsp); }
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opLt(lhs,rhs); }
|
||||
virtual string emitVerilog() { return "%k(%l %f< %r)"; }
|
||||
virtual string emitC() { return "VL_LT_%lq(%lW, %P, %li, %ri)"; }
|
||||
@@ -3955,6 +4066,7 @@ public:
|
||||
AstLtD(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiop(fl, lhsp, rhsp) {
|
||||
dtypeSetLogicBool(); }
|
||||
ASTNODE_NODE_FUNCS(LtD, LTD)
|
||||
virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { return new AstLtD(this->fileline(), lhsp, rhsp); }
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opLtD(lhs,rhs); }
|
||||
virtual string emitVerilog() { return "%k(%l %f< %r)"; }
|
||||
virtual string emitC() { V3ERROR_NA; return ""; }
|
||||
@@ -3970,6 +4082,7 @@ public:
|
||||
AstLtS(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiop(fl, lhsp, rhsp) {
|
||||
dtypeSetLogicBool(); }
|
||||
ASTNODE_NODE_FUNCS(LtS, LTS)
|
||||
virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { return new AstLtS(this->fileline(), lhsp, rhsp); }
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opLtS(lhs,rhs); }
|
||||
virtual string emitVerilog() { return "%k(%l %f< %r)"; }
|
||||
virtual string emitC() { return "VL_LTS_%nq%lq%rq(%nw,%lw,%rw, %P, %li, %ri)"; }
|
||||
@@ -3984,6 +4097,7 @@ public:
|
||||
AstLtN(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiop(fl, lhsp, rhsp) {
|
||||
dtypeSetLogicBool(); }
|
||||
ASTNODE_NODE_FUNCS(LtN, LTN)
|
||||
virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { return new AstLtN(this->fileline(), lhsp, rhsp); }
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opLtN(lhs,rhs); }
|
||||
virtual string emitVerilog() { return "%k(%l %f< %r)"; }
|
||||
virtual string emitC() { V3ERROR_NA; return ""; }
|
||||
@@ -3999,6 +4113,7 @@ public:
|
||||
AstGt(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiop(fl, lhsp, rhsp) {
|
||||
dtypeSetLogicBool(); }
|
||||
ASTNODE_NODE_FUNCS(Gt, GT)
|
||||
virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { return new AstGt(this->fileline(), lhsp, rhsp); }
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opGt(lhs,rhs); }
|
||||
virtual string emitVerilog() { return "%k(%l %f> %r)"; }
|
||||
virtual string emitC() { return "VL_GT_%lq(%lW, %P, %li, %ri)"; }
|
||||
@@ -4012,6 +4127,7 @@ public:
|
||||
AstGtD(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiop(fl, lhsp, rhsp) {
|
||||
dtypeSetLogicBool(); }
|
||||
ASTNODE_NODE_FUNCS(GtD, GTD)
|
||||
virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { return new AstGtD(this->fileline(), lhsp, rhsp); }
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opGtD(lhs,rhs); }
|
||||
virtual string emitVerilog() { return "%k(%l %f> %r)"; }
|
||||
virtual string emitC() { V3ERROR_NA; return ""; }
|
||||
@@ -4027,6 +4143,7 @@ public:
|
||||
AstGtS(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiop(fl, lhsp, rhsp) {
|
||||
dtypeSetLogicBool(); }
|
||||
ASTNODE_NODE_FUNCS(GtS, GTS)
|
||||
virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { return new AstGtS(this->fileline(), lhsp, rhsp); }
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opGtS(lhs,rhs); }
|
||||
virtual string emitVerilog() { return "%k(%l %f> %r)"; }
|
||||
virtual string emitC() { return "VL_GTS_%nq%lq%rq(%nw,%lw,%rw, %P, %li, %ri)"; }
|
||||
@@ -4041,6 +4158,7 @@ public:
|
||||
AstGtN(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiop(fl, lhsp, rhsp) {
|
||||
dtypeSetLogicBool(); }
|
||||
ASTNODE_NODE_FUNCS(GtN, GTN)
|
||||
virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { return new AstGtN(this->fileline(), lhsp, rhsp); }
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opGtN(lhs,rhs); }
|
||||
virtual string emitVerilog() { return "%k(%l %f> %r)"; }
|
||||
virtual string emitC() { V3ERROR_NA; return ""; }
|
||||
@@ -4056,6 +4174,7 @@ public:
|
||||
AstGte(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiop(fl, lhsp, rhsp) {
|
||||
dtypeSetLogicBool(); }
|
||||
ASTNODE_NODE_FUNCS(Gte, GTE)
|
||||
virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { return new AstGte(this->fileline(), lhsp, rhsp); }
|
||||
static AstNodeBiop* newTyped(FileLine* fl, AstNode* lhsp, AstNode* rhsp); // Return AstGte/AstGteS/AstGteD
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opGte(lhs,rhs); }
|
||||
virtual string emitVerilog() { return "%k(%l %f>= %r)"; }
|
||||
@@ -4070,6 +4189,7 @@ public:
|
||||
AstGteD(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiop(fl, lhsp, rhsp) {
|
||||
dtypeSetLogicBool(); }
|
||||
ASTNODE_NODE_FUNCS(GteD, GTED)
|
||||
virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { return new AstGteD(this->fileline(), lhsp, rhsp); }
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opGteD(lhs,rhs); }
|
||||
virtual string emitVerilog() { return "%k(%l %f>= %r)"; }
|
||||
virtual string emitC() { V3ERROR_NA; return ""; }
|
||||
@@ -4085,6 +4205,7 @@ public:
|
||||
AstGteS(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiop(fl, lhsp, rhsp) {
|
||||
dtypeSetLogicBool(); }
|
||||
ASTNODE_NODE_FUNCS(GteS, GTES)
|
||||
virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { return new AstGteS(this->fileline(), lhsp, rhsp); }
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opGteS(lhs,rhs); }
|
||||
virtual string emitVerilog() { return "%k(%l %f>= %r)"; }
|
||||
virtual string emitC() { return "VL_GTES_%nq%lq%rq(%nw,%lw,%rw, %P, %li, %ri)"; }
|
||||
@@ -4099,6 +4220,7 @@ public:
|
||||
AstGteN(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiop(fl, lhsp, rhsp) {
|
||||
dtypeSetLogicBool(); }
|
||||
ASTNODE_NODE_FUNCS(GteN, GTEN)
|
||||
virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { return new AstGteN(this->fileline(), lhsp, rhsp); }
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opGteN(lhs,rhs); }
|
||||
virtual string emitVerilog() { return "%k(%l %f>= %r)"; }
|
||||
virtual string emitC() { V3ERROR_NA; return ""; }
|
||||
@@ -4114,6 +4236,7 @@ public:
|
||||
AstLte(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiop(fl, lhsp, rhsp) {
|
||||
dtypeSetLogicBool(); }
|
||||
ASTNODE_NODE_FUNCS(Lte, LTE)
|
||||
virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { return new AstLte(this->fileline(), lhsp, rhsp); }
|
||||
static AstNodeBiop* newTyped(FileLine* fl, AstNode* lhsp, AstNode* rhsp); // Return AstLte/AstLteS/AstLteD
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opLte(lhs,rhs); }
|
||||
virtual string emitVerilog() { return "%k(%l %f<= %r)"; }
|
||||
@@ -4128,6 +4251,7 @@ public:
|
||||
AstLteD(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiop(fl, lhsp, rhsp) {
|
||||
dtypeSetLogicBool(); }
|
||||
ASTNODE_NODE_FUNCS(LteD, LTED)
|
||||
virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { return new AstLteD(this->fileline(), lhsp, rhsp); }
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opLteD(lhs,rhs); }
|
||||
virtual string emitVerilog() { return "%k(%l %f<= %r)"; }
|
||||
virtual string emitC() { V3ERROR_NA; return ""; }
|
||||
@@ -4143,6 +4267,7 @@ public:
|
||||
AstLteS(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiop(fl, lhsp, rhsp) {
|
||||
dtypeSetLogicBool(); }
|
||||
ASTNODE_NODE_FUNCS(LteS, LTES)
|
||||
virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { return new AstLteS(this->fileline(), lhsp, rhsp); }
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opLteS(lhs,rhs); }
|
||||
virtual string emitVerilog() { return "%k(%l %f<= %r)"; }
|
||||
virtual string emitC() { return "VL_LTES_%nq%lq%rq(%nw,%lw,%rw, %P, %li, %ri)"; }
|
||||
@@ -4157,6 +4282,7 @@ public:
|
||||
AstLteN(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiop(fl, lhsp, rhsp) {
|
||||
dtypeSetLogicBool(); }
|
||||
ASTNODE_NODE_FUNCS(LteN, LTEN)
|
||||
virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { return new AstLteN(this->fileline(), lhsp, rhsp); }
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opLteN(lhs,rhs); }
|
||||
virtual string emitVerilog() { return "%k(%l %f<= %r)"; }
|
||||
virtual string emitC() { V3ERROR_NA; return ""; }
|
||||
@@ -4174,6 +4300,7 @@ public:
|
||||
if (setwidth) { dtypeSetLogicSized(setwidth,setwidth,AstNumeric::UNSIGNED); }
|
||||
}
|
||||
ASTNODE_NODE_FUNCS(ShiftL, SHIFTL)
|
||||
virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { return new AstShiftL(this->fileline(), lhsp, rhsp); }
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opShiftL(lhs,rhs); }
|
||||
virtual string emitVerilog() { return "%k(%l %f<< %r)"; }
|
||||
virtual string emitC() { return "VL_SHIFTL_%nq%lq%rq(%nw,%lw,%rw, %P, %li, %ri)"; }
|
||||
@@ -4189,6 +4316,7 @@ public:
|
||||
if (setwidth) { dtypeSetLogicSized(setwidth,setwidth,AstNumeric::UNSIGNED); }
|
||||
}
|
||||
ASTNODE_NODE_FUNCS(ShiftR, SHIFTR)
|
||||
virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { return new AstShiftR(this->fileline(), lhsp, rhsp); }
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opShiftR(lhs,rhs); }
|
||||
virtual string emitVerilog() { return "%k(%l %f>> %r)"; }
|
||||
virtual string emitC() { return "VL_SHIFTR_%nq%lq%rq(%nw,%lw,%rw, %P, %li, %ri)"; }
|
||||
@@ -4207,6 +4335,7 @@ public:
|
||||
if (setwidth) { dtypeSetLogicSized(setwidth,setwidth,AstNumeric::SIGNED); }
|
||||
}
|
||||
ASTNODE_NODE_FUNCS(ShiftRS, SHIFTRS)
|
||||
virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { return new AstShiftRS(this->fileline(), lhsp, rhsp); }
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) {
|
||||
out.opShiftRS(lhs,rhs,lhsp()->widthMinV()); }
|
||||
virtual string emitVerilog() { return "%k(%l %f>>> %r)"; }
|
||||
@@ -4222,6 +4351,7 @@ public:
|
||||
AstAdd(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiComAsv(fl, lhsp, rhsp) {
|
||||
dtypeFrom(lhsp); }
|
||||
ASTNODE_NODE_FUNCS(Add, ADD)
|
||||
virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { return new AstAdd(this->fileline(), lhsp, rhsp); }
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opAdd(lhs,rhs); }
|
||||
virtual string emitVerilog() { return "%k(%l %f+ %r)"; }
|
||||
virtual string emitC() { return "VL_ADD_%lq(%lW, %P, %li, %ri)"; }
|
||||
@@ -4235,6 +4365,7 @@ public:
|
||||
AstAddD(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiComAsv(fl, lhsp, rhsp) {
|
||||
dtypeSetDouble(); }
|
||||
ASTNODE_NODE_FUNCS(AddD, ADDD)
|
||||
virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { return new AstAddD(this->fileline(), lhsp, rhsp); }
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opAddD(lhs,rhs); }
|
||||
virtual string emitVerilog() { return "%k(%l %f+ %r)"; }
|
||||
virtual string emitC() { V3ERROR_NA; return ""; }
|
||||
@@ -4250,6 +4381,7 @@ public:
|
||||
AstSub(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiop(fl, lhsp, rhsp) {
|
||||
dtypeFrom(lhsp); }
|
||||
ASTNODE_NODE_FUNCS(Sub, SUB)
|
||||
virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { return new AstSub(this->fileline(), lhsp, rhsp); }
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opSub(lhs,rhs); }
|
||||
virtual string emitVerilog() { return "%k(%l %f- %r)"; }
|
||||
virtual string emitC() { return "VL_SUB_%lq(%lW, %P, %li, %ri)"; }
|
||||
@@ -4263,6 +4395,7 @@ public:
|
||||
AstSubD(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiop(fl, lhsp, rhsp) {
|
||||
dtypeSetDouble(); }
|
||||
ASTNODE_NODE_FUNCS(SubD, SUBD)
|
||||
virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { return new AstSubD(this->fileline(), lhsp, rhsp); }
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opSubD(lhs,rhs); }
|
||||
virtual string emitVerilog() { return "%k(%l %f- %r)"; }
|
||||
virtual string emitC() { V3ERROR_NA; return ""; }
|
||||
@@ -4278,6 +4411,7 @@ public:
|
||||
AstMul(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiComAsv(fl, lhsp, rhsp) {
|
||||
dtypeFrom(lhsp); }
|
||||
ASTNODE_NODE_FUNCS(Mul, MUL)
|
||||
virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { return new AstMul(this->fileline(), lhsp, rhsp); }
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opMul(lhs,rhs); }
|
||||
virtual string emitVerilog() { return "%k(%l %f* %r)"; }
|
||||
virtual string emitC() { return "VL_MUL_%lq(%lW, %P, %li, %ri)"; }
|
||||
@@ -4292,6 +4426,7 @@ public:
|
||||
AstMulD(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiComAsv(fl, lhsp, rhsp) {
|
||||
dtypeSetDouble(); }
|
||||
ASTNODE_NODE_FUNCS(MulD, MULD)
|
||||
virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { return new AstMulD(this->fileline(), lhsp, rhsp); }
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opMulD(lhs,rhs); }
|
||||
virtual string emitVerilog() { return "%k(%l %f* %r)"; }
|
||||
virtual string emitC() { V3ERROR_NA; return ""; }
|
||||
@@ -4307,6 +4442,7 @@ public:
|
||||
AstMulS(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiComAsv(fl, lhsp, rhsp) {
|
||||
dtypeFrom(lhsp); }
|
||||
ASTNODE_NODE_FUNCS(MulS, MULS)
|
||||
virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { return new AstMulS(this->fileline(), lhsp, rhsp); }
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opMulS(lhs,rhs); }
|
||||
virtual string emitVerilog() { return "%k(%l %f* %r)"; }
|
||||
virtual string emitC() { return "VL_MULS_%nq%lq%rq(%nw,%lw,%rw, %P, %li, %ri)"; }
|
||||
@@ -4322,6 +4458,7 @@ public:
|
||||
AstDiv(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiop(fl, lhsp, rhsp) {
|
||||
dtypeFrom(lhsp); }
|
||||
ASTNODE_NODE_FUNCS(Div, DIV)
|
||||
virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { return new AstDiv(this->fileline(), lhsp, rhsp); }
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opDiv(lhs,rhs); }
|
||||
virtual string emitVerilog() { return "%k(%l %f/ %r)"; }
|
||||
virtual string emitC() { return "VL_DIV_%nq%lq%rq(%lw, %P, %li, %ri)"; }
|
||||
@@ -4335,6 +4472,7 @@ public:
|
||||
AstDivD(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiop(fl, lhsp, rhsp) {
|
||||
dtypeSetDouble(); }
|
||||
ASTNODE_NODE_FUNCS(DivD, DIVD)
|
||||
virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { return new AstDivD(this->fileline(), lhsp, rhsp); }
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opDivD(lhs,rhs); }
|
||||
virtual string emitVerilog() { return "%k(%l %f/ %r)"; }
|
||||
virtual string emitC() { V3ERROR_NA; return ""; }
|
||||
@@ -4350,6 +4488,7 @@ public:
|
||||
AstDivS(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiop(fl, lhsp, rhsp) {
|
||||
dtypeFrom(lhsp); }
|
||||
ASTNODE_NODE_FUNCS(DivS, DIVS)
|
||||
virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { return new AstDivS(this->fileline(), lhsp, rhsp); }
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opDivS(lhs,rhs); }
|
||||
virtual string emitVerilog() { return "%k(%l %f/ %r)"; }
|
||||
virtual string emitC() { return "VL_DIVS_%nq%lq%rq(%lw, %P, %li, %ri)"; }
|
||||
@@ -4364,6 +4503,7 @@ public:
|
||||
AstModDiv(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiop(fl, lhsp, rhsp) {
|
||||
dtypeFrom(lhsp); }
|
||||
ASTNODE_NODE_FUNCS(ModDiv, MODDIV)
|
||||
virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { return new AstModDiv(this->fileline(), lhsp, rhsp); }
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opModDiv(lhs,rhs); }
|
||||
virtual string emitVerilog() { return "%k(%l %f%% %r)"; }
|
||||
virtual string emitC() { return "VL_MODDIV_%nq%lq%rq(%lw, %P, %li, %ri)"; }
|
||||
@@ -4377,6 +4517,7 @@ public:
|
||||
AstModDivS(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiop(fl, lhsp, rhsp) {
|
||||
dtypeFrom(lhsp); }
|
||||
ASTNODE_NODE_FUNCS(ModDivS, MODDIVS)
|
||||
virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { return new AstModDivS(this->fileline(), lhsp, rhsp); }
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opModDivS(lhs,rhs); }
|
||||
virtual string emitVerilog() { return "%k(%l %f%% %r)"; }
|
||||
virtual string emitC() { return "VL_MODDIVS_%nq%lq%rq(%lw, %P, %li, %ri)"; }
|
||||
@@ -4391,6 +4532,7 @@ public:
|
||||
AstPow(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiop(fl, lhsp, rhsp) {
|
||||
dtypeFrom(lhsp); }
|
||||
ASTNODE_NODE_FUNCS(Pow, POW)
|
||||
virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { return new AstPow(this->fileline(), lhsp, rhsp); }
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opPow(lhs,rhs); }
|
||||
virtual string emitVerilog() { return "%k(%l %f** %r)"; }
|
||||
virtual string emitC() { return "VL_POW_%nq%lq%rq(%nw,%lw,%rw, %P, %li, %ri)"; }
|
||||
@@ -4404,6 +4546,7 @@ public:
|
||||
AstPowD(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiop(fl, lhsp, rhsp) {
|
||||
dtypeSetDouble(); }
|
||||
ASTNODE_NODE_FUNCS(PowD, POWD)
|
||||
virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { return new AstPowD(this->fileline(), lhsp, rhsp); }
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opPowD(lhs,rhs); }
|
||||
virtual string emitVerilog() { return "%k(%l %f** %r)"; }
|
||||
virtual string emitC() { return "pow(%li,%ri)"; }
|
||||
@@ -4418,6 +4561,7 @@ public:
|
||||
AstPowSU(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiop(fl, lhsp, rhsp) {
|
||||
dtypeFrom(lhsp); }
|
||||
ASTNODE_NODE_FUNCS(PowSU, POWSU)
|
||||
virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { return new AstPowSU(this->fileline(), lhsp, rhsp); }
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opPowSU(lhs,rhs); }
|
||||
virtual string emitVerilog() { return "%k(%l %f** %r)"; }
|
||||
virtual string emitC() { return "VL_POWSS_%nq%lq%rq(%nw,%lw,%rw, %P, %li, %ri, 1,0)"; }
|
||||
@@ -4432,6 +4576,7 @@ public:
|
||||
AstPowSS(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiop(fl, lhsp, rhsp) {
|
||||
dtypeFrom(lhsp); }
|
||||
ASTNODE_NODE_FUNCS(PowSS, POWSS)
|
||||
virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { return new AstPowSS(this->fileline(), lhsp, rhsp); }
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opPowSS(lhs,rhs); }
|
||||
virtual string emitVerilog() { return "%k(%l %f** %r)"; }
|
||||
virtual string emitC() { return "VL_POWSS_%nq%lq%rq(%nw,%lw,%rw, %P, %li, %ri, 1,1)"; }
|
||||
@@ -4446,6 +4591,7 @@ public:
|
||||
AstPowUS(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiop(fl, lhsp, rhsp) {
|
||||
dtypeFrom(lhsp); }
|
||||
ASTNODE_NODE_FUNCS(PowUS, POWUS)
|
||||
virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { return new AstPowUS(this->fileline(), lhsp, rhsp); }
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opPowUS(lhs,rhs); }
|
||||
virtual string emitVerilog() { return "%k(%l %f** %r)"; }
|
||||
virtual string emitC() { return "VL_POWSS_%nq%lq%rq(%nw,%lw,%rw, %P, %li, %ri, 0,1)"; }
|
||||
@@ -4460,6 +4606,7 @@ public:
|
||||
AstEqCase(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiCom(fl, lhsp, rhsp) {
|
||||
dtypeSetLogicBool(); }
|
||||
ASTNODE_NODE_FUNCS(EqCase, EQCASE)
|
||||
virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { return new AstEqCase(this->fileline(), lhsp, rhsp); }
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opCaseEq(lhs,rhs); }
|
||||
virtual string emitVerilog() { return "%k(%l %f=== %r)"; }
|
||||
virtual string emitC() { return "VL_EQ_%lq(%lW, %P, %li, %ri)"; }
|
||||
@@ -4473,6 +4620,7 @@ public:
|
||||
AstNeqCase(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiCom(fl, lhsp, rhsp) {
|
||||
dtypeSetLogicBool(); }
|
||||
ASTNODE_NODE_FUNCS(NeqCase, NEQCASE)
|
||||
virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { return new AstNeqCase(this->fileline(), lhsp, rhsp); }
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opCaseNeq(lhs,rhs); }
|
||||
virtual string emitVerilog() { return "%k(%l %f!== %r)"; }
|
||||
virtual string emitC() { return "VL_NEQ_%lq(%lW, %P, %li, %ri)"; }
|
||||
@@ -4487,6 +4635,7 @@ public:
|
||||
AstEqWild(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiop(fl, lhsp, rhsp) {
|
||||
dtypeSetLogicBool(); }
|
||||
ASTNODE_NODE_FUNCS(EqWild, EQWILD)
|
||||
virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { return new AstEqWild(this->fileline(), lhsp, rhsp); }
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opWildEq(lhs,rhs); }
|
||||
virtual string emitVerilog() { return "%k(%l %f==? %r)"; }
|
||||
virtual string emitC() { return "VL_EQ_%lq(%lW, %P, %li, %ri)"; }
|
||||
@@ -4500,6 +4649,7 @@ public:
|
||||
AstNeqWild(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiop(fl, lhsp, rhsp) {
|
||||
dtypeSetLogicBool(); }
|
||||
ASTNODE_NODE_FUNCS(NeqWild, NEQWILD)
|
||||
virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { return new AstNeqWild(this->fileline(), lhsp, rhsp); }
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opWildNeq(lhs,rhs); }
|
||||
virtual string emitVerilog() { return "%k(%l %f!=? %r)"; }
|
||||
virtual string emitC() { return "VL_NEQ_%lq(%lW, %P, %li, %ri)"; }
|
||||
@@ -4519,6 +4669,7 @@ public:
|
||||
}
|
||||
}
|
||||
ASTNODE_NODE_FUNCS(Concat, CONCAT)
|
||||
virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { return new AstConcat(this->fileline(), lhsp, rhsp); }
|
||||
virtual string emitVerilog() { return "%f{%l, %k%r}"; }
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opConcat(lhs,rhs); }
|
||||
virtual string emitC() { return "VL_CONCAT_%nq%lq%rq(%nw,%lw,%rw, %P, %li, %ri)"; }
|
||||
@@ -4534,6 +4685,7 @@ public:
|
||||
dtypeSetString();
|
||||
}
|
||||
ASTNODE_NODE_FUNCS(ConcatN, CONCATN)
|
||||
virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { return new AstConcatN(this->fileline(), lhsp, rhsp); }
|
||||
virtual string emitVerilog() { return "%f{%l, %k%r}"; }
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opConcatN(lhs,rhs); }
|
||||
virtual string emitC() { return "VL_CONCATN_NNN(%li, %ri)"; }
|
||||
@@ -4560,6 +4712,7 @@ public:
|
||||
AstReplicate(FileLine* fl, AstNode* lhsp, uint32_t repCount)
|
||||
: AstNodeBiop(fl, lhsp, new AstConst(fl, repCount)) { init(); }
|
||||
ASTNODE_NODE_FUNCS(Replicate, REPLICATE)
|
||||
virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { return new AstReplicate(this->fileline(), lhsp, rhsp); }
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opRepl(lhs,rhs); }
|
||||
virtual string emitVerilog() { return "%f{%r{%k%l}}"; }
|
||||
virtual string emitC() { return "VL_REPLICATE_%nq%lq%rq(%nw,%lw,%rw, %P, %li, %ri)"; }
|
||||
@@ -4578,6 +4731,7 @@ public:
|
||||
AstReplicateN(FileLine* fl, AstNode* lhsp, uint32_t repCount)
|
||||
: AstNodeBiop(fl, lhsp, new AstConst(fl, repCount)) { init(); }
|
||||
ASTNODE_NODE_FUNCS(ReplicateN, REPLICATEN)
|
||||
virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { return new AstReplicateN(this->fileline(), lhsp, rhsp); }
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opReplN(lhs,rhs); }
|
||||
virtual string emitVerilog() { return "%f{%r{%k%l}}"; }
|
||||
virtual string emitC() { return "VL_REPLICATEN_NN%rq(0,0,%rw, %li, %ri)"; }
|
||||
@@ -4592,6 +4746,7 @@ class AstStreamL : public AstNodeStream {
|
||||
public:
|
||||
AstStreamL(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeStream(fl, lhsp, rhsp) {}
|
||||
ASTNODE_NODE_FUNCS(StreamL, STREAML)
|
||||
virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { return new AstStreamL(this->fileline(), lhsp, rhsp); }
|
||||
virtual string emitVerilog() { return "%f{ << %r %k{%l} }"; }
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opStreamL(lhs,rhs); }
|
||||
virtual string emitC() { return "VL_STREAML_%nq%lq%rq(%nw,%lw,%rw, %P, %li, %ri)"; }
|
||||
@@ -4605,6 +4760,7 @@ class AstStreamR : public AstNodeStream {
|
||||
public:
|
||||
AstStreamR(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeStream(fl, lhsp, rhsp) {}
|
||||
ASTNODE_NODE_FUNCS(StreamR, STREAMR)
|
||||
virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { return new AstStreamR(this->fileline(), lhsp, rhsp); }
|
||||
virtual string emitVerilog() { return "%f{ >> %r %k{%l} }"; }
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opAssign(lhs); }
|
||||
virtual string emitC() { return isWide() ? "VL_ASSIGN_W(%nw, %P, %li)" : "%li"; }
|
||||
@@ -4620,6 +4776,7 @@ public:
|
||||
AstBufIf1(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiop(fl, lhsp, rhsp) {
|
||||
dtypeFrom(lhsp); }
|
||||
ASTNODE_NODE_FUNCS(BufIf1, BUFIF1)
|
||||
virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { return new AstBufIf1(this->fileline(), lhsp, rhsp); }
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opBufIf1(lhs,rhs); }
|
||||
virtual string emitVerilog() { return "bufif(%r,%l)"; }
|
||||
virtual string emitC() { V3ERROR_NA; return "";} // Lclean || Rclean
|
||||
@@ -4632,6 +4789,7 @@ class AstFGetS : public AstNodeBiop {
|
||||
public:
|
||||
AstFGetS(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiop(fl, lhsp, rhsp) {}
|
||||
ASTNODE_NODE_FUNCS(FGetS, FGETS)
|
||||
virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { return new AstFGetS(this->fileline(), lhsp, rhsp); }
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { V3ERROR_NA; }
|
||||
virtual string emitVerilog() { return "%f$fgets(%l,%r)"; }
|
||||
virtual string emitC() { return "VL_FGETS_%nqX%rq(%lw, %P, &(%li), %ri)"; }
|
||||
@@ -5098,6 +5256,21 @@ public:
|
||||
};
|
||||
|
||||
|
||||
class AstCReset : public AstNodeStmt {
|
||||
//Reset variable at startup
|
||||
public:
|
||||
AstCReset(FileLine* fl, AstNode* exprsp)
|
||||
: AstNodeStmt(fl) {
|
||||
addNOp1p(exprsp);
|
||||
}
|
||||
ASTNODE_NODE_FUNCS(CReset, CRESET)
|
||||
virtual bool isGateOptimizable() const { return false; }
|
||||
virtual bool isPredictOptimizable() const { return false; }
|
||||
virtual V3Hash sameHash() const { return V3Hash(); }
|
||||
virtual bool same(AstNode* samep) const { return true; }
|
||||
AstVarRef* varrefp() const { return op1p()->castVarRef(); } // op1= varref to reset
|
||||
};
|
||||
|
||||
class AstCStmt : public AstNodeStmt {
|
||||
// Emit C statement
|
||||
public:
|
||||
|
||||
+58
-8
@@ -51,12 +51,54 @@ public:
|
||||
AstNodeModule* m_topModp; // Top module
|
||||
AstScope* m_scopetopp; // Scope under TOPSCOPE
|
||||
AstCFunc* m_chgFuncp; // Change function we're building
|
||||
AstCFunc* m_tlChgFuncp; // Top level change function we're building
|
||||
int m_numStmts; // Number of statements added to m_chgFuncp
|
||||
int m_funcNum; // Number of change functions emitted
|
||||
|
||||
ChangedState() {
|
||||
m_topModp = NULL;
|
||||
m_chgFuncp = NULL;
|
||||
m_scopetopp = NULL;
|
||||
m_tlChgFuncp = NULL;
|
||||
m_numStmts = 0;
|
||||
m_funcNum = 0;
|
||||
}
|
||||
~ChangedState() {}
|
||||
|
||||
void maybeCreateChgFuncp() {
|
||||
// Don't create an extra function call if splitting is disabled
|
||||
if (!v3Global.opt.outputSplitCFuncs()) {
|
||||
m_chgFuncp = m_tlChgFuncp;
|
||||
return;
|
||||
}
|
||||
if (!m_chgFuncp || v3Global.opt.outputSplitCFuncs() < m_numStmts) {
|
||||
m_chgFuncp = new AstCFunc(m_scopetopp->fileline(), "_change_request_" + cvtToStr(++m_funcNum), m_scopetopp, "QData");
|
||||
m_chgFuncp->argTypes(EmitCBaseVisitor::symClassVar());
|
||||
m_chgFuncp->symProlog(true);
|
||||
m_chgFuncp->declPrivate(true);
|
||||
m_scopetopp->addActivep(m_chgFuncp);
|
||||
|
||||
// Add a top call to it
|
||||
AstCCall* callp = new AstCCall(m_scopetopp->fileline(), m_chgFuncp);
|
||||
callp->argTypes("vlSymsp");
|
||||
|
||||
if (!m_tlChgFuncp->stmtsp()) {
|
||||
m_tlChgFuncp->addStmtsp(new AstCReturn(m_scopetopp->fileline(), callp));
|
||||
} else {
|
||||
AstCReturn* returnp = m_tlChgFuncp->stmtsp()->castCReturn();
|
||||
if (!returnp) m_scopetopp->v3fatalSrc("Lost CReturn in top change function");
|
||||
// This is currently using AstLogOr which will shortcut the evaluation if
|
||||
// any function returns true. This is likely what we want and is similar to the logic already in use
|
||||
// inside V3EmitC, however, it also means that verbose logging may miss to print change detect variables.
|
||||
AstNode* newp = new AstCReturn(m_scopetopp->fileline(),
|
||||
new AstLogOr(m_scopetopp->fileline(), callp,
|
||||
returnp->lhsp()->unlinkFrBack()));
|
||||
returnp->replaceWith(newp);
|
||||
returnp->deleteTree(); VL_DANGLING(returnp);
|
||||
}
|
||||
m_numStmts = 0;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
//######################################################################
|
||||
@@ -87,6 +129,8 @@ private:
|
||||
<<"... Could recompile with DETECTARRAY_MAX_INDEXES increased"<<endl);
|
||||
return;
|
||||
}
|
||||
m_statep->maybeCreateChgFuncp();
|
||||
|
||||
AstChangeDet* changep = new AstChangeDet (m_vscp->fileline(),
|
||||
m_varEqnp->cloneTree(true),
|
||||
m_newRvEqnp->cloneTree(true), false);
|
||||
@@ -95,6 +139,8 @@ private:
|
||||
m_newLvEqnp->cloneTree(true),
|
||||
m_varEqnp->cloneTree(true));
|
||||
m_statep->m_chgFuncp->addFinalsp(initp);
|
||||
EmitCBaseCounterVisitor visitor(initp);
|
||||
m_statep->m_numStmts += visitor.count();
|
||||
}
|
||||
|
||||
virtual void visit(AstBasicDType* nodep, AstNUser*) {
|
||||
@@ -200,6 +246,7 @@ private:
|
||||
}
|
||||
nodep->iterateChildren(*this);
|
||||
}
|
||||
|
||||
virtual void visit(AstTopScope* nodep, AstNUser*) {
|
||||
UINFO(4," TS "<<nodep<<endl);
|
||||
// Clearing
|
||||
@@ -208,15 +255,18 @@ private:
|
||||
AstScope* scopep = nodep->scopep();
|
||||
if (!scopep) nodep->v3fatalSrc("No scope found on top level, perhaps you have no statements?\n");
|
||||
m_statep->m_scopetopp = scopep;
|
||||
// Create change detection function
|
||||
m_statep->m_chgFuncp = new AstCFunc(nodep->fileline(), "_change_request", scopep, "QData");
|
||||
m_statep->m_chgFuncp->argTypes(EmitCBaseVisitor::symClassVar());
|
||||
m_statep->m_chgFuncp->symProlog(true);
|
||||
m_statep->m_chgFuncp->declPrivate(true);
|
||||
m_statep->m_scopetopp->addActivep(m_statep->m_chgFuncp);
|
||||
// We need at least one change detect so we know to emit the correct code
|
||||
|
||||
// Create a wrapper change detection function that calls each change detection function
|
||||
m_statep->m_tlChgFuncp = new AstCFunc(nodep->fileline(), "_change_request", scopep, "QData");
|
||||
m_statep->m_tlChgFuncp->argTypes(EmitCBaseVisitor::symClassVar());
|
||||
m_statep->m_tlChgFuncp->symProlog(true);
|
||||
m_statep->m_tlChgFuncp->declPrivate(true);
|
||||
m_statep->m_scopetopp->addActivep(m_statep->m_tlChgFuncp);
|
||||
// Each change detection function needs at least one AstChangeDet
|
||||
// to ensure that V3EmitC outputs the necessary code.
|
||||
m_statep->maybeCreateChgFuncp();
|
||||
m_statep->m_chgFuncp->addStmtsp(new AstChangeDet(nodep->fileline(), NULL, NULL, false));
|
||||
//
|
||||
|
||||
nodep->iterateChildren(*this);
|
||||
}
|
||||
virtual void visit(AstVarScope* nodep, AstNUser*) {
|
||||
|
||||
@@ -242,6 +242,10 @@ private:
|
||||
// No cleaning, or would loose pointer to enum
|
||||
nodep->iterateChildren(*this);
|
||||
}
|
||||
virtual void visit(AstParamTypeDType* nodep, AstNUser*) {
|
||||
// No cleaning, or would loose pointer to enum
|
||||
nodep->iterateChildren(*this);
|
||||
}
|
||||
|
||||
// Control flow operators
|
||||
virtual void visit(AstNodeCond* nodep, AstNUser*) {
|
||||
@@ -269,6 +273,7 @@ private:
|
||||
virtual void visit(AstCCall* nodep, AstNUser*) {
|
||||
nodep->iterateChildren(*this);
|
||||
insureCleanAndNext (nodep->argsp());
|
||||
setClean (nodep, true);
|
||||
}
|
||||
|
||||
//--------------------
|
||||
|
||||
+21
-5
@@ -1464,9 +1464,21 @@ private:
|
||||
did=true;
|
||||
}
|
||||
else if (m_selp && valuep->castInitArray()) {
|
||||
int bit = m_selp->bitConst();
|
||||
AstNode* itemp = valuep->castInitArray()->initsp();
|
||||
for (int n=0; n<bit && itemp; ++n, itemp=itemp->nextp()) {}
|
||||
AstInitArray* initarp = valuep->castInitArray();
|
||||
uint32_t bit = m_selp->bitConst();
|
||||
int pos = 0;
|
||||
AstNode* itemp = initarp->initsp();
|
||||
for (; itemp; ++pos, itemp=itemp->nextp()) {
|
||||
uint32_t index = initarp->posIndex(pos);
|
||||
if (index == bit) break;
|
||||
if (index > bit) {
|
||||
if (initarp->defaultp()) {
|
||||
itemp = initarp->defaultp();
|
||||
} else {
|
||||
initarp->v3fatalSrc("Not enough values in array initalizement");
|
||||
}
|
||||
}
|
||||
}
|
||||
if (itemp->castConst()) {
|
||||
const V3Number& num = itemp->castConst()->num();
|
||||
//UINFO(2,"constVisit "<<(void*)valuep<<" "<<num<<endl);
|
||||
@@ -2260,8 +2272,12 @@ private:
|
||||
virtual void visit(AstNode* nodep, AstNUser*) {
|
||||
// Default: Just iterate
|
||||
if (m_required) {
|
||||
nodep->v3error("Expecting expression to be constant, but can't convert a "
|
||||
<<nodep->prettyTypeName()<<" to constant.");
|
||||
if (nodep->castNodeDType() || nodep->castRange()) {
|
||||
// Ignore dtypes for parameter type pins
|
||||
} else {
|
||||
nodep->v3error("Expecting expression to be constant, but can't convert a "
|
||||
<<nodep->prettyTypeName()<<" to constant.");
|
||||
}
|
||||
} else {
|
||||
// Calculate the width of this operation
|
||||
if (m_params && !nodep->width()) {
|
||||
|
||||
+1
-1
@@ -83,10 +83,10 @@ private:
|
||||
const char* varIgnoreToggle(AstVar* nodep) {
|
||||
// Return true if this shouldn't be traced
|
||||
// See also similar rule in V3TraceDecl::varIgnoreTrace
|
||||
string prettyName = nodep->prettyName();
|
||||
if (!nodep->isToggleCoverable())
|
||||
return "Not relevant signal type";
|
||||
if (!v3Global.opt.coverageUnderscore()) {
|
||||
string prettyName = nodep->prettyName();
|
||||
if (prettyName[0] == '_')
|
||||
return "Leading underscore";
|
||||
if (prettyName.find("._") != string::npos)
|
||||
|
||||
+176
-31
@@ -25,7 +25,18 @@
|
||||
// dependencies easier to resolve.
|
||||
// NOTE: If redo this, consider using maybePointedTo()/broken() ish scheme
|
||||
// instead of needing as many visitors.
|
||||
//*************************************************************************
|
||||
//
|
||||
// The following nodes have package pointers and are cleaned up here:
|
||||
// AstRefDType, AstEnumItemRef, AstNodeVarRef, AstNodeFTask
|
||||
// These have packagep but will not exist at this stage
|
||||
// AstPackageImport, AstDot, AstPackageRef
|
||||
//
|
||||
// Note on packagep: After the V3Scope/V3LinkDotScoped stage, package links
|
||||
// are no longer used, but their presence prevents us from removing empty
|
||||
// packages. As the links as no longer used after V3Scope, we remove them
|
||||
// here after scoping to allow more dead node
|
||||
// removal.
|
||||
// *************************************************************************
|
||||
|
||||
#include "config_build.h"
|
||||
#include "verilatedos.h"
|
||||
@@ -49,7 +60,7 @@ private:
|
||||
// VISITORS
|
||||
virtual void visit(AstCell* nodep, AstNUser*) {
|
||||
nodep->iterateChildren(*this);
|
||||
nodep->modp()->user1(nodep->modp()->user1() - 1);
|
||||
nodep->modp()->user1Inc(-1);
|
||||
}
|
||||
//-----
|
||||
virtual void visit(AstNodeMath* nodep, AstNUser*) {} // Accelerate
|
||||
@@ -71,10 +82,10 @@ class DeadVisitor : public AstNVisitor {
|
||||
private:
|
||||
// NODE STATE
|
||||
// Entire Netlist:
|
||||
// AstNodeModule::user1() -> int. Count of number of cells referencing this module.
|
||||
// AstVar::user1() -> int. Count of number of references
|
||||
// AstVarScope::user1() -> int. Count of number of references
|
||||
// AstNodeDType::user1() -> int. Count of number of references
|
||||
// AstNodeModule::user1() -> int. Count of number of cells referencing this module.
|
||||
// AstVar::user1() -> int. Count of number of references
|
||||
// AstVarScope::user1() -> int. Count of number of references
|
||||
// AstNodeDType::user1() -> int. Count of number of references
|
||||
AstUser1InUse m_inuser1;
|
||||
|
||||
// TYPES
|
||||
@@ -82,11 +93,16 @@ private:
|
||||
|
||||
// STATE
|
||||
AstNodeModule* m_modp; // Current module
|
||||
vector<AstNode*> m_varEtcsp; // List of all encountered to avoid another loop through tree
|
||||
vector<AstVar*> m_varsp; // List of all encountered to avoid another loop through tree
|
||||
vector<AstNode*> m_dtypesp; // List of all encountered to avoid another loop through tree
|
||||
vector<AstVarScope*> m_vscsp; // List of all encountered to avoid another loop through tree
|
||||
vector<AstScope*> m_scopesp; // List of all encountered to avoid another loop through tree
|
||||
vector<AstCell*> m_cellsp; // List of all encountered to avoid another loop through tree
|
||||
AssignMap m_assignMap; // List of all simple assignments for each variable
|
||||
bool m_elimUserVars; // Allow removal of user's vars
|
||||
bool m_elimDTypes; // Allow removal of DTypes
|
||||
bool m_elimScopes; // Allow removal of Scopes
|
||||
bool m_elimCells; // Allow removal of Cells
|
||||
bool m_sideEffect; // Side effects discovered in assign RHS
|
||||
|
||||
// METHODS
|
||||
@@ -97,19 +113,25 @@ private:
|
||||
}
|
||||
|
||||
void checkAll(AstNode* nodep) {
|
||||
if (nodep != nodep->dtypep()) { // NodeDTypes reference themselves
|
||||
if (AstNode* subnodep = nodep->dtypep()) subnodep->user1Inc();
|
||||
if (nodep != nodep->dtypep()) { // NodeDTypes reference themselves
|
||||
if (AstNode* subnodep = nodep->dtypep()) {
|
||||
subnodep->user1Inc();
|
||||
}
|
||||
}
|
||||
if (AstNode* subnodep = nodep->getChildDTypep()) {
|
||||
subnodep->user1Inc();
|
||||
}
|
||||
if (AstNode* subnodep = nodep->getChildDTypep()) subnodep->user1Inc();
|
||||
}
|
||||
void checkDType(AstNodeDType* nodep) {
|
||||
if (!nodep->generic() // Don't remove generic types
|
||||
&& m_elimDTypes // dtypes stick around until post-widthing
|
||||
&& !nodep->castMemberDType() // Keep member names iff upper type exists
|
||||
) {
|
||||
m_varEtcsp.push_back(nodep);
|
||||
m_dtypesp.push_back(nodep);
|
||||
}
|
||||
if (AstNode* subnodep = nodep->virtRefDTypep()) {
|
||||
subnodep->user1Inc();
|
||||
}
|
||||
if (AstNode* subnodep = nodep->virtRefDTypep()) subnodep->user1Inc();
|
||||
}
|
||||
|
||||
// VISITORS
|
||||
@@ -119,11 +141,27 @@ private:
|
||||
checkAll(nodep);
|
||||
m_modp = NULL;
|
||||
}
|
||||
virtual void visit(AstCFunc* nodep, AstNUser*) {
|
||||
nodep->iterateChildren(*this);
|
||||
checkAll(nodep);
|
||||
if (nodep->scopep()) nodep->scopep()->user1Inc();
|
||||
}
|
||||
virtual void visit(AstScope* nodep, AstNUser*) {
|
||||
nodep->iterateChildren(*this);
|
||||
checkAll(nodep);
|
||||
if (nodep->aboveScopep()) nodep->aboveScopep()->user1Inc();
|
||||
|
||||
if (!nodep->isTop() && !nodep->varsp() && !nodep->blocksp() && !nodep->finalClksp()) {
|
||||
m_scopesp.push_back(nodep);
|
||||
}
|
||||
}
|
||||
virtual void visit(AstCell* nodep, AstNUser*) {
|
||||
nodep->iterateChildren(*this);
|
||||
checkAll(nodep);
|
||||
m_cellsp.push_back(nodep);
|
||||
nodep->modp()->user1Inc();
|
||||
}
|
||||
|
||||
virtual void visit(AstNodeVarRef* nodep, AstNUser*) {
|
||||
nodep->iterateChildren(*this);
|
||||
checkAll(nodep);
|
||||
@@ -135,14 +173,16 @@ private:
|
||||
nodep->varp()->user1Inc();
|
||||
}
|
||||
if (nodep->packagep()) {
|
||||
nodep->packagep()->user1Inc();
|
||||
if (m_elimCells) nodep->packagep(NULL);
|
||||
else nodep->packagep()->user1Inc();
|
||||
}
|
||||
}
|
||||
virtual void visit(AstNodeFTaskRef* nodep, AstNUser*) {
|
||||
nodep->iterateChildren(*this);
|
||||
checkAll(nodep);
|
||||
if (nodep->packagep()) {
|
||||
nodep->packagep()->user1Inc();
|
||||
if (m_elimCells) nodep->packagep(NULL);
|
||||
else nodep->packagep()->user1Inc();
|
||||
}
|
||||
}
|
||||
virtual void visit(AstRefDType* nodep, AstNUser*) {
|
||||
@@ -150,7 +190,8 @@ private:
|
||||
checkDType(nodep);
|
||||
checkAll(nodep);
|
||||
if (nodep->packagep()) {
|
||||
nodep->packagep()->user1Inc();
|
||||
if (m_elimCells) nodep->packagep(NULL);
|
||||
else nodep->packagep()->user1Inc();
|
||||
}
|
||||
}
|
||||
virtual void visit(AstNodeDType* nodep, AstNUser*) {
|
||||
@@ -162,11 +203,27 @@ private:
|
||||
nodep->iterateChildren(*this);
|
||||
checkAll(nodep);
|
||||
if (nodep->packagep()) {
|
||||
nodep->packagep()->user1Inc();
|
||||
if (m_elimCells) nodep->packagep(NULL);
|
||||
else nodep->packagep()->user1Inc();
|
||||
}
|
||||
checkAll(nodep);
|
||||
}
|
||||
virtual void visit(AstModport* nodep, AstNUser*) {
|
||||
nodep->iterateChildren(*this);
|
||||
if (m_elimCells) {
|
||||
if (!nodep->varsp()) {
|
||||
pushDeletep(nodep->unlinkFrBack()); VL_DANGLING(nodep);
|
||||
return;
|
||||
}
|
||||
}
|
||||
checkAll(nodep);
|
||||
}
|
||||
virtual void visit(AstTypedef* nodep, AstNUser*) {
|
||||
nodep->iterateChildren(*this);
|
||||
if (m_elimCells && !nodep->attrPublic()) {
|
||||
pushDeletep(nodep->unlinkFrBack()); VL_DANGLING(nodep);
|
||||
return;
|
||||
}
|
||||
checkAll(nodep);
|
||||
// Don't let packages with only public variables disappear
|
||||
// Normal modules may disappear, e.g. if they are parameterized then removed
|
||||
@@ -175,7 +232,8 @@ private:
|
||||
virtual void visit(AstVarScope* nodep, AstNUser*) {
|
||||
nodep->iterateChildren(*this);
|
||||
checkAll(nodep);
|
||||
if (mightElim(nodep->varp())) {
|
||||
if (nodep->scopep()) nodep->scopep()->user1Inc();
|
||||
if (mightElimVar(nodep->varp())) {
|
||||
m_vscsp.push_back(nodep);
|
||||
}
|
||||
}
|
||||
@@ -183,11 +241,10 @@ private:
|
||||
nodep->iterateChildren(*this);
|
||||
checkAll(nodep);
|
||||
if (nodep->isSigPublic() && m_modp && m_modp->castPackage()) m_modp->user1Inc();
|
||||
if (mightElim(nodep)) {
|
||||
m_varEtcsp.push_back(nodep);
|
||||
if (mightElimVar(nodep)) {
|
||||
m_varsp.push_back(nodep);
|
||||
}
|
||||
}
|
||||
|
||||
virtual void visit(AstNodeAssign* nodep, AstNUser*) {
|
||||
// See if simple assignments to variables may be eliminated because that variable is never used.
|
||||
// Similar code in V3Life
|
||||
@@ -199,7 +256,7 @@ private:
|
||||
if (varrefp && !m_sideEffect
|
||||
&& varrefp->varScopep()) { // For simplicity, we only remove post-scoping
|
||||
m_assignMap.insert(make_pair(varrefp->varScopep(), nodep));
|
||||
checkAll(varrefp); // Must track reference to dtype()
|
||||
checkAll(varrefp); // Must track reference to dtype()
|
||||
} else { // Track like any other statement
|
||||
nodep->lhsp()->iterateAndNext(*this);
|
||||
}
|
||||
@@ -235,13 +292,45 @@ private:
|
||||
}
|
||||
}
|
||||
}
|
||||
bool mightElim(AstVar* nodep) {
|
||||
bool mightElimVar(AstVar* nodep) {
|
||||
return (!nodep->isSigPublic() // Can't elim publics!
|
||||
&& !nodep->isIO()
|
||||
&& (nodep->isTemp()
|
||||
|| (nodep->isParam() && !nodep->isTrace())
|
||||
|| m_elimUserVars)); // Post-Trace can kill most anything
|
||||
}
|
||||
|
||||
void deadCheckScope() {
|
||||
for (bool retry=true; retry; ) {
|
||||
retry = false;
|
||||
for (vector<AstScope*>::iterator it = m_scopesp.begin(); it != m_scopesp.end();++it) {
|
||||
AstScope* scp = *it;
|
||||
if (!scp)
|
||||
continue;
|
||||
if (scp->user1() == 0) {
|
||||
UINFO(4, " Dead AstScope " << scp << endl);
|
||||
scp->aboveScopep()->user1Inc(-1);
|
||||
if (scp->dtypep()) {
|
||||
scp->dtypep()->user1Inc(-1);
|
||||
}
|
||||
scp->unlinkFrBack()->deleteTree(); VL_DANGLING(scp);
|
||||
*it = NULL;
|
||||
retry = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void deadCheckCells() {
|
||||
for (vector<AstCell*>::iterator it = m_cellsp.begin(); it!=m_cellsp.end(); ++it) {
|
||||
AstCell* cellp = *it;
|
||||
if (cellp->user1() == 0 && !cellp->modp()->stmtsp()) {
|
||||
cellp->modp()->user1Inc(-1);
|
||||
cellp->unlinkFrBack()->deleteTree(); VL_DANGLING(cellp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void deadCheckVar() {
|
||||
// Delete any unused varscopes
|
||||
for (vector<AstVarScope*>::iterator it = m_vscsp.begin(); it!=m_vscsp.end(); ++it) {
|
||||
@@ -251,34 +340,76 @@ private:
|
||||
pair <AssignMap::iterator,AssignMap::iterator> eqrange = m_assignMap.equal_range(vscp);
|
||||
for (AssignMap::iterator it = eqrange.first; it != eqrange.second; ++it) {
|
||||
AstNodeAssign* assp = it->second;
|
||||
UINFO(4," Dead assign "<<assp<<endl);
|
||||
UINFO(4," Dead assign "<<assp<<endl);
|
||||
assp->dtypep()->user1Inc(-1);
|
||||
assp->unlinkFrBack()->deleteTree(); VL_DANGLING(assp);
|
||||
}
|
||||
if (vscp->scopep()) vscp->scopep()->user1Inc(-1);
|
||||
vscp->dtypep()->user1Inc(-1);
|
||||
vscp->unlinkFrBack()->deleteTree(); VL_DANGLING(vscp);
|
||||
}
|
||||
}
|
||||
for (vector<AstNode*>::iterator it = m_varEtcsp.begin(); it!=m_varEtcsp.end(); ++it) {
|
||||
for (bool retry=true; retry; ) {
|
||||
retry = false;
|
||||
for (vector<AstVar *>::iterator it = m_varsp.begin(); it != m_varsp.end();++it) {
|
||||
AstVar* varp = *it;
|
||||
if (!varp)
|
||||
continue;
|
||||
if (varp->user1() == 0) {
|
||||
UINFO(4, " Dead " << varp << endl);
|
||||
if (varp->dtypep()) {
|
||||
varp->dtypep()->user1Inc(-1);
|
||||
}
|
||||
varp->unlinkFrBack()->deleteTree(); VL_DANGLING(varp);
|
||||
*it = NULL;
|
||||
retry = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
for (vector<AstNode*>::iterator it = m_dtypesp.begin(); it != m_dtypesp.end();++it) {
|
||||
if ((*it)->user1() == 0) {
|
||||
UINFO(4," Dead "<<(*it)<<endl);
|
||||
(*it)->unlinkFrBack()->deleteTree(); (*it)=NULL;
|
||||
AstNodeClassDType *classp;
|
||||
// It's possible that there if a reference to each individual member, but
|
||||
// not to the dtype itself. Check and don't remove the parent dtype if
|
||||
// members are still alive.
|
||||
if ((classp = (*it)->castNodeClassDType())) {
|
||||
bool cont = true;
|
||||
for (AstMemberDType *memberp = classp->membersp(); memberp; memberp = memberp->nextp()->castMemberDType()) {
|
||||
if (memberp->user1() != 0) {
|
||||
cont = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!cont)
|
||||
continue;
|
||||
}
|
||||
(*it)->unlinkFrBack()->deleteTree(); VL_DANGLING(*it);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
// CONSTRUCTORS
|
||||
DeadVisitor(AstNetlist* nodep, bool elimUserVars, bool elimDTypes) {
|
||||
DeadVisitor(AstNetlist* nodep, bool elimUserVars, bool elimDTypes, bool elimScopes, bool elimCells) {
|
||||
m_modp = NULL;
|
||||
m_elimCells = elimCells;
|
||||
m_elimUserVars = elimUserVars;
|
||||
m_elimDTypes = elimDTypes;
|
||||
m_elimScopes = elimScopes;
|
||||
m_sideEffect = false;
|
||||
// Prepare to remove some datatypes
|
||||
nodep->typeTablep()->clearCache();
|
||||
// Operate on whole netlist
|
||||
nodep->accept(*this);
|
||||
|
||||
deadCheckVar();
|
||||
// We only elimate scopes when in a flattened structure
|
||||
// Otherwise we have no easy way to know if a scope is used
|
||||
if (elimScopes) deadCheckScope();
|
||||
if (elimCells) deadCheckCells();
|
||||
// Modules after vars, because might be vars we delete inside a mod we delete
|
||||
deadCheckMod();
|
||||
|
||||
// We may have removed some datatypes, cleanup
|
||||
nodep->typeTablep()->repairCache();
|
||||
}
|
||||
@@ -290,16 +421,30 @@ public:
|
||||
|
||||
void V3Dead::deadifyModules(AstNetlist* nodep) {
|
||||
UINFO(2,__FUNCTION__<<": "<<endl);
|
||||
DeadVisitor visitor (nodep, false, false);
|
||||
DeadVisitor visitor (nodep, false, false, false, false);
|
||||
V3Global::dumpCheckGlobalTree("deadModules.tree", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 6);
|
||||
}
|
||||
|
||||
void V3Dead::deadifyDTypes(AstNetlist* nodep) {
|
||||
UINFO(2,__FUNCTION__<<": "<<endl);
|
||||
DeadVisitor visitor (nodep, false, true);
|
||||
V3Global::dumpCheckGlobalTree("deadDType.tree", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
|
||||
DeadVisitor visitor (nodep, false, true, false, false);
|
||||
V3Global::dumpCheckGlobalTree("deadDtypes.tree", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
|
||||
}
|
||||
|
||||
void V3Dead::deadifyDTypesScoped(AstNetlist* nodep) {
|
||||
UINFO(2,__FUNCTION__<<": "<<endl);
|
||||
DeadVisitor visitor (nodep, false, true, true, false);
|
||||
V3Global::dumpCheckGlobalTree("deadDtypesScoped.tree", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
|
||||
}
|
||||
|
||||
void V3Dead::deadifyAll(AstNetlist* nodep) {
|
||||
UINFO(2,__FUNCTION__<<": "<<endl);
|
||||
DeadVisitor visitor (nodep, true, true);
|
||||
DeadVisitor visitor (nodep, true, true, false, true);
|
||||
V3Global::dumpCheckGlobalTree("deadAll.tree", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
|
||||
}
|
||||
|
||||
void V3Dead::deadifyAllScoped(AstNetlist* nodep) {
|
||||
UINFO(2,__FUNCTION__<<": "<<endl);
|
||||
DeadVisitor visitor (nodep, true, true, true, true);
|
||||
V3Global::dumpCheckGlobalTree("deadAllScoped.tree", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
|
||||
}
|
||||
|
||||
@@ -33,8 +33,10 @@ public:
|
||||
static void deadifyModules(AstNetlist* nodep);
|
||||
// Modules, Data types
|
||||
static void deadifyDTypes(AstNetlist* nodep);
|
||||
static void deadifyDTypesScoped(AstNetlist* nodep);
|
||||
// Everything that's possible
|
||||
static void deadifyAll(AstNetlist* nodep);
|
||||
static void deadifyAllScoped(AstNetlist* nodep);
|
||||
};
|
||||
|
||||
#endif // Guard
|
||||
|
||||
+115
-106
@@ -113,14 +113,14 @@ public:
|
||||
}
|
||||
if (AstEnumDType* adtypep = nodep->dtypep()->skipRefToEnump()->castEnumDType()) {
|
||||
if (adtypep->width()>64) {
|
||||
puts("// enum "+nodep->name()+" // Ignored: Too wide for C++\n");
|
||||
putsDecoration("// enum "+nodep->name()+" // Ignored: Too wide for C++\n");
|
||||
} else {
|
||||
puts("enum "+nodep->name()+" {\n");
|
||||
for (AstEnumItem* itemp = adtypep->itemsp(); itemp; itemp=itemp->nextp()->castEnumItem()) {
|
||||
puts(itemp->name());
|
||||
puts(" = ");
|
||||
itemp->valuep()->iterateAndNext(*this);
|
||||
if (nodep->nextp()) puts(",");
|
||||
if (itemp->nextp()->castEnumItem()) puts(",");
|
||||
puts("\n");
|
||||
}
|
||||
puts("};\n");
|
||||
@@ -220,7 +220,7 @@ public:
|
||||
nodep->v3fatalSrc("Case statements should have been reduced out\n");
|
||||
}
|
||||
virtual void visit(AstComment* nodep, AstNUser*) {
|
||||
puts((string)"// "+nodep->name()+" at "+nodep->fileline()->ascii()+"\n");
|
||||
putsDecoration((string)"// "+nodep->name()+" at "+nodep->fileline()->ascii()+"\n");
|
||||
nodep->iterateChildren(*this);
|
||||
}
|
||||
virtual void visit(AstCoverDecl* nodep, AstNUser*) {
|
||||
@@ -499,13 +499,13 @@ public:
|
||||
nodep->bodysp()->iterateAndNext(*this);
|
||||
}
|
||||
virtual void visit(AstUCStmt* nodep, AstNUser*) {
|
||||
puts("// $c statement at "+nodep->fileline()->ascii()+"\n");
|
||||
putsDecoration("// $c statement at "+nodep->fileline()->ascii()+"\n");
|
||||
nodep->bodysp()->iterateAndNext(*this);
|
||||
puts("\n");
|
||||
}
|
||||
virtual void visit(AstUCFunc* nodep, AstNUser*) {
|
||||
puts("\n");
|
||||
puts("// $c function at "+nodep->fileline()->ascii()+"\n");
|
||||
putsDecoration("// $c function at "+nodep->fileline()->ascii()+"\n");
|
||||
nodep->bodysp()->iterateAndNext(*this);
|
||||
puts("\n");
|
||||
}
|
||||
@@ -844,7 +844,7 @@ class EmitCImp : EmitCStmts {
|
||||
|
||||
if (nodep->symProlog()) puts(EmitCBaseVisitor::symTopAssign()+"\n");
|
||||
|
||||
if (nodep->initsp()) puts("// Variables\n");
|
||||
if (nodep->initsp()) putsDecoration("// Variables\n");
|
||||
ofp()->putAlign(V3OutFile::AL_AUTO, 4);
|
||||
for (AstNode* subnodep=nodep->argsp(); subnodep; subnodep = subnodep->nextp()) {
|
||||
if (AstVar* varp=subnodep->castVar()) {
|
||||
@@ -858,11 +858,11 @@ class EmitCImp : EmitCStmts {
|
||||
|
||||
nodep->initsp()->iterateAndNext(*this);
|
||||
|
||||
if (nodep->stmtsp()) puts("// Body\n");
|
||||
if (nodep->stmtsp()) putsDecoration("// Body\n");
|
||||
nodep->stmtsp()->iterateAndNext(*this);
|
||||
if (!m_blkChangeDetVec.empty()) emitChangeDet();
|
||||
|
||||
if (nodep->finalsp()) puts("// Final\n");
|
||||
if (nodep->finalsp()) putsDecoration("// Final\n");
|
||||
nodep->finalsp()->iterateAndNext(*this);
|
||||
//
|
||||
|
||||
@@ -873,7 +873,7 @@ class EmitCImp : EmitCStmts {
|
||||
}
|
||||
|
||||
void emitChangeDet() {
|
||||
puts("// Change detection\n");
|
||||
putsDecoration("// Change detection\n");
|
||||
puts("QData __req = false; // Logically a bool\n"); // But not because it results in faster code
|
||||
bool gotOne = false;
|
||||
for (vector<AstChangeDet*>::iterator it = m_blkChangeDetVec.begin();
|
||||
@@ -912,12 +912,17 @@ class EmitCImp : EmitCStmts {
|
||||
m_blkChangeDetVec.push_back(nodep);
|
||||
}
|
||||
|
||||
virtual void visit(AstCReset* nodep, AstNUser*) {
|
||||
AstVar* varp = nodep->varrefp()->varp();
|
||||
emitVarReset(varp);
|
||||
}
|
||||
|
||||
//---------------------------------------
|
||||
// ACCESSORS
|
||||
|
||||
// METHODS
|
||||
// Low level
|
||||
void emitVarResets(AstNodeModule* modp);
|
||||
void emitVarReset(AstVar* modp);
|
||||
void emitCellCtors(AstNodeModule* modp);
|
||||
void emitSensitives();
|
||||
// Medium level
|
||||
@@ -1382,97 +1387,94 @@ void EmitCStmts::displayNode(AstNode* nodep, AstScopeName* scopenamep,
|
||||
//######################################################################
|
||||
// Internal EmitC
|
||||
|
||||
void EmitCImp::emitVarResets(AstNodeModule* modp) {
|
||||
puts("// Reset internal values\n");
|
||||
if (modp->isTop()) {
|
||||
if (v3Global.opt.inhibitSim()) puts("__Vm_inhibitSim = false;\n");
|
||||
puts("\n");
|
||||
void EmitCImp::emitVarReset(AstVar* varp) {
|
||||
if (varp->isIO() && m_modp->isTop() && optSystemC()) {
|
||||
// System C top I/O doesn't need loading, as the lower level subinst code does it.}
|
||||
} else if (varp->isParam()) {
|
||||
if (!varp->valuep()) varp->v3fatalSrc("No init for a param?");
|
||||
// If a simple CONST value we initialize it using an enum
|
||||
// If an ARRAYINIT we initialize it using an initial block similar to a signal
|
||||
//puts("// parameter "+varp->name()+" = "+varp->valuep()->name()+"\n");
|
||||
}
|
||||
|
||||
puts("// Reset structure values\n");
|
||||
for (AstNode* nodep=modp->stmtsp(); nodep; nodep = nodep->nextp()) {
|
||||
if (AstVar* varp = nodep->castVar()) {
|
||||
if (varp->isIO() && modp->isTop() && optSystemC()) {
|
||||
// System C top I/O doesn't need loading, as the lower level subinst code does it.
|
||||
else if (AstInitArray* initarp = varp->valuep()->castInitArray()) {
|
||||
if (AstUnpackArrayDType* arrayp = varp->dtypeSkipRefp()->castUnpackArrayDType()) {
|
||||
if (initarp->defaultp()) {
|
||||
// MSVC++ pre V7 doesn't support 'for (int ...)', so declare in sep block
|
||||
puts("{ int __Vi=0;");
|
||||
puts(" for (; __Vi<"+cvtToStr(arrayp->elementsConst()));
|
||||
puts("; ++__Vi) {\n");
|
||||
emitSetVarConstant(varp->name()+"[__Vi]", initarp->defaultp()->castConst());
|
||||
puts("}}\n");
|
||||
}
|
||||
else if (varp->isParam()) {
|
||||
if (!varp->valuep()) nodep->v3fatalSrc("No init for a param?");
|
||||
// If a simple CONST value we initialize it using an enum
|
||||
// If an ARRAYINIT we initialize it using an initial block similar to a signal
|
||||
//puts("// parameter "+varp->name()+" = "+varp->valuep()->name()+"\n");
|
||||
}
|
||||
else if (AstInitArray* initarp = varp->valuep()->castInitArray()) {
|
||||
AstConst* constsp = initarp->initsp()->castConst();
|
||||
if (AstUnpackArrayDType* arrayp = varp->dtypeSkipRefp()->castUnpackArrayDType()) {
|
||||
for (int i=0; i<arrayp->elementsConst(); i++) {
|
||||
if (!constsp) initarp->v3fatalSrc("Not enough values in array initalizement");
|
||||
emitSetVarConstant(varp->name()+"["+cvtToStr(i)+"]", constsp);
|
||||
constsp = constsp->nextp()->castConst();
|
||||
}
|
||||
} else {
|
||||
varp->v3fatalSrc("InitArray under non-arrayed var");
|
||||
}
|
||||
}
|
||||
else if (varp->basicp() && varp->basicp()->keyword() == AstBasicDTypeKwd::STRING) {
|
||||
// Constructor deals with it
|
||||
}
|
||||
else {
|
||||
int vects = 0;
|
||||
// This isn't very robust and may need cleanup for other data types
|
||||
for (AstUnpackArrayDType* arrayp=varp->dtypeSkipRefp()->castUnpackArrayDType(); arrayp;
|
||||
arrayp = arrayp->subDTypep()->skipRefp()->castUnpackArrayDType()) {
|
||||
int vecnum = vects++;
|
||||
if (arrayp->msb() < arrayp->lsb()) varp->v3fatalSrc("Should have swapped msb & lsb earlier.");
|
||||
string ivar = string("__Vi")+cvtToStr(vecnum);
|
||||
// MSVC++ pre V7 doesn't support 'for (int ...)', so declare in sep block
|
||||
puts("{ int __Vi"+cvtToStr(vecnum)+"="+cvtToStr(0)+";");
|
||||
puts(" for (; "+ivar+"<"+cvtToStr(arrayp->elementsConst()));
|
||||
puts("; ++"+ivar+") {\n");
|
||||
}
|
||||
bool zeroit = (varp->attrFileDescr() // Zero it out, so we don't core dump if never call $fopen
|
||||
|| (varp->basicp() && varp->basicp()->isZeroInit())
|
||||
|| (varp->name().size()>=1 && varp->name()[0]=='_' && v3Global.opt.underlineZero()));
|
||||
if (varp->isWide()) {
|
||||
// DOCUMENT: We randomize everything. If the user wants a _var to be zero,
|
||||
// there should be a initial statement. (Different from verilator2.)
|
||||
if (zeroit) puts("VL_ZERO_RESET_W(");
|
||||
else puts("VL_RAND_RESET_W(");
|
||||
puts(cvtToStr(varp->widthMin()));
|
||||
puts(",");
|
||||
puts(varp->name());
|
||||
for (int v=0; v<vects; ++v) puts( "[__Vi"+cvtToStr(v)+"]");
|
||||
puts(");\n");
|
||||
} else {
|
||||
puts(varp->name());
|
||||
for (int v=0; v<vects; ++v) puts( "[__Vi"+cvtToStr(v)+"]");
|
||||
// If --x-initial-edge is set, we want to force an initial
|
||||
// edge on uninitialized clocks (from 'X' to whatever the
|
||||
// first value is). Since the class is instantiated before
|
||||
// initial blocks are evaluated, this should not clash
|
||||
// with any initial block settings.
|
||||
if (zeroit || (v3Global.opt.xInitialEdge() && varp->isUsedClock())) {
|
||||
puts(" = 0;\n");
|
||||
} else if (v3Global.opt.xInitialEdge()
|
||||
&& (0 == varp->name().find("__Vclklast__"))) {
|
||||
puts(" = 1;\n");
|
||||
} else {
|
||||
puts(" = VL_RAND_RESET_");
|
||||
emitIQW(varp);
|
||||
puts("(");
|
||||
puts(cvtToStr(varp->widthMin()));
|
||||
puts(");\n");
|
||||
}
|
||||
}
|
||||
for (int v=0; v<vects; ++v) puts( "}}\n");
|
||||
int pos = 0;
|
||||
for (AstNode* itemp = initarp->initsp(); itemp; ++pos, itemp=itemp->nextp()) {
|
||||
int index = initarp->posIndex(pos);
|
||||
if (!initarp->defaultp() && index!=pos) initarp->v3fatalSrc("Not enough values in array initalizement");
|
||||
emitSetVarConstant(varp->name()+"["+cvtToStr(index)+"]", itemp->castConst());
|
||||
}
|
||||
} else {
|
||||
varp->v3fatalSrc("InitArray under non-arrayed var");
|
||||
}
|
||||
}
|
||||
else if (varp->basicp() && varp->basicp()->keyword() == AstBasicDTypeKwd::STRING) {
|
||||
// Constructor deals with it
|
||||
}
|
||||
else {
|
||||
int vects = 0;
|
||||
// This isn't very robust and may need cleanup for other data types
|
||||
for (AstUnpackArrayDType* arrayp=varp->dtypeSkipRefp()->castUnpackArrayDType(); arrayp;
|
||||
arrayp = arrayp->subDTypep()->skipRefp()->castUnpackArrayDType()) {
|
||||
int vecnum = vects++;
|
||||
if (arrayp->msb() < arrayp->lsb()) varp->v3fatalSrc("Should have swapped msb & lsb earlier.");
|
||||
string ivar = string("__Vi")+cvtToStr(vecnum);
|
||||
// MSVC++ pre V7 doesn't support 'for (int ...)', so declare in sep block
|
||||
puts("{ int __Vi"+cvtToStr(vecnum)+"="+cvtToStr(0)+";");
|
||||
puts(" for (; "+ivar+"<"+cvtToStr(arrayp->elementsConst()));
|
||||
puts("; ++"+ivar+") {\n");
|
||||
}
|
||||
bool zeroit = (varp->attrFileDescr() // Zero it out, so we don't core dump if never call $fopen
|
||||
|| (varp->basicp() && varp->basicp()->isZeroInit())
|
||||
|| (varp->name().size()>=1 && varp->name()[0]=='_' && v3Global.opt.underlineZero()));
|
||||
if (varp->isWide()) {
|
||||
// DOCUMENT: We randomize everything. If the user wants a _var to be zero,
|
||||
// there should be a initial statement. (Different from verilator2.)
|
||||
if (zeroit) puts("VL_ZERO_RESET_W(");
|
||||
else puts("VL_RAND_RESET_W(");
|
||||
puts(cvtToStr(varp->widthMin()));
|
||||
puts(",");
|
||||
puts(varp->name());
|
||||
for (int v=0; v<vects; ++v) puts( "[__Vi"+cvtToStr(v)+"]");
|
||||
puts(");\n");
|
||||
} else {
|
||||
puts(varp->name());
|
||||
for (int v=0; v<vects; ++v) puts( "[__Vi"+cvtToStr(v)+"]");
|
||||
// If --x-initial-edge is set, we want to force an initial
|
||||
// edge on uninitialized clocks (from 'X' to whatever the
|
||||
// first value is). Since the class is instantiated before
|
||||
// initial blocks are evaluated, this should not clash
|
||||
// with any initial block settings.
|
||||
if (zeroit || (v3Global.opt.xInitialEdge() && varp->isUsedClock())) {
|
||||
puts(" = 0;\n");
|
||||
} else if (v3Global.opt.xInitialEdge()
|
||||
&& (0 == varp->name().find("__Vclklast__"))) {
|
||||
puts(" = 1;\n");
|
||||
} else {
|
||||
puts(" = VL_RAND_RESET_");
|
||||
emitIQW(varp);
|
||||
puts("(");
|
||||
puts(cvtToStr(varp->widthMin()));
|
||||
puts(");\n");
|
||||
}
|
||||
}
|
||||
for (int v=0; v<vects; ++v) puts( "}}\n");
|
||||
}
|
||||
splitSizeInc(1);
|
||||
}
|
||||
|
||||
void EmitCImp::emitCoverageDecl(AstNodeModule* modp) {
|
||||
if (v3Global.opt.coverage()) {
|
||||
ofp()->putsPrivate(true);
|
||||
puts("// Coverage\n");
|
||||
putsDecoration("// Coverage\n");
|
||||
puts("void __vlCoverInsert(uint32_t* countp, bool enable, const char* filenamep, int lineno, int column,\n");
|
||||
puts( "const char* hierp, const char* pagep, const char* commentp);\n");
|
||||
}
|
||||
@@ -1489,10 +1491,16 @@ void EmitCImp::emitCtorImp(AstNodeModule* modp) {
|
||||
}
|
||||
emitVarCtors();
|
||||
puts(" {\n");
|
||||
|
||||
emitCellCtors(modp);
|
||||
emitSensitives();
|
||||
emitVarResets(modp);
|
||||
|
||||
putsDecoration("// Reset internal values\n");
|
||||
if (modp->isTop()) {
|
||||
if (v3Global.opt.inhibitSim()) puts("__Vm_inhibitSim = false;\n");
|
||||
puts("\n");
|
||||
}
|
||||
putsDecoration("// Reset structure values\n");
|
||||
puts("_ctor_var_reset();\n");
|
||||
emitTextSection(AstType::atSCCTOR);
|
||||
if (optSystemPerl()) puts("SP_AUTO_CTOR;\n");
|
||||
puts("}\n");
|
||||
@@ -1507,7 +1515,7 @@ void EmitCImp::emitConfigureImp(AstNodeModule* modp) {
|
||||
if (nodep->castCoverDecl()) {
|
||||
if (first) {
|
||||
first = false;
|
||||
puts("// Coverage Declarations\n");
|
||||
putsDecoration("// Coverage Declarations\n");
|
||||
}
|
||||
nodep->accept(*this);
|
||||
splitSizeInc(nodep);
|
||||
@@ -1673,7 +1681,7 @@ void EmitCImp::emitSensitives() {
|
||||
// Create sensitivity list for when to evaluate the model.
|
||||
// If C++ code, the user must call this routine themself.
|
||||
if (m_modp->isTop() && optSystemC()) {
|
||||
puts("// Sensitivities on all clocks and combo inputs\n");
|
||||
putsDecoration("// Sensitivities on all clocks and combo inputs\n");
|
||||
puts("SC_METHOD(eval);\n");
|
||||
for (AstNode* nodep=m_modp->stmtsp(); nodep; nodep = nodep->nextp()) {
|
||||
if (AstVar* varp = nodep->castVar()) {
|
||||
@@ -1705,12 +1713,12 @@ void EmitCImp::emitWrapEval(AstNodeModule* modp) {
|
||||
puts("\nvoid "+modClassName(modp)+"::eval() {\n");
|
||||
puts(EmitCBaseVisitor::symClassVar()+" = this->__VlSymsp; // Setup global symbol table\n");
|
||||
puts(EmitCBaseVisitor::symTopAssign()+"\n");
|
||||
puts("// Initialize\n");
|
||||
putsDecoration("// Initialize\n");
|
||||
puts("if (VL_UNLIKELY(!vlSymsp->__Vm_didInit)) _eval_initial_loop(vlSymsp);\n");
|
||||
if (v3Global.opt.inhibitSim()) {
|
||||
puts("if (VL_UNLIKELY(__Vm_inhibitSim)) return;\n");
|
||||
}
|
||||
puts("// Evaluate till stable\n");
|
||||
putsDecoration("// Evaluate till stable\n");
|
||||
puts("VL_DEBUG_IF(VL_PRINTF(\"\\n----TOP Evaluate "+modClassName(modp)+"::eval\\n\"); );\n");
|
||||
puts("int __VclockLoop = 0;\n");
|
||||
puts("QData __Vchange=1;\n");
|
||||
@@ -1879,7 +1887,7 @@ void EmitCImp::emitInt(AstNodeModule* modp) {
|
||||
if (optSystemPerl()) {
|
||||
puts("/*AUTOSUBCELLS*/\n\n");
|
||||
} else {
|
||||
puts("// CELLS\n");
|
||||
putsDecoration("// CELLS\n");
|
||||
if (modp->isTop()) puts("// Public to allow access to /*verilator_public*/ items;\n");
|
||||
if (modp->isTop()) puts("// otherwise the application code can consider these internals.\n");
|
||||
for (AstNode* nodep=modp->stmtsp(); nodep; nodep = nodep->nextp()) {
|
||||
@@ -1931,9 +1939,9 @@ void EmitCImp::emitInt(AstNodeModule* modp) {
|
||||
// These should be static const values, however microsloth VC++ doesn't
|
||||
// support them. They also cause problems with GDB under GCC2.95.
|
||||
if (varp->isWide()) { // Unsupported for output
|
||||
puts("// enum WData "+varp->name()+" //wide");
|
||||
putsDecoration("// enum WData "+varp->name()+" //wide");
|
||||
} else if (!varp->valuep()->castConst()) { // Unsupported for output
|
||||
//puts("// enum ..... "+varp->name()+" //not simple value, see variable above instead");
|
||||
//putsDecoration("// enum ..... "+varp->name()+" //not simple value, see variable above instead");
|
||||
} else {
|
||||
puts("enum ");
|
||||
puts(varp->isQuad()?"_QData":"_IData");
|
||||
@@ -2014,6 +2022,7 @@ void EmitCImp::emitInt(AstNodeModule* modp) {
|
||||
puts("static void traceChg ("+v3Global.opt.traceClassBase()+"* vcdp, void* userthis, uint32_t code);\n");
|
||||
}
|
||||
if (v3Global.opt.savable()) {
|
||||
ofp()->putsPrivate(false); // public:
|
||||
puts("void __Vserialize(VerilatedSerialize& os);\n");
|
||||
puts("void __Vdeserialize(VerilatedDeserialize& os);\n");
|
||||
puts("\n");
|
||||
@@ -2213,7 +2222,7 @@ class EmitCTrace : EmitCStmts {
|
||||
|
||||
puts("void "+topClassName()+"::traceInit("
|
||||
+v3Global.opt.traceClassBase()+"* vcdp, void* userthis, uint32_t code) {\n");
|
||||
puts("// Callback from vcd->open()\n");
|
||||
putsDecoration("// Callback from vcd->open()\n");
|
||||
puts(topClassName()+"* t=("+topClassName()+"*)userthis;\n");
|
||||
puts(EmitCBaseVisitor::symClassVar()+" = t->__VlSymsp; // Setup global symbol table\n");
|
||||
puts("if (!Verilated::calcUnusedSigs()) vl_fatal(__FILE__,__LINE__,__FILE__,\"Turning on wave traces requires Verilated::traceEverOn(true) call before time 0.\");\n");
|
||||
@@ -2226,7 +2235,7 @@ class EmitCTrace : EmitCStmts {
|
||||
|
||||
puts("void "+topClassName()+"::traceFull("
|
||||
+v3Global.opt.traceClassBase()+"* vcdp, void* userthis, uint32_t code) {\n");
|
||||
puts("// Callback from vcd->dump()\n");
|
||||
putsDecoration("// Callback from vcd->dump()\n");
|
||||
puts(topClassName()+"* t=("+topClassName()+"*)userthis;\n");
|
||||
puts(EmitCBaseVisitor::symClassVar()+" = t->__VlSymsp; // Setup global symbol table\n");
|
||||
puts("t->traceFullThis (vlSymsp, vcdp, code);\n");
|
||||
@@ -2241,7 +2250,7 @@ class EmitCTrace : EmitCStmts {
|
||||
|
||||
puts("void "+topClassName()+"::traceChg("
|
||||
+v3Global.opt.traceClassBase()+"* vcdp, void* userthis, uint32_t code) {\n");
|
||||
puts("// Callback from vcd->dump()\n");
|
||||
putsDecoration("// Callback from vcd->dump()\n");
|
||||
puts(topClassName()+"* t=("+topClassName()+"*)userthis;\n");
|
||||
puts(EmitCBaseVisitor::symClassVar()+" = t->__VlSymsp; // Setup global symbol table\n");
|
||||
puts("if (vlSymsp->getClearActivity()) {\n");
|
||||
@@ -2395,16 +2404,16 @@ class EmitCTrace : EmitCStmts {
|
||||
} else if (nodep->funcType() == AstCFuncType::TRACE_CHANGE_SUB) {
|
||||
} else nodep->v3fatalSrc("Bad Case");
|
||||
|
||||
if (nodep->initsp()) puts("// Variables\n");
|
||||
if (nodep->initsp()) putsDecoration("// Variables\n");
|
||||
emitVarList(nodep->initsp(), EVL_ALL, "");
|
||||
nodep->initsp()->iterateAndNext(*this);
|
||||
ofp()->putAlign(V3OutFile::AL_AUTO, 4);
|
||||
|
||||
puts("// Body\n");
|
||||
putsDecoration("// Body\n");
|
||||
puts("{\n");
|
||||
nodep->stmtsp()->iterateAndNext(*this);
|
||||
puts("}\n");
|
||||
if (nodep->finalsp()) puts("// Final\n");
|
||||
if (nodep->finalsp()) putsDecoration("// Final\n");
|
||||
nodep->finalsp()->iterateAndNext(*this);
|
||||
puts("}\n");
|
||||
}
|
||||
|
||||
@@ -43,6 +43,7 @@ public:
|
||||
V3OutCFile* ofp() const { return m_ofp; }
|
||||
void puts(const string& str) { ofp()->puts(str); }
|
||||
void putbs(const string& str) { ofp()->putbs(str); }
|
||||
void putsDecoration(const string& str) { if (v3Global.opt.decoration()) puts(str); }
|
||||
void putsQuoted(const string& str) { ofp()->putsQuoted(str); }
|
||||
bool optSystemC() { return v3Global.opt.systemC(); }
|
||||
bool optSystemPerl() { return v3Global.opt.systemPerl(); }
|
||||
|
||||
+7
-3
@@ -448,9 +448,13 @@ class EmitVBaseVisitor : public EmitCBaseVisitor {
|
||||
}
|
||||
virtual void visit(AstInitArray* nodep, AstNUser*) {
|
||||
putfs(nodep,"`{");
|
||||
for (AstNode* subp = nodep->initsp(); subp; subp=subp->nextp()) {
|
||||
subp->accept(*this);
|
||||
if (subp->nextp()) putbs(",");
|
||||
int pos = 0;
|
||||
for (AstNode* itemp = nodep->initsp(); itemp; ++pos, itemp=itemp->nextp()) {
|
||||
int index = nodep->posIndex(pos);
|
||||
puts(cvtToStr(index));
|
||||
puts(":");
|
||||
itemp->accept(*this);
|
||||
if (itemp->nextp()) putbs(",");
|
||||
}
|
||||
puts("}");
|
||||
}
|
||||
|
||||
+8
-2
@@ -551,10 +551,12 @@ bool V3InFilter::readWholefile(const string& filename, V3InFilter::StrList& outl
|
||||
// V3OutFormatter: A class for printing to a file, with automatic indentation of C++ code.
|
||||
|
||||
V3OutFormatter::V3OutFormatter(const string& filename, V3OutFormatter::Language lang)
|
||||
: m_filename(filename), m_lang(lang), m_blockIndent(4)
|
||||
: m_filename(filename), m_lang(lang)
|
||||
, m_lineno(1), m_column(0)
|
||||
, m_nobreak(false), m_prependIndent(true), m_indentLevel(0)
|
||||
, m_declSAlign(0), m_declNSAlign(0), m_declPadNum(0) {
|
||||
m_blockIndent = v3Global.opt.decoration() ? 4 : 1;
|
||||
m_commaWidth = v3Global.opt.decoration() ? 50 : 150;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
@@ -682,7 +684,11 @@ void V3OutFormatter::puts (const char *strg) {
|
||||
break;
|
||||
case '(':
|
||||
indentInc();
|
||||
m_parenVec.push(m_column);
|
||||
if (v3Global.opt.decoration()) {
|
||||
m_parenVec.push(m_column); // Line up continuation with open paren, plus one indent
|
||||
} else {
|
||||
m_parenVec.push(m_indentLevel*m_blockIndent); // Line up continuation with block+1
|
||||
}
|
||||
break;
|
||||
case ')':
|
||||
if (!m_parenVec.empty()) m_parenVec.pop();
|
||||
|
||||
+2
-2
@@ -97,7 +97,6 @@ public:
|
||||
class V3OutFormatter {
|
||||
// TYPES
|
||||
enum MiscConsts {
|
||||
WIDTH = 50, // Width after which to break at ,'s
|
||||
MAXSPACE = 80}; // After this indent, stop indenting more
|
||||
public:
|
||||
enum AlignClass {
|
||||
@@ -115,6 +114,7 @@ private:
|
||||
string m_filename;
|
||||
Language m_lang; // Indenting Verilog code
|
||||
int m_blockIndent; // Characters per block indent
|
||||
int m_commaWidth; // Width after which to break at ,'s
|
||||
int m_lineno;
|
||||
int m_column;
|
||||
int m_nobreak; // Basic operator or begin paren, don't break next
|
||||
@@ -147,7 +147,7 @@ public:
|
||||
void putAlign(bool isstatic/*AlignClass*/, int align, int size=0/*=align*/, const string& prefix=""); // Declare a variable, with natural alignment
|
||||
void putbs(const char* strg) { putBreakExpr(); puts(strg); }
|
||||
void putbs(const string& strg) { putBreakExpr(); puts(strg); }
|
||||
bool exceededWidth() const { return m_column > WIDTH; }
|
||||
bool exceededWidth() const { return m_column > m_commaWidth; }
|
||||
bool tokenStart(const char* cp, const char* cmp);
|
||||
bool tokenEnd(const char* cp);
|
||||
void indentInc() { m_indentLevel += m_blockIndent; }
|
||||
|
||||
@@ -90,6 +90,7 @@ private:
|
||||
// Default: Just iterate
|
||||
virtual void visit(AstVar*, AstNUser*) {}
|
||||
virtual void visit(AstTypedef*, AstNUser*) {}
|
||||
virtual void visit(AstParamTypeDType*, AstNUser*) {}
|
||||
virtual void visit(AstNode* nodep, AstNUser*) {
|
||||
nodeHashIterate(nodep);
|
||||
}
|
||||
|
||||
+90
-12
@@ -77,6 +77,7 @@
|
||||
#include "V3SymTable.h"
|
||||
#include "V3Graph.h"
|
||||
#include "V3Ast.h"
|
||||
#include "V3ParseImp.h"
|
||||
|
||||
//######################################################################
|
||||
// LinkDot state, as a visitor of each AstNode
|
||||
@@ -194,6 +195,7 @@ public:
|
||||
else if (nodep->castFunc()) return "function";
|
||||
else if (nodep->castBegin()) return "block";
|
||||
else if (nodep->castIface()) return "interface";
|
||||
else if (nodep->castParamTypeDType()) return "parameter type";
|
||||
else return nodep->prettyTypeName();
|
||||
}
|
||||
|
||||
@@ -585,6 +587,42 @@ class LinkDotFindVisitor : public AstNVisitor {
|
||||
// METHODS
|
||||
int debug() { return LinkDotState::debug(); }
|
||||
|
||||
virtual AstConst* parseParamLiteral(FileLine* fl, string literal) {
|
||||
bool success = false;
|
||||
if (literal[0] == '"') {
|
||||
// This is a string
|
||||
string v = literal.substr(1, literal.find('"', 1) - 1);
|
||||
V3Number n(V3Number::VerilogStringLiteral(), fl, v);
|
||||
return new AstConst(fl,n);
|
||||
} else if ((literal.find(".") != string::npos)
|
||||
|| (literal.find("e") != string::npos)) {
|
||||
// This may be a real
|
||||
double v = V3ParseImp::parseDouble(literal.c_str(), literal.length(), &success);
|
||||
if (success) {
|
||||
return new AstConst(fl, AstConst::RealDouble(), v);
|
||||
}
|
||||
}
|
||||
if (!success) {
|
||||
// This is either an integer or an error
|
||||
// We first try to convert it as C literal. If strtol returns
|
||||
// 0 this is either an error or 0 was parsed. But in any case
|
||||
// we will try to parse it as a verilog literal, hence having
|
||||
// the false negative for 0 is okay. If anything remains in
|
||||
// the string after the number, this is invalid C and we try
|
||||
// the Verilog literal parser.
|
||||
char* endp;
|
||||
int v = strtol(literal.c_str(), &endp, 0);
|
||||
if ((v != 0) && (endp[0] == 0)) { // C literal
|
||||
V3Number n(fl, 32, v);
|
||||
return new AstConst(fl, n);
|
||||
} else { // Try a Verilog literal (fatals if not)
|
||||
V3Number n(fl, literal.c_str());
|
||||
return new AstConst(fl, n);
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// VISITs
|
||||
virtual void visit(AstNetlist* nodep, AstNUser*) {
|
||||
// Process $unit or other packages
|
||||
@@ -872,6 +910,24 @@ class LinkDotFindVisitor : public AstNVisitor {
|
||||
}
|
||||
}
|
||||
if (ins) {
|
||||
if (m_statep->forPrimary() && nodep->isGParam()
|
||||
&& (m_statep->rootEntp()->nodep() == m_modSymp->parentp()->nodep())) {
|
||||
// This is the toplevel module. Check for command line overwrites of parameters
|
||||
// We first search if the parameter is overwritten and then replace it with a
|
||||
// new value. It will keep the same FileLine information.
|
||||
if (v3Global.opt.hasParameter(nodep->name())) {
|
||||
AstVar* newp = new AstVar(nodep->fileline(), AstVarType(AstVarType::GPARAM),
|
||||
nodep->name(), nodep);
|
||||
string svalue = v3Global.opt.parameter(nodep->name());
|
||||
if (AstNode* valuep = parseParamLiteral(nodep->fileline(), svalue)) {
|
||||
newp->valuep(valuep);
|
||||
UINFO(9," replace parameter "<<nodep<<endl);
|
||||
UINFO(9," with "<<newp<<endl);
|
||||
nodep->replaceWith(newp); pushDeletep(nodep); VL_DANGLING(nodep);
|
||||
nodep = newp;
|
||||
}
|
||||
}
|
||||
}
|
||||
VSymEnt* insp = m_statep->insertSym(m_curSymp, nodep->name(), nodep, m_packagep);
|
||||
if (m_statep->forPrimary() && nodep->isGParam()) {
|
||||
m_paramNum++;
|
||||
@@ -893,6 +949,11 @@ class LinkDotFindVisitor : public AstNVisitor {
|
||||
nodep->iterateChildren(*this);
|
||||
m_statep->insertSym(m_curSymp, nodep->name(), nodep, m_packagep);
|
||||
}
|
||||
virtual void visit(AstParamTypeDType* nodep, AstNUser*) {
|
||||
if (!m_curSymp) nodep->v3fatalSrc("Parameter type not under module??\n");
|
||||
nodep->iterateChildren(*this);
|
||||
m_statep->insertSym(m_curSymp, nodep->name(), nodep, m_packagep);
|
||||
}
|
||||
virtual void visit(AstCFunc* nodep, AstNUser*) {
|
||||
// For dotted resolution, ignore all AstVars under functions, otherwise shouldn't exist
|
||||
if (m_statep->forScopeCreation()) nodep->v3fatalSrc("No CFuncs expected in tree yet");
|
||||
@@ -1440,6 +1501,15 @@ private:
|
||||
m_modp->addStmtp(varp);
|
||||
return varp;
|
||||
}
|
||||
void markAndCheckPinDup(AstNode* nodep, AstNode* refp, const char* whatp) {
|
||||
if (refp->user5p() && refp->user5p()->castNode()!=nodep) {
|
||||
nodep->v3error("Duplicate "<<whatp<<" connection: "<<nodep->prettyName()<<endl
|
||||
<<refp->user5p()->castNode()->warnMore()
|
||||
<<"... Location of original "<<whatp<<" connection");
|
||||
} else {
|
||||
refp->user5p(nodep);
|
||||
}
|
||||
}
|
||||
|
||||
// VISITs
|
||||
virtual void visit(AstNetlist* nodep, AstNUser* vup) {
|
||||
@@ -1513,27 +1583,30 @@ private:
|
||||
if (!nodep->modVarp()) {
|
||||
if (!m_pinSymp) nodep->v3fatalSrc("Pin not under cell?\n");
|
||||
VSymEnt* foundp = m_pinSymp->findIdFlat(nodep->name());
|
||||
AstVar* refp = foundp ? foundp->nodep()->castVar() : NULL;
|
||||
const char* whatp = nodep->param() ? "parameter pin" : "pin";
|
||||
if (!refp) {
|
||||
if (!foundp) {
|
||||
if (nodep->name() == "__paramNumber1" && m_cellp->modp()->castPrimitive()) {
|
||||
// Primitive parameter is really a delay we can just ignore
|
||||
nodep->unlinkFrBack()->deleteTree(); VL_DANGLING(nodep);
|
||||
return;
|
||||
}
|
||||
nodep->v3error(ucfirst(whatp)<<" not found: "<<nodep->prettyName());
|
||||
} else if (!refp->isIO() && !refp->isParam() && !refp->isIfaceRef()) {
|
||||
nodep->v3error(ucfirst(whatp)<<" is not an in/out/inout/param/interface: "<<nodep->prettyName());
|
||||
} else {
|
||||
nodep->modVarp(refp);
|
||||
if (refp->user5p() && refp->user5p()->castNode()!=nodep) {
|
||||
nodep->v3error("Duplicate "<<whatp<<" connection: "<<nodep->prettyName()<<endl
|
||||
<<refp->user5p()->castNode()->warnMore()
|
||||
<<"... Location of original "<<whatp<<" connection");
|
||||
}
|
||||
else if (AstVar* refp = foundp->nodep()->castVar()) {
|
||||
if (!refp->isIO() && !refp->isParam() && !refp->isIfaceRef()) {
|
||||
nodep->v3error(ucfirst(whatp)<<" is not an in/out/inout/param/interface: "<<nodep->prettyName());
|
||||
} else {
|
||||
refp->user5p(nodep);
|
||||
nodep->modVarp(refp);
|
||||
markAndCheckPinDup(nodep, refp, whatp);
|
||||
}
|
||||
}
|
||||
else if (AstParamTypeDType* refp = foundp->nodep()->castParamTypeDType()) {
|
||||
nodep->modPTypep(refp);
|
||||
markAndCheckPinDup(nodep, refp, whatp);
|
||||
}
|
||||
else {
|
||||
nodep->v3error(ucfirst(whatp)<<" not found: "<<nodep->prettyName());
|
||||
}
|
||||
}
|
||||
// Early return() above when deleted
|
||||
}
|
||||
@@ -2091,7 +2164,12 @@ private:
|
||||
if (AstTypedef* defp = foundp ? foundp->nodep()->castTypedef() : NULL) {
|
||||
nodep->refDTypep(defp->subDTypep());
|
||||
nodep->packagep(foundp->packagep());
|
||||
} else {
|
||||
}
|
||||
else if (AstParamTypeDType* defp = foundp ? foundp->nodep()->castParamTypeDType() : NULL) {
|
||||
nodep->refDTypep(defp);
|
||||
nodep->packagep(foundp->packagep());
|
||||
}
|
||||
else {
|
||||
nodep->v3error("Can't find typedef: "<<nodep->prettyName());
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -113,7 +113,7 @@ void V3LinkLevel::wrapTopCell(AstNetlist* netlistp) {
|
||||
|
||||
// Add instance
|
||||
AstCell* cellp = new AstCell(newmodp->fileline(),
|
||||
(v3Global.opt.l2Name() ? "v" : oldmodp->name()),
|
||||
((v3Global.opt.l2Name()!="") ? v3Global.opt.l2Name() : oldmodp->name()),
|
||||
oldmodp->name(),
|
||||
NULL, NULL, NULL);
|
||||
cellp->modp(oldmodp);
|
||||
|
||||
@@ -140,6 +140,21 @@ private:
|
||||
|
||||
virtual void visit(AstVar* nodep, AstNUser*) {
|
||||
cleanFileline(nodep);
|
||||
if (nodep->subDTypep()->castParseTypeDType()) {
|
||||
// It's a parameter type. Use a different node type for this.
|
||||
AstNodeDType* dtypep = nodep->valuep()->castNodeDType();
|
||||
if (!dtypep) {
|
||||
nodep->v3error("Parameter type's initial value isn't a type: "<<nodep->prettyName());
|
||||
nodep->unlinkFrBack();
|
||||
} else {
|
||||
dtypep->unlinkFrBack();
|
||||
AstNode* newp = new AstParamTypeDType(nodep->fileline(), nodep->varType(), nodep->name(),
|
||||
VFlagChildDType(), dtypep);
|
||||
nodep->replaceWith(newp); nodep->deleteTree(); VL_DANGLING(nodep);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// We used modTrace before leveling, and we may now
|
||||
// want to turn it off now that we know the levelizations
|
||||
if (v3Global.opt.traceDepth()
|
||||
@@ -307,6 +322,51 @@ private:
|
||||
nodep->unlinkFrBack()->deleteTree();
|
||||
}
|
||||
|
||||
virtual void visit(AstForeach* nodep, AstNUser*) {
|
||||
// FOREACH(array,loopvars,body)
|
||||
// -> BEGIN(declare vars, loopa=lowest; WHILE(loopa<=highest, ... body))
|
||||
//nodep->dumpTree(cout, "-foreach-old:");
|
||||
AstNode* newp = nodep->bodysp()->unlinkFrBackWithNext();
|
||||
AstNode* arrayp = nodep->arrayp();
|
||||
int dimension = 1;
|
||||
// Must do innermost (last) variable first
|
||||
AstNode* firstVarsp = nodep->varsp()->unlinkFrBackWithNext();
|
||||
AstNode* lastVarsp = firstVarsp;
|
||||
while (lastVarsp->nextp()) { lastVarsp = lastVarsp->nextp(); dimension++; }
|
||||
for (AstNode* varsp = lastVarsp; varsp; varsp=varsp->backp()) {
|
||||
UINFO(0,"foreachVar "<<varsp<<endl);
|
||||
FileLine* fl = varsp->fileline();
|
||||
AstNode* varp = new AstVar(fl, AstVarType::BLOCKTEMP,
|
||||
varsp->name(), nodep->findSigned32DType());
|
||||
AstNode* leftp = new AstAttrOf(fl, AstAttrType::DIM_LEFT,
|
||||
new AstVarRef(fl, arrayp->name(), false),
|
||||
new AstConst(fl, dimension));
|
||||
AstNode* rightp = new AstAttrOf(fl, AstAttrType::DIM_RIGHT,
|
||||
new AstVarRef(fl, arrayp->name(), false),
|
||||
new AstConst(fl, dimension));
|
||||
AstNode* stmtsp = varp;
|
||||
stmtsp->addNext(new AstAssign(fl, new AstVarRef(fl, varp->name(), true), leftp));
|
||||
AstNode* comparep =
|
||||
new AstCond(fl, new AstLte(fl, leftp->cloneTree(true), rightp->cloneTree(true)),
|
||||
// left increments up to right
|
||||
new AstLte(fl, new AstVarRef(fl, varp->name(), false), rightp->cloneTree(true)),
|
||||
// left decrements down to right
|
||||
new AstGte(fl, new AstVarRef(fl, varp->name(), false), rightp));
|
||||
AstNode* incp =
|
||||
new AstAssign(fl, new AstVarRef(fl, varp->name(), true),
|
||||
new AstAdd(fl, new AstVarRef(fl, varp->name(), false),
|
||||
new AstNegate(fl, new AstAttrOf(fl, AstAttrType::DIM_INCREMENT,
|
||||
new AstVarRef(fl, arrayp->name(), false),
|
||||
new AstConst(fl, dimension)))));
|
||||
stmtsp->addNext(new AstWhile(fl, comparep, newp, incp));
|
||||
newp = new AstBegin(nodep->fileline(),"",stmtsp);
|
||||
dimension--;
|
||||
}
|
||||
//newp->dumpTree(cout, "-foreach-new:");
|
||||
firstVarsp->deleteTree(); VL_DANGLING(firstVarsp);
|
||||
nodep->replaceWith(newp); nodep->deleteTree(); VL_DANGLING(nodep);
|
||||
}
|
||||
|
||||
virtual void visit(AstNodeModule* nodep, AstNUser*) {
|
||||
// Module: Create sim table for entire module and iterate
|
||||
cleanFileline(nodep);
|
||||
|
||||
+8
-2
@@ -605,7 +605,10 @@ string V3Number::displayed(FileLine*fl, const string& vformat) const {
|
||||
|
||||
uint32_t V3Number::toUInt() const {
|
||||
UASSERT(!isFourState(),"toUInt with 4-state "<<*this);
|
||||
UASSERT((width()<33 || (width()<65 && m_value[1]==0)), "Value too wide "<<*this);
|
||||
// We allow wide numbers that represent values <= 32 bits
|
||||
for (int i=1; i<words(); ++i) {
|
||||
UASSERT(!m_value[i], "Value too wide for 32-bits expected in this context "<<*this);
|
||||
}
|
||||
return m_value[0];
|
||||
}
|
||||
|
||||
@@ -636,7 +639,10 @@ vlsint32_t V3Number::toSInt() const {
|
||||
|
||||
vluint64_t V3Number::toUQuad() const {
|
||||
UASSERT(!isFourState(),"toUQuad with 4-state "<<*this);
|
||||
UASSERT(width()<65, "Value too wide "<<*this);
|
||||
// We allow wide numbers that represent values <= 64 bits
|
||||
for (int i=2; i<words(); ++i) {
|
||||
UASSERT(!m_value[i], "Value too wide for 64-bits expected in this context "<<*this);
|
||||
}
|
||||
if (width()<=32) return ((vluint64_t)(toUInt()));
|
||||
return ((vluint64_t)m_value[1]<<VL_ULL(32)) | ((vluint64_t)m_value[0]);
|
||||
}
|
||||
|
||||
+64
-2
@@ -130,6 +130,52 @@ void V3Options::addDefine(const string& defline, bool allowPlus) {
|
||||
V3PreShell::defineCmdLine(def,value);
|
||||
}
|
||||
}
|
||||
void V3Options::addParameter(const string& paramline, bool allowPlus) {
|
||||
// Split +define+foo=value into the appropriate parts and parse
|
||||
// Optional + says to allow multiple defines on the line
|
||||
// + is not quotable, as other simulators do not allow that
|
||||
string left = paramline;
|
||||
while (left != "") {
|
||||
string param = left;
|
||||
string::size_type pos;
|
||||
if (allowPlus && ((pos=left.find("+")) != string::npos)) {
|
||||
left = left.substr(pos+1);
|
||||
param.erase(pos);
|
||||
} else {
|
||||
left = "";
|
||||
}
|
||||
string value;
|
||||
if ((pos=param.find("=")) != string::npos) {
|
||||
value = param.substr(pos+1);
|
||||
param.erase(pos);
|
||||
}
|
||||
UINFO(4,"Add parameter"<<param<<"="<<value<<endl);
|
||||
(void)m_parameters.erase(param);
|
||||
m_parameters[param] = value;
|
||||
}
|
||||
}
|
||||
|
||||
bool V3Options::hasParameter(string name) {
|
||||
return m_parameters.find(name) != m_parameters.end();
|
||||
}
|
||||
|
||||
string V3Options::parameter(string name) {
|
||||
string value = m_parameters.find(name)->second;
|
||||
m_parameters.erase(m_parameters.find(name));
|
||||
return value;
|
||||
}
|
||||
|
||||
void V3Options::checkParameters() {
|
||||
if (!m_parameters.empty()) {
|
||||
stringstream msg;
|
||||
msg << "Parameters from the command line were not found in the design:";
|
||||
for (map<string,string>::iterator it = m_parameters.begin();
|
||||
it != m_parameters.end(); ++it) {
|
||||
msg << " " << it->first;
|
||||
}
|
||||
v3fatal(msg.str()<<endl);
|
||||
}
|
||||
}
|
||||
|
||||
void V3Options::addCppFile(const string& filename) {
|
||||
if (m_cppFiles.find(filename) == m_cppFiles.end()) {
|
||||
@@ -643,11 +689,11 @@ void V3Options::parseOptsList(FileLine* fl, const string& optdir, int argc, char
|
||||
else if ( onoff (sw, "-debug-check", flag/*ref*/) ){ m_debugCheck = flag; }
|
||||
else if ( !strcmp (sw, "-debug-sigsegv") ) { throwSigsegv(); } // Undocumented, see also --debug-abort
|
||||
else if ( !strcmp (sw, "-debug-fatalsrc") ) { v3fatalSrc("--debug-fatal-src"); } // Undocumented, see also --debug-abort
|
||||
else if ( onoff (sw, "-decoration", flag/*ref*/) ) { m_decoration = flag; }
|
||||
else if ( onoff (sw, "-dump-tree", flag/*ref*/) ) { m_dumpTree = flag ? 3 : 0; } // Also see --dump-treei
|
||||
else if ( onoff (sw, "-exe", flag/*ref*/) ) { m_exe = flag; }
|
||||
else if ( onoff (sw, "-ignc", flag/*ref*/) ) { m_ignc = flag; }
|
||||
else if ( onoff (sw, "-inhibit-sim", flag/*ref*/)){ m_inhibitSim = flag; }
|
||||
else if ( onoff (sw, "-l2name", flag/*ref*/) ) { m_l2Name = flag; }
|
||||
else if ( onoff (sw, "-lint-only", flag/*ref*/) ) { m_lintOnly = flag; }
|
||||
else if ( !strcmp (sw, "-no-pins64") ) { m_pinsBv = 33; }
|
||||
else if ( onoff (sw, "-order-clock-delay", flag/*ref*/) ) { m_orderClockDly = flag; }
|
||||
@@ -658,6 +704,7 @@ void V3Options::parseOptsList(FileLine* fl, const string& optdir, int argc, char
|
||||
else if ( !strcmp (sw, "-private") ) { m_public = false; }
|
||||
else if ( onoff (sw, "-profile-cfuncs", flag/*ref*/) ) { m_profileCFuncs = flag; }
|
||||
else if ( onoff (sw, "-public", flag/*ref*/) ) { m_public = flag; }
|
||||
else if ( !strncmp(sw, "-pvalue+", strlen("-pvalue+"))) { addParameter(string(sw+strlen("-pvalue+")), false); }
|
||||
else if ( onoff (sw, "-report-unoptflat", flag/*ref*/) ) { m_reportUnoptflat = flag; }
|
||||
else if ( onoff (sw, "-savable", flag/*ref*/) ) { m_savable = flag; }
|
||||
else if ( !strcmp (sw, "-sc") ) { m_outFormatOk = true; m_systemC = true; m_systemPerl = false; }
|
||||
@@ -748,6 +795,9 @@ void V3Options::parseOptsList(FileLine* fl, const string& optdir, int argc, char
|
||||
shift;
|
||||
V3Error::errorLimit(atoi(argv[i]));
|
||||
}
|
||||
else if ( !strncmp (sw, "-G", strlen("-G"))) {
|
||||
addParameter (string (sw+strlen("-G")), false);
|
||||
}
|
||||
else if ( !strncmp (sw, "-I", 2)) {
|
||||
addIncDirUser (parseFileArg(optdir, string (sw+strlen("-I"))));
|
||||
}
|
||||
@@ -763,6 +813,16 @@ void V3Options::parseOptsList(FileLine* fl, const string& optdir, int argc, char
|
||||
shift;
|
||||
addLdLibs(argv[i]);
|
||||
}
|
||||
else if ( !strcmp (sw, "-l2-name") && (i+1)<argc ) {
|
||||
shift;
|
||||
m_l2Name = argv[i];
|
||||
}
|
||||
else if ( !strcmp (sw, "-l2name")) { // Historical and undocumented
|
||||
m_l2Name = "v";
|
||||
}
|
||||
else if ( !strcmp (sw, "-no-l2name")) { // Historical and undocumented
|
||||
m_l2Name = "";
|
||||
}
|
||||
else if ( (!strcmp (sw, "-language") && (i+1)<argc)
|
||||
|| (!strcmp (sw, "-default-language") && (i+1)<argc)) {
|
||||
shift;
|
||||
@@ -927,6 +987,7 @@ void V3Options::parseOptsList(FileLine* fl, const string& optdir, int argc, char
|
||||
}
|
||||
else if ( !strcmp (sw, "-pins-bv") && (i+1)<argc ) {
|
||||
shift; m_pinsBv = atoi(argv[i]);
|
||||
if (m_pinsBv > 65) fl->v3fatal("--pins-bv maximum is 65: "<<argv[i]);
|
||||
}
|
||||
else if ( !strcmp (sw, "-pipe-filter") && (i+1)<argc ) {
|
||||
shift; m_pipeFilter = argv[i];
|
||||
@@ -1139,10 +1200,10 @@ V3Options::V3Options() {
|
||||
m_coverageUnderscore = false;
|
||||
m_coverageUser = false;
|
||||
m_debugCheck = false;
|
||||
m_decoration = true;
|
||||
m_exe = false;
|
||||
m_ignc = false;
|
||||
m_inhibitSim = false;
|
||||
m_l2Name = true;
|
||||
m_lintOnly = false;
|
||||
m_makeDepend = true;
|
||||
m_makePhony = false;
|
||||
@@ -1192,6 +1253,7 @@ V3Options::V3Options() {
|
||||
m_makeDir = "obj_dir";
|
||||
m_bin = "";
|
||||
m_flags = "";
|
||||
m_l2Name = "";
|
||||
m_unusedRegexp = "*unused*";
|
||||
m_xAssign = "fast";
|
||||
|
||||
|
||||
+11
-2
@@ -58,6 +58,8 @@ class V3Options {
|
||||
V3StringList m_vFiles; // argument: Verilog files to read
|
||||
DebugSrcMap m_debugSrcs; // argument: --debugi-<srcfile>=<level>
|
||||
DebugSrcMap m_dumpTrees; // argument: --dump-treei-<srcfile>=<level>
|
||||
map<string,string> m_parameters; // Parameters
|
||||
|
||||
|
||||
bool m_preprocOnly; // main switch: -E
|
||||
bool m_makeDepend; // main switch: -MMD
|
||||
@@ -73,10 +75,10 @@ class V3Options {
|
||||
bool m_coverageUnderscore;// main switch: --coverage-underscore
|
||||
bool m_coverageUser; // main switch: --coverage-func
|
||||
bool m_debugCheck; // main switch: --debug-check
|
||||
bool m_decoration; // main switch: --decoration
|
||||
bool m_exe; // main switch: --exe
|
||||
bool m_ignc; // main switch: --ignc
|
||||
bool m_inhibitSim; // main switch: --inhibit-sim
|
||||
bool m_l2Name; // main switch: --l2name
|
||||
bool m_lintOnly; // main switch: --lint-only
|
||||
bool m_orderClockDly;// main switch: --order-clock-delay
|
||||
bool m_outFormatOk; // main switch: --cc, --sc or --sp was specified
|
||||
@@ -122,6 +124,7 @@ class V3Options {
|
||||
string m_bin; // main switch: --bin {binary}
|
||||
string m_exeName; // main switch: -o {name}
|
||||
string m_flags; // main switch: -f {name}
|
||||
string m_l2Name; // main switch: --l2name; "" for top-module's name
|
||||
string m_makeDir; // main switch: -Mdir
|
||||
string m_modPrefix; // main switch: --mod-prefix
|
||||
string m_pipeFilter; // main switch: --pipe-filter
|
||||
@@ -162,6 +165,7 @@ class V3Options {
|
||||
void addFuture(const string& flag);
|
||||
void addIncDirUser(const string& incdir); // User requested
|
||||
void addIncDirFallback(const string& incdir); // Low priority if not found otherwise
|
||||
void addParameter(const string& paramline, bool allowPlus);
|
||||
void addLangExt(const string& langext, const V3LangCode& lc);
|
||||
void addLibExtV(const string& libext);
|
||||
void optimize(int level);
|
||||
@@ -223,6 +227,7 @@ class V3Options {
|
||||
bool coverageUnderscore() const { return m_coverageUnderscore; }
|
||||
bool coverageUser() const { return m_coverageUser; }
|
||||
bool debugCheck() const { return m_debugCheck; }
|
||||
bool decoration() const { return m_decoration; }
|
||||
bool exe() const { return m_exe; }
|
||||
bool trace() const { return m_trace; }
|
||||
bool traceDups() const { return m_traceDups; }
|
||||
@@ -237,7 +242,6 @@ class V3Options {
|
||||
bool pinsUint8() const { return m_pinsUint8; }
|
||||
bool profileCFuncs() const { return m_profileCFuncs; }
|
||||
bool allPublic() const { return m_public; }
|
||||
bool l2Name() const { return m_l2Name; }
|
||||
bool lintOnly() const { return m_lintOnly; }
|
||||
bool ignc() const { return m_ignc; }
|
||||
bool inhibitSim() const { return m_inhibitSim; }
|
||||
@@ -264,6 +268,7 @@ class V3Options {
|
||||
int compLimitParens() const { return m_compLimitParens; }
|
||||
|
||||
string exeName() const { return m_exeName!="" ? m_exeName : prefix(); }
|
||||
string l2Name() const { return m_l2Name; }
|
||||
string makeDir() const { return m_makeDir; }
|
||||
string modPrefix() const { return m_modPrefix; }
|
||||
string pipeFilter() const { return m_pipeFilter; }
|
||||
@@ -279,6 +284,10 @@ class V3Options {
|
||||
const V3StringList& vFiles() const { return m_vFiles; }
|
||||
const V3LangCode& defaultLanguage() const { return m_defaultLanguage; }
|
||||
|
||||
bool hasParameter(string name);
|
||||
string parameter(string name);
|
||||
void checkParameters();
|
||||
|
||||
bool isFuture(const string& flag) const;
|
||||
bool isLibraryFile(const string& filename) const;
|
||||
bool isClocker(const string& signame) const;
|
||||
|
||||
+102
-54
@@ -84,10 +84,10 @@ private:
|
||||
typedef deque<pair<AstIfaceRefDType*,AstIfaceRefDType*> > IfaceRefRefs; // Note may have duplicate entries
|
||||
|
||||
// STATE
|
||||
typedef map<AstVar*,AstVar*> VarCloneMap;
|
||||
typedef map<AstNode*,AstNode*> CloneMap;
|
||||
struct ModInfo {
|
||||
AstNodeModule* m_modp; // Module with specified name
|
||||
VarCloneMap m_cloneMap; // Map of old-varp -> new cloned varp
|
||||
CloneMap m_cloneMap; // Map of old-varp -> new cloned varp
|
||||
explicit ModInfo(AstNodeModule* modp) { m_modp=modp; }
|
||||
};
|
||||
typedef map<string,ModInfo> ModNameMap;
|
||||
@@ -131,7 +131,7 @@ private:
|
||||
}
|
||||
}
|
||||
}
|
||||
string paramSmallName(AstNodeModule* modp, AstVar* varp) {
|
||||
string paramSmallName(AstNodeModule* modp, AstNode* varp) {
|
||||
if (varp->user4()<=1) {
|
||||
makeSmallNames(modp);
|
||||
}
|
||||
@@ -145,7 +145,7 @@ private:
|
||||
return st;
|
||||
}
|
||||
string paramValueNumber(AstNode* nodep) {
|
||||
// Given a compilcated object create a number to use for param module assignment
|
||||
// Given a complicated object create a number to use for param module assignment
|
||||
// Ideally would be relatively stable if design changes (not use pointer value),
|
||||
// and must return same value given same input node
|
||||
// Return must presently be numeric so doesn't collide with 'small' alphanumeric parameter names
|
||||
@@ -166,14 +166,42 @@ private:
|
||||
return (string)"z"+cvtToStr(num);
|
||||
}
|
||||
}
|
||||
void relinkPins(VarCloneMap* clonemapp, AstPin* startpinp) {
|
||||
void collectPins(CloneMap* clonemapp, AstNodeModule* modp) {
|
||||
// Grab all I/O so we can remap our pins later
|
||||
for (AstNode* stmtp=modp->stmtsp(); stmtp; stmtp = stmtp->nextp()) {
|
||||
if (AstVar* varp = stmtp->castVar()) {
|
||||
if (varp->isIO() || varp->isGParam() || varp->isIfaceRef()) {
|
||||
// Cloning saved a pointer to the new node for us, so just follow that link.
|
||||
AstVar* oldvarp = varp->clonep()->castVar();
|
||||
//UINFO(8,"Clone list 0x"<<hex<<(uint32_t)oldvarp<<" -> 0x"<<(uint32_t)varp<<endl);
|
||||
clonemapp->insert(make_pair(oldvarp, varp));
|
||||
}
|
||||
}
|
||||
else if (AstParamTypeDType* ptp = stmtp->castParamTypeDType()) {
|
||||
if (ptp->isGParam()) {
|
||||
AstParamTypeDType* oldptp = ptp->clonep()->castParamTypeDType();
|
||||
clonemapp->insert(make_pair(oldptp, ptp));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
void relinkPins(CloneMap* clonemapp, AstPin* startpinp) {
|
||||
for (AstPin* pinp = startpinp; pinp; pinp=pinp->nextp()->castPin()) {
|
||||
if (!pinp->modVarp()) pinp->v3fatalSrc("Not linked?\n");
|
||||
// Find it in the clone structure
|
||||
//UINFO(8,"Clone find 0x"<<hex<<(uint32_t)pinp->modVarp()<<endl);
|
||||
VarCloneMap::iterator cloneiter = clonemapp->find(pinp->modVarp());
|
||||
UASSERT(cloneiter != clonemapp->end(), "Couldn't find pin in clone list");
|
||||
pinp->modVarp(cloneiter->second);
|
||||
if (pinp->modVarp()) {
|
||||
// Find it in the clone structure
|
||||
//UINFO(8,"Clone find 0x"<<hex<<(uint32_t)pinp->modVarp()<<endl);
|
||||
CloneMap::iterator cloneiter = clonemapp->find(pinp->modVarp());
|
||||
UASSERT(cloneiter != clonemapp->end(), "Couldn't find pin in clone list");
|
||||
pinp->modVarp(cloneiter->second->castVar());
|
||||
}
|
||||
else if (pinp->modPTypep()) {
|
||||
CloneMap::iterator cloneiter = clonemapp->find(pinp->modPTypep());
|
||||
UASSERT(cloneiter != clonemapp->end(), "Couldn't find pin in clone list");
|
||||
pinp->modPTypep(cloneiter->second->castParamTypeDType());
|
||||
}
|
||||
else {
|
||||
pinp->v3fatalSrc("Not linked?\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
void visitCell(AstCell* nodep);
|
||||
@@ -458,31 +486,50 @@ void ParamVisitor::visitCell(AstCell* nodep) {
|
||||
if (debug()>8) nodep->paramsp()->dumpTreeAndNext(cout,"-cellparams:\t");
|
||||
for (AstPin* pinp = nodep->paramsp(); pinp; pinp=pinp->nextp()->castPin()) {
|
||||
if (!pinp->exprp()) continue; // No-connect
|
||||
AstVar* modvarp = pinp->modVarp();
|
||||
if (!modvarp) {
|
||||
pinp->v3error("Parameter not found in sub-module: Param "<<pinp->name()<<" of "<<nodep->prettyName());
|
||||
} else if (!modvarp->isGParam()) {
|
||||
pinp->v3error("Attempted parameter setting of non-parameter: Param "<<pinp->name()<<" of "<<nodep->prettyName());
|
||||
} else {
|
||||
AstConst* constp = pinp->exprp()->castConst();
|
||||
AstConst* origconstp = modvarp->valuep()->castConst();
|
||||
if (!constp) {
|
||||
//if (debug()) pinp->dumpTree(cout,"error:");
|
||||
pinp->v3error("Can't convert defparam value to constant: Param "<<pinp->name()<<" of "<<nodep->prettyName());
|
||||
pinp->exprp()->replaceWith(new AstConst(pinp->fileline(), V3Number(pinp->fileline(), modvarp->width(), 0)));
|
||||
} else if (origconstp && constp->sameTree(origconstp)) {
|
||||
// Setting parameter to its default value. Just ignore it.
|
||||
// This prevents making additional modules, and makes coverage more
|
||||
// obvious as it won't show up under a unique module page name.
|
||||
} else if (constp->num().isDouble()
|
||||
|| constp->num().isString()
|
||||
|| constp->num().isFourState()) {
|
||||
longname += "_" + paramSmallName(nodep->modp(),pinp->modVarp())+paramValueNumber(constp);
|
||||
any_overrides = true;
|
||||
if (AstVar* modvarp = pinp->modVarp()) {
|
||||
if (!modvarp->isGParam()) {
|
||||
pinp->v3error("Attempted parameter setting of non-parameter: Param "<<pinp->prettyName()<<" of "<<nodep->prettyName());
|
||||
} else {
|
||||
longname += "_" + paramSmallName(nodep->modp(),pinp->modVarp())+constp->num().ascii(false);
|
||||
any_overrides = true;
|
||||
AstConst* exprp = pinp->exprp()->castConst();
|
||||
AstConst* origp = modvarp->valuep()->castConst();
|
||||
if (!exprp) {
|
||||
//if (debug()) pinp->dumpTree(cout,"error:");
|
||||
pinp->v3error("Can't convert defparam value to constant: Param "<<pinp->name()<<" of "<<nodep->prettyName());
|
||||
pinp->exprp()->replaceWith(new AstConst(pinp->fileline(), V3Number(pinp->fileline(), modvarp->width(), 0)));
|
||||
} else if (origp && exprp->sameTree(origp)) {
|
||||
// Setting parameter to its default value. Just ignore it.
|
||||
// This prevents making additional modules, and makes coverage more
|
||||
// obvious as it won't show up under a unique module page name.
|
||||
} else if (exprp->num().isDouble()
|
||||
|| exprp->num().isString()
|
||||
|| exprp->num().isFourState()) {
|
||||
longname += "_" + paramSmallName(nodep->modp(),modvarp)+paramValueNumber(exprp);
|
||||
any_overrides = true;
|
||||
} else {
|
||||
longname += "_" + paramSmallName(nodep->modp(),modvarp)+exprp->num().ascii(false);
|
||||
any_overrides = true;
|
||||
}
|
||||
}
|
||||
} else if (AstParamTypeDType* modvarp = pinp->modPTypep()) {
|
||||
AstNodeDType* exprp = pinp->exprp()->castNodeDType();
|
||||
AstNodeDType* origp = modvarp->subDTypep();
|
||||
if (!exprp) {
|
||||
pinp->v3error("Parameter type pin value isn't a type: Param "<<pinp->prettyName()<<" of "<<nodep->prettyName());
|
||||
} else if (!origp) {
|
||||
pinp->v3error("Parameter type variable isn't a type: Param "<<modvarp->prettyName());
|
||||
} else {
|
||||
UINFO(9,"Parameter type assignment expr="<<exprp<<" to "<<origp<<endl);
|
||||
if (origp && exprp->sameTree(origp)) {
|
||||
// Setting parameter to its default value. Just ignore it.
|
||||
// This prevents making additional modules, and makes coverage more
|
||||
// obvious as it won't show up under a unique module page name.
|
||||
} else {
|
||||
longname += "_" + paramSmallName(nodep->modp(),modvarp)+paramValueNumber(exprp);
|
||||
any_overrides = true;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
pinp->v3error("Parameter not found in sub-module: Param "<<pinp->prettyName()<<" of "<<nodep->prettyName());
|
||||
}
|
||||
}
|
||||
IfaceRefRefs ifaceRefRefs;
|
||||
@@ -573,22 +620,12 @@ void ParamVisitor::visitCell(AstCell* nodep) {
|
||||
|
||||
m_modNameMap.insert(make_pair(modp->name(), ModInfo(modp)));
|
||||
iter = m_modNameMap.find(newname);
|
||||
VarCloneMap* clonemapp = &(iter->second.m_cloneMap);
|
||||
CloneMap* clonemapp = &(iter->second.m_cloneMap);
|
||||
UINFO(4," De-parameterize to new: "<<modp<<endl);
|
||||
|
||||
// Grab all I/O so we can remap our pins later
|
||||
// Note we allow multiple users of a parameterized model, thus we need to stash this info.
|
||||
for (AstNode* stmtp=modp->stmtsp(); stmtp; stmtp = stmtp->nextp()) {
|
||||
if (AstVar* varp = stmtp->castVar()) {
|
||||
if (varp->isIO() || varp->isGParam() || varp->isIfaceRef()) {
|
||||
// Cloning saved a pointer to the new node for us, so just follow that link.
|
||||
AstVar* oldvarp = varp->clonep()->castVar();
|
||||
//UINFO(8,"Clone list 0x"<<hex<<(uint32_t)oldvarp<<" -> 0x"<<(uint32_t)varp<<endl);
|
||||
clonemapp->insert(make_pair(oldvarp, varp));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
collectPins(clonemapp, modp);
|
||||
// Relink parameter vars to the new module
|
||||
relinkPins(clonemapp, nodep->paramsp());
|
||||
|
||||
@@ -608,15 +645,26 @@ void ParamVisitor::visitCell(AstCell* nodep) {
|
||||
// Assign parameters to the constants specified
|
||||
// DOES clone() so must be finished with module clonep() before here
|
||||
for (AstPin* pinp = nodep->paramsp(); pinp; pinp=pinp->nextp()->castPin()) {
|
||||
AstVar* modvarp = pinp->modVarp();
|
||||
if (modvarp && pinp->exprp()) {
|
||||
AstConst* constp = pinp->exprp()->castConst();
|
||||
// Remove any existing parameter
|
||||
if (modvarp->valuep()) modvarp->valuep()->unlinkFrBack()->deleteTree();
|
||||
// Set this parameter to value requested by cell
|
||||
modvarp->valuep(constp->cloneTree(false));
|
||||
if (pinp->exprp()) {
|
||||
if (AstVar* modvarp = pinp->modVarp()) {
|
||||
AstConst* constp = pinp->exprp()->castConst();
|
||||
// Remove any existing parameter
|
||||
if (modvarp->valuep()) modvarp->valuep()->unlinkFrBack()->deleteTree();
|
||||
// Set this parameter to value requested by cell
|
||||
modvarp->valuep(constp->cloneTree(false));
|
||||
}
|
||||
else if (AstParamTypeDType* modptp = pinp->modPTypep()) {
|
||||
AstNodeDType* dtypep = pinp->exprp()->castNodeDType();
|
||||
if (!dtypep) pinp->v3fatalSrc("unlinked param dtype");
|
||||
if (modptp->childDTypep()) pushDeletep(modptp->childDTypep()->unlinkFrBack());
|
||||
// Set this parameter to value requested by cell
|
||||
modptp->childDTypep(dtypep->cloneTree(false));
|
||||
// Later V3LinkDot will convert the ParamDType to a Typedef
|
||||
// Not done here as may be localparams, etc, that also need conversion
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
UINFO(4," De-parameterize to old: "<<modp<<endl);
|
||||
}
|
||||
@@ -626,7 +674,7 @@ void ParamVisitor::visitCell(AstCell* nodep) {
|
||||
nodep->modName(newname);
|
||||
|
||||
// We need to relink the pins to the new module
|
||||
VarCloneMap* clonemapp = &(iter->second.m_cloneMap);
|
||||
CloneMap* clonemapp = &(iter->second.m_cloneMap);
|
||||
relinkPins(clonemapp, nodep->pinsp());
|
||||
UINFO(8," Done with "<<modp<<endl);
|
||||
} // if any_overrides
|
||||
|
||||
+1
-1
@@ -140,7 +140,7 @@ public:
|
||||
void verilatorCmtLintSave();
|
||||
void verilatorCmtLintRestore();
|
||||
void verilatorCmtBad(const char* text);
|
||||
double parseDouble(const char* text, size_t length);
|
||||
static double parseDouble(const char* text, size_t length, bool* successp = NULL);
|
||||
void pushBeginKeywords(int state) { m_inBeginKwd++; m_lastVerilogState=state; }
|
||||
bool popBeginKeywords() { if (m_inBeginKwd) { m_inBeginKwd--; return true; } else return false; }
|
||||
int lastVerilogState() const { return m_lastVerilogState; }
|
||||
|
||||
+10
-1
@@ -144,8 +144,12 @@ private:
|
||||
&& nodep->firstAbovep()->castNodeAssign()
|
||||
&& assignNoTemp(nodep->firstAbovep()->castNodeAssign())) {
|
||||
// Not much point if it's just a direct assignment to a constant
|
||||
} else if (nodep->backp()->castSel()
|
||||
&& nodep->backp()->castSel()->widthp() == nodep) {
|
||||
// AstSel::width must remain a constant
|
||||
} else if (nodep->firstAbovep()
|
||||
&& nodep->firstAbovep()->castArraySel()) { // ArraySel's are pointer refs, ignore
|
||||
&& nodep->firstAbovep()->castArraySel()) {
|
||||
// ArraySel's are pointer refs, ignore
|
||||
} else {
|
||||
UINFO(4,"Cre Temp: "<<nodep<<endl);
|
||||
createDeepTemp(nodep, false);
|
||||
@@ -263,6 +267,11 @@ private:
|
||||
// Shifts of > 32/64 bits in C++ will wrap-around and generate non-0s
|
||||
if (!nodep->user2SetOnce()) {
|
||||
UINFO(4," ShiftFix "<<nodep<<endl);
|
||||
AstConst* shiftp = nodep->rhsp()->castConst();
|
||||
if (shiftp && shiftp->num().mostSetBitP1() > 32) {
|
||||
shiftp->v3error("Unsupported: Shifting of by over 32-bit number isn't supported."
|
||||
<<" (This isn't a shift of 32 bits, but a shift of 2^32, or 4 billion!)\n");
|
||||
}
|
||||
if (nodep->widthMin()<=64 // Else we'll use large operators which work right
|
||||
// C operator's width must be < maximum shift which is based on Verilog width
|
||||
&& nodep->width() < (1LL<<nodep->rhsp()->widthMin())) {
|
||||
|
||||
+89
-40
@@ -139,37 +139,34 @@ class SliceCloneVisitor : public AstNVisitor {
|
||||
UINFO(4, "Cloning "<<nodep->user2()<<" times: "<<nodep<<endl);
|
||||
|
||||
AstNode* lhsp = NULL;
|
||||
AstNode* rhsp = NULL;
|
||||
for (int i = 0; i < nodep->user2(); ++i) {
|
||||
// Clone the node and iterate over the clone
|
||||
m_vecIdx = -1;
|
||||
AstNodeUniop* clonep = nodep->cloneTree(false)->castNodeUniop();
|
||||
clonep->iterateChildren(*this);
|
||||
if (!lhsp) lhsp = clonep;
|
||||
else rhsp = clonep;
|
||||
if (lhsp && rhsp) {
|
||||
else {
|
||||
switch (nodep->type()) {
|
||||
case AstType::atREDOR:
|
||||
lhsp = new AstOr(nodep->fileline(), lhsp, rhsp);
|
||||
lhsp = new AstOr(nodep->fileline(), lhsp, clonep);
|
||||
break;
|
||||
case AstType::atREDAND:
|
||||
lhsp = new AstAnd(nodep->fileline(), lhsp, rhsp);
|
||||
lhsp = new AstAnd(nodep->fileline(), lhsp, clonep);
|
||||
break;
|
||||
case AstType::atREDXOR:
|
||||
lhsp = new AstXor(nodep->fileline(), lhsp, rhsp);
|
||||
lhsp = new AstXor(nodep->fileline(), lhsp, clonep);
|
||||
break;
|
||||
case AstType::atREDXNOR:
|
||||
lhsp = new AstXnor(nodep->fileline(), lhsp, rhsp);
|
||||
lhsp = new AstXnor(nodep->fileline(), lhsp, clonep);
|
||||
break;
|
||||
default:
|
||||
nodep->v3fatalSrc("Unsupported: Unary operation on multiple packed dimensions");
|
||||
break;
|
||||
}
|
||||
rhsp = NULL;
|
||||
}
|
||||
}
|
||||
nodep->addNextHere(lhsp);
|
||||
nodep->unlinkFrBack()->deleteTree(); VL_DANGLING(nodep);
|
||||
nodep->replaceWith(lhsp);
|
||||
nodep->deleteTree(); VL_DANGLING(nodep);
|
||||
}
|
||||
virtual void visit(AstRedOr* nodep, AstNUser*) {
|
||||
cloneUniop(nodep);
|
||||
@@ -421,17 +418,19 @@ class SliceVisitor : public AstNVisitor {
|
||||
if (AstInitArray* initp = nodep->rhsp()->castInitArray()) {
|
||||
//if (debug()>=9) nodep->dumpTree(cout, "-InitArrayIn: ");
|
||||
AstNode* newp = NULL;
|
||||
int index = 0;
|
||||
while (AstNode* subp=initp->initsp()) {
|
||||
for (int pos = 0; AstNode* itemp=initp->initsp(); ++pos) {
|
||||
int index = initp->posIndex(pos);
|
||||
AstNode* lhsp = new AstArraySel(nodep->fileline(),
|
||||
nodep->lhsp()->cloneTree(false),
|
||||
index++);
|
||||
newp = AstNode::addNext(newp, nodep->cloneType(lhsp, subp->unlinkFrBack()));
|
||||
index);
|
||||
newp = AstNode::addNext(newp, nodep->cloneType(lhsp, itemp->unlinkFrBack()));
|
||||
// Deleted from list of items without correcting posIndex, but that's ok as about
|
||||
// to delete the entire InitArray
|
||||
}
|
||||
//if (debug()>=9) newp->dumpTreeAndNext(cout, "-InitArrayOut: ");
|
||||
nodep->replaceWith(newp);
|
||||
pushDeletep(nodep); VL_DANGLING(nodep);
|
||||
return; // WIll iterate in a moment
|
||||
return; // Will iterate in a moment
|
||||
}
|
||||
// Hasn't been searched for implicit slices yet
|
||||
findImplicit(nodep);
|
||||
@@ -439,44 +438,94 @@ class SliceVisitor : public AstNVisitor {
|
||||
}
|
||||
|
||||
void expandUniOp(AstNodeUniop* nodep) {
|
||||
nodep->user1(true);
|
||||
unsigned dim = 0;
|
||||
if (AstArraySel* selp = nodep->lhsp()->castArraySel()) {
|
||||
// We have explicit dimensions, either packed or unpacked
|
||||
dim = explicitDimensions(selp);
|
||||
}
|
||||
if (dim == 0 && !nodep->lhsp()->castVarRef()) {
|
||||
// No ArraySel nor VarRef, not something we can expand
|
||||
nodep->iterateChildren(*this);
|
||||
} else {
|
||||
AstVarRef* refp = findVarRefRecurse(nodep->lhsp());
|
||||
ArrayDimensions varDim = refp->varp()->dtypep()->dimensions(false);
|
||||
if ((int)(dim - varDim.second) < 0) {
|
||||
// Unpacked dimensions are referenced first, make sure we have them all
|
||||
nodep->v3error("Unary operator used across unpacked dimensions");
|
||||
if (!nodep->user1()) {
|
||||
nodep->user1(true);
|
||||
unsigned dim = 0;
|
||||
if (AstArraySel* selp = nodep->lhsp()->castArraySel()) {
|
||||
// We have explicit dimensions, either packed or unpacked
|
||||
dim = explicitDimensions(selp);
|
||||
}
|
||||
if (dim == 0 && !nodep->lhsp()->castVarRef()) {
|
||||
// No ArraySel nor VarRef, not something we can expand
|
||||
nodep->iterateChildren(*this);
|
||||
} else {
|
||||
AstVarRef* refp = findVarRefRecurse(nodep->lhsp());
|
||||
ArrayDimensions varDim = refp->varp()->dtypep()->dimensions(false);
|
||||
if ((int)(dim - varDim.second) < 0) {
|
||||
// Unpacked dimensions are referenced first, make sure we have them all
|
||||
nodep->v3error("Unary operator used across unpacked dimensions");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
virtual void visit(AstRedOr* nodep, AstNUser*) {
|
||||
if (!nodep->user1()) {
|
||||
expandUniOp(nodep);
|
||||
}
|
||||
expandUniOp(nodep);
|
||||
}
|
||||
virtual void visit(AstRedAnd* nodep, AstNUser*) {
|
||||
if (!nodep->user1()) {
|
||||
expandUniOp(nodep);
|
||||
}
|
||||
expandUniOp(nodep);
|
||||
}
|
||||
virtual void visit(AstRedXor* nodep, AstNUser*) {
|
||||
if (!nodep->user1()) {
|
||||
expandUniOp(nodep);
|
||||
}
|
||||
expandUniOp(nodep);
|
||||
}
|
||||
virtual void visit(AstRedXnor* nodep, AstNUser*) {
|
||||
expandUniOp(nodep);
|
||||
}
|
||||
|
||||
void expandBiOp(AstNodeBiop* nodep) {
|
||||
if (!nodep->user1()) {
|
||||
expandUniOp(nodep);
|
||||
nodep->user1(true);
|
||||
// If it's a unpacked array, blow it up into comparing each element
|
||||
AstNodeDType* fromDtp = nodep->lhsp()->dtypep()->skipRefp();
|
||||
UINFO(9, " Bi-Eq/Neq expansion "<<nodep<<endl);
|
||||
if (AstUnpackArrayDType* adtypep = fromDtp->castUnpackArrayDType()) {
|
||||
AstNodeBiop* logp = NULL;
|
||||
for (int index = adtypep->rangep()->lsbConst();
|
||||
index <= adtypep->rangep()->msbConst(); ++index) {
|
||||
// EQ(a,b) -> LOGAND(EQ(ARRAYSEL(a,0), ARRAYSEL(b,0)), ...[1])
|
||||
AstNodeBiop* clonep = nodep->cloneType
|
||||
(new AstArraySel(nodep->fileline(),
|
||||
nodep->lhsp()->cloneTree(false),
|
||||
index),
|
||||
new AstArraySel(nodep->fileline(),
|
||||
nodep->rhsp()->cloneTree(false),
|
||||
index))->castNodeBiop();
|
||||
if (!logp) logp = clonep;
|
||||
else {
|
||||
switch (nodep->type()) {
|
||||
case AstType::atEQ: // FALLTHRU
|
||||
case AstType::atEQCASE:
|
||||
logp = new AstLogAnd(nodep->fileline(), logp, clonep);
|
||||
break;
|
||||
case AstType::atNEQ: // FALLTHRU
|
||||
case AstType::atNEQCASE:
|
||||
logp = new AstLogOr(nodep->fileline(), logp, clonep);
|
||||
break;
|
||||
default:
|
||||
nodep->v3fatalSrc("Unknown node type processing array slice");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!logp) nodep->v3fatalSrc("Unpacked array with empty indices range");
|
||||
nodep->replaceWith(logp);
|
||||
pushDeletep(nodep); VL_DANGLING(nodep);
|
||||
nodep = logp;
|
||||
}
|
||||
nodep->iterateChildren(*this);
|
||||
}
|
||||
}
|
||||
virtual void visit(AstEq* nodep, AstNUser*) {
|
||||
expandBiOp(nodep);
|
||||
}
|
||||
virtual void visit(AstNeq* nodep, AstNUser*) {
|
||||
expandBiOp(nodep);
|
||||
}
|
||||
virtual void visit(AstEqCase* nodep, AstNUser*) {
|
||||
expandBiOp(nodep);
|
||||
}
|
||||
virtual void visit(AstNeqCase* nodep, AstNUser*) {
|
||||
expandBiOp(nodep);
|
||||
}
|
||||
|
||||
virtual void visit(AstNode* nodep, AstNUser*) {
|
||||
// Default: Just iterate
|
||||
|
||||
+2
-2
@@ -328,7 +328,7 @@ private:
|
||||
setp = new AstConst (outnump->fileline(), *outnump);
|
||||
}
|
||||
// Note InitArray requires us to have the values in inValue order
|
||||
m_tableVarps[outnum]->varp()->valuep()->castInitArray()->addInitsp(setp);
|
||||
m_tableVarps[outnum]->varp()->valuep()->castInitArray()->addValuep(setp);
|
||||
outnum++;
|
||||
}
|
||||
|
||||
@@ -336,7 +336,7 @@ private:
|
||||
if (inValue != inValueNextInitArray++)
|
||||
nodep->v3fatalSrc("InitArray requires us to have the values in inValue order");
|
||||
AstNode* setp = new AstConst (nodep->fileline(), outputChgMask);
|
||||
chgVscp->varp()->valuep()->castInitArray()->addInitsp(setp);
|
||||
chgVscp->varp()->valuep()->castInitArray()->addValuep(setp);
|
||||
}
|
||||
} // each value
|
||||
}
|
||||
|
||||
+9
-4
@@ -584,9 +584,14 @@ private:
|
||||
return new AstCStmt(portp->fileline(), stmt);
|
||||
}
|
||||
|
||||
AstNode* createAssignInternalToDpi(AstVar* portp, bool isPtr, const string& frSuffix, const string& toSuffix) {
|
||||
AstNode* createAssignInternalToDpi(AstVar* portp, bool isRtn, bool isPtr,
|
||||
const string& frSuffix, const string& toSuffix) {
|
||||
// Create assignment from internal format into DPI temporary
|
||||
bool bitvec = (portp->basicp()->isBitLogic() && portp->width() > 32);
|
||||
if (isRtn && bitvec) {
|
||||
portp->v3error("DPI functions cannot return > 32 bits; use a two-state type or task instead: "<<portp->prettyName());
|
||||
// Code below works, but won't compile right, and IEEE illegal
|
||||
}
|
||||
string stmt;
|
||||
string ket;
|
||||
// Someday we'll have better type support, and this can make variables and casts.
|
||||
@@ -727,14 +732,14 @@ private:
|
||||
for (AstNode* stmtp = nodep->stmtsp(); stmtp; stmtp=stmtp->nextp()) {
|
||||
if (AstVar* portp = stmtp->castVar()) {
|
||||
if (portp->isIO() && portp->isOutput() && !portp->isFuncReturn()) {
|
||||
dpip->addStmtsp(createAssignInternalToDpi(portp,true,"__Vcvt",""));
|
||||
dpip->addStmtsp(createAssignInternalToDpi(portp,false,true,"__Vcvt",""));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (rtnvarp) {
|
||||
dpip->addStmtsp(createDpiTemp(rtnvarp,""));
|
||||
dpip->addStmtsp(createAssignInternalToDpi(rtnvarp,false,"__Vcvt",""));
|
||||
dpip->addStmtsp(createAssignInternalToDpi(rtnvarp,true,false,"__Vcvt",""));
|
||||
string stmt = "return "+rtnvarp->name()+";\n";
|
||||
dpip->addStmtsp(new AstCStmt(nodep->fileline(), stmt));
|
||||
}
|
||||
@@ -784,7 +789,7 @@ private:
|
||||
|
||||
cfuncp->addStmtsp(createDpiTemp(portp,"__Vcvt"));
|
||||
if (portp->isInput()) {
|
||||
cfuncp->addStmtsp(createAssignInternalToDpi(portp,false,"","__Vcvt"));
|
||||
cfuncp->addStmtsp(createAssignInternalToDpi(portp,false,false,"","__Vcvt"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+11
-7
@@ -206,8 +206,13 @@ private:
|
||||
AstTraceInc* nodep = vvertexp->nodep();
|
||||
if (nodep->valuep()) {
|
||||
if (nodep->valuep()->backp() != nodep) nodep->v3fatalSrc("Trace duplicate back needs consistency, so we can map duplicates back to TRACEINCs");
|
||||
hashed.hashAndInsert(nodep->valuep());
|
||||
hashed.hash(nodep->valuep());
|
||||
UINFO(8, " Hashed "<<hex<<hashed.nodeHash(nodep->valuep())<<" "<<nodep<<endl);
|
||||
|
||||
// Just keep one node in the map and point all duplicates to this node
|
||||
if (hashed.findDuplicate(nodep->valuep()) == hashed.end()) {
|
||||
hashed.hashAndInsert(nodep->valuep());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -223,11 +228,8 @@ private:
|
||||
TraceTraceVertex* dupvertexp = dynamic_cast<TraceTraceVertex*>(dupincp->user1p()->castGraphVertex());
|
||||
UINFO(8," Orig "<<nodep<<endl);
|
||||
UINFO(8," dup "<<dupincp<<endl);
|
||||
// Mark the found node as a duplicate of the first node
|
||||
// (Not vice-versa as we get the iterator for the found node)
|
||||
dupvertexp->duplicatep(vvertexp);
|
||||
// Remove node from comparison so don't hit it again
|
||||
hashed.erase(dupit);
|
||||
// Mark the hashed node as the original and our iterating node as duplicated
|
||||
vvertexp->duplicatep(dupvertexp);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -493,11 +495,13 @@ private:
|
||||
//if (debug()>=9) nodep->dumpTree(cout,"- assnnode: ");
|
||||
// Find non-duplicated node; note some nodep's maybe null, as they were deleted below
|
||||
TraceTraceVertex* dupvertexp = vvertexp;
|
||||
while (dupvertexp->duplicatep()) {
|
||||
if (dupvertexp->duplicatep()) {
|
||||
dupvertexp = dupvertexp->duplicatep();
|
||||
UINFO(9," dupOf "<<((void*)dupvertexp)<<" "<<((void*)dupvertexp->nodep())
|
||||
<<" "<<dupvertexp<<endl);
|
||||
if (dupvertexp->duplicatep()) dupvertexp->nodep()->v3fatalSrc("Original node was marked as a duplicate");
|
||||
}
|
||||
|
||||
if (dupvertexp != vvertexp) {
|
||||
// It's an exact copy. We'll assign the code to the master on
|
||||
// the first one we hit; the later ones will share the code.
|
||||
|
||||
+1
-1
@@ -68,7 +68,6 @@ private:
|
||||
// Return true if this shouldn't be traced
|
||||
// See also similar rule in V3Coverage::varIgnoreToggle
|
||||
AstVar* varp = nodep->varp();
|
||||
string prettyName = varp->prettyName();
|
||||
if (!varp->isTrace()) {
|
||||
return "Verilator trace_off";
|
||||
}
|
||||
@@ -76,6 +75,7 @@ private:
|
||||
return "Verilator cell trace_off";
|
||||
}
|
||||
else if (!v3Global.opt.traceUnderscore()) {
|
||||
string prettyName = varp->prettyName();
|
||||
if (prettyName.size()>=1 && prettyName[0] == '_')
|
||||
return "Leading underscore";
|
||||
if (prettyName.find("._") != string::npos)
|
||||
|
||||
@@ -0,0 +1,94 @@
|
||||
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
||||
//*************************************************************************
|
||||
// DESCRIPTION: Verilator: Generate AstCReset nodes.
|
||||
//
|
||||
// Code available from: http://www.veripool.org/verilator
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2016 by Wilson Snyder. This program is free software; you can
|
||||
// redistribute it and/or modify it under the terms of either the GNU
|
||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||
// Version 2.0.
|
||||
//
|
||||
// Verilator is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
//*************************************************************************
|
||||
// V3VarReset's Transformations:
|
||||
// Iterates over all modules and creates a _ctor_var_reset AstCFunc
|
||||
// For each variable that needs reset, add a AstCReset node.
|
||||
// This transformation honors outputSplitCFuncs.
|
||||
//*************************************************************************
|
||||
#include "config_build.h"
|
||||
#include "verilatedos.h"
|
||||
#include <cstdio>
|
||||
#include <cstdarg>
|
||||
#include <unistd.h>
|
||||
#include <cmath>
|
||||
#include <map>
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
|
||||
#include "V3Global.h"
|
||||
#include "V3VarResets.h"
|
||||
|
||||
class V3VarReset {
|
||||
private:
|
||||
AstNodeModule* m_modp; // Current module
|
||||
AstCFunc* m_tlFuncp; // Top level function being built
|
||||
AstCFunc* m_funcp; // Current function
|
||||
int m_numStmts; // Number of statements output
|
||||
int m_funcNum; // Function number being built
|
||||
|
||||
void initializeVar(AstVar* nodep) {
|
||||
if (v3Global.opt.outputSplitCFuncs()
|
||||
&& v3Global.opt.outputSplitCFuncs() < m_numStmts) {
|
||||
m_funcp = NULL;
|
||||
}
|
||||
if (!m_funcp) {
|
||||
m_funcp = new AstCFunc(m_modp->fileline(), "_ctor_var_reset_" + cvtToStr(++m_funcNum), NULL, "void");
|
||||
m_funcp->isStatic(false);
|
||||
m_funcp->declPrivate(true);
|
||||
m_funcp->slow(true);
|
||||
m_modp->addStmtp(m_funcp);
|
||||
|
||||
// Add a top call to it
|
||||
AstCCall* callp = new AstCCall(m_modp->fileline(), m_funcp);
|
||||
|
||||
m_tlFuncp->addStmtsp(callp);
|
||||
m_numStmts = 0;
|
||||
}
|
||||
m_funcp->addStmtsp(new AstCReset(nodep->fileline(), new AstVarRef(nodep->fileline(), nodep, true)));
|
||||
m_numStmts += 1;
|
||||
}
|
||||
|
||||
public:
|
||||
V3VarReset(AstNodeModule* nodep) {
|
||||
m_modp = nodep;
|
||||
m_numStmts = 0;
|
||||
m_funcNum = 0;
|
||||
m_tlFuncp = new AstCFunc(nodep->fileline(), "_ctor_var_reset", NULL, "void");
|
||||
m_tlFuncp->declPrivate(true);
|
||||
m_tlFuncp->isStatic(false);
|
||||
m_tlFuncp->slow(true);
|
||||
m_funcp = m_tlFuncp;
|
||||
m_modp->addStmtp(m_tlFuncp);
|
||||
for (AstNode* np = m_modp->stmtsp(); np; np = np->nextp()) {
|
||||
AstVar* varp = np->castVar();
|
||||
if (varp) initializeVar(varp);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
//######################################################################
|
||||
|
||||
void V3VarResets::emitResets() {
|
||||
UINFO(2,__FUNCTION__<<": "<<endl);
|
||||
for (AstNodeModule* nodep = v3Global.rootp()->modulesp(); nodep; nodep=nodep->nextp()->castNodeModule()) {
|
||||
// Process each module in turn
|
||||
V3VarReset v(nodep);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
||||
//*************************************************************************
|
||||
// DESCRIPTION: Verilator: Emit C++ code for module tree
|
||||
//
|
||||
// Code available from: http://www.veripool.org/verilator
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2016 by Wilson Snyder. This program is free software; you can
|
||||
// redistribute it and/or modify it under the terms of either the GNU
|
||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||
// Version 2.0.
|
||||
//
|
||||
// Verilator is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
//*************************************************************************
|
||||
|
||||
#ifndef _V3VARRESETS_H_
|
||||
#define _V3VARRESETS_H_ 1
|
||||
#include "config_build.h"
|
||||
#include "verilatedos.h"
|
||||
#include "V3Error.h"
|
||||
#include "V3Ast.h"
|
||||
|
||||
//============================================================================
|
||||
|
||||
class V3VarResets {
|
||||
public:
|
||||
static void emitResets();
|
||||
};
|
||||
|
||||
|
||||
#endif // Guard
|
||||
+62
-25
@@ -151,6 +151,26 @@ ostream& operator<<(ostream& str, const WidthVP* vup) {
|
||||
|
||||
//######################################################################
|
||||
|
||||
class WidthClearVisitor {
|
||||
// Rather than a AstNVisitor, can just quickly touch every node
|
||||
void clearWidthRecurse(AstNode* nodep) {
|
||||
nodep->didWidth(false);
|
||||
if (nodep->op1p()) clearWidthRecurse(nodep->op1p());
|
||||
if (nodep->op2p()) clearWidthRecurse(nodep->op2p());
|
||||
if (nodep->op3p()) clearWidthRecurse(nodep->op3p());
|
||||
if (nodep->op4p()) clearWidthRecurse(nodep->op4p());
|
||||
if (nodep->nextp()) clearWidthRecurse(nodep->nextp());
|
||||
}
|
||||
public:
|
||||
// CONSTUCTORS
|
||||
explicit WidthClearVisitor(AstNetlist* nodep) {
|
||||
clearWidthRecurse(nodep);
|
||||
}
|
||||
virtual ~WidthClearVisitor() {}
|
||||
};
|
||||
|
||||
//######################################################################
|
||||
|
||||
class WidthVisitor : public AstNVisitor {
|
||||
private:
|
||||
// TYPES
|
||||
@@ -913,6 +933,9 @@ private:
|
||||
// calculation would return identical values. Therefore we can directly replace the width
|
||||
nodep->widthForce(nodep->rangep()->elementsConst(), nodep->rangep()->elementsConst());
|
||||
}
|
||||
else if (nodep->isRanged()) {
|
||||
nodep->widthForce(nodep->nrange().elements(), nodep->nrange().elements());
|
||||
}
|
||||
else if (nodep->implicit()) {
|
||||
// Parameters may notice implicitness and change to different dtype
|
||||
nodep->widthForce(1,1);
|
||||
@@ -951,6 +974,13 @@ private:
|
||||
nodep->iterateChildren(*this);
|
||||
nodep->dtypep(iterateEditDTypep(nodep, nodep->subDTypep()));
|
||||
}
|
||||
virtual void visit(AstParamTypeDType* nodep, AstNUser*) {
|
||||
if (nodep->didWidthAndSet()) return; // This node is a dtype & not both PRELIMed+FINALed
|
||||
if (nodep->childDTypep()) nodep->dtypep(moveChildDTypeEdit(nodep));
|
||||
nodep->iterateChildren(*this);
|
||||
nodep->dtypep(iterateEditDTypep(nodep, nodep->subDTypep()));
|
||||
nodep->widthFromSub(nodep->subDTypep());
|
||||
}
|
||||
virtual void visit(AstCastParse* nodep, AstNUser* vup) {
|
||||
// nodep->dtp could be data type, or a primary_constant
|
||||
// Don't iterate lhsp, will deal with that once convert the type
|
||||
@@ -1157,7 +1187,7 @@ private:
|
||||
// Note genvar's are also entered as integers
|
||||
nodep->dtypeFrom(nodep->varp());
|
||||
if (nodep->backp()->castNodeAssign() && nodep->lvalue()) { // On LHS
|
||||
if (!nodep->widthMin()) v3fatalSrc("LHS var should be size complete");
|
||||
if (!nodep->widthMin()) nodep->v3fatalSrc("LHS var should be size complete");
|
||||
}
|
||||
//if (debug()>=9) nodep->dumpTree(cout," VRout ");
|
||||
if (nodep->lvalue() && nodep->varp()->isConst()
|
||||
@@ -1463,6 +1493,7 @@ private:
|
||||
nodep->v3error("Unsupported: Arguments passed to enum.next method");
|
||||
}
|
||||
// Need a runtime lookup table. Yuk.
|
||||
// Most enums unless overridden are 32 bits, so we size array based on max enum value used.
|
||||
// Ideally we would have a fast algorithm when a number is
|
||||
// of small width and complete and so can use an array, and
|
||||
// a map for when the value is many bits and sparse.
|
||||
@@ -1473,15 +1504,20 @@ private:
|
||||
if (!vconstp) nodep->v3fatalSrc("Enum item without constified value");
|
||||
if (vconstp->toUQuad() >= msbdim) msbdim = vconstp->toUQuad();
|
||||
}
|
||||
if (adtypep->itemsp()->width() > 64 || msbdim >= 1024) {
|
||||
if (adtypep->itemsp()->width() > 64 || msbdim >= (1<<16)) {
|
||||
nodep->v3error("Unsupported; enum next/prev method on enum with > 10 bits");
|
||||
return;
|
||||
}
|
||||
}
|
||||
AstVar* varp = enumVarp(adtypep, attrType, msbdim);
|
||||
int selwidth = V3Number::log2b(msbdim)+1; // Width to address a bit
|
||||
AstVar* varp = enumVarp(adtypep, attrType, (VL_ULL(1)<<selwidth)-1);
|
||||
AstVarRef* varrefp = new AstVarRef(nodep->fileline(), varp, false);
|
||||
varrefp->packagep(v3Global.rootp()->dollarUnitPkgAddp());
|
||||
AstNode* newp = new AstArraySel(nodep->fileline(), varrefp, nodep->fromp()->unlinkFrBack());
|
||||
AstNode* newp = new AstArraySel(nodep->fileline(), varrefp,
|
||||
// Select in case widths are off due to msblen!=width
|
||||
new AstSel(nodep->fileline(),
|
||||
nodep->fromp()->unlinkFrBack(),
|
||||
0, selwidth));
|
||||
nodep->replaceWith(newp); nodep->deleteTree(); VL_DANGLING(nodep);
|
||||
} else {
|
||||
nodep->v3error("Unknown built-in enum method '"<<nodep->fromp()->prettyTypeName()<<"'");
|
||||
@@ -1667,11 +1703,13 @@ private:
|
||||
}
|
||||
if (arrayp->castUnpackArrayDType()) {
|
||||
if (!newp) {
|
||||
newp = new AstInitArray(nodep->fileline(), arrayp, valuep);
|
||||
AstInitArray* newap = new AstInitArray(nodep->fileline(), arrayp, NULL);
|
||||
newap->addValuep(valuep);
|
||||
newp = newap;
|
||||
} else {
|
||||
// We iterate hi()..lo() as that is what packed needs,
|
||||
// but INITARRAY needs lo() first
|
||||
newp->castInitArray()->initsp()->addHereThisAsNext(valuep);
|
||||
newp->castInitArray()->addFrontValuep(valuep);
|
||||
}
|
||||
} else { // Packed. Convert to concat for now.
|
||||
if (!newp) newp = valuep;
|
||||
@@ -2594,9 +2632,6 @@ private:
|
||||
AstNode* shiftp = nodep->rhsp();
|
||||
nodep->rhsp()->replaceWith(new AstConst(shiftp->fileline(), num));
|
||||
shiftp->deleteTree(); VL_DANGLING(shiftp);
|
||||
} else {
|
||||
nodep->rhsp()->v3error("Unsupported: Shifting of by over 32-bit number isn't supported."
|
||||
<<" (This isn't a shift of 32 bits, but a shift of 2^32, or 4 billion!)\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2724,6 +2759,7 @@ private:
|
||||
if (nodep->width()==0) nodep->v3fatalSrc("Under node "<<nodep->prettyTypeName()<<" has no expected width?? Missing Visitor func?");
|
||||
if (expWidth==0) nodep->v3fatalSrc("Node "<<nodep->prettyTypeName()<<" has no expected width?? Missing Visitor func?");
|
||||
if (expWidthMin==0) expWidthMin = expWidth;
|
||||
if (nodep->dtypep()->width() == expWidth) return false;
|
||||
if (nodep->dtypep()->widthSized() && nodep->width() != expWidthMin) return true;
|
||||
if (!nodep->dtypep()->widthSized() && nodep->widthMin() > expWidthMin) return true;
|
||||
return false;
|
||||
@@ -3372,9 +3408,9 @@ private:
|
||||
// Add to root, as don't know module we are in, and aids later structure sharing
|
||||
v3Global.rootp()->dollarUnitPkgAddp()->addStmtp(varp);
|
||||
// Element 0 is a non-index and has speced values
|
||||
initp->addInitsp(dimensionValue(nodep, attrType, 0));
|
||||
initp->addValuep(dimensionValue(nodep, attrType, 0));
|
||||
for (unsigned i=1; i<msbdim+1; ++i) {
|
||||
initp->addInitsp(dimensionValue(nodep, attrType, i));
|
||||
initp->addValuep(dimensionValue(nodep, attrType, i));
|
||||
}
|
||||
varp->iterate(*this); // May have already done $unit so must do this var
|
||||
m_tableMap.insert(make_pair(make_pair(nodep,attrType), varp));
|
||||
@@ -3382,7 +3418,7 @@ private:
|
||||
}
|
||||
AstVar* enumVarp(AstEnumDType* nodep, AstAttrType attrType, uint32_t msbdim) {
|
||||
// Return a variable table which has specified dimension properties for this variable
|
||||
TableMap::iterator pos = m_tableMap.find(make_pair(nodep,attrType));
|
||||
TableMap::iterator pos = m_tableMap.find(make_pair(nodep, attrType));
|
||||
if (pos != m_tableMap.end()) {
|
||||
return pos->second;
|
||||
}
|
||||
@@ -3391,7 +3427,7 @@ private:
|
||||
if (attrType == AstAttrType::ENUM_NAME) {
|
||||
basep = nodep->findStringDType();
|
||||
} else {
|
||||
basep = nodep->findSigned32DType();
|
||||
basep = nodep->dtypep();
|
||||
}
|
||||
AstNodeArrayDType* vardtypep = new AstUnpackArrayDType(nodep->fileline(),
|
||||
basep,
|
||||
@@ -3407,6 +3443,16 @@ private:
|
||||
// Add to root, as don't know module we are in, and aids later structure sharing
|
||||
v3Global.rootp()->dollarUnitPkgAddp()->addStmtp(varp);
|
||||
|
||||
// Default for all unspecified values
|
||||
if (attrType == AstAttrType::ENUM_NAME) {
|
||||
initp->defaultp(new AstConst(nodep->fileline(), AstConst::String(), ""));
|
||||
} else if (attrType == AstAttrType::ENUM_NEXT
|
||||
|| attrType == AstAttrType::ENUM_PREV) {
|
||||
initp->defaultp(new AstConst(nodep->fileline(), V3Number(nodep->fileline(), nodep->width(), 0)));
|
||||
} else {
|
||||
nodep->v3fatalSrc("Bad case");
|
||||
}
|
||||
|
||||
// Find valid values and populate
|
||||
if (!nodep->itemsp()) nodep->v3fatalSrc("enum without items");
|
||||
vector<AstNode*> values;
|
||||
@@ -3436,20 +3482,10 @@ private:
|
||||
itemp = nextp;
|
||||
}
|
||||
}
|
||||
// Fill in all unspecified values and add to table
|
||||
// Add all specified values to table
|
||||
for (unsigned i=0; i<(msbdim+1); ++i) {
|
||||
AstNode* valp = values[i];
|
||||
if (!valp) {
|
||||
if (attrType == AstAttrType::ENUM_NAME) {
|
||||
valp = new AstConst(nodep->fileline(), AstConst::String(), "");
|
||||
} else if (attrType == AstAttrType::ENUM_NEXT
|
||||
|| attrType == AstAttrType::ENUM_PREV) {
|
||||
valp = new AstConst(nodep->fileline(), V3Number(nodep->fileline(), nodep->width(), 0));
|
||||
} else {
|
||||
nodep->v3fatalSrc("Bad case");
|
||||
}
|
||||
}
|
||||
initp->addInitsp(valp);
|
||||
if (valp) initp->addIndexValuep(i, valp);
|
||||
}
|
||||
varp->iterate(*this); // May have already done $unit so must do this var
|
||||
m_tableMap.insert(make_pair(make_pair(nodep,attrType), varp));
|
||||
@@ -3528,6 +3564,7 @@ int V3Width::debug() {
|
||||
void V3Width::width(AstNetlist* nodep) {
|
||||
UINFO(2,__FUNCTION__<<": "<<endl);
|
||||
// We should do it in bottom-up module order, but it works in any order.
|
||||
WidthClearVisitor cvisitor (nodep);
|
||||
WidthVisitor visitor (false, false);
|
||||
(void)visitor.mainAcceptEdit(nodep);
|
||||
WidthRemoveVisitor rvisitor;
|
||||
|
||||
@@ -128,9 +128,17 @@ private:
|
||||
visitIterateNodeDType(nodep);
|
||||
}
|
||||
virtual void visit(AstNodeClassDType* nodep, AstNUser*) {
|
||||
if (nodep->user1SetOnce()) return; // Process once
|
||||
visitIterateNodeDType(nodep);
|
||||
nodep->clearCache();
|
||||
}
|
||||
virtual void visit(AstParamTypeDType* nodep, AstNUser*) {
|
||||
if (nodep->user1SetOnce()) return; // Process once
|
||||
visitIterateNodeDType(nodep);
|
||||
// Move to type table as all dtype pointers must resolve there
|
||||
nodep->unlinkFrBack(); // Make non-child
|
||||
v3Global.rootp()->typeTablep()->addTypesp(nodep);
|
||||
}
|
||||
void visitIterateNodeDType(AstNodeDType* nodep) {
|
||||
// Rather than use dtypeChg which may make new nodes, we simply edit in place,
|
||||
// as we don't need to preserve any widthMin's, and every dtype with the same width
|
||||
|
||||
+11
-4
@@ -39,6 +39,7 @@
|
||||
#include "V3Const.h"
|
||||
#include "V3Coverage.h"
|
||||
#include "V3CoverageJoin.h"
|
||||
#include "V3VarResets.h"
|
||||
#include "V3Dead.h"
|
||||
#include "V3Delayed.h"
|
||||
#include "V3Depth.h"
|
||||
@@ -160,6 +161,8 @@ void process () {
|
||||
// Cross-link dotted hierarchical references
|
||||
V3LinkDot::linkDotPrimary(v3Global.rootp());
|
||||
v3Global.checkTree(); // Force a check, as link is most likely place for problems
|
||||
// Check if all parameters have been found
|
||||
v3Global.opt.checkParameters();
|
||||
// Correct state we couldn't know at parse time, repair SEL's
|
||||
V3LinkResolve::linkResolve(v3Global.rootp());
|
||||
// Set Lvalue's in variable refs
|
||||
@@ -282,7 +285,7 @@ void process () {
|
||||
if (!v3Global.opt.xmlOnly()) {
|
||||
// Cleanup
|
||||
V3Const::constifyAll(v3Global.rootp());
|
||||
V3Dead::deadifyDTypes(v3Global.rootp());
|
||||
V3Dead::deadifyDTypesScoped(v3Global.rootp());
|
||||
v3Global.checkTree();
|
||||
|
||||
// Convert case statements to if() blocks. Must be after V3Unknown
|
||||
@@ -317,7 +320,7 @@ void process () {
|
||||
|
||||
// Cleanup
|
||||
V3Const::constifyAll(v3Global.rootp());
|
||||
V3Dead::deadifyDTypes(v3Global.rootp());
|
||||
V3Dead::deadifyDTypesScoped(v3Global.rootp());
|
||||
v3Global.checkTree();
|
||||
|
||||
// Detect clock enables and mode into sensitives, and split always based on clocks
|
||||
@@ -357,7 +360,7 @@ void process () {
|
||||
|
||||
// Remove unused vars
|
||||
V3Const::constifyAll(v3Global.rootp());
|
||||
V3Dead::deadifyAll(v3Global.rootp());
|
||||
V3Dead::deadifyAllScoped(v3Global.rootp());
|
||||
|
||||
// Clock domain crossing analysis
|
||||
if (v3Global.opt.cdc()) {
|
||||
@@ -402,7 +405,7 @@ void process () {
|
||||
|
||||
// Remove unused vars
|
||||
V3Const::constifyAll(v3Global.rootp());
|
||||
V3Dead::deadifyAll(v3Global.rootp());
|
||||
V3Dead::deadifyAllScoped(v3Global.rootp());
|
||||
|
||||
// Detect change loop
|
||||
V3Changed::changedAll(v3Global.rootp());
|
||||
@@ -495,6 +498,10 @@ void process () {
|
||||
}
|
||||
|
||||
V3Error::abortIfErrors();
|
||||
if (!v3Global.opt.lintOnly()
|
||||
&& !v3Global.opt.xmlOnly()) {
|
||||
V3VarResets::emitResets();
|
||||
}
|
||||
|
||||
// Output the text
|
||||
if (!v3Global.opt.lintOnly()
|
||||
|
||||
@@ -19,6 +19,7 @@ my $Opt_Prefix = $ARGV[0] or die "%Error: No prefix specified,";
|
||||
|
||||
foreach my $line (<STDIN>) {
|
||||
# Fix flex 2.6.0 warning
|
||||
$line =~ s/ > YY_CURRENT_BUFFER_LVALUE->yy_buf_size/ > (int) YY_CURRENT_BUFFER_LVALUE->yy_buf_size/;
|
||||
$line =~ s/ number_to_move == YY_MORE_ADJ / (int)number_to_move == (int)YY_MORE_ADJ /;
|
||||
# Fix flex 2.5.4 namespace omission
|
||||
$line =~ s/^class istream;/\#include <iostream>\nusing namespace std;\n/;
|
||||
|
||||
+8
-4
@@ -261,6 +261,7 @@ vnum {vnum1}|{vnum2}|{vnum3}|{vnum4}|{vnum5}
|
||||
"endtable" { yyerrorf("Syntax error: ENDTABLE outside of TABLE"); }
|
||||
"endtask" { FL; return yENDTASK; }
|
||||
"for" { FL; return yFOR; }
|
||||
"foreach" { FL; return yFOREACH; }
|
||||
"forever" { FL; return yFOREVER; }
|
||||
"function" { FL; return yFUNCTION; }
|
||||
"if" { FL; return yIF; }
|
||||
@@ -459,6 +460,7 @@ vnum {vnum1}|{vnum2}|{vnum3}|{vnum4}|{vnum5}
|
||||
"struct" { FL; return ySTRUCT; }
|
||||
"timeprecision" { FL; return yTIMEPRECISION; }
|
||||
"timeunit" { FL; return yTIMEUNIT; }
|
||||
"type" { FL; return yTYPE; }
|
||||
"typedef" { FL; return yTYPEDEF; }
|
||||
"union" { FL; return yUNION; }
|
||||
"unique" { FL; return yUNIQUE; }
|
||||
@@ -485,7 +487,6 @@ vnum {vnum1}|{vnum2}|{vnum3}|{vnum4}|{vnum5}
|
||||
"extends" { yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented: %s",yytext); }
|
||||
"extern" { yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented: %s",yytext); }
|
||||
"first_match" { yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented: %s",yytext); }
|
||||
"foreach" { yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented: %s",yytext); }
|
||||
"forkjoin" { yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented: %s",yytext); }
|
||||
"ignore_bins" { yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented: %s",yytext); }
|
||||
"illegal_bins" { yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented: %s",yytext); }
|
||||
@@ -508,7 +509,6 @@ vnum {vnum1}|{vnum2}|{vnum3}|{vnum4}|{vnum5}
|
||||
"tagged" { yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented: %s",yytext); }
|
||||
"this" { yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented: %s",yytext); }
|
||||
"throughout" { yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented: %s",yytext); }
|
||||
"type" { yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented: %s",yytext); }
|
||||
"virtual" { yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented: %s",yytext); }
|
||||
"wait_order" { yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented: %s",yytext); }
|
||||
"wildcard" { yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented: %s",yytext); }
|
||||
@@ -975,9 +975,10 @@ vnum {vnum1}|{vnum2}|{vnum3}|{vnum4}|{vnum5}
|
||||
%%
|
||||
int V3ParseImp::stateVerilogRecent() { return STATE_VERILOG_RECENT; }
|
||||
|
||||
double V3ParseImp::parseDouble(const char* textp, size_t length) {
|
||||
double V3ParseImp::parseDouble(const char* textp, size_t length, bool* successp) {
|
||||
char* strgp = new char[length+1];
|
||||
char* dp=strgp;
|
||||
if (successp) *successp = true;
|
||||
for (const char* sp=textp; sp<(textp+length); ++sp) {
|
||||
if (*sp != '_') *dp++ = *sp;
|
||||
}
|
||||
@@ -985,7 +986,10 @@ double V3ParseImp::parseDouble(const char* textp, size_t length) {
|
||||
char* endp = strgp;
|
||||
double d = strtod(strgp, &endp);
|
||||
size_t parsed_len = endp-strgp;
|
||||
if (parsed_len != strlen(strgp)) { yyerrorf("Syntax error parsing real: %s",strgp); }
|
||||
if (parsed_len != strlen(strgp)) {
|
||||
if (successp) *successp = false;
|
||||
else yyerrorf("Syntax error parsing real: %s",strgp);
|
||||
}
|
||||
delete[] strgp;
|
||||
return d;
|
||||
}
|
||||
|
||||
+73
-13
@@ -344,6 +344,7 @@ class AstSenTree;
|
||||
%token<fl> yEXPORT "export"
|
||||
%token<fl> yFINAL "final"
|
||||
%token<fl> yFOR "for"
|
||||
%token<fl> yFOREACH "foreach"
|
||||
%token<fl> yFOREVER "forever"
|
||||
%token<fl> yFUNCTION "function"
|
||||
%token<fl> yGENERATE "generate"
|
||||
@@ -421,6 +422,7 @@ class AstSenTree;
|
||||
%token<fl> yTRI0 "tri0"
|
||||
%token<fl> yTRI1 "tri1"
|
||||
%token<fl> yTRUE "true"
|
||||
%token<fl> yTYPE "type"
|
||||
%token<fl> yTYPEDEF "typedef"
|
||||
%token<fl> yUNION "union"
|
||||
%token<fl> yUNIQUE "unique"
|
||||
@@ -805,7 +807,7 @@ udpFront<modulep>:
|
||||
|
||||
parameter_value_assignmentE<pinp>: // IEEE: [ parameter_value_assignment ]
|
||||
/* empty */ { $$ = NULL; }
|
||||
| '#' '(' cellpinList ')' { $$ = $3; }
|
||||
| '#' '(' cellparamList ')' { $$ = $3; }
|
||||
// // Parentheses are optional around a single parameter
|
||||
| '#' yaINTNUM { $$ = new AstPin($1,1,"",new AstConst($1,*$2)); }
|
||||
| '#' yaFLOATNUM { $$ = new AstPin($1,1,"",new AstConst($1,AstConst::Unsized32(),(int)(($2<0)?($2-0.5):($2+0.5)))); }
|
||||
@@ -1123,6 +1125,7 @@ genvar_identifierDecl<varp>: // IEEE: genvar_identifier (for declaration)
|
||||
|
||||
local_parameter_declaration<nodep>: // IEEE: local_parameter_declaration
|
||||
// // See notes in parameter_declaration
|
||||
// // Front must execute first so VARDTYPE is ready before list of vars
|
||||
local_parameter_declarationFront list_of_param_assignments { $$ = $2; }
|
||||
;
|
||||
|
||||
@@ -1131,30 +1134,33 @@ parameter_declaration<nodep>: // IEEE: parameter_declaration
|
||||
// // Instead of list_of_type_assignments
|
||||
// // we use list_of_param_assignments because for port handling
|
||||
// // it already must accept types, so simpler to have code only one place
|
||||
// // Front must execute first so VARDTYPE is ready before list of vars
|
||||
parameter_declarationFront list_of_param_assignments { $$ = $2; }
|
||||
;
|
||||
|
||||
local_parameter_declarationFront: // IEEE: local_parameter_declaration w/o assignment
|
||||
// // Front must execute first so VARDTYPE is ready before list of vars
|
||||
varLParamReset implicit_typeE { /*VARRESET-in-varLParam*/ VARDTYPE($2); }
|
||||
| varLParamReset data_type { /*VARRESET-in-varLParam*/ VARDTYPE($2); }
|
||||
//UNSUP varLParamReset yTYPE { /*VARRESET-in-varLParam*/ VARDTYPE($2); }
|
||||
| varLParamReset yTYPE { /*VARRESET-in-varLParam*/ VARDTYPE(new AstParseTypeDType($2)); }
|
||||
;
|
||||
|
||||
parameter_declarationFront: // IEEE: parameter_declaration w/o assignment
|
||||
// // Front must execute first so VARDTYPE is ready before list of vars
|
||||
varGParamReset implicit_typeE { /*VARRESET-in-varGParam*/ VARDTYPE($2); }
|
||||
| varGParamReset data_type { /*VARRESET-in-varGParam*/ VARDTYPE($2); }
|
||||
//UNSUP varGParamReset yTYPE { /*VARRESET-in-varGParam*/ VARDTYPE($2); }
|
||||
| varGParamReset yTYPE { /*VARRESET-in-varGParam*/ VARDTYPE(new AstParseTypeDType($2)); }
|
||||
;
|
||||
|
||||
parameter_port_declarationFrontE: // IEEE: parameter_port_declaration w/o assignment
|
||||
// // IEEE: parameter_declaration (minus assignment)
|
||||
// // Front must execute first so VARDTYPE is ready before list of vars
|
||||
varGParamReset implicit_typeE { /*VARRESET-in-varGParam*/ VARDTYPE($2); }
|
||||
| varGParamReset data_type { /*VARRESET-in-varGParam*/ VARDTYPE($2); }
|
||||
| varGParamReset yTYPE { /*VARRESET-in-varGParam*/ VARDTYPE(new AstParseTypeDType($2)); }
|
||||
| implicit_typeE { /*VARRESET-in-varGParam*/ VARDTYPE($1); }
|
||||
| data_type { /*VARRESET-in-varGParam*/ VARDTYPE($1); }
|
||||
//UNSUP varGParamReset yTYPE { /*VARRESET-in-varGParam*/ VARDTYPE($2); }
|
||||
//UNSUP data_type { VARDTYPE($1); }
|
||||
//UNSUP yTYPE { VARDTYPE($1); }
|
||||
| yTYPE { /*VARRESET-in-varGParam*/ VARDTYPE(new AstParseTypeDType($1)); }
|
||||
;
|
||||
|
||||
net_declaration<nodep>: // IEEE: net_declaration - excluding implict
|
||||
@@ -1988,9 +1994,9 @@ packed_dimension<rangep>: // ==IEEE: packed_dimension
|
||||
param_assignment<varp>: // ==IEEE: param_assignment
|
||||
// // IEEE: constant_param_expression
|
||||
// // constant_param_expression: '$' is in expr
|
||||
id/*new-parameter*/ variable_dimensionListE sigAttrListE '=' expr
|
||||
// // note exptOrDataType being a data_type is only for yPARAMETER yTYPE
|
||||
id/*new-parameter*/ variable_dimensionListE sigAttrListE '=' exprOrDataType
|
||||
/**/ { $$ = VARDONEA($<fl>1,*$1, $2, $3); $$->valuep($5); }
|
||||
//UNSUP: exprOrDataType instead of expr
|
||||
;
|
||||
|
||||
list_of_param_assignments<varp>: // ==IEEE: list_of_param_assignments
|
||||
@@ -2067,16 +2073,25 @@ instRangeE<rangep>:
|
||||
| '[' constExpr ':' constExpr ']' { $$ = new AstRange($1,$2,$4); }
|
||||
;
|
||||
|
||||
cellparamList<pinp>:
|
||||
{VARRESET_LIST(UNKNOWN);} cellparamItList { $$ = $2; VARRESET_NONLIST(UNKNOWN); }
|
||||
;
|
||||
|
||||
cellpinList<pinp>:
|
||||
{VARRESET_LIST(UNKNOWN);} cellpinItList { $$ = $2; VARRESET_NONLIST(UNKNOWN); }
|
||||
;
|
||||
|
||||
cellpinItList<pinp>: // IEEE: list_of_port_connections + list_of_parameter_assignmente
|
||||
cellparamItList<pinp>: // IEEE: list_of_parameter_assignmente
|
||||
cellparamItemE { $$ = $1; }
|
||||
| cellparamItList ',' cellparamItemE { $$ = $1->addNextNull($3)->castPin(); }
|
||||
;
|
||||
|
||||
cellpinItList<pinp>: // IEEE: list_of_port_connections
|
||||
cellpinItemE { $$ = $1; }
|
||||
| cellpinItList ',' cellpinItemE { $$ = $1->addNextNull($3)->castPin(); }
|
||||
;
|
||||
|
||||
cellpinItemE<pinp>: // IEEE: named_port_connection + named_parameter_assignment + empty
|
||||
cellparamItemE<pinp>: // IEEE: named_parameter_assignment + empty
|
||||
// Note empty can match either () or (,); V3LinkCells cleans up ()
|
||||
/* empty: ',,' is legal */ { $$ = new AstPin(CRELINE(),PINNUMINC(),"",NULL); }
|
||||
| yP_DOTSTAR { $$ = new AstPin($1,PINNUMINC(),".*",NULL); }
|
||||
@@ -2088,9 +2103,26 @@ cellpinItemE<pinp>: // IEEE: named_port_connection + named_parameter_assignment
|
||||
//UNSUP '.' idAny '(' expr ':' expr ')' { }
|
||||
//UNSUP '.' idAny '(' expr ':' expr ':' expr ')' { }
|
||||
// // For parameters
|
||||
//UNSUP '.' idAny '(' data_type ')' { PINDONE($1,$2,$4); GRAMMARP->pinNumInc(); }
|
||||
| '.' idAny '(' data_type ')' { $$ = new AstPin($1,PINNUMINC(),*$2,$4); }
|
||||
// // For parameters
|
||||
//UNSUP data_type { PINDONE($1->fileline(),"",$1); GRAMMARP->pinNumInc(); }
|
||||
| data_type { $$ = new AstPin($1->fileline(),PINNUMINC(),"",$1); }
|
||||
//
|
||||
| expr { $$ = new AstPin($1->fileline(),PINNUMINC(),"",$1); }
|
||||
//UNSUP expr ':' expr { }
|
||||
//UNSUP expr ':' expr ':' expr { }
|
||||
;
|
||||
|
||||
cellpinItemE<pinp>: // IEEE: named_port_connection + empty
|
||||
// Note empty can match either () or (,); V3LinkCells cleans up ()
|
||||
/* empty: ',,' is legal */ { $$ = new AstPin(CRELINE(),PINNUMINC(),"",NULL); }
|
||||
| yP_DOTSTAR { $$ = new AstPin($1,PINNUMINC(),".*",NULL); }
|
||||
| '.' idSVKwd { $$ = new AstPin($1,PINNUMINC(),*$2,new AstVarRef($1,*$2,false)); $$->svImplicit(true);}
|
||||
| '.' idAny { $$ = new AstPin($1,PINNUMINC(),*$2,new AstVarRef($1,*$2,false)); $$->svImplicit(true);}
|
||||
| '.' idAny '(' ')' { $$ = new AstPin($1,PINNUMINC(),*$2,NULL); }
|
||||
// // mintypmax is expanded here, as it might be a UDP or gate primitive
|
||||
| '.' idAny '(' expr ')' { $$ = new AstPin($1,PINNUMINC(),*$2,$4); }
|
||||
//UNSUP '.' idAny '(' expr ':' expr ')' { }
|
||||
//UNSUP '.' idAny '(' expr ':' expr ':' expr ')' { }
|
||||
//
|
||||
| expr { $$ = new AstPin($1->fileline(),PINNUMINC(),"",$1); }
|
||||
//UNSUP expr ':' expr { }
|
||||
@@ -2296,7 +2328,7 @@ statement_item<nodep>: // IEEE: statement_item
|
||||
{ $$ = new AstBegin($1,"",$3); $3->addNext(new AstWhile($1, $4,$8,$6)); }
|
||||
| yDO stmtBlock yWHILE '(' expr ')' ';' { $$ = $2->cloneTree(true); $$->addNext(new AstWhile($1,$5,$2));}
|
||||
// // IEEE says array_identifier here, but dotted accepted in VMM and 1800-2009
|
||||
//UNSUP yFOREACH '(' idClassForeach/*array_id[loop_variables]*/ ')' stmt { UNSUP }
|
||||
| yFOREACH '(' idClassForeach '[' loop_variables ']' ')' stmtBlock { $$ = new AstForeach($1,$3,$5,$8); }
|
||||
//
|
||||
// // IEEE: jump_statement
|
||||
| yRETURN ';' { $$ = new AstReturn($1); }
|
||||
@@ -2528,6 +2560,11 @@ for_step<nodep>: // IEEE: for_step
|
||||
genvar_iteration { $$ = $1; }
|
||||
;
|
||||
|
||||
loop_variables<nodep>: // IEEE: loop_variables
|
||||
varRefBase { $$ = $1; }
|
||||
| loop_variables ',' varRefBase { $$ = $1;$1->addNext($3); }
|
||||
;
|
||||
|
||||
//************************************************
|
||||
// Functions/tasks
|
||||
|
||||
@@ -2674,6 +2711,12 @@ system_f_call<nodep>: // IEEE: system_tf_call (as func)
|
||||
| yD_VALUEPLUSARGS '(' str ',' expr ')' { $$ = new AstValuePlusArgs($1,*$3,$5); }
|
||||
;
|
||||
|
||||
exprOrDataType<nodep>: // expr | data_type: combined to prevent conflicts
|
||||
expr { $$ = $1; }
|
||||
// // data_type includes id that overlaps expr, so special flavor
|
||||
| data_type { $$ = $1; }
|
||||
;
|
||||
|
||||
list_of_argumentsE<nodep>: // IEEE: [list_of_arguments]
|
||||
argsDottedList { $$ = $1; }
|
||||
| argsExprListE { if ($1->castArg() && $1->castArg()->emptyConnectNoNext()) { $1->deleteTree(); $$ = NULL; } // Mis-created when have 'func()'
|
||||
@@ -3509,6 +3552,17 @@ idArrayed<nodep>: // IEEE: id + select
|
||||
| idArrayed '[' expr yP_MINUSCOLON constExpr ']' { $$ = new AstSelMinus($2,$1,$3,$5); }
|
||||
;
|
||||
|
||||
idClassForeach<nodep>:
|
||||
idForeach { $$ = $1; }
|
||||
| package_scopeIdFollows idForeach { $$ = AstDot::newIfPkg($2->fileline(), $1, $2); }
|
||||
;
|
||||
|
||||
idForeach<nodep>:
|
||||
varRefBase { $$ = $1; }
|
||||
| idForeach '.' varRefBase { $$ = new AstDot($2,$1,$3); }
|
||||
;
|
||||
|
||||
|
||||
// VarRef without any dots or vectorizaion
|
||||
varRefBase<varrefp>:
|
||||
id { $$ = new AstVarRef($<fl>1,*$1,false);}
|
||||
@@ -3765,6 +3819,12 @@ AstVar* V3ParseGrammar::createVariable(FileLine* fileline, string name, AstRange
|
||||
if (GRAMMARP->m_varDecl == AstVarType::SUPPLY1) {
|
||||
nodep->addNext(V3ParseGrammar::createSupplyExpr(fileline, nodep->name(), 1));
|
||||
}
|
||||
if (dtypep->castParseTypeDType()) {
|
||||
// Parser needs to know what is a type
|
||||
AstNode* newp = new AstTypedefFwd(fileline, name);
|
||||
nodep->addNext(newp);
|
||||
SYMP->reinsert(newp);
|
||||
}
|
||||
// Don't set dtypep in the ranging;
|
||||
// We need to autosize parameters and integers separately
|
||||
//
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
// please note it here, otherwise:**
|
||||
//
|
||||
// This file ONLY is placed into the Public Domain, for any use,
|
||||
// without warranty, 2015 by ____YOUR_NAME_HERE____.
|
||||
// without warranty, 2016 by ____YOUR_NAME_HERE____.
|
||||
|
||||
module t (/*AUTOARG*/
|
||||
// Inputs
|
||||
|
||||
Executable
+18
@@ -0,0 +1,18 @@
|
||||
#!/usr/bin/perl
|
||||
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
|
||||
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||
#
|
||||
# Copyright 2003 by Wilson Snyder. This program is free software; you can
|
||||
# redistribute it and/or modify it under the terms of either the GNU
|
||||
# Lesser General Public License Version 3 or the Perl Artistic License
|
||||
# Version 2.0.
|
||||
|
||||
compile (
|
||||
);
|
||||
|
||||
execute (
|
||||
check_finished=>1,
|
||||
);
|
||||
|
||||
ok(1);
|
||||
1;
|
||||
@@ -0,0 +1,58 @@
|
||||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// This file ONLY is placed into the Public Domain, for any use,
|
||||
// without warranty, 2016 by Andrew Bardsley.
|
||||
|
||||
// bug1071
|
||||
|
||||
module t (/*AUTOARG*/
|
||||
// Inputs
|
||||
clk
|
||||
);
|
||||
input clk;
|
||||
|
||||
reg [3:0] array_1 [2:0];
|
||||
reg [3:0] array_2 [2:0];
|
||||
reg [3:0] array_3 [3:1];
|
||||
|
||||
reg [3:0] elem;
|
||||
|
||||
reg array_1_ne_array_2;
|
||||
reg array_1_eq_array_2;
|
||||
reg array_1_ne_array_3;
|
||||
reg array_1_eq_array_3;
|
||||
|
||||
initial begin
|
||||
array_1[0] = 4'b1000;
|
||||
array_1[1] = 4'b1000;
|
||||
array_1[2] = 4'b1000;
|
||||
|
||||
array_2[0] = 4'b1000;
|
||||
array_2[1] = 4'b1000;
|
||||
array_2[2] = 4'b1000;
|
||||
|
||||
array_3[1] = 4'b1000;
|
||||
array_3[2] = 4'b0100;
|
||||
array_3[3] = 4'b0100;
|
||||
|
||||
// Comparisons only compare elements 0
|
||||
array_1_ne_array_2 = array_1 != array_2; // 0
|
||||
array_1_eq_array_2 = array_1 == array_2; // 0
|
||||
array_1_ne_array_3 = array_1 != array_3; // 1
|
||||
array_1_eq_array_3 = array_1 == array_3; // 1
|
||||
|
||||
`ifdef TEST_VERBOSE
|
||||
$write("array_1_ne_array2==%0d\n", array_1_ne_array_2);
|
||||
$write("array_1_ne_array3==%0d\n", array_1_ne_array_3);
|
||||
`endif
|
||||
|
||||
if (array_1_ne_array_2 !== 0) $stop;
|
||||
if (array_1_eq_array_2 !== 1) $stop;
|
||||
if (array_1_ne_array_3 !== 1) $stop;
|
||||
if (array_1_eq_array_3 !== 0) $stop;
|
||||
|
||||
$write("*-* All Finished *-*\n");
|
||||
$finish;
|
||||
end
|
||||
|
||||
endmodule
|
||||
@@ -19,7 +19,7 @@ execute (
|
||||
check_finished=>0,
|
||||
fails=> $Self->{vlt},
|
||||
expect=>
|
||||
'%Error: t_assert_synth.v:\d+: Assertion failed in top.v: synthesis full_case'
|
||||
'%Error: t_assert_synth.v:\d+: Assertion failed in top.t: synthesis full_case'
|
||||
);
|
||||
|
||||
ok(1);
|
||||
|
||||
@@ -19,7 +19,7 @@ execute (
|
||||
check_finished=>0,
|
||||
fails => $Self->{v3},
|
||||
expect=>
|
||||
'%Error: t_assert_synth.v:\d+: Assertion failed in top.v: synthesis parallel_case'
|
||||
'%Error: t_assert_synth.v:\d+: Assertion failed in top.t: synthesis parallel_case'
|
||||
);
|
||||
|
||||
ok(1);
|
||||
|
||||
@@ -12,11 +12,11 @@ compile (
|
||||
verilator_make_gcc => 0,
|
||||
fails => 1,
|
||||
expect=>
|
||||
'%Warning-CDCRSTLOGIC: t/t_cdc_async_bad.v:\d+: Logic in path that feeds async reset, via signal: v.rst2_bad_n
|
||||
'%Warning-CDCRSTLOGIC: t/t_cdc_async_bad.v:\d+: Logic in path that feeds async reset, via signal: t.rst2_bad_n
|
||||
%Warning-CDCRSTLOGIC: Use "/\* verilator lint_off CDCRSTLOGIC \*/" and lint_on around source to disable this message.
|
||||
%Warning-CDCRSTLOGIC: See details in obj_dir/t_cdc_async_bad/Vt_cdc_async_bad__cdc.txt
|
||||
%Warning-CDCRSTLOGIC: t/t_cdc_async_bad.v:\d+: Logic in path that feeds async reset, via signal: v.rst6a_bad_n
|
||||
%Warning-CDCRSTLOGIC: t/t_cdc_async_bad.v:\d+: Logic in path that feeds async reset, via signal: v.rst6b_bad_n
|
||||
%Warning-CDCRSTLOGIC: t/t_cdc_async_bad.v:\d+: Logic in path that feeds async reset, via signal: t.rst6a_bad_n
|
||||
%Warning-CDCRSTLOGIC: t/t_cdc_async_bad.v:\d+: Logic in path that feeds async reset, via signal: t.rst6b_bad_n
|
||||
%Error: Exiting due to.*',
|
||||
);
|
||||
|
||||
|
||||
@@ -77,7 +77,7 @@
|
||||
input toggle;
|
||||
always @ (posedge clk) begin
|
||||
%000002 if (toggle) begin
|
||||
// CHECK_COVER(-1,"top.v.a*",2)
|
||||
// CHECK_COVER(-1,"top.t.a*",2)
|
||||
// t.a1 and t.a2 collapse to a count of 2
|
||||
end
|
||||
if (toggle) begin
|
||||
@@ -100,11 +100,11 @@
|
||||
|
||||
always @ (posedge clk) begin
|
||||
%000000 if (0) begin
|
||||
// CHECK_COVER(-1,"top.v.b*",0)
|
||||
// CHECK_COVER(-1,"top.t.b*",0)
|
||||
// Make sure that we don't optimize away zero buckets
|
||||
end
|
||||
%000002 if (toggle) begin
|
||||
// CHECK_COVER(-1,"top.v.b*",2)
|
||||
// CHECK_COVER(-1,"top.t.b*",2)
|
||||
// t.b1 and t.b2 collapse to a count of 2
|
||||
end
|
||||
if (toggle) begin
|
||||
@@ -133,10 +133,10 @@
|
||||
input external;
|
||||
begin
|
||||
%000001 if (toggle) begin
|
||||
// CHECK_COVER(-1,"top.v.t1",1)
|
||||
// CHECK_COVER(-1,"top.t.t1",1)
|
||||
end
|
||||
%000001 if (external) begin
|
||||
// CHECK_COVER(-1,"top.v.t1",1)
|
||||
// CHECK_COVER(-1,"top.t.t1",1)
|
||||
$write("[%0t] Got external pulse\n", $time);
|
||||
end
|
||||
end
|
||||
@@ -161,7 +161,7 @@
|
||||
// verilator coverage_on
|
||||
always @ (posedge clk) begin
|
||||
%000001 if (toggle) begin
|
||||
// CHECK_COVER(-1,"top.v.o1",1)
|
||||
// CHECK_COVER(-1,"top.t.o1",1)
|
||||
// because under coverage_module_off
|
||||
end
|
||||
end
|
||||
|
||||
@@ -76,7 +76,7 @@ module alpha (/*AUTOARG*/
|
||||
input toggle;
|
||||
always @ (posedge clk) begin
|
||||
if (toggle) begin
|
||||
// CHECK_COVER(-1,"top.v.a*",2)
|
||||
// CHECK_COVER(-1,"top.t.a*",2)
|
||||
// t.a1 and t.a2 collapse to a count of 2
|
||||
end
|
||||
if (toggle) begin
|
||||
@@ -99,11 +99,11 @@ module beta (/*AUTOARG*/
|
||||
|
||||
always @ (posedge clk) begin
|
||||
if (0) begin
|
||||
// CHECK_COVER(-1,"top.v.b*",0)
|
||||
// CHECK_COVER(-1,"top.t.b*",0)
|
||||
// Make sure that we don't optimize away zero buckets
|
||||
end
|
||||
if (toggle) begin
|
||||
// CHECK_COVER(-1,"top.v.b*",2)
|
||||
// CHECK_COVER(-1,"top.t.b*",2)
|
||||
// t.b1 and t.b2 collapse to a count of 2
|
||||
end
|
||||
if (toggle) begin
|
||||
@@ -132,10 +132,10 @@ module tsk (/*AUTOARG*/
|
||||
input external;
|
||||
begin
|
||||
if (toggle) begin
|
||||
// CHECK_COVER(-1,"top.v.t1",1)
|
||||
// CHECK_COVER(-1,"top.t.t1",1)
|
||||
end
|
||||
if (external) begin
|
||||
// CHECK_COVER(-1,"top.v.t1",1)
|
||||
// CHECK_COVER(-1,"top.t.t1",1)
|
||||
$write("[%0t] Got external pulse\n", $time);
|
||||
end
|
||||
end
|
||||
@@ -160,7 +160,7 @@ module off (/*AUTOARG*/
|
||||
// verilator coverage_on
|
||||
always @ (posedge clk) begin
|
||||
if (toggle) begin
|
||||
// CHECK_COVER(-1,"top.v.o1",1)
|
||||
// CHECK_COVER(-1,"top.t.o1",1)
|
||||
// because under coverage_module_off
|
||||
end
|
||||
end
|
||||
|
||||
@@ -20,7 +20,7 @@ execute (
|
||||
# Allow old Perl format dump, or new binary dump
|
||||
# Check that the hierarchy doesn't include __PVT__
|
||||
# Otherwise our coverage reports would look really ugly
|
||||
file_grep ($Self->{coverage_filename}, qr/(top\.v\.sub.*.cyc_eq_5)/)
|
||||
file_grep ($Self->{coverage_filename}, qr/(top\.t\.sub.*.cyc_eq_5)/)
|
||||
if $Self->{vlt};
|
||||
|
||||
ok(1);
|
||||
|
||||
@@ -95,25 +95,25 @@ module alpha (/*AUTOARG*/
|
||||
input clk;
|
||||
|
||||
input toggle;
|
||||
// CHECK_COVER(-1,"top.v.a*",4)
|
||||
// CHECK_COVER(-1,"top.t.a*",4)
|
||||
// 2 edges * (t.a1 and t.a2)
|
||||
|
||||
input [7:0] cyc_copy;
|
||||
// CHECK_COVER(-1,"top.v.a*","cyc_copy[0]",22)
|
||||
// CHECK_COVER(-2,"top.v.a*","cyc_copy[1]",10)
|
||||
// CHECK_COVER(-3,"top.v.a*","cyc_copy[2]",4)
|
||||
// CHECK_COVER(-4,"top.v.a*","cyc_copy[3]",2)
|
||||
// CHECK_COVER(-5,"top.v.a*","cyc_copy[4]",0)
|
||||
// CHECK_COVER(-6,"top.v.a*","cyc_copy[5]",0)
|
||||
// CHECK_COVER(-7,"top.v.a*","cyc_copy[6]",0)
|
||||
// CHECK_COVER(-8,"top.v.a*","cyc_copy[7]",0)
|
||||
// CHECK_COVER(-1,"top.t.a*","cyc_copy[0]",22)
|
||||
// CHECK_COVER(-2,"top.t.a*","cyc_copy[1]",10)
|
||||
// CHECK_COVER(-3,"top.t.a*","cyc_copy[2]",4)
|
||||
// CHECK_COVER(-4,"top.t.a*","cyc_copy[3]",2)
|
||||
// CHECK_COVER(-5,"top.t.a*","cyc_copy[4]",0)
|
||||
// CHECK_COVER(-6,"top.t.a*","cyc_copy[5]",0)
|
||||
// CHECK_COVER(-7,"top.t.a*","cyc_copy[6]",0)
|
||||
// CHECK_COVER(-8,"top.t.a*","cyc_copy[7]",0)
|
||||
|
||||
reg toggle_internal;
|
||||
// CHECK_COVER(-1,"top.v.a*",4)
|
||||
// CHECK_COVER(-1,"top.t.a*",4)
|
||||
// 2 edges * (t.a1 and t.a2)
|
||||
|
||||
output reg toggle_up;
|
||||
// CHECK_COVER(-1,"top.v.a*",4)
|
||||
// CHECK_COVER(-1,"top.t.a*",4)
|
||||
// 2 edges * (t.a1 and t.a2)
|
||||
|
||||
always @ (posedge clk) begin
|
||||
@@ -130,7 +130,7 @@ module beta (/*AUTOARG*/
|
||||
input clk;
|
||||
|
||||
input toggle_up;
|
||||
// CHECK_COVER(-1,"top.v.b1","toggle_up",2)
|
||||
// CHECK_COVER(-1,"top.t.b1","toggle_up",2)
|
||||
|
||||
/* verilator public_module */
|
||||
|
||||
@@ -150,6 +150,6 @@ module off (/*AUTOARG*/
|
||||
|
||||
// verilator coverage_on
|
||||
input toggle;
|
||||
// CHECK_COVER(-1,"top.v.o1","toggle",2)
|
||||
// CHECK_COVER(-1,"top.t.o1","toggle",2)
|
||||
|
||||
endmodule
|
||||
|
||||
@@ -13,11 +13,11 @@ compile (
|
||||
execute (
|
||||
check_finished=>1,
|
||||
expect=>dequote(
|
||||
q{[0] In top.v: Hi
|
||||
[0] In top.v.sub (sub)
|
||||
[0] In top.v.sub.subblock (sub)
|
||||
[0] In top.v.sub2 (sub2)
|
||||
[0] In top.v.sub2.subblock2 (sub2)
|
||||
q{[0] In top.t: Hi
|
||||
[0] In top.t.sub (sub)
|
||||
[0] In top.t.sub.subblock (sub)
|
||||
[0] In top.t.sub2 (sub2)
|
||||
[0] In top.t.sub2.subblock2 (sub2)
|
||||
[0] Back \ Quote "
|
||||
[0] %b=000001100 %0b=1100 %b=00000101010111011101110111100110011001100 %0b=101010111011101110111100110011001100 %b=000001010101111000001001000110100010101100111100000010010001101000101011001111000 %0b=1010101111000001001000110100010101100111100000010010001101000101011001111000
|
||||
[0] %B=000001100 %0B=1100 %B=00000101010111011101110111100110011001100 %0B=101010111011101110111100110011001100 %B=000001010101111000001001000110100010101100111100000010010001101000101011001111000 %0B=1010101111000001001000110100010101100111100000010010001101000101011001111000
|
||||
|
||||
@@ -16,11 +16,11 @@ compile (
|
||||
execute (
|
||||
check_finished=>1,
|
||||
expect=>dequote(
|
||||
q{[0] In top.v: Hi
|
||||
[0] In top.v.sub (sub)
|
||||
[0] In top.v.sub.subblock (sub)
|
||||
[0] In top.v.sub2 (sub2)
|
||||
[0] In top.v.sub2.subblock2 (sub2)
|
||||
q{[0] In top.t: Hi
|
||||
[0] In top.t.sub (sub)
|
||||
[0] In top.t.sub.subblock (sub)
|
||||
[0] In top.t.sub2 (sub2)
|
||||
[0] In top.t.sub2.subblock2 (sub2)
|
||||
[0] Back \ Quote "
|
||||
[0] %b=000001100 %0b=1100 %b=00000101010111011101110111100110011001100 %0b=101010111011101110111100110011001100 %b=000001010101111000001001000110100010101100111100000010010001101000101011001111000 %0b=1010101111000001001000110100010101100111100000010010001101000101011001111000
|
||||
[0] %B=000001100 %0B=1100 %B=00000101010111011101110111100110011001100 %0B=101010111011101110111100110011001100 %B=000001010101111000001001000110100010101100111100000010010001101000101011001111000 %0B=1010101111000001001000110100010101100111100000010010001101000101011001111000
|
||||
|
||||
@@ -90,7 +90,7 @@ checkResult (bool p,
|
||||
int main ()
|
||||
{
|
||||
Vt_dpi_accessors *dut = new Vt_dpi_accessors ("dut");
|
||||
svSetScope (svGetScopeFromName ("dut.v"));
|
||||
svSetScope (svGetScopeFromName ("dut.t"));
|
||||
|
||||
// evaluate the model with no signal changes to get the initial blocks
|
||||
// executed.
|
||||
|
||||
@@ -22,8 +22,8 @@ dpii_display_call: constant
|
||||
dpii_display_call: constant_value
|
||||
one10=0000000a
|
||||
dpii_display_call: one10=0000000a
|
||||
Mod=top.v 16= 10 10=0000000a
|
||||
dpii_display_call: Mod=top.v 16= 10 10=0000000a
|
||||
Mod=top.t 16= 10 10=0000000a
|
||||
dpii_display_call: Mod=top.t 16= 10 10=0000000a
|
||||
*-* All Finished *-*
|
||||
}),
|
||||
);
|
||||
|
||||
@@ -11,7 +11,7 @@ compile (
|
||||
v_flags2 => ["--lint-only"],
|
||||
fails=>$Self->{v3},
|
||||
expect=>
|
||||
'%Error: t/t_dpi_dup_bad.v:\d+: Duplicate declaration of DPI function with different formal arguments: v.oth_f_int2
|
||||
'%Error: t/t_dpi_dup_bad.v:\d+: Duplicate declaration of DPI function with different formal arguments: t.oth_f_int2
|
||||
%Error: t/t_dpi_dup_bad.v:\d+: ... New prototype: pure int dpii_fa_bit \(int, int\)
|
||||
%Error: t/t_dpi_dup_bad.v:\d+: ... Original prototype: int dpii_fa_bit \(int\)
|
||||
%Error: Exiting due to .*'
|
||||
|
||||
Executable
+19
@@ -0,0 +1,19 @@
|
||||
#!/usr/bin/perl
|
||||
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
|
||||
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||
#
|
||||
# Copyright 2003 by Wilson Snyder. This program is free software; you can
|
||||
# redistribute it and/or modify it under the terms of either the GNU
|
||||
# Lesser General Public License Version 3 or the Perl Artistic License
|
||||
# Version 2.0.
|
||||
|
||||
compile (
|
||||
v_flags2 => ["--lint-only"],
|
||||
fails=>$Self->{v3},
|
||||
expect=>
|
||||
'%Error: t/t_dpi_exp_bad.v:\d+: DPI functions cannot return > 32 bits; use a two-state type or task instead: dpix_f_bit48__Vfuncrtn
|
||||
%Error: Exiting due to .*'
|
||||
);
|
||||
|
||||
ok(1);
|
||||
1;
|
||||
@@ -0,0 +1,13 @@
|
||||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// Copyright 2009 by Wilson Snyder. This program is free software; you can
|
||||
// redistribute it and/or modify it under the terms of either the GNU
|
||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||
// Version 2.0.
|
||||
|
||||
module t;
|
||||
|
||||
export "DPI-C" function dpix_f_bit48;
|
||||
function bit [47:0] dpix_f_bit48 (bit [47:0] i); dpix_f_bit48 = ~i; endfunction
|
||||
|
||||
endmodule
|
||||
@@ -38,6 +38,8 @@ module t;
|
||||
function longint dpix_f_longint (longint i); dpix_f_longint = ~i; endfunction
|
||||
function chandle dpix_f_chandle (chandle i); dpix_f_chandle = i; endfunction
|
||||
|
||||
export "DPI-C" task dpix_t_bit48;
|
||||
task dpix_t_bit48(input bit [47:0] i, output bit [47:0] o); o = ~i; endtask
|
||||
export "DPI-C" task dpix_t_bit95;
|
||||
task dpix_t_bit95(input bit [94:0] i, output bit [94:0] o); o = ~i; endtask
|
||||
export "DPI-C" task dpix_t_bit96;
|
||||
|
||||
@@ -46,6 +46,8 @@ extern "C" {
|
||||
extern int dpix_int123();
|
||||
|
||||
extern unsigned char dpix_f_bit(unsigned char i);
|
||||
extern svBitVecVal dpix_f_bit15(const svBitVecVal* i);
|
||||
extern svBitVecVal dpix_f_bit48(const svBitVecVal* i);
|
||||
extern int dpix_f_int(int i);
|
||||
extern char dpix_f_byte(char i);
|
||||
extern short int dpix_f_shortint(short int i);
|
||||
@@ -136,6 +138,17 @@ int dpix_run_tests() {
|
||||
CHECK_RESULT (unsigned long long, dpix_f_longint(1), 0xfffffffffffffffeULL);
|
||||
CHECK_RESULT (void*, dpix_f_chandle((void*)(12345)), (void*)(12345));
|
||||
|
||||
{
|
||||
svBitVecVal i_vec48[2] = {0xab782a12,0x8a413bd9};
|
||||
svBitVecVal o_vec48[2] = {0,0};
|
||||
dpix_t_bit48(i_vec48, o_vec48);
|
||||
CHECK_RESULT(int, o_vec48[0], ~i_vec48[0]);
|
||||
#ifdef VCS // VCS has bug where doesn't clean input
|
||||
CHECK_RESULT(int, o_vec48[1], (~i_vec48[1]));
|
||||
#else
|
||||
CHECK_RESULT(int, o_vec48[1], (~i_vec48[1])&0x0000ffffUL);
|
||||
#endif
|
||||
}
|
||||
{
|
||||
svBitVecVal i_vec95[3] = {0x72912312,0xab782a12,0x8a413bd9};
|
||||
svBitVecVal o_vec95[3] = {0,0,0};
|
||||
|
||||
Executable
+18
@@ -0,0 +1,18 @@
|
||||
#!/usr/bin/perl
|
||||
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
|
||||
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||
#
|
||||
# Copyright 2003 by Wilson Snyder. This program is free software; you can
|
||||
# redistribute it and/or modify it under the terms of either the GNU
|
||||
# Lesser General Public License Version 3 or the Perl Artistic License
|
||||
# Version 2.0.
|
||||
|
||||
compile (
|
||||
);
|
||||
|
||||
execute (
|
||||
check_finished=>1,
|
||||
);
|
||||
|
||||
ok(1);
|
||||
1;
|
||||
@@ -0,0 +1,55 @@
|
||||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// This file ONLY is placed into the Public Domain, for any use,
|
||||
// without warranty, 2014 by Wilson Snyder.
|
||||
|
||||
`define checkh(gotv,expv) do if ((gotv) !== (expv)) begin $write("%%Error: %s:%0d: got='h%x exp='h%x\n", `__FILE__,`__LINE__, (gotv), (expv)); $stop; end while(0);
|
||||
`define checks(gotv,expv) do if ((gotv) !== (expv)) begin $write("%%Error: %s:%0d: got='%s' exp='%s'\n", `__FILE__,`__LINE__, (gotv), (expv)); $stop; end while(0);
|
||||
|
||||
module t (/*AUTOARG*/
|
||||
// Inputs
|
||||
clk
|
||||
);
|
||||
input clk;
|
||||
|
||||
typedef enum {
|
||||
E01 = 'h1,
|
||||
ELARGE = 'hf00d
|
||||
} my_t;
|
||||
|
||||
integer cyc=0;
|
||||
my_t e;
|
||||
|
||||
string all;
|
||||
|
||||
// Check runtime
|
||||
always @ (posedge clk) begin
|
||||
cyc <= cyc + 1;
|
||||
if (cyc==0) begin
|
||||
// Setup
|
||||
e <= E01;
|
||||
end
|
||||
else if (cyc==1) begin
|
||||
`checks(e.name, "E01");
|
||||
`checkh(e.next, ELARGE);
|
||||
e <= ELARGE;
|
||||
end
|
||||
else if (cyc==3) begin
|
||||
`checks(e.name, "ELARGE");
|
||||
`checkh(e.next, E01);
|
||||
`checkh(e.prev, E01);
|
||||
e <= E01;
|
||||
end
|
||||
else if (cyc==20) begin
|
||||
e <= 'h11; // Unknown
|
||||
end
|
||||
else if (cyc==20) begin
|
||||
`checks(e.name, ""); // Unknown
|
||||
end
|
||||
else if (cyc==99) begin
|
||||
$write("*-* All Finished *-*\n");
|
||||
$finish;
|
||||
end
|
||||
end
|
||||
|
||||
endmodule
|
||||
@@ -12,11 +12,11 @@ module t (/*AUTOARG*/
|
||||
);
|
||||
input clk;
|
||||
|
||||
typedef enum {
|
||||
E01 = 1,
|
||||
E03 = 3,
|
||||
E04 = 4
|
||||
} my_t;
|
||||
typedef enum [3:0] {
|
||||
E01 = 1,
|
||||
E03 = 3,
|
||||
E04 = 4
|
||||
} my_t;
|
||||
|
||||
integer cyc=0;
|
||||
my_t e;
|
||||
|
||||
Executable
+19
@@ -0,0 +1,19 @@
|
||||
#!/usr/bin/perl
|
||||
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
|
||||
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||
#
|
||||
# Copyright 2003 by Wilson Snyder. This program is free software; you can
|
||||
# redistribute it and/or modify it under the terms of either the GNU
|
||||
# Lesser General Public License Version 3 or the Perl Artistic License
|
||||
# Version 2.0.
|
||||
|
||||
compile (
|
||||
verilator_flags2 => ["--mod-prefix modPrefix --top-module t --l2-name l2Name"],
|
||||
);
|
||||
|
||||
execute (
|
||||
check_finished=>1,
|
||||
);
|
||||
|
||||
ok(1);
|
||||
1;
|
||||
@@ -0,0 +1,23 @@
|
||||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// This file ONLY is placed into the Public Domain, for any use,
|
||||
// without warranty, 2016 by Wilson Snyder.
|
||||
|
||||
module t;
|
||||
sub sub ();
|
||||
endmodule
|
||||
|
||||
module sub;
|
||||
string scope;
|
||||
initial begin
|
||||
scope = $sformatf("%m");
|
||||
$write("[%0t] In %s\n", $time, scope);
|
||||
`ifdef VERILATOR
|
||||
if (scope != "top.l2Name.sub") $stop;
|
||||
`else
|
||||
if (scope != "top.t.sub") $stop;
|
||||
`endif
|
||||
$write("*-* All Finished *-*\n");
|
||||
$finish;
|
||||
end
|
||||
endmodule
|
||||
Executable
+20
@@ -0,0 +1,20 @@
|
||||
#!/usr/bin/perl
|
||||
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
|
||||
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||
#
|
||||
# Copyright 2008 by Wilson Snyder. This program is free software; you can
|
||||
# redistribute it and/or modify it under the terms of either the GNU
|
||||
# Lesser General Public License Version 3 or the Perl Artistic License
|
||||
# Version 2.0.
|
||||
|
||||
compile (
|
||||
# It is not possible to put them into the options file
|
||||
v_flags2 => ['-Gstring1="\"New String\"" -pvalue+string2="\"New String\"" -f t/t_flag_parameter.vc'],
|
||||
);
|
||||
|
||||
execute (
|
||||
check_finished=>1,
|
||||
);
|
||||
|
||||
ok(1);
|
||||
1;
|
||||
@@ -0,0 +1,49 @@
|
||||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// This file ONLY is placed into the Public Domain, for any use,
|
||||
// without warranty, 2016 by Wilson Snyder
|
||||
|
||||
`define check(gotv,expv) do if ((gotv) !== (expv)) begin $write("%%Error: %s:%0d: Wrong parameter value", `__FILE__,`__LINE__); $stop; end while(0);
|
||||
|
||||
module t;
|
||||
parameter string1 = "Original String";
|
||||
parameter string2 = "Original String";
|
||||
|
||||
parameter real11 = 0.1;
|
||||
parameter real12 = 0.1;
|
||||
parameter real21 = 0.1;
|
||||
parameter real22 = 0.1;
|
||||
parameter real31 = 0.1;
|
||||
parameter real32 = 0.1;
|
||||
|
||||
parameter int11 = 1;
|
||||
parameter int12 = 1;
|
||||
parameter int21 = 1;
|
||||
parameter int22 = 1;
|
||||
parameter int31 = 1;
|
||||
parameter int32 = 1;
|
||||
parameter int41 = 1;
|
||||
parameter int42 = 1;
|
||||
|
||||
initial begin
|
||||
`check(string1,"New String");
|
||||
`check(string2,"New String");
|
||||
`check(real11,0.2);
|
||||
`check(real12,0.2);
|
||||
`check(real21,400);
|
||||
`check(real22,400);
|
||||
`check(real31,20);
|
||||
`check(real32,20);
|
||||
`check(int11,16);
|
||||
`check(int12,16);
|
||||
`check(int21,16);
|
||||
`check(int22,16);
|
||||
`check(int31,123);
|
||||
`check(int32,123);
|
||||
`check(int41,32'hdeadbeef);
|
||||
`check(int42,32'hdeadbeef);
|
||||
|
||||
$write("*-* All Finished *-*\n");
|
||||
$finish;
|
||||
end
|
||||
endmodule
|
||||
@@ -0,0 +1,15 @@
|
||||
-Greal11=0.2
|
||||
-pvalue+real12=0.2
|
||||
-Greal21=4e2
|
||||
-pvalue+real22=4e2
|
||||
-Greal31=0.2e2
|
||||
-pvalue+real32=0.2e2
|
||||
-Gint11=0x10
|
||||
-pvalue+int12=0x10
|
||||
-Gint21=020
|
||||
-pvalue+int22=020
|
||||
-Gint31=123
|
||||
-pvalue+int32=123
|
||||
-Gint41=32'hdead_beef
|
||||
-pvalue+int42=32'hdead_beef
|
||||
|
||||
Executable
+18
@@ -0,0 +1,18 @@
|
||||
#!/usr/bin/perl
|
||||
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
|
||||
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||
#
|
||||
# Copyright 2003 by Wilson Snyder. This program is free software; you can
|
||||
# redistribute it and/or modify it under the terms of either the GNU
|
||||
# Lesser General Public License Version 3 or the Perl Artistic License
|
||||
# Version 2.0.
|
||||
|
||||
compile (
|
||||
);
|
||||
|
||||
execute (
|
||||
check_finished=>1,
|
||||
);
|
||||
|
||||
ok(1);
|
||||
1;
|
||||
@@ -0,0 +1,76 @@
|
||||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// This file ONLY is placed into the Public Domain, for any use,
|
||||
// without warranty, 2016 by Wilson Snyder.
|
||||
|
||||
`define checkh(gotv,expv) do if ((gotv) !== (expv)) begin $write("%%Error: %s:%0d: got='h%x exp='h%x\n", `__FILE__,`__LINE__, (gotv), (expv)); $stop; end while(0);
|
||||
|
||||
module t (/*AUTOARG*/);
|
||||
|
||||
// verilator lint_off LITENDIAN
|
||||
// verilator lint_off WIDTH
|
||||
|
||||
reg [63:0] sum;
|
||||
reg [2:1] [4:3] array [5:6] [7:8];
|
||||
reg [1:2] [3:4] larray [6:5] [8:7];
|
||||
|
||||
function [63:0] crc (input [63:0] sum, input [31:0] a, input [31:0] b, input [31:0] c, input [31:0] d);
|
||||
crc = {sum[62:0],sum[63]} ^ {4'b0,a[7:0], 4'h0,b[7:0], 4'h0,c[7:0], 4'h0,d[7:0]};
|
||||
endfunction
|
||||
|
||||
initial begin
|
||||
sum = 0;
|
||||
foreach (array[a]) begin
|
||||
sum = crc(sum, a, 0, 0, 0);
|
||||
end
|
||||
`checkh(sum, 64'h000000c000000000);
|
||||
|
||||
sum = 0;
|
||||
foreach (array[a,b]) begin
|
||||
sum = crc(sum, a, b, 0, 0);
|
||||
end
|
||||
`checkh(sum, 64'h000003601e000000);
|
||||
|
||||
sum = 0;
|
||||
foreach (array[a,b,c]) begin
|
||||
sum = crc(sum, a, b, c, 0);
|
||||
end
|
||||
`checkh(sum, 64'h00003123fc101000);
|
||||
|
||||
sum = 0;
|
||||
foreach (array[a,b,c,d]) begin
|
||||
sum = crc(sum, a, b, c, d);
|
||||
end
|
||||
`checkh(sum, 64'h0030128ab2a8e557);
|
||||
|
||||
//
|
||||
|
||||
sum = 0;
|
||||
foreach (larray[a]) begin
|
||||
sum = crc(sum, a, 0, 0, 0);
|
||||
end
|
||||
`checkh(sum, 64'h0000009000000000);
|
||||
|
||||
sum = 0;
|
||||
foreach (larray[a,b]) begin
|
||||
sum = crc(sum, a, b, 0, 0);
|
||||
sum = sum + {4'b0,a[7:0], 4'h0,b[7:0]};
|
||||
end
|
||||
`checkh(sum, 64'h000002704b057073);
|
||||
|
||||
sum = 0;
|
||||
foreach (larray[a,b,c]) begin
|
||||
sum = crc(sum, a, b, c, 0);
|
||||
end
|
||||
`checkh(sum, 64'h00002136f9000000);
|
||||
|
||||
sum = 0;
|
||||
foreach (larray[a,b,c,d]) begin
|
||||
sum = crc(sum, a, b, c, d);
|
||||
end
|
||||
`checkh(sum, 64'h0020179aa7aa0aaa);
|
||||
|
||||
$write("*-* All Finished *-*\n");
|
||||
$finish;
|
||||
end
|
||||
endmodule
|
||||
@@ -13,17 +13,17 @@ compile (
|
||||
execute (
|
||||
check_finished=>1,
|
||||
expect=>quotemeta(
|
||||
q{created tag with scope = top.v.b.gen[0].tag
|
||||
created tag with scope = top.v.b.gen[1].tag
|
||||
created tag with scope = top.v.tag
|
||||
mod a has scope = top.v
|
||||
mod a has tag = top.v.tag
|
||||
mod b has scope = top.v.b
|
||||
mod b has tag = top.v.tag
|
||||
mod c has scope = top.v.b.gen[0].c
|
||||
mod c has tag = top.v.b.gen[0].tag
|
||||
mod c has scope = top.v.b.gen[1].c
|
||||
mod c has tag = top.v.b.gen[1].tag
|
||||
q{created tag with scope = top.t.b.gen[0].tag
|
||||
created tag with scope = top.t.b.gen[1].tag
|
||||
created tag with scope = top.t.tag
|
||||
mod a has scope = top.t
|
||||
mod a has tag = top.t.tag
|
||||
mod b has scope = top.t.b
|
||||
mod b has tag = top.t.tag
|
||||
mod c has scope = top.t.b.gen[0].c
|
||||
mod c has tag = top.t.b.gen[0].tag
|
||||
mod c has scope = top.t.b.gen[1].c
|
||||
mod c has tag = top.t.b.gen[1].tag
|
||||
*-* All Finished *-*}),
|
||||
);
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@ compile (
|
||||
execute (
|
||||
check_finished=>1,
|
||||
expect=>
|
||||
'\] (%m|.*v\.ps): Clocked
|
||||
'\] (%m|.*t\.ps): Clocked
|
||||
',
|
||||
);
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@ if ($Self->{vlt}) {
|
||||
execute (
|
||||
check_finished=>1,
|
||||
expect=>
|
||||
'\] (%m|.*v\.ps): Clocked
|
||||
'\] (%m|.*t\.ps): Clocked
|
||||
',
|
||||
);
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@ compile (
|
||||
execute (
|
||||
check_finished=>1,
|
||||
expect=>
|
||||
'\] (%m|.*v\.ps): Clocked
|
||||
'\] (%m|.*t\.ps): Clocked
|
||||
',
|
||||
);
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@ compile (
|
||||
execute (
|
||||
check_finished=>1,
|
||||
expect=>
|
||||
'\] (%m|.*v\.ps): Clocked
|
||||
'\] (%m|.*t\.ps): Clocked
|
||||
',
|
||||
);
|
||||
|
||||
|
||||
@@ -7,8 +7,6 @@ if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); di
|
||||
# Lesser General Public License Version 3 or the Perl Artistic License
|
||||
# Version 2.0.
|
||||
|
||||
$Self->{vlt} and $Self->unsupported("Verilator unsupported, bug978");
|
||||
|
||||
compile (
|
||||
);
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@ compile (
|
||||
make_top_shell => 0,
|
||||
make_main => 0,
|
||||
expect=>
|
||||
'%Warning-MULTIDRIVEN: t/t_lint_multidriven_bad.v:\d+: Signal has multiple driving blocks: v.mem
|
||||
'%Warning-MULTIDRIVEN: t/t_lint_multidriven_bad.v:\d+: Signal has multiple driving blocks: t.mem
|
||||
%Warning-MULTIDRIVEN: t/t_lint_multidriven_bad.v:\d+: ... Location of first driving block
|
||||
%Warning-MULTIDRIVEN: t/t_lint_multidriven_bad.v:\d+: ... Location of other driving block
|
||||
%Warning-MULTIDRIVEN: Use ".*" and lint_on around source to disable this message.
|
||||
|
||||
@@ -13,10 +13,13 @@ module t (/*AUTOARG*/
|
||||
input clk;
|
||||
output [31:0] ign;
|
||||
|
||||
parameter [95:0] P6 = 6;
|
||||
localparam P64 = (1 << P6);
|
||||
|
||||
reg [31:0] right;
|
||||
reg [31:0] left;
|
||||
reg [63:0] qright;
|
||||
reg [63:0] qleft;
|
||||
reg [P64-1:0] qright;
|
||||
reg [P64-1:0] qleft;
|
||||
reg [31:0] amt;
|
||||
|
||||
assign ign = {31'h0, clk} >>> 4'bx; // bug760
|
||||
@@ -37,6 +40,7 @@ module t (/*AUTOARG*/
|
||||
`endif
|
||||
if (cyc==1) begin
|
||||
amt <= 32'd0;
|
||||
if (P64 != 64) $stop;
|
||||
if (5'b10110>>2 != 5'b00101) $stop;
|
||||
if (5'b10110>>>2 != 5'b00101) $stop; // Note it cares about sign-ness
|
||||
if (5'b10110<<2 != 5'b11000) $stop;
|
||||
|
||||
Executable
+21
@@ -0,0 +1,21 @@
|
||||
#!/usr/bin/perl
|
||||
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
|
||||
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||
#
|
||||
# Copyright 2010 by Wilson Snyder. This program is free software; you can
|
||||
# redistribute it and/or modify it under the terms of either the GNU
|
||||
# Lesser General Public License Version 3 or the Perl Artistic License
|
||||
# Version 2.0.
|
||||
|
||||
$Self->{vlt} or $Self->skip("Verilator only test");
|
||||
|
||||
compile (
|
||||
verilator_flags2 => ["--lint-only"],
|
||||
fails=>1,
|
||||
expect=>
|
||||
'%Error: Internal Error: .*: Value too wide for 32-bits expected in this context 64\'h123456789abcdef
|
||||
.',
|
||||
);
|
||||
|
||||
ok(1);
|
||||
1;
|
||||
@@ -0,0 +1,20 @@
|
||||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// This file ONLY is placed into the Public Domain, for any use,
|
||||
// without warranty, 2016 by Wilson Snyder.
|
||||
|
||||
module t (/*AUTOARG*/
|
||||
// Outputs
|
||||
o,
|
||||
// Inputs
|
||||
clk, i
|
||||
);
|
||||
|
||||
input clk;
|
||||
|
||||
input [31:0] i;
|
||||
output [31:0] o;
|
||||
|
||||
assign o = i << 64'h01234567_89abcdef;
|
||||
|
||||
endmodule
|
||||
@@ -16,7 +16,7 @@ compile (
|
||||
expect=>
|
||||
'%Error: Circular logic when ordering code .*
|
||||
%Error: Example path: t/t_order_loop_bad.v:\d+: ALWAYS
|
||||
%Error: Example path: t/t_order_loop_bad.v:\d+: v.ready
|
||||
%Error: Example path: t/t_order_loop_bad.v:\d+: t.ready
|
||||
%Error: Example path: t/t_order_loop_bad.v:\d+: ACTIVE
|
||||
.*',
|
||||
);
|
||||
|
||||
@@ -7,8 +7,6 @@ if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); di
|
||||
# Lesser General Public License Version 3 or the Perl Artistic License
|
||||
# Version 2.0.
|
||||
|
||||
$Self->{vlt} and $Self->unsupported("Verilator unsupported, bug474");
|
||||
|
||||
compile (
|
||||
);
|
||||
|
||||
|
||||
Executable
+20
@@ -0,0 +1,20 @@
|
||||
#!/usr/bin/perl
|
||||
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
|
||||
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||
#
|
||||
# Copyright 2003 by Wilson Snyder. This program is free software; you can
|
||||
# redistribute it and/or modify it under the terms of either the GNU
|
||||
# Lesser General Public License Version 3 or the Perl Artistic License
|
||||
# Version 2.0.
|
||||
|
||||
$Self->{vlt} and $Self->unsupported("Verilator unsupported, bug477");
|
||||
|
||||
compile (
|
||||
);
|
||||
|
||||
execute (
|
||||
check_finished=>1,
|
||||
);
|
||||
|
||||
ok(1);
|
||||
1;
|
||||
@@ -0,0 +1,38 @@
|
||||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// This file ONLY is placed into the Public Domain, for any use,
|
||||
// without warranty, 2016 by Wilson Snyder.
|
||||
|
||||
`define checkh(gotv,expv) do if ((gotv) !== (expv)) begin $write("%%Error: %s:%0d: got='h%x exp='h%x\n", `__FILE__,`__LINE__, (gotv), (expv)); $stop; end while(0);
|
||||
|
||||
module t (/*AUTOARG*/
|
||||
// Inputs
|
||||
clk
|
||||
);
|
||||
input clk;
|
||||
sub #(.IDX(0), .CHK(10)) i0;
|
||||
sub #(.IDX(2), .CHK(12)) i2;
|
||||
sub #(.IDX(7), .CHK(17)) i7;
|
||||
always @ (posedge clk) begin
|
||||
$write("*-* All Finished *-*\n");
|
||||
$finish;
|
||||
end
|
||||
endmodule
|
||||
|
||||
module sub ();
|
||||
function integer get_element;
|
||||
input integer index;
|
||||
input integer array_arg[7:0];
|
||||
get_element = array_arg[index];
|
||||
endfunction
|
||||
|
||||
parameter integer IDX = 5;
|
||||
parameter integer CHK = 5;
|
||||
localparam integer array[0:7] = '{10, 11, 12, 13, 14, 15, 16, 17};
|
||||
localparam element1 = array[IDX];
|
||||
localparam elementf = get_element(IDX, array);
|
||||
initial begin
|
||||
`checkh (element1, CHK);
|
||||
`checkh (elementf, CHK);
|
||||
end
|
||||
endmodule
|
||||
Executable
+18
@@ -0,0 +1,18 @@
|
||||
#!/usr/bin/perl
|
||||
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
|
||||
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||
#
|
||||
# Copyright 2003 by Wilson Snyder. This program is free software; you can
|
||||
# redistribute it and/or modify it under the terms of either the GNU
|
||||
# Lesser General Public License Version 3 or the Perl Artistic License
|
||||
# Version 2.0.
|
||||
|
||||
compile (
|
||||
);
|
||||
|
||||
execute (
|
||||
check_finished=>1,
|
||||
);
|
||||
|
||||
ok(1);
|
||||
1;
|
||||
@@ -0,0 +1,28 @@
|
||||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// This file ONLY is placed into the Public Domain, for any use,
|
||||
// without warranty, 2016 by Mandy Xu.
|
||||
|
||||
// verilator lint_off WIDTH
|
||||
|
||||
//bug1088
|
||||
|
||||
module t (/*AUTOARG*/
|
||||
// Outputs
|
||||
err_count,
|
||||
// Inputs
|
||||
clk, syndromes
|
||||
);
|
||||
|
||||
input clk;
|
||||
input [7:0] syndromes;
|
||||
output reg [1:0] err_count = 0;
|
||||
|
||||
localparam [95:0] M = 96'h4;
|
||||
wire [3:0] syn1 = syndromes[0+:M];
|
||||
always @(posedge clk) begin
|
||||
err_count <= {1'b0, |syn1};
|
||||
$write("*-* All Finished *-*\n");
|
||||
$finish;
|
||||
end
|
||||
endmodule
|
||||
@@ -7,10 +7,6 @@ if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); di
|
||||
# Lesser General Public License Version 3 or the Perl Artistic License
|
||||
# Version 2.0.
|
||||
|
||||
# Really we shouldn't need to warn in this case.
|
||||
# When supported, make a new test case that checks the warning
|
||||
#$Self->{vlt} and $Self->unsupported("Verilator unsupported, bug477");
|
||||
|
||||
top_filename("t/t_param_sel_range.v");
|
||||
|
||||
compile (
|
||||
|
||||
Executable
+18
@@ -0,0 +1,18 @@
|
||||
#!/usr/bin/perl
|
||||
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
|
||||
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||
#
|
||||
# Copyright 2003 by Wilson Snyder. This program is free software; you can
|
||||
# redistribute it and/or modify it under the terms of either the GNU
|
||||
# Lesser General Public License Version 3 or the Perl Artistic License
|
||||
# Version 2.0.
|
||||
|
||||
compile (
|
||||
);
|
||||
|
||||
execute (
|
||||
check_finished=>1,
|
||||
);
|
||||
|
||||
ok(1);
|
||||
1;
|
||||
@@ -0,0 +1,30 @@
|
||||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// This file ONLY is placed into the Public Domain, for any use,
|
||||
// without warranty, 2016 by Mandy Xu.
|
||||
|
||||
module t
|
||||
#(parameter[95:0] P = 1)
|
||||
(input clk);
|
||||
|
||||
localparam [32:0] M = 4;
|
||||
|
||||
function [M:0] gen_matrix;
|
||||
gen_matrix[0] = 1>> M;
|
||||
endfunction
|
||||
|
||||
reg [95: 0] lfsr = 0;
|
||||
always @(posedge clk) begin
|
||||
lfsr <= (1 >> P);
|
||||
end
|
||||
|
||||
wire [95: 0] lfsr_w = 1 >> P;
|
||||
|
||||
localparam [95: 0] lfsr_p = 1 >> P;
|
||||
|
||||
initial begin
|
||||
$write("*-* All Finished *-*\n");
|
||||
$finish;
|
||||
end
|
||||
|
||||
endmodule
|
||||
@@ -7,14 +7,12 @@ if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); di
|
||||
# Lesser General Public License Version 3 or the Perl Artistic License
|
||||
# Version 2.0.
|
||||
|
||||
$Self->{vlt} and $Self->unsupported("Verilator unsupported, bug376");
|
||||
|
||||
compile (
|
||||
);
|
||||
);
|
||||
|
||||
execute (
|
||||
check_finished=>1,
|
||||
);
|
||||
check_finished=>1,
|
||||
);
|
||||
|
||||
ok(1);
|
||||
1;
|
||||
|
||||
@@ -55,10 +55,12 @@ module mod_typ #(
|
||||
parameter type TYP = byte
|
||||
)(
|
||||
input logic clk,
|
||||
output TYP cnt = 0,
|
||||
output TYP cnt,
|
||||
output int siz
|
||||
);
|
||||
|
||||
initial cnt = 0;
|
||||
|
||||
always @ (posedge clk)
|
||||
cnt <= cnt + 1;
|
||||
|
||||
|
||||
Executable
+18
@@ -0,0 +1,18 @@
|
||||
#!/usr/bin/perl
|
||||
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
|
||||
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||
#
|
||||
# Copyright 2003 by Wilson Snyder. This program is free software; you can
|
||||
# redistribute it and/or modify it under the terms of either the GNU
|
||||
# Lesser General Public License Version 3 or the Perl Artistic License
|
||||
# Version 2.0.
|
||||
|
||||
compile (
|
||||
);
|
||||
|
||||
#execute (
|
||||
# check_finished=>1,
|
||||
# );
|
||||
|
||||
ok(1);
|
||||
1;
|
||||
@@ -0,0 +1,40 @@
|
||||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// This file ONLY is placed into the Public Domain, for any use,
|
||||
// without warranty, 2012 by Iztok Jeras.
|
||||
|
||||
package tt_pkg;
|
||||
typedef enum logic [1:0] {L0, L1, L2, L3} test_t;
|
||||
endpackage
|
||||
|
||||
module t (/*AUTOARG*/
|
||||
// Outputs
|
||||
ob
|
||||
);
|
||||
|
||||
output [1:0] ob;
|
||||
|
||||
import tt_pkg::*;
|
||||
|
||||
test_t a;
|
||||
test_t b;
|
||||
|
||||
assign a = L0;
|
||||
assign ob = b;
|
||||
|
||||
tt_buf #(.T_t(test_t))
|
||||
u_test
|
||||
(.i(a), .o(b));
|
||||
|
||||
endmodule
|
||||
|
||||
module tt_buf
|
||||
#(
|
||||
parameter type T_t = logic [0:0]
|
||||
)
|
||||
(
|
||||
input T_t i,
|
||||
output T_t o
|
||||
);
|
||||
assign o = i;
|
||||
endmodule
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user