# 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.
# 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
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.
# 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
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.
# 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'
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),
{
assert(!writeQueue.empty());
uint32_t numWritesThisTime = 0;
+ Tick actTick;
DPRINTF(DRAMWR, "Beginning DRAM Writes\n");
Tick temp1 M5_VAR_USED = std::max(curTick(), busBusyUntil);
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
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,
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
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