mem: Fix DRAM controller to operate on its own address space
authorNikos Nikoleris <nikos.nikoleris@arm.com>
Thu, 12 Sep 2019 15:10:26 +0000 (16:10 +0100)
committerNikos Nikoleris <nikos.nikoleris@arm.com>
Tue, 29 Oct 2019 09:48:10 +0000 (09:48 +0000)
Typically, a memory controller is assigned an address range of the
form [start, end). This address range might be interleaved and
therefore only a non-continuous subset of the addresses in the address
range is handed by this controller.

Prior to this patch, the DRAM controller was unaware of the
interleaving and as a result the address range could affect the
mapping of addresses to DRAM ranks, rows and columns. This patch
changes the DRAM controller, to transform the input address to a
continuous range of the form [0, size). As a result the DRAM
controller always operates on a dense and continuous address range
regardlesss of the system configuration.

Change-Id: I7d273a630928421d1854658c9bb0ab34e9360851
Signed-off-by: Nikos Nikoleris <nikos.nikoleris@arm.com>
Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/19328
Reviewed-by: Daniel Carvalho <odanrc@yahoo.com.br>
Reviewed-by: Wendy Elsasser <wendy.elsasser@arm.com>
Reviewed-by: Jason Lowe-Power <jason@lowepower.com>
Maintainer: Jason Lowe-Power <jason@lowepower.com>
Tested-by: kokoro <noreply+kokoro@google.com>
configs/common/MemConfig.py
src/mem/DRAMCtrl.py
src/mem/dram_ctrl.cc
src/mem/dram_ctrl.hh

index 7f737761e229609b4667647888fca65c1601fc20..0b5011c36bb8b8e1f918b20c23244ad7cd6be1de 100644 (file)
@@ -66,10 +66,6 @@ def create_mem_ctrl(cls, r, i, nbr_mem_ctrls, intlv_bits, intlv_size):
 
     # Only do this for DRAMs
     if issubclass(cls, m5.objects.DRAMCtrl):
-        # Inform each controller how many channels to account
-        # for
-        ctrl.channels = nbr_mem_ctrls
-
         # If the channel bits are appearing after the column
         # bits, we need to add the appropriate number of bits
         # for the row buffer size
index 14db3d3c9d7bc775345a70a1a69c6dae8a728ab9..4ed4e50d11c0011b12d5b245bf2fcebd837a59c1 100644 (file)
@@ -1,4 +1,4 @@
-# Copyright (c) 2012-2018 ARM Limited
+# Copyright (c) 2012-2019 ARM Limited
 # All rights reserved.
 #
 # The license below extends only to copyright in the software and shall
@@ -130,10 +130,6 @@ class DRAMCtrl(QoSMemCtrl):
     # update per memory class when bank group architecture is supported
     bank_groups_per_rank = Param.Unsigned(0, "Number of bank groups per rank")
     banks_per_rank = Param.Unsigned("Number of banks per rank")
-    # only used for the address mapping as the controller by
-    # construction is a single channel and multiple controllers have
-    # to be instantiated for a multi-channel configuration
-    channels = Param.Unsigned(1, "Number of channels")
 
     # Enable DRAM powerdown states if True. This is False by default due to
     # performance being lower when enabled
index 37db27ce07974d0651923cca39d2c588716dd682..896247edc84bc49b628ec50eb2db7868bc408e64 100644 (file)
@@ -76,7 +76,7 @@ DRAMCtrl::DRAMCtrl(const DRAMCtrlParams* p) :
     ranksPerChannel(p->ranks_per_channel),
     bankGroupsPerRank(p->bank_groups_per_rank),
     bankGroupArch(p->bank_groups_per_rank > 0),
-    banksPerRank(p->banks_per_rank), channels(p->channels), rowsPerBank(0),
+    banksPerRank(p->banks_per_rank), rowsPerBank(0),
     readBufferSize(p->read_buffer_size),
     writeBufferSize(p->write_buffer_size),
     writeHighThreshold(writeBufferSize * p->write_high_thresh_perc / 100.0),
