Skip to content

Commit 8090abe

Browse files
committedNov 25, 2016
drtio: large data support
1 parent 8b736dd commit 8090abe

File tree

1 file changed

+165
-80
lines changed

1 file changed

+165
-80
lines changed
 

Diff for: ‎artiq/gateware/drtio/rt_packets.py

+165-80
Original file line numberDiff line numberDiff line change
@@ -29,17 +29,29 @@ def add_type(self, name, *fields, pad=True):
2929
layout.append(("packet_pad", self.alignment - misalignment))
3030
self.layouts[name] = layout
3131

32+
def field_length(self, type_name, field_name):
33+
layout = self.layouts[type_name]
34+
for name, length in layout:
35+
if name == field_name:
36+
return length
37+
raise KeyError
38+
3239

3340
def get_m2s_layouts(alignment):
41+
if alignment > 128:
42+
short_data_len = alignment - 128 + 16
43+
else:
44+
short_data_len = 16
45+
3446
plm = PacketLayoutManager(alignment)
3547
plm.add_type("echo_request")
3648
plm.add_type("set_time", ("timestamp", 64))
3749
plm.add_type("reset", ("phy", 1))
3850
plm.add_type("write", ("timestamp", 64),
3951
("channel", 16),
4052
("address", 16),
41-
("data_len", 8),
42-
("short_data", 8))
53+
("extra_data_cnt", 8),
54+
("short_data", short_data_len))
4355
plm.add_type("fifo_space_request", ("channel", 16))
4456
return plm
4557

@@ -125,34 +137,33 @@ def __init__(self, frame, data, plm):
125137
self.ws = ws
126138
self.plm = plm
127139

128-
# inputs
129140
self.packet_buffer = Signal(max(layout_len(l)
130141
for l in plm.layouts.values()))
131142
w_in_packet = len(self.packet_buffer)//ws
132-
self.packet_len = Signal(max=w_in_packet+1)
143+
self.packet_last_n = Signal(max=w_in_packet)
144+
self.packet_stb = Signal()
145+
self.packet_last = Signal()
133146

134-
# control
135-
self.stb = Signal()
136-
self.done = Signal()
147+
self.raw_stb = Signal()
148+
self.raw_data = Signal(ws)
137149

138150
# # #
139151

