1#!/usr/bin/env perl 2# See copyright, etc in below POD section. 3###################################################################### 4 5require 5.006_001; 6use warnings; 7use Cwd; 8 9BEGIN { 10 if (!$ENV{VERILATOR_ROOT} && -x "../bin/verilator") { 11 $ENV{VERILATOR_ROOT} = Cwd::getcwd() . "/.."; 12 } 13 $ENV{MAKE} ||= "make"; 14 $ENV{CXX} ||= "c++"; 15} 16 17use Getopt::Long; 18use IO::File; 19use Pod::Usage; 20use Data::Dumper; $Data::Dumper::Sortkeys = 1; 21use FindBin qw($RealBin); 22use strict; 23use vars qw($Debug %Vars $Driver $Fork); 24use version; 25use POSIX qw(strftime); 26use lib "."; 27use Time::HiRes qw(usleep); 28use Digest::MD5 qw(md5); 29 30$::Driver = 1; 31$::Have_Forker = 0; 32 33eval "use Parallel::Forker; \$Fork=Parallel::Forker->new(use_sig_child=>1, poll_interval=>10*1000); \$::Have_Forker=1;"; 34$Fork = Forker->new(use_sig_child => 1) if !$Fork; 35my $forker_Min_Version = 1.258; 36if ($::Have_Forker && $Parallel::Forker::VERSION < $forker_Min_Version) { 37 print STDERR "driver.pl: Parallel::Forker is older than $forker_Min_Version, suggest 'cpan install Parallel::Forker'\n"; 38 $::Have_Forker = 0; 39} 40$SIG{CHLD} = sub { $Fork->sig_child() if $Fork; }; 41$SIG{TERM} = sub { $Fork->kill_tree_all('TERM') if $Fork; die "Quitting...\n"; }; 42 43#====================================================================== 44 45# Map of all scenarios, with the names used to enable them 46our %All_Scenarios 47 = (dist => [ "dist"], 48 atsim => [ "simulator", "simulator_st", "atsim"], 49 ghdl => ["linter", "simulator", "simulator_st", "ghdl"], 50 iv => [ "simulator", "simulator_st", "iv"], 51 ms => ["linter", "simulator", "simulator_st", "ms"], 52 nc => ["linter", "simulator", "simulator_st", "nc"], 53 vcs => ["linter", "simulator", "simulator_st", "vcs"], 54 xsim => ["linter", "simulator", "simulator_st", "xsim"], 55 vlt => ["linter", "simulator", "simulator_st", "vlt_all", "vlt"], 56 vltmt => [ "simulator", "vlt_all", "vltmt"], 57 ); 58 59#====================================================================== 60# main 61 62autoflush STDOUT 1; 63autoflush STDERR 1; 64 65our @Orig_ARGV = @ARGV; 66our @Orig_ARGV_Sw; foreach (@Orig_ARGV) { push @Orig_ARGV_Sw, $_ if /^-/ && !/^-j/; } 67our $Start = time(); 68our $Vltmt_threads = 3; 69 70$Debug = 0; 71my $opt_benchmark; 72my @opt_tests; 73my $opt_dist; 74my $opt_gdb; 75my $opt_rr; 76my $opt_gdbbt; 77my $opt_gdbsim; 78my $opt_hashset; 79my $opt_jobs = 1; 80my $opt_optimize; 81my $opt_quiet; 82my $opt_rerun; 83my $opt_rrsim; 84my $opt_sanitize; 85my %opt_scenarios; 86my $opt_site; 87my $opt_stop; 88my $opt_trace; 89my $opt_verbose; 90my $Opt_Verilated_Debug; 91our $Opt_Unsupported; 92our $Opt_Verilation = 1; 93our @Opt_Driver_Verilator_Flags; 94 95Getopt::Long::config("pass_through"); 96if (! GetOptions( 97 "benchmark:i" => sub { $opt_benchmark = $_[1] ? $_[1] : 1; }, 98 "debug" => \&debug, 99 #debugi see parameter() 100 "gdb!" => \$opt_gdb, 101 "gdbbt!" => \$opt_gdbbt, 102 "gdbsim!" => \$opt_gdbsim, 103 "golden!" => sub { $ENV{HARNESS_UPDATE_GOLDEN} = 1; }, 104 "hashset=s" => \$opt_hashset, 105 "help" => \&usage, 106 "j=i" => \$opt_jobs, 107 "optimize:s" => \$opt_optimize, 108 "quiet!" => \$opt_quiet, 109 "rerun!" => \$opt_rerun, 110 "rr!" => \$opt_rr, 111 "rrsim!" => \$opt_rrsim, 112 "sanitize!" => \$opt_sanitize, 113 "site!" => \$opt_site, 114 "stop!" => \$opt_stop, 115 "trace!" => \$opt_trace, 116 "unsupported!"=> \$Opt_Unsupported, 117 "verbose!" => \$opt_verbose, 118 "verilation!" => \$Opt_Verilation, # Undocumented debugging 119 "verilated-debug!" => \$Opt_Verilated_Debug, 120 #W see parameter() 121 # Scenarios 122 "atsim|athdl!"=> sub { $opt_scenarios{atsim} = $_[1]; }, 123 "dist!" => sub { $opt_scenarios{dist} = $_[1]; }, 124 "ghdl!" => sub { $opt_scenarios{ghdl} = $_[1]; }, 125 "iv!" => sub { $opt_scenarios{iv} = $_[1]; }, 126 "ms!" => sub { $opt_scenarios{ms} = $_[1]; }, 127 "nc!" => sub { $opt_scenarios{nc} = $_[1]; }, 128 "vlt!" => sub { $opt_scenarios{vlt} = $_[1]; }, 129 "vltmt!" => sub { $opt_scenarios{vltmt} = $_[1]; }, 130 "vcs!" => sub { $opt_scenarios{vcs} = $_[1]; }, 131 "xsim!" => sub { $opt_scenarios{xsim} = $_[1]; }, 132 "<>" => \¶meter, 133 )) { 134 die "%Error: Bad usage, try '$0 --help'\n"; 135} 136 137$opt_jobs = calc_jobs() if defined $opt_jobs && $opt_jobs == 0; 138$Fork->max_proc($opt_jobs); 139 140if ((scalar keys %opt_scenarios) < 1) { 141 $opt_scenarios{dist} = 1; 142 $opt_scenarios{vlt} = 1; 143} 144 145our @Test_Dirs = "t"; 146push @Test_Dirs, split(/:/, $ENV{VERILATOR_TESTS_SITE}) 147 if (($#opt_tests < 0 ? $opt_site : 1) && $ENV{VERILATOR_TESTS_SITE}); 148 149if ($#opt_tests < 0) { # Run everything 150 my %uniq; 151 foreach my $dir (@Test_Dirs) { 152 my @stats = stat($dir); # Uniquify by inode, so different paths to same place get combined 153 next if !$stats[1] || $uniq{$stats[1]}++; 154 push @opt_tests, sort(glob("${dir}/t_*.pl")); 155 } 156} 157@opt_tests = _calc_hashset(@opt_tests) if $opt_hashset; 158 159if ($#opt_tests >= 2 && $opt_jobs >= 2) { 160 # Without this tests such as t_debug_sigsegv_bt_bad.pl will occasionally 161 # block on input and cause a SIGSTOP, then a "fg" was needed to resume testing. 162 if (!$::Have_Forker) { 163 print STDERR "driver.pl: NO_FORKER: For faster testing 'sudo cpan install Parallel::Forker'\n"; 164 } 165 print STDERR "== Many jobs; redirecting STDIN\n"; 166 open(STDIN, "+>/dev/null"); 167} 168 169mkdir "obj_dist"; 170my $timestart = strftime("%Y%m%d_%H%M%S", localtime); 171 172my $runner; 173{ 174 $runner = Runner->new( 175 driver_log_filename => "obj_dist/driver_${timestart}.log", 176 quiet => $opt_quiet); 177 foreach my $testpl (@opt_tests) { 178 foreach my $scenario (sort keys %opt_scenarios) { 179 next if !$opt_scenarios{$scenario}; 180 $runner->one_test(pl_filename => $testpl, 181 $scenario => 1); 182 } 183 } 184 $runner->wait_and_report; 185} 186 187if ($opt_rerun && $runner->fail_count) { 188 print("=" x 70, "\n"); 189 print("=" x 70, "\n"); 190 print("RERUN ==\n\n"); 191 192 # Avoid parallel run to ensure that isn't causing problems 193 # If > 10 failures something more wrong and get results quickly 194 $Fork->max_proc(1) unless $runner->fail_count > 10; 195 196 my $orig_runner = $runner; 197 $runner = Runner->new( 198 driver_log_filename => "obj_dist/driver_${timestart}_rerun.log", 199 quiet => 0, 200 fail1_cnt => $orig_runner->fail_count, 201 ok_cnt => $orig_runner->{ok_cnt}, 202 skip_cnt => $orig_runner->{skip_cnt}, 203 unsup_cnt => $orig_runner->{unsup_cnt}); 204 foreach my $test (@{$orig_runner->{fail_tests}}) { 205 $test->clean; 206 # Reschedule test 207 $runner->one_test(pl_filename => $test->{pl_filename}, 208 $test->{scenario} => 1); 209 } 210 $runner->wait_and_report; 211} 212 213exit(10) if $runner->fail_count; 214 215#---------------------------------------------------------------------- 216 217sub usage { 218 pod2usage(-verbose => 2, -exitval => 0, -output => \*STDOUT); 219 exit(1); # Unreachable 220} 221 222sub debug { 223 $Debug = 1; 224 push @Opt_Driver_Verilator_Flags, "--debug --no-skip-identical"; 225} 226 227our $_Parameter_Next_Level; 228 229sub parameter { 230 my $param = shift; 231 if ($_Parameter_Next_Level) { 232 ($param =~ /^(\d+)$/) 233 or die "%Error: Expected number following $_Parameter_Next_Level: $param\n"; 234 push @Opt_Driver_Verilator_Flags, $param; 235 $_Parameter_Next_Level = undef; 236 } 237 elsif ($param =~ /\.pl/) { 238 push @opt_tests, $param; 239 } 240 elsif ($param =~ /^-?(-debugi|-dump-treei)/) { 241 push @Opt_Driver_Verilator_Flags, $param; 242 $_Parameter_Next_Level = $param; 243 } 244 elsif ($param =~ /^-?(-W||-debug-check)/) { 245 push @Opt_Driver_Verilator_Flags, $param; 246 } 247 else { 248 die "%Error: Unknown parameter: $param\n"; 249 } 250} 251 252our $_Max_Procs; 253 254sub max_procs { 255 if (!defined $_Max_Procs) { 256 $_Max_Procs = `python3 -c 'import multiprocessing\nprint(multiprocessing.cpu_count())'`; 257 chomp $_Max_Procs; 258 if ($_Max_Procs < 2) { 259 $_Max_Procs = 2; 260 warn "driver.pl: Python didn't find at least two CPUs\n"; 261 } 262 } 263 return $_Max_Procs; 264} 265 266sub calc_threads { 267 my $default = shift; 268 my $ok = max_procs(); 269 $ok && !$@ or return $default; 270 return ($ok < $default) ? $ok : $default; 271} 272 273sub calc_jobs { 274 my $ok = max_procs(); 275 $ok && !$@ or die "%Error: Can't use -j: $@\n"; 276 print "driver.pl: Found $ok cores, using -j ", $ok + 1, "\n"; 277 return $ok + 1; 278} 279 280sub _calc_hashset { 281 my @in = @_; 282 return @in if !$opt_hashset; 283 $opt_hashset =~ m!^(\d+)/(\d+)$! 284 or die "%Error: Need number/number format for --hashset: $opt_hashset\n"; 285 my ($set, $nsets) = ($1, $2); 286 my @new; 287 foreach my $t (@opt_tests) { 288 my $checksum = unpack('L', substr(md5($t), 0, 4)); 289 if (($set % $nsets) == ($checksum % $nsets)) { 290 push @new, $t; 291 } 292 } 293 return @new; 294} 295 296####################################################################### 297####################################################################### 298####################################################################### 299####################################################################### 300# Runner class 301 302package Runner; 303use strict; 304 305sub new { 306 my $class = shift; 307 my $self = { 308 # Parameters 309 driver_log_filename => undef, 310 quiet => 0, 311 # Counts 312 all_cnt => 0, 313 left_cnt => 0, 314 ok_cnt => 0, 315 fail1_cnt => 0, 316 fail_cnt => 0, 317 skip_cnt => 0, 318 unsup_cnt => 0, 319 skip_msgs => [], 320 fail_msgs => [], 321 fail_tests => [], 322 # Per-task identifiers 323 running_ids => {}, 324 @_}; 325 bless $self, $class; 326 return $self; 327} 328 329sub fail_count { return $_[0]->{fail_cnt}; } 330 331sub one_test { 332 my $self = shift; 333 my @params = @_; 334 my %params = (@params); 335 $self->{all_cnt}++; 336 $self->{left_cnt}++; 337 $::Fork->schedule 338 ( 339 test_pl_filename => $params{pl_filename}, 340 run_pre_start => sub { 341 my $process = shift; 342 # Running in context of parent, before run_on_start 343 # Make an identifier that is unique across all current running jobs 344 my $i = 1; while (exists $self->{running_ids}{$i}) { ++$i; } 345 $process->{running_id} = $i; 346 $self->{running_ids}{$process->{running_id}} = 1; 347 }, 348 run_on_start => sub { 349 my $process = shift; 350 # Running in context of child, so can't pass data to parent directly 351 if ($self->{quiet}) { 352 open(STDOUT, ">/dev/null"); 353 open(STDERR, ">&STDOUT"); 354 } 355 print("=" x 70, "\n"); 356 my $test = VTest->new(@params, 357 running_id => $process->{running_id}); 358 $test->oprint("=" x 50, "\n"); 359 unlink $test->{status_filename}; 360 $test->_prep; 361 $test->_read; 362 # Don't put anything other than _exit after _read, 363 # as may call _exit via another path 364 $test->_exit; 365 }, 366 run_on_finish => sub { 367 # Running in context of parent 368 my $process = shift; 369 my $test = VTest->new(@params, 370 running_id => $process->{running_id}); 371 $test->_read_status; 372 if ($test->ok) { 373 $self->{ok_cnt}++; 374 } elsif ($test->scenario_off && !$test->errors) { 375 } elsif ($test->skips && !$test->errors) { 376 push @{$self->{skip_msgs}}, 377 ("\t#" . $test->soprint("-Skip: $test->{skips}\n")); 378 $self->{skip_cnt}++; 379 } elsif ($test->unsupporteds && !$test->errors) { 380 $self->{unsup_cnt}++; 381 } else { 382 $test->oprint("FAILED: $test->{errors}\n"); 383 my $j = ($opt_jobs > 1 ? " -j" : ""); 384 my $makecmd = $ENV{VERILATOR_MAKE} || "$ENV{MAKE}$j &&"; 385 my $upperdir = (Cwd::getcwd() =~ /test_regress/ 386 ? 'test_regress/' : ''); 387 push @{$self->{fail_msgs}}, 388 ("\t#" . $test->soprint("%Error: $test->{errors}\n") 389 . "\t\t$makecmd " 390 . $upperdir . $test->{pl_filename} 391 . " " . join(' ', _manual_args()) 392 . " --" . $test->{scenario} . "\n"); 393 push @{$self->{fail_tests}}, $test; 394 $self->{fail_cnt}++; 395 $self->report($self->{driver_log_filename}); 396 my $other = ""; 397 foreach my $proc ($::Fork->running) { 398 $other .= " " . $proc->{test_pl_filename}; 399 } 400 $test->oprint("Simultaneous running tests:", $other, "\n") 401 if $other && !$opt_quiet; 402 if ($opt_stop) { die "%Error: --stop and errors found\n"; } 403 } 404 $self->{left_cnt}--; 405 $self->print_summary; 406 delete $self->{running_ids}{$process->{running_id}} if $process->{running_id}; 407 }, 408 )->ready(); 409} 410 411sub wait_and_report { 412 my $self = shift; 413 $self->print_summary(force => 1); 414 # Wait for all children to finish 415 while ($::Fork->is_any_left) { 416 $::Fork->poll; 417 if ((time() - ($self->{_last_summary_time} || 0) >= 30) 418 && (!$opt_gdb && !$opt_gdbsim)) { # Don't show for interactive gdb etc 419 $self->print_summary(force => 1, show_running => 1); 420 } 421 Time::HiRes::usleep 100 * 1000; 422 } 423 $runner->report(undef); 424 $runner->report($self->{driver_log_filename}); 425} 426 427sub report { 428 my $self = shift; 429 my $filename = shift; 430 431 my $fh = \*STDOUT; 432 if ($filename) { 433 $fh = IO::File->new(">$filename") or die "%Error: $! writing $filename,"; 434 } 435 436 $fh->print("\n"); 437 $fh->print("=" x 70, "\n"); 438 foreach my $f (sort @{$self->{fail_msgs}}) { 439 chomp $f; 440 $fh->print("$f\n"); 441 } 442 foreach my $f (sort @{$self->{skip_msgs}}) { 443 chomp $f; 444 $fh->print("$f\n"); 445 } 446 my $sum = ($self->{fail_cnt} && "FAILED" 447 || $self->{skip_cnt} && "PASSED w/SKIPS" 448 || "PASSED"); 449 $fh->print("TESTS DONE, $sum: " . $self->sprint_summary . "\n"); 450} 451 452sub print_summary { 453 my $self = shift; 454 my %params = (force => 0, # Force printing 455 show_running => 0, # Show running processes 456 @_); 457 if (!$self->{quiet} || $params{force} 458 || ($self->{left_cnt} < 5) 459 || (time() - ($self->{_last_summary_time} || 0) >= 15)) { # Don't show for interactive gdb etc 460 $self->{_last_summary_time} = time(); 461 print STDERR ("==SUMMARY: " . $self->sprint_summary . "\n"); 462 if ($params{show_running}) { 463 my $other; 464 foreach my $proc ($::Fork->running) { 465 $other .= " " . $proc->{test_pl_filename}; 466 } 467 print STDERR ("==STILL RUNNING: " . $other . "\n"); 468 } 469 } 470} 471 472sub sprint_summary { 473 my $self = shift; 474 475 my $delta = time() - $::Start; 476 my $leftmsg = $::Have_Forker ? $self->{left_cnt} : "NO-FORKER"; 477 my $pct = int(100 * ($self->{left_cnt} / ($self->{all_cnt} + 0.001)) + 0.999); 478 # Fudge of 120% works out about right so ETA correctly predicts completion time 479 my $eta = 1.2 * (($self->{all_cnt} 480 * ($delta / (($self->{all_cnt} - $self->{left_cnt})+0.001))) 481 - $delta); 482 $eta = 0 if $delta < 10; 483 my $out = ""; 484 $out .= "Left $leftmsg " if $self->{left_cnt}; 485 $out .= "Passed $self->{ok_cnt}"; 486 # Ordered below most severe to least severe 487 $out .= " Failed $self->{fail_cnt}"; 488 $out .= " Failed-First $self->{fail1_cnt}" if $self->{fail1_cnt}; 489 $out .= " Skipped $self->{skip_cnt}" if $self->{skip_cnt}; 490 $out .= " Unsup $self->{unsup_cnt}"; 491 $out .= sprintf(" Eta %d:%02d", int($eta / 60), $eta % 60) if $self->{left_cnt} > 10 && $eta > 10; 492 $out .= sprintf(" Time %d:%02d", int($delta / 60), $delta % 60); 493 return $out; 494} 495 496sub _manual_args { 497 # Return command line with scenarios stripped 498 my @out; 499 arg: 500 foreach my $arg (@Orig_ARGV_Sw) { 501 foreach my $allsc (keys %All_Scenarios) { 502 foreach my $allscarg (@{$All_Scenarios{$allsc}}) { 503 next arg if ("--$allscarg" eq $arg); 504 } 505 } 506 # Also strip certain flags that per-test debugging won't want 507 next arg if $arg eq '--rerun'; 508 next arg if $arg eq '--quiet'; 509 push @out, $arg; 510 } 511 return @out; 512} 513 514####################################################################### 515####################################################################### 516####################################################################### 517####################################################################### 518# Test class 519 520package VTest; 521use Carp; 522use Cwd; 523use Data::Dumper; 524use File::Spec; 525use File::Path qw(mkpath); 526 527use vars qw($Self $Self); 528use strict; 529 530sub defineOpt { 531 my $xsim = shift; 532 return $xsim ? "--define " : "+define+"; 533} 534 535sub new { 536 my $class = shift; 537 my $self = {@_}; 538 539 $self->{name} ||= $2 if $self->{pl_filename} =~ m!^(.*/)?([^/]*)\.pl$!; 540 541 $self->{scenario} = ""; 542 $self->{scenario} ||= "dist" if $self->{dist}; 543 $self->{scenario} ||= "atsim" if $self->{atsim}; 544 $self->{scenario} ||= "ghdl" if $self->{ghdl}; 545 $self->{scenario} ||= "vcs" if $self->{vcs}; 546 $self->{scenario} ||= "vlt" if $self->{vlt}; 547 $self->{scenario} ||= "vltmt" if $self->{vltmt}; 548 $self->{scenario} ||= "nc" if $self->{nc}; 549 $self->{scenario} ||= "ms" if $self->{ms}; 550 $self->{scenario} ||= "iv" if $self->{iv}; 551 $self->{scenario} ||= "xsim" if $self->{xsim}; 552 553 foreach my $dir (@::Test_Dirs) { 554 # t_dir used both absolutely and under obj_dir 555 if (-e "$dir/$self->{name}.pl") { 556 # Note most tests require error messages of the form t/x.v 557 # Therefore pl_filename must be t/ for local tests 558 $self->{pl_filename} = File::Spec->abs2rel("$dir/$self->{name}.pl"); 559 # t_dir must be absolute - used under t or under obj_dir 560 $self->{t_dir} ||= File::Spec->rel2abs($dir); 561 last; 562 } 563 } 564 $self->{t_dir} or die "%Error: Can't locate dir for $self->{name},"; 565 566 if (!$self->{obj_dir}) { 567 my $scen_dir = File::Spec->abs2rel("$self->{t_dir}/../obj_$self->{scenario}"); 568 $scen_dir =~ s!^t/\.\./!!; # Simplify filenames on local runs 569 mkdir $scen_dir; # Not a mkpath so find out if trying to build somewhere odd 570 $self->{obj_dir} = "$scen_dir/$self->{name}"; 571 } 572 573 my $define_opt = defineOpt($self->{xsim}); 574 575 $self = { 576 name => undef, # Set below, name of this test 577 pl_filename => undef, # Name of .pl file to get setup from 578 make_top_shell => 1, # Make a default __top.v file 579 make_main => 1, # Make __main.cpp 580 make_pli => 0, # need to compile pli 581 sc_time_resolution => "SC_PS", # Keep - PS is SystemC default 582 sim_time => 1100, 583 benchmark => $opt_benchmark, 584 verbose => $opt_verbose, 585 run_env => '', 586 # All compilers 587 v_flags => [split(/\s+/, 588 (($self->{xsim} ? " -f input.xsim.vc " : 589 (-r 'input.vc' ? " -f input.vc " : "")) 590 .($self->{t_dir} !~ m!/test_regress! # Don't include standard dir, only site's 591 ? " +incdir+$self->{t_dir} -y $self->{t_dir}" : "") 592 . " " . $define_opt . "TEST_OBJ_DIR=$self->{obj_dir}" 593 .($opt_verbose ? " " . $define_opt . "TEST_VERBOSE=1" : "") 594 .($opt_benchmark ? " " . $define_opt . "TEST_BENCHMARK=$opt_benchmark" : "") 595 .($opt_trace ? " " . $define_opt . "WAVES=1" : "") 596 ))], 597 v_flags2 => [], # Overridden in some sim files 598 v_other_filenames => [], # After the filename so we can spec multiple files 599 all_run_flags => [], 600 pli_flags => ["-I$ENV{VERILATOR_ROOT}/include/vltstd -fPIC -shared" 601 . (($^O eq "darwin" ) 602 ? " -Wl,-undefined,dynamic_lookup" 603 : " -export-dynamic") 604 . ($opt_verbose ? " -DTEST_VERBOSE=1" : "") 605 . (cfg_with_m32() ? " -m32" : "") 606 . " -o $self->{obj_dir}/libvpi.so"], 607 tool_c_flags => [], 608 # ATSIM 609 atsim => 0, 610 atsim_define => 'ATSIM', 611 atsim_flags => [split(/\s+/, "-c +sv +define+ATSIM"), 612 "+sv_dir+$self->{obj_dir}/.athdl_compile"], 613 atsim_flags2 => [], # Overridden in some sim files 614 atsim_run_flags => [], 615 # GHDL 616 ghdl => 0, 617 ghdl_define => 'GHDL', 618 ghdl_work_dir => "$self->{obj_dir}/ghdl_compile", 619 ghdl_flags => [($::Debug ? "-v" : ""), 620 "--workdir=$self->{obj_dir}/ghdl_compile", ], 621 ghdl_flags2 => [], # Overridden in some sim files 622 ghdl_run_flags => [], 623 # IV 624 iv => 0, 625 iv_define => 'IVERILOG', 626 iv_flags => [split(/\s+/, "+define+IVERILOG -g2012 -o $self->{obj_dir}/simiv")], 627 iv_flags2 => [], # Overridden in some sim files 628 iv_pli => 0, # need to use pli 629 iv_run_flags => [], 630 # VCS 631 vcs => 0, 632 vcs_define => 'VCS', 633 vcs_flags => [split(/\s+/, "+vcs+lic+wait +cli -debug_access +define+VCS+1 -q -sverilog -CFLAGS '-DVCS' ")], 634 vcs_flags2 => [], # Overridden in some sim files 635 vcs_run_flags => [split(/\s+/, "+vcs+lic_wait")], 636 # NC 637 nc => 0, 638 nc_define => 'NC', 639 nc_flags => [split(/\s+/, ("+licqueue +nowarn+LIBNOU +define+NC=1 -q +assert +sv -c " 640 . ($opt_trace ? " +access+r" : "")))], 641 nc_flags2 => [], # Overridden in some sim files 642 nc_run_flags => [split(/\s+/, "+licqueue -q +assert +sv -R")], 643 # ModelSim 644 ms => 0, 645 ms_define => 'MS', 646 ms_flags => [split(/\s+/, ("-sv -work $self->{obj_dir}/work +define+MS=1 -ccflags \"-DMS=1\""))], 647 ms_flags2 => [], # Overridden in some sim files 648 ms_pli => 1, # need to use pli 649 ms_run_flags => [split(/\s+/, "-lib $self->{obj_dir}/work -c -do 'run -all;quit' ")], 650 # XSim 651 xsim => 0, 652 xsim_define => 'XSIM', 653 xsim_flags => [split(/\s+/, ("--nolog --sv --define XSIM --work $self->{name}=$self->{obj_dir}/xsim"))], 654 xsim_flags2 => [], # Overridden in some sim files 655 xsim_run_flags => [split(/\s+/, ("--nolog --runall --lib $self->{name}=$self->{obj_dir}/xsim" 656 .($opt_trace ? " --debug all" : "")))], 657 xsim_run_flags2 => [], # Overridden in some sim files 658 # Verilator 659 vlt => 0, 660 vltmt => 0, 661 verilator_define => 'VERILATOR', 662 verilator_flags => ["-cc", 663 "-Mdir $self->{obj_dir}", 664 "-OD", # As currently disabled unless -O3 665 "--debug-check", 666 "--comp-limit-members 10", ], 667 verilator_flags2 => [], 668 verilator_flags3 => ["--clk clk"], 669 verilator_make_gmake => 1, 670 verilator_make_cmake => 0, 671 verilated_debug => $Opt_Verilated_Debug, 672 stdout_filename => undef, # Redirect stdout 673 %$self}; 674 bless $self, $class; 675 676 $self->{vlt_all} = $self->{vlt} || $self->{vltmt}; # Any Verilator scenario 677 678 $self->{VM_PREFIX} ||= "V" . $self->{name}; 679 $self->{stats} ||= "$self->{obj_dir}/V" . $self->{name} . "__stats.txt"; 680 $self->{status_filename} ||= "$self->{obj_dir}/V" . $self->{name} . ".status"; 681 $self->{run_log_filename} ||= "$self->{obj_dir}/vlt_sim.log"; 682 $self->{coverage_filename} ||= "$self->{obj_dir}/coverage.dat"; 683 $self->{main_filename} ||= "$self->{obj_dir}/$self->{VM_PREFIX}__main.cpp"; 684 ($self->{top_filename} ||= $self->{pl_filename}) =~ s/\.pl$//; 685 ($self->{golden_filename} ||= $self->{pl_filename}) =~ s/\.pl$/.out/; 686 if (-e ($self->{top_filename} . ".vhd")) { # If VHDL file exists 687 $self->{vhdl} = 1; 688 $self->{top_filename} .= ".vhd"; 689 } else { 690 $self->{top_filename} .= ".v"; 691 } 692 if (!$self->{make_top_shell}) { 693 $self->{top_shell_filename} = $self->{top_filename}; 694 } else { 695 $self->{top_shell_filename} = "$self->{obj_dir}/$self->{VM_PREFIX}__top.v"; 696 } 697 $self->{pli_filename} ||= $self->{name} . ".cpp"; 698 return $self; 699} 700 701sub benchmarksim_filename { 702 my $self = (ref $_[0] ? shift : $Self); 703 return $self->{obj_dir} . "/$self->{name}_benchmarksim.csv"; 704} 705 706sub init_benchmarksim { 707 my $self = (ref $_[0] ? shift : $Self); 708 # Simulations with benchmarksim enabled append to the same file between runs. 709 # Test files must ensure a clean benchmark data file before executing tests. 710 my $filename = $self->benchmarksim_filename(); 711 my $fh = IO::File->new(">" . $filename) or die "%Error: $! " . $filename; 712 print $fh "# Verilator simulation benchmark data\n"; 713 print $fh "# Test name: " . $self->{name} . "\n"; 714 print $fh "# Top file: " . $self->{top_filename} . "\n"; 715 print $fh "evals, time[s]\n"; 716} 717 718sub soprint { 719 my $self = (ref $_[0] ? shift : $Self); 720 my $str = "$self->{scenario}/$self->{name}: " . join('', @_); 721 $str =~ s/\n\n+$/\n/s; 722 return $str; 723} 724 725sub oprint { 726 my $self = (ref $_[0] ? shift : $Self); 727 print $self->soprint(@_); 728} 729 730sub error { 731 my $self = (ref $_[0] ? shift : $Self); 732 my $msg = join('', @_); 733 # Called from tests as: error("Reason message"[, ...]); 734 warn "%Warning: $self->{scenario}/$self->{name}: " . $msg . "\n"; 735 $self->{errors} ||= $msg; 736} 737 738sub error_keep_going { 739 my $self = (ref $_[0] ? shift : $Self); 740 my $msg = join('', @_); 741 # Called from tests as: error_keep_going("Reason message"[, ...]); 742 warn "%Warning: $self->{scenario}/$self->{name}: " . $msg . "\n"; 743 $self->{errors_keep_going} ||= $msg; 744} 745 746sub skip { 747 my $self = (ref $_[0] ? shift : $Self); 748 my $msg = join('', @_); 749 # Called from tests as: skip("Reason message"[, ...]); 750 warn "-Skip: $self->{scenario}/$self->{name}: " . $msg . "\n"; 751 $self->{skips} ||= "Skip: " . $msg; 752} 753 754sub unsupported { 755 my $self = (ref $_[0] ? shift : $Self); 756 my $msg = join('', @_); 757 # Called from tests as: unsupported("Reason message"[, ...]); 758 warn "-Unsupported: $self->{scenario}/$self->{name}: " . $msg . "\n"; 759 if (!$::Opt_Unsupported) { 760 $self->{unsupporteds} ||= "Unsupported: " . $msg; 761 } 762} 763 764sub scenarios { 765 my $self = (ref $_[0] ? shift : $Self); 766 my %params = (@_); 767 # Called from tests as: scenarios(...); 768 # to specify which scenarios this test runs under. 769 # Where ... is one cases listed in All_Scenarios 770 if ((scalar keys %params) < 1) { 771 $params{simulators} = 1; 772 } 773 my %enabled_scenarios; 774 foreach my $scenario (keys %params) { 775 my $value = $params{$scenario}; 776 my $hit = 0; 777 foreach my $allsc (keys %All_Scenarios) { 778 foreach my $allscarg (@{$All_Scenarios{$allsc}}) { 779 if ($scenario eq $allscarg) { 780 $hit = 1; 781 $enabled_scenarios{$allsc} = 1; 782 } 783 } 784 } 785 if (!$hit) { 786 $self->error("scenarios('$scenario' => ...) has unknown scenario '$scenario',"); 787 } 788 } 789 790 if (!$enabled_scenarios{$self->{scenario}}) { 791 $self->skip("scenario '$self->{scenario}' not enabled for test"); 792 $self->{scenario_off} ||= 1; 793 $self->_exit(); 794 } 795} 796 797sub _prep { 798 my $self = shift; 799 mkdir $self->{obj_dir}; # Ok if already exists 800} 801 802sub _read { 803 my $self = shift; 804 # Read the control file 805 (-r $self->{pl_filename}) 806 or return $self->error("Can't open $self->{pl_filename}\n"); 807 $Self = $self; 808 delete $INC{$self->{pl_filename}}; 809 require $self->{pl_filename}; 810} 811 812sub _exit { 813 my $self = shift; 814 if ($self->ok) { 815 $self->oprint("Self PASSED\n"); 816 } elsif ($self->skips && !$self->errors) { 817 $self->oprint("-Skip: $self->{skips}\n"); 818 } elsif ($self->unsupporteds && !$self->errors) { 819 $self->oprint("%Unsupported: $self->{unsupporteds}\n"); 820 } else { 821 $self->error("Missing ok\n") if !$self->errors; 822 $self->oprint("%Error: $self->{errors}\n"); 823 } 824 $self->_write_status; 825 exit(0); 826} 827 828sub _write_status { 829 my $self = shift; 830 my $filename = $self->{status_filename}; 831 my $fh = IO::File->new(">$filename") or die "%Error: $! $filename,"; 832 $Data::Dumper::Indent = 1; 833 $Data::Dumper::Sortkeys = 1; 834 print $fh Dumper($self); 835 print $fh "1;"; 836 $fh->close(); 837} 838 839sub _read_status { 840 my $self = shift; 841 my $filename = $self->{status_filename}; 842 use vars qw($VAR1); 843 local $VAR1; 844 if (!-r $filename) { 845 $self->error("driver.pl _read_status file missing: $filename"); 846 return; 847 } 848 { 849 local %INC = (); 850 require $filename or die "%Error: $! $filename,"; 851 } 852 if ($VAR1) { 853 %{$self} = %{$VAR1}; 854 } else { 855 $self->error("driver.pl _read_status file empty: $filename"); 856 return; 857 } 858} 859 860#---------------------------------------------------------------------- 861# Methods invoked by tests 862 863sub clean { 864 my $self = (ref $_[0] ? shift : $Self); 865 # Called on a rerun to cleanup files 866 if ($self->{clean_command}) { 867 system($self->{clean_command}); 868 } 869 if (1) { 870 # Prevents false-failures when switching compilers 871 # Remove old results to force hard rebuild 872 system("rm", "-rf", "$self->{obj_dir}__fail1"); 873 system("mv", "$self->{obj_dir}", "$self->{obj_dir}__fail1"); 874 } 875} 876 877sub clean_objs { 878 my $self = (ref $_[0] ? shift : $Self); 879 system("rm", "-rf", glob("$self->{obj_dir}/*")); 880} 881 882sub compile_vlt_cmd { 883 my $self = (ref $_[0] ? shift : $Self); 884 my %param = (%{$self}, @_); # Default arguments are from $self 885 return 1 if $self->errors || $self->skips || $self->unsupporteds; 886 887 my @vlt_cmd = ( 888 "perl", "$ENV{VERILATOR_ROOT}/bin/verilator", 889 $self->compile_vlt_flags(%param), 890 $param{top_filename}, 891 @{$param{v_other_filenames}}, 892 $param{stdout_filename} ? "> " . $param{stdout_filename} : "" 893 ); 894 return @vlt_cmd; 895} 896 897sub compile_vlt_flags { 898 my $self = (ref $_[0] ? shift : $Self); 899 my %param = (%{$self}, @_); # Default arguments are from $self 900 return 1 if $self->errors || $self->skips || $self->unsupporteds; 901 902 my $checkflags = join(' ', @{$param{v_flags}}, 903 @{$param{v_flags2}}, 904 @{$param{verilator_flags}}, 905 @{$param{verilator_flags2}}, 906 @{$param{verilator_flags3}}); 907 $self->{sc} = 1 if ($checkflags =~ /-sc\b/); 908 $self->{trace} = ($opt_trace || $checkflags =~ /-trace\b/ 909 || $checkflags =~ /-trace-fst\b/); 910 $self->{trace_format} = (($checkflags =~ /-trace-fst/ && $self->{sc} && 'fst-sc') 911 || ($checkflags =~ /-trace-fst/ && !$self->{sc} && 'fst-c') 912 || ($self->{sc} && 'vcd-sc') 913 || (!$self->{sc} && 'vcd-c')); 914 $self->{savable} = 1 if ($checkflags =~ /-savable\b/); 915 $self->{coverage} = 1 if ($checkflags =~ /-coverage\b/); 916 $self->{sanitize} = $opt_sanitize unless exists($self->{sanitize}); 917 $self->{benchmarksim} = 1 if ($param{benchmarksim}); 918 919 my @verilator_flags = @{$param{verilator_flags}}; 920 unshift @verilator_flags, "--gdb" if $opt_gdb; 921 unshift @verilator_flags, "--gdbbt" if $opt_gdbbt; 922 unshift @verilator_flags, "--rr" if $opt_rr; 923 unshift @verilator_flags, "--x-assign unique"; # More likely to be buggy 924 unshift @verilator_flags, "--trace" if $opt_trace; 925 my $threads = ::calc_threads($Vltmt_threads); 926 unshift @verilator_flags, "--threads $threads" if $param{vltmt} && $checkflags !~ /-threads /; 927 unshift @verilator_flags, "--trace-threads 1" if $param{vltmt} && $checkflags =~ /-trace /; 928 unshift @verilator_flags, "--trace-threads 2" if $param{vltmt} && $checkflags =~ /-trace-fst /; 929 unshift @verilator_flags, "--debug-partition" if $param{vltmt}; 930 unshift @verilator_flags, "-CFLAGS -ggdb -LDFLAGS -ggdb" if $opt_gdbsim; 931 unshift @verilator_flags, "-CFLAGS -fsanitize=address,undefined -LDFLAGS -fsanitize=address,undefined" if $param{sanitize}; 932 unshift @verilator_flags, "--make gmake" if $param{verilator_make_gmake}; 933 unshift @verilator_flags, "--make cmake" if $param{verilator_make_cmake}; 934 unshift @verilator_flags, "--exe" if 935 $param{make_main} && $param{verilator_make_gmake}; 936 unshift @verilator_flags, "../" . $self->{main_filename} if 937 $param{make_main} && $param{verilator_make_gmake}; 938 if (defined $opt_optimize) { 939 my $letters = ""; 940 if ($opt_optimize =~ /[a-zA-Z]/) { 941 $letters = $opt_optimize; 942 } else { # Randomly turn on/off different optimizations 943 foreach my $l ('a' .. 'z') { 944 $letters .= ((rand() > 0.5) ? $l : uc $l); 945 } 946 unshift @verilator_flags, "--trace" if rand() > 0.5; 947 unshift @verilator_flags, "--coverage" if rand() > 0.5; 948 } 949 unshift @verilator_flags, "--O" . $letters; 950 } 951 952 my @cmdargs = ( 953 "--prefix " . $param{VM_PREFIX}, 954 @verilator_flags, 955 @{$param{verilator_flags2}}, 956 @{$param{verilator_flags3}}, 957 @{$param{v_flags}}, 958 @{$param{v_flags2}}, 959 # Flags from driver cmdline override default flags and 960 # flags from the test itself 961 driver_verilator_flags(), 962 ); 963 return @cmdargs; 964} 965 966sub driver_verilator_flags { 967 # my $self = (ref $_[0] ? shift : $Self); 968 return @Opt_Driver_Verilator_Flags; 969} 970 971sub lint { 972 my $self = (ref $_[0] ? shift : $Self); 973 my %param = (# 974 %{$self}, # Default arguments are from $self 975 # Lint specific default overrides 976 make_main => 0, 977 make_top_shell => 0, 978 verilator_flags2 => ["--lint-only"], 979 verilator_make_gmake => 0, 980 @_); 981 $self->compile(%param); 982} 983 984sub compile { 985 my $self = (ref $_[0] ? shift : $Self); 986 my %param = (tee => 1, 987 %{$self}, @_); # Default arguments are from $self 988 return 1 if $self->errors || $self->skips || $self->unsupporteds; 989 $self->oprint("Compile\n") if $self->{verbose}; 990 991 compile_vlt_cmd(%param); 992 993 if (!$param{make_top_shell}) { 994 $param{top_shell_filename} 995 = $self->{top_shell_filename} = ""; 996 } else { 997 $param{top_shell_filename} 998 = $self->{top_shell_filename} = "$self->{obj_dir}/$self->{VM_PREFIX}__top." . $self->v_suffix; 999 } 1000 1001 if ($param{atsim}) { 1002 $param{tool_define} ||= $param{atsim_define}; 1003 $self->_make_top() if $param{make_top_shell}; 1004 $self->_run(logfile=>"$self->{obj_dir}/atsim_compile.log", 1005 fails=>$param{fails}, 1006 cmd=>[($ENV{VERILATOR_ATSIM} || "atsim"), 1007 @{$param{atsim_flags}}, 1008 @{$param{atsim_flags2}}, 1009 @{$param{v_flags}}, 1010 @{$param{v_flags2}}, 1011 $param{top_filename}, 1012 $param{top_shell_filename}, 1013 @{$param{v_other_filenames}}, 1014 ]); 1015 } 1016 elsif ($param{ghdl}) { 1017 $param{tool_define} ||= $param{ghdl_define}; 1018 mkdir $self->{ghdl_work_dir}; 1019 $self->_make_top() if $param{make_top_shell}; 1020 $self->_run(logfile=>"$self->{obj_dir}/ghdl_compile.log", 1021 fails=>$param{fails}, 1022 cmd=>[($ENV{VERILATOR_GHDL} || "ghdl"), 1023 # Add -c here, as having -c twice freaks it out 1024 ((($ENV{VERILATOR_GHDL} || ' ') =~ / -c\b/) ? "" : "-c"), 1025 @{$param{ghdl_flags}}, 1026 @{$param{ghdl_flags2}}, 1027 #@{$param{v_flags}}, # Not supported 1028 #@{$param{v_flags2}}, # Not supported 1029 $param{top_filename}, 1030 $param{top_shell_filename}, 1031 @{$param{v_other_filenames}}, 1032 "-e t", 1033 ]); 1034 } 1035 elsif ($param{vcs}) { 1036 $param{tool_define} ||= $param{vcs_define}; 1037 $self->_make_top() if $param{make_top_shell}; 1038 $self->_run(logfile=>"$self->{obj_dir}/vcs_compile.log", 1039 fails=>$param{fails}, 1040 cmd=>[($ENV{VERILATOR_VCS} || "vcs"), 1041 @{$param{vcs_flags}}, 1042 @{$param{vcs_flags2}}, 1043 ($opt_verbose ? " -CFLAGS -DTEST_VERBOSE=1" : ""), 1044 @{$param{v_flags}}, 1045 @{$param{v_flags2}}, 1046 $param{top_filename}, 1047 $param{top_shell_filename}, 1048 @{$param{v_other_filenames}}, 1049 ]); 1050 } 1051 elsif ($param{nc}) { 1052 $param{tool_define} ||= $param{nc_define}; 1053 $self->_make_top() if $param{make_top_shell}; 1054 my @more_args; 1055 if ($self->vhdl) { 1056 ((my $ts = $param{top_shell_filename}) =~ s!\.v!!); 1057 $ts =~ s!.*/!!; 1058 push @more_args, "-vhdltop", $ts; 1059 } 1060 $self->_run(logfile=>"$self->{obj_dir}/nc_compile.log", 1061 fails=>$param{fails}, 1062 cmd=>[($ENV{VERILATOR_NCVERILOG} || "ncverilog"), 1063 @{$param{nc_flags}}, 1064 @{$param{nc_flags2}}, 1065 @{$param{v_flags}}, 1066 @{$param{v_flags2}}, 1067 $param{top_filename}, 1068 $param{top_shell_filename}, 1069 @{$param{v_other_filenames}}, 1070 @more_args 1071 ]); 1072 } 1073 elsif ($param{ms}) { 1074 $param{tool_define} ||= $param{ms_define}; 1075 $self->_make_top() if $param{make_top_shell}; 1076 $self->_run(logfile=>"$self->{obj_dir}/ms_compile.log", 1077 fails=>$param{fails}, 1078 cmd=>[("vlib $self->{obj_dir}/work && "), 1079 ($ENV{VERILATOR_MODELSIM} || "vlog"), 1080 @{$param{ms_flags}}, 1081 @{$param{ms_flags2}}, 1082 @{$param{v_flags}}, 1083 @{$param{v_flags2}}, 1084 $param{top_filename}, 1085 $param{top_shell_filename}, 1086 @{$param{v_other_filenames}} 1087 ]); 1088 } 1089 elsif ($param{iv}) { 1090 $param{tool_define} ||= $param{iv_define}; 1091 $self->_make_top() if $param{make_top_shell}; 1092 my @cmd = (($ENV{VERILATOR_IVERILOG} || "iverilog"), 1093 @{$param{iv_flags}}, 1094 @{$param{iv_flags2}}, 1095 @{$param{v_flags}}, 1096 @{$param{v_flags2}}, 1097 $param{top_filename}, 1098 $param{top_shell_filename}, 1099 @{$param{v_other_filenames}}); 1100 @cmd = grep { s/\+define\+/-D /g; $_; } @cmd; 1101 1102 $self->_run(logfile=>"$self->{obj_dir}/iv_compile.log", 1103 fails=>$param{fails}, 1104 cmd=>\@cmd); 1105 } 1106 elsif ($param{xsim}) { 1107 $param{tool_define} ||= $param{xsim_define}; 1108 $self->_make_top() if $param{make_top_shell}; 1109 $self->_run(logfile=>"$self->{obj_dir}/xsim_compile.log", 1110 fails=>$param{fails}, 1111 cmd=>[($ENV{VERILATOR_XVLOG} || "xvlog"), 1112 @{$param{xsim_flags}}, 1113 @{$param{xsim_flags2}}, 1114 @{$param{v_flags}}, 1115 @{$param{v_flags2}}, 1116 $param{top_filename}, 1117 $param{top_shell_filename}, 1118 @{$param{v_other_filenames}} 1119 ]); 1120 } 1121 elsif ($param{vlt_all}) { 1122 $param{tool_define} ||= $param{verilator_define}; 1123 1124 if ($self->sc && !$self->have_sc) { 1125 $self->skip("Test requires SystemC; ignore error since not installed\n"); 1126 return 1; 1127 } 1128 1129 if ($self->{vltmt} && !$self->cfg_with_threaded) { 1130 $self->skip("Test requires Verilator configured with threads\n"); 1131 return 1; 1132 } 1133 1134 if ($param{verilator_make_cmake} && !$self->have_cmake) { 1135 $self->skip("Test requires CMake; ignore error since not available or version too old\n"); 1136 return 1; 1137 } 1138 1139 if (!$param{fails} && $param{make_main}) { 1140 $self->_make_main(); 1141 } 1142 1143 if ($param{verilator_make_gmake} 1144 || (!$param{verilator_make_gmake} && !$param{verilator_make_cmake})) { 1145 my @vlt_cmd = $self->compile_vlt_cmd(%param); 1146 $self->oprint("Running Verilator (gmake)\n") if $self->{verbose}; 1147 $self->_run(logfile => "$self->{obj_dir}/vlt_compile.log", 1148 fails => $param{fails}, 1149 tee => $param{tee}, 1150 expect => $param{expect}, 1151 expect_filename => $param{expect_filename}, 1152 verilator_run => 1, 1153 cmd => \@vlt_cmd) if $::Opt_Verilation; 1154 return 1 if $self->errors || $self->skips || $self->unsupporteds; 1155 } 1156 1157 if ($param{verilator_make_cmake}) { 1158 my @vlt_args = $self->compile_vlt_flags(%param); 1159 $self->oprint("Running cmake\n") if $self->{verbose}; 1160 mkdir $self->{obj_dir}; 1161 my @csources = (); 1162 unshift @csources, $self->{main_filename} if $param{make_main}; 1163 $self->_run(logfile => "$self->{obj_dir}/vlt_cmake.log", 1164 fails => $param{fails}, 1165 tee => $param{tee}, 1166 expect => $param{expect}, 1167 expect_filename => $param{expect_filename}, 1168 verilator_run => 1, 1169 cmd => ["cd \"" . $self->{obj_dir} . "\" && cmake", 1170 "\"" . $self->{t_dir} . "/..\"", 1171 "-DTEST_VERILATOR_ROOT=$ENV{VERILATOR_ROOT}", 1172 "-DTEST_NAME=$self->{name}", 1173 "-DTEST_CSOURCES=\"@csources\"", 1174 "-DTEST_VERILATOR_ARGS=\"@vlt_args\"", 1175 "-DTEST_VERILATOR_SOURCES=\"$param{top_filename} @{$param{v_other_filenames}}\"", 1176 "-DTEST_VERBOSE=\"" . ($self->{verbose} ? 1 : 0) . "\"", 1177 "-DTEST_SYSTEMC=\"" . ($self->sc ? 1 : 0) . "\"", 1178 "-DCMAKE_PREFIX_PATH=\"" . (($ENV{SYSTEMC_INCLUDE} || $ENV{SYSTEMC} || '') . "/..\""), 1179 "-DTEST_OPT_FAST=\"" . ($param{benchmark} ? "-Os" : "-O0") . "\"", 1180 "-DTEST_OPT_GLOBAL=\"" . ($param{benchmark} ? "-Os" : "-O0") . "\"", 1181 "-DTEST_VERILATION=\"" . $::Opt_Verilation . "\"", 1182 ]); 1183 return 1 if $self->errors || $self->skips || $self->unsupporteds; 1184 } 1185 1186 if (!$param{fails} && $param{verilator_make_gmake}) { 1187 $self->oprint("Running make (gmake)\n") if $self->{verbose}; 1188 $self->_run(logfile => "$self->{obj_dir}/vlt_gcc.log", 1189 entering => "$self->{obj_dir}", 1190 cmd => [$ENV{MAKE}, 1191 "-C " . $self->{obj_dir}, 1192 "-f " . $FindBin::RealBin . "/Makefile_obj", 1193 ($self->{verbose} ? "" : "--no-print-directory"), 1194 "VM_PREFIX=$self->{VM_PREFIX}", 1195 "TEST_OBJ_DIR=$self->{obj_dir}", 1196 "CPPFLAGS_DRIVER=-D" . uc($self->{name}), 1197 ($self->{verbose} ? "CPPFLAGS_DRIVER2=-DTEST_VERBOSE=1" : ""), 1198 ($param{benchmark} ? "" : "OPT_FAST=-O0"), 1199 ($param{benchmark} ? "" : "OPT_GLOBAL=-O0"), 1200 "$self->{VM_PREFIX}", # bypass default rule, as we don't need archive 1201 ($param{make_flags} || ""), 1202 ]); 1203 } 1204 1205 if (!$param{fails} && $param{verilator_make_cmake}) { 1206 $self->oprint("Running cmake --build\n") if $self->{verbose}; 1207 $self->_run(logfile => "$self->{obj_dir}/vlt_cmake_build.log", 1208 cmd => ["cmake", 1209 "--build", $self->{obj_dir}, 1210 ($self->{verbose} ? "--verbose" : ""), 1211 ]); 1212 } 1213 } 1214 else { 1215 $self->error("No compile step defined for '$self->{scenario}' scenario"); 1216 } 1217 1218 if ($param{make_pli}) { 1219 $self->oprint("Compile vpi\n") if $self->{verbose}; 1220 my @cmd = ($ENV{CXX}, @{$param{pli_flags}}, 1221 "-D" . $param{tool_define}, 1222 "-DIS_VPI", ($ENV{CFLAGS} || ''), 1223 "$self->{t_dir}/$self->{pli_filename}"); 1224 1225 $self->_run(logfile=>"$self->{obj_dir}/pli_compile.log", 1226 fails=>$param{fails}, 1227 cmd=>\@cmd); 1228 } 1229 1230 return 1; 1231} 1232 1233sub execute { 1234 my $self = (ref $_[0] ? shift : $Self); 1235 return 1 if $self->errors || $self->skips || $self->unsupporteds; 1236 my %param = (%{$self}, @_); # Default arguments are from $self 1237 # params may be expect or {tool}_expect 1238 $self->oprint("Run\n") if $self->{verbose}; 1239 1240 delete $ENV{SYSTEMC_DISABLE_COPYRIGHT_MESSAGE}; 1241 $ENV{SYSTEMC_DISABLE_COPYRIGHT_MESSAGE} = "DISABLE" if !$self->{verbose}; 1242 1243 my $run_env = $param{run_env}; 1244 $run_env .= ' ' if $run_env; 1245 1246 if ($param{atsim}) { 1247 $self->_run(logfile=>"$self->{obj_dir}/atsim_sim.log", 1248 fails=>$param{fails}, 1249 cmd=>["echo q | " . $run_env . "$self->{obj_dir}/athdl_sv", 1250 @{$param{atsim_run_flags}}, 1251 @{$param{all_run_flags}}, 1252 ], 1253 %param, 1254 expect=>$param{atsim_run_expect}, # non-verilator expect isn't the same 1255 expect_filename=>$param{atsim_run_expect_filename}, 1256 ); 1257 } 1258 elsif ($param{ghdl}) { 1259 $self->_run(logfile=>"$self->{obj_dir}/ghdl_sim.log", 1260 fails=>$param{fails}, 1261 cmd=>[$run_env . "$self->{obj_dir}/simghdl", 1262 @{$param{ghdl_run_flags}}, 1263 @{$param{all_run_flags}}, 1264 ], 1265 %param, 1266 expect=>$param{ghdl_run_expect}, # non-verilator expect isn't the same 1267 expect_filename=>$param{ghdl_run_expect_filename}, 1268 ); 1269 } 1270 elsif ($param{iv}) { 1271 my @cmd = ($run_env . "$self->{obj_dir}/simiv", 1272 @{$param{iv_run_flags}}, 1273 @{$param{all_run_flags}}, 1274 ); 1275 if ($param{use_libvpi}) { 1276 # don't enter command line on $stop, include vpi 1277 unshift @cmd, "vvp -n -m $self->{obj_dir}/libvpi.so"; 1278 } 1279 $self->_run(logfile=>"$self->{obj_dir}/iv_sim.log", 1280 fails=>$param{fails}, 1281 cmd=> \@cmd, 1282 %param, 1283 expect=>$param{iv_run_expect}, # non-verilator expect isn't the same 1284 expect_filename=>$param{iv_run_expect_filename}, 1285 ); 1286 } 1287 elsif ($param{ms}) { 1288 my @pli_opt = (); 1289 if ($param{use_libvpi}) { 1290 unshift @pli_opt, "-pli $self->{obj_dir}/libvpi.so"; 1291 } 1292 $self->_run(logfile=>"$self->{obj_dir}/ms_sim.log", 1293 fails=>$param{fails}, 1294 cmd=>["echo q | " . $run_env . ($ENV{VERILATOR_MODELSIM} || "vsim"), 1295 @{$param{ms_run_flags}}, 1296 @{$param{all_run_flags}}, 1297 @{pli_opt}, 1298 (" top") 1299 ], 1300 %param, 1301 expect=>$param{ms_run_expect}, # non-verilator expect isn't the same 1302 expect_filename=>$param{ms_expect_filename}, 1303 ); 1304 } 1305 elsif ($param{nc}) { 1306 $self->_run(logfile=>"$self->{obj_dir}/nc_sim.log", 1307 fails=>$param{fails}, 1308 cmd=>["echo q | " . $run_env . ($ENV{VERILATOR_NCVERILOG} || "ncverilog"), 1309 @{$param{nc_run_flags}}, 1310 @{$param{all_run_flags}}, 1311 ], 1312 %param, 1313 expect=>$param{nc_run_expect}, # non-verilator expect isn't the same 1314 expect_filename=>$param{nc_run_expect_filename}, 1315 ); 1316 } 1317 elsif ($param{vcs}) { 1318 #my $fh = IO::File->new(">simv.key") or die "%Error: $! simv.key,"; 1319 #$fh->print("quit\n"); $fh->close; 1320 $self->_run(logfile=>"$self->{obj_dir}/vcs_sim.log", 1321 cmd=>["echo q | " . $run_env . "./simv", 1322 @{$param{vcs_run_flags}}, 1323 @{$param{all_run_flags}}, 1324 ], 1325 %param, 1326 expect=>$param{vcs_run_expect}, # non-verilator expect isn't the same 1327 expect_filename=>$param{vcs_run_expect_filename}, 1328 ); 1329 } 1330 elsif ($param{xsim}) { 1331 $self->_run(logfile=>"$self->{obj_dir}/xsim_sim.log", 1332 fails=>$param{fails}, 1333 cmd=>[$run_env.($ENV{VERILATOR_XELAB} || "xelab"), 1334 @{$param{xsim_run_flags}}, 1335 @{$param{xsim_run_flags2}}, 1336 @{$param{all_run_flags}}, 1337 (" $self->{name}.top") 1338 ], 1339 %param, 1340 expect=>$param{xsim_run_expect}, # non-verilator expect isn't the same 1341 expect_filename=>$param{xsim_expect_filename}, 1342 ); 1343 } 1344 elsif ($param{vlt_all} 1345 #&& (!$param{needs_v4} || -r "$ENV{VERILATOR_ROOT}/src/V3Gate.cpp") 1346 ) { 1347 $param{executable} ||= "$self->{obj_dir}/$param{VM_PREFIX}"; 1348 my $debugger = ""; 1349 if ($opt_gdbsim) { 1350 $debugger = ($ENV{VERILATOR_GDB} || "gdb") . " "; 1351 } elsif ($opt_rrsim) { 1352 $debugger = "rr record "; 1353 } 1354 $self->_run(logfile=>"$self->{obj_dir}/vlt_sim.log", 1355 cmd=>[($run_env 1356 .$debugger 1357 .$param{executable} 1358 .($opt_gdbsim ? " -ex 'run " : "")), 1359 @{$param{all_run_flags}}, 1360 ($opt_gdbsim ? "'" : ""), 1361 ], 1362 %param, 1363 expect=>$param{expect}, # backward compatible name 1364 expect_filename=>$param{expect_filename}, # backward compatible name 1365 ); 1366 } 1367 else { 1368 $self->error("No execute step for this simulator"); 1369 } 1370} 1371 1372sub setenv { 1373 my $self = (ref $_[0] ? shift : $Self); 1374 my $var = shift; 1375 my $val = shift; 1376 print "\texport $var='$val'\n"; 1377 $ENV{$var} = $val; 1378} 1379 1380sub inline_checks { 1381 my $self = (ref $_[0] ? shift : $Self); 1382 return 1 if $self->errors || $self->skips || $self->unsupporteds; 1383 return 1 if !$self->{vlt_all}; 1384 1385 my %param = (%{$self}, @_); # Default arguments are from $self 1386 1387 my $covfn = $Self->{coverage_filename}; 1388 my $contents = $self->file_contents($covfn); 1389 1390 $self->oprint("Extract checks\n") if $self->{verbose}; 1391 my $fh = IO::File->new("<$self->{top_filename}"); 1392 while (defined(my $line = $fh->getline)) { 1393 if ($line =~ /CHECK/) { 1394 if ($line =~ /CHECK_COVER *\( *([---0-9]+) *, *"([^"]+)" *, *("([^"]+)" *,|) *(\d+) *\)/) { 1395 my $lineno = ($. + $1); my $hier = $2; my $comment = $4; my $count = $5; 1396 my $regexp = "\001l\002" . $lineno; 1397 $regexp .= ".*\001o\002" . quotemeta($comment) if $comment; 1398 $regexp .= ".*\001h\002" . quotemeta($hier) if $hier; 1399 $regexp .= ".*' " . $count; 1400 if ($contents !~ /$regexp/) { 1401 $self->error("CHECK_COVER: $covfn: Regexp not found: $regexp\n" . 1402 "From $self->{top_filename}:$.: $line"); 1403 } 1404 } 1405 elsif ($line =~ /CHECK_COVER_MISSING *\( *([---0-9]+) *\)/) { 1406 my $lineno = ($. + $1); 1407 my $regexp = "\001l\002" . $lineno; 1408 if ($contents =~ /$regexp/) { 1409 $self->error("CHECK_COVER_MISSING: $covfn: Regexp found: $regexp\n" . 1410 "From $self->{top_filename}:$.: $line"); 1411 } 1412 } 1413 else { 1414 $self->error("$self->{top_filename}:$.: Unknown CHECK request: $line"); 1415 } 1416 } 1417 } 1418 $fh->close; 1419} 1420 1421#---------------------------------------------------------------------- 1422# Accessors 1423 1424sub ok { 1425 my $self = (ref $_[0] ? shift : $Self); 1426 $self->{ok} = $_[0] if defined $_[0]; 1427 $self->{ok} = 0 if $self->{errors} || $self->{errors_keep_going} || $self->{skips} || $self->unsupporteds; 1428 return $self->{ok}; 1429} 1430 1431sub continuing { 1432 my $self = (ref $_[0] ? shift : $Self); 1433 return !($self->errors || $self->skips || $self->unsupporteds); 1434} 1435 1436sub errors { 1437 my $self = (ref $_[0] ? shift : $Self); 1438 return $self->{errors}; 1439} 1440 1441sub golden_filename { 1442 my $self = (ref $_[0] ? shift : $Self); 1443 $self->{golden_filename} = shift if defined $_[0]; 1444 return $self->{golden_filename}; 1445} 1446 1447sub scenario_off { 1448 my $self = (ref $_[0] ? shift : $Self); 1449 return $self->{scenario_off}; 1450} 1451 1452sub skips { 1453 my $self = (ref $_[0] ? shift : $Self); 1454 return $self->{skips}; 1455} 1456 1457sub unsupporteds { 1458 my $self = (ref $_[0] ? shift : $Self); 1459 return $self->{unsupporteds}; 1460} 1461 1462sub top_filename { 1463 my $self = (ref $_[0] ? shift : $Self); 1464 $self->{top_filename} = shift if defined $_[0]; 1465 return $self->{top_filename}; 1466} 1467 1468sub vhdl { 1469 my $self = (ref $_[0] ? shift : $Self); 1470 $self->{vhdl} = shift if defined $_[0]; 1471 if ($self->{vhdl}) { 1472 $self->{top_filename} =~ s/\.v$/\.vhdl/; 1473 } 1474 return $self->{vhdl}; 1475} 1476 1477sub v_suffix { 1478 my $self = (ref $_[0] ? shift : $Self); 1479 # Suffix for file type, e.g. .vhdl or .v 1480 return $self->{vhdl} ? "vhdl" : "v"; 1481} 1482 1483sub sc { 1484 my $self = (ref $_[0] ? shift : $Self); 1485 return $self->{sc}; 1486} 1487 1488sub have_sc { 1489 my $self = (ref $_[0] ? shift : $Self); 1490 return 1 if (defined $ENV{SYSTEMC} || defined $ENV{SYSTEMC_INCLUDE} || $ENV{CFG_HAVE_SYSTEMC}); 1491 return 1 if $self->verilator_version =~ /systemc found *= *1/i; 1492 return 0; 1493} 1494 1495sub make_version { 1496 my $ver = `$ENV{MAKE} --version`; 1497 if ($ver =~ /make ([0-9]+\.[0-9]+)/i) { 1498 return $1; 1499 } else { 1500 return -1; 1501 } 1502} 1503 1504sub have_cmake { 1505 return cmake_version() >= version->declare("3.8"); 1506} 1507 1508sub cmake_version { 1509 chomp(my $cmake_bin = `which cmake`); 1510 if (!$cmake_bin) { 1511 return undef; 1512 } 1513 my $cmake_version = `cmake --version`; 1514 if ($cmake_version !~ /cmake version (\d+)\.(\d+)/) { 1515 return undef; 1516 } 1517 $cmake_version = "$1.$2"; 1518 return version->declare($cmake_version); 1519} 1520 1521sub trace_filename { 1522 my $self = shift; 1523 return "$self->{obj_dir}/simx.fst" if $self->{trace_format} =~ /^fst/; 1524 return "$self->{obj_dir}/simx.vcd"; 1525} 1526 1527sub obj_dir { 1528 my $self = shift; 1529 return $self->{obj_dir}; 1530} 1531 1532sub get_default_vltmt_threads { 1533 return $Vltmt_threads; 1534} 1535 1536sub pli_filename { 1537 my $self = (ref $_[0] ? shift : $Self); 1538 $self->{pli_filename} = shift if defined $_[0]; 1539 return $self->{pli_filename}; 1540} 1541 1542sub too_few_cores { 1543 my $threads = ::calc_threads($Vltmt_threads); 1544 return $threads < $Vltmt_threads; 1545} 1546 1547sub skip_if_too_few_cores { 1548 my $self = (ref $_[0] ? shift : $Self); 1549 if (too_few_cores()) { 1550 $self->skip("Skipping due to too few cores\n"); 1551 } 1552} 1553 1554sub wno_unopthreads_for_few_cores { 1555 if (too_few_cores()) { 1556 warn "Too few cores, using -Wno-UNOPTTHREADS\n"; 1557 return "-Wno-UNOPTTHREADS"; 1558 } 1559 return ""; 1560} 1561 1562sub VM_PREFIX { 1563 my $self = (ref $_[0] ? shift : $Self); 1564 $self->{VM_PREFIX} = shift if defined $_[0]; 1565 return $self->{VM_PREFIX}; 1566} 1567 1568#---------------------------------------------------------------------- 1569 1570sub run { 1571 my $self = (ref $_[0] ? shift : $Self); 1572 $self->_run(@_); 1573} 1574 1575sub _run { 1576 my $self = (ref $_[0] ? shift : $Self); 1577 my %param = (tee => 1, 1578 #entering => # Print entering directory information 1579 #verilator_run => # Move gcov data to parallel area 1580 @_); 1581 1582 my $command = join(' ', @{$param{cmd}}); 1583 $command = "time $command" if $opt_benchmark && $command !~ /^cd /; 1584 1585 if ($param{verilator_run}) { 1586 # Gcov fails when parallel jobs write same data file, 1587 # so we make sure .gcda output dir is unique across all running jobs. 1588 # We can't just put each one in a unique obj_dir as it uses too much disk. 1589 # Must use absolute path as some execute()s have different PWD 1590 $ENV{GCOV_PREFIX_STRIP} = 99; 1591 $ENV{GCOV_PREFIX} = File::Spec->rel2abs("$FindBin::RealBin/obj_dist/gcov_$self->{running_id}"); 1592 mkdir $ENV{GCOV_PREFIX}; 1593 print "export GCOV_PREFIX_STRIP=99 GCOV_PREFIX=$ENV{GCOV_PREFIX}\n" if $self->{verbose}; 1594 } else { 1595 delete $ENV{GCOV_PREFIX_STRIP}; 1596 delete $ENV{GCOV_PREFIX}; 1597 } 1598 1599 print "\t$command"; 1600 print " > $param{logfile}" if $param{logfile}; 1601 print "\n"; 1602 1603 # Execute command redirecting output, keeping order between stderr and stdout. 1604 # Must do low-level IO so GCC interaction works (can't be line-based) 1605 my $status; 1606 { 1607 pipe(PARENTRD, CHILDWR) or die "%Error: Can't Pipe, stopped"; 1608 autoflush PARENTRD 1; 1609 autoflush CHILDWR 1; 1610 my $logfh; 1611 if ($param{logfile}) { 1612 $logfh = IO::File->new(">$param{logfile}") or die "%Error: Can't open $param{logfile}"; 1613 } 1614 my $pid = fork(); 1615 if ($pid) { # Parent 1616 close CHILDWR; 1617 print "driver: Entering directory '", 1618 File::Spec->rel2abs($param{entering}), "'\n" if $param{entering}; 1619 while (1) { 1620 my $buf = ''; 1621 my $got = sysread PARENTRD, $buf, 10000; 1622 last if defined $got && $got == 0; 1623 print $buf if $param{tee}; 1624 print $logfh $buf if $logfh; 1625 } 1626 close PARENTRD; 1627 close $logfh if $logfh; 1628 print "driver: Leaving directory '", 1629 File::Spec->rel2abs($param{entering}), "'\n" if $param{entering}; 1630 } 1631 else { # Child 1632 close PARENTRD; 1633 close $logfh if $logfh; 1634 # Reset signals 1635 $SIG{ALRM} = 'DEFAULT'; 1636 $SIG{CHLD} = 'DEFAULT'; 1637 # Logging 1638 open(STDOUT, ">&CHILDWR") or croak "%Error: Can't redirect stdout, stopped"; 1639 open(STDERR, ">&STDOUT") or croak "%Error: Can't dup stdout, stopped"; 1640 autoflush STDOUT 1; 1641 autoflush STDERR 1; 1642 system "$command"; 1643 my $status = $?; 1644 if (($status & 127) == 4 # SIGILL 1645 || ($status & 127) == 8 # SIGFPA 1646 || ($status & 127) == 11) { # SIGSEGV 1647 $Self->error("Exec failed with core dump"); 1648 } 1649 exit($? ? 10 : 0); # $?>>8 misses coredumps 1650 } 1651 waitpid($pid, 0); 1652 $status = $? || 0; 1653 } 1654 flush STDOUT; 1655 flush STDERR; 1656 1657 if (!$param{fails} && $status) { 1658 my $firstline = ""; 1659 if (my $fh = IO::File->new("<$param{logfile}")) { 1660 $firstline = $fh->getline || ''; 1661 chomp $firstline; 1662 } 1663 $self->error("Exec of $param{cmd}[0] failed: $firstline\n"); 1664 } 1665 if ($param{fails} && $status) { 1666 print "(Exec expected to fail, and did.)\n"; 1667 } 1668 if ($param{fails} && !$status) { 1669 $self->error("Exec of $param{cmd}[0] ok, but expected to fail\n"); 1670 } 1671 return if $self->errors || $self->skips || $self->unsupporteds; 1672 1673 # Read the log file a couple of times to allow for NFS delays 1674 if ($param{check_finished} || $param{expect}) { 1675 for (my $try = $self->tries - 1; $try >= 0; $try--) { 1676 sleep 1 if ($try != $self->tries - 1); 1677 my $moretry = $try != 0; 1678 1679 my $fh = IO::File->new("<$param{logfile}"); 1680 next if !$fh && $moretry; 1681 local $/; undef $/; 1682 my $wholefile = <$fh>; 1683 $fh->close(); 1684 1685 # Finished? 1686 if ($param{check_finished} && $wholefile !~ /\*\-\* All Finished \*\-\*/) { 1687 next if $moretry; 1688 $self->error("Missing All Finished\n"); 1689 } 1690 if ($param{expect}) { 1691 # Strip debugging comments 1692 # See also files_identical 1693 $wholefile =~ s/^- [^\n]+\n//mig; 1694 $wholefile =~ s/^- [a-z.0-9]+:\d+:[^\n]+\n//mig; 1695 $wholefile =~ s/^dot [^\n]+\n//mig; 1696 1697 # Compare 1698 my $quoted = quotemeta($param{expect}); 1699 my $ok = ($wholefile eq $param{expect} 1700 || _try_regex($wholefile, $param{expect}) == 1 1701 || $wholefile =~ /$quoted/ms); 1702 if (!$ok) { 1703 #print "**BAD $self->{name} $param{logfile} MT $moretry $try\n"; 1704 next if $moretry; 1705 $self->error("Miscompares in output from $param{cmd}[0]\n"); 1706 $self->error("Might be error in regexp format\n") if $ok < 1; 1707 print "GOT:\n"; 1708 print $wholefile; 1709 print "ENDGOT\n"; 1710 print "EXPECT:\n"; 1711 print $param{expect}; 1712 print "ENDEXPECT\n"; 1713 } 1714 } 1715 last; 1716 } 1717 } 1718 if ($param{expect_filename}) { 1719 files_identical($param{logfile}, $param{expect_filename}, 'logfile'); 1720 } 1721} 1722 1723####################################################################### 1724# Little utilities 1725 1726sub _try_regex { 1727 # Try to eval a regexp 1728 # Returns: 1729 # 1 if $text ~= /$regex/ms 1730 # 0 if no match 1731 # -1 if $regex is invalid, doesn't compile 1732 my ($text, $regex) = @_; 1733 my $result; 1734 { 1735 local $@; 1736 eval { 1737 $result = ($text =~ /$regex/ms); 1738 }; 1739 $result = -1 if $@; 1740 } 1741 return $result; 1742} 1743 1744sub _make_main { 1745 my $self = shift; 1746 1747 if ($self->vhdl) { 1748 $self->_read_inputs_vhdl(); 1749 } else { 1750 $self->_read_inputs_v(); 1751 } 1752 1753 my $filename = $self->{main_filename}; 1754 my $fh = IO::File->new(">$filename") or die "%Error: $! $filename,"; 1755 1756 print $fh "// Test defines\n"; 1757 print $fh "#define MAIN_TIME_MULTIPLIER " . ($self->{main_time_multiplier} || 1) . "\n"; 1758 1759 print $fh "#include <memory>\n"; 1760 print $fh "#include <fstream>\n" if $self->{benchmarksim}; 1761 print $fh "#include <chrono>\n" if $self->{benchmarksim}; 1762 print $fh "#include <iomanip>\n" if $self->{benchmarksim}; 1763 1764 print $fh "// OS header\n"; 1765 print $fh "#include \"verilatedos.h\"\n"; 1766 1767 print $fh "// Generated header\n"; 1768 my $VM_PREFIX = $self->{VM_PREFIX}; 1769 print $fh "#include \"$VM_PREFIX.h\"\n"; 1770 1771 print $fh "// General headers\n"; 1772 print $fh "#include \"verilated.h\"\n"; 1773 print $fh "#include \"systemc.h\"\n" if $self->sc; 1774 print $fh "#include \"verilated_fst_c.h\"\n" if $self->{trace} && $self->{trace_format} eq 'fst-c'; 1775 print $fh "#include \"verilated_fst_sc.h\"\n" if $self->{trace} && $self->{trace_format} eq 'fst-sc'; 1776 print $fh "#include \"verilated_vcd_c.h\"\n" if $self->{trace} && $self->{trace_format} eq 'vcd-c'; 1777 print $fh "#include \"verilated_vcd_sc.h\"\n" if $self->{trace} && $self->{trace_format} eq 'vcd-sc'; 1778 print $fh "#include \"verilated_save.h\"\n" if $self->{savable}; 1779 1780 print $fh "std::unique_ptr<$VM_PREFIX> topp;\n"; 1781 1782 if ($self->{savable}) { 1783 $fh->print("\n"); 1784 $fh->print("void save_model(const char* filenamep) {\n"); 1785 $fh->print(" VL_PRINTF(\"Saving model to '%s'\\n\", filenamep);\n"); 1786 $fh->print(" VerilatedSave os;\n"); 1787 $fh->print(" os.open(filenamep);\n"); 1788 $fh->print(" os << *topp;\n"); 1789 $fh->print(" os.close();\n"); 1790 $fh->print("}\n"); 1791 $fh->print("\n"); 1792 $fh->print("void restore_model(const char* filenamep) {\n"); 1793 $fh->print(" VL_PRINTF(\"Restoring model from '%s'\\n\", filenamep);\n"); 1794 $fh->print(" VerilatedRestore os;\n"); 1795 $fh->print(" os.open(filenamep);\n"); 1796 $fh->print(" os >> *topp;\n"); 1797 $fh->print(" os.close();\n"); 1798 $fh->print("}\n"); 1799 } 1800 1801 #### Main 1802 if ($self->sc) { 1803 print $fh "extern int sc_main(int argc, char** argv);\n"; 1804 print $fh "int sc_main(int argc, char** argv) {\n"; 1805 print $fh " sc_signal<bool> fastclk;\n" if $self->{inputs}{fastclk}; 1806 print $fh " sc_signal<bool> clk;\n" if $self->{inputs}{clk}; 1807 print $fh " sc_set_time_resolution(1, $Self->{sc_time_resolution});\n"; 1808 print $fh " sc_time sim_time($self->{sim_time}, $Self->{sc_time_resolution});\n"; 1809 } else { 1810 print $fh "int main(int argc, char** argv, char** env) {\n"; 1811 print $fh " vluint64_t sim_time = $self->{sim_time};\n"; 1812 } 1813 1814 print $fh " const std::unique_ptr<VerilatedContext> contextp{new VerilatedContext};\n"; 1815 print $fh " contextp->commandArgs(argc, argv);\n"; 1816 print $fh " contextp->debug(" . ($self->{verilated_debug} ? 1 : 0) . ");\n"; 1817 print $fh " srand48(5);\n"; # Ensure determinism 1818 print $fh " contextp->randReset(" . $self->{verilated_randReset} . ");\n" 1819 if defined $self->{verilated_randReset}; 1820 print $fh " topp.reset(new $VM_PREFIX(\"top\"));\n"; 1821 print $fh " contextp->internalsDump()\n;" if $self->{verilated_debug}; 1822 1823 my $set; 1824 if ($self->sc) { 1825 print $fh " topp->fastclk(fastclk);\n" if $self->{inputs}{fastclk}; 1826 print $fh " topp->clk(clk);\n" if $self->{inputs}{clk}; 1827 $set = ""; 1828 } else { 1829 print $fh " topp->eval();\n"; 1830 $set = "topp->"; 1831 } 1832 1833 if ($self->{benchmarksim}) { 1834 $fh->print(" std::chrono::time_point<std::chrono::steady_clock> starttime;\n"); 1835 $fh->print(" bool warm = false;\n"); 1836 $fh->print(" uint64_t n_evals = 0;\n"); 1837 } 1838 1839 if ($self->{trace}) { 1840 $fh->print("\n"); 1841 $fh->print("#if VM_TRACE\n"); 1842 $fh->print(" contextp->traceEverOn(true);\n"); 1843 $fh->print(" std::unique_ptr<VerilatedFstC> tfp{new VerilatedFstC};\n") if $self->{trace_format} eq 'fst-c'; 1844 $fh->print(" std::unique_ptr<VerilatedFstSc> tfp{new VerilatedFstSc};\n") if $self->{trace_format} eq 'fst-sc'; 1845 $fh->print(" std::unique_ptr<VerilatedVcdC> tfp{new VerilatedVcdC};\n") if $self->{trace_format} eq 'vcd-c'; 1846 $fh->print(" std::unique_ptr<VerilatedVcdSc> tfp{new VerilatedVcdSc};\n") if $self->{trace_format} eq 'vcd-sc'; 1847 $fh->print(" topp->trace(tfp.get(), 99);\n"); 1848 $fh->print(" tfp->open(\"" . $self->trace_filename . "\");\n"); 1849 1850 if ($self->{trace} && !$self->sc) { 1851 $fh->print(" if (tfp) tfp->dump(contextp->time());\n"); 1852 } 1853 $fh->print("#endif\n"); 1854 } 1855 1856 if ($self->{savable}) { 1857 $fh->print(" const char* save_time_strp = contextp->commandArgsPlusMatch(\"save_time=\");\n"); 1858 $fh->print(" unsigned int save_time = !save_time_strp[0] ? 0 : atoi(save_time_strp+strlen(\"+save_time=\"));\n"); 1859 $fh->print(" const char* save_restore_strp = contextp->commandArgsPlusMatch(\"save_restore=\");\n"); 1860 $fh->print(" unsigned int save_restore = !save_restore_strp[0] ? 0 : 1;\n"); 1861 } 1862 1863 if ($self->{savable}) { 1864 $fh->print(" if (save_restore) {\n"); 1865 $fh->print(" restore_model(\"$self->{obj_dir}/saved.vltsv\");\n"); 1866 $fh->print(" } else {\n"); 1867 } else { 1868 $fh->print(" {\n"); 1869 } 1870 print $fh " ${set}fastclk = false;\n" if $self->{inputs}{fastclk}; 1871 print $fh " ${set}clk = false;\n" if $self->{inputs}{clk}; 1872 _print_advance_time($self, $fh, 10); 1873 print $fh " }\n"; 1874 1875 my $time = $self->sc ? "sc_time_stamp()" : "contextp->time()"; 1876 1877 print $fh " while ((${time} < sim_time * MAIN_TIME_MULTIPLIER)\n"; 1878 print $fh " && !contextp->gotFinish()) {\n"; 1879 1880 for (my $i = 0; $i < 5; $i++) { 1881 my $action = 0; 1882 if ($self->{inputs}{fastclk}) { 1883 print $fh " ${set}fastclk = !${set}fastclk;\n"; 1884 $action = 1; 1885 } 1886 if ($i == 0 && $self->{inputs}{clk}) { 1887 print $fh " ${set}clk = !${set}clk;\n"; 1888 $action = 1; 1889 } 1890 if ($self->{savable}) { 1891 $fh->print(" if (save_time && ${time} == save_time) {\n"); 1892 $fh->print(" save_model(\"$self->{obj_dir}/saved.vltsv\");\n"); 1893 $fh->print(" printf(\"Exiting after save_model\\n\");\n"); 1894 $fh->print(" return 0;\n"); 1895 $fh->print(" }\n"); 1896 } 1897 _print_advance_time($self, $fh, 1, $action); 1898 } 1899 if ($self->{benchmarksim}) { 1900 $fh->print(" if (VL_UNLIKELY(!warm)) {\n"); 1901 $fh->print(" starttime = std::chrono::steady_clock::now();\n"); 1902 $fh->print(" warm = true;\n"); 1903 $fh->print(" } else {\n"); 1904 $fh->print(" ++n_evals;\n"); 1905 $fh->print(" }\n"); 1906 } 1907 print $fh " }\n"; 1908 1909 if ($self->{benchmarksim}) { 1910 $fh->print(" {\n"); 1911 $fh->print(" const std::chrono::duration<double> exec_s = std::chrono::steady_clock::now() - starttime;\n"); 1912 $fh->print(" std::ofstream benchfile(\"" . $self->benchmarksim_filename() . "\", std::ofstream::out | std::ofstream::app);\n"); 1913 $fh->print(" benchfile << std::fixed << std::setprecision(9) << n_evals << \",\" << exec_s.count() << std::endl;\n"); 1914 $fh->print(" benchfile.close();\n"); 1915 $fh->print(" }\n"); 1916 } 1917 1918 print $fh " if (!contextp->gotFinish()) {\n"; 1919 print $fh ' vl_fatal(__FILE__, __LINE__, "main", "%Error: Timeout; never got a $finish");', "\n"; 1920 print $fh " }\n"; 1921 print $fh " topp->final();\n"; 1922 1923 if ($self->{coverage}) { 1924 $fh->print("#if VM_COVERAGE\n"); 1925 $fh->print(" VerilatedCov::write(\"", $self->{coverage_filename}, "\");\n"); 1926 $fh->print("#endif // VM_COVERAGE\n"); 1927 } 1928 if ($self->{trace}) { 1929 $fh->print("#if VM_TRACE\n"); 1930 $fh->print(" if (tfp) tfp->close();\n"); 1931 $fh->print(" tfp.reset();\n"); 1932 $fh->print("#endif // VM_TRACE\n"); 1933 } 1934 $fh->print("\n"); 1935 1936 print $fh " topp.reset();\n"; 1937 print $fh " return 0;\n"; 1938 print $fh "}\n"; 1939 $fh->close(); 1940} 1941 1942sub _print_advance_time { 1943 my $self = shift; 1944 my $fh = shift; 1945 my $time = shift; 1946 my $action = shift; 1947 1948 my $set; 1949 if ($self->sc) { $set = ""; } 1950 else { $set = "topp->"; } 1951 1952 if ($self->sc) { 1953 print $fh " sc_start(${time}, $Self->{sc_time_resolution});\n"; 1954 } else { 1955 if ($action) { 1956 print $fh " ${set}eval();\n"; 1957 if ($self->{trace} && !$self->sc) { 1958 $fh->print("#if VM_TRACE\n"); 1959 $fh->print(" if (tfp) tfp->dump(contextp->time());\n"); 1960 $fh->print("#endif // VM_TRACE\n"); 1961 } 1962 } 1963 print $fh " contextp->timeInc(${time} * MAIN_TIME_MULTIPLIER);\n"; 1964 } 1965} 1966 1967####################################################################### 1968 1969sub _make_top { 1970 my $self = shift; 1971 if ($self->vhdl) { 1972 $self->_make_top_vhdl; 1973 } else { 1974 $self->_make_top_v; 1975 } 1976} 1977 1978sub _make_top_v { 1979 my $self = shift; 1980 1981 $self->_read_inputs_v(); 1982 1983 my $fh = IO::File->new(">$self->{top_shell_filename}") 1984 or die "%Error: $! $self->{top_shell_filename},"; 1985 print $fh "module top;\n"; 1986 foreach my $inp (sort (keys %{$self->{inputs}})) { 1987 print $fh " reg ${inp};\n"; 1988 } 1989 # Inst 1990 print $fh " t t (\n"; 1991 my $comma = ""; 1992 foreach my $inp (sort (keys %{$self->{inputs}})) { 1993 print $fh " ${comma}.${inp} (${inp})\n"; 1994 $comma = ","; 1995 } 1996 print $fh " );\n"; 1997 1998 # Waves 1999 print $fh "\n"; 2000 print $fh "`ifdef WAVES\n"; 2001 print $fh " initial begin\n"; 2002 print $fh " \$display(\"-Tracing Waves to Dumpfile: " . $self->trace_filename . "\");\n"; 2003 print $fh " \$dumpfile(\"" . $self->trace_filename . "\");\n"; 2004 print $fh " \$dumpvars(0, top);\n"; 2005 print $fh " end\n"; 2006 print $fh "`endif\n"; 2007 2008 # Test 2009 print $fh "\n"; 2010 print $fh " initial begin\n"; 2011 print $fh " fastclk = 0;\n" if $self->{inputs}{fastclk}; 2012 print $fh " clk = 0;\n" if $self->{inputs}{clk}; 2013 print $fh " #10;\n"; 2014 print $fh " fastclk = 1;\n" if $self->{inputs}{fastclk}; 2015 print $fh " clk = 1;\n" if $self->{inputs}{clk}; 2016 print $fh " while (\$time < $self->{sim_time}) begin\n"; 2017 for (my $i = 0; $i < 5; $i++) { 2018 print $fh " #1;\n"; 2019 print $fh " fastclk = !fastclk;\n" if $self->{inputs}{fastclk}; 2020 print $fh " clk = !clk;\n" if $i == 4 && $self->{inputs}{clk}; 2021 } 2022 print $fh " end\n"; 2023 print $fh " end\n"; 2024 2025 print $fh "endmodule\n"; 2026 $fh->close(); 2027} 2028 2029sub _make_top_vhdl { 2030 my $self = shift; 2031 2032 $self->_read_inputs_vhdl(); 2033 2034 my $fh = IO::File->new(">$self->{top_shell_filename}") or die "%Error: $! $self->{top_shell_filename},"; 2035 print $fh "library ieee;\n"; 2036 2037 my @ports = sort (keys %{$self->{inputs}}); 2038 2039 print $fh "entity t_ent is\n"; 2040 if ($#ports >= 0) { 2041 print $fh " port(\n"; 2042 my $semi = ""; 2043 foreach my $inp (@ports) { 2044 print $fh " ${semi}${inp} : in std_logic\n"; 2045 $semi = ";"; 2046 } 2047 print $fh " );\n"; 2048 } 2049 print $fh "end;\n"; 2050 2051 print $fh "entity top is\n"; 2052 print $fh "end;\n"; 2053 2054 # Inst 2055 print $fh "architecture t_beh of t_ent is\n"; 2056 if ($#ports >= 0) { 2057 foreach my $inp (@ports) { 2058 print $fh " signal ${inp} : std_logic := '0';\n"; 2059 } 2060 } 2061 print $fh " begin\n"; 2062 2063 print $fh " t : t_ent\n"; 2064 if ($#ports >= 0) { 2065 print $fh " port map(\n"; 2066 my $comma = ""; 2067 foreach my $inp (@ports) { 2068 print $fh "\t${comma}${inp} => ${inp}\n"; 2069 $comma = ","; 2070 } 2071 print $fh " )\n"; 2072 } 2073 print $fh " ;\n"; 2074 2075 print $fh " end;\n"; 2076 2077 # Waves TBD 2078 # Test TBD 2079 2080 print $fh "end;\n"; 2081 $fh->close(); 2082} 2083 2084####################################################################### 2085 2086sub _read_inputs_v { 2087 my $self = shift; 2088 my $filename = $self->top_filename; 2089 $filename = "$self->{t_dir}/$filename" if !-r $filename; 2090 my $fh = IO::File->new("<$filename") or die "%Error: $! $filename,"; 2091 my $get_sigs = 1; 2092 my %inputs; 2093 while (defined(my $line = $fh->getline)) { 2094 if ($get_sigs) { 2095 if ($line =~ /^\s*input\s*(\S+)\s*(\/[^\/]+\/|)\s*;/) { 2096 $inputs{$1} = $1; 2097 } 2098 if ($line =~ /^\s*(function|task|endmodule)/) { 2099 $get_sigs = 0; 2100 } 2101 } 2102 if ($line =~ /^\s*module\s+t\b/) { # Ignore any earlier inputs; Module 't' has precedence 2103 %inputs = (); 2104 $get_sigs = 1; 2105 } 2106 } 2107 $self->{inputs}{$_} = $inputs{$_} foreach keys %inputs; 2108 $fh->close(); 2109} 2110 2111####################################################################### 2112 2113sub _read_inputs_vhdl { 2114 my $self = shift; 2115 my $filename = $self->top_filename; 2116 $filename = "$self->{t_dir}/$filename" if !-r $filename; 2117 my $fh = IO::File->new("<$filename") or die "%Error: $! $filename,"; 2118 while (defined(my $line = $fh->getline)) { 2119 # Only supports this form right now: 2120 # signal: in ... 2121 # signal: out ... 2122 if ($line =~ /^\s*(\S+)\s*:\s*(in)\b\s*/) { 2123 $self->{inputs}{$1} = $1; 2124 } 2125 if ($line =~ /^\s*(architecture)/) { 2126 last; 2127 } 2128 } 2129 $fh->close(); 2130} 2131 2132####################################################################### 2133# Verilator utilities 2134 2135our $_Verilator_Version; 2136sub verilator_version { 2137 # Returns verbose version, line 1 contains actual version 2138 if (!defined $_Verilator_Version) { 2139 my @args = ("perl", "$ENV{VERILATOR_ROOT}/bin/verilator", "-V"); 2140 my $args = join(' ', @args); 2141 $_Verilator_Version = `$args`; 2142 $_Verilator_Version or die "can't fork: $! " . join(' ', @args); 2143 chomp $_Verilator_Version; 2144 } 2145 return $_Verilator_Version if defined $_Verilator_Version; 2146} 2147 2148####################################################################### 2149# File utilities 2150 2151sub files_identical { 2152 my $self = (ref $_[0] ? shift : $Self); 2153 my $fn1 = shift; 2154 my $fn2 = shift; 2155 my $fn1_is_logfile = shift; 2156 return 1 if $self->errors || $self->skips || $self->unsupporteds; 2157 2158 try: 2159 for (my $try = $self->tries - 1; $try >= 0; $try--) { 2160 sleep 1 if ($try != $self->tries - 1); 2161 my $moretry = $try != 0; 2162 2163 my $f1 = IO::File->new("<$fn1"); 2164 my $f2 = IO::File->new("<$fn2"); 2165 if (!$f1) { 2166 next try if $moretry; 2167 $self->error("Files_identical file does not exist $fn1\n"); 2168 return 0; 2169 } 2170 if (!$f2 && !$ENV{HARNESS_UPDATE_GOLDEN}) { 2171 next try if $moretry; 2172 $self->error("Files_identical file does not exist $fn2\n"); 2173 return 0; 2174 } 2175 my @l1 = $f1 && $f1->getlines(); 2176 my @l2 = $f2 && $f2->getlines(); 2177 if ($fn1_is_logfile) { 2178 @l1 = grep { 2179 !/^- [^\n]+\n/ 2180 && !/^- [a-z.0-9]+:\d+:[^\n]+\n/ 2181 && !/^-node:/ 2182 && !/^dot [^\n]+\n/ 2183 && !/^In file: .*\/sc_.*:\d+/ 2184 && !/^libgcov.*/ 2185 && !/--- \/tmp\// # t_difftree.pl 2186 && !/\+\+\+ \/tmp\// # t_difftree.pl 2187 } @l1; 2188 @l1 = map { 2189 s/(Internal Error: [^\n]+\.cpp):[0-9]+:/$1:#:/; 2190 s/^-V\{t[0-9]+,[0-9]+\}/-V{t#,#}/; # --vlt vs --vltmt run differences 2191 $_; 2192 } @l1; 2193 for (my $l = 0; $l <= $#l1; ++$l) { 2194 # Don't put control chars into our source repository 2195 $l1[$l] =~ s/\r/<#013>/mig; 2196 $l1[$l] =~ s/Command Failed[^\n]+/Command Failed/mig; 2197 $l1[$l] =~ s/Version: Verilator[^\n]+/Version: Verilator ###/mig; 2198 $l1[$l] =~ s/CPU Time: +[0-9.]+ seconds[^\n]+/CPU Time: ###/mig; 2199 $l1[$l] =~ s/\?v=[0-9.]+/?v=latest/mig; # warning URL 2200 $l1[$l] =~ s/_h[0-9a-f]{8}_/_h########_/mg; 2201 if ($l1[$l] =~ s/Exiting due to.*/Exiting due to/mig) { 2202 splice @l1, $l+1; # Trunc rest 2203 last; 2204 } 2205 } 2206 } 2207 my $nl = $#l1; $nl = $#l2 if ($#l2 > $nl); 2208 for (my $l=0; $l<=$nl; ++$l) { 2209 if (($l1[$l] || "") ne ($l2[$l] || "")) { 2210 next try if $moretry; 2211 $self->error_keep_going("Line " . ($l+1) . " miscompares; $fn1 != $fn2"); 2212 warn("F1: " . ($l1[$l] || "*EOF*\n") 2213 . "F2: " . ($l2[$l] || "*EOF*\n")); 2214 if ($ENV{HARNESS_UPDATE_GOLDEN}) { # Update golden files with current 2215 warn "%Warning: HARNESS_UPDATE_GOLDEN set: cp $fn1 $fn2\n"; 2216 my $fhw = IO::File->new(">$fn2") or $self->error("Files_identical $! $fn2\n"); 2217 $fhw->print(join('', @l1)); 2218 } else { 2219 warn "To update reference: HARNESS_UPDATE_GOLDEN=1 {command} or --golden\n"; 2220 } 2221 return 0; 2222 } 2223 } 2224 return 1; 2225 } 2226} 2227 2228sub files_identical_sorted { 2229 my $self = (ref $_[0] ? shift : $Self); 2230 my $fn1 = shift; 2231 my $fn2 = shift; 2232 my $fn1_is_logfile = shift; 2233 return 1 if $self->errors || $self->skips || $self->unsupporteds; 2234 # Set LC_ALL as suggested in the sort manpage to avoid sort order 2235 # changes from the locale. 2236 setenv('LC_ALL', "C"); 2237 my $fn1sort = "$fn1.sort"; 2238 run(cmd => ["sort", "$fn1", "> $fn1sort"]); 2239 return $self->files_identical($fn1sort, $fn2, $fn1_is_logfile); 2240} 2241 2242sub copy_if_golden { 2243 my $self = (ref $_[0] ? shift : $Self); 2244 my $fn1 = shift; 2245 my $fn2 = shift; 2246 if ($ENV{HARNESS_UPDATE_GOLDEN}) { # Update golden files with current 2247 warn "%Warning: HARNESS_UPDATE_GOLDEN set: cp $fn1 $fn2\n"; 2248 eval "use File::Copy;"; 2249 File::Copy::copy($fn1, $fn2); 2250 } 2251} 2252 2253sub vcd_identical { 2254 my $self = (ref $_[0] ? shift : $Self); 2255 my $fn1 = shift; 2256 my $fn2 = shift; 2257 return 0 if $self->errors || $self->skips || $self->unsupporteds; 2258 if (!-r $fn1) { $self->error("Vcd_identical file does not exist $fn1\n"); return 0; } 2259 if (!-r $fn2) { $self->error("Vcd_identical file does not exist $fn2\n"); return 0; } 2260 { 2261 # vcddiff to check transitions, if installed 2262 my $cmd = qq{vcddiff --help}; 2263 print "\t$cmd\n" if $::Debug; 2264 my $out = `$cmd`; 2265 if (!$out || $out !~ /Usage:/) { $self->skip("No vcddiff installed\n"); return 1; } 2266 2267 $cmd = qq{vcddiff "$fn1" "$fn2"}; 2268 print "\t$cmd\n" if $::Debug; 2269 $out = `$cmd`; 2270 if ($? != 0 || $out ne '') { 2271 print $out; 2272 $self->error("VCD miscompares $fn1 $fn2\n"); 2273 $self->copy_if_golden($fn1, $fn2); 2274 return 0; 2275 } 2276 } 2277 { 2278 # vcddiff doesn't check module and variable scope, so check that 2279 # Also provides backup if vcddiff not installed 2280 my $h1 = $self->_vcd_read($fn1); 2281 my $h2 = $self->_vcd_read($fn2); 2282 $Data::Dumper::Sortkeys = 1; 2283 my $a = Dumper($h1); 2284 my $b = Dumper($h2); 2285 if ($a ne $b) { 2286 print "$a\n$b\n" if $::Debug; 2287 $self->error("VCD hier miscompares $fn1 $fn2\n"); 2288 $self->copy_if_golden($fn1, $fn2); 2289 return 0; 2290 } 2291 } 2292 return 1; 2293} 2294 2295sub fst2vcd { 2296 my $self = (ref $_[0] ? shift : $Self); 2297 my $fn1 = shift; 2298 my $fn2 = shift; 2299 if (!-r $fn1) { $self->error("File does not exist $fn1\n"); return 0; } 2300 my $cmd = qq{fst2vcd -h}; 2301 print "\t$cmd\n" if $::Debug; 2302 my $out = `$cmd`; 2303 if (!$out || $out !~ /Usage:/) { $self->skip("No fst2vcd installed\n"); return 1; } 2304 2305 $cmd = qq{fst2vcd -e -f "$fn1" -o "$fn2"}; 2306 print "\t$cmd\n"; # Always print to help debug race cases 2307 $out = `$cmd`; 2308 return 1; 2309} 2310 2311sub fst_identical { 2312 my $self = (ref $_[0] ? shift : $Self); 2313 my $fn1 = shift; 2314 my $fn2 = shift; 2315 return 0 if $self->errors || $self->skips || $self->unsupporteds; 2316 my $tmp = $fn1 . ".vcd"; 2317 fst2vcd($fn1, $tmp); 2318 return vcd_identical($tmp, $fn2); 2319} 2320 2321sub _vcd_read { 2322 my $self = (ref $_[0] ? shift : $Self); 2323 my $filename = shift; 2324 my $data = {}; 2325 my $fh = IO::File->new("<$filename"); 2326 if (!$fh) { warn "%Error: $! $filename\n"; return $data; } 2327 my @hier = ($data); 2328 my $lasthier; 2329 while (defined(my $line = $fh->getline)) { 2330 if ($line =~ /\$scope (module|struct|interface)\s+(\S+)/) { 2331 $hier[$#hier]->{$1} ||= {}; 2332 push @hier, $hier[$#hier]->{$1}; 2333 $lasthier = $hier[$#hier]; 2334 } elsif ($line =~ /(\$var \S+\s+\d+\s+)\S+\s+(\S+)/) { 2335 $hier[$#hier]->{$1 . $2} ||= {}; 2336 $lasthier = $hier[$#hier]; 2337 } elsif ($line =~ /(\$attrbegin .* \$end)/) { 2338 if ($lasthier) { $lasthier->{$1} ||= 1; } 2339 } elsif ($line =~ /\$enddefinitions/) { 2340 last; 2341 } 2342 while ($line =~ s/\$upscope//) { 2343 pop @hier; 2344 $lasthier = undef; 2345 } 2346 } 2347 return $data; 2348} 2349 2350our $_Cxx_Version; 2351 2352sub cxx_version { 2353 $_Cxx_Version ||= `$ENV{MAKE} -C $ENV{VERILATOR_ROOT}/test_regress -f Makefile print-cxx-version`; 2354 return $_Cxx_Version; 2355} 2356 2357sub cfg_with_threaded { 2358 return 1; # C++11 now always required 2359} 2360 2361our $_Cfg_with_ccache; 2362 2363sub cfg_with_ccache { 2364 $_Cfg_with_ccache ||= `grep "OBJCACHE \?= ccache" "$ENV{VERILATOR_ROOT}/include/verilated.mk"` ne ""; 2365 return $_Cfg_with_ccache; 2366} 2367 2368our $_Cfg_with_m32; 2369 2370sub cfg_with_m32 { 2371 $_Cfg_with_m32 ||= `grep "CXX.*=.*-m32" "$ENV{VERILATOR_ROOT}/include/verilated.mk"` ne ""; 2372 return $_Cfg_with_m32; 2373} 2374 2375sub tries { 2376 # Number of retries when reading logfiles, generally only need many 2377 # retries when system is busy running a lot of tests 2378 return 2 if !$::Fork->running; 2379 return 7 if (scalar($::Fork->running)) > 1; 2380 return 2; 2381} 2382 2383sub glob_all { 2384 my $self = (ref $_[0] ? shift : $Self); 2385 my $pattern = shift; 2386 2387 return glob($pattern); 2388} 2389 2390sub glob_one { 2391 my $self = (ref $_[0] ? shift : $Self); 2392 my $pattern = shift; 2393 return if $self->errors || $self->skips || $self->unsupporteds; 2394 2395 my @files = glob($pattern); 2396 my $n = scalar @files; 2397 if ($n == 0) { 2398 $self->error("glob_one: pattern '$pattern' does not match any files\n"); 2399 } elsif ($n != 1) { 2400 my $msg = "glob_one: pattern '$pattern' matches multiple files:\n"; 2401 foreach my $file (@files) { 2402 $msg .= $file . "\n"; 2403 } 2404 $self->error($msg); 2405 } else { 2406 return $files[0]; 2407 } 2408} 2409 2410sub file_grep_not { 2411 my $self = (ref $_[0] ? shift : $Self); 2412 my $filename = shift; 2413 my $regexp = shift; 2414 my $expvalue = shift; 2415 return if $self->errors || $self->skips || $self->unsupporteds; 2416 !defined $expvalue or $self->error("file_grep_not: Unexpected 3rd argument: $expvalue"); 2417 2418 my $contents = $self->file_contents($filename); 2419 return if ($contents eq "_Already_Errored_"); 2420 if ($contents =~ /$regexp/) { 2421 $self->error("File_grep_not: $filename: Regexp found: $regexp\n"); 2422 } 2423} 2424 2425sub file_grep { 2426 my $self = (ref $_[0] ? shift : $Self); 2427 my $filename = shift; 2428 my $regexp = shift; 2429 my $expvalue = shift; 2430 return if $self->errors || $self->skips || $self->unsupporteds; 2431 2432 my $contents = $self->file_contents($filename); 2433 return if ($contents eq "_Already_Errored_"); 2434 if ($contents !~ /$regexp/) { 2435 $self->error("File_grep: $filename: Regexp not found: $regexp\n"); 2436 } elsif ($expvalue && $expvalue ne $1) { 2437 $self->error("File_grep: $filename: Got='$1' Expected='$expvalue' in regexp: $regexp\n"); 2438 } 2439} 2440 2441sub file_grep_any { 2442 my $self = $Self; 2443 my @filenames = @{$_[0]}; shift; 2444 my $regexp = shift; 2445 my $expvalue = shift; 2446 return if $self->errors || $self->skips || $self->unsupporteds; 2447 2448 foreach my $filename (@filenames) { 2449 my $contents = $self->file_contents($filename); 2450 return if ($contents eq "_Already_Errored_"); 2451 if ($contents =~ /$regexp/) { 2452 if ($expvalue && $expvalue ne $1) { 2453 $self->error("file_grep: $filename: Got='$1' Expected='$expvalue' in regexp: $regexp\n"); 2454 } 2455 return; 2456 } 2457 } 2458 my $msg = "file_grep_any: Regexp '$regexp' not found in any of the following files:\n"; 2459 foreach my $filename (@filenames) { 2460 $msg .= $filename . "\n"; 2461 } 2462 $self->error($msg); 2463} 2464 2465my %_File_Contents_Cache; 2466 2467sub file_contents { 2468 my $self = (ref $_[0] ? shift : $Self); 2469 my $filename = shift; 2470 2471 if (!$_File_Contents_Cache{$filename}) { 2472 my $fh = IO::File->new("<$filename"); 2473 if (!$fh) { 2474 $_File_Contents_Cache{$filename} = "_Already_Errored_"; 2475 $self->error("File_grep file not found: " . $filename . "\n"); 2476 return $_File_Contents_Cache{$filename}; 2477 } 2478 local $/; undef $/; 2479 my $wholefile = <$fh>; 2480 $fh->close(); 2481 $_File_Contents_Cache{$filename} = $wholefile; 2482 } 2483 2484 return $_File_Contents_Cache{$filename}; 2485} 2486 2487sub write_wholefile { 2488 my $self = (ref $_[0] ? shift : $Self); 2489 my $filename = shift; 2490 my $contents = shift; 2491 my $fh = IO::File->new(">$filename") or die "%Error: $! writing $filename,"; 2492 print $fh $contents; 2493 $fh->close; 2494 delete $_File_Contents_Cache{$filename}; 2495} 2496 2497sub file_sed { 2498 my $self = (ref $_[0] ? shift : $Self); 2499 my $infilename = shift; 2500 my $outfilename = shift; 2501 my $editcb = shift; 2502 my $contents = $self->file_contents($infilename); 2503 { 2504 $_ = $contents; 2505 $editcb->($contents); 2506 $contents = $_; 2507 } 2508 $self->write_wholefile($outfilename, $contents); 2509} 2510 2511sub extract { 2512 my $self = (ref $_[0] ? shift : $Self); 2513 my %param = ( #in =>, 2514 #out => 2515 regexp => qr/.*/, 2516 lineno_adjust => -9999, 2517 lines => undef, #'#, #-#', 2518 @_); 2519 2520 my $temp_fn = $param{out}; 2521 $temp_fn =~ s!.*/!!g; 2522 $temp_fn = $self->{obj_dir} . "/" . $temp_fn; 2523 2524 my @out; 2525 my $emph = ""; 2526 my $lineno = 0; 2527 my $lineno_out = 0; 2528 { 2529 my $fh = IO::File->new("<$param{in}") or die "%Error: $! $param{in},"; 2530 while (defined(my $line = $fh->getline)) { 2531 ++$lineno; 2532 if ($line =~ /$param{regexp}/ 2533 && _lineno_match($lineno, $param{lines})) { 2534 if ($line =~ m!t/[A-Za-z0-9_]+.v:(\d+):(\d+):!) { 2535 my $lineno = $1; 2536 my $col = $2; 2537 $lineno += $param{lineno_adjust}; 2538 $lineno = 1 if $lineno < 1; 2539 $line =~ s!t/[A-Za-z0-9_]+.v:(\d+):(\d+):!example.v:${lineno}:${col}!; 2540 } 2541 push @out, " " . $line; 2542 ++$lineno_out; 2543 if ($line =~ /<--/) { 2544 $emph .= "," if $emph; 2545 $emph .= $lineno_out; 2546 } 2547 } 2548 } 2549 } 2550 { 2551 my $fhw = IO::File->new(">$temp_fn") or die "%Error: $! $temp_fn,"; 2552 my $lang = ""; 2553 $lang = " sv" if $param{in} =~ /\.s?vh?$/; 2554 $fhw->print(".. comment: generated by " . $self->{name} . "\n"); 2555 $fhw->print(".. code-block::${lang}\n"); 2556 $fhw->print(" :linenos:\n") if $lang && $#out > 0; 2557 $fhw->print(" :emphasize-lines: ${emph}\n") if $emph; 2558 $fhw->print("\n"); 2559 2560 foreach my $line (@out) { 2561 $fhw->print($line); 2562 } 2563 } 2564 2565 $self->files_identical($temp_fn, $param{out}); 2566} 2567 2568sub _lineno_match { 2569 my $lineno = shift; 2570 my $lines = shift; 2571 return 1 if !defined $lines; 2572 foreach my $lc (split /,/, $lines) { 2573 if ($lc =~ /^(\d+)$/) { 2574 return 1 if $1 == $lineno; 2575 } elsif ($lc =~ /^(\d+)-(\d+)$/) { 2576 return 1 if $1 <= $lineno && $2 >= $lineno; 2577 } 2578 } 2579 return 0; 2580} 2581 2582####################################################################### 2583####################################################################### 2584####################################################################### 2585####################################################################### 2586# Forker class 2587 2588package Forker; 2589use strict; 2590 2591# This is a shell that matches Parallel::Forker. 2592# If that package is not installed, this runs the tests in *series* 2593 2594sub new { 2595 my $class = shift; 2596 my $self = {@_}; 2597 bless $self, $class; 2598 return $self; 2599} 2600 2601sub schedule { 2602 my $self = shift; 2603 my %params = (@_); 2604 2605 $params{run_pre_start}->($self); 2606 if (my $pid = fork()) { # Parent 2607 waitpid($pid, 0); 2608 } else { # Child 2609 $params{run_on_start}->($self); 2610 exit(0); # Don't close anything 2611 } 2612 $params{run_on_finish}->($self); 2613 return $self; 2614} 2615sub max_proc { } 2616sub sig_child { } 2617sub kill_tree_all { } 2618sub wait_all { } 2619sub ready { } 2620sub running { } 2621sub is_any_left { return 0; } 2622 2623####################################################################### 26241; 2625 2626package main; 2627__END__ 2628 2629=pod 2630 2631=head1 NAME 2632 2633driver.pl - Run regression tests 2634 2635=head1 SYNOPSIS 2636 2637 driver.pl 2638 2639=head1 DESCRIPTION 2640 2641driver.pl invokes Verilator or another simulator on each test file. 2642 2643The driver reports the number of tests which pass, fail, skipped (some 2644resource required by the test is not available, such as SystemC), or are 2645unsupported (buggy or require a feature change before will pass.) 2646 2647There are hundreds of tests, and for faster completion you may want to run 2648the regression tests with OBJCACHE enabled and in parallel on a machine 2649with many cores. See the -j option and OBJCACHE environment variable. 2650 2651=head1 TEST CONFIGURATION 2652 2653The test configuration script (e.g. C<test_regres/t/t_EXAMPLE.pl>) controls 2654how the test will run by driver.pl. In general it includes a call to the 2655C<compile> subroutine to compile the test with Verilator (or an alternative 2656simulator), followed by a call to the C<execute> subroutine to run the 2657test. Compile-only tests omit the call to C<execute>. 2658 2659If those complete, the script calls C<ok(1)> to increment the count of 2660successful tests and then returns 1 as its result. 2661 2662Both C<compile> and C<execute> take an optional argument hash table to 2663control their behavior. For example: 2664 2665 compile( 2666 verilator_flags2 => ["--lint-only"], 2667 fails => 1, 2668 ); 2669 2670indicates that when compiling this test, the C<--lint-only> flag should be 2671passed and that the test is expected to fail. 2672 2673The full list of arguments can be found by looking at the C<driver.pl> 2674source code. Some commonly used arguments are: 2675 2676=over 4 2677 2678=item all_run_flags 2679 2680A list of flags to be passed when running the simulator (Verilated model or 2681one of the other simulators). 2682 2683=item check_finished 2684 2685Set to 1 to indicate successful completion of the test is indicated by the 2686string C<*-* All Finished *-*> being printed on standard output. This is 2687the normal way for successful tests to finish. 2688 2689=item expect 2690 2691A quoted list of strings or regular expression to be matched in the 2692output. See </HINTS ON WRITING TESTS> for more detail on how this argument 2693should be used. 2694 2695=item fails 2696 2697Set to 1 to indicate this step (C<compile> or C<execute> or C<lint>) is 2698expected to fail. Tests that are expected to fail generally have _bad in 2699their filename. 2700 2701=item make_main 2702 2703Set to 0 to disable the automatic creation of a C++ test wrapper (for 2704example when a hand-written test wrapper is provided using C<--exe>). 2705 2706=item make_top_shell 2707 2708Set to 0 to disable the automatic creation of a top level shell to run the 2709executable (for example when a hand-written test wrapper is provided using 2710C<--exe>). 2711 2712=item ms_flags 2713 2714=item ms_flags2 2715 2716=item ms_run_flags 2717 2718The equivalent of C<v_flags>, C<v_flags2> and C<all_run_flags>, but only 2719for use with the ModelSim simulator. 2720 2721=item nc_flags 2722 2723=item nc_flags2 2724 2725=item nc_run_flags 2726 2727The equivalent of C<v_flags>, C<v_flags2> and C<all_run_flags>, but only 2728for use with the Cadence NC simulator. 2729 2730=item iv_flags 2731 2732=item iv_flags2 2733 2734=item iv_run_flags 2735 2736The equivalent of C<v_flags>, C<v_flags2> and C<all_run_flags>, but only 2737for use with the Icarus Verilog simulator. 2738 2739=item v_flags 2740 2741A list of standard Verilog simulator flags to be passed to the simulator 2742compiler (Verilator or one of the other simulators). This list is create 2743by the driver and rarely changed, use v_flags2 instead. 2744 2745=item v_flags2 2746 2747A list of standard Verilog simulator flags to be passed to the simulator 2748compiler (Verilator or one of the other simulators). Unlike v_flags, these 2749options may be overridden in some simulation files. 2750 2751Similar sets of flags exist for atsim, GHDL, Cadence NC, Modelsim and 2752Synopsys VCS. 2753 2754=item vcs_flags 2755 2756=item vcs_flags2 2757 2758=item vcs_run_flags 2759 2760The equivalent of C<v_flags>, C<v_flags2> and C<all_run_flags>, but only 2761for use with the Synopsys VCS simulator. 2762 2763=item verilator_flags 2764 2765=item verilator_flags2 2766 2767The equivalent of C<v_flags> and C<v_flags2>, but only for use with 2768Verilator. If a flag is a standard flag (+incdir for example) v_flags2 2769should be used instead. 2770 2771=item benchmarksim 2772 2773Output the number of model evaluations and execution time of a test to 2774I<test_output_dir>/I<test_name>_benchmarksim.csv. Multiple invocations 2775of the same test file will append to to the same .csv file. 2776 2777=item xsim_flags 2778 2779=item xsim_flags2 2780 2781=item xsim_run_flags 2782 2783The equivalent of C<v_flags>, C<v_flags2> and C<all_run_flags>, but only 2784for use with the Xilinx XSim simulator. 2785 2786=back 2787 2788=head2 HINTS ON WRITING TESTS 2789 2790There is generally no need for the test to create its own main program or 2791top level shell as the driver creates one automatically, however some tests 2792require their own C++ or SystemC test harness. This is commonly given the 2793same name as the test, but with .cpp as suffix 2794(C<test_regress/t/t_EXAMPLE.cpp>). This can be specified as follows: 2795 2796 compile( 2797 make_top_shell => 0, 2798 make_main => 0, 2799 verilator_flags2 => ["--exe $Self->{t_dir}/$Self->{name}.cpp"], ); 2800 2801Tests should be self-checking, rather than producing lots of output. If a 2802test succeeds it should print C<*-* All Finished *-*> to standard output 2803and terminate (in Verilog C<$finish>), if not it should just stop (in 2804Verilog C<$stop>) as that signals an error. 2805 2806If termination should be triggered from the C++ wrapper, the following code 2807can be used: 2808 2809 vl_fatal(__FILE__, __LINE__, "dut", "<error message goes here>"); 2810 exit(1); 2811 2812This can be particularly useful if checking that the Verilator model has 2813not unexpectedly terminated. 2814 2815 if (contextp->gotFinish()) { 2816 vl_fatal(__FILE__, __LINE__, "dut", "<error message goes here>"); 2817 exit(1); 2818 } 2819 2820Where it might be useful for a test to produce output, it should qualify 2821this with C<TEST_VERBOSE>. For example in Verilog: 2822 2823 `ifdef TEST_VERBOSE 2824 $write("Conditional generate if MASK [%1d] = %d\n", g, MASK[g]); 2825 `endif 2826 2827Or in a hand-written C++ wrapper: 2828 2829 #ifdef TEST_VERBOSE 2830 cout << "Read a = " << a << endl; 2831 #endif 2832 2833The C<expect_filename> specifies a filename that should be used to check 2834the output results. This should not generally be used to decide if a test 2835has succeeded. However, in the case of tests that are designed to fail at 2836compile time, it is the only option. For example: 2837 2838 compile( 2839 fails => 1, 2840 expect_filename => $Self->{golden_filename}, 2841 ); 2842 2843Note expect_filename strips some debugging information from the logfile 2844when comparing. 2845 2846The C<expect> argument specifies a regular expression which must match the 2847output. 2848 2849=head1 DRIVER ARGUMENTS 2850 2851=over 4 2852 2853=item --benchmark [<cycles>] 2854 2855Show execution times of each step. If an optional number is given, 2856specifies the number of simulation cycles (for tests that support it). 2857 2858=item --debug 2859 2860Same as C<verilator --debug>: Use the debug version of Verilator which 2861enables additional assertions, debugging messages, and structure dump 2862files. 2863 2864=item --debugi(-<srcfile>) <level> 2865 2866Same as C<verilator --debugi level>: Set Verilator internal debugging level 2867globally to the specified debug level (1-10) or set the specified source 2868file to the specified level. Higher levels produce more detailed messages 2869(plain C<--debug> is equivalent to C<--debugi 4>). 2870 2871=item --dump-tree 2872 2873Same as C<verilator --dump-tree>: Enable Verilator writing .tree debug 2874files with dumping level 3, which dumps the standard critical stages. For 2875details on the format see the Verilator Internals manual. 2876 2877=item --gdb 2878 2879Same as C<verilator --gdb>: Run Verilator under the debugger. 2880 2881=item --gdbbt 2882 2883Same as C<verilator --gdbbt>: Run Verilator under the debugger, only to 2884print backtrace information. Requires --debug. 2885 2886=item --gdbsim 2887 2888Run Verilator generated executable under the debugger. 2889 2890=item --golden 2891 2892Update golden files, equivalent to setting HARNESS_UPDATE_GOLDEN=1. 2893 2894=item --hashset I<set>/I<numsets> 2895 2896Split tests based on a hash of the test names into I<numsets> and run only 2897tests in set number I<set> (0..I<numsets>-1). 2898 2899=item --help 2900 2901Displays this message and program version and exits. 2902 2903=item --j # 2904 2905Run number of parallel tests, or 0 to determine the count based on the 2906number of cores installed. Requires Perl's Parallel::Forker package. 2907 2908=item --optimize 2909 2910Randomly turn on/off different optimizations. With specific flags, 2911use those optimization settings 2912 2913=item --quiet 2914 2915Suppress all output except for failures and progress messages every 15 2916seconds. Intended for use only in automated regressions. See also 2917C<--rerun>, and C<--verbose> which is not the opposite of C<--quiet>. 2918 2919=item --rerun 2920 2921Rerun all tests that failed in this run. Reruns force the flags 2922C<--no-quiet --j 1>. 2923 2924=item --rr 2925 2926Same as C<verilator --rr>: Run Verilator and record with rr. 2927 2928=item --rrsim 2929 2930Run Verilator generated executable and record with rr. 2931 2932=item --sanitize 2933 2934Enable address sanitizer to compile Verilated C++ code. 2935This may detect misuses of memory, such as out-of-bound accesses, use-after-free, 2936and memory leaks. 2937 2938=item --site 2939 2940Run site specific tests also. 2941 2942=item --stop 2943 2944Stop on the first error. 2945 2946=item --trace 2947 2948Set the simulator specific flags to request waveform tracing. 2949 2950=item --unsupported 2951 2952Run tests even if marked as unsupported. 2953 2954=item --verbose 2955 2956Compile and run the test in verbose mode. This means C<TEST_VERBOSE> will 2957be defined for the test (Verilog and any C++/SystemC wrapper). 2958 2959=back 2960 2961=head1 SCENARIO ARGUMENTS 2962 2963The following options control which simulator is used, and which tests are 2964run. Multiple flags may be used to run multiple simulators/scenarios 2965simultaneously. 2966 2967=over 4 2968 2969=item --atsim 2970 2971Run ATSIM simulator tests. 2972 2973=item --dist 2974 2975Run simulator-agnostic distribution tests. 2976 2977=item --ghdl 2978 2979Run GHDL simulator tests. 2980 2981=item --iv 2982 2983Run Icarus Verilog simulator tests. 2984 2985=item --ms 2986 2987Run ModelSim simulator tests. 2988 2989=item --nc 2990 2991Run Cadence NC-Verilog simulator tests. 2992 2993=item --vcs 2994 2995Run Synopsys VCS simulator tests. 2996 2997=item --vlt 2998 2999Run Verilator tests in single-threaded mode. Default unless another scenario flag is provided. 3000 3001=item --vltmt 3002 3003Run Verilator tests in multithreaded mode. 3004 3005=item --xsim 3006 3007Run Xilinx XSim simulator tests. 3008 3009=back 3010 3011=head1 ENVIRONMENT 3012 3013=over 4 3014 3015=item SYSTEMC 3016 3017Root directory name of SystemC kit. Only used if SYSTEMC_INCLUDE not set. 3018 3019=item SYSTEMC_INCLUDE 3020 3021Directory name with systemc.h in it. 3022 3023=item VERILATOR_GHDL 3024 3025Command to use to invoke GHDL. 3026 3027=item VERILATOR_IVERILOG 3028 3029Command to use to invoke Icarus Verilog. 3030 3031=item VERILATOR_MAKE 3032 3033Command to use to rebuild Verilator and run single test. Defaults to "make &&". 3034 3035=item VERILATOR_MODELSIM 3036 3037Command to use to invoke ModelSim. 3038 3039=item VERILATOR_NCVERILOG 3040 3041Command to use to invoke ncverilog. 3042 3043=item VERILATOR_TESTS_SITE 3044 3045Used with --site, a colon-separated list of directories with tests to be added to testlist. 3046 3047=item VERILATOR_VCS 3048 3049Command to use to invoke VCS. 3050 3051=item VERILATOR_XELAB 3052 3053Command to use to invoke XSim xelab 3054 3055=item VERILATOR_XVLOG 3056 3057Command to use to invoke XSim xvlog 3058 3059=back 3060 3061=head1 DISTRIBUTION 3062 3063The latest version is available from L<https://verilator.org>. 3064 3065Copyright 2003-2021 by Wilson Snyder. This program is free software; you 3066can redistribute it and/or modify it under the terms of either the GNU 3067Lesser General Public License Version 3 or the Perl Artistic License 3068Version 2.0. 3069 3070SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0 3071 3072=head1 AUTHORS 3073 3074Wilson Snyder <wsnyder@wsnyder.org> 3075 3076=head1 SEE ALSO 3077 3078L<verilator> 3079 3080=cut 3081 3082###################################################################### 3083