frameline GW: refactor broadcaster

This commit is contained in:
morgan 2025-01-22 16:05:21 +08:00
parent f6b13f271d
commit 624de51ad4

View File

@ -164,20 +164,15 @@ class CXPCRC32_Checker(Module):
class Stream_Broadcaster(Module): class Stream_Broadcaster(Module):
def __init__(self, n_buffer=1, default_id=0): def __init__(self, layout=word_layout_dchar, routing_ids=[0]):
assert n_buffer > 0 n_id = len(routing_ids)
assert n_id > 0
self.routing_ids = [Signal(char_width) for _ in range(1, n_buffer)] self.sources = [stream.Endpoint(layout) for _ in range(n_id)]
self.sink = stream.Endpoint(layout)
self.sources = [stream.Endpoint(word_layout_dchar) for _ in range(n_buffer)]
self.sink = stream.Endpoint(word_layout_dchar)
# # # # # #
routing_ids_r = [Signal(char_width) for _ in range(1, n_buffer)]
for i, id in enumerate(self.routing_ids):
self.sync += routing_ids_r[i].eq(id)
stream_id = Signal(char_width) stream_id = Signal(char_width)
pak_tag = Signal(char_width) pak_tag = Signal(char_width)
@ -215,54 +210,52 @@ class Stream_Broadcaster(Module):
), ),
) )
routing_case = {"default": NextState("DISCARD")}
for id in (routing_ids):
routing_case[id] = [NextState(f"COPY_TO_BUFFER_{id}")]
fsm.act( fsm.act(
"GET_PAK_SIZE_1", "GET_PAK_SIZE_1",
self.sink.ack.eq(1), self.sink.ack.eq(1),
If( If(
self.sink.stb, self.sink.stb,
NextValue(stream_pak_size[:8], self.sink.dchar), NextValue(stream_pak_size[:8], self.sink.dchar),
NextState("STORE_BUFFER"), Case(stream_id, routing_case),
), ),
) )
# routing decoder for key in routing_case:
sel = Signal(n_buffer) if key == "default":
no_match = Signal() fsm.act(
self.comb += sel[0].eq(stream_id == default_id) "DISCARD",
for i, id in enumerate(routing_ids_r): self.sink.ack.eq(1),
self.comb += sel[i+1].eq(stream_id == id) If(self.sink.stb,
# DEBUG: disrecard the stream id = 0 rule NextValue(stream_pak_size, stream_pak_size - 1),
# self.comb += source_sel[0].eq(self.stream_id == self.routing_table[0]) If(stream_pak_size == 0,
NextValue(stream_id, stream_id.reset),
# ensure the lower source has priority when two or more bits of sel are high NextValue(pak_tag, pak_tag.reset),
self.submodules.coder = coder = PriorityEncoder(n_buffer) NextValue(stream_pak_size, stream_pak_size.reset),
sel_r = Signal.like(coder.o) NextState("WAIT_HEADER"),
self.sync += [ )
coder.i.eq(sel), ),
sel_r.eq(coder.o), )
no_match.eq(coder.n), else:
] fsm.act(
f"COPY_TO_BUFFER_{key}",
routing = dict((i, self.sink.connect(s))for i, s in enumerate(self.sources)) self.sink.connect(self.sources[key]),
routing["default"] = self.sink.ack.eq(1) # discard if invalid
fsm.act( # assume downstream is not blocked
"STORE_BUFFER", If(self.sink.stb,
If(no_match, NextValue(stream_pak_size, stream_pak_size - 1),
self.sink.ack.eq(1), If(stream_pak_size == 0,
).Else( NextValue(stream_id, stream_id.reset),
Case(sel_r, routing), NextValue(pak_tag, pak_tag.reset),
), NextValue(stream_pak_size, stream_pak_size.reset),
# assume downstream is not blocked NextState("WAIT_HEADER"),
If(self.sink.stb, )
NextValue(stream_pak_size, stream_pak_size - 1), ),
If(stream_pak_size == 0,
NextValue(stream_id, stream_id.reset),
NextValue(pak_tag, pak_tag.reset),
NextValue(stream_pak_size, stream_pak_size.reset),
NextState("WAIT_HEADER"),
) )
),
)
class Frame_Header_Decoder(Module): class Frame_Header_Decoder(Module):
def __init__(self): def __init__(self):