Dynamic loading

Building either foreign resources or the VHDL simulation model as shared libraries allows to decouple the build procedures.

Loading foreign objects from within a simulation

Instead of linking and building foreign objects along with GHDL, it is also possible to load foreign resources dynamically. In order to do so, provide the path and name of the shared library where the resource is to be loaded from. For example:

attribute foreign of get_rand: function is "VHPIDIRECT ./getrand.so get_rand";

Generating shared libraries

Tip

Ensure reading and understanding Linking object files before this one.

There are three possibilities to elaborate simulation models as shared libraries, instead of executable binaries:

  • ghdl -e -shared [options...] primary_unit [secondary_unit]

  • ghdl -e -Wl,-shared -Wl,-Wl,--version-script=./file.ver -Wl,-Wl,-u,ghdl_main [options...] primary_unit [secondary_unit]

  • gcc -shared -Wl,`ghdl --list-link tb` -Wl,--version-script=./file.ver -Wl,-u,ghdl_main

The only difference between the two later procedures is the entrypoint (GHDL or GCC). Preference depends on the additional options that users need to provide. The main difference with the former is that it will make all symbols visible in the resulting shared library. In the other two procedures, visible symbols will be the ones defined in the default grt.ver added by GHDL and the file.ver provided by the user. Note that file.ver must include ghdl_main and any other added by the user. See example shghdl and ghdl-cosim#2.

Hint

When GHDL is configured with --default-pic explicitly, it uses it implicitly when executing any -a, -e or -r command. Hence, it is not required to provide these arguments (fPIC/PIE) to GHDL. However, these might need to be provided when building C sources with GCC. Otherwise linker errors such as the following are produced:

relocation R_X86_64_PC32 against symbol * can not be used when making a shared object; recompile with -fPIC

Hint

For further details regarding how to call ghdl_main see Wrapping a simulation.

Note

Alternatively, if the shared library is built with --bind and --list-link, the output from the later can be filtered with tools such as sed in order to remove the default version script (accomplished in ghdl#640), and make all symbols visible by default. However, this procedure is only recommended in edge cases where other solutions don’t fit.

Loading a simulation

Attention

By default, GHDL uses grt.ver to limit which symbols are exposed in the generated artifacts, and ghdl_main is not included. See Generating shared libraries for guidelines to generate shared objects with visible or filtered symbols.

In order to generate a position independent executable (PIE), be it an executable binary or a shared library, GHDL must be built with config option --default-pic. This will ensure that all the libraries and sources analyzed by GHDL generate position independent code (PIC).

PIE binaries can be loaded and executed from any language that supports C-alike signatures and types (C, C++, golang, Python, Rust, etc.). This allows seamless co-simulation using concurrent/parallel execution features available in each language: pthreads, goroutines/gochannels, multiprocessing/queues, etc. Moreover, it provides a mechanism to execute multiple GHDL simulations in parallel.

For example, in Python:

import ctypes
gbin = ctypes.CDLL(bin_path)

args = ['-gGENA="value"', 'gGENB="value"']

xargs = (ctypes.POINTER(ctypes.c_char) * (len(args)+1))()
for idx, arg in enumerate(args):
    xargs[idx+1] = ctypes.create_string_buffer(arg.encode('utf-8'))

gbin.main(len(xargs)-1, xargs)

import _ctypes
# On GNU/Linux
_ctypes.dlclose(gbin._handle)
# On Windows
#_ctypes.FreeLibrary(gbin._handle)

See a complete example written in C in shghdl.

Tip

As explained in Wrapping a simulation, ghdl_main must be called once, since reseting/restarting the simulation runtime is not supported yet (see ghdl#1184). When it is loaded dynamically, this means that the binary file/library needs to be unloaded from memory and loaded again (as in shghdl).

Tip

See ghdl#803 for details about expected differences in the exit codes, depending on the version of the VHDL standard that is used.