Beispiel #1
0
def main():
    args = get_argparser().parse_args()
    init_logger(args)
    if args.verbose == args.quiet == 0:
        logging.getLogger().setLevel(logging.INFO)

    def build_dir(*path, target=args.target):
        return os.path.join("/tmp/", "artiq_" + target, *path)

    if args.target == "kc705":
        board_type, firmware = "kc705", "runtime"
        variant = "nist_clock" if args.variant is None else args.variant
    elif args.target == "sayma":
        board_type, firmware = "sayma", "runtime"
        variant = "standalone" if args.variant is None else args.variant
    elif args.target == "kasli":
        board_type, firmware = "kasli", "runtime"
        variant = "tester" if args.variant is None else args.variant
    else:
        raise NotImplementedError("unknown target {}".format(args.target))

    board      = args.board.format(board_type=board_type)
    board_file = args.board_file.format(board=board)
    device     = args.device.format(board=board, host=args.host)
    serial     = args.serial.format(board=board)

    client = SSHClient(args.host, args.jump)

    flock_acquired = False
    flock_file = None # GC root
    def lock():
        nonlocal flock_acquired
        nonlocal flock_file

        if not flock_acquired:
            fuser_args = ["fuser", "-u", board_file]
            fuser = client.spawn_command(fuser_args)
            fuser_file = fuser.makefile('r')
            fuser_match = re.search(r"\((.+?)\)", fuser_file.readline())
            if fuser_match and fuser_match.group(1) == os.getenv("USER"):
                logger.info("Lock already acquired by {}".format(os.getenv("USER")))
                flock_acquired = True
                return

            logger.info("Acquiring device lock")
            flock_args = ["flock"]
            if not args.wait:
                flock_args.append("--nonblock")
            flock_args += ["--verbose", board_file]
            flock_args += ["sleep", "86400"]

            flock = client.spawn_command(flock_args, get_pty=True)
            flock_file = flock.makefile('r')
            while not flock_acquired:
                line = flock_file.readline()
                if not line:
                    break
                logger.debug(line.rstrip())
                if line.startswith("flock: executing"):
                    flock_acquired = True
                elif line.startswith("flock: failed"):
                    logger.error("Failed to get lock")
                    sys.exit(1)

    def command(*args, on_failure="Command failed"):
        logger.debug("Running {}".format(" ".join([shlex.quote(arg) for arg in args])))
        try:
            subprocess.check_call(args)
        except subprocess.CalledProcessError:
            logger.error(on_failure)
            sys.exit(1)

    def build(target, *extra_args, output_dir=build_dir(), variant=variant):
        build_args = ["python3", "-m", "artiq.gateware.targets." + target, *extra_args]
        if not args.gateware:
            build_args.append("--no-compile-gateware")
        if variant:
            build_args += ["--variant", variant]
        build_args += ["--output-dir", output_dir]
        command(*build_args, on_failure="Build failed")

    def flash(*steps):
        lock()

        flash_args = ["artiq_flash"]
        for _ in range(args.verbose):
            flash_args.append("-v")
        flash_args += ["-H", args.host]
        if args.jump:
            flash_args += ["-J", args.jump]
        flash_args += ["-t", board_type]
        flash_args += ["-V", variant]
        flash_args += ["-I", "source {}".format(board_file)]
        flash_args += ["--srcbuild", build_dir()]
        flash_args += steps
        command(*flash_args, on_failure="Flashing failed")

    for action in args.actions:
        if action == "build":
            logger.info("Building target")
            if args.target == "sayma":
                build("sayma_rtm", output_dir=build_dir("rtm_gateware"), variant=None)
                build("sayma_amc", "--rtm-csr-csv", build_dir("rtm_gateware", "rtm_csr.csv"))
            else:
                build(args.target)

        elif action == "clean":
            logger.info("Cleaning build directory")
            shutil.rmtree(build_dir(), ignore_errors=True)

        elif action == "reset":
            logger.info("Resetting device")
            flash("start")

        elif action == "flash":
            gateware = ["gateware"] if args.gateware else []

            logger.info("Flashing and booting")
            flash(*gateware, "bootloader", "firmware", "start")

        elif action == "flash+log":
            gateware = ["gateware"] if args.gateware else []

            logger.info("Flashing")
            flash(*gateware, "bootloader", "firmware")

            flterm = client.spawn_command(["flterm", serial, "--output-only"])
            logger.info("Booting")
            flash("start")
            client.drain(flterm)

        elif action == "load":
            logger.info("Loading gateware")
            flash("load")

        elif action == "connect":
            lock()

            transport = client.get_transport()
            transport.set_keepalive(30)

            def forwarder(local_stream, remote_stream):
                try:
                    while True:
                        r, _, _ = select.select([local_stream, remote_stream], [], [])
                        if local_stream in r:
                            data = local_stream.recv(65535)
                            if data == b"":
                                break
                            remote_stream.sendall(data)
                        if remote_stream in r:
                            data = remote_stream.recv(65535)
                            if data == b"":
                                break
                            local_stream.sendall(data)
                except Exception as err:
                    logger.error("Cannot forward on port %s: %s", port, repr(err))
                local_stream.close()
                remote_stream.close()

            def listener(port):
                listener = socket.socket()
                listener.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
                listener.bind(('localhost', port))
                listener.listen(8)
                while True:
                    local_stream, peer_addr = listener.accept()
                    logger.info("Accepting %s:%s and opening SSH channel to %s:%s",
                                *peer_addr, device, port)
                    try:
                        remote_stream = \
                            transport.open_channel('direct-tcpip', (device, port), peer_addr)
                    except Exception:
                        logger.exception("Cannot open channel on port %s", port)
                        continue

                    thread = threading.Thread(target=forwarder, args=(local_stream, remote_stream),
                                              name="forward-{}".format(port), daemon=True)
                    thread.start()

            ports = [1380, 1381, 1382, 1383]
            for port in ports:
                thread = threading.Thread(target=listener, args=(port,),
                                          name="listen-{}".format(port), daemon=True)
                thread.start()

            logger.info("Forwarding ports {} to core device and logs from core device"
                            .format(", ".join(map(str, ports))))
            client.run_command(["flterm", serial, "--output-only"])

        elif action == "hotswap":
            lock()

            logger.info("Hotswapping firmware")
            firmware = build_dir(variant, "software", firmware, firmware + ".bin")

            mgmt = CommMgmt(device)
            mgmt.open(ssh_transport=client.get_transport())
            with open(firmware, "rb") as f:
                mgmt.hotswap(f.read())

        else:
            logger.error("Unknown action {}".format(action))
            sys.exit(1)
