changeset eddb533708cb in /z/repo/gem5
details: http://repo.gem5.org/gem5?cmd=changeset;node=eddb533708cb
description:
mem: Split port retry for all different packet classes
This patch fixes a long-standing isue with the port flow
control. Before this patch the retry mechanism was shared between all
different packet classes. As a result, a snoop response could get
stuck behind a request waiting for a retry, even if the send/recv
functions were split. This caused message-dependent deadlocks in
stress-test scenarios.
The patch splits the retry into one per packet (message) class. Thus,
sendTimingReq has a corresponding recvReqRetry, sendTimingResp has
recvRespRetry etc. Most of the changes to the code involve simply
clarifying what type of request a specific object was accepting.
The biggest change in functionality is in the cache downstream packet
queue, facing the memory. This queue was shared by requests and snoop
responses, and it is now split into two queues, each with their own
flow control, but the same physical MasterPort. These changes fixes
the previously seen deadlocks.
diffstat:
src/arch/x86/pagetable_walker.cc | 6 +-
src/arch/x86/pagetable_walker.hh | 4 +-
src/cpu/kvm/base.hh | 4 +-
src/cpu/minor/fetch1.cc | 2 +-
src/cpu/minor/fetch1.hh | 4 +-
src/cpu/minor/lsq.cc | 2 +-
src/cpu/minor/lsq.hh | 4 +-
src/cpu/o3/cpu.cc | 8 +-
src/cpu/o3/cpu.hh | 4 +-
src/cpu/o3/fetch.hh | 2 +-
src/cpu/o3/fetch_impl.hh | 2 +-
src/cpu/o3/lsq.hh | 2 +-
src/cpu/o3/lsq_impl.hh | 2 +-
src/cpu/simple/atomic.hh | 2 +-
src/cpu/simple/timing.cc | 8 +-
src/cpu/simple/timing.hh | 8 +-
src/cpu/testers/directedtest/RubyDirectedTester.hh | 2 +-
src/cpu/testers/memtest/memtest.cc | 2 +-
src/cpu/testers/memtest/memtest.hh | 2 +-
src/cpu/testers/networktest/networktest.cc | 2 +-
src/cpu/testers/networktest/networktest.hh | 2 +-
src/cpu/testers/rubytest/RubyTester.hh | 2 +-
src/cpu/testers/traffic_gen/traffic_gen.cc | 2 +-
src/cpu/testers/traffic_gen/traffic_gen.hh | 4 +-
src/dev/dma_device.cc | 2 +-
src/dev/dma_device.hh | 2 +-
src/mem/addr_mapper.cc | 8 +-
src/mem/addr_mapper.hh | 12 +-
src/mem/bridge.cc | 8 +-
src/mem/bridge.hh | 4 +-
src/mem/cache/base.cc | 2 +-
src/mem/cache/base.hh | 12 +-
src/mem/cache/cache.hh | 15 +-
src/mem/cache/cache_impl.hh | 120 +++++++++------
src/mem/coherent_xbar.cc | 12 +-
src/mem/coherent_xbar.hh | 20 +-
src/mem/comm_monitor.cc | 8 +-
src/mem/comm_monitor.hh | 12 +-
src/mem/dram_ctrl.cc | 4 +-
src/mem/dram_ctrl.hh | 2 +-
src/mem/dramsim2.cc | 8 +-
src/mem/dramsim2.hh | 4 +-
src/mem/external_slave.cc | 6 +-
src/mem/mem_checker_monitor.cc | 8 +-
src/mem/mem_checker_monitor.hh | 12 +-
src/mem/mport.hh | 6 +-
src/mem/noncoherent_xbar.cc | 2 +-
src/mem/noncoherent_xbar.hh | 10 +-
src/mem/packet_queue.cc | 153 +++++++++++--------
src/mem/packet_queue.hh | 160 +++++++++++---------
src/mem/port.cc | 16 +-
src/mem/port.hh | 48 ++++--
src/mem/qport.hh | 65 +++++---
src/mem/ruby/slicc_interface/AbstractController.cc | 6 +-
src/mem/ruby/slicc_interface/AbstractController.hh | 5 +-
src/mem/ruby/structures/RubyMemoryControl.hh | 2 +-
src/mem/ruby/system/DMASequencer.cc | 2 +-
src/mem/ruby/system/DMASequencer.hh | 2 +-
src/mem/ruby/system/RubyPort.cc | 8 +-
src/mem/ruby/system/RubyPort.hh | 10 +-
src/mem/simple_mem.cc | 8 +-
src/mem/simple_mem.hh | 4 +-
src/mem/tport.cc | 2 +-
src/mem/tport.hh | 2 +-
src/mem/xbar.cc | 4 +-
src/mem/xbar.hh | 70 +++++++++-
src/sim/system.hh | 2 +-
67 files changed, 561 insertions(+), 389 deletions(-)
diffs (truncated from 2349 to 300 lines):
diff -r 245cd4691cbf -r eddb533708cb src/arch/x86/pagetable_walker.cc
--- a/src/arch/x86/pagetable_walker.cc Mon Mar 02 04:00:34 2015 -0500
+++ b/src/arch/x86/pagetable_walker.cc Mon Mar 02 04:00:35 2015 -0500
@@ -133,13 +133,13 @@
}
void
-Walker::WalkerPort::recvRetry()
+Walker::WalkerPort::recvReqRetry()
{
- walker->recvRetry();
+ walker->recvReqRetry();
}
void
-Walker::recvRetry()
+Walker::recvReqRetry()
{
std::list<WalkerState *>::iterator iter;
for (iter = currStates.begin(); iter != currStates.end(); iter++) {
diff -r 245cd4691cbf -r eddb533708cb src/arch/x86/pagetable_walker.hh
--- a/src/arch/x86/pagetable_walker.hh Mon Mar 02 04:00:34 2015 -0500
+++ b/src/arch/x86/pagetable_walker.hh Mon Mar 02 04:00:35 2015 -0500
@@ -77,7 +77,7 @@
void recvTimingSnoopReq(PacketPtr pkt) { }
Tick recvAtomicSnoop(PacketPtr pkt) { return 0; }
void recvFunctionalSnoop(PacketPtr pkt) { }
- void recvRetry();
+ void recvReqRetry();
bool isSnooping() const { return true; }
};
@@ -190,7 +190,7 @@
// Functions for dealing with packets.
bool recvTimingResp(PacketPtr pkt);
- void recvRetry();
+ void recvReqRetry();
bool sendTiming(WalkerState * sendingState, PacketPtr pkt);
public:
diff -r 245cd4691cbf -r eddb533708cb src/cpu/kvm/base.hh
--- a/src/cpu/kvm/base.hh Mon Mar 02 04:00:34 2015 -0500
+++ b/src/cpu/kvm/base.hh Mon Mar 02 04:00:35 2015 -0500
@@ -561,9 +561,9 @@
return true;
}
- void recvRetry()
+ void recvReqRetry()
{
- panic("The KVM CPU doesn't expect recvRetry!\n");
+ panic("The KVM CPU doesn't expect recvReqRetry!\n");
}
};
diff -r 245cd4691cbf -r eddb533708cb src/cpu/minor/fetch1.cc
--- a/src/cpu/minor/fetch1.cc Mon Mar 02 04:00:34 2015 -0500
+++ b/src/cpu/minor/fetch1.cc Mon Mar 02 04:00:35 2015 -0500
@@ -417,7 +417,7 @@
}
void
-Fetch1::recvRetry()
+Fetch1::recvReqRetry()
{
DPRINTF(Fetch, "recvRetry\n");
assert(icacheState == IcacheNeedsRetry);
diff -r 245cd4691cbf -r eddb533708cb src/cpu/minor/fetch1.hh
--- a/src/cpu/minor/fetch1.hh Mon Mar 02 04:00:34 2015 -0500
+++ b/src/cpu/minor/fetch1.hh Mon Mar 02 04:00:35 2015 -0500
@@ -77,7 +77,7 @@
bool recvTimingResp(PacketPtr pkt)
{ return fetch.recvTimingResp(pkt); }
- void recvRetry() { fetch.recvRetry(); }
+ void recvReqRetry() { fetch.recvReqRetry(); }
};
/** Memory access queuing.
@@ -345,7 +345,7 @@
/** Memory interface */
virtual bool recvTimingResp(PacketPtr pkt);
- virtual void recvRetry();
+ virtual void recvReqRetry();
public:
Fetch1(const std::string &name_,
diff -r 245cd4691cbf -r eddb533708cb src/cpu/minor/lsq.cc
--- a/src/cpu/minor/lsq.cc Mon Mar 02 04:00:34 2015 -0500
+++ b/src/cpu/minor/lsq.cc Mon Mar 02 04:00:35 2015 -0500
@@ -1235,7 +1235,7 @@
}
void
-LSQ::recvRetry()
+LSQ::recvReqRetry()
{
DPRINTF(MinorMem, "Received retry request\n");
diff -r 245cd4691cbf -r eddb533708cb src/cpu/minor/lsq.hh
--- a/src/cpu/minor/lsq.hh Mon Mar 02 04:00:34 2015 -0500
+++ b/src/cpu/minor/lsq.hh Mon Mar 02 04:00:35 2015 -0500
@@ -101,7 +101,7 @@
bool recvTimingResp(PacketPtr pkt)
{ return lsq.recvTimingResp(pkt); }
- void recvRetry() { lsq.recvRetry(); }
+ void recvReqRetry() { lsq.recvReqRetry(); }
void recvTimingSnoopReq(PacketPtr pkt)
{ return lsq.recvTimingSnoopReq(pkt); }
@@ -712,7 +712,7 @@
/** Memory interface */
bool recvTimingResp(PacketPtr pkt);
- void recvRetry();
+ void recvReqRetry();
void recvTimingSnoopReq(PacketPtr pkt);
/** Return the raw-bindable port */
diff -r 245cd4691cbf -r eddb533708cb src/cpu/o3/cpu.cc
--- a/src/cpu/o3/cpu.cc Mon Mar 02 04:00:34 2015 -0500
+++ b/src/cpu/o3/cpu.cc Mon Mar 02 04:00:35 2015 -0500
@@ -101,9 +101,9 @@
template<class Impl>
void
-FullO3CPU<Impl>::IcachePort::recvRetry()
+FullO3CPU<Impl>::IcachePort::recvReqRetry()
{
- fetch->recvRetry();
+ fetch->recvReqRetry();
}
template <class Impl>
@@ -126,9 +126,9 @@
template <class Impl>
void
-FullO3CPU<Impl>::DcachePort::recvRetry()
+FullO3CPU<Impl>::DcachePort::recvReqRetry()
{
- lsq->recvRetry();
+ lsq->recvReqRetry();
}
template <class Impl>
diff -r 245cd4691cbf -r eddb533708cb src/cpu/o3/cpu.hh
--- a/src/cpu/o3/cpu.hh Mon Mar 02 04:00:34 2015 -0500
+++ b/src/cpu/o3/cpu.hh Mon Mar 02 04:00:35 2015 -0500
@@ -150,7 +150,7 @@
virtual void recvTimingSnoopReq(PacketPtr pkt) { }
/** Handles doing a retry of a failed fetch. */
- virtual void recvRetry();
+ virtual void recvReqRetry();
};
/**
@@ -185,7 +185,7 @@
}
/** Handles doing a retry of the previous send. */
- virtual void recvRetry();
+ virtual void recvReqRetry();
/**
* As this CPU requires snooping to maintain the load store queue
diff -r 245cd4691cbf -r eddb533708cb src/cpu/o3/fetch.hh
--- a/src/cpu/o3/fetch.hh Mon Mar 02 04:00:34 2015 -0500
+++ b/src/cpu/o3/fetch.hh Mon Mar 02 04:00:35 2015 -0500
@@ -224,7 +224,7 @@
void startupStage();
/** Handles retrying the fetch access. */
- void recvRetry();
+ void recvReqRetry();
/** Processes cache completion event. */
void processCacheCompletion(PacketPtr pkt);
diff -r 245cd4691cbf -r eddb533708cb src/cpu/o3/fetch_impl.hh
--- a/src/cpu/o3/fetch_impl.hh Mon Mar 02 04:00:34 2015 -0500
+++ b/src/cpu/o3/fetch_impl.hh Mon Mar 02 04:00:35 2015 -0500
@@ -1407,7 +1407,7 @@
template<class Impl>
void
-DefaultFetch<Impl>::recvRetry()
+DefaultFetch<Impl>::recvReqRetry()
{
if (retryPkt != NULL) {
assert(cacheBlocked);
diff -r 245cd4691cbf -r eddb533708cb src/cpu/o3/lsq.hh
--- a/src/cpu/o3/lsq.hh Mon Mar 02 04:00:34 2015 -0500
+++ b/src/cpu/o3/lsq.hh Mon Mar 02 04:00:35 2015 -0500
@@ -286,7 +286,7 @@
/**
* Retry the previous send that failed.
*/
- void recvRetry();
+ void recvReqRetry();
/**
* Handles writing back and completing the load or store that has
diff -r 245cd4691cbf -r eddb533708cb src/cpu/o3/lsq_impl.hh
--- a/src/cpu/o3/lsq_impl.hh Mon Mar 02 04:00:34 2015 -0500
+++ b/src/cpu/o3/lsq_impl.hh Mon Mar 02 04:00:35 2015 -0500
@@ -330,7 +330,7 @@
template <class Impl>
void
-LSQ<Impl>::recvRetry()
+LSQ<Impl>::recvReqRetry()
{
iewStage->cacheUnblocked();
diff -r 245cd4691cbf -r eddb533708cb src/cpu/simple/atomic.hh
--- a/src/cpu/simple/atomic.hh Mon Mar 02 04:00:34 2015 -0500
+++ b/src/cpu/simple/atomic.hh Mon Mar 02 04:00:35 2015 -0500
@@ -139,7 +139,7 @@
return true;
}
- void recvRetry()
+ void recvReqRetry()
{
panic("Atomic CPU doesn't expect recvRetry!\n");
}
diff -r 245cd4691cbf -r eddb533708cb src/cpu/simple/timing.cc
--- a/src/cpu/simple/timing.cc Mon Mar 02 04:00:34 2015 -0500
+++ b/src/cpu/simple/timing.cc Mon Mar 02 04:00:35 2015 -0500
@@ -729,7 +729,7 @@
}
void
-TimingSimpleCPU::IcachePort::recvRetry()
+TimingSimpleCPU::IcachePort::recvReqRetry()
{
// we shouldn't get a retry unless we have a packet that we're
// waiting to transmit
@@ -846,8 +846,8 @@
// In the case of a split transaction and a cache that is
// faster than a CPU we could get two responses in the
// same tick, delay the second one
- if (!retryEvent.scheduled())
- cpu->schedule(retryEvent, cpu->clockEdge(Cycles(1)));
+ if (!retryRespEvent.scheduled())
+ cpu->schedule(retryRespEvent, cpu->clockEdge(Cycles(1)));
return false;
}
}
@@ -859,7 +859,7 @@
}
void
-TimingSimpleCPU::DcachePort::recvRetry()
+TimingSimpleCPU::DcachePort::recvReqRetry()
{
// we shouldn't get a retry unless we have a packet that we're
// waiting to transmit
diff -r 245cd4691cbf -r eddb533708cb src/cpu/simple/timing.hh
--- a/src/cpu/simple/timing.hh Mon Mar 02 04:00:34 2015 -0500
+++ b/src/cpu/simple/timing.hh Mon Mar 02 04:00:35 2015 -0500
@@ -157,7 +157,7 @@
public:
TimingCPUPort(const std::string& _name, TimingSimpleCPU* _cpu)
- : MasterPort(_name, _cpu), cpu(_cpu), retryEvent(this)
+ : MasterPort(_name, _cpu), cpu(_cpu), retryRespEvent(this)
{ }
protected:
@@ -179,7 +179,7 @@
void schedule(PacketPtr _pkt, Tick t);
};
- EventWrapper<MasterPort, &MasterPort::sendRetry> retryEvent;
+ EventWrapper<MasterPort, &MasterPort::sendRetryResp> retryRespEvent;
};
class IcachePort : public TimingCPUPort
@@ -195,7 +195,7 @@
virtual bool recvTimingResp(PacketPtr pkt);
- virtual void recvRetry();
+ virtual void recvReqRetry();
struct ITickEvent : public TickEvent
{
@@ -232,7 +232,7 @@
virtual bool recvTimingResp(PacketPtr pkt);
- virtual void recvRetry();
+ virtual void recvReqRetry();
virtual bool isSnooping() const {
_______________________________________________
gem5-dev mailing list
[email protected]
http://m5sim.org/mailman/listinfo/gem5-dev