Compare commits

...

6 Commits

Author SHA1 Message Date
Cary R. 929fbf3507
Merge pull request #1282 from steveicarus/msys2-clang-support
MSYS2 clang support
2025-10-20 19:42:30 -07:00
Martin Whitaker 6210c307fa Update CI scripts to continue testing PLI 1 support. 2025-10-18 20:07:23 +01:00
Martin Whitaker 935910c3c9 Modify VPI test suite to make PLI 1 tests optional. 2025-10-18 20:05:58 +01:00
Martin Whitaker cf66c64e32 Make support for PLI 1 (libveriuser and cadpli) a config option.
PLI 1 was deprecated in 1364-2005, so disable by default and note that
it is deprecated in the help text.

This works round the problem that the clang linker (lld) in MSYS2 does
not support the -r option, so cannot be used to build libveriuser.a.
2025-10-18 20:02:48 +01:00
Martin Whitaker 8e2d543304 Rework makefiles to eliminate the use of dlltool in Windows builds.
The clang dlltool is not compatible with the binutils dlltool. However
both the clang and binutils linkers support reading the .def file and
creating the import library directly, so we no longer need to perform
the link in two stages.
2025-10-18 20:00:19 +01:00
Martin Whitaker 10770c9129 Optimise Perl regression test scripts.
When redirection operators are included in a command string passed to
the system() subroutine, it spawns an intermediate shell to handle the
redirection. This is particularly inefficient when running the tests
in MSYS2. Creating our own version of system() based on fork() and
exec() allows us to handle the redirection directly.
2025-10-17 20:58:05 +01:00
14 changed files with 99 additions and 63 deletions

2
.github/test.sh vendored
View File

@ -9,7 +9,7 @@ status=0
perl vvp_reg.pl || status=1
perl vpi_reg.pl || status=1
perl vpi_reg.pl --with-pli1 || status=1
python3 vvp_reg.py || status=1

View File

@ -29,7 +29,7 @@ jobs:
run: |
export PATH="/usr/local/opt/bison/bin:$PATH"
autoconf
./configure
./configure --enable-libveriuser
make -j$(nproc) check
sudo make install
@ -59,7 +59,7 @@ jobs:
- name: Build, check and install
run: |
autoconf
./configure
./configure --enable-libveriuser
make -j$(nproc) check
sudo make install

View File

@ -37,11 +37,17 @@ exec_prefix = @exec_prefix@
srcdir = @srcdir@
datarootdir = @datarootdir@
SUBDIRS = ivlpp vhdlpp vvp vpi libveriuser cadpli tgt-null tgt-stub tgt-vvp \
SUBDIRS = ivlpp vhdlpp vvp vpi tgt-null tgt-stub tgt-vvp \
tgt-vhdl tgt-vlog95 tgt-pcb tgt-blif tgt-sizer driver
# Only run distclean for these directories.
NOTUSED = tgt-fpga tgt-pal tgt-verilog
ifeq (@LIBVERIUSER@,yes)
SUBDIRS += libveriuser cadpli
else
NOTUSED += libveriuser cadpli
endif
ifeq (@MINGW32@,yes)
SUBDIRS += driver-vpi
else
@ -75,7 +81,6 @@ BUILDCC = @CC_FOR_BUILD@
BUILDEXT = @BUILD_EXEEXT@
CC = @CC@
CXX = @CXX@
DLLTOOL = @DLLTOOL@
INSTALL = @INSTALL@
INSTALL_SCRIPT = @INSTALL_SCRIPT@
INSTALL_PROGRAM = @INSTALL_PROGRAM@
@ -214,15 +219,11 @@ config.status: $(srcdir)/configure
./config.status
ifeq (@WIN32@,yes)
# Under Windows (mingw) I need to make the ivl.exe in two steps.
# The first step makes an ivl.exe that dlltool can use to make an
# export and import library, and the last link makes a, ivl.exe
# that really exports the things that the import library imports.
# Under Windows we need to create an import library to allow the target code
# generators to access the items exported by ivl.exe. The .def file controls
# what is visible in the import library.
ivl@EXEEXT@: $O $(srcdir)/ivl.def
$(CXX) -o ivl@EXEEXT@ $O $(dllib) @EXTRALIBS@
$(DLLTOOL) --dllname ivl@EXEEXT@ --def $(srcdir)/ivl.def \
--output-lib libivl.a --output-exp ivl.exp
$(CXX) $(LDFLAGS) -o ivl@EXEEXT@ ivl.exp $O $(dllib) @EXTRALIBS@
$(CXX) $(LDFLAGS) -o ivl@EXEEXT@ -Wl,--out-implib=libivl.a $(srcdir)/ivl.def $O $(dllib) @EXTRALIBS@
else
ivl@EXEEXT@: $O
$(CXX) $(LDFLAGS) -o ivl@EXEEXT@ $O $(dllib)
@ -233,6 +234,7 @@ all: iverilog-vpi
iverilog-vpi: $(srcdir)/iverilog-vpi.sh Makefile
sed -e 's;@SHARED@;@shared@;' -e 's;@PIC@;@PICFLAG@;' \
-e 's;@ENABLE_PLI1@;@LIBVERIUSER@;' \
-e 's;@SUFFIX@;$(suffix);' \
-e 's;@IVCC@;$(CC);' \
-e 's;@IVCXX@;$(CXX);' \

