Fhs env for installing xilinx

UPDATE the code discussed here is now in GitHub - nix-community/nix-environments: Repository to maintain out-of-tree shell.nix files (maintainer=@mic92)

I just wanted to drop this shell.nix for installing xilinx vitis in case someone needs it:

{ pkgs ? import <nixpkgs> {} }:

let
  xrt = pkgs.callPackage ./xrt.nix {};

  fhs = pkgs.buildFHSUserEnv {
    name = "xilinx-env";
    targetPkgs = pkgs: with pkgs; [
      bash
      xrt
      coreutils
      zlib
      stdenv.cc.cc
      ncurses
      xorg.libXext
      xorg.libX11
      xorg.libXrender
      xorg.libXtst
      xorg.libXi
      xorg.libXft
      xorg.libxcb
      xorg.libxcb
      # common requirements
      freetype
      fontconfig
      glib
      gtk2
      gtk3

      # from installLibs.sh
      graphviz
      gcc
      unzip
      nettools
    ];
    multiPkgs = null;
    profile = ''
      vitis_dir=$(echo /opt/xilinx/Vitis/*/bin)
      export PATH=$vitis_dir:$PATH
      export XILINX_XRT="${xrt}"
    '';
  };
in fhs.env

and this xrt.nix

{ stdenv
, fetchFromGitHub
, linuxPackages_5_4
, cmake
, mesa
, libdrm
, pkg-config
, opencl-headers
, ocl-icd
, git
, boost
, ncurses
, openssl
, protobuf
, util-linux
, doxygen
, protobuf3_6
, valgrind
, python3Packages
, curl
, opencl-clhpp
, fetchurl
, libyaml
, udev
, dpkg
}:
let
  inherit (linuxPackages_5_4) kernel;
  suffix = "2.9.317";
  version = "202020.${suffix}";
  xrtBin = fetchurl {
    url = "https://www.xilinx.com/bin/public/openDownload?filename=xrt_${version}_20.04-amd64-xrt.deb";
    sha256 = "sha256-NTKjhOtTCFsjNweHOkH8CrM1ZloLM/+36NfM0w14l2Y=";
  };
  kernelMod = "$(pwd)/usr/src/xrt-${suffix}/driver/xocl";
  KERNELDIR = "${kernel.dev}/lib/modules/${kernel.modDirVersion}/build";

in stdenv.mkDerivation rec {
  pname = "xrt";
  inherit version;
  src = fetchFromGitHub {
    owner = "Xilinx";
    repo = "XRT";
    rev = version;
    sha256 = "sha256-h9zpNHpm9Ys99wG2xdiXPHkzLkRgmM3Qk1PmQwiQv4c=";
  };

  enableParallelBuilding = true;

  # we take the matter in our own hand
  dontFixCmake = true;

  buildInputs = [
    libdrm
    opencl-clhpp
    opencl-headers
    ocl-icd
    boost
    ncurses
    openssl
    protobuf3_6
    util-linux
    doxygen
    curl
    valgrind
    python3Packages.sphinx
    libyaml
    udev
  ];

  nativeBuildInputs = [
    cmake
    pkg-config
    git
    dpkg
  ];


  NIX_CFLAGS_COMPILE = [ "-Wno-error" ];

  preConfigure = ''
    dpkg-deb -x ${xrtBin} root
    export XRT_FIRMWARE_DIR=$(pwd)/root/lib/firmware/xilinx
    if [ ! -d $XRT_FIRMWARE_DIR ]; then
      echo "NO xrt firmware found in binary release"
      false
    fi
    cd src

    find . -type f -print0 | \
      xargs -0 sed -i -e "s!/opt/xilinx!$out/opt/xilinx!;s!/lib/firmware!$out/lib/firmware!"

    substituteInPlace CMakeLists.txt \
      --replace "/usr" "$out/opt/xilinx"

    find . -type f -iname "*.cmake" -print0 | \
      xargs -0 sed -i -e "s!/usr/src/!$out/src/!;s!/etc/OpenCL!$out/etc/OpenCL!;s!/usr/share/pkgconfig!$out/lib/pkgconfig!"
  '';

  postInstall = ''
    export INSTALL_MOD_PATH="$out"
    modDir=$(echo $out/src/xrt-*/driver/xocl)

    pushd $modDir/mgmtpf
    make -C "${KERNELDIR}" -j$NIX_BUILD_CORES M=$(pwd)
    make -C "${KERNELDIR}" -j$NIX_BUILD_CORES M=$(pwd) modules_install
    popd
    pushd $modDir/userpf
    make -C "${KERNELDIR}" -j$NIX_BUILD_CORES M=$(pwd)
    make -C "${KERNELDIR}" -j$NIX_BUILD_CORES M=$(pwd) modules_install
    popd

    ln -s $out/opt/xilinx/xrt/include $out/include
    ln -s $out/opt/xilinx/xrt $out/include/xrt
    ln -s $out/opt/xilinx/xrt/lib/* $out/lib
  '';

  meta = with stdenv.lib; {
    description = "xilinx runtime library";
    homepage = "https://www.xilinx.com/products/boards-and-kits/alveo/u50.html#gettingStarted";
    license = licenses.mit;
    maintainers = with maintainers; [ mic92 ];
    platforms = [ "x86_64-linux" ];
  };
}

Open a shell with it:

$ nix-shell shell.nix

and run the web installer downloaded from the xilinx website.

EDIT: the code above will be not regularly updated. But you can get a nix-shell for xilinx vitis by using this command:

nix develop --no-write-lock-file github:nix-community/nix-environments#xilinx-vitis
9 Likes

The code now lives in this repository:

For vivado users there is also a way of building derivations with it:

2 Likes

This is amazing. Currently Xilinx stuff is the only reason I have Docker on my laptop. (Because someone else told me that Docker works and I’m too lazy to try anything else.) I will hopefully try this out in a while when I get some time.

1 Like

I also add some module code to update xilinx firmware.
@dramforever Maybe consider moving out the code to a repo if you are an FPGA user yourself.
I only maintain this setup for post-docs in university and therefore cannot fully review changes to it.

I just got confirmation that with the NixOS module, flashing fpga firmware and the opencl drivers from xrt are functional.

I just tried this out. I used Xilinx_Unified_2020.2_1118_1232, and nixos-unstable channel version nixos-21.05pre281538.9e377a6ce42.

I had to make the following changes for Vivado to work:

  1. Replace ncurses with ncurses5, otherwise Vivado complains about missing libtinfo.so.5 on start.
  2. Replace gcc with (lib.hiPrio gcc). Otherwise the gcc ends up taken from stdenv.cc.cc and it’s unwrapped, which cannot compile executables. Vivado simulation needs gcc to work.

After making these changes I was able to try out the usual simulate, synthesize, implement, program, debug (with ILA) on a simple design and it worked great. Thank you so much for putting this together, @Mic92.

I do not use Vitis so I don’t know whether it was okay.

1 Like

I am still hoping someone can set up an repository in nix community or so with this code. Personally I cannot maintain this as I would require on a colleague to test every change.

Apologies, this is probably a bit of a basic question but what do you do with the vitis snippet you show above? It looks like it’s just a function that returns an attribute set - do you add it to your configuration.nix? Or run it in a shell somehow?

Save the snippet as shell.nix and than run nix-shell in the same directory to get a shell, where you can run the web installer. I did not install the IDE with nix itself because it is too big and complex.

Sorry, I probably wasn’t being very clear. I’ve got the installer one to work, and Vitis/Vivado have installed. But it seems like you’re using the second snippet (where you say “the code now lives in this repository”) to run vitis, rather than install it, and I can’t quite see how to use that particular bit of code.

I packaged the fhsuserenv shells as binaries and the linked code is a nixos module that you can copy out my repo (you will also need a few files from the pkgs in the same repository). The module will add the xilinx-shell and vivid command if you put it in a imports = [] list in your configuration.nix.
xilinx-shell is a bash shell that can run programs from your xilinx installation, the other one would just run vitis if I remember correctly? I no longer maintain this setup and removed it from the repository. If you can make it work and have you configuration shared somewhere, please post the link here.

Thanks, that gives me a starting point. If I get it working I’ll share it here. It would be nice to have the xilinx stuff defined as a proper nix derivation, but I’m not sure that that’s possible since it requires you to log in to download the software itself.

It’s also very huge for just one package. Having it separately seems to be the way to go.

Moved the nix expression from above to this repo: GitHub - nix-community/nix-environments: Repository to maintain out-of-tree shell.nix files (maintainer=@mic92)

I cloned the repo and run

nix-shell ./nix-environments -A xilinx-vitis

Then I run

TMPDIR=./tmp bash ./Xilinx_Unified_2021.2_1021_0703_Lin64.bin

Then I got something like

/xsetup:/bin/bash: No such file or directory

Could you please help? Thanks!

Sorry. Don’t know what happend there.
Is this installer supposed to be run with bash?
If so you can try bash -x to get more output when running the script.

I just compare it with other environment in the same repo and I found that there is no .env in the end. I added it and the runScript has another problem. The profile can’t be sourced either since I haven’t install it. After fixing those problem it finally works for me.

In the directory you can see this particular should be nix run (i.e. just run it like a normal package), rather than being used with nix-shell (i.e. starting a development environment over).

The top-level README doesn’t seem to mention this, and the name shell.nix seems pretty confusing. Looks like a docs issue to me.

Based on nix-community’s work, I created the repository nix-xilinx. It’s a nix flake that might help people launch xilinx’s tools in a semi-imperative manner. The README explains it all.

4 Likes

This definitely isn’t the right way to do things (Nix and FPGA noob), but It might help someone down the road. To install cable drives for Vivado I added the following to my configuration.nix. In my case I’m using the Basys 3, but I don’t think it should make a difference.

  services.udev.packages = [
    (pkgs.writeTextFile {
      name = "52-xilinx-digilent-usb.rules";
      text = ''
        ATTR{idVendor}=="1443", MODE:="666"
        ACTION=="add", ATTR{idVendor}=="0403", ATTR{manufacturer}=="Digilent", MODE:="666"
      '';

      destination = "/etc/udev/rules.d/52-xilinx-digilent-usb.rules";
    })
    (pkgs.writeTextFile {
      name = "52-xilinx-ftdi-usb.rules";
      text = ''
        ACTION=="add", ATTR{idVendor}=="0403", ATTR{manufacturer}=="Xilinx", MODE:="666"
      '';

      destination = "/etc/udev/rules.d/52-xilinx-ftdi-usb.rules";
    })
    (pkgs.writeTextFile {
      name = "52-xilinx-pcusb.rules";
      text = ''
        ATTR{idVendor}=="03fd", ATTR{idProduct}=="0008", MODE="666"
        ATTR{idVendor}=="03fd", ATTR{idProduct}=="0007", MODE="666"
        ATTR{idVendor}=="03fd", ATTR{idProduct}=="0009", MODE="666"
        ATTR{idVendor}=="03fd", ATTR{idProduct}=="000d", MODE="666"
        ATTR{idVendor}=="03fd", ATTR{idProduct}=="000f", MODE="666"
        ATTR{idVendor}=="03fd", ATTR{idProduct}=="0013", MODE="666"
        ATTR{idVendor}=="03fd", ATTR{idProduct}=="0015", MODE="666"
      '';

      destination = "/etc/udev/rules.d/52-xilinx-pcusb.rules";
    })
  ];

1 Like