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: b32217cc84c5
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: cb6c28006c55
Choose a head ref
  • 16 commits
  • 8 files changed
  • 1 contributor

Commits on Mar 8, 2016

  1. rtio: add RTIOBusy

    jordens committed Mar 8, 2016
    Copy the full SHA
    2cb5859 View commit details

Commits on Mar 9, 2016

  1. Merge commit '9d1903a' into rtiobusy

    * commit '9d1903a':
      coredevice/i2c,ttl,spi: consistent device get
      examples/device_db: remove --no-localhost-bind
      Monkey-patch asyncio create_server (fixes #253).
      pipistrello: drop ttls on pmod, add leds back in
      pipistrello: try with fewer leds/pmod ttl
    jordens committed Mar 9, 2016
    Copy the full SHA
    446dcfb View commit details
  2. Copy the full SHA
    b0de9ee View commit details
  3. Copy the full SHA
    522ec60 View commit details
  4. spi: fix frequency_to_div()

    jordens committed Mar 9, 2016
    Copy the full SHA
    0bd9add View commit details
  5. rtio: remove unused include

    jordens committed Mar 9, 2016
    Copy the full SHA
    db52312 View commit details
  6. Copy the full SHA
    bf188d0 View commit details
  7. tests: test spi business

    jordens committed Mar 9, 2016
    Copy the full SHA
    58e0e67 View commit details
  8. Copy the full SHA
    b50e3fa View commit details
  9. Copy the full SHA
    9a661bd View commit details
  10. Copy the full SHA
    8f6653e View commit details
  11. Merge branch 'master' into rtiobusy

    * master:
      coredevice: fix _DDSGeneric __init__ args
      rtio/core: fix syntax
      rtio: disable replace on rt2wb channels
      examples: dds_bus -> core_dds
      fix more multi-DDS-bus problems
      runtime: fix dds declarations
      support for multiple DDS buses (untested)
    jordens committed Mar 9, 2016
    Copy the full SHA
    349a661 View commit details
  12. test_spi: break_realtime

    jordens committed Mar 9, 2016
    Copy the full SHA
    10a0912 View commit details
  13. Copy the full SHA
    107e5cf View commit details
  14. exceptions: clarify RTIOBusy

    jordens committed Mar 9, 2016
    Copy the full SHA
    9edaf16 View commit details
  15. Merge branch 'rtiobusy' (closes #308)

    * rtiobusy:
      exceptions: clarify RTIOBusy
      gateware/rtio: factor _BlindTransfer
      test_spi: break_realtime
      test_spi: simplify test, add collision vs busy test
      hardware_testbench: clean up artiq_core_exeption printing
      hardware_testbench: also print artiq_core_exeption
      tests: test spi business
      rtio: cleanup RTIOBusy message
      rtio: remove unused include
      spi: fix frequency_to_div()
      hardware_testbench: don't allow unused *args
      coredevice: add RTIOBusy to __all__
      rtio: add RTIOBusy
    jordens committed Mar 9, 2016
    Copy the full SHA
    cb6c280 View commit details
4 changes: 2 additions & 2 deletions artiq/coredevice/__init__.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
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)

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

class RTIOBusy(Exception):
"""Raised when at least one output event could not be executed because
the given channel was already busy executing a previous event.
This exception is raised late: after the error condition occurred. 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 was discarded.
"""
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).
4 changes: 2 additions & 2 deletions artiq/coredevice/spi.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from artiq.language.core import (kernel, portable, seconds_to_mu, now_mu,
delay_mu, int)
delay_mu, int, mu_to_seconds)
from artiq.language.units import MHz
from artiq.coredevice.rtio import rtio_output, rtio_input_data

@@ -58,7 +58,7 @@ def __init__(self, dmgr, channel, core_device="core"):

@portable
def frequency_to_div(self, f):
return int(1/(f*self.ref_period)) + 1
return int(1/(f*mu_to_seconds(self.ref_period_mu))) + 1

@kernel
def set_config(self, flags=0, write_freq=20*MHz, read_freq=20*MHz):
59 changes: 43 additions & 16 deletions artiq/gateware/rtio/core.py
Original file line number Diff line number Diff line change
@@ -54,6 +54,26 @@ def __init__(self, width):
self.comb += gt.i.eq(self.value_rtio), self.value_sys.eq(gt.o)


class _BlindTransfer(Module):
def __init__(self):
self.i = Signal()
self.o = Signal()

ps = PulseSynchronizer("rio", "rsys")
ps_ack = PulseSynchronizer("rsys", "rio")
self.submodules += ps, ps_ack
blind = Signal()
self.sync.rio += [
If(self.i, blind.eq(1)),
If(ps_ack.o, blind.eq(0))
]
self.comb += [
ps.i.eq(self.i & ~blind),
ps_ack.i.eq(ps.o),
self.o.eq(ps.o)
]


