diff --git a/.github/test.sh b/.github/test.sh index a49bdfb3c..0caeca364 100755 --- a/.github/test.sh +++ b/.github/test.sh @@ -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 diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 7c01f0501..d027e05ee 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -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 diff --git a/Makefile.in b/Makefile.in index 094481b8e..f13a5615e 100644 --- a/Makefile.in +++ b/Makefile.in @@ -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);' \ diff --git a/configure.ac b/configure.ac index b93269b38..8188f10f5 100644 --- a/configure.ac +++ b/configure.ac @@ -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]) diff --git a/driver-vpi/Makefile.in b/driver-vpi/Makefile.in index 834c54860..799dcf591 100644 --- a/driver-vpi/Makefile.in +++ b/driver-vpi/Makefile.in @@ -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 diff --git a/driver-vpi/config.h.in b/driver-vpi/config.h.in index 2b6789dd4..4a2fca81f 100644 --- a/driver-vpi/config.h.in +++ b/driver-vpi/config.h.in @@ -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@" diff --git a/iverilog-vpi.sh b/iverilog-vpi.sh index 197d6b3d0..10083ab89 100644 --- a/iverilog-vpi.sh +++ b/iverilog-vpi.sh @@ -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= diff --git a/ivtest/perl-lib/Environment.pm b/ivtest/perl-lib/Environment.pm index 492637193..ecdb49e15 100644 --- a/ivtest/perl-lib/Environment.pm +++ b/ivtest/perl-lib/Environment.pm @@ -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 diff --git a/ivtest/vlog95_reg.pl b/ivtest/vlog95_reg.pl index d9021a7a9..25caee834 100755 --- a/ivtest/vlog95_reg.pl +++ b/ivtest/vlog95_reg.pl @@ -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"; } } diff --git a/ivtest/vpi_reg.pl b/ivtest/vpi_reg.pl index 03a192261..6cf15f2f7 100755 --- a/ivtest/vpi_reg.pl +++ b/ivtest/vpi_reg.pl @@ -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= # 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" . " # 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"; } } diff --git a/ivtest/vpi_regress.list b/ivtest/vpi_regress.list index 895a9ef23..e0878171d 100644 --- a/ivtest/vpi_regress.list +++ b/ivtest/vpi_regress.list @@ -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 diff --git a/ivtest/vvp_reg.pl b/ivtest/vvp_reg.pl index 4dc2853ca..77bdc93ed 100755 --- a/ivtest/vvp_reg.pl +++ b/ivtest/vvp_reg.pl @@ -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; } diff --git a/msys2/PKGBUILD b/msys2/PKGBUILD index 6ad4bab42..3d87de438 100644 --- a/msys2/PKGBUILD +++ b/msys2/PKGBUILD @@ -21,6 +21,7 @@ build() { cd "${srcdir}"/../.. sh autoconf.sh ./configure \ + --enable-libveriuser \ --prefix="${MINGW_PREFIX}" \ --host="$CARCH"-w64-mingw32 mingw32-make diff --git a/vvp/Makefile.in b/vvp/Makefile.in index 085a36249..a57cb0573 100644 --- a/vvp/Makefile.in +++ b/vvp/Makefile.in @@ -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)