1
0
Fork 0
artiq-zynq/sim_stream.py

167 lines
5.9 KiB
Python
Raw Normal View History

from migen import *
from misoc.interconnect import stream
from sim_pipeline import *
from src.gateware.cxp_pipeline import *
class CXP_Links(Module):
def __init__(self):
# TODO: select the correct buffer to read from
# NOTE: although there are double buffer in each connect, the reading must be faster than writing to avoid data loss
self.downconns = []
2024-11-07 16:21:02 +08:00
self.stream_buffers = []
for i in range(2):
downconn = Pipeline()
setattr(self.submodules, "cxp_conn"+str(i), downconn)
self.downconns.append(downconn)
2024-11-07 16:21:02 +08:00
double_buffer = Double_Stream_Buffer()
setattr(self.submodules, "stream_buffer"+str(i), double_buffer)
self.stream_buffers.append(double_buffer)
# no backpressure for sim purposes
self.sync += double_buffer.source.ack.eq(1)
self.submodules.crossbar = crossbar = Streams_Crossbar(self.downconns, self.stream_buffers)
# TODO: add extractor
2024-11-07 16:21:02 +08:00
# pipeline = [dispatcher, double_buffer]
# for s, d in zip(pipeline, pipeline[1:]):
# self.comb += s.source.connect(d.sink)
# self.source = pipeline[-1].source
2024-11-07 16:21:02 +08:00
# # no backpressure
# self.sync += self.source.ack.eq(1)
class Pipeline(Module):
def __init__(self):
self.submodules.generator = generator = StreamData_Generator()
self.submodules.dchar_decoder = dchar_decoder = Duplicated_Char_Decoder()
self.submodules.data_decoder = data_decoder = RX_Bootstrap()
self.submodules.eop_marker = eop_marker = EOP_Marker()
# # #
pipeline = [generator, dchar_decoder, data_decoder, eop_marker]
for s, d in zip(pipeline, pipeline[1:]):
self.comb += s.source.connect(d.sink)
self.sink = pipeline[0].sink
self.source = pipeline[-1].source
# self.comb += self.source.ack.eq(1)
dut = CXP_Links()
def check_case(packet=[]):
print("=================TEST========================")
2024-11-07 16:21:02 +08:00
downconns = dut.downconns
2024-11-07 16:21:02 +08:00
stream_buffers = dut.stream_buffers
ch = 0
for i, p in enumerate(packet):
for x in range(len(downconns)):
if x == ch:
yield downconns[x].sink.data.eq(p["data"])
yield downconns[x].sink.k.eq(p["k"])
yield downconns[x].sink.stb.eq(1)
else:
yield downconns[x].sink.data.eq(0)
yield downconns[x].sink.k.eq(0)
yield downconns[x].sink.stb.eq(0)
yield downconns[x].sink.eop.eq(0)
if "eop" in p:
yield downconns[ch].sink.eop.eq(1)
# compensate for delay
# yield
# yield downconns[ch].sink.data.eq(0)
# yield downconns[ch].sink.k.eq(0)
# yield downconns[ch].sink.stb.eq(0)
# yield downconns[ch].sink.eop.eq(0)
# yield
# yield
# yield
ch = (ch + 1) % len(downconns)
else:
yield downconns[ch].sink.eop.eq(0)
# check cycle result
yield
2024-11-07 16:21:02 +08:00
source = dut.stream_buffers[0].source
print(
f"\nCYCLE#{i} : source char = {yield source.data:#X} k = {yield source.k:#X} stb = {yield source.stb} ack = {yield source.ack} eop = {yield source.eop}"
# f" source dchar = {yield source.dchar:#X} dchar_k = {yield source.dchar_k:#X}"
2024-11-07 16:21:02 +08:00
f"\nCYCLE#{i} : read mask = {yield dut.crossbar .mux.sel}"
# f"\nCYCLE#{i} : stream id = {yield decoder.stream_id:#X} pak_tag = {yield decoder.pak_tag:#X}"
# f" stream_pak_size = {yield decoder.stream_pak_size:#X}"
)
# crc = downconns[1].generator.crc_inserter.crc
# crc = dut.double_buffer.crc
# print(
# f"CYCLE#{i} : crc error = {yield crc.error:#X} crc value = {yield crc.value:#X}"
# f" crc data = {yield crc.data:#X} engine next = {yield crc.engine.next:#X} ce = {yield crc.ce}"
# )
# extra clk cycles
cyc = i + 1
for i in range(cyc, cyc + 30):
for x in range(len(downconns)):
# yield won't reset every cycle
yield downconns[x].sink.data.eq(0)
yield downconns[x].sink.k.eq(0)
yield downconns[x].sink.stb.eq(0)
yield downconns[x].sink.eop.eq(0)
yield
print(
f"\nCYCLE#{i} : source char = {yield source.data:#X} k = {yield source.k:#X} stb = {yield source.stb} ack = {yield source.ack} eop = {yield source.eop}"
# f" source dchar = {yield source.dchar:#X} dchar_k = {yield source.dchar_k:#X}"
2024-11-07 16:21:02 +08:00
f"\nCYCLE#{i} : read mask = {yield dut.crossbar .mux.sel}"
# f"\nCYCLE#{i} : stream id = {yield decoder.stream_id:#X} pak_tag = {yield decoder.pak_tag:#X}"
# f" stream_pak_size = {yield decoder.stream_pak_size:#X}"
)
assert True
def testbench():
2024-11-07 16:21:02 +08:00
# stream_id = 0x01
streams = [
[
{"data": 0x11111111, "k": Replicate(0, 4)},
{"data": 0xB105F00D, "k": Replicate(0, 4)},
],
[
{"data": 0x22222222, "k": Replicate(0, 4)},
{"data": 0xC00010FF, "k": Replicate(0, 4)},
],
[
{"data": 0x33333333, "k": Replicate(0, 4)},
{"data": 0xC0A79AE5, "k": Replicate(0, 4)},
],
]
packet = []
for i, s in enumerate(streams):
s[-1]["eop"] = 0
packet += [
2024-11-07 16:21:02 +08:00
{"data": Replicate(C(i % 2, char_width), 4), "k": Replicate(0, 4)},
{"data": Replicate(C(i, char_width), 4), "k": Replicate(0, 4)},
{
"data": Replicate(C(len(s) >> 8 & 0xFF, char_width), 4),
"k": Replicate(0, 4),
},
{"data": Replicate(C(len(s) & 0xFF, char_width), 4), "k": Replicate(0, 4)},
*s,
]
yield from check_case(packet)
run_simulation(dut, testbench(), vcd_name="sim-cxp.vcd")