support kernel handover with coherent time

This commit is contained in:
Sebastien Bourdeauducq 2015-05-02 23:41:49 +08:00
parent cb65b1e322
commit 4048568d8e
10 changed files with 129 additions and 29 deletions

View File

@ -3,7 +3,6 @@ import logging
from enum import Enum
from fractions import Fraction
from artiq.coredevice.runtime import Environment
from artiq.coredevice import runtime_exceptions
from artiq.language import core as core_language
from artiq.coredevice.rpc_wrapper import RPCWrapper
@ -89,7 +88,7 @@ class CommGeneric:
logger.debug("sending message: type=%r length=%d", ty, length)
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)
_, ty = self._read_header()
if ty != _D2HMsgType.IDENT_REPLY:
@ -102,7 +101,6 @@ class CommGeneric:
if runtime_id != "AROR":
raise UnsupportedDevice("Unsupported runtime ID: {}"
.format(runtime_id))
return Environment()
def switch_clock(self, external):
self._write_header(10, _H2DMsgType.SWITCH_CLOCK)
@ -118,8 +116,9 @@ class CommGeneric:
if ty != _D2HMsgType.LOAD_COMPLETED:
raise IOError("Incorrect reply from device: "+str(ty))
def run(self, kname):
self._write_header(len(kname) + 9, _H2DMsgType.RUN_KERNEL)
def run(self, kname, reset_now):
self._write_header(len(kname) + 10, _H2DMsgType.RUN_KERNEL)
self.write(struct.pack("B", reset_now))
self.write(bytes(kname, "ascii"))
logger.debug("running kernel: %s", kname)

View File

@ -15,6 +15,8 @@ from artiq.transforms.interleave import interleave
from artiq.transforms.lower_time import lower_time
from artiq.transforms.unparse import unparse
from artiq.coredevice.runtime import Environment
from artiq.py2llvm import get_runtime_binary
@ -52,12 +54,10 @@ class Core(AutoDB):
external_clock = Argument(False)
def build(self):
self.runtime_env = self.comm.get_runtime_env()
self.first_run = True
self.core = self
self.comm.core = self
self.comm.switch_clock(self.external_clock)
self.initial_time = int64(self.runtime_env.warmup_time/self.ref_period)
self.runtime_env = Environment()
def transform_stack(self, func_def, rpc_map, exception_map,
debug_unparse=_no_debug_unparse):
@ -79,7 +79,7 @@ class Core(AutoDB):
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)
remove_inter_assigns(func_def)
@ -113,11 +113,16 @@ class Core(AutoDB):
return binary, rpc_map, exception_map
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(
k_function, k_args, k_kwargs)
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.first_run = False
@kernel
def get_rtio_time(self):
@ -125,5 +130,5 @@ class Core(AutoDB):
@kernel
def recover_underflow(self):
t = syscall("rtio_get_counter") + self.initial_time
t = syscall("rtio_get_counter") + 125000
at(cycles_to_time(t))

View File

@ -12,6 +12,8 @@ llvm.initialize_all_targets()
llvm.initialize_all_asmprinters()
_syscalls = {
"now_init": "n:I",
"now_save": "I:n",
"watchdog_set": "i:i",
"watchdog_clear": "i:n",
"rtio_set_o": "Iib:n",

View File

@ -27,7 +27,7 @@ class ELFRunner(Experiment, AutoDB):
def run(self):
with open(self.file, "rb") as f:
self.core.comm.load(f.read())
self.core.comm.run("run")
self.core.comm.run("run", False)
self.core.comm.serve(dict(), dict())

View File

@ -14,9 +14,6 @@ output function.
import ast
from artiq.transforms.tools import value_to_ast
from artiq.language.core import int64
class _TimeLowerer(ast.NodeTransformer):
def visit_Call(self, node):
@ -45,9 +42,23 @@ class _TimeLowerer(ast.NodeTransformer):
return r
def lower_time(func_def, initial_time):
def lower_time(func_def):
_TimeLowerer().visit(func_def)
func_def.body.insert(0, ast.copy_location(
ast.Assign(targets=[ast.Name("now", ast.Store())],
value=value_to_ast(int64(initial_time))),
func_def))
call_init = ast.Call(
func=ast.Name("syscall", ast.Load()),
args=[ast.Str("now_init")],
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])
]

View File

@ -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()

View File

@ -7,6 +7,8 @@ from elftools.elf.elffile import ELFFile
services = [
("syscalls", [
("now_init", "now_init"),
("now_save", "now_save"),
("rpc", "rpc"),
("watchdog_set", "watchdog_set"),
("watchdog_clear", "watchdog_clear"),

View File

@ -18,12 +18,12 @@ void exception_handler(unsigned long vect, unsigned long *sp);
void exception_handler(unsigned long vect, unsigned long *sp)
{
struct msg_exception msg;
int i;
msg.type = MESSAGE_TYPE_EXCEPTION;
msg.eid = EID_INTERNAL_ERROR;
for(i=0;i<3;i++)
msg.eparams[i] = 0;
msg.eparams[0] = 256;
msg.eparams[1] = 256;
msg.eparams[2] = 256;
mailbox_send_and_wait(&msg);
while(1);
}
@ -51,8 +51,6 @@ int main(void)
} else {
struct msg_base msg;
dds_init();
rtio_init();
k();
exception_pop(1);
@ -63,6 +61,41 @@ int main(void)
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)
{
struct msg_watchdog_set_request request;
@ -75,7 +108,7 @@ int watchdog_set(int ms)
reply = mailbox_wait_and_receive();
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;
mailbox_acknowledge();
@ -105,7 +138,7 @@ int rpc(int rpc_num, ...)
reply = mailbox_wait_and_receive();
if(reply->type != MESSAGE_TYPE_RPC_REPLY)
exception_raise(EID_INTERNAL_ERROR);
exception_raise_params(EID_INTERNAL_ERROR, 3, 0, 0);
eid = reply->eid;
retval = reply->retval;
mailbox_acknowledge();

View File

@ -4,6 +4,9 @@
#include <stdarg.h>
enum {
MESSAGE_TYPE_NOW_INIT_REQUEST,
MESSAGE_TYPE_NOW_INIT_REPLY,
MESSAGE_TYPE_NOW_SAVE,
MESSAGE_TYPE_FINISHED,
MESSAGE_TYPE_EXCEPTION,
MESSAGE_TYPE_WATCHDOG_SET_REQUEST,
@ -30,6 +33,16 @@ struct msg_base {
/* 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 {
int type;
int eid;

View File

@ -54,6 +54,7 @@ static void submit_output(int len)
}
static int user_kernel_state;
static long long int now;
enum {
USER_KERNEL_NONE = 0,
@ -167,7 +168,10 @@ static int process_input(void)
}
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) {
log("Failed to find kernel entry point '%s' in object", &buffer_in[9]);
buffer_out[8] = REMOTEMSG_TYPE_KERNEL_STARTUP_FAILED;
@ -394,6 +398,21 @@ static int process_kmsg(struct msg_base *umsg)
return 0;
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:
buffer_out[8] = REMOTEMSG_TYPE_KERNEL_FINISHED;
submit_output(9);