View File

@ -21,7 +21,6 @@ AC_PROG_CXX
AC_PROG_RANLIB
AC_CHECK_TOOL(LD, ld, false)
AC_CHECK_TOOL(AR, ar, false)
AC_CHECK_TOOL(DLLTOOL, dlltool, false)
AC_CHECK_TOOL(STRIP, strip, true)
AC_CHECK_TOOL(WINDRES,windres,false)
AC_CHECK_PROGS(XGPERF,gperf,none)
@ -178,7 +177,7 @@ AC_SUBST(HAVE_LIBBZ2)
AC_FUNC_ALLOCA
AC_FUNC_FSEEKO
# Package Options
# Feature Options
# ---------------
# Build VVP as a library and stub
@ -186,6 +185,14 @@ AC_ARG_ENABLE([libvvp],
[AS_HELP_STRING([--enable-libvvp], [build VVP as a shared library])],
[AC_SUBST(LIBVVP, yes)],[])
AC_ARG_ENABLE([libveriuser],
[AS_HELP_STRING([--enable-libveriuser], [include support for PLI 1 (deprecated)])],
[AC_SUBST(LIBVERIUSER, yes)],
[AC_SUBST(LIBVERIUSER, no)])
# Package Options
# ---------------
# valgrind checks
AC_ARG_WITH([valgrind], [AS_HELP_STRING([--with-valgrind],[Add valgrind hooks])],
[], [check_valgrind=yes])

View File

@ -84,6 +84,11 @@ config.h: $(srcdir)/config.h.in Makefile
-e 's;@IVLCFLAGS@;$(CFLAGS);' \
-e 's;@IVLCXXFLAGS@;$(CXXFLAGS);' \
-e 's;@SHARED@;@shared@;' $< > $@
ifeq (@LIBVERIUSER@,yes)
sed -i 's;@VPILIBS@;-lveriuser$(suffix) -lvpi$(suffix);' $@
else
sed -i 's;@VPILIBS@;-lvpi$(suffix);' $@
endif
# Windows specific...
res.rc: $(srcdir)/res.rc.in ../version.exe

View File

@ -6,5 +6,5 @@
#define IVERILOG_VPI_CFLAGS " @IVLCFLAGS@"
#define IVERILOG_VPI_CXXFLAGS " @IVLCXXFLAGS@"
#define IVERILOG_VPI_LDFLAGS "@SHARED@"
#define IVERILOG_VPI_LDLIBS "-lveriuser@SUFFIX@ -lvpi@SUFFIX@"
#define IVERILOG_VPI_LDLIBS "@VPILIBS@"
#define IVERILOG_SUFFIX "@SUFFIX@"

