diff --git a/artiq/frontend/artiq_coremgmt.py b/artiq/frontend/artiq_coremgmt.py index 903a5615f..448349f85 100755 --- a/artiq/frontend/artiq_coremgmt.py +++ b/artiq/frontend/artiq_coremgmt.py @@ -12,8 +12,7 @@ from artiq import __version__ as artiq_version from artiq.master.databases import DeviceDB from artiq.coredevice.comm_kernel import CommKernel from artiq.coredevice.comm_mgmt import CommMgmt -from artiq.frontend.bit2bin import bit2bin -from artiq.frontend.fetch_bin import fetch_bin +from artiq.frontend.flash_tools import bit2bin, fetch_bin def get_argparser(): diff --git a/artiq/frontend/artiq_flash.py b/artiq/frontend/artiq_flash.py index b9563a339..5a5296979 100755 --- a/artiq/frontend/artiq_flash.py +++ b/artiq/frontend/artiq_flash.py @@ -14,8 +14,7 @@ from sipyco import common_args from artiq import __version__ as artiq_version from artiq.remoting import SSHClient, LocalClient -from artiq.frontend.bit2bin import bit2bin -from artiq.frontend.fetch_bin import fetch_bin +from artiq.frontend.flash_tools import artifact_path, bit2bin, fetch_bin def get_argparser(): @@ -305,10 +304,10 @@ def main(): for action in args.action: if action == "gateware": - gateware_bin = fetch_bin(binary_dir, "gateware", args.srcbuild) + gateware_bin = fetch_bin(binary_dir, ["gateware"], args.srcbuild) programmer.write_binary(*config["gateware"], gateware_bin) elif action == "bootloader": - bootloader_bin = fetch_bin(binary_dir, "bootloader", args.srcbuild) + bootloader_bin = fetch_bin(binary_dir, ["bootloader"], args.srcbuild) programmer.write_binary(*config["bootloader"], bootloader_bin) elif action == "storage": storage_img = args.storage diff --git a/artiq/frontend/bit2bin.py b/artiq/frontend/bit2bin.py deleted file mode 100755 index df3927415..000000000 --- a/artiq/frontend/bit2bin.py +++ /dev/null @@ -1,69 +0,0 @@ -#!/usr/bin/env python3 -# Copyright 2014-2017 Robert Jordens -# after -# https://github.com/mfischer/fpgadev-zynq/blob/master/top/python/bit_to_zynq_bin.py - -import struct - - -def flip32(data): - sl = struct.Struct("I") - b = memoryview(data) - d = bytearray(len(data)) - for offset in range(0, len(data), sl.size): - sb.pack_into(d, offset, *sl.unpack_from(b, offset)) - return d - - -def bit2bin(bit, bin, flip=False): - l, = struct.unpack(">H", bit.read(2)) - if l != 9: - raise ValueError("Missing <0009> header, not a bit file") - _ = bit.read(l) # unknown data - l, = struct.unpack(">H", bit.read(2)) - if l != 1: - raise ValueError("Missing <0001> header, not a bit file") - - while True: - key = bit.read(1).decode() - if not key: - break - if key in "abcd": - d = bit.read(*struct.unpack(">H", bit.read(2))) - assert d.endswith(b"\x00") - d = d[:-1].decode() - name = { - "a": "Design", - "b": "Part name", - "c": "Date", - "d": "Time" - }[key] - print("{}: {}".format(name, d)) - elif key == "e": - l, = struct.unpack(">I", bit.read(4)) - print("Bitstream payload length: {:#x}".format(l)) - d = bit.read(l) - if flip: - d = flip32(d) - bin.write(d) - else: - d = bit.read(*struct.unpack(">H", bit.read(2))) - print("Unexpected key: {}: {}".format(key, d)) - - -if __name__ == "__main__": - import argparse - parser = argparse.ArgumentParser( - description="Convert FPGA bit files to raw bin format " - "suitable for flashing") - parser.add_argument("-f", "--flip", dest="flip", action="store_true", - default=False, help="Flip 32-bit endianess (needed for Zynq)") - parser.add_argument("bitfile", metavar="BITFILE", - help="Input bit file name") - parser.add_argument("binfile", metavar="BINFILE", - help="Output bin file name") - args = parser.parse_args() - - with open(args.bitfile, "rb") as f, open(args.binfile, "wb") as g: - bit2bin(f, g, args.flip) diff --git a/artiq/frontend/fetch_bin.py b/artiq/frontend/fetch_bin.py deleted file mode 100644 index 890c3413c..000000000 --- a/artiq/frontend/fetch_bin.py +++ /dev/null @@ -1,59 +0,0 @@ -import atexit -import os -import tempfile - -from artiq.frontend.bit2bin import bit2bin - - -def fetch_bin(binary_dir, component, srcbuild=False): - def artifact_path(this_binary_dir, *path_filename): - if srcbuild: - # source tree - use path elements to locate file - return os.path.join(this_binary_dir, *path_filename) - else: - # flat tree - all files in the same directory, discard path elements - *_, filename = path_filename - return os.path.join(this_binary_dir, filename) - - def convert_gateware(bit_filename): - bin_handle, bin_filename = tempfile.mkstemp( - prefix="artiq_", suffix="_" + os.path.basename(bit_filename)) - with open(bit_filename, "rb") as bit_file, open(bin_handle, "wb") as bin_file: - bit2bin(bit_file, bin_file) - atexit.register(lambda: os.unlink(bin_filename)) - return bin_filename - - if type(component) == list: - bins = [] - for option in component: - try: - bins.append(fetch_bin(binary_dir, option, srcbuild)) - except FileNotFoundError: - pass - - if bins is None: - raise FileNotFoundError("multiple components not found: {}".format( - " ".join(component))) - - if len(bins) > 1: - raise ValueError("more than one file, " - "please clean up your build directory. " - "Found files: {}".format( - " ".join(bins))) - - return bins[0] - - path = artifact_path(binary_dir, *{ - "gateware": ["gateware", "top.bit"], - "bootloader": ["software", "bootloader", "bootloader.bin"], - "runtime": ["software", "runtime", "runtime.fbi"], - "satman": ["software", "satman", "satman.fbi"], - }[component]) - - if not os.path.exists(path): - raise FileNotFoundError("{} not found".format(component)) - - if component == "gateware": - path = convert_gateware(path) - - return path diff --git a/artiq/frontend/flash_tools.py b/artiq/frontend/flash_tools.py new file mode 100644 index 000000000..d486454d3 --- /dev/null +++ b/artiq/frontend/flash_tools.py @@ -0,0 +1,114 @@ +import atexit +import os +import tempfile + + +def artifact_path(this_binary_dir, *path_filename, srcbuild=False): + if srcbuild: + # source tree - use path elements to locate file + return os.path.join(this_binary_dir, *path_filename) + else: + # flat tree - all files in the same directory, discard path elements + *_, filename = path_filename + return os.path.join(this_binary_dir, filename) + + +def fetch_bin(binary_dir, components, srcbuild=False): + def convert_gateware(bit_filename): + bin_handle, bin_filename = tempfile.mkstemp( + prefix="artiq_", suffix="_" + os.path.basename(bit_filename)) + with open(bit_filename, "rb") as bit_file, open(bin_handle, "wb") as bin_file: + bit2bin(bit_file, bin_file) + atexit.register(lambda: os.unlink(bin_filename)) + return bin_filename + + if len(components) > 1: + bins = [] + for option in components: + try: + bins.append(fetch_bin(binary_dir, [option], srcbuild)) + except FileNotFoundError: + pass + + if bins is None: + raise FileNotFoundError("multiple components not found: {}".format( + " ".join(components))) + + if len(bins) > 1: + raise ValueError("more than one file, " + "please clean up your build directory. " + "Found files: {}".format( + " ".join(bins))) + + return bins[0] + + else: + component = components[0] + path = artifact_path(binary_dir, *{ + "gateware": ["gateware", "top.bit"], + "boot": ["boot.bin"], + "bootloader": ["software", "bootloader", "bootloader.bin"], + "runtime": ["software", "runtime", "runtime.fbi"], + "satman": ["software", "satman", "satman.fbi"], + }[component], srcbuild=srcbuild) + + if not os.path.exists(path): + raise FileNotFoundError("{} not found".format(component)) + + if component == "gateware": + path = convert_gateware(path) + + return path + + +# Copyright 2014-2017 Robert Jordens +# after +# https://github.com/mfischer/fpgadev-zynq/blob/master/top/python/bit_to_zynq_bin.py + +import struct + + +def flip32(data): + sl = struct.Struct("I") + b = memoryview(data) + d = bytearray(len(data)) + for offset in range(0, len(data), sl.size): + sb.pack_into(d, offset, *sl.unpack_from(b, offset)) + return d + + +def bit2bin(bit, bin, flip=False): + l, = struct.unpack(">H", bit.read(2)) + if l != 9: + raise ValueError("Missing <0009> header, not a bit file") + _ = bit.read(l) # unknown data + l, = struct.unpack(">H", bit.read(2)) + if l != 1: + raise ValueError("Missing <0001> header, not a bit file") + + while True: + key = bit.read(1).decode() + if not key: + break + if key in "abcd": + d = bit.read(*struct.unpack(">H", bit.read(2))) + assert d.endswith(b"\x00") + d = d[:-1].decode() + name = { + "a": "Design", + "b": "Part name", + "c": "Date", + "d": "Time" + }[key] + print("{}: {}".format(name, d)) + elif key == "e": + l, = struct.unpack(">I", bit.read(4)) + print("Bitstream payload length: {:#x}".format(l)) + d = bit.read(l) + if flip: + d = flip32(d) + bin.write(d) + else: + d = bit.read(*struct.unpack(">H", bit.read(2))) + print("Unexpected key: {}: {}".format(key, d))