Beispiel #2
0
def main():
    args = get_argparser().parse_args()
    init_logger(args)

    config = {
        "kasli": {
            "programmer":
            partial(ProgrammerXC7,
                    board="kasli",
                    proxy="bscan_spi_xc7a100t.bit"),
            "def_variant":
            "opticlock",
            "gateware": ("spi0", 0x000000),
            "bootloader": ("spi0", 0x400000),
            "storage": ("spi0", 0x440000),
            "firmware": ("spi0", 0x450000),
        },
        "sayma": {
            "programmer": ProgrammerSayma,
            "def_variant": "standalone",
            "gateware": ("spi0", 0x000000),
            "bootloader": ("spi1", 0x000000),
            "storage": ("spi1", 0x040000),
            "firmware": ("spi1", 0x050000),
            "rtm_gateware": ("spi1", 0x200000),
        },
        "kc705": {
            "programmer":
            partial(ProgrammerXC7,
                    board="kc705",
                    proxy="bscan_spi_xc7k325t.bit"),
            "def_variant":
            "nist_clock",
            "gateware": ("spi0", 0x000000),
            "bootloader": ("spi0", 0xaf0000),
            "storage": ("spi0", 0xb30000),
            "firmware": ("spi0", 0xb40000),
        },
    }[args.target]

    variant = args.variant
    if variant is None:
        variant = config["def_variant"]

    bin_dir = args.dir
    if bin_dir is None:
        bin_name = args.target
        if variant:
            bin_name += "-" + variant
        bin_dir = os.path.join(artiq_dir, "binaries", bin_name)

    if args.host is None:
        client = LocalClient()
    else:
        client = SSHClient(args.host, args.jump)

    programmer = config["programmer"](client,
                                      preinit_script=args.preinit_command)

    def artifact_path(*path_filename):
        if args.srcbuild is None:
            *path, filename = path_filename
            return os.path.join(bin_dir, filename)
        else:
            return os.path.join(args.srcbuild, *path_filename)

    def convert_gateware(bit_filename, header=False):
        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:
            if header:
                bin_file.write(b"\x00" * 8)
            bit2bin(bit_file, bin_file)
            if header:
                magic = 0x5352544d  # "SRTM", see sayma_rtm target
                length = bin_file.tell() - 8
                bin_file.seek(0)
                bin_file.write(magic.to_bytes(4, byteorder="big"))
                bin_file.write(length.to_bytes(4, byteorder="big"))
        atexit.register(lambda: os.unlink(bin_filename))
        return bin_filename

    for action in args.action:
        if action == "gateware":
            gateware_bin = convert_gateware(
                artifact_path(variant, "gateware", "top.bit"))
            programmer.write_binary(*config["gateware"], gateware_bin)
            if args.target == "sayma" and args.variant != "master":
                rtm_gateware_bin = convert_gateware(artifact_path(
                    "rtm_gateware", "rtm.bit"),
                                                    header=True)
                programmer.write_binary(*config["rtm_gateware"],
                                        rtm_gateware_bin)
        elif action == "bootloader":
            bootloader_bin = artifact_path(variant, "software", "bootloader",
                                           "bootloader.bin")
            programmer.write_binary(*config["bootloader"], bootloader_bin)
        elif action == "storage":
            storage_img = args.storage
            programmer.write_binary(*config["storage"], storage_img)
        elif action == "firmware":
            if variant == "satellite":
                firmware = "satman"
            else:
                firmware = "runtime"

            firmware_fbi = artifact_path(variant, "software", firmware,
                                         firmware + ".fbi")
            programmer.write_binary(*config["firmware"], firmware_fbi)
        elif action == "load":
            if args.target == "sayma":
                rtm_gateware_bit = artifact_path("rtm_gateware", "rtm.bit")
                programmer.load(rtm_gateware_bit, 0)
                gateware_bit = artifact_path(variant, "gateware", "top.bit")
                programmer.load(gateware_bit, 1)
            else:
                gateware_bit = artifact_path(variant, "gateware", "top.bit")
                programmer.load(gateware_bit, 0)
        elif action == "start":
            programmer.start()
        else:
            raise ValueError("invalid action", action)

    if args.dry_run:
        print("\n".join(programmer.script()))
    else:
        programmer.run()
