Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: m-labs/artiq
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: 7166ca82d16b
Choose a base ref
...
head repository: m-labs/artiq
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: 50e0bf3280f0
Choose a head ref
  • 3 commits
  • 3 files changed
  • 1 contributor

Commits on Dec 1, 2014

  1. Verified

    This commit was signed with the committer’s verified signature. The key has expired.
    jluttine Jaakko Luttinen
    Copy the full SHA
    d50dbc0 View commit details
  2. Verified

    This commit was signed with the committer’s verified signature. The key has expired.
    jluttine Jaakko Luttinen
    Copy the full SHA
    572eecc View commit details
  3. Copy the full SHA
    50e0bf3 View commit details
Showing with 48 additions and 33 deletions.
  1. +5 −4 artiq/coredevice/runtime_exceptions.py
  2. +13 −16 soc/artiqlib/rtio/core.py
  3. +30 −13 soc/runtime/rtio.c
9 changes: 5 additions & 4 deletions artiq/coredevice/runtime_exceptions.py
Original file line number Diff line number Diff line change
@@ -16,7 +16,7 @@ class RTIOUnderflow(RuntimeException):
"""Raised when the CPU fails to submit a RTIO event early enough
(with respect to the event's timestamp).
Causes a reset of the RTIO core, except its time counter.
The offending event is discarded and the RTIO core keeps operating.
"""
eid = 1
@@ -28,8 +28,7 @@ class RTIOSequenceError(RuntimeException):
"""Raised when an event is submitted on a given channel with a timestamp
not larger than the previous one.
The offending event is discarded and RTIO operation is not affected
further.
The offending event is discarded and the RTIO core keeps operating.
"""
eid = 2
@@ -39,7 +38,9 @@ class RTIOOverflow(RuntimeException):
"""Raised when at least one event could not be registered into the RTIO
input FIFO because it was full (CPU not reading fast enough).
Causes a reset of the RTIO core, except its time counter.
This does not interrupt operations further than cancelling the current
read attempt and discarding some events. Reading can be reattempted after
the exception is caught, and events will be partially retrieved.
"""
eid = 3
29 changes: 13 additions & 16 deletions soc/artiqlib/rtio/core.py
Original file line number Diff line number Diff line change
@@ -67,22 +67,23 @@ def __init__(self, width, loopback_latency):
# guard_io_cycles > (4*Tio + 4*Tsys)/Tio
#
# We are writing to the FIFO from the buffer when the guard time has been
# reached without checking the FIFO's writable status. If the FIFO is full,
# this will produce an overflow and the event will be incorrectly discarded.
# reached. This can fill the FIFO and deassert the writable flag. A race
# condition occurs that causes problems if the deassertion happens between
# the CPU checking the writable flag (and reading 1) and writing a new event.
#
# When the FIFO is full, it contains fifo_depth events of strictly increasing
# timestamps.
# When the FIFO is about to be full, it contains fifo_depth-1 events of
# strictly increasing timestamps.
#
# Thus the overflow-causing event's timestamp must satisfy:
# timestamp*Tio > fifo_depth*Tio + time
# Thus the FIFO-filling event's timestamp must satisfy:
# timestamp*Tio > (fifo_depth-1)*Tio + time
# We also have (guard time reached):
# timestamp*Tio < time + guard_io_cycles*Tio
# [NB: time > counter.o_value_sys*Tio]
# Thus we must have:
# guard_io_cycles > fifo_depth
# guard_io_cycles > fifo_depth-1
#
# We can prevent overflows by choosing instead:
# guard_io_cycles < fifo_depth
# guard_io_cycles < fifo_depth-1

