mem: port: add TracingExtension for debug purpose
TracingExtension contains a stack recording the port names passed through of the Packet. The target receiving the Packet can dump out the whole path of this Packet for the debug purpose. This mechanism can be enabled with the debug flag PortTrace. Change-Id: Ic11e708b35fdddc4f4b786d91b35fd4def08948c Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/71538 Reviewed-by: Jason Lowe-Power <power.jg@gmail.com> Maintainer: Jason Lowe-Power <power.jg@gmail.com> Tested-by: kokoro <noreply+kokoro@google.com> Reviewed-by: Yu-hsin Wang <yuhsingw@google.com>
This commit is contained in:
@@ -151,6 +151,7 @@ DebugFlag('MemCtrl')
|
||||
DebugFlag('MMU')
|
||||
DebugFlag('MemoryAccess')
|
||||
DebugFlag('PacketQueue')
|
||||
DebugFlag("PortTrace")
|
||||
DebugFlag('ResponsePort')
|
||||
DebugFlag('StackDist')
|
||||
DebugFlag("DRAMSim2")
|
||||
|
||||
@@ -45,6 +45,7 @@
|
||||
#include "mem/port.hh"
|
||||
|
||||
#include "base/trace.hh"
|
||||
#include "debug/PortTrace.hh"
|
||||
#include "debug/ResponsePort.hh"
|
||||
#include "sim/sim_object.hh"
|
||||
|
||||
@@ -186,6 +187,29 @@ RequestPort::printAddr(Addr a)
|
||||
sendFunctional(&pkt);
|
||||
}
|
||||
|
||||
void
|
||||
RequestPort::addTrace(PacketPtr pkt) const
|
||||
{
|
||||
if (!gem5::debug::PortTrace || !pkt)
|
||||
return;
|
||||
auto ext = pkt->getExtension<TracingExtension>();
|
||||
if (!ext) {
|
||||
ext = std::make_shared<TracingExtension>();
|
||||
pkt->setExtension(ext);
|
||||
}
|
||||
ext->add(name(), _responsePort->name());
|
||||
}
|
||||
|
||||
void
|
||||
RequestPort::removeTrace(PacketPtr pkt) const
|
||||
{
|
||||
if (!gem5::debug::PortTrace || !pkt)
|
||||
return;
|
||||
auto ext = pkt->getExtension<TracingExtension>();
|
||||
panic_if(!ext, "There is no TracingExtension in the packet.");
|
||||
ext->remove();
|
||||
}
|
||||
|
||||
/**
|
||||
* Response port
|
||||
*/
|
||||
|
||||
@@ -46,6 +46,10 @@
|
||||
#ifndef __MEM_PORT_HH__
|
||||
#define __MEM_PORT_HH__
|
||||
|
||||
#include <memory>
|
||||
#include <stack>
|
||||
#include <string>
|
||||
|
||||
#include "base/addr_range.hh"
|
||||
#include "mem/packet.hh"
|
||||
#include "mem/protocol/atomic.hh"
|
||||
@@ -64,6 +68,43 @@ class SlavePort;
|
||||
|
||||
class ResponsePort;
|
||||
|
||||
/**
|
||||
* TracingExtension is an Extension of the Packet for recording the trace
|
||||
* of the Packet. The stack in the TracingExtension holds the name of the
|
||||
* ports that the Packet has passed through.
|
||||
*/
|
||||
class TracingExtension : public gem5::Extension<Packet, TracingExtension>
|
||||
{
|
||||
public:
|
||||
TracingExtension() = default;
|
||||
TracingExtension(const std::stack<std::string>& q) { trace_ = q; }
|
||||
|
||||
std::unique_ptr<ExtensionBase> clone() const override
|
||||
{
|
||||
return std::make_unique<TracingExtension>(trace_);
|
||||
}
|
||||
|
||||
void
|
||||
add(std::string request_port, std::string response_port)
|
||||
{
|
||||
trace_.push(request_port);
|
||||
trace_.push(response_port);
|
||||
}
|
||||
|
||||
void
|
||||
remove()
|
||||
{
|
||||
trace_.pop(); // Remove the response port name.
|
||||
trace_.pop(); // Remove the request port name.
|
||||
}
|
||||
|
||||
bool empty() { return trace_.empty(); }
|
||||
std::stack<std::string>& getTrace() { return trace_; }
|
||||
|
||||
private:
|
||||
std::stack<std::string> trace_;
|
||||
};
|
||||
|
||||
/**
|
||||
* A RequestPort is a specialisation of a Port, which
|
||||
* implements the default protocol for the three different level of
|
||||
@@ -266,6 +307,10 @@ class RequestPort: public Port, public AtomicRequestProtocol,
|
||||
{
|
||||
panic("%s was not expecting a snoop retry.\n", name());
|
||||
}
|
||||
|
||||
private:
|
||||
void addTrace(PacketPtr pkt) const;
|
||||
void removeTrace(PacketPtr pkt) const;
|
||||
};
|
||||
|
||||
class [[deprecated]] MasterPort : public RequestPort
|
||||
@@ -393,7 +438,11 @@ class ResponsePort : public Port, public AtomicResponseProtocol,
|
||||
sendTimingResp(PacketPtr pkt)
|
||||
{
|
||||
try {
|
||||
return TimingResponseProtocol::sendResp(_requestPort, pkt);
|
||||
_requestPort->removeTrace(pkt);
|
||||
bool succ = TimingResponseProtocol::sendResp(_requestPort, pkt);
|
||||
if (!succ)
|
||||
_requestPort->addTrace(pkt);
|
||||
return succ;
|
||||
} catch (UnboundPortException) {
|
||||
reportUnbound();
|
||||
}
|
||||
@@ -487,7 +536,10 @@ inline Tick
|
||||
RequestPort::sendAtomic(PacketPtr pkt)
|
||||
{
|
||||
try {
|
||||
return AtomicRequestProtocol::send(_responsePort, pkt);
|
||||
addTrace(pkt);
|
||||
Tick tick = AtomicRequestProtocol::send(_responsePort, pkt);
|
||||
removeTrace(pkt);
|
||||
return tick;
|
||||
} catch (UnboundPortException) {
|
||||
reportUnbound();
|
||||
}
|
||||
@@ -497,8 +549,11 @@ inline Tick
|
||||
RequestPort::sendAtomicBackdoor(PacketPtr pkt, MemBackdoorPtr &backdoor)
|
||||
{
|
||||
try {
|
||||
return AtomicRequestProtocol::sendBackdoor(_responsePort,
|
||||
pkt, backdoor);
|
||||
addTrace(pkt);
|
||||
Tick tick = AtomicRequestProtocol::sendBackdoor(_responsePort,
|
||||
pkt, backdoor);
|
||||
removeTrace(pkt);
|
||||
return tick;
|
||||
} catch (UnboundPortException) {
|
||||
reportUnbound();
|
||||
}
|
||||
@@ -508,7 +563,9 @@ inline void
|
||||
RequestPort::sendFunctional(PacketPtr pkt) const
|
||||
{
|
||||
try {
|
||||
return FunctionalRequestProtocol::send(_responsePort, pkt);
|
||||
addTrace(pkt);
|
||||
FunctionalRequestProtocol::send(_responsePort, pkt);
|
||||
removeTrace(pkt);
|
||||
} catch (UnboundPortException) {
|
||||
reportUnbound();
|
||||
}
|
||||
@@ -530,7 +587,11 @@ inline bool
|
||||
RequestPort::sendTimingReq(PacketPtr pkt)
|
||||
{
|
||||
try {
|
||||
return TimingRequestProtocol::sendReq(_responsePort, pkt);
|
||||
addTrace(pkt);
|
||||
bool succ = TimingRequestProtocol::sendReq(_responsePort, pkt);
|
||||
if (!succ)
|
||||
removeTrace(pkt);
|
||||
return succ;
|
||||
} catch (UnboundPortException) {
|
||||
reportUnbound();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user