diff --git a/artiq/devices/core.py b/artiq/devices/core.py index 8630ef4d0..8635f75a6 100644 --- a/artiq/devices/core.py +++ b/artiq/devices/core.py @@ -70,4 +70,4 @@ class Core: binary = get_runtime_binary(self.runtime_env, func_def) self.core_com.load(binary) self.core_com.run(func_def.name) - self.core_com.serve(rpc_map) + self.core_com.serve(rpc_map, exception_map) diff --git a/artiq/devices/corecom_dummy.py b/artiq/devices/corecom_dummy.py index 003daba4b..306865da6 100644 --- a/artiq/devices/corecom_dummy.py +++ b/artiq/devices/corecom_dummy.py @@ -25,9 +25,14 @@ class CoreCom: def run(self, kname): print("RUN: "+kname) - def serve(self, rpc_map): + def serve(self, rpc_map, exception_map): print("================") print(" RPC map") print("================") for k, v in sorted(rpc_map.items(), key=itemgetter(0)): print(str(k)+" -> "+str(v)) + print("================") + print(" Exception map") + print("================") + for k, v in sorted(exception_map.items(), key=itemgetter(0)): + print(str(k)+" -> "+str(v)) diff --git a/artiq/devices/corecom_serial.py b/artiq/devices/corecom_serial.py index 86c2aea46..019c7803e 100644 --- a/artiq/devices/corecom_serial.py +++ b/artiq/devices/corecom_serial.py @@ -31,8 +31,9 @@ class _D2HMsgType(Enum): CRC_FAILED = 6 OBJECT_UNRECOGNIZED = 7 KERNEL_FINISHED = 8 - KERNEL_STARTUP_FAILED = 9 - RPC_REQUEST = 10 + KERNEL_EXCEPTION = 9 + KERNEL_STARTUP_FAILED = 10 + RPC_REQUEST = 11 def _write_exactly(f, data): @@ -141,12 +142,10 @@ class CoreCom: _write_exactly(self.port, struct.pack("b", ord(c))) logger.debug("running kernel: {}".format(kname)) - def serve(self, rpc_map): + def serve(self, rpc_map, exception_map): while True: msg = self._get_device_msg() - if msg == _D2HMsgType.KERNEL_FINISHED: - return - elif msg == _D2HMsgType.RPC_REQUEST: + if msg == _D2HMsgType.RPC_REQUEST: rpc_num, n_args = struct.unpack(">hb", _read_exactly(self.port, 3)) args = [] @@ -160,5 +159,11 @@ class CoreCom: _write_exactly(self.port, struct.pack(">l", r)) logger.debug("rpc service: {} ({}) == {}".format( rpc_num, args, r)) + elif msg == _D2HMsgType.KERNEL_EXCEPTION: + (exception_num, ) = struct.unpack(">l", + _read_exactly(self.port, 4)) + raise exception_map[exception_num] + elif msg == _D2HMsgType.KERNEL_FINISHED: + return else: raise IOError("Incorrect request from device: "+str(msg)) diff --git a/soc/runtime/corecom.h b/soc/runtime/corecom.h index 1bc552bba..fe5a67439 100644 --- a/soc/runtime/corecom.h +++ b/soc/runtime/corecom.h @@ -1,8 +1,14 @@ #ifndef __CORECOM_H #define __CORECOM_H +enum { + KERNEL_RUN_FINISHED, + KERNEL_RUN_EXCEPTION, + KERNEL_RUN_STARTUP_FAILED +}; + typedef int (*object_loader)(void *, int); -typedef int (*kernel_runner)(const char *); +typedef int (*kernel_runner)(const char *, int *); void corecom_serve(object_loader load_object, kernel_runner run_kernel); int corecom_rpc(int rpc_num, int n_args, ...); diff --git a/soc/runtime/corecom_serial.c b/soc/runtime/corecom_serial.c index b1457f6e0..fdb445a8d 100644 --- a/soc/runtime/corecom_serial.c +++ b/soc/runtime/corecom_serial.c @@ -25,6 +25,7 @@ enum { MSGTYPE_OBJECT_UNRECOGNIZED, MSGTYPE_KERNEL_FINISHED, + MSGTYPE_KERNEL_EXCEPTION, MSGTYPE_KERNEL_STARTUP_FAILED, MSGTYPE_RPC_REQUEST, @@ -114,7 +115,7 @@ static void receive_and_run_kernel(kernel_runner run_kernel) int length; int i; char kernel_name[256]; - int r; + int r, eid; length = receive_int(); if(length > (sizeof(kernel_name)-1)) { @@ -125,8 +126,22 @@ static void receive_and_run_kernel(kernel_runner run_kernel) kernel_name[i] = receive_char(); kernel_name[length] = 0; - r = run_kernel(kernel_name); - send_char(r ? MSGTYPE_KERNEL_FINISHED : MSGTYPE_KERNEL_STARTUP_FAILED); + r = run_kernel(kernel_name, &eid); + switch(r) { + case KERNEL_RUN_FINISHED: + send_char(MSGTYPE_KERNEL_FINISHED); + break; + case KERNEL_RUN_EXCEPTION: + send_char(MSGTYPE_KERNEL_EXCEPTION); + send_int(eid); + break; + case KERNEL_RUN_STARTUP_FAILED: + send_char(MSGTYPE_KERNEL_STARTUP_FAILED); + break; + default: + corecom_log("BUG: run_kernel returned unexpected value '%d'", r); + break; + } } void corecom_serve(object_loader load_object, kernel_runner run_kernel) diff --git a/soc/runtime/main.c b/soc/runtime/main.c index 113aed9f4..777d81b53 100644 --- a/soc/runtime/main.c +++ b/soc/runtime/main.c @@ -8,6 +8,7 @@ #include "corecom.h" #include "elf_loader.h" +#include "exceptions.h" #include "services.h" #include "rtio.h" #include "dds.h" @@ -64,19 +65,28 @@ static int load_object(void *buffer, int length) typedef void (*kernel_function)(void); -static int run_kernel(const char *kernel_name) +static int run_kernel(const char *kernel_name, int *eid) { kernel_function k; + struct exception_env ee; + int exception_occured; k = find_symbol(symtab, kernel_name); if(k == NULL) { corecom_log("Failed to find kernel entry point '%s' in object", kernel_name); - return 0; + return KERNEL_RUN_STARTUP_FAILED; + } + + exception_occured = exception_catch(&ee, eid); + if(exception_occured) + return KERNEL_RUN_EXCEPTION; + else { + rtio_init(); + flush_cpu_icache(); + k(); + exception_pop(); + return KERNEL_RUN_FINISHED; } - rtio_init(); - flush_cpu_icache(); - k(); - return 1; } static void blink_led(void)