diff --git a/artiq/coredevice/comm_generic.py b/artiq/coredevice/comm_generic.py index d8bf00b4b..afd57bcb8 100644 --- a/artiq/coredevice/comm_generic.py +++ b/artiq/coredevice/comm_generic.py @@ -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) diff --git a/artiq/coredevice/core.py b/artiq/coredevice/core.py index 9addf1b3c..043601f47 100644 --- a/artiq/coredevice/core.py +++ b/artiq/coredevice/core.py @@ -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)) diff --git a/artiq/coredevice/runtime.py b/artiq/coredevice/runtime.py index ff5e77e56..3d84decc8 100644 --- a/artiq/coredevice/runtime.py +++ b/artiq/coredevice/runtime.py @@ -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", diff --git a/artiq/frontend/artiq_run.py b/artiq/frontend/artiq_run.py index 308c15f53..9b499fb96 100755 --- a/artiq/frontend/artiq_run.py +++ b/artiq/frontend/artiq_run.py @@ -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()) diff --git a/artiq/transforms/lower_time.py b/artiq/transforms/lower_time.py index aa799de8e..c2c779b84 100644 --- a/artiq/transforms/lower_time.py +++ b/artiq/transforms/lower_time.py @@ -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]) + ] diff --git a/examples/master/repository/handover.py b/examples/master/repository/handover.py new file mode 100644 index 000000000..8974678a9 --- /dev/null +++ b/examples/master/repository/handover.py @@ -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() diff --git a/soc/runtime/gen_service_table.py b/soc/runtime/gen_service_table.py index 6d200757f..c4731be8f 100755 --- a/soc/runtime/gen_service_table.py +++ b/soc/runtime/gen_service_table.py @@ -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"), diff --git a/soc/runtime/ksupport.c b/soc/runtime/ksupport.c index 5330c54d8..964391341 100644 --- a/soc/runtime/ksupport.c +++ b/soc/runtime/ksupport.c @@ -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(); diff --git a/soc/runtime/messages.h b/soc/runtime/messages.h index 1f008150d..4a4e10737 100644 --- a/soc/runtime/messages.h +++ b/soc/runtime/messages.h @@ -4,6 +4,9 @@ #include 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; diff --git a/soc/runtime/session.c b/soc/runtime/session.c index 7f320aefe..bfcc6b823 100644 --- a/soc/runtime/session.c +++ b/soc/runtime/session.c @@ -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);