Skip to content

Commit f7232fd

Browse files
committedDec 20, 2014
support exceptions raised by RPCs
1 parent 8ea21f5 commit f7232fd

File tree

6 files changed

+103
-19
lines changed

6 files changed

+103
-19
lines changed
 

‎artiq/coredevice/comm_serial.py

+9-8
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
from artiq.language.context import *
1111
from artiq.coredevice.runtime import Environment
1212
from artiq.coredevice import runtime_exceptions
13+
from artiq.coredevice.rpc_wrapper import RPCWrapper
1314

1415

1516
logger = logging.getLogger(__name__)
@@ -69,6 +70,7 @@ def build(self):
6970
self.port.flush()
7071
self.set_remote_baud(self.baud_rate)
7172
self.set_baud(self.baud_rate)
73+
self.rpc_wrapper = RPCWrapper()
7274

7375
def set_baud(self, baud):
7476
self.port.baudrate = baud
@@ -183,19 +185,18 @@ def _receive_rpc_values(self):
183185
if type_tag == "l":
184186
r.append(self._receive_rpc_values())
185187

186-
def _serve_rpc(self, rpc_map):
187-
(rpc_num, ) = struct.unpack(">h", _read_exactly(self.port, 2))
188+
def _serve_rpc(self, rpc_map, user_exception_map):
189+
rpc_num = struct.unpack(">h", _read_exactly(self.port, 2))[0]
188190
args = self._receive_rpc_values()
189191
logger.debug("rpc service: {} ({})".format(rpc_num, args))
190-
r = rpc_map[rpc_num](*args)
191-
if r is None:
192-
r = 0
193-
_write_exactly(self.port, struct.pack(">l", r))
192+
eid, r = self.rpc_wrapper.run_rpc(user_exception_map, rpc_map[rpc_num], args)
193+
_write_exactly(self.port, struct.pack(">ll", eid, r))
194194
logger.debug("rpc service: {} ({}) == {}".format(
195195
rpc_num, args, r))
196196

197197
def _serve_exception(self, user_exception_map):
198-
(eid, ) = struct.unpack(">l", _read_exactly(self.port, 4))
198+
eid = struct.unpack(">l", _read_exactly(self.port, 4))[0]
199+
self.rpc_wrapper.filter_rpc_exception(eid)
199200
if eid < core_language.first_user_eid:
200201
exception = runtime_exceptions.exception_map[eid]
201202
else:
@@ -206,7 +207,7 @@ def serve(self, rpc_map, user_exception_map):
206207
while True:
207208
msg = self._get_device_msg()
208209
if msg == _D2HMsgType.RPC_REQUEST:
209-
self._serve_rpc(rpc_map)
210+
self._serve_rpc(rpc_map, user_exception_map)
210211
elif msg == _D2HMsgType.KERNEL_EXCEPTION:
211212
self._serve_exception(user_exception_map)
212213
elif msg == _D2HMsgType.KERNEL_FINISHED:

‎artiq/coredevice/rpc_wrapper.py

+40
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
from artiq.coredevice.runtime_exceptions import exception_map, _RPCException
2+
3+
4+
def _lookup_exception(d, e):
5+
for eid, exception in d.items():
6+
if isinstance(e, exception):
7+
return eid
8+
return 0
9+
10+
11+
class RPCWrapper:
12+
def __init__(self):
13+
self.last_exception = None
14+
15+
def run_rpc(self, user_exception_map, fn, args):
16+
eid = 0
17+
r = None
18+
19+
try:
20+
r = fn(*args)
21+
except Exception as e:
22+
eid = _lookup_exception(user_exception_map, e)
23+
if not eid:
24+
eid = _lookup_exception(exception_map, e)
25+
if eid:
26+
self.last_exception = None
27+
else:
28+
self.last_exception = e
29+
eid = _RPCException.eid
30+
31+
if r is None:
32+
r = 0
33+
else:
34+
r = int(r)
35+
36+
return eid, r
37+
38+
def filter_rpc_exception(self, eid):
39+
if eid == _RPCException.eid:
40+
raise self.last_exception

‎artiq/coredevice/runtime_exceptions.py

+8-6
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,11 @@ class OutOfMemory(RuntimeException):
99
"""Raised when the runtime fails to allocate memory.
1010
1111
"""
12-
eid = 0
12+
eid = 1
13+
14+
15+
class _RPCException(RuntimeException):
16+
eid = 2
1317

