mirror of https://github.com/m-labs/artiq.git
rtio/sed: take global fine TS width
This commit is contained in:
parent
65baca8c57
commit
81d6317053
|
@ -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)
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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()
|
||||||
|
|
|
@ -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:
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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):
|
||||||
|
|
|
@ -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)
|
||||||
|
|
Loading…
Reference in New Issue