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

View File

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