mem: Add tTAW and tFAW to the SimpleDRAM model
This patch adds two additional scheduling constraints to the DRAM controller model, to constrain the activation rate. The two metrics are determine the size of the activation window in terms of the number of activates and the minimum time required for that number of activates. This maps to current DDRx, LPDDRx and WIOx standards that have either tFAW (4 activate window) or tTAW (2 activate window) scheduling constraints.
This commit is contained in:
@@ -112,7 +112,12 @@ class SimpleDRAM(AbstractMemory):
|
||||
# write-to-read turn around penalty, assumed same as read-to-write
|
||||
tWTR = Param.Latency("1ns", "Write to read switching time")
|
||||
|
||||
# Currently unimplemented, unused, deduced or rolled into other params
|
||||
# time window in which a maximum number of activates are allowed
|
||||
# to take place, set to 0 to disable
|
||||
tXAW = Param.Latency("0ns", "X activation window")
|
||||
activation_limit = Param.Unsigned(4, "Max number of activates in window")
|
||||
|
||||
# Currently rolled into other params
|
||||
######################################################################
|
||||
|
||||
# the minimum amount of time between a row being activated, and
|
||||
@@ -122,10 +127,3 @@ class SimpleDRAM(AbstractMemory):
|
||||
# tRC - assumed to be 4 * tRP
|
||||
|
||||
# burst length for an access derived from peerBlockSize
|
||||
|
||||
# @todo: Implement tFAW in the model
|
||||
# minimum time window in which a maximum of four activates are
|
||||
# allowed to take place
|
||||
# tFAW = Param.Latency("30ns", "Four activation window")
|
||||
|
||||
|
||||
|
||||
@@ -51,7 +51,7 @@ SimpleDRAM::SimpleDRAM(const SimpleDRAMParams* p) :
|
||||
AbstractMemory(p),
|
||||
port(name() + ".port", *this),
|
||||
retryRdReq(false), retryWrReq(false),
|
||||
rowHitFlag(false), stopReads(false),
|
||||
rowHitFlag(false), stopReads(false), actTicks(p->activation_limit, 0),
|
||||
writeEvent(this), respondEvent(this),
|
||||
refreshEvent(this), nextReqEvent(this), drainManager(NULL),
|
||||
bytesPerCacheLine(0),
|
||||
@@ -64,6 +64,7 @@ SimpleDRAM::SimpleDRAM(const SimpleDRAMParams* p) :
|
||||
tWTR(p->tWTR), tBURST(p->tBURST),
|
||||
tRCD(p->tRCD), tCL(p->tCL), tRP(p->tRP),
|
||||
tRFC(p->tRFC), tREFI(p->tREFI),
|
||||
tXAW(p->tXAW), activationLimit(p->activation_limit),
|
||||
memSchedPolicy(p->mem_sched_policy), addrMapping(p->addr_mapping),
|
||||
pageMgmt(p->page_policy),
|
||||
busBusyUntil(0), prevdramaccess(0), writeStartTime(0),
|
||||
@@ -304,10 +305,13 @@ SimpleDRAM::processWriteEvent()
|
||||
|
||||
if (!rowHitFlag) {
|
||||
bank.tRASDoneAt = bank.freeAt + tRP;
|
||||
recordActivate(bank.freeAt - tCL - tRCD);
|
||||
busBusyUntil = bank.freeAt - tCL - tRCD;
|
||||
}
|
||||
} 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;
|
||||
DPRINTF(DRAMWR, "processWriteEvent::bank.freeAt for "
|
||||
"banks_id %d is %lld\n",
|
||||
@@ -791,6 +795,41 @@ SimpleDRAM::processNextReqEvent()
|
||||
scheduleNextReq();
|
||||
}
|
||||
|
||||
void
|
||||
SimpleDRAM::recordActivate(Tick act_tick)
|
||||
{
|
||||
assert(actTicks.size() == activationLimit);
|
||||
|
||||
DPRINTF(DRAM, "Activate at tick %d\n", act_tick);
|
||||
|
||||
// sanity check
|
||||
if (actTicks.back() && (act_tick - actTicks.back()) < tXAW) {
|
||||
panic("Got %d activates in window %d (%d - %d) which is smaller "
|
||||
"than %d\n", activationLimit, act_tick - actTicks.back(),
|
||||
act_tick, actTicks.back(), tXAW);
|
||||
}
|
||||
|
||||
// shift the times used for the book keeping, the last element
|
||||
// (highest index) is the oldest one and hence the lowest value
|
||||
actTicks.pop_back();
|
||||
|
||||
// record an new activation (in the future)
|
||||
actTicks.push_front(act_tick);
|
||||
|
||||
// cannot activate more than X times in time window tXAW, push the
|
||||
// next one (the X + 1'st activate) to be tXAW away from the
|
||||
// oldest in our window of X
|
||||
if (actTicks.back() && (act_tick - actTicks.back()) < tXAW) {
|
||||
DPRINTF(DRAM, "Enforcing tXAW with X = %d, next activate no earlier "
|
||||
"than %d\n", activationLimit, actTicks.back() + tXAW);
|
||||
for(int i = 0; i < ranksPerChannel; i++)
|
||||
for(int j = 0; j < banksPerRank; j++)
|
||||
// next activate must not happen before end of window
|
||||
banks[i][j].freeAt = std::max(banks[i][j].freeAt,
|
||||
actTicks.back() + tXAW);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
SimpleDRAM::doDRAMAccess(DRAMPacket* dram_pkt)
|
||||
{
|
||||
@@ -821,14 +860,18 @@ SimpleDRAM::doDRAMAccess(DRAMPacket* dram_pkt)
|
||||
bank.openRow = dram_pkt->row;
|
||||
bank.freeAt = curTick() + addDelay + accessLat;
|
||||
// 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
|
||||
if (!rowHitFlag)
|
||||
// will have to respect tRAS for this bank. Assume tRAS ~= 3 * tRP.
|
||||
// Also need to account for t_XAW
|
||||
if (!rowHitFlag) {
|
||||
bank.tRASDoneAt = bank.freeAt + tRP;
|
||||
|
||||
recordActivate(bank.freeAt - tCL - tRCD); //since this is open page,
|
||||
//no tRP by default
|
||||
}
|
||||
} else if (pageMgmt == Enums::close) { // accounting for tRAS also
|
||||
// assuming that tRAS ~= 3 * tRP, and tRAS ~= 4 * tRP, as is common
|
||||
// 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)
|
||||
DPRINTF(DRAM,"doDRAMAccess::bank.freeAt is %lld\n",bank.freeAt);
|
||||
} else
|
||||
panic("No page management policy chosen\n");
|
||||
|
||||
@@ -46,6 +46,8 @@
|
||||
#ifndef __MEM_SIMPLE_DRAM_HH__
|
||||
#define __MEM_SIMPLE_DRAM_HH__
|
||||
|
||||
#include <deque>
|
||||
|
||||
#include "base/statistics.hh"
|
||||
#include "enums/AddrMap.hh"
|
||||
#include "enums/MemSched.hh"
|
||||
@@ -127,6 +129,9 @@ class SimpleDRAM : public AbstractMemory
|
||||
*/
|
||||
bool stopReads;
|
||||
|
||||
/** List to keep track of activate ticks */
|
||||
std::deque<Tick> actTicks;
|
||||
|
||||
/**
|
||||
* A basic class to track the bank state indirectly via
|
||||
* times "freeAt" and "tRASDoneAt" and what page is currently open
|
||||
@@ -323,6 +328,15 @@ class SimpleDRAM : public AbstractMemory
|
||||
*/
|
||||
Tick maxBankFreeAt() const;
|
||||
|
||||
|
||||
/**
|
||||
* Keep track of when row activations happen, in order to enforce
|
||||
* the maximum number of activations in the activation window. The
|
||||
* method updates the time that the banks become available based
|
||||
* on the current limits.
|
||||
*/
|
||||
void recordActivate(Tick act_tick);
|
||||
|
||||
void printParams() const;
|
||||
void printQs() const;
|
||||
|
||||
@@ -381,6 +395,8 @@ class SimpleDRAM : public AbstractMemory
|
||||
const Tick tRP;
|
||||
const Tick tRFC;
|
||||
const Tick tREFI;
|
||||
const Tick tXAW;
|
||||
const uint32_t activationLimit;
|
||||
|
||||
/**
|
||||
* Memory controller configuration initialized based on parameter
|
||||
|
||||
Reference in New Issue
Block a user