140-
packet_buffer_count = Signal(max=w_in_packet+1)
152+
packet_buffer_count = Signal(max=w_in_packet)
153+
self.comb += self.packet_last.eq(packet_buffer_count == self.packet_last_n)
141154
self.sync += [
142-
self.done.eq(0),
143155
frame.eq(0),
144156
packet_buffer_count.eq(0),
145-
146-
If(self.stb & ~self.done,
147-
If(packet_buffer_count == self.packet_len,
148-
self.done.eq(1)
149-
).Else(
150-
frame.eq(1),
151-
Case(packet_buffer_count,
152-
{i: data.eq(self.packet_buffer[i*ws:(i+1)*ws])
153-
for i in range(w_in_packet)}),
154-
packet_buffer_count.eq(packet_buffer_count + 1)
155-
)
157+
If(self.packet_stb,
158+
frame.eq(1),
159+
Case(packet_buffer_count,
160+
{i: data.eq(self.packet_buffer[i*ws:(i+1)*ws])
161+
for i in range(w_in_packet)}),
162+
packet_buffer_count.eq(packet_buffer_count + 1)
163+
),
164+
If(self.raw_stb,
165+
frame.eq(1),
166+
data.eq(self.raw_data)
156167
)
157168
]
158169

@@ -170,8 +181,9 @@ def send(self, ty, **kwargs):
170181
if kwargs:
171182
raise ValueError
172183
return [
184+
self.packet_stb.eq(1),
173185
self.packet_buffer.eq(value),
174-
self.packet_len.eq(idx//self.ws)
186+
self.packet_last_n.eq(idx//self.ws-1)
175187
]
176188

177189

@@ -191,7 +203,7 @@ def __init__(self, link_layer):
191203
self.write_timestamp = Signal(64)
192204
self.write_channel = Signal(16)
193205
self.write_address = Signal(16)
194-
self.write_data = Signal(256)
206+
self.write_data = Signal(512)
195207
self.write_overflow = Signal()
196208
self.write_overflow_ack = Signal()
197209
self.write_underflow = Signal()
@@ -212,6 +224,20 @@ def __init__(self, link_layer):
212224
link_layer.tx_rt_frame, link_layer.tx_rt_data, tx_plm)
213225
self.submodules += tx_dp
214226

227+
# RX write data buffer
228+
write_data_buffer_load = Signal()
229+
write_data_buffer_cnt = Signal(max=512//ws+1)
230+
write_data_buffer = Signal(512)
231+
self.sync += \
232+
If(write_data_buffer_load,
233+
Case(write_data_buffer_cnt,
234+
{i: write_data_buffer[i*ws:(i+1)*ws].eq(link_layer.rx_rt_data)
235+
for i in range(512//ws)}),
236+
write_data_buffer_cnt.eq(write_data_buffer_cnt + 1)
237+
).Else(
238+
write_data_buffer_cnt.eq(0)
239+
)
240+
215241
# RX->TX
216242
echo_req = Signal()
217243
err_set = Signal()
@@ -241,7 +267,7 @@ def __init__(self, link_layer):
241267
self.write_address.eq(
242268
rx_dp.packet_as["write"].address),
243269
self.write_data.eq(
244-
rx_dp.packet_as["write"].short_data)
270+
Cat(rx_dp.packet_as["write"].short_data, write_data_buffer))
245271
]
246272

247273
reset = Signal()
@@ -287,8 +313,11 @@ def __init__(self, link_layer):
287313
NextState("INPUT")
288314
)
289315
rx_fsm.act("WRITE",
290-
self.write_stb.eq(1),
291-
NextState("INPUT")
316+
write_data_buffer_load.eq(1),
317+
If(write_data_buffer_cnt == rx_dp.packet_as["write"].extra_data_cnt,
318+
self.write_stb.eq(1),
319+
NextState("INPUT")
320+
)
292321
)
293322
rx_fsm.act("FIFO_SPACE",
294323
fifo_space_set.eq(1),
@@ -309,32 +338,27 @@ def __init__(self, link_layer):
309338
)
310339
tx_fsm.act("ECHO",
311340
tx_dp.send("echo_reply"),
312-
tx_dp.stb.eq(1),
313-
If(tx_dp.done, NextState("IDLE"))
341+
If(tx_dp.packet_last, NextState("IDLE"))
314342
)
315343
tx_fsm.act("FIFO_SPACE",
316344
fifo_space_ack.eq(1),
317345
tx_dp.send("fifo_space_reply", space=self.fifo_space),
318-
tx_dp.stb.eq(1),
319-
If(tx_dp.done, NextState("IDLE"))
346+
If(tx_dp.packet_last, NextState("IDLE"))
320347
)
321348
tx_fsm.act("ERROR_WRITE_OVERFLOW",
322349
self.write_overflow_ack.eq(1),
323350
tx_dp.send("error", code=error_codes["write_overflow"]),
324-
tx_dp.stb.eq(1),
325-
If(tx_dp.done, NextState("IDLE"))
351+
If(tx_dp.packet_last, NextState("IDLE"))
326352
)
327353
tx_fsm.act("ERROR_WRITE_UNDERFLOW",
328354
self.write_underflow_ack.eq(1),
329355
tx_dp.send("error", code=error_codes["write_underflow"]),
330-
tx_dp.stb.eq(1),
331-
If(tx_dp.done, NextState("IDLE"))
356+
If(tx_dp.packet_last, NextState("IDLE"))
332357
)
333358
tx_fsm.act("ERROR",
334359
err_ack.eq(1),
335360
tx_dp.send("error", code=err_code),
336-
tx_dp.stb.eq(1),
337-
If(tx_dp.done, NextState("IDLE"))
361+
If(tx_dp.packet_last, NextState("IDLE"))
338362
)
339363

340364

@@ -399,7 +423,7 @@ def __init__(self, link_layer, write_fifo_depth=4):
399423
self.write_timestamp = Signal(64)
400424
self.write_channel = Signal(16)
401425
self.write_address = Signal(16)
402-
self.write_data = Signal(256)
426+
self.write_data = Signal(512)
403427

404428
# fifo space interface
405429
# write with timestamp[48:] == 0xffff to make a fifo space request
@@ -437,23 +461,83 @@ def __init__(self, link_layer, write_fifo_depth=4):
437461

438462
# # #
439463

440-
# CDC
464+
# RX/TX datapath
465+
assert len(link_layer.tx_rt_data) == len(link_layer.rx_rt_data)
466+
assert len(link_layer.tx_rt_data) % 8 == 0
467+
ws = len(link_layer.tx_rt_data)
468+
tx_plm = get_m2s_layouts(ws)
469+
tx_dp = ClockDomainsRenamer("rtio")(TransmitDatapath(
470+
link_layer.tx_rt_frame, link_layer.tx_rt_data, tx_plm))
471+
self.submodules += tx_dp
472+
rx_plm = get_s2m_layouts(ws)
473+
rx_dp = ClockDomainsRenamer("rtio_rx")(ReceiveDatapath(
474+
link_layer.rx_rt_frame, link_layer.rx_rt_data, rx_plm))
475+
self.submodules += rx_dp
476+
477+
# Write FIFO and extra data count
441478
wfifo = ClockDomainsRenamer({"write": "sys", "read": "rtio"})(
442-
AsyncFIFO(64+16+16+256, write_fifo_depth))
479+
AsyncFIFO(64+16+16+512, write_fifo_depth))
443480
self.submodules += wfifo
444-
write_timestamp = Signal(64)
445-
write_channel = Signal(16)
446-
write_address = Signal(16)
447-
write_data = Signal(256)
481+
write_timestamp_d = Signal(64)
482+
write_channel_d = Signal(16)
483+
write_address_d = Signal(16)
484+
write_data_d = Signal(512)
448485
self.comb += [
449486
wfifo.we.eq(self.write_stb),
450487
self.write_ack.eq(wfifo.writable),
451488
wfifo.din.eq(Cat(self.write_timestamp, self.write_channel,
452489
self.write_address, self.write_data)),
453-
Cat(write_timestamp, write_channel,
454-
write_address, write_data).eq(wfifo.dout)
490+
Cat(write_timestamp_d, write_channel_d,
491+
write_address_d, write_data_d).eq(wfifo.dout)
492+
]
493+
494+
wfb_readable = Signal()
495+
wfb_re = Signal()
496+
497+
self.comb += wfifo.re.eq(wfifo.readable & (~wfb_readable | wfb_re))
498+
self.sync.rtio += \
499+
If(wfifo.re,
500+
wfb_readable.eq(1),
501+
).Elif(wfb_re,
502+
wfb_readable.eq(0),
503+
)
504+
505+
write_timestamp = Signal(64)
506+
write_channel = Signal(16)
507+
write_address = Signal(16)
508+
write_extra_data_cnt = Signal(8)
509+
write_data = Signal(512)
510+
511+
self.sync.rtio += If(wfifo.re,
512+
write_timestamp.eq(write_timestamp_d),
513+
write_channel.eq(write_channel_d),
514+
write_address.eq(write_address_d),
515+
write_data.eq(write_data_d))
516+
517+
short_data_len = tx_plm.field_length("write", "short_data")
518+
write_extra_data = Signal(512)
519+
self.comb += write_extra_data.eq(write_data[short_data_len:])
520+
for i in range(512//ws):
521+
self.sync.rtio += If(wfifo.re,
522+
If(write_extra_data[ws*i:ws*(i+1)] != 0, write_extra_data_cnt.eq(i+1)))
523+
524+
extra_data_ce = Signal()
525+
extra_data_last = Signal()
526+
extra_data_counter = Signal(max=512//ws+1)
527+
self.comb += [
528+
Case(extra_data_counter,
529+
{i+1: tx_dp.raw_data.eq(write_extra_data[i*ws:(i+1)*ws])
530+
for i in range(512//ws)}),
531+
extra_data_last.eq(extra_data_counter == write_extra_data_cnt)
455532
]
533+
self.sync.rtio += \
534+
If(extra_data_ce,
535+
extra_data_counter.eq(extra_data_counter + 1),
536+
).Else(
537+
extra_data_counter.eq(1)
538+
)
456539

540+
# CDC
457541
fifo_space_not = Signal()
458542
fifo_space = Signal(16)
459543
self.submodules += _CrossDomainNotification("rtio_rx",
@@ -485,21 +569,8 @@ def __init__(self, link_layer, write_fifo_depth=4):
485569
error_not, error_code,
486570
self.error_not, self.error_not_ack, self.error_code)
487571

488-
# RX/TX datapath
489-
assert len(link_layer.tx_rt_data) == len(link_layer.rx_rt_data)
490-
assert len(link_layer.tx_rt_data) % 8 == 0
491-
ws = len(link_layer.tx_rt_data)
492-
tx_plm = get_m2s_layouts(ws)
493-
tx_dp = ClockDomainsRenamer("rtio")(TransmitDatapath(
494-
link_layer.tx_rt_frame, link_layer.tx_rt_data, tx_plm))
495-
self.submodules += tx_dp
496-
rx_plm = get_s2m_layouts(ws)
497-
rx_dp = ClockDomainsRenamer("rtio_rx")(ReceiveDatapath(
498-
link_layer.rx_rt_frame, link_layer.rx_rt_data, rx_plm))
499-
self.submodules += rx_dp
500-
501572
# TX FSM
502-
tx_fsm = ClockDomainsRenamer("rtio")(FSM(reset_state="IDLE_WRITE"))
573+
tx_fsm = ClockDomainsRenamer("rtio")(FSM(reset_state="IDLE"))
503574
self.submodules += tx_fsm
504575

505576
echo_sent_now = Signal()
@@ -508,18 +579,12 @@ def __init__(self, link_layer, write_fifo_depth=4):
508579
tsc_value_load = Signal()
509580
self.sync.rtio += If(tsc_value_load, tsc_value.eq(self.tsc_value))
510581

511-
tx_fsm.act("IDLE_WRITE",
512-
tx_dp.send("write",
513-
timestamp=write_timestamp,
514-
channel=write_channel,
515-
address=write_address,
516-
short_data=write_data),
517-
If(wfifo.readable,
582+
tx_fsm.act("IDLE",
583+
If(wfb_readable,
518584
If(write_timestamp[48:] == 0xffff,
519585
NextState("FIFO_SPACE")
520586
).Else(
521-
tx_dp.stb.eq(1),
522-
wfifo.re.eq(tx_dp.done)
587+
NextState("WRITE")
523588
)
524589
).Else(
525590
If(echo_stb,
@@ -533,36 +598,56 @@ def __init__(self, link_layer, write_fifo_depth=4):
533598
)
534599
)
535600
)
601+
tx_fsm.act("WRITE",
602+
tx_dp.send("write",
603+
timestamp=write_timestamp,
604+
channel=write_channel,
605+
address=write_address,
606+
extra_data_cnt=write_extra_data_cnt,
607+
short_data=write_data[:short_data_len]),
608+
If(tx_dp.packet_last,
609+
If(write_extra_data_cnt == 0,
610+
wfb_re.eq(1),
611+
NextState("IDLE")
612+
).Else(
613+
NextState("WRITE_EXTRA")
614+
)
615+
)
616+
)
617+
tx_fsm.act("WRITE_EXTRA",
618+
tx_dp.raw_stb.eq(1),
619+
extra_data_ce.eq(1),
620+
If(extra_data_last,
621+
wfb_re.eq(1),
622+
NextState("IDLE")
623+
)
624+
)
536625
tx_fsm.act("FIFO_SPACE",
537626
tx_dp.send("fifo_space_request", channel=write_channel),
538-
tx_dp.stb.eq(1),
539-
If(tx_dp.done,
540-
wfifo.re.eq(1),
541-
NextState("IDLE_WRITE")
627+
If(tx_dp.packet_last,
628+
wfb_re.eq(1),
629+
NextState("IDLE")
542630
)
543631
)
544632
tx_fsm.act("ECHO",
545633
tx_dp.send("echo_request"),
546-
tx_dp.stb.eq(1),
547-
If(tx_dp.done,
634+
If(tx_dp.packet_last,
548635
echo_ack.eq(1),
549-
NextState("IDLE_WRITE")
636+
NextState("IDLE")
550637
)
551638
)
552639
tx_fsm.act("SET_TIME",
553640
tx_dp.send("set_time", timestamp=tsc_value),
554-
tx_dp.stb.eq(1),
555-
If(tx_dp.done,
641+
If(tx_dp.packet_last,
556642
set_time_ack.eq(1),
557-
NextState("IDLE_WRITE")
643+
NextState("IDLE")
558644
)
559645
)
560646
tx_fsm.act("RESET",
561647
tx_dp.send("reset", phy=reset_phy),
562-
tx_dp.stb.eq(1),
563-
If(tx_dp.done,
648+
If(tx_dp.packet_last,
564649
reset_ack.eq(1),
565-
NextState("IDLE_WRITE")
650+
NextState("IDLE")
566651
)
567652
)
568653

0 commit comments

Comments
 (0)
Please sign in to comment.