No description
  • Shell 62.8%
  • Dockerfile 19.8%
  • C 17.4%
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
Paulo Ficagna aa96fc7634 Add --batch mode for agent job containers
No display, no privileges or route out, tools read-only, rootless only;
--usb passes just the JTAG adapters. Used by the pi-docker --fpga broker.
2026-10-18 16:28:17 +02:00
Vitis-AI@77cb9e6ad6 Initial commit: Xilinx Vivado + Vitis AI dev environment 2026-03-19 05:33:22 +01:00
vivado-vitis Stub libudev so batch Vivado builds stop segfaulting 2026-08-11 16:12:00 +02:00
.gitignore Initial commit: Xilinx Vivado + Vitis AI dev environment 2026-03-19 05:33:22 +01:00
.gitmodules Initial commit: Xilinx Vivado + Vitis AI dev environment 2026-03-19 05:33:22 +01:00
centos7-os-release Initial commit: Xilinx Vivado + Vitis AI dev environment 2026-03-19 05:33:22 +01:00
install_vivado.sh Support Vivado 2021.2 SFD installer 2026-07-09 16:01:13 +02:00
README.md Keep vivado clock frozen; de-preload sim tools spawned by vivado 2026-07-14 08:02:40 +02:00
vivado_docker.sh Add --batch mode for agent job containers 2026-10-18 16:28:17 +02:00

xilinx-dev-env

Reusable Xilinx Vivado + Vitis AI development environment for Arch Linux. Designed to run Enterprise Linux tools (Vivado, Vitis) in Docker containers on a host that doesn't meet Xilinx's OS requirements (e.g., Arch, Hyprland).

Strategy

The Docker image provides only OS dependencies (Ubuntu 20.04 + GUI libs). Vivado tools (~100GB) live on the host at ~/dev/fpga/xilinx_tools and are mounted into the container at /tools/Xilinx at runtime — keeping the image small and the installation persistent across container rebuilds.

Structure

xilinx-dev-env/
  vivado-vitis/
    Dockerfile            # Ubuntu 20.04 base image with GUI dependencies
    vivado_uninstall.sh   # Safe version-specific uninstaller
  Vitis-AI/               # Git submodule — official Xilinx repo
  vivado_docker.sh        # Launches Vivado container (GUI or batch mode)
  install_vivado.sh       # One-time Vivado installer script
  centos7-os-release      # CentOS stub required by some Xilinx tools

Setup (one time)

1. Clone

git clone --recurse-submodules [email protected]:Pcsf/xilinx-dev-env.git

2. Build the Vivado Docker image

cd vivado-vitis
docker build -t vivado-image:2021.2 .

3. Install Vivado

Recommended for 2021.2: download AMD Unified Installer 2021.2 SFD from the AMD/Xilinx 2021.2 archive and place it in ~/dev/fpga/xilinx_tools/.

The older Xilinx_Unified_2021.2_1021_0703_Lin64.bin web installer can report that it has been deprecated. Use the SFD tarball instead; it is the full offline installer image.

mkdir -p ~/dev/fpga/xilinx_tools
tar -xf ~/dev/fpga/xilinx_tools/Xilinx_Unified_2021.2_*.tar.gz -C ~/dev/fpga/xilinx_tools
# Auto-finds xsetup in ~/dev/fpga/xilinx_tools/ if the SFD was extracted there
./install_vivado.sh

# Or specify path explicitly
./install_vivado.sh /path/to/extracted/sfd/xsetup

For releases where the web installer is still supported, place the .bin file in ~/dev/fpga/xilinx_tools/ or pass it explicitly:

./install_vivado.sh /path/to/Xilinx_Unified_2021.2_1021_0703_Lin64.bin

CRITICAL: When the installer asks for the installation path, set it to /tools/Xilinx. This maps to ~/dev/fpga/xilinx_tools on the host.

Reclaim disk space after install. The extracted installer (Xilinx_Unified_2021.2_*, ~73 GB) is only used during installation — the installed Vivado/Vitis/Vitis_HLS trees are self-contained and don't reference it. Once the tools launch correctly, you can delete it:

rm -rf ~/dev/fpga/xilinx_tools/Xilinx_Unified_2021.2_*

If you later need to add a device family, repair, or reinstall offline, re-download the SFD from the AMD/Xilinx archive.

4. Configure the license (portable, node-locked)

A node-locked Xilinx license is tied to a host ID — for Vivado, the MAC address of a network interface (the HOSTID line in your .lic file). If the container inherited the host's real MAC, the license would break every time you moved to a different machine. Instead, vivado_docker.sh pins a fixed MAC so FlexLM always sees the licensed host ID, on any host.

