rtio/sed: take global fine TS width

This commit is contained in:
Sebastien Bourdeauducq 2017-09-18 10:26:06 +08:00
parent 65baca8c57
commit 81d6317053
7 changed files with 28 additions and 27 deletions

View File

@ -1,6 +1,5 @@
from migen import * from migen import *
from artiq.gateware.rtio import rtlink
from artiq.gateware.rtio.sed import layouts from artiq.gateware.rtio.sed import layouts
from artiq.gateware.rtio.sed.lane_distributor import * from artiq.gateware.rtio.sed.lane_distributor import *
from artiq.gateware.rtio.sed.fifos import * from artiq.gateware.rtio.sed.fifos import *
@ -12,7 +11,8 @@ __all__ = ["SED"]
class SED(Module): 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): quash_channels=[], interface=None):
if mode == "sync": if mode == "sync":
lane_dist_cdr = lambda x: x lane_dist_cdr = lambda x: x
@ -27,13 +27,11 @@ class SED(Module):
else: else:
raise ValueError 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) seqn_width = layouts.seqn_width(lane_count, fifo_depth)
self.submodules.lane_dist = lane_dist_cdr( self.submodules.lane_dist = lane_dist_cdr(
LaneDistributor(lane_count, seqn_width, LaneDistributor(lane_count, seqn_width,
layouts.fifo_payload(channels), fine_ts_width, layouts.fifo_payload(channels), glbl_fine_ts_width,
enable_spread=enable_spread, enable_spread=enable_spread,
quash_channels=quash_channels, quash_channels=quash_channels,
interface=interface)) interface=interface))
@ -43,9 +41,9 @@ class SED(Module):
self.submodules.gates = gates_cdr( self.submodules.gates = gates_cdr(
Gates(lane_count, seqn_width, Gates(lane_count, seqn_width,
layouts.fifo_payload(channels), 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( 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): for o, i in zip(self.lane_dist.output, self.fifos.input):
self.comb += o.connect(i) self.comb += o.connect(i)

View File

@ -14,18 +14,18 @@ class Gates(Module):
for _ in range(lane_count)] for _ in range(lane_count)]
if hasattr(self.output[0].payload, "fine_ts"): 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: 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 input, output in zip(self.input, self.output):
for field, _ in output.payload.layout: for field, _ in output.payload.layout:
if field == "fine_ts": 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: else:
self.sync += getattr(output.payload, field).eq(getattr(input.payload, field)) self.sync += getattr(output.payload, field).eq(getattr(input.payload, field))
self.sync += output.seqn.eq(input.seqn) self.sync += output.seqn.eq(input.seqn)
@ -34,5 +34,5 @@ class Gates(Module):
output.nondata_replace_occured.eq(0) 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) self.sync += output.valid.eq(input.re & input.readable)

View File

@ -13,7 +13,7 @@ __all__ = ["LaneDistributor"]
# 3. check status # 3. check status
class LaneDistributor(Module): 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): enable_spread=True, quash_channels=[], interface=None):
if lane_count & (lane_count - 1): if lane_count & (lane_count - 1):
raise NotImplementedError("lane count must be a power of 2") raise NotImplementedError("lane count must be a power of 2")
@ -21,7 +21,7 @@ class LaneDistributor(Module):
if interface is None: if interface is None:
interface = cri.Interface() interface = cri.Interface()
self.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)) self.output = [Record(layouts.fifo_ingress(seqn_width, layout_payload))
for _ in range(lane_count)] for _ in range(lane_count)]
@ -35,8 +35,8 @@ class LaneDistributor(Module):
# internal state # internal state
current_lane = Signal(max=lane_count) current_lane = Signal(max=lane_count)
last_coarse_timestamp = Signal(64-fine_ts_width) last_coarse_timestamp = Signal(64-glbl_fine_ts_width)
last_lane_coarse_timestamps = Array(Signal(64-fine_ts_width) last_lane_coarse_timestamps = Array(Signal(64-glbl_fine_ts_width)
for _ in range(lane_count)) for _ in range(lane_count))
seqn = Signal(seqn_width) seqn = Signal(seqn_width)
@ -53,8 +53,8 @@ class LaneDistributor(Module):
self.comb += lio.payload.data.eq(self.cri.o_data) self.comb += lio.payload.data.eq(self.cri.o_data)
# when timestamp and channel arrive in cycle #1, prepare computations # when timestamp and channel arrive in cycle #1, prepare computations
coarse_timestamp = Signal(64-fine_ts_width) coarse_timestamp = Signal(64-glbl_fine_ts_width)
self.comb += coarse_timestamp.eq(self.cri.timestamp[fine_ts_width:]) self.comb += coarse_timestamp.eq(self.cri.timestamp[glbl_fine_ts_width:])
timestamp_above_min = Signal() timestamp_above_min = Signal()
timestamp_above_laneA_min = Signal() timestamp_above_laneA_min = Signal()
timestamp_above_laneB_min = Signal() timestamp_above_laneB_min = Signal()

View File

@ -45,17 +45,20 @@ def fifo_egress(seqn_width, layout_payload):
] ]
def output_network_payload(channels): # We use glbl_fine_ts_width in the output network so that collisions due
fine_ts_width = max(rtlink.get_fine_ts_width(channel.interface.o) # to insufficiently increasing timestamps are always reliably detected.
for channel in channels) # 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) address_width = max(rtlink.get_address_width(channel.interface.o)
for channel in channels) for channel in channels)
data_width = max(rtlink.get_data_width(channel.interface.o) data_width = max(rtlink.get_data_width(channel.interface.o)
for channel in channels) for channel in channels)
layout = [("channel", bits_for(len(channels)-1))] layout = [("channel", bits_for(len(channels)-1))]
if fine_ts_width: if glbl_fine_ts_width:
layout.append(("fine_ts", fine_ts_width)) layout.append(("fine_ts", glbl_fine_ts_width))
if address_width: if address_width:
layout.append(("address", address_width)) layout.append(("address", address_width))
if data_width: if data_width:

View File

@ -11,14 +11,14 @@ __all__ = ["OutputDriver"]
class OutputDriver(Module): 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 = Signal()
self.collision_channel = Signal(max=len(channels)) self.collision_channel = Signal(max=len(channels))
self.busy = Signal() self.busy = Signal()
self.busy_channel = Signal(max=len(channels)) self.busy_channel = Signal(max=len(channels))
# output network # 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) output_network = OutputNetwork(lane_count, seqn_width, layout_on_payload)
self.submodules += output_network self.submodules += output_network
self.input = output_network.input self.input = output_network.input

View File

@ -37,7 +37,7 @@ class DUT(Module):
] ]
self.submodules.output_driver = output_driver.OutputDriver( 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): def simulate(input_events):

View File

@ -22,7 +22,7 @@ class DUT(Module):
rtio.Channel.from_phy(self.phy1) rtio.Channel.from_phy(self.phy1)
] ]
self.submodules.sed = SED(rtio_channels, "sync") self.submodules.sed = SED(rtio_channels, 0, "sync")
self.sync += [ self.sync += [
self.sed.coarse_timestamp.eq(self.sed.coarse_timestamp + 1), self.sed.coarse_timestamp.eq(self.sed.coarse_timestamp + 1),
self.sed.minimum_coarse_timestamp.eq(self.sed.coarse_timestamp + 16) self.sed.minimum_coarse_timestamp.eq(self.sed.coarse_timestamp + 16)