cpu: Ensure timing CPU sinks response before sending new request

This patch changes how the timing CPU deals with processing responses,
always scheduling an event, even if it is for the current tick. This
helps to avoid situations where a new request shows up before a
response is finished in the crossbar, and also is more in line with
any realistic behaviour.
This commit is contained in:
Andreas Hansson 2015-02-03 14:25:27 -05:00
parent 3e33786db8
commit 20111ba917

View file

@ -718,14 +718,12 @@ TimingSimpleCPU::IcachePort::ITickEvent::process()
bool bool
TimingSimpleCPU::IcachePort::recvTimingResp(PacketPtr pkt) TimingSimpleCPU::IcachePort::recvTimingResp(PacketPtr pkt)
{ {
DPRINTF(SimpleCPU, "Received timing response %#x\n", pkt->getAddr()); DPRINTF(SimpleCPU, "Received fetch response %#x\n", pkt->getAddr());
// we should only ever see one response per cycle since we only
// issue a new request once this response is sunk
assert(!tickEvent.scheduled());
// delay processing of returned data until next CPU clock edge // delay processing of returned data until next CPU clock edge
Tick next_tick = cpu->clockEdge(); tickEvent.schedule(pkt, cpu->clockEdge());
if (next_tick == curTick())
cpu->completeIfetch(pkt);
else
tickEvent.schedule(pkt, next_tick);
return true; return true;
} }
@ -836,25 +834,22 @@ TimingSimpleCPU::DcachePort::recvFunctionalSnoop(PacketPtr pkt)
bool bool
TimingSimpleCPU::DcachePort::recvTimingResp(PacketPtr pkt) TimingSimpleCPU::DcachePort::recvTimingResp(PacketPtr pkt)
{ {
// delay processing of returned data until next CPU clock edge DPRINTF(SimpleCPU, "Received load/store response %#x\n", pkt->getAddr());
Tick next_tick = cpu->clockEdge();
if (next_tick == curTick()) { // The timing CPU is not really ticked, instead it relies on the
cpu->completeDataAccess(pkt); // memory system (fetch and load/store) to set the pace.
if (!tickEvent.scheduled()) {
// Delay processing of returned data until next CPU clock edge
tickEvent.schedule(pkt, cpu->clockEdge());
return true;
} else { } else {
if (!tickEvent.scheduled()) { // In the case of a split transaction and a cache that is
tickEvent.schedule(pkt, next_tick); // faster than a CPU we could get two responses in the
} else { // same tick, delay the second one
// In the case of a split transaction and a cache that is if (!retryEvent.scheduled())
// faster than a CPU we could get two responses before cpu->schedule(retryEvent, cpu->clockEdge(Cycles(1)));
// next_tick expires return false;
if (!retryEvent.scheduled())
cpu->schedule(retryEvent, next_tick);
return false;
}
} }
return true;
} }
void void