class _RTIOBankO(Module):
def __init__(self, rbus, counter, fine_ts_width, fifo_depth, guard_io_cycles):
@@ -296,17 +297,15 @@ def __init__(self, phy, clk_freq, counter_width=32,

self._r_o_timestamp = CSRStorage(counter_width + fine_ts_width)
self._r_o_value = CSRStorage(2)
self._r_o_writable = CSRStatus()
self._r_o_we = CSR()
self._r_o_replace = CSR()
self._r_o_underflow = CSRStatus()
self._r_o_status = CSRStatus(2)
self._r_o_underflow_reset = CSR()

self._r_i_timestamp = CSRStatus(counter_width + fine_ts_width)
self._r_i_value = CSRStatus()
self._r_i_readable = CSRStatus()
self._r_i_re = CSR()
self._r_i_overflow = CSRStatus()
self._r_i_status = CSRStatus(2)
self._r_i_overflow_reset = CSR()
self._r_i_pileup_count = CSRStatus(16)
self._r_i_pileup_reset = CSR()
@@ -350,10 +349,9 @@ def __init__(self, phy, clk_freq, counter_width=32,
self.bank_o.sel.eq(self._r_chan_sel.storage),
self.bank_o.timestamp.eq(self._r_o_timestamp.storage),
self.bank_o.value.eq(self._r_o_value.storage),
self._r_o_writable.status.eq(self.bank_o.writable),
self.bank_o.we.eq(self._r_o_we.re),
self.bank_o.replace.eq(self._r_o_replace.re),
self._r_o_underflow.status.eq(self.bank_o.underflow),
self._r_o_status.status.eq(Cat(~self.bank_o.writable, self.bank_o.underflow)),
self.bank_o.underflow_reset.eq(self._r_o_underflow_reset.re)
]

@@ -362,9 +360,8 @@ def __init__(self, phy, clk_freq, counter_width=32,
self.bank_i.sel.eq(self._r_chan_sel.storage),
self._r_i_timestamp.status.eq(self.bank_i.timestamp),
self._r_i_value.status.eq(self.bank_i.value),
self._r_i_readable.status.eq(self.bank_i.readable),
self.bank_i.re.eq(self._r_i_re.re),
self._r_i_overflow.status.eq(self.bank_i.overflow),
self._r_i_status.status.eq(Cat(~self.bank_i.readable, self.bank_i.overflow)),
self.bank_i.overflow_reset.eq(self._r_i_overflow_reset.re),
self._r_i_pileup_count.status.eq(self.bank_i.pileup_count),
self.bank_i.pileup_reset.eq(self._r_i_pileup_reset.re)
43 changes: 30 additions & 13 deletions soc/runtime/rtio.c
Original file line number Diff line number Diff line change
@@ -3,6 +3,11 @@
#include "exceptions.h"
#include "rtio.h"

#define RTIO_O_STATUS_FULL 1
#define RTIO_O_STATUS_UNDERFLOW 2
#define RTIO_I_STATUS_EMPTY 1
#define RTIO_I_STATUS_OVERFLOW 2

long long int previous_fud_end_time;

void rtio_init(void)
@@ -20,14 +25,20 @@ void rtio_oe(int channel, int oe)

void rtio_set(long long int timestamp, int channel, int value)
{
int status;

rtio_chan_sel_write(channel);
rtio_o_timestamp_write(timestamp);
rtio_o_value_write(value);
while(!rtio_o_writable_read());
rtio_o_we_write(1);
if(rtio_o_underflow_read()) {
rtio_o_underflow_reset_write(1);
exception_raise(EID_RTIO_UNDERFLOW);
status = rtio_o_status_read();
if(status) {
if(status & RTIO_O_STATUS_FULL)
while(rtio_o_status_read() & RTIO_O_STATUS_FULL);
if(status & RTIO_O_STATUS_UNDERFLOW) {
rtio_o_underflow_reset_write(1);
exception_raise(EID_RTIO_UNDERFLOW);
}
}
}

@@ -37,7 +48,7 @@ void rtio_replace(long long int timestamp, int channel, int value)
rtio_o_timestamp_write(timestamp);
rtio_o_value_write(value);
rtio_o_replace_write(1);
if(rtio_o_underflow_read()) {
if(rtio_o_status_read() & RTIO_O_STATUS_UNDERFLOW) {
rtio_o_underflow_reset_write(1);
exception_raise(EID_RTIO_UNDERFLOW);
}
@@ -52,20 +63,26 @@ long long int rtio_get_counter(void)
long long int rtio_get(int channel, long long int time_limit)
{
long long int r;
int status;

rtio_chan_sel_write(channel);
while(rtio_i_readable_read() || (rtio_get_counter() < time_limit)) {
if(rtio_i_overflow_read()) {
while(status = rtio_i_status_read()) {
if(rtio_i_status_read() & RTIO_I_STATUS_OVERFLOW) {
rtio_i_overflow_reset_write(1);
exception_raise(EID_RTIO_OVERFLOW);
}
if(rtio_i_readable_read()) {
r = rtio_i_timestamp_read();
rtio_i_re_write(1);
return r;
if(rtio_get_counter() >= time_limit) {
/* check empty flag again to prevent race condition.
* now we are sure that the time limit has been exceeded.
*/
if(rtio_i_status_read() & RTIO_I_STATUS_EMPTY)
return -1;
}
/* input FIFO is empty - keep waiting */
}
return -1;
r = rtio_i_timestamp_read();
rtio_i_re_write(1);
return r;
}

int rtio_pileup_count(int channel)
@@ -101,7 +118,7 @@ void rtio_fud(long long int fud_time)
rtio_o_timestamp_write(fud_end_time);
rtio_o_value_write(0);
rtio_o_we_write(1);
if(rtio_o_underflow_read()) {
if(rtio_o_status_read() & RTIO_O_STATUS_UNDERFLOW) {
rtio_o_underflow_reset_write(1);
exception_raise(EID_RTIO_UNDERFLOW);
}