mem: Port trace in xbar when address error (#180)

When xbar encounters the address error, print out the port trace in the
packet for user to debug if the port trace is enabled.

To gain the packet of the access, the parameter of findPort() function
is changed from AddrRange to PacketPtr.

When running gem5 with "--debug-flags=PortTrace", we can see the full
path of the unexpected access when xbar cannot find the destination of
the address.
This commit is contained in:
Bobby R. Bruce
2023-08-15 23:27:17 -07:00
committed by GitHub
6 changed files with 51 additions and 18 deletions

View File

@@ -159,7 +159,7 @@ CoherentXBar::recvTimingReq(PacketPtr pkt, PortID cpu_side_port_id)
assert(is_express_snoop == cache_responding);
// determine the destination based on the destination address range
PortID mem_side_port_id = findPort(pkt->getAddrRange());
PortID mem_side_port_id = findPort(pkt);
// test if the crossbar should be considered occupied for the current
// port, and exclude express snoops from the check
@@ -563,7 +563,7 @@ CoherentXBar::recvTimingSnoopReq(PacketPtr pkt, PortID mem_side_port_id)
// device responsible for the address range something is
// wrong, hence there is nothing further to do as the packet
// would be going back to where it came from
assert(findPort(pkt->getAddrRange()) == mem_side_port_id);
assert(findPort(pkt) == mem_side_port_id);
}
bool
@@ -799,7 +799,7 @@ CoherentXBar::recvAtomicBackdoor(PacketPtr pkt, PortID cpu_side_port_id,
// even if we had a snoop response, we must continue and also
// perform the actual request at the destination
PortID mem_side_port_id = findPort(pkt->getAddrRange());
PortID mem_side_port_id = findPort(pkt);
if (sink_packet) {
DPRINTF(CoherentXBar, "%s: Not forwarding %s\n", __func__,
@@ -1035,7 +1035,7 @@ CoherentXBar::recvFunctional(PacketPtr pkt, PortID cpu_side_port_id)
}
}
PortID dest_id = findPort(pkt->getAddrRange());
PortID dest_id = findPort(pkt);
memSidePorts[dest_id]->sendFunctional(pkt);
}

View File

@@ -107,8 +107,8 @@ NoncoherentXBar::recvTimingReq(PacketPtr pkt, PortID cpu_side_port_id)
// we should never see express snoops on a non-coherent crossbar
assert(!pkt->isExpressSnoop());
// determine the destination based on the address
PortID mem_side_port_id = findPort(pkt->getAddrRange());
// determine the destination port
PortID mem_side_port_id = findPort(pkt);
// test if the layer should be considered occupied for the current
// port
@@ -255,7 +255,7 @@ NoncoherentXBar::recvAtomicBackdoor(PacketPtr pkt, PortID cpu_side_port_id,
unsigned int pkt_cmd = pkt->cmdToIndex();
// determine the destination port
PortID mem_side_port_id = findPort(pkt->getAddrRange());
PortID mem_side_port_id = findPort(pkt);
// stats updates for the request
pktCount[cpu_side_port_id][mem_side_port_id]++;
@@ -316,7 +316,7 @@ NoncoherentXBar::recvFunctional(PacketPtr pkt, PortID cpu_side_port_id)
}
// determine the destination port
PortID dest_id = findPort(pkt->getAddrRange());
PortID dest_id = findPort(pkt);
// forward the request to the appropriate destination
memSidePorts[dest_id]->sendFunctional(pkt);

View File

@@ -197,7 +197,7 @@ RequestPort::addTrace(PacketPtr pkt) const
ext = std::make_shared<TracingExtension>();
pkt->setExtension(ext);
}
ext->add(name(), _responsePort->name());
ext->add(name(), _responsePort->name(), pkt->getAddr());
}
void

View File

@@ -47,6 +47,7 @@
#define __MEM_PORT_HH__
#include <memory>
#include <sstream>
#include <stack>
#include <string>
@@ -85,9 +86,9 @@ class TracingExtension : public gem5::Extension<Packet, TracingExtension>
}
void
add(std::string request_port, std::string response_port)
add(std::string request_port, std::string response_port, gem5::Addr addr)
{
trace_.push(request_port);
trace_.push(request_port + csprintf(" addr=%#llx", addr));
trace_.push(response_port);
}
@@ -100,6 +101,21 @@ class TracingExtension : public gem5::Extension<Packet, TracingExtension>
bool empty() { return trace_.empty(); }
std::stack<std::string>& getTrace() { return trace_; }
std::string getTraceInString()
{
std::stringstream port_trace;
std::stack<std::string> copy_stack = trace_;
port_trace << "Port trace of the Packet (" << std::endl
<< "[Destination] ";
while (!copy_stack.empty()) {
if (copy_stack.size() == 1)
port_trace << "[Source] ";
port_trace << copy_stack.top() << std::endl;
copy_stack.pop();
}
port_trace << ")";
return port_trace.str();
}
private:
std::stack<std::string> trace_;

View File

@@ -45,6 +45,9 @@
#include "mem/xbar.hh"
#include <memory>
#include <string>
#include "base/logging.hh"
#include "base/trace.hh"
#include "debug/AddrRanges.hh"
@@ -328,7 +331,7 @@ BaseXBar::Layer<SrcType, DstType>::recvRetry()
}
PortID
BaseXBar::findPort(AddrRange addr_range)
BaseXBar::findPort(AddrRange addr_range, PacketPtr pkt)
{
// we should never see any address lookups before we've got the
// ranges of all connected CPU-side-port modules
@@ -353,10 +356,17 @@ BaseXBar::findPort(AddrRange addr_range)
return defaultPortID;
}
// we should use the range for the default port and it did not
// match, or the default port is not set
fatal("Unable to find destination for %s on %s\n", addr_range.to_string(),
name());
// We should use the range for the default port and it did not match,
// or the default port is not set. Dump out the port trace if possible.
std::string port_trace = "";
if (pkt) {
std::shared_ptr<TracingExtension> ext =
pkt->getExtension<TracingExtension>();
port_trace = ext ? ext->getTraceInString() :
"Use --debug-flags=PortTrace to see the port trace of the packet.";
}
fatal("Unable to find destination for %s on %s\n%s\n",
addr_range.to_string(), name(), port_trace);
}
/** Function called by the port when the crossbar is receiving a range change.*/

View File

@@ -344,9 +344,16 @@ class BaseXBar : public ClockedObject
* given a packet with this address range.
*
* @param addr_range Address range to find port for.
* @return id of port that the packet should be sent out of.
* @param pkt Packet that containing the address range.
* @return id of port that the packet should be sent ou of.
*/
PortID findPort(AddrRange addr_range);
PortID findPort(AddrRange addr_range, PacketPtr pkt=nullptr);
PortID
findPort(PacketPtr pkt)
{
return findPort(pkt->getAddrRange(), pkt);
}
/**
* Return the address ranges the crossbar is responsible for.