ruby: Remove RubyMemoryControl and associated files
authorAndreas Hansson <andreas.hansson@arm.com>
Mon, 5 Dec 2016 21:49:07 +0000 (16:49 -0500)
committerAndreas Hansson <andreas.hansson@arm.com>
Mon, 5 Dec 2016 21:49:07 +0000 (16:49 -0500)
This patch removes the deprecated RubyMemoryControl. The DRAMCtrl
module should be used instead.

src/mem/ruby/SConscript
src/mem/ruby/profiler/MemCntrlProfiler.cc [deleted file]
src/mem/ruby/profiler/MemCntrlProfiler.hh [deleted file]
src/mem/ruby/profiler/SConscript
src/mem/ruby/structures/MemoryNode.cc [deleted file]
src/mem/ruby/structures/MemoryNode.hh [deleted file]
src/mem/ruby/structures/RubyMemoryControl.cc [deleted file]
src/mem/ruby/structures/RubyMemoryControl.hh [deleted file]
src/mem/ruby/structures/RubyMemoryControl.py [deleted file]
src/mem/ruby/structures/SConscript

index 82a16c9b05d9af000cbd5fefc2ae0a2d7859ca1f..88edb44a404dbe9ae9b9143e8f49fb169339fc6e 100644 (file)
@@ -42,7 +42,6 @@ DebugFlag('RubyCache')
 DebugFlag('RubyCacheTrace')
 DebugFlag('RubyDma')
 DebugFlag('RubyGenerated')
-DebugFlag('RubyMemory')
 DebugFlag('RubyNetwork')
 DebugFlag('RubyPort')
 DebugFlag('RubyPrefetcher')
@@ -56,7 +55,7 @@ DebugFlag('RubyResourceStalls')
 
 CompoundFlag('Ruby', [ 'RubyQueue', 'RubyNetwork', 'RubyTester',
     'RubyGenerated', 'RubySlicc', 'RubySystem', 'RubyCache',
-    'RubyMemory', 'RubyDma', 'RubyPort', 'RubySequencer', 'RubyCacheTrace',
+    'RubyDma', 'RubyPort', 'RubySequencer', 'RubyCacheTrace',
     'RubyPrefetcher'])
 
 if env['PROTOCOL'] == 'None':
