From 81d6317053dcc97a8f219b8b9f8da3113b9468d9 Mon Sep 17 00:00:00 2001 From: Sebastien Bourdeauducq Date: Mon, 18 Sep 2017 10:26:06 +0800 Subject: [PATCH] rtio/sed: take global fine TS width --- artiq/gateware/rtio/sed/core.py | 12 +++++------- artiq/gateware/rtio/sed/gates.py | 10 +++++----- artiq/gateware/rtio/sed/lane_distributor.py | 12 ++++++------ artiq/gateware/rtio/sed/layouts.py | 13 ++++++++----- artiq/gateware/rtio/sed/output_driver.py | 4 ++-- artiq/gateware/test/rtio/test_sed_output_driver.py | 2 +- artiq/gateware/test/rtio/test_sed_top.py | 2 +- 7 files changed, 28 insertions(+), 27 deletions(-) diff --git a/artiq/gateware/rtio/sed/core.py b/artiq/gateware/rtio/sed/core.py index 55a068c4b..3cea2cf85 100644 --- a/artiq/gateware/rtio/sed/core.py +++ b/artiq/gateware/rtio/sed/core.py @@ -1,6 +1,5 @@ from migen import * -from artiq.gateware.rtio import rtlink from artiq.gateware.rtio.sed import layouts from artiq.gateware.rtio.sed.lane_distributor import * from artiq.gateware.rtio.sed.fifos import * @@ -12,7 +11,8 @@ __all__ = ["SED"] class SED(Module): - def __init__(self, channels, mode, lane_count=8, fifo_depth=128, enable_spread=True, + def __init__(self, channels, glbl_fine_ts_width, mode, + lane_count=8, fifo_depth=128, enable_spread=True, quash_channels=[], interface=None): if mode == "sync": lane_dist_cdr = lambda x: x @@ -27,13 +27,11 @@ class SED(Module): else: raise ValueError - fine_ts_width = max(rtlink.get_fine_ts_width(c.interface.o) - for c in channels) seqn_width = layouts.seqn_width(lane_count, fifo_depth) self.submodules.lane_dist = lane_dist_cdr( LaneDistributor(lane_count, seqn_width, - layouts.fifo_payload(channels), fine_ts_width, + layouts.fifo_payload(channels), glbl_fine_ts_width, enable_spread=enable_spread, quash_channels=quash_channels, interface=interface)) @@ -43,9 +41,9 @@ class SED(Module): self.submodules.gates = gates_cdr( Gates(lane_count, seqn_width, layouts.fifo_payload(channels), - layouts.output_network_payload(channels))) + layouts.output_network_payload(channels, glbl_fine_ts_width))) self.submodules.output_driver = output_driver_cdr( - OutputDriver(channels, lane_count, seqn_width)) + OutputDriver(channels, glbl_fine_ts_width, lane_count, seqn_width)) for o, i in zip(self.lane_dist.output, self.fifos.input): self.comb += o.connect(i) diff --git a/artiq/gateware/rtio/sed/gates.py b/artiq/gateware/rtio/sed/gates.py index 8d0f604e4..9b1c27d23 100644 --- a/artiq/gateware/rtio/sed/gates.py +++ b/artiq/gateware/rtio/sed/gates.py @@ -14,18 +14,18 @@ class Gates(Module): for _ in range(lane_count)] if hasattr(self.output[0].payload, "fine_ts"): - fine_ts_width = len(self.output[0].payload.fine_ts) + glbl_fine_ts_width = len(self.output[0].payload.fine_ts) else: - fine_ts_width = 0 + glbl_fine_ts_width = 0 - self.coarse_timestamp = Signal(64-fine_ts_width) + self.coarse_timestamp = Signal(64-glbl_fine_ts_width) # # # for input, output in zip(self.input, self.output): for field, _ in output.payload.layout: if field == "fine_ts": - self.sync += output.payload.fine_ts.eq(input.payload.timestamp[:fine_ts_width]) + self.sync += output.payload.fine_ts.eq(input.payload.timestamp[:glbl_fine_ts_width]) else: self.sync += getattr(output.payload, field).eq(getattr(input.payload, field)) self.sync += output.seqn.eq(input.seqn) @@ -34,5 +34,5 @@ class Gates(Module): output.nondata_replace_occured.eq(0) ] - self.comb += input.re.eq(input.payload.timestamp[fine_ts_width:] == self.coarse_timestamp) + self.comb += input.re.eq(input.payload.timestamp[glbl_fine_ts_width:] == self.coarse_timestamp) self.sync += output.valid.eq(input.re & input.readable) diff --git a/artiq/gateware/rtio/sed/lane_distributor.py b/artiq/gateware/rtio/sed/lane_distributor.py index 986d7a470..436e59695 100644 --- a/artiq/gateware/rtio/sed/lane_distributor.py +++ b/artiq/gateware/rtio/sed/lane_distributor.py @@ -13,7 +13,7 @@ __all__ = ["LaneDistributor"] # 3. check status class LaneDistributor(Module): - def __init__(self, lane_count, seqn_width, layout_payload, fine_ts_width, + def __init__(self, lane_count, seqn_width, layout_payload, glbl_fine_ts_width, enable_spread=True, quash_channels=[], interface=None): if lane_count & (lane_count - 1): raise NotImplementedError("lane count must be a power of 2") @@ -21,7 +21,7 @@ class LaneDistributor(Module): if interface is None: interface = cri.Interface() self.cri = interface - self.minimum_coarse_timestamp = Signal(64-fine_ts_width) + self.minimum_coarse_timestamp = Signal(64-glbl_fine_ts_width) self.output = [Record(layouts.fifo_ingress(seqn_width, layout_payload)) for _ in range(lane_count)] @@ -35,8 +35,8 @@ class LaneDistributor(Module): # internal state current_lane = Signal(max=lane_count) - last_coarse_timestamp = Signal(64-fine_ts_width) - last_lane_coarse_timestamps = Array(Signal(64-fine_ts_width) + last_coarse_timestamp = Signal(64-glbl_fine_ts_width) + last_lane_coarse_timestamps = Array(Signal(64-glbl_fine_ts_width) for _ in range(lane_count)) seqn = Signal(seqn_width) @@ -53,8 +53,8 @@ class LaneDistributor(Module): self.comb += lio.payload.data.eq(self.cri.o_data) # when timestamp and channel arrive in cycle #1, prepare computations - coarse_timestamp = Signal(64-fine_ts_width) - self.comb += coarse_timestamp.eq(self.cri.timestamp[fine_ts_width:]) + coarse_timestamp = Signal(64-glbl_fine_ts_width) + self.comb += coarse_timestamp.eq(self.cri.timestamp[glbl_fine_ts_width:]) timestamp_above_min = Signal() timestamp_above_laneA_min = Signal() timestamp_above_laneB_min = Signal() diff --git a/artiq/gateware/rtio/sed/layouts.py b/artiq/gateware/rtio/sed/layouts.py index b49e1139b..1fbb8f6ec 100644 --- a/artiq/gateware/rtio/sed/layouts.py +++ b/artiq/gateware/rtio/sed/layouts.py @@ -45,17 +45,20 @@ def fifo_egress(seqn_width, layout_payload): ] -def output_network_payload(channels): - fine_ts_width = max(rtlink.get_fine_ts_width(channel.interface.o) - for channel in channels) +# We use glbl_fine_ts_width in the output network so that collisions due +# to insufficiently increasing timestamps are always reliably detected. +# We can still have undetected collisions on the address by making it wrap +# around, but those are more rare and easier to debug, and addresses are +# not normally exposed directly to the ARTIQ user. +def output_network_payload(channels, glbl_fine_ts_width): address_width = max(rtlink.get_address_width(channel.interface.o) for channel in channels) data_width = max(rtlink.get_data_width(channel.interface.o) for channel in channels) layout = [("channel", bits_for(len(channels)-1))] - if fine_ts_width: - layout.append(("fine_ts", fine_ts_width)) + if glbl_fine_ts_width: + layout.append(("fine_ts", glbl_fine_ts_width)) if address_width: layout.append(("address", address_width)) if data_width: diff --git a/artiq/gateware/rtio/sed/output_driver.py b/artiq/gateware/rtio/sed/output_driver.py index 7f26ec58a..3150e98b6 100644 --- a/artiq/gateware/rtio/sed/output_driver.py +++ b/artiq/gateware/rtio/sed/output_driver.py @@ -11,14 +11,14 @@ __all__ = ["OutputDriver"] class OutputDriver(Module): - def __init__(self, channels, lane_count, seqn_width): + def __init__(self, channels, glbl_fine_ts_width, lane_count, seqn_width): self.collision = Signal() self.collision_channel = Signal(max=len(channels)) self.busy = Signal() self.busy_channel = Signal(max=len(channels)) # output network - layout_on_payload = layouts.output_network_payload(channels) + layout_on_payload = layouts.output_network_payload(channels, glbl_fine_ts_width) output_network = OutputNetwork(lane_count, seqn_width, layout_on_payload) self.submodules += output_network self.input = output_network.input diff --git a/artiq/gateware/test/rtio/test_sed_output_driver.py b/artiq/gateware/test/rtio/test_sed_output_driver.py index 44e478e42..4da3bd463 100644 --- a/artiq/gateware/test/rtio/test_sed_output_driver.py +++ b/artiq/gateware/test/rtio/test_sed_output_driver.py @@ -37,7 +37,7 @@ class DUT(Module): ] self.submodules.output_driver = output_driver.OutputDriver( - rtio_channels, LANE_COUNT, 4*LANE_COUNT) + rtio_channels, 0, LANE_COUNT, 4*LANE_COUNT) def simulate(input_events): diff --git a/artiq/gateware/test/rtio/test_sed_top.py b/artiq/gateware/test/rtio/test_sed_top.py index 25a65ae2a..2ed1f91a2 100644 --- a/artiq/gateware/test/rtio/test_sed_top.py +++ b/artiq/gateware/test/rtio/test_sed_top.py @@ -22,7 +22,7 @@ class DUT(Module): rtio.Channel.from_phy(self.phy1) ] - self.submodules.sed = SED(rtio_channels, "sync") + self.submodules.sed = SED(rtio_channels, 0, "sync") self.sync += [ self.sed.coarse_timestamp.eq(self.sed.coarse_timestamp + 1), self.sed.minimum_coarse_timestamp.eq(self.sed.coarse_timestamp + 16)