diff --git a/artiq/coredevice/comm_generic.py b/artiq/coredevice/comm_generic.py index a737dfb84..88fee184b 100644 --- a/artiq/coredevice/comm_generic.py +++ b/artiq/coredevice/comm_generic.py @@ -95,7 +95,12 @@ class CommGeneric: def _write_header(self, length, ty): self.open() logger.debug("sending message: type=%r length=%d", ty, length) - self.write(struct.pack(">llB", 0x5a5a5a5a, length, ty.value)) + self.write(struct.pack(">ll", 0x5a5a5a5a, length)) + if ty is not None: + self.write(struct.pack("B", ty.value)) + + def reset_session(self): + self._write_header(0, None) def check_ident(self): self._write_header(9, _H2DMsgType.IDENT_REQUEST) @@ -125,9 +130,8 @@ class CommGeneric: if ty != _D2HMsgType.LOAD_COMPLETED: raise IOError("Incorrect reply from device: "+str(ty)) - def run(self, kname, reset_now): - self._write_header(len(kname) + 10, _H2DMsgType.RUN_KERNEL) - self.write(struct.pack("B", reset_now)) + def run(self, kname): + self._write_header(len(kname) + 9, _H2DMsgType.RUN_KERNEL) self.write(bytes(kname, "ascii")) logger.debug("running kernel: %s", kname) diff --git a/artiq/coredevice/comm_serial.py b/artiq/coredevice/comm_serial.py index 691b43928..25c926a25 100644 --- a/artiq/coredevice/comm_serial.py +++ b/artiq/coredevice/comm_serial.py @@ -19,6 +19,7 @@ class Comm(CommGeneric, AutoDB): return self.port = serial.serial_for_url(self.serial_dev, baudrate=self.baud_rate) + self.reset_session() def close(self): if not hasattr(self, "port"): diff --git a/artiq/coredevice/core.py b/artiq/coredevice/core.py index 6923b8ce9..61e7ed353 100644 --- a/artiq/coredevice/core.py +++ b/artiq/coredevice/core.py @@ -116,7 +116,7 @@ class Core(AutoDB): binary, rpc_map, exception_map = self.compile( k_function, k_args, k_kwargs) self.comm.load(binary) - self.comm.run(k_function.__name__, self.first_run) + self.comm.run(k_function.__name__) self.comm.serve(rpc_map, exception_map) self.first_run = False diff --git a/artiq/gateware/rtio/core.py b/artiq/gateware/rtio/core.py index 9aad47127..ffe3a978f 100644 --- a/artiq/gateware/rtio/core.py +++ b/artiq/gateware/rtio/core.py @@ -44,7 +44,8 @@ class _RTIOCounter(Module): # # # - self.sync.rio += self.value_rio.eq(self.value_rio + 1), + # note: counter is in rtio domain and never affected by the reset CSRs + self.sync.rtio += self.value_rio.eq(self.value_rio + 1) gt = _GrayCodeTransfer(width) self.submodules += gt self.comb += gt.i.eq(self.value_rio), self.value_sys.eq(gt.o) diff --git a/artiq/test/coredevice.py b/artiq/test/coredevice.py index 1be60a398..0c5c32990 100644 --- a/artiq/test/coredevice.py +++ b/artiq/test/coredevice.py @@ -147,6 +147,33 @@ class SequenceError(Experiment, AutoDB): self.ttl_out.pulse(25*us) +class TimeKeepsRunning(Experiment, AutoDB): + class DBKeys: + core = Device() + time_at_start = Result() + + @kernel + def run(self): + self.time_at_start = now_mu() + + +class Handover(Experiment, AutoDB): + class DBKeys: + core = Device() + t1 = Result() + t2 = Result() + + @kernel + def get_now(self): + self.time_at_start = now_mu() + + def run(self): + self.get_now() + self.t1 = self.time_at_start + self.get_now() + self.t2 = self.time_at_start + + class CoredeviceTest(ExperimentCase): def test_rtt(self): self.execute(RTT) @@ -192,6 +219,21 @@ class CoredeviceTest(ExperimentCase): with self.assertRaises(IOError): self.execute(Watchdog) + def test_time_keeps_running(self): + self.execute(TimeKeepsRunning) + t1 = self.dbh.get_result("time_at_start").read + self.dbh.close_devices() # a fortiori the core device connection + self.execute(TimeKeepsRunning) + t2 = self.dbh.get_result("time_at_start").read + self.assertGreater(mu_to_seconds(t2 - t1, + self.dbh.get_device("core")), + 1*ms) + + def test_handover(self): + self.execute(Handover) + self.assertEqual(self.dbh.get_result("t1").read, + self.dbh.get_result("t2").read) + class RPCTiming(Experiment, AutoDB): class DBKeys: diff --git a/soc/runtime/ksupport.c b/soc/runtime/ksupport.c index a2eb090c6..032fe88ec 100644 --- a/soc/runtime/ksupport.c +++ b/soc/runtime/ksupport.c @@ -79,7 +79,7 @@ long long int now_init(void) if(now < 0) { rtio_init(); - now = 125000; + now = rtio_get_counter() + 125000; } return now; diff --git a/soc/runtime/main.c b/soc/runtime/main.c index fec357a0f..41433d264 100644 --- a/soc/runtime/main.c +++ b/soc/runtime/main.c @@ -151,16 +151,18 @@ static void regular_main(void) #else /* CSR_ETHMAC_BASE */ -static void reset_serial_session(void) +static void reset_serial_session(int signal) { int i; session_end(); - /* Signal end-of-session inband with zero length packet. */ - for(i=0;i<4;i++) - uart_write(0x5a); - for(i=0;i<4;i++) - uart_write(0x00); + if(signal) { + /* Signal end-of-session inband with zero length packet. */ + for(i=0;i<4;i++) + uart_write(0x5a); + for(i=0;i<4;i++) + uart_write(0x00); + } session_start(); } @@ -181,7 +183,8 @@ static void serial_service(void) if(r > 0) rxpending = 0; if(r < 0) - reset_serial_session(); + /* do not signal if reset was requested by host */ + reset_serial_session(r != -2); } session_poll((void **)&txdata, &txlen); @@ -191,7 +194,7 @@ static void serial_service(void) session_ack_data(txlen); session_ack_mem(txlen); } else if(txlen < 0) - reset_serial_session(); + reset_serial_session(1); } static void regular_main(void) diff --git a/soc/runtime/rtio.c b/soc/runtime/rtio.c index 0e5cdad10..3329019ba 100644 --- a/soc/runtime/rtio.c +++ b/soc/runtime/rtio.c @@ -14,4 +14,3 @@ long long int rtio_get_counter(void) rtio_counter_update_write(1); return rtio_counter_read(); } - diff --git a/soc/runtime/session.c b/soc/runtime/session.c index 352bca791..1a7f5d879 100644 --- a/soc/runtime/session.c +++ b/soc/runtime/session.c @@ -70,11 +70,13 @@ void session_start(void) memset(&buffer_out[4], 0, 4); kloader_stop(); user_kernel_state = USER_KERNEL_NONE; + now = -1; } void session_end(void) { kloader_stop(); + now = -1; kloader_start_idle_kernel(); } @@ -189,10 +191,7 @@ static int process_input(void) } buffer_in[buffer_in_index] = 0; - if(buffer_in[9]) - now = -1; - - k = kloader_find((char *)&buffer_in[10]); + k = kloader_find((char *)&buffer_in[9]); if(k == NULL) { log("Failed to find kernel entry point '%s' in object", &buffer_in[9]); buffer_out[8] = REMOTEMSG_TYPE_KERNEL_STARTUP_FAILED; @@ -311,6 +310,9 @@ int session_input(void *data, int len) /* receiving length */ buffer_in[buffer_in_index++] = _data[consumed]; consumed++; len--; + if((buffer_in_index == 8) && (get_in_packet_len() == 0)) + /* zero-length packet = session reset */ + return -2; } else { /* receiving payload */ int packet_len; @@ -465,12 +467,14 @@ static int send_rpc_request(int rpc_num, va_list args) /* assumes output buffer is empty when called */ static int process_kmsg(struct msg_base *umsg) { - if(user_kernel_state != USER_KERNEL_RUNNING) { - log("Received message from kernel CPU while not in running state"); - return 0; - } if(!validate_kpointer(umsg)) return 0; + if((user_kernel_state != USER_KERNEL_RUNNING) + && (umsg->type != MESSAGE_TYPE_NOW_INIT_REQUEST) + && (umsg->type != MESSAGE_TYPE_NOW_SAVE)) { + log("Received unexpected message from kernel CPU while not in running state"); + return 0; + } switch(umsg->type) { case MESSAGE_TYPE_NOW_INIT_REQUEST: {