artiq-fast: build gateware from a self-contained separate source derivation #23
|
@ -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
|
||||||
|
|
|
@ -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");
|
|
@ -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")
|
|
|
@ -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)
|
|
Loading…
Reference in New Issue