1418

1519
class RTIOUnderflow(RuntimeException):
@@ -19,19 +23,17 @@ class RTIOUnderflow(RuntimeException):
1923
The offending event is discarded and the RTIO core keeps operating.
2024
2125
"""
22-
eid = 1
26+
eid = 3
2327

2428

25-
# Raised by RTIO driver for regular RTIO.
26-
# Raised by runtime for DDS FUD.
2729
class RTIOSequenceError(RuntimeException):
2830
"""Raised when an event is submitted on a given channel with a timestamp
2931
not larger than the previous one.
3032
3133
The offending event is discarded and the RTIO core keeps operating.
3234
3335
"""
34-
eid = 2
36+
eid = 4
3537

3638

3739
class RTIOOverflow(RuntimeException):
@@ -43,7 +45,7 @@ class RTIOOverflow(RuntimeException):
4345
the exception is caught, and events will be partially retrieved.
4446
4547
"""
46-
eid = 3
48+
eid = 5
4749

4850

4951
exception_map = {e.eid: e for e in globals().values()

‎artiq/test/full_stack.py

+30
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,25 @@ def run(self):
170170
self.trace.append(104)
171171

172172

173+
class _RPCExceptions(AutoContext):
174+
def build(self):
175+
self.success = False
176+
177+
def exception_raiser(self):
178+
raise _MyException
179+
180+
@kernel
181+
def do_not_catch(self):
182+
self.exception_raiser()
183+
184+
@kernel
185+
def catch(self):
186+
try:
187+
self.exception_raiser()
188+
except _MyException:
189+
self.success = True
190+
191+
173192
@unittest.skipIf(no_hardware, "no hardware")
174193
class ExecutionCase(unittest.TestCase):
175194
def test_primes(self):
@@ -219,6 +238,17 @@ def test_exceptions(self):
219238
_run_on_host(_Exceptions, trace=t_host)
220239
self.assertEqual(t_device, t_host)
221240

241+
def test_rpc_exceptions(self):
242+
comm = comm_serial.Comm()
243+
try:
244+
uut = _RPCExceptions(core=core.Core(comm=comm))
245+
with self.assertRaises(_MyException):
246+
uut.do_not_catch()
247+
uut.catch()
248+
self.assertTrue(uut.success)
249+
finally:
250+
comm.close()
251+
222252

223253
class _RTIOLoopback(AutoContext):
224254
i = Device("ttl_in")

‎soc/runtime/comm_serial.c

+10-1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
#include <generated/csr.h>
55

66
#include "comm.h"
7+
#include "exceptions.h"
78

89
/* host to device */
910
enum {
@@ -224,6 +225,8 @@ static int send_value(int type_tag, void *value)
224225
int comm_rpc(int rpc_num, ...)
225226
{
226227
int type_tag;
228+
int eid;
229+
int retval;
227230

228231
send_char(MSGTYPE_RPC_REQUEST);
229232
send_sint(rpc_num);
@@ -235,7 +238,13 @@ int comm_rpc(int rpc_num, ...)
235238
va_end(args);
236239
send_char(0);
237240

238-
return receive_int();
241+
eid = receive_int();
242+
retval = receive_int();
243+
244+
if(eid != EID_NONE)
245+
exception_raise(eid);
246+
247+
return retval;
239248
}
240249

241250
void comm_log(const char *fmt, ...)

‎soc/runtime/exceptions.h

+6-4
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,12 @@
22
#define __EXCEPTIONS_H
33

44
enum {
5-
EID_OUT_OF_MEMORY = 0,
6-
EID_RTIO_UNDERFLOW = 1,
7-
EID_RTIO_SEQUENCE_ERROR = 2,
8-
EID_RTIO_OVERFLOW = 3,
5+
EID_NONE = 0,
6+
EID_OUT_OF_MEMORY = 1,
7+
EID_RPC_EXCEPTION = 2,
8+
EID_RTIO_UNDERFLOW = 3,
9+
EID_RTIO_SEQUENCE_ERROR = 4,
10+
EID_RTIO_OVERFLOW = 5,
911
};
1012

1113
int exception_setjmp(void *jb) __attribute__((returns_twice));

0 commit comments

Comments
 (0)
Please sign in to comment.