From c90be2ffd2200ffde31f859f8a4507edc110762c Mon Sep 17 00:00:00 2001 From: umarcor Date: Sun, 19 Apr 2020 02:10:38 +0200 Subject: [PATCH 01/10] vhpidirect/quickstart/wrapping: add 'exitcb' --- doc/vhpidirect/examples/quickstart.rst | 6 ++ test.py | 4 + vhpidirect/quickstart/wrapping/exitcb/caux.c | 19 ++++ vhpidirect/quickstart/wrapping/exitcb/main.c | 5 + vhpidirect/quickstart/wrapping/exitcb/main.py | 13 +++ .../quickstart/wrapping/exitcb/main_sigabrt.c | 16 +++ vhpidirect/quickstart/wrapping/exitcb/run.sh | 101 ++++++++++++++++++ vhpidirect/quickstart/wrapping/exitcb/tb.vhd | 18 ++++ 8 files changed, 182 insertions(+) create mode 100644 vhpidirect/quickstart/wrapping/exitcb/caux.c create mode 100644 vhpidirect/quickstart/wrapping/exitcb/main.c create mode 100644 vhpidirect/quickstart/wrapping/exitcb/main.py create mode 100644 vhpidirect/quickstart/wrapping/exitcb/main_sigabrt.c create mode 100755 vhpidirect/quickstart/wrapping/exitcb/run.sh create mode 100644 vhpidirect/quickstart/wrapping/exitcb/tb.vhd diff --git a/doc/vhpidirect/examples/quickstart.rst b/doc/vhpidirect/examples/quickstart.rst index 152d60e0..47e91d36 100644 --- a/doc/vhpidirect/examples/quickstart.rst +++ b/doc/vhpidirect/examples/quickstart.rst @@ -98,6 +98,12 @@ to the compiler and/or linker. However, since it is not possible to do so with A ``int argc, void** argv, void** envp``. This is done for illustration purposes only, as it has no real effect on the exercise. +:cosimtree:`exitcb ` +------------------------------------------------ + +On exit, ``ghdl_main`` behaves differently depending on the version of the standard that it used for VHDL. + + .. _COSIM:VHPIDIRECT:Examples:quickstart:linking: Linking diff --git a/test.py b/test.py index da938666..3560a178 100644 --- a/test.py +++ b/test.py @@ -67,6 +67,10 @@ def test_vhpidirect_quickstart_wrapping_time(self): ]) + def test_vhpidirect_quickstart_wrapping_exitcb(self): + self._sh([str(self.vhpidirect / 'quickstart' / 'wrapping' / 'exitcb' / 'run.sh')]) + + @unittest.skipIf( isWin, 'win: needs investigation, output of list-link seems to have wrong path format', diff --git a/vhpidirect/quickstart/wrapping/exitcb/caux.c b/vhpidirect/quickstart/wrapping/exitcb/caux.c new file mode 100644 index 00000000..e5670107 --- /dev/null +++ b/vhpidirect/quickstart/wrapping/exitcb/caux.c @@ -0,0 +1,19 @@ +#include +#include + +extern int ghdl_main(int argc, void** argv); + +// Procedure to be executed when GHDL exits. +static void exit_handler(void) { + printf("This is the exit handler.\n"); +} + +int wrapper(int argc, void** argv) { + atexit(exit_handler); + + printf("Hello wrapper!\n"); + printf("ghdl_main: %d\n", ghdl_main(argc, argv)); + printf("Bye wrapper!\n"); + + return 0; +} diff --git a/vhpidirect/quickstart/wrapping/exitcb/main.c b/vhpidirect/quickstart/wrapping/exitcb/main.c new file mode 100644 index 00000000..4b5f93dd --- /dev/null +++ b/vhpidirect/quickstart/wrapping/exitcb/main.c @@ -0,0 +1,5 @@ +extern int wrapper(int argc, void** argv); + +int main(int argc, void** argv) { + return wrapper(argc, argv); +} diff --git a/vhpidirect/quickstart/wrapping/exitcb/main.py b/vhpidirect/quickstart/wrapping/exitcb/main.py new file mode 100644 index 00000000..4378fe80 --- /dev/null +++ b/vhpidirect/quickstart/wrapping/exitcb/main.py @@ -0,0 +1,13 @@ +# When VHDL 1993 is used, the simulation is terminated with an `abort`, which prevents the user from running post-checks. +# These are some snippets to test it. See https://github.com/VUnit/vunit/pull/469#issuecomment-485723516. + +import os +import signal + +#https://bugs.python.org/issue12423 + +def handler(signum, frame): + print('Signal handler called with signal', signum) + +signal.signal(signal.SIGABRT, handler) +os.abort() diff --git a/vhpidirect/quickstart/wrapping/exitcb/main_sigabrt.c b/vhpidirect/quickstart/wrapping/exitcb/main_sigabrt.c new file mode 100644 index 00000000..6c5b05e4 --- /dev/null +++ b/vhpidirect/quickstart/wrapping/exitcb/main_sigabrt.c @@ -0,0 +1,16 @@ +#include +#include + +extern int wrapper(int argc, void** argv); + +void sigabrtHandler(int sig_num) { + // Reset handler to catch SIGABRT next time. Refer http://en.cppreference.com/w/c/program/signal + signal(SIGABRT, sigabrtHandler); + printf("\nSIGABRT caught %d!\n", sig_num); + fflush(stdout); +} + +int main(int argc, void** argv) { + signal(SIGABRT, sigabrtHandler); + return wrapper(argc, argv); +} diff --git a/vhpidirect/quickstart/wrapping/exitcb/run.sh b/vhpidirect/quickstart/wrapping/exitcb/run.sh new file mode 100755 index 00000000..b9b8f7e0 --- /dev/null +++ b/vhpidirect/quickstart/wrapping/exitcb/run.sh @@ -0,0 +1,101 @@ +#!/usr/bin/env sh + +set -e + +cd $(dirname "$0") + + +echo "> Analyze tb.vhd" +ghdl -a tb.vhd + + +echo "> Build tb pass (with main.c)" +ghdl -e -Wl,caux.c -Wl,main.c -o tb_pass tb pass + +echo "> Execute tb_pass" +./tb_pass +echo $? +echo "" + + +echo "> Build tb fail (with main.c)" +ghdl -e -Wl,caux.c -Wl,main.c -o tb_fail tb fail + +set +e + +echo "> Execute tb_fail" +./tb_fail +echo $? +echo "" + +set -e + + +echo "> Build tb pass_sigabrt (with main_sigabrt.c)" +ghdl -e -Wl,caux.c -Wl,main_sigabrt.c -o tb_pass_sigabrt tb pass + +echo "> Execute tb_pass_sigabrt" +./tb_pass_sigabrt +echo $? +echo "" + + +echo "> Build tb fail_sigabrt (with main_sigabrt.c)" +ghdl -e -Wl,caux.c -Wl,main_sigabrt.c -o tb_fail_sigabrt tb fail + +set +e + +echo "> Execute tb_fail_sigabrt" +./tb_fail_sigabrt +echo $? +echo "" + +set -e + + +echo "> Analyze --std=08 tb.vhd" +ghdl -a --std=08 tb.vhd + + +echo "> Build --std=08 tb pass (with main.c)" +ghdl -e --std=08 -Wl,caux.c -Wl,main.c -o tb_pass08 tb pass + +echo "> Execute tb_pass08" +./tb_pass08 +echo $? +echo "" + + +echo "> Build --std=08 tb fail (with main.c)" +ghdl -e --std=08 -Wl,caux.c -Wl,main.c -o tb_fail08 tb fail + +set +e + +echo "> Execute --std=08 tb_fail08" +./tb_fail08 +echo $? +echo "" + +set -e + + +echo "> Build --std=08 tb pass (with main_sigabrt.c)" +ghdl -e --std=08 -Wl,caux.c -Wl,main_sigabrt.c -o tb_pass08_sigabrt tb pass + +echo "> Execute tb_pass08_sigabrt" +./tb_pass08_sigabrt +echo $? +echo "" + + +echo "> Build --std=08 tb fail (with main_sigabrt.c)" +ghdl -e --std=08 -Wl,caux.c -Wl,main_sigabrt.c -o tb_fail08_sigabrt tb fail + +set +e + +echo "> Execute --std=08 tb_fail08_sigabrt" +./tb_fail08_sigabrt +echo $? +echo "" + +set -e diff --git a/vhpidirect/quickstart/wrapping/exitcb/tb.vhd b/vhpidirect/quickstart/wrapping/exitcb/tb.vhd new file mode 100644 index 00000000..bed04dda --- /dev/null +++ b/vhpidirect/quickstart/wrapping/exitcb/tb.vhd @@ -0,0 +1,18 @@ +entity tb is +end entity; + +architecture pass of tb is +begin + process begin + report "Hello wrapping/exitcb [pass]!" severity note; + wait; + end process; +end; + +architecture fail of tb is +begin + process begin + report "Hello wrapping/exitcb [fail]!" severity failure; + wait; + end process; +end; From e87a39cbc286425f1cd504979228a71928e2ac9d Mon Sep 17 00:00:00 2001 From: umarcor Date: Sun, 19 Apr 2020 05:06:30 +0200 Subject: [PATCH 02/10] vhpidirect/quickstart/wrapping: add 'exitcb/py' --- test.py | 4 + vhpidirect/quickstart/wrapping/exitcb/caux.c | 5 +- .../quickstart/wrapping/exitcb/main_sigabrt.c | 2 +- .../quickstart/wrapping/exitcb/py/cosim.py | 8 ++ .../quickstart/wrapping/exitcb/py/pyaux.py | 35 +++++++ .../wrapping/exitcb/py/vunit_cosim.py | 14 +++ .../wrapping/exitcb/py/vunit_run.py | 43 +++++++++ .../wrapping/exitcb/py/vunit_run.sh | 11 +++ .../wrapping/exitcb/py/vunit_tb.vhd | 24 +++++ vhpidirect/quickstart/wrapping/exitcb/run.sh | 94 ++++++++++--------- 10 files changed, 194 insertions(+), 46 deletions(-) create mode 100644 vhpidirect/quickstart/wrapping/exitcb/py/cosim.py create mode 100644 vhpidirect/quickstart/wrapping/exitcb/py/pyaux.py create mode 100644 vhpidirect/quickstart/wrapping/exitcb/py/vunit_cosim.py create mode 100644 vhpidirect/quickstart/wrapping/exitcb/py/vunit_run.py create mode 100755 vhpidirect/quickstart/wrapping/exitcb/py/vunit_run.sh create mode 100644 vhpidirect/quickstart/wrapping/exitcb/py/vunit_tb.vhd diff --git a/test.py b/test.py index 3560a178..4068c675 100644 --- a/test.py +++ b/test.py @@ -71,6 +71,10 @@ def test_vhpidirect_quickstart_wrapping_exitcb(self): self._sh([str(self.vhpidirect / 'quickstart' / 'wrapping' / 'exitcb' / 'run.sh')]) + def test_vhpidirect_quickstart_wrapping_exitcb_py(self): + self._sh([str(self.vhpidirect / 'quickstart' / 'wrapping' / 'exitcb' / 'py' / 'vunit_run.sh')]) + + @unittest.skipIf( isWin, 'win: needs investigation, output of list-link seems to have wrong path format', diff --git a/vhpidirect/quickstart/wrapping/exitcb/caux.c b/vhpidirect/quickstart/wrapping/exitcb/caux.c index e5670107..30dbaae7 100644 --- a/vhpidirect/quickstart/wrapping/exitcb/caux.c +++ b/vhpidirect/quickstart/wrapping/exitcb/caux.c @@ -3,7 +3,6 @@ extern int ghdl_main(int argc, void** argv); -// Procedure to be executed when GHDL exits. static void exit_handler(void) { printf("This is the exit handler.\n"); } @@ -12,8 +11,8 @@ int wrapper(int argc, void** argv) { atexit(exit_handler); printf("Hello wrapper!\n"); - printf("ghdl_main: %d\n", ghdl_main(argc, argv)); - printf("Bye wrapper!\n"); + int ecode = ghdl_main(argc, argv); + printf("Bye wrapper <%d>!\n", ecode); return 0; } diff --git a/vhpidirect/quickstart/wrapping/exitcb/main_sigabrt.c b/vhpidirect/quickstart/wrapping/exitcb/main_sigabrt.c index 6c5b05e4..a323d931 100644 --- a/vhpidirect/quickstart/wrapping/exitcb/main_sigabrt.c +++ b/vhpidirect/quickstart/wrapping/exitcb/main_sigabrt.c @@ -6,7 +6,7 @@ extern int wrapper(int argc, void** argv); void sigabrtHandler(int sig_num) { // Reset handler to catch SIGABRT next time. Refer http://en.cppreference.com/w/c/program/signal signal(SIGABRT, sigabrtHandler); - printf("\nSIGABRT caught %d!\n", sig_num); + printf("SIGABRT caught %d!\n", sig_num); fflush(stdout); } diff --git a/vhpidirect/quickstart/wrapping/exitcb/py/cosim.py b/vhpidirect/quickstart/wrapping/exitcb/py/cosim.py new file mode 100644 index 00000000..7243a8dd --- /dev/null +++ b/vhpidirect/quickstart/wrapping/exitcb/py/cosim.py @@ -0,0 +1,8 @@ +from pyaux import dlopen, dlclose, enc_args, run +from pathlib import Path + +print("PY COSIM ENTER") + +run(str(Path(__file__).resolve().parent.parent / "tb-fail.so"), 0, None) + +print("PY COSIM EXIT") diff --git a/vhpidirect/quickstart/wrapping/exitcb/py/pyaux.py b/vhpidirect/quickstart/wrapping/exitcb/py/pyaux.py new file mode 100644 index 00000000..c0dada6a --- /dev/null +++ b/vhpidirect/quickstart/wrapping/exitcb/py/pyaux.py @@ -0,0 +1,35 @@ +from pathlib import Path +import ctypes +import _ctypes + + +def dlopen(path): + if not Path(path).exists(): + print('Executable binary not found: ' + path) + exit(1) + try: + return ctypes.CDLL(path) + except OSError: + print('Loading executables dynamically seems not to be supported on this platform') + exit(1) + + +def dlclose(obj): + _ctypes.dlclose(obj._handle) + + +def enc_args(args): + xargs = (ctypes.POINTER(ctypes.c_char) * len(args))() + for idx, arg in enumerate(args): + xargs[idx] = ctypes.create_string_buffer(arg.encode('utf-8')) + return xargs + +def run(path, argc, argv): + print("PY RUN ENTER") + ghdl = dlopen(path) + ghdl.main(argc, argv) + # FIXME With VHDL 93, the execution is Aborted and Python exits here + + dlclose(ghdl) + + print("PY RUN EXIT") diff --git a/vhpidirect/quickstart/wrapping/exitcb/py/vunit_cosim.py b/vhpidirect/quickstart/wrapping/exitcb/py/vunit_cosim.py new file mode 100644 index 00000000..ac39fbda --- /dev/null +++ b/vhpidirect/quickstart/wrapping/exitcb/py/vunit_cosim.py @@ -0,0 +1,14 @@ +from pyaux import dlopen, dlclose, enc_args, run +from pathlib import Path +from json import load + +print("PY COSIM ENTER") + +with (Path(__file__).parent / 'vunit_out' / 'cosim' / 'tb_abrt.json').open() as json_file: + ARGS = load(json_file) + +XARGS = enc_args([ARGS["bin"]] + ARGS["sim"]) + +run(ARGS["bin"], len(XARGS) - 1, XARGS) + +print("PY COSIM EXIT") diff --git a/vhpidirect/quickstart/wrapping/exitcb/py/vunit_run.py b/vhpidirect/quickstart/wrapping/exitcb/py/vunit_run.py new file mode 100644 index 00000000..70950420 --- /dev/null +++ b/vhpidirect/quickstart/wrapping/exitcb/py/vunit_run.py @@ -0,0 +1,43 @@ +from vunit import VUnit +from os import makedirs, getenv +from pathlib import Path +from shutil import copyfile +import re + + +def post_func(results): + """ + Copy args.json to vunit/cosim/*.json + """ + report = results.get_report() + cosim_args_dir = Path(report.output_path) / "cosim" + try: + makedirs(str(cosim_args_dir)) + except FileExistsError: + pass + for key, item in report.tests.items(): + copyfile( + str(Path(item.path) / "ghdl" / "args.json"), + str( + cosim_args_dir / ("%s.json" % re.search(r"lib\.(.+)\.all", key)[1]) + ), + ) + + +ROOT = Path(__file__).resolve().parent + +vu = VUnit.from_argv(vhdl_standard=getenv('VUNIT_VHDL_STANDARD', '2008')) + +lib = vu.add_library('lib').add_source_files(str(ROOT / 'vunit_tb.vhd')) + +vu.set_sim_option('ghdl.elab_flags', [ + '-shared', + '-Wl,-fPIC', + '-Wl,' + str(ROOT.parent / 'caux.c'), + '-Wl,' + str(ROOT.parent / 'main_sigabrt.c') +]) + +vu.set_sim_option("ghdl.elab_e", True) +vu._args.elaborate = True + +vu.main(post_run=post_func) diff --git a/vhpidirect/quickstart/wrapping/exitcb/py/vunit_run.sh b/vhpidirect/quickstart/wrapping/exitcb/py/vunit_run.sh new file mode 100755 index 00000000..097e46c8 --- /dev/null +++ b/vhpidirect/quickstart/wrapping/exitcb/py/vunit_run.sh @@ -0,0 +1,11 @@ +#!/usr/bin/env sh + +cd $(dirname "$0") + +export VUNIT_VHDL_STANDARD="2008" +python3 vunit_run.py -v +python3 vunit_cosim.py + +export VUNIT_VHDL_STANDARD="93" +python3 vunit_run.py -v +python3 vunit_cosim.py diff --git a/vhpidirect/quickstart/wrapping/exitcb/py/vunit_tb.vhd b/vhpidirect/quickstart/wrapping/exitcb/py/vunit_tb.vhd new file mode 100644 index 00000000..5c5c7b1e --- /dev/null +++ b/vhpidirect/quickstart/wrapping/exitcb/py/vunit_tb.vhd @@ -0,0 +1,24 @@ +library vunit_lib; +use vunit_lib.run_pkg.all; +use vunit_lib.logger_pkg.all; + +entity tb_abrt is + generic ( runner_cfg : string ); +end entity; + +architecture tb of tb_abrt is + + constant block_len : natural := 5; + +begin + + main: process + variable val, ind: integer; + begin + test_runner_setup(runner, runner_cfg); + info("Hello wrapping/exitcb/py_vunit!"); + test_runner_cleanup(runner); + wait; + end process; + +end architecture; diff --git a/vhpidirect/quickstart/wrapping/exitcb/run.sh b/vhpidirect/quickstart/wrapping/exitcb/run.sh index b9b8f7e0..0d770a6f 100755 --- a/vhpidirect/quickstart/wrapping/exitcb/run.sh +++ b/vhpidirect/quickstart/wrapping/exitcb/run.sh @@ -4,98 +4,108 @@ set -e cd $(dirname "$0") +for std in '08' '93'; do -echo "> Analyze tb.vhd" -ghdl -a tb.vhd +echo "> [$std] Analyze tb.vhd" +ghdl -a --std="$std" tb.vhd -echo "> Build tb pass (with main.c)" -ghdl -e -Wl,caux.c -Wl,main.c -o tb_pass tb pass +echo "> [$std] Build tb pass" +ghdl -e --std="$std" -Wl,caux.c -Wl,main.c -o tb"$std"_pass tb pass -echo "> Execute tb_pass" -./tb_pass +echo "> [$std] Execute tb_pass" +./tb"$std"_pass echo $? echo "" -echo "> Build tb fail (with main.c)" -ghdl -e -Wl,caux.c -Wl,main.c -o tb_fail tb fail +echo "> [$std] Build tb-pass.so" +ghdl -e --std="$std" -shared -Wl,-fPIC -Wl,caux.c -Wl,main.c tb pass +mv tb-pass.so tb-fail.so +echo "" set +e -echo "> Execute tb_fail" -./tb_fail -echo $? +echo "> [$std] Python cosim pass" +python3 py/cosim.py echo "" set -e -echo "> Build tb pass_sigabrt (with main_sigabrt.c)" -ghdl -e -Wl,caux.c -Wl,main_sigabrt.c -o tb_pass_sigabrt tb pass +echo "> [$std] Build tb fail" +ghdl -e --std="$std" -Wl,caux.c -Wl,main.c -o tb"$std"_fail tb fail -echo "> Execute tb_pass_sigabrt" -./tb_pass_sigabrt +set +e + +echo "> [$std] Execute tb_fail" +./tb"$std"_fail echo $? echo "" +set -e + -echo "> Build tb fail_sigabrt (with main_sigabrt.c)" -ghdl -e -Wl,caux.c -Wl,main_sigabrt.c -o tb_fail_sigabrt tb fail +echo "> [$std] Build tb-fail.so" +ghdl -e --std="$std" -shared -Wl,-fPIC -Wl,caux.c -Wl,main.c tb fail +echo "" set +e -echo "> Execute tb_fail_sigabrt" -./tb_fail_sigabrt -echo $? +echo "> [$std] Python cosim fail" +python3 py/cosim.py echo "" set -e -echo "> Analyze --std=08 tb.vhd" -ghdl -a --std=08 tb.vhd - - -echo "> Build --std=08 tb pass (with main.c)" -ghdl -e --std=08 -Wl,caux.c -Wl,main.c -o tb_pass08 tb pass +echo "> [$std] Build tb pass_sigabrt" +ghdl -e --std="$std" -Wl,caux.c -Wl,main_sigabrt.c -o tb"$std"_pass_sigabrt tb pass -echo "> Execute tb_pass08" -./tb_pass08 +echo "> [$std] Execute tb_pass_sigabrt" +./tb"$std"_pass_sigabrt echo $? echo "" +set -e + -echo "> Build --std=08 tb fail (with main.c)" -ghdl -e --std=08 -Wl,caux.c -Wl,main.c -o tb_fail08 tb fail +echo "> [$std] Build tb-pass.so (sigabrt)" +ghdl -e --std="$std" -shared -Wl,-fPIC -Wl,caux.c -Wl,main_sigabrt.c tb pass +mv tb-pass.so tb-fail.so +echo "" set +e -echo "> Execute --std=08 tb_fail08" -./tb_fail08 -echo $? +echo "> [$std] Python cosim pass (sigabrt)" +python3 py/cosim.py echo "" set -e -echo "> Build --std=08 tb pass (with main_sigabrt.c)" -ghdl -e --std=08 -Wl,caux.c -Wl,main_sigabrt.c -o tb_pass08_sigabrt tb pass +echo "> [$std] Build tb fail_sigabrt)" +ghdl -e --std="$std" -Wl,caux.c -Wl,main_sigabrt.c -o tb"$std"_fail_sigabrt tb fail + +set +e -echo "> Execute tb_pass08_sigabrt" -./tb_pass08_sigabrt +echo "> [$std] Execute tb_fail_sigabrt" +./tb"$std"_fail_sigabrt echo $? echo "" +set -e -echo "> Build --std=08 tb fail (with main_sigabrt.c)" -ghdl -e --std=08 -Wl,caux.c -Wl,main_sigabrt.c -o tb_fail08_sigabrt tb fail +echo "> [$std] Build tb-fail.so (sigabrt)" +ghdl -e --std="$std" -shared -Wl,-fPIC -Wl,caux.c -Wl,main_sigabrt.c tb fail +echo "" set +e -echo "> Execute --std=08 tb_fail08_sigabrt" -./tb_fail08_sigabrt -echo $? +echo "> [$std] Python cosim fail (sigabrt)" +python3 py/cosim.py echo "" set -e + +done From 27b25bcb07902541fea729c4cfc14f246d7762c7 Mon Sep 17 00:00:00 2001 From: umarcor Date: Tue, 26 Jan 2021 23:26:04 +0100 Subject: [PATCH 03/10] ci: deprecate 'win-stable', add 'win-msys2' --- .github/workflows/test.yml | 39 +++++++++++++++++++------------------- 1 file changed, 20 insertions(+), 19 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 4cd751d2..8a3b7f9a 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -27,25 +27,6 @@ jobs: - uses: actions/checkout@v2 - run: docker run --rm -v $(pwd):/src -w /src -e CI ghdl/cosim:matplotlib python3 -m pytest -v -s -ra test.py --color=yes - win-stable: - runs-on: windows-latest - steps: - - uses: actions/checkout@v2 - - uses: actions/setup-python@v2 - with: - python-version: 3.8 - - env: - WINDOWS_RELEASE: 0.37-mingw64-llvm - shell: bash - run: | - curl -fsSL -o ghdl.zip https://github.com/ghdl/ghdl/releases/download/v0.37/ghdl-${WINDOWS_RELEASE}.zip - 7z x ghdl.zip "-o../ghdl-tmp" -y - mv ../ghdl-tmp/GHDL/${WINDOWS_RELEASE}/ ../ghdl - rm -rf ../ghdl-tmp ghdl.zip - export PATH=$PATH:$(pwd)/../ghdl/bin - python -m pip install pytest vunit_hdl matplotlib numpy --progress-bar off - python -m pytest -v -s -ra test.py --color=yes - lin-setup: runs-on: ubuntu-latest steps: @@ -85,3 +66,23 @@ jobs: backend: llvm - run: python -m pip install --progress-bar off pytest vunit_hdl - run: python -m pytest -v -s -ra test.py --color=yes + + win-msys: + runs-on: windows-latest + defaults: + run: + shell: msys2 {0} + steps: + - uses: msys2/setup-msys2@v2 + with: + msystem: MINGW64 + update: true + install: > + mingw-w64-x86_64-ghdl-llvm + mingw-w64-x86_64-python-pip + mingw-w64-x86_64-python-numpy + mingw-w64-x86_64-python-matplotlib + mingw-w64-x86_64-openssl + - uses: actions/checkout@v2 + - run: python -m pip install --progress-bar off pytest vunit_hdl + - run: python -m pytest -v -s -ra test.py --color=yes From b2946feeacaf234d3a1def87bae9f8f0e394956e Mon Sep 17 00:00:00 2001 From: umarcor Date: Wed, 27 Jan 2021 00:20:25 +0100 Subject: [PATCH 04/10] ci/win: install dlfcn through pacman --- .github/workflows/test.yml | 2 ++ test.py | 8 -------- 2 files changed, 2 insertions(+), 8 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 8a3b7f9a..88f986b8 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -60,6 +60,7 @@ jobs: mingw-w64-x86_64-python-numpy mingw-w64-x86_64-python-matplotlib mingw-w64-x86_64-openssl + mingw-w64-x86_64-dlfcn - uses: actions/checkout@v2 - uses: ghdl/setup-ghdl-ci@master with: @@ -83,6 +84,7 @@ jobs: mingw-w64-x86_64-python-numpy mingw-w64-x86_64-python-matplotlib mingw-w64-x86_64-openssl + mingw-w64-x86_64-dlfcn - uses: actions/checkout@v2 - run: python -m pip install --progress-bar off pytest vunit_hdl - run: python -m pytest -v -s -ra test.py --color=yes diff --git a/test.py b/test.py index 4068c675..6ad60a97 100644 --- a/test.py +++ b/test.py @@ -105,18 +105,10 @@ def test_vhpidirect_shared_shlib(self): self._sh([str(self.vhpidirect / 'shared' / 'shlib' / 'run.sh')]) - @unittest.skipIf( - isWin, - 'win: dlfcn.h is not available on win', - ) def test_vhpidirect_shared_dlopen(self): self._sh([str(self.vhpidirect / 'shared' / 'dlopen' / 'run.sh')]) - @unittest.skipIf( - isWin, - 'win: dlfcn.h is not available on win', - ) def test_vhpidirect_shared_shghdl(self): self._sh([str(self.vhpidirect / 'shared' / 'shghdl' / 'run.sh')]) From 0241e0477f3e319d20e75b0290e84f90aac9521e Mon Sep 17 00:00:00 2001 From: umarcor Date: Wed, 27 Jan 2021 00:17:27 +0100 Subject: [PATCH 05/10] vhpidirect/shared/shghdl: enable partially on MSYS2 --- vhpidirect/shared/shghdl/main.c | 7 ++++-- vhpidirect/shared/shghdl/run.sh | 39 +++++++++++++++++++++++---------- 2 files changed, 32 insertions(+), 14 deletions(-) diff --git a/vhpidirect/shared/shghdl/main.c b/vhpidirect/shared/shghdl/main.c index 19b32b36..dea38e72 100644 --- a/vhpidirect/shared/shghdl/main.c +++ b/vhpidirect/shared/shghdl/main.c @@ -2,9 +2,12 @@ #include #include +// TODO: Use different procedures for Linux, Windows and macOS +// See https://github.com/ghdl/ghdl/tree/master/testsuite/gna/issue803 + int main(int argc, void** argv) { - void* h = dlopen("./tb.so", RTLD_LAZY); + void* h = dlopen("./tb.lib", RTLD_LAZY); if (!h){ fprintf(stderr, "%s\n", dlerror()); exit(1); @@ -37,7 +40,7 @@ int main(int argc, void** argv) { dlclose(h); if (i<2) { - h = dlopen("./tb.so", RTLD_LAZY); + h = dlopen("./tb.lib", RTLD_LAZY); if (!h){ fprintf(stderr, "%s\n", dlerror()); exit(1); diff --git a/vhpidirect/shared/shghdl/run.sh b/vhpidirect/shared/shghdl/run.sh index 0a7e5202..9e6bb828 100755 --- a/vhpidirect/shared/shghdl/run.sh +++ b/vhpidirect/shared/shghdl/run.sh @@ -4,6 +4,11 @@ set -e cd $(dirname "$0") +_os='linux' +case "$(uname)" in + MINGW*) _os='windows';; +esac + echo "> Analyze tb.vhd" ghdl -a tb.vhd @@ -12,21 +17,31 @@ gcc main.c -o main -ldl #--- -echo "> Build and execute [GHDL]" -ghdl -e -Wl,test.c -Wl,-Wl,--version-script=./test.ver -o tb.so tb -./main +if [ "x${_os}" != "xwindows" ]; then + # This is hackish, since the generated file is an executable, not a shared library. + # It might work on some platforms due to the similarities between ELF binaries and libs. + echo "> Build and execute [GHDL]" + ghdl -e -Wl,test.c -Wl,-Wl,--version-script=./test.ver -o tb.lib tb + ./main -echo "> Build and execute [GHDL -shared]" -ghdl -e -Wl,test.c -shared -o tb.so tb -./main + # Custom function names are not exported/visible by default on some platforms. + # This might work, but spicifying a custom '--version-script' is recommended (see below). + echo "> Build and execute [GHDL -shared]" + ghdl -e -Wl,test.c -shared -o tb.so tb + ./main +fi echo "> Build and execute [GHDL -Wl,-shared]" -ghdl -e -Wl,test.c -Wl,-shared -Wl,-Wl,--version-script=./test.ver -Wl,-Wl,-u,ghdl_main -o tb.so tb +ghdl -e -Wl,test.c -Wl,-shared -Wl,-Wl,--version-script=./test.ver -Wl,-Wl,-u,ghdl_main -o tb.lib tb ./main -echo "> Bind tb" -ghdl --bind tb +if [ "x${_os}" != "xwindows" ]; then + # FIXME: This should work on MSYS2. The problem is the paths returned by '--list-link', + # which contain mixed '\' and '/'. See quickstart/linking/bind + echo "> Bind tb" + ghdl --bind tb -echo "> Build and execute [GCC -shared]" -gcc test.c -shared -Wl,`ghdl --list-link tb` -Wl,--version-script=./test.ver -Wl,-u,ghdl_main -o tb.so -./main + echo "> Build and execute [GCC -shared]" + gcc test.c -shared -Wl,`ghdl --list-link tb` -Wl,--version-script=./test.ver -Wl,-u,ghdl_main -o tb.lib + ./main +fi From b20453f193c962ed71c07cc667d8de9483a37611 Mon Sep 17 00:00:00 2001 From: umarcor Date: Wed, 27 Jan 2021 00:16:23 +0100 Subject: [PATCH 06/10] vhpidirect/quickstart/linking/bind: enable partially on MSYS2 --- test.py | 4 --- vhpidirect/quickstart/linking/bind/run.sh | 41 ++++++++++++++--------- 2 files changed, 26 insertions(+), 19 deletions(-) diff --git a/test.py b/test.py index 6ad60a97..fe5c235b 100644 --- a/test.py +++ b/test.py @@ -75,10 +75,6 @@ def test_vhpidirect_quickstart_wrapping_exitcb_py(self): self._sh([str(self.vhpidirect / 'quickstart' / 'wrapping' / 'exitcb' / 'py' / 'vunit_run.sh')]) - @unittest.skipIf( - isWin, - 'win: needs investigation, output of list-link seems to have wrong path format', - ) def test_vhpidirect_quickstart_linking_bind(self): self._sh([str(self.vhpidirect / 'quickstart' / 'linking' / 'bind' / 'run.sh')]) diff --git a/vhpidirect/quickstart/linking/bind/run.sh b/vhpidirect/quickstart/linking/bind/run.sh index fdfa55b8..3ecd1dd3 100755 --- a/vhpidirect/quickstart/linking/bind/run.sh +++ b/vhpidirect/quickstart/linking/bind/run.sh @@ -4,6 +4,11 @@ set -e cd $(dirname "$0") +_os='linux' +case "$(uname)" in + MINGW*) _os='windows';; +esac + echo "Analyze tb.vhd" ghdl -a tb.vhd @@ -28,25 +33,31 @@ echo "Execute tb_o" # OR -echo "Bind tb" -ghdl --bind tb +if [ "x${_os}" != "xwindows" ]; then + # FIXME: This should work on MSYS2, but the output of '--list-link' is broken. + # The returned paths contain mixed '\' and '/'. -echo "Build tb (with main.c) [GCC]" -gcc main.c -Wl,`ghdl --list-link tb` -o tb_lc + echo "Bind tb" + ghdl --bind tb -echo "Execute tb_lc" -./tb_lc + echo "Build tb (with main.c) [GCC]" + gcc main.c -Wl,`ghdl --list-link tb` -o tb_lc -# OR + echo "Execute tb_lc" + ./tb_lc -echo "Build main.c" -gcc -c main.c + # OR + + echo "Build main.c" + gcc -c main.c + + echo "Bind tb" + ghdl --bind tb -echo "Bind tb" -ghdl --bind tb + echo "Build tb (with main.o) [GCC]" + gcc main.o -Wl,`ghdl --list-link tb` -o tb_lo -echo "Build tb (with main.o) [GCC]" -gcc main.o -Wl,`ghdl --list-link tb` -o tb_lo + echo "Execute tb_lo" + ./tb_lo -echo "Execute tb_lo" -./tb_lo +fi From 9bbbb6665e9cd446fd2d2cb4ca140b99a9ff686c Mon Sep 17 00:00:00 2001 From: umarcor Date: Wed, 27 Jan 2021 01:21:41 +0100 Subject: [PATCH 07/10] ci: move VFFI demo to separate jobs --- .github/workflows/test.yml | 27 +++++++++++++++++++++++++++ test.py | 4 ---- 2 files changed, 27 insertions(+), 4 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 88f986b8..17cba408 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -88,3 +88,30 @@ jobs: - uses: actions/checkout@v2 - run: python -m pip install --progress-bar off pytest vunit_hdl - run: python -m pytest -v -s -ra test.py --color=yes + +#-- + + lin-setup-vffi-demo: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - uses: ghdl/setup-ghdl-ci@master + with: + backend: llvm + - run: ./vhpidirect/vffi_user/demo/run.sh + + win-setup-vffi-demo: + runs-on: windows-latest + defaults: + run: + shell: msys2 {0} + steps: + - uses: msys2/setup-msys2@v2 + with: + msystem: MINGW64 + update: true + - uses: actions/checkout@v2 + - uses: ghdl/setup-ghdl-ci@master + with: + backend: llvm + - run: ./vhpidirect/vffi_user/demo/run.sh diff --git a/test.py b/test.py index fe5c235b..d66e03f8 100644 --- a/test.py +++ b/test.py @@ -137,10 +137,6 @@ def test_vhpidirect_arrays_matrices_framebuffer(self): self._sh([str(self.vhpidirect / 'arrays' / 'matrices' / 'framebuffer' / 'run.sh')]) - def test_vhpidirect_vffi_demo(self): - self._sh([str(self.vhpidirect / 'vffi_user' / 'demo' / 'run.sh')]) - - @unittest.skipUnless( 'MINGW_PREFIX' in environ or not isWin, "needs OpenSSL", From 2095ccccfa8b535a983009b022ef8311f07f1a3d Mon Sep 17 00:00:00 2001 From: umarcor Date: Wed, 27 Jan 2021 01:39:26 +0100 Subject: [PATCH 08/10] ci: add labels and emojis/icons --- .github/workflows/doc.yml | 23 ++++++-- .github/workflows/test.yml | 112 ++++++++++++++++++++++++++++--------- 2 files changed, 105 insertions(+), 30 deletions(-) diff --git a/.github/workflows/doc.yml b/.github/workflows/doc.yml index 47823d93..9e68913d 100644 --- a/.github/workflows/doc.yml +++ b/.github/workflows/doc.yml @@ -1,15 +1,28 @@ name: 'doc' -on: [push, pull_request] + +on: + push: + pull_request: + jobs: - linux: + + + btd: + name: '📓 Docs' if: github.event_name != 'pull_request' runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 - - uses: buildthedocs/btd@v0 + + - name: '🧰 Checkout' + uses: actions/checkout@v2 + + - name: '📓 BuildTheDocs (BTD)' + uses: buildthedocs/btd@v0 with: token: ${{ secrets.GITHUB_TOKEN }} - - uses: actions/upload-artifact@master + + - name: '📤 Upload artifact: HTML' + uses: actions/upload-artifact@master with: name: doc path: doc/_build/html diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 17cba408..815c109c 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -11,47 +11,77 @@ env: jobs: + xyce-docker: + name: '🛳️ ghdl/cosim:xyce' runs-on: ubuntu-latest env: DOCKER_BUILDKIT: 1 steps: - - uses: actions/checkout@v2 - - run: docker run --rm -v $(pwd):/src -w /src -e CI ghdl/cosim:xyce python3 -m pytest -v -s -ra test.py::TestExamples::test_vhpidirect_vffi_xyce --color=yes + + - name: '🧰 Checkout' + uses: actions/checkout@v2 + + - name: '🚧 Run tests' + run: docker run --rm -v $(pwd):/src -w /src -e CI ghdl/cosim:xyce python3 -m pytest -v -s -ra test.py::TestExamples::test_vhpidirect_vffi_xyce --color=yes + lin-docker: + name: '🛳️ ghdl/cosim:matplotlib' runs-on: ubuntu-latest env: DOCKER_BUILDKIT: 1 steps: - - uses: actions/checkout@v2 - - run: docker run --rm -v $(pwd):/src -w /src -e CI ghdl/cosim:matplotlib python3 -m pytest -v -s -ra test.py --color=yes + + - name: '🧰 Checkout' + uses: actions/checkout@v2 + + - name: '🚧 Run tests' + run: docker run --rm -v $(pwd):/src -w /src -e CI ghdl/cosim:matplotlib python3 -m pytest -v -s -ra test.py --color=yes + lin-setup: + name: '🐧Ubuntu · nightly LLVM' runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 - - uses: ghdl/setup-ghdl-ci@master + + - name: '🧰 Checkout' + uses: actions/checkout@v2 + + - name: '⚙️ Setup GHDL (LLVM)' + uses: ghdl/setup-ghdl-ci@master with: backend: llvm - - uses: actions/setup-python@v2 + + - name: '🐍 Setup Python' + uses: actions/setup-python@v2 with: python-version: 3.8 - - name: Install dependencies + + - name: '⚙️ Install dependencies' run: | ghdl --version sudo apt update -qq sudo apt install -y imagemagick libssl-dev python -m pip install --progress-bar off pytest vunit_hdl matplotlib numpy - - run: python -m pytest -v -s -ra test.py --color=yes + + - name: '🚧 Run tests' + run: python -m pytest -v -s -ra test.py --color=yes + win-setup: + name: '🟪 MSYS2 · nightly LLVM' runs-on: windows-latest defaults: run: shell: msys2 {0} steps: - - uses: msys2/setup-msys2@v2 + + - name: '🧰 Checkout' + uses: actions/checkout@v2 + + - name: '🟪 Setup MSYS2' + uses: msys2/setup-msys2@v2 with: msystem: MINGW64 update: true @@ -61,20 +91,32 @@ jobs: mingw-w64-x86_64-python-matplotlib mingw-w64-x86_64-openssl mingw-w64-x86_64-dlfcn - - uses: actions/checkout@v2 - - uses: ghdl/setup-ghdl-ci@master + + - name: '⚙️ Setup GHDL (LLVM)' + uses: ghdl/setup-ghdl-ci@master with: backend: llvm - - run: python -m pip install --progress-bar off pytest vunit_hdl - - run: python -m pytest -v -s -ra test.py --color=yes + + - name: '🐍 Install dependencies' + run: python -m pip install --progress-bar off pytest vunit_hdl + + - name: '🚧 Run tests' + run: python -m pytest -v -s -ra test.py --color=yes + win-msys: + name: '🟪 MSYS2 · pacman LLVM' runs-on: windows-latest defaults: run: shell: msys2 {0} steps: - - uses: msys2/setup-msys2@v2 + + - name: '🧰 Checkout' + uses: actions/checkout@v2 + + - name: '🟪 Setup MSYS2' + uses: msys2/setup-msys2@v2 with: msystem: MINGW64 update: true @@ -85,33 +127,53 @@ jobs: mingw-w64-x86_64-python-matplotlib mingw-w64-x86_64-openssl mingw-w64-x86_64-dlfcn - - uses: actions/checkout@v2 - - run: python -m pip install --progress-bar off pytest vunit_hdl - - run: python -m pytest -v -s -ra test.py --color=yes + + - name: '🐍 Install dependencies' + run: python -m pip install --progress-bar off pytest vunit_hdl + + - name: '🚧 Run tests' + run: python -m pytest -v -s -ra test.py --color=yes #-- lin-setup-vffi-demo: + name: '🐧Ubuntu · nightly LLVM · VFFI' runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 - - uses: ghdl/setup-ghdl-ci@master + + - name: '🧰 Checkout' + uses: actions/checkout@v2 + + - name: '⚙️ Setup GHDL (LLVM)' + uses: ghdl/setup-ghdl-ci@master with: backend: llvm - - run: ./vhpidirect/vffi_user/demo/run.sh + + - name: '🚧 Run tests' + run: ./vhpidirect/vffi_user/demo/run.sh + win-setup-vffi-demo: + name: '🟪 MSYS2 · nightly LLVM · VFFI' runs-on: windows-latest defaults: run: shell: msys2 {0} steps: - - uses: msys2/setup-msys2@v2 + + - name: '🧰 Checkout' + uses: actions/checkout@v2 + + - name: '🟪 Setup MSYS2' + uses: msys2/setup-msys2@v2 with: msystem: MINGW64 update: true - - uses: actions/checkout@v2 - - uses: ghdl/setup-ghdl-ci@master + + - name: '⚙️ Setup GHDL (LLVM)' + uses: ghdl/setup-ghdl-ci@master with: backend: llvm - - run: ./vhpidirect/vffi_user/demo/run.sh + + - name: '🚧 Run tests' + run: ./vhpidirect/vffi_user/demo/run.sh From 6fc1842e612ca470127894c215a48517008d3cb0 Mon Sep 17 00:00:00 2001 From: umarcor Date: Tue, 26 Jan 2021 10:26:17 +0100 Subject: [PATCH 09/10] vhpidirect/quickstart/wrapping/exitcb: cleanup after abort fix in ghdl/ghdl --- doc/vhpidirect/examples/quickstart.rst | 12 +- doc/vhpidirect/examples/shared.rst | 43 +++++-- test.py | 11 +- vhpidirect/quickstart/wrapping/exitcb/caux.c | 18 --- vhpidirect/quickstart/wrapping/exitcb/main.c | 30 ++++- .../quickstart/wrapping/exitcb/main_sigabrt.c | 16 --- .../quickstart/wrapping/exitcb/py/cosim.py | 8 -- .../wrapping/exitcb/py/vunit_cosim.py | 14 --- .../wrapping/exitcb/py/vunit_run.sh | 11 -- vhpidirect/quickstart/wrapping/exitcb/run.sh | 114 +++--------------- .../wrapping/exitcb => shared}/py/pyaux.py | 12 +- vhpidirect/shared/py/run.sh | 31 +++++ vhpidirect/shared/py/vunit/cosim.py | 12 ++ .../vunit_run.py => shared/py/vunit/run.py} | 5 +- vhpidirect/shared/py/vunit/run.sh | 23 ++++ .../main.py => shared/py/vunit/sigabrt.py} | 0 .../vunit_tb.vhd => shared/py/vunit/tb.vhd} | 10 +- 17 files changed, 172 insertions(+), 198 deletions(-) delete mode 100644 vhpidirect/quickstart/wrapping/exitcb/caux.c delete mode 100644 vhpidirect/quickstart/wrapping/exitcb/main_sigabrt.c delete mode 100644 vhpidirect/quickstart/wrapping/exitcb/py/cosim.py delete mode 100644 vhpidirect/quickstart/wrapping/exitcb/py/vunit_cosim.py delete mode 100755 vhpidirect/quickstart/wrapping/exitcb/py/vunit_run.sh rename vhpidirect/{quickstart/wrapping/exitcb => shared}/py/pyaux.py (80%) create mode 100755 vhpidirect/shared/py/run.sh create mode 100644 vhpidirect/shared/py/vunit/cosim.py rename vhpidirect/{quickstart/wrapping/exitcb/py/vunit_run.py => shared/py/vunit/run.py} (84%) create mode 100755 vhpidirect/shared/py/vunit/run.sh rename vhpidirect/{quickstart/wrapping/exitcb/main.py => shared/py/vunit/sigabrt.py} (100%) rename vhpidirect/{quickstart/wrapping/exitcb/py/vunit_tb.vhd => shared/py/vunit/tb.vhd} (62%) diff --git a/doc/vhpidirect/examples/quickstart.rst b/doc/vhpidirect/examples/quickstart.rst index 47e91d36..90eb3715 100644 --- a/doc/vhpidirect/examples/quickstart.rst +++ b/doc/vhpidirect/examples/quickstart.rst @@ -98,11 +98,19 @@ to the compiler and/or linker. However, since it is not possible to do so with A ``int argc, void** argv, void** envp``. This is done for illustration purposes only, as it has no real effect on the exercise. +.. _COSIM:VHPIDIRECT:Examples:quickstart:wrapping:exitcb: + :cosimtree:`exitcb ` ------------------------------------------------- +----------------------------------------------------------- -On exit, ``ghdl_main`` behaves differently depending on the version of the standard that it used for VHDL. +When wrapped in a foreign language, calls to ``ghdl_main`` should return an exit code and allow the regular execution of the +wrapper, so that users can handle simulation results in there. However, bugs might result in failures that exit immediately +through an abortion signal. This example shows how to register an exit handler and a signal handler, to allow executing +custom code regardless of crashes in the simulation. +In VHDL 1993, simulation termination statements and exit codes that simulators should produce were undefined. Therefore, it was +common practice to termine the simulations through reports of severity ``failure``. When wrapping GHDL, such strategies +might result in undesired exit procedures. Using VHDL 2008 is suggested. .. _COSIM:VHPIDIRECT:Examples:quickstart:linking: diff --git a/doc/vhpidirect/examples/shared.rst b/doc/vhpidirect/examples/shared.rst index 9240158e..61d0b694 100644 --- a/doc/vhpidirect/examples/shared.rst +++ b/doc/vhpidirect/examples/shared.rst @@ -8,6 +8,16 @@ Shared libs and dynamic loading As explained in :ref:`COSIM:VHPIDIRECT:Dynamic:loading_a_simulation`, in order to load binaries/libraries dynamically, those need to be built as position independent code/executables (PIC/PIE). +This set of examples is an introduction from scratch for users who are familiar with C, but who have never built or loaded +shared libraries (``*.so``, ``*.dll`` or ``*.dyn``): + +* :ref:`COSIM:VHPIDIRECT:Examples:shared:shlib`: write C code and compile it as a shared library. +* :ref:`COSIM:VHPIDIRECT:Examples:shared:dlopen`: write two shared libraries in C, and write a main C program for loading and executing both of them. +* :ref:`COSIM:VHPIDIRECT:Examples:shared:shghdl`: build a simulation as a shared library, and write a main C program for loading and executing it. +* :ref:`COSIM:VHPIDIRECT:Examples:shared:py`: build a simulation as a shared library, and write a Python script for loading and executing it. +* :ref:`COSIM:VHPIDIRECT:Examples:shared:pycb`: build a simulation as a shared library, and write a Python script for loading it and replacing callbacks + through ``ctypes`` before executing the simulation. + .. _COSIM:VHPIDIRECT:Examples:shared:shlib: :cosimtree:`shlib ` @@ -62,23 +72,36 @@ symbols in the shared libraries. :ref:`COSIM:VHPIDIRECT:Dynamic:generating_shared_libraries`. In this example, this case is also tested. However, this is not suggested at all, since it won't work on all platforms. -.. WARNING:: - Currently, failing simulations that are dynamically loaded do produce an *Abortion*. This forces any C or Python - wrapper/caller to exit inmediately, without running any post-check. See :ghdlsharp:`803` and :cosimsharp:`15` for - further details. - .. _COSIM:VHPIDIRECT:Examples:shared:py: -py -** +:cosimtree:`py ` +************************************** `Python `_'s :py:mod:`ctypes` module is a built-in "*foreign function library for Python*", which "*provides C compatible data types, and allows calling functions in DLLs or shared libraries*". Thus, it is posible to reproduce :ref:`COSIM:VHPIDIRECT:Examples:shared:shghdl` by loading and executing the simulation from Python, instead of -C. In fact, this is the foundation of `VUnit/cosim `_. +C. + +This example uses the testbench and C sources from :ref:`COSIM:VHPIDIRECT:Examples:quickstart:wrapping:exitcb`, but the simulation +is built as a shared library and loaded dynamically from Python. A helper Python module is used for providing OS agnostic +utilities (see :cosimtree:`pyaux.py `). -Nonethless, this example has not been added yet because of :cosimsharp:`15`. As soon as GHDL is fixed so that both successful -and failing simulations exit cleanly, a minimal Python example will be added here. +.. WARNING:: + On some Linux environments, failing simulations that are dynamically loaded from Python do produce an *Abortion*. This + forces the wrapper/caller to exit inmediately, without running any post-check. See :ghdlsharp:`803` and :cosimsharp:`15` for + further details. + +:cosimtree:`py/vunit ` +================================================== + +This is equivalent to the previous example (:ref:`COSIM:VHPIDIRECT:Examples:shared:py`). Instead of calling GHDL's CLI explicitly, +VUnit's Python aided plumbing is used. This allows including any of VUnit's VHDL features into the simulation models, which +are then to be loaded dynamically from Python. In fact, this is the foundation of `VUnit/cosim `_. + +.. WARNING:: + On some Linux environments, using VHDL 2008 works but VHDL 1993 does not return cleanly in case of failure. An *Abortion* is + produced, which prevents the regular after-simulation execution of VUnit. See :ghdlsharp:`803` and :cosimsharp:`15` for + further details. .. _COSIM:VHPIDIRECT:Examples:shared:pycb: diff --git a/test.py b/test.py index d66e03f8..b9e63c5b 100644 --- a/test.py +++ b/test.py @@ -71,10 +71,6 @@ def test_vhpidirect_quickstart_wrapping_exitcb(self): self._sh([str(self.vhpidirect / 'quickstart' / 'wrapping' / 'exitcb' / 'run.sh')]) - def test_vhpidirect_quickstart_wrapping_exitcb_py(self): - self._sh([str(self.vhpidirect / 'quickstart' / 'wrapping' / 'exitcb' / 'py' / 'vunit_run.sh')]) - - def test_vhpidirect_quickstart_linking_bind(self): self._sh([str(self.vhpidirect / 'quickstart' / 'linking' / 'bind' / 'run.sh')]) @@ -109,6 +105,13 @@ def test_vhpidirect_shared_shghdl(self): self._sh([str(self.vhpidirect / 'shared' / 'shghdl' / 'run.sh')]) + def test_vhpidirect_shared_py(self): + self._sh([str(self.vhpidirect / 'shared' / 'py' / 'run.sh')]) + + def test_vhpidirect_shared_py_vunit(self): + self._sh([str(self.vhpidirect / 'shared' / 'py' / 'vunit' / 'run.sh')]) + + def test_vhpidirect_shared_pycb(self): self._sh([str(self.vhpidirect / 'shared' / 'pycb' / 'run.sh')]) diff --git a/vhpidirect/quickstart/wrapping/exitcb/caux.c b/vhpidirect/quickstart/wrapping/exitcb/caux.c deleted file mode 100644 index 30dbaae7..00000000 --- a/vhpidirect/quickstart/wrapping/exitcb/caux.c +++ /dev/null @@ -1,18 +0,0 @@ -#include -#include - -extern int ghdl_main(int argc, void** argv); - -static void exit_handler(void) { - printf("This is the exit handler.\n"); -} - -int wrapper(int argc, void** argv) { - atexit(exit_handler); - - printf("Hello wrapper!\n"); - int ecode = ghdl_main(argc, argv); - printf("Bye wrapper <%d>!\n", ecode); - - return 0; -} diff --git a/vhpidirect/quickstart/wrapping/exitcb/main.c b/vhpidirect/quickstart/wrapping/exitcb/main.c index 4b5f93dd..e5dcb465 100644 --- a/vhpidirect/quickstart/wrapping/exitcb/main.c +++ b/vhpidirect/quickstart/wrapping/exitcb/main.c @@ -1,5 +1,31 @@ -extern int wrapper(int argc, void** argv); +#include +#include +#include + +extern int ghdl_main(int argc, void** argv); + +void sigabrtHandler(int sig_num) { + // Reset handler to catch SIGABRT next time. Refer http://en.cppreference.com/w/c/program/signal + signal(SIGABRT, sigabrtHandler); + printf("SIGABRT caught %d!\n", sig_num); + fflush(stdout); +} + +static void exit_handler(void) { + printf("This is the exit handler.\n"); +} + +int entry(int argc, void** argv) { + signal(SIGABRT, sigabrtHandler); + atexit(exit_handler); + + printf("Hello entry!\n"); + int ecode = ghdl_main(argc, argv); + printf("Bye entry <%d>!\n", ecode); + + return 0; +} int main(int argc, void** argv) { - return wrapper(argc, argv); + return entry(argc, argv); } diff --git a/vhpidirect/quickstart/wrapping/exitcb/main_sigabrt.c b/vhpidirect/quickstart/wrapping/exitcb/main_sigabrt.c deleted file mode 100644 index a323d931..00000000 --- a/vhpidirect/quickstart/wrapping/exitcb/main_sigabrt.c +++ /dev/null @@ -1,16 +0,0 @@ -#include -#include - -extern int wrapper(int argc, void** argv); - -void sigabrtHandler(int sig_num) { - // Reset handler to catch SIGABRT next time. Refer http://en.cppreference.com/w/c/program/signal - signal(SIGABRT, sigabrtHandler); - printf("SIGABRT caught %d!\n", sig_num); - fflush(stdout); -} - -int main(int argc, void** argv) { - signal(SIGABRT, sigabrtHandler); - return wrapper(argc, argv); -} diff --git a/vhpidirect/quickstart/wrapping/exitcb/py/cosim.py b/vhpidirect/quickstart/wrapping/exitcb/py/cosim.py deleted file mode 100644 index 7243a8dd..00000000 --- a/vhpidirect/quickstart/wrapping/exitcb/py/cosim.py +++ /dev/null @@ -1,8 +0,0 @@ -from pyaux import dlopen, dlclose, enc_args, run -from pathlib import Path - -print("PY COSIM ENTER") - -run(str(Path(__file__).resolve().parent.parent / "tb-fail.so"), 0, None) - -print("PY COSIM EXIT") diff --git a/vhpidirect/quickstart/wrapping/exitcb/py/vunit_cosim.py b/vhpidirect/quickstart/wrapping/exitcb/py/vunit_cosim.py deleted file mode 100644 index ac39fbda..00000000 --- a/vhpidirect/quickstart/wrapping/exitcb/py/vunit_cosim.py +++ /dev/null @@ -1,14 +0,0 @@ -from pyaux import dlopen, dlclose, enc_args, run -from pathlib import Path -from json import load - -print("PY COSIM ENTER") - -with (Path(__file__).parent / 'vunit_out' / 'cosim' / 'tb_abrt.json').open() as json_file: - ARGS = load(json_file) - -XARGS = enc_args([ARGS["bin"]] + ARGS["sim"]) - -run(ARGS["bin"], len(XARGS) - 1, XARGS) - -print("PY COSIM EXIT") diff --git a/vhpidirect/quickstart/wrapping/exitcb/py/vunit_run.sh b/vhpidirect/quickstart/wrapping/exitcb/py/vunit_run.sh deleted file mode 100755 index 097e46c8..00000000 --- a/vhpidirect/quickstart/wrapping/exitcb/py/vunit_run.sh +++ /dev/null @@ -1,11 +0,0 @@ -#!/usr/bin/env sh - -cd $(dirname "$0") - -export VUNIT_VHDL_STANDARD="2008" -python3 vunit_run.py -v -python3 vunit_cosim.py - -export VUNIT_VHDL_STANDARD="93" -python3 vunit_run.py -v -python3 vunit_cosim.py diff --git a/vhpidirect/quickstart/wrapping/exitcb/run.sh b/vhpidirect/quickstart/wrapping/exitcb/run.sh index 0d770a6f..28410c8a 100755 --- a/vhpidirect/quickstart/wrapping/exitcb/run.sh +++ b/vhpidirect/quickstart/wrapping/exitcb/run.sh @@ -4,108 +4,26 @@ set -e cd $(dirname "$0") -for std in '08' '93'; do - -echo "> [$std] Analyze tb.vhd" -ghdl -a --std="$std" tb.vhd - - -echo "> [$std] Build tb pass" -ghdl -e --std="$std" -Wl,caux.c -Wl,main.c -o tb"$std"_pass tb pass - -echo "> [$std] Execute tb_pass" -./tb"$std"_pass -echo $? -echo "" - - -echo "> [$std] Build tb-pass.so" -ghdl -e --std="$std" -shared -Wl,-fPIC -Wl,caux.c -Wl,main.c tb pass -mv tb-pass.so tb-fail.so -echo "" - -set +e - -echo "> [$std] Python cosim pass" -python3 py/cosim.py -echo "" - -set -e - - -echo "> [$std] Build tb fail" -ghdl -e --std="$std" -Wl,caux.c -Wl,main.c -o tb"$std"_fail tb fail - -set +e - -echo "> [$std] Execute tb_fail" -./tb"$std"_fail -echo $? -echo "" - -set -e - - -echo "> [$std] Build tb-fail.so" -ghdl -e --std="$std" -shared -Wl,-fPIC -Wl,caux.c -Wl,main.c tb fail -echo "" - -set +e - -echo "> [$std] Python cosim fail" -python3 py/cosim.py -echo "" +_ext='so' +case "$(uname)" in + MINGW*) _ext='dll';; +esac -set -e - - -echo "> [$std] Build tb pass_sigabrt" -ghdl -e --std="$std" -Wl,caux.c -Wl,main_sigabrt.c -o tb"$std"_pass_sigabrt tb pass - -echo "> [$std] Execute tb_pass_sigabrt" -./tb"$std"_pass_sigabrt -echo $? -echo "" - -set -e - - -echo "> [$std] Build tb-pass.so (sigabrt)" -ghdl -e --std="$std" -shared -Wl,-fPIC -Wl,caux.c -Wl,main_sigabrt.c tb pass -mv tb-pass.so tb-fail.so -echo "" - -set +e - -echo "> [$std] Python cosim pass (sigabrt)" -python3 py/cosim.py -echo "" - -set -e - - -echo "> [$std] Build tb fail_sigabrt)" -ghdl -e --std="$std" -Wl,caux.c -Wl,main_sigabrt.c -o tb"$std"_fail_sigabrt tb fail - -set +e - -echo "> [$std] Execute tb_fail_sigabrt" -./tb"$std"_fail_sigabrt -echo $? -echo "" - -set -e +for std in '08' '93'; do -echo "> [$std] Build tb-fail.so (sigabrt)" -ghdl -e --std="$std" -shared -Wl,-fPIC -Wl,caux.c -Wl,main_sigabrt.c tb fail -echo "" + echo "> [$std] Analyze tb.vhd" + ghdl -a --std="$std" tb.vhd -set +e + echo "" -echo "> [$std] Python cosim fail (sigabrt)" -python3 py/cosim.py -echo "" + for item in 'pass' 'fail'; do + echo "> [$std] Build tb-${item}" + ghdl -e --std="$std" -Wl,-fPIC -Wl,main.c tb ${item} + echo "" -set -e + echo "> [$std]Run tb-${item}" + ./tb-"${item}" + echo "" + done done diff --git a/vhpidirect/quickstart/wrapping/exitcb/py/pyaux.py b/vhpidirect/shared/py/pyaux.py similarity index 80% rename from vhpidirect/quickstart/wrapping/exitcb/py/pyaux.py rename to vhpidirect/shared/py/pyaux.py index c0dada6a..3c183466 100644 --- a/vhpidirect/quickstart/wrapping/exitcb/py/pyaux.py +++ b/vhpidirect/shared/py/pyaux.py @@ -1,3 +1,4 @@ +from sys import platform from pathlib import Path import ctypes import _ctypes @@ -15,7 +16,10 @@ def dlopen(path): def dlclose(obj): - _ctypes.dlclose(obj._handle) + if platform == "win32": + _ctypes.FreeLibrary(obj._handle) + else: + _ctypes.dlclose(obj._handle) def enc_args(args): @@ -24,12 +28,10 @@ def enc_args(args): xargs[idx] = ctypes.create_string_buffer(arg.encode('utf-8')) return xargs + def run(path, argc, argv): print("PY RUN ENTER") ghdl = dlopen(path) - ghdl.main(argc, argv) - # FIXME With VHDL 93, the execution is Aborted and Python exits here - + ghdl.entry(argc, argv) dlclose(ghdl) - print("PY RUN EXIT") diff --git a/vhpidirect/shared/py/run.sh b/vhpidirect/shared/py/run.sh new file mode 100755 index 00000000..91367d22 --- /dev/null +++ b/vhpidirect/shared/py/run.sh @@ -0,0 +1,31 @@ +#!/usr/bin/env sh + +set -e + +cd $(dirname "$0") + +_exitcbdir='../../quickstart/wrapping/exitcb' + +_ext='so' +case "$(uname)" in + MINGW*) _ext='dll';; +esac + +for std in '08' '93'; do + + echo "> [$std] Analyze tb.vhd" + ghdl -a --std="$std" "${_exitcbdir}"/tb.vhd + + echo "" + + for item in 'pass' 'fail'; do + echo "> [$std] Build tb-${item}.${_ext}" + ghdl -e --std="$std" -shared -Wl,-fPIC -Wl,"${_exitcbdir}"/main.c tb ${item} + echo "" + + echo "> [$std] Python load and run tb-${item}.${_ext}" + PYTHONPATH=$(pwd) python3 -c 'from pyaux import run; run("./tb-'"${item}.${_ext}"'", 0, None)' + echo "" + done + +done diff --git a/vhpidirect/shared/py/vunit/cosim.py b/vhpidirect/shared/py/vunit/cosim.py new file mode 100644 index 00000000..1e0f2778 --- /dev/null +++ b/vhpidirect/shared/py/vunit/cosim.py @@ -0,0 +1,12 @@ +from sys import platform +from pathlib import Path +from json import load +from pyaux import enc_args, run + + +with (Path(__file__).parent / 'vunit_out' / 'cosim' / 'tb_vunit.json').open() as json_file: + ARGS = load(json_file) + +_bin = ARGS["bin"] if platform != 'win32' else ARGS["bin"]+'.exe' + +run(_bin, len(ARGS), enc_args([_bin] + ARGS["sim"])) diff --git a/vhpidirect/quickstart/wrapping/exitcb/py/vunit_run.py b/vhpidirect/shared/py/vunit/run.py similarity index 84% rename from vhpidirect/quickstart/wrapping/exitcb/py/vunit_run.py rename to vhpidirect/shared/py/vunit/run.py index 70950420..4d1ef1b6 100644 --- a/vhpidirect/quickstart/wrapping/exitcb/py/vunit_run.py +++ b/vhpidirect/shared/py/vunit/run.py @@ -28,13 +28,12 @@ def post_func(results): vu = VUnit.from_argv(vhdl_standard=getenv('VUNIT_VHDL_STANDARD', '2008')) -lib = vu.add_library('lib').add_source_files(str(ROOT / 'vunit_tb.vhd')) +lib = vu.add_library('lib').add_source_files(str(ROOT / 'tb.vhd')) vu.set_sim_option('ghdl.elab_flags', [ '-shared', '-Wl,-fPIC', - '-Wl,' + str(ROOT.parent / 'caux.c'), - '-Wl,' + str(ROOT.parent / 'main_sigabrt.c') + '-Wl,' + str(ROOT.parent.parent.parent / 'quickstart' / 'wrapping' / 'exitcb' / 'main.c') ]) vu.set_sim_option("ghdl.elab_e", True) diff --git a/vhpidirect/shared/py/vunit/run.sh b/vhpidirect/shared/py/vunit/run.sh new file mode 100755 index 00000000..defaf379 --- /dev/null +++ b/vhpidirect/shared/py/vunit/run.sh @@ -0,0 +1,23 @@ +#!/usr/bin/env sh + +set -e + +cd $(dirname "$0") + +for std in '2008' '93'; do + export VUNIT_VHDL_STANDARD="$std" + + echo "> [$std] VUnit compile" + if ! $(python3 run.py --compile > vunit.log 2>&1); then + cat vunit.log; + fi + echo "" + + echo "> [$std] VUnit run" + python3 run.py -v + echo "" + + echo "> [$std] VUnit cosim" + PYTHONPATH=$(pwd)/.. python3 cosim.py + echo "" +done diff --git a/vhpidirect/quickstart/wrapping/exitcb/main.py b/vhpidirect/shared/py/vunit/sigabrt.py similarity index 100% rename from vhpidirect/quickstart/wrapping/exitcb/main.py rename to vhpidirect/shared/py/vunit/sigabrt.py diff --git a/vhpidirect/quickstart/wrapping/exitcb/py/vunit_tb.vhd b/vhpidirect/shared/py/vunit/tb.vhd similarity index 62% rename from vhpidirect/quickstart/wrapping/exitcb/py/vunit_tb.vhd rename to vhpidirect/shared/py/vunit/tb.vhd index 5c5c7b1e..b9c4465f 100644 --- a/vhpidirect/quickstart/wrapping/exitcb/py/vunit_tb.vhd +++ b/vhpidirect/shared/py/vunit/tb.vhd @@ -2,21 +2,17 @@ library vunit_lib; use vunit_lib.run_pkg.all; use vunit_lib.logger_pkg.all; -entity tb_abrt is +entity tb_vunit is generic ( runner_cfg : string ); end entity; -architecture tb of tb_abrt is - - constant block_len : natural := 5; - +architecture tb of tb_vunit is begin main: process - variable val, ind: integer; begin test_runner_setup(runner, runner_cfg); - info("Hello wrapping/exitcb/py_vunit!"); + info("Hello shared/py/vunit!"); test_runner_cleanup(runner); wait; end process; From de0b36eaa23bcf7f23d996ebd32916b0bbe80515 Mon Sep 17 00:00:00 2001 From: umarcor Date: Wed, 27 Jan 2021 02:08:25 +0100 Subject: [PATCH 10/10] pytest: user marks --- test.py | 28 ++++++++++++++++++---------- 1 file changed, 18 insertions(+), 10 deletions(-) diff --git a/test.py b/test.py index b9e63c5b..40e1bc3c 100644 --- a/test.py +++ b/test.py @@ -8,14 +8,14 @@ from pathlib import Path from subprocess import check_call, STDOUT from shutil import which -import unittest +from unittest import TestCase import pytest isWin = platform == 'win32' -class TestExamples(unittest.TestCase): +class TestExamples(TestCase): """ Verify that example run scripts work correctly """ @@ -105,9 +105,17 @@ def test_vhpidirect_shared_shghdl(self): self._sh([str(self.vhpidirect / 'shared' / 'shghdl' / 'run.sh')]) + @pytest.mark.xfail( + not isWin, + reason="abortion is produced on some Linux environements" + ) def test_vhpidirect_shared_py(self): self._sh([str(self.vhpidirect / 'shared' / 'py' / 'run.sh')]) + @pytest.mark.xfail( + not isWin, + reason="abortion is produced on some Linux environements" + ) def test_vhpidirect_shared_py_vunit(self): self._sh([str(self.vhpidirect / 'shared' / 'py' / 'vunit' / 'run.sh')]) @@ -132,25 +140,25 @@ def test_vhpidirect_arrays_matrices_vunit_axis_vcs(self): self._py([str(self.vhpidirect / 'arrays' / 'matrices' / 'vunit_axis_vcs' / 'run.py'), '-v']) - @unittest.skipIf( + @pytest.mark.skipif( isWin, - "win: needs ImageMagick's 'convert'", + reason="win: needs ImageMagick's 'convert'", ) def test_vhpidirect_arrays_matrices_framebuffer(self): self._sh([str(self.vhpidirect / 'arrays' / 'matrices' / 'framebuffer' / 'run.sh')]) - @unittest.skipUnless( - 'MINGW_PREFIX' in environ or not isWin, - "needs OpenSSL", + @pytest.mark.skipif( + isWin and ('MINGW_PREFIX' not in environ), + reason="needs OpenSSL", ) def test_vhpidirect_vffi_crypto(self): self._sh([str(self.vhpidirect / 'vffi_user' / 'crypto' / 'run.sh')]) - @unittest.skipUnless( - which('Xyce'), - "needs Xyce", + @pytest.mark.skipif( + not which('Xyce'), + reason="needs Xyce", ) def test_vhpidirect_vffi_xyce(self): self._py([str(self.vhpidirect / 'vffi_user' / 'xyce' / 'run_minimal.py'), '-v', '--clean', '--xunit-xml=%s' % str(self.report_file), '--output-path=%s' % str(self.output_path)])