240 lines
7.8 KiB
Perl
240 lines
7.8 KiB
Perl
|
|
#!/usr/bin/env perl
|
||
|
|
#
|
||
|
|
# Regression script for VHDL output. Based on vvp_reg.pl.
|
||
|
|
#
|
||
|
|
# This script is based on code with the following Copyright.
|
||
|
|
#
|
||
|
|
# Copyright (c) 1999-2020 Guy Hutchison (ghutchis@pacbell.net)
|
||
|
|
#
|
||
|
|
# This source code is free software; you can redistribute it
|
||
|
|
# and/or modify it in source code form under the terms of the GNU
|
||
|
|
# General Public License as published by the Free Software
|
||
|
|
# Foundation; either version 2 of the License, or (at your option)
|
||
|
|
# any later version.
|
||
|
|
#
|
||
|
|
# This program is distributed in the hope that it will be useful,
|
||
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
|
|
# GNU General Public License for more details.
|
||
|
|
#
|
||
|
|
# You should have received a copy of the GNU General Public License
|
||
|
|
# along with this program; if not, write to the Free Software
|
||
|
|
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||
|
|
|
||
|
|
use lib './perl-lib';
|
||
|
|
|
||
|
|
use RegressionList;
|
||
|
|
use Diff;
|
||
|
|
use Reporting;
|
||
|
|
use Environment;
|
||
|
|
|
||
|
|
|
||
|
|
#
|
||
|
|
# Main script
|
||
|
|
#
|
||
|
|
&open_report_file('vhdl_regression_report.txt');
|
||
|
|
my ($suffix, $strict, $with_valg, $force_sv) = &get_args;
|
||
|
|
my $ver = &get_ivl_version($suffix);
|
||
|
|
my $msg = $with_valg ? " (with valgrind)" : "";
|
||
|
|
&print_rpt("Running VHDL tests for Icarus Verilog version: $ver$msg.\n");
|
||
|
|
&print_rpt("-" x 70 . "\n");
|
||
|
|
if ($#ARGV != -1) {
|
||
|
|
my $regress_fn = &get_regress_fn;
|
||
|
|
&read_regression_list($regress_fn, $ver, $force_sv, "");
|
||
|
|
} else {
|
||
|
|
&read_regression_list("vhdl_regress.list", $ver, $force_sv, "");
|
||
|
|
}
|
||
|
|
&execute_regression($suffix, $with_valg);
|
||
|
|
&close_report_file;
|
||
|
|
|
||
|
|
|
||
|
|
#
|
||
|
|
# execute_regression sequentially compiles and executes each test in
|
||
|
|
# the regression. It then checks that the output matches the gold file.
|
||
|
|
#
|
||
|
|
sub execute_regression {
|
||
|
|
my $sfx = shift(@_);
|
||
|
|
my $with_valg = shift(@_);
|
||
|
|
my ($tname, $total, $passed, $failed, $expected_fail, $not_impl,
|
||
|
|
$len, $cmd, $diff_file, $outfile, $unit);
|
||
|
|
|
||
|
|
$total = 0;
|
||
|
|
$passed = 0;
|
||
|
|
$failed = 0;
|
||
|
|
$expected_fail = 0;
|
||
|
|
$not_impl = 0;
|
||
|
|
$len = 0;
|
||
|
|
|
||
|
|
# Check for the VHDL output directory
|
||
|
|
mkdir 'vhdl' unless (-d 'vhdl');
|
||
|
|
|
||
|
|
foreach $tname (@testlist) {
|
||
|
|
$len = length($tname) if (length($tname) > $len);
|
||
|
|
}
|
||
|
|
|
||
|
|
foreach $tname (@testlist) {
|
||
|
|
next if ($tname eq ""); # Skip test that have been replaced.
|
||
|
|
|
||
|
|
$total++;
|
||
|
|
&print_rpt(sprintf("%${len}s: ", $tname));
|
||
|
|
if ($diff{$tname} ne "" and -e $diff{$tname}) {
|
||
|
|
unlink $diff{$tname} or
|
||
|
|
die "Error: unable to remove old diff file $diff{$tname}.\n";
|
||
|
|
}
|
||
|
|
if (-e "log/$tname.log") {
|
||
|
|
unlink "log/$tname.log" or
|
||
|
|
die "Error: unable to remove old log file log/$tname.log.\n";
|
||
|
|
}
|
||
|
|
|
||
|
|
if ($testtype{$tname} eq "NI") {
|
||
|
|
&print_rpt("Not Implemented.\n");
|
||
|
|
$not_impl++;
|
||
|
|
next;
|
||
|
|
}
|
||
|
|
|
||
|
|
# Store all the output in the vhdl subdirectory for debugging
|
||
|
|
$outfile = "vhdl/$tname.vhd";
|
||
|
|
|
||
|
|
#
|
||
|
|
# Build up the iverilog command line and run it.
|
||
|
|
#
|
||
|
|
$cmd = $with_valg ? "valgrind --trace-children=yes " : "";
|
||
|
|
$cmd .= "iverilog$sfx -t vhdl -o $outfile $args{$tname}";
|
||
|
|
$cmd .= " -s $testmod{$tname}" if ($testmod{$tname} ne "");
|
||
|
|
$cmd .= " ./$srcpath{$tname}/$tname.v > log/$tname.log 2>&1";
|
||
|
|
#print "$cmd\n";
|
||
|
|
if (system("$cmd")) {
|
||
|
|
if ($testtype{$tname} eq "CE") {
|
||
|
|
# Check if the system command core dumped!
|
||
|
|
if ($? >> 8 & 128) {
|
||
|
|
&print_rpt("==> Failed - CE (core dump).\n");
|
||
|
|
$failed++;
|
||
|
|
} else {
|
||
|
|
&print_rpt("Passed - CE.\n");
|
||
|
|
$passed++;
|
||
|
|
}
|
||
|
|
next;
|
||
|
|
}
|
||
|
|
|
||
|
|
# Check the log file for an un-translatable construct error
|
||
|
|
# We report this separately so we can distinguish between
|
||
|
|
# expected and unexpected failures
|
||
|
|
$cmd = "grep -q -i -E '(no vhdl translation|cannot be translated)' log/$tname.log";
|
||
|
|
if (system($cmd) == 0) {
|
||
|
|
&print_rpt("==> Failed - No VHDL translation.\n");
|
||
|
|
$not_impl++;
|
||
|
|
next;
|
||
|
|
}
|
||
|
|
else {
|
||
|
|
&print_rpt("==> Failed - running iverilog.\n");
|
||
|
|
$failed++;
|
||
|
|
next;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
#
|
||
|
|
# Compile the output with GHDL
|
||
|
|
#
|
||
|
|
$cmd = "(cd vhdl ; ghdl -a $tname.vhd) >> log/$tname.log 2>&1";
|
||
|
|
#print "$cmd\n";
|
||
|
|
if (system("$cmd")) {
|
||
|
|
if ($testtype{$tname} eq "CE") {
|
||
|
|
# Check if the system command core dumped!
|
||
|
|
if ($? >> 8 & 128) {
|
||
|
|
&print_rpt("==> Failed - CE (core dump).\n");
|
||
|
|
$failed++;
|
||
|
|
} else {
|
||
|
|
&print_rpt("Passed - CE.\n");
|
||
|
|
$passed++;
|
||
|
|
}
|
||
|
|
next;
|
||
|
|
}
|
||
|
|
&print_rpt("==> Failed - running ghdl.\n");
|
||
|
|
$failed++;
|
||
|
|
next;
|
||
|
|
}
|
||
|
|
|
||
|
|
# The CO test type now includes compilation of the VHDL
|
||
|
|
if ($testtype{$tname} eq "CO") {
|
||
|
|
&print_rpt("Passed - CO.\n");
|
||
|
|
$passed++;
|
||
|
|
next;
|
||
|
|
}
|
||
|
|
|
||
|
|
# Try to guess the name of the primary VHDL unit
|
||
|
|
# ghdl -f lists all the units in a file: take the first one
|
||
|
|
($unit) = `ghdl -f $outfile` =~ /^entity (\w+)/;
|
||
|
|
unless ($unit) {
|
||
|
|
&print_rpt("==> Failed -- cannot determine primary VHDL unit.\n");
|
||
|
|
$failed++;
|
||
|
|
next;
|
||
|
|
}
|
||
|
|
#print "primary unit is $unit\n";
|
||
|
|
|
||
|
|
# Elaborate the primary unit to produce and executable
|
||
|
|
# Could elaborate and run in a single step, but this should
|
||
|
|
# provide better error detection.
|
||
|
|
$cmd = "(cd vhdl ; ghdl -e $unit) >> log/$tname.log 2>&1";
|
||
|
|
#print "$cmd\n";
|
||
|
|
if (system($cmd)) {
|
||
|
|
&print_rpt("==> Failed - running ghdl elaboration step.\n");
|
||
|
|
$failed++;
|
||
|
|
next;
|
||
|
|
}
|
||
|
|
|
||
|
|
# Finally, run the exectutable
|
||
|
|
$cmd = "(cd vhdl ; ghdl -r $unit --stop-delta=10000) >> log/$tname.log 2>&1";
|
||
|
|
#print "$cmd\n";
|
||
|
|
if (system($cmd)) {
|
||
|
|
if ($testtype{$tname} eq "RE") {
|
||
|
|
&print_rpt("Passed - RE.\n");
|
||
|
|
$passed++;
|
||
|
|
next;
|
||
|
|
}
|
||
|
|
else {
|
||
|
|
# If the log contains `SIMULATION FINISHED' then
|
||
|
|
# this is OK
|
||
|
|
$cmd = "grep -q 'SIMULATION FINISHED' log/$tname.log";
|
||
|
|
if (system($cmd)) {
|
||
|
|
&print_rpt("==> Failed - simulating VHDL.\n");
|
||
|
|
$failed++;
|
||
|
|
next;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
if ($diff{$tname} ne "") {
|
||
|
|
$diff_file = $diff{$tname}
|
||
|
|
} else {
|
||
|
|
$diff_file = "log/$tname.log";
|
||
|
|
}
|
||
|
|
# print "diff $gold{$tname}, $diff_file, $offset{$tname}\n";
|
||
|
|
if (diff($gold{$tname}, $diff_file, $offset{$tname})) {
|
||
|
|
if ($testtype{$tname} eq "EF") {
|
||
|
|
&print_rpt("Passed - expected fail.\n");
|
||
|
|
$expected_fail++;
|
||
|
|
next;
|
||
|
|
}
|
||
|
|
&print_rpt("==> Failed - output does not match gold file.\n");
|
||
|
|
$failed++;
|
||
|
|
next;
|
||
|
|
}
|
||
|
|
|
||
|
|
&print_rpt("Passed.\n");
|
||
|
|
$passed++;
|
||
|
|
|
||
|
|
} continue {
|
||
|
|
if ($tname ne "") {
|
||
|
|
# Remove GHDL temporary files
|
||
|
|
my $tmpfiles = './vhdl/*.o ./vhdl/work-obj93.cf';
|
||
|
|
$tmpfiles .= " ./vhdl/$unit" if $unit;
|
||
|
|
system("rm -f $tmpfiles") and
|
||
|
|
die "Error: failed to remove temporary files.\n";
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
&print_rpt("=" x 70 . "\n");
|
||
|
|
&print_rpt("Test results:\n Total=$total, Passed=$passed, Failed=$failed,".
|
||
|
|
" Not Implemented=$not_impl, Expected Fail=$expected_fail\n");
|
||
|
|
}
|