diff -r 78c1695b68d7 -r 70bd9d295117 src/mem/dram_ctrl.hh --- a/src/mem/dram_ctrl.hh Mon Mar 17 08:19:08 2014 +0000 +++ b/src/mem/dram_ctrl.hh Mon Mar 17 08:19:09 2014 +0000 @@ -487,6 +487,7 @@ const uint32_t writeLowThreshold; const uint32_t minWritesPerSwitch; uint32_t writesThisTime; + uint32_t readsThisTime; /** * Basic memory timing parameters initialized based on parameter @@ -570,6 +571,8 @@ Stats::Vector rdQLenPdf; Stats::Vector wrQLenPdf; Stats::Histogram bytesPerActivate; + Stats::Histogram rdPerTurnAround; + Stats::Histogram wrPerTurnAround; // Latencies summed over all requests Stats::Scalar totQLat; diff -r 78c1695b68d7 -r 70bd9d295117 src/mem/dram_ctrl.cc --- a/src/mem/dram_ctrl.cc Mon Mar 17 08:19:08 2014 +0000 +++ b/src/mem/dram_ctrl.cc Mon Mar 17 08:19:09 2014 +0000 @@ -70,7 +70,8 @@ writeBufferSize(p->write_buffer_size), writeHighThreshold(writeBufferSize * p->write_high_thresh_perc / 100.0), writeLowThreshold(writeBufferSize * p->write_low_thresh_perc / 100.0), - minWritesPerSwitch(p->min_writes_per_switch), writesThisTime(0), + minWritesPerSwitch(p->min_writes_per_switch), + writesThisTime(0), readsThisTime(0), tWTR(p->tWTR), tBURST(p->tBURST), tRCD(p->tRCD), tCL(p->tCL), tRP(p->tRP), tRAS(p->tRAS), tRFC(p->tRFC), tREFI(p->tREFI), tRRD(p->tRRD), @@ -396,24 +397,29 @@ writeQueue.pop_front(); delete dram_pkt; - ++writesThisTime; - DPRINTF(DRAM, "Writing, bus busy for %lld ticks, banks busy " "for %lld ticks\n", busBusyUntil - temp1, maxBankFreeAt() - temp2); // Update stats avgWrQLen = writeQueue.size(); - // If we emptied the write queue, or got below the threshold and + // If we emptied the write queue, or got sufficiently below the + // threshold (using the minWritesPerSwitch as the hysteresis) and // are not draining, or we have reads waiting and have done enough // writes, then switch to reads. The retry above could already // have caused it to be scheduled, so first check if (writeQueue.empty() || - (writeQueue.size() < writeLowThreshold && !drainManager) || + (writeQueue.size() + minWritesPerSwitch < writeLowThreshold && + !drainManager) || (!readQueue.empty() && writesThisTime >= minWritesPerSwitch)) { // turn the bus back around for reads again busBusyUntil += tWTR; stopReads = false; + + DPRINTF(DRAM, "Switching to reads after %d writes with %d writes " + "waiting\n", writesThisTime, writeQueue.size()); + + wrPerTurnAround.sample(writesThisTime); writesThisTime = 0; if (!nextReqEvent.scheduled()) @@ -441,7 +447,9 @@ void DRAMCtrl::triggerWrites() { - DPRINTF(DRAM, "Writes triggered at %lld\n", curTick()); + DPRINTF(DRAM, "Switching to writes after %d reads with %d reads " + "waiting\n", readsThisTime, readQueue.size()); + // Flag variable to stop any more read scheduling stopReads = true; @@ -449,6 +457,11 @@ DPRINTF(DRAM, "Writes scheduled at %lld\n", writeStartTime); + // there is some danger here as there might still be reads + // happening before the switch actually takes place + rdPerTurnAround.sample(readsThisTime); + readsThisTime = 0; + assert(writeStartTime >= curTick()); assert(!writeEvent.scheduled()); schedule(writeEvent, writeStartTime); @@ -1203,11 +1216,13 @@ // Update the access related stats if (dram_pkt->isRead) { + ++readsThisTime; if (rowHitFlag) readRowHits++; bytesReadDRAM += burstSize; perBankRdBursts[dram_pkt->bankId]++; } else { + ++writesThisTime; if (rowHitFlag) writeRowHits++; bytesWritten += burstSize; @@ -1523,6 +1538,18 @@ .desc("Bytes accessed per row activation") .flags(nozero); + rdPerTurnAround + .init(readBufferSize) + .name(name() + ".rdPerTurnAround") + .desc("Reads before turning the bus around for writes") + .flags(nozero); + + wrPerTurnAround + .init(writeBufferSize) + .name(name() + ".wrPerTurnAround") + .desc("Writes before turning the bus around for reads") + .flags(nozero); + bytesReadDRAM .name(name() + ".bytesReadDRAM") .desc("Total number of bytes read from DRAM");