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          "<>"          => \&parameter,
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