Two variables at the top of vivado_docker.sh control this:

Variable What it does
LICENSE_MAC MAC address the container presents to FlexLM. Set it to your license's HOSTID, formatted with colons. The launcher passes it as Docker's --mac-address (which is why the container uses a bridge network, not --net=host). Leave empty to fall back to Docker's default, non-portable MAC.
LICENSE_FILE Path inside the container to the license file. Exported as XILINXD_LICENSE_FILE so Vivado checks out the license automatically instead of prompting the License Manager on every launch. Can also be a floating server as port@host. Leave empty to disable.

Set LICENSE_MAC. Find your host ID in the .lic file and add colons every two hex digits:

grep -i hostid ~/dev/fpga/xilinx_tools/Xilinx.lic   # e.g. HOSTID=6edfde44ec7d
# -> set LICENSE_MAC="6e:df:de:44:ec:7d"

Set LICENSE_FILE. Place the .lic file anywhere under the tools dir (mounted at /tools/Xilinx). If it sits next to the install as ~/dev/fpga/xilinx_tools/Xilinx.lic, the default LICENSE_FILE="/tools/Xilinx/Xilinx.lic" already points at it — no change needed.

Verify the host ID the container presents matches your license. The bundled lmutil is an unwrapped binary whose ELF interpreter (ld-lsb-x86-64.so.3) isn't present on Ubuntu 20.04, so invoke it through the system loader:

./vivado_docker.sh -c   # drop into the container shell, then:
/lib64/ld-linux-x86-64.so.2 \
  /tools/Xilinx/Vivado/2021.2/bin/unwrapped/lnx64.o/lmutil lmhostid
# -> "The FlexNet host ID of this machine is <LICENSE_MAC without colons>"

That value must equal the HOSTID in your .lic file. Once it matches, the GUI opens straight into a licensed session with no manual license loading.

5. Pull the Vitis AI container

docker pull xilinx/vitis-ai-pytorch-cpu:latest

Daily Usage

Launch Vivado (GUI)

./vivado_docker.sh

Launch Vivado (batch mode)

./vivado_docker.sh -mode batch -source /path/to/script.tcl

Launch container in CLI/bash mode

Drops into an interactive bash shell with the Vivado environment sourced. Useful for running TCL scripts, batch flows, or debugging without opening the GUI.

./vivado_docker.sh --cli
# or
./vivado_docker.sh -c

From the shell you can run any Xilinx CLI tool directly, e.g.:

vivado -mode batch -source my_script.tcl

Frozen clock (license date)

Pass --frozen-time (or -f) to run Vivado with a frozen wall-clock date via libfaketime, so the license manager sees a date the license is valid on. The clock is frozen at FROZEN_DATE (faketime @ form) — it must NOT be a ticking relative offset: that segfaults FlexLM during license checkout (libXil_lmgr11 → libudev heap corruption right after "Attempting to get a license").

./vivado_docker.sh --frozen-time                       # GUI
./vivado_docker.sh -c -f                               # CLI shell
./vivado_docker.sh -f -mode batch -source build.tcl    # batch

The frozen date is defined by FROZEN_DATE at the top of vivado_docker.sh (default: 2026-04-20 00:00:00). Only the wall clock is frozen — monotonic timers are left untouched (FAKETIME_DONT_FAKE_MONOTONIC=1), so Vivado's internal progress counters still work.

The freeze applies only to the vivado launcher (through a wrapper script prepended to PATH inside the container), not to the whole container. Preloading libfaketime into everything deadlocks XSim: xsim hangs forever right after printing Time resolution is 1 ps, whether the clock is frozen or ticking. Since the simulation tools need no license, counter-wrappers for xvhdl/xvlog/xelab/xsim strip the preload again — vivado resolves them via PATH, so simulations run on the real clock even when launched from inside vivado (launch_simulation, batch or GUI).

Verified with a full synth_design pass on xc7z020clg484-1: license manager accepts the shifted date and synthesis completes normally. If you use a paid-tier part, make sure your license is still valid on the shifted date.

Launch Vitis AI

cd Vitis-AI
./docker_run.sh xilinx/vitis-ai-pytorch-cpu:latest

Uninstalling a Vivado version

./vivado-vitis/vivado_uninstall.sh 2021.2

Important Notes

  • _JAVA_AWT_WM_NONREPARENTING=1 is set in the launch scripts — required for GUI rendering under tiling WMs (Hyprland/XWayland)
  • Do not use the Vitis AI GPU image (requires NVIDIA CUDA); use CPU image only
  • Do not build Vitis AI from source (broken dependencies)
  • The Vivado container runs as the host user to avoid file permission issues