# CHOOSING A GUARD TIME
#
# The buffer must be transferred to the FIFO soon enough to account for:
@@ -104,6 +124,7 @@ def __init__(self, interface, counter, fifo_depth, guard_io_cycles):
self.underflow = Signal() # valid 1 cycle after we, pulsed
self.sequence_error = Signal()
self.collision = Signal()
self.busy = Signal() # pulsed

# # #

@@ -220,12 +241,19 @@ def __init__(self, interface, counter, fifo_depth, guard_io_cycles):
self.comb += fifo.re.eq(fifo.readable & (~dout_stb | dout_ack))

# FIFO read through buffer
# TODO: report error on stb & busy
self.comb += [
dout_ack.eq(
dout.timestamp[fine_ts_width:] == counter.value_rtio),
interface.stb.eq(dout_stb & dout_ack)
]

busy_transfer = _BlindTransfer()
self.submodules += busy_transfer
self.comb += [
busy_transfer.i.eq(interface.stb & interface.busy),
self.busy.eq(busy_transfer.o),
]

if data_width:
self.comb += interface.data.eq(dout.data)
if address_width:
@@ -248,7 +276,7 @@ def __init__(self, interface, counter, fifo_depth):

self.readable = Signal()
self.re = Signal()

self.overflow = Signal() # pulsed

# # #
@@ -281,18 +309,11 @@ def __init__(self, interface, counter, fifo_depth):
fifo.re.eq(self.re)
]

overflow_sync = PulseSynchronizer("rio", "rsys")
overflow_ack_sync = PulseSynchronizer("rsys", "rio")
self.submodules += overflow_sync, overflow_ack_sync
overflow_blind = Signal()
self.comb += overflow_sync.i.eq(fifo.we & ~fifo.writable & ~overflow_blind)
self.sync.rio += [
If(fifo.we & ~fifo.writable, overflow_blind.eq(1)),
If(overflow_ack_sync.o, overflow_blind.eq(0))
]
overflow_transfer = _BlindTransfer()
self.submodules += overflow_transfer
self.comb += [
overflow_ack_sync.i.eq(overflow_sync.o),
self.overflow.eq(overflow_sync.o)
overflow_transfer.i.eq(fifo.we & ~fifo.writable),
self.overflow.eq(overflow_transfer.o),
]


@@ -339,10 +360,11 @@ def __init__(self, chan_sel_width,
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)
@@ -430,21 +452,26 @@ def __init__(self, channels, full_ts_width=63, guard_io_cycles=20):
underflow = Signal()
sequence_error = Signal()
collision = Signal()
busy = Signal()
self.sync.rsys += [
If(selected & self.kcsrs.o_underflow_reset.re,
underflow.eq(0)),
If(selected & self.kcsrs.o_sequence_error_reset.re,
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,
6 changes: 6 additions & 0 deletions artiq/runtime/rtio.c
Original file line number Diff line number Diff line change
@@ -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 on channel {0}",
channel, 0, 0);
}
}


1 change: 1 addition & 0 deletions artiq/runtime/rtio.h
Original file line number Diff line number Diff line change
@@ -7,6 +7,7 @@
#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

45 changes: 45 additions & 0 deletions artiq/test/coredevice/test_spi.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
from artiq.experiment import *
from artiq.test.hardware_testbench import ExperimentCase


class Collision(EnvExperiment):
def build(self):
self.setattr_device("core")
self.setattr_device("spi0")

@kernel
def run(self):
self.core.break_realtime()
t = now_mu()
self.spi0.set_config_mu()
at_mu(t)
self.spi0.set_config_mu()


class Busy(EnvExperiment):
def build(self):
self.setattr_device("core")
self.setattr_device("spi0")
self.setattr_device("led")

@kernel
def run(self):
self.core.break_realtime()
t = now_mu()
self.spi0.set_config_mu()
at_mu(t + self.spi0.ref_period_mu)
self.spi0.set_config_mu() # causes the error
self.led.on()
self.led.sync() # registers the error
self.core.break_realtime()
self.spi0.set_config_mu() # raises the error


class SPITest(ExperimentCase):
def test_collision(self):
with self.assertRaises(RTIOCollision):
self.execute(Collision)

def test_busy(self):
with self.assertRaises(RTIOBusy):
self.execute(Busy)
7 changes: 6 additions & 1 deletion artiq/test/hardware_testbench.py
Original file line number Diff line number Diff line change
@@ -109,7 +109,7 @@ def create(self, cls, **kwargs):
# skip if ddb does not match requirements
raise unittest.SkipTest(*e.args)

def execute(self, cls, *args, **kwargs):
def execute(self, cls, **kwargs):
expid = {
"file": sys.modules[cls.__module__].__file__,
"class_name": cls.__name__,
@@ -124,3 +124,8 @@ def execute(self, cls, *args, **kwargs):
except CompileError as error:
# Reduce amount of text on terminal.
raise error from None
except Exception as exn:
if hasattr(exn, "artiq_core_exception"):
exn.args = "{}\n{}".format(exn.args[0],
exn.artiq_core_exception),
raise exn