Beispiel #3
0
def main():
    args = get_argparser().parse_args()
    init_logger(args)
    if args.verbose == args.quiet == 0:
        logging.getLogger().setLevel(logging.INFO)

    def build_dir(*path, target=args.target):
        return os.path.join("/tmp/", "artiq_" + target, *path)

    if args.target == "kc705":
        board_type, firmware = "kc705", "runtime"
        variant = "nist_clock" if args.variant is None else args.variant
    elif args.target == "sayma":
        board_type, firmware = "sayma", "runtime"
        variant = "standalone" if args.variant is None else args.variant
    elif args.target == "kasli":
        board_type, firmware = "kasli", "runtime"
        variant = "tester" if args.variant is None else args.variant
    else:
        raise NotImplementedError("unknown target {}".format(args.target))

    board = args.board.format(board_type=board_type)
    board_file = args.board_file.format(board=board)
    device = args.device.format(board=board, host=args.host)
    serial = args.serial.format(board=board)

    client = SSHClient(args.host, args.jump)

    flock_acquired = False
    flock_file = None  # GC root

    def lock():
        nonlocal flock_acquired
        nonlocal flock_file

        if not flock_acquired:
            fuser_args = ["fuser", "-u", board_file]
            fuser = client.spawn_command(fuser_args)
            fuser_file = fuser.makefile('r')
            fuser_match = re.search(r"\((.+?)\)", fuser_file.readline())
            if fuser_match and fuser_match.group(1) == os.getenv("USER"):
                logger.info("Lock already acquired by {}".format(
                    os.getenv("USER")))
                flock_acquired = True
                return

            logger.info("Acquiring device lock")
            flock_args = ["flock"]
            if not args.wait:
                flock_args.append("--nonblock")
            flock_args += ["--verbose", board_file]
            flock_args += ["sleep", "86400"]

            flock = client.spawn_command(flock_args, get_pty=True)
            flock_file = flock.makefile('r')
            while not flock_acquired:
                line = flock_file.readline()
                if not line:
                    break
                logger.debug(line.rstrip())
                if line.startswith("flock: executing"):
                    flock_acquired = True
                elif line.startswith("flock: failed"):
                    logger.error("Failed to get lock")
                    sys.exit(1)

    def command(*args, on_failure="Command failed"):
        logger.debug("Running {}".format(" ".join(
            [shlex.quote(arg) for arg in args])))
        try:
            subprocess.check_call(args)
        except subprocess.CalledProcessError:
            logger.error(on_failure)
            sys.exit(1)

    def build(target, *extra_args, output_dir=build_dir(), variant=variant):
        build_args = [
            "python3", "-m", "artiq.gateware.targets." + target, *extra_args
        ]
        if not args.gateware:
            build_args.append("--no-compile-gateware")
        if variant:
            build_args += ["--variant", variant]
        build_args += ["--output-dir", output_dir]
        command(*build_args, on_failure="Build failed")

    def flash(*steps):
        lock()

        flash_args = ["artiq_flash"]
        for _ in range(args.verbose):
            flash_args.append("-v")
        flash_args += ["-H", args.host]
        if args.jump:
            flash_args += ["-J", args.jump]
        flash_args += ["-t", board_type]
        flash_args += ["-V", variant]
        flash_args += ["-I", "source {}".format(board_file)]
        flash_args += ["--srcbuild", build_dir()]
        flash_args += steps
        command(*flash_args, on_failure="Flashing failed")

    for action in args.actions:
        if action == "build":
            logger.info("Building target")
            if args.target == "sayma":
                build("sayma_rtm",
                      output_dir=build_dir("rtm_gateware"),
                      variant=None)
                build("sayma_amc", "--rtm-csr-csv",
                      build_dir("rtm_gateware", "rtm_csr.csv"))
            else:
                build(args.target)

        elif action == "clean":
            logger.info("Cleaning build directory")
            shutil.rmtree(build_dir(), ignore_errors=True)

        elif action == "reset":
            logger.info("Resetting device")
            flash("start")

        elif action == "flash":
            gateware = ["gateware"] if args.gateware else []

            logger.info("Flashing and booting")
            flash(*gateware, "bootloader", "firmware", "start")

        elif action == "flash+log":
            gateware = ["gateware"] if args.gateware else []

            logger.info("Flashing")
            flash(*gateware, "bootloader", "firmware")

            flterm = client.spawn_command(["flterm", serial, "--output-only"])
            logger.info("Booting")
            flash("start")
            client.drain(flterm)

        elif action == "load":
            logger.info("Loading gateware")
            flash("load")

        elif action == "connect":
            lock()

            transport = client.get_transport()
            transport.set_keepalive(30)

            def forwarder(local_stream, remote_stream):
                try:
                    while True:
                        r, _, _ = select.select([local_stream, remote_stream],
                                                [], [])
                        if local_stream in r:
                            data = local_stream.recv(65535)
                            if data == b"":
                                break
                            remote_stream.sendall(data)
                        if remote_stream in r:
                            data = remote_stream.recv(65535)
                            if data == b"":
                                break
                            local_stream.sendall(data)
                except Exception as err:
                    logger.error("Cannot forward on port %s: %s", port,
                                 repr(err))
                local_stream.close()
                remote_stream.close()

            def listener(port):
                listener = socket.socket()
                listener.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
                listener.bind(('localhost', port))
                listener.listen(8)
                while True:
                    local_stream, peer_addr = listener.accept()
                    logger.info(
                        "Accepting %s:%s and opening SSH channel to %s:%s",
                        *peer_addr, device, port)
                    try:
                        remote_stream = \
                            transport.open_channel('direct-tcpip', (device, port), peer_addr)
                    except Exception:
                        logger.exception("Cannot open channel on port %s",
                                         port)
                        continue

                    thread = threading.Thread(target=forwarder,
                                              args=(local_stream,
                                                    remote_stream),
                                              name="forward-{}".format(port),
                                              daemon=True)
                    thread.start()

            ports = [1380, 1381, 1382, 1383]
            for port in ports:
                thread = threading.Thread(target=listener,
                                          args=(port, ),
                                          name="listen-{}".format(port),
                                          daemon=True)
                thread.start()

            logger.info(
                "Forwarding ports {} to core device and logs from core device".
                format(", ".join(map(str, ports))))
            client.run_command(["flterm", serial, "--output-only"])

        elif action == "hotswap":
            lock()

            logger.info("Hotswapping firmware")
            firmware = build_dir(variant, "software", firmware,
                                 firmware + ".bin")

            mgmt = CommMgmt(device)
            mgmt.open(ssh_transport=client.get_transport())
            with open(firmware, "rb") as f:
                mgmt.hotswap(f.read())

        else:
            logger.error("Unknown action {}".format(action))
            sys.exit(1)
