artiq-fast: build gateware from a self-contained separate source derivation #23

Merged
sb10q merged 6 commits from split-software-gateware-builds into master 2020-12-02 17:22:55 +08:00
3 changed files with 94 additions and 10 deletions
Showing only changes of commit a30db2ba2e - Show all commits

View File

@ -59,8 +59,7 @@ let
name = "${name}-firmware"; name = "${name}-firmware";
inherit version src; inherit version src;
phases = [ "buildPhase" "installCheckPhase" "installPhase" "checkPhase" ]; phases = [ "buildPhase" "installCheckPhase" "installPhase" "checkPhase" ];
nativeBuildInputs = [ buildInputs = [
vivado
pkgs.gnumake pkgs.which pkgs.gnumake pkgs.which
artiqpkgs.cargo artiqpkgs.cargo
artiqpkgs.rustc artiqpkgs.rustc
@ -94,11 +93,28 @@ let
''; '';
}); });
vivadoIdentifiers = import (pkgs.stdenv.mkDerivation {
name = "${name}-vivado-identifiers.nix";
src = "${boardModule}/src/gateware";
buildInputs = [ pkgs.python ];
phases = [ "unpackPhase" "buildPhase" ];
buildPhase = "python ${./scripts/get-identifiers.py} top.v > $out";
});
vivadoInput = pkgs.stdenv.mkDerivation {
name = "${name}-vivado-input";
src = "${boardModule}/src/gateware";
buildInputs = [ pkgs.python ];
phases = [ "unpackPhase" "patchPhase" "installPhase" ];
patchPhase = "python ${./scripts/remove-identifiers.py} top.v";
installPhase = "cp -ar . $out";
};
vivadoInputArchive = pkgs.stdenv.mkDerivation { vivadoInputArchive = pkgs.stdenv.mkDerivation {
name = "${name}-vivado-input.nar.base64"; name = "${name}-vivado-input.nar.base64";
buildInputs = [ pkgs.nix ]; buildInputs = [ pkgs.nix ];
phases = [ "installPhase" ]; phases = [ "installPhase" ];
installPhase = "nix-store --dump ${boardModule}/src/gateware | base64 -w0 > $out"; installPhase = "nix-store --dump ${vivadoInput} | base64 -w0 > $out";
}; };
# Funnelling the source code through a Nix string allows dropping # Funnelling the source code through a Nix string allows dropping
@ -110,22 +126,49 @@ let
)); ));
# Depends on just Vivado and the generated Bitstream source # Depends on just Vivado and the generated Bitstream source
vivadoOutput = pkgs.stdenvNoCC.mkDerivation { vivadoCheckpoint = pkgs.stdenvNoCC.mkDerivation {
name = builtins.unsafeDiscardStringContext "${name}-vivado-output"; name = builtins.unsafeDiscardStringContext "${name}-vivado-checkpoint";
unpackPhase = "base64 -d < ${pureVivadoInputArchive} | nix-store --restore gateware"; unpackPhase = "base64 -d < ${pureVivadoInputArchive} | nix-store --restore gateware";
buildInputs = [ vivado pkgs.nix ]; buildInputs = [ vivado pkgs.nix ];
buildPhase = '' buildPhase = ''
cd gateware cd gateware
vivado -mode batch -source top.tcl vivado -mode batch -source top_route.tcl
''; '';
installPhase = ''
mkdir -p $out
chmod a+r top_route.dcp
cp top_route.dcp $out
cp top_bitstream.tcl $out
'';
};
vivadoOutput = pkgs.stdenvNoCC.mkDerivation {
name = builtins.unsafeDiscardStringContext "${name}-vivado-output";
src = vivadoCheckpoint;
buildInputs = [ vivado ];
buildPhase =
''
cat >top.tcl <<EOF
open_checkpoint top_route.dcp
'' +
(pkgs.lib.concatMapStrings ({ cell, init }:
''
set_property INIT ${init} [get_cell ${cell}]
''
) vivadoIdentifiers) +
''
source "top_bitstream.tcl"
EOF
vivado -mode batch -source top.tcl
'';
installPhase = '' installPhase = ''
TARGET_DIR=$out/${builtins.unsafeDiscardStringContext installPath} TARGET_DIR=$out/${builtins.unsafeDiscardStringContext installPath}
mkdir -p $TARGET_DIR mkdir -p $TARGET_DIR
chmod a+r top.bit chmod a+r top.bit
cp top.bit $TARGET_DIR cp top.bit $TARGET_DIR/
''; '';
# temporarily disabled because there is currently always at least one Kasli bitstream # temporarily disabled because there is currently always at least one Kasli bitstream
@ -146,7 +189,8 @@ let
check_log "Timing constraints are not met\." check_log "Timing constraints are not met\."
''; '';
}; };
in pkgs.buildEnv rec { in
pkgs.buildEnv rec {
inherit name; inherit name;
paths = [ boardModule vivadoOutput ]; paths = [ boardModule vivadoOutput ];
pathsToLink = [ "/${installPath}" ]; pathsToLink = [ "/${installPath}" ];

View File

@ -0,0 +1,24 @@
#!/usr/bin/env python
import sys, re
if len(sys.argv) != 2:
raise ValueError('Filename argument missing')
filename = sys.argv[1]
with open(filename, 'r') as f:
data = f.read()
identifiers = re.findall(r"\.INIT\((\d+'d\d+\)\s*\)\s*identifier_str\d+)", data)
f = sys.stdout
f.write("[\n")
for identifier in identifiers:
m = re.match(r"(\d+)'d(\d+)\)\s*\)\s*(\S+)", identifier)
if m is not None:
cell = m.group(3)
# the literal must be converted to hex for Vivado Tcl `set_property`
init = "{}'h{:X}".format(m.group(1), int(m.group(2)))
f.write(' {{ cell = "{}"; init = "{}"; }}\n'.format(cell, init))
f.write("]\n")

View File

@ -0,0 +1,16 @@
#!/usr/bin/env python
import sys, re
if len(sys.argv) != 2:
raise ValueError('Filename argument missing')
filename = sys.argv[1]
with open(filename, 'r') as f:
data = f.read()
data = re.sub(r"\.INIT\((\d+'d\d+)\)(\s*)\)(\s*)identifier_str", r".INIT(32'hAAAAAAAA)\2)\3identifier_str", data)
with open(filename, 'w') as f:
f.write(data)