Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 15 additions & 8 deletions noc/LinkOrRTL.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,27 +23,34 @@ def construct(s, DataType):
# Interface
s.recv_fu = RecvIfcRTL(DataType)
s.recv_xbar = RecvIfcRTL(DataType)
s.fu_xbar_rdy = InPort(b1)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

s.recv_fu already contains a rdy signal, why would we still need s.fu_xbar_rdy?

s.send = SendIfcRTL(DataType)

@update
def process():
# Initializes the delivered message.
s.send.msg @= DataType()

# The messages from two sources (i.e., xbar and FU) won't be valid
# simultaneously (confliction would be caused if they both are valid),
# which is guaranteed by the compiler/software.
s.send.msg.predicate @= s.recv_fu.msg.predicate | s.recv_xbar.msg.predicate
s.send.msg.payload @= s.recv_xbar.msg.payload | s.recv_fu.msg.payload
fu_active = s.recv_fu.val & s.fu_xbar_rdy

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is that a handshake check?

xbar_active = s.recv_xbar.val

if fu_active:
s.send.msg.predicate @= s.send.msg.predicate | s.recv_fu.msg.predicate
s.send.msg.payload @= s.send.msg.payload | s.recv_fu.msg.payload
if xbar_active:
s.send.msg.predicate @= s.send.msg.predicate | s.recv_xbar.msg.predicate
s.send.msg.payload @= s.send.msg.payload | s.recv_xbar.msg.payload

# FIXME: bypass won't be necessary any more with separate xbar design.
# s.send.msg.bypass @= 0
# s.send.msg.delay @= s.recv_fu.msg.delay | s.recv_xbar.msg.delay

s.send.val @= s.recv_fu.val | s.recv_xbar.val
s.recv_fu.rdy @= s.send.rdy
# Only let FU traffic win once the FU crossbar has actually committed
# the multicast/send for this cycle; otherwise the link can expose
# transient FU output and create cross-tile bubbles.
s.send.val @= fu_active | xbar_active
s.recv_fu.rdy @= s.send.rdy & s.fu_xbar_rdy
Comment on lines +48 to +52

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have similar feeling with @yyan7223, this part is a bit confusing. It sounds the root cause might not be here. Or we need a concrete example to show case why we need to change this file. The file originally should only target simple or functionality...

s.recv_xbar.rdy @= s.send.rdy

def line_trace(s):
return f"from_fu:{s.recv_fu.msg} or from_xbar:{s.recv_xbar.msg} => out:{s.send.msg} ## "

36 changes: 36 additions & 0 deletions noc/test/LinkOrRTL_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ def construct(s, MsgType, src_msgs_0, src_msgs_1, sink_msgs):
s.src0.send //= s.dut.recv_fu
s.src1.send //= s.dut.recv_xbar
s.dut.send //= s.sink.recv
s.dut.fu_xbar_rdy //= 1

def done(s):
return s.src0.done() and s.src1.done() and s.sink.done()
Expand Down Expand Up @@ -83,3 +84,38 @@ def test_simple():
th = TestHarness(DataType, test_msgs_0, test_msgs_1, sink_msgs)
run_sim(th)

def test_invalid_fu_msg_does_not_pollute_xbar_output():
dut = LinkOrRTL(DataType)
dut.elaborate()
dut.apply(DefaultPassGroup())
dut.sim_reset()

dut.recv_fu.val @= 0
dut.recv_fu.msg @= DataType(0, 1)
dut.recv_xbar.val @= 1
dut.recv_xbar.msg @= DataType(1, 1)
dut.fu_xbar_rdy @= 1
dut.send.rdy @= 1
dut.sim_eval_combinational()

assert dut.send.val == b1(1)
assert dut.send.msg == DataType(1, 1)

def test_uncommitted_fu_msg_is_not_consumed():
dut = LinkOrRTL(DataType)
dut.elaborate()
dut.apply(DefaultPassGroup())
dut.sim_reset()

dut.recv_fu.val @= 1
dut.recv_fu.msg @= DataType(7, 1)
dut.recv_xbar.val @= 1
dut.recv_xbar.msg @= DataType(1, 1)
dut.fu_xbar_rdy @= 0
dut.send.rdy @= 1
dut.sim_eval_combinational()

assert dut.send.val == b1(1)
assert dut.send.msg == DataType(1, 1)
assert dut.recv_fu.rdy == b1(0)
assert dut.recv_xbar.rdy == b1(1)
Loading