Ruby Sparse Memory: Add function for collating blocks
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.
This commit is contained in:
parent
c3109f7775
commit
8b3ad17cc3
2 changed files with 78 additions and 2 deletions
|
@ -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
|
||||
{
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue