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
4 changed files with 34 additions and 60 deletions
Showing only changes of commit 85c4719f33 - Show all commits

View File

@ -59,7 +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" ];
buildInputs = [ nativeBuildInputs = [
pkgs.gnumake pkgs.which pkgs.gnumake pkgs.which
artiqpkgs.cargo artiqpkgs.cargo
artiqpkgs.rustc artiqpkgs.rustc
@ -73,7 +73,7 @@ let
'' ''
export CARGO_HOME=${cargoVendored} export CARGO_HOME=${cargoVendored}
export TARGET_AR=or1k-linux-ar export TARGET_AR=or1k-linux-ar
${buildCommand} --no-compile-gateware ${buildCommand} --no-compile-gateware --gateware-identifier-str=unprogrammed
''; '';
installPhase = installPhase =
'' ''
@ -93,28 +93,18 @@ let
''; '';
}); });
vivadoIdentifiers = import (pkgs.stdenv.mkDerivation { identifierStr = "${version};${variant}";
name = "${name}-vivado-identifiers.nix"; identifiers = import (
src = "${boardModule}/src/gateware"; pkgs.runCommandLocal "${name}-identifiers.nix" {
buildInputs = [ pkgs.python ]; buildInputs = [ pkgs.python3 ];
phases = [ "unpackPhase" "buildPhase" ]; } ''python ${./generate-identifier.py} "${identifierStr}" > $out''
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 ${vivadoInput} | base64 -w0 > $out"; installPhase = "nix-store --dump ${boardModule}/src/gateware | base64 -w0 > $out";
}; };
# Funnelling the source code through a Nix string allows dropping # Funnelling the source code through a Nix string allows dropping
@ -158,7 +148,7 @@ let
'' ''
set_property INIT ${init} [get_cell ${cell}] set_property INIT ${init} [get_cell ${cell}]
'' ''
) vivadoIdentifiers) + ) identifiers) +
'' ''
source "top_bitstream.tcl" source "top_bitstream.tcl"
EOF EOF

View File

@ -0,0 +1,24 @@
#!/usr/bin/env python
#
# Encodes data like ARTIQ build_soc.py ReprogrammableIdentifier
import sys
if len(sys.argv) != 2:
raise ValueError('argument missing')
identifier_str = sys.argv[1]
contents = list(identifier_str.encode())
l = len(contents)
if l > 255:
raise ValueError("Identifier string must be 255 characters or less")
contents.insert(0, l)
f = sys.stdout
f.write("[\n");
for i in range(7):
init = sum(1 << j if c & (1 << i) else 0 for j, c in enumerate(contents))
f.write(
' {{ cell = "identifier_str{}"; init = "256\'h{:X}"; }}\n'.format(i, init)
)
f.write("]\n");

View File

@ -1,24 +0,0 @@
#!/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

@ -1,16 +0,0 @@
#!/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)