Beispiel #4
0
def main():
    args = get_argparser().parse_args()
    common_args.init_logger_from_args(args)

    config = {
        "kasli": {
            "programmer":
            partial(ProgrammerXC7,
                    board="kasli",
                    proxy="bscan_spi_xc7a100t.bit"),
            "gateware": ("spi0", 0x000000),
            "bootloader": ("spi0", 0x400000),
            "storage": ("spi0", 0x440000),
            "firmware": ("spi0", 0x450000),
        },
        "sayma": {
            "programmer": ProgrammerAMCRTM,
            "gateware": ("spi0", 0x000000),
            "bootloader": ("spi1", 0x000000),
            "storage": ("spi1", 0x040000),
            "firmware": ("spi1", 0x050000),
            "rtm_gateware": ("spi1", 0x200000),
        },
        "kc705": {
            "programmer":
            partial(ProgrammerXC7,
                    board="kc705",
                    proxy="bscan_spi_xc7k325t.bit"),
            "def_variant":
            "nist_clock",
            "gateware": ("spi0", 0x000000),
            "bootloader": ("spi0", 0xaf0000),
            "storage": ("spi0", 0xb30000),
            "firmware": ("spi0", 0xb40000),
        },
    }[args.target]

    bin_dir = args.dir
    if bin_dir is None:
        bin_dir = os.path.join(artiq_dir, "board-support")

    needs_artifacts = not args.action or any(
        action in args.action for action in [
            "gateware", "rtm_gateware", "bootloader", "firmware", "load",
            "rtm_load"
        ])
    variant = args.variant
    if needs_artifacts and variant is None:
        variants = []
        if args.srcbuild:
            for entry in os.scandir(bin_dir):
                if entry.is_dir():
                    variants.append(entry.name)
        else:
            prefix = args.target + "-"
            for entry in os.scandir(bin_dir):
                if entry.is_dir() and entry.name.startswith(prefix):
                    variants.append(entry.name[len(prefix):])
        if args.target == "sayma":
            try:
                variants.remove("rtm")
            except ValueError:
                pass
        if len(variants) == 0:
            raise FileNotFoundError(
                "no variants found, did you install a board binary package?")
        elif len(variants) == 1:
            variant = variants[0]
        else:
            raise ValueError(
                "more than one variant found for selected board, specify -V. "
                "Found variants: {}".format(" ".join(sorted(variants))))
    if needs_artifacts:
        if args.srcbuild:
            variant_dir = variant
        else:
            variant_dir = args.target + "-" + variant
        if args.target == "sayma":
            if args.srcbuild:
                rtm_variant_dir = "rtm"
            else:
                rtm_variant_dir = "sayma-rtm"

    if not args.action:
        if args.target == "sayma" and variant != "simplesatellite" and variant != "master":
            args.action = "gateware rtm_gateware bootloader firmware start".split(
            )
        else:
            args.action = "gateware bootloader firmware start".split()

    if args.host is None:
        client = LocalClient()
    else:
        client = SSHClient(args.host, args.jump)

    if args.target == "sayma" and args.no_rtm_jtag:
        programmer_cls = ProgrammerAMC
    else:
        programmer_cls = config["programmer"]
    programmer = programmer_cls(client, preinit_script=args.preinit_command)

    def artifact_path(this_variant_dir, *path_filename):
        if args.srcbuild:
            # source tree - use path elements to locate file
            return os.path.join(bin_dir, this_variant_dir, *path_filename)
        else:
            # flat tree - all files in the same directory, discard path elements
            *_, filename = path_filename
            return os.path.join(bin_dir, this_variant_dir, filename)

    def convert_gateware(bit_filename, header=False):
        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:
            if header:
                bin_file.write(b"\x00" * 8)
            bit2bin(bit_file, bin_file)
            if header:
                magic = 0x5352544d  # "SRTM", see sayma_rtm target
                length = bin_file.tell() - 8
                bin_file.seek(0)
                bin_file.write(magic.to_bytes(4, byteorder="big"))
                bin_file.write(length.to_bytes(4, byteorder="big"))
        atexit.register(lambda: os.unlink(bin_filename))
        return bin_filename

    for action in args.action:
        if action == "gateware":
            gateware_bin = convert_gateware(
                artifact_path(variant_dir, "gateware", "top.bit"))
            programmer.write_binary(*config["gateware"], gateware_bin)
        elif action == "rtm_gateware":
            rtm_gateware_bin = convert_gateware(artifact_path(
                rtm_variant_dir, "gateware", "top.bit"),
                                                header=True)
            programmer.write_binary(*config["rtm_gateware"], rtm_gateware_bin)
        elif action == "bootloader":
            bootloader_bin = artifact_path(variant_dir, "software",
                                           "bootloader", "bootloader.bin")
            programmer.write_binary(*config["bootloader"], bootloader_bin)
        elif action == "storage":
            storage_img = args.storage
            programmer.write_binary(*config["storage"], storage_img)
        elif action == "firmware":
            if variant.endswith("satellite"):
                firmware = "satman"
            else:
                firmware = "runtime"

            firmware_fbi = artifact_path(variant_dir, "software", firmware,
                                         firmware + ".fbi")
            programmer.write_binary(*config["firmware"], firmware_fbi)
        elif action == "load":
            if args.target == "sayma":
                gateware_bit = artifact_path(variant_dir, "gateware",
                                             "top.bit")
                programmer.load(gateware_bit, 1)
            else:
                gateware_bit = artifact_path(variant_dir, "gateware",
                                             "top.bit")
                programmer.load(gateware_bit, 0)
        elif action == "rtm_load":
            rtm_gateware_bit = artifact_path(rtm_variant_dir, "gateware",
                                             "top.bit")
            programmer.load(rtm_gateware_bit, 0)
        elif action == "start":
            programmer.start()
        elif action == "erase":
            if args.target == "sayma" or args.target == "metlino":
                programmer.erase_flash("spi0")
                programmer.erase_flash("spi1")
            else:
                programmer.erase_flash("spi0")
        else:
            raise ValueError("invalid action", action)

    if args.dry_run:
        print("\n".join(programmer.script()))
    else:
        programmer.run()
