From 17e14efa7e7358f02f2664e10e4001faf6b7811e Mon Sep 17 00:00:00 2001 From: Brad Beckmann Date: Wed, 18 Nov 2009 13:55:57 -0800 Subject: ruby: Ruby 64-bit address output fixes. --- src/mem/ruby/system/Sequencer.cc | 8 ++++++-- src/mem/ruby/system/Sequencer.hh | 2 ++ 2 files changed, 8 insertions(+), 2 deletions(-) (limited to 'src/mem/ruby/system') diff --git a/src/mem/ruby/system/Sequencer.cc b/src/mem/ruby/system/Sequencer.cc index 780c1128e..c693e0f37 100644 --- a/src/mem/ruby/system/Sequencer.cc +++ b/src/mem/ruby/system/Sequencer.cc @@ -44,6 +44,10 @@ //Sequencer::Sequencer(int core_id, MessageBuffer* mandatory_q) #define LLSC_FAIL -2 +ostream& operator<<(std::ostream& out, const SequencerRequest& obj) { + out << obj.ruby_request << flush; + return out; +} Sequencer::Sequencer(const string & name) :RubyPort(name) @@ -106,7 +110,7 @@ void Sequencer::wakeup() { SequencerRequest* request = m_readRequestTable.lookup(keys[i]); if (current_time - request->issue_time >= m_deadlock_threshold) { WARN_MSG("Possible Deadlock detected"); - WARN_EXPR(request); + WARN_EXPR(request->ruby_request); WARN_EXPR(m_version); WARN_EXPR(keys.size()); WARN_EXPR(current_time); @@ -121,7 +125,7 @@ void Sequencer::wakeup() { SequencerRequest* request = m_writeRequestTable.lookup(keys[i]); if (current_time - request->issue_time >= m_deadlock_threshold) { WARN_MSG("Possible Deadlock detected"); - WARN_EXPR(request); + WARN_EXPR(request->ruby_request); WARN_EXPR(m_version); WARN_EXPR(current_time); WARN_EXPR(request->issue_time); diff --git a/src/mem/ruby/system/Sequencer.hh b/src/mem/ruby/system/Sequencer.hh index 2b1f023c5..cf12c2a0b 100644 --- a/src/mem/ruby/system/Sequencer.hh +++ b/src/mem/ruby/system/Sequencer.hh @@ -63,6 +63,8 @@ struct SequencerRequest { {} }; +std::ostream& operator<<(std::ostream& out, const SequencerRequest& obj); + class Sequencer : public Consumer, public RubyPort { public: // Constructors -- cgit v1.2.3 From 3cf24f9716eebab8c24fa645d02c636584033514 Mon Sep 17 00:00:00 2001 From: Brad Beckmann Date: Wed, 18 Nov 2009 13:55:58 -0800 Subject: ruby: Support for merging ALPHA_FS and ruby Connects M5 cpu and dma ports directly to ruby sequencers and dma sequencers. Rubymem also includes a pio port so that pio requests and be forwarded to a special pio bus connecting to device pio ports. --- src/mem/ruby/system/System.hh | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'src/mem/ruby/system') diff --git a/src/mem/ruby/system/System.hh b/src/mem/ruby/system/System.hh index 38ef09177..1d36de878 100644 --- a/src/mem/ruby/system/System.hh +++ b/src/mem/ruby/system/System.hh @@ -107,7 +107,10 @@ public: if (m_ports.count(name) != 1){ cerr << "Port " << name << " has " << m_ports.count(name) << " instances" << endl; } - assert(m_ports.count(name) == 1); m_ports[name]->registerHitCallback(hit_callback); return m_ports[name]; } + assert(m_ports.count(name) == 1); + m_ports[name]->registerHitCallback(hit_callback); + return m_ports[name]; + } static Network* getNetwork() { assert(m_network_ptr != NULL); return m_network_ptr; } static Topology* getTopology(const string & name) { assert(m_topologies.count(name) == 1); return m_topologies[name]; } static CacheMemory* getCache(const string & name) { assert(m_caches.count(name) == 1); return m_caches[name]; } -- cgit v1.2.3 From 204d1776caa17329b84e5ebbe50fca4f1e80c100 Mon Sep 17 00:00:00 2001 From: Brad Beckmann Date: Wed, 18 Nov 2009 13:55:58 -0800 Subject: ruby: Fixed Directory memory destructor --- src/mem/ruby/system/DirectoryMemory.cc | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) (limited to 'src/mem/ruby/system') diff --git a/src/mem/ruby/system/DirectoryMemory.cc b/src/mem/ruby/system/DirectoryMemory.cc index c87be94a2..e230059ad 100644 --- a/src/mem/ruby/system/DirectoryMemory.cc +++ b/src/mem/ruby/system/DirectoryMemory.cc @@ -84,11 +84,14 @@ void DirectoryMemory::init(const vector & argv) DirectoryMemory::~DirectoryMemory() { // free up all the directory entries - for (int i=0;i Date: Wed, 18 Nov 2009 16:33:35 -0800 Subject: ruby: split CacheMemory.hh into a .hh and a .cc --- src/mem/ruby/system/CacheMemory.cc | 459 +++++++++++++++++++++++++++++++++++++ src/mem/ruby/system/CacheMemory.hh | 459 ------------------------------------- src/mem/ruby/system/SConscript | 1 + 3 files changed, 460 insertions(+), 459 deletions(-) create mode 100644 src/mem/ruby/system/CacheMemory.cc (limited to 'src/mem/ruby/system') diff --git a/src/mem/ruby/system/CacheMemory.cc b/src/mem/ruby/system/CacheMemory.cc new file mode 100644 index 000000000..8d5ba3270 --- /dev/null +++ b/src/mem/ruby/system/CacheMemory.cc @@ -0,0 +1,459 @@ +/* + * 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/system/CacheMemory.hh" + +// Output operator declaration +//ostream& operator<<(ostream& out, const CacheMemory& obj); + +// ******************* Definitions ******************* + +// Output operator definition +ostream& operator<<(ostream& out, const CacheMemory& obj) +{ + obj.print(out); + out << flush; + return out; +} + + +// **************************************************************** + +CacheMemory::CacheMemory(const string & name) + : m_cache_name(name) +{ + m_profiler_ptr = new CacheProfiler(name); +} + +void CacheMemory::init(const vector & argv) +{ + int cache_size = 0; + string policy; + + m_controller = NULL; + for (uint32 i=0; igetName() << endl; + out << " cache_associativity: " << m_cache_assoc << endl; + out << " num_cache_sets_bits: " << m_cache_num_set_bits << endl; + const int cache_num_sets = 1 << m_cache_num_set_bits; + out << " num_cache_sets: " << cache_num_sets << endl; + out << " cache_set_size_bytes: " << cache_num_sets * RubySystem::getBlockSizeBytes() << endl; + out << " cache_set_size_Kbytes: " + << double(cache_num_sets * RubySystem::getBlockSizeBytes()) / (1<<10) << endl; + out << " cache_set_size_Mbytes: " + << double(cache_num_sets * RubySystem::getBlockSizeBytes()) / (1<<20) << endl; + out << " cache_size_bytes: " + << cache_num_sets * RubySystem::getBlockSizeBytes() * m_cache_assoc << endl; + out << " cache_size_Kbytes: " + << double(cache_num_sets * RubySystem::getBlockSizeBytes() * m_cache_assoc) / (1<<10) << endl; + out << " cache_size_Mbytes: " + << double(cache_num_sets * RubySystem::getBlockSizeBytes() * m_cache_assoc) / (1<<20) << endl; +} + +// PRIVATE METHODS + +// convert a Address to its location in the cache +Index CacheMemory::addressToCacheSet(const Address& address) const +{ + assert(address == line_address(address)); + return address.bitSelect(RubySystem::getBlockSizeBits(), RubySystem::getBlockSizeBits() + m_cache_num_set_bits-1); +} + +// Given a cache index: returns the index of the tag in a set. +// returns -1 if the tag is not found. +int CacheMemory::findTagInSet(Index cacheSet, const Address& tag) const +{ + assert(tag == line_address(tag)); + // search the set for the tags + for (int i=0; i < m_cache_assoc; i++) { + if ((m_cache[cacheSet][i] != NULL) && + (m_cache[cacheSet][i]->m_Address == tag) && + (m_cache[cacheSet][i]->m_Permission != AccessPermission_NotPresent)) { + return i; + } + } + return -1; // Not found +} + +// Given a cache index: returns the index of the tag in a set. +// returns -1 if the tag is not found. +int CacheMemory::findTagInSetIgnorePermissions(Index cacheSet, const Address& tag) const +{ + assert(tag == line_address(tag)); + // search the set for the tags + for (int i=0; i < m_cache_assoc; i++) { + if (m_cache[cacheSet][i] != NULL && m_cache[cacheSet][i]->m_Address == tag) + return i; + } + return -1; // Not found +} + +// PUBLIC METHODS +bool CacheMemory::tryCacheAccess(const Address& address, + CacheRequestType type, + DataBlock*& data_ptr) +{ + assert(address == line_address(address)); + DEBUG_EXPR(CACHE_COMP, HighPrio, address); + Index cacheSet = addressToCacheSet(address); + int loc = findTagInSet(cacheSet, address); + if(loc != -1){ // Do we even have a tag match? + AbstractCacheEntry* entry = m_cache[cacheSet][loc]; + m_replacementPolicy_ptr->touch(cacheSet, loc, g_eventQueue_ptr->getTime()); + data_ptr = &(entry->getDataBlk()); + + if(entry->m_Permission == AccessPermission_Read_Write) { + return true; + } + if ((entry->m_Permission == AccessPermission_Read_Only) && + (type == CacheRequestType_LD || type == CacheRequestType_IFETCH)) { + return true; + } + // The line must not be accessible + } + data_ptr = NULL; + return false; +} + +bool CacheMemory::testCacheAccess(const Address& address, + CacheRequestType type, + DataBlock*& data_ptr) +{ + assert(address == line_address(address)); + DEBUG_EXPR(CACHE_COMP, HighPrio, address); + Index cacheSet = addressToCacheSet(address); + int loc = findTagInSet(cacheSet, address); + if(loc != -1){ // Do we even have a tag match? + AbstractCacheEntry* entry = m_cache[cacheSet][loc]; + m_replacementPolicy_ptr->touch(cacheSet, loc, g_eventQueue_ptr->getTime()); + data_ptr = &(entry->getDataBlk()); + + return (m_cache[cacheSet][loc]->m_Permission != AccessPermission_NotPresent); + } + data_ptr = NULL; + return false; +} + +// tests to see if an address is present in the cache +bool CacheMemory::isTagPresent(const Address& address) const +{ + assert(address == line_address(address)); + Index cacheSet = addressToCacheSet(address); + int location = findTagInSet(cacheSet, address); + + if (location == -1) { + // We didn't find the tag + DEBUG_EXPR(CACHE_COMP, LowPrio, address); + DEBUG_MSG(CACHE_COMP, LowPrio, "No tag match"); + return false; + } + DEBUG_EXPR(CACHE_COMP, LowPrio, address); + DEBUG_MSG(CACHE_COMP, LowPrio, "found"); + return true; +} + +// Returns true if there is: +// a) a tag match on this address or there is +// b) an unused line in the same cache "way" +bool CacheMemory::cacheAvail(const Address& address) const +{ + assert(address == line_address(address)); + + Index cacheSet = addressToCacheSet(address); + + for (int i=0; i < m_cache_assoc; i++) { + AbstractCacheEntry* entry = m_cache[cacheSet][i]; + if (entry != NULL) { + if (entry->m_Address == address || // Already in the cache + entry->m_Permission == AccessPermission_NotPresent) { // We found an empty entry + return true; + } + } else { + return true; + } + } + return false; +} + +void CacheMemory::allocate(const Address& address, AbstractCacheEntry* entry) +{ + assert(address == line_address(address)); + assert(!isTagPresent(address)); + assert(cacheAvail(address)); + DEBUG_EXPR(CACHE_COMP, HighPrio, address); + + // Find the first open slot + Index cacheSet = addressToCacheSet(address); + for (int i=0; i < m_cache_assoc; i++) { + if (m_cache[cacheSet][i] == NULL || + m_cache[cacheSet][i]->m_Permission == AccessPermission_NotPresent) { + m_cache[cacheSet][i] = entry; // Init entry + m_cache[cacheSet][i]->m_Address = address; + m_cache[cacheSet][i]->m_Permission = AccessPermission_Invalid; + m_locked[cacheSet][i] = -1; + + m_replacementPolicy_ptr->touch(cacheSet, i, g_eventQueue_ptr->getTime()); + + return; + } + } + ERROR_MSG("Allocate didn't find an available entry"); +} + +void CacheMemory::deallocate(const Address& address) +{ + assert(address == line_address(address)); + assert(isTagPresent(address)); + DEBUG_EXPR(CACHE_COMP, HighPrio, address); + Index cacheSet = addressToCacheSet(address); + int location = findTagInSet(cacheSet, address); + if (location != -1){ + delete m_cache[cacheSet][location]; + m_cache[cacheSet][location] = NULL; + m_locked[cacheSet][location] = -1; + } +} + +// Returns with the physical address of the conflicting cache line +Address CacheMemory::cacheProbe(const Address& address) const +{ + assert(address == line_address(address)); + assert(!cacheAvail(address)); + + Index cacheSet = addressToCacheSet(address); + return m_cache[cacheSet][m_replacementPolicy_ptr->getVictim(cacheSet)]->m_Address; +} + +// looks an address up in the cache +AbstractCacheEntry& CacheMemory::lookup(const Address& address) +{ + assert(address == line_address(address)); + Index cacheSet = addressToCacheSet(address); + int loc = findTagInSet(cacheSet, address); + assert(loc != -1); + return *m_cache[cacheSet][loc]; +} + +// looks an address up in the cache +const AbstractCacheEntry& CacheMemory::lookup(const Address& address) const +{ + assert(address == line_address(address)); + Index cacheSet = addressToCacheSet(address); + int loc = findTagInSet(cacheSet, address); + assert(loc != -1); + return *m_cache[cacheSet][loc]; +} + +AccessPermission CacheMemory::getPermission(const Address& address) const +{ + assert(address == line_address(address)); + return lookup(address).m_Permission; +} + +void CacheMemory::changePermission(const Address& address, AccessPermission new_perm) +{ + assert(address == line_address(address)); + lookup(address).m_Permission = new_perm; + Index cacheSet = addressToCacheSet(address); + int loc = findTagInSet(cacheSet, address); + m_locked[cacheSet][loc] = -1; + assert(getPermission(address) == new_perm); +} + +// Sets the most recently used bit for a cache block +void CacheMemory::setMRU(const Address& address) +{ + Index cacheSet; + + cacheSet = addressToCacheSet(address); + m_replacementPolicy_ptr->touch(cacheSet, + findTagInSet(cacheSet, address), + g_eventQueue_ptr->getTime()); +} + +void CacheMemory::profileMiss(const CacheMsg & msg) +{ + m_profiler_ptr->addStatSample(msg.getType(), msg.getAccessMode(), + msg.getSize(), msg.getPrefetch()); +} + +void CacheMemory::recordCacheContents(CacheRecorder& tr) const +{ + for (int i = 0; i < m_cache_num_sets; i++) { + for (int j = 0; j < m_cache_assoc; j++) { + AccessPermission perm = m_cache[i][j]->m_Permission; + CacheRequestType request_type = CacheRequestType_NULL; + if (perm == AccessPermission_Read_Only) { + if (m_is_instruction_only_cache) { + request_type = CacheRequestType_IFETCH; + } else { + request_type = CacheRequestType_LD; + } + } else if (perm == AccessPermission_Read_Write) { + request_type = CacheRequestType_ST; + } + + if (request_type != CacheRequestType_NULL) { + // tr.addRecord(m_chip_ptr->getID(), m_cache[i][j].m_Address, + // Address(0), request_type, m_replacementPolicy_ptr->getLastAccess(i, j)); + } + } + } +} + +void CacheMemory::print(ostream& out) const +{ + out << "Cache dump: " << m_cache_name << endl; + for (int i = 0; i < m_cache_num_sets; i++) { + for (int j = 0; j < m_cache_assoc; j++) { + if (m_cache[i][j] != NULL) { + out << " Index: " << i + << " way: " << j + << " entry: " << *m_cache[i][j] << endl; + } else { + out << " Index: " << i + << " way: " << j + << " entry: NULL" << endl; + } + } + } +} + +void CacheMemory::printData(ostream& out) const +{ + out << "printData() not supported" << endl; +} + +void CacheMemory::clearStats() const +{ + m_profiler_ptr->clearStats(); +} + +void CacheMemory::printStats(ostream& out) const +{ + m_profiler_ptr->printStats(out); +} + +void CacheMemory::getMemoryValue(const Address& addr, char* value, + unsigned int size_in_bytes ){ + AbstractCacheEntry& entry = lookup(line_address(addr)); + unsigned int startByte = addr.getAddress() - line_address(addr).getAddress(); + for(unsigned int i=0; i 0); + for(unsigned int i=0; i m_all_caches; }; -// Output operator declaration -//ostream& operator<<(ostream& out, const CacheMemory& obj); - -// ******************* Definitions ******************* - -// Output operator definition -inline -ostream& operator<<(ostream& out, const CacheMemory& obj) -{ - obj.print(out); - out << flush; - return out; -} - - -// **************************************************************** - -inline -CacheMemory::CacheMemory(const string & name) - : m_cache_name(name) -{ - m_profiler_ptr = new CacheProfiler(name); -} - -inline -void CacheMemory::init(const vector & argv) -{ - int cache_size = 0; - string policy; - - m_controller = NULL; - for (uint32 i=0; igetName() << endl; - out << " cache_associativity: " << m_cache_assoc << endl; - out << " num_cache_sets_bits: " << m_cache_num_set_bits << endl; - const int cache_num_sets = 1 << m_cache_num_set_bits; - out << " num_cache_sets: " << cache_num_sets << endl; - out << " cache_set_size_bytes: " << cache_num_sets * RubySystem::getBlockSizeBytes() << endl; - out << " cache_set_size_Kbytes: " - << double(cache_num_sets * RubySystem::getBlockSizeBytes()) / (1<<10) << endl; - out << " cache_set_size_Mbytes: " - << double(cache_num_sets * RubySystem::getBlockSizeBytes()) / (1<<20) << endl; - out << " cache_size_bytes: " - << cache_num_sets * RubySystem::getBlockSizeBytes() * m_cache_assoc << endl; - out << " cache_size_Kbytes: " - << double(cache_num_sets * RubySystem::getBlockSizeBytes() * m_cache_assoc) / (1<<10) << endl; - out << " cache_size_Mbytes: " - << double(cache_num_sets * RubySystem::getBlockSizeBytes() * m_cache_assoc) / (1<<20) << endl; -} - -// PRIVATE METHODS - -// convert a Address to its location in the cache -inline -Index CacheMemory::addressToCacheSet(const Address& address) const -{ - assert(address == line_address(address)); - return address.bitSelect(RubySystem::getBlockSizeBits(), RubySystem::getBlockSizeBits() + m_cache_num_set_bits-1); -} - -// Given a cache index: returns the index of the tag in a set. -// returns -1 if the tag is not found. -inline -int CacheMemory::findTagInSet(Index cacheSet, const Address& tag) const -{ - assert(tag == line_address(tag)); - // search the set for the tags - for (int i=0; i < m_cache_assoc; i++) { - if ((m_cache[cacheSet][i] != NULL) && - (m_cache[cacheSet][i]->m_Address == tag) && - (m_cache[cacheSet][i]->m_Permission != AccessPermission_NotPresent)) { - return i; - } - } - return -1; // Not found -} - -// Given a cache index: returns the index of the tag in a set. -// returns -1 if the tag is not found. -inline -int CacheMemory::findTagInSetIgnorePermissions(Index cacheSet, const Address& tag) const -{ - assert(tag == line_address(tag)); - // search the set for the tags - for (int i=0; i < m_cache_assoc; i++) { - if (m_cache[cacheSet][i] != NULL && m_cache[cacheSet][i]->m_Address == tag) - return i; - } - return -1; // Not found -} - -// PUBLIC METHODS -inline -bool CacheMemory::tryCacheAccess(const Address& address, - CacheRequestType type, - DataBlock*& data_ptr) -{ - assert(address == line_address(address)); - DEBUG_EXPR(CACHE_COMP, HighPrio, address); - Index cacheSet = addressToCacheSet(address); - int loc = findTagInSet(cacheSet, address); - if(loc != -1){ // Do we even have a tag match? - AbstractCacheEntry* entry = m_cache[cacheSet][loc]; - m_replacementPolicy_ptr->touch(cacheSet, loc, g_eventQueue_ptr->getTime()); - data_ptr = &(entry->getDataBlk()); - - if(entry->m_Permission == AccessPermission_Read_Write) { - return true; - } - if ((entry->m_Permission == AccessPermission_Read_Only) && - (type == CacheRequestType_LD || type == CacheRequestType_IFETCH)) { - return true; - } - // The line must not be accessible - } - data_ptr = NULL; - return false; -} - -inline -bool CacheMemory::testCacheAccess(const Address& address, - CacheRequestType type, - DataBlock*& data_ptr) -{ - assert(address == line_address(address)); - DEBUG_EXPR(CACHE_COMP, HighPrio, address); - Index cacheSet = addressToCacheSet(address); - int loc = findTagInSet(cacheSet, address); - if(loc != -1){ // Do we even have a tag match? - AbstractCacheEntry* entry = m_cache[cacheSet][loc]; - m_replacementPolicy_ptr->touch(cacheSet, loc, g_eventQueue_ptr->getTime()); - data_ptr = &(entry->getDataBlk()); - - return (m_cache[cacheSet][loc]->m_Permission != AccessPermission_NotPresent); - } - data_ptr = NULL; - return false; -} - -// tests to see if an address is present in the cache -inline -bool CacheMemory::isTagPresent(const Address& address) const -{ - assert(address == line_address(address)); - Index cacheSet = addressToCacheSet(address); - int location = findTagInSet(cacheSet, address); - - if (location == -1) { - // We didn't find the tag - DEBUG_EXPR(CACHE_COMP, LowPrio, address); - DEBUG_MSG(CACHE_COMP, LowPrio, "No tag match"); - return false; - } - DEBUG_EXPR(CACHE_COMP, LowPrio, address); - DEBUG_MSG(CACHE_COMP, LowPrio, "found"); - return true; -} - -// Returns true if there is: -// a) a tag match on this address or there is -// b) an unused line in the same cache "way" -inline -bool CacheMemory::cacheAvail(const Address& address) const -{ - assert(address == line_address(address)); - - Index cacheSet = addressToCacheSet(address); - - for (int i=0; i < m_cache_assoc; i++) { - AbstractCacheEntry* entry = m_cache[cacheSet][i]; - if (entry != NULL) { - if (entry->m_Address == address || // Already in the cache - entry->m_Permission == AccessPermission_NotPresent) { // We found an empty entry - return true; - } - } else { - return true; - } - } - return false; -} - -inline -void CacheMemory::allocate(const Address& address, AbstractCacheEntry* entry) -{ - assert(address == line_address(address)); - assert(!isTagPresent(address)); - assert(cacheAvail(address)); - DEBUG_EXPR(CACHE_COMP, HighPrio, address); - - // Find the first open slot - Index cacheSet = addressToCacheSet(address); - for (int i=0; i < m_cache_assoc; i++) { - if (m_cache[cacheSet][i] == NULL || - m_cache[cacheSet][i]->m_Permission == AccessPermission_NotPresent) { - m_cache[cacheSet][i] = entry; // Init entry - m_cache[cacheSet][i]->m_Address = address; - m_cache[cacheSet][i]->m_Permission = AccessPermission_Invalid; - m_locked[cacheSet][i] = -1; - - m_replacementPolicy_ptr->touch(cacheSet, i, g_eventQueue_ptr->getTime()); - - return; - } - } - ERROR_MSG("Allocate didn't find an available entry"); -} - -inline -void CacheMemory::deallocate(const Address& address) -{ - assert(address == line_address(address)); - assert(isTagPresent(address)); - DEBUG_EXPR(CACHE_COMP, HighPrio, address); - Index cacheSet = addressToCacheSet(address); - int location = findTagInSet(cacheSet, address); - if (location != -1){ - delete m_cache[cacheSet][location]; - m_cache[cacheSet][location] = NULL; - m_locked[cacheSet][location] = -1; - } -} - -// Returns with the physical address of the conflicting cache line -inline -Address CacheMemory::cacheProbe(const Address& address) const -{ - assert(address == line_address(address)); - assert(!cacheAvail(address)); - - Index cacheSet = addressToCacheSet(address); - return m_cache[cacheSet][m_replacementPolicy_ptr->getVictim(cacheSet)]->m_Address; -} - -// looks an address up in the cache -inline -AbstractCacheEntry& CacheMemory::lookup(const Address& address) -{ - assert(address == line_address(address)); - Index cacheSet = addressToCacheSet(address); - int loc = findTagInSet(cacheSet, address); - assert(loc != -1); - return *m_cache[cacheSet][loc]; -} - -// looks an address up in the cache -inline -const AbstractCacheEntry& CacheMemory::lookup(const Address& address) const -{ - assert(address == line_address(address)); - Index cacheSet = addressToCacheSet(address); - int loc = findTagInSet(cacheSet, address); - assert(loc != -1); - return *m_cache[cacheSet][loc]; -} - -inline -AccessPermission CacheMemory::getPermission(const Address& address) const -{ - assert(address == line_address(address)); - return lookup(address).m_Permission; -} - -inline -void CacheMemory::changePermission(const Address& address, AccessPermission new_perm) -{ - assert(address == line_address(address)); - lookup(address).m_Permission = new_perm; - Index cacheSet = addressToCacheSet(address); - int loc = findTagInSet(cacheSet, address); - m_locked[cacheSet][loc] = -1; - assert(getPermission(address) == new_perm); -} - -// Sets the most recently used bit for a cache block -inline -void CacheMemory::setMRU(const Address& address) -{ - Index cacheSet; - - cacheSet = addressToCacheSet(address); - m_replacementPolicy_ptr->touch(cacheSet, - findTagInSet(cacheSet, address), - g_eventQueue_ptr->getTime()); -} - -inline -void CacheMemory::profileMiss(const CacheMsg & msg) -{ - m_profiler_ptr->addStatSample(msg.getType(), msg.getAccessMode(), - msg.getSize(), msg.getPrefetch()); -} - -inline -void CacheMemory::recordCacheContents(CacheRecorder& tr) const -{ - for (int i = 0; i < m_cache_num_sets; i++) { - for (int j = 0; j < m_cache_assoc; j++) { - AccessPermission perm = m_cache[i][j]->m_Permission; - CacheRequestType request_type = CacheRequestType_NULL; - if (perm == AccessPermission_Read_Only) { - if (m_is_instruction_only_cache) { - request_type = CacheRequestType_IFETCH; - } else { - request_type = CacheRequestType_LD; - } - } else if (perm == AccessPermission_Read_Write) { - request_type = CacheRequestType_ST; - } - - if (request_type != CacheRequestType_NULL) { - // tr.addRecord(m_chip_ptr->getID(), m_cache[i][j].m_Address, - // Address(0), request_type, m_replacementPolicy_ptr->getLastAccess(i, j)); - } - } - } -} - -inline -void CacheMemory::print(ostream& out) const -{ - out << "Cache dump: " << m_cache_name << endl; - for (int i = 0; i < m_cache_num_sets; i++) { - for (int j = 0; j < m_cache_assoc; j++) { - if (m_cache[i][j] != NULL) { - out << " Index: " << i - << " way: " << j - << " entry: " << *m_cache[i][j] << endl; - } else { - out << " Index: " << i - << " way: " << j - << " entry: NULL" << endl; - } - } - } -} - -inline -void CacheMemory::printData(ostream& out) const -{ - out << "printData() not supported" << endl; -} - -inline void CacheMemory::clearStats() const -{ - m_profiler_ptr->clearStats(); -} - -inline -void CacheMemory::printStats(ostream& out) const -{ - m_profiler_ptr->printStats(out); -} - -inline -void CacheMemory::getMemoryValue(const Address& addr, char* value, - unsigned int size_in_bytes ){ - AbstractCacheEntry& entry = lookup(line_address(addr)); - unsigned int startByte = addr.getAddress() - line_address(addr).getAddress(); - for(unsigned int i=0; i 0); - for(unsigned int i=0; i Date: Wed, 18 Nov 2009 16:33:35 -0800 Subject: ruby: fix CacheMemory destructor --- src/mem/ruby/system/CacheMemory.cc | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'src/mem/ruby/system') diff --git a/src/mem/ruby/system/CacheMemory.cc b/src/mem/ruby/system/CacheMemory.cc index 8d5ba3270..04adbcf69 100644 --- a/src/mem/ruby/system/CacheMemory.cc +++ b/src/mem/ruby/system/CacheMemory.cc @@ -98,6 +98,12 @@ CacheMemory::~CacheMemory() { if(m_replacementPolicy_ptr != NULL) delete m_replacementPolicy_ptr; + delete m_profiler_ptr; + for (int i = 0; i < m_cache_num_sets; i++) { + for (int j = 0; j < m_cache_assoc; j++) { + delete m_cache[i][j]; + } + } } void CacheMemory::printConfig(ostream& out) -- cgit v1.2.3 From 7b8fcecf11813492d770a0d766fb9a9fb01be3e2 Mon Sep 17 00:00:00 2001 From: Brad Beckmann Date: Wed, 18 Nov 2009 16:34:31 -0800 Subject: ruby: cache configuration fix to use bytes Changed cache size to be in bytes instead of kb so that testers can use very small caches and increase the chance of writeback races. --- src/mem/ruby/system/CacheMemory.cc | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) (limited to 'src/mem/ruby/system') diff --git a/src/mem/ruby/system/CacheMemory.cc b/src/mem/ruby/system/CacheMemory.cc index 04adbcf69..a5c881a61 100644 --- a/src/mem/ruby/system/CacheMemory.cc +++ b/src/mem/ruby/system/CacheMemory.cc @@ -52,12 +52,12 @@ CacheMemory::CacheMemory(const string & name) void CacheMemory::init(const vector & argv) { - int cache_size = 0; + int cache_size = -1; string policy; m_controller = NULL; for (uint32 i=0; i & argv) } } - m_cache_num_sets = cache_size / m_cache_assoc; + assert(cache_size != -1); + + m_cache_num_sets = (cache_size / m_cache_assoc) / RubySystem::getBlockSizeBytes(); + assert(m_cache_num_sets > 1); m_cache_num_set_bits = log_int(m_cache_num_sets); + assert(m_cache_num_set_bits > 0); if(policy == "PSEUDO_LRU") m_replacementPolicy_ptr = new PseudoLRUPolicy(m_cache_num_sets, m_cache_assoc); -- cgit v1.2.3 From 2783a7b9ad90d04d74418d7463c255c29ffd8046 Mon Sep 17 00:00:00 2001 From: Brad Beckmann Date: Wed, 18 Nov 2009 16:34:31 -0800 Subject: ruby: returns the number of LLC needed for broadcast Added feature to CacheMemory to return the number of last level caches. This count is need for broadcast protocols such as MOESI_hammer. --- src/mem/ruby/system/CacheMemory.cc | 18 ++++++++++++++++++ src/mem/ruby/system/CacheMemory.hh | 4 ++++ 2 files changed, 22 insertions(+) (limited to 'src/mem/ruby/system') diff --git a/src/mem/ruby/system/CacheMemory.cc b/src/mem/ruby/system/CacheMemory.cc index a5c881a61..630b94542 100644 --- a/src/mem/ruby/system/CacheMemory.cc +++ b/src/mem/ruby/system/CacheMemory.cc @@ -28,6 +28,9 @@ #include "mem/ruby/system/CacheMemory.hh" +int CacheMemory::m_num_last_level_caches = 0; +MachineType CacheMemory::m_last_level_machine_type = MachineType_FIRST; + // Output operator declaration //ostream& operator<<(ostream& out, const CacheMemory& obj); @@ -55,6 +58,8 @@ void CacheMemory::init(const vector & argv) int cache_size = -1; string policy; + m_num_last_level_caches = + MachineType_base_count(MachineType_FIRST); m_controller = NULL; for (uint32 i=0; i & argv) policy = argv[i+1]; } else if (argv[i] == "controller") { m_controller = RubySystem::getController(argv[i+1]); + if (m_last_level_machine_type < m_controller->getMachineType()) { + m_num_last_level_caches = + MachineType_base_count(m_controller->getMachineType()); + m_last_level_machine_type = + m_controller->getMachineType(); + } } else { cerr << "WARNING: CacheMemory: Unknown configuration parameter: " << argv[i] << endl; } @@ -110,6 +121,13 @@ CacheMemory::~CacheMemory() } } +int +CacheMemory::numberOfLastLevelCaches() +{ + return m_num_last_level_caches; +} + + void CacheMemory::printConfig(ostream& out) { out << "Cache config: " << m_cache_name << endl; diff --git a/src/mem/ruby/system/CacheMemory.hh b/src/mem/ruby/system/CacheMemory.hh index 00cd8ae35..856b7bcac 100644 --- a/src/mem/ruby/system/CacheMemory.hh +++ b/src/mem/ruby/system/CacheMemory.hh @@ -70,6 +70,8 @@ public: // static CacheMemory* createCache(int level, int num, char split_type, AbstractCacheEntry* (*entry_factory)()); // static CacheMemory* getCache(int cache_id); + static int numberOfLastLevelCaches(); + // Public Methods void printConfig(ostream& out); @@ -167,6 +169,8 @@ private: int m_cache_num_set_bits; int m_cache_assoc; + static int m_num_last_level_caches; + static MachineType m_last_level_machine_type; static Vector< CacheMemory* > m_all_caches; }; -- cgit v1.2.3 From 8011e80725dfd2cba0cdc19917a0f740a1b40a06 Mon Sep 17 00:00:00 2001 From: Brad Beckmann Date: Wed, 18 Nov 2009 16:34:32 -0800 Subject: ruby: The persistent table files from GEMS These files are need by the MOESI_CMP_token protocol. --- src/mem/ruby/system/PersistentTable.cc | 190 +++++++++++++++++++++++++++++++++ src/mem/ruby/system/PersistentTable.hh | 92 ++++++++++++++++ 2 files changed, 282 insertions(+) create mode 100644 src/mem/ruby/system/PersistentTable.cc create mode 100644 src/mem/ruby/system/PersistentTable.hh (limited to 'src/mem/ruby/system') diff --git a/src/mem/ruby/system/PersistentTable.cc b/src/mem/ruby/system/PersistentTable.cc new file mode 100644 index 000000000..1e056f6e5 --- /dev/null +++ b/src/mem/ruby/system/PersistentTable.cc @@ -0,0 +1,190 @@ + +/* + * 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 "PersistentTable.hh" +#include "NetDest.h" +#include "Map.h" +#include "Address.h" +#include "AbstractChip.h" +#include "util.h" + +// randomize so that handoffs are not locality-aware +// int persistent_randomize[] = {0, 4, 8, 12, 1, 5, 9, 13, 2, 6, 10, 14, 3, 7, 11, 15}; +// int persistent_randomize[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}; + + +class PersistentTableEntry { +public: + NetDest m_starving; + NetDest m_marked; + NetDest m_request_to_write; +}; + +PersistentTable::PersistentTable(AbstractChip* chip_ptr, int version) +{ + m_chip_ptr = chip_ptr; + m_map_ptr = new Map; + m_version = version; +} + +PersistentTable::~PersistentTable() +{ + delete m_map_ptr; + m_map_ptr = NULL; + m_chip_ptr = NULL; +} + +void PersistentTable::persistentRequestLock(const Address& address, MachineID locker, AccessType type) +{ + + // if (locker == m_chip_ptr->getID() ) + // cout << "Chip " << m_chip_ptr->getID() << ": " << llocker << " requesting lock for " << address << endl; + + // MachineID locker = (MachineID) persistent_randomize[llocker]; + + assert(address == line_address(address)); + if (!m_map_ptr->exist(address)) { + // Allocate if not present + PersistentTableEntry entry; + entry.m_starving.add(locker); + if (type == AccessType_Write) { + entry.m_request_to_write.add(locker); + } + m_map_ptr->add(address, entry); + } else { + PersistentTableEntry& entry = m_map_ptr->lookup(address); + assert(!(entry.m_starving.isElement(locker))); // Make sure we're not already in the locked set + + entry.m_starving.add(locker); + if (type == AccessType_Write) { + entry.m_request_to_write.add(locker); + } + assert(entry.m_marked.isSubset(entry.m_starving)); + } +} + +void PersistentTable::persistentRequestUnlock(const Address& address, MachineID unlocker) +{ + // if (unlocker == m_chip_ptr->getID() ) + // cout << "Chip " << m_chip_ptr->getID() << ": " << uunlocker << " requesting unlock for " << address << endl; + + // MachineID unlocker = (MachineID) persistent_randomize[uunlocker]; + + assert(address == line_address(address)); + assert(m_map_ptr->exist(address)); + PersistentTableEntry& entry = m_map_ptr->lookup(address); + assert(entry.m_starving.isElement(unlocker)); // Make sure we're in the locked set + assert(entry.m_marked.isSubset(entry.m_starving)); + entry.m_starving.remove(unlocker); + entry.m_marked.remove(unlocker); + entry.m_request_to_write.remove(unlocker); + assert(entry.m_marked.isSubset(entry.m_starving)); + + // Deallocate if empty + if (entry.m_starving.isEmpty()) { + assert(entry.m_marked.isEmpty()); + m_map_ptr->erase(address); + } +} + +bool PersistentTable::okToIssueStarving(const Address& address) const +{ + assert(address == line_address(address)); + if (!m_map_ptr->exist(address)) { + return true; // No entry present + } else if (m_map_ptr->lookup(address).m_starving.isElement( (MachineID) {MachineType_L1Cache, m_version})) { + return false; // We can't issue another lockdown until are previous unlock has occurred + } else { + return (m_map_ptr->lookup(address).m_marked.isEmpty()); + } +} + +MachineID PersistentTable::findSmallest(const Address& address) const +{ + assert(address == line_address(address)); + assert(m_map_ptr->exist(address)); + const PersistentTableEntry& entry = m_map_ptr->lookup(address); + // cout << "Node " << m_chip_ptr->getID() << " returning " << persistent_randomize[entry.m_starving.smallestElement()] << " for findSmallest(" << address << ")" << endl; + // return (MachineID) persistent_randomize[entry.m_starving.smallestElement()]; + return (MachineID) { MachineType_L1Cache, entry.m_starving.smallestElement() }; +} + +AccessType PersistentTable::typeOfSmallest(const Address& address) const +{ + assert(address == line_address(address)); + assert(m_map_ptr->exist(address)); + const PersistentTableEntry& entry = m_map_ptr->lookup(address); + if (entry.m_request_to_write.isElement((MachineID) {MachineType_L1Cache, entry.m_starving.smallestElement()})) { + return AccessType_Write; + } else { + return AccessType_Read; + } +} + +void PersistentTable::markEntries(const Address& address) +{ + assert(address == line_address(address)); + if (m_map_ptr->exist(address)) { + PersistentTableEntry& entry = m_map_ptr->lookup(address); + assert(entry.m_marked.isEmpty()); // None should be marked + entry.m_marked = entry.m_starving; // Mark all the nodes currently in the table + } +} + +bool PersistentTable::isLocked(const Address& address) const +{ + assert(address == line_address(address)); + // If an entry is present, it must be locked + return (m_map_ptr->exist(address)); +} + +int PersistentTable::countStarvingForAddress(const Address& address) const +{ + if (m_map_ptr->exist(address)) { + PersistentTableEntry& entry = m_map_ptr->lookup(address); + return (entry.m_starving.count()); + } + else { + return 0; + } +} + +int PersistentTable::countReadStarvingForAddress(const Address& address) const +{ + int count = 0; + if (m_map_ptr->exist(address)) { + PersistentTableEntry& entry = m_map_ptr->lookup(address); + return (entry.m_starving.count() - entry.m_request_to_write.count()); + } + else { + return 0; + } +} + + diff --git a/src/mem/ruby/system/PersistentTable.hh b/src/mem/ruby/system/PersistentTable.hh new file mode 100644 index 000000000..ab000843d --- /dev/null +++ b/src/mem/ruby/system/PersistentTable.hh @@ -0,0 +1,92 @@ + +/* + * 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 PersistentTable_H +#define PersistentTable_H + +#include "Global.h" +#include "MachineID.h" +#include "AccessType.h" + +class AbstractChip; + +template class Map; +class Address; +class PersistentTableEntry; + +class PersistentTable { +public: + // Constructors + PersistentTable(AbstractChip* chip_ptr, int version); + + // Destructor + ~PersistentTable(); + + // Public Methods + void persistentRequestLock(const Address& address, MachineID locker, AccessType type); + void persistentRequestUnlock(const Address& address, MachineID unlocker); + bool okToIssueStarving(const Address& address) const; + MachineID findSmallest(const Address& address) const; + AccessType typeOfSmallest(const Address& address) const; + void markEntries(const Address& address); + bool isLocked(const Address& addr) const; + int countStarvingForAddress(const Address& addr) const; + int countReadStarvingForAddress(const Address& addr) const; + + static void printConfig(ostream& out) {} + + void print(ostream& out) const; +private: + // Private Methods + + // Private copy constructor and assignment operator + PersistentTable(const PersistentTable& obj); + PersistentTable& operator=(const PersistentTable& obj); + + // Data Members (m_prefix) + Map* m_map_ptr; + AbstractChip* m_chip_ptr; + int m_version; +}; + +// Output operator declaration +ostream& operator<<(ostream& out, const PersistentTable& obj); + +// ******************* Definitions ******************* + +// Output operator definition +extern inline +ostream& operator<<(ostream& out, const PersistentTable& obj) +{ + obj.print(out); + out << flush; + return out; +} + +#endif //PersistentTable_H -- cgit v1.2.3 From 5d8a669539a142ece820cf0c82722ea1c755d7cd Mon Sep 17 00:00:00 2001 From: Brad Beckmann Date: Wed, 18 Nov 2009 16:34:33 -0800 Subject: Resurrection of the CMP token protocol to GEM5 --- src/mem/ruby/system/PersistentTable.cc | 82 ++++++++++++++++++++-------------- src/mem/ruby/system/PersistentTable.hh | 40 ++++++++++------- src/mem/ruby/system/SConscript | 1 + 3 files changed, 74 insertions(+), 49 deletions(-) (limited to 'src/mem/ruby/system') diff --git a/src/mem/ruby/system/PersistentTable.cc b/src/mem/ruby/system/PersistentTable.cc index 1e056f6e5..58b67ea60 100644 --- a/src/mem/ruby/system/PersistentTable.cc +++ b/src/mem/ruby/system/PersistentTable.cc @@ -27,44 +27,33 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include "PersistentTable.hh" -#include "NetDest.h" -#include "Map.h" -#include "Address.h" -#include "AbstractChip.h" -#include "util.h" +#include "mem/ruby/system/PersistentTable.hh" +#include "mem/gems_common/util.hh" // randomize so that handoffs are not locality-aware // int persistent_randomize[] = {0, 4, 8, 12, 1, 5, 9, 13, 2, 6, 10, 14, 3, 7, 11, 15}; // int persistent_randomize[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}; -class PersistentTableEntry { -public: - NetDest m_starving; - NetDest m_marked; - NetDest m_request_to_write; -}; - -PersistentTable::PersistentTable(AbstractChip* chip_ptr, int version) +PersistentTable::PersistentTable() { - m_chip_ptr = chip_ptr; m_map_ptr = new Map; - m_version = version; } PersistentTable::~PersistentTable() { delete m_map_ptr; m_map_ptr = NULL; - m_chip_ptr = NULL; } -void PersistentTable::persistentRequestLock(const Address& address, MachineID locker, AccessType type) +void PersistentTable::persistentRequestLock(const Address& address, + MachineID locker, + AccessType type) { // if (locker == m_chip_ptr->getID() ) - // cout << "Chip " << m_chip_ptr->getID() << ": " << llocker << " requesting lock for " << address << endl; + // cout << "Chip " << m_chip_ptr->getID() << ": " << llocker + // << " requesting lock for " << address << endl; // MachineID locker = (MachineID) persistent_randomize[llocker]; @@ -79,7 +68,11 @@ void PersistentTable::persistentRequestLock(const Address& address, MachineID lo m_map_ptr->add(address, entry); } else { PersistentTableEntry& entry = m_map_ptr->lookup(address); - assert(!(entry.m_starving.isElement(locker))); // Make sure we're not already in the locked set + + // + // Make sure we're not already in the locked set + // + assert(!(entry.m_starving.isElement(locker))); entry.m_starving.add(locker); if (type == AccessType_Write) { @@ -89,17 +82,23 @@ void PersistentTable::persistentRequestLock(const Address& address, MachineID lo } } -void PersistentTable::persistentRequestUnlock(const Address& address, MachineID unlocker) +void PersistentTable::persistentRequestUnlock(const Address& address, + MachineID unlocker) { // if (unlocker == m_chip_ptr->getID() ) - // cout << "Chip " << m_chip_ptr->getID() << ": " << uunlocker << " requesting unlock for " << address << endl; + // cout << "Chip " << m_chip_ptr->getID() << ": " << uunlocker + // << " requesting unlock for " << address << endl; // MachineID unlocker = (MachineID) persistent_randomize[uunlocker]; assert(address == line_address(address)); assert(m_map_ptr->exist(address)); PersistentTableEntry& entry = m_map_ptr->lookup(address); - assert(entry.m_starving.isElement(unlocker)); // Make sure we're in the locked set + + // + // Make sure we're in the locked set + // + assert(entry.m_starving.isElement(unlocker)); assert(entry.m_marked.isSubset(entry.m_starving)); entry.m_starving.remove(unlocker); entry.m_marked.remove(unlocker); @@ -113,13 +112,20 @@ void PersistentTable::persistentRequestUnlock(const Address& address, MachineID } } -bool PersistentTable::okToIssueStarving(const Address& address) const +bool PersistentTable::okToIssueStarving(const Address& address, + MachineID machId) const { assert(address == line_address(address)); if (!m_map_ptr->exist(address)) { - return true; // No entry present - } else if (m_map_ptr->lookup(address).m_starving.isElement( (MachineID) {MachineType_L1Cache, m_version})) { - return false; // We can't issue another lockdown until are previous unlock has occurred + // + // No entry present + // + return true; + } else if (m_map_ptr->lookup(address).m_starving.isElement(machId)) { + // + // We can't issue another lockdown until are previous unlock has occurred + // + return false; } else { return (m_map_ptr->lookup(address).m_marked.isEmpty()); } @@ -130,9 +136,7 @@ MachineID PersistentTable::findSmallest(const Address& address) const assert(address == line_address(address)); assert(m_map_ptr->exist(address)); const PersistentTableEntry& entry = m_map_ptr->lookup(address); - // cout << "Node " << m_chip_ptr->getID() << " returning " << persistent_randomize[entry.m_starving.smallestElement()] << " for findSmallest(" << address << ")" << endl; - // return (MachineID) persistent_randomize[entry.m_starving.smallestElement()]; - return (MachineID) { MachineType_L1Cache, entry.m_starving.smallestElement() }; + return entry.m_starving.smallestElement(); } AccessType PersistentTable::typeOfSmallest(const Address& address) const @@ -140,7 +144,7 @@ AccessType PersistentTable::typeOfSmallest(const Address& address) const assert(address == line_address(address)); assert(m_map_ptr->exist(address)); const PersistentTableEntry& entry = m_map_ptr->lookup(address); - if (entry.m_request_to_write.isElement((MachineID) {MachineType_L1Cache, entry.m_starving.smallestElement()})) { + if (entry.m_request_to_write.isElement(entry.m_starving.smallestElement())) { return AccessType_Write; } else { return AccessType_Read; @@ -152,8 +156,16 @@ void PersistentTable::markEntries(const Address& address) assert(address == line_address(address)); if (m_map_ptr->exist(address)) { PersistentTableEntry& entry = m_map_ptr->lookup(address); - assert(entry.m_marked.isEmpty()); // None should be marked - entry.m_marked = entry.m_starving; // Mark all the nodes currently in the table + + // + // None should be marked + // + assert(entry.m_marked.isEmpty()); + + // + // Mark all the nodes currently in the table + // + entry.m_marked = entry.m_starving; } } @@ -177,7 +189,6 @@ int PersistentTable::countStarvingForAddress(const Address& address) const int PersistentTable::countReadStarvingForAddress(const Address& address) const { - int count = 0; if (m_map_ptr->exist(address)) { PersistentTableEntry& entry = m_map_ptr->lookup(address); return (entry.m_starving.count() - entry.m_request_to_write.count()); @@ -187,4 +198,7 @@ int PersistentTable::countReadStarvingForAddress(const Address& address) const } } +void PersistentTable::print(ostream& out) const +{ +} diff --git a/src/mem/ruby/system/PersistentTable.hh b/src/mem/ruby/system/PersistentTable.hh index ab000843d..8cbb48817 100644 --- a/src/mem/ruby/system/PersistentTable.hh +++ b/src/mem/ruby/system/PersistentTable.hh @@ -30,20 +30,26 @@ #ifndef PersistentTable_H #define PersistentTable_H -#include "Global.h" -#include "MachineID.h" -#include "AccessType.h" +#include "mem/ruby/common/Global.hh" +#include "mem/gems_common/Map.hh" +#include "mem/ruby/common/Address.hh" +#include "mem/ruby/system/MachineID.hh" +#include "mem/protocol/AccessType.hh" +#include "mem/ruby/common/NetDest.hh" -class AbstractChip; +class PersistentTableEntry { +public: + void print(ostream& out) const {} -template class Map; -class Address; -class PersistentTableEntry; + NetDest m_starving; + NetDest m_marked; + NetDest m_request_to_write; +}; class PersistentTable { public: // Constructors - PersistentTable(AbstractChip* chip_ptr, int version); + PersistentTable(); // Destructor ~PersistentTable(); @@ -51,7 +57,7 @@ public: // Public Methods void persistentRequestLock(const Address& address, MachineID locker, AccessType type); void persistentRequestUnlock(const Address& address, MachineID unlocker); - bool okToIssueStarving(const Address& address) const; + bool okToIssueStarving(const Address& address, MachineID machID) const; MachineID findSmallest(const Address& address) const; AccessType typeOfSmallest(const Address& address) const; void markEntries(const Address& address); @@ -71,17 +77,12 @@ private: // Data Members (m_prefix) Map* m_map_ptr; - AbstractChip* m_chip_ptr; - int m_version; }; -// Output operator declaration -ostream& operator<<(ostream& out, const PersistentTable& obj); - // ******************* Definitions ******************* // Output operator definition -extern inline +extern inline ostream& operator<<(ostream& out, const PersistentTable& obj) { obj.print(out); @@ -89,4 +90,13 @@ ostream& operator<<(ostream& out, const PersistentTable& obj) return out; } +// Output operator definition +extern inline +ostream& operator<<(ostream& out, const PersistentTableEntry& obj) +{ + obj.print(out); + out << flush; + return out; +} + #endif //PersistentTable_H diff --git a/src/mem/ruby/system/SConscript b/src/mem/ruby/system/SConscript index 496fce2fd..4ca1af114 100644 --- a/src/mem/ruby/system/SConscript +++ b/src/mem/ruby/system/SConscript @@ -38,6 +38,7 @@ Source('DirectoryMemory.cc') Source('CacheMemory.cc') Source('MemoryControl.cc') Source('MemoryNode.cc') +Source('PersistentTable.cc') Source('RubyPort.cc') Source('Sequencer.cc', Werror=False) Source('System.cc') -- cgit v1.2.3