Ruby Sparse Memory: Add function for collating blocks
authorNilay Vaish <nilay@cs.wisc.edu>
Wed, 11 Jan 2012 19:29:54 +0000 (13:29 -0600)
committerNilay Vaish <nilay@cs.wisc.edu>
Wed, 11 Jan 2012 19:29:54 +0000 (13:29 -0600)
This patch adds function to the Sparse Memory so that the blocks can be
recorded in a cache trace. The blocks are added to the cache recorder
which can later write them into a file.

src/mem/ruby/system/SparseMemory.cc
src/mem/ruby/system/SparseMemory.hh

index 0cfd0d90c57361f3a2c33b11980049e996444541..db8d494f8b78a741627747a85b2e3f57be1b9301 100644 (file)
@@ -1,5 +1,6 @@
 /*
  * Copyright (c) 2009 Advanced Micro Devices, Inc.
+ * Copyright (c) 2012 Mark D. Hill and David A. Wood
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -26,6 +27,8 @@
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
+#include <queue>
+
 #include "debug/RubyCache.hh"
 #include "mem/ruby/system/SparseMemory.hh"
 #include "mem/ruby/system/System.hh"
@@ -341,6 +344,70 @@ SparseMemory::lookup(const Address& address)
     return entry;
 }
 
+void
+SparseMemory::recordBlocks(int cntrl_id, CacheRecorder* tr) const
+{
+    queue<SparseMapType*> unexplored_nodes[2];
+    queue<physical_address_t> address_of_nodes[2];
+
+    unexplored_nodes[0].push(m_map_head);
+    address_of_nodes[0].push(0);
+
+    int parity_of_level = 0;
+    physical_address_t address, temp_address;
+    Address curAddress;
+
+    // Initiallize the high bit to be the total number of bits plus
+    // the block offset.  However the highest bit index is one less
+    // than this value.
+    int highBit = m_total_number_of_bits + RubySystem::getBlockSizeBits();
+    int lowBit;
+
+    for (int cur_level = 0; cur_level < m_number_of_levels; cur_level++) {
+
+        // create the appropriate address for this level
+        // Note: that set Address is inclusive of the specified range,
+        // thus the high bit is one less than the total number of bits
+        // used to create the address.
+        lowBit = highBit - m_number_of_bits_per_level[cur_level];
+
+        while (!unexplored_nodes[parity_of_level].empty()) {
+
+            SparseMapType* node = unexplored_nodes[parity_of_level].front();
+            unexplored_nodes[parity_of_level].pop();
+
+            address = address_of_nodes[parity_of_level].front();
+            address_of_nodes[parity_of_level].pop();
+
+            SparseMapType::iterator iter;
+
+            for (iter = node->begin(); iter != node->end(); iter++) {
+                SparseMemEntry entry = (*iter).second;
+                curAddress = (*iter).first;
+
+                if (cur_level != (m_number_of_levels - 1)) {
+                    // If not at the last level, put this node in the queue
+                    unexplored_nodes[1 - parity_of_level].push(
+                                                     (SparseMapType*)(entry));
+                    address_of_nodes[1 - parity_of_level].push(address |
+                                         (curAddress.getAddress() << lowBit));
+                } else {
+                    // If at the last level, add a trace record
+                    temp_address = address | (curAddress.getAddress()
+                                                                   << lowBit);
+                    DataBlock block = ((AbstractEntry*)entry)->getDataBlk();
+                    tr->addRecord(cntrl_id, temp_address, 0, RubyRequestType_ST, 0,
+                                  block);
+                }
+            }
+        }
+
+        // Adjust the highBit value for the next level
+        highBit -= m_number_of_bits_per_level[cur_level];
+        parity_of_level = 1 - parity_of_level;
+    }
+}
+
 void
 SparseMemory::print(ostream& out) const
 {
index f4cc12f9772c746017686292339757395964a4e9..e4237dbcd4388c746cc379fbc1b3181706decd9c 100644 (file)
@@ -1,5 +1,6 @@
 /*
  * Copyright (c) 2009 Advanced Micro Devices, Inc.
+ * Copyright (c) 2012 Mark D. Hill and David A. Wood
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -32,9 +33,9 @@
 #include <iostream>
 
 #include "base/hashmap.hh"
-#include "mem/ruby/slicc_interface/AbstractEntry.hh"
 #include "mem/ruby/common/Address.hh"
-#include "mem/ruby/common/Global.hh"
+#include "mem/ruby/recorder/CacheRecorder.hh"
+#include "mem/ruby/slicc_interface/AbstractEntry.hh"
 
 typedef void* SparseMemEntry;
 typedef m5::hash_map<Address, SparseMemEntry> SparseMapType;
@@ -59,6 +60,14 @@ class SparseMemory
     void add(const Address& address, AbstractEntry*);
     void remove(const Address& address);
 
+    /*!
+     * Function for recording the contents of memory. This function walks
+     * through all the levels of the sparse memory in a breadth first
+     * fashion. This might need more memory than a depth first approach.
+     * But breadth first seems easier to me than a depth first approach.
+     */
+    void recordBlocks(int cntrl_id, CacheRecorder *) const;
+
     AbstractEntry* lookup(const Address& address);
 
     // Print cache contents