Beispiel #5
0
def main():
    args = get_argparser().parse_args()
    common_args.init_logger_from_args(args)

    config = {
        "kasli": {
            "programmer":
            partial(ProgrammerXC7,
                    board="kasli",
                    proxy="bscan_spi_xc7a100t.bit"),
            "gateware": ("spi0", 0x000000),
            "bootloader": ("spi0", 0x400000),
            "storage": ("spi0", 0x440000),
            "firmware": ("spi0", 0x450000),
        },
        "sayma": {
            "programmer": ProgrammerAMCRTM,
            "gateware": ("spi0", 0x000000),
            "bootloader": ("spi1", 0x000000),
            "storage": ("spi1", 0x040000),
            "firmware": ("spi1", 0x050000),
            "rtm_gateware": ("spi1", 0x200000),
        },
        "metlino": {
            "programmer": ProgrammerAMC,
            "gateware": ("spi0", 0x000000),
            "bootloader": ("spi1", 0x000000),
            "storage": ("spi1", 0x040000),
            "firmware": ("spi1", 0x050000),
        },
        "kc705": {
            "programmer":
            partial(ProgrammerXC7,
                    board="kc705",
                    proxy="bscan_spi_xc7k325t.bit"),
            "gateware": ("spi0", 0x000000),
            "bootloader": ("spi0", 0xaf0000),
            "storage": ("spi0", 0xb30000),
            "firmware": ("spi0", 0xb40000),
        },
    }[args.target]

    if not args.action:
        if args.target == "sayma":
            args.action = "gateware rtm_gateware bootloader firmware start".split(
            )
        else:
            args.action = "gateware bootloader firmware start".split()
    needs_artifacts = any(action in args.action for action in [
        "gateware", "rtm_gateware", "bootloader", "firmware", "load",
        "rtm_load"
    ])
    if needs_artifacts and args.dir is None:
        raise ValueError(
            "the directory containing the binaries need to be specified using -d."
        )

    binary_dir = args.dir
    if binary_dir is not None:
        rtm_binary_dir = os.path.join(binary_dir, "rtm")
    else:
        rtm_binary_dir = None

    if args.host is None:
        client = LocalClient()
    else:
        client = SSHClient(args.host, args.jump)

    if args.target == "sayma" and args.no_rtm_jtag:
        programmer_cls = ProgrammerAMC
    else:
        programmer_cls = config["programmer"]
    programmer = programmer_cls(client, preinit_script=args.preinit_command)

    def artifact_path(this_binary_dir, *path_filename):
        if args.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, header=False):
        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:
            if header:
                bin_file.write(b"\x00" * 8)
            bit2bin(bit_file, bin_file)
            if header:
                magic = 0x5352544d  # "SRTM", see sayma_rtm target
                length = bin_file.tell() - 8
                bin_file.seek(0)
                bin_file.write(magic.to_bytes(4, byteorder="little"))
                bin_file.write(length.to_bytes(4, byteorder="little"))
        atexit.register(lambda: os.unlink(bin_filename))
        return bin_filename

    for action in args.action:
        if action == "gateware":
            gateware_bin = convert_gateware(
                artifact_path(binary_dir, "gateware", "top.bit"))
            programmer.write_binary(*config["gateware"], gateware_bin)
        elif action == "rtm_gateware":
            rtm_gateware_bin = convert_gateware(artifact_path(
                rtm_binary_dir, "gateware", "top.bit"),
                                                header=True)
            programmer.write_binary(*config["rtm_gateware"], rtm_gateware_bin)
        elif action == "bootloader":
            bootloader_bin = artifact_path(binary_dir, "software",
                                           "bootloader", "bootloader.bin")
            programmer.write_binary(*config["bootloader"], bootloader_bin)
        elif action == "storage":
            storage_img = args.storage
            programmer.write_binary(*config["storage"], storage_img)
        elif action == "firmware":
            firmware_fbis = []
            for firmware in "satman", "runtime":
                filename = artifact_path(binary_dir, "software", firmware,
                                         firmware + ".fbi")
                if os.path.exists(filename):
                    firmware_fbis.append(filename)
            if not firmware_fbis:
                raise FileNotFoundError("no firmware found")
            if len(firmware_fbis) > 1:
                raise ValueError(
                    "more than one firmware file, please clean up your build directory. "
                    "Found firmware files: {}".format(" ".join(firmware_fbis)))
            programmer.write_binary(*config["firmware"], firmware_fbis[0])
        elif action == "load":
            if args.target == "sayma":
                gateware_bit = artifact_path(binary_dir, "gateware", "top.bit")
                programmer.load(gateware_bit, 1)
            else:
                gateware_bit = artifact_path(binary_dir, "gateware", "top.bit")
                programmer.load(gateware_bit, 0)
        elif action == "rtm_load":
            rtm_gateware_bit = artifact_path(rtm_binary_dir, "gateware",
                                             "top.bit")
            programmer.load(rtm_gateware_bit, 0)
        elif action == "start":
            programmer.start()
        elif action == "erase":
            if args.target == "sayma" or args.target == "metlino":
                programmer.erase_flash("spi0")
                programmer.erase_flash("spi1")
            else:
                programmer.erase_flash("spi0")
        else:
            raise ValueError("invalid action", action)

    if args.dry_run:
        print("\n".join(programmer.script()))
    else:
        programmer.run()
