- Shell 62.8%
- Dockerfile 19.8%
- C 17.4%
| Filename | Latest commit message | Latest commit date |
|---|---|---|
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. |
||
| Vitis-AI@77cb9e6ad6 | ||
| vivado-vitis | ||
| .gitignore | ||
| .gitmodules | ||
| centos7-os-release | ||
| install_vivado.sh | ||
| README.md | ||
| vivado_docker.sh | ||
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=1is 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