Containers and/or Virtual Machines

The ‘classic’ approach to virtual machines is through tools such as VirtualBox, QEMU or VMware. However, for most use cases sharing complete system images is overkill. Here, containerization or operating-system-level virtualization comes into the game. Without going into technical details, containers are a kind of lightweight virtual machines, and the most known product that uses the technology is Docker.


Products such as Vagrant are meant to simplify the usage of virtual machines and/or containers by providing a common (black) box approach. In the end, there are enough open/non-open and free/non-free solutions for each user/company to choose the one that best fits their needs. From the hardware designer point-of-view, we ‘just’ need a box (no matter the exact underlying technology) that includes VUnit and a simulator.

Contributors of project GHDL provide ready-to-use docker images at Some of these include not only GHDL but also VUnit. Precisely, ghdl/vunit:{mcode|llvm|gcc} are images based on Debian Buster image, with GHDL built from the latest commit of the master branch, and the latest release of VUnit installed through pip. ghdl/vunit:{mcode|llvm|gcc}-master images include the latest commit of VUnit from the master branch. There are other ready-to-use images with additional tools. For example, ghdl/ext includes GTKWave.

As a result, the burden for the adoption of continuous integration for VUnit users is significantly reduced by using containers; which are available in GNU/Linux, FreeBSD, Windows and macOS, and are supported on most cloud services (GitHub Actions, Travis CI, AWS, Codefresh, etc.) or CI frameworks (Jenkins, Drone, GitLab Runner, etc.).

For example, script examples/vhdl/ shows how to run all the VHDL examples on any x86 platform:

docker run --rm \
  -v /$(pwd)://work \
  -w //work \
  ghdl/vunit:llvm-master sh -c ' \
    for f in $(find ./ -name ''); do python3 $f; done \


  • run: create and start a container.

  • --rm: automatically remove the container when it exits.

  • -v: bind mount a volume, to share a folder between the host and the container. In this example the current path in the host is used ($(pwd)), and it is bind to /work inside the container. Note that both paths must be absolute.

  • -w: sets the working directory inside the container, i.e. where the commands we provide as arguments are executed.

  • ghdl/vunit:llvm-master: the image we want to create a container from.

  • sh -c: the command that is executed as soon as the container is created.

Note that, the arguments to sh -c are the same commands that you would execute locally, shall all the dependencies be installed on the host:

for f in $(find ./ -name ''); do python3 $f; done


The leading slashes in /$(pwd) and //work are only required for the paths to be properly handled in MINGW64 shells, and are ignored in other shells. See docker/for-win#1509.


Docker offers two variants Community Edition (CE) and Enterprise Edition (EE). Any of them can be used. Moreover, part of Docker is being split to Moby project.


If you don’t want or cannot install docker, you can still use it online. Play with Docker (PWD) “is a Docker playground which allows users to run Docker commands in a matter of seconds. It provides a free Alpine Linux Virtual Machine in browser, where you can build and run Docker containers and even create clusters”.


Both GHDL and VUnit are free software. Docker is almost fully open source, but it depends on the host platform. See Is Docker still free and open source?.

Customizing existing images

All the (automated) flow to generate images in ghdl/docker is open source and public. Hence, any user can learn and extend it. However, many users will want to just add a few dependencies to an existing image, without the hassle of handling credentials to access That can be achieved with a short Dockerfile. For instance:

FROM ghdl/vunit:llvm-master

RUN pip install pytest matplotlib

Then, in the CI workflow:

docker build -t imageName - < path/to/Dockerfile
docker run ... imageName ...

Packaging non-FLOSS simulators

Although the licenses of most commercial simulators do not allow to share ready-to-use docker images, it is straightforward to mimic the process for in-house usage. Unlike GHDL, many commercial simulators provide a GUI and/or require a GUI for executing the installer. In those contexts, mviereck/x11docker and mviereck/runx can be useful. See mviereck/x11docker#201.