diff options
-rw-r--r-- | src/mem/SimpleDRAM.py | 14 | ||||
-rw-r--r-- | src/mem/simple_dram.cc | 53 | ||||
-rw-r--r-- | src/mem/simple_dram.hh | 16 |
3 files changed, 70 insertions, 13 deletions
diff --git a/src/mem/SimpleDRAM.py b/src/mem/SimpleDRAM.py index 3211f576a..83eaac611 100644 --- a/src/mem/SimpleDRAM.py +++ b/src/mem/SimpleDRAM.py @@ -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") - - diff --git a/src/mem/simple_dram.cc b/src/mem/simple_dram.cc index 305a7bcaf..6885e48c0 100644 --- a/src/mem/simple_dram.cc +++ b/src/mem/simple_dram.cc @@ -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", @@ -792,6 +796,41 @@ SimpleDRAM::processNextReqEvent() } 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"); diff --git a/src/mem/simple_dram.hh b/src/mem/simple_dram.hh index de597d668..d8f51a745 100644 --- a/src/mem/simple_dram.hh +++ b/src/mem/simple_dram.hh @@ -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 |