rtio/sed: take global fine TS width

pull/889/head
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 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)

View File

@ -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)

View File

@ -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()

View File

@ -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:

View File

@ -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

View File

@ -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):

View File

@ -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)