View File

@ -29,7 +29,11 @@ SUFFIX=@SUFFIX@
# These are used for linking...
LD=$CC
LDFLAGS="@IVCTARGETFLAGS@ @SHARED@ -L@LIBDIR@"
LDLIBS="-lveriuser$SUFFIX -lvpi$SUFFIX"
if [ x@ENABLE_PLI1@ = xyes ] ; then
LDLIBS="-lveriuser$SUFFIX -lvpi$SUFFIX"
else
LDLIBS="-lvpi$SUFFIX"
fi
CCSRC=
CXSRC=

View File

@ -11,7 +11,7 @@ our $VERSION = '1.03';
use base 'Exporter';
our @EXPORT = qw(get_args get_regress_fn get_ivl_version);
our @EXPORT = qw(get_args get_regress_fn get_ivl_version run_program);
use constant DEF_REGRESS_FN => './regress.list'; # Default regression list.
use constant DEF_SUFFIX => ''; # Default suffix.
@ -102,4 +102,26 @@ sub get_ivl_version {
}
}
#
# Run a subprogram. This avoids spawing an intermediate shell when output
# is redirected to a log file.
#
sub run_program {
my ($cmd, $log_mode, $log_file) = @_;
my $pid = fork();
if (!defined($pid)) {
die("couldn't spawn new process\n");
} elsif ($pid == 0) {
if ($log_mode) {
open(STDOUT, $log_mode, $log_file) or die("couldn't open log file '$log_file'\n");
open(STDERR, '>&STDOUT');
}
exec($cmd);
} else {
waitpid($pid, 0);
$?; # return the child's exit status
}
}
1; # Module loaded OK

View File

