-
Notifications
You must be signed in to change notification settings - Fork 201
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
whitequark
committed
Nov 10, 2016
1 parent
0e76cbc
commit 3b6cbb1
Showing
2 changed files
with
146 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,144 @@ | ||
#!/usr/bin/env python3.5 | ||
|
||
# This script makes the following assumptions: | ||
# * miniconda is installed remotely at ~/miniconda | ||
# * misoc and artiq are installed remotely via conda | ||
|
||
import sys | ||
import argparse | ||
import subprocess | ||
import socket | ||
import select | ||
import threading | ||
import paramiko | ||
|
||
from artiq.tools import verbosity_args, init_logger, logger | ||
from random import Random | ||
|
||
|
||
def get_argparser(): | ||
parser = argparse.ArgumentParser(description="ARTIQ core device " | ||
"development tool") | ||
|
||
verbosity_args(parser) | ||
|
||
parser.add_argument("--host", nargs=1, metavar="HOST", | ||
type=str, default="lab.m-labs.hk", | ||
help="SSH host where the development board is located") | ||
parser.add_argument("--serial", nargs=1, metavar="SERIAL", | ||
type=str, default="/dev/ttyUSB0", | ||
help="TTY device corresponding to the development board") | ||
parser.add_argument("--ip", nargs=1, metavar="IP", | ||
type=str, default="kc705.lab.m-labs.hk", | ||
help="IP address corresponding to the development board") | ||
|
||
parser.add_argument("actions", metavar="ACTION", | ||
type=str, default=[], nargs="+", | ||
help="actions to perform (sequence of: build boot connect)") | ||
|
||
return parser | ||
|
||
|
||
def main(): | ||
args = get_argparser().parse_args() | ||
init_logger(args) | ||
|
||
ssh = None | ||
def get_ssh(): | ||
nonlocal ssh | ||
if ssh is not None: | ||
return ssh | ||
ssh = paramiko.SSHClient() | ||
ssh.load_system_host_keys() | ||
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) | ||
ssh.connect(args.host) | ||
return ssh | ||
|
||
sftp = None | ||
def get_sftp(): | ||
nonlocal sftp | ||
if sftp is not None: | ||
return sftp | ||
sftp = get_ssh().open_sftp() | ||
return sftp | ||
|
||
rng = Random() | ||
tmp = "artiq" + "".join([rng.choice("ABCDEFGHIJKLMNOPQRSTUVWXYZ") for _ in range(6)]) | ||
env = "bash -c 'export PATH=$HOME/miniconda/bin:$PATH; exec $0 $*' " | ||
|
||
def run_command(cmd): | ||
logger.info("Executing {}".format(cmd)) | ||
chan = get_ssh().get_transport().open_session() | ||
chan.set_combine_stderr(True) | ||
chan.exec_command(cmd.format(tmp=tmp, env=env, serial=args.serial, ip=args.ip)) | ||
return chan.makefile() | ||
|
||
def drain(chan): | ||
while True: | ||
char = chan.read(1) | ||
if char == b"": | ||
break | ||
sys.stderr.write(char.decode("utf-8")) | ||
|
||
for action in args.actions: | ||
if action == "build": | ||
logger.info("Building runtime") | ||
subprocess.call(["python3", "-m", "artiq.gateware.targets.kc705", | ||
"-H", "nist_clock", | ||
"--no-compile-gateware", | ||
"--output-dir", "/tmp/kc705"]) | ||
|
||
elif action == "boot": | ||
logger.info("Uploading runtime") | ||
get_sftp().mkdir("/tmp/{tmp}".format(tmp=tmp)) | ||
get_sftp().put("/tmp/kc705/software/runtime/runtime.bin", | ||
"/tmp/{tmp}/runtime.bin".format(tmp=tmp)) | ||
|
||
logger.info("Booting runtime") | ||
flterm = run_command( | ||
"{env} python3 flterm.py {serial} " + | ||
"--kernel /tmp/{tmp}/runtime.bin --upload-only") | ||
artiq_flash = run_command( | ||
"{env} artiq_flash start") | ||
drain(flterm) | ||
|
||
elif action == "connect": | ||
def forwarder(port): | ||
listener = socket.socket() | ||
listener.bind(('localhost', port)) | ||
listener.listen(1) | ||
while True: | ||
local_stream, peer_addr = listener.accept() | ||
logger.info("Accepting %s:%s and opening SSH channel to %s:%s", | ||
*peer_addr, args.ip, port) | ||
remote_stream = get_ssh().get_transport() \ | ||
.open_channel('direct-tcpip', (args.ip, port), peer_addr) | ||
while True: | ||
r, w, x = select.select([local_stream, remote_stream], [], []) | ||
if local_stream in r: | ||
data = local_stream.recv(1024) | ||
if data == b"": | ||
break | ||
remote_stream.send(data) | ||
if remote_stream in r: | ||
data = remote_stream.recv(1024) | ||
if data == b"": | ||
break | ||
local_stream.send(data) | ||
|
||
for port in (1381, 1382): | ||
thread = threading.Thread(target=forwarder, args=(port,), | ||
name="port-{}".format(port), daemon=True) | ||
thread.start() | ||
|
||
logger.info("Connecting to device") | ||
flterm = run_command( | ||
"{env} python3 flterm.py {serial} --output-only") | ||
drain(flterm) | ||
|
||
else: | ||
logger.error("Unknown action {}".format(action)) | ||
sys.exit(1) | ||
|
||
if __name__ == "__main__": | ||
main() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters