Fix Physical Memory to allow memory sizes bigger than 128MB.
authorAli Saidi <saidi@eecs.umich.edu>
Wed, 16 Aug 2006 23:01:11 +0000 (19:01 -0400)
committerAli Saidi <saidi@eecs.umich.edu>
Wed, 16 Aug 2006 23:01:11 +0000 (19:01 -0400)
Kinda port DRAM to new memory system. The code is *really* ugly (not my fault) and right now something about the stats it uses
causes a simulator segfault.

src/SConscript:
    Add dram.cc to sconscript
src/mem/physical.cc:
src/mem/physical.hh:
    Add params struct to physical memory, use params, make latency function be virtual
src/python/m5/objects/PhysicalMemory.py:
    Add DRAMMemory python class

--HG--
extra : convert_revision : 5bd9f2e071c62da89e8efa46fa016f342c01535d

src/SConscript
src/mem/dram.cc [new file with mode: 0644]
src/mem/dram.hh [new file with mode: 0644]
src/mem/physical.cc
src/mem/physical.hh
src/python/m5/objects/PhysicalMemory.py

index f14ba490ce1e78a57b4c793c986e6f5ced32559a..260aca25cc04697ef1b5f366801cbd79a7b4abe6 100644 (file)
@@ -94,6 +94,7 @@ base_sources = Split('''
 
         mem/bridge.cc
         mem/bus.cc
+        mem/dram.cc
         mem/mem_object.cc
         mem/packet.cc
         mem/physical.cc
diff --git a/src/mem/dram.cc b/src/mem/dram.cc
new file mode 100644 (file)
index 0000000..d7b9559
--- /dev/null
@@ -0,0 +1,2746 @@
+/*
+ * Copyright (c) 2004 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Authors: Ali Saidi
+ *          Ron Dreslinski
+ */
+
+/*
+ Copyright (c) 2000 Computer Engineering and Communication Networks Lab (TIK)
+ Swiss Federal Institute of Technology (ETH) Zurich, Switzerland
+
+ All rights reserved.
+ Permission is hereby granted, without written agreement and without
+ license or royalty fees, to use, copy, modify, and distribute this
+ software and its documentation for any purpose, provided that the above
+ copyright notice and the following two paragraphs appear in all copies
+ of this software.
+
+ IN NO EVENT SHALL THE TIK OR THE ETH ZURICH BE LIABLE TO ANY PARTY
+ FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
+ THE TIK OR THE ETH ZURICH HAVE BEEN ADVISED OF THE POSSIBILITY OF
+ SUCH DAMAGE.
+
+ THE TIK AND THE ETH ZURICH SPECIFICALLY DISCLAIM ANY WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE
+ PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND TIK AND THE ETH ZURICH
+ HAVE NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES,
+ ENHANCEMENTS, OR MODIFICATIONS.
+*/
+
+/* authors: Andreas Romer 4/99 - 7/99
+            Matthias Gries 4/99 - 2/01
+
+
+References: http://www.tik.ee.ethz.ch/
+======================================
+-> Publications http://www.tik.ee.ethz.ch/db/tik/publications/form_search_publications.php3
+
+
+Matthias Gries: A Survey of Synchronous RAM Architectures.
+TIK Report Nr. 71, Computer Engineering and Networks Lab (TIK),
+Swiss Federal Institute of Technology (ETH) Zurich, April, 1999
+
+-> DRAM survey
+
+
+Matthias Gries, Andreas Romer: Performance Evaluation of Recent
+DRAM Architectures for Embedded Systems.
+TIK Report Nr. 82, Computer Engineering and Networks Lab (TIK),
+Swiss Federal Institute of Technology (ETH) Zurich, November, 1999.
+
+-> description of the DRAM and controller models for SimpleScalar in the appendix
+(note that the current software version additionally supports overlapping in
+ closed-page mode with slightly modified timing)
+
+
+Matthias Gries: The Impact of Recent DRAM Architectures on Embedded Systems Performance.
+Euromicro2000, Symposium on Digital Systems Design, IEEE Computer, Maastricht, Netherlands,
+Vol. 1, pages 282-289, September, 2000.
+
+-> performance study with SimpleScalar
+
+
+Matthias Gries: Modeling a Memory Subsystem with Petri Nets: a Case Study.
+A. Yakovlev, L. Gomes, and L. Lavagno (Eds), Hardware Design and Petri Nets,
+Kluwer Academic, pages 291-310, March, 2000.
+
+-> SDRAM + controller performance model as a high-level Petri net
+*/
+
+/**
+ * @file
+ * Definition of a DRAM like main memory.
+ */
+
+
+#include "mem/dram.hh"
+#include "sim/builder.hh"
+
+#include <string>
+
+extern int maxThreadsPerCPU;
+
+/* SDRAM system: PC100/PC133 2-2-2 DIMM timing according to
+   PC SDRAM Specification, Rev. 1.7, Intel Corp, Nov. 1999.
+
+   64 bit DIMM consists of four 16x organized 256 Mbit SDRAMs, 128 MByte of main memory in total.*/
+/* the settings above must be changed if another memory is used */
+/* DRDRAM system: 16 bit channel, four chips (single RIMM), 128 MByte of main memory in total.
+   Timing: Rambus Inc, Direct RDRAM, preliminary information, 256/288Mbit: 40-800 timing */
+
+
+#define  DR_STACK_BASE 0x8000000 /* total size of memory: 128 Mbyte */
+#define  DR_BANK_SIZE  0x100000  /* size of a bank      :   1 Mbyte */
+#define  DR_ROW_SIZE 0x800       /* size of a row       :   2 Kbyte */
+#define  DR_NUM_BANKS (DR_STACK_BASE/DR_BANK_SIZE)      /* number of banks        : 128 */
+#define  DR_NUM_ROWS (DR_BANK_SIZE/DR_ROW_SIZE)         /* number of rows per bank: 512 */
+#define  DR_DATA_BASE  0x4000000 /* Size of textsegment :  64 Mbyte */
+#define  DR_NUM_BYTE_MEM  16     /* data packet capacity:  16 byte  */
+#define  DR_NUM_DEVS 4   /* number of devices along channel */
+#define  DR_BANK_SAMP 16 /* 16 banks are together in one group in each device: bank 15 and 16 have no shared SAMPs */
+#define  DR_T_PACKET 4   /* number of cycles (in 400 MHz) the memory needs to deliver a data packet */
+#define  DR_T_RCD 7  /* RAS to CAS delay */
+#define  DR_T_CAC 8  /* read access delay: number of cylces from read to data  (trailing to leading edge of packet!) */
+#define  DR_T_CWD 6  /* Write delay: number of cylces from write to write data (trailing to leading edge of packet!) */
+#define  DR_T_RP  8  /* row precharge delay */
+#define  DR_T_RTR 8  /* retire delay*/
+#define  DR_T_RDP 4  /* min delay from read to precharge in cycles */
+#define  DR_T_PP  8  /* precharge to precharge time to any bank in the same device */
+#define  DR_T_RAS 20 /* minimal row active time */
+/*the settings above need to be changed if the memory is altered*/
+#define  DR_DYNAMIC_SIZE (DR_STACK_BASE - DR_DATA_BASE) /* size of the heap and stack at most: 64 Mbyte */
+// #define  DR_NUM_BANKS (DR_STACK_BASE/DR_BANK_SIZE)      /* number of banks        : 128 */
+// #define  DR_NUM_ROWS (DR_BANK_SIZE/DR_ROW_SIZE)         /* number of rows per bank: 512 */
+#define  DR_T_OWR (DR_T_CWD + DR_T_PACKET - DR_T_RTR)   /* overlap after write retire   */
+#define  DR_T_HELP (DR_T_CAC+DR_T_PACKET-DR_T_RDP+DR_T_PACKET) /* used for read after read with precharge */
+/*delays until data is ready/written to the memory for the DRDRAM*/
+#define  DR_T_READ_READ_SROW    (DR_T_CAC + DR_T_PACKET) /* RAR, row hit, current bank */
+#define  DR_T_READ_WRITE_SROW   (DR_T_CAC + DR_T_PACKET) /* RAW, row hit, current bank */
+#define  DR_T_WRITE_READ_SROW   (DR_T_CWD + DR_T_PACKET) /* WAR, row hit, current bank */
+#define  DR_T_WRITE_WRITE_SROW  (DR_T_CWD + DR_T_PACKET) /* WAW, row hit, current bank */
+#define  DR_T_READ_READ_SBANK   (DR_T_RP+DR_T_RCD+DR_T_CAC+DR_T_PACKET) /* RAR, row miss, current bank */
+#define  DR_T_READ_WRITE_SBANK  (DR_T_RP+DR_T_RCD+DR_T_CAC+DR_T_PACKET) /* RAW, row miss, current bank */
+#define  DR_T_WRITE_READ_SBANK  (DR_T_RP+DR_T_RCD+DR_T_CWD+DR_T_PACKET) /* WAR, row miss, current bank */
+#define  DR_T_WRITE_WRITE_SBANK (DR_T_RP+DR_T_RCD+DR_T_CWD+DR_T_PACKET) /* WAR, row miss, current bank */
+#define  DR_T_READ_READ_OBANK   (DR_T_PP+DR_T_RP+DR_T_RCD+DR_T_CAC+DR_T_PACKET) /* RAR, row miss, another bank */
+#define  DR_T_READ_WRITE_OBANK  (DR_T_PP+DR_T_RP+DR_T_RCD+DR_T_CAC+DR_T_PACKET) /* RAW, row miss, another bank */
+#define  DR_T_WRITE_READ_OBANK  (DR_T_PP+DR_T_RP+DR_T_RCD+DR_T_CWD+DR_T_PACKET) /* WAR, row miss, another bank */
+#define  DR_T_WRITE_WRITE_OBANK (DR_T_PP+DR_T_RP+DR_T_RCD+DR_T_CWD+DR_T_PACKET) /* WAR, row miss, another bank */
+/* best-case latencies (due to overlap / row hits in another bank) */
+#define  DR_BEST_T_READ_READ_SROW    0                               /* RAR, row hit, current bank */
+#define  DR_BEST_T_READ_WRITE_SROW   (DR_T_CAC+DR_T_PACKET-DR_T_OWR) /* RAW, row hit, current bank */
+#define  DR_BEST_T_WRITE_READ_SROW   0                               /* WAR, row hit, current bank */
+#define  DR_BEST_T_WRITE_WRITE_SROW  (DR_T_CWD+DR_T_PACKET-DR_T_OWR) /* WAR, row hit, current bank */
+#define  DR_BEST_T_READ_READ_SBANK   (DR_T_RCD + DR_T_CAC)                            /* RAR, row miss, current bank */
+#define  DR_BEST_T_READ_WRITE_SBANK  (DR_T_RP-DR_T_OWR+DR_T_RCD+DR_T_CAC+DR_T_PACKET) /* RAW, row miss, current bank */
+#define  DR_BEST_T_WRITE_READ_SBANK  (DR_T_RCD+DR_T_CWD)                              /* WAR, row miss, current bank */
+#define  DR_BEST_T_WRITE_WRITE_SBANK (DR_T_RP-DR_T_OWR+DR_T_RCD+DR_T_CWD+DR_T_PACKET) /* WAW, row miss, current bank */
+#define  DR_BEST_T_READ_READ_OBANK   0                   /* RAR, row miss/hit, another bank   */
+#define  DR_BEST_T_READ_WRITE_OBANK  (DR_T_PACKET+DR_T_CAC-DR_T_OWR) /* RAW, row miss/hit, another bank */
+#define  DR_BEST_T_WRITE_READ_OBANK  0                   /* WAR, row miss/hit, another bank   */
+#define  DR_BEST_T_WRITE_WRITE_OBANK 0                   /* WAW, row miss/hit, another bank   */
+#define  DR_BEST_T_READ_WRITE_ODEV   (DR_T_CAC-DR_T_CWD) /* RAW, row miss/hit, another device */
+
+
+#define MIN(a,b) ((a<b) ? a : b)
+#define  SD_ROW_SIZE 0x1000      /* size of a row       :   4 Kbyte */
+
+
+
+DRAMMemory::DRAMMemory(Params *p)
+    : PhysicalMemory(p), cpu_ratio(p->cpu_ratio), bus_width(p->bus_width),
+      mem_type(p->mem_type), mem_actpolicy(p->mem_actpolicy),
+      memctrladdr_type(p->memctrladdr_type), act_lat(p->act_lat),
+      cas_lat(p->cas_lat), war_lat(p->war_lat),
+      pre_lat(p->pre_lat), dpl_lat(p->dpl_lat),
+      trc_lat(p->trc_lat), num_banks(p->num_banks),
+      num_cpus(p->num_cpus), last_dev(DR_NUM_DEVS+1),
+      lastCmdIsRead(true), precharge(0), same_row_read_access(0), srr_after_read(0),
+      srr_after_write(0), same_row_write_access(0), srw_after_read(0),
+      srw_after_write(0), same_bank_read_access(0), sbr_after_read(0),
+      sbr_after_write(0), same_bank_write_access(0), sbw_after_read(0),
+      sbw_after_write(0), other_bank_read_access_hit(0), obr_after_read_hit(0),
+      obr_after_write_hit(0), other_bank_write_access_hit(0),
+      obw_after_read_hit(0), obw_after_write_hit(0), obr_after_read_miss(0),
+      obr_after_write_miss(0),
+      obw_after_read_miss(0), obw_after_write_miss(0), total_access(0),
+      adjacent_access(0), adjacent_read(0), adjacent_write(0),
+      command_overlapping(0), best_case(0), in_between_case(0), worst_case(0),
+      full_overlapping(0), partial_overlapping(0), mem_access_details(false),
+      memctrlpipe_enable(false), time_last_access(0)
+{
+    warn("This DRAM module has not been tested with the new memory system at all!");
+        bank_size = (params()->addrRange.size() + 1) / num_banks;
+        num_rows = bank_size / SD_ROW_SIZE; /* 0x1000 size of row 4Kbtye */
+        active_row = new int[num_banks];
+        last_bank = num_banks+1;
+        last_row  = num_rows;
+        busy_until = new Tick[num_banks];
+        memset(busy_until,0,sizeof(Tick)*num_banks); /* initiliaze */
+
+}
+
+void
+DRAMMemory::regStats()
+{
+    using namespace Stats;
+
+    accesses
+        .init(maxThreadsPerCPU)
+        .name(name() + ".accesses")
+        .desc("total number of accesses")
+        .flags(total)
+        ;
+
+    bytesRequested
+        .init(maxThreadsPerCPU)
+        .name(name() + ".bytes_requested")
+        .desc("total number of bytes requested")
+        .flags(total)
+        ;
+
+    bytesSent
+        .init(maxThreadsPerCPU)
+        .name(name() + ".bytes_sent")
+        .desc("total number of bytes sent")
+        .flags(total)
+        ;
+
+    compressedAccesses
+        .init(maxThreadsPerCPU)
+        .name(name() + ".compressed_responses")
+        .desc("total number of accesses that are compressed")
+        .flags(total)
+        ;
+
+        // stats for power modelling
+    cycles_nCKE
+        .init(1)
+        .name(name() + ".cycles_nCKE")
+        .desc("cycles when CKE is low")
+        .flags(total)
+        ;
+
+    cycles_all_precharge_CKE
+        .init(1)
+        .name(name() + ".cycles_all_precharge_CKE")
+        .desc("cycles when all banks precharged")
+        .flags(total)
+        ;
+
+    cycles_all_precharge_nCKE
+        .init(1)
+        .name(name() + ".cycles_all_precharge_nCKE")
+        .desc("cycles when all banks precharged and CKE is low")
+        .flags(total)
+        ;
+
+    cycles_bank_active_nCKE
+        .init(1)
+        .name(name() + ".cycles_bank_active_nCKE")
+        .desc("cycles when banks active and CKE low")
+        .flags(total)
+        ;
+
+        // we derive this from other stats later
+        // so DR TODO for now this counter is unused
+        cycles_avg_ACT
+        .init(1)
+        .name(name() + ".cycles_avg_ACT")
+        .desc("avg cycles between ACT commands")
+        .flags(total)
+        ;
+
+        cycles_read_out
+        .init(1)
+        .name(name() + ".cycles_read_out")
+        .desc("cycles outputting read data")
+        .flags(total)
+        ;
+
+        cycles_write_in
+        .init(1)
+        .name(name() + ".cycles_write_in")
+        .desc("cycles inputting write data")
+        .flags(total)
+        ;
+
+        cycles_between_misses
+        .init(1)
+        .name(name() + ".cycles_between_misses")
+        .desc("cycles between open page misses")
+        .flags(total)
+        ;
+
+        other_bank_read_access_miss
+        .init(1)
+        .name(name() + ".other_bank_read_access_miss")
+        .desc("read miss count")
+        .flags(total)
+        ;
+
+        other_bank_write_access_miss
+        .init(1)
+        .name(name() + ".other_bank_write_access_miss")
+        .desc("write miss count")
+        .flags(total)
+        ;
+
+    // DR TODO for now, only output stats which are involved in power equations
+        total_latency
+        .name(name() + ".total_latency")
+        .desc("total DRAM latency")
+        ;
+
+        total_arb_latency
+        .name(name() + ".total_arb_latency")
+        .desc("total arbitration latency")
+        ;
+
+        avg_latency
+        .name(name() + ".avg_latency")
+        .desc("average DRAM latency")
+        ;
+
+        avg_arb_latency
+        .name(name() + ".avg_arb_latency")
+        .desc("average arbitration DRAM latency")
+        ;
+
+        bank_access_profile
+        .init(num_banks,num_cpus)
+        .name(name() + "[cpu][bank]")
+        .desc("DRAM bank access profile")
+        ;
+
+        total_icache_req
+        .name(name() + ".total_icache_req")
+        .desc("total number of requests from icache")
+        ;
+
+        avg_latency = total_latency / accesses;
+        avg_arb_latency = total_arb_latency / accesses;
+}
+
+
+
+
+// DR DEBUG: assume we have a 500 MHz CPU and 100 MHz RAM
+// static float cpu_ratio = 5; // ratio between CPU speed and memory bus speed
+// DR TODO: get this parameter from the simulation
+
+static char *mem_access_output=NULL;
+                /* latency of access [CPU cycles]*/
+Tick
+DRAMMemory::calculateLatency(Packet *pkt)
+{
+
+  bool cmdIsRead = pkt->isRead();
+
+  int lat=0, temp=0, current_bank=0;
+  int current_row=0, current_device=0;
+
+  int was_miss = 0;    // determines if there was an active row miss this access
+
+  //md_addr_t physic_address; /* linear memory address to be accessed */
+  Addr physic_address; /* linear memory address to be accessed */
+
+  int num_blocks=0;
+  int corrected_overlap, /* overlap of consecutive accesses [CPU cycles] */
+    overlap=0;           /* overlap of consecutive accesses [mem bus cycles] */
+  int adjacent=0; /* 1 indicates that current bank is adjacent to the last accessed  one*/
+
+  int chunks = (pkt->getSize() + (bus_width - 1)) / bus_width; // burst length
+  assert(chunks >0);
+  physic_address = pkt->getAddr();
+
+    ///////////////////////////////////////////////////////////////////////////
+    // DR added more stats for power modelling
+    // NOTE:
+    // for DRAM closed-page, automatic precharge after read or write,
+    // i.e. whenever idle
+
+
+    // count number of cycles where dram is not busy, use for CKE low signal
+    // calculate as percentage of all clock cycles
+    // if busy, do not add to idle count.  Else add cycles since last access
+/* #define  SD_NUM_BANKS (SD_STACK_BASE/SD_BANK_SIZE)     */      /* number of banks */
+/* #define  SD_NUM_ROWS (SD_BANK_SIZE/SD_ROW_SIZE)       */       /* number of rows per bank */
+/*delays until data is ready/written to the memory for the SDRAM*/
+        int SD_T_READ_READ_SROW = cas_lat; /* RAR, row hit, current bank  */
+        int SD_T_READ_WRITE_SROW = cas_lat; /* RAW, row hit, current bank  */
+        int SD_T_WRITE_READ_SROW = war_lat-1; /* WAR, row hit, current bank  */
+        int SD_T_WRITE_WRITE_SROW = 0; /* WAW, row hit, current bank  */
+        int SD_T_READ_READ_SBANK = (pre_lat+act_lat+cas_lat); /* RAR, row miss, current bank */
+        int SD_T_READ_WRITE_SBANK = (pre_lat+act_lat+cas_lat+(dpl_lat-1)); /* RAW, row miss, current bank */
+        int SD_T_WRITE_READ_SBANK = (pre_lat+act_lat); /* WAR, row miss, current bank */
+        int SD_T_WRITE_WRITE_SBANK = (pre_lat+act_lat+(dpl_lat-1)); /* WAW, row miss, current bank */
+        int SD_T_READ_READ_OBANK = (pre_lat+act_lat+cas_lat); /* RAR, row miss, another bank */
+        int SD_T_READ_WRITE_OBANK = (pre_lat+act_lat+cas_lat); /* RAW, row miss, another bank */
+        int SD_T_WRITE_READ_OBANK = (pre_lat+act_lat); /* WAR, row miss, another bank */
+        int SD_T_WRITE_WRITE_OBANK = (pre_lat+act_lat); /* WAW, row miss, another bank */
+/* best-case latencies (due to overlap / row hits in another bank) */
+        int SD_BEST_T_READ_READ_SROW = 0; /* RAR, row hit, current bank  */
+        int SD_BEST_T_READ_READ_SBANK = (act_lat+cas_lat); /* RAR, row miss, current bank */
+        int SD_BEST_T_WRITE_READ_SBANK = (act_lat); /* WAR, row miss, current bank */
+        int SD_BEST_T_READ_READ_OBANK = 0; /* RAR, row miss/hit, another bank */
+        int SD_BEST_T_READ_WRITE_OBANK = cas_lat; /* RAW, row miss/hit, another bank */
+        int SD_BEST_T_WRITE_READ_OBANK = (war_lat -1); /* WAR, row miss/hit, another bank */
+        int SD_BEST_T_WRITE_WRITE_OBANK = 0; /* WAW, row miss/hit, another bank */
+
+    Tick time_since_last_access = curTick-time_last_access;
+    Tick time_last_miss = 0;   // used for keeping track of times between activations (page misses)
+    //int was_idle = (curTick > busy_until);
+        bool srow_flag = false;
+        int timing_correction = 0;
+
+    int was_idle = (curTick > busy_until[current_bank]);
+    cycles_nCKE[0] += was_idle ? MIN(curTick-busy_until[current_bank], time_since_last_access) : 0;
+
+    // bank is precharged
+    //active_row[current_bank] == DR_NUM_ROWS
+    int all_precharged = 1;
+    int bank_max = num_banks;
+    int row_max = num_rows;
+
+    if( (mem_type == "SDRAM") && (mem_actpolicy == "closed") ) {
+        // SDRAM does not use the active_row array in closed_page mode
+        // TODO: handle closed page operation
+
+    } else {           // DRDRAM uses the active_row array
+        for( int i = 0; i < bank_max; i++ ) {
+                if( (active_row[current_bank] != row_max)) all_precharged = 0;
+        }
+    }
+
+    if(all_precharged) {
+        if(was_idle) {
+                cycles_all_precharge_nCKE[0] += MIN(curTick-busy_until[current_bank], time_since_last_access);
+                cycles_all_precharge_CKE[0] += MIN(0, busy_until[current_bank]-time_last_access);
+        }
+        else {
+                cycles_all_precharge_CKE[0] += time_since_last_access;
+        }
+    } else { // some bank is active
+        if(was_idle) {
+                cycles_bank_active_nCKE[0] += MIN(curTick-busy_until[current_bank], time_since_last_access);
+        }
+        else {
+        }
+    }
+
+    if( cmdIsRead ) {
+        cycles_read_out[0] += chunks;
+    } else {
+        cycles_write_in[0] += chunks;
+    }
+
+
+    time_last_access = curTick;
+    ////////////////////////////////////////////////////////////////////////////
+
+    if ((mem_type == "SDRAM") && (mem_actpolicy == "open"))
+      {
+        /* Split transaction on m5 makes it challenging to  */
+        /* model the DRAM. A single cycle latency is assumed */
+        /* for dequeueing an address bus request. In response to  */
+        /* that, the current DRAM implementation assumes that a */
+        /* seperate DRAM command generator / controller exists per */
+        /* bank and the dequeued addresses are queued to these */
+        /* controllers. We can view this as an ideal scenario for */
+        /* a shared DRAM command generator / controller with */
+        /* support for overlapping DRAM commands. */
+        /* Compare DRAM PRE,ACT,CAS etc. latencies, DRAM clock  */
+        /* frequency and the number of banks to determine whether */
+        /* the ideal scenario with a shared DRAM command generator */
+        /* is equivalent to having multiple DRAM command generators */
+        /* per bank */
+        if ((memctrladdr_type != "interleaved"))/* i.e. mc_type is linear */
+          {
+            current_bank=physic_address/bank_size;
+            temp=physic_address-current_bank*bank_size;/*address in bank*/
+            current_row=temp/SD_ROW_SIZE;
+          }
+        else/* mc_type interleaved */
+          /* This memory controller maps the addresses differently
+           * depending on the row_size, every row is mapped to another
+           * bank. Thus, the text segment uses half of every bank, the heap
+           * the next quarter of each bank, and the stack the rest.
+           */
+
+          {
+            num_blocks = physic_address/SD_ROW_SIZE; /* row number */
+            current_bank=num_blocks%num_banks;
+            current_row=num_blocks/num_banks;
+          }
+
+        if (mem_access_details == true)
+          {
+                // DR TODO
+            //fprintf(mem_accessfd,"       %09u  %4d   %3d\n",physic_address,current_row,current_bank);
+          }
+        else
+          {
+            if (mem_access_output!=0)
+              {
+                //fprintf(mem_accessfd,"\n");
+              }
+          }
+        total_access++;
+
+        if (memctrlpipe_enable == true)
+          {
+            overlap=(int)(busy_until[current_bank] - curTick);
+          }
+        else overlap = 0;
+
+        if (cpu_ratio < 1.0)
+          {
+            corrected_overlap = overlap*((int)(1/cpu_ratio)); /* floor */
+          }
+        else
+          {
+            corrected_overlap = (int) (overlap/cpu_ratio);
+          }
+
+        /*fprintf(stderr,"%10.0f %10.0f %4d %4d ",(double)busy_until, (double)curTick, overlap, corrected_overlap); debugging*/
+
+        if (cmdIsRead == lastCmdIsRead)/*same command*/
+          {
+            if (current_bank == last_bank)/*same bank*/
+              {
+                if (current_row == last_row)/*same row*/
+                  {
+                          /* Page Hit */
+                    if (cmdIsRead)
+                      {
+                        if (corrected_overlap > 0)/*overlapping*/
+                          {
+                            /*best case*/
+                            if (corrected_overlap >= cas_lat)
+                              {
+                                lat=SD_BEST_T_READ_READ_SROW;
+                                srow_flag = true;
+                                best_case++;
+                                full_overlapping++;
+                              }
+                            else/*in between case*/
+                              {
+                                lat = cas_lat-corrected_overlap;
+                                srow_flag = true;
+                                in_between_case++;
+                                partial_overlapping++;
+                              }
+                          }
+                        else
+                          {
+                            /*worst case*/
+                            lat = SD_T_READ_READ_SROW;
+                                srow_flag = true;
+                            worst_case++;
+                          }
+                        same_row_read_access++;
+                        srr_after_read++;
+                      }
+                    else/*write*/
+                      {/*no option case*/
+                        lat = SD_T_WRITE_WRITE_SROW;
+                        srow_flag = true;
+                        same_row_write_access++;
+                        srw_after_write++;
+                        worst_case++;
+                      }
+                  }
+                else /*other row in same bank*/
+                  {
+                        /* Page miss */
+                    if (cmdIsRead)
+                      {
+                        if (corrected_overlap > 0)/*overlapping*/
+                          {
+                            if (corrected_overlap >= pre_lat)/*best case*/
+                              {
+                                lat = SD_BEST_T_READ_READ_SBANK;
+                                best_case++;
+                                full_overlapping++;
+                              }
+                            else/*in between case*/
+                              {
+                                lat = SD_T_READ_READ_SBANK-corrected_overlap;
+                                in_between_case++;
+                                partial_overlapping++;
+                              }
+                          }
+                        else/*worst case*/
+                          {
+                            lat = SD_T_READ_READ_SBANK;
+                            worst_case++;
+                          }
+                        same_bank_read_access++;
+                        sbr_after_read++;
+                      }
+                    else/*write*/
+                      {/*no option case*/
+                        lat = SD_T_WRITE_WRITE_SBANK;
+                        same_bank_write_access++;
+                        sbw_after_write++;
+                        worst_case++;
+                      }
+                  }
+              }
+            else /*other bank*/
+              {
+                if (cmdIsRead)
+                  {
+                        /* Page empty */
+                    if (current_row == active_row[current_bank])/*row is still active*/
+                      {
+                        if (corrected_overlap > 0 )/*overlapping*/
+                          {
+                            if(corrected_overlap >= pre_lat)/*best case*/
+                              {
+                                lat = SD_BEST_T_READ_READ_OBANK;
+                                best_case++;
+                                full_overlapping++;
+                              }
+                            else/*in between case*/
+                              {
+                                lat = SD_T_READ_READ_OBANK - corrected_overlap;
+                                in_between_case++;
+                                partial_overlapping++;
+                              }
+                          }
+                        else/*in between case*/
+                          {
+                            lat = SD_T_READ_READ_OBANK;
+                            in_between_case++;
+                          }
+                        other_bank_read_access_hit++;
+                        obr_after_read_hit++;
+                      }
+                    else/*row is not active*/
+                      {
+                        if (corrected_overlap > 0 )/*overlapping*/
+                          {
+                            if(corrected_overlap >= SD_T_READ_READ_OBANK )/*best case*/
+                              {
+                                lat = SD_BEST_T_READ_READ_OBANK;
+                                best_case++;
+                                full_overlapping++;
+                              }
+                            else/*in between case*/
+                              {
+                                lat = SD_T_READ_READ_OBANK-corrected_overlap;
+                                in_between_case++;
+                                partial_overlapping++;
+                              }
+                          }
+                        else/*worst case*/
+                          {
+                            lat = SD_T_READ_READ_OBANK;
+                            worst_case++;
+                          }
+
+                          // DR keep track of time between misses
+                          was_miss = 1;
+
+                        other_bank_read_access_miss[0]++;
+                        obr_after_read_miss++;
+                      }
+                  }
+                else/*write*/
+                  {
+                    if (current_row == active_row[current_bank])/*row is still active*/
+                      { /*best_case*/
+                        lat = SD_BEST_T_WRITE_WRITE_OBANK;
+                        best_case++;
+                        other_bank_write_access_hit++;
+                        obw_after_write_hit++;
+                      }
+                    else/*row is not active*/
+                      {
+                        if (corrected_overlap > 0 )/*overlapping*/
+                          {
+                            if(corrected_overlap >=SD_T_WRITE_WRITE_OBANK)/*best case*/
+                              {
+                                lat = SD_BEST_T_WRITE_WRITE_OBANK;
+                                best_case++;
+                                full_overlapping++;
+                              }
+                            else/*in between case*/
+                              {
+                                lat = SD_T_WRITE_WRITE_OBANK-corrected_overlap;
+                                in_between_case++;
+                                partial_overlapping++;
+                              }
+                          }
+                        else/*worst case*/
+                          {
+                            lat = SD_T_WRITE_WRITE_OBANK;
+                            worst_case++;
+                          }
+
+                          // DR keep track of time between misses
+                          was_miss = 1;
+
+                        other_bank_write_access_miss[0]++;
+                        obw_after_write_miss++;
+
+                      }
+                  }
+              }
+          }
+        else /*lastCmdIsRead != cmdIsRead*/
+          {
+            if (current_bank == last_bank)/*same bank*/
+              {
+                if (current_row == last_row)/*same row*/
+                  {
+                        /* Page Hit */
+                    if (cmdIsRead)
+                      {/*worst case*/
+                        lat = SD_T_READ_WRITE_SROW;
+                        srow_flag = true;
+                        same_row_read_access++;
+                        srr_after_write++;
+                        worst_case++;
+                      }
+                    else/*write*/
+                      {/*worst case*/
+                        lat = SD_T_WRITE_READ_SROW;
+                        srow_flag = true;
+                        same_row_write_access++;
+                        srw_after_read++;
+                        worst_case++;
+                      }
+                  }
+                else /*other row in same bank*/
+                  {
+                        /* Page Miss */
+                    if (cmdIsRead)
+                      {/*worst case*/
+                        lat = SD_T_READ_WRITE_SBANK;
+                        same_bank_read_access++;
+                        sbr_after_write++;
+                        worst_case++;
+                      }
+                    else/*write*/
+                      {
+                        if (corrected_overlap > 0 )/*overlapping*/
+                          {
+                            if (corrected_overlap >= pre_lat)/*best case*/
+                              {
+                                lat = SD_BEST_T_WRITE_READ_SBANK;
+                                best_case++;
+                                full_overlapping++;
+                              }
+                            else/*in between case*/
+                              {
+                                lat = SD_T_WRITE_READ_SBANK-corrected_overlap;
+                                in_between_case++;
+                                partial_overlapping++;
+                              }
+                          }
+                        else/*worst case*/
+                          {
+                            lat = SD_T_WRITE_READ_OBANK;
+                            worst_case++;
+                          }
+                        same_bank_write_access++;
+                        sbw_after_read++;
+                      }
+                  }
+              }
+            else /*other bank*/
+              {
+                        /* Page empty */
+                if (cmdIsRead)
+                  {
+                    if (current_row == active_row[current_bank])/*row is still active*/
+                      { /*best case*/
+                        lat = SD_BEST_T_READ_WRITE_OBANK;
+                        best_case++;
+                        other_bank_read_access_hit++;
+                        obr_after_write_hit++;
+                      }
+                    else/*row is not active*/
+                      {
+                        if (corrected_overlap > 0 )/*overlapping*/
+                          {
+                            if(corrected_overlap >= (pre_lat+act_lat))/*best case*/
+                              {
+                                lat = SD_BEST_T_READ_WRITE_OBANK;
+                                best_case++;
+                                full_overlapping++;
+                              }
+                            else/*in between case*/
+                              {
+                                lat = SD_T_READ_WRITE_OBANK-corrected_overlap;
+                                in_between_case++;
+                                partial_overlapping++;
+                              }
+                          }
+                        else/*worst case*/
+                          {
+                            lat = SD_T_READ_WRITE_OBANK;
+                            worst_case++;
+                          }
+                          // DR keep track of time between misses
+                          was_miss = 1;
+
+                        other_bank_read_access_miss[0]++;
+                        obr_after_write_miss++;
+                      }
+                  }
+                else/*write*/
+                  {
+                    if (current_row == active_row[current_bank])/*row is still active*/
+                      { /*best case*/
+                        lat = SD_BEST_T_WRITE_READ_OBANK;
+                        best_case++;
+                        other_bank_write_access_hit++;
+                        obw_after_read_hit++;
+                      }
+                    else/*row is not active*/
+                      {
+                        if (corrected_overlap > 0 )/*overlapping*/
+                          {
+                            if (corrected_overlap >= (SD_T_WRITE_READ_OBANK-SD_BEST_T_WRITE_READ_OBANK))/*best case*/
+                              {/*best case*/
+                                lat = SD_BEST_T_WRITE_READ_OBANK;
+                                best_case++;
+                                full_overlapping++;
+                              }
+                            else/*in between case*/
+                              {
+                                lat = SD_T_WRITE_READ_OBANK-corrected_overlap;
+                                in_between_case++;
+                                partial_overlapping++;
+                              }
+                          }
+                        else/*worst case*/
+                          {
+                            lat = SD_T_WRITE_READ_OBANK;
+                            worst_case++;
+                          }
+
+                          // DR keep track of time between misses
+                          was_miss = 1;
+
+                        other_bank_write_access_miss[0]++;
+                        obw_after_read_miss++;
+                      }
+                  }
+              }
+          }
+        /*fprintf(stderr,"%4d %4d ",lat,active_row[current_bank]);debugging*/
+
+        lat += chunks; /* burst length added*/
+        if(srow_flag == false)
+                timing_correction = cpu_ratio*(trc_lat - pre_lat - act_lat - cas_lat - 1);
+
+
+        /*fprintf(stderr,"%4d ",lat);debugging*/
+
+        active_row[current_bank]=current_row; /* open-page (hit) register */
+        lastCmdIsRead = cmdIsRead;
+        last_bank = current_bank;
+        last_row  = current_row;
+
+        if (cpu_ratio < 1.0)
+          {
+            lat = (lat+((int)(1/cpu_ratio)-1))/(int)(1/cpu_ratio);
+          }
+        else
+          {
+            temp = (int)(lat*cpu_ratio);
+            lat = (lat*cpu_ratio == temp)?temp:(temp+1); /*round up*/
+          }
+
+        /*fprintf(stderr,"%4d \n",lat);debugging*/
+
+        if (overlap <= 0) /*memory interface is not busy*/
+          {
+            if (memctrlpipe_enable == true)
+              {
+              busy_until[current_bank]=curTick+lat+
+                        timing_correction;
+              }
+            else
+              {
+                if (busy_until[current_bank] >= curTick)
+                  {
+                    busy_until[current_bank]+=(lat+
+                                timing_correction);
+                        total_arb_latency += (busy_until[current_bank]
+                                - curTick - lat
+                                - timing_correction);
+                    lat=busy_until[current_bank] - curTick;
+                  }
+                else busy_until[current_bank]=curTick+lat+
+                        timing_correction;
+              }
+          }
+        else/*the memory request will be satisfied temp cycles after curTick*/
+          {
+            busy_until[current_bank] +=(lat+
+                        timing_correction);
+            command_overlapping++;
+            lat+=overlap;
+                total_arb_latency += overlap;
+          }
+
+          // DR for power stats
+          if( was_miss ) {
+                cycles_between_misses[0] += (busy_until[current_bank] - time_last_miss);
+                time_last_miss = busy_until[current_bank];
+          }
+        // cout <<"cpu id = " << _cpu_num << "current_bank = " << current_bank << endl;
+        // if((_cpu_num < num_cpus) && (_cpu_num >= 0))
+    // bank_access_profile[_cpu_num][current_bank]++;
+
+        return lat;
+      }
+
+
+    /***********************************************************/
+    /********************     DRDRAM     ***********************/
+    /***********************************************************/
+
+    else if ((mem_type == "DRDRAM") && (mem_actpolicy == "open"))/*DRDRAM*/ /*a closed bank has an activ_row number of DR_NUM_ROWS: highest +1*/
+      {
+        if ((memctrladdr_type != "interleaved"))/* i.e. mc_type is linear */
+          {
+            current_bank=physic_address/DR_BANK_SIZE;
+            temp=physic_address-current_bank*DR_BANK_SIZE;/*address in bank*/
+            current_row=temp/DR_ROW_SIZE;
+            current_device=current_bank/(DR_NUM_BANKS/DR_NUM_DEVS);
+          }
+
+        else/*mc_type interleaved*/
+          /* This memory controller maps the addresses differently
+           * depending on the row-size, every row is mapped to another
+           * bank. So the text segment uses half of every bank. The heap
+           * the next quarter of each bank and the stack the rest.
+           */
+
+          {
+            num_blocks = physic_address/DR_ROW_SIZE; /* row number */
+            current_bank=(num_blocks%DR_NUM_BANKS)*2; /*every 'second' bank will be used*/
+            /*banks above DR_NUM_BANKS are the uneven banks*/
+            current_bank = ((current_bank <  DR_NUM_BANKS) ? current_bank:(current_bank - DR_NUM_BANKS+1));
+            current_row=num_blocks/DR_NUM_BANKS;
+            current_device=current_bank/(DR_NUM_BANKS/DR_NUM_DEVS);
+          }
+        if (abs(current_bank-last_bank)==1)/*access to an adjacent bank*/
+          {
+            if (!((current_bank%DR_BANK_SAMP == (DR_BANK_SAMP-1))&&(last_bank%DR_BANK_SAMP == 0))/*not 15/16 (current/last)*/
+                &&(!((last_bank%DR_BANK_SAMP == (DR_BANK_SAMP-1))&&(current_bank%DR_BANK_SAMP == 0))))/*not 16/15(current/last)*/
+              {
+                adjacent_access++;
+                adjacent=1;/*an adjacent bank is accessed*/
+                if (cmdIsRead)
+                  adjacent_read++;
+                else
+                  adjacent_write++;
+              }
+          }
+        precharge=0;/*at this moment no bank needs to be precharged*/
+        if (active_row[current_bank] == DR_NUM_ROWS)/*bank is precharged*/
+          {
+            if (prechargeBanksAround(current_bank)> 0)/*a bank next to the current is activated*/
+              {
+                if ((adjacent==1)&&(precharge==1))
+                  {
+                    /*since adjacent banks share SAMPs, this access would be the same as (in terms of latency)
+                     *an access to another row in the same bank if only one adjacent bank was active*/
+                    last_bank = current_bank;
+                    last_row = current_row+1;
+                    precharge=0;/*set to 0 for next memory access*/
+                  }
+              }
+          }
+        if (mem_access_details == true)
+          {
+            //fprintf(mem_accessfd,"       %09u  %4d   %3d  %15d\n",physic_address,current_row,current_bank,(int)adjacent_access);
+          }
+        else
+          {
+            if (mem_access_output!=NULL)
+              {
+                //fprintf(mem_accessfd,"\n");
+              }
+          }
+        total_access++;
+
+        if (memctrlpipe_enable == true)
+          {
+            overlap=(int)(busy_until[current_bank] - curTick);
+          }
+        else overlap=0;
+
+        if (cpu_ratio < 1.0)
+          {
+            corrected_overlap = overlap*((int)(1/cpu_ratio)); /* floor */
+          }
+        else
+          {
+            corrected_overlap = (int) (overlap/cpu_ratio);
+          }
+
+        /*fprintf(stderr,"%10.0f %10.0f %6d %6d %2d %2d ",(double)busy_until, (double)curTick, overlap, corrected_overlap,precharge,adjacent);debugging*/
+
+        if (cmdIsRead == lastCmdIsRead)/*same command*/
+          {
+            if (current_bank == last_bank)/*same bank*/
+              {
+                if (current_row == last_row)/*same row*/
+                  {
+                    if (cmdIsRead)
+                      {
+                        if (corrected_overlap > 0)/*overlapping*/
+                          {
+                            /*best case*/
+                            if (corrected_overlap >= DR_T_READ_READ_SROW)
+                              {
+                                lat=DR_BEST_T_READ_READ_SROW;
+                                srow_flag = true;
+                                best_case++;
+                                full_overlapping++;
+                              }
+                            else/*in between case*/
+                              {
+                                lat = DR_T_READ_READ_SROW-corrected_overlap;
+                                srow_flag = true;
+                                in_between_case++;
+                                partial_overlapping++;
+                              }
+                          }
+                        else
+                          {
+                            /*worst case*/
+                            lat = DR_T_READ_READ_SROW;
+                                srow_flag = true;
+                            worst_case++;
+                          }
+                        same_row_read_access++;
+                        srr_after_read++;
+                      }
+                    else/*write, always retire the previous data*/
+                      {
+                        if (corrected_overlap > 0)/*overlapping*/
+                          {
+                            /*best case*/
+                            if (corrected_overlap >= DR_T_OWR)
+                              {
+                                lat=DR_BEST_T_WRITE_WRITE_SROW;
+                                srow_flag = true;
+                                best_case++;
+                                full_overlapping++;
+                              }
+                            else/*in between case*/
+                              {
+                                lat = DR_T_WRITE_WRITE_SROW-corrected_overlap;
+                                srow_flag = true;
+                                in_between_case++;
+                                partial_overlapping++;
+                              }
+                          }
+                        else
+                          {
+                            /*worst case*/
+                            lat = DR_T_WRITE_WRITE_SROW;
+                                srow_flag = true;
+                            worst_case++;
+                          }
+                        same_row_write_access++;
+                        srw_after_write++;
+                      }
+                  }
+                else /*other row in same bank*/
+                  {
+                    if (cmdIsRead)
+                      {
+                        if (corrected_overlap > 0)/*overlapping*/
+                          {
+                            if (corrected_overlap >= DR_T_HELP)/*best case*/
+                              {
+                                lat = DR_BEST_T_READ_READ_SBANK;
+                                best_case++;
+                                full_overlapping++;
+                              }
+                            else/*in between case*/
+                              {
+                                lat = DR_T_READ_READ_SBANK-corrected_overlap;
+                                in_between_case++;
+                                partial_overlapping++;
+                              }
+                          }
+                        else/*worst case*/
+                          {
+                            lat = DR_T_READ_READ_SBANK;
+                            worst_case++;
+                          }
+                        same_bank_read_access++;
+                        sbr_after_read++;
+                      }
+                    else/*write*/
+                      {
+                        if (corrected_overlap > 0)/*overlapping*/
+                          {
+                            if (corrected_overlap >= DR_T_OWR)/*best case*/
+                              {
+                                lat = DR_BEST_T_WRITE_WRITE_SBANK;
+                                best_case++;
+                                full_overlapping++;
+                              }
+                            else/*in between case*/
+                              {
+                                lat = DR_T_WRITE_WRITE_SBANK-corrected_overlap;
+                                in_between_case++;
+                                partial_overlapping++;
+                              }
+                          }
+                        else/*worst case*/
+                          {
+                            lat = DR_T_WRITE_WRITE_SBANK;
+                            worst_case++;
+                          }
+                        same_bank_write_access++;
+                        sbw_after_write++;
+                      }
+                  }
+              }
+            else /*other bank*/
+              {
+                if (cmdIsRead)
+                  {
+                    if (current_row == active_row[current_bank])/*row is still active*/
+                      {
+                        if (corrected_overlap > 0 )/*overlapping*/
+                          {
+                            if(corrected_overlap >= (DR_T_CAC+DR_T_PACKET))/*best case*/
+                              {
+                                lat = DR_BEST_T_READ_READ_OBANK;
+                                best_case++;
+                                full_overlapping++;
+                              }
+                            else/*in between case*/
+                              {
+                                lat = DR_T_CAC+DR_T_PACKET-corrected_overlap;
+                                in_between_case++;
+                                partial_overlapping++;
+                              }
+                          }
+                        else/*in between case*/
+                          {
+                            lat = DR_T_CAC+DR_T_PACKET;
+                            in_between_case++;
+                          }
+                        other_bank_read_access_hit++;
+                        obr_after_read_hit++;
+                      }
+                    else/*row is not active or bank is precharged/not active*/
+                      {
+                        if (active_row[current_bank]!=DR_NUM_ROWS)/*row is not active, but bank is active*/
+                          {
+                            if (corrected_overlap > 0 )/*overlapping*/
+                              {
+                                if(corrected_overlap >= (DR_T_RP+DR_T_RCD+DR_T_CAC+DR_T_PACKET))/*best case*/
+                                  {
+                                    lat = DR_BEST_T_READ_READ_OBANK;
+                                    best_case++;
+                                    full_overlapping++;
+                                  }
+                                else/*in between case*/
+                                  {
+                                    lat = DR_T_RP+DR_T_RCD+DR_T_CAC+DR_T_PACKET-corrected_overlap;
+                                    in_between_case++;
+                                    partial_overlapping++;
+                                  }
+                              }
+                            else/*worst case*/
+                              {
+                                lat = DR_T_RP+DR_T_RCD+DR_T_CAC+DR_T_PACKET;
+                                in_between_case++;
+                              }
+                          }
+                        else/*current_row == DR_NUM_ROWS:precharged or inactive*/
+                          {
+                            if(precharge == 0)/*no adjacent bank is active*/
+                              {
+                                if (corrected_overlap > 0 )/*overlapping*/
+                                  {
+                                    if(corrected_overlap >= (DR_T_RCD+DR_T_CAC+DR_T_PACKET))/*best case*/
+                                      {
+                                        lat = DR_BEST_T_READ_READ_OBANK;
+                                        best_case++;
+                                        full_overlapping++;
+                                      }
+                                    else/*in between case*/
+                                      {
+                                        lat = DR_T_RCD+DR_T_CAC+DR_T_PACKET-corrected_overlap;
+                                        in_between_case++;
+                                        partial_overlapping++;
+                                      }
+                                  }
+                                else/*worst case*/
+                                  {
+                                    lat = DR_T_RCD+DR_T_CAC+DR_T_PACKET;
+                                    in_between_case++;
+                                  }
+                              }
+                            else/*one ore two adjacent banks are active*/
+                              {
+                                if (precharge == 1)
+                                  {
+                                    if (corrected_overlap > 0 )/*overlapping*/
+                                      {
+                                        if(corrected_overlap >= (DR_T_RP+DR_T_RCD+DR_T_CAC+DR_T_PACKET))/*best case*/
+                                          {
+                                            lat = DR_BEST_T_READ_READ_OBANK;
+                                            best_case++;
+                                            full_overlapping++;
+                                          }
+                                        else/*in between case*/
+                                          {
+                                            lat = (DR_T_RP+DR_T_RCD+DR_T_CAC+DR_T_PACKET)-corrected_overlap;
+                                            in_between_case++;
+                                            partial_overlapping++;
+                                          }
+                                      }
+                                    else/*worst case*/
+                                      {
+                                        lat = (DR_T_RP+DR_T_RCD+DR_T_CAC+DR_T_PACKET);
+                                        in_between_case++;
+                                      }
+                                  }
+                                else /*precharge ==2: two rows must be precharged*/
+                                  {
+                                    if (adjacent == 1)/*these banks are adjacent*/
+                                      {
+                                        if (corrected_overlap > 0 )/*overlapping*/
+                                          {
+                                            if(corrected_overlap >= DR_T_PP+2*DR_T_PACKET-DR_T_RDP+DR_T_CAC)/*best case*/
+                                              {
+                                                lat = DR_T_RDP+DR_T_RP+DR_T_RCD-DR_T_PACKET;
+                                                in_between_case++;
+                                                full_overlapping++;
+                                              }
+                                            else/*in between case*/
+                                              {
+                                                lat = DR_T_READ_READ_OBANK-corrected_overlap;
+                                                in_between_case++;
+                                                partial_overlapping++;
+                                              }
+                                          }
+                                        else/*worst case*/
+                                          {
+                                            lat = DR_T_READ_READ_OBANK;
+                                            worst_case++;
+                                          }
+                                      }
+                                    else/*adjacent == 0: two not adjacent banks need to be precharged*/
+                                      {
+                                        if (corrected_overlap > 0 )/*overlapping*/
+                                          {
+                                            if(corrected_overlap >= DR_T_READ_READ_OBANK)/*best case*/
+                                              {
+                                                lat = DR_BEST_T_READ_READ_OBANK;
+                                                best_case++;
+                                                full_overlapping++;
+                                              }
+                                            else/*in between case*/
+                                              {
+                                                lat = DR_T_READ_READ_OBANK-corrected_overlap;
+                                                in_between_case++;
+                                                partial_overlapping++;
+                                              }
+                                          }
+                                        else/*worst case*/
+                                          {
+                                            lat = DR_T_READ_READ_OBANK;
+                                            worst_case++;
+                                          }
+                                      }
+                                  }
+                              }
+                          }
+                        other_bank_read_access_miss[0]++;
+                        obr_after_read_miss++;
+                      }
+                  }
+                else/*write*/
+                  {
+                    if (current_row == active_row[current_bank])/*row is still active*/
+                      {
+                        if (corrected_overlap > 0 )/*overlapping*/
+                          {
+                            if(corrected_overlap >= (DR_T_CWD+DR_T_PACKET))/*best case*/
+                              {
+                                lat = DR_BEST_T_WRITE_WRITE_OBANK;
+                                best_case++;
+                                full_overlapping++;
+                              }
+                            else/*in between case*/
+                              {
+                                lat = DR_T_CWD+DR_T_PACKET-corrected_overlap;
+                                in_between_case++;
+                                partial_overlapping++;
+                              }
+                          }
+                        else/*worst case*/
+                          {
+                            lat = DR_T_CWD+DR_T_PACKET;
+                            in_between_case++;
+                          }
+                        other_bank_write_access_hit++;
+                        obw_after_write_hit++;
+                      }
+                    else/*row is not active or bank is precharged/not active*/
+                      {
+                        if (active_row[current_bank] != DR_NUM_ROWS)/*row is not active,but bank is active*/
+                          {
+                            if (corrected_overlap > 0 )/*overlapping*/
+                              {
+                                if(corrected_overlap >= (DR_T_RP+DR_T_RCD+DR_T_CWD+DR_T_PACKET))/*best case*/
+                                  {
+                                    lat = DR_BEST_T_WRITE_WRITE_OBANK;
+                                    best_case++;
+                                    full_overlapping++;
+                                  }
+                                else/*in between case*/
+                                  {
+                                    lat = DR_T_RP+DR_T_RCD+DR_T_CWD+DR_T_PACKET-corrected_overlap;
+                                    in_between_case++;
+                                    partial_overlapping++;
+                                  }
+                              }
+                            else/*worst case*/
+                              {
+                                lat = DR_T_RP+DR_T_RCD+DR_T_CWD+DR_T_PACKET;
+                                in_between_case++;
+                              }
+                          }
+                        else/*current_row == DR_NUM_ROWS:precharged or inactive*/
+                          {
+                            if(precharge == 0)/*no adjacent bank is active*/
+                              {
+                                if (corrected_overlap > 0 )/*overlapping*/
+                                  {
+                                    if(corrected_overlap >= (DR_T_RCD+DR_T_CWD+DR_T_PACKET))/*best case*/
+                                      {
+                                        lat = DR_BEST_T_WRITE_WRITE_OBANK;
+                                        best_case++;
+                                        full_overlapping++;
+                                      }
+                                    else/*in between case*/
+                                      {
+                                        lat = DR_T_RCD+DR_T_CWD+DR_T_PACKET-corrected_overlap;
+                                        in_between_case++;
+                                        partial_overlapping++;
+                                      }
+                                  }
+                                else/*worst case*/
+                                  {
+                                    lat = DR_T_RCD+DR_T_CWD+DR_T_PACKET;
+                                    in_between_case++;
+                                  }
+                              }
+                            else/*one ore two adjacent banks are active*/
+                              {
+                                if (precharge == 1)/*last_bank is no adjacent*/
+                                  {
+                                    if (corrected_overlap > 0 )/*overlapping*/
+                                      {
+                                        if(corrected_overlap >= (DR_T_RP+DR_T_RCD+DR_T_CWD+DR_T_PACKET))/*best case*/
+                                          {
+                                            lat = DR_BEST_T_WRITE_WRITE_OBANK;
+                                            best_case++;
+                                            full_overlapping++;
+                                          }
+                                        else/*in between case*/
+                                          {
+                                            lat = (DR_T_RP+DR_T_RCD+DR_T_CWD+DR_T_PACKET)-corrected_overlap;
+                                            in_between_case++;
+                                            partial_overlapping++;
+                                          }
+                                      }
+                                    else/*worst case*/
+                                      {
+                                        lat = (DR_T_RP+DR_T_RCD+DR_T_CWD+DR_T_PACKET);
+                                        in_between_case++;
+                                      }
+                                  }
+                                else /*precharge ==2: two rows have to be precharged*/
+                                  {
+                                    if (adjacent == 1)/*these banks are adjacent*/
+                                      {
+                                        if (corrected_overlap > 0 )/*overlapping*/
+                                          {
+                                            if(corrected_overlap >= DR_T_OWR+DR_T_PP)/*best case*/
+                                              {
+                                                lat = DR_T_WRITE_WRITE_OBANK-DR_T_OWR-DR_T_PP;
+                                                in_between_case++;
+                                                full_overlapping++;
+                                              }
+                                            else/*in between case*/
+                                              {
+                                                lat = DR_T_WRITE_WRITE_OBANK-corrected_overlap;
+                                                in_between_case++;
+                                                partial_overlapping++;
+                                              }
+                                          }
+                                        else/*worst case*/
+                                          {
+                                            lat = DR_T_WRITE_WRITE_OBANK;
+                                            worst_case++;
+                                          }
+                                      }
+                                    else/*adjacent == 0: two not adjacent banks need to be precharged*/
+                                      {
+                                        if (corrected_overlap > 0 )/*overlapping*/
+                                          {
+                                            if(corrected_overlap >= DR_T_WRITE_WRITE_OBANK)/*best case*/
+                                              {
+                                                lat = DR_BEST_T_WRITE_WRITE_OBANK;
+                                                best_case++;
+                                                full_overlapping++;
+                                              }
+                                            else/*in between case*/
+                                              {
+                                                lat = DR_T_WRITE_WRITE_OBANK-corrected_overlap;
+                                                in_between_case++;
+                                                partial_overlapping++;
+                                              }
+                                          }
+                                        else/*worst case*/
+                                          {
+                                            lat = DR_T_WRITE_WRITE_OBANK;
+                                            worst_case++;
+                                          }
+                                      }
+                                  }
+                              }
+                          }
+                        other_bank_write_access_miss[0]++;
+                        obw_after_write_miss++;
+                      }
+                  }
+              }
+          }
+        else /*lastCmdIsRead != cmdIsRead*/
+          {
+            if (current_bank == last_bank)/*same bank*/
+              {
+                if (current_row == last_row)/*same row*/
+                  {
+                    if (cmdIsRead)
+                      {
+                        if (corrected_overlap > 0)/*overlapping*/
+                          {
+                            /*best case*/
+                            if (corrected_overlap >= DR_T_OWR)
+                              {
+                                lat=DR_BEST_T_READ_WRITE_SROW;
+                                srow_flag = true;
+                                best_case++;
+                                full_overlapping++;
+                              }
+                            else/*in between case*/
+                              {
+                                lat = DR_T_READ_WRITE_SROW-corrected_overlap;
+                                srow_flag = true;
+                                in_between_case++;
+                                partial_overlapping++;
+                              }
+                          }
+                        else
+                          {
+                            /*worst case*/
+                            lat = DR_T_READ_WRITE_SROW;
+                                srow_flag = true;
+                            worst_case++;
+                          }
+                        same_row_read_access++;
+                        srr_after_write++;
+                      }
+                    else/*write*/
+                      {
+                        if (corrected_overlap > 0)/*overlapping*/
+                          {
+                            /*best case*/
+                            if (corrected_overlap >= DR_T_WRITE_READ_SROW)
+                              {
+                                lat=DR_BEST_T_WRITE_READ_SROW;
+                                srow_flag = true;
+                                best_case++;
+                                full_overlapping++;
+                              }
+                            else/*in between case*/
+                              {
+                                lat = DR_T_WRITE_READ_SROW-corrected_overlap;
+                                srow_flag = true;
+                                in_between_case++;
+                                partial_overlapping++;
+                              }
+                          }
+                        else
+                          {
+                            /*worst case*/
+                            lat = DR_T_WRITE_READ_SROW;
+                                srow_flag = true;
+                            worst_case++;
+                          }
+                        same_row_write_access++;
+                        srw_after_read++;
+                      }
+                  }
+                else /*other row in same bank*/
+                  {
+                    if (cmdIsRead)
+                      {
+                        if (corrected_overlap > 0 )/*overlapping*/
+                          {
+                            if (corrected_overlap >= DR_T_OWR)/*best case*/
+                              {
+                                lat = DR_BEST_T_READ_WRITE_SBANK;
+                                best_case++;
+                                full_overlapping++;
+                              }
+                            else/*in between case*/
+                              {
+                                lat = DR_T_READ_WRITE_SBANK-corrected_overlap;
+                                in_between_case++;
+                                partial_overlapping++;
+                              }
+                          }
+                        else/*worst case*/
+                          {
+                            lat = DR_T_READ_WRITE_SBANK;
+                            worst_case++;
+                          }
+                        same_bank_read_access++;
+                        sbr_after_write++;
+                      }
+                    else/*write*/
+                      {
+                        if (corrected_overlap > 0 )/*overlapping*/
+                          {
+                            if (corrected_overlap >= DR_T_HELP)/*best case*/
+                              {
+                                lat = DR_BEST_T_WRITE_READ_SBANK;
+                                best_case++;
+                                full_overlapping++;
+                              }
+                            else/*in between case*/
+                              {
+                                lat = DR_T_WRITE_READ_SBANK-corrected_overlap;
+                                in_between_case++;
+                                partial_overlapping++;
+                              }
+                          }
+                        else/*worst case*/
+                          {
+                            lat = DR_T_WRITE_READ_SBANK;
+                            worst_case++;
+                          }
+                        same_bank_write_access++;
+                        sbw_after_read++;
+                      }
+                  }
+              }
+            else /*other bank*/
+              {
+                if (cmdIsRead)
+                  {
+                    if (current_row == active_row[current_bank])/*row is still active*/
+                      {
+                        if (corrected_overlap > 0 )/*overlapping*/
+                          {
+                            if(last_dev != current_device)
+                              {
+                                if(corrected_overlap >= DR_T_CWD+DR_T_PACKET)/*best case*/
+                                  {
+                                    lat = DR_BEST_T_READ_WRITE_ODEV;
+                                    best_case++;
+                                    full_overlapping++;
+                                  }
+                                else/*in between case*/
+                                  {
+                                    lat = DR_T_CAC+DR_T_PACKET-corrected_overlap;
+                                    in_between_case++;
+                                    partial_overlapping++;
+                                  }
+                              }
+                            else /* same device */
+                              {
+                                if(corrected_overlap >= DR_T_OWR)/*best case*/
+                                  {
+                                    lat = DR_BEST_T_READ_WRITE_OBANK;
+                                    best_case++;
+                                    full_overlapping++;
+                                  }
+                                else/*in between case*/
+                                  {
+                                    lat = DR_T_CAC+DR_T_PACKET-corrected_overlap;
+                                    in_between_case++;
+                                    partial_overlapping++;
+                                  }
+                              }
+                          }
+                        else/*in between case, no overlap*/
+                          {
+                            lat = DR_T_CAC+DR_T_PACKET;
+                            in_between_case++;
+                          }
+                        other_bank_read_access_hit++;
+                        obr_after_write_hit++;
+                      }
+
+                    else/*row is not active or bank is precharged/not active*/
+                      {
+                        if (active_row[current_bank] != DR_NUM_ROWS)/*row is not active,but bank is active*/
+                          {
+                            if (corrected_overlap > 0 )/*overlapping*/
+                              {
+                                if (last_dev != current_device)
+                                  {
+                                    if(corrected_overlap >= (DR_T_RP+DR_T_RCD+DR_T_CWD+DR_T_PACKET))/*best case*/
+                                      {
+                                        lat = DR_BEST_T_READ_WRITE_ODEV;
+                                        best_case++;
+                                        full_overlapping++;
+                                      }
+                                    else/*in between case*/
+                                      {
+                                        lat = DR_T_RP+DR_T_RCD+DR_T_CAC+DR_T_PACKET-corrected_overlap;
+                                        in_between_case++;
+                                        partial_overlapping++;
+                                      }
+                                  }
+                                else /* same device */
+                                  {
+                                    if(corrected_overlap >= (DR_T_RP+DR_T_RCD+DR_T_OWR))/*best case*/
+                                      {
+                                        lat = DR_BEST_T_READ_WRITE_OBANK;
+                                        best_case++;
+                                        full_overlapping++;
+                                      }
+                                    else/*in between case*/
+                                      {
+                                        lat = DR_T_RP+DR_T_RCD+DR_T_CAC+DR_T_PACKET-corrected_overlap;
+                                        in_between_case++;
+                                        partial_overlapping++;
+                                      }
+                                  }
+                              }
+                            else/*worst case*/
+                              {
+                                lat = DR_T_RP+DR_T_RCD+DR_T_CAC+DR_T_PACKET;
+                                in_between_case++;
+                              }
+                          }
+                        else/*current_row == DR_NUM_ROWS:precharged or inactive*/
+                          {
+                            if(precharge == 0)/*no adjacent bank is active*/
+                              {
+                                if (corrected_overlap > 0 )/*overlapping*/
+                                  {
+                                    if(last_dev != current_device)
+                                      {
+                                        if(corrected_overlap >= (DR_T_RCD+DR_T_CWD+DR_T_PACKET))/*best case*/
+                                          {
+                                            lat = DR_BEST_T_READ_WRITE_ODEV;
+                                            best_case++;
+                                            full_overlapping++;
+                                          }
+                                        else/*in between case*/
+                                          {
+                                            lat = DR_T_RCD+DR_T_CAC+DR_T_PACKET-corrected_overlap;
+                                            in_between_case++;
+                                            partial_overlapping++;
+                                          }
+                                      }
+                                    else /* same device */
+                                      {
+                                        if(corrected_overlap >= (DR_T_RCD+DR_T_OWR))/*best case*/
+                                          {
+                                            lat = DR_BEST_T_READ_WRITE_OBANK;
+                                            best_case++;
+                                            full_overlapping++;
+                                          }
+                                        else/*in between case*/
+                                          {
+                                            lat = DR_T_RCD+DR_T_CAC+DR_T_PACKET-corrected_overlap;
+                                            in_between_case++;
+                                            partial_overlapping++;
+                                          }
+                                      }
+                                  }
+                                else/*worst case*/
+                                  {
+                                    lat = DR_T_RCD+DR_T_CAC+DR_T_PACKET;
+                                    in_between_case++;
+                                  }
+                              }
+                            else/*one or two adjacent banks are active*/
+                              {
+                                if (precharge == 1)/*an adjacent bank (!=last_bank) needs to be precharged*/
+                                  {
+                                    if (corrected_overlap > 0 )/*overlapping*/
+                                      {
+                                        if(last_dev != current_device)
+                                          {
+                                            if(corrected_overlap >= (DR_T_RP+DR_T_RCD+DR_T_CWD+DR_T_PACKET))/*best case*/
+                                              {
+                                                lat = DR_BEST_T_READ_WRITE_ODEV;
+                                                best_case++;
+                                                full_overlapping++;
+                                              }
+                                            else/*in between case*/
+                                              {
+                                                lat = (DR_T_RP+DR_T_RCD+DR_T_CAC+DR_T_PACKET)-corrected_overlap;
+                                                in_between_case++;
+                                                partial_overlapping++;
+                                              }
+                                          }
+                                        else /* same device */
+                                          {
+                                            if(corrected_overlap >= (DR_T_RP+DR_T_RCD+DR_T_OWR))/*best case*/
+                                              {
+                                                lat = DR_BEST_T_READ_WRITE_OBANK;
+                                                best_case++;
+                                                full_overlapping++;
+                                              }
+                                            else/*in between case*/
+                                              {
+                                                lat = (DR_T_RP+DR_T_RCD+DR_T_CAC+DR_T_PACKET)-corrected_overlap;
+                                                in_between_case++;
+                                                partial_overlapping++;
+                                              }
+                                          }
+                                      }
+                                    else/*worst case*/
+                                      {
+                                        lat = (DR_T_RP+DR_T_RCD+DR_T_CAC+DR_T_PACKET);
+                                        in_between_case++;
+                                      }
+                                  }
+                                else /*precharge ==2: two rows have to be precharged*/
+                                  {
+                                    if (adjacent == 1) /* the banks are adjacent */
+                                      {
+                                        if (corrected_overlap > 0 )/*overlapping*/
+                                          {
+                                            if(corrected_overlap >= DR_T_OWR + DR_T_PP)/*best case*/
+                                              {
+                                                lat = DR_T_READ_WRITE_OBANK-DR_T_OWR - DR_T_PP;
+                                                in_between_case++;
+                                                full_overlapping++;
+                                              }
+                                            else/*in between case*/
+                                              {
+                                                lat = DR_T_READ_WRITE_OBANK-corrected_overlap;
+                                                in_between_case++;
+                                                partial_overlapping++;
+                                              }
+                                          }
+                                        else/*worst case*/
+                                          {
+                                            lat = DR_T_READ_WRITE_OBANK;
+                                            worst_case++;
+                                          }
+                                      }
+                                    else/*adjacent == 0: two not adjacent banks need to be precharged*/
+                                      {
+                                        if (corrected_overlap > 0 )/*overlapping*/
+                                          {
+                                            if (last_dev != current_device)
+                                              {
+                                                if(corrected_overlap >= (DR_T_PP+DR_T_RP+DR_T_RCD+DR_T_CWD+DR_T_PACKET))/*best case*/
+                                                  {
+                                                    lat = DR_BEST_T_READ_WRITE_ODEV;
+                                                    best_case++;
+                                                    full_overlapping++;
+                                                  }
+                                                else/*in between case*/
+                                                  {
+                                                    lat = DR_T_READ_WRITE_OBANK-corrected_overlap;
+                                                    in_between_case++;
+                                                    partial_overlapping++;
+                                                  }
+                                              }
+                                            else /* same device */
+                                              {
+                                                if(corrected_overlap >= (DR_T_PP+DR_T_RP+DR_T_RCD+DR_T_OWR))/*best case*/
+                                                  {
+                                                    lat = DR_BEST_T_READ_WRITE_OBANK;
+                                                    best_case++;
+                                                    full_overlapping++;
+                                                  }
+                                                else/*in between case*/
+                                                  {
+                                                    lat = DR_T_READ_WRITE_OBANK-corrected_overlap;
+                                                    in_between_case++;
+                                                    partial_overlapping++;
+                                                  }
+                                              }
+                                          }
+                                        else/*worst case*/
+                                          {
+                                            lat = DR_T_READ_WRITE_OBANK;
+                                            worst_case++;
+                                          }
+                                      }
+                                  }
+                              }
+                          }
+                        other_bank_read_access_miss[0]++;
+                        obr_after_write_miss++;
+                      }
+                  }
+                else/*write*/
+                  {
+                    if (current_row == active_row[current_bank])/*row is still active*/
+                      {
+                        if (corrected_overlap > 0 )/*overlapping*/
+                          {
+                            if(corrected_overlap >= DR_T_CWD+DR_T_PACKET)/*best case*/
+                              {
+                                lat = DR_BEST_T_WRITE_READ_OBANK;
+                                best_case++;
+                                full_overlapping++;
+                              }
+                            else/*in between case*/
+                              {
+                                lat = DR_T_CWD+DR_T_PACKET-corrected_overlap;
+                                in_between_case++;
+                                partial_overlapping++;
+                              }
+                          }
+                        else/*in between case*/
+                          {
+                            lat = DR_T_CWD+DR_T_PACKET;
+                            in_between_case++;
+                          }
+                        other_bank_write_access_hit++;
+                        obw_after_read_hit++;
+                      }
+                    else/*row is not active or bank is precharged/not active*/
+                      {
+                        if (active_row[current_bank] != DR_NUM_ROWS)/*row is not active,but bank is active*/
+                          {
+                            if (corrected_overlap > 0 )/*overlapping*/
+                              {
+                                if(corrected_overlap >= (DR_T_RP+DR_T_RCD+DR_T_CWD+DR_T_PACKET))/*best case*/
+                                  {
+                                    lat = DR_BEST_T_WRITE_READ_OBANK;
+                                    best_case++;
+                                    full_overlapping++;
+                                  }
+                                else/*in between case*/
+                                  {
+                                    lat = DR_T_RP+DR_T_RCD+DR_T_CWD+DR_T_PACKET-corrected_overlap;
+                                    in_between_case++;
+                                    partial_overlapping++;
+                                  }
+                              }
+                            else/*worst case*/
+                              {
+                                lat = DR_T_RP+DR_T_RCD+DR_T_CWD+DR_T_PACKET;
+                                in_between_case++;
+                              }
+                          }
+                        else/*current_row == DR_NUM_ROWS:precharged or inactive*/
+                          {
+                            if(precharge == 0)/*no adjacent bank is active*/
+                              {
+                                if (corrected_overlap > 0 )/*overlapping*/
+                                  {
+                                    if(corrected_overlap >= (DR_T_RCD+DR_T_CWD+DR_T_PACKET))/*best case*/
+                                      {
+                                        lat = DR_BEST_T_WRITE_READ_OBANK;
+                                        best_case++;
+                                        full_overlapping++;
+                                      }
+                                    else/*in between case*/
+                                      {
+                                        lat = DR_T_RCD+DR_T_CWD+DR_T_PACKET-corrected_overlap;
+                                        in_between_case++;
+                                        partial_overlapping++;
+                                      }
+                                  }
+                                else/*worst case*/
+                                  {
+                                    lat = DR_T_RCD+DR_T_CWD+DR_T_PACKET;
+                                    in_between_case++;
+                                  }
+                              }
+                            else/*one or two adjacent banks are active*/
+                              {
+                                if (precharge == 1)/*an adjacent bank (!=last_bank)  needs to be precharged first*/
+                                  {
+                                    if (corrected_overlap > 0 )/*overlapping*/
+                                      {
+                                        if(corrected_overlap >= (DR_T_RP+DR_T_RCD+DR_T_CWD+DR_T_PACKET))/*best case*/
+                                          {
+                                            lat = DR_BEST_T_WRITE_READ_OBANK;
+                                            best_case++;
+                                            full_overlapping++;
+                                          }
+                                        else/*in between case*/
+                                          {
+                                            lat = (DR_T_RP+DR_T_RCD+DR_T_CWD+DR_T_PACKET)-corrected_overlap;
+                                            in_between_case++;
+                                            partial_overlapping++;
+                                          }
+                                      }
+                                    else/*worst case*/
+                                      {
+                                        lat = (DR_T_RP+DR_T_RCD+DR_T_CWD+DR_T_PACKET);
+                                        in_between_case++;
+                                      }
+                                  }
+                                else /*precharge ==2: two rows have to be precharged*/
+                                  {
+                                    if (adjacent == 1)/*these banks are adjacent*/
+                                      {
+                                        if (corrected_overlap > 0 )/*overlapping*/
+                                          {
+                                            if(corrected_overlap >= DR_T_PP-DR_T_RDP+2*DR_T_PACKET+DR_T_CAC)/*best case*/
+                                              {
+                                                lat = DR_T_WRITE_READ_OBANK-(DR_T_PP-DR_T_RDP+2*DR_T_PACKET+DR_T_CAC);
+                                                in_between_case++;
+                                                full_overlapping++;
+                                              }
+                                            else/*in between case*/
+                                              {
+                                                lat = DR_T_WRITE_READ_OBANK-corrected_overlap;
+                                                in_between_case++;
+                                                partial_overlapping++;
+                                              }
+                                          }
+                                        else/*worst case*/
+                                          {
+                                            lat = DR_T_WRITE_READ_OBANK;
+                                            worst_case++;
+                                          }
+                                      }
+                                    else/*adjacent == 0: two not adjacent banks need to be precharged*/
+                                      {
+                                        if (corrected_overlap > 0 )/*overlapping*/
+                                          {
+                                            if(corrected_overlap >= DR_T_WRITE_READ_OBANK)/*best case*/
+                                              {
+                                                lat = DR_BEST_T_WRITE_READ_OBANK;
+                                                best_case++;
+                                                full_overlapping++;
+                                              }
+                                            else/*in between case*/
+                                              {
+                                                lat = DR_T_WRITE_READ_OBANK-corrected_overlap;
+                                                in_between_case++;
+                                                partial_overlapping++;
+                                              }
+                                          }
+                                        else/*worst case*/
+                                          {
+                                            lat = DR_T_WRITE_READ_OBANK;
+                                            worst_case++;
+                                          }
+                                      }
+                                  }
+                              }
+                          }
+                        other_bank_write_access_miss[0]++;
+                        obw_after_read_miss++;
+                      }
+                  }
+              }
+          }
+        /*fprintf(stderr,"%4d %4d ",lat,active_row[current_bank]);debugging*/
+
+        lat += chunks * DR_T_PACKET; /*every 128 bit need DR_NUM_CYCLES*/
+
+        /*fprintf(stderr,"%4d ",lat);debugging*/
+
+        if (cpu_ratio < 1.0)
+          {
+            lat = (lat+((int)(1/cpu_ratio)-1))/(int)(1/cpu_ratio);
+          }
+        else
+          {
+            temp = (int)(lat*cpu_ratio);
+            lat = (lat*cpu_ratio == temp)?temp:(temp+1); /*round up*/
+          }
+
+        active_row[current_bank]=current_row;
+        lastCmdIsRead = cmdIsRead;
+        last_bank=current_bank;
+        last_row = current_row;
+        last_dev = current_device;
+
+        /*fprintf(stderr,"%4d \n",lat);debugging*/
+
+        if (overlap <= 0) /*memory interface is not busy*/
+          {
+            if (memctrlpipe_enable == true)
+              {
+                busy_until[current_bank] =curTick+lat;
+              }
+            else
+              {
+                if (busy_until[current_bank] >= curTick)
+                  {
+                    busy_until[current_bank] +=lat;
+                    lat=busy_until[current_bank] - curTick;
+                  }
+                else busy_until[current_bank] = curTick+lat;
+              }
+          }
+        else/*the memory request will be satisfied temp cycles after curTick*/
+          {
+            busy_until[current_bank] +=lat;
+            command_overlapping++;
+            lat+=overlap;
+          }
+
+        // if((_cpu_num < num_cpus) && (_cpu_num >= 0))
+                // cout <<"cpu id = " << _cpu_num << "current_bank = " << current_bank << endl;
+    // bank_access_profile[_cpu_num][current_bank]++;
+        return lat;
+      }
+
+    /******************************************************************/
+
+        else if ((mem_type== "SDRAM") && (mem_actpolicy == "closed") && (memctrlpipe_enable == true))
+           /* SDRAM closed-page with overlap, 2/00 MG */
+      {
+        if ((memctrladdr_type != "interleaved"))/* i.e. mc_type is linear*/
+          {
+            // current_bank=physic_address/SD_BANK_SIZE;
+            current_bank=physic_address/bank_size;
+          }
+        else/*mc_type interleaved*/
+          /* This memory management unit maps the addresses different
+           * depending on the row_size, every row is mapped to another
+           * bank. So the text segment uses half of every bank. The heap
+           * the next quarter of each bank and the stack the rest.
+           */
+          {
+            num_blocks = physic_address/SD_ROW_SIZE; /* row number */
+            // current_bank=num_blocks%SD_NUM_BANKS;
+            current_bank=num_blocks%num_banks;
+          }
+
+        if (mem_access_details == true)
+          {
+            //fprintf(mem_accessfd,"       %09u   %3d\n",physic_address,current_bank);
+          }
+        else
+          {
+            if (mem_access_output!=NULL)
+              {
+                //fprintf(mem_accessfd,"\n");
+              }
+          }
+        total_access++;
+
+        overlap=(int)(busy_until[current_bank] - curTick);
+
+        if (current_bank == last_bank)/*same bank*/
+          {
+            if ((lastCmdIsRead == cmdIsRead) && (cmdIsRead))/* RAR */
+              {
+                lat = act_lat + cas_lat;
+              }
+            else if ((lastCmdIsRead == cmdIsRead) && (!cmdIsRead)) /* WAW */
+              {
+                lat = act_lat;
+              }
+            else if ((lastCmdIsRead != cmdIsRead) && (cmdIsRead)) /* RAW */
+              {
+                lat = act_lat + cas_lat;
+              }
+            else /* WAR */
+              {
+                lat = act_lat;
+              }
+          }
+        else /* other bank */
+          {
+            if (cpu_ratio < 1.0)
+              {
+                corrected_overlap = overlap*((int)(1/cpu_ratio)); /* floor */
+              }
+            else
+              {
+                corrected_overlap = (int) (overlap/cpu_ratio);
+              }
+
+            if ((lastCmdIsRead == cmdIsRead) && (cmdIsRead))/* RAR */
+              {
+                if (corrected_overlap > act_lat + cas_lat)
+                  {
+                    lat = 0;
+                    best_case++;
+                    full_overlapping++;
+                  }
+                else if (corrected_overlap > 0)
+                  {
+                    lat = act_lat + cas_lat - corrected_overlap;
+                    in_between_case++;
+                    partial_overlapping++;
+                  }
+                else
+                  {
+                    lat = act_lat + cas_lat;
+                    worst_case++;
+                  }
+              }
+            else if ((lastCmdIsRead == cmdIsRead) && (!cmdIsRead)) /* WAW */
+              {
+                if (corrected_overlap > act_lat + pre_lat + (dpl_lat-1))
+                  {
+                    lat = - pre_lat - dpl_lat +1;
+                    best_case++;
+                    full_overlapping++;
+                  }
+                else if (corrected_overlap > 0)
+                  {
+                    lat = act_lat - corrected_overlap;
+                    in_between_case++;
+                    partial_overlapping++;
+                  }
+                else
+                  {
+                    lat = act_lat;
+                    worst_case++;
+                  }
+              }
+            else if ((lastCmdIsRead != cmdIsRead) && (cmdIsRead)) /* RAW */
+              {
+                if (corrected_overlap > cas_lat + pre_lat + dpl_lat - 1 )
+                  {
+                    lat = act_lat - (pre_lat + dpl_lat - 1);
+                    best_case++;
+                    partial_overlapping++;
+                  }
+                else if (corrected_overlap > 0)
+                  {
+                    lat = act_lat + cas_lat - corrected_overlap;
+                    in_between_case++;
+                    partial_overlapping++;
+                  }
+                else
+                  {
+                    lat = act_lat + cas_lat;
+                    worst_case++;
+                  }
+              }
+            else /* WAR */
+              {
+                if (corrected_overlap > act_lat - (dpl_lat-1))
+                  {
+                    lat = dpl_lat-1;
+                    best_case++;
+                    partial_overlapping++;
+                  }
+                else if (corrected_overlap > 0)
+                  {
+                    lat = act_lat - corrected_overlap;
+                    in_between_case++;
+                    partial_overlapping++;
+                  }
+                else
+                  {
+                    lat = act_lat;
+                    worst_case++;
+                  }
+              }
+          }
+        lastCmdIsRead = cmdIsRead;
+        last_bank=current_bank;
+        last_row = current_row;
+
+        lat += chunks;
+
+        if (cpu_ratio < 1.0)
+          {
+            lat = (lat+((int)(1/cpu_ratio)-1))/(int)(1/cpu_ratio);
+          }
+        else
+          {
+            temp = (int)(lat*cpu_ratio);
+            lat = (lat*cpu_ratio == temp)?temp:(temp+1); /*round up*/
+          }
+
+        /*fprintf(stderr,"%4d \n",lat); debugging */
+
+        if (overlap <= 0) /*memory interface is not busy*/
+          {
+            busy_until[current_bank] = curTick+lat;
+          }
+        else /*the memory request will be satisfied temp cycles after curTick*/
+          {
+            busy_until[current_bank] +=lat;
+            command_overlapping++;
+                total_arb_latency += overlap;
+            lat+=overlap;
+          }
+        if (!cmdIsRead)
+          {
+           temp = (int)(((dpl_lat-1) + pre_lat)*cpu_ratio);
+           busy_until[current_bank] += (((dpl_lat-1) + pre_lat)*cpu_ratio == temp)?temp:(temp+1);
+          }
+
+
+
+        /*fprintf(stderr,"%10.0f %10.0f %4d %4d \n",(double)busy_until, (double)curTick, overlap, lat);debug*/
+        // if((_cpu_num < num_cpus) && (_cpu_num >= 0))
+                // cout <<"cpu id = " << _cpu_num << "current_bank = " << current_bank << endl;
+    // bank_access_profile[_cpu_num][current_bank]++;
+        return lat;
+      }
+
+    /******************************************************************/
+
+    else if ((mem_type == "DRDRAM") && (mem_actpolicy == "closed") && (memctrlpipe_enable == true))
+      /* DRDRAM closed-page with overlap*/
+     {
+
+        if ((memctrladdr_type != "interleaved"))/*i.e. mc_type is linear*/
+          {
+            current_bank=physic_address/DR_BANK_SIZE;
+            current_device=current_bank/(DR_NUM_BANKS/DR_NUM_DEVS);
+          }
+        else/*mc_type interleaved*/
+          /* This memory management unit maps the addresses different
+           * depending on the row-size, every row is mapped to another
+           * bank. So the text segment uses half of every bank. The heap
+           * the next quarter of each bank and the stack the rest.
+           */
+          {
+            num_blocks = physic_address/DR_ROW_SIZE; /* row number */
+            current_bank=(num_blocks%DR_NUM_BANKS)*2; /*every 'second' bank will be used*/
+            /*banks above DR_NUM_BANKS are the uneven banks*/
+            current_bank = ((current_bank <  DR_NUM_BANKS) ? current_bank:(current_bank - DR_NUM_BANKS+1));
+            current_device=current_bank/(DR_NUM_BANKS/DR_NUM_DEVS);
+          }
+
+
+        if (mem_access_details == true)
+          {
+            //fprintf(mem_accessfd,"       %09u   %3d  \n",physic_address,current_bank);
+          }
+        else
+          {
+            if (mem_access_output!=NULL)
+              {
+                //fprintf(mem_accessfd,"\n");
+              }
+          }
+        total_access++;
+
+        overlap=(int)(busy_until[current_bank] - curTick);
+
+        if (cpu_ratio < 1.0)
+          {
+            corrected_overlap = overlap*((int)(1/cpu_ratio)); /* floor */
+          }
+        else
+          {
+            corrected_overlap = (int) (overlap/cpu_ratio);
+          }
+
+        if (current_bank == last_bank)/*same bank*/
+          {
+            if ((lastCmdIsRead == cmdIsRead) && (cmdIsRead))/* RAR */
+              {
+                lat = DR_T_RCD + DR_T_CAC + DR_T_PACKET;
+                worst_case++;
+              }
+            else if ((lastCmdIsRead == cmdIsRead) && (!cmdIsRead)) /* WAW */
+              {
+                lat = DR_T_RCD + DR_T_CWD + DR_T_PACKET;
+                worst_case++;
+              }
+            else if ((lastCmdIsRead != cmdIsRead) && (cmdIsRead)) /* RAW */
+              {
+                lat = DR_T_RCD + DR_T_CAC + DR_T_PACKET;
+                worst_case++;
+              }
+            else /* WAR */
+              {
+                lat = DR_T_RCD + DR_T_CWD + DR_T_PACKET;
+                worst_case++;
+              }
+          }
+        else /* other bank */
+          {
+            if ((lastCmdIsRead == cmdIsRead) && (cmdIsRead))/* RAR */
+              {
+                if (corrected_overlap > DR_T_RAS + DR_T_RP - 2 * DR_T_PACKET)
+                  {
+                    lat = - DR_T_RAS + DR_T_RCD + DR_T_PACKET + DR_T_CAC;
+                    best_case++;
+                    full_overlapping++;
+                  }
+                else if (corrected_overlap > 0)
+                  {
+                    lat = DR_T_RCD + DR_T_CAC + DR_T_PACKET - corrected_overlap;
+                    in_between_case++;
+                    partial_overlapping++;
+                  }
+                else
+                  {
+                    lat = DR_T_RCD + DR_T_CAC + DR_T_PACKET;
+                    worst_case++;
+                  }
+              }
+            else if ((lastCmdIsRead == cmdIsRead) && (!cmdIsRead)) /* WAW */
+              {
+                if (corrected_overlap > DR_T_RCD + DR_T_RTR  + DR_T_RP)
+                  {
+                    lat = - DR_T_CWD - 2 * DR_T_PACKET + DR_T_RTR;
+                    best_case++;
+                    full_overlapping++;
+                  }
+                else if (corrected_overlap > 0)
+                  {
+                    lat = DR_T_RCD + DR_T_CWD + DR_T_PACKET - corrected_overlap;
+                    in_between_case++;
+                    partial_overlapping++;
+                  }
+                else
+                  {
+                    lat = DR_T_RCD + DR_T_CWD + DR_T_PACKET;
+                    worst_case++;
+                  }
+              }
+            else if ((lastCmdIsRead != cmdIsRead) && (cmdIsRead)) /* RAW */
+              {
+                if (current_device == last_dev) /* same device */
+                  {
+                    if (corrected_overlap >  DR_T_RCD + DR_T_RP)
+                      {
+                        lat = DR_T_PACKET + DR_T_CAC - DR_T_RP;
+                        best_case++;
+                        partial_overlapping++;
+                      }
+                    else if (corrected_overlap > 0)
+                      {
+                        lat = DR_T_RCD + DR_T_CAC + DR_T_PACKET - corrected_overlap;
+                        in_between_case++;
+                        partial_overlapping++;
+                      }
+                    else
+                      {
+                        lat = DR_T_RCD + DR_T_CAC + DR_T_PACKET;
+                        worst_case++;
+                      }
+                  }
+                else /* other device */
+                  {
+                    if (corrected_overlap > DR_T_RCD + DR_T_RP + 2 * DR_T_PACKET)
+                      {
+                        lat = - DR_T_PACKET + DR_T_CAC - DR_T_RP;
+                        best_case++;
+                        partial_overlapping++;
+                      }
+                    else if (corrected_overlap > 0)
+                      {
+                        lat = DR_T_RCD + DR_T_CAC + DR_T_PACKET - corrected_overlap;
+                        in_between_case++;
+                        partial_overlapping++;
+                      }
+                    else
+                      {
+                        lat = DR_T_RCD + DR_T_CAC + DR_T_PACKET;
+                        worst_case++;
+                      }
+                  }
+              }
+            else /* WAR */
+              {
+                if (corrected_overlap > DR_T_RAS + DR_T_RP - 2 * DR_T_PACKET - (DR_T_CAC - DR_T_CWD))
+                  {
+                    lat = - DR_T_RAS + DR_T_RCD + DR_T_PACKET + DR_T_CAC;
+                    best_case++;
+                    full_overlapping++;
+                  }
+                else if (corrected_overlap > 0)
+                  {
+                    lat = DR_T_RCD + DR_T_CWD + DR_T_PACKET - corrected_overlap;
+                    in_between_case++;
+                    partial_overlapping++;
+                  }
+                else
+                  {
+                    lat = DR_T_RCD + DR_T_CWD + DR_T_PACKET;
+                    worst_case++;
+                  }
+              }
+          }
+
+        lat += chunks * DR_T_PACKET; /*every 128 bit need DR_NUM_CYCLES*/
+
+        /*fprintf(stderr,"%4d ",lat);debugging*/
+
+        if (cpu_ratio < 1.0)
+          {
+            lat = (lat+((int)(1/cpu_ratio)-1))/(int)(1/cpu_ratio);
+          }
+        else
+          {
+            temp = (int)(lat*cpu_ratio);
+            lat = (lat*cpu_ratio == temp)?temp:(temp+1); /*round up*/
+          }
+
+        lastCmdIsRead=cmdIsRead;
+        last_bank=current_bank;
+        last_dev = current_device;
+
+        /*fprintf(stderr,"%4d \n",lat);debugging*/
+
+        if (overlap <= 0) /*memory interface is not busy*/
+          {
+            busy_until[current_bank] = curTick+lat;
+          }
+        else/*the memory request will be satisfied temp cycles after curTick*/
+          {
+            busy_until[current_bank] +=lat;
+            command_overlapping++;
+            lat+=overlap;
+          }
+
+        /*fprintf(stderr,"%10.0f %10.0f %4d %4d \n",(double)busy_until, (double)curTick, overlap, lat);*/
+
+        if (cmdIsRead)
+          {
+            if (cpu_ratio < 1.0)
+              {
+                busy_until[current_bank] += abs(((DR_T_RAS - (DR_T_RCD + DR_T_PACKET + DR_T_CAC)) + 1)/((int)(1/cpu_ratio))); /* CPU clock cycles */
+              }
+            else
+              {
+                busy_until[current_bank] += (int) abs(((DR_T_RAS - (DR_T_RCD + DR_T_PACKET + DR_T_CAC)) + 1)*cpu_ratio); /* CPU clock cycles */
+              }
+          }
+         else /* !cmdIsRead */
+          {
+            if (cpu_ratio < 1.0)
+              {
+                busy_until[current_bank] += abs((-DR_T_PACKET + DR_T_RTR + DR_T_RP - DR_T_CWD + 1)/((int)(1/cpu_ratio))); /* CPU clock cycles */
+              }
+            else
+              {
+                busy_until[current_bank] += (int) abs((-DR_T_PACKET + DR_T_RTR + DR_T_RP - DR_T_CWD + 1)*cpu_ratio); /* CPU clock cycles */
+              }
+          }
+
+        // if((_cpu_num < num_cpus) && (_cpu_num >= 0))
+                // cout <<"cpu id = " << _cpu_num << "current_bank = " << current_bank << endl;
+    // bank_access_profile[_cpu_num][current_bank]++;
+        return lat;
+      }
+
+    /******************************************************************/
+
+    else if ((mem_type == "SDRAM") && (mem_actpolicy == "closed") && (memctrlpipe_enable == false))
+      /* SDRAM closed-page without overlap, 7/99 MG */
+      {
+        if (mem_access_output != NULL)
+          {
+            //fprintf(mem_accessfd,"\n");
+          }
+        assert(chunks >0);
+
+        if (cmdIsRead)
+          {
+            lat = act_lat + cas_lat;
+          }
+        else /* !cmdIsRead */
+          {
+            lat = act_lat;
+          }
+        total_access++;
+        lat += chunks;
+
+        overlap=(int)(busy_until[current_bank] - curTick);
+        lastCmdIsRead=cmdIsRead;
+
+        if (cpu_ratio < 1.0)
+          {
+            lat = (lat+((int)(1/cpu_ratio)-1))/(int)(1/cpu_ratio);
+          }
+        else
+          {
+            temp = (int)(lat*cpu_ratio);
+            lat = (lat*cpu_ratio == temp)?temp:(temp+1); /*round up*/
+          }
+
+        if (overlap <= 0) /*memory interface is not busy*/
+          {
+            busy_until[current_bank] = curTick+lat;
+          }
+        else/*the memory request will be satisfied temp cycles after curTick*/
+          {
+            busy_until[current_bank] +=lat;
+            command_overlapping++;
+            lat+=overlap;
+          }
+        if (!cmdIsRead)
+          {
+            temp = (int)(((dpl_lat-1) + pre_lat)*cpu_ratio);
+            busy_until[current_bank] += (((dpl_lat-1) + pre_lat)*cpu_ratio == temp)?temp:(temp+1);
+          }
+
+        // if((_cpu_num < num_cpus) && (_cpu_num >= 0))
+                // cout <<"cpu id = " << _cpu_num << "current_bank = " << current_bank << endl;
+    // bank_access_profile[_cpu_num][current_bank]++;
+        return lat;
+      }
+
+    /******************************************************************/
+
+    else if ((mem_type == "DRDRAM") && (mem_actpolicy == "closed") && (memctrlpipe_enable == false))
+      /* DRDRAM closed-page without overlap */
+      {
+        if (cmdIsRead)
+          {
+            lat = DR_T_RCD + DR_T_CAC + DR_T_PACKET; /*  DR_T_RP + */
+          }
+        else /* !cmdIsRead */
+          {
+            lat = DR_T_RCD + DR_T_CWD + DR_T_PACKET; /* DR_T_RP + */
+          }
+        total_access++;
+        overlap=(int)(busy_until[current_bank] - curTick);
+        lat += chunks * DR_T_PACKET; /*every 128 bit need DR_NUM_CYCLES*/
+
+        if (cpu_ratio < 1.0)
+          {
+            lat = (lat+((int)(1/cpu_ratio)-1))/(int)(1/cpu_ratio);
+          }
+        else
+          {
+            temp = (int)(lat*cpu_ratio);
+            lat = (lat*cpu_ratio == temp)?temp:(temp+1); /*round up*/
+          }
+
+        lastCmdIsRead=cmdIsRead;
+
+        if (overlap <= 0) /*memory interface is not busy*/
+          {
+            busy_until[current_bank] = curTick+lat;
+          }
+        else/*the memory request will be satisfied temp cycles after curTick*/
+          {
+            busy_until[current_bank] += lat;
+            command_overlapping++;
+            lat+=overlap;
+          }
+
+        if (cmdIsRead)
+          {
+            if (cpu_ratio < 1.0)
+              {
+                busy_until[current_bank] += abs(((DR_T_RAS - (DR_T_RCD + DR_T_PACKET + DR_T_CAC)) + 1)/((int)(1/cpu_ratio))); /* CPU clock cycles */
+              }
+            else
+              {
+                busy_until[current_bank] += (int) abs(((DR_T_RAS - (DR_T_RCD + DR_T_PACKET + DR_T_CAC)) + 1)*cpu_ratio); /* CPU clock cycles */
+              }
+          }
+         else /* !cmdIsRead */
+          {
+            if (cpu_ratio < 1.0)
+              {
+                busy_until[current_bank] += abs((-DR_T_PACKET + DR_T_RTR + DR_T_RP - DR_T_CWD + 1)/((int)(1/cpu_ratio))); /* CPU clock cycles */
+              }
+            else
+              {
+                busy_until[current_bank] += (int) abs((-DR_T_PACKET + DR_T_RTR + DR_T_RP - DR_T_CWD + 1)*cpu_ratio); /* CPU clock cycles */
+              }
+          }
+        // if((_cpu_num < num_cpus) && (_cpu_num >= 0))
+                // cout <<"cpu id = " << _cpu_num << "current_bank = " << current_bank << endl;
+    // bank_access_profile[_cpu_num][current_bank]++;
+        return lat;
+      }
+
+    /******************************************************************/
+
+    else /*STD*/
+      {
+        if (mem_access_output != NULL)
+          {
+            //fprintf(mem_accessfd,"\n");
+          }
+        assert(chunks >0);
+        // if((_cpu_num < num_cpus) && (_cpu_num >= 0))
+                // cout <<"cpu id = " << _cpu_num << "current_bank = " << current_bank << endl;
+    // bank_access_profile[_cpu_num][current_bank]++;
+        return(/* first chunk latency */act_lat +
+               (/* remainder chunk latency */cas_lat * (chunks - 1)));
+      }
+
+}
+
+/*end added by ar, MG*/
+
+/*begin added by ar, MG*/
+
+/* ================ helper functions ========================= */
+
+/****** DRDRAM specific: shared sense amplifiers ******/
+/* precharges the adjacent banks and returns the number of them (1 or 2)*/
+int /*number of precharged banks*/
+DRAMMemory::prechargeBanksAround(int bank)/*access to bank */
+{
+int temp;
+
+temp=bank%DR_BANK_SAMP;
+
+if (temp == 0) /*bank 0, 16,32 ....*/
+  {
+    if (active_row[bank+1]!=DR_NUM_ROWS)
+      {
+        precharge++;
+        active_row[bank+1]=DR_NUM_ROWS;
+      }
+  }
+else
+  {
+    if (temp==DR_BANK_SAMP-1)/*banks 15,31 ...*/
+      {
+        if (active_row[bank-1]!=DR_NUM_ROWS)
+          {
+            precharge++;
+            active_row[bank-1]=DR_NUM_ROWS;
+          }
+      }
+    else
+      {
+        if (active_row[bank-1]!=DR_NUM_ROWS)
+          {
+            precharge++;
+            active_row[bank-1]=DR_NUM_ROWS;
+          }
+        if (active_row[bank+1]!=DR_NUM_ROWS)
+          {
+            precharge++;
+            active_row[bank+1]=DR_NUM_ROWS;
+          }
+      }
+  }
+return precharge;
+}
+
+
+#ifndef DOXYGEN_SHOULD_SKIP_THIS
+
+BEGIN_DECLARE_SIM_OBJECT_PARAMS(DRAMMemory)
+
+    Param<std::string> file;
+    Param<Range<Addr> > range;
+    Param<Tick> latency;
+    /* additional params for dram protocol*/
+    Param<int> cpu_ratio;
+    Param<std::string> mem_type;
+    Param<std::string> mem_actpolicy;
+    Param<std::string> memctrladdr_type;
+    Param<int> bus_width;
+    Param<int> act_lat;
+    Param<int> cas_lat;
+    Param<int> war_lat;
+    Param<int> pre_lat;
+    Param<int> dpl_lat;
+    Param<int> trc_lat;
+    Param<int> num_banks;
+    Param<int> num_cpus;
+
+END_DECLARE_SIM_OBJECT_PARAMS(DRAMMemory)
+
+BEGIN_INIT_SIM_OBJECT_PARAMS(DRAMMemory)
+
+    INIT_PARAM_DFLT(file, "memory mapped file", ""),
+    INIT_PARAM(range, "Device Address Range"),
+    INIT_PARAM(latency, "Memory access latency"),
+
+    /* additional params for dram protocol*/
+    INIT_PARAM_DFLT(cpu_ratio,"ratio between CPU speed and memory bus speed",5),
+    INIT_PARAM_DFLT(mem_type,"type of DRAM","SDRAM"),
+    INIT_PARAM_DFLT(mem_actpolicy,"open / closed page policy","open"),
+    INIT_PARAM_DFLT(memctrladdr_type,"interleaved or direct mapping","interleaved"),
+    INIT_PARAM_DFLT(bus_width,"memory access bus width",16),
+    INIT_PARAM_DFLT(act_lat,"RAS to CAS delay",2),
+    INIT_PARAM_DFLT(cas_lat,"CAS delay",1),
+    INIT_PARAM_DFLT(war_lat,"write after read delay",2),
+    INIT_PARAM_DFLT(pre_lat,"precharge delay",2),
+    INIT_PARAM_DFLT(dpl_lat,"data in to precharge delay",2),
+    INIT_PARAM_DFLT(trc_lat,"row cycle delay",6),
+    INIT_PARAM_DFLT(num_banks,"Number of Banks",4),
+    INIT_PARAM_DFLT(num_cpus,"Number of CPUs connected to DRAM",4)
+
+END_INIT_SIM_OBJECT_PARAMS(DRAMMemory)
+
+CREATE_SIM_OBJECT(DRAMMemory)
+{
+    DRAMMemory::Params *p = new DRAMMemory::Params;
+    p->name = getInstanceName();
+    p->addrRange = range;
+    p->latency = latency;
+
+    /* additional params for dram */
+    p->cpu_ratio = cpu_ratio;
+    p->bus_width = bus_width;
+    p->mem_type = mem_type;
+    p->mem_actpolicy = mem_actpolicy;
+    p->memctrladdr_type = memctrladdr_type;
+    p->act_lat = act_lat;
+    p->cas_lat = cas_lat;
+    p->war_lat = war_lat;
+    p->pre_lat = pre_lat;
+    p->dpl_lat = dpl_lat;
+    p->trc_lat = trc_lat;
+    p->num_banks = num_banks;
+    p->num_cpus = num_cpus;
+
+    return new DRAMMemory(p);
+}
+
+REGISTER_SIM_OBJECT("DRAMMemory", DRAMMemory)
+
+#endif // DOXYGEN_SHOULD_SKIP_THIS
+
+
diff --git a/src/mem/dram.hh b/src/mem/dram.hh
new file mode 100644 (file)
index 0000000..32d1175
--- /dev/null
@@ -0,0 +1,172 @@
+/*
+ * Copyright (c) 2003-2004 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Authors: Ron Dreslinski
+ *          Ali Saidi
+ */
+
+/**
+ * @file
+ * Derrive a class from PhysicalMemory that support DRAM like timing access.
+ */
+#ifndef __MEM_DRAM_HH__
+#define __MEM_DRAM_HH__
+
+#include "base/statistics.hh"
+#include "mem/physical.hh"
+
+class DRAMMemory : public PhysicalMemory
+{
+  protected:
+    /* added for dram support */
+    const int cpu_ratio; // ratio between CPU speed and memory bus speed
+    const int bus_width;  // memory access bus width (in bytes)
+    /* memory access latency (<first_chunk> <inter_chunk>) */
+    const std::string mem_type;
+    const std::string mem_actpolicy;
+    const std::string memctrladdr_type;
+    const int act_lat;
+    const int cas_lat;
+    const int war_lat;
+    const int pre_lat;
+    const int dpl_lat;
+    const int trc_lat;
+    const int num_banks;
+    const int num_cpus;
+
+    int bank_size;
+    int num_rows;
+    int *active_row;
+    int last_bank;
+    int last_row;
+    Tick *busy_until;
+    int last_dev;
+    bool lastCmdIsRead;
+    int precharge;
+
+    /* memory access statistics */
+    int same_row_read_access;
+    int srr_after_read;
+    int srr_after_write;
+    int same_row_write_access;
+    int srw_after_read;
+    int srw_after_write;
+
+    int same_bank_read_access;
+    int sbr_after_read;
+    int sbr_after_write;
+    int same_bank_write_access;
+    int sbw_after_read;
+    int sbw_after_write;
+
+    int other_bank_read_access_hit;
+    int obr_after_read_hit;
+    int obr_after_write_hit;
+    int other_bank_write_access_hit;
+    int obw_after_read_hit;
+    int obw_after_write_hit;
+    // DR
+    // int other_bank_read_access_miss;
+    int obr_after_read_miss;
+    int obr_after_write_miss;
+    // DR
+    // int other_bank_write_access_miss;
+    int obw_after_read_miss;
+    int obw_after_write_miss;
+
+    int total_access;
+
+    int adjacent_access;
+    int adjacent_read;
+    int adjacent_write;
+    int command_overlapping;
+    int best_case;
+    int in_between_case;
+    int worst_case;
+    int full_overlapping;
+    int partial_overlapping;
+
+    int mem_access_details;
+    int memctrlpipe_enable;
+
+    Tick time_last_access;
+
+
+    Stats::Vector<> accesses;
+    Stats::Vector<> bytesRequested;
+    Stats::Vector<> bytesSent;
+    Stats::Vector<> compressedAccesses;
+
+    Stats::Vector<> cycles_nCKE;
+    Stats::Vector<> cycles_all_precharge_CKE;
+    Stats::Vector<> cycles_all_precharge_nCKE;
+    Stats::Vector<> cycles_bank_active_nCKE;
+    Stats::Vector<> cycles_avg_ACT;
+    Stats::Vector<> cycles_read_out;
+    Stats::Vector<> cycles_write_in;
+    Stats::Vector<> cycles_between_misses;
+    Stats::Vector<> other_bank_read_access_miss;
+    Stats::Vector<> other_bank_write_access_miss;
+    Stats::Scalar<> total_latency;
+    Stats::Scalar<> total_icache_req;
+    Stats::Scalar<> total_arb_latency;
+    Stats::Formula avg_latency;
+    Stats::Formula avg_arb_latency;
+    Stats::Vector2d<> bank_access_profile;
+
+
+  protected:
+    Tick calculateLatency(Packet *pkt);
+    int prechargeBanksAround(int bank);
+
+  public:
+    struct Params : public PhysicalMemory::Params
+    {
+        /* additional params for dram protocol*/
+        int cpu_ratio;
+        int bus_width;
+
+        std::string mem_type; /* DRDRAM, SDRAM */
+        std::string mem_actpolicy; /* closed, open */
+        std::string memctrladdr_type; /* interleaved, anythingelse */
+
+        int act_lat;
+        int cas_lat;
+        int war_lat;
+        int pre_lat;
+        int dpl_lat;
+        int trc_lat;
+        int num_banks;
+        int num_cpus;
+
+    };
+    virtual void regStats();
+    DRAMMemory(Params *p);
+};
+
+#endif// __MEM_DRAM_HH__
+
index 291c70d8c456b69a990a4fd56dff7fea850dc5dd..5eb89e1265f12858af2b739555a327eb8c4470ae 100644 (file)
@@ -54,25 +54,22 @@ using namespace std;
 using namespace TheISA;
 
 
-PhysicalMemory::PhysicalMemory(const string &n, Tick latency)
-    : MemObject(n),base_addr(0), pmem_addr(NULL), port(NULL), lat(latency)
+PhysicalMemory::PhysicalMemory(Params *p)
+    : MemObject(p->name), pmemAddr(NULL), port(NULL), lat(p->latency), _params(p)
 {
-    // Hardcoded to 128 MB for now.
-    pmem_size = 1 << 27;
-
-    if (pmem_size % TheISA::PageBytes != 0)
+    if (params()->addrRange.size() % TheISA::PageBytes != 0)
         panic("Memory Size not divisible by page size\n");
 
     int map_flags = MAP_ANON | MAP_PRIVATE;
-    pmem_addr = (uint8_t *)mmap(NULL, pmem_size, PROT_READ | PROT_WRITE,
+    pmemAddr = (uint8_t *)mmap(NULL, params()->addrRange.size(), PROT_READ | PROT_WRITE,
                                 map_flags, -1, 0);
 
-    if (pmem_addr == (void *)MAP_FAILED) {
+    if (pmemAddr == (void *)MAP_FAILED) {
         perror("mmap");
         fatal("Could not mmap!\n");
     }
 
-    page_ptr = 0;
+    pagePtr = 0;
 }
 
 void
@@ -85,18 +82,18 @@ PhysicalMemory::init()
 
 PhysicalMemory::~PhysicalMemory()
 {
-    if (pmem_addr)
-        munmap(pmem_addr, pmem_size);
+    if (pmemAddr)
+        munmap(pmemAddr, params()->addrRange.size());
     //Remove memPorts?
 }
 
 Addr
 PhysicalMemory::new_page()
 {
-    Addr return_addr = page_ptr << LogVMPageSize;
-    return_addr += base_addr;
+    Addr return_addr = pagePtr << LogVMPageSize;
+    return_addr += params()->addrRange.start;
 
-    ++page_ptr;
+    ++pagePtr;
     return return_addr;
 }
 
@@ -107,20 +104,25 @@ PhysicalMemory::deviceBlockSize()
     return 0;
 }
 
+Tick
+PhysicalMemory::calculateLatency(Packet *pkt)
+{
+    return lat;
+}
 
 Tick
 PhysicalMemory::doFunctionalAccess(Packet *pkt)
 {
-    assert(pkt->getAddr() + pkt->getSize() < pmem_size);
+    assert(pkt->getAddr() + pkt->getSize() < params()->addrRange.size());
 
     switch (pkt->cmd) {
       case Packet::ReadReq:
         memcpy(pkt->getPtr<uint8_t>(),
-               pmem_addr + pkt->getAddr() - base_addr,
+               pmemAddr + pkt->getAddr() - params()->addrRange.start,
                pkt->getSize());
         break;
       case Packet::WriteReq:
-        memcpy(pmem_addr + pkt->getAddr() - base_addr,
+        memcpy(pmemAddr + pkt->getAddr() - params()->addrRange.start,
                pkt->getPtr<uint8_t>(),
                pkt->getSize());
         // temporary hack: will need to add real LL/SC implementation
@@ -134,7 +136,7 @@ PhysicalMemory::doFunctionalAccess(Packet *pkt)
     }
 
     pkt->result = Packet::Success;
-    return lat;
+    return calculateLatency(pkt);
 }
 
 Port *
@@ -181,7 +183,7 @@ PhysicalMemory::getAddressRanges(AddrRangeList &resp, AddrRangeList &snoop)
 {
     snoop.clear();
     resp.clear();
-    resp.push_back(RangeSize(base_addr, pmem_size));
+    resp.push_back(RangeSize(params()->addrRange.start, params()->addrRange.size()));
 }
 
 int
@@ -232,7 +234,6 @@ PhysicalMemory::serialize(ostream &os)
     gzFile compressedMem;
     string filename = name() + ".physmem";
 
-    SERIALIZE_SCALAR(pmem_size);
     SERIALIZE_SCALAR(filename);
 
     // write memory file
@@ -248,7 +249,7 @@ PhysicalMemory::serialize(ostream &os)
         fatal("Insufficient memory to allocate compression state for %s\n",
                 filename);
 
-    if (gzwrite(compressedMem, pmem_addr, pmem_size) != pmem_size) {
+    if (gzwrite(compressedMem, pmemAddr, params()->addrRange.size()) != params()->addrRange.size()) {
         fatal("Write failed on physical memory checkpoint file '%s'\n",
               filename);
     }
@@ -269,12 +270,8 @@ PhysicalMemory::unserialize(Checkpoint *cp, const string &section)
     const int chunkSize = 16384;
 
 
-    // unmap file that was mmaped in the constructor
-    munmap(pmem_addr, pmem_size);
-
     string filename;
 
-    UNSERIALIZE_SCALAR(pmem_size);
     UNSERIALIZE_SCALAR(filename);
 
     filename = cp->cptDir + "/" + filename;
@@ -291,11 +288,15 @@ PhysicalMemory::unserialize(Checkpoint *cp, const string &section)
         fatal("Insufficient memory to allocate compression state for %s\n",
                 filename);
 
+    // unmap file that was mmaped in the constructor
+    // This is done here to make sure that gzip and open don't muck with our
+    // nice large space of memory before we reallocate it
+    munmap(pmemAddr, params()->addrRange.size());
 
-    pmem_addr = (uint8_t *)mmap(NULL, pmem_size, PROT_READ | PROT_WRITE,
+    pmemAddr = (uint8_t *)mmap(NULL, params()->addrRange.size(), PROT_READ | PROT_WRITE,
                                 MAP_ANON | MAP_PRIVATE, -1, 0);
 
-    if (pmem_addr == (void *)MAP_FAILED) {
+    if (pmemAddr == (void *)MAP_FAILED) {
         perror("mmap");
         fatal("Could not mmap physical memory!\n");
     }
@@ -306,19 +307,19 @@ PhysicalMemory::unserialize(Checkpoint *cp, const string &section)
         fatal("Unable to malloc memory to read file %s\n", filename);
 
     /* Only copy bytes that are non-zero, so we don't give the VM system hell */
-    while (curSize < pmem_size) {
+    while (curSize < params()->addrRange.size()) {
         bytesRead = gzread(compressedMem, tempPage, chunkSize);
-        if (bytesRead != chunkSize && bytesRead != pmem_size - curSize)
+        if (bytesRead != chunkSize && bytesRead != params()->addrRange.size() - curSize)
             fatal("Read failed on physical memory checkpoint file '%s'"
                   " got %d bytes, expected %d or %d bytes\n",
-                  filename, bytesRead, chunkSize, pmem_size-curSize);
+                  filename, bytesRead, chunkSize, params()->addrRange.size()-curSize);
 
         assert(bytesRead % sizeof(long) == 0);
 
         for (int x = 0; x < bytesRead/sizeof(long); x++)
         {
              if (*(tempPage+x) != 0) {
-                 pmem_current = (long*)(pmem_addr + curSize + x * sizeof(long));
+                 pmem_current = (long*)(pmemAddr + curSize + x * sizeof(long));
                  *pmem_current = *(tempPage+x);
              }
         }
@@ -352,8 +353,11 @@ END_INIT_SIM_OBJECT_PARAMS(PhysicalMemory)
 
 CREATE_SIM_OBJECT(PhysicalMemory)
 {
-
-    return new PhysicalMemory(getInstanceName(), latency);
+    PhysicalMemory::Params *p = new PhysicalMemory::Params;
+    p->name = getInstanceName();
+    p->addrRange = range;
+    p->latency = latency;
+    return new PhysicalMemory(p);
 }
 
 REGISTER_SIM_OBJECT("PhysicalMemory", PhysicalMemory)
index b549c1f8bc48537db0db83b00c90b47fc7eb5bba..c0a5523ba6c3518b77974ed956b52798dae37694 100644 (file)
@@ -80,19 +80,28 @@ class PhysicalMemory : public MemObject
     const PhysicalMemory &operator=(const PhysicalMemory &specmem);
 
   protected:
-    Addr base_addr;
-    Addr pmem_size;
-    uint8_t *pmem_addr;
+    uint8_t *pmemAddr;
     MemoryPort *port;
-    int page_ptr;
+    int pagePtr;
     Tick lat;
 
   public:
     Addr new_page();
-    uint64_t size() { return pmem_size; }
+    uint64_t size() { return params()->addrRange.size(); }
+
+    struct Params
+    {
+        std::string name;
+        Range<Addr> addrRange;
+        Tick latency;
+    };
+
+  protected:
+    Params *_params;
 
   public:
-    PhysicalMemory(const std::string &n, Tick latency);
+    const Params *params() const { return _params; }
+    PhysicalMemory(Params *p);
     virtual ~PhysicalMemory();
 
   public:
@@ -102,9 +111,9 @@ class PhysicalMemory : public MemObject
     void virtual init();
     unsigned int drain(Event *de);
 
-  private:
+  protected:
     Tick doFunctionalAccess(Packet *pkt);
-
+    virtual Tick calculateLatency(Packet *pkt);
     void recvStatusChange(Port::Status status);
 
   public:
index 9cc7510a285fd05b14b1ca50e970fbf7554960d5..f4818763fd25278840993f9519d78b17d852dd75 100644 (file)
@@ -7,3 +7,21 @@ class PhysicalMemory(MemObject):
     range = Param.AddrRange("Device Address")
     file = Param.String('', "memory mapped file")
     latency = Param.Latency(Parent.clock, "latency of an access")
+
+class DRAMMemory(PhysicalMemory):
+    type = 'DRAMMemory'
+    # Many of these should be observed from the configuration
+    cpu_ratio = Param.Int(5,"ratio between CPU speed and memory bus speed")
+    mem_type = Param.String("SDRAM", "Type of DRAM (DRDRAM, SDRAM)")
+    mem_actpolicy = Param.String("open", "Open/Close policy")
+    memctrladdr_type = Param.String("interleaved", "Mapping interleaved or direct")
+    bus_width = Param.Int(16, "")
+    act_lat = Param.Int(2, "RAS to CAS delay")
+    cas_lat = Param.Int(1, "CAS delay")
+    war_lat = Param.Int(2, "write after read delay")
+    pre_lat = Param.Int(2, "precharge delay")
+    dpl_lat = Param.Int(2, "data in to precharge delay")
+    trc_lat = Param.Int(6, "row cycle delay")
+    num_banks = Param.Int(4, "Number of Banks")
+    num_cpus = Param.Int(4, "Number of CPUs connected to DRAM")
+