diff --git a/test.py b/test.py index 2beb058f..9d71a46f 100644 --- a/test.py +++ b/test.py @@ -64,6 +64,9 @@ def test_vhpidirect_quickstart_wrapping_time(self): def test_vhpidirect_quickstart_wrapping_exitcb(self): check_call(self.shell + [str(self.vhpidirect / 'quickstart' / 'wrapping' / 'exitcb' / 'run.sh')], shell=True) + def test_vhpidirect_quickstart_wrapping_exitcb_py(self): + check_call(self.shell + [str(self.vhpidirect / 'quickstart' / 'wrapping' / 'exitcb' / 'py' / 'vunit_run.sh')], shell=True) + @unittest.skipUnless( platform != 'win32', "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