Internals: Detab and fix spacing style issues in tests and scripts. No functional change.

This commit is contained in:
Wilson Snyder 2019-05-07 22:34:09 -04:00
parent 37c8cc82b2
commit f818ddc71c
77 changed files with 3109 additions and 3102 deletions

View File

@ -58,17 +58,17 @@ foreach my $sw (@ARGV) {
} }
Getopt::Long::config("no_auto_abbrev","pass_through"); Getopt::Long::config("no_auto_abbrev","pass_through");
if (! GetOptions ( if (! GetOptions(
# Major operating modes # Major operating modes
"help" => \&usage, "help" => \&usage,
"debug:s" => \&debug, "debug:s" => \&debug,
# "version!" => \&version, # Also passthru'ed # "version!" => \&version, # Also passthru'ed
# Switches # Switches
"gdb!" => \$opt_gdb, "gdb!" => \$opt_gdb,
"gdbbt!" => \$opt_gdbbt, "gdbbt!" => \$opt_gdbbt,
# Additional parameters # Additional parameters
"<>" => sub {}, # Ignored "<>" => sub {}, # Ignored
)) { )) {
pod2usage(-exitstatus=>2, -verbose=>0); pod2usage(-exitstatus=>2, -verbose=>0);
} }
@ -2082,7 +2082,7 @@ command line, or the link), you'd then:
#include "svdpi.h" #include "svdpi.h"
#include "Vour__Dpi.h" #include "Vour__Dpi.h"
int add (int a, int b) { return a+b; } int add(int a, int b) { return a+b; }
=head2 DPI System Task/Functions =head2 DPI System Task/Functions
@ -2132,7 +2132,7 @@ respect to that top level module, then the scope could be set with
#include "svdpi.h" #include "svdpi.h"
... ...
svSetScope (svGetScopeFromName ("dut")); svSetScope(svGetScopeFromName("dut"));
(Remember that Verilator adds a "V" to the top of the module hierarchy.) (Remember that Verilator adds a "V" to the top of the module hierarchy.)
@ -2146,7 +2146,7 @@ comments within the svdpi.h header for more information.
Verilator allows writing $display like functions using this syntax: Verilator allows writing $display like functions using this syntax:
import "DPI-C" function void import "DPI-C" function void
\$my_display (input string formatted /*verilator sformat*/ ); \$my_display(input string formatted /*verilator sformat*/ );
The /*verilator sformat*/ indicates that this function accepts a $display The /*verilator sformat*/ indicates that this function accepts a $display
like format specifier followed by any number of arguments to satisfy the like format specifier followed by any number of arguments to satisfy the
@ -2254,7 +2254,7 @@ accesses the above signal "readme" would be:
#include "verilated_vpi.h" // Required to get definitions #include "verilated_vpi.h" // Required to get definitions
vluint64_t main_time = 0; // See comments in first example vluint64_t main_time = 0; // See comments in first example
double sc_time_stamp () { return main_time; } double sc_time_stamp() { return main_time; }
void read_and_check() { void read_and_check() {
vpiHandle vh1 = vpi_handle_by_name((PLI_BYTE8*)"TOP.our.readme", NULL); vpiHandle vh1 = vpi_handle_by_name((PLI_BYTE8*)"TOP.our.readme", NULL);
@ -3416,7 +3416,7 @@ it's a bit slower than a non-delayed assignment.) Here's an example
always @ (posedge clk) always @ (posedge clk)
if (~reset_l) begin if (~reset_l) begin
for (i=0; i<`ARRAY_SIZE; i++) begin for (i=0; i<`ARRAY_SIZE; i++) begin
array[i] = 0; // Non-delayed for verilator array[i] = 0; // Non-delayed for verilator
end end
This message is only seen on large or complicated loops because Verilator This message is only seen on large or complicated loops because Verilator

View File

@ -19,8 +19,8 @@ require 5.006_001;
use warnings; use warnings;
BEGIN { BEGIN {
if ($ENV{DIRPROJECT} && $ENV{DIRPROJECT_PERL_BOOT}) { if ($ENV{DIRPROJECT} && $ENV{DIRPROJECT_PERL_BOOT}) {
# Magic to allow author testing of perl packages in local directory # Magic to allow author testing of perl packages in local directory
require $ENV{DIRPROJECT}."/".$ENV{DIRPROJECT_PERL_BOOT}; require $ENV{DIRPROJECT}."/".$ENV{DIRPROJECT_PERL_BOOT};
} }
} }
@ -56,12 +56,12 @@ foreach my $sw (@ARGV) {
Getopt::Long::config("no_auto_abbrev","pass_through"); Getopt::Long::config("no_auto_abbrev","pass_through");
if (! GetOptions ( if (! GetOptions (
# Major operating modes # Major operating modes
"help" => \&usage, "help" => \&usage,
"debug:s" => \&debug, "debug:s" => \&debug,
# "version!" => \&version, # Also passthru'ed # "version!" => \&version, # Also passthru'ed
# Additional parameters # Additional parameters
"<>" => sub {}, # Ignored "<>" => sub {}, # Ignored
)) { )) {
pod2usage(-exitstatus=>2, -verbose=>0); pod2usage(-exitstatus=>2, -verbose=>0);
} }
@ -90,25 +90,25 @@ sub verilator_coverage_bin {
my $bin = ""; my $bin = "";
# Use VERILATOR_ROOT if defined, else assume verilator_bin is in the search path # Use VERILATOR_ROOT if defined, else assume verilator_bin is in the search path
my $basename = ($ENV{VERILATOR_COVERAGE_BIN} my $basename = ($ENV{VERILATOR_COVERAGE_BIN}
|| "verilator_coverage_bin_dbg"); || "verilator_coverage_bin_dbg");
if (defined($ENV{VERILATOR_ROOT})) { if (defined($ENV{VERILATOR_ROOT})) {
my $dir = $ENV{VERILATOR_ROOT}; my $dir = $ENV{VERILATOR_ROOT};
if (-x "$dir/bin/$basename" if (-x "$dir/bin/$basename"
|| -x "$dir/bin/$basename.exe") { # From a "make install" into VERILATOR_ROOT || -x "$dir/bin/$basename.exe") { # From a "make install" into VERILATOR_ROOT
$bin = "$dir/bin/$basename"; $bin = "$dir/bin/$basename";
} else { } else {
$bin = "$dir/$basename"; # From pointing to kit directory $bin = "$dir/$basename"; # From pointing to kit directory
} }
} else { } else {
if (-x "$RealBin/$basename" if (-x "$RealBin/$basename"
|| -x "$RealBin/$basename.exe") { || -x "$RealBin/$basename.exe") {
$bin = "$RealBin/$basename"; # From path/to/verilator with verilator_bin installed $bin = "$RealBin/$basename"; # From path/to/verilator with verilator_bin installed
} else { } else {
$bin = $basename; # Find in PATH $bin = $basename; # Find in PATH
} }
# Note we don't look under bin/$basename which would be right if running # Note we don't look under bin/$basename which would be right if running
# in the kit dir. Running that would likely break, since # in the kit dir. Running that would likely break, since
# VERILATOR_ROOT wouldn't be set and Verilator won't find internal files. # VERILATOR_ROOT wouldn't be set and Verilator won't find internal files.
} }
return $bin; return $bin;
} }
@ -125,23 +125,23 @@ sub run {
system($command); system($command);
my $status = $?; my $status = $?;
if ($status) { if ($status) {
if ($! =~ /no such file or directory/i) { if ($! =~ /no such file or directory/i) {
warn "%Error: verilator_coverage: Misinstalled, or VERILATOR_ROOT might need to be in environment\n"; warn "%Error: verilator_coverage: Misinstalled, or VERILATOR_ROOT might need to be in environment\n";
} }
if ($Debug) { # For easy rerunning if ($Debug) { # For easy rerunning
warn "%Error: export VERILATOR_ROOT=".($ENV{VERILATOR_ROOT}||"")."\n"; warn "%Error: export VERILATOR_ROOT=".($ENV{VERILATOR_ROOT}||"")."\n";
warn "%Error: $command\n"; warn "%Error: $command\n";
} }
if ($status & 127) { if ($status & 127) {
if (($status & 127) == 8 || ($status & 127) == 11) { # SIGFPA or SIGSEGV if (($status & 127) == 8 || ($status & 127) == 11) { # SIGFPA or SIGSEGV
warn "%Error: Verilator_coverage internal fault, sorry.\n" if !$Debug; warn "%Error: Verilator_coverage internal fault, sorry.\n" if !$Debug;
} elsif (($status & 127) == 6) { # SIGABRT } elsif (($status & 127) == 6) { # SIGABRT
warn "%Error: Verilator_coverage aborted.\n" if !$Debug; warn "%Error: Verilator_coverage aborted.\n" if !$Debug;
} else { } else {
warn "%Error: Verilator_coverage threw signal $status.\n" if !$Debug; warn "%Error: Verilator_coverage threw signal $status.\n" if !$Debug;
} }
} }
die "%Error: Command Failed $command\n"; die "%Error: Command Failed $command\n";
} }
} }

View File

@ -38,11 +38,11 @@ my $Opt_Lineno = 1;
autoflush STDOUT 1; autoflush STDOUT 1;
autoflush STDERR 1; autoflush STDERR 1;
Getopt::Long::config("no_auto_abbrev"); Getopt::Long::config("no_auto_abbrev");
if (! GetOptions ( if (! GetOptions(
"help" => \&usage, "help" => \&usage,
"debug" => \&debug, "debug" => \&debug,
"<>" => \&parameter, "<>" => \&parameter,
"lineno!" => \$Opt_Lineno, "lineno!" => \$Opt_Lineno,
)) { )) {
die "%Error: Bad usage, try 'verilator_difftree --help'\n"; die "%Error: Bad usage, try 'verilator_difftree --help'\n";
} }
@ -68,22 +68,22 @@ sub diff_dir {
my %files; my %files;
foreach my $fn (glob("$a/*.tree")) { foreach my $fn (glob("$a/*.tree")) {
(my $base = $fn) =~ s!.*/!!; (my $base = $fn) =~ s!.*/!!;
$files{$base}{a} = $fn; $files{$base}{a} = $fn;
} }
foreach my $fn (glob("$b/*.tree")) { foreach my $fn (glob("$b/*.tree")) {
(my $base = $fn) =~ s!.*/!!; (my $base = $fn) =~ s!.*/!!;
$files{$base}{b} = $fn; $files{$base}{b} = $fn;
} }
my $any; my $any;
foreach my $base (sort (keys %files)) { foreach my $base (sort (keys %files)) {
my $a = $files{$base}{a}; my $a = $files{$base}{a};
my $b = $files{$base}{b}; my $b = $files{$base}{b};
next if !$a || !$b; next if !$a || !$b;
print "="x70,"\n"; print "="x70,"\n";
print "= $a <-> $b\n"; print "= $a <-> $b\n";
diff_file($a,$b); diff_file($a,$b);
$any = 1; $any = 1;
} }
$any or warn("%Warning: No .tree files found that have similar base names:\n " $any or warn("%Warning: No .tree files found that have similar base names:\n "
.join("\n ", sort keys %files),"\n"); .join("\n ", sort keys %files),"\n");
@ -101,7 +101,7 @@ sub diff_file {
my $vera = version_from($a); my $vera = version_from($a);
my $verb = version_from($b); my $verb = version_from($b);
my $verCvt = (($vera < 0x3900 && $verb >= 0x3900) my $verCvt = (($vera < 0x3900 && $verb >= 0x3900)
|| ($vera >= 0x3900 && $verb < 0x3900)); || ($vera >= 0x3900 && $verb < 0x3900));
filter($a, $tmp_a, $verCvt); filter($a, $tmp_a, $verCvt);
filter($b, $tmp_b, $verCvt); filter($b, $tmp_b, $verCvt);
@ -115,8 +115,8 @@ sub version_from {
# Return dump format # Return dump format
my $f1 = IO::File->new ($fn) or die "%Error: $! $fn,"; my $f1 = IO::File->new ($fn) or die "%Error: $! $fn,";
while (defined (my $line=$f1->getline())) { while (defined (my $line=$f1->getline())) {
last if $. > 10; last if $. > 10;
return hex $1 if $line =~ /\(format (0x[0-9.]+)\)/; return hex $1 if $line =~ /\(format (0x[0-9.]+)\)/;
} }
return 1.0; return 1.0;
} }
@ -130,36 +130,36 @@ sub filter {
my $f2 = IO::File->new ($fn2,"w") or die "%Error: $! $fn2,"; my $f2 = IO::File->new ($fn2,"w") or die "%Error: $! $fn2,";
while (defined (my $line=$f1->getline())) { while (defined (my $line=$f1->getline())) {
same_line: same_line:
next if $line =~ / This=/; next if $line =~ / This=/;
$line =~ s/0x[a-f0-9]+/0x/g; $line =~ s/0x[a-f0-9]+/0x/g;
$line =~ s/<e[0-9]+\#?>/<e>/g; $line =~ s/<e[0-9]+\#?>/<e>/g;
$line =~ s/{[a-z]*\d+}/{}/g if !$Opt_Lineno; $line =~ s/{[a-z]*\d+}/{}/g if !$Opt_Lineno;
if ($verCvt) { if ($verCvt) {
next if $line =~ /^ NETLIST/; next if $line =~ /^ NETLIST/;
$line =~ s!\@dt=0x\(G?/?([^)]+)\)!$1!g; # NEW: @dt -> OLD: non @dt format $line =~ s!\@dt=0x\(G?/?([^)]+)\)!$1!g; # NEW: @dt -> OLD: non @dt format
# # Below Ver1_Non_Dtyped may replace above further # # Below Ver1_Non_Dtyped may replace above further
if ($line =~ /: ([A-Z]+) /) { if ($line =~ /: ([A-Z]+) /) {
my $type = $1; my $type = $1;
next if $type =~ 'DTYPE'; next if $type =~ 'DTYPE';
if ($type eq 'TYPETABLE' || $type eq 'RANGE') { if ($type eq 'TYPETABLE' || $type eq 'RANGE') {
$line =~ /^(\s+\S+:) /; my $prefix = $1; $line =~ /^(\s+\S+:) /; my $prefix = $1;
while (defined ($line=$f1->getline())) { while (defined ($line=$f1->getline())) {
next if $line =~ /^\s+[a-z]/; # Table body next if $line =~ /^\s+[a-z]/; # Table body
next if $line =~ /^${prefix}[0-9]:/; next if $line =~ /^${prefix}[0-9]:/;
goto same_line; goto same_line;
} }
next; next;
} }
if ($Ver1_Non_Dtyped{$type}) { if ($Ver1_Non_Dtyped{$type}) {
$line =~ s! w[0-9]+!!g; $line =~ s! w[0-9]+!!g;
} }
} }
$line =~ s!\@dt=0$!NoW!g; # NEW: dt=null -> common format $line =~ s!\@dt=0$!NoW!g; # NEW: dt=null -> common format
$line =~ s!\@dt=0 !NoW !g; # NEW: dt=null -> common format $line =~ s!\@dt=0 !NoW !g; # NEW: dt=null -> common format
$line =~ s! s?w0$! NoW!g; # OLD: no width -> common format $line =~ s! s?w0$! NoW!g; # OLD: no width -> common format
$line =~ s! s?w0 ! NoW !g; # OLD: no width -> common format $line =~ s! s?w0 ! NoW !g; # OLD: no width -> common format
} }
print $f2 $line; print $f2 $line;
} }
$f1->close; $f1->close;
$f2->close; $f2->close;
@ -179,11 +179,11 @@ sub debug {
sub parameter { sub parameter {
my $param = shift; my $param = shift;
if (!defined $Opt_A) { if (!defined $Opt_A) {
$Opt_A = $param; $Opt_A = $param;
} elsif (!defined $Opt_B) { } elsif (!defined $Opt_B) {
$Opt_B = $param; $Opt_B = $param;
} else { } else {
die "%Error: Unknown parameter: $param\n"; die "%Error: Unknown parameter: $param\n";
} }
} }

View File

@ -24,11 +24,11 @@ my $Opt_File;
autoflush STDOUT 1; autoflush STDOUT 1;
autoflush STDERR 1; autoflush STDERR 1;
Getopt::Long::config("no_auto_abbrev"); Getopt::Long::config("no_auto_abbrev");
if (! GetOptions ( if (! GetOptions(
"help" => \&usage, "help" => \&usage,
"debug" => \&debug, "debug" => \&debug,
"<>" => \&parameter, "<>" => \&parameter,
)) { )) {
die "%Error: Bad usage, try 'verilator_profcfunc --help'\n"; die "%Error: Bad usage, try 'verilator_profcfunc --help'\n";
} }
@ -50,9 +50,9 @@ sub debug {
sub parameter { sub parameter {
my $param = shift; my $param = shift;
if (!defined $Opt_File) { if (!defined $Opt_File) {
$Opt_File = $param; $Opt_File = $param;
} else { } else {
die "%Error: Unknown parameter: $param\n"; die "%Error: Unknown parameter: $param\n";
} }
} }
@ -66,13 +66,13 @@ sub profcfunc {
my %funcs; my %funcs;
while (defined (my $line=$fh->getline())) { while (defined (my $line=$fh->getline())) {
# %time cumesec selfsec calls {stuff} name # %time cumesec selfsec calls {stuff} name
if ($line =~ /^\s*([0-9.]+)\s+[0-9.]+\s+([0-9.]+)\s+([0-9.]+)\s+[^a-zA-Z_]*([a-zA-Z_].*)$/) { if ($line =~ /^\s*([0-9.]+)\s+[0-9.]+\s+([0-9.]+)\s+([0-9.]+)\s+[^a-zA-Z_]*([a-zA-Z_].*)$/) {
my $pct=$1; my $sec=$2; my $calls=$3; my $func=$4; my $pct=$1; my $sec=$2; my $calls=$3; my $func=$4;
$funcs{$func}{pct} += $pct; $funcs{$func}{pct} += $pct;
$funcs{$func}{sec} += $sec; $funcs{$func}{sec} += $sec;
$funcs{$func}{calls} += $calls; $funcs{$func}{calls} += $calls;
} }
# Older gprofs have no call column for single-call functions # Older gprofs have no call column for single-call functions
# %time cumesec selfsec {stuff} name # %time cumesec selfsec {stuff} name
elsif ($line =~ /^\s*([0-9.]+)\s+[0-9.]+\s+([0-9.]+)\s+[^a-zA-Z_]*([a-zA-Z_].*)$/) { elsif ($line =~ /^\s*([0-9.]+)\s+[0-9.]+\s+([0-9.]+)\s+[^a-zA-Z_]*([a-zA-Z_].*)$/) {
@ -88,10 +88,10 @@ sub profcfunc {
my %pointer_mods; my %pointer_mods;
my %verilated_mods; my %verilated_mods;
foreach my $func (keys %funcs) { foreach my $func (keys %funcs) {
if ($func =~ /(.*)::_eval\(([a-zA-Z_0-9]+__Syms).*\)$/) { if ($func =~ /(.*)::_eval\(([a-zA-Z_0-9]+__Syms).*\)$/) {
$verilated_mods{$1} = qr/^$1/; $verilated_mods{$1} = qr/^$1/;
$pointer_mods{$2} = $1; $pointer_mods{$2} = $1;
} }
} }
#print Dumper(\%pointer_mods, \%verilated_mods); #print Dumper(\%pointer_mods, \%verilated_mods);
@ -99,72 +99,72 @@ sub profcfunc {
my %vfuncs; my %vfuncs;
my %groups; my %groups;
foreach my $func (keys %funcs) { foreach my $func (keys %funcs) {
my $pct = $funcs{$func}{pct}; my $pct = $funcs{$func}{pct};
my $vfunc = $func; my $vfunc = $func;
my $design; my $design;
if ($func =~ /\(([a-zA-Z_0-9]+__Syms)/) { if ($func =~ /\(([a-zA-Z_0-9]+__Syms)/) {
$design = $pointer_mods{$1}; $design = $pointer_mods{$1};
} }
foreach my $vde (keys %verilated_mods) { foreach my $vde (keys %verilated_mods) {
last if $design; last if $design;
if ($func =~ /$verilated_mods{$vde}/) { if ($func =~ /$verilated_mods{$vde}/) {
$design=$vde; $design=$vde;
last; last;
} }
} }
if ($vfunc =~ /__PROF__([a-zA-Z_0-9]+)__l?([0-9]+)\(/) { if ($vfunc =~ /__PROF__([a-zA-Z_0-9]+)__l?([0-9]+)\(/) {
$vfunc = sprintf("VBlock %s:%d", $1, $2); $vfunc = sprintf("VBlock %s:%d", $1, $2);
$groups{type}{"Verilog Blocks under $design"} += $pct; $groups{type}{"Verilog Blocks under $design"} += $pct;
$groups{design}{$design} += $pct; $groups{design}{$design} += $pct;
$groups{module}{$1} += $pct; $groups{module}{$1} += $pct;
} else { } else {
if ($design) { if ($design) {
$vfunc = sprintf("VCommon %s", $func); $vfunc = sprintf("VCommon %s", $func);
$groups{type}{"Common code under $design"} += $pct; $groups{type}{"Common code under $design"} += $pct;
$groups{design}{$design} += $pct; $groups{design}{$design} += $pct;
$groups{module}{$design." common code"} += $pct; $groups{module}{$design." common code"} += $pct;
} elsif ($func =~ /^VL_[A-Z0-9_]+/ } elsif ($func =~ /^VL_[A-Z0-9_]+/
|| $func =~ /^_?vl_[a-zA-Z0-9_]+/ || $func =~ /^_?vl_[a-zA-Z0-9_]+/
|| $func =~ /^verilated/i) { || $func =~ /^verilated/i) {
$vfunc = sprintf("VLib %s", $func); $vfunc = sprintf("VLib %s", $func);
$groups{type}{'VLib'} += $pct; $groups{type}{'VLib'} += $pct;
$groups{design}{'VLib'} += $pct; $groups{design}{'VLib'} += $pct;
$groups{module}{'VLib'} += $pct; $groups{module}{'VLib'} += $pct;
} elsif ($func =~ /^_mcount_private/) { } elsif ($func =~ /^_mcount_private/) {
$vfunc = sprintf("Prof %s", $func); $vfunc = sprintf("Prof %s", $func);
$groups{type}{'Prof'} += $pct; $groups{type}{'Prof'} += $pct;
$groups{design}{'Prof'} += $pct; $groups{design}{'Prof'} += $pct;
$groups{module}{'Prof'} += $pct; $groups{module}{'Prof'} += $pct;
} else { } else {
$vfunc = sprintf("C++ %s", $func); $vfunc = sprintf("C++ %s", $func);
$groups{type}{'C++'} += $pct; $groups{type}{'C++'} += $pct;
$groups{design}{'C++'} += $pct; $groups{design}{'C++'} += $pct;
$groups{module}{'C++'} += $pct; $groups{module}{'C++'} += $pct;
} }
} }
$vfuncs{$vfunc} = $funcs{$func}; $vfuncs{$vfunc} = $funcs{$func};
} }
foreach my $type (qw(type design module)) { foreach my $type (qw(type design module)) {
my $missing = 100; my $missing = 100;
foreach (sort (keys %{$groups{$type}})) { foreach (sort (keys %{$groups{$type}})) {
$missing -= $groups{$type}{$_}; $missing -= $groups{$type}{$_};
} }
if ($missing) { if ($missing) {
$groups{$type}{"\377Unaccounted for/rounding error"} = $missing; $groups{$type}{"\377Unaccounted for/rounding error"} = $missing;
} }
print("Overall summary by $type:\n"); print("Overall summary by $type:\n");
printf(" %-6s %s\n","% time",$type); printf(" %-6s %s\n","% time",$type);
foreach my $what (sort (keys %{$groups{$type}})) { foreach my $what (sort (keys %{$groups{$type}})) {
(my $pwhat = $what) =~ s/^\377//; # Just used to establish sort order (my $pwhat = $what) =~ s/^\377//; # Just used to establish sort order
printf(" %6.2f %s\n", $groups{$type}{$what}, $pwhat); printf(" %6.2f %s\n", $groups{$type}{$what}, $pwhat);
} }
print("\n"); print("\n");
} }
print("Verilog code profile:\n"); print("Verilog code profile:\n");
@ -181,14 +181,14 @@ sub profcfunc {
my $cume = 0; my $cume = 0;
foreach my $func (sort {$vfuncs{$b}{sec} <=> $vfuncs{$a}{sec} foreach my $func (sort {$vfuncs{$b}{sec} <=> $vfuncs{$a}{sec}
|| $a cmp $b} || $a cmp $b}
(keys %vfuncs)) { (keys %vfuncs)) {
$cume += $vfuncs{$func}{sec}; $cume += $vfuncs{$func}{sec};
printf +("%6.2f %9.2f %8.2f %8d %s\n", printf +("%6.2f %9.2f %8.2f %8d %s\n",
$vfuncs{$func}{pct}, $vfuncs{$func}{pct},
$cume, $vfuncs{$func}{sec}, $cume, $vfuncs{$func}{sec},
$vfuncs{$func}{calls}, $vfuncs{$func}{calls},
$func); $func);
} }
} }

View File

@ -41,7 +41,7 @@ int main(int argc, char** argv, char** env) {
Verilated::commandArgs(argc, argv); Verilated::commandArgs(argc, argv);
// Construct the Verilated model, from Vtop.h generated from Verilating "top.v" // Construct the Verilated model, from Vtop.h generated from Verilating "top.v"
Vtop* top = new Vtop; // Or use a const unique_ptr, or the VL_UNIQUE_PTR wrapper Vtop* top = new Vtop; // Or use a const unique_ptr, or the VL_UNIQUE_PTR wrapper
#if VM_TRACE #if VM_TRACE
// If verilator was invoked with --trace argument, // If verilator was invoked with --trace argument,
@ -94,14 +94,14 @@ int main(int argc, char** argv, char** env) {
#if VM_TRACE #if VM_TRACE
// Dump trace data for this cycle // Dump trace data for this cycle
if (tfp) tfp->dump (main_time); if (tfp) tfp->dump(main_time);
#endif #endif
// Read outputs // Read outputs
VL_PRINTF ("[%" VL_PRI64 "d] clk=%x rstl=%x iquad=%" VL_PRI64 "x" VL_PRINTF("[%" VL_PRI64 "d] clk=%x rstl=%x iquad=%" VL_PRI64 "x"
" -> oquad=%" VL_PRI64"x owide=%x_%08x_%08x\n", " -> oquad=%" VL_PRI64"x owide=%x_%08x_%08x\n",
main_time, top->clk, top->reset_l, top->in_quad, main_time, top->clk, top->reset_l, top->in_quad,
top->out_quad, top->out_wide[2], top->out_wide[1], top->out_wide[0]); top->out_quad, top->out_wide[2], top->out_wide[1], top->out_wide[0]);
} }
// Final model cleanup // Final model cleanup

View File

@ -115,9 +115,9 @@ int sc_main(int argc, char* argv[]) {
// Apply inputs // Apply inputs
if (VL_TIME_Q() > 1 && VL_TIME_Q() < 10) { if (VL_TIME_Q() > 1 && VL_TIME_Q() < 10) {
reset_l = !1; // Assert reset reset_l = !1; // Assert reset
} else if (VL_TIME_Q() > 1) { } else if (VL_TIME_Q() > 1) {
reset_l = !0; // Deassert reset reset_l = !0; // Deassert reset
} }
// Simulate 1ns // Simulate 1ns

View File

@ -49,7 +49,7 @@ module sub
// An example assertion // An example assertion
always_ff @ (posedge clk) begin always_ff @ (posedge clk) begin
AssertionExample: assert (!reset_l || count_c<100); AssertionExample: assert(!reset_l || count_c<100);
end end
// And example coverage analysis // And example coverage analysis

View File

@ -23,9 +23,9 @@ our $Debug;
our $Opt_Unsup; our $Opt_Unsup;
if (! GetOptions ( if (! GetOptions (
#"help" => \&usage, #"help" => \&usage,
"debug" => sub { $Debug = 1; }, "debug" => sub { $Debug = 1; },
"unsup!" => \$Opt_Unsup, # Ignore unsupported "unsup!" => \$Opt_Unsup, # Ignore unsupported
)) { )) {
die "usage();" die "usage();"
} }
@ -59,24 +59,24 @@ sub prep {
my $rule = ""; my $rule = "";
my $skip = 1; my $skip = 1;
while (defined(my $line = $fh->getline)) { while (defined(my $line = $fh->getline)) {
if ($skip == 1) { if ($skip == 1) {
next if $line !~ /%token/; next if $line !~ /%token/;
$skip = 2; $skip = 2;
} }
if ($Opt_Unsup) { if ($Opt_Unsup) {
$line =~ s!//UNSUP!|!g; $line =~ s!//UNSUP!|!g;
$line =~ s!(\s+)\|(\s+)!$1$2!g; # As "UNSUP" often replaces "|" $line =~ s!(\s+)\|(\s+)!$1$2!g; # As "UNSUP" often replaces "|"
} }
# %type<foo> # %type<foo>
$line =~ s/^(%\S+)<(\S+)>/$1/; $line =~ s/^(%\S+)<(\S+)>/$1/;
# rule<foo> # rule<foo>
$line =~ s/^([a-zA-Z0-9_]+)<\S+>:/$1:/; $line =~ s/^([a-zA-Z0-9_]+)<\S+>:/$1:/;
# Productions # Productions
$line =~ s/[ \t]{[^}]*?}/\t{}/g; $line =~ s/[ \t]{[^}]*?}/\t{}/g;
$fho->print($line); $fho->print($line);
} }
} }

View File

@ -32,27 +32,27 @@ foreach my $line (<STDIN>) {
$line =~ s!\s+! !g; $line =~ s!\s+! !g;
next if $line eq ''; next if $line eq '';
if ($line =~ m!^\%\%!) { if ($line =~ m!^\%\%!) {
$body++; $body++;
} elsif ($body == 1) { } elsif ($body == 1) {
$rule .= $line; $rule .= $line;
if ($line =~ m!^\s*;\s*$!) { if ($line =~ m!^\s*;\s*$!) {
#print "Rule: $rule\n"; #print "Rule: $rule\n";
($rule =~ /^([a-zA-Z0-9_]+)(<\S+>)?:(.*)$/) or die "%Error: No rule name: $1\n"; ($rule =~ /^([a-zA-Z0-9_]+)(<\S+>)?:(.*)$/) or die "%Error: No rule name: $1\n";
my $rulename = $1; my $preaction = $3; my $rulename = $1; my $preaction = $3;
$declared{$rulename} = $lineno; $declared{$rulename} = $lineno;
$preaction =~ s/\{[^\}]*\}/ /g; $preaction =~ s/\{[^\}]*\}/ /g;
#print "RULEN $rulename PA $preaction\n" if $Debug; #print "RULEN $rulename PA $preaction\n" if $Debug;
$rule = ''; $rule = '';
foreach my $ref (split /\s+/, $preaction) { foreach my $ref (split /\s+/, $preaction) {
next if $ref !~ /^[a-zA-Z]/; next if $ref !~ /^[a-zA-Z]/;
next if $ref eq $rulename; next if $ref eq $rulename;
if (!$used{$ref} && $declared{$ref}) { if (!$used{$ref} && $declared{$ref}) {
print " %Warning: $lineno: $ref used by $rulename after declaration\n"; print " %Warning: $lineno: $ref used by $rulename after declaration\n";
} }
$used{$ref} = $lineno; $used{$ref} = $lineno;
print " ref $ref\n" if $Debug; print " ref $ref\n" if $Debug;
} }
} }
} }
} }

View File

@ -24,11 +24,11 @@ $Debug = 0;
my $opt_filename; my $opt_filename;
autoflush STDOUT 1; autoflush STDOUT 1;
autoflush STDERR 1; autoflush STDERR 1;
if (! GetOptions ( if (! GetOptions(
"help" => \&usage, "help" => \&usage,
"debug" => \&debug, "debug" => \&debug,
"<>" => \&parameter, "<>" => \&parameter,
)) { )) {
usage(); usage();
} }
@ -49,9 +49,9 @@ sub debug {
sub parameter { sub parameter {
my $param = shift; my $param = shift;
if (!$opt_filename) { if (!$opt_filename) {
$opt_filename = $param; $opt_filename = $param;
} else { } else {
die "%Error: Unknown parameter: $param\n"; die "%Error: Unknown parameter: $param\n";
} }
} }
@ -64,30 +64,30 @@ sub dotread {
my $header = 1; my $header = 1;
my $vnum = 0; my $vnum = 0;
while (defined (my $line = $fh->getline)) { while (defined (my $line = $fh->getline)) {
if ($line =~ /^\t([a-zA-Z0-9_]+)\t(.*)$/) { if ($line =~ /^\t([a-zA-Z0-9_]+)\t(.*)$/) {
next if $1 eq 'nTITLE'; next if $1 eq 'nTITLE';
$header = 0; $header = 0;
$Vertexes{$1} = {num => $vnum++, $Vertexes{$1} = {num => $vnum++,
line => $line, line => $line,
name => $1,}; name => $1,};
} }
elsif ($line =~ /^\t([a-zA-Z0-9_]+)\s+->\s+([a-zA-Z0-9_]+)\s+(.*)$/) { elsif ($line =~ /^\t([a-zA-Z0-9_]+)\s+->\s+([a-zA-Z0-9_]+)\s+(.*)$/) {
my $from=$1; my $to=$2; my $from=$1; my $to=$2;
my $weight = 1; $weight = $1 if $line =~ /weight=(\d+)/; my $weight = 1; $weight = $1 if $line =~ /weight=(\d+)/;
my $cutable = undef; $cutable = $1 if $line =~ /style=(\S+)/; my $cutable = undef; $cutable = $1 if $line =~ /style=(\S+)/;
my $edge = {num => $vnum++, my $edge = {num => $vnum++,
line => $line, line => $line,
weight => $weight, weight => $weight,
cutable => $cutable, cutable => $cutable,
from => $from, from => $from,
to => $to,}; to => $to,};
push @Edges, $edge; push @Edges, $edge;
$Edges{$from}{$to} = $edge; $Edges{$from}{$to} = $edge;
} }
elsif ($header) { elsif ($header) {
push @Header, $line; push @Header, $line;
print "IGNORE: $line"; print "IGNORE: $line";
} }
} }
} }
@ -100,14 +100,14 @@ sub cwrite {
$fh->print("void V3GraphTestImport::dotImport() {\n"); $fh->print("void V3GraphTestImport::dotImport() {\n");
$fh->print(" DfaGraph* gp = &m_graph;\n"); $fh->print(" DfaGraph* gp = &m_graph;\n");
foreach my $ver (sort {$a->{num} <=> $b->{num}} (values %Vertexes)) { foreach my $ver (sort {$a->{num} <=> $b->{num}} (values %Vertexes)) {
$fh->printf(" V3GraphTestVertex* %s = new V3GraphTestVertex(gp, \"%s\"); if (%s) {}\n", $fh->printf(" V3GraphTestVertex* %s = new V3GraphTestVertex(gp, \"%s\"); if (%s) {}\n",
$ver->{name}, $ver->{name}, $ver->{name}); $ver->{name}, $ver->{name}, $ver->{name});
} }
$fh->print("\n"); $fh->print("\n");
foreach my $edge (@Edges) { foreach my $edge (@Edges) {
$fh->printf(" new V3GraphEdge(gp, %s, %s, %s, %s);\n", $fh->printf(" new V3GraphEdge(gp, %s, %s, %s, %s);\n",
$edge->{from}, $edge->{to}, $edge->{from}, $edge->{to},
$edge->{weight}, $edge->{cutable}?"true":"false"); $edge->{weight}, $edge->{cutable}?"true":"false");
} }
$fh->print("}\n"); $fh->print("}\n");
} }

View File

@ -26,12 +26,12 @@ my $opt_filename;
my $opt_circle; my $opt_circle;
autoflush STDOUT 1; autoflush STDOUT 1;
autoflush STDERR 1; autoflush STDERR 1;
if (! GetOptions ( if (! GetOptions(
"help" => \&usage, "help" => \&usage,
"debug" => \&debug, "debug" => \&debug,
"<>" => \&parameter, "<>" => \&parameter,
"circle=s" => \$opt_circle, "circle=s" => \$opt_circle,
)) { )) {
usage(); usage();
} }
@ -54,9 +54,9 @@ sub debug {
sub parameter { sub parameter {
my $param = shift; my $param = shift;
if (!$opt_filename) { if (!$opt_filename) {
$opt_filename = $param; $opt_filename = $param;
} else { } else {
die "%Error: Unknown parameter: $param\n"; die "%Error: Unknown parameter: $param\n";
} }
} }
@ -68,16 +68,16 @@ sub dotread {
my $fh = IO::File->new($filename) or die "%Error: $! $filename,"; my $fh = IO::File->new($filename) or die "%Error: $! $filename,";
my $header = 1; my $header = 1;
while (defined (my $line = $fh->getline)) { while (defined (my $line = $fh->getline)) {
if ($line =~ /^\t([a-zA-Z0-9_]+)\t(.*)$/) { if ($line =~ /^\t([a-zA-Z0-9_]+)\t(.*)$/) {
$header = 0; $header = 0;
$Vertexes{$1} = $2; $Vertexes{$1} = $2;
} }
elsif ($line =~ /^\t([a-zA-Z0-9_]+)\s+->\s+([a-zA-Z0-9_]+)\s+(.*)$/) { elsif ($line =~ /^\t([a-zA-Z0-9_]+)\s+->\s+([a-zA-Z0-9_]+)\s+(.*)$/) {
$Edges{$1}{$2} = $3; $Edges{$1}{$2} = $3;
} }
elsif ($header) { elsif ($header) {
push @Header, $line; push @Header, $line;
} }
} }
} }
@ -85,12 +85,12 @@ sub dotread {
sub simplify { sub simplify {
foreach my $ver (sort (keys %Vertexes)) { foreach my $ver (sort (keys %Vertexes)) {
$Vertexes{$ver} = _simplify($Vertexes{$ver}); $Vertexes{$ver} = _simplify($Vertexes{$ver});
} }
foreach my $v1 (sort (keys %Edges)) { foreach my $v1 (sort (keys %Edges)) {
foreach my $v2 (sort (keys %{$Edges{$v1}})) { foreach my $v2 (sort (keys %{$Edges{$v1}})) {
$Edges{$v1}{$v2} = _simplify($Edges{$v1}{$v2}); $Edges{$v1}{$v2} = _simplify($Edges{$v1}{$v2});
} }
} }
} }
@ -103,15 +103,15 @@ sub _simplify {
sub dotwrite { sub dotwrite {
foreach my $line (@Header) { foreach my $line (@Header) {
print "$line"; print "$line";
} }
foreach my $ver (sort (keys %Vertexes)) { foreach my $ver (sort (keys %Vertexes)) {
print "\t$ver\t$Vertexes{$ver}\n"; print "\t$ver\t$Vertexes{$ver}\n";
} }
foreach my $v1 (sort (keys %Edges)) { foreach my $v1 (sort (keys %Edges)) {
foreach my $v2 (sort (keys %{$Edges{$v1}})) { foreach my $v2 (sort (keys %{$Edges{$v1}})) {
print "\t$v1 -> $v2\t$Edges{$v1}{$v2}\n"; print "\t$v1 -> $v2\t$Edges{$v1}{$v2}\n";
} }
} }
print "}\n"; print "}\n";
} }
@ -125,15 +125,15 @@ sub circle {
_circle_recurse($node, 1); _circle_recurse($node, 1);
foreach my $ver (keys %Vertexes) { foreach my $ver (keys %Vertexes) {
if (!$User{$ver}) { if (!$User{$ver}) {
delete $Vertexes{$ver}; delete $Vertexes{$ver};
delete $Edges{$ver}; delete $Edges{$ver};
} }
} }
foreach my $v1 (sort (keys %Edges)) { foreach my $v1 (sort (keys %Edges)) {
foreach my $v2 (sort (keys %{$Edges{$v1}})) { foreach my $v2 (sort (keys %{$Edges{$v1}})) {
if (!$Vertexes{$v2}) { delete $Edges{$v1}{$v2}; } if (!$Vertexes{$v2}) { delete $Edges{$v1}{$v2}; }
} }
} }
} }
@ -148,7 +148,7 @@ sub _circle_recurse {
$User2{$node} = 1; $User2{$node} = 1;
my $r = 0; my $r = 0;
foreach my $v2 (keys %{$Edges{$node}}) { foreach my $v2 (keys %{$Edges{$node}}) {
$r |= _circle_recurse($v2,$level++)||0; $r |= _circle_recurse($v2,$level++)||0;
} }
$User{$node} = 1 if $r; $User{$node} = 1 if $r;
$User2{$node} = 2; $User2{$node} = 2;

View File

@ -18,11 +18,11 @@ our $Opt_Jobs = calc_jobs();
autoflush STDOUT 1; autoflush STDOUT 1;
autoflush STDERR 1; autoflush STDERR 1;
Getopt::Long::config("no_auto_abbrev"); Getopt::Long::config("no_auto_abbrev");
if (! GetOptions ( if (! GetOptions(
"debug" => sub { $Debug = 1; }, "debug" => sub { $Debug = 1; },
"<>" => sub { die "%Error: Unknown parameter: $_[0]\n"; }, "<>" => sub { die "%Error: Unknown parameter: $_[0]\n"; },
"stage=i" => \$Opt_Stage, "stage=i" => \$Opt_Stage,
"j=i" => \$Opt_Jobs, "j=i" => \$Opt_Jobs,
)) { )) {
die "%Error: Bad usage, try 'install_test --help'\n"; die "%Error: Bad usage, try 'install_test --help'\n";
} }
@ -46,51 +46,51 @@ sub test {
my $testdirn= $srcdir."/test_regress/obj_dir/install_test_testn"; my $testdirn= $srcdir."/test_regress/obj_dir/install_test_testn";
if ($Opt_Stage <= 0) { if ($Opt_Stage <= 0) {
run("/bin/rm -rf $blddir"); run("/bin/rm -rf $blddir");
run("/bin/mkdir -p $blddir"); run("/bin/mkdir -p $blddir");
run("cd $blddir && $srcdir/configure --prefix $prefix"); run("cd $blddir && $srcdir/configure --prefix $prefix");
run("cd $blddir && make -j $Opt_Jobs"); run("cd $blddir && make -j $Opt_Jobs");
} }
# Install it under the prefix # Install it under the prefix
if ($Opt_Stage <= 1) { if ($Opt_Stage <= 1) {
run("/bin/rm -rf $prefix"); run("/bin/rm -rf $prefix");
run("/bin/mkdir -p $prefix"); run("/bin/mkdir -p $prefix");
run("cd $blddir && make install"); run("cd $blddir && make install");
run("test -e $prefix/share/man/man1/verilator.1"); run("test -e $prefix/share/man/man1/verilator.1");
run("test -e $prefix/share/verilator/examples/tracing_c/Makefile"); run("test -e $prefix/share/verilator/examples/tracing_c/Makefile");
run("test -e $prefix/share/verilator/include/verilated.h"); run("test -e $prefix/share/verilator/include/verilated.h");
run("test -e $prefix/bin/verilator"); run("test -e $prefix/bin/verilator");
run("test -e $prefix/bin/verilator_bin"); run("test -e $prefix/bin/verilator_bin");
run("test -e $prefix/bin/verilator_bin_dbg"); run("test -e $prefix/bin/verilator_bin_dbg");
run("test -e $prefix/bin/verilator_gantt"); run("test -e $prefix/bin/verilator_gantt");
run("test -e $prefix/bin/verilator_profcfunc"); run("test -e $prefix/bin/verilator_profcfunc");
} }
# Run a test using just the path # Run a test using just the path
if ($Opt_Stage <= 2) { if ($Opt_Stage <= 2) {
my $dir = $testdirp; my $dir = $testdirp;
run("/bin/rm -rf $dir"); run("/bin/rm -rf $dir");
run("/bin/mkdir -p $dir"); run("/bin/mkdir -p $dir");
my $bin1 = $prefix."/bin"; my $bin1 = $prefix."/bin";
my $bin2 = $prefix."/share/bin"; my $bin2 = $prefix."/share/bin";
write_verilog($dir); write_verilog($dir);
run("cd $dir && PATH=$bin1:$bin2:\$PATH verilator --cc foo.v --exe foo.cpp"); run("cd $dir && PATH=$bin1:$bin2:\$PATH verilator --cc foo.v --exe foo.cpp");
run("cd $dir/obj_dir && PATH=$bin1:$bin2:\$PATH make -f Vfoo.mk"); run("cd $dir/obj_dir && PATH=$bin1:$bin2:\$PATH make -f Vfoo.mk");
run("cd $dir && PATH=$bin1:$bin2:\$PATH obj_dir/Vfoo"); run("cd $dir && PATH=$bin1:$bin2:\$PATH obj_dir/Vfoo");
} }
# Run a test using exact path to binary # Run a test using exact path to binary
if ($Opt_Stage <= 3) { if ($Opt_Stage <= 3) {
my $dir = $testdirn; my $dir = $testdirn;
run("/bin/rm -rf $dir"); run("/bin/rm -rf $dir");
run("/bin/mkdir -p $dir"); run("/bin/mkdir -p $dir");
write_verilog($dir); write_verilog($dir);
my $bin1 = $prefix."/bin"; my $bin1 = $prefix."/bin";
my $bin2 = $prefix."/share/bin"; my $bin2 = $prefix."/share/bin";
run("cd $dir && $bin1/verilator --cc foo.v --exe foo.cpp"); run("cd $dir && $bin1/verilator --cc foo.v --exe foo.cpp");
run("cd $dir/obj_dir && make -f Vfoo.mk"); run("cd $dir/obj_dir && make -f Vfoo.mk");
run("cd $dir/obj_dir && ./Vfoo"); run("cd $dir/obj_dir && ./Vfoo");
} }
if ($Opt_Stage <= 9) { if ($Opt_Stage <= 9) {
@ -102,29 +102,29 @@ sub write_verilog {
my $dir = shift; my $dir = shift;
IO::File->new(">$dir/foo.v")->print('module t; initial begin $display("HELLO WORLD"); $finish; end endmodule'."\n"); IO::File->new(">$dir/foo.v")->print('module t; initial begin $display("HELLO WORLD"); $finish; end endmodule'."\n");
my $fh = IO::File->new(">$dir/foo.cpp"); my $fh = IO::File->new(">$dir/foo.cpp");
$fh->print('#include "Vfoo.h"' ,"\n"); $fh->print('#include "Vfoo.h"' ,"\n");
$fh->print('unsigned int main_time = 0;' ,"\n"); $fh->print('unsigned int main_time = 0;' ,"\n");
$fh->print('double sc_time_stamp() {' ,"\n"); $fh->print('double sc_time_stamp() {' ,"\n");
$fh->print(' return main_time;' ,"\n"); $fh->print(' return main_time;' ,"\n");
$fh->print('}' ,"\n"); $fh->print('}' ,"\n");
$fh->print('int main() {' ,"\n"); $fh->print('int main() {' ,"\n");
$fh->print(' Vfoo *top = new Vfoo;' ,"\n"); $fh->print(' Vfoo *top = new Vfoo;' ,"\n");
$fh->print(' while (!Verilated::gotFinish()) {',"\n"); $fh->print(' while (!Verilated::gotFinish()) {',"\n");
$fh->print(' top->eval();' ,"\n"); $fh->print(' top->eval();' ,"\n");
$fh->print(' main_time++;' ,"\n"); $fh->print(' main_time++;' ,"\n");
$fh->print(' }' ,"\n"); $fh->print(' }' ,"\n");
$fh->print(' top->final();' ,"\n"); $fh->print(' top->final();' ,"\n");
$fh->print('}' ,"\n"); $fh->print('}' ,"\n");
} }
sub cleanenv { sub cleanenv {
foreach my $var (keys %ENV) { foreach my $var (keys %ENV) {
if ($var eq "VERILATOR_ROOT" if ($var eq "VERILATOR_ROOT"
|| $var eq "VERILATOR_INCLUDE" || $var eq "VERILATOR_INCLUDE"
|| $var eq "VERILATOR_NO_OPT_BUILD") { || $var eq "VERILATOR_NO_OPT_BUILD") {
print "unset $var # Was '$ENV{$var}'\n"; print "unset $var # Was '$ENV{$var}'\n";
delete $ENV{$var} delete $ENV{$var}
} }
} }
} }
@ -132,8 +132,8 @@ sub cleanenv {
sub calc_jobs { sub calc_jobs {
my $ok = eval " my $ok = eval "
use Unix::Processors; use Unix::Processors;
return Unix::Processors->new->max_online; return Unix::Processors->new->max_online;
"; ";
$ok && !$@ or return 1; $ok && !$@ or return 1;
print "driver.pl: Found $ok cores, using -j ",$ok+1,"\n" if $Debug; print "driver.pl: Found $ok cores, using -j ",$ok+1,"\n" if $Debug;

View File

@ -23,11 +23,11 @@ $Debug = 0;
my $opt_filename; my $opt_filename;
autoflush STDOUT 1; autoflush STDOUT 1;
autoflush STDERR 1; autoflush STDERR 1;
if (! GetOptions ( if (! GetOptions(
"help" => \&usage, "help" => \&usage,
"debug" => \&debug, "debug" => \&debug,
"<>" => \&parameter, "<>" => \&parameter,
)) { )) {
usage(); usage();
} }
@ -51,9 +51,9 @@ sub debug {
sub parameter { sub parameter {
my $param = shift; my $param = shift;
if (!$opt_filename) { if (!$opt_filename) {
$opt_filename = $param; $opt_filename = $param;
} else { } else {
die "%Error: Unknown parameter: $param\n"; die "%Error: Unknown parameter: $param\n";
} }
} }
@ -64,45 +64,45 @@ sub vread {
my $fh = IO::File->new($filename) or die "%Error: $! $filename,"; my $fh = IO::File->new($filename) or die "%Error: $! $filename,";
my $lasthier=""; my $lasthier="";
$Tree = { $Tree = {
op => 'NETLIST', op => 'NETLIST',
t => [[],[],[],[],[],], t => [[],[],[],[],[],],
}; };
my @stack; my @stack;
$stack[1] = $Tree; $stack[1] = $Tree;
while (defined (my $line = $fh->getline)) { while (defined (my $line = $fh->getline)) {
if ($line =~ /^\s+(\S+):\s+(\S+)\s+0x\S+\s+{(\d+)}\s+w(\d+)\s+(.*)$/) { if ($line =~ /^\s+(\S+):\s+(\S+)\s+0x\S+\s+{(\d+)}\s+w(\d+)\s+(.*)$/) {
my $hier = $1; my $hier = $1;
my $op = $2; my $op = $2;
my $lineno = $3; my $lineno = $3;
my $width = $4; my $width = $4;
my $etc = $5; my $etc = $5;
$etc =~ s/__DOT__/./g; $etc =~ s/__DOT__/./g;
$etc =~ s/__PVT__//g; $etc =~ s/__PVT__//g;
my $self = { my $self = {
op => $op, op => $op,
#width => $width, #width => $width,
#lineno => $lineno, #lineno => $lineno,
#line => $line, #line => $line,
etc => $etc, etc => $etc,
args => [split(/[ \t]+/,$etc)], args => [split(/[ \t]+/,$etc)],
t => [[],[],[],[],[],], t => [[],[],[],[],[],],
}; };
my @hiers = (1,split(/:/,$hier)); my @hiers = (1,split(/:/,$hier));
my $depth = $#hiers+1; my $depth = $#hiers+1;
my $newchild = $hiers[$#hiers]; my $newchild = $hiers[$#hiers];
#print "DD $depth $newchild $op\n"; #print "DD $depth $newchild $op\n";
push @{$stack[$depth-1]->{t}[$newchild]}, $self; push @{$stack[$depth-1]->{t}[$newchild]}, $self;
$stack[$depth] = $self; $stack[$depth] = $self;
$lasthier = $hier; $lasthier = $hier;
#print " $lasthier\n"; #print " $lasthier\n";
#print Dumper($Tree); #print Dumper($Tree);
} }
} }
} }
@ -168,125 +168,125 @@ sub nl { p "\n"," "x$Indent; }
sub gentree { sub gentree {
%OpMap = ( %OpMap = (
'NULLNODE' => sub { "" }, 'NULLNODE' => sub { "" },
'NETLIST' => sub { nl;t1;t2;t3;t4;t5; }, 'NETLIST' => sub { nl;t1;t2;t3;t4;t5; },
'ACTIVE' => sub { p "always_act @(";t1;p ") begin";indentInc;nl;t2;t3;t4;t5;indentDec;p "end";nl; }, 'ACTIVE' => sub { p "always_act @(";t1;p ") begin";indentInc;nl;t2;t3;t4;t5;indentDec;p "end";nl; },
'ADD' => sub { p1;p " + ";p2; }, 'ADD' => sub { p1;p " + ";p2; },
'ALWAYS' => sub { p "always @(";t1;p ") begin";indentInc;nl;t2;t3;t4;t5;indentDec;p "end";nl; }, 'ALWAYS' => sub { p "always @(";t1;p ") begin";indentInc;nl;t2;t3;t4;t5;indentDec;p "end";nl; },
'ALWAYSPOST' => sub { p "ALWAYSPOST what{";p1;p ",";p2;p ",";p3;p ",";p4;p ",";p5;p "}";nl; }, 'ALWAYSPOST' => sub { p "ALWAYSPOST what{";p1;p ",";p2;p ",";p3;p ",";p4;p ",";p5;p "}";nl; },
'AND' => sub { p1;p " & ";p2; }, 'AND' => sub { p1;p " & ";p2; },
'ARRAYSEL' => sub { t1;p "[";t2;p "]"; }, 'ARRAYSEL' => sub { t1;p "[";t2;p "]"; },
'ASSIGN' => sub { t2;p " = ";t1;p ";";nl; }, 'ASSIGN' => sub { t2;p " = ";t1;p ";";nl; },
'ASSIGNDLY' => sub { t2;p " <= ";t1;p ";";nl; }, 'ASSIGNDLY' => sub { t2;p " <= ";t1;p ";";nl; },
'ASSIGNPOST' => sub { p "ASSIGNPOST what{";t1;p " = ";t2;p ";";nl; }, 'ASSIGNPOST' => sub { p "ASSIGNPOST what{";t1;p " = ";t2;p ";";nl; },
'ASSIGNPRE' => sub { p "ASSIGNPRE what{";t1;p " = ";t2;p ";";nl; }, 'ASSIGNPRE' => sub { p "ASSIGNPRE what{";t1;p " = ";t2;p ";";nl; },
'ASSIGNW' => sub { p "assign ";t2;p " = ";t1;p ";";nl; }, 'ASSIGNW' => sub { p "assign ";t2;p " = ";t1;p ";";nl; },
'ATTROF' => sub { p "ATTROF what{";p1;p ",";p2;p ",";p3;p ",";p4;p ",";p5;p "}";nl; }, 'ATTROF' => sub { p "ATTROF what{";p1;p ",";p2;p ",";p3;p ",";p4;p ",";p5;p "}";nl; },
'BEGIN' => sub { p "begin";indentInc;nl;t1;t2;t3;t4;t5;indentDec;p "end";nl; }, 'BEGIN' => sub { p "begin";indentInc;nl;t1;t2;t3;t4;t5;indentDec;p "end";nl; },
'BITSEL' => sub { t1;local $Avoid_Hex=1; p "[";t2;p "]"; }, 'BITSEL' => sub { t1;local $Avoid_Hex=1; p "[";t2;p "]"; },
'CASE' => sub { p "CASE what{";p1;p ",";p2;p ",";p3;p ",";p4;p ",";p5;p "}";nl; }, 'CASE' => sub { p "CASE what{";p1;p ",";p2;p ",";p3;p ",";p4;p ",";p5;p "}";nl; },
'CASEITEM' => sub { p "CASEITEM what{";p1;p ",";p2;p ",";p3;p ",";p4;p ",";p5;p "}";nl; }, 'CASEITEM' => sub { p "CASEITEM what{";p1;p ",";p2;p ",";p3;p ",";p4;p ",";p5;p "}";nl; },
'CAST' => sub { p "CAST what{";p1;p ",";p2;p ",";p3;p ",";p4;p ",";p5;p "}";nl; }, 'CAST' => sub { p "CAST what{";p1;p ",";p2;p ",";p3;p ",";p4;p ",";p5;p "}";nl; },
'CCALL' => sub { p "CCALL what{";p1;p ",";p2;p ",";p3;p ",";p4;p ",";p5;p "}";nl; }, 'CCALL' => sub { p "CCALL what{";p1;p ",";p2;p ",";p3;p ",";p4;p ",";p5;p "}";nl; },
'CELL' => sub { a1;p " ";a7;p " (/*CELL*/);"; nl; }, 'CELL' => sub { a1;p " ";a7;p " (/*CELL*/);"; nl; },
'CFUNC' => sub { p "CFUNC what{";p1;p ",";p2;p ",";p3;p ",";p4;p ",";p5;p "}";nl; }, 'CFUNC' => sub { p "CFUNC what{";p1;p ",";p2;p ",";p3;p ",";p4;p ",";p5;p "}";nl; },
'CHANGEDET' => sub { p "CHANGEDET what{";p1;p ",";p2;p ",";p3;p ",";p4;p ",";p5;p "}";nl; }, 'CHANGEDET' => sub { p "CHANGEDET what{";p1;p ",";p2;p ",";p3;p ",";p4;p ",";p5;p "}";nl; },
'CINCLUDE' => sub { p "CINCLUDE what{";p1;p ",";p2;p ",";p3;p ",";p4;p ",";p5;p "}";nl; }, 'CINCLUDE' => sub { p "CINCLUDE what{";p1;p ",";p2;p ",";p3;p ",";p4;p ",";p5;p "}";nl; },
'COMMENT' => sub { p "//COMMENT what{";p1;p ",";p2;p ",";p3;p ",";p4;p ",";p5;p "}";nl;nl; }, 'COMMENT' => sub { p "//COMMENT what{";p1;p ",";p2;p ",";p3;p ",";p4;p ",";p5;p "}";nl;nl; },
'CONCAT' => sub { p "{";p1;p ",";p2;p "}"; }, 'CONCAT' => sub { p "{";p1;p ",";p2;p "}"; },
'CONDITIONAL' => sub { p1;p " ? ";p2;p " : ";p3; }, 'CONDITIONAL' => sub { p1;p " ? ";p2;p " : ";p3; },
'CONST' => sub { p_const(); }, 'CONST' => sub { p_const(); },
'COVER' => sub { p "COVER what{";p1;p ",";p2;p ",";p3;p ",";p4;p ",";p5;p "}";nl; }, 'COVER' => sub { p "COVER what{";p1;p ",";p2;p ",";p3;p ",";p4;p ",";p5;p "}";nl; },
'CRETURN' => sub { p "CRETURN what{";p1;p ",";p2;p ",";p3;p ",";p4;p ",";p5;p "}";nl; }, 'CRETURN' => sub { p "CRETURN what{";p1;p ",";p2;p ",";p3;p ",";p4;p ",";p5;p "}";nl; },
'CSTMT' => sub { p "CSTMT what{";p1;p ",";p2;p ",";p3;p ",";p4;p ",";p5;p "}";nl; }, 'CSTMT' => sub { p "CSTMT what{";p1;p ",";p2;p ",";p3;p ",";p4;p ",";p5;p "}";nl; },
'DEFPARAM' => sub { p "defparam ";p1;p " = ";p2;p ";";nl; }, 'DEFPARAM' => sub { p "defparam ";p1;p " = ";p2;p ";";nl; },
'DISPLAY' => sub { p '$write("';p1;p "\",";p2;p3;p4;p5;p ");";nl; }, 'DISPLAY' => sub { p '$write("';p1;p "\",";p2;p3;p4;p5;p ");";nl; },
'DIV' => sub { p1;p " / ";p2; }, 'DIV' => sub { p1;p " / ";p2; },
'EQ' => sub { p1;p " == ";p2; }, 'EQ' => sub { p1;p " == ";p2; },
'EQCASE' => sub { p1;p " === ";p2; }, 'EQCASE' => sub { p1;p " === ";p2; },
'EXTEND' => sub { t1; }, 'EXTEND' => sub { t1; },
'EXTRACT' => sub { t1;local $Avoid_Hex=1; p "[";t2;p ":";t3;p "]"; }, 'EXTRACT' => sub { t1;local $Avoid_Hex=1; p "[";t2;p ":";t3;p "]"; },
'FINISH' => sub { p '$finish;';nl }, 'FINISH' => sub { p '$finish;';nl },
'FOR' => sub { p "for (";p1;p ",";p2;p ",";p3;p ") begin";indentInc;nl;p4;p5;indentDec;p "end";nl; }, 'FOR' => sub { p "for (";p1;p ",";p2;p ",";p3;p ") begin";indentInc;nl;p4;p5;indentDec;p "end";nl; },
'FUNC' => sub { p "FUNC what{";p1;p ",";p2;p ",";p3;p ",";p4;p ",";p5;p "}";nl; }, 'FUNC' => sub { p "FUNC what{";p1;p ",";p2;p ",";p3;p ",";p4;p ",";p5;p "}";nl; },
'FUNCREF' => sub { p "FUNCREF what{";p1;p ",";p2;p ",";p3;p ",";p4;p ",";p5;p "}";nl; }, 'FUNCREF' => sub { p "FUNCREF what{";p1;p ",";p2;p ",";p3;p ",";p4;p ",";p5;p "}";nl; },
'GT' => sub { p1;p " > ";p2; }, 'GT' => sub { p1;p " > ";p2; },
'GTE' => sub { p1;p " >= ";p2; }, 'GTE' => sub { p1;p " >= ";p2; },
'IF' => sub { p "if (";p1;p ") begin";indentInc;nl;t2;indentDec;if (exists3) {p "end else begin";indentInc;nl;t3;indentDec;} p "end"; nl; }, 'IF' => sub { p "if (";p1;p ") begin";indentInc;nl;t2;indentDec;if (exists3) {p "end else begin";indentInc;nl;t3;indentDec;} p "end"; nl; },
'INITARRAY' => sub { p "INITARRAY what{";p1;p ",";p2;p ",";p3;p ",";p4;p ",";p5;p "}";nl; }, 'INITARRAY' => sub { p "INITARRAY what{";p1;p ",";p2;p ",";p3;p ",";p4;p ",";p5;p "}";nl; },
'INITIAL' => sub { p "initial begin";indentInc;nl;t1;t2;t3;t4;t5;indentDec;p "end";nl; }, 'INITIAL' => sub { p "initial begin";indentInc;nl;t1;t2;t3;t4;t5;indentDec;p "end";nl; },
'LOGAND' => sub { p1;p " && ";p2; }, 'LOGAND' => sub { p1;p " && ";p2; },
'LOGNOT' => sub { p1;p " || ";p2; }, 'LOGNOT' => sub { p1;p " || ";p2; },
'LOGOR' => sub { p "!";p1; }, 'LOGOR' => sub { p "!";p1; },
'LT' => sub { p1;p " < ";p2; }, 'LT' => sub { p1;p " < ";p2; },
'LTE' => sub { p1;p " <= ";p2; }, 'LTE' => sub { p1;p " <= ";p2; },
'MODDIV' => sub { p1;p " % ";p2; }, 'MODDIV' => sub { p1;p " % ";p2; },
'MODULE' => sub { p "module ";a1;p " (/*AUTOARG*/);";indentInc;nl;t1;t2;t3;t4;t5;indentDec;nl;p "endmodule";nl; }, 'MODULE' => sub { p "module ";a1;p " (/*AUTOARG*/);";indentInc;nl;t1;t2;t3;t4;t5;indentDec;nl;p "endmodule";nl; },
'MUL' => sub { p1;p " * ";p2; }, 'MUL' => sub { p1;p " * ";p2; },
'NEQ' => sub { p1;p " != ";p2; }, 'NEQ' => sub { p1;p " != ";p2; },
'NEQCASE' => sub { p1;p " !== ";p2; }, 'NEQCASE' => sub { p1;p " !== ";p2; },
'NOT' => sub { p " ~";p1; }, 'NOT' => sub { p " ~";p1; },
'OR' => sub { p1;p " | ";p2; }, 'OR' => sub { p1;p " | ";p2; },
'PIN' => sub { p ";p ";p1;p " (";p2;p "),";nl; }, 'PIN' => sub { p ";p ";p1;p " (";p2;p "),";nl; },
'PORT' => sub { p ""; }, 'PORT' => sub { p ""; },
'PRAGMA' => sub { p "PRAGMA what{";p1;p ",";p2;p ",";p3;p ",";p4;p ",";p5;p "}";nl; }, 'PRAGMA' => sub { p "PRAGMA what{";p1;p ",";p2;p ",";p3;p ",";p4;p ",";p5;p "}";nl; },
'RAND' => sub { p '$rand'; }, 'RAND' => sub { p '$rand'; },
'RANGE' => sub { t1; local $Avoid_Hex=1; p "[";t2;p ":";t3;p "]"; }, 'RANGE' => sub { t1; local $Avoid_Hex=1; p "[";t2;p ":";t3;p "]"; },
'REDAND' => sub { p "&(";p1;p ")"; }, 'REDAND' => sub { p "&(";p1;p ")"; },
'REDOR' => sub { p "|(";p1;p ")"; }, 'REDOR' => sub { p "|(";p1;p ")"; },
'REDXNOR' => sub { p "~|(";p1;p ")"; }, 'REDXNOR' => sub { p "~|(";p1;p ")"; },
'REDXOR' => sub { p "~^(";p1;p ")"; }, 'REDXOR' => sub { p "~^(";p1;p ")"; },
'REPLICATE' => sub { p "{";p1;p "{";p2;p "}}"; }, 'REPLICATE' => sub { p "{";p1;p "{";p2;p "}}"; },
'SCCTOR' => sub { p "SCCTOR what{";p1;p ",";p2;p ",";p3;p ",";p4;p ",";p5;p "}";nl; }, 'SCCTOR' => sub { p "SCCTOR what{";p1;p ",";p2;p ",";p3;p ",";p4;p ",";p5;p "}";nl; },
'SCHDR' => sub { p "SCHDR what{";p1;p ",";p2;p ",";p3;p ",";p4;p ",";p5;p "}";nl; }, 'SCHDR' => sub { p "SCHDR what{";p1;p ",";p2;p ",";p3;p ",";p4;p ",";p5;p "}";nl; },
'SCIMP' => sub { p "SCIMP what{";p1;p ",";p2;p ",";p3;p ",";p4;p ",";p5;p "}";nl; }, 'SCIMP' => sub { p "SCIMP what{";p1;p ",";p2;p ",";p3;p ",";p4;p ",";p5;p "}";nl; },
'SCINT' => sub { p "SCINT what{";p1;p ",";p2;p ",";p3;p ",";p4;p ",";p5;p "}";nl; }, 'SCINT' => sub { p "SCINT what{";p1;p ",";p2;p ",";p3;p ",";p4;p ",";p5;p "}";nl; },
'SCOPE' => sub { t1;t2;t3;t4;t5; }, 'SCOPE' => sub { t1;t2;t3;t4;t5; },
'SENITEM' => sub { a1;p " ";t1; }, 'SENITEM' => sub { a1;p " ";t1; },
'SENTREE' => sub { t1;t2;t3;t4;t5; }, 'SENTREE' => sub { t1;t2;t3;t4;t5; },
'SHIFTL' => sub { p1;p " << ";p2; }, 'SHIFTL' => sub { p1;p " << ";p2; },
'SHIFTR' => sub { p1;p " >> ";p2; }, 'SHIFTR' => sub { p1;p " >> ";p2; },
'STOP' => sub { p '$stop;';nl; }, 'STOP' => sub { p '$stop;';nl; },
'SUB' => sub { p1;p " - ";p2; }, 'SUB' => sub { p1;p " - ";p2; },
'TASK' => sub { p "TASK what{";p1;p ",";p2;p ",";p3;p ",";p4;p ",";p5;p "}";nl; }, 'TASK' => sub { p "TASK what{";p1;p ",";p2;p ",";p3;p ",";p4;p ",";p5;p "}";nl; },
'TASKREF' => sub { p "TASKREF what{";p1;p ",";p2;p ",";p3;p ",";p4;p ",";p5;p "}";nl; }, 'TASKREF' => sub { p "TASKREF what{";p1;p ",";p2;p ",";p3;p ",";p4;p ",";p5;p "}";nl; },
'TEXT' => sub { p "TEXT what{";p1;p ",";p2;p ",";p3;p ",";p4;p ",";p5;p "}";nl; }, 'TEXT' => sub { p "TEXT what{";p1;p ",";p2;p ",";p3;p ",";p4;p ",";p5;p "}";nl; },
'TIME' => sub { p '$time'; }, 'TIME' => sub { p '$time'; },
'TOPSCOPE' => sub { t1;t2;t3;t4;t5; }, 'TOPSCOPE' => sub { t1;t2;t3;t4;t5; },
'TRACE' => sub { p "TRACE what{";p1;p ",";p2;p ",";p3;p ",";p4;p ",";p5;p "}";nl; }, 'TRACE' => sub { p "TRACE what{";p1;p ",";p2;p ",";p3;p ",";p4;p ",";p5;p "}";nl; },
'UCFUNC' => sub { p '$c(';p1;p ",";p2;p ",";p3;p ",";p4;p ",";p5;p ")"; }, 'UCFUNC' => sub { p '$c(';p1;p ",";p2;p ",";p3;p ",";p4;p ",";p5;p ")"; },
'UCSTMT' => sub { p '$c(';p1;p ",";p2;p ",";p3;p ",";p4;p ",";p5;p ");";nl; }, 'UCSTMT' => sub { p '$c(';p1;p ",";p2;p ",";p3;p ",";p4;p ",";p5;p ");";nl; },
'NEGATE' => sub { p " -";p1; }, 'NEGATE' => sub { p " -";p1; },
'VAR' => sub { p_var(); }, 'VAR' => sub { p_var(); },
'VARPIN' => sub { p "VARPIN what{";p1;p ",";p2;p ",";p3;p ",";p4;p ",";p5;p "}";nl; }, 'VARPIN' => sub { p "VARPIN what{";p1;p ",";p2;p ",";p3;p ",";p4;p ",";p5;p "}";nl; },
'VARREF' => sub { a1; }, 'VARREF' => sub { a1; },
'VARSCOPE' => sub { }, 'VARSCOPE' => sub { },
'WHILE' => sub { t1; p "while (";t2;p ") begin";indentInc;nl;t3;t4;indentDec;p "end";nl; }, 'WHILE' => sub { t1; p "while (";t2;p ") begin";indentInc;nl;t3;t4;indentDec;p "end";nl; },
'WORDSEL' => sub { p1;p "[";p2;p ":";p3;p "]"; }, 'WORDSEL' => sub { p1;p "[";p2;p ":";p3;p "]"; },
'XNOR' => sub { p1;p " ~^ ";p2; }, 'XNOR' => sub { p1;p " ~^ ";p2; },
'XOR' => sub { p1;p " ^";p2; }, 'XOR' => sub { p1;p " ^";p2; },
); );
} }
sub p_var { sub p_var {
my $self = $Code_Self; my $self = $Code_Self;
if ($self->{etc} =~ /\[I\]/) { if ($self->{etc} =~ /\[I\]/) {
print "input"; print "input";
} elsif ($self->{etc} =~ /\[O\]/) { } elsif ($self->{etc} =~ /\[O\]/) {
print "output"; print "output";
} else { } else {
print "reg"; print "reg";
} }
p "\t"; p "\t";
{ {
local $Avoid_Hex=1; local $Avoid_Hex=1;
t1; t1;
} }
p "\t"; p "\t";
a1; a1;
if (exists2()) { if (exists2()) {
p " = "; p " = ";
t2; t2;
} }
p ";"; p ";";
nl; nl;
@ -295,10 +295,10 @@ sub p_var {
sub p_const { sub p_const {
my $v = $Code_Self->{args}[0]; my $v = $Code_Self->{args}[0];
if ($v =~ /\?32\?h(.*)$/ if ($v =~ /\?32\?h(.*)$/
|| ($Avoid_Hex && $v =~ /^[0-9?]*h(.*)$/)) { || ($Avoid_Hex && $v =~ /^[0-9?]*h(.*)$/)) {
print hex $1; print hex $1;
} else { } else {
print $v; print $v;
} }
} }

View File

@ -7,7 +7,7 @@ use Getopt::Long;
use IO::File; use IO::File;
use Pod::Usage; use Pod::Usage;
use strict; use strict;
use vars qw ($Debug @Types %Classes %Children %ClassRefs %Stages); use vars qw($Debug @Types %Classes %Children %ClassRefs %Stages);
#====================================================================== #======================================================================
# main # main
@ -17,8 +17,8 @@ my $opt_classes;
my $opt_report; my $opt_report;
my @Opt_Cpt; my @Opt_Cpt;
my @Opt_I; my @Opt_I;
Getopt::Long::config ("pass_through", "no_auto_abbrev"); Getopt::Long::config("pass_through", "no_auto_abbrev");
if (! GetOptions ( if (! GetOptions(
"help" => \&usage, "help" => \&usage,
"debug" => sub { $Debug = 1; }, "debug" => sub { $Debug = 1; },
"classes!" => \$opt_classes, "classes!" => \$opt_classes,
@ -51,17 +51,17 @@ foreach my $cpt (@Opt_Cpt) {
sub usage { sub usage {
pod2usage(-verbose=>2, -exitval=>2, -output=>\*STDOUT); pod2usage(-verbose=>2, -exitval=>2, -output=>\*STDOUT);
exit (1); exit(1);
} }
sub parameter { sub parameter {
my $param = shift; my $param = shift;
if ($param =~ /^-+I(\S+)/) { if ($param =~ /^-+I(\S+)/) {
push @Opt_I, $1; push @Opt_I, $1;
} elsif ($param =~ s/\.cpp$//) { } elsif ($param =~ s/\.cpp$//) {
push @Opt_Cpt, $param; push @Opt_Cpt, $param;
} else { } else {
die "%Error: Unknown parameter: $param,"; die "%Error: Unknown parameter: $param,";
} }
} }
@ -72,21 +72,21 @@ sub read_types {
my $fh = IO::File->new($filename) or die "%Error: $! $filename,"; my $fh = IO::File->new($filename) or die "%Error: $! $filename,";
while (defined (my $line = $fh->getline())) { while (defined (my $line = $fh->getline())) {
$line =~ s/\/\/.*$//; $line =~ s/\/\/.*$//;
next if $line =~ /^\s*$/; next if $line =~ /^\s*$/;
if ($line =~ /^\s*(class|struct)\s*(\S+)/) { if ($line =~ /^\s*(class|struct)\s*(\S+)/) {
my $class = $2; my $class = $2;
my $inh = ""; my $inh = "";
$inh = $1 if ($line =~ /:\s*public\s+(\S+)/); $inh = $1 if ($line =~ /:\s*public\s+(\S+)/);
print "class $class : $inh\n" if $Debug; print "class $class : $inh\n" if $Debug;
$inh = "" if $class eq "AstNode"; $inh = "" if $class eq "AstNode";
if ($inh =~ /Ast/ || $class eq "AstNode") { if ($inh =~ /Ast/ || $class eq "AstNode") {
$class =~ s/^Ast//; $class =~ s/^Ast//;
$inh =~ s/^Ast//; $inh =~ s/^Ast//;
$Classes{$class} = $inh; $Classes{$class} = $inh;
$Children{$inh}{$class} = 1; $Children{$inh}{$class} = 1;
} }
} }
} }
} }
@ -96,14 +96,14 @@ sub read_stages {
my $fh = IO::File->new($filename) or die "%Error: $! $filename,"; my $fh = IO::File->new($filename) or die "%Error: $! $filename,";
my $n = 0; my $n = 0;
while (defined (my $line = $fh->getline())) { while (defined (my $line = $fh->getline())) {
$line =~ s/\/\/.*$//; $line =~ s/\/\/.*$//;
next if $line =~ /^\s*$/; next if $line =~ /^\s*$/;
if ($line =~ /^\s*([A-Za-z0-9]+)::/) { if ($line =~ /^\s*([A-Za-z0-9]+)::/) {
my $stage = $1.".cpp"; my $stage = $1.".cpp";
if (!defined ($Stages{$stage})) { if (!defined ($Stages{$stage})) {
$Stages{$stage} = $n++; $Stages{$stage} = $n++;
} }
} }
} }
} }
@ -111,17 +111,17 @@ sub read_refs {
my @filenames = @_; my @filenames = @_;
foreach my $filename (@filenames) { foreach my $filename (@filenames) {
(my $basename = $filename) =~ s!.*/!!; (my $basename = $filename) =~ s!.*/!!;
my $fh = IO::File->new($filename) or die "%Error: $! $filename,"; my $fh = IO::File->new($filename) or die "%Error: $! $filename,";
while (defined (my $line = $fh->getline())) { while (defined (my $line = $fh->getline())) {
$line =~ s/\/\/.*$//; $line =~ s/\/\/.*$//;
while ($line =~ /\bnew\s*(Ast[A-Za-z0-9_]+)/g) { while ($line =~ /\bnew\s*(Ast[A-Za-z0-9_]+)/g) {
$ClassRefs{$1}{newed}{$basename} = 1; $ClassRefs{$1}{newed}{$basename} = 1;
} }
while ($line =~ /\b(Ast[A-Za-z0-9_]+)/g) { while ($line =~ /\b(Ast[A-Za-z0-9_]+)/g) {
$ClassRefs{$1}{used}{$basename} = 1; $ClassRefs{$1}{used}{$basename} = 1;
} }
} }
} }
#use Data::Dumper;print Dumper(\%ClassRefs); #use Data::Dumper;print Dumper(\%ClassRefs);
} }
@ -142,8 +142,8 @@ sub subclasses_of {
my @cllist; my @cllist;
for (my $subclass = $::Classes{$type}; $subclass; ) { for (my $subclass = $::Classes{$type}; $subclass; ) {
push @cllist, $subclass; push @cllist, $subclass;
$subclass = $::Classes{$subclass}; $subclass = $::Classes{$subclass};
} }
return (reverse @cllist); return (reverse @cllist);
@ -156,10 +156,10 @@ sub children_of {
my @todo; my @todo;
push @todo, $type; push @todo, $type;
while (my $subclass = shift @todo) { while (my $subclass = shift @todo) {
foreach my $child (sort keys %{$::Children{$subclass}}) { foreach my $child (sort keys %{$::Children{$subclass}}) {
push @todo, $child; push @todo, $child;
push @cllist, $child; push @cllist, $child;
} }
} }
return (@cllist); return (@cllist);
@ -173,39 +173,39 @@ sub write_report {
$fh->print("Processing stages (approximate, based on order in Verilator.cpp):\n"); $fh->print("Processing stages (approximate, based on order in Verilator.cpp):\n");
foreach my $class (sort {$Stages{$a} <=> $Stages{$b}} keys %Stages) { foreach my $class (sort {$Stages{$a} <=> $Stages{$b}} keys %Stages) {
$fh->print("\t$class\n"); $fh->print("\t$class\n");
} }
$fh->print("\nProcessing stages (approximate, based on order in Verilator.cpp):\n"); $fh->print("\nProcessing stages (approximate, based on order in Verilator.cpp):\n");
foreach my $type (sort (keys %Classes)) { foreach my $type (sort (keys %Classes)) {
printf $fh " class %-20s\n", "Ast${type}"; printf $fh " class %-20s\n", "Ast${type}";
$fh->print("\tparent:\t"); $fh->print("\tparent:\t");
foreach my $subclass (subclasses_of($type)) { foreach my $subclass (subclasses_of($type)) {
next if $subclass eq 'Node'; next if $subclass eq 'Node';
printf $fh "Ast%-12s ",$subclass; printf $fh "Ast%-12s ",$subclass;
} }
printf $fh "\n"; printf $fh "\n";
$fh->print("\tchilds:\t"); $fh->print("\tchilds:\t");
foreach my $subclass (children_of($type)) { foreach my $subclass (children_of($type)) {
next if $subclass eq 'Node'; next if $subclass eq 'Node';
printf $fh "Ast%-12s ",$subclass; printf $fh "Ast%-12s ",$subclass;
} }
printf $fh "\n"; printf $fh "\n";
if (my $refs = $ClassRefs{"Ast${type}"}) { if (my $refs = $ClassRefs{"Ast${type}"}) {
$fh->print("\tnewed:\t"); $fh->print("\tnewed:\t");
foreach my $stage (sort {($Stages{$a}||-1) <=> ($Stages{$b}||-1)} foreach my $stage (sort {($Stages{$a}||-1) <=> ($Stages{$b}||-1)}
keys %{$refs->{newed}}) { keys %{$refs->{newed}}) {
$fh->print($stage." "); $fh->print($stage." ");
} }
$fh->print("\n"); $fh->print("\n");
$fh->print("\tused:\t"); $fh->print("\tused:\t");
foreach my $stage (sort {($Stages{$a}||-1) <=> ($Stages{$b}||-1)} foreach my $stage (sort {($Stages{$a}||-1) <=> ($Stages{$b}||-1)}
keys %{$refs->{used}}) { keys %{$refs->{used}}) {
$fh->print($stage." "); $fh->print($stage." ");
} }
$fh->print("\n"); $fh->print("\n");
} }
$fh->print("\n"); $fh->print("\n");
} }
} }
@ -213,11 +213,11 @@ sub write_classes {
my $fh = open_file(@_); my $fh = open_file(@_);
printf $fh "class AstNode;\n"; printf $fh "class AstNode;\n";
foreach my $type (sort (keys %Classes)) { foreach my $type (sort (keys %Classes)) {
printf $fh "class %-20s // ", "Ast${type};"; printf $fh "class %-20s // ", "Ast${type};";
foreach my $subclass (subclasses_of($type)) { foreach my $subclass (subclasses_of($type)) {
printf $fh "Ast%-12s ",$subclass; printf $fh "Ast%-12s ",$subclass;
} }
printf $fh "\n"; printf $fh "\n";
} }
$fh->close(); $fh->close();
} }
@ -225,12 +225,12 @@ sub write_classes {
sub write_visitor { sub write_visitor {
my $fh = open_file(@_); my $fh = open_file(@_);
foreach my $type (sort (keys %Classes)) { foreach my $type (sort (keys %Classes)) {
my $base = $Classes{$type}; my $base = $Classes{$type};
if ($base) { if ($base) {
printf $fh " virtual void visit(Ast${type}* nodep) { visit((Ast${base}*)(nodep)); }\n"; printf $fh " virtual void visit(Ast${type}* nodep) { visit((Ast${base}*)(nodep)); }\n";
} else { } else {
printf $fh " virtual void visit(Ast${type}*) = 0;\n"; printf $fh " virtual void visit(Ast${type}*) = 0;\n";
} }
} }
$fh->close(); $fh->close();
} }
@ -262,11 +262,11 @@ sub write_impl {
print $fh "\n"; print $fh "\n";
print $fh " // These for use by VN_IS macro only\n"; print $fh " // These for use by VN_IS macro only\n";
foreach my $type (sort (keys %Classes)) { foreach my $type (sort (keys %Classes)) {
if (children_of($type)) { if (children_of($type)) {
print $fh "inline bool AstNode::privateIs",$type,"(const AstNode* nodep) { return (bool)(dynamic_cast<const Ast",$type,"*>(nodep)); }\n"; print $fh "inline bool AstNode::privateIs",$type,"(const AstNode* nodep) { return (bool)(dynamic_cast<const Ast",$type,"*>(nodep)); }\n";
} else { } else {
print $fh "inline bool AstNode::privateIs",$type,"(const AstNode* nodep) { return nodep && nodep->type() == AstType::at",$type,"; }\n"; print $fh "inline bool AstNode::privateIs",$type,"(const AstNode* nodep) { return nodep && nodep->type() == AstType::at",$type,"; }\n";
} }
} }
foreach my $type (sort (keys %Classes)) { foreach my $type (sort (keys %Classes)) {
@ -285,16 +285,16 @@ sub write_types {
printf $fh " enum en {\n"; printf $fh " enum en {\n";
# Add "at" prefix to avoid conflicting with FOPEN and other macros in include files # Add "at" prefix to avoid conflicting with FOPEN and other macros in include files
foreach my $type (sort (keys %Classes)) { foreach my $type (sort (keys %Classes)) {
next if $type =~ /^Node/; next if $type =~ /^Node/;
print $fh "\tat",$type,",\n"; print $fh "\tat",$type,",\n";
} }
printf $fh "\t_ENUM_END\n"; printf $fh "\t_ENUM_END\n";
printf $fh " };\n"; printf $fh " };\n";
printf $fh " const char* ascii() const {\n"; printf $fh " const char* ascii() const {\n";
printf $fh " const char* const names[] = {\n"; printf $fh " const char* const names[] = {\n";
foreach my $type (sort (keys %Classes)) { foreach my $type (sort (keys %Classes)) {
next if $type =~ /^Node/; next if $type =~ /^Node/;
print $fh "\t\"", uc $type, "\",\n"; print $fh "\t\"", uc $type, "\",\n";
} }
printf $fh "\t\"_ENUM_END\"\n"; printf $fh "\t\"_ENUM_END\"\n";
printf $fh " };\n"; printf $fh " };\n";
@ -332,11 +332,11 @@ sub _output_line {
sub process { sub process {
my $self = { my $self = {
in_filename => undef, in_filename => undef,
out_filename => undef, out_filename => undef,
out_lines => [], out_lines => [],
out_linenum => 1, out_linenum => 1,
@_, @_,
}; };
bless $self, __PACKAGE__; bless $self, __PACKAGE__;
@ -346,25 +346,25 @@ sub process {
# Read the file and parse into list of functions that generate output # Read the file and parse into list of functions that generate output
my $fhi = IO::File->new($self->{in_filename}) or die "%Error: $! $self->{in_filename},"; my $fhi = IO::File->new($self->{in_filename}) or die "%Error: $! $self->{in_filename},";
while (defined(my $line = $fhi->getline)) { while (defined(my $line = $fhi->getline)) {
if (!$didln) { if (!$didln) {
$self->print("#line $. \"$self->{in_filename}\"\n"); $self->print("#line $. \"$self->{in_filename}\"\n");
$didln = 1; $didln = 1;
} }
if ($line =~ /^\s+(TREE.*)$/) { if ($line =~ /^\s+(TREE.*)$/) {
my $func = $1; my $func = $1;
$self->{in_linenum} = $.; $self->{in_linenum} = $.;
$self->print("//$line"); $self->print("//$line");
$self->output_func(sub{my $self=shift; $self->_output_line(); }); $self->output_func(sub{my $self=shift; $self->_output_line(); });
$self->tree_line ($func); $self->tree_line($func);
$didln = 0; $didln = 0;
} }
elsif ($line !~ /^\s*\/[\/\*]\s*TREE/ elsif ($line !~ /^\s*\/[\/\*]\s*TREE/
&& $line =~ /\s+TREE/) { && $line =~ /\s+TREE/) {
$self->error("Unknown astgen line: $line"); $self->error("Unknown astgen line: $line");
} }
else { else {
$self->print($line); $self->print($line);
} }
} }
$fhi->close; $fhi->close;
@ -373,16 +373,16 @@ sub process {
my $fho = ::open_file($self->{out_filename}); my $fho = ::open_file($self->{out_filename});
my @togen = @{$self->{out_lines}}; my @togen = @{$self->{out_lines}};
foreach my $line (@togen) { foreach my $line (@togen) {
if (ref $line) { if (ref $line) {
$self->{out_lines} = []; $self->{out_lines} = [];
&$line($self); &$line($self);
} else { } else {
$self->{out_lines} = [$line]; $self->{out_lines} = [$line];
} }
foreach my $out (@{$self->{out_lines}}) { foreach my $out (@{$self->{out_lines}}) {
$self->{out_linenum}++ while ($out =~ /\n/smg); $self->{out_linenum}++ while ($out =~ /\n/smg);
print $fho $out; print $fho $out;
} }
} }
$fho->close; $fho->close;
} }
@ -396,64 +396,64 @@ sub tree_line {
# doflag "S" indicates an op specifying short-circuiting for a type. # doflag "S" indicates an op specifying short-circuiting for a type.
if ($func =~ /TREEOP(1?)([VCS]?)\s*\(\s* \"([^\"]*)\" \s*,\s* \"([^\"]*)\" \s*\)/sx) { if ($func =~ /TREEOP(1?)([VCS]?)\s*\(\s* \"([^\"]*)\" \s*,\s* \"([^\"]*)\" \s*\)/sx) {
my $order = $1; my $doflag = $2; my $from = $3; my $to = $4; my $order = $1; my $doflag = $2; my $from = $3; my $to = $4;
#$self->print("// $from $to\n"); #$self->print("// $from $to\n");
if (!$self->{did_out_tree}) { if (!$self->{did_out_tree}) {
$self->{did_out_tree} = 1; $self->{did_out_tree} = 1;
$self->output_func(sub{ my $self=shift; $self->output_func(sub{ my $self=shift;
$self->tree_match(); $self->tree_match();
$self->tree_base(); $self->tree_base();
}); });
} }
$from =~ /Ast([a-zA-Z0-9]+)\s*\{(.*)\}\s*$/ $from =~ /Ast([a-zA-Z0-9]+)\s*\{(.*)\}\s*$/
or $self->error("Can't parse from function: $func"); or $self->error("Can't parse from function: $func");
my $type = $1; my $type = $1;
my $subnodes = $2; my $subnodes = $2;
(::subclasses_of($type)) or $self->error("Unknown AstNode type: $type: in $func"); (::subclasses_of($type)) or $self->error("Unknown AstNode type: $type: in $func");
my $mif; my $mif;
if ($doflag eq '') { $mif = "m_doNConst"; } if ($doflag eq '') { $mif = "m_doNConst"; }
elsif ($doflag eq 'V') { $mif = "m_doV"; } elsif ($doflag eq 'V') { $mif = "m_doV"; }
elsif ($doflag eq 'C') { $mif = ""; } elsif ($doflag eq 'C') { $mif = ""; }
elsif ($doflag eq 'S') { $mif = "m_doNConst"; } # Not just for m_doGenerate elsif ($doflag eq 'S') { $mif = "m_doNConst"; } # Not just for m_doGenerate
else { die; } else { die; }
$subnodes =~ s/,,/__ESCAPEDCOMMA__/g; $subnodes =~ s/,,/__ESCAPEDCOMMA__/g;
foreach my $subnode (split /\s*,\s*/, $subnodes) { foreach my $subnode (split /\s*,\s*/, $subnodes) {
$subnode =~ s/__ESCAPEDCOMMA__/,/g; $subnode =~ s/__ESCAPEDCOMMA__/,/g;
next if $subnode =~ /^\$([a-z0-9]+)$/gi; # "$lhs" is just a comment that this op has a lhs next if $subnode =~ /^\$([a-z0-9]+)$/gi; # "$lhs" is just a comment that this op has a lhs
$mif .= " && " if $mif; $mif .= " && " if $mif;
my $subnodeif = $subnode; my $subnodeif = $subnode;
$subnodeif =~ s/\$([a-zA-Z0-9]+)\.cast([A-Z][A-Za-z0-9]+)$/VN_IS(nodep->$1(),$2)/g; $subnodeif =~ s/\$([a-zA-Z0-9]+)\.cast([A-Z][A-Za-z0-9]+)$/VN_IS(nodep->$1(),$2)/g;
$subnodeif =~ s/\$([a-zA-Z0-9]+)\.([a-zA-Z0-9]+)$/nodep->$1()->$2()/g; $subnodeif =~ s/\$([a-zA-Z0-9]+)\.([a-zA-Z0-9]+)$/nodep->$1()->$2()/g;
$subnodeif = add_nodep($subnodeif); $subnodeif = add_nodep($subnodeif);
$mif .= $subnodeif; $mif .= $subnodeif;
} }
my $exec_func = treeop_exec_func($self, $to); my $exec_func = treeop_exec_func($self, $to);
while ($exec_func =~ s/([-()a-zA-Z0-9_>]+)->cast([A-Z][A-Za-z0-9]+)\(\)/VN_CAST($1,$2)/) {} while ($exec_func =~ s/([-()a-zA-Z0-9_>]+)->cast([A-Z][A-Za-z0-9]+)\(\)/VN_CAST($1,$2)/) {}
$self->{treeop}{$type} ||= []; $self->{treeop}{$type} ||= [];
my $n = $#{$self->{treeop}{$type}} + 1; my $n = $#{$self->{treeop}{$type}} + 1;
my $typefunc = { my $typefunc = {
order => $order, order => $order,
comment => $func, comment => $func,
match_func => "match_${type}_${n}", match_func => "match_${type}_${n}",
match_if => $mif, match_if => $mif,
exec_func => $exec_func, exec_func => $exec_func,
uinfo_level => ($to =~ /^!/ ? 0:7), uinfo_level => ($to =~ /^!/ ? 0:7),
short_circuit => ($doflag eq 'S'), short_circuit => ($doflag eq 'S'),
}; };
($typefunc->{uinfo} = $func) =~ s/[ \t\"\{\}]+/ /g; ($typefunc->{uinfo} = $func) =~ s/[ \t\"\{\}]+/ /g;
push @{$self->{treeop}{$type}}, $typefunc; push @{$self->{treeop}{$type}}, $typefunc;
} }
elsif ($func =~ /TREE_SKIP_VISIT\s*\(\s* \"([^\"]*)\" \s*\)/sx) { elsif ($func =~ /TREE_SKIP_VISIT\s*\(\s* \"([^\"]*)\" \s*\)/sx) {
my $type = $1; my $type = $1;
$self->{tree_skip_visit}{$type} = 1; $self->{tree_skip_visit}{$type} = 1;
$::Classes{$type} or $self->error("Unknown node type: $type"); $::Classes{$type} or $self->error("Unknown node type: $type");
} }
else { else {
$self->error("Unknown astgen op: $func"); $self->error("Unknown astgen op: $func");
} }
} }
@ -468,12 +468,12 @@ our $_Exec_Nsyms;
sub _exec_syms_recurse { sub _exec_syms_recurse {
my $aref = shift; my $aref = shift;
foreach my $sym (@{$aref}) { foreach my $sym (@{$aref}) {
if (ref $sym) { _exec_syms_recurse($sym); } if (ref $sym) { _exec_syms_recurse($sym); }
elsif ($sym =~ /^\$.*/) { elsif ($sym =~ /^\$.*/) {
if (!defined $_Exec_Syms{$sym}) { if (!defined $_Exec_Syms{$sym}) {
$_Exec_Syms{$sym} = "arg".(++$_Exec_Nsyms)."p"; $_Exec_Syms{$sym} = "arg".(++$_Exec_Nsyms)."p";
} }
} }
} }
} }
@ -482,14 +482,14 @@ sub _exec_new_recurse {
my $out = "new ".$aref->[0]."(nodep->fileline()"; my $out = "new ".$aref->[0]."(nodep->fileline()";
my $first = 1; my $first = 1;
foreach my $sym (@{$aref}) { foreach my $sym (@{$aref}) {
if ($first) { $first=0; next; } if ($first) { $first=0; next; }
$out .= ", "; $out .= ", ";
if (ref $sym) { $out.=_exec_new_recurse($sym); } if (ref $sym) { $out.=_exec_new_recurse($sym); }
elsif ($sym =~ /^\$.*/) { elsif ($sym =~ /^\$.*/) {
$out .= $_Exec_Syms{$sym}; $out .= $_Exec_Syms{$sym};
} else { } else {
$out .= $sym; $out .= $sym;
} }
} }
return $out.")"; return $out.")";
} }
@ -500,142 +500,142 @@ sub treeop_exec_func {
my $out = ""; my $out = "";
$func =~ s/^!//; $func =~ s/^!//;
if ($func =~ /^\s*[a-zA-Z0-9]+\s*\(/) { # Function call if ($func =~ /^\s*[a-zA-Z0-9]+\s*\(/) { # Function call
(my $outl = $func) =~ s/\$([a-zA-Z0-9]+)/nodep->$1()/g; (my $outl = $func) =~ s/\$([a-zA-Z0-9]+)/nodep->$1()/g;
$out .= $outl.";"; $out .= $outl.";";
} }
elsif ($func =~ /^\s*Ast([a-zA-Z0-9]+) \s*\{\s* (.*) \s* \}$/x) { elsif ($func =~ /^\s*Ast([a-zA-Z0-9]+) \s*\{\s* (.*) \s* \}$/x) {
my $nargs = 0; my $nargs = 0;
my %argnums; # Number for each argument name my %argnums; # Number for each argument name
my $aref = undef; # Recursive array with structure to form my $aref = undef; # Recursive array with structure to form
my @astack; my @astack;
my $forming = ""; my $forming = "";
my $argtext = $func . "\000"; # EOF character my $argtext = $func . "\000"; # EOF character
#print "FF $func\n" if $Debug; #print "FF $func\n" if $Debug;
while ($argtext =~ s/^(.)//) { while ($argtext =~ s/^(.)//) {
my $tok = $1; my $tok = $1;
#print "TOK: $tok $forming\n" if $tok !~ /[a-zA-Z0-9]/; #print "TOK: $tok $forming\n" if $tok !~ /[a-zA-Z0-9]/;
if ($tok eq "\000") { if ($tok eq "\000") {
} elsif ($tok =~ /\s+/) { } elsif ($tok =~ /\s+/) {
} elsif ($tok eq "{") { } elsif ($tok eq "{") {
my $newref = [$forming]; my $newref = [$forming];
push @{$aref}, $newref; push @{$aref}, $newref;
push @astack, $aref if $aref; push @astack, $aref if $aref;
$aref = $newref; $aref = $newref;
$forming = ""; $forming = "";
} elsif ($tok eq "}") { } elsif ($tok eq "}") {
push @{$aref}, $forming if $forming; push @{$aref}, $forming if $forming;
$aref = pop @astack; $aref = pop @astack;
$aref or $self->error("Too many } in execution function: $func\n"); $aref or $self->error("Too many } in execution function: $func\n");
$forming = ""; $forming = "";
} elsif ($tok eq ",") { } elsif ($tok eq ",") {
push @{$aref}, $forming if $forming; push @{$aref}, $forming if $forming;
$forming = ""; $forming = "";
} else { } else {
$forming .= $tok; $forming .= $tok;
} }
} }
($aref && ref $aref->[0] && !$aref->[1]) or $self->error("Badly formed execution function: $func\n"); ($aref && ref $aref->[0] && !$aref->[1]) or $self->error("Badly formed execution function: $func\n");
$aref = $aref->[0]; $aref = $aref->[0];
#use Data::Dumper; print Dumper($aref),"\n"; #use Data::Dumper; print Dumper($aref),"\n";
# Assign numbers to each $ symbol # Assign numbers to each $ symbol
%_Exec_Syms = (); %_Exec_Syms = ();
$_Exec_Nsyms = 0; $_Exec_Nsyms = 0;
_exec_syms_recurse($aref); _exec_syms_recurse($aref);
foreach my $sym (sort {$_Exec_Syms{$a} cmp $_Exec_Syms{$b}} (keys %_Exec_Syms)) { foreach my $sym (sort {$_Exec_Syms{$a} cmp $_Exec_Syms{$b}} (keys %_Exec_Syms)) {
my $argnp = $_Exec_Syms{$sym}; my $argnp = $_Exec_Syms{$sym};
my $arg = add_nodep($sym); my $arg = add_nodep($sym);
$out .= "AstNode* ${argnp} = ${arg}->unlinkFrBack();\n"; $out .= "AstNode* ${argnp} = ${arg}->unlinkFrBack();\n";
} }
$out .= "AstNode* newp = " . _exec_new_recurse($aref).";\n"; $out .= "AstNode* newp = " . _exec_new_recurse($aref).";\n";
$out .= "nodep->replaceWith(newp);"; $out .= "nodep->replaceWith(newp);";
$out .= "nodep->deleteTree(); VL_DANGLING(nodep);"; $out .= "nodep->deleteTree(); VL_DANGLING(nodep);";
#print "FF $out\n" if $Debug; #print "FF $out\n" if $Debug;
} elsif ($func eq "NEVER") { } elsif ($func eq "NEVER") {
$out .= "nodep->v3fatalSrc(\"Executing transform that was NEVERed\");"; $out .= "nodep->v3fatalSrc(\"Executing transform that was NEVERed\");";
} elsif ($func eq "DONE") { } elsif ($func eq "DONE") {
} else { } else {
$self->error("Unknown execution function format: $func\n"); $self->error("Unknown execution function format: $func\n");
} }
return $out; return $out;
} }
sub tree_match { sub tree_match {
my $self = shift; my $self = shift;
$self->print (" // TREEOP functions, each return true if they matched & transformed\n"); $self->print(" // TREEOP functions, each return true if they matched & transformed\n");
#use Data::Dumper; print Dumper($self); #use Data::Dumper; print Dumper($self);
foreach my $base (sort (keys %{$self->{treeop}})) { foreach my $base (sort (keys %{$self->{treeop}})) {
foreach my $typefunc (@{$self->{treeop}{$base}}) { foreach my $typefunc (@{$self->{treeop}{$base}}) {
$self->print(" // Generated by astgen\n"); $self->print(" // Generated by astgen\n");
$self->print(" bool $typefunc->{match_func}(Ast${base}* nodep) {\n", $self->print(" bool $typefunc->{match_func}(Ast${base}* nodep) {\n",
"\t// $typefunc->{comment}\n",); "\t// $typefunc->{comment}\n",);
$self->print( "\tif ($typefunc->{match_if}) {\n"); $self->print( "\tif ($typefunc->{match_if}) {\n");
$self->print( "\t UINFO($typefunc->{uinfo_level},cvtToHex(nodep)" $self->print( "\t UINFO($typefunc->{uinfo_level},cvtToHex(nodep)"
."<<\" $typefunc->{uinfo}\\n\");\n"); ."<<\" $typefunc->{uinfo}\\n\");\n");
$self->print( "\t $typefunc->{exec_func}\n"); $self->print( "\t $typefunc->{exec_func}\n");
$self->print( "\t return true;\n"); $self->print( "\t return true;\n");
$self->print( "\t}\n"); $self->print( "\t}\n");
$self->print( "\treturn false;\n"); $self->print( "\treturn false;\n");
$self->print(" }\n",); $self->print(" }\n",);
} }
} }
} }
sub tree_base { sub tree_base {
my $self = shift; my $self = shift;
$self->print (" // TREEOP visitors, call each base type's match\n"); $self->print(" // TREEOP visitors, call each base type's match\n");
$self->print (" // Bottom class up, as more simple transforms are generally better\n"); $self->print(" // Bottom class up, as more simple transforms are generally better\n");
foreach my $type (sort (keys %::Classes)) { foreach my $type (sort (keys %::Classes)) {
my $base = $::Classes{$type}; my $base = $::Classes{$type};
my @out_for_type_sc; my @out_for_type_sc;
my @out_for_type; my @out_for_type;
foreach my $base (::subclasses_of($type), $type) { foreach my $base (::subclasses_of($type), $type) {
foreach my $typefunc (@{$self->{treeop}{$base}}) { foreach my $typefunc (@{$self->{treeop}{$base}}) {
my @lines = (" if ($typefunc->{match_func}(nodep)) return;\n",); my @lines = (" if ($typefunc->{match_func}(nodep)) return;\n",);
if ($typefunc->{short_circuit}) { # short-circuit match fn if ($typefunc->{short_circuit}) { # short-circuit match fn
push @out_for_type_sc, @lines; push @out_for_type_sc, @lines;
} else { # Standard match fn } else { # Standard match fn
if ($typefunc->{order}) { if ($typefunc->{order}) {
unshift @out_for_type, @lines; # TREEOP1's go in front of others unshift @out_for_type, @lines; # TREEOP1's go in front of others
} else { } else {
push @out_for_type, @lines; push @out_for_type, @lines;
} }
} }
} }
} }
# We need to deal with two cases. For short circuited functions we # We need to deal with two cases. For short circuited functions we
# evaluate the LHS, then apply the short-circuit matches, then # evaluate the LHS, then apply the short-circuit matches, then
# evaluate the RHS and possibly THS (ternary operators may # evaluate the RHS and possibly THS (ternary operators may
# short-circuit) and apply all the other matches. # short-circuit) and apply all the other matches.
# For types without short-circuits, we just use iterateChildren, which # For types without short-circuits, we just use iterateChildren, which
# saves one comparison. # saves one comparison.
if ($out_for_type_sc[0]) { # Short-circuited types if ($out_for_type_sc[0]) { # Short-circuited types
$self->print(" // Generated by astgen with short-circuiting\n", $self->print(" // Generated by astgen with short-circuiting\n",
" virtual void visit(Ast${type}* nodep) {\n", " virtual void visit(Ast${type}* nodep) {\n",
" iterateAndNextNull(nodep->lhsp());\n", " iterateAndNextNull(nodep->lhsp());\n",
@out_for_type_sc); @out_for_type_sc);
$self->print(" iterateAndNextNull(nodep->rhsp());\n", $self->print(" iterateAndNextNull(nodep->rhsp());\n",
" AstNodeTriop *tnp = VN_CAST(nodep, NodeTriop);\n", " AstNodeTriop *tnp = VN_CAST(nodep, NodeTriop);\n",
" if (tnp && tnp->thsp()) iterateAndNextNull(tnp->thsp());\n", " if (tnp && tnp->thsp()) iterateAndNextNull(tnp->thsp());\n",
@out_for_type, @out_for_type,
" }\n") if ($out_for_type[0]); " }\n") if ($out_for_type[0]);
} elsif ($out_for_type[0]) { # Other types with something to print } elsif ($out_for_type[0]) { # Other types with something to print
my $skip = $self->{tree_skip_visit}{$type}; my $skip = $self->{tree_skip_visit}{$type};
my $gen = $skip ? "Gen" : ""; my $gen = $skip ? "Gen" : "";
$self->print(" // Generated by astgen\n", $self->print(" // Generated by astgen\n",
" virtual void visit$gen(Ast${type}* nodep) {\n", " virtual void visit$gen(Ast${type}* nodep) {\n",
($skip?"": ($skip?"":
" iterateChildren(nodep);\n"), " iterateChildren(nodep);\n"),
@out_for_type, @out_for_type,
" }\n"); " }\n");
} }
} }
} }

View File

@ -7,7 +7,7 @@ use Getopt::Long;
use IO::File; use IO::File;
use Pod::Usage; use Pod::Usage;
use strict; use strict;
use vars qw ($Debug $VERSION); use vars qw($Debug $VERSION);
$VERSION = '3.404'; $VERSION = '3.404';
@ -28,21 +28,21 @@ our $Opt_Input;
autoflush STDOUT 1; autoflush STDOUT 1;
autoflush STDERR 1; autoflush STDERR 1;
Getopt::Long::config ("no_auto_abbrev"); Getopt::Long::config("no_auto_abbrev");
if (! GetOptions ( if (! GetOptions(
# Local options # Local options
"help" => \&usage, "help" => \&usage,
"version" => sub { print "Version $VERSION\n"; exit(0); }, "version" => sub { print "Version $VERSION\n"; exit(0); },
"yacc=s" => \$Opt_Yacc, "yacc=s" => \$Opt_Yacc,
# Passed to Bison # Passed to Bison
"t|debug" => sub { $Opt_Debug = 1; }, "t|debug" => sub { $Opt_Debug = 1; },
"b|file-prefix=s" => \$Opt_File_Prefix, "b|file-prefix=s" => \$Opt_File_Prefix,
"d" => \$Opt_Definitions, "d" => \$Opt_Definitions,
"k|token-table" => \$Opt_Token_Table, "k|token-table" => \$Opt_Token_Table,
"o=s" => \$Opt_Output, "o=s" => \$Opt_Output,
"p|name-prefix=s" => \$Opt_Name_Prefix, "p|name-prefix=s" => \$Opt_Name_Prefix,
"v|verbose" => \$Opt_Verbose, "v|verbose" => \$Opt_Verbose,
"<>" => \&parameter, "<>" => \&parameter,
)) { )) {
die "%Error: Bad usage, try 'bisonpre --help'\n"; die "%Error: Bad usage, try 'bisonpre --help'\n";
} }
@ -57,15 +57,15 @@ process();
sub usage { sub usage {
print "Version $VERSION\n"; print "Version $VERSION\n";
pod2usage(-verbose=>2, -exitval=>2, -output=>\*STDOUT, -noperldoc=>1); pod2usage(-verbose=>2, -exitval=>2, -output=>\*STDOUT, -noperldoc=>1);
exit (1); exit(1);
} }
sub parameter { sub parameter {
my $param = shift; my $param = shift;
if (!defined $Opt_Input) { if (!defined $Opt_Input) {
$Opt_Input = $param; $Opt_Input = $param;
} else { } else {
die "bisonpre: %Error: Unknown parameter: $param\n"; die "bisonpre: %Error: Unknown parameter: $param\n";
} }
} }
@ -81,31 +81,31 @@ sub process {
# Run bison # Run bison
my $command = ($Opt_Yacc my $command = ($Opt_Yacc
.($Opt_Debug?" -t":"") .($Opt_Debug?" -t":"")
.($Opt_Definitions?" -d":"") .($Opt_Definitions?" -d":"")
.($Opt_Token_Table?" -k":"") .($Opt_Token_Table?" -k":"")
.($Opt_Verbose?" -v":"") .($Opt_Verbose?" -v":"")
.(($Opt_Verbose && $supports_report)?" --report=itemset --report=lookahead":"") .(($Opt_Verbose && $supports_report)?" --report=itemset --report=lookahead":"")
# -p required for GLR parsers; they write to -p basename, not -o # -p required for GLR parsers; they write to -p basename, not -o
.($Opt_Name_Prefix?" -p $Opt_Name_Prefix":"") .($Opt_Name_Prefix?" -p $Opt_Name_Prefix":"")
." -b ".tmp_prefix() ." -b ".tmp_prefix()
." -o ".tmp_prefix().".c" ." -o ".tmp_prefix().".c"
." ".tmp_prefix().".y" ); ." ".tmp_prefix().".y" );
print " $command\n"; print " $command\n";
system $command; system $command;
my $status = $?; my $status = $?;
if ($status != 0) { if ($status != 0) {
remove_outputs(); remove_outputs();
my $v = bison_version_check(); my $v = bison_version_check();
die "bisonpre: %Error: $Opt_Yacc version $v run failed due to errors\n"; die "bisonpre: %Error: $Opt_Yacc version $v run failed due to errors\n";
} }
clean_output(tmp_prefix().".output",output_prefix().".output", 1,0); clean_output(tmp_prefix().".output",output_prefix().".output", 1,0);
warning_check(output_prefix().".output"); warning_check(output_prefix().".output");
clean_output(tmp_prefix().".c", output_prefix().".c", 0,1); clean_output(tmp_prefix().".c", output_prefix().".c", 0,1);
clean_output(tmp_prefix().".h", output_prefix().".h", 0,1); clean_output(tmp_prefix().".h", output_prefix().".h", 0,1);
remove_tmp(); remove_tmp();
} }
@ -116,10 +116,10 @@ sub tmp_prefix {
sub output_prefix { sub output_prefix {
my $o; my $o;
if ($Opt_Output) { if ($Opt_Output) {
(my $o = $Opt_Output) =~ s!\.[^.]*$!!; (my $o = $Opt_Output) =~ s!\.[^.]*$!!;
return $o; return $o;
} else { } else {
return $Opt_File_Prefix.".tab"; return $Opt_File_Prefix.".tab";
} }
} }
@ -139,11 +139,11 @@ sub remove_outputs {
sub bison_version_check { sub bison_version_check {
my $v = `$Opt_Yacc --version`; my $v = `$Opt_Yacc --version`;
if ($v && $v =~ /([0-9]+\.[0-9]+)/) { if ($v && $v =~ /([0-9]+\.[0-9]+)/) {
my $v = $1; my $v = $1;
($v >= 1.875) or die "bisonpre: %Error: '$Opt_Yacc' is version $v; version 1.875 or newer is required\n"; ($v >= 1.875) or die "bisonpre: %Error: '$Opt_Yacc' is version $v; version 1.875 or newer is required\n";
return $v; return $v;
} else { } else {
die "bisonpre: %Error: '$Opt_Yacc' is not installed, or not working\n"; die "bisonpre: %Error: '$Opt_Yacc' is not installed, or not working\n";
} }
} }
@ -164,55 +164,55 @@ sub clean_output {
$newbase =~ s/\.y/./; $newbase =~ s/\.y/./;
if ($is_output) { if ($is_output) {
my %state_line; my $l=0; my %state_line; my $l=0;
foreach my $line (@lines) { foreach my $line (@lines) {
$l++; $l++;
# We add a colon so it's easy to search for the definition # We add a colon so it's easy to search for the definition
$state_line{$1} = $l if $line =~ s/^state (\d+)\s*$/state $1:/; $state_line{$1} = $l if $line =~ s/^state (\d+)\s*$/state $1:/;
} }
my @out; my @out;
foreach my $line (@lines) { foreach my $line (@lines) {
if ($line =~ /^State (\d+) (conflicts)/) { if ($line =~ /^State (\d+) (conflicts)/) {
chomp $line; chomp $line;
$line .= " // line $state_line{$1}" if $state_line{$1}; $line .= " // line $state_line{$1}" if $state_line{$1};
$line .= "\n"; $line .= "\n";
} }
push @out, $line; push @out, $line;
} }
@lines = @out; @out = (); @lines = @out; @out = ();
} }
if ($is_c) { if ($is_c) {
my %token_values; my %token_values;
my $in_en=0; my $in_en=0;
foreach my $line (@lines) { foreach my $line (@lines) {
$in_en=1 if $line =~ /enum\s+yytokentype/; $in_en=1 if $line =~ /enum\s+yytokentype/;
$in_en=0 if $line =~ /;/; $in_en=0 if $line =~ /;/;
$token_values{$2} = $1 if $in_en && $line =~ /\b(\S+) = (\d+)/; $token_values{$2} = $1 if $in_en && $line =~ /\b(\S+) = (\d+)/;
} }
my @out; my @out;
foreach my $line (@lines) { foreach my $line (@lines) {
if ($line =~ /BISONPRE_TOKEN_NAMES/) { if ($line =~ /BISONPRE_TOKEN_NAMES/) {
push @out, $line; push @out, $line;
foreach my $tv (sort keys %token_values) { foreach my $tv (sort keys %token_values) {
push @out, sprintf("\tcase %d: return \"%s\";\n", push @out, sprintf("\tcase %d: return \"%s\";\n",
$tv, $token_values{$tv}); $tv, $token_values{$tv});
} }
next; next;
} }
push @out, $line; push @out, $line;
} }
@lines = @out; @out = (); @lines = @out; @out = ();
} }
$fh = IO::File->new(">$outname") or die "%Error: $! writing $outname\n"; $fh = IO::File->new(">$outname") or die "%Error: $! writing $outname\n";
foreach my $line (@lines) { foreach my $line (@lines) {
# Fix filename refs # Fix filename refs
$line =~ s!$basename!$newbase!g; $line =~ s!$basename!$newbase!g;
# Fix bison 2.3 and GCC 4.2.1 # Fix bison 2.3 and GCC 4.2.1
$line =~ s!\(YY_\("!(YY_((char*)"!g; $line =~ s!\(YY_\("!(YY_((char*)"!g;
# Fix bison 2.3 glr-parser warning about yyerrorloc.YYTYPE::yydummy uninit # Fix bison 2.3 glr-parser warning about yyerrorloc.YYTYPE::yydummy uninit
$line =~ s!(YYLTYPE yyerrloc;)!$1 yyerrloc.yydummy=0;/*bisonpre*/!g; $line =~ s!(YYLTYPE yyerrloc;)!$1 yyerrloc.yydummy=0;/*bisonpre*/!g;
$fh->write($line); $fh->write($line);
} }
$fh->close; $fh->close;
} }
@ -222,9 +222,9 @@ sub warning_check {
my $fh = IO::File->new("<$filename") or die "%Error: $! $filename\n"; my $fh = IO::File->new("<$filename") or die "%Error: $! $filename\n";
while (defined(my $line = $fh->getline)) { while (defined(my $line = $fh->getline)) {
if ($line =~ /(conflicts|warning:|^useless)/i) { if ($line =~ /(conflicts|warning:|^useless)/i) {
die "%Error: $filename:$.: $line\n"; die "%Error: $filename:$.: $line\n";
} }
} }
$fh->close; $fh->close;
} }
@ -249,160 +249,160 @@ sub clean_input {
my $last_rule; my $last_rule;
my $section = 1; my $section = 1;
{ {
my @linesin = @lines; @lines=(); my $l=0; my @linesin = @lines; @lines=(); my $l=0;
foreach my $line (@linesin) { foreach my $line (@linesin) {
$l++; $l++;
# ^/ to prevent comments from matching # ^/ to prevent comments from matching
$line =~ m!^[a-zA-Z0-9_<>]+:[^/]*[a-zA-Z]! and die "%Error: $filename:$l: Move text on rule line to next line: $line\n"; $line =~ m!^[a-zA-Z0-9_<>]+:[^/]*[a-zA-Z]! and die "%Error: $filename:$l: Move text on rule line to next line: $line\n";
if ($line =~ /^%%/) { if ($line =~ /^%%/) {
$section++; $section++;
if ($section==2) { $last_rule = undef; } if ($section==2) { $last_rule = undef; }
} }
elsif ($line =~ s/^([a-zA-Z0-9_]+)<(\S*)>:/$1:/) { elsif ($line =~ s/^([a-zA-Z0-9_]+)<(\S*)>:/$1:/) {
!$rules{$1}{name} or die "%Error: $filename:$l: Redeclaring '$1': $line\n"; !$rules{$1}{name} or die "%Error: $filename:$l: Redeclaring '$1': $line\n";
$types{$2}{$1} = 1; $types{$2}{$1} = 1;
$rules{$1}{name} = $1; $rules{$1}{name} = $1;
$rules{$1}{type} = $2; $rules{$1}{type} = $2;
!$last_rule or die "%Error: $filename:$l: Unterminated previous rule\n"; !$last_rule or die "%Error: $filename:$l: Unterminated previous rule\n";
$last_rule = $1; $last_rule = $1;
} elsif ($line =~ /^([a-zA-Z0-9_]+):/) { } elsif ($line =~ /^([a-zA-Z0-9_]+):/) {
!$rules{$1}{name} or die "%Error: $filename:$l: Redeclaring '$1': $line\n"; !$rules{$1}{name} or die "%Error: $filename:$l: Redeclaring '$1': $line\n";
$rules{$1}{name} = $1; $rules{$1}{name} = $1;
$rules{$1}{type} = ""; $rules{$1}{type} = "";
!$last_rule or die "%Error: $filename:$l: Unterminated previous rule\n"; !$last_rule or die "%Error: $filename:$l: Unterminated previous rule\n";
$last_rule = $1; $last_rule = $1;
} }
push @lines, $line; push @lines, $line;
# Now clean the line and extract some more info # Now clean the line and extract some more info
(my $cline = $line) =~ s/\/\/.*$/\n/; (my $cline = $line) =~ s/\/\/.*$/\n/;
(my $rline = $line) =~ s/\/\/.*$/\n/; (my $rline = $line) =~ s/\/\/.*$/\n/;
if ($cline =~ /^\s*;/) { if ($cline =~ /^\s*;/) {
$last_rule or die "%Error: $filename:$l: Stray semicolon\n"; $last_rule or die "%Error: $filename:$l: Stray semicolon\n";
$last_rule = undef; $last_rule = undef;
} elsif ($last_rule) { } elsif ($last_rule) {
$rules{$last_rule}{rules_and_productions} .= $cline; $rules{$last_rule}{rules_and_productions} .= $cline;
} }
if ($cline =~ /^%token\s*<(\S+)>\s*(\S+)/) { if ($cline =~ /^%token\s*<(\S+)>\s*(\S+)/) {
!$tokens{$2} or die "%Error: $filename:$l: Redeclaring '$2': $line\n"; !$tokens{$2} or die "%Error: $filename:$l: Redeclaring '$2': $line\n";
$tokens{$2} = $1; $tokens{$2} = $1;
} }
foreach my $tok (split /[^a-zA-Z0-9_]+/, $cline) { foreach my $tok (split /[^a-zA-Z0-9_]+/, $cline) {
if ($last_rule && $tok=~/^[a-zA-Z]/) { if ($last_rule && $tok=~/^[a-zA-Z]/) {
#print "TT $last_rule $tok\n"; #print "TT $last_rule $tok\n";
$rules{$last_rule}{subrules}{$tok} = 1; $rules{$last_rule}{subrules}{$tok} = 1;
$rules{$tok}{parentrules}{$last_rule} = 1; $rules{$tok}{parentrules}{$last_rule} = 1;
} }
} }
} }
} }
#use Data::Dumper; print Dumper(\%rules); #use Data::Dumper; print Dumper(\%rules);
# Replace BISONPRE_VERSION(ver,,...) with expanded list # Replace BISONPRE_VERSION(ver,,...) with expanded list
{ {
my @linesin = @lines; @lines=(); my $l=0; my @linesin = @lines; @lines=(); my $l=0;
foreach my $line (@linesin) { foreach my $line (@linesin) {
$l++; $l++;
if ($line =~ /BISONPRE_VERSION/) { if ($line =~ /BISONPRE_VERSION/) {
# 1 3 4 # 1 3 4
($line =~ /BISONPRE_VERSION\((\S+)\s*,\s*((\S+)\s*,)?\s*([^\),]+)\)\s*$/) ($line =~ /BISONPRE_VERSION\((\S+)\s*,\s*((\S+)\s*,)?\s*([^\),]+)\)\s*$/)
or die "%Error: $filename:$l: Bad form of BISONPRE_VERSION: $line\n"; or die "%Error: $filename:$l: Bad form of BISONPRE_VERSION: $line\n";
my $ver=$1; my $ver_max=$3; my $cmd=$4; my $ver=$1; my $ver_max=$3; my $cmd=$4;
if ($Self->{bison_version} >= $1 if ($Self->{bison_version} >= $1
&& (!$ver_max || $Self->{bison_version} <= $ver_max)) { && (!$ver_max || $Self->{bison_version} <= $ver_max)) {
$line = $cmd."\n"; $line = $cmd."\n";
} else { } else {
$line = "//NOP: $line"; $line = "//NOP: $line";
} }
} }
push @lines, $line; push @lines, $line;
} }
} }
# Replace BISONPRE_NOT(type,...) with expanded list # Replace BISONPRE_NOT(type,...) with expanded list
{ {
my @linesin = @lines; @lines=(); my $l=0; my @linesin = @lines; @lines=(); my $l=0;
foreach my $line (@linesin) { foreach my $line (@linesin) {
$l++; $l++;
if ($line =~ /BISONPRE_NOT/) { if ($line =~ /BISONPRE_NOT/) {
($line =~ s/BISONPRE_NOT\((\S+)\)\s*(\{[^}]+})\s*$//) ($line =~ s/BISONPRE_NOT\((\S+)\)\s*(\{[^}]+})\s*$//)
or die "%Error: $filename:$l: Bad form of BISONPRE_NOT: $line\n"; or die "%Error: $filename:$l: Bad form of BISONPRE_NOT: $line\n";
my $endtok = $1; my $action = $2; my $endtok = $1; my $action = $2;
my @endtoks = split (/,/, $endtok); my @endtoks = split(/,/, $endtok);
map { $tokens{$_} or die "%Error: $filename:$l: Can't find definition for token: $_\n" map { $tokens{$_} or die "%Error: $filename:$l: Can't find definition for token: $_\n"
} @endtoks; } @endtoks;
# Push it all onto one line to avoid error messages changing # Push it all onto one line to avoid error messages changing
my $bar = ""; my $bar = "";
tok: tok:
foreach my $tok (sort keys %tokens) { foreach my $tok (sort keys %tokens) {
foreach (@endtoks) { foreach (@endtoks) {
next tok if $tok eq $_; next tok if $tok eq $_;
} }
if ($endtok ne $tok) { if ($endtok ne $tok) {
$line .= "\t$bar $tok $action"; $line .= "\t$bar $tok $action";
$bar = "|"; $bar = "|";
} }
} }
$line .= "\n"; $line .= "\n";
} }
push @lines, $line; push @lines, $line;
} }
} }
# Replace BISONPRE_COPY(type,{code}) # Replace BISONPRE_COPY(type,{code})
{ {
my @linesin = @lines; @lines=(); my $l=0; my @linesin = @lines; @lines=(); my $l=0;
foreach my $line (@linesin) { foreach my $line (@linesin) {
$l++; $l++;
if ($line =~ /BISONPRE_COPY/) { if ($line =~ /BISONPRE_COPY/) {
$line = _bisonpre_copy($line,$l,0); $line = _bisonpre_copy($line,$l,0);
} }
push @lines, $line; push @lines, $line;
} }
} }
# Replace ~[x]~ - must be after BISONPRE_COPY expansion # Replace ~[x]~ - must be after BISONPRE_COPY expansion
{ {
my @linesin = @lines; @lines=(); my $l=0; my @linesin = @lines; @lines=(); my $l=0;
foreach my $line (@linesin) { foreach my $line (@linesin) {
$l++; $l++;
$line =~ s/~[a-zA-Z0-9_]+~//g; $line =~ s/~[a-zA-Z0-9_]+~//g;
push @lines, $line; push @lines, $line;
} }
} }
# Find "BISONPRE_TYPES" # Find "BISONPRE_TYPES"
{ {
my @linesin = @lines; @lines=(); my $l=0; my @linesin = @lines; @lines=(); my $l=0;
my $needmore = 0; my $needmore = 0;
foreach my $line (@linesin) { foreach my $line (@linesin) {
$l++; $l++;
if ($line =~ m!//BISONPRE_TYPES!) { if ($line =~ m!//BISONPRE_TYPES!) {
push @lines, $line; push @lines, $line;
foreach my $type (sort keys %types) { foreach my $type (sort keys %types) {
next if !$type; next if !$type;
my $line = "%type<$type>\t"; my $line = "%type<$type>\t";
foreach my $rule (sort keys %{$types{$type}}) { foreach my $rule (sort keys %{$types{$type}}) {
$line.=" ".$rule; $line.=" ".$rule;
} }
$line .= "\n"; $line .= "\n";
push @lines, $line; push @lines, $line;
$needmore++ $needmore++
} }
} elsif ($needmore) { } elsif ($needmore) {
# Bison doesn't have a #line directive, so we need somewhere to insert into # Bison doesn't have a #line directive, so we need somewhere to insert into
$line =~ s!^\s*//.*$!!; $line =~ s!^\s*//.*$!!;
($line =~ m/^\s*$/) or die "%Error: $filename:$l: Need $needmore more blank lines to insure line numbers are constant\n"; ($line =~ m/^\s*$/) or die "%Error: $filename:$l: Need $needmore more blank lines to insure line numbers are constant\n";
$needmore--; $needmore--;
} else { } else {
push @lines, $line; push @lines, $line;
} }
} }
} }
$fh = IO::File->new(">$outname") or die "%Error: $! writing $outname\n"; $fh = IO::File->new(">$outname") or die "%Error: $! writing $outname\n";
foreach my $line (@lines) { foreach my $line (@lines) {
$fh->write($line); $fh->write($line);
} }
$fh->close; $fh->close;
} }
@ -412,28 +412,28 @@ sub _bisonpre_copy {
my $l = shift; my $l = shift;
my $depth = shift; my $depth = shift;
while ($text =~ /BISONPRE_COPY/) { while ($text =~ /BISONPRE_COPY/) {
($text =~ s/BISONPRE_COPY(_ONCE)?\((\S+)\s*,\s*\{([^}]*)}\s*\)/{HERE}/) ($text =~ s/BISONPRE_COPY(_ONCE)?\((\S+)\s*,\s*\{([^}]*)}\s*\)/{HERE}/)
or die "%Error: $Self->{filename}:$l: Bad form of BISONPRE_NOT: $text\n"; or die "%Error: $Self->{filename}:$l: Bad form of BISONPRE_NOT: $text\n";
my $once = $1; my $rule = $2; my $code = $3; my $once = $1; my $rule = $2; my $code = $3;
$Self->{rules}{$rule} or die "%Error: $Self->{filename}:$l: Can't find definition for rule: $rule\n"; $Self->{rules}{$rule} or die "%Error: $Self->{filename}:$l: Can't find definition for rule: $rule\n";
if ($depth > 0 && $once) { if ($depth > 0 && $once) {
# _ONCE means don't inherit # _ONCE means don't inherit
$text =~ s/\|[ \t]+{HERE}//; # Don't OR in nothing $text =~ s/\|[ \t]+{HERE}//; # Don't OR in nothing
$text =~ s/{HERE}//; $text =~ s/{HERE}//;
} else { } else {
# Push it all onto one line to avoid error messages changing # Push it all onto one line to avoid error messages changing
my $insert = $Self->{rules}{$rule}{rules_and_productions}; my $insert = $Self->{rules}{$rule}{rules_and_productions};
$insert =~ s/^\S+://g; # Strip rule name $insert =~ s/^\S+://g; # Strip rule name
# Recurse so BISONPRE under B # Recurse so BISONPRE under B
#print "COPY $l code $code\n"; #print "COPY $l code $code\n";
#print "COPY $l in $insert\n"; #print "COPY $l in $insert\n";
$_=$insert; eval("$code; \$_;"); $insert = $_; $_=$insert; eval("$code; \$_;"); $insert = $_;
#print "COPY $l out $insert\n"; #print "COPY $l out $insert\n";
while ($insert =~ s/[ \t\n]+\n/\n/go) {} while ($insert =~ s/[ \t\n]+\n/\n/go) {}
while ($insert =~ s/\n/ /go) {} # Optional - preserve line numbering while ($insert =~ s/\n/ /go) {} # Optional - preserve line numbering
$text =~ s/{HERE}/$insert/; $text =~ s/{HERE}/$insert/;
} }
$depth++; $depth++;
} }
return $text; return $text;
} }

View File

@ -7,7 +7,7 @@ use Getopt::Long;
use IO::File; use IO::File;
use Pod::Usage; use Pod::Usage;
use strict; use strict;
use vars qw ($Debug $VERSION); use vars qw($Debug $VERSION);
$VERSION = '3.881'; $VERSION = '3.881';
@ -23,12 +23,12 @@ our $Opt_Debug;
autoflush STDOUT 1; autoflush STDOUT 1;
autoflush STDERR 1; autoflush STDERR 1;
Getopt::Long::config ("no_auto_abbrev","pass_through"); Getopt::Long::config("no_auto_abbrev","pass_through");
our @Opt_Args = ("cppcheck", @ARGV); our @Opt_Args = ("cppcheck", @ARGV);
if (! GetOptions ( if (! GetOptions(
# Local options # Local options
"help" => \&usage, "help" => \&usage,
"version" => sub { print "Version $VERSION\n"; system("cppcheck","--version"); exit(0); }, "version" => sub { print "Version $VERSION\n"; system("cppcheck","--version"); exit(0); },
)) { )) {
die "%Error: Bad usage, try 'cppcheck_filtered --help'\n"; die "%Error: Bad usage, try 'cppcheck_filtered --help'\n";
} }
@ -40,7 +40,7 @@ process();
sub usage { sub usage {
print "Version $VERSION\n"; print "Version $VERSION\n";
pod2usage(-verbose=>2, -exitval=>2, -output=>\*STDOUT, -noperldoc=>1); pod2usage(-verbose=>2, -exitval=>2, -output=>\*STDOUT, -noperldoc=>1);
exit (1); exit(1);
} }
####################################################################### #######################################################################
@ -54,72 +54,72 @@ sub process {
my %errs; my %errs;
my $last_error = ""; my $last_error = "";
while (defined(my $line = $fh->getline())) { while (defined(my $line = $fh->getline())) {
$line =~ s/^\s+//; $line =~ s/^\s+//;
$line =~ s/Checking usage of global functions\.+//; # Sometimes tacked at end-of-line $line =~ s/Checking usage of global functions\.+//; # Sometimes tacked at end-of-line
# General gunk # General gunk
next if $uniq{$line}++; next if $uniq{$line}++;
next if $line =~ m!^<\?xml version!; next if $line =~ m!^<\?xml version!;
next if $line =~ m!^<cppcheck!; next if $line =~ m!^<cppcheck!;
next if $line =~ m!^<results!; next if $line =~ m!^<results!;
next if $line =~ m!^</results>!; next if $line =~ m!^</results>!;
next if $line =~ m!^<errors!; next if $line =~ m!^<errors!;
next if $line =~ m!^</error>!; next if $line =~ m!^</error>!;
next if $line =~ m!^</errors>!; next if $line =~ m!^</errors>!;
next if $line =~ m!^<error.*id="unmatchedSuppression"!; # --suppress=unmatchedSuppression doesn't work next if $line =~ m!^<error.*id="unmatchedSuppression"!; # --suppress=unmatchedSuppression doesn't work
next if $line =~ m!Cppcheck cannot find all the include files!; # An earlier id line is more specific next if $line =~ m!Cppcheck cannot find all the include files!; # An earlier id line is more specific
next if $line =~ m!^Checking !; next if $line =~ m!^Checking !;
next if $line =~ m!^make.*Entering directory !; next if $line =~ m!^make.*Entering directory !;
next if $line =~ m!^make.*Leaving directory !; next if $line =~ m!^make.*Leaving directory !;
next if $line =~ m!^\s+$!g; next if $line =~ m!^\s+$!g;
# Specific suppressions (see _suppress also) # Specific suppressions (see _suppress also)
next if $line =~ m!id="unusedPrivateFunction" .*::debug!; # Doesn't know UINFO will use it next if $line =~ m!id="unusedPrivateFunction" .*::debug!; # Doesn't know UINFO will use it
# Output # Output
if ($line =~ /^cppcheck --/) { if ($line =~ /^cppcheck --/) {
print $line if $Debug; print $line if $Debug;
} elsif ($line =~ m!^\d+/\d+ files checked!) { } elsif ($line =~ m!^\d+/\d+ files checked!) {
print $line; print $line;
} else { } else {
my $suppress; my $suppress;
# --xml-format=1 # --xml-format=1
if ($line =~ /file="([^"]+)"\s+line="(\d+)"\s+id="([^"]+)"/) { if ($line =~ /file="([^"]+)"\s+line="(\d+)"\s+id="([^"]+)"/) {
my $file = $1; my $linenum = $2; my $id = $3; my $file = $1; my $linenum = $2; my $id = $3;
$suppress = 1 if _suppress($file,$linenum,$id); $suppress = 1 if _suppress($file,$linenum,$id);
} }
# --xml-format=2 # --xml-format=2
if ($line =~ /<error id.*/) { if ($line =~ /<error id.*/) {
$last_error = $line; $last_error = $line;
chomp $last_error; chomp $last_error;
$suppress = 1; $suppress = 1;
} }
elsif ($line =~ /<location.* file="([^"]+)"\s+line="(\d+)"/) { elsif ($line =~ /<location.* file="([^"]+)"\s+line="(\d+)"/) {
my $file = $1; my $linenum = $2; my $id; my $file = $1; my $linenum = $2; my $id;
if ($last_error =~ / id="([^"]+)"/) { if ($last_error =~ / id="([^"]+)"/) {
$id = $1; $id = $1;
} else { } else {
$id = "?"; $id = "?";
} }
$suppress = 1 if _suppress($file,$linenum,$id); $suppress = 1 if _suppress($file,$linenum,$id);
$suppress = 1 if $file eq "*"; $suppress = 1 if $file eq "*";
if (!$suppress) { if (!$suppress) {
chomp $line; chomp $line;
print "$file:$linenum: ".$last_error."\n"; print "$file:$linenum: ".$last_error."\n";
$suppress = 1; $suppress = 1;
} }
} }
if (!$suppress) { if (!$suppress) {
my $eline = "%Error: cppcheck: $line"; my $eline = "%Error: cppcheck: $line";
print $eline; print $eline;
$errs{$eline}++; $errs{$eline}++;
} }
} }
} }
if (scalar(keys %errs)) { if (scalar(keys %errs)) {
#my $all = join('',sort(keys %errs)); #my $all = join('',sort(keys %errs));
#$Self->error("Cppcheck errors:\n$all"); #$Self->error("Cppcheck errors:\n$all");
#die "%Error: cppcheck_filtered found errors\n"; #die "%Error: cppcheck_filtered found errors\n";
exit(1); exit(1);
} }
} }
@ -143,32 +143,32 @@ sub _suppress {
my $fh = IO::File->new("<$filename"); my $fh = IO::File->new("<$filename");
if (!$fh) { if (!$fh) {
warn "%Warning: $! $filename,"; warn "%Warning: $! $filename,";
return undef; return undef;
} }
my $l = 0; my $l = 0;
while (defined(my $line = $fh->getline())) { while (defined(my $line = $fh->getline())) {
++$l; ++$l;
if ($l+1 == $linenum) { if ($l+1 == $linenum) {
if ($line =~ /cppcheck-suppress((\s+\S+)+)/) { if ($line =~ /cppcheck-suppress((\s+\S+)+)/) {
my $supids = $1; my $supids = $1;
foreach my $supid (split /\s+/, $supids) { foreach my $supid (split /\s+/, $supids) {
if ($supid eq $id if ($supid eq $id
|| $supid eq ($SuppressMap{$id}||'')) { || $supid eq ($SuppressMap{$id}||'')) {
return 1; return 1;
} }
} }
warn "%Warning: $filename: $l: Found suppress for ids='$supids', not expected id='$id'\n"; warn "%Warning: $filename: $l: Found suppress for ids='$supids', not expected id='$id'\n";
} }
} }
if ($l == $linenum) { if ($l == $linenum) {
if (0 && # We now use VL_DANGLING instead of this rule if (0 && # We now use VL_DANGLING instead of this rule
$id eq "uselessAssignmentPtrArg" $id eq "uselessAssignmentPtrArg"
&& $line =~ /(delete|Delete|Edit).*p *= *(NULL|nullptr);/) { && $line =~ /(delete|Delete|Edit).*p *= *(NULL|nullptr);/) {
# delete(nodep); nodep=NULL; # This is ok, it's how we prevent later using nodep # delete(nodep); nodep=NULL; # This is ok, it's how we prevent later using nodep
return 1; return 1;
} }
} }
} }
return undef; return undef;
} }

View File

@ -7,7 +7,7 @@ use Getopt::Long;
use IO::File; use IO::File;
use Pod::Usage; use Pod::Usage;
use strict; use strict;
use vars qw ($Debug); use vars qw($Debug);
our @Items; our @Items;
@ -16,12 +16,12 @@ our @Items;
$Debug = 0; $Debug = 0;
my $Opt_Srcdir = "."; my $Opt_Srcdir = ".";
Getopt::Long::config ("pass_through", "no_auto_abbrev"); Getopt::Long::config("pass_through", "no_auto_abbrev");
if (! GetOptions ( if (! GetOptions(
"help" => \&usage, "help" => \&usage,
"debug" => sub { $Debug = 1; }, "debug" => sub { $Debug = 1; },
"srcdir=s" => \$Opt_Srcdir, "srcdir=s" => \$Opt_Srcdir,
"<>" => sub { die "%Error: Unknown parameter: $_[0],"; }, "<>" => sub { die "%Error: Unknown parameter: $_[0],"; },
)) { )) {
usage(); usage();
} }
@ -34,7 +34,7 @@ write_keys("$Opt_Srcdir/../include/verilated_cov_key.h");
sub usage { sub usage {
pod2usage(-verbose=>2, -exitval=>2, -output=>\*STDOUT); pod2usage(-verbose=>2, -exitval=>2, -output=>\*STDOUT);
exit (1); exit(1);
} }
####################################################################### #######################################################################
@ -44,17 +44,17 @@ sub read_keys {
my $fh = IO::File->new("<$filename") or die "%Error: $! $filename,"; my $fh = IO::File->new("<$filename") or die "%Error: $! $filename,";
while (defined (my $line = $fh->getline())) { while (defined (my $line = $fh->getline())) {
$line =~ s/\/\/.*$//; $line =~ s/\/\/.*$//;
next if $line =~ /^\s*$/; next if $line =~ /^\s*$/;
if ($line =~ /^\s*VLCOVGEN_ITEM/) { if ($line =~ /^\s*VLCOVGEN_ITEM/) {
$line =~ /^\s*VLCOVGEN_ITEM *\( *"([^"]+)" *\)/ $line =~ /^\s*VLCOVGEN_ITEM *\( *"([^"]+)" *\)/
or die "%Error: $filename:$.: Misformed VLCOVGEN_ITEM line,"; or die "%Error: $filename:$.: Misformed VLCOVGEN_ITEM line,";
my @data; my @data;
my $code = "\@data = ($1);"; my $code = "\@data = ($1);";
eval $code; eval $code;
die "%Error: $filename:$.: Parsing '$code': $@," if $@; die "%Error: $filename:$.: Parsing '$code': $@," if $@;
push @Items, {@data}; push @Items, {@data};
} }
} }
} }
@ -64,11 +64,11 @@ sub lint {
my %shorts; my %shorts;
my $ok = 1; my $ok = 1;
foreach my $itemref (@Items) { foreach my $itemref (@Items) {
if ($shorts{$itemref->{short}}) { if ($shorts{$itemref->{short}}) {
warn "%Error: Duplicate short code: $itemref->{short},"; warn "%Error: Duplicate short code: $itemref->{short},";
$ok = 0; $ok = 0;
} }
$shorts{$itemref->{short}} = 1; $shorts{$itemref->{short}} = 1;
} }
return $ok; return $ok;
} }
@ -82,40 +82,40 @@ sub write_keys {
my @out; my @out;
my $deleting; my $deleting;
while (defined(my $line = $fh->getline)) { while (defined(my $line = $fh->getline)) {
push @in, $line; push @in, $line;
if ($line =~ /VLCOVGEN_CIK_AUTO_EDIT_BEGIN/) { if ($line =~ /VLCOVGEN_CIK_AUTO_EDIT_BEGIN/) {
$deleting = 1; $deleting = 1;
push @out, $line; push @out, $line;
foreach my $keyref (sort {$a->{name} cmp $b->{name}} @Items) { foreach my $keyref (sort {$a->{name} cmp $b->{name}} @Items) {
push @out, sprintf("#define VL_CIK_%s \"%s\"\n", push @out, sprintf("#define VL_CIK_%s \"%s\"\n",
uc $keyref->{name}, $keyref->{short}); uc $keyref->{name}, $keyref->{short});
} }
} }
elsif ($line =~ /VLCOVGEN_SHORT_AUTO_EDIT_BEGIN/) { elsif ($line =~ /VLCOVGEN_SHORT_AUTO_EDIT_BEGIN/) {
$deleting = 1; $deleting = 1;
push @out, $line; push @out, $line;
foreach my $keyref (sort {$a->{name} cmp $b->{name}} @Items) { foreach my $keyref (sort {$a->{name} cmp $b->{name}} @Items) {
push @out, sprintf(" if (key == \"%s\") return VL_CIK_%s;\n", push @out, sprintf(" if (key == \"%s\") return VL_CIK_%s;\n",
$keyref->{name}, uc $keyref->{name}); $keyref->{name}, uc $keyref->{name});
} }
} }
elsif ($line =~ /VLCOVGEN_.*AUTO_EDIT_END/) { elsif ($line =~ /VLCOVGEN_.*AUTO_EDIT_END/) {
$deleting = 0; $deleting = 0;
push @out, $line; push @out, $line;
} }
elsif ($deleting) { elsif ($deleting) {
} }
else { else {
push @out, $line; push @out, $line;
} }
} }
$fh->close; $fh->close;
my $ok = join("", @out) eq join("", @in); my $ok = join("", @out) eq join("", @in);
if (!$ok) { if (!$ok) {
my $fh = IO::File->new(">$filename") or die "%Error: $! writing $filename\n"; my $fh = IO::File->new(">$filename") or die "%Error: $! writing $filename\n";
$fh->print(join "", @out); $fh->print(join "", @out);
$fh->close; $fh->close;
} }
} }

File diff suppressed because it is too large Load Diff

View File

@ -19,34 +19,35 @@
class TestSimulator { class TestSimulator {
private: private:
struct SimTypes { struct SimTypes {
int verilator; int verilator;
int icarus; int icarus;
int mti; int mti;
int ncsim; int ncsim;
int vcs; int vcs;
}; };
s_vpi_vlog_info m_info; s_vpi_vlog_info m_info;
SimTypes m_simulators; SimTypes m_simulators;
public: public:
TestSimulator() { TestSimulator() {
vpi_get_vlog_info(&m_info); vpi_get_vlog_info(&m_info);
if (0 == strcmp(m_info.product, "Verilator")) { if (0 == strcmp(m_info.product, "Verilator")) {
m_simulators.verilator = true; m_simulators.verilator = true;
} else if (0 == strcmp(m_info.product, "Verilator")) { } else if (0 == strcmp(m_info.product, "Verilator")) {
m_simulators.icarus = true; m_simulators.icarus = true;
} else if (0 == strncmp(m_info.product, "Chronologic Simulation VCS", strlen("Chronologic Simulation VCS"))) { } else if (0 == strncmp(m_info.product, "Chronologic Simulation VCS",
m_simulators.vcs = true; strlen("Chronologic Simulation VCS"))) {
} else { m_simulators.vcs = true;
printf("%%Warning: %s:%d: Unknown simulator in TestSimulator.h: %s\n", } else {
__FILE__, __LINE__, m_info.product); printf("%%Warning: %s:%d: Unknown simulator in TestSimulator.h: %s\n",
} __FILE__, __LINE__, m_info.product);
}
} }
~TestSimulator() { } ~TestSimulator() { }
// METHORS // METHORS
private: private:
static TestSimulator& singleton() { static TestSimulator& singleton() {
static TestSimulator s_singleton; static TestSimulator s_singleton;
return s_singleton; return s_singleton;
} }
static const SimTypes& simulators() { return singleton().m_simulators; } static const SimTypes& simulators() { return singleton().m_simulators; }
public: public:
@ -62,19 +63,19 @@ public:
static bool has_get_scalar() { return !simulators().icarus; } static bool has_get_scalar() { return !simulators().icarus; }
// return test level scope // return test level scope
static const char* top() { static const char* top() {
if (simulators().verilator) { if (simulators().verilator) {
return "t"; return "t";
} else { } else {
return "top.t"; return "top.t";
} }
} }
// return absolute scope of obj // return absolute scope of obj
static const char* rooted(const char *obj) { static const char* rooted(const char *obj) {
static string buf; static string buf;
ostringstream os; ostringstream os;
os<<top()<<"."<<obj; os<<top()<<"."<<obj;
buf = os.str(); buf = os.str();
return buf.c_str(); return buf.c_str();
} }
}; };

View File

@ -24,7 +24,7 @@ class TestVpiHandle {
public: public:
TestVpiHandle() : m_handle(NULL), m_free(true) { } TestVpiHandle() : m_handle(NULL), m_free(true) { }
TestVpiHandle(vpiHandle h) : m_handle(h), m_free(true) { } TestVpiHandle(vpiHandle h) : m_handle(h), m_free(true) { }
~TestVpiHandle() { if (m_handle && m_free) { vpi_free_object(m_handle); m_handle=NULL; } } // icarus has yet to catch up with 1800-2009 ~TestVpiHandle() { if (m_handle && m_free) { vpi_free_object(m_handle); m_handle=NULL; } }
operator vpiHandle() const { return m_handle; } operator vpiHandle() const { return m_handle; }
inline TestVpiHandle& operator= (vpiHandle h) { m_handle = h; return *this; } inline TestVpiHandle& operator= (vpiHandle h) { m_handle = h; return *this; }
TestVpiHandle& nofree() { TestVpiHandle& nofree() {

View File

@ -14,7 +14,7 @@ compile(
); );
if ($Self->{vlt_all}) { if ($Self->{vlt_all}) {
file_grep ($Self->{stats}, qr/Optimizations, Split always\s+(\d+)/i, 0); file_grep($Self->{stats}, qr/Optimizations, Split always\s+(\d+)/i, 0);
} }
execute( execute(

View File

@ -14,7 +14,7 @@ compile(
); );
if ($Self->{vlt_all}) { if ($Self->{vlt_all}) {
file_grep ($Self->{stats}, qr/Optimizations, Split always\s+(\d+)/i, 0); file_grep($Self->{stats}, qr/Optimizations, Split always\s+(\d+)/i, 0);
} }
execute( execute(

View File

@ -23,7 +23,7 @@ execute(
fails => $Self->{vlt_all}, fails => $Self->{vlt_all},
); );
file_grep ("$Self->{obj_dir}/vlt_compile.log", file_grep("$Self->{obj_dir}/vlt_compile.log",
qr/%Warning-USERFATAL: Parameter 5 is invalid...string and constant both work/); qr/%Warning-USERFATAL: Parameter 5 is invalid...string and constant both work/);
ok(1); ok(1);

View File

@ -20,9 +20,9 @@ execute(
fails => 1 fails => 1
); );
file_grep ($Self->{run_log_filename}, qr/'assert property' failed/); file_grep($Self->{run_log_filename}, qr/'assert property' failed/);
# We expect to get a message when this assert fires: # We expect to get a message when this assert fires:
file_grep ($Self->{run_log_filename}, qr/cyc != 3/); file_grep($Self->{run_log_filename}, qr/cyc != 3/);
ok(1); ok(1);
1; 1;

View File

@ -20,7 +20,7 @@ execute(
fails => 1 fails => 1
); );
file_grep ($Self->{run_log_filename}, qr/'assert property' failed/); file_grep($Self->{run_log_filename}, qr/'assert property' failed/);
ok(1); ok(1);
1; 1;

View File

@ -15,8 +15,8 @@ compile(
verilator_flags2 => ["--stats --prof-cfuncs -CFLAGS '-pg' -LDFLAGS '-pg'"], verilator_flags2 => ["--stats --prof-cfuncs -CFLAGS '-pg' -LDFLAGS '-pg'"],
); );
file_grep ($Self->{stats}, qr/Optimizations, Tables created\s+(\d+)/i, 10); file_grep($Self->{stats}, qr/Optimizations, Tables created\s+(\d+)/i, 10);
file_grep ($Self->{stats}, qr/Optimizations, Combined CFuncs\s+(\d+)/i, 10); file_grep($Self->{stats}, qr/Optimizations, Combined CFuncs\s+(\d+)/i, 10);
unlink $_ foreach (glob "$Self->{obj_dir}/gmon.out.*"); unlink $_ foreach (glob "$Self->{obj_dir}/gmon.out.*");
$ENV{GMON_OUT_PREFIX} = "$Self->{obj_dir}/gmon.out"; $ENV{GMON_OUT_PREFIX} = "$Self->{obj_dir}/gmon.out";
@ -36,7 +36,7 @@ run(cmd => ["cd $Self->{obj_dir} && gprof $Self->{VM_PREFIX} $gmon_base > gprof.
run(cmd => ["cd $Self->{obj_dir} && $ENV{VERILATOR_ROOT}/bin/verilator_profcfunc gprof.out > cfuncs.out"], run(cmd => ["cd $Self->{obj_dir} && $ENV{VERILATOR_ROOT}/bin/verilator_profcfunc gprof.out > cfuncs.out"],
check_finished => 0); check_finished => 0);
file_grep ("$Self->{obj_dir}/cfuncs.out", qr/Overall summary by/); file_grep("$Self->{obj_dir}/cfuncs.out", qr/Overall summary by/);
ok(1); ok(1);
1; 1;

View File

@ -18,7 +18,7 @@ compile(
expect_filename => $Self->{golden_filename}, expect_filename => $Self->{golden_filename},
); );
file_grep ("$Self->{obj_dir}/V$Self->{name}__cdc.txt", qr/CDC Report/); file_grep("$Self->{obj_dir}/V$Self->{name}__cdc.txt", qr/CDC Report/);
ok(1); ok(1);
1; 1;

View File

@ -18,7 +18,7 @@ execute(
); );
if ($Self->{vlt_all}) { if ($Self->{vlt_all}) {
file_grep ($Self->{stats}, qr/Optimizations, Gate assign merged\s+(\d+)/i, 28); file_grep($Self->{stats}, qr/Optimizations, Gate assign merged\s+(\d+)/i, 28);
}; };
ok(1); ok(1);

View File

@ -38,16 +38,16 @@ int main(int argc, char *argv[]) {
Verilated::debug(0); Verilated::debug(0);
for (int i = 0; i < 2; i++) { for (int i = 0; i < 2; i++) {
clockit(0, 0); clockit(0, 0);
clockit(0, 1); clockit(0, 1);
clockit(1, 1); clockit(1, 1);
clockit(0, 0); clockit(0, 0);
clockit(1, 1); clockit(1, 1);
clockit(1, 0); clockit(1, 0);
clockit(0, 0); clockit(0, 0);
clockit(0, 1); clockit(0, 1);
clockit(1, 0); clockit(1, 0);
clockit(0, 0); clockit(0, 0);
} }
topp->check = 1; topp->check = 1;
clockit(0,0); clockit(0,0);

View File

@ -20,7 +20,7 @@ execute(
# Read the input .v file and do any CHECK_COVER requests # Read the input .v file and do any CHECK_COVER requests
inline_checks(); inline_checks();
file_grep ($Self->{stats}, qr/Coverage, Toggle points joined\s+(\d+)/i, 25) file_grep($Self->{stats}, qr/Coverage, Toggle points joined\s+(\d+)/i, 25)
if $Self->{vlt_all}; if $Self->{vlt_all};
ok(1); ok(1);

View File

@ -14,7 +14,7 @@ compile(
); );
if ($Self->{vlt_all}) { if ($Self->{vlt_all}) {
file_grep ($Self->{stats}, qr/Optimizations, Gate sigs deduped\s+(\d+)/i, 4); file_grep($Self->{stats}, qr/Optimizations, Gate sigs deduped\s+(\d+)/i, 4);
} }
ok(1); ok(1);

View File

@ -14,7 +14,7 @@ compile(
); );
if ($Self->{vlt_all}) { if ($Self->{vlt_all}) {
file_grep ($Self->{stats}, qr/Optimizations, Gate sigs deduped\s+(\d+)/i, 6); file_grep($Self->{stats}, qr/Optimizations, Gate sigs deduped\s+(\d+)/i, 6);
} }
ok(1); ok(1);

View File

@ -18,8 +18,8 @@ execute(
expect_filename => $Self->{golden_filename}, expect_filename => $Self->{golden_filename},
); );
file_grep ("$Self->{obj_dir}/$Self->{VM_PREFIX}__stats.txt", file_grep("$Self->{obj_dir}/$Self->{VM_PREFIX}__stats.txt",
qr/Node count, DISPLAY \s+ 32 \s+ 25 \s+ 25 \s+ 25/); qr/Node count, DISPLAY \s+ 32 \s+ 25 \s+ 25 \s+ 25/);
ok(1); ok(1);
1; 1;

File diff suppressed because it is too large Load Diff

View File

@ -51,58 +51,58 @@ extern "C" {
int dpic_line() { int dpic_line() {
svScope scope = svGetScope(); svScope scope = svGetScope();
if (!scope) { if (!scope) {
printf("%%Warning: svGetScope failed\n"); printf("%%Warning: svGetScope failed\n");
return 0; return 0;
} }
#ifdef VERILATOR #ifdef VERILATOR
static int didDump = 0; static int didDump = 0;
if (didDump++ == 0) { if (didDump++ == 0) {
Verilated::scopesDump(); Verilated::scopesDump();
} }
#endif #endif
const char* scopenamep = svGetNameFromScope(scope); const char* scopenamep = svGetNameFromScope(scope);
if (!scopenamep) { if (!scopenamep) {
printf("%%Warning: svGetNameFromScope failed\n"); printf("%%Warning: svGetNameFromScope failed\n");
return 0; return 0;
} }
if (scope != svGetScopeFromName(scopenamep)) { if (scope != svGetScopeFromName(scopenamep)) {
printf("%%Warning: svGetScopeFromName repeat failed\n"); printf("%%Warning: svGetScopeFromName repeat failed\n");
return 0; return 0;
} }
const char* filenamep = ""; const char* filenamep = "";
int lineno = 0; int lineno = 0;
if (svGetCallerInfo(&filenamep, &lineno)) { if (svGetCallerInfo(&filenamep, &lineno)) {
printf("Call from %s:%d:%s\n", filenamep, lineno, scopenamep); printf("Call from %s:%d:%s\n", filenamep, lineno, scopenamep);
} else { } else {
printf("%%Warning: svGetCallerInfo failed\n"); printf("%%Warning: svGetCallerInfo failed\n");
return 0; return 0;
} }
return lineno; return lineno;
} }
extern int Dpic_Unique; extern int Dpic_Unique;
int Dpic_Unique = 0; // Address used for uniqueness int Dpic_Unique = 0; // Address used for uniqueness
int dpic_save(int value) { int dpic_save(int value) {
svScope scope = svGetScope(); svScope scope = svGetScope();
if (!scope) { if (!scope) {
printf("%%Warning: svGetScope failed\n"); printf("%%Warning: svGetScope failed\n");
return 0; return 0;
} }
// Use union to avoid cast to different size pointer warnings // Use union to avoid cast to different size pointer warnings
union valpack { union valpack {
void* ptr; void* ptr;
int i; int i;
} vp; } vp;
vp.i = value; vp.i = value;
if (svPutUserData(scope, &Dpic_Unique, vp.ptr)) { if (svPutUserData(scope, &Dpic_Unique, vp.ptr)) {
printf("%%Warning: svPutUserData failed\n"); printf("%%Warning: svPutUserData failed\n");
return 0; return 0;
} }
return 1; return 1;
} }
@ -110,21 +110,21 @@ int dpic_save(int value) {
int dpic_restore() { int dpic_restore() {
svScope scope = svGetScope(); svScope scope = svGetScope();
if (!scope) { if (!scope) {
printf("%%Warning: svGetScope failed\n"); printf("%%Warning: svGetScope failed\n");
return 0; return 0;
} }
if (void* userp = svGetUserData(scope, (void*)&Dpic_Unique)) { if (void* userp = svGetUserData(scope, (void*)&Dpic_Unique)) {
// Use union to avoid cast to different size pointer warnings // Use union to avoid cast to different size pointer warnings
union valpack { union valpack {
void* ptr; void* ptr;
int i; int i;
} vp; } vp;
vp.ptr = userp; vp.ptr = userp;
return vp.i; return vp.i;
} else { } else {
printf("%%Warning: svGetUserData failed\n"); printf("%%Warning: svGetUserData failed\n");
return 0; return 0;
} }
} }

View File

@ -19,7 +19,7 @@
#ifdef _WIN32 #ifdef _WIN32
# define T_PRI64 "I64" # define T_PRI64 "I64"
#else // Linux or compliant Unix flavors #else // Linux or compliant Unix flavors
# define T_PRI64 "ll" # define T_PRI64 "ll"
#endif #endif
@ -71,20 +71,20 @@ extern "C" {
//====================================================================== //======================================================================
#define CHECK_RESULT(type, got, exp) \ #define CHECK_RESULT(type, got, exp) \
if ((got) != (exp)) { \ if ((got) != (exp)) { \
printf("%%Error: %s:%d:", __FILE__,__LINE__); \ printf("%%Error: %s:%d:", __FILE__,__LINE__); \
union { type a; long long l; } u; \ union { type a; long long l; } u; \
u.l = 0; u.a = got; \ u.l = 0; u.a = got; \
printf(" GOT = %" T_PRI64 "x", u.l); \ printf(" GOT = %" T_PRI64 "x", u.l); \
u.l = 0; u.a = exp; \ u.l = 0; u.a = exp; \
printf(" EXP = %" T_PRI64 "x\n", u.l); \ printf(" EXP = %" T_PRI64 "x\n", u.l); \
return __LINE__; \ return __LINE__; \
} }
#define CHECK_RESULT_NNULL(got) \ #define CHECK_RESULT_NNULL(got) \
if (!(got)) { \ if (!(got)) { \
printf("%%Error: %s:%d: GOT = %p EXP = !NULL\n", __FILE__,__LINE__, (got)); \ printf("%%Error: %s:%d: GOT = %p EXP = !NULL\n", __FILE__,__LINE__, (got)); \
return __LINE__; \ return __LINE__; \
} }
static int check_sub(const char* name, int i) { static int check_sub(const char* name, int i) {
@ -112,69 +112,69 @@ int dpix_run_tests() {
static int didDump = 0; static int didDump = 0;
if (didDump++ == 0) { if (didDump++ == 0) {
# ifdef TEST_VERBOSE # ifdef TEST_VERBOSE
Verilated::internalsDump(); Verilated::internalsDump();
# endif # endif
} }
#endif #endif
#ifndef CADENCE // Unimplemented; how hard is it? #ifndef CADENCE // Unimplemented; how hard is it?
printf("svDpiVersion: %s\n",svDpiVersion()); printf("svDpiVersion: %s\n",svDpiVersion());
CHECK_RESULT (bool, CHECK_RESULT(bool,
strcmp(svDpiVersion(), "1800-2005")==0 strcmp(svDpiVersion(), "1800-2005")==0
|| strcmp(svDpiVersion(), "P1800-2005")==0 || strcmp(svDpiVersion(), "P1800-2005")==0
, 1); , 1);
#endif #endif
CHECK_RESULT (int, dpix_int123(), 0x123 ); CHECK_RESULT(int, dpix_int123(), 0x123 );
#ifndef CADENCE // No export calls from an import #ifndef CADENCE // No export calls from an import
int o; int o;
dpix_t_int(0x456, &o); dpix_t_int(0x456, &o);
CHECK_RESULT (unsigned long, o, ~0x456UL); CHECK_RESULT(unsigned long, o, ~0x456UL);
dpix_t_renamed(0x456, &o); dpix_t_renamed(0x456, &o);
CHECK_RESULT (int, o, 0x458UL); CHECK_RESULT(int, o, 0x458UL);
#endif #endif
svBitVecVal vec10[1] = {0x10}; svBitVecVal vec10[1] = {0x10};
CHECK_RESULT (int, dpix_f_bit(1), 0x0); CHECK_RESULT(int, dpix_f_bit(1), 0x0);
CHECK_RESULT (int, dpix_f_bit(0), 0x1); CHECK_RESULT(int, dpix_f_bit(0), 0x1);
CHECK_RESULT (int, dpix_f_bit15(vec10) & 0x7fUL, 0x6f); CHECK_RESULT(int, dpix_f_bit15(vec10) & 0x7fUL, 0x6f);
// Simulators disagree over the next three's sign extension unless we mask the upper bits // Simulators disagree over the next three's sign extension unless we mask the upper bits
CHECK_RESULT (int, dpix_f_int(1) & 0xffffffffUL, 0xfffffffeUL); CHECK_RESULT(int, dpix_f_int(1) & 0xffffffffUL, 0xfffffffeUL);
CHECK_RESULT (int, dpix_f_byte(1) & 0xffUL, 0xfe); CHECK_RESULT(int, dpix_f_byte(1) & 0xffUL, 0xfe);
CHECK_RESULT (int, dpix_f_shortint(1) & 0xffffUL, 0xfffeUL); CHECK_RESULT(int, dpix_f_shortint(1) & 0xffffUL, 0xfffeUL);
CHECK_RESULT (unsigned long long, dpix_f_longint(1), 0xfffffffffffffffeULL); CHECK_RESULT(unsigned long long, dpix_f_longint(1), 0xfffffffffffffffeULL);
CHECK_RESULT (void*, dpix_f_chandle((void*)(12345)), (void*)(12345)); CHECK_RESULT(void*, dpix_f_chandle((void*)(12345)), (void*)(12345));
{ {
svBitVecVal i_vec48[2] = {0xab782a12,0x8a413bd9}; svBitVecVal i_vec48[2] = {0xab782a12,0x8a413bd9};
svBitVecVal o_vec48[2] = {0,0}; svBitVecVal o_vec48[2] = {0,0};
dpix_t_bit48(i_vec48, o_vec48); dpix_t_bit48(i_vec48, o_vec48);
CHECK_RESULT(int, o_vec48[0], ~i_vec48[0]); CHECK_RESULT(int, o_vec48[0], ~i_vec48[0]);
#ifdef VCS // VCS has bug where doesn't clean input #ifdef VCS // VCS has bug where doesn't clean input
CHECK_RESULT(int, o_vec48[1], (~i_vec48[1])); CHECK_RESULT(int, o_vec48[1], (~i_vec48[1]));
#else #else
CHECK_RESULT(int, o_vec48[1], (~i_vec48[1])&0x0000ffffUL); CHECK_RESULT(int, o_vec48[1], (~i_vec48[1])&0x0000ffffUL);
#endif #endif
} }
{ {
svBitVecVal i_vec95[3] = {0x72912312,0xab782a12,0x8a413bd9}; svBitVecVal i_vec95[3] = {0x72912312,0xab782a12,0x8a413bd9};
svBitVecVal o_vec95[3] = {0,0,0}; svBitVecVal o_vec95[3] = {0,0,0};
dpix_t_bit95(i_vec95, o_vec95); dpix_t_bit95(i_vec95, o_vec95);
CHECK_RESULT(int, o_vec95[0], ~i_vec95[0]); CHECK_RESULT(int, o_vec95[0], ~i_vec95[0]);
CHECK_RESULT(int, o_vec95[1], ~i_vec95[1]); CHECK_RESULT(int, o_vec95[1], ~i_vec95[1]);
CHECK_RESULT(int, o_vec95[2], (~i_vec95[2])&0x7fffffffUL); CHECK_RESULT(int, o_vec95[2], (~i_vec95[2])&0x7fffffffUL);
} }
{ {
svBitVecVal i_vec96[3] = {0xf2912312,0xab782a12,0x8a413bd9}; svBitVecVal i_vec96[3] = {0xf2912312,0xab782a12,0x8a413bd9};
svBitVecVal o_vec96[3] = {0,0,0}; svBitVecVal o_vec96[3] = {0,0,0};
dpix_t_bit96(i_vec96, o_vec96); dpix_t_bit96(i_vec96, o_vec96);
CHECK_RESULT(int, o_vec96[0], ~i_vec96[0]); CHECK_RESULT(int, o_vec96[0], ~i_vec96[0]);
CHECK_RESULT(int, o_vec96[1], ~i_vec96[1]); CHECK_RESULT(int, o_vec96[1], ~i_vec96[1]);
CHECK_RESULT(int, o_vec96[2], ~i_vec96[2]); CHECK_RESULT(int, o_vec96[2], ~i_vec96[2]);
} }
extern void dpix_t_reg(svLogic i, svLogic* o); extern void dpix_t_reg(svLogic i, svLogic* o);

View File

@ -54,23 +54,23 @@ extern "C" {
extern double dpii_f_real (double i); extern double dpii_f_real (double i);
extern float dpii_f_shortreal(float i); extern float dpii_f_shortreal(float i);
extern void dpii_v_bit (unsigned char i, unsigned char* o); extern void dpii_v_bit (unsigned char i, unsigned char* o);
extern void dpii_v_int (int i, int *o); extern void dpii_v_int (int i, int *o);
extern void dpii_v_uint (unsigned int i, unsigned int *o); extern void dpii_v_uint (unsigned int i, unsigned int *o);
extern void dpii_v_byte (char i, char *o); extern void dpii_v_byte (char i, char *o);
extern void dpii_v_shortint (short int i, short int *o); extern void dpii_v_shortint (short int i, short int *o);
extern void dpii_v_ushort (unsigned short i, unsigned short *o); extern void dpii_v_ushort (unsigned short i, unsigned short *o);
extern void dpii_v_longint (long long i, long long *o); extern void dpii_v_longint (long long i, long long *o);
extern void dpii_v_ulong (unsigned long long i, unsigned long long *o); extern void dpii_v_ulong (unsigned long long i, unsigned long long *o);
extern void dpii_v_struct (const svBitVecVal* i, svBitVecVal* o); extern void dpii_v_struct (const svBitVecVal* i, svBitVecVal* o);
extern void dpii_v_substruct (const svBitVecVal* i, int* o); extern void dpii_v_substruct (const svBitVecVal* i, int* o);
extern void dpii_v_chandle (void* i, void* *o); extern void dpii_v_chandle (void* i, void* *o);
extern void dpii_v_string (const char* i, const char** o); extern void dpii_v_string (const char* i, const char** o);
extern void dpii_v_real (double i, double* o); extern void dpii_v_real (double i, double* o);
extern void dpii_v_shortreal(float i, float* o); extern void dpii_v_shortreal(float i, float* o);
extern void dpii_v_struct (const svBitVecVal* i, svBitVecVal* o); extern void dpii_v_struct (const svBitVecVal* i, svBitVecVal* o);
extern void dpii_v_substruct (const svBitVecVal* i, int* o); extern void dpii_v_substruct (const svBitVecVal* i, int* o);
extern void dpii_v_bit64(const svBitVecVal* i, svBitVecVal* o); extern void dpii_v_bit64(const svBitVecVal* i, svBitVecVal* o);
extern void dpii_v_bit95(const svBitVecVal* i, svBitVecVal* o); extern void dpii_v_bit95(const svBitVecVal* i, svBitVecVal* o);
extern void dpii_v_bit96(const svBitVecVal* i, svBitVecVal* o); extern void dpii_v_bit96(const svBitVecVal* i, svBitVecVal* o);
@ -100,17 +100,17 @@ svBitVecVal dpii_f_bit9 (const svBitVecVal *i) { return 0x1ffUL & ~*i;
svBitVecVal dpii_f_bit16(const svBitVecVal *i) { return 0xffffUL & ~*i; } svBitVecVal dpii_f_bit16(const svBitVecVal *i) { return 0xffffUL & ~*i; }
svBitVecVal dpii_f_bit17(const svBitVecVal *i) { return 0x1ffffUL & ~*i; } svBitVecVal dpii_f_bit17(const svBitVecVal *i) { return 0x1ffffUL & ~*i; }
svBitVecVal dpii_f_bit32(const svBitVecVal *i) { return ~*i; } svBitVecVal dpii_f_bit32(const svBitVecVal *i) { return ~*i; }
long long dpii_f_bit33(const svBitVecVal *i) { return ((1ULL<<33)-1) & ~((long long)(i[1])<<32ULL | i[0]); } long long dpii_f_bit33(const svBitVecVal *i) { return ((1ULL<<33)-1) & ~((long long)(i[1])<<32ULL | i[0]); }
long long dpii_f_bit64(const svBitVecVal *i) { return ~((long long)(i[1])<<32ULL | i[0]); } long long dpii_f_bit64(const svBitVecVal *i) { return ~((long long)(i[1])<<32ULL | i[0]); }
int dpii_f_int (int i) { return ~i; } int dpii_f_int (int i) { return ~i; }
char dpii_f_byte (char i) { return ~i; } char dpii_f_byte (char i) { return ~i; }
short int dpii_f_shortint(short int i) { return ~i; } short int dpii_f_shortint(short int i) { return ~i; }
long long dpii_f_longint (long long i) { return ~i; } long long dpii_f_longint (long long i) { return ~i; }
void* dpii_f_chandle (void* i) { return i; } void* dpii_f_chandle (void* i) { return i; }
const char* dpii_f_string (const char* i) { return i; } const char* dpii_f_string (const char* i) { return i; }
double dpii_f_real (double i) { return i+1.5; } double dpii_f_real (double i) { return i+1.5; }
float dpii_f_shortreal(float i) { return i+1.5f; } float dpii_f_shortreal(float i) { return i+1.5f; }
void dpii_v_bit(unsigned char i, unsigned char *o) { *o = 1 & ~i; } void dpii_v_bit(unsigned char i, unsigned char *o) { *o = 1 & ~i; }
void dpii_v_int(int i, int *o) { *o = ~i; } void dpii_v_int(int i, int *o) { *o = ~i; }
@ -149,33 +149,33 @@ void dpii_v_time(const svLogicVecVal* i, svLogicVecVal* o) {
o[1].bval = 0; o[1].bval = 0;
} }
void dpii_v_struct (const svBitVecVal* i, svBitVecVal* o) { void dpii_v_struct(const svBitVecVal* i, svBitVecVal* o) {
o[0] = ~i[0]; o[0] = ~i[0];
o[1] = ~i[1]; o[1] = ~i[1];
o[2] = ~i[2]; o[2] = ~i[2];
} }
void dpii_v_substruct (const svBitVecVal* i, int* o) { void dpii_v_substruct(const svBitVecVal* i, int* o) {
// To be most like other tools, this should automagically take the substruct_t // To be most like other tools, this should automagically take the substruct_t
// as an argument, and not require this cast... // as an argument, and not require this cast...
substruct_t* issp = (substruct_t*) i; substruct_t* issp = (substruct_t*) i;
o[0] = issp->b - issp->a; o[0] = issp->b - issp->a;
} }
void dpii_v_bit64(const svBitVecVal* i, svBitVecVal* o) { void dpii_v_bit64(const svBitVecVal* i, svBitVecVal* o) {
o[0] = ~i[0]; o[0] = ~i[0];
o[1] = ~i[1]; o[1] = ~i[1];
} }
void dpii_v_bit95(const svBitVecVal* i, svBitVecVal* o) { void dpii_v_bit95(const svBitVecVal* i, svBitVecVal* o) {
o[0] = (~i[0]); o[0] = (~i[0]);
o[1] = (~i[1]); o[1] = (~i[1]);
o[2] = (~i[2]) & 0x7fffffffUL; o[2] = (~i[2]) & 0x7fffffffUL;
} }
void dpii_v_bit96(const svBitVecVal* i, svBitVecVal* o) { void dpii_v_bit96(const svBitVecVal* i, svBitVecVal* o) {
o[0] = ~i[0]; o[0] = ~i[0];
o[1] = ~i[1]; o[1] = ~i[1];
o[2] = ~i[2]; o[2] = ~i[2];
} }
int dpii_f_strlen (const char* i) { return strlen(i); } int dpii_f_strlen(const char* i) { return strlen(i); }
//====================================================================== //======================================================================

View File

@ -56,9 +56,9 @@ int dpii_failure() { return failure; }
void dpii_lib_bit_check() { void dpii_lib_bit_check() {
svBitVecVal bv [3]; svBitVecVal bv [3];
bv[0] = 0xa3a2a1a0; // 31..0 bv[0] = 0xa3a2a1a0; // 31..0
bv[1] = 0xa7a6a5a4; // 63..32 bv[1] = 0xa7a6a5a4; // 63..32
bv[2] = 0xabaaa9a8; // 95..64 bv[2] = 0xabaaa9a8; // 95..64
CHECK_RESULT_HEX((int)svGetBitselBit(bv, 32), 0); CHECK_RESULT_HEX((int)svGetBitselBit(bv, 32), 0);
CHECK_RESULT_HEX((int)svGetBitselBit(bv, 33), 0); CHECK_RESULT_HEX((int)svGetBitselBit(bv, 33), 0);
CHECK_RESULT_HEX((int)svGetBitselBit(bv, 34), 1); CHECK_RESULT_HEX((int)svGetBitselBit(bv, 34), 1);
@ -88,12 +88,12 @@ void dpii_lib_bit_check() {
void dpii_lib_logic_check() { void dpii_lib_logic_check() {
svLogicVecVal lv [3]; svLogicVecVal lv [3];
lv[0].aval = 0xb3b2b1b0; // 31..0 lv[0].aval = 0xb3b2b1b0; // 31..0
lv[1].aval = 0xb7b6b5b4; // 63..32 lv[1].aval = 0xb7b6b5b4; // 63..32
lv[2].aval = 0xbbbab9b8; // 95..64 lv[2].aval = 0xbbbab9b8; // 95..64
lv[0].bval = 0xc3c2c1c0; // 31..0 lv[0].bval = 0xc3c2c1c0; // 31..0
lv[1].bval = 0xc7c6c5c4; // 63..32 lv[1].bval = 0xc7c6c5c4; // 63..32
lv[2].bval = 0xcbcac9c8; // 95..64 lv[2].bval = 0xcbcac9c8; // 95..64
CHECK_RESULT_HEX((int)svGetBitselLogic(lv, 32), 0); CHECK_RESULT_HEX((int)svGetBitselLogic(lv, 32), 0);
CHECK_RESULT_HEX((int)svGetBitselLogic(lv, 33), 0); CHECK_RESULT_HEX((int)svGetBitselLogic(lv, 33), 0);
CHECK_RESULT_HEX((int)svGetBitselLogic(lv, 34), 3); CHECK_RESULT_HEX((int)svGetBitselLogic(lv, 34), 3);

View File

@ -85,7 +85,7 @@ int dpii_failure() { return failure; }
#ifdef _WIN32 #ifdef _WIN32
# define T_PRI64 "I64" # define T_PRI64 "I64"
#else // Linux or compliant Unix flavors #else // Linux or compliant Unix flavors
# define T_PRI64 "ll" # define T_PRI64 "ll"
#endif #endif

View File

@ -47,10 +47,10 @@ int main(int argc, char *argv[]) {
topp->in = 1.1; topp->in = 1.1;
topp->eval(); topp->eval();
if (topp->out != 1.2) { if (topp->out != 1.2) {
VL_PRINTF("*-* All Finished *-*\n"); VL_PRINTF("*-* All Finished *-*\n");
topp->final(); topp->final();
} else { } else {
vl_fatal(__FILE__,__LINE__,"top", "Unexpected results\n"); vl_fatal(__FILE__,__LINE__,"top", "Unexpected results\n");
} }
return 0; return 0;
} }

View File

@ -42,7 +42,7 @@ void mon_do(MyMon* monp) {
#ifdef TEST_VERBOSE #ifdef TEST_VERBOSE
VL_PRINTF("- mon_do(%08x(&%p) -> %08x(&%p));\n", VL_PRINTF("- mon_do(%08x(&%p) -> %08x(&%p));\n",
*(monp->sigsp[0]), monp->sigsp[0], *(monp->sigsp[1]), monp->sigsp[1]); *(monp->sigsp[0]), monp->sigsp[0], *(monp->sigsp[1]), monp->sigsp[1]);
#endif #endif
} }
@ -74,13 +74,13 @@ void mon_register_b(const char* namep, int isOut) {
const VerilatedScope* scopep = Verilated::dpiScope(); const VerilatedScope* scopep = Verilated::dpiScope();
const VerilatedVar* varp = scopep->varFind(namep); const VerilatedVar* varp = scopep->varFind(namep);
if (!varp) { if (!varp) {
VL_PRINTF("%%Warning: mon_register_b signal not found: \"%s\"\n", namep); VL_PRINTF("%%Warning: mon_register_b signal not found: \"%s\"\n", namep);
} else if (varp->vltype() != VLVT_UINT32) { } else if (varp->vltype() != VLVT_UINT32) {
VL_PRINTF("%%Warning: wrong type for signal: \"%s\"\n", namep); VL_PRINTF("%%Warning: wrong type for signal: \"%s\"\n", namep);
} else { } else {
vluint32_t* datap = (vluint32_t*)(varp->datap()); vluint32_t* datap = (vluint32_t*)(varp->datap());
VL_PRINTF("- mon_register_b('%s', \"%s\", %p, %d);\n", modp, namep, datap, isOut); VL_PRINTF("- mon_register_b('%s', \"%s\", %p, %d);\n", modp, namep, datap, isOut);
mons[1].sigsp[isOut] = (vluint32_t*)(varp->datap()); mons[1].sigsp[isOut] = (vluint32_t*)(varp->datap());
} }
} }
@ -93,10 +93,10 @@ void mon_register_done() {
// Print list of all signals - if we didn't register2 anything we'd pick them off here // Print list of all signals - if we didn't register2 anything we'd pick them off here
const VerilatedScope* scopep = Verilated::dpiScope(); const VerilatedScope* scopep = Verilated::dpiScope();
if (VerilatedVarNameMap* varsp = scopep->varsp()) { if (VerilatedVarNameMap* varsp = scopep->varsp()) {
for (VerilatedVarNameMap::const_iterator it = varsp->begin(); for (VerilatedVarNameMap::const_iterator it = varsp->begin();
it != varsp->end(); ++it) { it != varsp->end(); ++it) {
VL_PRINTF("- mon2: %s\n", it->first); VL_PRINTF("- mon2: %s\n", it->first);
} }
} }
} }
@ -132,13 +132,13 @@ int main(int argc, char **argv, char **env) {
main_time += 10; main_time += 10;
while (sc_time_stamp() < sim_time && !Verilated::gotFinish()) { while (sc_time_stamp() < sim_time && !Verilated::gotFinish()) {
main_time += 1; main_time += 1;
topp->eval(); topp->eval();
topp->clk = !topp->clk; topp->clk = !topp->clk;
//mon_do(); //mon_do();
} }
if (!Verilated::gotFinish()) { if (!Verilated::gotFinish()) {
vl_fatal(__FILE__,__LINE__,"main", "%Error: Timeout; never got a $finish"); vl_fatal(__FILE__,__LINE__,"main", "%Error: Timeout; never got a $finish");
} }
topp->final(); topp->final();

View File

@ -45,24 +45,24 @@ extern "C" {
//====================================================================== //======================================================================
extern int T_Embed_Child_Unique; extern int T_Embed_Child_Unique;
int T_Embed_Child_Unique = 0; // Address used for uniqueness int T_Embed_Child_Unique = 0; // Address used for uniqueness
Vt_embed1_child* __get_modelp() { Vt_embed1_child* __get_modelp() {
svScope scope = svGetScope(); svScope scope = svGetScope();
if (!scope) { if (!scope) {
vl_fatal(__FILE__,__LINE__,__FILE__,"svGetScope failed"); vl_fatal(__FILE__,__LINE__,__FILE__,"svGetScope failed");
return NULL; return NULL;
} }
void* __modelp = svGetUserData(scope, &T_Embed_Child_Unique); void* __modelp = svGetUserData(scope, &T_Embed_Child_Unique);
if (!__modelp) { if (!__modelp) {
// Create the model // Create the model
const char* scopenamep = svGetNameFromScope(scope); const char* scopenamep = svGetNameFromScope(scope);
if (!scopenamep) vl_fatal(__FILE__,__LINE__,__FILE__,"svGetNameFromScope failed"); if (!scopenamep) vl_fatal(__FILE__,__LINE__,__FILE__,"svGetNameFromScope failed");
__modelp = new Vt_embed1_child(scopenamep); __modelp = new Vt_embed1_child(scopenamep);
if (svPutUserData(scope, &T_Embed_Child_Unique, __modelp)) { if (svPutUserData(scope, &T_Embed_Child_Unique, __modelp)) {
vl_fatal(__FILE__,__LINE__,__FILE__,"svPutUserData failed"); vl_fatal(__FILE__,__LINE__,__FILE__,"svPutUserData failed");
} }
} }
return (Vt_embed1_child*)(__modelp); return (Vt_embed1_child*)(__modelp);
} }
@ -97,8 +97,8 @@ void t_embed_child_io_eval(unsigned char clk,
VL_DEBUG_IF(VL_PRINTF(" t_embed1_child_io_eval\n"); ); VL_DEBUG_IF(VL_PRINTF(" t_embed1_child_io_eval\n"); );
Vt_embed1_child* __modelp = __get_modelp(); Vt_embed1_child* __modelp = __get_modelp();
VL_DEBUG_IF(VL_PRINTF("[%0ld] in clk=%x b=%x V=%x R=%x\n", VL_DEBUG_IF(VL_PRINTF("[%0ld] in clk=%x b=%x V=%x R=%x\n",
(long int) (VL_TIME_Q()), clk, bit_in, vec_in[0], (long int) (VL_TIME_Q()), clk, bit_in, vec_in[0],
is_ref);); is_ref););
__modelp->clk = clk; __modelp->clk = clk;
__modelp->bit_in = bit_in; __modelp->bit_in = bit_in;
__modelp->vec_in = vec_in[0]; __modelp->vec_in = vec_in[0];
@ -120,6 +120,6 @@ void t_embed_child_io_eval(unsigned char clk,
wide_out[3] = __modelp->wide_out[3]; wide_out[3] = __modelp->wide_out[3];
*did_init_out = __modelp->did_init_out; *did_init_out = __modelp->did_init_out;
VL_DEBUG_IF(VL_PRINTF("[%0ld] out b=%x V=%x DI=%x\n", VL_DEBUG_IF(VL_PRINTF("[%0ld] out b=%x V=%x DI=%x\n",
(long int)(VL_TIME_Q()), *bit_out, *vec_out, (long int)(VL_TIME_Q()), *bit_out, *vec_out,
*did_init_out);); *did_init_out););
} }

View File

@ -17,7 +17,7 @@ scenarios(vlt => 1);
print "Old mtime=",$oldstats[9],"\n"; print "Old mtime=",$oldstats[9],"\n";
$oldstats[9] or error("No output file found: $outfile\n"); $oldstats[9] or error("No output file found: $outfile\n");
sleep (1); # Or else it might take < 1 second to compile and see no diff. sleep(1); # Or else it might take < 1 second to compile and see no diff.
compile(); compile();

View File

@ -15,13 +15,13 @@ int main(int argc, char *argv[]) {
printf("\nTesting\n"); printf("\nTesting\n");
for (int i = 0; i < 10; i++) { for (int i = 0; i < 10; i++) {
topp->clk = 0; topp->clk = 0;
topp->eval(); topp->eval();
topp->clk = 1; topp->clk = 1;
topp->eval(); topp->eval();
} }
if (topp->Rand != 0xfeed0fad) { if (topp->Rand != 0xfeed0fad) {
vl_fatal(__FILE__,__LINE__,"top", "Unexpected value for Rand output\n"); vl_fatal(__FILE__,__LINE__,"top", "Unexpected value for Rand output\n");
} }
printf("*-* All Finished *-*\n"); printf("*-* All Finished *-*\n");
} }

View File

@ -52,7 +52,7 @@ my $global_mtask_ct = 0;
$gantt_line_ct++; $gantt_line_ct++;
my $this_thread_mtask_ct = 0; my $this_thread_mtask_ct = 0;
my @mtasks = split(/\[/, $line); my @mtasks = split(/\[/, $line);
shift @mtasks; # throw the '>> ' away shift @mtasks; # throw the '>> ' away
foreach my $mtask (@mtasks) { foreach my $mtask (@mtasks) {
# Format of each mtask is "[123--]" where the hyphens # Format of each mtask is "[123--]" where the hyphens
# number or ] may or may not appear; it depends on exact timing. # number or ] may or may not appear; it depends on exact timing.

View File

@ -53,7 +53,7 @@ execute(
); );
# Must be <<9000 above to prove this worked # Must be <<9000 above to prove this worked
file_grep ($Self->{stats}, qr/Optimizations, Gate sigs deleted\s+(\d+)/i, 8575); file_grep($Self->{stats}, qr/Optimizations, Gate sigs deleted\s+(\d+)/i, 8575);
ok(1); ok(1);
1; 1;

View File

@ -22,7 +22,7 @@ foreach my $prog (
logfile => "$Self->{obj_dir}/t_help.log", logfile => "$Self->{obj_dir}/t_help.log",
tee => 0, tee => 0,
); );
file_grep ("$Self->{obj_dir}/t_help.log", qr/DISTRIBUTION/i); file_grep("$Self->{obj_dir}/t_help.log", qr/DISTRIBUTION/i);
} }
ok(1); ok(1);

View File

@ -38,8 +38,8 @@ sub checkRelativeRefs {
if ($Self->{vlt_all}) { if ($Self->{vlt_all}) {
# We expect to combine sequent functions across multiple instances of # We expect to combine sequent functions across multiple instances of
# l2, l3, l4, l5. If this number drops, please confirm this has not broken. # l2, l3, l4, l5. If this number drops, please confirm this has not broken.
file_grep ($Self->{stats}, qr/Optimizations, Combined CFuncs\s+(\d+)/i, file_grep($Self->{stats}, qr/Optimizations, Combined CFuncs\s+(\d+)/i,
($Self->{vltmt} ? 84 : 52)); ($Self->{vltmt} ? 84 : 52));
# Expect absolute refs in CFuncs for t (top module) and l1 (because it # Expect absolute refs in CFuncs for t (top module) and l1 (because it
# has only one instance) # has only one instance)

View File

@ -18,8 +18,8 @@ compile(
if ($Self->{vlt_all}) { if ($Self->{vlt_all}) {
# Fewer optimizations than t_inst_tree_inl0_pub1 which allows # Fewer optimizations than t_inst_tree_inl0_pub1 which allows
# relative CFuncs: # relative CFuncs:
file_grep ($Self->{stats}, qr/Optimizations, Combined CFuncs\s+(\d+)/i, file_grep($Self->{stats}, qr/Optimizations, Combined CFuncs\s+(\d+)/i,
($Self->{vltmt} ? 0 : 31)); ($Self->{vltmt} ? 0 : 31));
# Should not find any 'this->' except some 'this->__VlSymsp' # Should not find any 'this->' except some 'this->__VlSymsp'
my @files = `ls $Self->{obj_dir}/*.cpp`; my @files = `ls $Self->{obj_dir}/*.cpp`;

View File

@ -11,7 +11,7 @@ scenarios(simulator => 1);
compile( compile(
v_flags2 => ['+libext+.vi+.extranoneed'], v_flags2 => ['+libext+.vi+.extranoneed'],
nc => 0, # Error: Multiple +libext flags found nc => 0, # Error: Multiple +libext flags found
vcs => 0, vcs => 0,
); );

View File

@ -20,7 +20,7 @@ double sc_time_stamp() {
long long get_memory_usage() { long long get_memory_usage() {
// Return memory usage. Return 0 if the system doesn't look quite right. // Return memory usage. Return 0 if the system doesn't look quite right.
#if 0 // BSD only. #if 0 // BSD only.
struct rusage usage; struct rusage usage;
getrusage(RUSAGE_SELF, &usage); getrusage(RUSAGE_SELF, &usage);
return usage.ru_ixrss + usage.ru_idrss + usage.ru_isrss; return usage.ru_ixrss + usage.ru_idrss + usage.ru_isrss;
@ -29,20 +29,20 @@ long long get_memory_usage() {
FILE* fp = fopen("/proc/self/stat", "r"); FILE* fp = fopen("/proc/self/stat", "r");
if (!fp) return 0; if (!fp) return 0;
int ps_ign; int ps_ign;
vluint64_t ps_vsize, ps_rss; vluint64_t ps_vsize, ps_rss;
int items = fscanf(fp, ("%d (%*[^) ]) %*1s %d %*d %*d %*d %*d %u" int items = fscanf(fp, ("%d (%*[^) ]) %*1s %d %*d %*d %*d %*d %u"
" %u %u %u %u %d %d %d %d" " %u %u %u %u %d %d %d %d"
" %*d %*d %*u %*u %d %" VL_PRI64 "u %" VL_PRI64 "u "), " %*d %*d %*u %*u %d %" VL_PRI64 "u %" VL_PRI64 "u "),
&ps_ign, &ps_ign, &ps_ign, &ps_ign, &ps_ign, &ps_ign,
&ps_ign, &ps_ign, &ps_ign, &ps_ign, &ps_ign, &ps_ign, &ps_ign, &ps_ign,
&ps_ign, &ps_ign, &ps_ign, &ps_ign, &ps_ign, &ps_ign, &ps_ign, &ps_ign,
&ps_ign, &ps_vsize, &ps_rss); &ps_ign, &ps_vsize, &ps_rss);
fclose(fp); fclose(fp);
if (items >= 14) { if (items >= 14) {
return ps_vsize; return ps_vsize;
} else { } else {
return 0; return 0;
} }
} }
@ -54,9 +54,9 @@ void make_and_destroy() {
topp->eval(); topp->eval();
topp->clk = true; topp->clk = true;
while (!Verilated::gotFinish()) { while (!Verilated::gotFinish()) {
main_time+=5; main_time+=5;
topp->clk=!topp->clk; topp->clk=!topp->clk;
topp->eval(); topp->eval();
} }
delete topp; topp=NULL; delete topp; topp=NULL;
@ -67,22 +67,22 @@ int main(int argc, char *argv[]) {
// Warmup phase // Warmup phase
for (int i=0; i<1000; i++) { for (int i=0; i<1000; i++) {
make_and_destroy(); make_and_destroy();
} }
firstUsage = get_memory_usage(); firstUsage = get_memory_usage();
printf("Memory size %" VL_PRI64 "d bytes\n", firstUsage); printf("Memory size %" VL_PRI64 "d bytes\n", firstUsage);
int loops = 100*1000; int loops = 100*1000;
for (int left=loops; left>0;) { for (int left=loops; left>0;) {
for (int j=0; j<1000; j++, left--) { for (int j=0; j<1000; j++, left--) {
make_and_destroy(); make_and_destroy();
} }
} }
vluint64_t leaked = get_memory_usage() - firstUsage; vluint64_t leaked = get_memory_usage() - firstUsage;
if (leaked > 64*1024) { // Have to allow some slop for this code. if (leaked > 64*1024) { // Have to allow some slop for this code.
printf("Leaked %" VL_PRI64 "d bytes, or ~ %" VL_PRI64 "d bytes/construt\n", leaked, leaked/loops); printf("Leaked %" VL_PRI64 "d bytes, or ~ %" VL_PRI64 "d bytes/construt\n", leaked, leaked/loops);
vl_fatal(__FILE__,__LINE__,"top", "Leaked memory\n"); vl_fatal(__FILE__,__LINE__,"top", "Leaked memory\n");
} }
printf("*-* All Finished *-*\n"); printf("*-* All Finished *-*\n");

View File

@ -6,7 +6,7 @@
QData MaskVal(int lbit, int hbit) { QData MaskVal(int lbit, int hbit) {
QData val; QData val;
for (val = 0; lbit <= hbit; lbit++) for (val = 0; lbit <= hbit; lbit++)
val |= (1ULL << lbit); val |= (1ULL << lbit);
return val; return val;
} }
@ -18,35 +18,35 @@ int main(int argc, char *argv[]) {
int errs=0; int errs=0;
for (lbit = 0; lbit < 32; lbit++) { for (lbit = 0; lbit < 32; lbit++) {
for (hbit = lbit; hbit < 32; hbit++) { for (hbit = lbit; hbit < 32; hbit++) {
QData expected; QData expected;
sim->LowMaskSel_Bot = lbit; sim->LowMaskSel_Bot = lbit;
sim->LowMaskSel_Top = lbit; sim->LowMaskSel_Top = lbit;
sim->HighMaskSel_Bot = hbit; sim->HighMaskSel_Bot = hbit;
sim->HighMaskSel_Top = hbit; sim->HighMaskSel_Top = hbit;
sim->eval(); sim->eval();
expected = (MaskVal(sim->LowMaskSel_Top, sim->HighMaskSel_Top) << 32ULL) expected = (MaskVal(sim->LowMaskSel_Top, sim->HighMaskSel_Top) << 32ULL)
| MaskVal(sim->LowMaskSel_Bot, sim->HighMaskSel_Bot); | MaskVal(sim->LowMaskSel_Bot, sim->HighMaskSel_Bot);
if (sim->LogicImm != expected) { if (sim->LogicImm != expected) {
printf("%%Error: %d.%d,%d.%d -> %016" VL_PRI64 "x/%016" VL_PRI64 "x -> %016" VL_PRI64 "x (expected %016" VL_PRI64 "x)\n", printf("%%Error: %d.%d,%d.%d -> %016" VL_PRI64 "x/%016" VL_PRI64 "x -> %016" VL_PRI64 "x (expected %016" VL_PRI64 "x)\n",
sim->LowMaskSel_Top, sim->HighMaskSel_Top, sim->LowMaskSel_Top, sim->HighMaskSel_Top,
sim->LowMaskSel_Bot, sim->HighMaskSel_Bot, sim->LowMaskSel_Bot, sim->HighMaskSel_Bot,
sim->LowLogicImm, sim->HighLogicImm, sim->LowLogicImm, sim->HighLogicImm,
sim->LogicImm, expected); sim->LogicImm, expected);
errs=1; errs=1;
} }
} }
} }
if (errs) { if (errs) {
vl_stop(__FILE__, __LINE__, "TOP-cpp"); vl_stop(__FILE__, __LINE__, "TOP-cpp");
exit(10); exit(10);
} else { } else {
printf("*-* All Finished *-*\n"); printf("*-* All Finished *-*\n");
exit(0); exit(0);
} }
} }

View File

@ -14,8 +14,8 @@ double sc_time_stamp() {
void check(const char* bus, int got, int exp) { void check(const char* bus, int got, int exp) {
if (got != exp) { if (got != exp) {
VL_PRINTF("%%Error: Data mismatch on '%s', got=%x, exp=%x\n", bus, got, exp); VL_PRINTF("%%Error: Data mismatch on '%s', got=%x, exp=%x\n", bus, got, exp);
pass = false; pass = false;
} }
} }
@ -29,22 +29,22 @@ int main()
tb = new VM_PREFIX("tb"); tb = new VM_PREFIX("tb");
#ifdef SYSTEMC_VERSION #ifdef SYSTEMC_VERSION
sc_signal<vluint32_t> i3; sc_signal<vluint32_t> i3;
sc_signal<vluint32_t> o3; sc_signal<vluint32_t> o3;
sc_signal<vluint32_t> i34[4]; sc_signal<vluint32_t> i34[4];
sc_signal<vluint32_t> o34[4]; sc_signal<vluint32_t> o34[4];
sc_signal<vluint32_t> i345[4][5]; sc_signal<vluint32_t> i345[4][5];
sc_signal<vluint32_t> o345[4][5]; sc_signal<vluint32_t> o345[4][5];
tb->i3(i3); tb->i3(i3);
tb->o3(o3); tb->o3(o3);
for (int i=0; i<4; i++) { for (int i=0; i<4; i++) {
tb->i34[i](i34[i]); tb->i34[i](i34[i]);
tb->o34[i](o34[i]); tb->o34[i](o34[i]);
for (int j=0; j<5; j++) { for (int j=0; j<5; j++) {
tb->i345[i][j](i345[i][j]); tb->i345[i][j](i345[i][j]);
tb->o345[i][j](o345[i][j]); tb->o345[i][j](o345[i][j]);
} }
} }
#endif #endif
@ -61,10 +61,10 @@ int main()
ASSIGN(i3, 13); ASSIGN(i3, 13);
for (int i=0; i<4; i++) { for (int i=0; i<4; i++) {
ASSIGN(i34[i], i); ASSIGN(i34[i], i);
for (int j=0; j<5; j++) { for (int j=0; j<5; j++) {
ASSIGN(i345[i][j], i*8 + j); ASSIGN(i345[i][j], i*8 + j);
} }
} }
#ifdef SYSTEMC_VERSION #ifdef SYSTEMC_VERSION
@ -75,16 +75,16 @@ int main()
check("o3", READ(o3), 13); check("o3", READ(o3), 13);
for (int i=0; i<4; i++) { for (int i=0; i<4; i++) {
check("o34", READ(o34[i]), i); check("o34", READ(o34[i]), i);
for (int j=0; j<5; j++) { for (int j=0; j<5; j++) {
check("o345", READ(o345[i][j]), i*8 + j); check("o345", READ(o345[i][j]), i*8 + j);
} }
} }
if (pass) { if (pass) {
VL_PRINTF("*-* All Finished *-*\n"); VL_PRINTF("*-* All Finished *-*\n");
} else { } else {
vl_fatal(__FILE__,__LINE__,"top", "Unexpected results from test\n"); vl_fatal(__FILE__,__LINE__,"top", "Unexpected results from test\n");
} }
return 0; return 0;
} }

View File

@ -25,9 +25,9 @@ int main()
bool pass = true; bool pass = true;
if (pass) { if (pass) {
VL_PRINTF("*-* All Finished *-*\n"); VL_PRINTF("*-* All Finished *-*\n");
} else { } else {
vl_fatal(__FILE__,__LINE__,"top", "Unexpected results from test\n"); vl_fatal(__FILE__,__LINE__,"top", "Unexpected results from test\n");
} }
return 0; return 0;
} }

View File

@ -14,7 +14,7 @@ compile(
); );
if ($Self->{vlt_all}) { if ($Self->{vlt_all}) {
file_grep ($Self->{stats}, qr/Optimizations, Delayed shared-sets\s+(\d+)/i, 14); file_grep($Self->{stats}, qr/Optimizations, Delayed shared-sets\s+(\d+)/i, 14);
} }
execute( execute(

View File

@ -30,9 +30,9 @@ unsigned int StepSim(Vt_mem_slot *sim, unsigned int slot, unsigned int bit, unsi
} }
if (val) if (val)
Array[slot] |= (1 << bit); Array[slot] |= (1 << bit);
else else
Array[slot] &= ~(1 << bit); Array[slot] &= ~(1 << bit);
return sim->OutputVal; return sim->OutputVal;
} }
@ -45,7 +45,7 @@ int main(int argc, char *argv[]) {
/* clear all bits in the array */ /* clear all bits in the array */
for (slot = 0; slot < 3; slot++) for (slot = 0; slot < 3; slot++)
for (bit = 0; bit < 2; bit++) for (bit = 0; bit < 2; bit++)
StepSim(sim, slot, bit, 0, 0); StepSim(sim, slot, bit, 0, 0);
printf("\nTesting\n"); printf("\nTesting\n");

View File

@ -21,8 +21,8 @@ bool fail = false;
void check(QData got, QData exp) { void check(QData got, QData exp) {
if (got != exp) { if (got != exp) {
VL_PRINTF("%%Error: got=0x%" VL_PRI64 "x exp=0x%" VL_PRI64 "x\n", got, exp); VL_PRINTF("%%Error: got=0x%" VL_PRI64 "x exp=0x%" VL_PRI64 "x\n", got, exp);
fail = true; fail = true;
} }
} }
@ -41,10 +41,10 @@ int main(int argc, char *argv[]) {
topp->final(); topp->final();
if (!fail) { if (!fail) {
VL_PRINTF("*-* All Finished *-*\n"); VL_PRINTF("*-* All Finished *-*\n");
topp->final(); topp->final();
} else { } else {
vl_fatal(__FILE__,__LINE__,"top", "Unexpected results\n"); vl_fatal(__FILE__,__LINE__,"top", "Unexpected results\n");
} }
return 0; return 0;
} }

View File

@ -17,38 +17,38 @@ print STDERR "t_pipe_filter.pf: Hello in Perl\n" if $Debug;
while (defined(my $cmd = <STDIN>)) { while (defined(my $cmd = <STDIN>)) {
print STDERR "t_pipe_filter.pf: gotcmd: $cmd" if $Debug; print STDERR "t_pipe_filter.pf: gotcmd: $cmd" if $Debug;
if ($cmd =~ /^read "(.*)"/) { if ($cmd =~ /^read "(.*)"/) {
my $filename = $1; my $filename = $1;
open(my $fh, "<$filename") open(my $fh, "<$filename")
or die "t_pipe_filter.pf: %Error: $! $filename\n"; or die "t_pipe_filter.pf: %Error: $! $filename\n";
my $wholefile=""; my $wholefile="";
# It's faster to slurp the whole file then scan (if needed), # It's faster to slurp the whole file then scan (if needed),
# then to read it into an array with getlines # then to read it into an array with getlines
{ local $/; undef $/; $wholefile = <$fh>; } { local $/; undef $/; $wholefile = <$fh>; }
close $fh; close $fh;
if ($wholefile =~ /example_lint/) { # else short circuit if ($wholefile =~ /example_lint/) { # else short circuit
my $lineno = 1; my $pos=0; my $lineno = 1; my $pos=0;
my @prefixes; my @prefixes;
while (1) { while (1) {
my $newpos=index($wholefile,"\n",$pos); my $newpos=index($wholefile,"\n",$pos);
last if $newpos<$pos; last if $newpos<$pos;
my $line = substr($wholefile,$pos,$newpos-$pos); my $line = substr($wholefile,$pos,$newpos-$pos);
if ($line =~ /example_lint/) { if ($line =~ /example_lint/) {
# We don't have a way to specify this yet, so just for now # We don't have a way to specify this yet, so just for now
#print STDERR $line; #print STDERR $line;
push @prefixes, "int lint_off_line_${lineno} = 1;\n"; push @prefixes, "int lint_off_line_${lineno} = 1;\n";
} }
$lineno++; $lineno++;
$pos = $newpos+1; $pos = $newpos+1;
} }
#print STDERR "Line count: $lineno\n"; #print STDERR "Line count: $lineno\n";
$wholefile = join('',@prefixes) . $wholefile; $wholefile = join('',@prefixes) . $wholefile;
} }
print STDOUT "Content-Length: ".length($wholefile)."\n".$wholefile."\n"; print STDOUT "Content-Length: ".length($wholefile)."\n".$wholefile."\n";
} else { } else {
die "t_pipe_filter.pf: %Error: Unknown command: $cmd\n"; die "t_pipe_filter.pf: %Error: Unknown command: $cmd\n";
} }
} }

View File

@ -19,10 +19,10 @@ execute(
); );
if ($Self->{vlt_all}) { if ($Self->{vlt_all}) {
file_grep ($Self->{stats}, qr/Optimizations, Reloop iterations\s+(\d+)/i, file_grep($Self->{stats}, qr/Optimizations, Reloop iterations\s+(\d+)/i,
768); 768);
file_grep ($Self->{stats}, qr/Optimizations, Reloops\s+(\d+)/i, file_grep($Self->{stats}, qr/Optimizations, Reloops\s+(\d+)/i,
3); 3);
} }
ok(1); ok(1);

View File

@ -13,7 +13,7 @@ top_filename("t/t_sys_readmem.v");
# Use random reset to ensure we're fully initializing arrays before # Use random reset to ensure we're fully initializing arrays before
# $writememh, to avoid miscompares with X's on 4-state simulators. # $writememh, to avoid miscompares with X's on 4-state simulators.
$Self->{verilated_randReset} = 2; # 2 == truly random $Self->{verilated_randReset} = 2; # 2 == truly random
compile(v_flags2 => [ compile(v_flags2 => [
"+define+WRITEMEM_READ_BACK=1", "+define+WRITEMEM_READ_BACK=1",

View File

@ -17,7 +17,7 @@ execute(
check_finished => 1, check_finished => 1,
); );
file_grep ("$Self->{obj_dir}/simx.vcd", qr/\$enddefinitions/x); file_grep("$Self->{obj_dir}/simx.vcd", qr/\$enddefinitions/x);
ok(1); ok(1);
1; 1;

View File

@ -39,26 +39,26 @@ int main(int argc, char **argv, char **env) {
while (main_time < 190) { // Creates 2 files while (main_time < 190) { // Creates 2 files
top->clk = !top->clk; top->clk = !top->clk;
top->eval(); top->eval();
if ((main_time % 100) == 0) { if ((main_time % 100) == 0) {
#if defined(T_TRACE_CAT) #if defined(T_TRACE_CAT)
tfp->openNext(true); tfp->openNext(true);
#elif defined(T_TRACE_CAT_REOPEN) #elif defined(T_TRACE_CAT_REOPEN)
tfp->close(); tfp->close();
tfp->open(trace_name()); tfp->open(trace_name());
#elif defined(T_TRACE_CAT_RENEW) #elif defined(T_TRACE_CAT_RENEW)
tfp->close(); tfp->close();
delete tfp; delete tfp;
tfp = new VerilatedVcdC; tfp = new VerilatedVcdC;
top->trace(tfp,99); top->trace(tfp,99);
tfp->open(trace_name()); tfp->open(trace_name());
#else #else
# error "Unknown test" # error "Unknown test"
#endif #endif
} }
tfp->dump((unsigned int)(main_time)); tfp->dump((unsigned int)(main_time));
++main_time; ++main_time;
} }
tfp->close(); tfp->close();
top->final(); top->final();

View File

@ -19,7 +19,7 @@ execute(
check_finished => 1, check_finished => 1,
); );
file_grep ("$Self->{obj_dir}/simx.vcd", qr/ PARAM /); file_grep ("$Self->{obj_dir}/simx.vcd", qr/ PARAM /);
vcd_identical("$Self->{obj_dir}/simx.vcd", $Self->{golden_filename}); vcd_identical("$Self->{obj_dir}/simx.vcd", $Self->{golden_filename});

View File

@ -25,7 +25,7 @@ else {
if ($Self->{vlt_all}) { if ($Self->{vlt_all}) {
# Note more checks in _cc.pl # Note more checks in _cc.pl
file_grep ("$Self->{obj_dir}/simx.vcd", qr/\$enddefinitions/x); file_grep ("$Self->{obj_dir}/simx.vcd", qr/\$enddefinitions/x);
vcd_identical("$Self->{obj_dir}/simx.vcd", $Self->{golden_filename}); vcd_identical("$Self->{obj_dir}/simx.vcd", $Self->{golden_filename});
} }

View File

@ -33,13 +33,13 @@ int main(int argc, char **argv, char **env) {
tfp->open(STRINGIFY(TEST_OBJ_DIR) "/simx.vcd"); tfp->open(STRINGIFY(TEST_OBJ_DIR) "/simx.vcd");
while (main_time <= 20) { while (main_time <= 20) {
top->CLK = (main_time/dt_2)%2; top->CLK = (main_time/dt_2)%2;
top->eval(); top->eval();
top->t->glbl->setGSR(main_time < 7); top->t->glbl->setGSR(main_time < 7);
tfp->dump((unsigned int)(main_time)); tfp->dump((unsigned int)(main_time));
++main_time; ++main_time;
} }
tfp->close(); tfp->close();
top->final(); top->final();

View File

@ -33,13 +33,13 @@ int main(int argc, char **argv, char **env) {
tfp->open(STRINGIFY(TEST_OBJ_DIR) "/simx.vcd"); tfp->open(STRINGIFY(TEST_OBJ_DIR) "/simx.vcd");
while (main_time <= 20) { while (main_time <= 20) {
top->CLK = (main_time/dt_2)%2; top->CLK = (main_time/dt_2)%2;
top->eval(); top->eval();
top->t->glbl->GSR = (main_time < 7); top->t->glbl->GSR = (main_time < 7);
tfp->dump((unsigned int)(main_time)); tfp->dump((unsigned int)(main_time));
++main_time; ++main_time;
} }
tfp->close(); tfp->close();
top->final(); top->final();

View File

@ -36,11 +36,11 @@ int main(int argc, char **argv, char **env) {
while (main_time < 190*VL_TIME_MULTIPLIER) { while (main_time < 190*VL_TIME_MULTIPLIER) {
top->clk = !top->clk; top->clk = !top->clk;
top->eval(); top->eval();
tfp->dump((unsigned int)(main_time)); tfp->dump((unsigned int)(main_time));
// Advance by 0.5 time units, to make sure our fractional // Advance by 0.5 time units, to make sure our fractional
// time is working correctly // time is working correctly
main_time += VL_TIME_MULTIPLIER/2; main_time += VL_TIME_MULTIPLIER/2;
} }
tfp->close(); tfp->close();
top->final(); top->final();

View File

@ -21,16 +21,16 @@ bool check() {
#endif #endif
if(tb->W == c && tb->X == c && tb->Y == c && tb->Z == c) { if(tb->W == c && tb->X == c && tb->Y == c && tb->Z == c) {
pass = true; pass = true;
if (verbose) printf("- pass: "); if (verbose) printf("- pass: ");
} else { } else {
pass = false; pass = false;
verbose = true; verbose = true;
printf("%%E-FAIL: "); printf("%%E-FAIL: ");
} }
if (verbose) { if (verbose) {
printf("SEL=%d A=%d got: W=%d X=%d Y=%d Z=%d exp: WXYZ=%d\n", printf("SEL=%d A=%d got: W=%d X=%d Y=%d Z=%d exp: WXYZ=%d\n",
tb->SEL, tb->A, tb->W, tb->X, tb->Y, tb->Z, c); tb->SEL, tb->A, tb->W, tb->X, tb->Y, tb->Z, c);
} }
return pass; return pass;
} }
@ -43,19 +43,19 @@ int main() {
// loop through every possibility and check the result // loop through every possibility and check the result
for (tb->SEL=0; tb->SEL<2; tb->SEL++) { for (tb->SEL=0; tb->SEL<2; tb->SEL++) {
for (tb->A=0; tb->A<4; tb->A++) { for (tb->A=0; tb->A<4; tb->A++) {
tb->eval(); tb->eval();
if(!check()) { if(!check()) {
pass =false; pass =false;
} }
} }
} }
if(pass) { if(pass) {
VL_PRINTF("*-* All Finished *-*\n"); VL_PRINTF("*-* All Finished *-*\n");
tb->final(); tb->final();
} else { } else {
vl_fatal(__FILE__,__LINE__,"top", "Unexpected results from tristate test\n"); vl_fatal(__FILE__,__LINE__,"top", "Unexpected results from tristate test\n");
} }
return 0; return 0;
} }

View File

@ -15,17 +15,17 @@ bool check() {
bool pass; bool pass;
int Z; int Z;
if (tb->SEL) { if (tb->SEL) {
Z = tb->A; Z = tb->A;
} else { } else {
Z = tb->B; Z = tb->B;
} }
if (tb->Z == tb->Y1 && tb->Z == tb->Y2 && tb->Z == Z) { if (tb->Z == tb->Y1 && tb->Z == tb->Y2 && tb->Z == Z) {
printf("PASS: "); printf("PASS: ");
pass = true; pass = true;
} else { } else {
printf("FAIL: "); printf("FAIL: ");
pass = false; pass = false;
} }
#ifdef TEST_VERBOSE #ifdef TEST_VERBOSE
printf("SEL=%d A=%d B=%d Z=%d Y1=%d Y2=%d\n", tb->SEL, tb->A, tb->B, tb->Z, tb->Y1, tb->Y2); printf("SEL=%d A=%d B=%d Z=%d Y1=%d Y2=%d\n", tb->SEL, tb->A, tb->B, tb->Z, tb->Y1, tb->Y2);
@ -41,21 +41,21 @@ int main() {
// loop through every possibility and check the result // loop through every possibility and check the result
for (tb->SEL=0; tb->SEL<2; tb->SEL++) { for (tb->SEL=0; tb->SEL<2; tb->SEL++) {
for (tb->A=0; tb->A<2; tb->A++) { for (tb->A=0; tb->A<2; tb->A++) {
for (tb->B=0; tb->B<2; tb->B++) { for (tb->B=0; tb->B<2; tb->B++) {
tb->eval(); tb->eval();
if (!check()) { if (!check()) {
pass = false; pass = false;
} }
} }
} }
} }
if(pass) { if(pass) {
VL_PRINTF("*-* All Finished *-*\n"); VL_PRINTF("*-* All Finished *-*\n");
tb->final(); tb->final();
} else { } else {
vl_fatal(__FILE__,__LINE__,"top", "Unexpected results from inout test\n"); vl_fatal(__FILE__,__LINE__,"top", "Unexpected results from inout test\n");
} }
return 0; return 0;
} }

View File

@ -15,13 +15,13 @@ bool check() {
bool pass; bool pass;
int Z, Y, X; int Z, Y, X;
if (tb->OE) { if (tb->OE) {
Z = tb->A; Z = tb->A;
Y = tb->A; Y = tb->A;
X = tb->A; X = tb->A;
} else { } else {
Z = 1; Z = 1;
Y = 0; Y = 0;
X = 1; X = 1;
} }
#ifdef TEST_VERBOSE #ifdef TEST_VERBOSE
@ -31,12 +31,12 @@ bool check() {
#endif #endif
if (tb->Z == Z && tb->Y == Y && tb->X == X) { if (tb->Z == Z && tb->Y == Y && tb->X == X) {
if (verbose) printf("PASS: "); if (verbose) printf("PASS: ");
pass = true; pass = true;
} else { } else {
printf("%%E-FAIL: "); printf("%%E-FAIL: ");
verbose = true; verbose = true;
pass = false; pass = false;
} }
if (verbose) printf("OE=%d A=%d X=%d xexp=%d Y=%d yexp=%d Z=%d zexp=%d\n", tb->OE, tb->A, tb->X,X, tb->Y,Y, tb->Z,Z); if (verbose) printf("OE=%d A=%d X=%d xexp=%d Y=%d yexp=%d Z=%d zexp=%d\n", tb->OE, tb->A, tb->X,X, tb->Y,Y, tb->Z,Z);
return pass; return pass;
@ -50,19 +50,19 @@ int main() {
// loop through every possibility and check the result // loop through every possibility and check the result
for (tb->OE=0; tb->OE<2; tb->OE++) { for (tb->OE=0; tb->OE<2; tb->OE++) {
for (tb->A=0; tb->A<2; tb->A++) { for (tb->A=0; tb->A<2; tb->A++) {
tb->eval(); tb->eval();
if (!check()) { if (!check()) {
pass = false; pass = false;
} }
} }
} }
if (pass) { if (pass) {
VL_PRINTF("*-* All Finished *-*\n"); VL_PRINTF("*-* All Finished *-*\n");
tb->final(); tb->final();
} else { } else {
vl_fatal(__FILE__,__LINE__,"top", "Unexpected results from pullup test\n"); vl_fatal(__FILE__,__LINE__,"top", "Unexpected results from pullup test\n");
} }
return 0; return 0;
} }

View File

@ -17,24 +17,24 @@ bool check() {
#endif #endif
int Y = ((tb->OE1) & (!tb->OE2)) ? tb->A1 int Y = ((tb->OE1) & (!tb->OE2)) ? tb->A1
: ((!tb->OE1) & (tb->OE2)) ? tb->A2 : ((!tb->OE1) & (tb->OE2)) ? tb->A2
: ((tb->OE1) & (tb->OE2)) ? (tb->A1 | tb->A2) : ((tb->OE1) & (tb->OE2)) ? (tb->A1 | tb->A2)
: 3; // pullup : 3; // pullup
int W = (((tb->OE2) ? (tb->A2 & 0x1) : 0) << tb->A1) int W = (((tb->OE2) ? (tb->A2 & 0x1) : 0) << tb->A1)
| (((tb->OE1) ? (tb->A2 >> 1)&0x1 : 0) << tb->A2); | (((tb->OE1) ? (tb->A2 >> 1)&0x1 : 0) << tb->A2);
if(tb->Y1 == Y && tb->Y2 == Y && tb->Y3 == Y && tb->W == W) { if(tb->Y1 == Y && tb->Y2 == Y && tb->Y3 == Y && tb->W == W) {
pass = true; pass = true;
if (verbose) printf("- pass: "); if (verbose) printf("- pass: ");
} else { } else {
pass = false; pass = false;
verbose = true; verbose = true;
printf("%%E-Fail: "); printf("%%E-Fail: ");
} }
if (verbose) printf("Read: OE1=%d OE2=%d A1=0x%x A2=0x%x Y1=0x%x Y2=0x%x Y3=0x%x W=0x%x Expected: Y1=Y2=Y3=%d and W=0x%x\n", if (verbose) printf("Read: OE1=%d OE2=%d A1=0x%x A2=0x%x Y1=0x%x Y2=0x%x Y3=0x%x W=0x%x Expected: Y1=Y2=Y3=%d and W=0x%x\n",
tb->OE1, tb->OE2, tb->A1, tb->A2, tb->Y1, tb->Y2, tb->Y3, tb->W, Y,W); tb->OE1, tb->OE2, tb->A1, tb->A2, tb->Y1, tb->Y2, tb->Y3, tb->W, Y,W);
return pass; return pass;
} }
@ -46,23 +46,23 @@ int main() {
// loop through every possibility and check the result // loop through every possibility and check the result
for (tb->OE1=0; tb->OE1<2; tb->OE1++) { for (tb->OE1=0; tb->OE1<2; tb->OE1++) {
for (tb->OE2=0; tb->OE2<2; tb->OE2++) { for (tb->OE2=0; tb->OE2<2; tb->OE2++) {
for (tb->A1=0; tb->A1<4; tb->A1++) { for (tb->A1=0; tb->A1<4; tb->A1++) {
for (tb->A2=0; tb->A2<4; tb->A2++) { for (tb->A2=0; tb->A2<4; tb->A2++) {
tb->eval(); tb->eval();
if(!check()) { if(!check()) {
pass = false; pass = false;
} }
} }
} }
} }
} }
if(pass) { if(pass) {
VL_PRINTF("*-* All Finished *-*\n"); VL_PRINTF("*-* All Finished *-*\n");
tb->final(); tb->final();
} else { } else {
vl_fatal(__FILE__,__LINE__,"top", "Unexpected results from t_tri_select\n"); vl_fatal(__FILE__,__LINE__,"top", "Unexpected results from t_tri_select\n");
} }
return 0; return 0;
} }

View File

@ -35,7 +35,7 @@ int main(int argc, char **argv, char **env) {
topp->eval(); topp->eval();
main_time += 10; main_time += 10;
topp->clk = 0x2; // ILLEGAL topp->clk = 0x2; // ILLEGAL
topp->eval(); topp->eval();
topp->final(); topp->final();

View File

@ -53,37 +53,37 @@ unsigned int main_time = false;
#define CHECK_RESULT_VH(got, exp) \ #define CHECK_RESULT_VH(got, exp) \
if ((got) != (exp)) { \ if ((got) != (exp)) { \
printf("%%Error: %s:%d: GOT = %p EXP = %p\n", \ printf("%%Error: %s:%d: GOT = %p EXP = %p\n", \
FILENM,__LINE__, (got), (exp)); \ FILENM,__LINE__, (got), (exp)); \
return __LINE__; \ return __LINE__; \
} }
#define CHECK_RESULT_NZ(got) \ #define CHECK_RESULT_NZ(got) \
if (!(got)) { \ if (!(got)) { \
printf("%%Error: %s:%d: GOT = NULL EXP = !NULL\n", FILENM,__LINE__); \ printf("%%Error: %s:%d: GOT = NULL EXP = !NULL\n", FILENM,__LINE__); \
return __LINE__; \ return __LINE__; \
} }
// Use cout to avoid issues with %d/%lx etc // Use cout to avoid issues with %d/%lx etc
#define CHECK_RESULT(got, exp) \ #define CHECK_RESULT(got, exp) \
if ((got) != (exp)) { \ if ((got) != (exp)) { \
cout<<dec<<"%Error: "<<FILENM<<":"<<__LINE__ \ cout<<dec<<"%Error: "<<FILENM<<":"<<__LINE__ \
<<": GOT = "<<(got)<<" EXP = "<<(exp)<<endl; \ <<": GOT = "<<(got)<<" EXP = "<<(exp)<<endl; \
return __LINE__; \ return __LINE__; \
} }
#define CHECK_RESULT_HEX(got, exp) \ #define CHECK_RESULT_HEX(got, exp) \
if ((got) != (exp)) { \ if ((got) != (exp)) { \
cout<<dec<<"%Error: "<<FILENM<<":"<<__LINE__<<hex \ cout<<dec<<"%Error: "<<FILENM<<":"<<__LINE__<<hex \
<<": GOT = "<<(got)<<" EXP = "<<(exp)<<endl; \ <<": GOT = "<<(got)<<" EXP = "<<(exp)<<endl; \
return __LINE__; \ return __LINE__; \
} }
#define CHECK_RESULT_CSTR(got, exp) \ #define CHECK_RESULT_CSTR(got, exp) \
if (strcmp((got),(exp))) { \ if (strcmp((got),(exp))) { \
printf("%%Error: %s:%d: GOT = '%s' EXP = '%s'\n", \ printf("%%Error: %s:%d: GOT = '%s' EXP = '%s'\n", \
FILENM,__LINE__, (got)?(got):"<null>", (exp)?(exp):"<null>"); \ FILENM,__LINE__, (got)?(got):"<null>", (exp)?(exp):"<null>"); \
return __LINE__; \ return __LINE__; \
} }
#define CHECK_RESULT_CSTR_STRIP(got, exp) \ #define CHECK_RESULT_CSTR_STRIP(got, exp) \
@ -91,7 +91,7 @@ unsigned int main_time = false;
static int _mon_check_props(TestVpiHandle& handle, int size, int direction, int scalar, int type) { static int _mon_check_props(TestVpiHandle& handle, int size, int direction, int scalar, int type) {
s_vpi_value value = { s_vpi_value value = {
vpiIntVal, .value = {.integer = 0} vpiIntVal, .value = {.integer = 0}
}; };
// check size of object // check size of object
int vpisize = vpi_get(vpiSize, handle); int vpisize = vpi_get(vpiSize, handle);
@ -145,7 +145,7 @@ static int _mon_check_props(TestVpiHandle& handle, int size, int direction, int
CHECK_RESULT(vpitype, type); CHECK_RESULT(vpitype, type);
} }
return 0; // Ok return 0; // Ok
} }
struct params { struct params {
@ -201,7 +201,7 @@ int mon_check_props() {
int mon_check() { int mon_check() {
// Callback from initial block in monitor // Callback from initial block in monitor
if (int status = mon_check_props()) return status; if (int status = mon_check_props()) return status;
return 0; // Ok return 0; // Ok
} }
//====================================================================== //======================================================================
@ -267,17 +267,17 @@ int main(int argc, char **argv, char **env) {
main_time += 10; main_time += 10;
while (sc_time_stamp() < sim_time && !Verilated::gotFinish()) { while (sc_time_stamp() < sim_time && !Verilated::gotFinish()) {
main_time += 1; main_time += 1;
topp->eval(); topp->eval();
VerilatedVpi::callValueCbs(); VerilatedVpi::callValueCbs();
topp->clk = !topp->clk; topp->clk = !topp->clk;
//mon_do(); //mon_do();
#if VM_TRACE #if VM_TRACE
if (tfp) tfp->dump (main_time); if (tfp) tfp->dump (main_time);
#endif #endif
} }
if (!Verilated::gotFinish()) { if (!Verilated::gotFinish()) {
vl_fatal(FILENM,__LINE__,"main", "%Error: Timeout; never got a $finish"); vl_fatal(FILENM,__LINE__,"main", "%Error: Timeout; never got a $finish");
} }
topp->final(); topp->final();

View File

@ -53,37 +53,37 @@ unsigned int main_time = false;
#define CHECK_RESULT_VH(got, exp) \ #define CHECK_RESULT_VH(got, exp) \
if ((got) != (exp)) { \ if ((got) != (exp)) { \
printf("%%Error: %s:%d: GOT = %p EXP = %p\n", \ printf("%%Error: %s:%d: GOT = %p EXP = %p\n", \
FILENM,__LINE__, (got), (exp)); \ FILENM,__LINE__, (got), (exp)); \
return __LINE__; \ return __LINE__; \
} }
#define CHECK_RESULT_NZ(got) \ #define CHECK_RESULT_NZ(got) \
if (!(got)) { \ if (!(got)) { \
printf("%%Error: %s:%d: GOT = NULL EXP = !NULL\n", FILENM,__LINE__); \ printf("%%Error: %s:%d: GOT = NULL EXP = !NULL\n", FILENM,__LINE__); \
return __LINE__; \ return __LINE__; \
} }
// Use cout to avoid issues with %d/%lx etc // Use cout to avoid issues with %d/%lx etc
#define CHECK_RESULT(got, exp) \ #define CHECK_RESULT(got, exp) \
if ((got) != (exp)) { \ if ((got) != (exp)) { \
cout<<dec<<"%Error: "<<FILENM<<":"<<__LINE__ \ cout<<dec<<"%Error: "<<FILENM<<":"<<__LINE__ \
<<": GOT = "<<(got)<<" EXP = "<<(exp)<<endl; \ <<": GOT = "<<(got)<<" EXP = "<<(exp)<<endl; \
return __LINE__; \ return __LINE__; \
} }
#define CHECK_RESULT_HEX(got, exp) \ #define CHECK_RESULT_HEX(got, exp) \
if ((got) != (exp)) { \ if ((got) != (exp)) { \
cout<<dec<<"%Error: "<<FILENM<<":"<<__LINE__<<hex \ cout<<dec<<"%Error: "<<FILENM<<":"<<__LINE__<<hex \
<<": GOT = "<<(got)<<" EXP = "<<(exp)<<endl; \ <<": GOT = "<<(got)<<" EXP = "<<(exp)<<endl; \
return __LINE__; \ return __LINE__; \
} }
#define CHECK_RESULT_CSTR(got, exp) \ #define CHECK_RESULT_CSTR(got, exp) \
if (strcmp((got),(exp))) { \ if (strcmp((got),(exp))) { \
printf("%%Error: %s:%d: GOT = '%s' EXP = '%s'\n", \ printf("%%Error: %s:%d: GOT = '%s' EXP = '%s'\n", \
FILENM,__LINE__, (got)?(got):"<null>", (exp)?(exp):"<null>"); \ FILENM,__LINE__, (got)?(got):"<null>", (exp)?(exp):"<null>"); \
return __LINE__; \ return __LINE__; \
} }
#define CHECK_RESULT_CSTR_STRIP(got, exp) \ #define CHECK_RESULT_CSTR_STRIP(got, exp) \
@ -92,7 +92,7 @@ unsigned int main_time = false;
int _mon_check_range(TestVpiHandle& handle, int size, int left, int right) { int _mon_check_range(TestVpiHandle& handle, int size, int left, int right) {
TestVpiHandle iter_h, left_h, right_h; TestVpiHandle iter_h, left_h, right_h;
s_vpi_value value = { s_vpi_value value = {
vpiIntVal, .value = {.integer = 0} vpiIntVal, .value = {.integer = 0}
}; };
// check size of object // check size of object
int vpisize = vpi_get(vpiSize, handle); int vpisize = vpi_get(vpiSize, handle);
@ -115,15 +115,15 @@ int _mon_check_range(TestVpiHandle& handle, int size, int left, int right) {
// calculate size & check // calculate size & check
coherency = abs(coherency) + 1; coherency = abs(coherency) + 1;
CHECK_RESULT(coherency, size); CHECK_RESULT(coherency, size);
return 0; // Ok return 0; // Ok
} }
int _mon_check_memory() { int _mon_check_memory() {
int cnt; int cnt;
TestVpiHandle mem_h, lcl_h; TestVpiHandle mem_h, lcl_h;
vpiHandle iter_h; // icarus does not like auto free of iterator handles vpiHandle iter_h; // Icarus does not like auto free of iterator handles
s_vpi_value value = { s_vpi_value value = {
vpiIntVal, .value = {.integer = 0} vpiIntVal, .value = {.integer = 0}
}; };
vpi_printf((PLI_BYTE8*)"Check memory vpi ...\n"); vpi_printf((PLI_BYTE8*)"Check memory vpi ...\n");
mem_h = vpi_handle_by_name((PLI_BYTE8*)TestSimulator::rooted("mem0"), NULL); mem_h = vpi_handle_by_name((PLI_BYTE8*)TestSimulator::rooted("mem0"), NULL);
@ -136,12 +136,12 @@ int _mon_check_memory() {
iter_h = vpi_iterate(vpiMemoryWord, mem_h); iter_h = vpi_iterate(vpiMemoryWord, mem_h);
cnt = 0; cnt = 0;
while ((lcl_h = vpi_scan(iter_h))) { while ((lcl_h = vpi_scan(iter_h))) {
value.value.integer = ++cnt; value.value.integer = ++cnt;
vpi_put_value(lcl_h, &value, NULL, vpiNoDelay); vpi_put_value(lcl_h, &value, NULL, vpiNoDelay);
// check size and range // check size and range
if (int status = _mon_check_range(lcl_h, 32, 31, 0)) return status; if (int status = _mon_check_range(lcl_h, 32, 31, 0)) return status;
} }
CHECK_RESULT(cnt, 16); // should be 16 addresses CHECK_RESULT(cnt, 16); // should be 16 addresses
// iterate and accumulate // iterate and accumulate
iter_h = vpi_iterate(vpiMemoryWord, mem_h); iter_h = vpi_iterate(vpiMemoryWord, mem_h);
cnt = 0; cnt = 0;
@ -150,12 +150,12 @@ int _mon_check_memory() {
vpi_get_value(lcl_h, &value); vpi_get_value(lcl_h, &value);
CHECK_RESULT(value.value.integer, cnt); CHECK_RESULT(value.value.integer, cnt);
} }
CHECK_RESULT(cnt, 16); // should be 16 addresses CHECK_RESULT(cnt, 16); // should be 16 addresses
// don't care for non verilator // don't care for non verilator
// (crashes on Icarus) // (crashes on Icarus)
if (TestSimulator::is_icarus()) { if (TestSimulator::is_icarus()) {
vpi_printf((PLI_BYTE8*)"Skipping property checks for simulator %s\n", TestSimulator::get_info().product); vpi_printf((PLI_BYTE8*)"Skipping property checks for simulator %s\n", TestSimulator::get_info().product);
return 0; // Ok return 0; // Ok
} }
// make sure trying to get properties that don't exist // make sure trying to get properties that don't exist
// doesn't crash // doesn't crash
@ -169,13 +169,13 @@ int _mon_check_memory() {
CHECK_RESULT(should_be_NULL, 0); CHECK_RESULT(should_be_NULL, 0);
should_be_NULL = vpi_handle(vpiScope, iter_h); should_be_NULL = vpi_handle(vpiScope, iter_h);
CHECK_RESULT(should_be_NULL, 0); CHECK_RESULT(should_be_NULL, 0);
return 0; // Ok return 0; // Ok
} }
int mon_check() { int mon_check() {
// Callback from initial block in monitor // Callback from initial block in monitor
if (int status = _mon_check_memory()) return status; if (int status = _mon_check_memory()) return status;
return 0; // Ok return 0; // Ok
} }
//====================================================================== //======================================================================
@ -220,7 +220,8 @@ int main(int argc, char **argv, char **env) {
double sim_time = 1100; double sim_time = 1100;
Verilated::commandArgs(argc, argv); Verilated::commandArgs(argc, argv);
Verilated::debug(0); Verilated::debug(0);
Verilated::fatalOnVpiError(0); // we're going to be checking for these errors do don't crash out // we're going to be checking for these errors do don't crash out
Verilated::fatalOnVpiError(0);
VM_PREFIX* topp = new VM_PREFIX(""); // Note null name - we're flattening it out VM_PREFIX* topp = new VM_PREFIX(""); // Note null name - we're flattening it out
@ -243,17 +244,17 @@ int main(int argc, char **argv, char **env) {
main_time += 10; main_time += 10;
while (sc_time_stamp() < sim_time && !Verilated::gotFinish()) { while (sc_time_stamp() < sim_time && !Verilated::gotFinish()) {
main_time += 1; main_time += 1;
topp->eval(); topp->eval();
VerilatedVpi::callValueCbs(); VerilatedVpi::callValueCbs();
topp->clk = !topp->clk; topp->clk = !topp->clk;
//mon_do(); //mon_do();
#if VM_TRACE #if VM_TRACE
if (tfp) tfp->dump (main_time); if (tfp) tfp->dump (main_time);
#endif #endif
} }
if (!Verilated::gotFinish()) { if (!Verilated::gotFinish()) {
vl_fatal(FILENM,__LINE__,"main", "%Error: Timeout; never got a $finish"); vl_fatal(FILENM,__LINE__,"main", "%Error: Timeout; never got a $finish");
} }
topp->final(); topp->final();
@ -266,4 +267,3 @@ int main(int argc, char **argv, char **env) {
} }
#endif #endif

View File

@ -41,37 +41,37 @@ unsigned int callback_count = false;
#define CHECK_RESULT_VH(got, exp) \ #define CHECK_RESULT_VH(got, exp) \
if ((got) != (exp)) { \ if ((got) != (exp)) { \
printf("%%Error: %s:%d: GOT = %p EXP = %p\n", \ printf("%%Error: %s:%d: GOT = %p EXP = %p\n", \
FILENM,__LINE__, (got), (exp)); \ FILENM,__LINE__, (got), (exp)); \
return __LINE__; \ return __LINE__; \
} }
#define CHECK_RESULT_NZ(got) \ #define CHECK_RESULT_NZ(got) \
if (!(got)) { \ if (!(got)) { \
printf("%%Error: %s:%d: GOT = NULL EXP = !NULL\n", FILENM,__LINE__); \ printf("%%Error: %s:%d: GOT = NULL EXP = !NULL\n", FILENM,__LINE__); \
return __LINE__; \ return __LINE__; \
} }
// Use cout to avoid issues with %d/%lx etc // Use cout to avoid issues with %d/%lx etc
#define CHECK_RESULT(got, exp) \ #define CHECK_RESULT(got, exp) \
if ((got) != (exp)) { \ if ((got) != (exp)) { \
std::cout<<std::dec<<"%Error: "<<FILENM<<":"<<__LINE__ \ std::cout<<std::dec<<"%Error: "<<FILENM<<":"<<__LINE__ \
<<": GOT = "<<(got)<<" EXP = "<<(exp)<<std::endl; \ <<": GOT = "<<(got)<<" EXP = "<<(exp)<<std::endl; \
return __LINE__; \ return __LINE__; \
} }
#define CHECK_RESULT_HEX(got, exp) \ #define CHECK_RESULT_HEX(got, exp) \
if ((got) != (exp)) { \ if ((got) != (exp)) { \
std::cout<<std::dec<<"%Error: "<<FILENM<<":"<<__LINE__<<std::hex \ std::cout<<std::dec<<"%Error: "<<FILENM<<":"<<__LINE__<<std::hex \
<<": GOT = "<<(got)<<" EXP = "<<(exp)<<std::endl; \ <<": GOT = "<<(got)<<" EXP = "<<(exp)<<std::endl; \
return __LINE__; \ return __LINE__; \
} }
#define CHECK_RESULT_CSTR(got, exp) \ #define CHECK_RESULT_CSTR(got, exp) \
if (strcmp((got),(exp))) { \ if (strcmp((got),(exp))) { \
printf("%%Error: %s:%d: GOT = '%s' EXP = '%s'\n", \ printf("%%Error: %s:%d: GOT = '%s' EXP = '%s'\n", \
FILENM,__LINE__, (got)?(got):"<null>", (exp)?(exp):"<null>"); \ FILENM,__LINE__, (got)?(got):"<null>", (exp)?(exp):"<null>"); \
return __LINE__; \ return __LINE__; \
} }
#define CHECK_RESULT_CSTR_STRIP(got, exp) \ #define CHECK_RESULT_CSTR_STRIP(got, exp) \
@ -80,28 +80,28 @@ unsigned int callback_count = false;
int _mon_check_unimpl(p_cb_data cb_data) { int _mon_check_unimpl(p_cb_data cb_data) {
static TestVpiHandle cb, clk_h; static TestVpiHandle cb, clk_h;
if (cb_data) { if (cb_data) {
// this is the callback // this is the callback
s_vpi_error_info info; s_vpi_error_info info;
vpi_chk_error(&info); vpi_chk_error(&info);
callback_count++; callback_count++;
printf("%%Info: got pli message %s\n", info.message); printf("%%Info: got pli message %s\n", info.message);
} else { } else {
// setup and install // setup and install
static t_cb_data cb_data; static t_cb_data cb_data;
clk_h = vpi_handle_by_name((PLI_BYTE8*)"t.clk", NULL); clk_h = vpi_handle_by_name((PLI_BYTE8*)"t.clk", NULL);
cb_data.reason = cbPLIError; cb_data.reason = cbPLIError;
cb_data.cb_rtn = _mon_check_unimpl; // this function cb_data.cb_rtn = _mon_check_unimpl; // this function
cb = vpi_register_cb(&cb_data); cb = vpi_register_cb(&cb_data);
CHECK_RESULT_NZ(cb); CHECK_RESULT_NZ(cb);
// now exercise unimplemented fns // now exercise unimplemented fns
vpi_get_cb_info(cb, NULL); vpi_get_cb_info(cb, NULL);
CHECK_RESULT(callback_count, 1); CHECK_RESULT(callback_count, 1);
vpi_register_systf(NULL); vpi_register_systf(NULL);
CHECK_RESULT(callback_count, 2); CHECK_RESULT(callback_count, 2);
vpi_get_systf_info(NULL, NULL); vpi_get_systf_info(NULL, NULL);
CHECK_RESULT(callback_count, 3); CHECK_RESULT(callback_count, 3);
vpi_handle_multi(0, NULL, NULL); vpi_handle_multi(0, NULL, NULL);
CHECK_RESULT(callback_count, 4); CHECK_RESULT(callback_count, 4);
@ -111,34 +111,34 @@ int _mon_check_unimpl(p_cb_data cb_data) {
CHECK_RESULT(callback_count, 6); CHECK_RESULT(callback_count, 6);
vpi_put_delays(NULL, NULL); vpi_put_delays(NULL, NULL);
CHECK_RESULT(callback_count, 7); CHECK_RESULT(callback_count, 7);
vpi_get_value_array(NULL, NULL, NULL, 0); vpi_get_value_array(NULL, NULL, NULL, 0);
CHECK_RESULT(callback_count, 8); CHECK_RESULT(callback_count, 8);
vpi_put_value_array(NULL, NULL, NULL, 0); vpi_put_value_array(NULL, NULL, NULL, 0);
CHECK_RESULT(callback_count, 9); CHECK_RESULT(callback_count, 9);
vpi_get_time(NULL, NULL); vpi_get_time(NULL, NULL);
CHECK_RESULT(callback_count, 10); CHECK_RESULT(callback_count, 10);
vpi_mcd_name(0); vpi_mcd_name(0);
CHECK_RESULT(callback_count, 11); CHECK_RESULT(callback_count, 11);
vpi_compare_objects(NULL, NULL); vpi_compare_objects(NULL, NULL);
CHECK_RESULT(callback_count, 12); CHECK_RESULT(callback_count, 12);
vpi_get_data(0, NULL, 0); vpi_get_data(0, NULL, 0);
CHECK_RESULT(callback_count, 13); CHECK_RESULT(callback_count, 13);
vpi_put_data(0, NULL, 0); vpi_put_data(0, NULL, 0);
CHECK_RESULT(callback_count, 14); CHECK_RESULT(callback_count, 14);
vpi_get_userdata(NULL); vpi_get_userdata(NULL);
CHECK_RESULT(callback_count, 15); CHECK_RESULT(callback_count, 15);
vpi_put_userdata(NULL, NULL); vpi_put_userdata(NULL, NULL);
CHECK_RESULT(callback_count, 16); CHECK_RESULT(callback_count, 16);
vpi_handle_by_multi_index(NULL, 0, NULL); vpi_handle_by_multi_index(NULL, 0, NULL);
CHECK_RESULT(callback_count, 17); CHECK_RESULT(callback_count, 17);
} }
return 0; // Ok return 0; // Ok
} }
int mon_check() { int mon_check() {
// Callback from initial block in monitor // Callback from initial block in monitor
if (int status = _mon_check_unimpl(NULL)) return status; if (int status = _mon_check_unimpl(NULL)) return status;
return 0; // Ok return 0; // Ok
} }
//====================================================================== //======================================================================
@ -151,7 +151,8 @@ int main(int argc, char **argv, char **env) {
double sim_time = 1100; double sim_time = 1100;
Verilated::commandArgs(argc, argv); Verilated::commandArgs(argc, argv);
Verilated::debug(0); Verilated::debug(0);
Verilated::fatalOnVpiError(0); // we're going to be checking for these errors do don't crash out // we're going to be checking for these errors do don't crash out
Verilated::fatalOnVpiError(0);
VM_PREFIX* topp = new VM_PREFIX(""); // Note null name - we're flattening it out VM_PREFIX* topp = new VM_PREFIX(""); // Note null name - we're flattening it out
@ -174,18 +175,18 @@ int main(int argc, char **argv, char **env) {
main_time += 10; main_time += 10;
while (sc_time_stamp() < sim_time && !Verilated::gotFinish()) { while (sc_time_stamp() < sim_time && !Verilated::gotFinish()) {
main_time += 1; main_time += 1;
topp->eval(); topp->eval();
//VerilatedVpi::callValueCbs(); // Make sure can link without verilated_vpi.h included //VerilatedVpi::callValueCbs(); // Make sure can link without verilated_vpi.h included
topp->clk = !topp->clk; topp->clk = !topp->clk;
//mon_do(); //mon_do();
#if VM_TRACE #if VM_TRACE
if (tfp) tfp->dump (main_time); if (tfp) tfp->dump (main_time);
#endif #endif
} }
CHECK_RESULT(callback_count, 17); CHECK_RESULT(callback_count, 17);
if (!Verilated::gotFinish()) { if (!Verilated::gotFinish()) {
vl_fatal(FILENM,__LINE__,"main", "%Error: Timeout; never got a $finish"); vl_fatal(FILENM,__LINE__,"main", "%Error: Timeout; never got a $finish");
} }
topp->final(); topp->final();

View File

@ -55,37 +55,37 @@ unsigned int callback_count_strs_max = 500;
#define CHECK_RESULT_VH(got, exp) \ #define CHECK_RESULT_VH(got, exp) \
if ((got) != (exp)) { \ if ((got) != (exp)) { \
printf("%%Error: %s:%d: GOT = %p EXP = %p\n", \ printf("%%Error: %s:%d: GOT = %p EXP = %p\n", \
FILENM,__LINE__, (got), (exp)); \ FILENM,__LINE__, (got), (exp)); \
return __LINE__; \ return __LINE__; \
} }
#define CHECK_RESULT_NZ(got) \ #define CHECK_RESULT_NZ(got) \
if (!(got)) { \ if (!(got)) { \
printf("%%Error: %s:%d: GOT = NULL EXP = !NULL\n", FILENM,__LINE__); \ printf("%%Error: %s:%d: GOT = NULL EXP = !NULL\n", FILENM,__LINE__); \
return __LINE__; \ return __LINE__; \
} }
// Use cout to avoid issues with %d/%lx etc // Use cout to avoid issues with %d/%lx etc
#define CHECK_RESULT(got, exp) \ #define CHECK_RESULT(got, exp) \
if ((got) != (exp)) { \ if ((got) != (exp)) { \
cout<<dec<<"%Error: "<<FILENM<<":"<<__LINE__ \ cout<<dec<<"%Error: "<<FILENM<<":"<<__LINE__ \
<<": GOT = "<<(got)<<" EXP = "<<(exp)<<endl; \ <<": GOT = "<<(got)<<" EXP = "<<(exp)<<endl; \
return __LINE__; \ return __LINE__; \
} }
#define CHECK_RESULT_HEX(got, exp) \ #define CHECK_RESULT_HEX(got, exp) \
if ((got) != (exp)) { \ if ((got) != (exp)) { \
cout<<dec<<"%Error: "<<FILENM<<":"<<__LINE__<<hex \ cout<<dec<<"%Error: "<<FILENM<<":"<<__LINE__<<hex \
<<": GOT = "<<(got)<<" EXP = "<<(exp)<<endl; \ <<": GOT = "<<(got)<<" EXP = "<<(exp)<<endl; \
return __LINE__; \ return __LINE__; \
} }
#define CHECK_RESULT_CSTR(got, exp) \ #define CHECK_RESULT_CSTR(got, exp) \
if (strcmp((got),(exp))) { \ if (strcmp((got),(exp))) { \
printf("%%Error: %s:%d: GOT = '%s' EXP = '%s'\n", \ printf("%%Error: %s:%d: GOT = '%s' EXP = '%s'\n", \
FILENM,__LINE__, (got)?(got):"<null>", (exp)?(exp):"<null>"); \ FILENM,__LINE__, (got)?(got):"<null>", (exp)?(exp):"<null>"); \
return __LINE__; \ return __LINE__; \
} }
#define CHECK_RESULT_CSTR_STRIP(got, exp) \ #define CHECK_RESULT_CSTR_STRIP(got, exp) \
@ -103,9 +103,9 @@ int _mon_check_mcd() {
CHECK_RESULT_NZ(mcd); CHECK_RESULT_NZ(mcd);
{ // Check it got written { // Check it got written
FILE* fp = fopen(filename,"r"); FILE* fp = fopen(filename,"r");
CHECK_RESULT_NZ(fp); CHECK_RESULT_NZ(fp);
fclose(fp); fclose(fp);
} }
status = vpi_mcd_printf(mcd, (PLI_BYTE8*)"hello %s", "vpi_mcd_printf"); status = vpi_mcd_printf(mcd, (PLI_BYTE8*)"hello %s", "vpi_mcd_printf");
@ -167,8 +167,8 @@ int _value_callback_half(p_cb_data cb_data) {
int _value_callback_quad(p_cb_data cb_data) { int _value_callback_quad(p_cb_data cb_data) {
for (int index=0;index<2;index++) { for (int index=0;index<2;index++) {
CHECK_RESULT_HEX(cb_data->value->value.vector[1].aval, (unsigned long)((index==2)?0x1c77bb9bUL:0x12819213UL)); CHECK_RESULT_HEX(cb_data->value->value.vector[1].aval, (unsigned long)((index==2)?0x1c77bb9bUL:0x12819213UL));
CHECK_RESULT_HEX(cb_data->value->value.vector[0].aval, (unsigned long)((index==2)?0x3784ea09UL:0xabd31a1cUL)); CHECK_RESULT_HEX(cb_data->value->value.vector[0].aval, (unsigned long)((index==2)?0x3784ea09UL:0xabd31a1cUL));
} }
callback_count_quad++; callback_count_quad++;
return 0; return 0;
@ -264,30 +264,30 @@ int _mon_check_var() {
t_vpi_value tmpValue; t_vpi_value tmpValue;
tmpValue.format = vpiIntVal; tmpValue.format = vpiIntVal;
{ {
TestVpiHandle vh10 = vpi_handle(vpiLeftRange, vh4); TestVpiHandle vh10 = vpi_handle(vpiLeftRange, vh4);
CHECK_RESULT_NZ(vh10); CHECK_RESULT_NZ(vh10);
vpi_get_value(vh10, &tmpValue); vpi_get_value(vh10, &tmpValue);
CHECK_RESULT(tmpValue.value.integer,4); CHECK_RESULT(tmpValue.value.integer,4);
} }
{ {
TestVpiHandle vh10 = vpi_handle(vpiRightRange, vh4); TestVpiHandle vh10 = vpi_handle(vpiRightRange, vh4);
CHECK_RESULT_NZ(vh10); CHECK_RESULT_NZ(vh10);
vpi_get_value(vh10, &tmpValue); vpi_get_value(vh10, &tmpValue);
CHECK_RESULT(tmpValue.value.integer,3); CHECK_RESULT(tmpValue.value.integer,3);
} }
{ {
TestVpiHandle vh10 = vpi_iterate(vpiMemoryWord, vh4); TestVpiHandle vh10 = vpi_iterate(vpiMemoryWord, vh4);
CHECK_RESULT_NZ(vh10); CHECK_RESULT_NZ(vh10);
TestVpiHandle vh11 = vpi_scan(vh10); TestVpiHandle vh11 = vpi_scan(vh10);
CHECK_RESULT_NZ(vh11); CHECK_RESULT_NZ(vh11);
TestVpiHandle vh12 = vpi_handle(vpiLeftRange, vh11); TestVpiHandle vh12 = vpi_handle(vpiLeftRange, vh11);
CHECK_RESULT_NZ(vh12); CHECK_RESULT_NZ(vh12);
vpi_get_value(vh12, &tmpValue); vpi_get_value(vh12, &tmpValue);
CHECK_RESULT(tmpValue.value.integer,2); CHECK_RESULT(tmpValue.value.integer,2);
TestVpiHandle vh13 = vpi_handle(vpiRightRange, vh11); TestVpiHandle vh13 = vpi_handle(vpiRightRange, vh11);
CHECK_RESULT_NZ(vh13); CHECK_RESULT_NZ(vh13);
vpi_get_value(vh13, &tmpValue); vpi_get_value(vh13, &tmpValue);
CHECK_RESULT(tmpValue.value.integer,1); CHECK_RESULT(tmpValue.value.integer,1);
} }
return 0; return 0;
@ -382,12 +382,12 @@ int _mon_check_quad() {
int _mon_check_string() { int _mon_check_string() {
static struct { static struct {
const char *name; const char *name;
const char *initial; const char *initial;
const char *value; const char *value;
} text_test_obs[] = { } text_test_obs[] = {
{"text_byte", "B", "xxA"}, // x's dropped {"text_byte", "B", "xxA"}, // x's dropped
{"text_half", "Hf", "xxT2"}, // x's dropped {"text_half", "Hf", "xxT2"}, // x's dropped
{"text_word", "Word", "Tree"}, {"text_word", "Word", "Tree"},
{"text_long", "Long64b", "44Four44"}, {"text_long", "Long64b", "44Four44"},
{"text" , "Verilog Test module", "lorem ipsum"}, {"text" , "Verilog Test module", "lorem ipsum"},
@ -404,7 +404,7 @@ int _mon_check_string() {
v.format = vpiStringVal; v.format = vpiStringVal;
vpi_get_value(vh1, &v); vpi_get_value(vh1, &v);
if (vpi_chk_error(&e)) { if (vpi_chk_error(&e)) {
printf("%%vpi_chk_error : %s\n", e.message); printf("%%vpi_chk_error : %s\n", e.message);
} }
CHECK_RESULT_CSTR_STRIP(v.value.str, text_test_obs[i].initial); CHECK_RESULT_CSTR_STRIP(v.value.str, text_test_obs[i].initial);
@ -419,43 +419,43 @@ int _mon_check_string() {
int _mon_check_putget_str(p_cb_data cb_data) { int _mon_check_putget_str(p_cb_data cb_data) {
static TestVpiHandle cb; static TestVpiHandle cb;
static struct { static struct {
TestVpiHandle scope, sig, rfr, check, verbose; TestVpiHandle scope, sig, rfr, check, verbose;
char str[128+1]; // char per bit plus null terminator char str[128+1]; // char per bit plus null terminator
int type; // value type in .str int type; // value type in .str
union { union {
PLI_INT32 integer; PLI_INT32 integer;
s_vpi_vecval vector[4]; s_vpi_vecval vector[4];
} value; // reference } value; // reference
} data[129]; } data[129];
if (cb_data) { if (cb_data) {
// this is the callback // this is the callback
static unsigned int seed = 1; static unsigned int seed = 1;
s_vpi_time t; s_vpi_time t;
t.type = vpiSimTime; t.type = vpiSimTime;
t.high = 0; t.high = 0;
t.low = 0; t.low = 0;
for (int i=2; i<=128; i++) { for (int i=2; i<=128; i++) {
static s_vpi_value v; static s_vpi_value v;
int words = (i+31)>>5; int words = (i+31)>>5;
TEST_MSG("========== %d ==========\n", i); TEST_MSG("========== %d ==========\n", i);
if (callback_count_strs) { if (callback_count_strs) {
// check persistance // check persistance
if (data[i].type) { if (data[i].type) {
v.format = data[i].type; v.format = data[i].type;
} else { } else {
static PLI_INT32 vals[] = {vpiBinStrVal, vpiOctStrVal, vpiHexStrVal, vpiDecStrVal}; static PLI_INT32 vals[] = {vpiBinStrVal, vpiOctStrVal, vpiHexStrVal, vpiDecStrVal};
v.format = vals[rand_r(&seed) % ((words>2)?3:4)]; v.format = vals[rand_r(&seed) % ((words>2)?3:4)];
TEST_MSG("new format %d\n", v.format); TEST_MSG("new format %d\n", v.format);
} }
vpi_get_value(data[i].sig, &v); vpi_get_value(data[i].sig, &v);
TEST_MSG("%s\n", v.value.str); TEST_MSG("%s\n", v.value.str);
if (data[i].type) { if (data[i].type) {
CHECK_RESULT_CSTR(v.value.str, data[i].str); CHECK_RESULT_CSTR(v.value.str, data[i].str);
} else { } else {
data[i].type = v.format; data[i].type = v.format;
strcpy(data[i].str, v.value.str); strcpy(data[i].str, v.value.str);
} }
} }
// check for corruption // check for corruption
v.format = (words==1)?vpiIntVal:vpiVectorVal; v.format = (words==1)?vpiIntVal:vpiVectorVal;
@ -463,12 +463,12 @@ int _mon_check_putget_str(p_cb_data cb_data) {
if (v.format == vpiIntVal) { if (v.format == vpiIntVal) {
TEST_MSG("%08x %08x\n", v.value.integer, data[i].value.integer); TEST_MSG("%08x %08x\n", v.value.integer, data[i].value.integer);
CHECK_RESULT(v.value.integer, data[i].value.integer); CHECK_RESULT(v.value.integer, data[i].value.integer);
} else { } else {
for (int k=0; k < words; k++) { for (int k=0; k < words; k++) {
TEST_MSG("%d %08x %08x\n", k, v.value.vector[k].aval, data[i].value.vector[k].aval); TEST_MSG("%d %08x %08x\n", k, v.value.vector[k].aval, data[i].value.vector[k].aval);
CHECK_RESULT_HEX(v.value.vector[k].aval, data[i].value.vector[k].aval); CHECK_RESULT_HEX(v.value.vector[k].aval, data[i].value.vector[k].aval);
} }
} }
if (callback_count_strs & 7) { if (callback_count_strs & 7) {
// put same value back - checking encoding/decoding equivalent // put same value back - checking encoding/decoding equivalent
@ -479,53 +479,53 @@ int _mon_check_putget_str(p_cb_data cb_data) {
v.value.integer = 1; v.value.integer = 1;
//vpi_put_value(data[i].verbose, &v, &t, vpiNoDelay); //vpi_put_value(data[i].verbose, &v, &t, vpiNoDelay);
vpi_put_value(data[i].check, &v, &t, vpiNoDelay); vpi_put_value(data[i].check, &v, &t, vpiNoDelay);
} else { } else {
// stick a new random value in // stick a new random value in
unsigned int mask = ((i&31)?(1<<(i&31)):0)-1; unsigned int mask = ((i&31)?(1<<(i&31)):0)-1;
if (words == 1) { if (words == 1) {
v.value.integer = rand_r(&seed); v.value.integer = rand_r(&seed);
data[i].value.integer = v.value.integer &= mask; data[i].value.integer = v.value.integer &= mask;
v.format = vpiIntVal; v.format = vpiIntVal;
TEST_MSG("new value %08x\n", data[i].value.integer); TEST_MSG("new value %08x\n", data[i].value.integer);
} else { } else {
TEST_MSG("new value\n"); TEST_MSG("new value\n");
for (int j=0; j<4; j++) { for (int j=0; j<4; j++) {
data[i].value.vector[j].aval = rand_r(&seed); data[i].value.vector[j].aval = rand_r(&seed);
if (j==(words-1)) { if (j==(words-1)) {
data[i].value.vector[j].aval &= mask; data[i].value.vector[j].aval &= mask;
} }
TEST_MSG(" %08x\n", data[i].value.vector[j].aval); TEST_MSG(" %08x\n", data[i].value.vector[j].aval);
} }
v.value.vector = data[i].value.vector; v.value.vector = data[i].value.vector;
v.format = vpiVectorVal; v.format = vpiVectorVal;
} }
vpi_put_value(data[i].sig, &v, &t, vpiNoDelay); vpi_put_value(data[i].sig, &v, &t, vpiNoDelay);
vpi_put_value(data[i].rfr, &v, &t, vpiNoDelay); vpi_put_value(data[i].rfr, &v, &t, vpiNoDelay);
} }
if ((callback_count_strs & 1) == 0) data[i].type = 0; if ((callback_count_strs & 1) == 0) data[i].type = 0;
} }
if (++callback_count_strs == callback_count_strs_max) { if (++callback_count_strs == callback_count_strs_max) {
int success = vpi_remove_cb(cb); int success = vpi_remove_cb(cb);
CHECK_RESULT_NZ(success); CHECK_RESULT_NZ(success);
}; };
} else { } else {
// setup and install // setup and install
for (int i=1; i<=128; i++) { for (int i=1; i<=128; i++) {
char buf[32]; char buf[32];
snprintf(buf, sizeof(buf), TestSimulator::rooted("arr[%d].arr"), i); snprintf(buf, sizeof(buf), TestSimulator::rooted("arr[%d].arr"), i);
CHECK_RESULT_NZ(data[i].scope = vpi_handle_by_name((PLI_BYTE8*)buf, NULL)); CHECK_RESULT_NZ(data[i].scope = vpi_handle_by_name((PLI_BYTE8*)buf, NULL));
CHECK_RESULT_NZ(data[i].sig = vpi_handle_by_name((PLI_BYTE8*)"sig", data[i].scope)); CHECK_RESULT_NZ(data[i].sig = vpi_handle_by_name((PLI_BYTE8*)"sig", data[i].scope));
CHECK_RESULT_NZ(data[i].rfr = vpi_handle_by_name((PLI_BYTE8*)"rfr", data[i].scope)); CHECK_RESULT_NZ(data[i].rfr = vpi_handle_by_name((PLI_BYTE8*)"rfr", data[i].scope));
CHECK_RESULT_NZ(data[i].check = vpi_handle_by_name((PLI_BYTE8*)"check", data[i].scope)); CHECK_RESULT_NZ(data[i].check = vpi_handle_by_name((PLI_BYTE8*)"check", data[i].scope));
CHECK_RESULT_NZ(data[i].verbose = vpi_handle_by_name((PLI_BYTE8*)"verbose", data[i].scope)); CHECK_RESULT_NZ(data[i].verbose = vpi_handle_by_name((PLI_BYTE8*)"verbose", data[i].scope));
} }
static t_cb_data cb_data; static t_cb_data cb_data;
static s_vpi_value v; static s_vpi_value v;
static TestVpiHandle count_h = VPI_HANDLE("count"); static TestVpiHandle count_h = VPI_HANDLE("count");
cb_data.reason = cbValueChange; cb_data.reason = cbValueChange;
cb_data.cb_rtn = _mon_check_putget_str; // this function cb_data.cb_rtn = _mon_check_putget_str; // this function
cb_data.obj = count_h; cb_data.obj = count_h;
cb_data.value = &v; cb_data.value = &v;
cb_data.time = NULL; cb_data.time = NULL;
@ -567,7 +567,7 @@ int mon_check() {
#ifndef IS_VPI #ifndef IS_VPI
VerilatedVpi::selfTest(); VerilatedVpi::selfTest();
#endif #endif
return 0; // Ok return 0; // Ok
} }
//====================================================================== //======================================================================
@ -634,13 +634,13 @@ int main(int argc, char **argv, char **env) {
main_time += 10; main_time += 10;
while (sc_time_stamp() < sim_time && !Verilated::gotFinish()) { while (sc_time_stamp() < sim_time && !Verilated::gotFinish()) {
main_time += 1; main_time += 1;
topp->eval(); topp->eval();
VerilatedVpi::callValueCbs(); VerilatedVpi::callValueCbs();
topp->clk = !topp->clk; topp->clk = !topp->clk;
//mon_do(); //mon_do();
#if VM_TRACE #if VM_TRACE
if (tfp) tfp->dump (main_time); if (tfp) tfp->dump (main_time);
#endif #endif
} }
CHECK_RESULT(callback_count, 501); CHECK_RESULT(callback_count, 501);
@ -648,7 +648,7 @@ int main(int argc, char **argv, char **env) {
CHECK_RESULT(callback_count_quad, 2); CHECK_RESULT(callback_count_quad, 2);
CHECK_RESULT(callback_count_strs, callback_count_strs_max); CHECK_RESULT(callback_count_strs, callback_count_strs_max);
if (!Verilated::gotFinish()) { if (!Verilated::gotFinish()) {
vl_fatal(FILENM,__LINE__,"main", "%Error: Timeout; never got a $finish"); vl_fatal(FILENM,__LINE__,"main", "%Error: Timeout; never got a $finish");
} }
topp->final(); topp->final();

View File

@ -9,95 +9,95 @@ use Pod::Usage;
use Data::Dumper; $Data::Dumper::Indent = 1; use Data::Dumper; $Data::Dumper::Indent = 1;
use Bit::Vector; use Bit::Vector;
use strict; use strict;
use vars qw ($Debug); use vars qw($Debug);
our @Orig_ARGV = @ARGV; our @Orig_ARGV = @ARGV;
our $Rerun_Args = $0." ".join(' ',@Orig_ARGV); our $Rerun_Args = $0." ".join(' ',@Orig_ARGV);
$Rerun_Args =~ s/\s+$//; $Rerun_Args =~ s/\s+$//;
use vars qw (@Blocks use vars qw(@Blocks
%Vars %Vars
%VarAttrs %VarAttrs
%VarsBlock %VarsBlock
%Tree %Tree
@Commit @Commit
$Depth $Depth
%IdWidth %IdWidth
%Ops); %Ops);
#====================================================================== #======================================================================
# width=> Number of bits the output size is, 0=you tell me. # width=> Number of bits the output size is, 0=you tell me.
# func=> What to put in output file # func=> What to put in output file
# signed=> 0=unsigned output, 1=signed output, '%1'=signed if op1 signed # signed=> 0=unsigned output, 1=signed output, '%1'=signed if op1 signed
# lsb=> LSB for variable declarations # lsb=> LSB for variable declarations
# em=> How to calculate emulated return value # em=> How to calculate emulated return value
# %w Width of this output op ($treeref->{width}) # %w Width of this output op ($treeref->{width})
# %v Output value ($treeref->{val}) # %v Output value ($treeref->{val})
# %1r First operand ($treeref->{op1}) # %1r First operand ($treeref->{op1})
# %1v First operand value ($treeref->{op1}{val}) # %1v First operand value ($treeref->{op1}{val})
# %1w First operand width ($treeref->{op1}{width}) # %1w First operand width ($treeref->{op1}{width})
our $Raise_Weight_Max = 50; our $Raise_Weight_Max = 50;
%Ops = %Ops =
( (
'VCONST'=> {weight=>1&&20, width=>0, sc=>1, terminal=>1, v=>'%v', }, 'VCONST'=> {weight=>1&&20, width=>0, sc=>1, terminal=>1, v=>'%v', },
'VIDNEW'=> {weight=>1&&10, width=>0, sc=>1, terminal=>0, v=>'%i', }, 'VIDNEW'=> {weight=>1&&10, width=>0, sc=>1, terminal=>0, v=>'%i', },
'VIDOLD'=> {weight=>1&&20, width=>0, sc=>1, terminal=>0, v=>'%i', }, 'VIDOLD'=> {weight=>1&&20, width=>0, sc=>1, terminal=>0, v=>'%i', },
'VIDSAME'=> {weight=>1&&20, width=>0, sc=>1, terminal=>0, v=>'%i', }, 'VIDSAME'=> {weight=>1&&20, width=>0, sc=>1, terminal=>0, v=>'%i', },
'VRANGE'=> {weight=>1&&30, width=>0, signed=>0,sc=>0, terminal=>0, v=>'%i[%2:%3]', }, 'VRANGE'=> {weight=>1&&30, width=>0, signed=>0,sc=>0, terminal=>0, v=>'%i[%2:%3]', },
'VBITSEL'=> {weight=>1&&10, width=>1, signed=>0,sc=>0, terminal=>0, v=>'%i[%2]', }, 'VBITSEL'=> {weight=>1&&10, width=>1, signed=>0,sc=>0, terminal=>0, v=>'%i[%2]', },
'VBITSELP'=> {weight=>1&&10, width=>0, signed=>0,sc=>0, terminal=>0, v=>'%i[%2+:%3]', }, 'VBITSELP'=> {weight=>1&&10, width=>0, signed=>0,sc=>0, terminal=>0, v=>'%i[%2+:%3]', },
'VBITSELM'=> {weight=>1&&10, width=>0, signed=>0,sc=>0, terminal=>0, v=>'%i[%2-:%3]', }, 'VBITSELM'=> {weight=>1&&10, width=>0, signed=>0,sc=>0, terminal=>0, v=>'%i[%2-:%3]', },
# Unary # Unary
'VEXTEND'=> {weight=>1&&3, width=>-2, signed=>0,sc=>0, terminal=>0, v=>'{%xd\'h0,%1}', }, 'VEXTEND'=> {weight=>1&&3, width=>-2, signed=>0,sc=>0, terminal=>0, v=>'{%xd\'h0,%1}', },
'VLOGNOT'=> {weight=>1&&1, width=>1, signed=>0, sc=>0, terminal=>0, v=>'(! %1)', }, 'VLOGNOT'=> {weight=>1&&1, width=>1, signed=>0, sc=>0, terminal=>0, v=>'(! %1)', },
'VREDAND'=> {weight=>1&&1, width=>1, signed=>0, sc=>0, terminal=>0, v=>'(& %1)', }, 'VREDAND'=> {weight=>1&&1, width=>1, signed=>0, sc=>0, terminal=>0, v=>'(& %1)', },
'VREDOR'=> {weight=>1&&1, width=>1, signed=>0, sc=>0, terminal=>0, v=>'(| %1)', }, 'VREDOR'=> {weight=>1&&1, width=>1, signed=>0, sc=>0, terminal=>0, v=>'(| %1)', },
'VREDNAND'=> {weight=>1&&1, width=>1, signed=>0, sc=>0, terminal=>0, v=>'(~& %1)', }, 'VREDNAND'=> {weight=>1&&1, width=>1, signed=>0, sc=>0, terminal=>0, v=>'(~& %1)', },
'VREDNOR'=> {weight=>1&&1, width=>1, signed=>0, sc=>0, terminal=>0, v=>'(~| %1)', }, 'VREDNOR'=> {weight=>1&&1, width=>1, signed=>0, sc=>0, terminal=>0, v=>'(~| %1)', },
'VREDXNOR'=> {weight=>1&&1, width=>1, signed=>0, sc=>0, terminal=>0, v=>'(^~ %1)', }, 'VREDXNOR'=> {weight=>1&&1, width=>1, signed=>0, sc=>0, terminal=>0, v=>'(^~ %1)', },
'VREDXOR'=> {weight=>1&&1, width=>1, signed=>0, sc=>0, terminal=>0, v=>'(^ %1)', }, 'VREDXOR'=> {weight=>1&&1, width=>1, signed=>0, sc=>0, terminal=>0, v=>'(^ %1)', },
'VNOT'=> {weight=>1&&3, width=>0, sc=>1, terminal=>0, v=>'(~ %1)', }, 'VNOT'=> {weight=>1&&3, width=>0, sc=>1, terminal=>0, v=>'(~ %1)', },
'VNEGATE'=> {weight=>1&&2, width=>0, sc=>1, terminal=>0, v=>'(- %1)', }, 'VNEGATE'=> {weight=>1&&2, width=>0, sc=>1, terminal=>0, v=>'(- %1)', },
'VCOUNTONES'=> {weight=>0&&2, width=>32, signed=>0, sc=>0, terminal=>0, v=>'\$countones(%1)', }, # No ncv support 'VCOUNTONES'=> {weight=>0&&2, width=>32, signed=>0, sc=>0, terminal=>0, v=>'\$countones(%1)', }, # No ncv support
'VONEHOT'=> {weight=>0&&2, width=>1, signed=>0, sc=>0, terminal=>0, v=>'\$onehot(%1)', }, # No ncv support 'VONEHOT'=> {weight=>0&&2, width=>1, signed=>0, sc=>0, terminal=>0, v=>'\$onehot(%1)', }, # No ncv support
'VONEHOT0'=> {weight=>0&&2, width=>1, signed=>0, sc=>0, terminal=>0, v=>'\$onehot0(%1)', }, # No ncv support 'VONEHOT0'=> {weight=>0&&2, width=>1, signed=>0, sc=>0, terminal=>0, v=>'\$onehot0(%1)', }, # No ncv support
# Binary # Binary
'VAND'=> {weight=>1&&2, width=>0, sc=>1, terminal=>0, v=>'(%1 & %2)', }, 'VAND'=> {weight=>1&&2, width=>0, sc=>1, terminal=>0, v=>'(%1 & %2)', },
'VOR'=> {weight=>1&&2, width=>0, sc=>1, terminal=>0, v=>'(%1 | %2)', }, 'VOR'=> {weight=>1&&2, width=>0, sc=>1, terminal=>0, v=>'(%1 | %2)', },
'VNAND'=> {weight=>1&&0, width=>0, sc=>0, terminal=>0, v=>'(%1 ~& %2)', }, #FIX vcs bug! 'VNAND'=> {weight=>1&&0, width=>0, sc=>0, terminal=>0, v=>'(%1 ~& %2)', }, #FIX vcs bug!
'VNOR'=> {weight=>1&&0, width=>0, sc=>0, terminal=>0, v=>'(%1 ~| %2)', }, #FIX vcs bug! 'VNOR'=> {weight=>1&&0, width=>0, sc=>0, terminal=>0, v=>'(%1 ~| %2)', }, #FIX vcs bug!
'VXOR'=> {weight=>1&&2, width=>0, sc=>1, terminal=>0, v=>'(%1 ^ %2)', }, 'VXOR'=> {weight=>1&&2, width=>0, sc=>1, terminal=>0, v=>'(%1 ^ %2)', },
'VXNOR'=> {weight=>1&&0, width=>0, sc=>0, terminal=>0, v=>'(%1 ^~ %2)', }, #FIX vcs bug! 'VXNOR'=> {weight=>1&&0, width=>0, sc=>0, terminal=>0, v=>'(%1 ^~ %2)', }, #FIX vcs bug!
'VEQ'=> {weight=>1&&2, width=>1, signed=>0, sc=>0, terminal=>0, v=>'(%1 == %2)', }, 'VEQ'=> {weight=>1&&2, width=>1, signed=>0, sc=>0, terminal=>0, v=>'(%1 == %2)', },
'VNEQ'=> {weight=>1&&2, width=>1, signed=>0, sc=>0, terminal=>0, v=>'(%1 != %2)', }, 'VNEQ'=> {weight=>1&&2, width=>1, signed=>0, sc=>0, terminal=>0, v=>'(%1 != %2)', },
'VGT'=> {weight=>1&&2, width=>1, signed=>0, sc=>0, terminal=>0, v=>'(%1 > %2)', }, 'VGT'=> {weight=>1&&2, width=>1, signed=>0, sc=>0, terminal=>0, v=>'(%1 > %2)', },
'VGTE'=> {weight=>1&&2, width=>1, signed=>0, sc=>0, terminal=>0, v=>'(%1 >= %2)', }, 'VGTE'=> {weight=>1&&2, width=>1, signed=>0, sc=>0, terminal=>0, v=>'(%1 >= %2)', },
'VLT'=> {weight=>1&&2, width=>1, signed=>0, sc=>0, terminal=>0, v=>'(%1 < %2)', }, 'VLT'=> {weight=>1&&2, width=>1, signed=>0, sc=>0, terminal=>0, v=>'(%1 < %2)', },
'VLTE'=> {weight=>1&&2, width=>1, signed=>0, sc=>0, terminal=>0, v=>'(%1 <= %2)', }, 'VLTE'=> {weight=>1&&2, width=>1, signed=>0, sc=>0, terminal=>0, v=>'(%1 <= %2)', },
'VEQCASE'=> {weight=>1&&2, width=>1, signed=>0, sc=>0, terminal=>0, v=>'(%1 === %2)', }, # FIX just a = for now 'VEQCASE'=> {weight=>1&&2, width=>1, signed=>0, sc=>0, terminal=>0, v=>'(%1 === %2)', }, # FIX just a = for now
'VNEQCASE'=> {weight=>1&&2, width=>1, signed=>0, sc=>0, terminal=>0, v=>'(%1 !== %2)', }, # FIX just a != for now 'VNEQCASE'=> {weight=>1&&2, width=>1, signed=>0, sc=>0, terminal=>0, v=>'(%1 !== %2)', }, # FIX just a != for now
'VLOGOR'=> {weight=>1&&2, width=>1, signed=>0, sc=>0, terminal=>0, v=>'(%1 || %2)', }, 'VLOGOR'=> {weight=>1&&2, width=>1, signed=>0, sc=>0, terminal=>0, v=>'(%1 || %2)', },
'VLOGAND'=> {weight=>1&&2, width=>1, signed=>0, sc=>0, terminal=>0, v=>'(%1 && %2)', }, 'VLOGAND'=> {weight=>1&&2, width=>1, signed=>0, sc=>0, terminal=>0, v=>'(%1 && %2)', },
'VADD'=> {weight=>1&&10, width=>0, sc=>1, terminal=>0, v=>'(%1 + %2)', }, 'VADD'=> {weight=>1&&10, width=>0, sc=>1, terminal=>0, v=>'(%1 + %2)', },
'VSUB'=> {weight=>1&&10, width=>0, sc=>1, terminal=>0, v=>'(%1 - %2)', }, 'VSUB'=> {weight=>1&&10, width=>0, sc=>1, terminal=>0, v=>'(%1 - %2)', },
'VMUL'=> {weight=>1&&15,width=>0, sc=>1, terminal=>0, v=>'(%1 * %2)', }, # High % as rarely applyable 'VMUL'=> {weight=>1&&15,width=>0, sc=>1, terminal=>0, v=>'(%1 * %2)', }, # High % as rarely applyable
# Unspecified behavior with == (a-signed / b) -- see t_math_signed5.v test # Unspecified behavior with == (a-signed / b) -- see t_math_signed5.v test
'VDIV'=> {weight=>1&&8, width=>0, signed=>0, sc=>1, terminal=>0, v=>'((%2)==%xw\'h0 ? %xw\'%xsh0:(%1 / %2))', }, 'VDIV'=> {weight=>1&&8, width=>0, signed=>0, sc=>1, terminal=>0, v=>'((%2)==%xw\'h0 ? %xw\'%xsh0:(%1 / %2))', },
'VMODDIV'=> {weight=>1&&8, width=>0, signed=>0, sc=>1, terminal=>0, v=>'((%2)==%xw\'h0 ? %xw\'%xsh0:(%1 %% %2))', }, 'VMODDIV'=> {weight=>1&&8, width=>0, signed=>0, sc=>1, terminal=>0, v=>'((%2)==%xw\'h0 ? %xw\'%xsh0:(%1 %% %2))', },
#'VPOW'=> {weight=>2&&0,width=>-64, sc=>0, terminal=>0, v=>'(%1 ** %2)', }, #'VPOW'=> {weight=>2&&0,width=>-64, sc=>0, terminal=>0, v=>'(%1 ** %2)', },
'VSHIFTL'=> {weight=>1&&8, width=>0, signed=>0, sc=>0, terminal=>0, v=>'(%1 << %2)', }, 'VSHIFTL'=> {weight=>1&&8, width=>0, signed=>0, sc=>0, terminal=>0, v=>'(%1 << %2)', },
'VSHIFTLS'=> {weight=>1&&8, width=>0, signed=>1, sc=>0, terminal=>0, v=>'(%1 <<< %2)', }, 'VSHIFTLS'=> {weight=>1&&8, width=>0, signed=>1, sc=>0, terminal=>0, v=>'(%1 <<< %2)', },
'VSHIFTR'=> {weight=>1&&8, width=>0, signed=>0, sc=>0, terminal=>0, v=>'(%1 >> %2)', }, 'VSHIFTR'=> {weight=>1&&8, width=>0, signed=>0, sc=>0, terminal=>0, v=>'(%1 >> %2)', },
'VSHIFTRS'=> {weight=>1&&15,width=>0, signed=>1, sc=>0, terminal=>0, v=>'(%1 >>> %2)', }, # ShiftR seems to sign extend differently for <=32 and >32 bits 'VSHIFTRS'=> {weight=>1&&15,width=>0, signed=>1, sc=>0, terminal=>0, v=>'(%1 >>> %2)', }, # ShiftR seems to sign extend differently for <=32 and >32 bits
'VCONCAT'=> {weight=>1&&4, width=>-2,signed=>0, sc=>0, terminal=>0, v=>'{%1,%2}', }, 'VCONCAT'=> {weight=>1&&4, width=>-2,signed=>0, sc=>0, terminal=>0, v=>'{%1,%2}', },
'VREPLIC'=> {weight=>1&&2, width=>0, signed=>0, sc=>0, terminal=>0, v=>'{%1{%2}}', }, 'VREPLIC'=> {weight=>1&&2, width=>0, signed=>0, sc=>0, terminal=>0, v=>'{%1{%2}}', },
'VREPLIC1W'=> {weight=>1&&2, width=>0, signed=>0, sc=>0, terminal=>0, v=>'{%1{%2}}', }, 'VREPLIC1W'=> {weight=>1&&2, width=>0, signed=>0, sc=>0, terminal=>0, v=>'{%1{%2}}', },
'VSIGNED'=> {weight=>1&&2, width=>0, signed=>1, sc=>0, terminal=>0, v=>'\$signed(%1)', }, 'VSIGNED'=> {weight=>1&&2, width=>0, signed=>1, sc=>0, terminal=>0, v=>'\$signed(%1)', },
'VUNSIGNED'=> {weight=>1&&2, width=>0, signed=>0, sc=>0, terminal=>0, v=>'\$unsigned(%1)', }, 'VUNSIGNED'=> {weight=>1&&2, width=>0, signed=>0, sc=>0, terminal=>0, v=>'\$unsigned(%1)', },
# Triops # Triops
'VCOND'=> {weight=>1&&4, width=>0, sc=>0, terminal=>0, v=>'(%1 ? %2 : %3)', }, 'VCOND'=> {weight=>1&&4, width=>0, sc=>0, terminal=>0, v=>'(%1 ? %2 : %3)', },
# Control flow # Control flow
#VIF #VIF
#VFOR #VFOR
@ -108,86 +108,86 @@ our $Raise_Weight_Max = 50;
my %ops2 = my %ops2 =
( (
'VCONST'=> {pl=>'', rnd=>'rnd_const(%tr);'}, 'VCONST'=> {pl=>'', rnd=>'rnd_const(%tr);'},
'VIDNEW'=> {pl=>'%tv=$Vars{%i}{val};', 'VIDNEW'=> {pl=>'%tv=$Vars{%i}{val};',
rnd=>'%i=next_id(%tw);' rnd=>'%i=next_id(%tw);'
.' $Vars{%i}=gen_leaf(width=>%tw,trunc=>1,signed=>%tg);' .' $Vars{%i}=gen_leaf(width=>%tw,trunc=>1,signed=>%tg);'
.' $VarAttrs{%i}{lsb} = rnd_lsb();' .' $VarAttrs{%i}{lsb} = rnd_lsb();'
.' id_commit(%tr,"%i");1;',}, .' id_commit(%tr,"%i");1;',},
'VIDOLD'=> {pl=>'%tv=$Vars{%i}{val};', rnd=>'%i=id_old(%tr);', ok_id_width=>1,}, 'VIDOLD'=> {pl=>'%tv=$Vars{%i}{val};', rnd=>'%i=id_old(%tr);', ok_id_width=>1,},
'VIDSAME'=> {pl=>'%tv=$Vars{%i}{val};', rnd=>'%i=id_same(%tr);', ok_id_width=>1,}, 'VIDSAME'=> {pl=>'%tv=$Vars{%i}{val};', rnd=>'%i=id_same(%tr);', ok_id_width=>1,},
# These create IDs they then extract from # These create IDs they then extract from
'VRANGE'=> {pl=>'VRANGE(%tr,$Vars{%i}{val},%2v,%3v,$VarAttrs{%i}{lsb});', 'VRANGE'=> {pl=>'VRANGE(%tr,$Vars{%i}{val},%2v,%3v,$VarAttrs{%i}{lsb});',
rnd=>'%i=next_id(%tw); $VarAttrs{%i}{lsb} = 0&&rnd_lsb();' rnd=>'%i=next_id(%tw); $VarAttrs{%i}{lsb} = 0&&rnd_lsb();'
.' my $lsb=rnd(128-%tw); my $msb=$lsb+%tw-1;' .' my $lsb=rnd(128-%tw); my $msb=$lsb+%tw-1;'
.' %2r=val_leaf($msb); %3r=val_leaf($lsb);' .' %2r=val_leaf($msb); %3r=val_leaf($lsb);'
.' $Vars{%i}=gen_leaf(width=>($msb+1));'}, .' $Vars{%i}=gen_leaf(width=>($msb+1));'},
'VBITSEL'=> {pl=>'VRANGE(%tr,$Vars{%i}{val},%2v,%2v,$VarAttrs{%i}{lsb});', 'VBITSEL'=> {pl=>'VRANGE(%tr,$Vars{%i}{val},%2v,%2v,$VarAttrs{%i}{lsb});',
rnd=>'%i=next_id(%tw); $VarAttrs{%i}{lsb} = 0&&rnd_lsb();' rnd=>'%i=next_id(%tw); $VarAttrs{%i}{lsb} = 0&&rnd_lsb();'
.' my $wid=min(128,rnd_width()|3);' .' my $wid=min(128,rnd_width()|3);'
.' %2r=gen_leaf(width=>(log2($wid)-1),signed=>0);' .' %2r=gen_leaf(width=>(log2($wid)-1),signed=>0);'
.' $Vars{%i}=gen_leaf(width=>$wid);'}, .' $Vars{%i}=gen_leaf(width=>$wid);'},
'VBITSELP'=> {pl=>'VBITSELP(%tr,$Vars{%i}{val},%2v,%3v,$VarAttrs{%i}{lsb});', 'VBITSELP'=> {pl=>'VBITSELP(%tr,$Vars{%i}{val},%2v,%3v,$VarAttrs{%i}{lsb});',
rnd=>'%i=next_id(%tw); $VarAttrs{%i}{lsb} = 0&&rnd_lsb();' rnd=>'%i=next_id(%tw); $VarAttrs{%i}{lsb} = 0&&rnd_lsb();'
.' my $wid=min(128,(%tw+rnd_width()|3)); %3r=val_leaf(%tw); my $maxval = $wid-%tw; %2r=(($maxval<4)?val_leaf($maxval):gen_leaf(width=>(log2($maxval)-1),signed=>0));' .' my $wid=min(128,(%tw+rnd_width()|3)); %3r=val_leaf(%tw); my $maxval = $wid-%tw; %2r=(($maxval<4)?val_leaf($maxval):gen_leaf(width=>(log2($maxval)-1),signed=>0));'
.' $Vars{%i}=gen_leaf(width=>$wid);'}, .' $Vars{%i}=gen_leaf(width=>$wid);'},
'VBITSELM'=> {pl=>'VBITSELM(%tr,$Vars{%i}{val},%2v,%3v,$VarAttrs{%i}{lsb});', 'VBITSELM'=> {pl=>'VBITSELM(%tr,$Vars{%i}{val},%2v,%3v,$VarAttrs{%i}{lsb});',
rnd=>'%i=next_id(%tw); $VarAttrs{%i}{lsb} = 0&&rnd_lsb();' rnd=>'%i=next_id(%tw); $VarAttrs{%i}{lsb} = 0&&rnd_lsb();'
.' my $wid=min(128,(%tw+rnd_width()|3)); %3r=val_leaf(%tw); my $maxval = $wid-1; my $minval=%tw-1; %2r=val_leaf(rnd($maxval-$minval)+$minval);' .' my $wid=min(128,(%tw+rnd_width()|3)); %3r=val_leaf(%tw); my $maxval = $wid-1; my $minval=%tw-1; %2r=val_leaf(rnd($maxval-$minval)+$minval);'
.' $Vars{%i}=gen_leaf(width=>$wid);'}, # No easy way to make expr with specified minimum .' $Vars{%i}=gen_leaf(width=>$wid);'}, # No easy way to make expr with specified minimum
# Unary # Unary
'VEXTEND'=> {pl=>'VRESIZE (%tr,%1v);', rnd=>'%1r=gen_leaf(width=>rnd_width(%tw-1));'}, 'VEXTEND'=> {pl=>'VRESIZE (%tr,%1v);', rnd=>'%1r=gen_leaf(width=>rnd_width(%tw-1));'},
'VLOGNOT'=> {pl=>'VLOGNOT (%tr,%1v);', rnd=>'%1r=gen_leaf(width=>0);'}, 'VLOGNOT'=> {pl=>'VLOGNOT (%tr,%1v);', rnd=>'%1r=gen_leaf(width=>0);'},
'VREDAND'=> {pl=>'VREDAND (%tr,%1v);', rnd=>'%1r=gen_leaf(width=>0);'}, 'VREDAND'=> {pl=>'VREDAND (%tr,%1v);', rnd=>'%1r=gen_leaf(width=>0);'},
'VREDOR'=> {pl=>'VREDOR (%tr,%1v);', rnd=>'%1r=gen_leaf(width=>0);'}, 'VREDOR'=> {pl=>'VREDOR (%tr,%1v);', rnd=>'%1r=gen_leaf(width=>0);'},
'VREDNAND'=> {pl=>'VREDNAND (%tr,%1v);', rnd=>'%1r=gen_leaf(width=>0);'}, 'VREDNAND'=> {pl=>'VREDNAND (%tr,%1v);', rnd=>'%1r=gen_leaf(width=>0);'},
'VREDNOR'=> {pl=>'VREDNOR (%tr,%1v);', rnd=>'%1r=gen_leaf(width=>0);'}, 'VREDNOR'=> {pl=>'VREDNOR (%tr,%1v);', rnd=>'%1r=gen_leaf(width=>0);'},
'VREDXOR'=> {pl=>'VREDXOR (%tr,%1v);', rnd=>'%1r=gen_leaf(width=>0);'}, 'VREDXOR'=> {pl=>'VREDXOR (%tr,%1v);', rnd=>'%1r=gen_leaf(width=>0);'},
'VREDXNOR'=> {pl=>'VREDXNOR (%tr,%1v);', rnd=>'%1r=gen_leaf(width=>0);'}, 'VREDXNOR'=> {pl=>'VREDXNOR (%tr,%1v);', rnd=>'%1r=gen_leaf(width=>0);'},
'VNOT'=> {pl=>'VNOT (%tr,%1v);', rnd=>'%1r=gen_leaf(width=>%tw,signed=>%tg);'}, 'VNOT'=> {pl=>'VNOT (%tr,%1v);', rnd=>'%1r=gen_leaf(width=>%tw,signed=>%tg);'},
'VNEGATE'=> {pl=>'VNEGATE (%tr,%1v);', rnd=>'%1r=gen_leaf(width=>%tw,signed=>%tg);'}, 'VNEGATE'=> {pl=>'VNEGATE (%tr,%1v);', rnd=>'%1r=gen_leaf(width=>%tw,signed=>%tg);'},
'VCOUNTONES'=> {pl=>'VCOUNTONES(%tr,%1v);', rnd=>'%1r=gen_leaf(width=>0);'}, 'VCOUNTONES'=> {pl=>'VCOUNTONES(%tr,%1v);', rnd=>'%1r=gen_leaf(width=>0);'},
'VONEHOT'=> {pl=>'VONEHOT (%tr,%1v);', rnd=>'%1r=gen_leaf(width=>0);'}, 'VONEHOT'=> {pl=>'VONEHOT (%tr,%1v);', rnd=>'%1r=gen_leaf(width=>0);'},
'VONEHOT0'=> {pl=>'VONEHOT0 (%tr,%1v);', rnd=>'%1r=gen_leaf(width=>0);'}, 'VONEHOT0'=> {pl=>'VONEHOT0 (%tr,%1v);', rnd=>'%1r=gen_leaf(width=>0);'},
# Binary # Binary
'VAND'=> {pl=>'VAND (%tr,%1v,%2v);', rnd=>'%1r=gen_leaf(width=>%tw,signed=>%tg); %2r=gen_leaf(width=>%tw,signed=>%tg);'}, 'VAND'=> {pl=>'VAND (%tr,%1v,%2v);', rnd=>'%1r=gen_leaf(width=>%tw,signed=>%tg); %2r=gen_leaf(width=>%tw,signed=>%tg);'},
'VOR'=> {pl=>'VOR (%tr,%1v,%2v);', rnd=>'%1r=gen_leaf(width=>%tw,signed=>%tg); %2r=gen_leaf(width=>%tw,signed=>%tg);'}, 'VOR'=> {pl=>'VOR (%tr,%1v,%2v);', rnd=>'%1r=gen_leaf(width=>%tw,signed=>%tg); %2r=gen_leaf(width=>%tw,signed=>%tg);'},
'VNAND'=> {pl=>'VNAND (%tr,%1v,%2v);', rnd=>'%1r=gen_leaf(width=>%tw,signed=>%tg); %2r=gen_leaf(width=>%tw,signed=>%tg);'}, 'VNAND'=> {pl=>'VNAND (%tr,%1v,%2v);', rnd=>'%1r=gen_leaf(width=>%tw,signed=>%tg); %2r=gen_leaf(width=>%tw,signed=>%tg);'},
'VNOR'=> {pl=>'VNOR (%tr,%1v,%2v);', rnd=>'%1r=gen_leaf(width=>%tw,signed=>%tg); %2r=gen_leaf(width=>%tw,signed=>%tg);'}, 'VNOR'=> {pl=>'VNOR (%tr,%1v,%2v);', rnd=>'%1r=gen_leaf(width=>%tw,signed=>%tg); %2r=gen_leaf(width=>%tw,signed=>%tg);'},
'VXOR'=> {pl=>'VXOR (%tr,%1v,%2v);', rnd=>'%1r=gen_leaf(width=>%tw,signed=>%tg); %2r=gen_leaf(width=>%tw,signed=>%tg);'}, 'VXOR'=> {pl=>'VXOR (%tr,%1v,%2v);', rnd=>'%1r=gen_leaf(width=>%tw,signed=>%tg); %2r=gen_leaf(width=>%tw,signed=>%tg);'},
'VXNOR'=> {pl=>'VXNOR (%tr,%1v,%2v);', rnd=>'%1r=gen_leaf(width=>%tw,signed=>%tg); %2r=gen_leaf(width=>%tw,signed=>%tg);'}, 'VXNOR'=> {pl=>'VXNOR (%tr,%1v,%2v);', rnd=>'%1r=gen_leaf(width=>%tw,signed=>%tg); %2r=gen_leaf(width=>%tw,signed=>%tg);'},
'VEQ'=> {pl=>'VEQ (%tr,%1r,%2r);', rnd=>'%1r=gen_leaf(width=>0); %2r=gen_leaf(width=>%1w,signed=>%1g);'}, 'VEQ'=> {pl=>'VEQ (%tr,%1r,%2r);', rnd=>'%1r=gen_leaf(width=>0); %2r=gen_leaf(width=>%1w,signed=>%1g);'},
'VNEQ'=> {pl=>'VNE (%tr,%1r,%2r);', rnd=>'%1r=gen_leaf(width=>0); %2r=gen_leaf(width=>%1w,signed=>%1g);'}, 'VNEQ'=> {pl=>'VNE (%tr,%1r,%2r);', rnd=>'%1r=gen_leaf(width=>0); %2r=gen_leaf(width=>%1w,signed=>%1g);'},
'VGT'=> {pl=>'VGT (%tr,%1r,%2r);', rnd=>'%1r=gen_leaf(width=>0); %2r=gen_leaf(width=>%1w,signed=>%1g);'}, 'VGT'=> {pl=>'VGT (%tr,%1r,%2r);', rnd=>'%1r=gen_leaf(width=>0); %2r=gen_leaf(width=>%1w,signed=>%1g);'},
'VGTE'=> {pl=>'VGE (%tr,%1r,%2r);', rnd=>'%1r=gen_leaf(width=>0); %2r=gen_leaf(width=>%1w,signed=>%1g);'}, 'VGTE'=> {pl=>'VGE (%tr,%1r,%2r);', rnd=>'%1r=gen_leaf(width=>0); %2r=gen_leaf(width=>%1w,signed=>%1g);'},
'VLT'=> {pl=>'VLT (%tr,%1r,%2r);', rnd=>'%1r=gen_leaf(width=>0); %2r=gen_leaf(width=>%1w,signed=>%1g);'}, 'VLT'=> {pl=>'VLT (%tr,%1r,%2r);', rnd=>'%1r=gen_leaf(width=>0); %2r=gen_leaf(width=>%1w,signed=>%1g);'},
'VLTE'=> {pl=>'VLE (%tr,%1r,%2r);', rnd=>'%1r=gen_leaf(width=>0); %2r=gen_leaf(width=>%1w,signed=>%1g);'}, 'VLTE'=> {pl=>'VLE (%tr,%1r,%2r);', rnd=>'%1r=gen_leaf(width=>0); %2r=gen_leaf(width=>%1w,signed=>%1g);'},
'VEQCASE'=> {pl=>'VEQ (%tr,%1r,%2r);', rnd=>'%1r=gen_leaf(width=>0); %2r=gen_leaf(width=>%1w,signed=>%1g);'}, 'VEQCASE'=> {pl=>'VEQ (%tr,%1r,%2r);', rnd=>'%1r=gen_leaf(width=>0); %2r=gen_leaf(width=>%1w,signed=>%1g);'},
'VNEQCASE'=> {pl=>'VNE (%tr,%1r,%2r);', rnd=>'%1r=gen_leaf(width=>0); %2r=gen_leaf(width=>%1w,signed=>%1g);'}, 'VNEQCASE'=> {pl=>'VNE (%tr,%1r,%2r);', rnd=>'%1r=gen_leaf(width=>0); %2r=gen_leaf(width=>%1w,signed=>%1g);'},
'VLOGOR'=> {pl=>'VLOGOR (%tr,%1v,%2v);', rnd=>'%1r=gen_leaf(width=>0); %2r=gen_leaf(width=>0);'}, 'VLOGOR'=> {pl=>'VLOGOR (%tr,%1v,%2v);', rnd=>'%1r=gen_leaf(width=>0); %2r=gen_leaf(width=>0);'},
'VLOGAND'=> {pl=>'VLOGAND(%tr,%1v,%2v);', rnd=>'%1r=gen_leaf(width=>0); %2r=gen_leaf(width=>0);'}, 'VLOGAND'=> {pl=>'VLOGAND(%tr,%1v,%2v);', rnd=>'%1r=gen_leaf(width=>0); %2r=gen_leaf(width=>0);'},
'VADD'=> {pl=>'VADD (%tr,%1v,%2v);', rnd=>'%1r=gen_leaf(width=>%tw,signed=>%tg); %2r=gen_leaf(width=>%tw,signed=>%tg);', trunc=>1,}, 'VADD'=> {pl=>'VADD (%tr,%1v,%2v);', rnd=>'%1r=gen_leaf(width=>%tw,signed=>%tg); %2r=gen_leaf(width=>%tw,signed=>%tg);', trunc=>1,},
'VSUB'=> {pl=>'VSUB (%tr,%1v,%2v);', rnd=>'%1r=gen_leaf(width=>%tw,signed=>%tg); %2r=gen_leaf(width=>%tw,signed=>%tg);', trunc=>1,}, 'VSUB'=> {pl=>'VSUB (%tr,%1v,%2v);', rnd=>'%1r=gen_leaf(width=>%tw,signed=>%tg); %2r=gen_leaf(width=>%tw,signed=>%tg);', trunc=>1,},
'VMUL'=> {pl=>'VMUL (%tr,%1v,%2v);', rnd=>'%1r=gen_leaf(width=>%tw,signed=>%tg); %2r=gen_leaf(width=>%tw,signed=>%tg);', trunc=>1,}, # Multiply generates larger width, so need truncate for safety 'VMUL'=> {pl=>'VMUL (%tr,%1v,%2v);', rnd=>'%1r=gen_leaf(width=>%tw,signed=>%tg); %2r=gen_leaf(width=>%tw,signed=>%tg);', trunc=>1,}, # Multiply generates larger width, so need truncate for safety
'VDIV'=> {pl=>'VDIV (%tr,%1r,%2r,0);', rnd=>'%1r=gen_leaf(width=>%tw,signed=>%tg); %2r=gen_leaf(width=>%tw,signed=>%tg);'}, 'VDIV'=> {pl=>'VDIV (%tr,%1r,%2r,0);', rnd=>'%1r=gen_leaf(width=>%tw,signed=>%tg); %2r=gen_leaf(width=>%tw,signed=>%tg);'},
'VMODDIV'=> {pl=>'VDIV (%tr,%1r,%2r,1);', rnd=>'%1r=gen_leaf(width=>%tw,signed=>%tg); %2r=gen_leaf(width=>%tw,signed=>%tg);'}, 'VMODDIV'=> {pl=>'VDIV (%tr,%1r,%2r,1);', rnd=>'%1r=gen_leaf(width=>%tw,signed=>%tg); %2r=gen_leaf(width=>%tw,signed=>%tg);'},
#'VPOW'=> {pl=>'VPOW (%tr,%1r,%2r);', rnd=>'%1r=gen_leaf(width=>min(%tw,6),signed=>%tg); %2r=gen_leaf(width=>min(%tw,8),signed=>%tg);', trunc=>1,}, # Generates larger width, so need truncate for safety #'VPOW'=> {pl=>'VPOW (%tr,%1r,%2r);', rnd=>'%1r=gen_leaf(width=>min(%tw,6),signed=>%tg); %2r=gen_leaf(width=>min(%tw,8),signed=>%tg);', trunc=>1,}, # Generates larger width, so need truncate for safety
'VSHIFTL'=> {pl=>'VSHIFTL(%tr,%1v,%2v);', rnd=>'%1r=gen_leaf(width=>%tw,signed=>%tg); %2r=gen_leaf(width=>log2(%tw)+1,signed=>%tg);'}, 'VSHIFTL'=> {pl=>'VSHIFTL(%tr,%1v,%2v);', rnd=>'%1r=gen_leaf(width=>%tw,signed=>%tg); %2r=gen_leaf(width=>log2(%tw)+1,signed=>%tg);'},
'VSHIFTLS'=> {pl=>'VSHIFTL(%tr,%1v,%2v);', rnd=>'%1r=gen_leaf(width=>%tw,signed=>%tg); %2r=gen_leaf(width=>log2(%tw)+1,signed=>%tg);'}, 'VSHIFTLS'=> {pl=>'VSHIFTL(%tr,%1v,%2v);', rnd=>'%1r=gen_leaf(width=>%tw,signed=>%tg); %2r=gen_leaf(width=>log2(%tw)+1,signed=>%tg);'},
'VSHIFTR'=> {pl=>'VSHIFTR(%tr,%1v,%2v);', rnd=>'%1r=gen_leaf(width=>%tw,signed=>%tg); %2r=gen_leaf(width=>log2(%tw)+1,signed=>%tg);'}, 'VSHIFTR'=> {pl=>'VSHIFTR(%tr,%1v,%2v);', rnd=>'%1r=gen_leaf(width=>%tw,signed=>%tg); %2r=gen_leaf(width=>log2(%tw)+1,signed=>%tg);'},
'VSHIFTRS'=> {pl=>'VSHIFTRS(%tr,%1v,%2v);', rnd=>'%1r=gen_leaf(width=>%tw,signed=>%tg); %2r=gen_leaf(width=>log2(%tw)+1,signed=>%tg);'}, 'VSHIFTRS'=> {pl=>'VSHIFTRS(%tr,%1v,%2v);', rnd=>'%1r=gen_leaf(width=>%tw,signed=>%tg); %2r=gen_leaf(width=>log2(%tw)+1,signed=>%tg);'},
'VCONCAT'=> {pl=>'VCONCAT(%tr,%1v,%2v);', rnd=>'my $d=(rnd(%tw-2)+1); %1r=gen_leaf(width=>$d,signed=>0); %2r=gen_leaf(width=>(%tw-$d),signed=>0);'}, 'VCONCAT'=> {pl=>'VCONCAT(%tr,%1v,%2v);', rnd=>'my $d=(rnd(%tw-2)+1); %1r=gen_leaf(width=>$d,signed=>0); %2r=gen_leaf(width=>(%tw-$d),signed=>0);'},
'VREPLIC'=> {pl=>'VREPLIC(%tr,%1v,%2v);', rnd=>'my $d=rnd_rep_width(%tw); %1r=val_leaf($d); %2r=gen_leaf(width=>(%tw/$d),signed=>0);'}, 'VREPLIC'=> {pl=>'VREPLIC(%tr,%1v,%2v);', rnd=>'my $d=rnd_rep_width(%tw); %1r=val_leaf($d); %2r=gen_leaf(width=>(%tw/$d),signed=>0);'},
'VREPLIC1W'=> {pl=>'VREPLIC(%tr,%1v,%2v);', rnd=>'%1r=val_leaf(%tw); %2r=gen_leaf(width=>1,signed=>0);'}, 'VREPLIC1W'=> {pl=>'VREPLIC(%tr,%1v,%2v);', rnd=>'%1r=val_leaf(%tw); %2r=gen_leaf(width=>1,signed=>0);'},
'VSIGNED'=> {pl=>'VCLONE (%tr,%1v,0);', rnd=>'%1r=gen_leaf(width=>%tw);'}, 'VSIGNED'=> {pl=>'VCLONE (%tr,%1v,0);', rnd=>'%1r=gen_leaf(width=>%tw);'},
'VUNSIGNED'=> {pl=>'VCLONE (%tr,%1v,0);', rnd=>'%1r=gen_leaf(width=>%tw);'}, 'VUNSIGNED'=> {pl=>'VCLONE (%tr,%1v,0);', rnd=>'%1r=gen_leaf(width=>%tw);'},
# Triops # Triops
'VCOND'=> {pl=>'VCOND(%tr,%1v,%2v,%3v);', rnd=>'%1r=gen_leaf(width=>1); %2r=gen_leaf(width=>%tw,signed=>%tg); %3r=gen_leaf(width=>%tw,signed=>%tg);'}, 'VCOND'=> {pl=>'VCOND(%tr,%1v,%2v,%3v);', rnd=>'%1r=gen_leaf(width=>1); %2r=gen_leaf(width=>%tw,signed=>%tg); %3r=gen_leaf(width=>%tw,signed=>%tg);'},
); );
foreach my $op (keys %ops2) { foreach my $op (keys %ops2) {
while ((my $key,my $val) = each %{$ops2{$op}}) { while ((my $key,my $val) = each %{$ops2{$op}}) {
$Ops{$op}{$key} = $val; $Ops{$op}{$key} = $val;
} }
} }
@ -207,17 +207,17 @@ our $Opt_BlockStmts = 2;
our $Signed_Pct = 60; our $Signed_Pct = 60;
$Debug = 0; $Debug = 0;
if (! GetOptions ( if (! GetOptions (
"help" => \&usage, "help" => \&usage,
"debug" => \&debug, "debug" => \&debug,
"depth=i" => \$Opt_Depth, "depth=i" => \$Opt_Depth,
"blockstmts=i"=> \$Opt_BlockStmts, "blockstmts=i"=> \$Opt_BlockStmts,
"numops=i" => \$Opt_NumOps, "numops=i" => \$Opt_NumOps,
"o=s" => \$Opt_Output, "o=s" => \$Opt_Output,
"raise=i" => \$Opt_Raise, "raise=i" => \$Opt_Raise,
"seed=i" => \$opt_seed, "seed=i" => \$opt_seed,
"signed!" => \$Opt_Signed, "signed!" => \$Opt_Signed,
"<>" => \&parameter, "<>" => \&parameter,
)) { )) {
usage(); usage();
} }
@ -238,7 +238,7 @@ write_output_v($Opt_Output);
sub usage { sub usage {
pod2usage(-verbose=>2, -exitval=>2, -output=>\*STDOUT); pod2usage(-verbose=>2, -exitval=>2, -output=>\*STDOUT);
exit (1); exit(1);
} }
sub debug { sub debug {
@ -258,31 +258,31 @@ sub parameter {
sub init { sub init {
for my $op (keys %Ops) { for my $op (keys %Ops) {
my $opref = $Ops{$op}; my $opref = $Ops{$op};
$opref->{name} = $op; $opref->{name} = $op;
gen_v($opref); gen_v($opref);
gen_pl($opref); gen_pl($opref);
gen_rnd($opref); gen_rnd($opref);
} }
raise(); raise();
} }
sub raise { sub raise {
for (my $i=0; $i<($Opt_Raise||0); $i++) { for (my $i=0; $i<($Opt_Raise||0); $i++) {
my @ops = (values %Ops); my @ops = (values %Ops);
while (1) { while (1) {
my $rndop = $ops[rnd($#ops + 1)]; my $rndop = $ops[rnd($#ops + 1)];
next if !$rndop->{weight}; # Don't turn on disabled ops next if !$rndop->{weight}; # Don't turn on disabled ops
$rndop->{weight} += rnd($Raise_Weight_Max); $rndop->{weight} += rnd($Raise_Weight_Max);
printf "\tWeight %-15s +%d\n",$rndop->{name},$rndop->{weight}; printf "\tWeight %-15s +%d\n",$rndop->{name},$rndop->{weight};
last; last;
} }
} }
} }
sub gentest { sub gentest {
for (my $opn=0; $opn<$Opt_NumOps/$Opt_BlockStmts; $opn++) { for (my $opn=0; $opn<$Opt_NumOps/$Opt_BlockStmts; $opn++) {
do_a_test(); do_a_test();
} }
} }
@ -293,20 +293,20 @@ sub _rnd_op_ok {
my $opref = shift; my $opref = shift;
my $paramref = shift; my $paramref = shift;
return (($opref->{width} == 0 return (($opref->{width} == 0
|| $opref->{width} == $paramref->{width} || $opref->{width} == $paramref->{width}
# Note -2 means >, while -32 means <! # Note -2 means >, while -32 means <!
|| ($opref->{width}==-31 && $paramref->{width}<=31) # -31... must be <31 bits || ($opref->{width}==-31 && $paramref->{width}<=31) # -31... must be <31 bits
|| ($opref->{width}==-32 && $paramref->{width}<=32) # -32... must be <32 bits || ($opref->{width}==-32 && $paramref->{width}<=32) # -32... must be <32 bits
|| ($opref->{width}==-63 && $paramref->{width}<=63) # -63... must be <63 bits || ($opref->{width}==-63 && $paramref->{width}<=63) # -63... must be <63 bits
|| ($opref->{width}==-64 && $paramref->{width}<=64) # -64... must be <64 bits || ($opref->{width}==-64 && $paramref->{width}<=64) # -64... must be <64 bits
|| ($opref->{width}==-2 && $paramref->{width}>=2) # -2... must be >2 bits || ($opref->{width}==-2 && $paramref->{width}>=2) # -2... must be >2 bits
) )
&& (!$opref->{ok_id_width} || $IdWidth{$paramref->{width}}{$paramref->{signed}||0}) && (!$opref->{ok_id_width} || $IdWidth{$paramref->{width}}{$paramref->{signed}||0})
&& (!defined $opref->{signed} || ($opref->{signed} == ($paramref->{signed}||0))) && (!defined $opref->{signed} || ($opref->{signed} == ($paramref->{signed}||0)))
&& (!$opref->{trunc} || $paramref->{trunc}) && (!$opref->{trunc} || $paramref->{trunc})
&& (!$opref->{opt_signed} || $Opt_Signed) && (!$opref->{opt_signed} || $Opt_Signed)
&& (($Depth < $Opt_Depth && !$paramref->{need_terminal}) && (($Depth < $Opt_Depth && !$paramref->{need_terminal})
|| $opref->{terminal})); || $opref->{terminal}));
} }
sub rnd_op { sub rnd_op {
@ -314,19 +314,19 @@ sub rnd_op {
my $totweight = 0; my $totweight = 0;
foreach my $opref (values %Ops) { foreach my $opref (values %Ops) {
if (_rnd_op_ok($opref,$paramref)) { if (_rnd_op_ok($opref,$paramref)) {
$totweight += $opref->{weight}; $totweight += $opref->{weight};
} }
} }
my $chooseweight = rnd($totweight); my $chooseweight = rnd($totweight);
$totweight = 0; $totweight = 0;
foreach my $opref (values %Ops) { foreach my $opref (values %Ops) {
if (_rnd_op_ok($opref,$paramref)) { if (_rnd_op_ok($opref,$paramref)) {
$totweight += $opref->{weight}; $totweight += $opref->{weight};
if ($chooseweight < $totweight) { if ($chooseweight < $totweight) {
return $opref; return $opref;
} }
} }
} }
die "%Error: No instructions match,"; die "%Error: No instructions match,";
} }
@ -335,15 +335,15 @@ sub rnd_width {
my $max = shift; my $max = shift;
my $v = rnd(100); my $v = rnd(100);
my $n = (0 my $n = (0
|| (($v<20) && 1) || (($v<20) && 1)
|| (($v<25) && 2) || (($v<25) && 2)
|| (($v<30) && 31) || (($v<30) && 31)
|| (($v<35) && 32) || (($v<35) && 32)
|| (($v<40) && 63) || (($v<40) && 63)
|| (($v<45) && 64) || (($v<45) && 64)
|| (($v<50) && 95) || (($v<50) && 95)
|| (($v<55) && 96) || (($v<55) && 96)
|| (rnd(128)+1)); || (rnd(128)+1));
if ($max && $n>=$max) { $n = rnd($max-1)+1; } if ($max && $n>=$max) { $n = rnd($max-1)+1; }
return $n; return $n;
} }
@ -354,9 +354,9 @@ sub rnd_rep_width {
# We'd like to pick any divisor that works. # We'd like to pick any divisor that works.
my @factors; my @factors;
for (my $div=1; $div<$out; $div++) { for (my $div=1; $div<$out; $div++) {
if (int($out/$div)==($out/$div)) { if (int($out/$div)==($out/$div)) {
push @factors, $div; push @factors, $div;
} }
} }
my $fac = $factors[rnd($#factors+1)]; my $fac = $factors[rnd($#factors+1)];
#print "RND REP $out -> $fac (@factors)\n" if $Debug; #print "RND REP $out -> $fac (@factors)\n" if $Debug;
@ -369,17 +369,17 @@ sub rnd_const {
my $v = rnd(100); my $v = rnd(100);
my $val = Bit::Vector->new($width); my $val = Bit::Vector->new($width);
if ($v<25) { # zero if ($v<25) { # zero
} elsif ($v<50) { # ones } elsif ($v<50) { # ones
for (my $w=0; $w<$val->Word_Size; ++$w) { for (my $w=0; $w<$val->Word_Size; ++$w) {
$val->Word_Store(0,~0); $val->Word_Store(0,~0);
} }
} elsif ($v<60) { # one } elsif ($v<60) { # one
$val->Word_Store(0,1); $val->Word_Store(0,1);
} else { #random } else { # random
for (my $w=0; $w<$val->Word_Size; ++$w) { for (my $w=0; $w<$val->Word_Size; ++$w) {
$val->Word_Store($w,rnd_int()); $val->Word_Store($w,rnd_int());
} }
} }
$treeref->{val} = $val; $treeref->{val} = $val;
} }
@ -403,7 +403,7 @@ sub rnd {
} }
sub rnd32 { sub rnd32 {
my $vp = int(rand(1<<16)); my $vp = int(rand(1<<16));
$vp ^= (int(rand(1<<8)))<<16;# Single 1<<16 doesn't work $vp ^= (int(rand(1<<8)))<<16; # Single 1<<16 doesn't work
$vp ^= (int(rand(1<<8)))<<24; $vp ^= (int(rand(1<<8)))<<24;
return ($vp); return ($vp);
} }
@ -423,10 +423,10 @@ sub id_commit {
my $signed = $treeref->{signed}; my $signed = $treeref->{signed};
my $id = shift; my $id = shift;
push @Commit, sub { push @Commit, sub {
$IdWidth{$width}{$signed} = [] if !$IdWidth{$width}{$signed}; $IdWidth{$width}{$signed} = [] if !$IdWidth{$width}{$signed};
push @{$IdWidth{$width}{$signed}}, $id; push @{$IdWidth{$width}{$signed}}, $id;
$VarsBlock{$id}{set} = 1; $VarsBlock{$id}{set} = 1;
1; 1;
}; };
} }
@ -449,15 +449,15 @@ sub id_same {
my @possible; my @possible;
foreach my $id (keys %VarsBlock) { foreach my $id (keys %VarsBlock) {
next if !$VarsBlock{$id}{used}; next if !$VarsBlock{$id}{used};
my $varref = $Vars{$id}; my $varref = $Vars{$id};
next if $varref->{signed} != $signed; next if $varref->{signed} != $signed;
next if $varref->{width} != $width; next if $varref->{width} != $width;
push @possible, $id; push @possible, $id;
} }
my $n = $#possible + 1; my $n = $#possible + 1;
if ($n<1) { # Nothing, grab another! if ($n<1) { # Nothing, grab another!
return id_old($treeref,$width,$signed); return id_old($treeref,$width,$signed);
} }
my $idn = rnd($n); my $idn = rnd($n);
my $id = $possible[$idn]; my $id = $possible[$idn];
@ -484,41 +484,41 @@ sub write_output_v {
my $cycles = 2; my $cycles = 2;
foreach my $var (sort (keys %Vars)) { foreach my $var (sort (keys %Vars)) {
print $fh "",decl_text ($var),"\n"; print $fh "",decl_text ($var),"\n";
} }
foreach my $block (@Blocks) { foreach my $block (@Blocks) {
print $fh "\t//".('='x60)."\n"; print $fh "\t//".('='x60)."\n";
my $style = rnd(100); my $style = rnd(100);
if ($style < 15) { if ($style < 15) {
# This allows statements to get split up, and constants to propagate # This allows statements to get split up, and constants to propagate
print $fh " always @(", join(" or ", ('check', @{$block->{inputs}})); print $fh " always @(", join(" or ", ('check', @{$block->{inputs}}));
print $fh ") begin : $block->{name}\n"; print $fh ") begin : $block->{name}\n";
print $fh @{$block->{preass}}; print $fh @{$block->{preass}};
print $fh " end\n"; print $fh " end\n";
print $fh " always @(posedge clk) begin : $block->{name}Check\n"; print $fh " always @(posedge clk) begin : $block->{name}Check\n";
print $fh @{$block->{body}}; print $fh @{$block->{body}};
print $fh " end\n"; print $fh " end\n";
} }
elsif ($style < 40) { elsif ($style < 40) {
print $fh " always @(", join(" or ", ('check', @{$block->{inputs}})); print $fh " always @(", join(" or ", ('check', @{$block->{inputs}}));
print $fh ") begin : $block->{name}\n"; print $fh ") begin : $block->{name}\n";
print $fh @{$block->{preass}}; print $fh @{$block->{preass}};
print $fh @{$block->{body}}; print $fh @{$block->{body}};
print $fh " end\n"; print $fh " end\n";
} }
else { else {
foreach my $stmt (@{$block->{preass}}) { foreach my $stmt (@{$block->{preass}}) {
$cycles++; $cycles++;
print $fh " always @(posedge clk) begin\n"; print $fh " always @(posedge clk) begin\n";
$stmt =~ s/ = / <= /mg; $stmt =~ s/ = / <= /mg;
print $fh $stmt; print $fh $stmt;
print $fh " end\n"; print $fh " end\n";
} }
print $fh " always @(posedge clk) begin\n"; print $fh " always @(posedge clk) begin\n";
print $fh @{$block->{body}}; print $fh @{$block->{body}};
print $fh " end\n"; print $fh " end\n";
} }
} }
print $fh "\n"; print $fh "\n";
@ -551,9 +551,9 @@ sub write_output_v {
sub callers { sub callers {
for (my $i=0; ; $i++) { for (my $i=0; ; $i++) {
my @c = caller($i); my @c = caller($i);
last if !$c[0]; last if !$c[0];
print "Caller $i: ",join(' ',@c[0..3]),"\n"; print "Caller $i: ",join(' ',@c[0..3]),"\n";
} }
} }
@ -569,35 +569,35 @@ sub do_a_test {
%VarsBlock = (); %VarsBlock = ();
my $block = { my $block = {
name=>"Block".($#Blocks+2), name=>"Block".($#Blocks+2),
body=>[], body=>[],
preass=>[], preass=>[],
inputs=>[], inputs=>[],
outputs=>[], outputs=>[],
}; };
for (my $i=0; $i<$Opt_BlockStmts; $i++) { for (my $i=0; $i<$Opt_BlockStmts; $i++) {
my $treeref = gen_leaf(width=>0); my $treeref = gen_leaf(width=>0);
push @{$block->{body}}, push @{$block->{body}},
"\tif ($treeref->{text} != ".$treeref->val_to_text().") if (check) ".stop_text().";\n"; "\tif ($treeref->{text} != ".$treeref->val_to_text().") if (check) ".stop_text().";\n";
} }
foreach my $var (keys %VarsBlock) { foreach my $var (keys %VarsBlock) {
push @{$block->{inputs}}, $var push @{$block->{inputs}}, $var
if $VarsBlock{$var}{used} && !$VarsBlock{$var}{set}; if $VarsBlock{$var}{used} && !$VarsBlock{$var}{set};
} }
foreach my $var (reverse (sort (keys %Vars))) { foreach my $var (reverse (sort (keys %Vars))) {
my $varref = $Vars{$var}; my $varref = $Vars{$var};
next if $varref->{printedit}; next if $varref->{printedit};
$varref->{printedit} = 1; $varref->{printedit} = 1;
push @{$block->{outputs}}, $var; push @{$block->{outputs}}, $var;
push @{$block->{preass}}, sprintf ("\t$var = %s;\n" push @{$block->{preass}}, sprintf ("\t$var = %s;\n"
,$varref->{text}); ,$varref->{text});
} }
foreach my $com (@Commit) { foreach my $com (@Commit) {
&{$com} or die "%Error: Can't eval:\n$com\n $@ "; &{$com} or die "%Error: Can't eval:\n$com\n $@ ";
} }
push @Blocks, $block; push @Blocks, $block;
@ -605,22 +605,22 @@ sub do_a_test {
sub gen_leaf { sub gen_leaf {
my $inforef = {width=>0, # Anything my $inforef = {width=>0, # Anything
need_terminal=>0, need_terminal=>0,
#trunc=>undef, # Allow multiply op #trunc=>undef, # Allow multiply op
@_}; @_};
$inforef->{width} ||= rnd_width(); $inforef->{width} ||= rnd_width();
$inforef->{signed} = ($Opt_Signed && $inforef->{width}>1 && (rnd(100)<$Signed_Pct))?1:0 $inforef->{signed} = ($Opt_Signed && $inforef->{width}>1 && (rnd(100)<$Signed_Pct))?1:0
if !defined $inforef->{signed}; if !defined $inforef->{signed};
print +((" "x$Depth)."Leaf of width $inforef->{width}\n") if $Debug; print +((" "x$Depth)."Leaf of width $inforef->{width}\n") if $Debug;
my $op = rnd_op($inforef); my $op = rnd_op($inforef);
my $treeref = new Vg::Base; my $treeref = new Vg::Base;
while ((my $key,my $val) = each %{$op}) { while ((my $key,my $val) = each %{$op}) {
$treeref->{$key} = $val; $treeref->{$key} = $val;
} }
while ((my $key,my $val) = each %{$inforef}) { while ((my $key,my $val) = each %{$inforef}) {
$treeref->{$key} = $val; $treeref->{$key} = $val;
} }
local $Depth = $Depth+1; local $Depth = $Depth+1;
@ -636,11 +636,11 @@ sub gen_leaf {
print " Value ",$treeref->{val}," = ",$treeref->val_to_text(),"\n" if $Debug; print " Value ",$treeref->{val}," = ",$treeref->val_to_text(),"\n" if $Debug;
#$treeref->tree_dump() if $Debug; #$treeref->tree_dump() if $Debug;
$treeref->{val_size} = $treeref->{val}->Size; #Debugging $treeref->{val_size} = $treeref->{val}->Size; # Debugging
$treeref->{val_text} = $treeref->{val}->to_Hex; #Debugging $treeref->{val_text} = $treeref->{val}->to_Hex; # Debugging
($treeref->{val}->Size == $treeref->{width}) ($treeref->{val}->Size == $treeref->{width})
or die "%Error: Size mismatch ",$treeref->{val}->Size,"!=",$treeref->{width},"\n",Dumper($treeref); or die "%Error: Size mismatch ",$treeref->{val}->Size,"!=",$treeref->{width},"\n",Dumper($treeref);
return $treeref; return $treeref;
} }
@ -659,23 +659,23 @@ sub gen_v {
my $argl = $opref->{v}; my $argl = $opref->{v};
my @args; my @args;
while ($argl =~ s/(%x.|%.)//) { while ($argl =~ s/(%x.|%.)//) {
my $arg = $1; my $arg = $1;
push @args, '$treeref->{op1}{text}' if $arg =~ /%1/; push @args, '$treeref->{op1}{text}' if $arg =~ /%1/;
push @args, '$treeref->{op2}{text}' if $arg =~ /%2/; push @args, '$treeref->{op2}{text}' if $arg =~ /%2/;
push @args, '$treeref->{op3}{text}' if $arg =~ /%3/; push @args, '$treeref->{op3}{text}' if $arg =~ /%3/;
push @args, '$treeref->val_to_text' if $arg =~ /%v/; push @args, '$treeref->val_to_text' if $arg =~ /%v/;
push @args, '$treeref->{id}' if $arg =~ /%i/; push @args, '$treeref->{id}' if $arg =~ /%i/;
push @args, '$treeref->{signed}?"s":""' if $arg =~ /%xs/; push @args, '$treeref->{signed}?"s":""' if $arg =~ /%xs/;
push @args, '$treeref->{width}' if $arg =~ /%xw/; push @args, '$treeref->{width}' if $arg =~ /%xw/;
push @args, '$treeref->{width}-$treeref->{op1}{width}' if $arg =~ /%xd/; push @args, '$treeref->{width}-$treeref->{op1}{width}' if $arg =~ /%xd/;
} }
my $func = ("sub { " my $func = ("sub { "
." my \$treeref = shift;" ." my \$treeref = shift;"
." sprintf(\"$fmt\",".join(',',@args).");" ." sprintf(\"$fmt\",".join(',',@args).");"
."}"); ."}");
my $set = ("\$opref->{v_sub} = $func; 1;"); my $set = ("\$opref->{v_sub} = $func; 1;");
$opref->{v_sub_text} = $func; # For seeing it in debugging dumps $opref->{v_sub_text} = $func; # For seeing it in debugging dumps
#print "Op V $opref->{name} $set\n"; #print "Op V $opref->{name} $set\n";
eval($set) or die "%Error: Can't eval:\n$set\n $@ "; eval($set) or die "%Error: Can't eval:\n$set\n $@ ";
} }
@ -716,11 +716,11 @@ sub gen_pl {
my $str = escapes($opref->{pl}, $opref->{name}); my $str = escapes($opref->{pl}, $opref->{name});
my $func = ("sub { " my $func = ("sub { "
." my \$treeref = shift;" ." my \$treeref = shift;"
." $str;" ." $str;"
."}"); ."}");
my $set = ("\$opref->{pl_sub} = $func; 1;"); my $set = ("\$opref->{pl_sub} = $func; 1;");
$opref->{pl_sub_text} = $func; # For seeing it in debugging dumps $opref->{pl_sub_text} = $func; # For seeing it in debugging dumps
#print "Op PL $opref->{name} $set\n"; #print "Op PL $opref->{name} $set\n";
eval($set) or die "%Error: Can't eval:\n$set\n $@ "; eval($set) or die "%Error: Can't eval:\n$set\n $@ ";
} }
@ -731,11 +731,11 @@ sub gen_rnd {
my $str = escapes($opref->{rnd}, $opref->{name}); my $str = escapes($opref->{rnd}, $opref->{name});
my $func = ("sub { " my $func = ("sub { "
." my \$treeref = shift;" ." my \$treeref = shift;"
." $str;" ." $str;"
."}"); ."}");
my $set = ("\$opref->{rnd_sub} = $func; 1;"); my $set = ("\$opref->{rnd_sub} = $func; 1;");
$opref->{rnd_sub_text} = $func; # For seeing it in debugging dumps $opref->{rnd_sub_text} = $func; # For seeing it in debugging dumps
#print "Op RND $opref->{name} $set\n"; #print "Op RND $opref->{name} $set\n";
eval($set) or die "%Error: Can't eval:\n$set\n $@ "; eval($set) or die "%Error: Can't eval:\n$set\n $@ ";
} }
@ -749,14 +749,14 @@ sub decl_text {
my $decl_with = shift; my $decl_with = shift;
my $varref = $Vars{$var}; my $varref = $Vars{$var};
return sprintf (" reg %s [%3d:%3d] %s %s; //=%d'h%s" return sprintf(" reg %s [%3d:%3d] %s %s; //=%d'h%s"
, ($varref->{signed}?"signed":" ") , ($varref->{signed}?"signed":" ")
, ($varref->{val}->Size)-1+$VarAttrs{$var}{lsb}, , ($varref->{val}->Size)-1+$VarAttrs{$var}{lsb},
, $VarAttrs{$var}{lsb} , $VarAttrs{$var}{lsb}
, $var , $var
, (rnd(100)<30 ? "/*verilator public*/":(" "x length("/*verilator public*/"))) , (rnd(100)<30 ? "/*verilator public*/":(" "x length("/*verilator public*/")))
, $varref->{val}->Size , $varref->{val}->Size
, lc $varref->{val}->to_Hex); , lc $varref->{val}->to_Hex);
} }
####################################################################### #######################################################################
@ -789,7 +789,7 @@ sub min { return $_[0]>$_[1] ? $_[1] : $_[0]; }
sub log2 { sub log2 {
for (my $i=31; $i>=0; $i--) { for (my $i=31; $i>=0; $i--) {
return $i+1 if $_[0]>(1<<$i); return $i+1 if $_[0]>(1<<$i);
} }
return 0; return 0;
} }
@ -797,7 +797,7 @@ sub log2 {
sub countones { sub countones {
my $out = 0; my $out = 0;
for (my $bit=0; $bit < $_[0]->Size; $bit++) { for (my $bit=0; $bit < $_[0]->Size; $bit++) {
$out ++ if $_[0]->bit_test($bit); $out ++ if $_[0]->bit_test($bit);
} }
return $out; return $out;
} }
@ -820,20 +820,20 @@ sub VREDNOR { $_[0]{val} = makebool(($_[1]->is_empty)?1:0); }
sub VREDXOR { sub VREDXOR {
my $out = 0; my $out = 0;
for (my $bit=0; $bit < $_[1]->Size; $bit++) { for (my $bit=0; $bit < $_[1]->Size; $bit++) {
$out ^= $_[1]->bit_test($bit); $out ^= $_[1]->bit_test($bit);
} }
$_[0]{val} = makebool($out); $_[0]{val} = makebool($out);
} }
sub VREDXNOR { sub VREDXNOR {
my $out = 1; my $out = 1;
for (my $bit=0; $bit < $_[1]->Size; $bit++) { for (my $bit=0; $bit < $_[1]->Size; $bit++) {
$out ^= $_[1]->bit_test($bit); $out ^= $_[1]->bit_test($bit);
} }
$_[0]{val} = makebool($out); $_[0]{val} = makebool($out);
} }
sub eithercompare { ($_[1]->{signed} && $_[2]->{signed}) sub eithercompare { ($_[1]->{signed} && $_[2]->{signed})
? $_[1]{val}->Compare($_[2]{val}) ? $_[1]{val}->Compare($_[2]{val})
: $_[1]{val}->Lexicompare($_[2]{val}); } : $_[1]{val}->Lexicompare($_[2]{val}); }
sub VEQ { $_[0]{val} = makebool( (eithercompare($_[0],$_[1],$_[2])==0) ?1:0); } sub VEQ { $_[0]{val} = makebool( (eithercompare($_[0],$_[1],$_[2])==0) ?1:0); }
sub VNE { $_[0]{val} = makebool( (eithercompare($_[0],$_[1],$_[2])!=0) ?1:0); } sub VNE { $_[0]{val} = makebool( (eithercompare($_[0],$_[1],$_[2])!=0) ?1:0); }
sub VLT { $_[0]{val} = makebool( (eithercompare($_[0],$_[1],$_[2])< 0) ?1:0); } sub VLT { $_[0]{val} = makebool( (eithercompare($_[0],$_[1],$_[2])< 0) ?1:0); }
@ -858,8 +858,8 @@ sub VNOT { $_[0]{val}=my $o=newsized($_[1]); $o->Complement($_[1]); }
sub VSHIFTL{ $_[0]{val}=my $o=$_[1]->Clone; $o->Move_Left ($_[2]->Word_Read(0)); } sub VSHIFTL{ $_[0]{val}=my $o=$_[1]->Clone; $o->Move_Left ($_[2]->Word_Read(0)); }
sub VSHIFTR{ $_[0]{val}=my $o=$_[1]->Clone; $o->Move_Right($_[2]->Word_Read(0)); } sub VSHIFTR{ $_[0]{val}=my $o=$_[1]->Clone; $o->Move_Right($_[2]->Word_Read(0)); }
sub VSHIFTRS{$_[0]{val}=my $o=$_[1]->Clone; $o->Move_Right($_[2]->Word_Read(0)); sub VSHIFTRS{$_[0]{val}=my $o=$_[1]->Clone; $o->Move_Right($_[2]->Word_Read(0));
if ($_[1]->msb() && $_[2]->Word_Read(0)>0) {$o->Interval_Fill(max(0,$o->Size-1-$_[2]->Word_Read(0)), $o->Size-1); } if ($_[1]->msb() && $_[2]->Word_Read(0)>0) {$o->Interval_Fill(max(0,$o->Size-1-$_[2]->Word_Read(0)), $o->Size-1); }
#print (" SHI ",$_[0]{val}->to_Hex,' = ',$_[1]->to_Hex,' >>> ',$_[2]->Word_Read(0),"\n"); #print (" SHI ",$_[0]{val}->to_Hex,' = ',$_[1]->to_Hex,' >>> ',$_[2]->Word_Read(0),"\n");
} }
sub VCLONE { $_[0]{val}=$_[1]->Clone; } sub VCLONE { $_[0]{val}=$_[1]->Clone; }
sub VRESIZE { sub VRESIZE {
@ -880,21 +880,21 @@ sub VMUL {
sub VDIV { sub VDIV {
my $is_mod = $_[3]; my $is_mod = $_[3];
if ($_[2]{val}->is_empty) { # Avoid divide by zero if ($_[2]{val}->is_empty) { # Avoid divide by zero
$_[0]{val}=newsized($_[1]{val}); $_[0]{val}=newsized($_[1]{val});
return; return;
} }
my $a=$_[1]{val}->Clone; if (!$_[1]->{signed}) { $a->Resize($a->Size + 1); } my $a=$_[1]{val}->Clone; if (!$_[1]->{signed}) { $a->Resize($a->Size + 1); }
my $b=$_[2]{val}->Clone; if (!$_[2]->{signed}) { $b->Resize($b->Size + 1); } my $b=$_[2]{val}->Clone; if (!$_[2]->{signed}) { $b->Resize($b->Size + 1); }
#print ("//DIVpp ",$_[1]->to_Hex,' ',$_[2]->to_Hex,' ',$_[1]->Size,'.',$_[2]->Size," \n"); #print ("//DIVpp ",$_[1]->to_Hex,' ',$_[2]->to_Hex,' ',$_[1]->Size,'.',$_[2]->Size," \n");
#print ("//DIVpp ",$a->to_Hex,' ',$b->to_Hex,' ',$a->Size,'.',$b->Size," \n"); #print ("//DIVpp ",$a->to_Hex,' ',$b->to_Hex,' ',$a->Size,'.',$b->Size," \n");
my $quo=newsized($a); my $rem=newsized($a); my $quo=newsized($a); my $rem=newsized($a);
$quo->Divide($a,$b,$rem); # No division by zero - handled by if above $quo->Divide($a,$b,$rem); # No division by zero - handled by if above
my $o=newsized($_[1]{val}); my $o=newsized($_[1]{val});
$o->Interval_Copy($is_mod ? $rem : $quo,0,0,$_[1]{val}->Size); $o->Interval_Copy($is_mod ? $rem : $quo,0,0,$_[1]{val}->Size);
#print "//DIV",($_[1]->{signed}?"S":" "),' w',$a->Size,' ',$_[1]{val}->to_Hex,' ',$_[2]{val}->to_Hex,' =',$quo->to_Hex,'.',$rem->to_Hex," \n"; #print "//DIV",($_[1]->{signed}?"S":" "),' w',$a->Size,' ',$_[1]{val}->to_Hex,' ',$_[2]{val}->to_Hex,' =',$quo->to_Hex,'.',$rem->to_Hex," \n";
$_[0]{val}=$o; $_[0]{val}=$o;
} }
sub VPOW { # Power is a signed operation sub VPOW { # Power is a signed operation
my $a=$_[1]{val}->Clone; if (!$_[1]->{signed}) { $a->Resize($_[1]{val}->Size + 1); } my $a=$_[1]{val}->Clone; if (!$_[1]->{signed}) { $a->Resize($_[1]{val}->Size + 1); }
my $b=$_[2]{val}->Clone; if (!$_[2]->{signed}) { $b->Resize($_[2]{val}->Size + 1); } my $b=$_[2]{val}->Clone; if (!$_[2]->{signed}) { $b->Resize($_[2]{val}->Size + 1); }
print "VVpow = ",$_[1]{val}->to_Hex," ** ",$_[2]{val}->to_Hex,"\n"; print "VVpow = ",$_[1]{val}->to_Hex," ** ",$_[2]{val}->to_Hex,"\n";
@ -904,19 +904,26 @@ sub VPOW { # Power is a signed operation
$_[0]{val}=$o; $_[0]{val}=$o;
print "VV = $o\n"; print "VV = $o\n";
} }
sub VRANGE { #print "RANGE ",$_[1]->to_Hex,' ',$_[2]->to_Hex,' ',$_[3]->to_Hex," \n"; sub VRANGE {
return VRANGE_CONST($_[0],$_[1],$_[2]->Word_Read(0),$_[3]->Word_Read(0), $_[4]); } #print "RANGE ",$_[1]->to_Hex,' ',$_[2]->to_Hex,' ',$_[3]->to_Hex," \n";
return VRANGE_CONST($_[0], $_[1], $_[2]->Word_Read(0),
$_[3]->Word_Read(0), $_[4]);
}
sub VBITSELP { sub VBITSELP {
return VRANGE_CONST($_[0],$_[1],$_[2]->Word_Read(0)+$_[3]->Word_Read(0)-1, $_[2]->Word_Read(0), $_[4]); } return VRANGE_CONST($_[0], $_[1], $_[2]->Word_Read(0)+$_[3]->Word_Read(0)-1,
$_[2]->Word_Read(0), $_[4]);
}
sub VBITSELM { sub VBITSELM {
return VRANGE_CONST($_[0],$_[1],$_[2]->Word_Read(0), $_[2]->Word_Read(0)-$_[3]->Word_Read(0)+1, $_[4]); } return VRANGE_CONST($_[0],$_[1],$_[2]->Word_Read(0),
$_[2]->Word_Read(0)-$_[3]->Word_Read(0)+1, $_[4]);
}
sub VRANGE_CONST { sub VRANGE_CONST {
# to, from, msb, lsb, variable_lsb_to_subtract # to, from, msb, lsb, variable_lsb_to_subtract
#print "RANGE ",$_[1]->to_Hex,' ',$_[2],' ',$_[3],' ',$_[4]," \n"; #print "RANGE ",$_[1]->to_Hex,' ',$_[2],' ',$_[3],' ',$_[4]," \n";
my $size = $_[2] - $_[3] + 1; my $size = $_[2] - $_[3] + 1;
my $o=Bit::Vector->new($size); my $o=Bit::Vector->new($size);
if ($_[3] < $_[1]->Size) { if ($_[3] < $_[1]->Size) {
$o->Interval_Copy($_[1],0,$_[3]-$_[4],$size); $o->Interval_Copy($_[1],0,$_[3]-$_[4],$size);
} }
$_[0]{val}=$o; } $_[0]{val}=$o; }
sub VCONCAT { sub VCONCAT {
@ -929,8 +936,8 @@ sub VREPLIC {
my $o=Bit::Vector->new($_[1]->Word_Read(0) * $_[2]->Size); my $o=Bit::Vector->new($_[1]->Word_Read(0) * $_[2]->Size);
my $pos = 0; my $pos = 0;
for (my $time=0; $time<($_[1]->Word_Read(0)); $time++) { for (my $time=0; $time<($_[1]->Word_Read(0)); $time++) {
$o->Interval_Copy($_[2],$pos,0,$_[2]->Size); $o->Interval_Copy($_[2],$pos,0,$_[2]->Size);
$pos += $_[2]->Size; $pos += $_[2]->Size;
} }
$_[0]{val}=$o; $_[0]{val}=$o;
} }
@ -949,9 +956,9 @@ use strict;
sub new { sub new {
my $class = shift; my $class = shift;
my $self = { my $self = {
width=>0, # Width of expression, 0=Pick a width width=>0, # Width of expression, 0=Pick a width
#signed=>0/1, # Undef = pick a sign #signed=>0/1, # Undef = pick a sign
@_}; @_};
bless $self, $class; bless $self, $class;
return $self; return $self;
} }
@ -966,8 +973,8 @@ sub val_to_text {
my $val = lc $treeref->{val}->to_Hex(); my $val = lc $treeref->{val}->to_Hex();
$val = "0" if $treeref->{val}->is_empty; $val = "0" if $treeref->{val}->is_empty;
return ($treeref->{width} return ($treeref->{width}
.($treeref->{signed}?"'sh":"'h") .($treeref->{signed}?"'sh":"'h")
.$val); .$val);
} }
sub tree_dump { sub tree_dump {