@@ -201,10 +201,6 @@ DRAMCtrl::init()
     // a bit of sanity checks on the interleaving, save it for here to
     // ensure that the system pointer is initialised
     if (range.interleaved()) {
-        if (channels != range.stripes())
-            fatal("%s has %d interleaved address stripes but %d channel(s)\n",
-                  name(), range.stripes(), channels);
-
         if (addrMapping == Enums::RoRaBaChCo) {
             if (rowBufferSize != range.granularity()) {
                 fatal("Channel interleaving of %s doesn't match RoRaBaChCo "
@@ -323,14 +319,11 @@ DRAMCtrl::decodeAddr(const PacketPtr pkt, Addr dramPktAddr, unsigned size,
 
     // we have removed the lowest order address bits that denote the
     // position within the column
-    if (addrMapping == Enums::RoRaBaChCo) {
+    if (addrMapping == Enums::RoRaBaChCo || addrMapping == Enums::RoRaBaCoCh) {
         // the lowest order bits denote the column to ensure that
         // sequential cache lines occupy the same row
         addr = addr / columnsPerRowBuffer;
 
-        // take out the channel part of the address
-        addr = addr / channels;
-
         // after the channel bits, get the bank bits to interleave
         // over the banks
         bank = addr % banksPerRank;
@@ -341,28 +334,6 @@ DRAMCtrl::decodeAddr(const PacketPtr pkt, Addr dramPktAddr, unsigned size,
         rank = addr % ranksPerChannel;
         addr = addr / ranksPerChannel;
 
-        // lastly, get the row bits, no need to remove them from addr
-        row = addr % rowsPerBank;
-    } else if (addrMapping == Enums::RoRaBaCoCh) {
-        // take out the lower-order column bits
-        addr = addr / columnsPerStripe;
-
-        // take out the channel part of the address
-        addr = addr / channels;
-
-        // next, the higher-order column bites
-        addr = addr / (columnsPerRowBuffer / columnsPerStripe);
-
-        // after the column bits, we get the bank bits to interleave
-        // over the banks
-        bank = addr % banksPerRank;
-        addr = addr / banksPerRank;
-
-        // after the bank, we get the rank bits which thus interleaves
-        // over the ranks
-        rank = addr % ranksPerChannel;
-        addr = addr / ranksPerChannel;
-
         // lastly, get the row bits, no need to remove them from addr
         row = addr % rowsPerBank;
     } else if (addrMapping == Enums::RoCoRaBaCh) {
@@ -372,11 +343,6 @@ DRAMCtrl::decodeAddr(const PacketPtr pkt, Addr dramPktAddr, unsigned size,
         // take out the lower-order column bits
         addr = addr / columnsPerStripe;
 
-        // take out the channel part of the address, not that this has
-        // to match with how accesses are interleaved between the
-        // controllers in the address mapping
-        addr = addr / channels;
-
         // start with the bank bits, as this provides the maximum
         // opportunity for parallelism between requests
         bank = addr % banksPerRank;
@@ -425,12 +391,13 @@ DRAMCtrl::addToReadQueue(PacketPtr pkt, unsigned int pktCount)
     // address of first DRAM packet is kept unaliged. Subsequent DRAM packets
     // are aligned to burst size boundaries. This is to ensure we accurately
     // check read packets against packets in write queue.
-    Addr addr = pkt->getAddr();
+    const Addr base_addr = getCtrlAddr(pkt->getAddr());
+    Addr addr = base_addr;
     unsigned pktsServicedByWrQ = 0;
     BurstHelper* burst_helper = NULL;
     for (int cnt = 0; cnt < pktCount; ++cnt) {
         unsigned size = std::min((addr | (burstSize - 1)) + 1,
-                        pkt->getAddr() + pkt->getSize()) - addr;
+                                 base_addr + pkt->getSize()) - addr;
         stats.readPktSize[ceilLog2(size)]++;
         stats.readBursts++;
         stats.masterReadAccesses[pkt->masterId()]++;
@@ -525,10 +492,11 @@ DRAMCtrl::addToWriteQueue(PacketPtr pkt, unsigned int pktCount)
 
     // if the request size is larger than burst size, the pkt is split into
     // multiple DRAM packets
-    Addr addr = pkt->getAddr();
+    const Addr base_addr = getCtrlAddr(pkt->getAddr());
+    Addr addr = base_addr;
     for (int cnt = 0; cnt < pktCount; ++cnt) {
         unsigned size = std::min((addr | (burstSize - 1)) + 1,
-                        pkt->getAddr() + pkt->getSize()) - addr;
+                                 base_addr + pkt->getSize()) - addr;
         stats.writePktSize[ceilLog2(size)]++;
         stats.writeBursts++;
         stats.masterWriteAccesses[pkt->masterId()]++;
index 8c8c24552fb4c69f7c8b228476369e2d5364a40c..ad2f051fbe909427b08124310eeb6985cbe17b40 100644 (file)
@@ -818,6 +818,20 @@ class DRAMCtrl : public QoS::MemCtrl
     DRAMPacket* decodeAddr(const PacketPtr pkt, Addr dramPktAddr,
                            unsigned int size, bool isRead) const;
 
+    /**
+     * Get an address in a dense range which starts from 0. The input
+     * address is the physical address of the request in an address
+     * space that contains other SimObjects apart from this
+     * controller.
+     *
+     * @param addr The intput address which should be in the addrRange
+     * @return An address in the continues range [0, max)
+     */
+    Addr getCtrlAddr(Addr addr)
+    {
+        return range.getOffset(addr);
+    }
+
     /**
      * The memory schduler/arbiter - picks which request needs to
      * go next, based on the specified policy such as FCFS or FR-FCFS
@@ -946,7 +960,6 @@ class DRAMCtrl : public QoS::MemCtrl
     const uint32_t bankGroupsPerRank;
     const bool bankGroupArch;
     const uint32_t banksPerRank;
-    const uint32_t channels;
     uint32_t rowsPerBank;
     const uint32_t readBufferSize;
     const uint32_t writeBufferSize;