mirror of
https://github.com/m-labs/artiq.git
synced 2024-12-27 12:18:26 +08:00
bit2bin, fetch_bin -> flash_tools
This commit is contained in:
parent
f2c13a5041
commit
de349e4c39
@ -12,8 +12,7 @@ from artiq import __version__ as artiq_version
|
|||||||
from artiq.master.databases import DeviceDB
|
from artiq.master.databases import DeviceDB
|
||||||
from artiq.coredevice.comm_kernel import CommKernel
|
from artiq.coredevice.comm_kernel import CommKernel
|
||||||
from artiq.coredevice.comm_mgmt import CommMgmt
|
from artiq.coredevice.comm_mgmt import CommMgmt
|
||||||
from artiq.frontend.bit2bin import bit2bin
|
from artiq.frontend.flash_tools import bit2bin, fetch_bin
|
||||||
from artiq.frontend.fetch_bin import fetch_bin
|
|
||||||
|
|
||||||
|
|
||||||
def get_argparser():
|
def get_argparser():
|
||||||
|
@ -14,8 +14,7 @@ from sipyco import common_args
|
|||||||
|
|
||||||
from artiq import __version__ as artiq_version
|
from artiq import __version__ as artiq_version
|
||||||
from artiq.remoting import SSHClient, LocalClient
|
from artiq.remoting import SSHClient, LocalClient
|
||||||
from artiq.frontend.bit2bin import bit2bin
|
from artiq.frontend.flash_tools import artifact_path, bit2bin, fetch_bin
|
||||||
from artiq.frontend.fetch_bin import fetch_bin
|
|
||||||
|
|
||||||
|
|
||||||
def get_argparser():
|
def get_argparser():
|
||||||
@ -305,10 +304,10 @@ def main():
|
|||||||
|
|
||||||
for action in args.action:
|
for action in args.action:
|
||||||
if action == "gateware":
|
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)
|
programmer.write_binary(*config["gateware"], gateware_bin)
|
||||||
elif action == "bootloader":
|
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)
|
programmer.write_binary(*config["bootloader"], bootloader_bin)
|
||||||
elif action == "storage":
|
elif action == "storage":
|
||||||
storage_img = args.storage
|
storage_img = args.storage
|
||||||
|
@ -1,69 +0,0 @@
|
|||||||
#!/usr/bin/env python3
|
|
||||||
# Copyright 2014-2017 Robert Jordens <jordens@gmail.com>
|
|
||||||
# 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")
|
|
||||||
sb = 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)
|
|
@ -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
|
|
114
artiq/frontend/flash_tools.py
Normal file
114
artiq/frontend/flash_tools.py
Normal file
@ -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 <jordens@gmail.com>
|
||||||
|
# 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")
|
||||||
|
sb = 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))
|
Loading…
Reference in New Issue
Block a user