mem: Add tRRD as a timing parameter for the DRAM controller
authorAndreas Hansson <andreas.hansson@arm.com>
Fri, 1 Nov 2013 15:56:24 +0000 (11:56 -0400)
committerAndreas Hansson <andreas.hansson@arm.com>
Fri, 1 Nov 2013 15:56:24 +0000 (11:56 -0400)
This patch adds the tRRD parameter to the DRAM controller. With the
recent addition of the actAllowedAt member for each bank, this
addition is trivial.

src/mem/SimpleDRAM.py
src/mem/simple_dram.cc
src/mem/simple_dram.hh

index 8de21064134ed7f7e7785e7713f2c6479bae357f..81bb0ff426df060b6ef83a38238248082407b0eb 100644 (file)
@@ -135,6 +135,9 @@ class SimpleDRAM(AbstractMemory):
     # write-to-read turn around penalty, assumed same as read-to-write
     tWTR = Param.Latency("Write to read switching time")
 
+    # minimum row activate to row activate delay time
+    tRRD = Param.Latency("ACT to ACT delay")
+
     # time window in which a maximum number of activates are allowed
     # to take place, set to 0 to disable
     tXAW = Param.Latency("X activation window")
@@ -187,6 +190,9 @@ class DDR3_1600_x64(SimpleDRAM):
     # Greater of 4 CK or 7.5 ns, 4 CK @ 800 MHz = 5 ns
     tWTR = '7.5ns'
 
+    # Assume 5 CK for activate to activate for different banks
+    tRRD = '6.25ns'
+
     # With a 2kbyte page size, DDR3-1600 lands around 40 ns
     tXAW = '40ns'
     activation_limit = 4
@@ -239,6 +245,9 @@ class LPDDR2_S4_1066_x32(SimpleDRAM):
     # Irrespective of speed grade, tWTR is 7.5 ns
     tWTR = '7.5ns'
 
+    # Activate to activate irrespective of density and speed grade
+    tRRD = '10.0ns'
+
     # Irrespective of density, tFAW is 50 ns
     tXAW = '50ns'
     activation_limit = 4
@@ -284,6 +293,9 @@ class WideIO_200_x128(SimpleDRAM):
     # Greater of 2 CK or 15 ns, 2 CK @ 200 MHz = 10 ns
     tWTR = '15ns'
 
+    # Activate to activate irrespective of density and speed grade
+    tRRD = '10.0ns'
+
     # Two instead of four activation window
     tXAW = '50ns'
     activation_limit = 2
@@ -335,6 +347,9 @@ class LPDDR3_1600_x32(SimpleDRAM):
     # Irrespective of speed grade, tWTR is 7.5 ns
     tWTR = '7.5ns'
 
+    # Activate to activate irrespective of density and speed grade
+    tRRD = '10.0ns'
+
     # Irrespective of size, tFAW is 50 ns
     tXAW = '50ns'
     activation_limit = 4
index bd700c09dc3fcb94f9e51533e1b844a4440f119d..7e377b861f08ecc53ed800ea5935316a056b6c19 100644 (file)
@@ -70,7 +70,7 @@ SimpleDRAM::SimpleDRAM(const SimpleDRAMParams* p) :
     writeThresholdPerc(p->write_thresh_perc),
     tWTR(p->tWTR), tBURST(p->tBURST),
     tRCD(p->tRCD), tCL(p->tCL), tRP(p->tRP), tRAS(p->tRAS),
-    tRFC(p->tRFC), tREFI(p->tREFI),
+    tRFC(p->tRFC), tREFI(p->tREFI), tRRD(p->tRRD),
     tXAW(p->tXAW), activationLimit(p->activation_limit),
     memSchedPolicy(p->mem_sched_policy), addrMapping(p->addr_mapping),
     pageMgmt(p->page_policy),
@@ -988,14 +988,25 @@ SimpleDRAM::processNextReqEvent()
 }
 
 void
-SimpleDRAM::recordActivate(Tick act_tick, uint8_t rank)
+SimpleDRAM::recordActivate(Tick act_tick, uint8_t rank, uint8_t bank)
 {
     assert(0 <= rank && rank < ranksPerChannel);
     assert(actTicks[rank].size() == activationLimit);
 
     DPRINTF(DRAM, "Activate at tick %d\n", act_tick);
 
-    // if the activation limit is disabled then we are done
+    // start by enforcing tRRD
+    for(int i = 0; i < banksPerRank; i++) {
+        // next activate must not happen before tRRD
+        banks[rank][i].actAllowedAt = act_tick + tRRD;
+    }
+    // tRC should be added to activation tick of the bank currently accessed,
+    // where tRC = tRAS + tRP, this is just for a check as actAllowedAt for same
+    // bank is already captured by bank.freeAt and bank.tRASDoneAt
+    banks[rank][bank].actAllowedAt = act_tick + tRAS + tRP;
+
+    // next, we deal with tXAW, if the activation limit is disabled
+    // then we are done
     if (actTicks[rank].empty())
         return;
 
@@ -1061,24 +1072,24 @@ SimpleDRAM::doDRAMAccess(DRAMPacket* dram_pkt)
             // any waiting for banks account for in freeAt
             actTick = bank.freeAt - tCL - tRCD;
             bank.tRASDoneAt = actTick + tRAS;
-            recordActivate(actTick, dram_pkt->rank);
+            recordActivate(actTick, dram_pkt->rank, dram_pkt->bank);
 
             // sample the number of bytes accessed and reset it as
             // we are now closing this row
             bytesPerActivate.sample(bank.bytesAccessed);
             bank.bytesAccessed = 0;
         }
+        DPRINTF(DRAM, "doDRAMAccess::bank.freeAt is %lld\n", bank.freeAt);
     } else if (pageMgmt == Enums::close) {
         actTick = curTick() + addDelay + accessLat - tRCD - tCL;
-        recordActivate(actTick, dram_pkt->rank);
+        recordActivate(actTick, dram_pkt->rank, dram_pkt->bank);
 
         // 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);
+        DPRINTF(DRAM, "doDRAMAccess::bank.freeAt is %lld\n", bank.freeAt);
         bytesPerActivate.sample(burstSize);
     } else
         panic("No page management policy chosen\n");
index c97f70e1df68a7872a89cbe0bc0b9ef12bfd6390..dfb8fc15f02cd422be4f05a3d7223bb312d92af7 100644 (file)
@@ -420,7 +420,7 @@ class SimpleDRAM : public AbstractMemory
      * method updates the time that the banks become available based
      * on the current limits.
      */
-    void recordActivate(Tick act_tick, uint8_t rank);
+    void recordActivate(Tick act_tick, uint8_t rank, uint8_t bank);
 
     void printParams() const;
     void printQs() const;
@@ -487,6 +487,7 @@ class SimpleDRAM : public AbstractMemory
     const Tick tRAS;
     const Tick tRFC;
     const Tick tREFI;
+    const Tick tRRD;
     const Tick tXAW;
     const uint32_t activationLimit;