rtio: when rtlink addresses are different, issue collision not replace (fixes #320)

This commit is contained in:
Sebastien Bourdeauducq 2016-03-08 15:58:25 +08:00
parent 71105fd0d7
commit 2953b069dc
2 changed files with 23 additions and 4 deletions

View File

@ -130,19 +130,23 @@ class _OutputManager(Module):
any_error = Signal() any_error = Signal()
nop = Signal() nop = Signal()
self.sync.rsys += [ self.sync.rsys += [
# Note: replace does not perform any RTLink address checks, # Note: replace may be asserted at the same time as collision
# i.e. a write to a different address will be silently replaced # when addresses are different. In that case, it is a collision.
# as well.
replace.eq(self.ev.timestamp == buf.timestamp), replace.eq(self.ev.timestamp == buf.timestamp),
# Detect sequence errors on coarse timestamps only # Detect sequence errors on coarse timestamps only
# so that they are mutually exclusive with collision errors. # so that they are mutually exclusive with collision errors.
sequence_error.eq(self.ev.timestamp[fine_ts_width:] sequence_error.eq(self.ev.timestamp[fine_ts_width:]
< buf.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: if fine_ts_width:
self.sync.rsys += collision.eq( 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])) & ((self.ev.timestamp[:fine_ts_width] != buf.timestamp[:fine_ts_width])
|different_addresses))
self.comb += any_error.eq(sequence_error | collision) self.comb += any_error.eq(sequence_error | collision)
if interface.suppress_nop: if interface.suppress_nop:
# disable NOP at reset: do not suppress a first write with all 0s # disable NOP at reset: do not suppress a first write with all 0s

View File

@ -163,6 +163,17 @@ class Collision(EnvExperiment):
delay_mu(1) 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): class TimeKeepsRunning(EnvExperiment):
def build(self): def build(self):
self.setattr_device("core") self.setattr_device("core")
@ -224,6 +235,10 @@ class CoredeviceTest(ExperimentCase):
with self.assertRaises(RTIOCollision): with self.assertRaises(RTIOCollision):
self.execute(Collision) self.execute(Collision)
def test_address_collision(self):
with self.assertRaises(RTIOCollision):
self.execute(AddressCollision)
def test_watchdog(self): def test_watchdog(self):
# watchdog only works on the device # watchdog only works on the device
with self.assertRaises(IOError): with self.assertRaises(IOError):