forked from M-Labs/artiq
support kernel handover with coherent time
This commit is contained in:
parent
cb65b1e322
commit
4048568d8e
|
@ -3,7 +3,6 @@ import logging
|
||||||
from enum import Enum
|
from enum import Enum
|
||||||
from fractions import Fraction
|
from fractions import Fraction
|
||||||
|
|
||||||
from artiq.coredevice.runtime import Environment
|
|
||||||
from artiq.coredevice import runtime_exceptions
|
from artiq.coredevice import runtime_exceptions
|
||||||
from artiq.language import core as core_language
|
from artiq.language import core as core_language
|
||||||
from artiq.coredevice.rpc_wrapper import RPCWrapper
|
from artiq.coredevice.rpc_wrapper import RPCWrapper
|
||||||
|
@ -89,7 +88,7 @@ class CommGeneric:
|
||||||
logger.debug("sending message: type=%r length=%d", ty, length)
|
logger.debug("sending message: type=%r length=%d", ty, length)
|
||||||
self.write(struct.pack(">llB", 0x5a5a5a5a, length, ty.value))
|
self.write(struct.pack(">llB", 0x5a5a5a5a, length, ty.value))
|
||||||
|
|
||||||
def get_runtime_env(self):
|
def check_ident(self):
|
||||||
self._write_header(9, _H2DMsgType.IDENT_REQUEST)
|
self._write_header(9, _H2DMsgType.IDENT_REQUEST)
|
||||||
_, ty = self._read_header()
|
_, ty = self._read_header()
|
||||||
if ty != _D2HMsgType.IDENT_REPLY:
|
if ty != _D2HMsgType.IDENT_REPLY:
|
||||||
|
@ -102,7 +101,6 @@ class CommGeneric:
|
||||||
if runtime_id != "AROR":
|
if runtime_id != "AROR":
|
||||||
raise UnsupportedDevice("Unsupported runtime ID: {}"
|
raise UnsupportedDevice("Unsupported runtime ID: {}"
|
||||||
.format(runtime_id))
|
.format(runtime_id))
|
||||||
return Environment()
|
|
||||||
|
|
||||||
def switch_clock(self, external):
|
def switch_clock(self, external):
|
||||||
self._write_header(10, _H2DMsgType.SWITCH_CLOCK)
|
self._write_header(10, _H2DMsgType.SWITCH_CLOCK)
|
||||||
|
@ -118,8 +116,9 @@ class CommGeneric:
|
||||||
if ty != _D2HMsgType.LOAD_COMPLETED:
|
if ty != _D2HMsgType.LOAD_COMPLETED:
|
||||||
raise IOError("Incorrect reply from device: "+str(ty))
|
raise IOError("Incorrect reply from device: "+str(ty))
|
||||||
|
|
||||||
def run(self, kname):
|
def run(self, kname, reset_now):
|
||||||
self._write_header(len(kname) + 9, _H2DMsgType.RUN_KERNEL)
|
self._write_header(len(kname) + 10, _H2DMsgType.RUN_KERNEL)
|
||||||
|
self.write(struct.pack("B", reset_now))
|
||||||
self.write(bytes(kname, "ascii"))
|
self.write(bytes(kname, "ascii"))
|
||||||
logger.debug("running kernel: %s", kname)
|
logger.debug("running kernel: %s", kname)
|
||||||
|
|
||||||
|
|
|
@ -15,6 +15,8 @@ from artiq.transforms.interleave import interleave
|
||||||
from artiq.transforms.lower_time import lower_time
|
from artiq.transforms.lower_time import lower_time
|
||||||
from artiq.transforms.unparse import unparse
|
from artiq.transforms.unparse import unparse
|
||||||
|
|
||||||
|
from artiq.coredevice.runtime import Environment
|
||||||
|
|
||||||
from artiq.py2llvm import get_runtime_binary
|
from artiq.py2llvm import get_runtime_binary
|
||||||
|
|
||||||
|
|
||||||
|
@ -52,12 +54,10 @@ class Core(AutoDB):
|
||||||
external_clock = Argument(False)
|
external_clock = Argument(False)
|
||||||
|
|
||||||
def build(self):
|
def build(self):
|
||||||
self.runtime_env = self.comm.get_runtime_env()
|
self.first_run = True
|
||||||
self.core = self
|
self.core = self
|
||||||
self.comm.core = self
|
self.comm.core = self
|
||||||
|
self.runtime_env = Environment()
|
||||||
self.comm.switch_clock(self.external_clock)
|
|
||||||
self.initial_time = int64(self.runtime_env.warmup_time/self.ref_period)
|
|
||||||
|
|
||||||
def transform_stack(self, func_def, rpc_map, exception_map,
|
def transform_stack(self, func_def, rpc_map, exception_map,
|
||||||
debug_unparse=_no_debug_unparse):
|
debug_unparse=_no_debug_unparse):
|
||||||
|
@ -79,7 +79,7 @@ class Core(AutoDB):
|
||||||
interleave(func_def)
|
interleave(func_def)
|
||||||
debug_unparse("interleave", func_def)
|
debug_unparse("interleave", func_def)
|
||||||
|
|
||||||
lower_time(func_def, self.initial_time)
|
lower_time(func_def)
|
||||||
debug_unparse("lower_time", func_def)
|
debug_unparse("lower_time", func_def)
|
||||||
|
|
||||||
remove_inter_assigns(func_def)
|
remove_inter_assigns(func_def)
|
||||||
|
@ -113,11 +113,16 @@ class Core(AutoDB):
|
||||||
return binary, rpc_map, exception_map
|
return binary, rpc_map, exception_map
|
||||||
|
|
||||||
def run(self, k_function, k_args, k_kwargs):
|
def run(self, k_function, k_args, k_kwargs):
|
||||||
|
if self.first_run:
|
||||||
|
self.comm.check_ident()
|
||||||
|
self.comm.switch_clock(self.external_clock)
|
||||||
|
|
||||||
binary, rpc_map, exception_map = self.compile(
|
binary, rpc_map, exception_map = self.compile(
|
||||||
k_function, k_args, k_kwargs)
|
k_function, k_args, k_kwargs)
|
||||||
self.comm.load(binary)
|
self.comm.load(binary)
|
||||||
self.comm.run(k_function.__name__)
|
self.comm.run(k_function.__name__, self.first_run)
|
||||||
self.comm.serve(rpc_map, exception_map)
|
self.comm.serve(rpc_map, exception_map)
|
||||||
|
self.first_run = False
|
||||||
|
|
||||||
@kernel
|
@kernel
|
||||||
def get_rtio_time(self):
|
def get_rtio_time(self):
|
||||||
|
@ -125,5 +130,5 @@ class Core(AutoDB):
|
||||||
|
|
||||||
@kernel
|
@kernel
|
||||||
def recover_underflow(self):
|
def recover_underflow(self):
|
||||||
t = syscall("rtio_get_counter") + self.initial_time
|
t = syscall("rtio_get_counter") + 125000
|
||||||
at(cycles_to_time(t))
|
at(cycles_to_time(t))
|
||||||
|
|
|
@ -12,6 +12,8 @@ llvm.initialize_all_targets()
|
||||||
llvm.initialize_all_asmprinters()
|
llvm.initialize_all_asmprinters()
|
||||||
|
|
||||||
_syscalls = {
|
_syscalls = {
|
||||||
|
"now_init": "n:I",
|
||||||
|
"now_save": "I:n",
|
||||||
"watchdog_set": "i:i",
|
"watchdog_set": "i:i",
|
||||||
"watchdog_clear": "i:n",
|
"watchdog_clear": "i:n",
|
||||||
"rtio_set_o": "Iib:n",
|
"rtio_set_o": "Iib:n",
|
||||||
|
|
|
@ -27,7 +27,7 @@ class ELFRunner(Experiment, AutoDB):
|
||||||
def run(self):
|
def run(self):
|
||||||
with open(self.file, "rb") as f:
|
with open(self.file, "rb") as f:
|
||||||
self.core.comm.load(f.read())
|
self.core.comm.load(f.read())
|
||||||
self.core.comm.run("run")
|
self.core.comm.run("run", False)
|
||||||
self.core.comm.serve(dict(), dict())
|
self.core.comm.serve(dict(), dict())
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -14,9 +14,6 @@ output function.
|
||||||
|
|
||||||
import ast
|
import ast
|
||||||
|
|
||||||
from artiq.transforms.tools import value_to_ast
|
|
||||||
from artiq.language.core import int64
|
|
||||||
|
|
||||||
|
|
||||||
class _TimeLowerer(ast.NodeTransformer):
|
class _TimeLowerer(ast.NodeTransformer):
|
||||||
def visit_Call(self, node):
|
def visit_Call(self, node):
|
||||||
|
@ -45,9 +42,23 @@ class _TimeLowerer(ast.NodeTransformer):
|
||||||
return r
|
return r
|
||||||
|
|
||||||
|
|
||||||
def lower_time(func_def, initial_time):
|
def lower_time(func_def):
|
||||||
_TimeLowerer().visit(func_def)
|
_TimeLowerer().visit(func_def)
|
||||||
func_def.body.insert(0, ast.copy_location(
|
call_init = ast.Call(
|
||||||
ast.Assign(targets=[ast.Name("now", ast.Store())],
|
func=ast.Name("syscall", ast.Load()),
|
||||||
value=value_to_ast(int64(initial_time))),
|
args=[ast.Str("now_init")],
|
||||||
func_def))
|
keywords=[], starargs=None, kwargs=None)
|
||||||
|
stmt_init = ast.Assign(targets=[ast.Name("now", ast.Store())],
|
||||||
|
value=call_init)
|
||||||
|
call_save = ast.Call(
|
||||||
|
func=ast.Name("syscall", ast.Load()),
|
||||||
|
args=[ast.Str("now_save"), ast.Name("now", ast.Load())],
|
||||||
|
keywords=[], starargs=None, kwargs=None)
|
||||||
|
stmt_save = ast.Expr(call_save)
|
||||||
|
func_def.body = [
|
||||||
|
stmt_init,
|
||||||
|
ast.Try(body=func_def.body,
|
||||||
|
handlers=[],
|
||||||
|
orelse=[],
|
||||||
|
finalbody=[stmt_save])
|
||||||
|
]
|
||||||
|
|
|
@ -0,0 +1,16 @@
|
||||||
|
from artiq import *
|
||||||
|
|
||||||
|
|
||||||
|
class Handover(Experiment, AutoDB):
|
||||||
|
class DBKeys:
|
||||||
|
core = Device()
|
||||||
|
led = Device()
|
||||||
|
|
||||||
|
@kernel
|
||||||
|
def blink_once(self):
|
||||||
|
self.led.pulse(250*ms)
|
||||||
|
delay(250*ms)
|
||||||
|
|
||||||
|
def run(self):
|
||||||
|
while True:
|
||||||
|
self.blink_once()
|
|
@ -7,6 +7,8 @@ from elftools.elf.elffile import ELFFile
|
||||||
|
|
||||||
services = [
|
services = [
|
||||||
("syscalls", [
|
("syscalls", [
|
||||||
|
("now_init", "now_init"),
|
||||||
|
("now_save", "now_save"),
|
||||||
("rpc", "rpc"),
|
("rpc", "rpc"),
|
||||||
("watchdog_set", "watchdog_set"),
|
("watchdog_set", "watchdog_set"),
|
||||||
("watchdog_clear", "watchdog_clear"),
|
("watchdog_clear", "watchdog_clear"),
|
||||||
|
|
|
@ -18,12 +18,12 @@ void exception_handler(unsigned long vect, unsigned long *sp);
|
||||||
void exception_handler(unsigned long vect, unsigned long *sp)
|
void exception_handler(unsigned long vect, unsigned long *sp)
|
||||||
{
|
{
|
||||||
struct msg_exception msg;
|
struct msg_exception msg;
|
||||||
int i;
|
|
||||||
|
|
||||||
msg.type = MESSAGE_TYPE_EXCEPTION;
|
msg.type = MESSAGE_TYPE_EXCEPTION;
|
||||||
msg.eid = EID_INTERNAL_ERROR;
|
msg.eid = EID_INTERNAL_ERROR;
|
||||||
for(i=0;i<3;i++)
|
msg.eparams[0] = 256;
|
||||||
msg.eparams[i] = 0;
|
msg.eparams[1] = 256;
|
||||||
|
msg.eparams[2] = 256;
|
||||||
mailbox_send_and_wait(&msg);
|
mailbox_send_and_wait(&msg);
|
||||||
while(1);
|
while(1);
|
||||||
}
|
}
|
||||||
|
@ -51,8 +51,6 @@ int main(void)
|
||||||
} else {
|
} else {
|
||||||
struct msg_base msg;
|
struct msg_base msg;
|
||||||
|
|
||||||
dds_init();
|
|
||||||
rtio_init();
|
|
||||||
k();
|
k();
|
||||||
exception_pop(1);
|
exception_pop(1);
|
||||||
|
|
||||||
|
@ -63,6 +61,41 @@ int main(void)
|
||||||
while(1);
|
while(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
long long int now_init(void);
|
||||||
|
long long int now_init(void)
|
||||||
|
{
|
||||||
|
struct msg_base request;
|
||||||
|
struct msg_now_init_reply *reply;
|
||||||
|
long long int now;
|
||||||
|
|
||||||
|
request.type = MESSAGE_TYPE_NOW_INIT_REQUEST;
|
||||||
|
mailbox_send_and_wait(&request);
|
||||||
|
|
||||||
|
reply = mailbox_wait_and_receive();
|
||||||
|
if(reply->type != MESSAGE_TYPE_NOW_INIT_REPLY)
|
||||||
|
exception_raise_params(EID_INTERNAL_ERROR, 1, 0, 0);
|
||||||
|
now = reply->now;
|
||||||
|
mailbox_acknowledge();
|
||||||
|
|
||||||
|
if(now < 0) {
|
||||||
|
dds_init();
|
||||||
|
rtio_init();
|
||||||
|
now = 125000;
|
||||||
|
}
|
||||||
|
|
||||||
|
return now;
|
||||||
|
}
|
||||||
|
|
||||||
|
void now_save(long long int now);
|
||||||
|
void now_save(long long int now)
|
||||||
|
{
|
||||||
|
struct msg_now_save request;
|
||||||
|
|
||||||
|
request.type = MESSAGE_TYPE_NOW_SAVE;
|
||||||
|
request.now = now;
|
||||||
|
mailbox_send_and_wait(&request);
|
||||||
|
}
|
||||||
|
|
||||||
int watchdog_set(int ms)
|
int watchdog_set(int ms)
|
||||||
{
|
{
|
||||||
struct msg_watchdog_set_request request;
|
struct msg_watchdog_set_request request;
|
||||||
|
@ -75,7 +108,7 @@ int watchdog_set(int ms)
|
||||||
|
|
||||||
reply = mailbox_wait_and_receive();
|
reply = mailbox_wait_and_receive();
|
||||||
if(reply->type != MESSAGE_TYPE_WATCHDOG_SET_REPLY)
|
if(reply->type != MESSAGE_TYPE_WATCHDOG_SET_REPLY)
|
||||||
exception_raise(EID_INTERNAL_ERROR);
|
exception_raise_params(EID_INTERNAL_ERROR, 2, 0, 0);
|
||||||
id = reply->id;
|
id = reply->id;
|
||||||
mailbox_acknowledge();
|
mailbox_acknowledge();
|
||||||
|
|
||||||
|
@ -105,7 +138,7 @@ int rpc(int rpc_num, ...)
|
||||||
|
|
||||||
reply = mailbox_wait_and_receive();
|
reply = mailbox_wait_and_receive();
|
||||||
if(reply->type != MESSAGE_TYPE_RPC_REPLY)
|
if(reply->type != MESSAGE_TYPE_RPC_REPLY)
|
||||||
exception_raise(EID_INTERNAL_ERROR);
|
exception_raise_params(EID_INTERNAL_ERROR, 3, 0, 0);
|
||||||
eid = reply->eid;
|
eid = reply->eid;
|
||||||
retval = reply->retval;
|
retval = reply->retval;
|
||||||
mailbox_acknowledge();
|
mailbox_acknowledge();
|
||||||
|
|
|
@ -4,6 +4,9 @@
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
|
MESSAGE_TYPE_NOW_INIT_REQUEST,
|
||||||
|
MESSAGE_TYPE_NOW_INIT_REPLY,
|
||||||
|
MESSAGE_TYPE_NOW_SAVE,
|
||||||
MESSAGE_TYPE_FINISHED,
|
MESSAGE_TYPE_FINISHED,
|
||||||
MESSAGE_TYPE_EXCEPTION,
|
MESSAGE_TYPE_EXCEPTION,
|
||||||
MESSAGE_TYPE_WATCHDOG_SET_REQUEST,
|
MESSAGE_TYPE_WATCHDOG_SET_REQUEST,
|
||||||
|
@ -30,6 +33,16 @@ struct msg_base {
|
||||||
|
|
||||||
/* kernel messages */
|
/* kernel messages */
|
||||||
|
|
||||||
|
struct msg_now_init_reply {
|
||||||
|
int type;
|
||||||
|
long long int now;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct msg_now_save {
|
||||||
|
int type;
|
||||||
|
long long int now;
|
||||||
|
};
|
||||||
|
|
||||||
struct msg_exception {
|
struct msg_exception {
|
||||||
int type;
|
int type;
|
||||||
int eid;
|
int eid;
|
||||||
|
|
|
@ -54,6 +54,7 @@ static void submit_output(int len)
|
||||||
}
|
}
|
||||||
|
|
||||||
static int user_kernel_state;
|
static int user_kernel_state;
|
||||||
|
static long long int now;
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
USER_KERNEL_NONE = 0,
|
USER_KERNEL_NONE = 0,
|
||||||
|
@ -167,7 +168,10 @@ static int process_input(void)
|
||||||
}
|
}
|
||||||
buffer_in[buffer_in_index] = 0;
|
buffer_in[buffer_in_index] = 0;
|
||||||
|
|
||||||
k = kloader_find((char *)&buffer_in[9]);
|
if(buffer_in[9])
|
||||||
|
now = -1;
|
||||||
|
|
||||||
|
k = kloader_find((char *)&buffer_in[10]);
|
||||||
if(k == NULL) {
|
if(k == NULL) {
|
||||||
log("Failed to find kernel entry point '%s' in object", &buffer_in[9]);
|
log("Failed to find kernel entry point '%s' in object", &buffer_in[9]);
|
||||||
buffer_out[8] = REMOTEMSG_TYPE_KERNEL_STARTUP_FAILED;
|
buffer_out[8] = REMOTEMSG_TYPE_KERNEL_STARTUP_FAILED;
|
||||||
|
@ -394,6 +398,21 @@ static int process_kmsg(struct msg_base *umsg)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
switch(umsg->type) {
|
switch(umsg->type) {
|
||||||
|
case MESSAGE_TYPE_NOW_INIT_REQUEST: {
|
||||||
|
struct msg_now_init_reply reply;
|
||||||
|
|
||||||
|
reply.type = MESSAGE_TYPE_NOW_INIT_REPLY;
|
||||||
|
reply.now = now;
|
||||||
|
mailbox_send_and_wait(&reply);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case MESSAGE_TYPE_NOW_SAVE: {
|
||||||
|
struct msg_now_save *msg = (struct msg_now_save *)umsg;
|
||||||
|
|
||||||
|
now = msg->now;
|
||||||
|
mailbox_acknowledge();
|
||||||
|
break;
|
||||||
|
}
|
||||||
case MESSAGE_TYPE_FINISHED:
|
case MESSAGE_TYPE_FINISHED:
|
||||||
buffer_out[8] = REMOTEMSG_TYPE_KERNEL_FINISHED;
|
buffer_out[8] = REMOTEMSG_TYPE_KERNEL_FINISHED;
|
||||||
submit_output(9);
|
submit_output(9);
|
||||||
|
|
Loading…
Reference in New Issue