ruby: Remove the RubyCache/CacheMemory latency
authorJoel Hestness <jthestness@gmail.com>
Fri, 14 Aug 2015 05:19:37 +0000 (00:19 -0500)
committerJoel Hestness <jthestness@gmail.com>
Fri, 14 Aug 2015 05:19:37 +0000 (00:19 -0500)
The RubyCache (CacheMemory) latency parameter is only used for top-level caches
instantiated for Ruby coherence protocols. However, the top-level cache hit
latency is assessed by the Sequencer as accesses flow through to the cache
hierarchy. Further, protocol state machines should be enforcing these cache hit
latencies, but RubyCaches do not expose their latency to any existng state
machines through the SLICC/C++ interface. Thus, the RubyCache latency parameter
is superfluous for all caches. This is confusing for users.

As a step toward pushing L0/L1 cache hit latency into the top-level cache
controllers, move their latencies out of the RubyCache declarations and over to
their Sequencers. Eventually, these Sequencer parameters should be exposed as
parameters to the top-level cache controllers, which should assess the latency.
NOTE: Assessing these latencies in the cache controllers will require modifying
each to eliminate instantaneous Ruby hit callbacks in transitions that finish
accesses, which is likely a large undertaking.

13 files changed:
configs/ruby/MESI_Three_Level.py
configs/ruby/MESI_Two_Level.py
configs/ruby/MI_example.py
configs/ruby/MOESI_CMP_directory.py
configs/ruby/MOESI_CMP_token.py
configs/ruby/MOESI_hammer.py
configs/ruby/Network_test.py
src/mem/ruby/structures/Cache.py
src/mem/ruby/structures/CacheMemory.cc
src/mem/ruby/structures/CacheMemory.hh
src/mem/ruby/system/Sequencer.cc
src/mem/ruby/system/Sequencer.hh
src/mem/ruby/system/Sequencer.py

index a4074e8425706c40dfaa2abd99c739394c73719f..74eb15887f4bcad4f1a46d69ba985a0589078988 100644 (file)
@@ -37,19 +37,11 @@ from Ruby import create_topology
 from Ruby import send_evicts
 
 #
-# Note: the L1 Cache latency is only used by the sequencer on fast path hits
+# Declare caches used by the protocol
 #
