diff --git a/src/mem/SimpleDRAM.py b/src/mem/SimpleDRAM.py index 8de210641..81bb0ff42 100644 --- a/src/mem/SimpleDRAM.py +++ b/src/mem/SimpleDRAM.py @@ -135,6 +135,9 @@ class SimpleDRAM(AbstractMemory): # write-to-read turn around penalty, assumed same as read-to-write tWTR = Param.Latency("Write to read switching time") + # minimum row activate to row activate delay time + tRRD = Param.Latency("ACT to ACT delay") + # time window in which a maximum number of activates are allowed # to take place, set to 0 to disable tXAW = Param.Latency("X activation window") @@ -187,6 +190,9 @@ class DDR3_1600_x64(SimpleDRAM): # Greater of 4 CK or 7.5 ns, 4 CK @ 800 MHz = 5 ns tWTR = '7.5ns' + # Assume 5 CK for activate to activate for different banks + tRRD = '6.25ns' + # With a 2kbyte page size, DDR3-1600 lands around 40 ns tXAW = '40ns' activation_limit = 4 @@ -239,6 +245,9 @@ class LPDDR2_S4_1066_x32(SimpleDRAM): # Irrespective of speed grade, tWTR is 7.5 ns tWTR = '7.5ns' + # Activate to activate irrespective of density and speed grade + tRRD = '10.0ns' + # Irrespective of density, tFAW is 50 ns tXAW = '50ns' activation_limit = 4 @@ -284,6 +293,9 @@ class WideIO_200_x128(SimpleDRAM): # Greater of 2 CK or 15 ns, 2 CK @ 200 MHz = 10 ns tWTR = '15ns' + # Activate to activate irrespective of density and speed grade + tRRD = '10.0ns' + # Two instead of four activation window tXAW = '50ns' activation_limit = 2 @@ -335,6 +347,9 @@ class LPDDR3_1600_x32(SimpleDRAM): # Irrespective of speed grade, tWTR is 7.5 ns tWTR = '7.5ns' + # Activate to activate irrespective of density and speed grade + tRRD = '10.0ns' + # Irrespective of size, tFAW is 50 ns tXAW = '50ns' activation_limit = 4 diff --git a/src/mem/simple_dram.cc b/src/mem/simple_dram.cc index bd700c09d..7e377b861 100644 --- a/src/mem/simple_dram.cc +++ b/src/mem/simple_dram.cc @@ -70,7 +70,7 @@ SimpleDRAM::SimpleDRAM(const SimpleDRAMParams* p) : writeThresholdPerc(p->write_thresh_perc), tWTR(p->tWTR), tBURST(p->tBURST), tRCD(p->tRCD), tCL(p->tCL), tRP(p->tRP), tRAS(p->tRAS), - tRFC(p->tRFC), tREFI(p->tREFI), + tRFC(p->tRFC), tREFI(p->tREFI), tRRD(p->tRRD), tXAW(p->tXAW), activationLimit(p->activation_limit), memSchedPolicy(p->mem_sched_policy), addrMapping(p->addr_mapping), pageMgmt(p->page_policy), @@ -988,14 +988,25 @@ SimpleDRAM::processNextReqEvent() } void -SimpleDRAM::recordActivate(Tick act_tick, uint8_t rank) +SimpleDRAM::recordActivate(Tick act_tick, uint8_t rank, uint8_t bank) { assert(0 <= rank && rank < ranksPerChannel); assert(actTicks[rank].size() == activationLimit); DPRINTF(DRAM, "Activate at tick %d\n", act_tick); - // if the activation limit is disabled then we are done + // start by enforcing tRRD + for(int i = 0; i < banksPerRank; i++) { + // next activate must not happen before tRRD + banks[rank][i].actAllowedAt = act_tick + tRRD; + } + // tRC should be added to activation tick of the bank currently accessed, + // where tRC = tRAS + tRP, this is just for a check as actAllowedAt for same + // bank is already captured by bank.freeAt and bank.tRASDoneAt + banks[rank][bank].actAllowedAt = act_tick + tRAS + tRP; + + // next, we deal with tXAW, if the activation limit is disabled + // then we are done if (actTicks[rank].empty()) return; @@ -1061,24 +1072,24 @@ SimpleDRAM::doDRAMAccess(DRAMPacket* dram_pkt) // any waiting for banks account for in freeAt actTick = bank.freeAt - tCL - tRCD; bank.tRASDoneAt = actTick + tRAS; - recordActivate(actTick, dram_pkt->rank); + recordActivate(actTick, dram_pkt->rank, dram_pkt->bank); // sample the number of bytes accessed and reset it as // we are now closing this row bytesPerActivate.sample(bank.bytesAccessed); bank.bytesAccessed = 0; } + DPRINTF(DRAM, "doDRAMAccess::bank.freeAt is %lld\n", bank.freeAt); } else if (pageMgmt == Enums::close) { actTick = curTick() + addDelay + accessLat - tRCD - tCL; - recordActivate(actTick, dram_pkt->rank); + recordActivate(actTick, dram_pkt->rank, dram_pkt->bank); // If the DRAM has a very quick tRAS, bank can be made free // after consecutive tCL,tRCD,tRP times. In general, however, // an additional wait is required to respect tRAS. bank.freeAt = std::max(actTick + tRAS + tRP, actTick + tRCD + tCL + tRP); - - DPRINTF(DRAM,"doDRAMAccess::bank.freeAt is %lld\n",bank.freeAt); + DPRINTF(DRAM, "doDRAMAccess::bank.freeAt is %lld\n", bank.freeAt); bytesPerActivate.sample(burstSize); } else panic("No page management policy chosen\n"); diff --git a/src/mem/simple_dram.hh b/src/mem/simple_dram.hh index c97f70e1d..dfb8fc15f 100644 --- a/src/mem/simple_dram.hh +++ b/src/mem/simple_dram.hh @@ -420,7 +420,7 @@ class SimpleDRAM : public AbstractMemory * method updates the time that the banks become available based * on the current limits. */ - void recordActivate(Tick act_tick, uint8_t rank); + void recordActivate(Tick act_tick, uint8_t rank, uint8_t bank); void printParams() const; void printQs() const; @@ -487,6 +487,7 @@ class SimpleDRAM : public AbstractMemory const Tick tRAS; const Tick tRFC; const Tick tREFI; + const Tick tRRD; const Tick tXAW; const uint32_t activationLimit;