forked from M-Labs/artiq-zynq
sim: split generator into its own file
This commit is contained in:
parent
9b967f4279
commit
473d44fd82
|
@ -0,0 +1,120 @@
|
||||||
|
from migen import *
|
||||||
|
from misoc.interconnect.csr import *
|
||||||
|
from misoc.interconnect import stream
|
||||||
|
|
||||||
|
from sim_pipeline import CXPCRC32
|
||||||
|
from src.gateware.cxp_pipeline import *
|
||||||
|
|
||||||
|
class CXPCRC32Inserter(Module):
|
||||||
|
def __init__(self):
|
||||||
|
self.sink = stream.Endpoint(word_layout)
|
||||||
|
self.source = stream.Endpoint(word_layout)
|
||||||
|
|
||||||
|
# # #
|
||||||
|
|
||||||
|
self.submodules.crc = crc = CXPCRC32(word_dw)
|
||||||
|
self.submodules.fsm = fsm = FSM(reset_state="IDLE")
|
||||||
|
|
||||||
|
fsm.act(
|
||||||
|
"IDLE",
|
||||||
|
crc.reset.eq(1),
|
||||||
|
self.sink.ack.eq(1),
|
||||||
|
If(
|
||||||
|
self.sink.stb,
|
||||||
|
self.sink.ack.eq(0),
|
||||||
|
NextState("COPY"),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
fsm.act(
|
||||||
|
"COPY",
|
||||||
|
crc.ce.eq(self.sink.stb & self.source.ack),
|
||||||
|
crc.data.eq(self.sink.data),
|
||||||
|
self.sink.connect(self.source),
|
||||||
|
self.source.eop.eq(0),
|
||||||
|
If(
|
||||||
|
self.sink.stb & self.sink.eop & self.source.ack,
|
||||||
|
NextState("INSERT"),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
fsm.act(
|
||||||
|
"INSERT",
|
||||||
|
self.source.stb.eq(1),
|
||||||
|
self.source.eop.eq(1),
|
||||||
|
self.source.data.eq(crc.value),
|
||||||
|
If(self.source.ack, NextState("IDLE")),
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class StreamPacket_Wrapper(Module):
|
||||||
|
def __init__(self):
|
||||||
|
self.sink = stream.Endpoint(word_layout)
|
||||||
|
self.source = stream.Endpoint(word_layout)
|
||||||
|
|
||||||
|
# # #
|
||||||
|
|
||||||
|
self.submodules.fsm = fsm = FSM(reset_state="IDLE")
|
||||||
|
|
||||||
|
fsm.act(
|
||||||
|
"IDLE",
|
||||||
|
self.sink.ack.eq(1),
|
||||||
|
If(
|
||||||
|
self.sink.stb,
|
||||||
|
self.sink.ack.eq(0),
|
||||||
|
NextState("INSERT_HEADER_0"),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
fsm.act(
|
||||||
|
"INSERT_HEADER_0",
|
||||||
|
self.sink.ack.eq(0),
|
||||||
|
self.source.stb.eq(1),
|
||||||
|
self.source.data.eq(Replicate(KCode["pak_start"], 4)),
|
||||||
|
self.source.k.eq(Replicate(1, 4)),
|
||||||
|
If(self.source.ack, NextState("INSERT_HEADER_1")),
|
||||||
|
)
|
||||||
|
|
||||||
|
fsm.act(
|
||||||
|
"INSERT_HEADER_1",
|
||||||
|
self.sink.ack.eq(0),
|
||||||
|
self.source.stb.eq(1),
|
||||||
|
self.source.data.eq(Replicate(C(0x01, char_width), 4)),
|
||||||
|
self.source.k.eq(Replicate(0, 4)),
|
||||||
|
If(self.source.ack, NextState("COPY")),
|
||||||
|
)
|
||||||
|
|
||||||
|
fsm.act(
|
||||||
|
"COPY",
|
||||||
|
self.sink.connect(self.source),
|
||||||
|
self.source.eop.eq(0),
|
||||||
|
If(
|
||||||
|
self.sink.stb & self.sink.eop & self.source.ack,
|
||||||
|
NextState("INSERT_FOOTER"),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
fsm.act(
|
||||||
|
"INSERT_FOOTER",
|
||||||
|
self.sink.ack.eq(0),
|
||||||
|
self.source.stb.eq(1),
|
||||||
|
self.source.data.eq(Replicate(KCode["pak_end"], 4)),
|
||||||
|
self.source.k.eq(Replicate(1, 4)),
|
||||||
|
# Simulate RX don't have eop tagged
|
||||||
|
# self.source.eop.eq(1),
|
||||||
|
If(self.source.ack, NextState("IDLE")),
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
# With KCode & 0x01*4
|
||||||
|
class StreamData_Generator(Module):
|
||||||
|
def __init__(self):
|
||||||
|
# should be big enough for all test
|
||||||
|
self.submodules.buffer = buffer = stream.SyncFIFO(word_layout, 32)
|
||||||
|
self.submodules.crc_inserter = crc_inserter = CXPCRC32Inserter()
|
||||||
|
self.submodules.wrapper = wrapper = StreamPacket_Wrapper()
|
||||||
|
|
||||||
|
# # #
|
||||||
|
pipeline = [buffer, crc_inserter, wrapper]
|
||||||
|
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
|
297
sim_pipeline.py
297
sim_pipeline.py
|
@ -24,110 +24,6 @@ class EOP_Marker(Module):
|
||||||
self.sink.ack.eq(~self.source.stb | self.source.ack),
|
self.sink.ack.eq(~self.source.stb | self.source.ack),
|
||||||
self.source.eop.eq(~self.sink.stb & last_stb),
|
self.source.eop.eq(~self.sink.stb & last_stb),
|
||||||
]
|
]
|
||||||
|
|
||||||
class Stream_MetaData_Extractor(Module):
|
|
||||||
def __init__(self):
|
|
||||||
self.sink = stream.Endpoint(word_layout_dchar)
|
|
||||||
self.source = stream.Endpoint(word_layout_dchar)
|
|
||||||
|
|
||||||
# # #
|
|
||||||
|
|
||||||
# GOAL:
|
|
||||||
# 0) accept four sinks??
|
|
||||||
# 1) decode SPH, SPT
|
|
||||||
# 2) decode Image header, line break
|
|
||||||
# 3) verify the crc before phrasing image data downstream
|
|
||||||
|
|
||||||
# HOW??
|
|
||||||
# combine streams?
|
|
||||||
# phrase linedata to sys CD
|
|
||||||
# check stream data tag
|
|
||||||
# only need to support mono16 for now
|
|
||||||
|
|
||||||
self.stream_id = Signal(char_width)
|
|
||||||
self.pak_tag = Signal(char_width)
|
|
||||||
self.stream_pak_size = Signal(char_width * 2)
|
|
||||||
|
|
||||||
self.submodules.fsm = fsm = FSM(reset_state="WAIT_HEADER")
|
|
||||||
|
|
||||||
fsm.act(
|
|
||||||
"WAIT_HEADER",
|
|
||||||
NextValue(self.stream_id, self.stream_id.reset),
|
|
||||||
NextValue(self.pak_tag, self.pak_tag.reset),
|
|
||||||
NextValue(self.stream_pak_size, self.stream_pak_size.reset),
|
|
||||||
self.sink.ack.eq(1),
|
|
||||||
If(
|
|
||||||
self.sink.stb,
|
|
||||||
NextValue(self.stream_id, self.sink.dchar),
|
|
||||||
NextState("GET_PAK_TAG"),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
|
|
||||||
fsm.act(
|
|
||||||
"GET_PAK_TAG",
|
|
||||||
If(
|
|
||||||
self.sink.stb,
|
|
||||||
self.sink.ack.eq(1),
|
|
||||||
NextValue(self.pak_tag, self.sink.dchar),
|
|
||||||
NextState("GET_PAK_SIZE_0"),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
|
|
||||||
fsm.act(
|
|
||||||
"GET_PAK_SIZE_0",
|
|
||||||
self.sink.ack.eq(1),
|
|
||||||
If(
|
|
||||||
self.sink.stb,
|
|
||||||
NextValue(self.stream_pak_size[8:], self.sink.dchar),
|
|
||||||
NextState("GET_PAK_SIZE_1"),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
|
|
||||||
fsm.act(
|
|
||||||
"GET_PAK_SIZE_1",
|
|
||||||
self.sink.ack.eq(1),
|
|
||||||
If(
|
|
||||||
self.sink.stb,
|
|
||||||
NextValue(self.stream_pak_size[:8], self.sink.dchar),
|
|
||||||
NextState("STORE_BUFFER"),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
|
|
||||||
fsm.act(
|
|
||||||
"STORE_BUFFER",
|
|
||||||
self.sink.connect(self.source),
|
|
||||||
# both serve the same function but using the pak size I can remove eop injecter and save 1 cycle
|
|
||||||
If(self.sink.stb,
|
|
||||||
NextValue(self.stream_pak_size, self.stream_pak_size - 1),
|
|
||||||
If(self.stream_pak_size == 1,
|
|
||||||
NextState("WAIT_HEADER"),
|
|
||||||
)
|
|
||||||
),
|
|
||||||
# If((self.sink.stb & self.sink.eop),
|
|
||||||
# NextState("WAIT_HEADER"),
|
|
||||||
# )
|
|
||||||
)
|
|
||||||
|
|
||||||
class Frame_Decoder(Module):
|
|
||||||
def __init__(self):
|
|
||||||
self.sink = stream.Endpoint(word_layout_dchar)
|
|
||||||
self.source = stream.Endpoint(word_layout_dchar)
|
|
||||||
|
|
||||||
# # #
|
|
||||||
|
|
||||||
# TODO: decode Image header, line break
|
|
||||||
|
|
||||||
class Pixel_Decoder(Module):
|
|
||||||
def __init__(self, pixel_format="mono16"):
|
|
||||||
assert pixel_format == "mono16"
|
|
||||||
|
|
||||||
self.sink = stream.Endpoint(word_layout_dchar)
|
|
||||||
self.source = stream.Endpoint(word_layout_dchar)
|
|
||||||
|
|
||||||
# # #
|
|
||||||
|
|
||||||
# TODO: support mono16 for now?
|
|
||||||
|
|
||||||
class Streams_Crossbar(Module):
|
class Streams_Crossbar(Module):
|
||||||
def __init__(self, downconns, streams_buffer):
|
def __init__(self, downconns, streams_buffer):
|
||||||
n_downconn = len(downconns)
|
n_downconn = len(downconns)
|
||||||
|
@ -205,113 +101,10 @@ class CXPCRC32(Module):
|
||||||
self.error.eq(reg != self.check),
|
self.error.eq(reg != self.check),
|
||||||
]
|
]
|
||||||
|
|
||||||
class CXPCRC32Inserter(Module):
|
|
||||||
def __init__(self):
|
|
||||||
self.sink = stream.Endpoint(word_layout)
|
|
||||||
self.source = stream.Endpoint(word_layout)
|
|
||||||
|
|
||||||
# # #
|
|
||||||
|
|
||||||
self.submodules.crc = crc = CXPCRC32(word_dw)
|
|
||||||
self.submodules.fsm = fsm = FSM(reset_state="IDLE")
|
|
||||||
|
|
||||||
fsm.act("IDLE",
|
|
||||||
crc.reset.eq(1),
|
|
||||||
self.sink.ack.eq(1),
|
|
||||||
If(self.sink.stb,
|
|
||||||
self.sink.ack.eq(0),
|
|
||||||
NextState("COPY"),
|
|
||||||
)
|
|
||||||
)
|
|
||||||
fsm.act("COPY",
|
|
||||||
crc.ce.eq(self.sink.stb & self.source.ack),
|
|
||||||
crc.data.eq(self.sink.data),
|
|
||||||
self.sink.connect(self.source),
|
|
||||||
self.source.eop.eq(0),
|
|
||||||
If(self.sink.stb & self.sink.eop & self.source.ack,
|
|
||||||
NextState("INSERT"),
|
|
||||||
)
|
|
||||||
)
|
|
||||||
fsm.act("INSERT",
|
|
||||||
self.source.stb.eq(1),
|
|
||||||
self.source.eop.eq(1),
|
|
||||||
self.source.data.eq(crc.value),
|
|
||||||
If(self.source.ack, NextState("IDLE"))
|
|
||||||
)
|
|
||||||
|
|
||||||
class StreamPacket_Wrapper(Module):
|
|
||||||
def __init__(self):
|
|
||||||
self.sink = stream.Endpoint(word_layout)
|
|
||||||
self.source = stream.Endpoint(word_layout)
|
|
||||||
|
|
||||||
# # #
|
|
||||||
|
|
||||||
self.submodules.fsm = fsm = FSM(reset_state="IDLE")
|
|
||||||
|
|
||||||
fsm.act("IDLE",
|
|
||||||
self.sink.ack.eq(1),
|
|
||||||
If(self.sink.stb,
|
|
||||||
self.sink.ack.eq(0),
|
|
||||||
NextState("INSERT_HEADER_0"),
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
fsm.act("INSERT_HEADER_0",
|
|
||||||
self.sink.ack.eq(0),
|
|
||||||
self.source.stb.eq(1),
|
|
||||||
self.source.data.eq(Replicate(KCode["pak_start"], 4)),
|
|
||||||
self.source.k.eq(Replicate(1, 4)),
|
|
||||||
If(self.source.ack, NextState("INSERT_HEADER_1")),
|
|
||||||
)
|
|
||||||
|
|
||||||
fsm.act("INSERT_HEADER_1",
|
|
||||||
self.sink.ack.eq(0),
|
|
||||||
self.source.stb.eq(1),
|
|
||||||
self.source.data.eq(Replicate(C(0x01, char_width), 4)),
|
|
||||||
self.source.k.eq(Replicate(0, 4)),
|
|
||||||
If(self.source.ack, NextState("COPY")),
|
|
||||||
)
|
|
||||||
|
|
||||||
fsm.act("COPY",
|
|
||||||
self.sink.connect(self.source),
|
|
||||||
self.source.eop.eq(0),
|
|
||||||
If(self.sink.stb & self.sink.eop & self.source.ack,
|
|
||||||
NextState("INSERT_FOOTER"),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
|
|
||||||
fsm.act("INSERT_FOOTER",
|
|
||||||
self.sink.ack.eq(0),
|
|
||||||
self.source.stb.eq(1),
|
|
||||||
self.source.data.eq(Replicate(KCode["pak_end"], 4)),
|
|
||||||
self.source.k.eq(Replicate(1, 4)),
|
|
||||||
# Simulate RX don't have eop tagged
|
|
||||||
# self.source.eop.eq(1),
|
|
||||||
If(self.source.ack, NextState("IDLE")),
|
|
||||||
)
|
|
||||||
|
|
||||||
# With KCode & 0x01*4
|
|
||||||
class StreamData_Generator(Module):
|
|
||||||
def __init__(self):
|
|
||||||
# should be big enough for all test
|
|
||||||
self.submodules.buffer = buffer = stream.SyncFIFO(word_layout, 32)
|
|
||||||
self.submodules.crc_inserter = crc_inserter = CXPCRC32Inserter()
|
|
||||||
self.submodules.wrapper = wrapper = StreamPacket_Wrapper()
|
|
||||||
|
|
||||||
# # #
|
|
||||||
pipeline = [buffer, crc_inserter, wrapper]
|
|
||||||
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
|
|
||||||
|
|
||||||
# For verifying crc in stream data packet
|
# For verifying crc in stream data packet
|
||||||
class Double_Stream_Buffer(Module):
|
class Double_Stream_Buffer(Module):
|
||||||
# default size is 2 kBtyes - Section 9.5.2 (CXP-001-2021)
|
# default size is 2 kBtyes - Section 9.5.2 (CXP-001-2021)
|
||||||
def __init__(self, size=16000):
|
def __init__(self, size=16000):
|
||||||
# detect and tag end of packet for crc
|
|
||||||
# self.submodules.eop_marker = eop_marker = EOP_Marker()
|
|
||||||
# self.sink = eop_marker.sink
|
|
||||||
self.sink = stream.Endpoint(word_layout_dchar)
|
self.sink = stream.Endpoint(word_layout_dchar)
|
||||||
|
|
||||||
self.submodules.crc = crc = CXPCRC32(word_dw)
|
self.submodules.crc = crc = CXPCRC32(word_dw)
|
||||||
|
@ -393,3 +186,93 @@ class Double_Stream_Buffer(Module):
|
||||||
|
|
||||||
# last_eop = Signal()
|
# last_eop = Signal()
|
||||||
# self.comb += self.source.eop.eq(~last_eop & self.sink.eop)
|
# self.comb += self.source.eop.eq(~last_eop & self.sink.eop)
|
||||||
|
|
||||||
|
|
||||||
|
class Stream_Parser(Module):
|
||||||
|
def __init__(self):
|
||||||
|
self.sink = stream.Endpoint(word_layout_dchar)
|
||||||
|
self.source = stream.Endpoint(word_layout_dchar)
|
||||||
|
|
||||||
|
# # #
|
||||||
|
|
||||||
|
self.stream_id = Signal(char_width)
|
||||||
|
self.pak_tag = Signal(char_width)
|
||||||
|
self.stream_pak_size = Signal(char_width * 2)
|
||||||
|
|
||||||
|
self.submodules.fsm = fsm = FSM(reset_state="WAIT_HEADER")
|
||||||
|
|
||||||
|
fsm.act(
|
||||||
|
"WAIT_HEADER",
|
||||||
|
NextValue(self.stream_id, self.stream_id.reset),
|
||||||
|
NextValue(self.pak_tag, self.pak_tag.reset),
|
||||||
|
NextValue(self.stream_pak_size, self.stream_pak_size.reset),
|
||||||
|
self.sink.ack.eq(1),
|
||||||
|
If(
|
||||||
|
self.sink.stb,
|
||||||
|
NextValue(self.stream_id, self.sink.dchar),
|
||||||
|
NextState("GET_PAK_TAG"),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
fsm.act(
|
||||||
|
"GET_PAK_TAG",
|
||||||
|
If(
|
||||||
|
self.sink.stb,
|
||||||
|
self.sink.ack.eq(1),
|
||||||
|
NextValue(self.pak_tag, self.sink.dchar),
|
||||||
|
NextState("GET_PAK_SIZE_0"),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
fsm.act(
|
||||||
|
"GET_PAK_SIZE_0",
|
||||||
|
self.sink.ack.eq(1),
|
||||||
|
If(
|
||||||
|
self.sink.stb,
|
||||||
|
NextValue(self.stream_pak_size[8:], self.sink.dchar),
|
||||||
|
NextState("GET_PAK_SIZE_1"),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
fsm.act(
|
||||||
|
"GET_PAK_SIZE_1",
|
||||||
|
self.sink.ack.eq(1),
|
||||||
|
If(
|
||||||
|
self.sink.stb,
|
||||||
|
NextValue(self.stream_pak_size[:8], self.sink.dchar),
|
||||||
|
NextState("STORE_BUFFER"),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
fsm.act(
|
||||||
|
"STORE_BUFFER",
|
||||||
|
self.sink.connect(self.source),
|
||||||
|
# both serve the same function but using the pak size I can remove eop injecter and save 1 cycle
|
||||||
|
If(self.sink.stb,
|
||||||
|
NextValue(self.stream_pak_size, self.stream_pak_size - 1),
|
||||||
|
If(self.stream_pak_size == 1,
|
||||||
|
NextState("WAIT_HEADER"),
|
||||||
|
)
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
class Frame_Decoder(Module):
|
||||||
|
def __init__(self):
|
||||||
|
self.sink = stream.Endpoint(word_layout_dchar)
|
||||||
|
self.source = stream.Endpoint(word_layout_dchar)
|
||||||
|
|
||||||
|
# # #
|
||||||
|
|
||||||
|
# TODO: decode Image header, line break
|
||||||
|
|
||||||
|
class Pixel_Decoder(Module):
|
||||||
|
def __init__(self, pixel_format="mono16"):
|
||||||
|
assert pixel_format == "mono16"
|
||||||
|
|
||||||
|
self.sink = stream.Endpoint(word_layout_dchar)
|
||||||
|
self.source = stream.Endpoint(word_layout_dchar)
|
||||||
|
|
||||||
|
# # #
|
||||||
|
|
||||||
|
# TODO: support mono16 for now?
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
from migen import *
|
from migen import *
|
||||||
from misoc.interconnect import stream
|
from misoc.interconnect import stream
|
||||||
|
|
||||||
from sim_pipeline import *
|
from sim_pipeline import *
|
||||||
|
from sim_generator import StreamData_Generator
|
||||||
|
|
||||||
from src.gateware.cxp_pipeline import *
|
from src.gateware.cxp_pipeline import *
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue