forked from M-Labs/artiq
1
0
Fork 0

drtio: introduce 'standard request' interface in RT packet layer

This commit is contained in:
Sebastien Bourdeauducq 2017-03-13 00:08:03 +08:00
parent 2b8729f326
commit 6b7c781ff2
2 changed files with 84 additions and 72 deletions

View File

@ -100,13 +100,13 @@ class RTController(Module):
fifo_spaces.adr.eq(chan_sel),
last_timestamps.adr.eq(chan_sel),
last_timestamps.dat_w.eq(self.cri.timestamp),
rt_packets.write_channel.eq(chan_sel),
rt_packets.write_address.eq(self.cri.o_address),
rt_packets.write_data.eq(self.cri.o_data),
rt_packets.sr_channel.eq(chan_sel),
rt_packets.sr_address.eq(self.cri.o_address),
rt_packets.sr_data.eq(self.cri.o_data),
rt_packets.sr_timestamp.eq(self.cri.timestamp),
If(rt_packets_fifo_request,
rt_packets.write_timestamp.eq(0xffff000000000000)
).Else(
rt_packets.write_timestamp.eq(self.cri.timestamp)
rt_packets.sr_notwrite.eq(1),
rt_packets.sr_address.eq(0)
)
]
@ -159,8 +159,8 @@ class RTController(Module):
)
fsm.act("WRITE",
status_wait.eq(1),
rt_packets.write_stb.eq(1),
If(rt_packets.write_ack,
rt_packets.sr_stb.eq(1),
If(rt_packets.sr_ack,
fifo_spaces.we.eq(1),
fifo_spaces.dat_w.eq(fifo_spaces.dat_r - 1),
last_timestamps.we.eq(1),
@ -174,9 +174,9 @@ class RTController(Module):
fsm.act("GET_FIFO_SPACE",
status_wait.eq(1),
rt_packets_fifo_request.eq(1),
rt_packets.write_stb.eq(1),
rt_packets.sr_stb.eq(1),
rt_packets.fifo_space_not_ack.eq(1),
If(rt_packets.write_ack,
If(rt_packets.sr_ack,
NextState("GET_FIFO_SPACE_REPLY")
)
)
@ -211,7 +211,7 @@ class RTController(Module):
)
]
self.sync += \
If((rt_packets.write_stb & rt_packets.write_ack & rt_packets_fifo_request),
If((rt_packets.sr_stb & rt_packets.sr_ack & rt_packets_fifo_request),
self.csrs.o_dbg_fifo_space_req_cnt.status.eq(
self.csrs.o_dbg_fifo_space_req_cnt.status + 1)
)

View File

@ -61,20 +61,28 @@ class _CrossDomainNotification(Module):
class RTPacketMaster(Module):
def __init__(self, link_layer, write_fifo_depth=4):
def __init__(self, link_layer, sr_fifo_depth=4):
# all interface signals in sys domain unless otherwise specified
# write interface, optimized for throughput
self.write_stb = Signal()
self.write_ack = Signal()
self.write_timestamp = Signal(64)
self.write_channel = Signal(16)
self.write_address = Signal(16)
self.write_data = Signal(512)
# standard request interface
#
# notwrite=1 address=0 FIFO space request <channel>
# notwrite=1 address=1 read request <channel, timestamp>
# notwrite=1 address=2 read consume
#
# optimized for write throughput
# requests are performed on the DRTIO link preserving their order of issue
# this is important for FIFO space requests, which have to be ordered
# wrt writes.
self.sr_stb = Signal()
self.sr_ack = Signal()
self.sr_notwrite = Signal()
self.sr_timestamp = Signal(64)
self.sr_channel = Signal(16)
self.sr_address = Signal(16)
self.sr_data = Signal(512)
# fifo space interface
# write with timestamp[48:] == 0xffff to make a fifo space request
# (space requests have to be ordered wrt writes)
# fifo space reply interface
self.fifo_space_not = Signal()
self.fifo_space_not_ack = Signal()
self.fifo_space = Signal(16)
@ -122,63 +130,66 @@ class RTPacketMaster(Module):
self.submodules += rx_dp
# Write FIFO and extra data count
wfifo = ClockDomainsRenamer({"write": "sys_with_rst", "read": "rtio_with_rst"})(
AsyncFIFO(64+16+16+512, write_fifo_depth))
self.submodules += wfifo
write_timestamp_d = Signal(64)
write_channel_d = Signal(16)
write_address_d = Signal(16)
write_data_d = Signal(512)
sr_fifo = ClockDomainsRenamer({"write": "sys_with_rst", "read": "rtio_with_rst"})(
AsyncFIFO(1+64+16+16+512, sr_fifo_depth))
self.submodules += sr_fifo
sr_notwrite_d = Signal()
sr_timestamp_d = Signal(64)
sr_channel_d = Signal(16)
sr_address_d = Signal(16)
sr_data_d = Signal(512)
self.comb += [
wfifo.we.eq(self.write_stb),
self.write_ack.eq(wfifo.writable),
wfifo.din.eq(Cat(self.write_timestamp, self.write_channel,
self.write_address, self.write_data)),
Cat(write_timestamp_d, write_channel_d,
write_address_d, write_data_d).eq(wfifo.dout)
sr_fifo.we.eq(self.sr_stb),
self.sr_ack.eq(sr_fifo.writable),
sr_fifo.din.eq(Cat(self.sr_notwrite, self.sr_timestamp, self.sr_channel,
self.sr_address, self.sr_data)),
Cat(sr_notwrite_d, sr_timestamp_d, sr_channel_d,
sr_address_d, sr_data_d).eq(sr_fifo.dout)
]
wfb_readable = Signal()
wfb_re = Signal()
sr_buf_readable = Signal()
sr_buf_re = Signal()
self.comb += wfifo.re.eq(wfifo.readable & (~wfb_readable | wfb_re))
self.comb += sr_fifo.re.eq(sr_fifo.readable & (~sr_buf_readable | sr_buf_re))
self.sync.rtio += \
If(wfifo.re,
wfb_readable.eq(1),
).Elif(wfb_re,
wfb_readable.eq(0),
If(sr_fifo.re,
sr_buf_readable.eq(1),
).Elif(sr_buf_re,
sr_buf_readable.eq(0),
)
write_timestamp = Signal(64)
write_channel = Signal(16)
write_address = Signal(16)
write_extra_data_cnt = Signal(8)
write_data = Signal(512)
sr_notwrite = Signal()
sr_timestamp = Signal(64)
sr_channel = Signal(16)
sr_address = Signal(16)
sr_extra_data_cnt = Signal(8)
sr_data = Signal(512)
self.sync.rtio += If(wfifo.re,
write_timestamp.eq(write_timestamp_d),
write_channel.eq(write_channel_d),
write_address.eq(write_address_d),
write_data.eq(write_data_d))
self.sync.rtio += If(sr_fifo.re,
sr_notwrite.eq(sr_notwrite_d),
sr_timestamp.eq(sr_timestamp_d),
sr_channel.eq(sr_channel_d),
sr_address.eq(sr_address_d),
sr_data.eq(sr_data_d))
short_data_len = tx_plm.field_length("write", "short_data")
write_extra_data_d = Signal(512)
self.comb += write_extra_data_d.eq(write_data_d[short_data_len:])
sr_extra_data_d = Signal(512)
self.comb += sr_extra_data_d.eq(sr_data_d[short_data_len:])
for i in range(512//ws):
self.sync.rtio += If(wfifo.re,
If(write_extra_data_d[ws*i:ws*(i+1)] != 0, write_extra_data_cnt.eq(i+1)))
self.sync.rtio += If(sr_fifo.re,
If(sr_extra_data_d[ws*i:ws*(i+1)] != 0, sr_extra_data_cnt.eq(i+1)))
write_extra_data = Signal(512)
self.sync.rtio += If(wfifo.re, write_extra_data.eq(write_extra_data_d))
sr_extra_data = Signal(512)
self.sync.rtio += If(sr_fifo.re, sr_extra_data.eq(sr_extra_data_d))
extra_data_ce = Signal()
extra_data_last = Signal()
extra_data_counter = Signal(max=512//ws+1)
self.comb += [
Case(extra_data_counter,
{i+1: tx_dp.raw_data.eq(write_extra_data[i*ws:(i+1)*ws])
{i+1: tx_dp.raw_data.eq(sr_extra_data[i*ws:(i+1)*ws])
for i in range(512//ws)}),
extra_data_last.eq(extra_data_counter == write_extra_data_cnt)
extra_data_last.eq(extra_data_counter == sr_extra_data_cnt)
]
self.sync.rtio += \
If(extra_data_ce,
@ -230,8 +241,9 @@ class RTPacketMaster(Module):
self.sync.rtio += If(tsc_value_load, tsc_value.eq(self.tsc_value))
tx_fsm.act("IDLE",
If(wfb_readable,
If(write_timestamp[48:] == 0xffff,
If(sr_buf_readable,
If(sr_notwrite,
# TODO: sr_address
NextState("FIFO_SPACE")
).Else(
NextState("WRITE")
@ -250,14 +262,14 @@ class RTPacketMaster(Module):
)
tx_fsm.act("WRITE",
tx_dp.send("write",
timestamp=write_timestamp,
channel=write_channel,
address=write_address,
extra_data_cnt=write_extra_data_cnt,
short_data=write_data[:short_data_len]),
timestamp=sr_timestamp,
channel=sr_channel,
address=sr_address,
extra_data_cnt=sr_extra_data_cnt,
short_data=sr_data[:short_data_len]),
If(tx_dp.packet_last,
If(write_extra_data_cnt == 0,
wfb_re.eq(1),
If(sr_extra_data_cnt == 0,
sr_buf_re.eq(1),
NextState("IDLE")
).Else(
NextState("WRITE_EXTRA")
@ -268,14 +280,14 @@ class RTPacketMaster(Module):
tx_dp.raw_stb.eq(1),
extra_data_ce.eq(1),
If(extra_data_last,
wfb_re.eq(1),
sr_buf_re.eq(1),
NextState("IDLE")
)
)
tx_fsm.act("FIFO_SPACE",
tx_dp.send("fifo_space_request", channel=write_channel),
tx_dp.send("fifo_space_request", channel=sr_channel),
If(tx_dp.packet_last,
wfb_re.eq(1),
sr_buf_re.eq(1),
NextState("IDLE")
)
)