diff --git a/src/mem/ruby/profiler/MemCntrlProfiler.cc b/src/mem/ruby/profiler/MemCntrlProfiler.cc
deleted file mode 100644 (file)
index 0cfc1e6..0000000
+++ /dev/null
@@ -1,266 +0,0 @@
-/*
- * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood
- * 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.
- */
-
-#include "mem/ruby/profiler/MemCntrlProfiler.hh"
-
-using namespace std;
-
-MemCntrlProfiler::MemCntrlProfiler(const string& description,
-    int banks_per_rank, int ranks_per_dimm, int dimms_per_channel)
-{
-    m_description = description;
-    m_banks_per_rank = banks_per_rank;
-    m_ranks_per_dimm = ranks_per_dimm;
-    m_dimms_per_channel = dimms_per_channel;
-}
-
-MemCntrlProfiler::~MemCntrlProfiler()
-{
-}
-
-void
-MemCntrlProfiler::profileMemReq(int bank)
-{
-    m_memReq++;
-    m_memBankCount[bank]++;
-}
-
-void
-MemCntrlProfiler::profileMemBankBusy()
-{
-    m_memBankBusy++;
-}
-
-void
-MemCntrlProfiler::profileMemBusBusy()
-{
-    m_memBusBusy++;
-}
-
-void
-MemCntrlProfiler::profileMemReadWriteBusy()
-{
-    m_memReadWriteBusy++;
-}
-
-void
-MemCntrlProfiler::profileMemDataBusBusy()
-{
-    m_memDataBusBusy++;
-}
-
-void
-MemCntrlProfiler::profileMemTfawBusy()
-{
-    m_memTfawBusy++;
-}
-
-void
-MemCntrlProfiler::profileMemRefresh()
-{
-    m_memRefresh++;
-}
-
-void
-MemCntrlProfiler::profileMemRead()
-{
-    m_memRead++;
-}
-
-void
-MemCntrlProfiler::profileMemWrite()
-{
-    m_memWrite++;
-}
-
-void
-MemCntrlProfiler::profileMemWaitCycles(int cycles)
-{
-    m_memWaitCycles += cycles;
-}
-
-void
-MemCntrlProfiler::profileMemInputQ(int cycles)
-{
-    m_memInputQ += cycles;
-}
-
-void
-MemCntrlProfiler::profileMemBankQ(int cycles)
-{
-    m_memBankQ += cycles;
-}
-
-void
-MemCntrlProfiler::profileMemArbWait(int cycles)
-{
-    m_memArbWait += cycles;
-}
-
-void
-MemCntrlProfiler::profileMemRandBusy()
-{
-    m_memRandBusy++;
-}
-
-void
-MemCntrlProfiler::profileMemNotOld()
-{
-    m_memNotOld++;
-}
-
-void
-MemCntrlProfiler::regStats()
-{
-    m_memReq
-        .name(m_description + ".memReq")
-        .desc("Total number of memory requests")
-        .flags(Stats::nozero)
-        ;
-
-    m_memRead
-        .name(m_description + ".memRead")
-        .desc("Number of memory reads")
-        .flags(Stats::nozero)
-        ;
-
-    m_memWrite
-        .name(m_description + ".memWrite")
-        .desc("Number of memory writes")
-        .flags(Stats::nozero)
-        ;
-
-    m_memRefresh
-        .name(m_description + ".memRefresh")
-        .desc("Number of memory refreshes")
-        .flags(Stats::nozero)
-        ;
-
-    m_memInputQ
-        .name(m_description + ".memInputQ")
-        .desc("Delay in the input queue")
-        .flags(Stats::nozero)
-        ;
-
-    m_memBankQ
-        .name(m_description + ".memBankQ")
-        .desc("Delay behind the head of the bank queue")
-        .flags(Stats::nozero)
-        ;
-
-    m_memWaitCycles
-        .name(m_description + ".memWaitCycles")
-        .desc("Delay stalled at the head of the bank queue")
-        .flags(Stats::nozero)
-        ;
-
-    m_totalStalls
-        .name(m_description + ".totalStalls")
-        .desc("Total number of stall cycles")
-        .flags(Stats::nozero)
-        ;
-
-    m_totalStalls = m_memInputQ + m_memBankQ + m_memWaitCycles;
-
-    m_stallsPerReq
-        .name(m_description + ".stallsPerReq")
-        .desc("Expected number of stall cycles per request")
-        .flags(Stats::nozero)
-        ;
-
-    m_stallsPerReq = m_totalStalls / m_memReq;
-
-    // Note: The following "memory stalls" entries are a breakdown of
-    // the cycles which already showed up in m_memWaitCycles.  The
-    // order is significant; it is the priority of attributing the
-    // cycles.  For example, bank_busy is before arbitration because
-    // if the bank was busy, we didn't even check arbitration.
-    // Note: "not old enough" means that since we grouped waiting
-    // heads-of-queues into batches to avoid starvation, a request in
-    // a newer batch didn't try to arbitrate yet because there are
-    // older requests waiting.
-    m_memBankBusy
-        .name(m_description + ".memBankBusy")
-        .desc("memory stalls due to busy bank")
-        .flags(Stats::nozero)
-        ;
-
-    m_memRandBusy
-        .name(m_description + ".memRandBusy")
-        .desc("memory stalls due to busy random")
-        .flags(Stats::nozero)
-        ;
-
-    m_memNotOld
-        .name(m_description + ".memNotOld")
-        .desc("memory stalls due to anti starvation")
-        .flags(Stats::nozero)
-        ;
-
-    m_memArbWait
-        .name(m_description + ".memArbWait")
-        .desc("memory stalls due to arbitration")
-        .flags(Stats::nozero)
-        ;
-
-    m_memBusBusy
-        .name(m_description + ".memBusBusy")
-        .desc("memory stalls due to busy bus")
-        .flags(Stats::nozero)
-        ;
-
-    m_memTfawBusy
-        .name(m_description + ".memTfawBusy")
-        .desc("memory stalls for Tfaw")
-        .flags(Stats::nozero)
-        ;
-
-    m_memReadWriteBusy
-        .name(m_description + ".memReadWriteBusy")
-        .desc("memory stalls due to read write turnaround")
-        .flags(Stats::nozero)
-        ;
-
-    m_memDataBusBusy
-        .name(m_description + ".memDataBusBusy")
-        .desc("memory stalls due to read read turnaround")
-        .flags(Stats::nozero)
-        ;
-
-    int totalBanks = m_banks_per_rank * m_ranks_per_dimm * m_dimms_per_channel;
-    m_memBankCount
-        .init(totalBanks)
-        .name(m_description + ".memBankCount")
-        .desc("Number of accesses per bank")
-        .flags(Stats::pdf | Stats::total|Stats::oneline)
-        ;
-    for (int i = 0; i < totalBanks; i++) {
-        m_memBankCount.subname(i, "");
-    }
-}
-
diff --git a/src/mem/ruby/profiler/MemCntrlProfiler.hh b/src/mem/ruby/profiler/MemCntrlProfiler.hh
deleted file mode 100644 (file)
index 56e283f..0000000
+++ /dev/null
@@ -1,106 +0,0 @@
-/*
- * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood
- * 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.
- */
-
-#ifndef __MEM_RUBY_PROFILER_MEMCNTRLPROFILER_HH__
-#define __MEM_RUBY_PROFILER_MEMCNTRLPROFILER_HH__
-
-#include <iostream>
-#include <string>
-#include <vector>
-
-#include "base/statistics.hh"
-#include "mem/ruby/common/TypeDefines.hh"
-
-class MemCntrlProfiler
-{
-  public:
-    MemCntrlProfiler(const std::string& description, int banks_per_rank,
-                     int ranks_per_dimm, int dimms_per_channel);
-    ~MemCntrlProfiler();
-
-    void regStats();
-
-    void profileMemReq(int bank);
-    void profileMemBankBusy();
-    void profileMemBusBusy();
-    void profileMemTfawBusy();
-    void profileMemReadWriteBusy();
-    void profileMemDataBusBusy();
-    void profileMemRefresh();
-    void profileMemRead();
-    void profileMemWrite();
-    void profileMemWaitCycles(int cycles);
-    void profileMemInputQ(int cycles);
-    void profileMemBankQ(int cycles);
-    void profileMemArbWait(int cycles);
-    void profileMemRandBusy();
-    void profileMemNotOld();
-
-    void print(std::ostream& out) const;
-
-private:
-    // Private copy constructor and assignment operator
-    MemCntrlProfiler(const MemCntrlProfiler& obj);
-    MemCntrlProfiler& operator=(const MemCntrlProfiler& obj);
-
-    std::string m_description;
-    Stats::Scalar m_memReq;
-    Stats::Scalar m_memRead;
-    Stats::Scalar m_memWrite;
-    Stats::Scalar m_memRefresh;
-
-    Stats::Scalar m_memWaitCycles;
-    Stats::Scalar m_memInputQ;
-    Stats::Scalar m_memBankQ;
-    Stats::Formula m_totalStalls;
-    Stats::Formula m_stallsPerReq;
-
-    Stats::Scalar m_memBankBusy;
-    Stats::Scalar m_memBusBusy;
-    Stats::Scalar m_memTfawBusy;
-    Stats::Scalar m_memReadWriteBusy;
-    Stats::Scalar m_memDataBusBusy;
-    Stats::Scalar m_memArbWait;
-    Stats::Scalar m_memRandBusy;
-    Stats::Scalar m_memNotOld;
-    Stats::Vector m_memBankCount;
-
-    int m_banks_per_rank;
-    int m_ranks_per_dimm;
-    int m_dimms_per_channel;
-};
-
-inline std::ostream&
-operator<<(std::ostream& out, const MemCntrlProfiler& obj)
-{
-    obj.print(out);
-    out << std::flush;
-    return out;
-}
-
-#endif // __MEM_RUBY_PROFILER_MEMCNTRLPROFILER_HH__
index d1e9972e45c983874002a9dc26f2311331519c15..783dc78db344b9dfaf5f1b2baa30f8ac5c8be47d 100644 (file)
@@ -35,6 +35,5 @@ if env['PROTOCOL'] == 'None':
 
 Source('AccessTraceForAddress.cc')
 Source('AddressProfiler.cc')
-Source('MemCntrlProfiler.cc')
 Source('Profiler.cc')
 Source('StoreTrace.cc')
