Implement proper downstream TLP routing
This commit is contained in:
parent
178133498b
commit
1630200cd8
103
tb/pcie.py
103
tb/pcie.py
@ -2472,7 +2472,7 @@ class Bridge(Function):
|
|||||||
tlp.fmt_type = TLP_CFG_READ_0
|
tlp.fmt_type = TLP_CFG_READ_0
|
||||||
elif tlp.fmt_type == TLP_CFG_WRITE_1:
|
elif tlp.fmt_type == TLP_CFG_WRITE_1:
|
||||||
tlp.fmt_type = TLP_CFG_WRITE_0
|
tlp.fmt_type = TLP_CFG_WRITE_0
|
||||||
yield from self.downstream_send(tlp)
|
yield from self.route_downstream_tlp(tlp, False)
|
||||||
else:
|
else:
|
||||||
# error
|
# error
|
||||||
pass
|
pass
|
||||||
@ -2483,7 +2483,7 @@ class Bridge(Function):
|
|||||||
# for me
|
# for me
|
||||||
yield from self.handle_tlp(tlp)
|
yield from self.handle_tlp(tlp)
|
||||||
elif self.sec_bus_num <= tlp.requester_id.bus <= self.sub_bus_num:
|
elif self.sec_bus_num <= tlp.requester_id.bus <= self.sub_bus_num:
|
||||||
yield from self.downstream_send(tlp)
|
yield from self.route_downstream_tlp(tlp, False)
|
||||||
else:
|
else:
|
||||||
# error
|
# error
|
||||||
pass
|
pass
|
||||||
@ -2493,7 +2493,7 @@ class Bridge(Function):
|
|||||||
# for me
|
# for me
|
||||||
yield from self.handle_tlp(tlp)
|
yield from self.handle_tlp(tlp)
|
||||||
elif self.sec_bus_num <= tlp.dest_id.bus <= self.sub_bus_num:
|
elif self.sec_bus_num <= tlp.dest_id.bus <= self.sub_bus_num:
|
||||||
yield from self.downstream_send(tlp)
|
yield from self.route_downstream_tlp(tlp, False)
|
||||||
else:
|
else:
|
||||||
# error
|
# error
|
||||||
pass
|
pass
|
||||||
@ -2503,7 +2503,7 @@ class Bridge(Function):
|
|||||||
# for me
|
# for me
|
||||||
yield from self.handle_tlp(tlp)
|
yield from self.handle_tlp(tlp)
|
||||||
elif self.io_base <= tlp.address <= self.io_limit:
|
elif self.io_base <= tlp.address <= self.io_limit:
|
||||||
yield from self.downstream_send(tlp)
|
yield from self.route_downstream_tlp(tlp, False)
|
||||||
else:
|
else:
|
||||||
# error
|
# error
|
||||||
pass
|
pass
|
||||||
@ -2514,7 +2514,7 @@ class Bridge(Function):
|
|||||||
# for me
|
# for me
|
||||||
yield from self.handle_tlp(tlp)
|
yield from self.handle_tlp(tlp)
|
||||||
elif self.mem_base <= tlp.address <= self.mem_limit or self.prefetchable_mem_base <= tlp.address <= self.prefetchable_mem_limit:
|
elif self.mem_base <= tlp.address <= self.mem_limit or self.prefetchable_mem_base <= tlp.address <= self.prefetchable_mem_limit:
|
||||||
yield from self.downstream_send(tlp)
|
yield from self.route_downstream_tlp(tlp, False)
|
||||||
else:
|
else:
|
||||||
# error
|
# error
|
||||||
pass
|
pass
|
||||||
@ -2537,6 +2537,9 @@ class Bridge(Function):
|
|||||||
# logging
|
# logging
|
||||||
raise Exception("Unknown/invalid packet type")
|
raise Exception("Unknown/invalid packet type")
|
||||||
|
|
||||||
|
def route_downstream_tlp(self, tlp, from_downstream=False):
|
||||||
|
yield from self.downstream_send(tlp)
|
||||||
|
|
||||||
def downstream_send(self, tlp):
|
def downstream_send(self, tlp):
|
||||||
assert tlp.check()
|
assert tlp.check()
|
||||||
if self.downstream_tx_handler is None:
|
if self.downstream_tx_handler is None:
|
||||||
@ -2562,7 +2565,7 @@ class Bridge(Function):
|
|||||||
if self.root and tlp.requester_id.bus == self.pri_bus_num and tlp.requester_id.device == 0:
|
if self.root and tlp.requester_id.bus == self.pri_bus_num and tlp.requester_id.device == 0:
|
||||||
yield from self.upstream_send(tlp)
|
yield from self.upstream_send(tlp)
|
||||||
else:
|
else:
|
||||||
yield from self.downstream_send(tlp)
|
yield from self.route_downstream_tlp(tlp, True)
|
||||||
else:
|
else:
|
||||||
yield from self.upstream_send(tlp)
|
yield from self.upstream_send(tlp)
|
||||||
elif tlp.fmt_type == TLP_MSG_ID or tlp.fmt_type == TLP_MSG_DATA_ID:
|
elif tlp.fmt_type == TLP_MSG_ID or tlp.fmt_type == TLP_MSG_DATA_ID:
|
||||||
@ -2574,7 +2577,7 @@ class Bridge(Function):
|
|||||||
if self.root and tlp.dest_id.bus == self.pri_bus_num and tlp.dest_id.device == 0:
|
if self.root and tlp.dest_id.bus == self.pri_bus_num and tlp.dest_id.device == 0:
|
||||||
yield from self.upstream_send(tlp)
|
yield from self.upstream_send(tlp)
|
||||||
else:
|
else:
|
||||||
yield from self.downstream_send(tlp)
|
yield from self.route_downstream_tlp(tlp, True)
|
||||||
else:
|
else:
|
||||||
yield from self.upstream_send(tlp)
|
yield from self.upstream_send(tlp)
|
||||||
elif (tlp.fmt_type == TLP_IO_READ or tlp.fmt_type == TLP_IO_WRITE):
|
elif (tlp.fmt_type == TLP_IO_READ or tlp.fmt_type == TLP_IO_WRITE):
|
||||||
@ -2583,7 +2586,7 @@ class Bridge(Function):
|
|||||||
# for me
|
# for me
|
||||||
yield from self.handle_tlp(tlp)
|
yield from self.handle_tlp(tlp)
|
||||||
elif self.io_base <= tlp.address <= self.io_limit:
|
elif self.io_base <= tlp.address <= self.io_limit:
|
||||||
yield from self.downstream_send(tlp)
|
yield from self.route_downstream_tlp(tlp, True)
|
||||||
else:
|
else:
|
||||||
yield from self.upstream_send(tlp)
|
yield from self.upstream_send(tlp)
|
||||||
elif (tlp.fmt_type == TLP_MEM_READ or tlp.fmt_type == TLP_MEM_READ_64 or
|
elif (tlp.fmt_type == TLP_MEM_READ or tlp.fmt_type == TLP_MEM_READ_64 or
|
||||||
@ -2593,7 +2596,7 @@ class Bridge(Function):
|
|||||||
# for me
|
# for me
|
||||||
yield from self.handle_tlp(tlp)
|
yield from self.handle_tlp(tlp)
|
||||||
elif self.mem_base <= tlp.address <= self.mem_limit or self.prefetchable_mem_base <= tlp.address <= self.prefetchable_mem_limit:
|
elif self.mem_base <= tlp.address <= self.mem_limit or self.prefetchable_mem_base <= tlp.address <= self.prefetchable_mem_limit:
|
||||||
yield from self.downstream_send(tlp)
|
yield from self.route_downstream_tlp(tlp, True)
|
||||||
else:
|
else:
|
||||||
yield from self.upstream_send(tlp)
|
yield from self.upstream_send(tlp)
|
||||||
elif tlp.fmt_type == TLP_MSG_TO_RC or tlp.fmt_type == TLP_MSG_DATA_TO_RC:
|
elif tlp.fmt_type == TLP_MSG_TO_RC or tlp.fmt_type == TLP_MSG_DATA_TO_RC:
|
||||||
@ -2625,15 +2628,91 @@ class SwitchUpstreamPort(Bridge):
|
|||||||
self.pcie_device_type = 0x5
|
self.pcie_device_type = 0x5
|
||||||
|
|
||||||
self.downstream_port = BusPort(self, self.downstream_recv)
|
self.downstream_port = BusPort(self, self.downstream_recv)
|
||||||
self.downstream_tx_handler = self.downstream_port.send
|
self.downstream_tx_handler = None
|
||||||
|
|
||||||
self.desc = "SwitchUpstreamPort"
|
self.desc = "SwitchUpstreamPort"
|
||||||
|
|
||||||
self.vendor_id = 0x1234
|
self.vendor_id = 0x1234
|
||||||
self.device_id = 0x0003
|
self.device_id = 0x0003
|
||||||
|
|
||||||
def connect(self, port):
|
def route_downstream_tlp(self, tlp, from_downstream=False):
|
||||||
self.downstream_port.connect(port)
|
assert tlp.check()
|
||||||
|
|
||||||
|
# route downstream packet
|
||||||
|
for p in self.downstream_port.other:
|
||||||
|
dev = p.parent
|
||||||
|
if tlp.fmt_type == TLP_CFG_READ_0 or tlp.fmt_type == TLP_CFG_WRITE_0:
|
||||||
|
# config type 0
|
||||||
|
if tlp.dest_id.device == dev.device_num and tlp.dest_id.function == dev.function_num:
|
||||||
|
yield from p.ext_recv(TLP(tlp))
|
||||||
|
return
|
||||||
|
elif tlp.fmt_type == TLP_CFG_READ_1 or tlp.fmt_type == TLP_CFG_WRITE_1:
|
||||||
|
# config type 1
|
||||||
|
if isinstance(dev, Bridge) and dev.sec_bus_num <= tlp.dest_id.bus <= dev.sub_bus_num:
|
||||||
|
yield from p.ext_recv(TLP(tlp))
|
||||||
|
return
|
||||||
|
elif (tlp.fmt_type == TLP_CPL or tlp.fmt_type == TLP_CPL_DATA or
|
||||||
|
tlp.fmt_type == TLP_CPL_LOCKED or tlp.fmt_type == TLP_CPL_LOCKED_DATA):
|
||||||
|
# Completions
|
||||||
|
if tlp.requester_id == dev.get_id():
|
||||||
|
yield from p.ext_recv(TLP(tlp))
|
||||||
|
return
|
||||||
|
elif isinstance(dev, Bridge) and dev.sec_bus_num <= tlp.requester_id.bus <= dev.sub_bus_num:
|
||||||
|
yield from p.ext_recv(TLP(tlp))
|
||||||
|
return
|
||||||
|
elif tlp.fmt_type == TLP_MSG_ID or tlp.fmt_type == TLP_MSG_DATA_ID:
|
||||||
|
# ID routed message
|
||||||
|
if tlp.dest_id == dev.get_id():
|
||||||
|
yield from p.ext_recv(TLP(tlp))
|
||||||
|
return
|
||||||
|
elif isinstance(dev, Bridge) and dev.sec_bus_num <= tlp.requester_id.bus <= dev.sub_bus_num:
|
||||||
|
yield from p.ext_recv(TLP(tlp))
|
||||||
|
return
|
||||||
|
elif (tlp.fmt_type == TLP_IO_READ or tlp.fmt_type == TLP_IO_WRITE):
|
||||||
|
# IO read/write
|
||||||
|
if dev.match_bar(tlp.address, True):
|
||||||
|
yield from p.ext_recv(TLP(tlp))
|
||||||
|
return
|
||||||
|
elif isinstance(dev, Bridge) and dev.io_base <= tlp.address <= dev.io_limit:
|
||||||
|
yield from p.ext_recv(TLP(tlp))
|
||||||
|
return
|
||||||
|
elif (tlp.fmt_type == TLP_MEM_READ or tlp.fmt_type == TLP_MEM_READ_64 or
|
||||||
|
tlp.fmt_type == TLP_MEM_WRITE or tlp.fmt_type == TLP_MEM_WRITE_64):
|
||||||
|
# Memory read/write
|
||||||
|
if dev.match_bar(tlp.address):
|
||||||
|
yield from p.ext_recv(TLP(tlp))
|
||||||
|
return
|
||||||
|
elif isinstance(dev, Bridge) and (dev.mem_base <= tlp.address <= dev.mem_limit or dev.prefetchable_mem_base <= tlp.address <= dev.prefetchable_mem_limit):
|
||||||
|
yield from p.ext_recv(TLP(tlp))
|
||||||
|
return
|
||||||
|
elif tlp.fmt_type == TLP_MSG_TO_RC or tlp.fmt_type == TLP_MSG_DATA_TO_RC:
|
||||||
|
# Message to root complex
|
||||||
|
# error
|
||||||
|
pass
|
||||||
|
elif tlp.fmt_type == TLP_MSG_BCAST or tlp.fmt_type == TLP_MSG_DATA_BCAST:
|
||||||
|
# Message broadcast from root complex
|
||||||
|
pass
|
||||||
|
elif tlp.fmt_type == TLP_MSG_LOCAL or tlp.fmt_type == TLP_MSG_DATA_LOCAL:
|
||||||
|
# Message local to receiver
|
||||||
|
# error
|
||||||
|
pass
|
||||||
|
elif tlp.fmt_type == TLP_MSG_GATHER or tlp.fmt_type == TLP_MSG_DATA_GATHER:
|
||||||
|
# Message gather to root complex
|
||||||
|
# error
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
# logging
|
||||||
|
raise Exception("Unknown/invalid packet type")
|
||||||
|
|
||||||
|
# Unsupported request
|
||||||
|
cpl = TLP()
|
||||||
|
cpl.set_ur_completion(tlp, (self.bus_num, self.device_num, 0))
|
||||||
|
# logging
|
||||||
|
print("[%s] UR Completion: %s" % (highlight(self.get_desc()), repr(cpl)))
|
||||||
|
if from_downstream:
|
||||||
|
yield from self.downstream_send(cpl)
|
||||||
|
else:
|
||||||
|
yield from self.upstream_send(cpl)
|
||||||
|
|
||||||
|
|
||||||
class SwitchDownstreamPort(Bridge):
|
class SwitchDownstreamPort(Bridge):
|
||||||
|
Loading…
x
Reference in New Issue
Block a user