* Authors: Andreas Hansson
*/
+#include "mem/dramsim2.hh"
+
#include "DRAMSim2/Callback.h"
#include "base/callback.hh"
#include "base/trace.hh"
#include "debug/DRAMSim2.hh"
#include "debug/Drain.hh"
-#include "mem/dramsim2.hh"
#include "sim/system.hh"
DRAMSim2::DRAMSim2(const Params* p) :
p->traceFile, p->range.size() / 1024 / 1024, p->enableDebug),
retryReq(false), retryResp(false), startTick(0),
nbrOutstandingReads(0), nbrOutstandingWrites(0),
- drainManager(NULL),
- sendResponseEvent(this), tickEvent(this)
+ sendResponseEvent([this]{ sendResponse(); }, name()),
+ tickEvent([this]{ tick(); }, name())
{
DPRINTF(DRAMSim2,
"Instantiated DRAMSim2 with clock %d ns and queue size %d\n",
if (!responseQueue.empty() && !sendResponseEvent.scheduled())
schedule(sendResponseEvent, curTick());
- // check if we were asked to drain and if we are now done
- if (drainManager && nbrOutstanding() == 0) {
- drainManager->signalDrainDone();
- drainManager = NULL;
- }
+ if (nbrOutstanding() == 0)
+ signalDrainDone();
} else {
retryResp = true;
// state and send a retry if conditions have changed
if (retryReq && nbrOutstanding() < wrapper.queueSize()) {
retryReq = false;
- port.sendRetry();
+ port.sendRetryReq();
}
schedule(tickEvent, curTick() + wrapper.clockPeriod() * SimClock::Int::ns);
access(pkt);
// 50 ns is just an arbitrary value at this point
- return pkt->memInhibitAsserted() ? 0 : 50000;
+ return pkt->cacheResponding() ? 0 : 50000;
}
void
// potentially update the packets in our response queue as well
for (auto i = responseQueue.begin(); i != responseQueue.end(); ++i)
- pkt->checkFunctional(*i);
+ pkt->trySatisfyFunctional(*i);
pkt->popLabel();
}
bool
DRAMSim2::recvTimingReq(PacketPtr pkt)
{
- // we should never see a new request while in retry
- assert(!retryReq);
-
- // @todo temporary hack to deal with memory corruption issues until
- // 4-phase transactions are complete
- for (int x = 0; x < pendingDelete.size(); x++)
- delete pendingDelete[x];
- pendingDelete.clear();
-
- if (pkt->memInhibitAsserted()) {
- // snooper will supply based on copy of packet
- // still target's responsibility to delete packet
- pendingDelete.push_back(pkt);
+ // if a cache is responding, sink the packet without further action
+ if (pkt->cacheResponding()) {
+ pendingDelete.reset(pkt);
return true;
}
+ // we should not get a new request after committing to retry the
+ // current one, but unfortunately the CPU violates this rule, so
+ // simply ignore it for now
+ if (retryReq)
+ return false;
+
// if we cannot accept we need to send a retry once progress can
// be made
bool can_accept = nbrOutstanding() < wrapper.queueSize();
}
void
-DRAMSim2::recvRetry()
+DRAMSim2::recvRespRetry()
{
DPRINTF(DRAMSim2, "Retrying\n");
if (needsResponse) {
// access already turned the packet into a response
assert(pkt->isResponse());
-
- // @todo someone should pay for this
+ // Here we pay for xbar additional delay and to process the payload
+ // of the packet.
+ Tick time = curTick() + pkt->headerDelay + pkt->payloadDelay;
+ // Reset the timings of the packet
pkt->headerDelay = pkt->payloadDelay = 0;
DPRINTF(DRAMSim2, "Queuing response for address %lld\n",
// if we are not already waiting for a retry, or are scheduled
// to send a response, schedule an event
if (!retryResp && !sendResponseEvent.scheduled())
- schedule(sendResponseEvent, curTick());
+ schedule(sendResponseEvent, time);
} else {
- // @todo the packet is going to be deleted, and the DRAMPacket
- // is still having a pointer to it
- pendingDelete.push_back(pkt);
+ // queue the packet for deletion
+ pendingDelete.reset(pkt);
}
}
assert(nbrOutstandingWrites != 0);
--nbrOutstandingWrites;
- // check if we were asked to drain and if we are now done
- if (drainManager && nbrOutstanding() == 0) {
- drainManager->signalDrainDone();
- drainManager = NULL;
- }
+ if (nbrOutstanding() == 0)
+ signalDrainDone();
}
-BaseSlavePort&
-DRAMSim2::getSlavePort(const std::string &if_name, PortID idx)
+Port &
+DRAMSim2::getPort(const std::string &if_name, PortID idx)
{
if (if_name != "port") {
- return MemObject::getSlavePort(if_name, idx);
+ return AbstractMemory::getPort(if_name, idx);
} else {
return port;
}
}
-unsigned int
-DRAMSim2::drain(DrainManager* dm)
+DrainState
+DRAMSim2::drain()
{
// check our outstanding reads and writes and if any they need to
// drain
- if (nbrOutstanding() != 0) {
- setDrainState(Drainable::Draining);
- drainManager = dm;
- return 1;
- } else {
- setDrainState(Drainable::Drained);
- return 0;
- }
+ return nbrOutstanding() != 0 ? DrainState::Draining : DrainState::Drained;
}
DRAMSim2::MemoryPort::MemoryPort(const std::string& _name,
}
void
-DRAMSim2::MemoryPort::recvRetry()
+DRAMSim2::MemoryPort::recvRespRetry()
{
- memory.recvRetry();
+ memory.recvRespRetry();
}
DRAMSim2*