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: f2ec8692c059
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: 324660ab407f
Choose a head ref
  • 2 commits
  • 7 files changed
  • 1 contributor

Commits on Mar 1, 2016

  1. Copy the full SHA
    c2fe9a0 View commit details
  2. rt2wb, exceptions: remove RTIOTimeout

    Assume that rt2wb transactions either collide and are then
    reported (#308) or that
    they complete and the delay with which they complete does not matter.
    
    If a transaction is ack'ed with a delay because the WB core's downstream
    logic is busy, that may lead to a later collision with another WB
    transaction.
    jordens committed Mar 1, 2016
    Copy the full SHA
    324660a View commit details
Showing with 60 additions and 96 deletions.
  1. +2 −3 artiq/coredevice/__init__.py
  2. +0 −11 artiq/coredevice/exceptions.py
  3. +0 −5 artiq/coredevice/rt2wb.py
  4. +16 −21 artiq/coredevice/spi.py
  5. +35 −24 artiq/gateware/spi.py
  6. +0 −1 artiq/runtime/ksupport.c
  7. +7 −31 artiq/runtime/rt2wb.c
5 changes: 2 additions & 3 deletions artiq/coredevice/__init__.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
from artiq.coredevice import exceptions, dds, spi
from artiq.coredevice.exceptions import (RTIOUnderflow, RTIOSequenceError,
RTIOCollisionError, RTIOOverflow,
DDSBatchError, CacheError,
RTIOTimeout)
DDSBatchError, CacheError)
from artiq.coredevice.dds import (PHASE_MODE_CONTINUOUS, PHASE_MODE_ABSOLUTE,
PHASE_MODE_TRACKING)