Beispiel #6
0
def main():
    args = get_argparser().parse_args()
    init_logger(args)

    config = {
        "kc705": {
            "programmer":
            partial(ProgrammerXC7,
                    board="kc705",
                    proxy="bscan_spi_xc7k325t.bit"),
            "variants": ["nist_clock", "nist_qc2"],
            "gateware": ("spi0", 0x000000),
            "bootloader": ("spi0", 0xaf0000),
            "storage": ("spi0", 0xb30000),
            "firmware": ("spi0", 0xb40000),
        },
        "kasli": {
            "programmer":
            partial(ProgrammerXC7,
                    board="kasli",
                    proxy="bscan_spi_xc7a100t.bit"),
            "variants": ["opticlock", "master", "satellite"],
            "gateware": ("spi0", 0x000000),
            "bootloader": ("spi0", 0x400000),
            "storage": ("spi0", 0x440000),
            "firmware": ("spi0", 0x450000),
        },
        "sayma": {
            "programmer": ProgrammerSayma,
            "variants": ["standalone", "master", "satellite"],
            "gateware": ("spi0", 0x000000),
            "bootloader": ("spi1", 0x000000),
            "storage": ("spi1", 0x040000),
            "firmware": ("spi1", 0x050000),
        },
    }[args.target]

    variant = args.variant
    if "variants" in config:
        if variant is not None and variant not in config["variants"]:
            raise SystemExit("Invalid variant for this board")
        if variant is None:
            variant = config["variants"][0]

    bin_dir = args.dir
    if bin_dir is None:
        bin_name = args.target
        if variant:
            bin_name += "-" + variant
        bin_dir = os.path.join(artiq_dir, "binaries", bin_name)

    if args.host is None:
        client = LocalClient()
    else:
        client = SSHClient(args.host)

    programmer = config["programmer"](client,
                                      preinit_script=args.preinit_command)

    def artifact_path(*path_filename):
        if args.srcbuild is None:
            *path, filename = path_filename
            return os.path.join(bin_dir, filename)
        else:
            return os.path.join(args.srcbuild, *path_filename)

    try:
        for action in args.action:
            if action == "gateware":
                gateware_bin = artifact_path("gateware", "top.bin")
                if not os.access(gateware_bin, os.R_OK):
                    bin_handle, gateware_bin = tempfile.mkstemp()
                    gateware_bit = artifact_path("gateware", "top.bit")
                    with open(gateware_bit,
                              "rb") as bit_file, open(bin_handle,
                                                      "wb") as bin_file:
                        bit2bin(bit_file, bin_file)
                    atexit.register(lambda: os.unlink(gateware_bin))

                programmer.write_binary(*config["gateware"], gateware_bin)
            elif action == "bootloader":
                bootloader_bin = artifact_path("software", "bootloader",
                                               "bootloader.bin")
                programmer.write_binary(*config["bootloader"], bootloader_bin)
            elif action == "storage":
                storage_img = args.storage
                programmer.write_binary(*config["storage"], storage_img)
            elif action == "firmware":
                if variant == "satellite":
                    firmware = "satman"
                else:
                    firmware = "runtime"

                firmware_fbi = artifact_path("software", firmware,
                                             firmware + ".fbi")
                programmer.write_binary(*config["firmware"], firmware_fbi)
            elif action == "load":
                if args.target == "sayma":
                    rtm_gateware_bit = artifact_path("rtm_gateware", "rtm.bit")
                    programmer.load(rtm_gateware_bit, 0)
                    gateware_bit = artifact_path("gateware", "top.bit")
                    programmer.load(gateware_bit, 1)
                else:
                    gateware_bit = artifact_path("gateware", "top.bit")
                    programmer.load(gateware_bit, 0)
            elif action == "start":
                programmer.start()
            else:
                raise ValueError("invalid action", action)
    except FileNotFoundError as e:
        raise SystemExit(e)

    if args.dry_run:
        print("\n".join(programmer.script()))
    else:
        programmer.run()