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.
This commit is contained in:
parent
0e6ced5c4f
commit
d4cf009b95
3 changed files with 47 additions and 23 deletions
|
@ -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'
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in a new issue