__all__ = []
__all__ += ["RTIOUnderflow", "RTIOSequenceError", "RTIOCollisionError",
"RTIOOverflow", "DDSBatchError", "CacheError", "RTIOTimeout"]
"RTIOOverflow", "DDSBatchError", "CacheError"]
__all__ += ["PHASE_MODE_CONTINUOUS", "PHASE_MODE_ABSOLUTE",
"PHASE_MODE_TRACKING"]
11 changes: 0 additions & 11 deletions artiq/coredevice/exceptions.py
Original file line number Diff line number Diff line change
@@ -108,17 +108,6 @@ class RTIOOverflow(Exception):
"""
artiq_builtin = True

class RTIOTimeout(Exception):
"""Raised when an RTIO input operation does not complete within the expected
time. This is only raised by channels where a response is guaranteed, such
as RT2WB (DDS and SPI).
This does not interrupt operations further than cancelling the current read
attempt. Reading can be reattempted after the exception is caught, and
events that have arrived in the meantime will be retrieved.
"""
artiq_builtin = True

class DDSBatchError(Exception):
"""Raised when attempting to start a DDS batch while already in a batch,
or when too many commands are batched.
5 changes: 0 additions & 5 deletions artiq/coredevice/rt2wb.py
Original file line number Diff line number Diff line change
@@ -11,8 +11,3 @@ def rt2wb_output(time_mu: TInt64, channel: TInt32, addr: TInt32, data: TInt32
@syscall
def rt2wb_input(channel: TInt32) -> TInt32:
raise NotImplementedError("syscall not simulated")


@syscall
def rt2wb_input_sync(timeout_mu: TInt64, channel: TInt32) -> TInt32:
raise NotImplementedError("syscall not simulated")
37 changes: 16 additions & 21 deletions artiq/coredevice/spi.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from artiq.language.core import (kernel, portable, seconds_to_mu, now_mu,
delay_mu, int)
from artiq.language.units import MHz
from artiq.coredevice.rt2wb import rt2wb_output, rt2wb_input, rt2wb_input_sync
from artiq.coredevice.rt2wb import rt2wb_output, rt2wb_input


SPI_DATA_ADDR, SPI_XFER_ADDR, SPI_CONFIG_ADDR = range(3)
@@ -55,17 +55,12 @@ def set_config_mu(self, flags=0, write_div=6, read_div=6):
self.read_period_mu = int(read_div*self.ref_period_mu)
delay_mu(3*self.ref_period_mu)

@portable
def get_xfer_period_mu(self, write_length, read_length):
return int(write_length*self.write_period_mu +
read_length*self.read_period_mu)

@kernel
def set_xfer(self, chip_select=0, write_length=0, read_length=0):
rt2wb_output(now_mu(), self.channel, SPI_XFER_ADDR,
chip_select | (write_length << 16) | (read_length << 24))
self.xfer_period_mu = self.get_xfer_period_mu(write_length,
read_length)
self.xfer_period_mu = int(write_length*self.write_period_mu +
read_length*self.read_period_mu)
delay_mu(3*self.ref_period_mu)

@kernel
@@ -74,28 +69,28 @@ def write(self, data):
delay_mu(3*self.ref_period_mu)

@kernel
def read(self):
def read_async(self):
# every read_async() must be matched by an input_async()
rt2wb_output(now_mu(), self.channel, SPI_DATA_ADDR | SPI_RT2WB_READ, 0)
delay_mu(3*self.ref_period_mu)

@kernel
def input(self):
def input_async(self):
# matches the preeeding read_async()
return rt2wb_input(self.channel)

@kernel
def _rt2wb_read_sync(self, addr=0):
t = now_mu()
rt2wb_output(t, self.channel, addr | SPI_RT2WB_READ, 0)
return rt2wb_input_sync(t + 3*self.ref_period_mu, self.channel)

@kernel
def read_sync(self):
return self._rt2wb_read_sync(SPI_DATA_ADDR)
rt2wb_output(now_mu(), self.channel, SPI_DATA_ADDR | SPI_RT2WB_READ, 0)
return rt2wb_input(self.channel)

@kernel
def _get_config_sync(self):
return self._rt2wb_read_sync(SPI_CONFIG_ADDR)
def _get_xfer_sync(self):
rt2wb_output(now_mu(), self.channel, SPI_XFER_ADDR | SPI_RT2WB_READ, 0)
return rt2wb_input(self.channel)

@kernel
def _get_xfer_sync(self):
return self._rt2wb_read_sync(SPI_XFER_ADDR)
def _get_config_sync(self):
rt2wb_output(now_mu(), self.channel, SPI_CONFIG_ADDR | SPI_RT2WB_READ,
0)
return rt2wb_input(self.channel)
59 changes: 35 additions & 24 deletions artiq/gateware/spi.py
Original file line number Diff line number Diff line change
@@ -205,29 +205,33 @@ class SPIMaster(Module):
Transfers submitted this way are chained and executed without
deasserting cs. Once a transfer completes, the previous transfer's
read data is available in the data register.
* A wishbone transaction is ack-ed when the transfer has been written
to the intermediate buffer. It will be started when there are no
other transactions being executed. Writes take one cycle when
there is either no transfer being executed, no data in the
intermediate buffer, or a transfer just completing. Reads always
finish in one cycle.
* Writes to the config register take effect immediately. Writes to xfer
and data are synchronized to the start of a transfer.
* A wishbone data register write is ack-ed when the transfer has
been written to the intermediate buffer. It will be started when
there are no other transactions being executed, either starting
a new SPI transfer of chained to an in-flight transfer.
Writes take two cycles unless the write is to the data register
and another chained transfer is pending and the transfer being
executed is not complete. Reads always finish in two cycles.
Transaction Sequence:
* If desired, write the config register to set up the core.
* If desired, write the xfer register to change lengths and cs_n.
* Write the data register (also for zero-length writes),
writing triggers the transfer and when the transfer is accepted to
the inermediate buffer, the write is ack-ed.
* If desired, read the data register.
* If desired, write data for the next, chained, transfer.
* If desired, read the data register corresponding to the last
completed transfer.
* If desired, change xfer register for the next transfer.
* If desired, write data queuing the next (possibly chained) transfer.
Register address and bit map:
config (address 2):
1 offline: all pins high-z (reset=1)
1 active: cs/transfer active (read-only)
1 pending: transfer pending in intermediate buffer, bus writes will
block (read-only)
1 pending: transfer pending in intermediate buffer (read-only)
1 cs_polarity: active level of chip select (reset=0)
1 clk_polarity: idle level of clk (reset=0)
1 clk_phase: first edge after cs assertion to sample data on (reset=0)
@@ -246,18 +250,18 @@ class SPIMaster(Module):
8 div_read: ditto for the read clock
xfer (address 1):
16 cs: active high bit mask of chip selects to assert
6 write_len: 0-M bits
16 cs: active high bit mask of chip selects to assert (reset=0)
6 write_len: 0-M bits (reset=0)
2 undefined
6 read_len: 0-M bits
6 read_len: 0-M bits (reset=0)
2 undefined
data (address 0):
M write/read data
M write/read data (reset=0)
"""
def __init__(self, pads, bus=None, data_width=32):
def __init__(self, pads, bus=None):
if bus is None:
bus = wishbone.Interface(data_width=data_width)
bus = wishbone.Interface(data_width=32)
self.bus = bus

###
@@ -289,7 +293,8 @@ def __init__(self, pads, bus=None, data_width=32):
assert len(xfer) <= len(bus.dat_w)

self.submodules.spi = spi = SPIMachine(
data_width, clock_width=len(config.div_read),
data_width=len(bus.dat_w),
clock_width=len(config.div_read),
bits_width=len(xfer.read_length))

pending = Signal()
@@ -318,15 +323,21 @@ def __init__(self, pads, bus=None, data_width=32):
spi.reg.data.eq(data_write),
pending.eq(0),
),
bus.ack.eq(bus.cyc & bus.stb & (~bus.we | ~pending | spi.done)),
# wb.ack a transaction if any of the following:
# a) reading,
# b) writing to non-data register
# c) writing to data register and no pending transfer
# d) writing to data register and pending and swapping buffers
bus.ack.eq(bus.cyc & bus.stb &
(~bus.we | (bus.adr != 0) | ~pending | spi.done)),
If(bus.ack,
bus.ack.eq(0),
),
If(bus.we & bus.ack,
Array([data_write, xfer.raw_bits(), config.raw_bits()
])[bus.adr].eq(bus.dat_w),
If(bus.adr == 0, # data register
pending.eq(1),
If(bus.we,
Array([data_write, xfer.raw_bits(), config.raw_bits()
])[bus.adr].eq(bus.dat_w),
If(bus.adr == 0, # data register
pending.eq(1),
),
),
),
config.active.eq(spi.cs),
1 change: 0 additions & 1 deletion artiq/runtime/ksupport.c
Original file line number Diff line number Diff line change
@@ -124,7 +124,6 @@ static const struct symbol runtime_exports[] = {

{"rt2wb_output", &rt2wb_output},
{"rt2wb_input", &rt2wb_input},
{"rt2wb_input_sync", &rt2wb_input_sync},

{"cache_get", &cache_get},
{"cache_put", &cache_put},
38 changes: 7 additions & 31 deletions artiq/runtime/rt2wb.c
Original file line number Diff line number Diff line change
@@ -18,38 +18,14 @@ unsigned int rt2wb_input(int channel)
int status;

rtio_chan_sel_write(channel);
status = rtio_i_status_read();
if (status & RTIO_I_STATUS_OVERFLOW) {
rtio_i_overflow_reset_write(1);
artiq_raise_from_c("RTIOOverflow",
"RT2WB input overflow on channel {0}",
channel, 0, 0);
while((status = rtio_i_status_read())) {
if(status & RTIO_I_STATUS_OVERFLOW) {
rtio_i_overflow_reset_write(1);
artiq_raise_from_c("RTIOOverflow",
"RT2WB input overflow on channel {0}",
channel, 0, 0);
}
}
if (status & RTIO_I_STATUS_EMPTY)
artiq_raise_from_c("RTIOTimeout",
"RT2WB input timeout on channel {0}",
channel, 0, 0);

data = rtio_i_data_read();
rtio_i_re_write(1);
return data;
}


unsigned int rt2wb_input_sync(long long int timeout, int channel)
{
unsigned int data;
int status;

status = rtio_input_wait(timeout, channel);
if (status & RTIO_I_STATUS_OVERFLOW)
artiq_raise_from_c("RTIOOverflow",
"RT2WB input overflow on channel {0}",
channel, 0, 0);
if (status & RTIO_I_STATUS_EMPTY)
artiq_raise_from_c("RTIOTimeout",
"RT2WB input timeout on channel {0}",
channel, 0, 0);

data = rtio_i_data_read();
rtio_i_re_write(1);