From d4cf009b95d34b75408363bc085c2e9e9de458d9 Mon Sep 17 00:00:00 2001 From: Ani Udipi Date: Fri, 1 Nov 2013 11:56:16 -0400 Subject: [PATCH] mem: Add tRAS parameter to the DRAM controller model This patch adds an explicit tRAS parameter to the DRAM controller model. Previously tRAS was, rather conservatively, assumed to be tRCD + tCL + tRP. The default values for tRAS are chosen to match the previous behaviour and will be updated later. --- src/mem/SimpleDRAM.py | 15 ++++++++---- src/mem/simple_dram.cc | 54 ++++++++++++++++++++++++++++-------------- src/mem/simple_dram.hh | 1 + 3 files changed, 47 insertions(+), 23 deletions(-) diff --git a/src/mem/SimpleDRAM.py b/src/mem/SimpleDRAM.py index 0ce94ba3e..f75860dce 100644 --- a/src/mem/SimpleDRAM.py +++ b/src/mem/SimpleDRAM.py @@ -114,6 +114,9 @@ class SimpleDRAM(AbstractMemory): # minimum time between a precharge and subsequent activate tRP = Param.Latency("Row precharge time") + # minimum time between an activate and a precharge to the same row + tRAS = Param.Latency("ACT to PRE delay") + # time to complete a burst transfer, typically the burst length # divided by two due to the DDR bus, but by making it a parameter # it is easier to also evaluate SDR memories like WideIO. @@ -140,11 +143,7 @@ class SimpleDRAM(AbstractMemory): # Currently rolled into other params ###################################################################### - # the minimum amount of time between a row being activated, and - # precharged (de-activated) - # tRAS - assumed to be 3 * tRP - - # tRC - assumed to be 4 * tRP + # tRC - assumed to be tRAS + tRP # A single DDR3 x64 interface (one command and address bus), with # default timings based on DDR3-1600 4 Gbit parts in an 8x8 @@ -173,6 +172,7 @@ class DDR3_1600_x64(SimpleDRAM): tRCD = '13.75ns' tCL = '13.75ns' tRP = '13.75ns' + tRAS = '41.25ns' # 8 beats across an x64 interface translates to 4 clocks @ 800 MHz. # Note this is a BL8 DDR device. @@ -224,6 +224,8 @@ class LPDDR2_S4_1066_x32(SimpleDRAM): # Pre-charge one bank 15 ns (all banks 18 ns) tRP = '15ns' + tRAS = '45ns' + # 8 beats across an x32 DDR interface translates to 4 clocks @ 533 MHz. # Note this is a BL8 DDR device. # Requests larger than 32 bytes are broken down into multiple requests @@ -267,6 +269,7 @@ class WideIO_200_x128(SimpleDRAM): tRCD = '18ns' tCL = '18ns' tRP = '18ns' + tRAS = '54ns' # 4 beats across an x128 SDR interface translates to 4 clocks @ 200 MHz. # Note this is a BL4 SDR device. @@ -314,6 +317,8 @@ class LPDDR3_1600_x32(SimpleDRAM): # 12 CK read latency, 6 CK write latency @ 800 MHz, 1.25 ns cycle time tCL = '15ns' + tRAS = '45ns' + # Pre-charge one bank 15 ns (all banks 18 ns) tRP = '15ns' diff --git a/src/mem/simple_dram.cc b/src/mem/simple_dram.cc index 0deaedcf9..c537006a1 100644 --- a/src/mem/simple_dram.cc +++ b/src/mem/simple_dram.cc @@ -68,7 +68,7 @@ SimpleDRAM::SimpleDRAM(const SimpleDRAMParams* p) : writeBufferSize(p->write_buffer_size), writeThresholdPerc(p->write_thresh_perc), tWTR(p->tWTR), tBURST(p->tBURST), - tRCD(p->tRCD), tCL(p->tCL), tRP(p->tRP), + tRCD(p->tRCD), tCL(p->tCL), tRP(p->tRP), tRAS(p->tRAS), tRFC(p->tRFC), tREFI(p->tREFI), tXAW(p->tXAW), activationLimit(p->activation_limit), memSchedPolicy(p->mem_sched_policy), addrMapping(p->addr_mapping), @@ -382,6 +382,7 @@ SimpleDRAM::processWriteEvent() { assert(!writeQueue.empty()); uint32_t numWritesThisTime = 0; + Tick actTick; DPRINTF(DRAMWR, "Beginning DRAM Writes\n"); Tick temp1 M5_VAR_USED = std::max(curTick(), busBusyUntil); @@ -422,9 +423,10 @@ SimpleDRAM::processWriteEvent() bank.bytesAccessed += burstSize; if (!rowHitFlag) { - bank.tRASDoneAt = bank.freeAt + tRP; - recordActivate(bank.freeAt - tCL - tRCD); - busBusyUntil = bank.freeAt - tCL - tRCD; + actTick = bank.freeAt - tCL - tRCD;//new row opened + bank.tRASDoneAt = actTick + tRAS; + recordActivate(actTick); + busBusyUntil = actTick; // sample the number of bytes accessed and reset it as // we are now closing this row @@ -432,10 +434,19 @@ SimpleDRAM::processWriteEvent() bank.bytesAccessed = 0; } } else if (pageMgmt == Enums::close) { - bank.freeAt = schedTime + tBURST + accessLat + tRP + tRP; - // Work backwards from bank.freeAt to determine activate time - recordActivate(bank.freeAt - tRP - tRP - tCL - tRCD); - busBusyUntil = bank.freeAt - tRP - tRP - tCL - tRCD; + // All ticks waiting for a bank (if required) are included + // in accessLat + actTick = schedTime + tBURST + accessLat - tCL - tRCD; + recordActivate(actTick); + + // 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 + tCL + tRCD + tRP); + + //assuming that DRAM first gets write data, then activates + busBusyUntil = actTick; DPRINTF(DRAMWR, "processWriteEvent::bank.freeAt for " "banks_id %d is %lld\n", dram_pkt->rank * banksPerRank + dram_pkt->bank, @@ -1043,6 +1054,7 @@ SimpleDRAM::doDRAMAccess(DRAMPacket* dram_pkt) pair lat = estimateLatency(dram_pkt, curTick()); Tick bankLat = lat.first; Tick accessLat = lat.second; + Tick actTick; // This request was woken up at this time based on a prior call // to estimateLatency(). However, between then and now, both the @@ -1061,22 +1073,28 @@ SimpleDRAM::doDRAMAccess(DRAMPacket* dram_pkt) bank.bytesAccessed += burstSize; // If you activated a new row do to this access, the next access - // will have to respect tRAS for this bank. Assume tRAS ~= 3 * tRP. - // Also need to account for t_XAW + // will have to respect tRAS for this bank. if (!rowHitFlag) { - bank.tRASDoneAt = bank.freeAt + tRP; - recordActivate(bank.freeAt - tCL - tRCD); //since this is open page, - //no tRP by default + // any waiting for banks account for in freeAt + actTick = bank.freeAt - tCL - tRCD; + bank.tRASDoneAt = actTick + tRAS; + recordActivate(actTick); + // sample the number of bytes accessed and reset it as // we are now closing this row bytesPerActivate.sample(bank.bytesAccessed); bank.bytesAccessed = 0; } - } else if (pageMgmt == Enums::close) { // accounting for tRAS also - // assuming that tRAS ~= 3 * tRP, and tRC ~= 4 * tRP, as is common - // (refer Jacob/Ng/Wang and Micron datasheets) - bank.freeAt = curTick() + addDelay + accessLat + tRP + tRP; - recordActivate(bank.freeAt - tRP - tRP - tCL - tRCD); //essentially (freeAt - tRC) + } else if (pageMgmt == Enums::close) { + actTick = curTick() + addDelay + accessLat - tRCD - tCL; + recordActivate(actTick); + + // 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); bytesPerActivate.sample(burstSize); } else diff --git a/src/mem/simple_dram.hh b/src/mem/simple_dram.hh index abc64c3cd..a340a427d 100644 --- a/src/mem/simple_dram.hh +++ b/src/mem/simple_dram.hh @@ -462,6 +462,7 @@ class SimpleDRAM : public AbstractMemory const Tick tRCD; const Tick tCL; const Tick tRP; + const Tick tRAS; const Tick tRFC; const Tick tREFI; const Tick tXAW;