forked from M-Labs/artiq
1
0
Fork 0

rtio: add RTIOBusy

This commit is contained in:
Robert Jördens 2016-03-08 18:04:34 +01:00
parent 0d431cb019
commit 2cb58592ff
5 changed files with 46 additions and 4 deletions

View File

@ -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)

View File

@ -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).

View File

@ -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,

View File

@ -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);
}
}

View File

@ -2,11 +2,13 @@
#define __RTIO_H
#include <stdarg.h>
#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