From 2cb58592fff4bab2028081b2432794042efcc66b Mon Sep 17 00:00:00 2001 From: Robert Jordens Date: Tue, 8 Mar 2016 18:04:34 +0100 Subject: [PATCH] rtio: add RTIOBusy --- artiq/coredevice/__init__.py | 2 +- artiq/coredevice/exceptions.py | 13 +++++++++++++ artiq/gateware/rtio/core.py | 27 ++++++++++++++++++++++++--- artiq/runtime/rtio.c | 6 ++++++ artiq/runtime/rtio.h | 2 ++ 5 files changed, 46 insertions(+), 4 deletions(-) diff --git a/artiq/coredevice/__init__.py b/artiq/coredevice/__init__.py index da8c72b1d..4eac74667 100644 --- a/artiq/coredevice/__init__.py +++ b/artiq/coredevice/__init__.py @@ -1,6 +1,6 @@ from artiq.coredevice import exceptions, dds, spi from artiq.coredevice.exceptions import (RTIOUnderflow, RTIOSequenceError, - RTIOCollision, RTIOOverflow, + RTIOCollision, RTIOOverflow, RTIOBusy, DDSBatchError, CacheError) from artiq.coredevice.dds import (PHASE_MODE_CONTINUOUS, PHASE_MODE_ABSOLUTE, PHASE_MODE_TRACKING) diff --git a/artiq/coredevice/exceptions.py b/artiq/coredevice/exceptions.py index aa00ad784..987f5a127 100644 --- a/artiq/coredevice/exceptions.py +++ b/artiq/coredevice/exceptions.py @@ -98,6 +98,19 @@ class RTIOCollision(Exception): """ artiq_builtin = True +class RTIOBusy(Exception): + """Raised when an event could not be executed because the given channel + was already busy executing a previous event. The two events were not + sufficiently spaced on the timeline. + + This exception is raised after the error condition appeared. More + specifically it is raised on submitting an event on the same channel after + the execution of the faulty event was attempted. + + The offending event is discarded and the RTIO core keeps operating. + """ + artiq_builtin = True + class RTIOOverflow(Exception): """Raised when at least one event could not be registered into the RTIO input FIFO because it was full (CPU not reading fast enough). diff --git a/artiq/gateware/rtio/core.py b/artiq/gateware/rtio/core.py index 8c2d1b237..cdc36598d 100644 --- a/artiq/gateware/rtio/core.py +++ b/artiq/gateware/rtio/core.py @@ -104,6 +104,7 @@ class _OutputManager(Module): self.underflow = Signal() # valid 1 cycle after we, pulsed self.sequence_error = Signal() self.collision = Signal() + self.busy = Signal() # pulsed # # # @@ -223,6 +224,20 @@ class _OutputManager(Module): dout.timestamp[fine_ts_width:] == counter.value_rtio), interface.stb.eq(dout_stb & dout_ack) ] + busy_sync = PulseSynchronizer("rio", "rsys") + busy_ack_sync = PulseSynchronizer("rsys", "rio") + self.submodules += busy_sync, busy_ack_sync + busy_blind = Signal() + self.comb += busy_sync.i.eq(interface.stb & interface.busy & ~busy_blind) + self.sync.rio += [ + If(interface.stb & interface.busy, busy_blind.eq(1)), + If(busy_ack_sync.o, busy_blind.eq(0)) + ] + self.comb += [ + busy_ack_sync.i.eq(busy_sync.o), + self.busy.eq(busy_sync.o) + ] + if data_width: self.comb += interface.data.eq(dout.data) if address_width: @@ -336,10 +351,11 @@ class _KernelCSRs(AutoCSR): self.o_address = CSRStorage(address_width) self.o_timestamp = CSRStorage(full_ts_width) self.o_we = CSR() - self.o_status = CSRStatus(4) + self.o_status = CSRStatus(5) self.o_underflow_reset = CSR() self.o_sequence_error_reset = CSR() self.o_collision_reset = CSR() + self.o_busy_reset = CSR() if data_width: self.i_data = CSRStatus(data_width) @@ -427,6 +443,7 @@ class RTIO(Module): underflow = Signal() sequence_error = Signal() collision = Signal() + busy = Signal() self.sync.rsys += [ If(selected & self.kcsrs.o_underflow_reset.re, underflow.eq(0)), @@ -434,14 +451,18 @@ class RTIO(Module): sequence_error.eq(0)), If(selected & self.kcsrs.o_collision_reset.re, collision.eq(0)), + If(selected & self.kcsrs.o_busy_reset.re, + busy.eq(0)), If(o_manager.underflow, underflow.eq(1)), If(o_manager.sequence_error, sequence_error.eq(1)), - If(o_manager.collision, collision.eq(1)) + If(o_manager.collision, collision.eq(1)), + If(o_manager.busy, busy.eq(1)) ] o_statuses.append(Cat(~o_manager.writable, underflow, sequence_error, - collision)) + collision, + busy)) if channel.interface.i is not None: i_manager = _InputManager(channel.interface.i, self.counter, diff --git a/artiq/runtime/rtio.c b/artiq/runtime/rtio.c index 90dd7fb5e..385011cf5 100644 --- a/artiq/runtime/rtio.c +++ b/artiq/runtime/rtio.c @@ -39,6 +39,12 @@ static void rtio_process_exceptional_status( "RTIO collision at {0} mu, channel {1}", timestamp, channel, 0); } + if(status & RTIO_O_STATUS_BUSY) { + rtio_o_busy_reset_write(1); + artiq_raise_from_c("RTIOBusy", + "RTIO busy at {0} mu, channel {1}", + timestamp, channel, 0); + } } diff --git a/artiq/runtime/rtio.h b/artiq/runtime/rtio.h index c32dca484..cdaf8a6e1 100644 --- a/artiq/runtime/rtio.h +++ b/artiq/runtime/rtio.h @@ -2,11 +2,13 @@ #define __RTIO_H #include +#include "generated/csr.h" #define RTIO_O_STATUS_FULL 1 #define RTIO_O_STATUS_UNDERFLOW 2 #define RTIO_O_STATUS_SEQUENCE_ERROR 4 #define RTIO_O_STATUS_COLLISION 8 +#define RTIO_O_STATUS_BUSY 16 #define RTIO_I_STATUS_EMPTY 1 #define RTIO_I_STATUS_OVERFLOW 2