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 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)
|
||||
|
||||
|
@ -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))
|
||||
|
@ -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",
|
||||
|
@ -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())
|
||||
|
||||
|
||||
|
@ -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])
|
||||
]
|
||||
|
16
examples/master/repository/handover.py
Normal file
16
examples/master/repository/handover.py
Normal 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()
|
@ -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"),
|
||||
|
@ -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();
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user