@ -4,7 +4,7 @@
#
# This script is based on code with the following Copyright.
#
# Copyright (c) 1999-2024 Guy Hutchison (ghutchis@pacbell.net)
# Copyright (c) 1999-2025 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
@ -126,9 +126,9 @@ sub execute_regression {
$cmd .= $testtype{$tname} eq "CN" ? " -t null" : " -t vlog95";
$cmd .= " -pfileline=1 -pspacing=4" if ($testtype{$tname} ne "CN");
$cmd .= " -D__ICARUS_UNSIZED__ $args{$tname}";
$cmd .= " ./$srcpath{$tname}/$tname.v > log/$tname.log 2>&1";
$cmd .= " ./$srcpath{$tname}/$tname.v";
# print "$cmd\n";
if (system("$cmd")) {
if (run_program($cmd, '>', "log/$tname.log")) {
if ($testtype{$tname} eq "CE") {
# Check if the system command core dumped!
if ($? >> 8 & 128) {
@ -186,9 +186,9 @@ sub execute_regression {
$args{$tname} =~ s/-gverilog-ams//g;
$cmd = "iverilog$sfx -o vsim $gen_flag $args{$tname}";
$cmd .= " -s $testmod{$tname}" if ($testmod{$tname} ne "");
$cmd .= " vlog95.v >> log/$tname.log 2>&1";
$cmd .= " vlog95.v";
# print "$cmd\n";
if ($pass_type == 0 and system("$cmd")) {
if ($pass_type == 0 and run_program($cmd, '>>', "log/$tname.log")) {
if ($testtype{$tname} eq "TE") {
# Check if the system command core dumped!
if ($? >> 8 & 128) {
@ -205,9 +205,9 @@ sub execute_regression {
}
}
$cmd = "vvp$sfx vsim $plargs{$tname} >> log/$tname.log 2>&1";
$cmd = "vvp$sfx vsim $plargs{$tname}";
# print "$cmd\n";
if ($pass_type == 0 and system("$cmd")) {
if ($pass_type == 0 and run_program($cmd, '>>', "log/$tname.log")) {
if ($testtype{$tname} eq "RE") {
# Check if the system command core dumped!
if ($? >> 8 & 128) {
@ -275,7 +275,7 @@ sub execute_regression {
} continue {
if ($tname ne "") {
system("rm -f ./vlog95.v ./vsim") and
run_program("rm -f ./vlog95.v ./vsim") and
die "Error: failed to remove temporary file.\n";
}
}

View File

@ -11,8 +11,10 @@ $| = 1; # This turns off buffered I/O
# We support a --suffix= and --with-valgrind flags.
use Getopt::Long;
$sfx = ""; # Default suffix.
$with_pli1 = 0; # Default PLI 1 support (keep this off).
$with_valg = 0; # Default valgrind usage (keep this off).
if (!GetOptions("suffix=s" => \$sfx,
"with-pli1" => \$with_pli1,
"with-valgrind" => \$with_valg,
"help" => \&usage)) {
die "Error: Invalid argument(s).\n";
@ -22,6 +24,8 @@ sub usage {
warn "$0 usage:\n\n" .
" --suffix=<suffix> # The Icarus executables suffix, " .
"default \"\".\n" .
" --with-pli1 # Include the PLI 1 tests, " .
"default \"off\".\n" .
" --with-valgrind # Run the test suite with valgrind, " .
"default \"off\".\n" .
" <regression file> # The regression file, " .
@ -104,6 +108,7 @@ sub read_regression_list {
$testtype = $fields[1];
$args{$tname} = "";
}
next if ($testtype eq "PLI1" && !$with_pli1); # Skip PLI 1 tests if not enabled.
# This version of the program does not implement something
# required to run this test.
if ($testtype eq "NI") {
@ -128,8 +133,10 @@ sub read_regression_list {
$args{$tname} = join(' ', split(',', $args{$tname}));
}
} else {
$testtype = $fields[1];
$args{$tname} = "";
}
next if ($testtype eq "PLI1" && !$with_pli1); # Skip PLI 1 tests if not enabled.
$ccode{$tname} = $fields[2];
$goldfile{$tname} = $fields[3];
$cargs{$tname} = $fields[4];
@ -189,17 +196,16 @@ sub execute_regression {
}
$cmd = "iverilog-vpi$sfx --name=$tname $cargs{$tname} " .
"vpi/$ccode{$tname} > vpi_log/$tname.log 2>&1";
if (system("$cmd")) {
"vpi/$ccode{$tname}";
if (run_program($cmd, '>', "vpi_log/$tname.log")) {
print "==> Failed - running iverilog-vpi.\n";
$failed++;
next;
}
$cmd = $with_valg ? "valgrind --trace-children=yes " : "";
$cmd .= "iverilog$sfx $args{$tname} -L . -m $tname -o vsim vpi/$tname.v >> " .
"vpi_log/$tname.log 2>&1";
if (system("$cmd")) {
$cmd .= "iverilog$sfx $args{$tname} -L . -m $tname -o vsim vpi/$tname.v";
if (run_program($cmd, '>>', "vpi_log/$tname.log")) {
print "==> Failed - running iverilog.\n";
$failed++;
next;
@ -207,8 +213,8 @@ sub execute_regression {
$cmd = $with_valg ? "valgrind --leak-check=full " .
"--show-reachable=yes " : "";
$cmd .= "vvp$sfx vsim >> vpi_log/$tname.log 2>&1";
if (system("$cmd")) {
$cmd .= "vvp$sfx vsim";
if (run_program($cmd, '>>', "vpi_log/$tname.log")) {
print "==> Failed - running vvp.\n";
$failed++;
next;
@ -230,7 +236,7 @@ sub execute_regression {
if ($tname ne "" and $ccode{$tname} ne "") {
my $doto = $ccode{$tname};
$doto =~ s/\.(c|cc|cpp)$/.o/;
system("rm -f $doto $tname.vpi vsim") and
run_program("rm -f $doto $tname.vpi vsim") and
die "Error: failed to remove temporary files.\n";
}
}

View File

@ -62,7 +62,7 @@ br_gh59 normal br_gh59.c br_gh59.gold
br_gh73a normal force.c br_gh73a.gold
br_gh73b normal force.c br_gh73b.gold
br_gh117 normal br_gh117.c br_gh117.gold
br_gh141 normal br_gh141.c br_gh141.gold
br_gh141 PLI1 br_gh141.c br_gh141.gold
br_gh169a normal br_gh169.c br_gh169a.gold
br_gh169b normal,-g2009 br_gh169.c br_gh169b.gold
br_gh184 normal start_of_simtime1.c br_gh184.gold
@ -93,9 +93,9 @@ force_wire_real normal force_real.c force_wire_real.gold
genblk_named normal genblk_names.c genblk_named.gold
genblk_unnamed normal genblk_names.c genblk_unnamed.gold
genblk_direct normal,-g2009 genblk_names.c genblk_direct.gold
getp normal getp.c getp.log
getp PLI1 getp.c getp.log
hello_poke normal hello_poke.c hello_poke.log
hello_tf normal hello_tf.c hello_tf.log
hello_tf PLI1 hello_tf.c hello_tf.log
hello_vpi normal hello_vpi.c hello.log
hello_vpi2 normal hello_vpi2.c hello2.log vpi/hello_vpi1.c
listparams normal listparams.c listparams.log
@ -105,15 +105,15 @@ nextsimtime_cb3 normal nextsimtime_cb3.c nextsimtime_cb3.gold
nextsimtime_cb4 normal nextsimtime_cb4.c nextsimtime_cb4.gold
memmon normal,-g1995 memmon.c memmon.log
memwide normal memwide.cc memwide.log
mipname normal mipname.c mipname.log
mipname PLI1 mipname.c mipname.log
myscope normal myscope.c myscope.gold
myscope2 normal myscope2.c myscope2.gold
myscope2 PLI1 myscope2.c myscope2.gold
nulls1 normal nulls1.c nulls1.log
poke_escaped normal poke_escaped.c poke_escaped.gold
pokevent normal pokevent.cc pokevent.log
pokereg normal pokereg.cc pokereg.log
ports_params normal ports_params.c ports_params.gold
pr521 normal pr521.c pr521.log
pr521 PLI1 pr521.c pr521.log
pr686 normal pr686.c pr686.log
pr723 normal pr723.c pr723.log
pr1693971 normal pr1693971.c pr1693971.log
@ -121,8 +121,8 @@ pr2048463 normal pr2048463.c pr2048463.log
pr2314742 normal pr2314742.c pr2314742.gold
pr2966059 normal pr2966059.c pr2966059.gold
pr2971220 normal pr2971220.c pr2971220.gold
putp normal putp.c putp.log
putp2 normal putp2.c putp2.log
putp PLI1 putp.c putp.log
putp2 PLI1 putp2.c putp2.log
putvalue normal putvalue.c putvalue.log
range1 normal range1.c range1.gold
realcb normal realcb.c realcb.log
@ -137,7 +137,7 @@ sim_time_cb1 normal sim_time_cb1.c sim_time_cb1.gold
sim_time_cb2 normal sim_time_cb2.c sim_time_cb2.gold
spec_delays normal,-gspecify spec_delays.c spec_delays.log
start_of_simtime1 normal start_of_simtime1.c start_of_simtime1.log
timescale normal timescale.c timescale.log
timescale PLI1 timescale.c timescale.log
value_change_cb1 normal,-g2009 value_change_cb1.c value_change_cb1.gold
value_change_cb2 normal,-g2009 value_change_cb2.c value_change_cb2.gold
value_change_cb3 normal,-g2009 value_change_cb3.c value_change_cb3.gold

View File

@ -4,7 +4,7 @@
#
# This script is based on code with the following Copyright.
#
# Copyright (c) 1999-2024 Guy Hutchison (ghutchis@pacbell.net)
# Copyright (c) 1999-2025 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
@ -136,9 +136,9 @@ sub execute_regression {
$cmd .= "iverilog$sfx -o vsim $ivl_args $args{$tname}";
$cmd .= " -s $testmod{$tname}" if ($testmod{$tname} ne "");
$cmd .= " -t null" if ($testtype{$tname} eq "CN");
$cmd .= " ./$srcpath{$tname}/$tname.v > log/$tname.log 2>&1";
$cmd .= " ./$srcpath{$tname}/$tname.v";
# print "$cmd\n";
if (system("$cmd")) {
if (run_program($cmd, '>', "log/$tname.log")) {
if ($testtype{$tname} eq "CE") {
# Check if the system command core dumped!
if ($? >> 8 & 128) {
@ -174,9 +174,9 @@ sub execute_regression {
$cmd = $with_valg ? "valgrind --leak-check=full " .
"--show-reachable=yes " : "";
$cmd .= "vvp$sfx vsim $vvp_args $plargs{$tname} >> log/$tname.log 2>&1";
$cmd .= "vvp$sfx vsim $vvp_args $plargs{$tname}";
# print "$cmd\n";
if ($pass_type == 0 and system("$cmd")) {
if ($pass_type == 0 and run_program($cmd, '>>', "log/$tname.log")) {
if ($testtype{$tname} eq "RE") {
# Check if the system command core dumped!
if ($? >> 8 & 128) {
@ -242,7 +242,7 @@ sub execute_regression {
} continue {
if ($tname ne "") {
system("rm -f ./vsim && rm -rf ivl_vhdl_work") and
run_program("rm -rf ./vsim ivl_vhdl_work") and
die "Error: failed to remove temporary file.\n";
}
}
@ -252,7 +252,7 @@ sub execute_regression {
" Not Implemented=$not_impl, Expected Fail=$expected_fail\n");
# Remove remaining temporary files
system("rm -f *.tmp ivltests/*.tmp");
run_program("rm -f *.tmp ivltests/*.tmp");
return $failed;
}

View File

@ -21,6 +21,7 @@ build() {
cd "${srcdir}"/../..
sh autoconf.sh
./configure \
--enable-libveriuser \
--prefix="${MINGW_PREFIX}" \
--host="$CARCH"-w64-mingw32
mingw32-make

View File

@ -41,7 +41,6 @@ HOSTCFLAGS = @WARNING_FLAGS@ @WARNING_FLAGS_CC@ @CFLAGS@
BUILDCC = @CC_FOR_BUILD@
BUILDEXT = @BUILD_EXEEXT@
CXX = @CXX@
DLLTOOL = @DLLTOOL@
INSTALL = @INSTALL@
INSTALL_SCRIPT = @INSTALL_SCRIPT@
INSTALL_PROGRAM = @INSTALL_PROGRAM@
@ -149,19 +148,9 @@ else
ifeq (@WIN32@,yes)
# To support cocotb, we export the VPI functions directly. This allows
# cocotb to build VPI modules without using our vpi_user.h and libvpi.a.
# This requires making the vvp.exe in two steps. The first step makes
# a vvp.exe that dlltool can use to make an export library, and the
# second step makes a vvp.exe that really exports those things.
#
# To get this to work correctly we must use the suffixed version of the
# executable to build the export library, but leave the final vvp.exe
# without a suffix.
# The .def file controls what is exported.
vvp@EXEEXT@: main.o $O $(srcdir)/vvp.def
$(CXX) -o vvp$(suffix)@EXEEXT@ $(LDFLAGS) main.o $O $(dllib) $(LIBS)
$(DLLTOOL) --dllname vvp$(suffix)@EXEEXT@ --def $(srcdir)/vvp.def \
--output-exp vvp.exp
rm -f vvp$(suffix)@EXEEXT@
$(CXX) $(LDFLAGS) -o vvp@EXEEXT@ vvp.exp $(LDFLAGS) main.o $O $(dllib) $(LIBS)
$(CXX) $(LDFLAGS) -o vvp@EXEEXT@ $(LDFLAGS) $(srcdir)/vvp.def main.o $O $(dllib) $(LIBS)
else
vvp@EXEEXT@: $O main.o
$(CXX) $(LDFLAGS) -o vvp@EXEEXT@ main.o $O $(LIBS) $(dllib)