-class L0Cache(RubyCache):
-    latency = 1
-
-class L1Cache(RubyCache):
-    latency = 5
-
-#
-# Note: the L2 Cache latency is not currently used
-#
-class L2Cache(RubyCache):
-    latency = 15
+class L0Cache(RubyCache): pass
+class L1Cache(RubyCache): pass
+class L2Cache(RubyCache): pass
 
 def define_options(parser):
     parser.add_option("--num-clusters", type="int", default=1,
index d911d76ef3f9687569130f216e8c592f4f774ee4..9f286fa5309788e56e7c26010ddfd4d7ad4f9737 100644 (file)
@@ -35,16 +35,10 @@ from Ruby import create_topology
 from Ruby import send_evicts
 
 #
-# Note: the L1 Cache latency is only used by the sequencer on fast path hits
+# Declare caches used by the protocol
 #
-class L1Cache(RubyCache):
-    latency = 3
-
-#
-# Note: the L2 Cache latency is not currently used
-#
-class L2Cache(RubyCache):
-    latency = 15
+class L1Cache(RubyCache): pass
+class L2Cache(RubyCache): pass
 
 def define_options(parser):
     return
index 3bb332c1d708717bf4bad72a1cecac0d83b98625..5afee674a4fe0315f878ad0486d2d9eec2310357 100644 (file)
@@ -35,10 +35,9 @@ from Ruby import create_topology
 from Ruby import send_evicts
 
 #
-# Note: the cache latency is only used by the sequencer on fast path hits
+# Declare caches used by the protocol
 #
-class Cache(RubyCache):
-    latency = 3
+class Cache(RubyCache): pass
 
 def define_options(parser):
     return
index d327001665a30fb15225dab6438ad02825460eea..f02c459876fc8bf10aa2de6f8a0f679284e9bb9f 100644 (file)
@@ -35,16 +35,10 @@ from Ruby import create_topology
 from Ruby import send_evicts
 
 #
-# Note: the L1 Cache latency is only used by the sequencer on fast path hits
+# Declare caches used by the protocol
 #
-class L1Cache(RubyCache):
-    latency = 3
-
-#
-# Note: the L2 Cache latency is not currently used
-#
-class L2Cache(RubyCache):
-    latency = 15
+class L1Cache(RubyCache): pass
+class L2Cache(RubyCache): pass
 
 def define_options(parser):
     return
index 26cbc10d98f9238e5df7e03d6fa30240cab4a773..4b09fc937de79ebb25f60d12c664e87af713ab84 100644 (file)
@@ -35,16 +35,10 @@ from Ruby import create_topology
 from Ruby import send_evicts
 
 #
-# Note: the L1 Cache latency is only used by the sequencer on fast path hits
+# Declare caches used by the protocol
 #
-class L1Cache(RubyCache):
-    latency = 2
-
-#
-# Note: the L2 Cache latency is not currently used
-#
-class L2Cache(RubyCache):
-    latency = 10
+class L1Cache(RubyCache): pass
+class L2Cache(RubyCache): pass
 
 def define_options(parser):
     parser.add_option("--l1-retries", type="int", default=1,
index b421387438a3b43760af773fc95e9699661aa31d..afbb25dc368a9abcfaf01cfb223ab8f9d1e994cc 100644 (file)
@@ -35,22 +35,14 @@ from Ruby import create_topology
 from Ruby import send_evicts
 
 #
-# Note: the L1 Cache latency is only used by the sequencer on fast path hits
+# Declare caches used by the protocol
 #
-class L1Cache(RubyCache):
-    latency = 2
-
-#
-# Note: the L2 Cache latency is not currently used
-#
-class L2Cache(RubyCache):
-    latency = 10
-
+class L1Cache(RubyCache): pass
+class L2Cache(RubyCache): pass
 #
-# Probe filter is a cache, latency is not used
+# Probe filter is a cache
 #
-class ProbeFilter(RubyCache):
-    latency = 1
+class ProbeFilter(RubyCache): pass
 
 def define_options(parser):
     parser.add_option("--allow-atomic-migration", action="store_true",
index a4641ae6491ad51945fe2b594f707c99fcefb2d0..5eeaba98b6363cfea44f3f73a6a8a4126e8b907e 100644 (file)
@@ -34,10 +34,9 @@ from m5.util import addToPath
 from Ruby import create_topology
 
 #
-# Note: the cache latency is only used by the sequencer on fast path hits
+# Declare caches used by the protocol
 #
-class Cache(RubyCache):
-    latency = 3
+class Cache(RubyCache): pass
 
 def define_options(parser):
     return
index 7f26e659f28b0a9e7b0907c64f6c75cc41cf24ac..4eb87ac7459d8ad64880fbff8a0f958d739ff386 100644 (file)
@@ -37,7 +37,6 @@ class RubyCache(SimObject):
     cxx_class = 'CacheMemory'
     cxx_header = "mem/ruby/structures/CacheMemory.hh"
     size = Param.MemorySize("capacity in bytes");
-    latency = Param.Cycles("");
     assoc = Param.Int("");
     replacement_policy = Param.ReplacementPolicy(PseudoLRUReplacementPolicy(),
                          "")
index e444ae09cb2557b8edb080a2376c218bd27a8f60..64a8e9e8a8d599bc1ffa10d4de5fd03706e1641e 100644 (file)
@@ -60,7 +60,6 @@ CacheMemory::CacheMemory(const Params *p)
              p->start_index_bit, p->ruby_system)
 {
     m_cache_size = p->size;
-    m_latency = p->latency;
     m_cache_assoc = p->assoc;
     m_replacementPolicy_ptr = p->replacement_policy;
     m_replacementPolicy_ptr->setCache(this);
index 57f2885b6ea81e679283ced2db2731c8c7fc4c83..792d8fd931f02107d7596a9ab98f6327ab344e93 100644 (file)
@@ -96,7 +96,6 @@ class CacheMemory : public SimObject
     AbstractCacheEntry* lookup(const Address& address);
     const AbstractCacheEntry* lookup(const Address& address) const;
 
-    Cycles getLatency() const { return m_latency; }
     Cycles getTagLatency() const { return tagArray.getLatency(); }
     Cycles getDataLatency() const { return dataArray.getLatency(); }
 
@@ -159,8 +158,6 @@ class CacheMemory : public SimObject
     CacheMemory& operator=(const CacheMemory& obj);
 
   private:
-    Cycles m_latency;
-
     // Data Members (m_prefix)
     bool m_is_instruction_only_cache;
 
index 01b868017bab91e78e852c038222594d065d33d6..36bd9cd627ee1ed57cf8c0eeef30b16de5e0b968 100644 (file)
@@ -58,6 +58,8 @@ Sequencer::Sequencer(const Params *p)
 
     m_instCache_ptr = p->icache;
     m_dataCache_ptr = p->dcache;
+    m_data_cache_hit_latency = p->dcache_hit_latency;
+    m_inst_cache_hit_latency = p->icache_hit_latency;
     m_max_outstanding_requests = p->max_outstanding_requests;
     m_deadlock_threshold = p->deadlock_threshold;
 
@@ -65,6 +67,8 @@ Sequencer::Sequencer(const Params *p)
     assert(m_deadlock_threshold > 0);
     assert(m_instCache_ptr != NULL);
     assert(m_dataCache_ptr != NULL);
+    assert(m_data_cache_hit_latency > 0);
+    assert(m_inst_cache_hit_latency > 0);
 
     m_usingNetworkTester = p->using_network_tester;
 }
@@ -691,12 +695,17 @@ Sequencer::issueRequest(PacketPtr pkt, RubyRequestType secondary_type)
             msg->getPhysicalAddress(),
             RubyRequestType_to_string(secondary_type));
 
-    Cycles latency(0);  // initialzed to an null value
-
+    // The Sequencer currently assesses instruction and data cache hit latency
+    // for the top-level caches at the beginning of a memory access.
+    // TODO: Eventually, this latency should be moved to represent the actual
+    // cache access latency portion of the memory access. This will require
+    // changing cache controller protocol files to assess the latency on the
+    // access response path.
+    Cycles latency(0);  // Initialize to zero to catch misconfigured latency
     if (secondary_type == RubyRequestType_IFETCH)
-        latency = m_instCache_ptr->getLatency();
+        latency = m_inst_cache_hit_latency;
     else
-        latency = m_dataCache_ptr->getLatency();
+        latency = m_data_cache_hit_latency;
 
     // Send the message to the cache controller
     assert(latency > 0);
index d5cd17f5fb356a1a1d7850291c04b1d6c88a6939..505b3f3bce2d4a5d9c99d2460bc5a5b520e73c8d 100644 (file)
@@ -180,6 +180,13 @@ class Sequencer : public RubyPort
     CacheMemory* m_dataCache_ptr;
     CacheMemory* m_instCache_ptr;
 
+    // The cache access latency for top-level caches (L0/L1). These are
+    // currently assessed at the beginning of each memory access through the
+    // sequencer.
+    // TODO: Migrate these latencies into top-level cache controllers.
+    Cycles m_data_cache_hit_latency;
+    Cycles m_inst_cache_hit_latency;
+
     typedef m5::hash_map<Address, SequencerRequest*> RequestTable;
     RequestTable m_writeRequestTable;
     RequestTable m_readRequestTable;
index e545000cf35970464719df4ac8c760b2e22bde32..7494986e9aa668348fbe582c8ac38d3c9453a2f8 100644 (file)
@@ -61,6 +61,12 @@ class RubySequencer(RubyPort):
 
     icache = Param.RubyCache("")
     dcache = Param.RubyCache("")
+    # Cache latencies currently assessed at the beginning of each access
+    # NOTE: Setting these values to a value greater than one will result in
+    # O3 CPU pipeline bubbles and negatively impact performance
+    # TODO: Latencies should be migrated into each top-level cache controller
+    icache_hit_latency = Param.Cycles(1, "Inst cache hit latency")
+    dcache_hit_latency = Param.Cycles(1, "Data cache hit latency")
     max_outstanding_requests = Param.Int(16,
         "max requests (incl. prefetches) outstanding")
     deadlock_threshold = Param.Cycles(500000,