addr_mapping = Param.AddrMap('RaBaChCo', "Address mapping policy")
page_policy = Param.PageManage('open', "Page closure management policy")
+ # pipeline latency of the controller and PHY, split into a
+ # frontend part and a backend part, with reads and writes serviced
+ # by the queues only seeing the frontend contribution, and reads
+ # serviced by the memory seeing the sum of the two
+ static_frontend_latency = Param.Latency("10ns", "Static frontend latency")
+ static_backend_latency = Param.Latency("10ns", "Static backend latency")
+
# the physical organisation of the DRAM
lines_per_rowbuffer = Param.Unsigned("Row buffer size in cache lines")
ranks_per_channel = Param.Unsigned("Number of ranks per channel")
tXAW(p->tXAW), activationLimit(p->activation_limit),
memSchedPolicy(p->mem_sched_policy), addrMapping(p->addr_mapping),
pageMgmt(p->page_policy),
+ frontendLatency(p->static_frontend_latency),
+ backendLatency(p->static_backend_latency),
busBusyUntil(0), writeStartTime(0),
prevArrival(0), numReqs(0)
{
DPRINTF(DRAM, "Read to %lld serviced by write queue\n", addr);
bytesRead += bytesPerCacheLine;
bytesConsumedRd += pkt->getSize();
- accessAndRespond(pkt);
+ accessAndRespond(pkt, frontendLatency);
return;
}
}
bytesConsumedWr += pkt->getSize();
bytesWritten += bytesPerCacheLine;
- accessAndRespond(pkt);
+ accessAndRespond(pkt, frontendLatency);
// If your write buffer is starting to fill up, drain it!
if (writeQueue.size() > writeThreshold && !stopReads){
} else {
DPRINTF(DRAM,"Neither read nor write, ignore timing\n");
neitherReadNorWrite++;
- accessAndRespond(pkt);
+ accessAndRespond(pkt, 1);
}
retryRdReq = false;
// Actually responds to the requestor
bytesConsumedRd += pkt->getSize();
bytesRead += bytesPerCacheLine;
- accessAndRespond(pkt);
+ accessAndRespond(pkt, frontendLatency + backendLatency);
delete respQueue.front();
respQueue.pop_front();
}
void
-SimpleDRAM::accessAndRespond(PacketPtr pkt)
+SimpleDRAM::accessAndRespond(PacketPtr pkt, Tick static_latency)
{
DPRINTF(DRAM, "Responding to Address %lld.. ",pkt->getAddr());
// @todo someone should pay for this
pkt->busFirstWordDelay = pkt->busLastWordDelay = 0;
- // queue the packet in the response queue to be sent out the
- // next tick
- port.schedTimingResp(pkt, curTick() + 1);
+ // queue the packet in the response queue to be sent out after
+ // the static latency has passed
+ port.schedTimingResp(pkt, curTick() + static_latency);
} else {
// @todo the packet is going to be deleted, and the DRAMPacket
// is still having a pointer to it
* world requestor.
*
* @param pkt The packet from the outside world
+ * @param static_latency Static latency to add before sending the packet
*/
- void accessAndRespond(PacketPtr pkt);
+ void accessAndRespond(PacketPtr pkt, Tick static_latency);
/**
* Address decoder to figure out physical mapping onto ranks,
Enums::AddrMap addrMapping;
Enums::PageManage pageMgmt;
+ /**
+ * Pipeline latency of the controller frontend. The frontend
+ * contribution is added to writes (that complete when they are in
+ * the write buffer) and reads that are serviced the write buffer.
+ */
+ const Tick frontendLatency;
+
+ /**
+ * Pipeline latency of the backend and PHY. Along with the
+ * frontend contribution, this latency is added to reads serviced
+ * by the DRAM.
+ */
+ const Tick backendLatency;
+
/**
* Till when has the main data bus been spoken for already?
*/