summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAni Udipi <ani.udipi@arm.com>2013-11-01 11:56:16 -0400
committerAni Udipi <ani.udipi@arm.com>2013-11-01 11:56:16 -0400
commitd4cf009b95d34b75408363bc085c2e9e9de458d9 (patch)
tree01825a265f0e48f850f5ef4d33dc8e03932f2d3f /src
parent0e6ced5c4f0c0e2f35dcbdfe4797215f4c7b0e8e (diff)
downloadgem5-d4cf009b95d34b75408363bc085c2e9e9de458d9.tar.xz
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.
Diffstat (limited to 'src')
-rw-r--r--src/mem/SimpleDRAM.py15
-rw-r--r--src/mem/simple_dram.cc54
-rw-r--r--src/mem/simple_dram.hh1
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<Tick, Tick> 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;