diff --git a/src/mem/ruby/structures/MemoryNode.cc b/src/mem/ruby/structures/MemoryNode.cc
deleted file mode 100644 (file)
index 1e68cc4..0000000
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Copyright (c) 1999 Mark D. Hill and David A. Wood
- * 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.
- */
-
-#include "mem/ruby/structures/MemoryNode.hh"
-
-using namespace std;
-
-void
-MemoryNode::print(ostream& out) const
-{
-    out << "[";
-    out << m_time << ", ";
-    out << m_msg_counter << ", ";
-    out << pkt << "; ";
-    out << "]";
-}
diff --git a/src/mem/ruby/structures/MemoryNode.hh b/src/mem/ruby/structures/MemoryNode.hh
deleted file mode 100644 (file)
index 558457e..0000000
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * Copyright (c) 2008 Mark D. Hill and David A. Wood
- * 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.
- */
-
-/*
- * Description:
- * This structure records everything known about a single
- * memory request that is queued in the memory controller.
- * It is created when the memory request first arrives
- * at a memory controller and is deleted when the underlying
- * message is enqueued to be sent back to the directory.
- */
-
-#ifndef __MEM_RUBY_STRUCTURES_MEMORYNODE_HH__
-#define __MEM_RUBY_STRUCTURES_MEMORYNODE_HH__
-
-#include <iostream>
-
-#include "mem/ruby/common/TypeDefines.hh"
-#include "mem/ruby/slicc_interface/Message.hh"
-
-class MemoryNode
-{
-  public:
-    // old constructor
-    MemoryNode(const Cycles& time, int counter, const PacketPtr p,
-               Addr addr, const bool is_mem_read)
-        : m_time(time), pkt(p)
-    {
-        m_msg_counter = counter;
-        m_addr = addr;
-        m_is_mem_read = is_mem_read;
-        m_is_dirty_wb = !is_mem_read;
-    }
-
-    // new constructor
-    MemoryNode(const Cycles& time, const PacketPtr p,
-               Addr addr, const bool is_mem_read,
-               const bool is_dirty_wb)
-        : m_time(time), pkt(p)
-    {
-        m_msg_counter = 0;
-        m_addr = addr;
-        m_is_mem_read = is_mem_read;
-        m_is_dirty_wb = is_dirty_wb;
-    }
-
-    void print(std::ostream& out) const;
-
-    Cycles m_time;
-    int m_msg_counter;
-    PacketPtr pkt;
-    Addr m_addr;
-    bool m_is_mem_read;
-    bool m_is_dirty_wb;
-};
-
-inline std::ostream&
-operator<<(std::ostream& out, const MemoryNode& obj)
-{
-    obj.print(out);
-    out << std::flush;
-    return out;
-}
-
-#endif // __MEM_RUBY_STRUCTURES_MEMORYNODE_HH__
diff --git a/src/mem/ruby/structures/RubyMemoryControl.cc b/src/mem/ruby/structures/RubyMemoryControl.cc
deleted file mode 100644 (file)
index 095b2e3..0000000
+++ /dev/null
@@ -1,802 +0,0 @@
-/*
- * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood
- * Copyright (c) 2012 Advanced Micro Devices, Inc.
- * 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.
- */
-
-/*
- * Description:  This module simulates a basic DDR-style memory controller
- * (and can easily be extended to do FB-DIMM as well).
- *
- * This module models a single channel, connected to any number of
- * DIMMs with any number of ranks of DRAMs each.  If you want multiple
- * address/data channels, you need to instantiate multiple copies of
- * this module.
- *
- * Each memory request is placed in a queue associated with a specific
- * memory bank.  This queue is of finite size; if the queue is full
- * the request will back up in an (infinite) common queue and will
- * effectively throttle the whole system.  This sort of behavior is
- * intended to be closer to real system behavior than if we had an
- * infinite queue on each bank.  If you want the latter, just make
- * the bank queues unreasonably large.
- *
- * The head item on a bank queue is issued when all of the
- * following are true:
- *   the bank is available
- *   the address path to the DIMM is available
- *   the data path to or from the DIMM is available
- *
- * Note that we are not concerned about fixed offsets in time.  The bank
- * will not be used at the same moment as the address path, but since
- * there is no queue in the DIMM or the DRAM it will be used at a constant
- * number of cycles later, so it is treated as if it is used at the same
- * time.
- *
- * We are assuming closed bank policy; that is, we automatically close
- * each bank after a single read or write.  Adding an option for open
- * bank policy is for future work.
- *
- * We are assuming "posted CAS"; that is, we send the READ or WRITE
- * immediately after the ACTIVATE.  This makes scheduling the address
- * bus trivial; we always schedule a fixed set of cycles.  For DDR-400,
- * this is a set of two cycles; for some configurations such as
- * DDR-800 the parameter tRRD forces this to be set to three cycles.
- *
- * We assume a four-bit-time transfer on the data wires.  This is
- * the minimum burst length for DDR-2.  This would correspond
- * to (for example) a memory where each DIMM is 72 bits wide
- * and DIMMs are ganged in pairs to deliver 64 bytes at a shot.
- * This gives us the same occupancy on the data wires as on the
- * address wires (for the two-address-cycle case).
- *
- * The only non-trivial scheduling problem is the data wires.
- * A write will use the wires earlier in the operation than a read
- * will; typically one cycle earlier as seen at the DRAM, but earlier
- * by a worst-case round-trip wire delay when seen at the memory controller.
- * So, while reads from one rank can be scheduled back-to-back
- * every two cycles, and writes (to any rank) scheduled every two cycles,
- * when a read is followed by a write we need to insert a bubble.
- * Furthermore, consecutive reads from two different ranks may need
- * to insert a bubble due to skew between when one DRAM stops driving the
- * wires and when the other one starts.  (These bubbles are parameters.)
- *
- * This means that when some number of reads and writes are at the
- * heads of their queues, reads could starve writes, and/or reads
- * to the same rank could starve out other requests, since the others
- * would never see the data bus ready.
- * For this reason, we have implemented an anti-starvation feature.
- * A group of requests is marked "old", and a counter is incremented
- * each cycle as long as any request from that batch has not issued.
- * if the counter reaches twice the bank busy time, we hold off any
- * newer requests until all of the "old" requests have issued.
- *
- * We also model tFAW.  This is an obscure DRAM parameter that says
- * that no more than four activate requests can happen within a window
- * of a certain size.  For most configurations this does not come into play,
- * or has very little effect, but it could be used to throttle the power
- * consumption of the DRAM.  In this implementation (unlike in a DRAM
- * data sheet) TFAW is measured in memory bus cycles; i.e. if TFAW = 16
- * then no more than four activates may happen within any 16 cycle window.
- * Refreshes are included in the activates.
- *
- */
-
-#include "base/cast.hh"
-#include "base/cprintf.hh"
-#include "base/random.hh"
-#include "debug/RubyMemory.hh"
-#include "mem/ruby/common/Address.hh"
-#include "mem/ruby/profiler/Profiler.hh"
-#include "mem/ruby/slicc_interface/Message.hh"
-#include "mem/ruby/slicc_interface/RubySlicc_ComponentMapping.hh"
-#include "mem/ruby/structures/RubyMemoryControl.hh"
-#include "mem/ruby/system/RubySystem.hh"
-
-using namespace std;
-
-// Value to reset watchdog timer to.
-// If we're idle for this many memory control cycles,
-// shut down our clock (our rescheduling of ourselves).
-// Refresh shuts down as well.
-// When we restart, we'll be in a different phase
-// with respect to ruby cycles, so this introduces
-// a slight inaccuracy.  But it is necessary or the
-// ruby tester never terminates because the event
-// queue is never empty.
-#define IDLECOUNT_MAX_VALUE 1000
-
-// Output operator definition
-
-ostream&
-operator<<(ostream& out, const RubyMemoryControl& obj)
-{
-    obj.print(out);
-    out << flush;
-    return out;
-}
-
-
-// ****************************************************************
-
-// CONSTRUCTOR
-RubyMemoryControl::RubyMemoryControl(const Params *p)
-    : AbstractMemory(p), Consumer(this), port(name() + ".port", *this),
-      m_event(this)
-{
-    m_banks_per_rank = p->banks_per_rank;
-    m_ranks_per_dimm = p->ranks_per_dimm;
-    m_dimms_per_channel = p->dimms_per_channel;
-    m_bank_bit_0 = p->bank_bit_0;
-    m_rank_bit_0 = p->rank_bit_0;
-    m_dimm_bit_0 = p->dimm_bit_0;
-    m_bank_queue_size = p->bank_queue_size;
-    m_bank_busy_time = p->bank_busy_time;
-    m_rank_rank_delay = p->rank_rank_delay;
-    m_read_write_delay = p->read_write_delay;
-    m_basic_bus_busy_time = p->basic_bus_busy_time;
-    m_mem_ctl_latency = p->mem_ctl_latency;
-    m_refresh_period = p->refresh_period;
-    m_tFaw = p->tFaw;
-    m_mem_random_arbitrate = p->mem_random_arbitrate;
-    m_mem_fixed_delay = p->mem_fixed_delay;
-
-    m_profiler_ptr = new MemCntrlProfiler(name(),
-                                          m_banks_per_rank,
-                                          m_ranks_per_dimm,
-                                          m_dimms_per_channel);
-
-    warn("RubyMemoryControl is deprecated, use a DRAMCtrl subclass instead\n");
-}
-
-void
-RubyMemoryControl::init()
-{
-    m_msg_counter = 0;
-    assert(m_tFaw <= 62); // must fit in a uint64_t shift register
-
-    m_total_banks = m_banks_per_rank * m_ranks_per_dimm * m_dimms_per_channel;
-    m_total_ranks = m_ranks_per_dimm * m_dimms_per_channel;
-    m_refresh_period_system = m_refresh_period / m_total_banks;
-
-    m_bankQueues = new list<MemoryNode *> [m_total_banks];
-    assert(m_bankQueues);
-
-    m_bankBusyCounter = new int [m_total_banks];
-    assert(m_bankBusyCounter);
-
-    m_oldRequest = new int [m_total_banks];
-    assert(m_oldRequest);
-
-    for (int i = 0; i < m_total_banks; i++) {
-        m_bankBusyCounter[i] = 0;
-        m_oldRequest[i] = 0;
-    }
-
-    m_busBusyCounter_Basic = 0;
-    m_busBusyCounter_Write = 0;
-    m_busBusyCounter_ReadNewRank = 0;
-    m_busBusy_WhichRank = 0;
-
-    m_roundRobin = 0;
-    m_refresh_count = 1;
-    m_need_refresh = 0;
-    m_refresh_bank = 0;
-    m_idleCount = 0;
-    m_ageCounter = 0;
-
-    // Each tfaw shift register keeps a moving bit pattern
-    // which shows when recent activates have occurred.
-    // m_tfaw_count keeps track of how many 1 bits are set
-    // in each shift register.  When m_tfaw_count is >= 4,
-    // new activates are not allowed.
-    m_tfaw_shift = new uint64_t[m_total_ranks];
-    m_tfaw_count = new int[m_total_ranks];
-    for (int i = 0; i < m_total_ranks; i++) {
-        m_tfaw_shift[i] = 0;
-        m_tfaw_count[i] = 0;
-    }
-}
-
-BaseSlavePort&
-RubyMemoryControl::getSlavePort(const string &if_name, PortID idx)
-{
-    if (if_name != "port") {
-        return MemObject::getSlavePort(if_name, idx);
-    } else {
-        return port;
-    }
-}
-
-void
-RubyMemoryControl::reset()
-{
-    m_msg_counter = 0;
-
-    assert(m_tFaw <= 62); // must fit in a uint64_t shift register
-
-    m_total_banks = m_banks_per_rank * m_ranks_per_dimm * m_dimms_per_channel;
-    m_total_ranks = m_ranks_per_dimm * m_dimms_per_channel;
-    m_refresh_period_system = m_refresh_period / m_total_banks;
-
-    assert(m_bankQueues);
-
-    assert(m_bankBusyCounter);
-
-    assert(m_oldRequest);
-
-    for (int i = 0; i < m_total_banks; i++) {
-        m_bankBusyCounter[i] = 0;
-        m_oldRequest[i] = 0;
-    }
-
-    m_busBusyCounter_Basic = 0;
-    m_busBusyCounter_Write = 0;
-    m_busBusyCounter_ReadNewRank = 0;
-    m_busBusy_WhichRank = 0;
-
-    m_roundRobin = 0;
-    m_refresh_count = 1;
-    m_need_refresh = 0;
-    m_refresh_bank = 0;
-    m_idleCount = 0;
-    m_ageCounter = 0;
-
-    // Each tfaw shift register keeps a moving bit pattern
-    // which shows when recent activates have occurred.
-    // m_tfaw_count keeps track of how many 1 bits are set
-    // in each shift register.  When m_tfaw_count is >= 4,
-    // new activates are not allowed.
-    for (int i = 0; i < m_total_ranks; i++) {
-        m_tfaw_shift[i] = 0;
-        m_tfaw_count[i] = 0;
-    }
-}
-
-RubyMemoryControl::~RubyMemoryControl()
-{
-    delete [] m_bankQueues;
-    delete [] m_bankBusyCounter;
-    delete [] m_oldRequest;
-    delete m_profiler_ptr;
-}
-
-// enqueue new request from directory
-bool
-RubyMemoryControl::recvTimingReq(PacketPtr pkt)
-{
-    Cycles arrival_time = curCycle();
-    Addr addr = pkt->getAddr();
-    bool is_mem_read = pkt->isRead();
-
-    access(pkt);
-    MemoryNode *thisReq = new MemoryNode(arrival_time, pkt, addr,
-                                         is_mem_read, !is_mem_read);
-    enqueueMemRef(thisReq);
-    return true;
-}
-
-// Alternate entry point used when we already have a MemoryNode
-// structure built.
-void
-RubyMemoryControl::enqueueMemRef(MemoryNode *memRef)
-{
-    m_msg_counter++;
-    memRef->m_msg_counter = m_msg_counter;
-    Addr addr = memRef->m_addr;
-    int bank = getBank(addr);
-
-    m_profiler_ptr->profileMemReq(bank);
-    m_input_queue.push_back(memRef);
-
-    if (!m_event.scheduled()) {
-        schedule(m_event, clockEdge());
-    }
-}
-
-void
-RubyMemoryControl::print(ostream& out) const
-{
-}
-
-// Queue up a completed request to send back to directory
-void
-RubyMemoryControl::enqueueToDirectory(MemoryNode *req, Cycles latency)
-{
-    Tick arrival_time = clockEdge(latency);
-    PacketPtr pkt = req->pkt;
-
-    // access already turned the packet into a response
-    assert(pkt->isResponse());
-
-    // queue the packet in the response queue to be sent out after
-    // the static latency has passed
-    port.schedTimingResp(pkt, arrival_time);
-
-    DPRINTF(RubyMemory, "Enqueueing msg %#08x %c back to directory at %15d\n",
-            req->m_addr, req->m_is_mem_read ? 'R':'W', arrival_time);
-}
-
-// getBank returns an integer that is unique for each
-// bank across this memory controller.
-int
-RubyMemoryControl::getBank(const Addr addr) const
-{
-    int dimm = (addr >> m_dimm_bit_0) & (m_dimms_per_channel - 1);
-    int rank = (addr >> m_rank_bit_0) & (m_ranks_per_dimm - 1);
-    int bank = (addr >> m_bank_bit_0) & (m_banks_per_rank - 1);
-    return (dimm * m_ranks_per_dimm * m_banks_per_rank)
-        + (rank * m_banks_per_rank)
-        + bank;
-}
-
-int
-RubyMemoryControl::getRank(const Addr addr) const
-{
-    int bank = getBank(addr);
-    int rank = (bank / m_banks_per_rank);
-    assert (rank < (m_ranks_per_dimm * m_dimms_per_channel));
-    return rank;
-}
-
-// getRank returns an integer that is unique for each rank
-// and independent of individual bank.
-int
-RubyMemoryControl::getRank(int bank) const
-{
-    int rank = (bank / m_banks_per_rank);
-    assert (rank < (m_ranks_per_dimm * m_dimms_per_channel));
-    return rank;
-}
-
-// Not used!
-int
-RubyMemoryControl::getChannel(const Addr addr) const
-{
-    assert(false);
-    return -1;
-}
-
-// Not used!
-int
-RubyMemoryControl::getRow(const Addr addr) const
-{
-    assert(false);
-    return -1;
-}
-
-// queueReady determines if the head item in a bank queue
-// can be issued this cycle
-bool
-RubyMemoryControl::queueReady(int bank)
-{
-    if ((m_bankBusyCounter[bank] > 0) && !m_mem_fixed_delay) {
-        m_profiler_ptr->profileMemBankBusy();
-
-        DPRINTF(RubyMemory, "bank %x busy %d\n", bank, m_bankBusyCounter[bank]);
-        return false;
-    }
-
-    if (m_mem_random_arbitrate >= 2) {
-        if (random_mt.random(0, 100) < m_mem_random_arbitrate) {
-            m_profiler_ptr->profileMemRandBusy();
-            return false;
-        }
-    }
-
-    if (m_mem_fixed_delay)
-        return true;
-
-    if ((m_ageCounter > (2 * m_bank_busy_time)) && !m_oldRequest[bank]) {
-        m_profiler_ptr->profileMemNotOld();
-        return false;
-    }
-
-    if (m_busBusyCounter_Basic == m_basic_bus_busy_time) {
-        // Another bank must have issued this same cycle.  For
-        // profiling, we count this as an arb wait rather than a bus
-        // wait.  This is a little inaccurate since it MIGHT have also
-        // been blocked waiting for a read-write or a read-read
-        // instead, but it's pretty close.
-        m_profiler_ptr->profileMemArbWait(1);
-        return false;
-    }
-
-    if (m_busBusyCounter_Basic > 0) {
-        m_profiler_ptr->profileMemBusBusy();
-        return false;
-    }
-
-    int rank = getRank(bank);
-    if (m_tfaw_count[rank] >= ACTIVATE_PER_TFAW) {
-        m_profiler_ptr->profileMemTfawBusy();
-        return false;
-    }
-
-    bool write = !m_bankQueues[bank].front()->m_is_mem_read;
-    if (write && (m_busBusyCounter_Write > 0)) {
-        m_profiler_ptr->profileMemReadWriteBusy();
-        return false;
-    }
-
-    if (!write && (rank != m_busBusy_WhichRank)
-        && (m_busBusyCounter_ReadNewRank > 0)) {
-        m_profiler_ptr->profileMemDataBusBusy();
-        return false;
-    }
-
-    return true;
-}
-
-// issueRefresh checks to see if this bank has a refresh scheduled
-// and, if so, does the refresh and returns true
-bool
-RubyMemoryControl::issueRefresh(int bank)
-{
-    if (!m_need_refresh || (m_refresh_bank != bank))
-        return false;
-    if (m_bankBusyCounter[bank] > 0)
-        return false;
-    // Note that m_busBusyCounter will prevent multiple issues during
-    // the same cycle, as well as on different but close cycles:
-    if (m_busBusyCounter_Basic > 0)
-        return false;
-    int rank = getRank(bank);
-    if (m_tfaw_count[rank] >= ACTIVATE_PER_TFAW)
-        return false;
-
-    // Issue it:
-    DPRINTF(RubyMemory, "Refresh bank %3x\n", bank);
-
-    m_profiler_ptr->profileMemRefresh();
-    m_need_refresh--;
-    m_refresh_bank++;
-    if (m_refresh_bank >= m_total_banks)
-        m_refresh_bank = 0;
-    m_bankBusyCounter[bank] = m_bank_busy_time;
-    m_busBusyCounter_Basic = m_basic_bus_busy_time;
-    m_busBusyCounter_Write = m_basic_bus_busy_time;
-    m_busBusyCounter_ReadNewRank = m_basic_bus_busy_time;
-    markTfaw(rank);
-    return true;
-}
-
-// Mark the activate in the tFaw shift register
-void
-RubyMemoryControl::markTfaw(int rank)
-{
-    if (m_tFaw) {
-        m_tfaw_shift[rank] |= (1 << (m_tFaw-1));
-        m_tfaw_count[rank]++;
-    }
-}
-
-// Issue a memory request: Activate the bank, reserve the address and
-// data buses, and queue the request for return to the requesting
-// processor after a fixed latency.
-void
-RubyMemoryControl::issueRequest(int bank)
-{
-    int rank = getRank(bank);
-    MemoryNode *req = m_bankQueues[bank].front();
-    m_bankQueues[bank].pop_front();
-
-    DPRINTF(RubyMemory, "Mem issue request%7d: %#08x %c "
-            "bank=%3x sched %c\n", req->m_msg_counter, req->m_addr,
-            req->m_is_mem_read? 'R':'W',
-            bank, m_event.scheduled() ? 'Y':'N');
-
-    enqueueToDirectory(req, Cycles(m_mem_ctl_latency + m_mem_fixed_delay));
-
-    m_oldRequest[bank] = 0;
-    markTfaw(rank);
-    m_bankBusyCounter[bank] = m_bank_busy_time;
-    m_busBusy_WhichRank = rank;
-    if (req->m_is_mem_read) {
-        m_profiler_ptr->profileMemRead();
-        m_busBusyCounter_Basic = m_basic_bus_busy_time;
-        m_busBusyCounter_Write = m_basic_bus_busy_time + m_read_write_delay;
-        m_busBusyCounter_ReadNewRank =
-            m_basic_bus_busy_time + m_rank_rank_delay;
-    } else {
-        m_profiler_ptr->profileMemWrite();
-        m_busBusyCounter_Basic = m_basic_bus_busy_time;
-        m_busBusyCounter_Write = m_basic_bus_busy_time;
-        m_busBusyCounter_ReadNewRank = m_basic_bus_busy_time;
-    }
-
-    delete req;
-}
-
-// executeCycle:  This function is called once per memory clock cycle
-// to simulate all the periodic hardware.
-void
-RubyMemoryControl::executeCycle()
-{
-    // Keep track of time by counting down the busy counters:
-    for (int bank=0; bank < m_total_banks; bank++) {
-        if (m_bankBusyCounter[bank] > 0) m_bankBusyCounter[bank]--;
-    }
-    if (m_busBusyCounter_Write > 0)
-        m_busBusyCounter_Write--;
-    if (m_busBusyCounter_ReadNewRank > 0)
-        m_busBusyCounter_ReadNewRank--;
-    if (m_busBusyCounter_Basic > 0)
-        m_busBusyCounter_Basic--;
-
-    // Count down the tFAW shift registers:
-    for (int rank=0; rank < m_total_ranks; rank++) {
-        if (m_tfaw_shift[rank] & 1) m_tfaw_count[rank]--;
-        m_tfaw_shift[rank] >>= 1;
-    }
-
-    // After time period expires, latch an indication that we need a refresh.
-    // Disable refresh if in mem_fixed_delay mode.
-    if (!m_mem_fixed_delay) m_refresh_count--;
-    if (m_refresh_count == 0) {
-        m_refresh_count = m_refresh_period_system;
-
-        // Are we overrunning our ability to refresh?
-        assert(m_need_refresh < 10);
-        m_need_refresh++;
-    }
-
-    // If this batch of requests is all done, make a new batch:
-    m_ageCounter++;
-    int anyOld = 0;
-    for (int bank=0; bank < m_total_banks; bank++) {
-        anyOld |= m_oldRequest[bank];
-    }
-    if (!anyOld) {
-        for (int bank=0; bank < m_total_banks; bank++) {
-            if (!m_bankQueues[bank].empty()) m_oldRequest[bank] = 1;
-        }
-        m_ageCounter = 0;
-    }
-
-    // If randomness desired, re-randomize round-robin position each cycle
-    if (m_mem_random_arbitrate) {
-        m_roundRobin = random_mt.random(0, m_total_banks - 1);
-    }
-
-    // For each channel, scan round-robin, and pick an old, ready
-    // request and issue it.  Treat a refresh request as if it were at
-    // the head of its bank queue.  After we issue something, keep
-    // scanning the queues just to gather statistics about how many
-    // are waiting.  If in mem_fixed_delay mode, we can issue more
-    // than one request per cycle.
-    int queueHeads = 0;
-    int banksIssued = 0;
-    for (int i = 0; i < m_total_banks; i++) {
-        m_roundRobin++;
-        if (m_roundRobin >= m_total_banks) m_roundRobin = 0;
-        issueRefresh(m_roundRobin);
-        int qs = m_bankQueues[m_roundRobin].size();
-        if (qs > 1) {
-            m_profiler_ptr->profileMemBankQ(qs-1);
-        }
-        if (qs > 0) {
-            // we're not idle if anything is queued
-            m_idleCount = IDLECOUNT_MAX_VALUE;
-            queueHeads++;
-            if (queueReady(m_roundRobin)) {
-                issueRequest(m_roundRobin);
-                banksIssued++;
-                if (m_mem_fixed_delay) {
-                    m_profiler_ptr->profileMemWaitCycles(m_mem_fixed_delay);
-                }
-            }
-        }
-    }
-
-    // memWaitCycles is a redundant catch-all for the specific
-    // counters in queueReady
-    m_profiler_ptr->profileMemWaitCycles(queueHeads - banksIssued);
-
-    // Check input queue and move anything to bank queues if not full.
-    // Since this is done here at the end of the cycle, there will
-    // always be at least one cycle of latency in the bank queue.  We
-    // deliberately move at most one request per cycle (to simulate
-    // typical hardware).  Note that if one bank queue fills up, other
-    // requests can get stuck behind it here.
-    if (!m_input_queue.empty()) {
-        // we're not idle if anything is pending
-        m_idleCount = IDLECOUNT_MAX_VALUE;
-        MemoryNode *req = m_input_queue.front();
-        int bank = getBank(req->m_addr);
-        if (m_bankQueues[bank].size() < m_bank_queue_size) {
-            m_input_queue.pop_front();
-            m_bankQueues[bank].push_back(req);
-        }
-        m_profiler_ptr->profileMemInputQ(m_input_queue.size());
-    }
-}
-
-DrainState
-RubyMemoryControl::drain()
-{
-    DPRINTF(RubyMemory, "MemoryController drain\n");
-    if (m_event.scheduled()) {
-        deschedule(m_event);
-    }
-    return DrainState::Drained;
-}
-
-// wakeup:  This function is called once per memory controller clock cycle.
-void
-RubyMemoryControl::wakeup()
-{
-    DPRINTF(RubyMemory, "MemoryController wakeup\n");
-    // execute everything
-    executeCycle();
-
-    m_idleCount--;
-    if (m_idleCount > 0) {
-        assert(!m_event.scheduled());
-        schedule(m_event, clockEdge(Cycles(1)));
-    }
-}
-
-/**
- * This function reads the different buffers that exist in the Ruby Memory
- * Controller, and figures out if any of the buffers hold a message that
- * contains the data for the address provided in the packet. True is returned
- * if any of the messages was read, otherwise false is returned.
- *
- * I think we should move these buffers to being message buffers, instead of
- * being lists.
- */
-bool
-RubyMemoryControl::functionalRead(Packet *pkt)
-{
-    for (std::list<MemoryNode *>::iterator it = m_input_queue.begin();
-         it != m_input_queue.end(); ++it) {
-        PacketPtr msg = (*it)->pkt;
-        if (pkt->checkFunctional(msg)) {
-            return true;
-        }
-    }
-
-    for (std::list<MemoryNode *>::iterator it = m_response_queue.begin();
-         it != m_response_queue.end(); ++it) {
-        PacketPtr msg = (*it)->pkt;
-        if (pkt->checkFunctional(msg)) {
-            return true;
-        }
-    }
-
-    for (uint32_t bank = 0; bank < m_total_banks; ++bank) {
-        for (std::list<MemoryNode *>::iterator it = m_bankQueues[bank].begin();
-             it != m_bankQueues[bank].end(); ++it) {
-            PacketPtr msg = (*it)->pkt;
-            if (pkt->checkFunctional(msg)) {
-                return true;
-            }
-        }
-    }
-
-    functionalAccess(pkt);
-    return true;
-}
-
-/**
- * This function reads the different buffers that exist in the Ruby Memory
- * Controller, and figures out if any of the buffers hold a message that
- * needs to functionally written with the data in the packet.
- *
- * The number of messages written is returned at the end. This is required
- * for debugging purposes.
- */
-uint32_t
-RubyMemoryControl::functionalWrite(Packet *pkt)
-{
-    uint32_t num_functional_writes = 0;
-
-    for (std::list<MemoryNode *>::iterator it = m_input_queue.begin();
-         it != m_input_queue.end(); ++it) {
-        PacketPtr msg = (*it)->pkt;
-        if (pkt->checkFunctional(msg)) {
-            num_functional_writes++;
-        }
-    }
-
-    for (std::list<MemoryNode *>::iterator it = m_response_queue.begin();
-         it != m_response_queue.end(); ++it) {
-        PacketPtr msg = (*it)->pkt;
-        if (pkt->checkFunctional(msg)) {
-            num_functional_writes++;
-        }
-    }
-
-    for (uint32_t bank = 0; bank < m_total_banks; ++bank) {
-        for (std::list<MemoryNode *>::iterator it = m_bankQueues[bank].begin();
-             it != m_bankQueues[bank].end(); ++it) {
-            PacketPtr msg = (*it)->pkt;
-            if (pkt->checkFunctional(msg)) {
-                num_functional_writes++;
-            }
-        }
-    }
-
-    functionalAccess(pkt);
-    num_functional_writes++;
-    return num_functional_writes;
-}
-
-void
-RubyMemoryControl::regStats()
-{
-    m_profiler_ptr->regStats();
-    AbstractMemory::regStats();
-}
-
-RubyMemoryControl *
-RubyMemoryControlParams::create()
-{
-    return new RubyMemoryControl(this);
-}
-
-RubyMemoryControl::MemoryPort::MemoryPort(const std::string& name,
-                                          RubyMemoryControl& _memory)
-    : QueuedSlavePort(name, &_memory, queue), queue(_memory, *this),
-      memory(_memory)
-{ }
-
-AddrRangeList
-RubyMemoryControl::MemoryPort::getAddrRanges() const
-{
-    AddrRangeList ranges;
-    ranges.push_back(memory.getAddrRange());
-    return ranges;
-}
-
-void
-RubyMemoryControl::MemoryPort::recvFunctional(PacketPtr pkt)
-{
-    pkt->pushLabel(memory.name());
-
-    if (!queue.checkFunctional(pkt)) {
-        // Default implementation of SimpleTimingPort::recvFunctional()
-        // calls recvAtomic() and throws away the latency; we can save a
-        // little here by just not calculating the latency.
-        memory.functionalWrite(pkt);
-    }
-
-    pkt->popLabel();
-}
-
-Tick
-RubyMemoryControl::MemoryPort::recvAtomic(PacketPtr pkt)
-{
-    panic("This controller does not support recv atomic!\n");
-}
-
-bool
-RubyMemoryControl::MemoryPort::recvTimingReq(PacketPtr pkt)
-{
-    // pass it to the memory controller
-    return memory.recvTimingReq(pkt);
-}
diff --git a/src/mem/ruby/structures/RubyMemoryControl.hh b/src/mem/ruby/structures/RubyMemoryControl.hh
deleted file mode 100644 (file)
index 601c4d1..0000000
+++ /dev/null
@@ -1,205 +0,0 @@
-/*
- * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood
- * Copyright (c) 2012 Advanced Micro Devices, Inc.
- * 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.
- */
-
-#ifndef __MEM_RUBY_STRUCTURES_MEMORY_CONTROL_HH__
-#define __MEM_RUBY_STRUCTURES_MEMORY_CONTROL_HH__
-
-#include <iostream>
-#include <list>
-#include <string>
-
-#include "mem/abstract_mem.hh"
-#include "mem/protocol/MemoryMsg.hh"
-#include "mem/ruby/common/Address.hh"
-#include "mem/ruby/profiler/MemCntrlProfiler.hh"
-#include "mem/ruby/structures/MemoryNode.hh"
-#include "mem/ruby/system/RubySystem.hh"
-#include "params/RubyMemoryControl.hh"
-
-// This constant is part of the definition of tFAW; see
-// the comments in header to RubyMemoryControl.cc
-#define ACTIVATE_PER_TFAW 4
-
-//////////////////////////////////////////////////////////////////////////////
-
-class RubyMemoryControl : public AbstractMemory, public Consumer
-{
-  public:
-    typedef RubyMemoryControlParams Params;
-    RubyMemoryControl(const Params *p);
-    void init() override;
-    void reset();
-
-    ~RubyMemoryControl();
-
-    virtual BaseSlavePort& getSlavePort(const std::string& if_name,
-                                        PortID idx = InvalidPortID) override;
-    DrainState drain() override;
-    void wakeup() override;
-
-    void setDescription(const std::string& name) { m_description = name; };
-    std::string getDescription() { return m_description; };
-
-    // Called from the directory:
-    bool recvTimingReq(PacketPtr pkt);
-    void recvFunctional(PacketPtr pkt);
-    void enqueueMemRef(MemoryNode *memRef);
-    bool areNSlotsAvailable(int n) { return true; };  // infinite queue length
-
-    void print(std::ostream& out) const override;
-    void regStats() override;
-
-    int getBank(const Addr addr) const;
-    int getRank(const Addr addr) const;
-
-    // not used in Ruby memory controller
-    int getChannel(const Addr addr) const;
-    int getRow(const Addr addr) const;
-
-    //added by SS
-    int getBanksPerRank() { return m_banks_per_rank; };
-    int getRanksPerDimm() { return m_ranks_per_dimm; };
-    int getDimmsPerChannel() { return m_dimms_per_channel; }
-
-    bool functionalRead(Packet *pkt);
-    uint32_t functionalWrite(Packet *pkt);
-
-  private:
-    void enqueueToDirectory(MemoryNode *req, Cycles latency);
-    int getRank(int bank) const;
-    bool queueReady(int bank);
-    void issueRequest(int bank);
-    bool issueRefresh(int bank);
-    void markTfaw(int rank);
-    void executeCycle();
-
-    // Private copy constructor and assignment operator
-    RubyMemoryControl (const RubyMemoryControl& obj);
-    RubyMemoryControl& operator=(const RubyMemoryControl& obj);
-
-  private:
-    // For now, make use of a queued slave port to avoid dealing with
-    // flow control for the responses being sent back
-    class MemoryPort : public QueuedSlavePort
-    {
-        RespPacketQueue queue;
-        RubyMemoryControl& memory;
-
-      public:
-        MemoryPort(const std::string& name, RubyMemoryControl& _memory);
-
-      protected:
-        Tick recvAtomic(PacketPtr pkt);
-
-        void recvFunctional(PacketPtr pkt);
-
-        bool recvTimingReq(PacketPtr);
-
-        virtual AddrRangeList getAddrRanges() const;
-    };
-
-    /**
-     * Our incoming port, for a multi-ported controller add a crossbar
-     * in front of it
-     */
-    MemoryPort port;
-
-    // data members
-    std::string m_description;
-    int m_msg_counter;
-
-    int m_banks_per_rank;
-    int m_ranks_per_dimm;
-    int m_dimms_per_channel;
-    int m_bank_bit_0;
-    int m_rank_bit_0;
-    int m_dimm_bit_0;
-    unsigned int m_bank_queue_size;
-    int m_bank_busy_time;
-    int m_rank_rank_delay;
-    int m_read_write_delay;
-    int m_basic_bus_busy_time;
-    Cycles m_mem_ctl_latency;
-    int m_refresh_period;
-    int m_mem_random_arbitrate;
-    int m_tFaw;
-    Cycles m_mem_fixed_delay;
-
-    int m_total_banks;
-    int m_total_ranks;
-    int m_refresh_period_system;
-
-    // queues where memory requests live
-    std::list<MemoryNode *> m_response_queue;
-    std::list<MemoryNode *> m_input_queue;
-    std::list<MemoryNode *>* m_bankQueues;
-
-    // Each entry indicates number of address-bus cycles until bank
-    // is reschedulable:
-    int *m_bankBusyCounter;
-    int *m_oldRequest;
-
-    uint64_t *m_tfaw_shift;
-    int *m_tfaw_count;
-
-    // Each of these indicates number of address-bus cycles until
-    // we can issue a new request of the corresponding type:
-    int m_busBusyCounter_Write;
-    int m_busBusyCounter_ReadNewRank;
-    int m_busBusyCounter_Basic;
-
-    int m_busBusy_WhichRank;  // which rank last granted
-    int m_roundRobin;         // which bank queue was last granted
-    int m_refresh_count;      // cycles until next refresh
-    int m_need_refresh;       // set whenever m_refresh_count goes to zero
-    int m_refresh_bank;       // which bank to refresh next
-    int m_ageCounter;         // age of old requests; to detect starvation
-    int m_idleCount;          // watchdog timer for shutting down
-
-    MemCntrlProfiler *m_profiler_ptr;
-
-    class MemCntrlEvent : public Event
-    {
-      public:
-        MemCntrlEvent(RubyMemoryControl *_mem_cntrl)
-        {
-            mem_cntrl = _mem_cntrl;
-        }
-      private:
-        void process() { mem_cntrl->wakeup(); }
-
-        RubyMemoryControl* mem_cntrl;
-    };
-
-    MemCntrlEvent m_event;
-};
-
-std::ostream& operator<<(std::ostream& out, const RubyMemoryControl& obj);
-
-#endif // __MEM_RUBY_STRUCTURES_MEMORY_CONTROL_HH__
diff --git a/src/mem/ruby/structures/RubyMemoryControl.py b/src/mem/ruby/structures/RubyMemoryControl.py
deleted file mode 100644 (file)
index 78f2d8d..0000000
+++ /dev/null
@@ -1,57 +0,0 @@
-# Copyright (c) 2009 Advanced Micro Devices, Inc.
-# 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: Steve Reinhardt
-#          Brad Beckmann
-
-from m5.params import *
-from AbstractMemory import AbstractMemory
-
-class RubyMemoryControl(AbstractMemory):
-    type = 'RubyMemoryControl'
-    cxx_class = 'RubyMemoryControl'
-    cxx_header = "mem/ruby/structures/RubyMemoryControl.hh"
-
-    banks_per_rank = Param.Int(8, "");
-    ranks_per_dimm = Param.Int(2, "");
-    dimms_per_channel = Param.Int(2, "");
-    bank_bit_0 = Param.Int(8, "");
-    rank_bit_0 = Param.Int(11, "");
-    dimm_bit_0 = Param.Int(12, "");
-    bank_queue_size = Param.Int(12, "");
-    bank_busy_time = Param.Int(11, "");
-    rank_rank_delay = Param.Int(1, "");
-    read_write_delay = Param.Int(2, "");
-    basic_bus_busy_time = Param.Int(2, "");
-    mem_ctl_latency = Param.Cycles(12, "");
-    refresh_period = Param.Cycles(1560, "");
-    tFaw = Param.Int(0, "");
-    mem_random_arbitrate = Param.Int(0, "");
-    mem_fixed_delay = Param.Cycles(0, "");
-
-    # single-ported on the system interface side, instantiate with a
-    # crossbar in front of the controller for multiple ports
-    port = SlavePort("Slave port")
index 75fc6370eba72123effa6aa809bf47b112ae1685..c39cd0e51e5d47dc7406c595a0305b3c08cec36c 100644 (file)
@@ -38,7 +38,6 @@ SimObject('DirectoryMemory.py')
 SimObject('LRUReplacementPolicy.py')
 SimObject('PseudoLRUReplacementPolicy.py')
 SimObject('ReplacementPolicy.py')
-SimObject('RubyMemoryControl.py')
 SimObject('RubyPrefetcher.py')
 SimObject('WireBuffer.py')
 
@@ -48,8 +47,6 @@ Source('CacheMemory.cc')
 Source('LRUPolicy.cc')
 Source('PseudoLRUPolicy.cc')
 Source('WireBuffer.cc')
-Source('RubyMemoryControl.cc')
-Source('MemoryNode.cc')
 Source('PersistentTable.cc')
 Source('Prefetcher.cc')
 Source('TimerTable.cc')