From 2953b069dcb42d849891ca5b4cb0b3000ae23470 Mon Sep 17 00:00:00 2001 From: Sebastien Bourdeauducq Date: Tue, 8 Mar 2016 15:58:25 +0800 Subject: [PATCH] rtio: when rtlink addresses are different, issue collision not replace (fixes #320) --- artiq/gateware/rtio/core.py | 12 ++++++++---- artiq/test/coredevice/test_rtio.py | 15 +++++++++++++++ 2 files changed, 23 insertions(+), 4 deletions(-) diff --git a/artiq/gateware/rtio/core.py b/artiq/gateware/rtio/core.py index 0f84769e6..8c2d1b237 100644 --- a/artiq/gateware/rtio/core.py +++ b/artiq/gateware/rtio/core.py @@ -130,19 +130,23 @@ class _OutputManager(Module): any_error = Signal() nop = Signal() self.sync.rsys += [ - # Note: replace does not perform any RTLink address checks, - # i.e. a write to a different address will be silently replaced - # as well. + # Note: replace may be asserted at the same time as collision + # when addresses are different. In that case, it is a collision. replace.eq(self.ev.timestamp == buf.timestamp), # Detect sequence errors on coarse timestamps only # so that they are mutually exclusive with collision errors. sequence_error.eq(self.ev.timestamp[fine_ts_width:] < buf.timestamp[fine_ts_width:]) ] + if hasattr(self.ev, "a"): + different_addresses = self.ev.a != buf.a + else: + different_addresses = 0 if fine_ts_width: self.sync.rsys += collision.eq( (self.ev.timestamp[fine_ts_width:] == buf.timestamp[fine_ts_width:]) - & (self.ev.timestamp[:fine_ts_width] != buf.timestamp[:fine_ts_width])) + & ((self.ev.timestamp[:fine_ts_width] != buf.timestamp[:fine_ts_width]) + |different_addresses)) self.comb += any_error.eq(sequence_error | collision) if interface.suppress_nop: # disable NOP at reset: do not suppress a first write with all 0s diff --git a/artiq/test/coredevice/test_rtio.py b/artiq/test/coredevice/test_rtio.py index 9caccc68b..8f5dcb48c 100644 --- a/artiq/test/coredevice/test_rtio.py +++ b/artiq/test/coredevice/test_rtio.py @@ -163,6 +163,17 @@ class Collision(EnvExperiment): delay_mu(1) +class AddressCollision(EnvExperiment): + def build(self): + self.setattr_device("core") + self.setattr_device("loop_in") + + @kernel + def run(self): + self.loop_in.input() + self.loop_in.pulse(10*us) + + class TimeKeepsRunning(EnvExperiment): def build(self): self.setattr_device("core") @@ -224,6 +235,10 @@ class CoredeviceTest(ExperimentCase): with self.assertRaises(RTIOCollision): self.execute(Collision) + def test_address_collision(self): + with self.assertRaises(RTIOCollision): + self.execute(AddressCollision) + def test_watchdog(self): # watchdog only works on the device with self.assertRaises(IOError):