diff options
Diffstat (limited to 'src/mem/ruby/system')
31 files changed, 3046 insertions, 3187 deletions
diff --git a/src/mem/ruby/system/AbstractMemOrCache.hh b/src/mem/ruby/system/AbstractMemOrCache.hh index 4a8b667e8..28b446ef8 100644 --- a/src/mem/ruby/system/AbstractMemOrCache.hh +++ b/src/mem/ruby/system/AbstractMemOrCache.hh @@ -26,42 +26,34 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -/* - * AbstractMemOrCache.hh - * - * Description: - * - * - */ - -#ifndef ABSTRACT_MEM_OR_CACHE_H -#define ABSTRACT_MEM_OR_CACHE_H - -#include "mem/ruby/common/Global.hh" -#include "mem/ruby/common/Address.hh" - -class AbstractMemOrCache { -public: - - virtual ~AbstractMemOrCache() {}; - virtual void setConsumer(Consumer* consumer_ptr) = 0; - virtual Consumer* getConsumer() = 0; - - virtual void enqueue (const MsgPtr& message, int latency ) = 0; - virtual void enqueueMemRef (MemoryNode& memRef) = 0; - virtual void dequeue () = 0; - virtual const Message* peek () = 0; - virtual bool isReady () = 0; - virtual MemoryNode peekNode () = 0; - virtual bool areNSlotsAvailable (int n) = 0; - virtual void printConfig (ostream& out) = 0; - virtual void print (ostream& out) const = 0; - virtual void setDebug (int debugFlag) = 0; - -private: - +#ifndef __MEM_RUBY_SYSTEM_ABSTRACTMEMORCACHE_HH__ +#define __MEM_RUBY_SYSTEM_ABSTRACTMEMORCACHE_HH__ + +#include <iosfwd> + +#include "mem/ruby/slicc_interface/Message.hh" + +class Consumer; +class MemoryNode; +class Message; + +class AbstractMemOrCache +{ + public: + virtual ~AbstractMemOrCache() {}; + virtual void setConsumer(Consumer* consumer_ptr) = 0; + virtual Consumer* getConsumer() = 0; + + virtual void enqueue (const MsgPtr& message, int latency) = 0; + virtual void enqueueMemRef (MemoryNode& memRef) = 0; + virtual void dequeue () = 0; + virtual const Message* peek () = 0; + virtual bool isReady () = 0; + virtual MemoryNode peekNode () = 0; + virtual bool areNSlotsAvailable (int n) = 0; + virtual void printConfig (std::ostream& out) = 0; + virtual void print (std::ostream& out) const = 0; + virtual void setDebug (int debugFlag) = 0; }; - -#endif - +#endif // __MEM_RUBY_SYSTEM_ABSTRACTMEMORCACHE_HH__ diff --git a/src/mem/ruby/system/AbstractReplacementPolicy.hh b/src/mem/ruby/system/AbstractReplacementPolicy.hh index f06b8b8ee..3ddf4ab60 100644 --- a/src/mem/ruby/system/AbstractReplacementPolicy.hh +++ b/src/mem/ruby/system/AbstractReplacementPolicy.hh @@ -26,64 +26,64 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef ABSTRACTREPLACEMENTPOLICY_H -#define ABSTRACTREPLACEMENTPOLICY_H +#ifndef __MEM_RUBY_SYSTEM_ABSTRACTREPLACEMENTPOLICY_HH__ +#define __MEM_RUBY_SYSTEM_ABSTRACTREPLACEMENTPOLICY_HH__ #include "mem/ruby/common/Global.hh" -class AbstractReplacementPolicy { - -public: - - AbstractReplacementPolicy(Index num_sets, Index assoc); - virtual ~AbstractReplacementPolicy(); +class AbstractReplacementPolicy +{ + public: + AbstractReplacementPolicy(Index num_sets, Index assoc); + virtual ~AbstractReplacementPolicy(); - /* touch a block. a.k.a. update timestamp */ - virtual void touch(Index set, Index way, Time time) = 0; + /* touch a block. a.k.a. update timestamp */ + virtual void touch(Index set, Index way, Time time) = 0; - /* returns the way to replace */ - virtual Index getVictim(Index set) const = 0; + /* returns the way to replace */ + virtual Index getVictim(Index set) const = 0; - /* get the time of the last access */ - Time getLastAccess(Index set, Index way); + /* get the time of the last access */ + Time getLastAccess(Index set, Index way); - protected: - unsigned int m_num_sets; /** total number of sets */ - unsigned int m_assoc; /** set associativity */ - Time **m_last_ref_ptr; /** timestamp of last reference */ + protected: + unsigned m_num_sets; /** total number of sets */ + unsigned m_assoc; /** set associativity */ + Time **m_last_ref_ptr; /** timestamp of last reference */ }; inline -AbstractReplacementPolicy::AbstractReplacementPolicy(Index num_sets, Index assoc) +AbstractReplacementPolicy::AbstractReplacementPolicy(Index num_sets, + Index assoc) { - m_num_sets = num_sets; - m_assoc = assoc; - m_last_ref_ptr = new Time*[m_num_sets]; - for(unsigned int i = 0; i < m_num_sets; i++){ - m_last_ref_ptr[i] = new Time[m_assoc]; - for(unsigned int j = 0; j < m_assoc; j++){ - m_last_ref_ptr[i][j] = 0; + m_num_sets = num_sets; + m_assoc = assoc; + m_last_ref_ptr = new Time*[m_num_sets]; + for(unsigned i = 0; i < m_num_sets; i++){ + m_last_ref_ptr[i] = new Time[m_assoc]; + for(unsigned j = 0; j < m_assoc; j++){ + m_last_ref_ptr[i][j] = 0; + } } - } } inline AbstractReplacementPolicy::~AbstractReplacementPolicy() { - if(m_last_ref_ptr != NULL){ - for(unsigned int i = 0; i < m_num_sets; i++){ - if(m_last_ref_ptr[i] != NULL){ - delete[] m_last_ref_ptr[i]; - } + if (m_last_ref_ptr != NULL){ + for (unsigned i = 0; i < m_num_sets; i++){ + if (m_last_ref_ptr[i] != NULL){ + delete[] m_last_ref_ptr[i]; + } + } + delete[] m_last_ref_ptr; } - delete[] m_last_ref_ptr; - } } -inline -Time AbstractReplacementPolicy::getLastAccess(Index set, Index way) +inline Time +AbstractReplacementPolicy::getLastAccess(Index set, Index way) { - return m_last_ref_ptr[set][way]; + return m_last_ref_ptr[set][way]; } -#endif // ABSTRACTREPLACEMENTPOLICY_H +#endif // __MEM_RUBY_SYSTEM_ABSTRACTREPLACEMENTPOLICY_HH__ diff --git a/src/mem/ruby/system/CacheMemory.cc b/src/mem/ruby/system/CacheMemory.cc index 35625245a..10ea8a6fc 100644 --- a/src/mem/ruby/system/CacheMemory.cc +++ b/src/mem/ruby/system/CacheMemory.cc @@ -28,19 +28,14 @@ #include "mem/ruby/system/CacheMemory.hh" -// ******************* Definitions ******************* - -// Output operator definition -ostream& operator<<(ostream& out, const CacheMemory& obj) +ostream& +operator<<(ostream& out, const CacheMemory& obj) { - obj.print(out); - out << flush; - return out; + obj.print(out); + out << flush; + return out; } - -// **************************************************************** - CacheMemory * RubyCacheParams::create() { @@ -57,410 +52,451 @@ CacheMemory::CacheMemory(const Params *p) m_profiler_ptr = new CacheProfiler(name()); } - -void CacheMemory::init() +void +CacheMemory::init() { - m_cache_num_sets = (m_cache_size / m_cache_assoc) / RubySystem::getBlockSizeBytes(); + m_cache_num_sets = (m_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(m_policy == "PSEUDO_LRU") - m_replacementPolicy_ptr = new PseudoLRUPolicy(m_cache_num_sets, m_cache_assoc); + + if (m_policy == "PSEUDO_LRU") + m_replacementPolicy_ptr = + new PseudoLRUPolicy(m_cache_num_sets, m_cache_assoc); else if (m_policy == "LRU") - m_replacementPolicy_ptr = new LRUPolicy(m_cache_num_sets, m_cache_assoc); + m_replacementPolicy_ptr = + new LRUPolicy(m_cache_num_sets, m_cache_assoc); else - assert(false); - - m_cache.setSize(m_cache_num_sets); - m_locked.setSize(m_cache_num_sets); - for (int i = 0; i < m_cache_num_sets; i++) { - m_cache[i].setSize(m_cache_assoc); - m_locked[i].setSize(m_cache_assoc); - for (int j = 0; j < m_cache_assoc; j++) { - m_cache[i][j] = NULL; - m_locked[i][j] = -1; + assert(false); + + m_cache.setSize(m_cache_num_sets); + m_locked.setSize(m_cache_num_sets); + for (int i = 0; i < m_cache_num_sets; i++) { + m_cache[i].setSize(m_cache_assoc); + m_locked[i].setSize(m_cache_assoc); + for (int j = 0; j < m_cache_assoc; j++) { + m_cache[i][j] = NULL; + m_locked[i][j] = -1; + } } - } } 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]; + 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) +void +CacheMemory::printConfig(ostream& out) { - out << "Cache config: " << m_cache_name << 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; + int block_size = RubySystem::getBlockSizeBytes(); + + out << "Cache config: " << m_cache_name << 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 * block_size << endl; + out << " cache_set_size_Kbytes: " + << double(cache_num_sets * block_size) / (1<<10) << endl; + out << " cache_set_size_Mbytes: " + << double(cache_num_sets * block_size) / (1<<20) << endl; + out << " cache_size_bytes: " + << cache_num_sets * block_size * m_cache_assoc << endl; + out << " cache_size_Kbytes: " + << double(cache_num_sets * block_size * m_cache_assoc) / (1<<10) + << endl; + out << " cache_size_Mbytes: " + << double(cache_num_sets * block_size * m_cache_assoc) / (1<<20) + << endl; } -// PRIVATE METHODS - // convert a Address to its location in the cache -Index CacheMemory::addressToCacheSet(const Address& address) const +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); + 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 +int +CacheMemory::findTagInSet(Index cacheSet, const Address& tag) const { - assert(tag == line_address(tag)); - // search the set for the tags - m5::hash_map<Address, int>::const_iterator it = m_tag_index.find(tag); - if (it != m_tag_index.end()) - if (m_cache[cacheSet][it->second]->m_Permission != AccessPermission_NotPresent) - return it->second; - return -1; // Not found + assert(tag == line_address(tag)); + // search the set for the tags + m5::hash_map<Address, int>::const_iterator it = m_tag_index.find(tag); + if (it != m_tag_index.end()) + if (m_cache[cacheSet][it->second]->m_Permission != + AccessPermission_NotPresent) + return it->second; + 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 - m5::hash_map<Address, int>::const_iterator it = m_tag_index.find(tag); - if (it != m_tag_index.end()) - return it->second; - 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; +int +CacheMemory::findTagInSetIgnorePermissions(Index cacheSet, + const Address& tag) const +{ + assert(tag == line_address(tag)); + // search the set for the tags + m5::hash_map<Address, int>::const_iterator it = m_tag_index.find(tag); + if (it != m_tag_index.end()) + return it->second; + return -1; // Not found +} + +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 } - // The line must not be accessible - } - data_ptr = NULL; - return false; + data_ptr = NULL; + return false; } -bool CacheMemory::testCacheAccess(const Address& address, - CacheRequestType type, - DataBlock*& data_ptr) +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()); + 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; + } - return (m_cache[cacheSet][loc]->m_Permission != AccessPermission_NotPresent); - } - data_ptr = NULL; - return false; + data_ptr = NULL; + return false; } // tests to see if an address is present in the cache -bool CacheMemory::isTagPresent(const Address& address) const +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 + assert(address == line_address(address)); + Index cacheSet = addressToCacheSet(address); + int loc = findTagInSet(cacheSet, address); + + if (loc == -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, "No tag match"); - return false; - } - DEBUG_EXPR(CACHE_COMP, LowPrio, address); - DEBUG_MSG(CACHE_COMP, LowPrio, "found"); - return true; + 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 +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; + 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 || + entry->m_Permission == AccessPermission_NotPresent) { + // Already in the cache or we found an empty entry + return true; + } + } else { + return true; + } } - } - return false; + return false; } -void CacheMemory::allocate(const Address& address, AbstractCacheEntry* entry) +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; - DPRINTF(RubyCache, "Allocate clearing lock for addr: %llx\n", address); - m_locked[cacheSet][i] = -1; - m_tag_index[address] = i; - - m_replacementPolicy_ptr->touch(cacheSet, i, g_eventQueue_ptr->getTime()); - - return; + 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); + Vector<AbstractCacheEntry*> &set = m_cache[cacheSet]; + for (int i = 0; i < m_cache_assoc; i++) { + if (!set[i] || set[i]->m_Permission == AccessPermission_NotPresent) { + set[i] = entry; // Init entry + set[i]->m_Address = address; + set[i]->m_Permission = AccessPermission_Invalid; + DPRINTF(RubyCache, "Allocate clearing lock for addr: %x\n", + address); + m_locked[cacheSet][i] = -1; + m_tag_index[address] = i; + + m_replacementPolicy_ptr-> + touch(cacheSet, i, g_eventQueue_ptr->getTime()); + + return; + } } - } - ERROR_MSG("Allocate didn't find an available entry"); + ERROR_MSG("Allocate didn't find an available entry"); } -void CacheMemory::deallocate(const Address& address) +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; - DPRINTF(RubyCache, "Deallocate clearing lock for addr: %llx\n", address); - m_locked[cacheSet][location] = -1; - m_tag_index.erase(address); - } + assert(address == line_address(address)); + assert(isTagPresent(address)); + DEBUG_EXPR(CACHE_COMP, HighPrio, address); + Index cacheSet = addressToCacheSet(address); + int loc = findTagInSet(cacheSet, address); + if (loc != -1) { + delete m_cache[cacheSet][loc]; + m_cache[cacheSet][loc] = NULL; + DPRINTF(RubyCache, "Deallocate clearing lock for addr: %x\n", + address); + m_locked[cacheSet][loc] = -1; + m_tag_index.erase(address); + } } // Returns with the physical address of the conflicting cache line -Address CacheMemory::cacheProbe(const Address& address) const +Address +CacheMemory::cacheProbe(const Address& address) const { - assert(address == line_address(address)); - assert(!cacheAvail(address)); + assert(address == line_address(address)); + assert(!cacheAvail(address)); - Index cacheSet = addressToCacheSet(address); - return m_cache[cacheSet][m_replacementPolicy_ptr->getVictim(cacheSet)]->m_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) +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]; + 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 +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]; + 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 +AccessPermission +CacheMemory::getPermission(const Address& address) const { - assert(address == line_address(address)); - return lookup(address).m_Permission; + assert(address == line_address(address)); + return lookup(address).m_Permission; } -void CacheMemory::changePermission(const Address& address, AccessPermission new_perm) +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); - if (new_perm != AccessPermission_Read_Write) { - DPRINTF(RubyCache, "Permission clearing lock for addr: %llx\n", address); - m_locked[cacheSet][loc] = -1; - } - assert(getPermission(address) == new_perm); + assert(address == line_address(address)); + lookup(address).m_Permission = new_perm; + Index cacheSet = addressToCacheSet(address); + int loc = findTagInSet(cacheSet, address); + if (new_perm != AccessPermission_Read_Write) { + DPRINTF(RubyCache, "Permission clearing lock for addr: %x\n", 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) +void +CacheMemory::setMRU(const Address& address) { - Index cacheSet; + Index cacheSet; - cacheSet = addressToCacheSet(address); - m_replacementPolicy_ptr->touch(cacheSet, - findTagInSet(cacheSet, address), - g_eventQueue_ptr->getTime()); + cacheSet = addressToCacheSet(address); + m_replacementPolicy_ptr-> + touch(cacheSet, findTagInSet(cacheSet, address), + g_eventQueue_ptr->getTime()); } -void CacheMemory::profileMiss(const CacheMsg & msg) +void +CacheMemory::profileMiss(const CacheMsg& msg) { - m_profiler_ptr->addStatSample(msg.getType(), msg.getAccessMode(), - msg.getSize(), msg.getPrefetch()); + m_profiler_ptr->addStatSample(msg.getType(), msg.getAccessMode(), + msg.getSize(), msg.getPrefetch()); } -void CacheMemory::recordCacheContents(CacheRecorder& tr) const +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; + 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) { +#if 0 + tr.addRecord(m_chip_ptr->getID(), m_cache[i][j].m_Address, + Address(0), request_type, + m_replacementPolicy_ptr->getLastAccess(i, j)); +#endif + } } - } 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::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 +void +CacheMemory::printData(ostream& out) const { - out << "printData() not supported" << endl; + out << "printData() not supported" << endl; } -void CacheMemory::clearStats() const +void +CacheMemory::clearStats() const { - m_profiler_ptr->clearStats(); + m_profiler_ptr->clearStats(); } -void CacheMemory::printStats(ostream& out) const +void +CacheMemory::printStats(ostream& out) const { - m_profiler_ptr->printStats(out); + 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<size_in_bytes; ++i){ - value[i] = entry.getDataBlk().getByte(i + startByte); - } +void +CacheMemory::getMemoryValue(const Address& addr, char* value, + unsigned size_in_bytes) +{ + AbstractCacheEntry& entry = lookup(line_address(addr)); + unsigned startByte = addr.getAddress() - line_address(addr).getAddress(); + for (unsigned i = 0; i < size_in_bytes; ++i) { + value[i] = entry.getDataBlk().getByte(i + startByte); + } } -void CacheMemory::setMemoryValue(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(); - assert(size_in_bytes > 0); - for(unsigned int i=0; i<size_in_bytes; ++i){ - entry.getDataBlk().setByte(i + startByte, value[i]); - } +void +CacheMemory::setMemoryValue(const Address& addr, char* value, + unsigned size_in_bytes) +{ + AbstractCacheEntry& entry = lookup(line_address(addr)); + unsigned startByte = addr.getAddress() - line_address(addr).getAddress(); + assert(size_in_bytes > 0); + for (unsigned i = 0; i < size_in_bytes; ++i) { + entry.getDataBlk().setByte(i + startByte, value[i]); + } - // entry = lookup(line_address(addr)); + // entry = lookup(line_address(addr)); } -void -CacheMemory::setLocked(const Address& address, int context) -{ - DPRINTF(RubyCache, - "Setting Lock for addr: %llx to %d\n", - address, - context); - assert(address == line_address(address)); - Index cacheSet = addressToCacheSet(address); - int loc = findTagInSet(cacheSet, address); - assert(loc != -1); - m_locked[cacheSet][loc] = context; +void +CacheMemory::setLocked(const Address& address, int context) +{ + DPRINTF(RubyCache, "Setting Lock for addr: %x to %d\n", address, context); + assert(address == line_address(address)); + Index cacheSet = addressToCacheSet(address); + int loc = findTagInSet(cacheSet, address); + assert(loc != -1); + m_locked[cacheSet][loc] = context; } -void -CacheMemory::clearLocked(const Address& address) +void +CacheMemory::clearLocked(const Address& address) { - DPRINTF(RubyCache, "Clear Lock for addr: %llx\n", address); - assert(address == line_address(address)); - Index cacheSet = addressToCacheSet(address); - int loc = findTagInSet(cacheSet, address); - assert(loc != -1); - m_locked[cacheSet][loc] = -1; + DPRINTF(RubyCache, "Clear Lock for addr: %x\n", address); + assert(address == line_address(address)); + Index cacheSet = addressToCacheSet(address); + int loc = findTagInSet(cacheSet, address); + assert(loc != -1); + m_locked[cacheSet][loc] = -1; } bool CacheMemory::isLocked(const Address& address, int context) { - assert(address == line_address(address)); - Index cacheSet = addressToCacheSet(address); - int loc = findTagInSet(cacheSet, address); - assert(loc != -1); - DPRINTF(RubyCache, - "Testing Lock for addr: %llx cur %d con %d\n", - address, - m_locked[cacheSet][loc], - context); - return m_locked[cacheSet][loc] == context; + assert(address == line_address(address)); + Index cacheSet = addressToCacheSet(address); + int loc = findTagInSet(cacheSet, address); + assert(loc != -1); + DPRINTF(RubyCache, "Testing Lock for addr: %llx cur %d con %d\n", + address, m_locked[cacheSet][loc], context); + return m_locked[cacheSet][loc] == context; } diff --git a/src/mem/ruby/system/CacheMemory.hh b/src/mem/ruby/system/CacheMemory.hh index 74eb5d68d..bdf2bb25c 100644 --- a/src/mem/ruby/system/CacheMemory.hh +++ b/src/mem/ruby/system/CacheMemory.hh @@ -26,151 +26,144 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -/* - * CacheMemory.hh - * - * Description: - * - * $Id: CacheMemory.hh,v 3.7 2004/06/18 20:15:15 beckmann Exp $ - * - */ +#ifndef __MEM_RUBY_SYSTEM_CACHEMEMORY_HH__ +#define __MEM_RUBY_SYSTEM_CACHEMEMORY_HH__ -#ifndef CACHEMEMORY_H -#define CACHEMEMORY_H - -#include "sim/sim_object.hh" -#include "params/RubyCache.hh" +#include <vector> -#include "mem/ruby/common/Global.hh" +#include "base/hashmap.hh" +#include "mem/gems_common/Vector.hh" #include "mem/protocol/AccessPermission.hh" -#include "mem/ruby/common/Address.hh" -#include "mem/ruby/recorder/CacheRecorder.hh" +#include "mem/protocol/CacheMsg.hh" #include "mem/protocol/CacheRequestType.hh" -#include "mem/gems_common/Vector.hh" -#include "mem/ruby/common/DataBlock.hh" #include "mem/protocol/MachineType.hh" +#include "mem/ruby/common/Address.hh" +#include "mem/ruby/common/DataBlock.hh" +#include "mem/ruby/common/Global.hh" +#include "mem/ruby/profiler/CacheProfiler.hh" +#include "mem/ruby/recorder/CacheRecorder.hh" +#include "mem/ruby/slicc_interface/AbstractCacheEntry.hh" +#include "mem/ruby/slicc_interface/AbstractController.hh" #include "mem/ruby/slicc_interface/RubySlicc_ComponentMapping.hh" -#include "mem/ruby/system/PseudoLRUPolicy.hh" #include "mem/ruby/system/LRUPolicy.hh" -#include "mem/ruby/slicc_interface/AbstractCacheEntry.hh" +#include "mem/ruby/system/PseudoLRUPolicy.hh" #include "mem/ruby/system/System.hh" -#include "mem/ruby/slicc_interface/AbstractController.hh" -#include "mem/ruby/profiler/CacheProfiler.hh" -#include "mem/protocol/CacheMsg.hh" -#include "base/hashmap.hh" -#include <vector> - -class CacheMemory : public SimObject { -public: +#include "params/RubyCache.hh" +#include "sim/sim_object.hh" +class CacheMemory : public SimObject +{ + public: typedef RubyCacheParams Params; - // Constructors - CacheMemory(const Params *p); - // CacheMemory(const string & name); - void init(); - - // Destructor - ~CacheMemory(); + CacheMemory(const Params *p); + ~CacheMemory(); - // Public Methods - void printConfig(ostream& out); + void init(); - // perform a cache access and see if we hit or not. Return true on a hit. - bool tryCacheAccess(const Address& address, CacheRequestType type, DataBlock*& data_ptr); + // Public Methods + void printConfig(ostream& out); - // similar to above, but doesn't require full access check - bool testCacheAccess(const Address& address, CacheRequestType type, DataBlock*& data_ptr); + // perform a cache access and see if we hit or not. Return true on a hit. + bool tryCacheAccess(const Address& address, CacheRequestType type, + DataBlock*& data_ptr); - // tests to see if an address is present in the cache - bool isTagPresent(const Address& address) const; + // similar to above, but doesn't require full access check + bool testCacheAccess(const Address& address, CacheRequestType type, + DataBlock*& data_ptr); - // 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 cacheAvail(const Address& address) const; + // tests to see if an address is present in the cache + bool isTagPresent(const Address& address) const; - // find an unused entry and sets the tag appropriate for the address - void allocate(const Address& address, AbstractCacheEntry* new_entry); + // 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 cacheAvail(const Address& address) const; - // Explicitly free up this address - void deallocate(const Address& address); + // find an unused entry and sets the tag appropriate for the address + void allocate(const Address& address, AbstractCacheEntry* new_entry); - // Returns with the physical address of the conflicting cache line - Address cacheProbe(const Address& address) const; + // Explicitly free up this address + void deallocate(const Address& address); - // looks an address up in the cache - AbstractCacheEntry& lookup(const Address& address); - const AbstractCacheEntry& lookup(const Address& address) const; + // Returns with the physical address of the conflicting cache line + Address cacheProbe(const Address& address) const; - // Get/Set permission of cache block - AccessPermission getPermission(const Address& address) const; - void changePermission(const Address& address, AccessPermission new_perm); + // looks an address up in the cache + AbstractCacheEntry& lookup(const Address& address); + const AbstractCacheEntry& lookup(const Address& address) const; - int getLatency() const { return m_latency; } + // Get/Set permission of cache block + AccessPermission getPermission(const Address& address) const; + void changePermission(const Address& address, AccessPermission new_perm); - // Hook for checkpointing the contents of the cache - void recordCacheContents(CacheRecorder& tr) const; - void setAsInstructionCache(bool is_icache) { m_is_instruction_only_cache = is_icache; } + int getLatency() const { return m_latency; } - // Set this address to most recently used - void setMRU(const Address& address); + // Hook for checkpointing the contents of the cache + void recordCacheContents(CacheRecorder& tr) const; + void + setAsInstructionCache(bool is_icache) + { + m_is_instruction_only_cache = is_icache; + } - void profileMiss(const CacheMsg & msg); + // Set this address to most recently used + void setMRU(const Address& address); - void getMemoryValue(const Address& addr, char* value, - unsigned int size_in_bytes ); - void setMemoryValue(const Address& addr, char* value, - unsigned int size_in_bytes ); + void profileMiss(const CacheMsg & msg); - void setLocked (const Address& addr, int context); - void clearLocked (const Address& addr); - bool isLocked (const Address& addr, int context); - // Print cache contents - void print(ostream& out) const; - void printData(ostream& out) const; + void getMemoryValue(const Address& addr, char* value, + unsigned int size_in_bytes); + void setMemoryValue(const Address& addr, char* value, + unsigned int size_in_bytes); - void clearStats() const; - void printStats(ostream& out) const; + void setLocked (const Address& addr, int context); + void clearLocked (const Address& addr); + bool isLocked (const Address& addr, int context); + // Print cache contents + void print(ostream& out) const; + void printData(ostream& out) const; -private: - // Private Methods + void clearStats() const; + void printStats(ostream& out) const; - // convert a Address to its location in the cache - Index addressToCacheSet(const Address& address) const; + private: + // convert a Address to its location in the cache + Index addressToCacheSet(const Address& address) const; - // Given a cache tag: returns the index of the tag in a set. - // returns -1 if the tag is not found. - int findTagInSet(Index line, const Address& tag) const; - int findTagInSetIgnorePermissions(Index cacheSet, const Address& tag) const; + // Given a cache tag: returns the index of the tag in a set. + // returns -1 if the tag is not found. + int findTagInSet(Index line, const Address& tag) const; + int findTagInSetIgnorePermissions(Index cacheSet, + const Address& tag) const; - // Private copy constructor and assignment operator - CacheMemory(const CacheMemory& obj); - CacheMemory& operator=(const CacheMemory& obj); + // Private copy constructor and assignment operator + CacheMemory(const CacheMemory& obj); + CacheMemory& operator=(const CacheMemory& obj); -private: - const string m_cache_name; - int m_latency; + private: + const string m_cache_name; + int m_latency; - // Data Members (m_prefix) - bool m_is_instruction_only_cache; - bool m_is_data_only_cache; + // Data Members (m_prefix) + bool m_is_instruction_only_cache; + bool m_is_data_only_cache; - // The first index is the # of cache lines. - // The second index is the the amount associativity. - m5::hash_map<Address, int> m_tag_index; - Vector<Vector<AbstractCacheEntry*> > m_cache; - Vector<Vector<int> > m_locked; + // The first index is the # of cache lines. + // The second index is the the amount associativity. + m5::hash_map<Address, int> m_tag_index; + Vector<Vector<AbstractCacheEntry*> > m_cache; + Vector<Vector<int> > m_locked; - AbstractReplacementPolicy *m_replacementPolicy_ptr; + AbstractReplacementPolicy *m_replacementPolicy_ptr; - CacheProfiler* m_profiler_ptr; + CacheProfiler* m_profiler_ptr; - int m_cache_size; - string m_policy; - int m_cache_num_sets; - int m_cache_num_set_bits; - int m_cache_assoc; + int m_cache_size; + string m_policy; + int m_cache_num_sets; + int m_cache_num_set_bits; + int m_cache_assoc; }; -#endif //CACHEMEMORY_H +#endif // __MEM_RUBY_SYSTEM_CACHEMEMORY_HH__ diff --git a/src/mem/ruby/system/DMASequencer.cc b/src/mem/ruby/system/DMASequencer.cc index 063b66862..315dab62a 100644 --- a/src/mem/ruby/system/DMASequencer.cc +++ b/src/mem/ruby/system/DMASequencer.cc @@ -26,149 +26,148 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include "mem/ruby/system/DMASequencer.hh" -#include "mem/ruby/buffers/MessageBuffer.hh" -#include "mem/ruby/slicc_interface/AbstractController.hh" - -/* SLICC generated types */ #include "mem/protocol/SequencerMsg.hh" #include "mem/protocol/SequencerRequestType.hh" +#include "mem/ruby/buffers/MessageBuffer.hh" +#include "mem/ruby/slicc_interface/AbstractController.hh" +#include "mem/ruby/system/DMASequencer.hh" #include "mem/ruby/system/System.hh" -// -// Fix me: This code needs comments! -// - DMASequencer::DMASequencer(const Params *p) - : RubyPort(p) + : RubyPort(p) { } -void DMASequencer::init() +void +DMASequencer::init() { - RubyPort::init(); - m_is_busy = false; - m_data_block_mask = ~ (~0 << RubySystem::getBlockSizeBits()); + RubyPort::init(); + m_is_busy = false; + m_data_block_mask = ~ (~0 << RubySystem::getBlockSizeBits()); } -RequestStatus DMASequencer::makeRequest(const RubyRequest & request) +RequestStatus +DMASequencer::makeRequest(const RubyRequest &request) { - uint64_t paddr = request.paddr; - uint8_t* data = request.data; - int len = request.len; - bool write = false; - switch(request.type) { - case RubyRequestType_LD: - write = false; - break; - case RubyRequestType_ST: - write = true; - break; - case RubyRequestType_NULL: - case RubyRequestType_IFETCH: - case RubyRequestType_Locked_Read: - case RubyRequestType_Locked_Write: - case RubyRequestType_RMW_Read: - case RubyRequestType_RMW_Write: - case RubyRequestType_NUM: - panic("DMASequencer::makeRequest does not support the RubyRequestType"); - return RequestStatus_NULL; - } - - assert(!m_is_busy); // only support one outstanding DMA request - m_is_busy = true; - - active_request.start_paddr = paddr; - active_request.write = write; - active_request.data = data; - active_request.len = len; - active_request.bytes_completed = 0; - active_request.bytes_issued = 0; - active_request.pkt = request.pkt; - - SequencerMsg msg; - msg.getPhysicalAddress() = Address(paddr); - msg.getLineAddress() = line_address(msg.getPhysicalAddress()); - msg.getType() = write ? SequencerRequestType_ST : SequencerRequestType_LD; - int offset = paddr & m_data_block_mask; - - msg.getLen() = (offset + len) <= RubySystem::getBlockSizeBytes() ? - len : - RubySystem::getBlockSizeBytes() - offset; - - if (write) { - msg.getDataBlk().setData(data, offset, msg.getLen()); - } - - assert(m_mandatory_q_ptr != NULL); - m_mandatory_q_ptr->enqueue(msg); - active_request.bytes_issued += msg.getLen(); - - return RequestStatus_Issued; + uint64_t paddr = request.paddr; + uint8_t* data = request.data; + int len = request.len; + bool write = false; + switch(request.type) { + case RubyRequestType_LD: + write = false; + break; + case RubyRequestType_ST: + write = true; + break; + case RubyRequestType_NULL: + case RubyRequestType_IFETCH: + case RubyRequestType_Locked_Read: + case RubyRequestType_Locked_Write: + case RubyRequestType_RMW_Read: + case RubyRequestType_RMW_Write: + case RubyRequestType_NUM: + panic("DMASequencer::makeRequest does not support RubyRequestType"); + return RequestStatus_NULL; + } + + assert(!m_is_busy); // only support one outstanding DMA request + m_is_busy = true; + + active_request.start_paddr = paddr; + active_request.write = write; + active_request.data = data; + active_request.len = len; + active_request.bytes_completed = 0; + active_request.bytes_issued = 0; + active_request.pkt = request.pkt; + + SequencerMsg msg; + msg.getPhysicalAddress() = Address(paddr); + msg.getLineAddress() = line_address(msg.getPhysicalAddress()); + msg.getType() = write ? SequencerRequestType_ST : SequencerRequestType_LD; + int offset = paddr & m_data_block_mask; + + msg.getLen() = (offset + len) <= RubySystem::getBlockSizeBytes() ? + len : RubySystem::getBlockSizeBytes() - offset; + + if (write) { + msg.getDataBlk().setData(data, offset, msg.getLen()); + } + + assert(m_mandatory_q_ptr != NULL); + m_mandatory_q_ptr->enqueue(msg); + active_request.bytes_issued += msg.getLen(); + + return RequestStatus_Issued; } -void DMASequencer::issueNext() +void +DMASequencer::issueNext() { - assert(m_is_busy == true); - active_request.bytes_completed = active_request.bytes_issued; - if (active_request.len == active_request.bytes_completed) { - ruby_hit_callback(active_request.pkt); - m_is_busy = false; - return; - } - - SequencerMsg msg; - msg.getPhysicalAddress() = Address(active_request.start_paddr + - active_request.bytes_completed); - - assert((msg.getPhysicalAddress().getAddress() & m_data_block_mask) == 0); - msg.getLineAddress() = line_address(msg.getPhysicalAddress()); - - msg.getType() = (active_request.write ? SequencerRequestType_ST : - SequencerRequestType_LD); - - msg.getLen() = (active_request.len - - active_request.bytes_completed < RubySystem::getBlockSizeBytes() ? - active_request.len - active_request.bytes_completed : - RubySystem::getBlockSizeBytes()); - - if (active_request.write) { - msg.getDataBlk().setData(&active_request.data[active_request.bytes_completed], - 0, msg.getLen()); - msg.getType() = SequencerRequestType_ST; - } else { - msg.getType() = SequencerRequestType_LD; - } - - assert(m_mandatory_q_ptr != NULL); - m_mandatory_q_ptr->enqueue(msg); - active_request.bytes_issued += msg.getLen(); + assert(m_is_busy == true); + active_request.bytes_completed = active_request.bytes_issued; + if (active_request.len == active_request.bytes_completed) { + ruby_hit_callback(active_request.pkt); + m_is_busy = false; + return; + } + + SequencerMsg msg; + msg.getPhysicalAddress() = Address(active_request.start_paddr + + active_request.bytes_completed); + + assert((msg.getPhysicalAddress().getAddress() & m_data_block_mask) == 0); + msg.getLineAddress() = line_address(msg.getPhysicalAddress()); + + msg.getType() = (active_request.write ? SequencerRequestType_ST : + SequencerRequestType_LD); + + msg.getLen() = + (active_request.len - + active_request.bytes_completed < RubySystem::getBlockSizeBytes() ? + active_request.len - active_request.bytes_completed : + RubySystem::getBlockSizeBytes()); + + if (active_request.write) { + msg.getDataBlk(). + setData(&active_request.data[active_request.bytes_completed], + 0, msg.getLen()); + msg.getType() = SequencerRequestType_ST; + } else { + msg.getType() = SequencerRequestType_LD; + } + + assert(m_mandatory_q_ptr != NULL); + m_mandatory_q_ptr->enqueue(msg); + active_request.bytes_issued += msg.getLen(); } -void DMASequencer::dataCallback(const DataBlock & dblk) +void +DMASequencer::dataCallback(const DataBlock & dblk) { - assert(m_is_busy == true); - int len = active_request.bytes_issued - active_request.bytes_completed; - int offset = 0; - if (active_request.bytes_completed == 0) - offset = active_request.start_paddr & m_data_block_mask; - assert( active_request.write == false ); - memcpy(&active_request.data[active_request.bytes_completed], - dblk.getData(offset, len), len); - issueNext(); + assert(m_is_busy == true); + int len = active_request.bytes_issued - active_request.bytes_completed; + int offset = 0; + if (active_request.bytes_completed == 0) + offset = active_request.start_paddr & m_data_block_mask; + assert(active_request.write == false); + memcpy(&active_request.data[active_request.bytes_completed], + dblk.getData(offset, len), len); + issueNext(); } -void DMASequencer::ackCallback() +void +DMASequencer::ackCallback() { - issueNext(); + issueNext(); } -void DMASequencer::printConfig(ostream & out) +void +DMASequencer::printConfig(ostream & out) { - } - DMASequencer * DMASequencerParams::create() { diff --git a/src/mem/ruby/system/DMASequencer.hh b/src/mem/ruby/system/DMASequencer.hh index 24129526a..61d7ef1c6 100644 --- a/src/mem/ruby/system/DMASequencer.hh +++ b/src/mem/ruby/system/DMASequencer.hh @@ -26,48 +26,50 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef DMASEQUENCER_H -#define DMASEQUENCER_H +#ifndef __MEM_RUBY_SYSTEM_DMASEQUENCER_HH__ +#define __MEM_RUBY_SYSTEM_DMASEQUENCER_HH__ #include <ostream> + #include "mem/ruby/common/DataBlock.hh" #include "mem/ruby/system/RubyPort.hh" - #include "params/DMASequencer.hh" -struct DMARequest { - uint64_t start_paddr; - int len; - bool write; - int bytes_completed; - int bytes_issued; - uint8* data; - PacketPtr pkt; +struct DMARequest +{ + uint64_t start_paddr; + int len; + bool write; + int bytes_completed; + int bytes_issued; + uint8* data; + PacketPtr pkt; }; -class DMASequencer :public RubyPort { -public: +class DMASequencer : public RubyPort +{ + public: typedef DMASequencerParams Params; - DMASequencer(const Params *); - void init(); - /* external interface */ - RequestStatus makeRequest(const RubyRequest & request); - bool busy() { return m_is_busy;} + DMASequencer(const Params *); + void init(); + /* external interface */ + RequestStatus makeRequest(const RubyRequest & request); + bool busy() { return m_is_busy;} - /* SLICC callback */ - void dataCallback(const DataBlock & dblk); - void ackCallback(); + /* SLICC callback */ + void dataCallback(const DataBlock & dblk); + void ackCallback(); - void printConfig(std::ostream & out); + void printConfig(std::ostream & out); -private: - void issueNext(); + private: + void issueNext(); -private: - bool m_is_busy; - uint64_t m_data_block_mask; - DMARequest active_request; - int num_active_requests; + private: + bool m_is_busy; + uint64_t m_data_block_mask; + DMARequest active_request; + int num_active_requests; }; -#endif // DMACONTROLLER_H +#endif // __MEM_RUBY_SYSTEM_DMASEQUENCER_HH__ diff --git a/src/mem/ruby/system/DirectoryMemory.cc b/src/mem/ruby/system/DirectoryMemory.cc index d8037aec1..93f537090 100644 --- a/src/mem/ruby/system/DirectoryMemory.cc +++ b/src/mem/ruby/system/DirectoryMemory.cc @@ -1,4 +1,3 @@ - /* * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood * All rights reserved. @@ -27,19 +26,10 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -/* - * DirectoryMemory.cc - * - * Description: See DirectoryMemory.hh - * - * $Id$ - * - */ - -#include "mem/ruby/system/System.hh" -#include "mem/ruby/system/DirectoryMemory.hh" -#include "mem/ruby/slicc_interface/RubySlicc_Util.hh" #include "mem/gems_common/util.hh" +#include "mem/ruby/slicc_interface/RubySlicc_Util.hh" +#include "mem/ruby/system/DirectoryMemory.hh" +#include "mem/ruby/system/System.hh" int DirectoryMemory::m_num_directories = 0; int DirectoryMemory::m_num_directories_bits = 0; @@ -58,89 +48,95 @@ DirectoryMemory::DirectoryMemory(const Params *p) m_numa_high_bit = p->numa_high_bit; } -void DirectoryMemory::init() +void +DirectoryMemory::init() { - m_num_entries = m_size_bytes / RubySystem::getBlockSizeBytes(); - - if (m_use_map) { - int entry_bits = log_int(m_num_entries); - assert(entry_bits >= m_map_levels); - m_sparseMemory = new SparseMemory(entry_bits, m_map_levels); - } else { - m_entries = new Directory_Entry*[m_num_entries]; - for (int i=0; i < m_num_entries; i++) - m_entries[i] = NULL; - m_ram = g_system_ptr->getMemoryVector(); - } - - m_num_directories++; - m_num_directories_bits = log_int(m_num_directories); - m_total_size_bytes += m_size_bytes; - - if (m_numa_high_bit == 0) { - m_numa_high_bit = RubySystem::getMemorySizeBits(); - } - assert(m_numa_high_bit != 0); + m_num_entries = m_size_bytes / RubySystem::getBlockSizeBytes(); + + if (m_use_map) { + int entry_bits = log_int(m_num_entries); + assert(entry_bits >= m_map_levels); + m_sparseMemory = new SparseMemory(entry_bits, m_map_levels); + } else { + m_entries = new Directory_Entry*[m_num_entries]; + for (int i = 0; i < m_num_entries; i++) + m_entries[i] = NULL; + m_ram = g_system_ptr->getMemoryVector(); + } + + m_num_directories++; + m_num_directories_bits = log_int(m_num_directories); + m_total_size_bytes += m_size_bytes; + + if (m_numa_high_bit == 0) { + m_numa_high_bit = RubySystem::getMemorySizeBits(); + } + assert(m_numa_high_bit != 0); } DirectoryMemory::~DirectoryMemory() { - // free up all the directory entries - if (m_entries != NULL) { - for (uint64 i = 0; i < m_num_entries; i++) { - if (m_entries[i] != NULL) { - delete m_entries[i]; - } - } - delete [] m_entries; - } else if (m_use_map) { - delete m_sparseMemory; - } + // free up all the directory entries + if (m_entries != NULL) { + for (uint64 i = 0; i < m_num_entries; i++) { + if (m_entries[i] != NULL) { + delete m_entries[i]; + } + } + delete [] m_entries; + } else if (m_use_map) { + delete m_sparseMemory; + } } -void DirectoryMemory::printConfig(ostream& out) const +void +DirectoryMemory::printConfig(ostream& out) const { - out << "DirectoryMemory module config: " << m_name << endl; - out << " version: " << m_version << endl; - out << " memory_bits: " << m_size_bits << endl; - out << " memory_size_bytes: " << m_size_bytes << endl; - out << " memory_size_Kbytes: " << double(m_size_bytes) / (1<<10) << endl; - out << " memory_size_Mbytes: " << double(m_size_bytes) / (1<<20) << endl; - out << " memory_size_Gbytes: " << double(m_size_bytes) / (1<<30) << endl; + out << "DirectoryMemory module config: " << m_name << endl + << " version: " << m_version << endl + << " memory_bits: " << m_size_bits << endl + << " memory_size_bytes: " << m_size_bytes << endl + << " memory_size_Kbytes: " << double(m_size_bytes) / (1<<10) << endl + << " memory_size_Mbytes: " << double(m_size_bytes) / (1<<20) << endl + << " memory_size_Gbytes: " << double(m_size_bytes) / (1<<30) << endl; } // Static method -void DirectoryMemory::printGlobalConfig(ostream & out) +void +DirectoryMemory::printGlobalConfig(ostream & out) { - out << "DirectoryMemory Global Config: " << endl; - out << " number of directory memories: " << m_num_directories << endl; - if (m_num_directories > 1) { - out << " number of selection bits: " << m_num_directories_bits << endl; - out << " selection bits: " << m_numa_high_bit - << "-" << m_numa_high_bit-m_num_directories_bits - << endl; - } - out << " total memory size bytes: " << m_total_size_bytes << endl; - out << " total memory bits: " << log_int(m_total_size_bytes) << endl; - + out << "DirectoryMemory Global Config: " << endl; + out << " number of directory memories: " << m_num_directories << endl; + if (m_num_directories > 1) { + out << " number of selection bits: " << m_num_directories_bits << endl + << " selection bits: " << m_numa_high_bit + << "-" << m_numa_high_bit-m_num_directories_bits + << endl; + } + out << " total memory size bytes: " << m_total_size_bytes << endl; + out << " total memory bits: " << log_int(m_total_size_bytes) << endl; } -uint64 DirectoryMemory::mapAddressToDirectoryVersion(PhysAddress address) +uint64 +DirectoryMemory::mapAddressToDirectoryVersion(PhysAddress address) { - if (m_num_directories_bits == 0) return 0; - uint64 ret = address.bitSelect(m_numa_high_bit - m_num_directories_bits, - m_numa_high_bit); - return ret; + if (m_num_directories_bits == 0) + return 0; + + uint64 ret = address.bitSelect(m_numa_high_bit - m_num_directories_bits, + m_numa_high_bit); + return ret; } -// Public method -bool DirectoryMemory::isPresent(PhysAddress address) +bool +DirectoryMemory::isPresent(PhysAddress address) { - bool ret = (mapAddressToDirectoryVersion(address) == m_version); - return ret; + bool ret = (mapAddressToDirectoryVersion(address) == m_version); + return ret; } -uint64 DirectoryMemory::mapAddressToLocalIdx(PhysAddress address) +uint64 +DirectoryMemory::mapAddressToLocalIdx(PhysAddress address) { uint64 ret = address.bitRemove(m_numa_high_bit - m_num_directories_bits, m_numa_high_bit) @@ -148,98 +144,99 @@ uint64 DirectoryMemory::mapAddressToLocalIdx(PhysAddress address) return ret; } -Directory_Entry& DirectoryMemory::lookup(PhysAddress address) +Directory_Entry& +DirectoryMemory::lookup(PhysAddress address) { - assert(isPresent(address)); - Directory_Entry* entry; - uint64 idx; - DEBUG_EXPR(CACHE_COMP, HighPrio, address); - - if (m_use_map) { - if (m_sparseMemory->exist(address)) { - entry = m_sparseMemory->lookup(address); - assert(entry != NULL); - } else { - // - // Note: SparseMemory internally creates a new Directory Entry - // - m_sparseMemory->add(address); - entry = m_sparseMemory->lookup(address); - } - } else { - idx = mapAddressToLocalIdx(address); - assert(idx < m_num_entries); - entry = m_entries[idx]; + assert(isPresent(address)); + Directory_Entry* entry; + uint64 idx; + DEBUG_EXPR(CACHE_COMP, HighPrio, address); - if (entry == NULL) { - entry = new Directory_Entry(); - entry->getDataBlk().assign(m_ram->getBlockPtr(address)); - m_entries[idx] = entry; + if (m_use_map) { + if (m_sparseMemory->exist(address)) { + entry = m_sparseMemory->lookup(address); + assert(entry != NULL); + } else { + // Note: SparseMemory internally creates a new Directory Entry + m_sparseMemory->add(address); + entry = m_sparseMemory->lookup(address); + } + } else { + idx = mapAddressToLocalIdx(address); + assert(idx < m_num_entries); + entry = m_entries[idx]; + + if (entry == NULL) { + entry = new Directory_Entry(); + entry->getDataBlk().assign(m_ram->getBlockPtr(address)); + m_entries[idx] = entry; + } } - } - return (*entry); -} -/* -Directory_Entry& DirectoryMemory::lookup(PhysAddress address) -{ - assert(isPresent(address)); - Index index = address.memoryModuleIndex(); - - if (index < 0 || index > m_size) { - WARN_EXPR(address.getAddress()); - WARN_EXPR(index); - WARN_EXPR(m_size); - ERROR_MSG("Directory Memory Assertion: accessing memory out of range."); - } - Directory_Entry* entry = m_entries[index]; - - // allocate the directory entry on demand. - if (entry == NULL) { - entry = new Directory_Entry; - entry->getDataBlk().assign(m_ram->getBlockPtr(address)); - - // store entry to the table - m_entries[index] = entry; - } - - return (*entry); + return *entry; } -*/ -void DirectoryMemory::invalidateBlock(PhysAddress address) +#if 0 +Directory_Entry& +DirectoryMemory::lookup(PhysAddress address) { - - if (m_use_map) { - assert(m_sparseMemory->exist(address)); - m_sparseMemory->remove(address); - } - /* - else { assert(isPresent(address)); - Index index = address.memoryModuleIndex(); - + if (index < 0 || index > m_size) { - ERROR_MSG("Directory Memory Assertion: accessing memory out of range."); + WARN_EXPR(address.getAddress()); + WARN_EXPR(index); + WARN_EXPR(m_size); + ERROR_MSG("Directory Memory Assertion: accessing memory out of range"); } + Directory_Entry* entry = m_entries[index]; - if(m_entries[index] != NULL){ - delete m_entries[index]; - m_entries[index] = NULL; - } - } - */ + // allocate the directory entry on demand. + if (entry == NULL) { + entry = new Directory_Entry; + entry->getDataBlk().assign(m_ram->getBlockPtr(address)); + // store entry to the table + m_entries[index] = entry; + } + return *entry; } +#endif -void DirectoryMemory::print(ostream& out) const +void +DirectoryMemory::invalidateBlock(PhysAddress address) { + if (m_use_map) { + assert(m_sparseMemory->exist(address)); + m_sparseMemory->remove(address); + } +#if 0 + else { + assert(isPresent(address)); + + Index index = address.memoryModuleIndex(); + + if (index < 0 || index > m_size) { + ERROR_MSG("Directory Memory Assertion: " + "accessing memory out of range."); + } + + if (m_entries[index] != NULL){ + delete m_entries[index]; + m_entries[index] = NULL; + } + } +#endif +} +void +DirectoryMemory::print(ostream& out) const +{ } -void DirectoryMemory::printStats(ostream& out) const +void +DirectoryMemory::printStats(ostream& out) const { if (m_use_map) { m_sparseMemory->printStats(out); diff --git a/src/mem/ruby/system/DirectoryMemory.hh b/src/mem/ruby/system/DirectoryMemory.hh index 8b23ced02..4e7bfc4f6 100644 --- a/src/mem/ruby/system/DirectoryMemory.hh +++ b/src/mem/ruby/system/DirectoryMemory.hh @@ -1,4 +1,3 @@ - /* * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood * All rights reserved. @@ -27,94 +26,74 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -/* - * DirectoryMemory.hh - * - * Description: - * - * $Id$ - * - */ - -#ifndef DIRECTORYMEMORY_H -#define DIRECTORYMEMORY_H +#ifndef __MEM_RUBY_SYSTEM_DIRECTORYMEMORY_HH__ +#define __MEM_RUBY_SYSTEM_DIRECTORYMEMORY_HH__ -#include "mem/ruby/common/Global.hh" +#include "mem/protocol/Directory_Entry.hh" #include "mem/ruby/common/Address.hh" +#include "mem/ruby/common/Global.hh" #include "mem/ruby/system/MemoryVector.hh" -#include "mem/protocol/Directory_Entry.hh" -#include "sim/sim_object.hh" -#include "params/RubyDirectoryMemory.hh" #include "mem/ruby/system/SparseMemory.hh" +#include "params/RubyDirectoryMemory.hh" +#include "sim/sim_object.hh" -class DirectoryMemory : public SimObject { -public: - // Constructors +class DirectoryMemory : public SimObject +{ + public: typedef RubyDirectoryMemoryParams Params; DirectoryMemory(const Params *p); - void init(); - // DirectoryMemory(int version); - - // Destructor - ~DirectoryMemory(); - - uint64 mapAddressToLocalIdx(PhysAddress address); - static uint64 mapAddressToDirectoryVersion(PhysAddress address); - - bool isSparseImplementation() { return m_use_map; } - uint64 getSize() { return m_size_bytes; } - - // Public Methods - void printConfig(ostream& out) const; - static void printGlobalConfig(ostream & out); - bool isPresent(PhysAddress address); - Directory_Entry& lookup(PhysAddress address); - - void invalidateBlock(PhysAddress address); - - void print(ostream& out) const; - void printStats(ostream& out) const; - -private: - // Private Methods - - // Private copy constructor and assignment operator - DirectoryMemory(const DirectoryMemory& obj); - DirectoryMemory& operator=(const DirectoryMemory& obj); - -private: - const string m_name; - // Data Members (m_ prefix) - Directory_Entry **m_entries; - // int m_size; // # of memory module blocks this directory is responsible for - uint64 m_size_bytes; - uint64 m_size_bits; - uint64 m_num_entries; - int m_version; - - static int m_num_directories; - static int m_num_directories_bits; - static uint64_t m_total_size_bytes; - static int m_numa_high_bit; - - MemoryVector* m_ram; - SparseMemory* m_sparseMemory; - bool m_use_map; - int m_map_levels; + ~DirectoryMemory(); + + void init(); + + uint64 mapAddressToLocalIdx(PhysAddress address); + static uint64 mapAddressToDirectoryVersion(PhysAddress address); + + bool isSparseImplementation() { return m_use_map; } + uint64 getSize() { return m_size_bytes; } + + void printConfig(ostream& out) const; + static void printGlobalConfig(ostream & out); + bool isPresent(PhysAddress address); + Directory_Entry& lookup(PhysAddress address); + + void invalidateBlock(PhysAddress address); + + void print(ostream& out) const; + void printStats(ostream& out) const; + + private: + // Private copy constructor and assignment operator + DirectoryMemory(const DirectoryMemory& obj); + DirectoryMemory& operator=(const DirectoryMemory& obj); + + private: + const string m_name; + Directory_Entry **m_entries; + // int m_size; // # of memory module blocks this directory is + // responsible for + uint64 m_size_bytes; + uint64 m_size_bits; + uint64 m_num_entries; + int m_version; + + static int m_num_directories; + static int m_num_directories_bits; + static uint64_t m_total_size_bytes; + static int m_numa_high_bit; + + MemoryVector* m_ram; + SparseMemory* m_sparseMemory; + bool m_use_map; + int m_map_levels; }; -// Output operator declaration -ostream& operator<<(ostream& out, const DirectoryMemory& obj); - -// ******************* Definitions ******************* - -// Output operator definition -extern inline -ostream& operator<<(ostream& out, const DirectoryMemory& obj) +inline ostream& +operator<<(ostream& out, const DirectoryMemory& obj) { - obj.print(out); - out << flush; - return out; + obj.print(out); + out << flush; + return out; } -#endif //DIRECTORYMEMORY_H +#endif // __MEM_RUBY_SYSTEM_DIRECTORYMEMORY_HH__ diff --git a/src/mem/ruby/system/LRUPolicy.hh b/src/mem/ruby/system/LRUPolicy.hh index 55b1eec6e..b1b9d7478 100644 --- a/src/mem/ruby/system/LRUPolicy.hh +++ b/src/mem/ruby/system/LRUPolicy.hh @@ -26,26 +26,26 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef LRUPOLICY_H -#define LRUPOLICY_H +#ifndef __MEM_RUBY_SYSTEM_LRUPOLICY_HH__ +#define __MEM_RUBY_SYSTEM_LRUPOLICY_HH__ #include "mem/ruby/system/AbstractReplacementPolicy.hh" /* Simple true LRU replacement policy */ -class LRUPolicy : public AbstractReplacementPolicy { - public: - - LRUPolicy(Index num_sets, Index assoc); - ~LRUPolicy(); +class LRUPolicy : public AbstractReplacementPolicy +{ + public: + LRUPolicy(Index num_sets, Index assoc); + ~LRUPolicy(); - void touch(Index set, Index way, Time time); - Index getVictim(Index set) const; + void touch(Index set, Index way, Time time); + Index getVictim(Index set) const; }; inline LRUPolicy::LRUPolicy(Index num_sets, Index assoc) - : AbstractReplacementPolicy(num_sets, assoc) + : AbstractReplacementPolicy(num_sets, assoc) { } @@ -54,39 +54,42 @@ LRUPolicy::~LRUPolicy() { } -inline -void LRUPolicy::touch(Index set, Index index, Time time){ - assert(index >= 0 && index < m_assoc); - assert(set >= 0 && set < m_num_sets); +inline void +LRUPolicy::touch(Index set, Index index, Time time) +{ + assert(index >= 0 && index < m_assoc); + assert(set >= 0 && set < m_num_sets); - m_last_ref_ptr[set][index] = time; + m_last_ref_ptr[set][index] = time; } -inline -Index LRUPolicy::getVictim(Index set) const { - // assert(m_assoc != 0); - Time time, smallest_time; - Index smallest_index; - - smallest_index = 0; - smallest_time = m_last_ref_ptr[set][0]; - - for (unsigned int i=0; i < m_assoc; i++) { - time = m_last_ref_ptr[set][i]; - //assert(m_cache[cacheSet][i].m_Permission != AccessPermission_NotPresent); - - if (time < smallest_time){ - smallest_index = i; - smallest_time = time; +inline Index +LRUPolicy::getVictim(Index set) const +{ + // assert(m_assoc != 0); + Time time, smallest_time; + Index smallest_index; + + smallest_index = 0; + smallest_time = m_last_ref_ptr[set][0]; + + for (unsigned i = 0; i < m_assoc; i++) { + time = m_last_ref_ptr[set][i]; + // assert(m_cache[cacheSet][i].m_Permission != + // AccessPermission_NotPresent); + + if (time < smallest_time) { + smallest_index = i; + smallest_time = time; + } } - } - // DEBUG_EXPR(CACHE_COMP, MedPrio, cacheSet); - // DEBUG_EXPR(CACHE_COMP, MedPrio, smallest_index); - // DEBUG_EXPR(CACHE_COMP, MedPrio, m_cache[cacheSet][smallest_index]); - // DEBUG_EXPR(CACHE_COMP, MedPrio, *this); + // DEBUG_EXPR(CACHE_COMP, MedPrio, cacheSet); + // DEBUG_EXPR(CACHE_COMP, MedPrio, smallest_index); + // DEBUG_EXPR(CACHE_COMP, MedPrio, m_cache[cacheSet][smallest_index]); + // DEBUG_EXPR(CACHE_COMP, MedPrio, *this); - return smallest_index; + return smallest_index; } -#endif // PSEUDOLRUBITS_H +#endif // __MEM_RUBY_SYSTEM_LRUPOLICY_HH__ diff --git a/src/mem/ruby/system/MachineID.hh b/src/mem/ruby/system/MachineID.hh index 9da71f349..716196248 100644 --- a/src/mem/ruby/system/MachineID.hh +++ b/src/mem/ruby/system/MachineID.hh @@ -1,4 +1,3 @@ - /* * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood * All rights reserved. @@ -27,66 +26,55 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -/* - * NodeID.hh - * - * Description: - * - * $Id$ - * - */ - -#ifndef MACHINEID_H -#define MACHINEID_H +#ifndef __MEM_RUBY_SYSTEM_MACHINEID_HH__ +#define __MEM_RUBY_SYSTEM_MACHINEID_HH__ #include <iostream> #include <string> -#include "mem/ruby/common/Global.hh" #include "mem/gems_common/util.hh" #include "mem/protocol/MachineType.hh" +#include "mem/ruby/common/Global.hh" -struct MachineID { - MachineType type; - int num; // range: 0 ... number of this machine's components in the system - 1 +struct MachineID +{ + MachineType type; + int num; // range: 0 ... number of this machine's components in system - 1 }; -extern inline -std::string MachineIDToString (MachineID machine) { - return MachineType_to_string(machine.type)+"_"+int_to_string(machine.num); +inline std::string +MachineIDToString(MachineID machine) +{ + return MachineType_to_string(machine.type)+"_"+int_to_string(machine.num); } -extern inline -bool operator==(const MachineID & obj1, const MachineID & obj2) +inline bool +operator==(const MachineID & obj1, const MachineID & obj2) { - return (obj1.type == obj2.type && obj1.num == obj2.num); + return (obj1.type == obj2.type && obj1.num == obj2.num); } -extern inline -bool operator!=(const MachineID & obj1, const MachineID & obj2) +inline bool +operator!=(const MachineID & obj1, const MachineID & obj2) { - return (obj1.type != obj2.type || obj1.num != obj2.num); + return (obj1.type != obj2.type || obj1.num != obj2.num); } // Output operator declaration std::ostream& operator<<(std::ostream& out, const MachineID& obj); -// ******************* Definitions ******************* - -// Output operator definition -extern inline -std::ostream& operator<<(std::ostream& out, const MachineID& obj) +inline std::ostream& +operator<<(std::ostream& out, const MachineID& obj) { - if ((obj.type < MachineType_NUM) && (obj.type >= MachineType_FIRST)) { - out << MachineType_to_string(obj.type); - } else { - out << "NULL"; - } - out << "-"; - out << obj.num; - out << std::flush; - return out; + if ((obj.type < MachineType_NUM) && (obj.type >= MachineType_FIRST)) { + out << MachineType_to_string(obj.type); + } else { + out << "NULL"; + } + out << "-"; + out << obj.num; + out << std::flush; + return out; } - -#endif //MACHINEID_H +#endif // __MEM_RUBY_SYSTEM_MACHINEID_HH__ diff --git a/src/mem/ruby/system/MemoryControl.cc b/src/mem/ruby/system/MemoryControl.cc index 0f12efc36..963cc3947 100644 --- a/src/mem/ruby/system/MemoryControl.cc +++ b/src/mem/ruby/system/MemoryControl.cc @@ -1,4 +1,3 @@ - /* * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood * All rights reserved. @@ -28,8 +27,6 @@ */ /* - * MemoryControl.cc - * * Description: This module simulates a basic DDR-style memory controller * (and can easily be extended to do FB-DIMM as well). * @@ -105,25 +102,21 @@ * then no more than four activates may happen within any 16 cycle window. * Refreshes are included in the activates. * - * - * $Id: $ - * */ -#include "mem/ruby/common/Global.hh" +#include <list> + +#include "base/cprintf.hh" #include "mem/gems_common/Map.hh" #include "mem/ruby/common/Address.hh" +#include "mem/ruby/common/Consumer.hh" +#include "mem/ruby/common/Global.hh" +#include "mem/ruby/network/Network.hh" #include "mem/ruby/profiler/Profiler.hh" -#include "mem/ruby/system/System.hh" -#include "mem/ruby/slicc_interface/RubySlicc_ComponentMapping.hh" #include "mem/ruby/slicc_interface/NetworkMessage.hh" -#include "mem/ruby/network/Network.hh" - -#include "mem/ruby/common/Consumer.hh" - +#include "mem/ruby/slicc_interface/RubySlicc_ComponentMapping.hh" #include "mem/ruby/system/MemoryControl.hh" - -#include <list> +#include "mem/ruby/system/System.hh" class Consumer; @@ -140,11 +133,12 @@ class Consumer; // Output operator definition -ostream& operator<<(ostream& out, const MemoryControl& obj) +ostream& +operator<<(ostream& out, const MemoryControl& obj) { - obj.print(out); - out << flush; - return out; + obj.print(out); + out << flush; + return out; } @@ -178,471 +172,509 @@ MemoryControl::MemoryControl(const Params *p) m_dimms_per_channel); } -void MemoryControl::init() +void +MemoryControl::init() { - m_msg_counter = 0; - - m_debug = 0; - - assert(m_tFaw <= 62); // must fit in a uint64 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_awakened = 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 [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; - } -} + m_msg_counter = 0; + m_debug = 0; -// DESTRUCTOR + assert(m_tFaw <= 62); // must fit in a uint64 shift register -MemoryControl::~MemoryControl () { - delete [] m_bankQueues; - delete [] m_bankBusyCounter; - delete [] m_oldRequest; - delete m_profiler_ptr; -} + 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); -// PUBLIC METHODS + m_bankBusyCounter = new int [m_total_banks]; + assert(m_bankBusyCounter); -// enqueue new request from directory - -void MemoryControl::enqueue (const MsgPtr& message, int latency) { - Time current_time = g_eventQueue_ptr->getTime(); - Time arrival_time = current_time + latency; - const MemoryMsg* memMess = dynamic_cast<const MemoryMsg*>(message.ref()); - physical_address_t addr = memMess->getAddress().getAddress(); - MemoryRequestType type = memMess->getType(); - bool is_mem_read = (type == MemoryRequestType_MEMORY_READ); - MemoryNode thisReq(arrival_time, message, addr, is_mem_read, !is_mem_read); - enqueueMemRef(thisReq); -} - -// Alternate entry point used when we already have a MemoryNode structure built. - -void MemoryControl::enqueueMemRef (MemoryNode& memRef) { - m_msg_counter++; - memRef.m_msg_counter = m_msg_counter; - Time arrival_time = memRef.m_time; - uint64 at = arrival_time; - bool is_mem_read = memRef.m_is_mem_read; - physical_address_t addr = memRef.m_addr; - int bank = getBank(addr); - if (m_debug) { - printf("New memory request%7d: 0x%08llx %c arrived at %10lld ", m_msg_counter, addr, is_mem_read? 'R':'W', at); - printf("bank =%3x\n", bank); - } - - m_profiler_ptr->profileMemReq(bank); - m_input_queue.push_back(memRef); - if (!m_awakened) { - g_eventQueue_ptr->scheduleEvent(this, 1); - m_awakened = 1; - } -} + 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; -// dequeue, peek, and isReady are used to transfer completed requests -// back to the directory + m_roundRobin = 0; + m_refresh_count = 1; + m_need_refresh = 0; + m_refresh_bank = 0; + m_awakened = 0; + m_idleCount = 0; + m_ageCounter = 0; -void MemoryControl::dequeue () { - assert(isReady()); - m_response_queue.pop_front(); + // 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[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; + } } - -const Message* MemoryControl::peek () { - MemoryNode node = peekNode(); - Message* msg_ptr = node.m_msgptr.ref(); - assert(msg_ptr != NULL); - return msg_ptr; +MemoryControl::~MemoryControl() +{ + delete [] m_bankQueues; + delete [] m_bankBusyCounter; + delete [] m_oldRequest; + delete m_profiler_ptr; } - -MemoryNode MemoryControl::peekNode () { - assert(isReady()); - MemoryNode req = m_response_queue.front(); - uint64 returnTime = req.m_time; - if (m_debug) { - printf("Old memory request%7d: 0x%08llx %c peeked at %10lld\n", - req.m_msg_counter, req.m_addr, req.m_is_mem_read? 'R':'W', returnTime); - } - return req; +// enqueue new request from directory +void +MemoryControl::enqueue(const MsgPtr& message, int latency) +{ + Time current_time = g_eventQueue_ptr->getTime(); + Time arrival_time = current_time + latency; + const MemoryMsg* memMess = dynamic_cast<const MemoryMsg*>(message.ref()); + physical_address_t addr = memMess->getAddress().getAddress(); + MemoryRequestType type = memMess->getType(); + bool is_mem_read = (type == MemoryRequestType_MEMORY_READ); + MemoryNode thisReq(arrival_time, message, addr, is_mem_read, !is_mem_read); + enqueueMemRef(thisReq); } +// Alternate entry point used when we already have a MemoryNode +// structure built. +void +MemoryControl::enqueueMemRef(MemoryNode& memRef) +{ + m_msg_counter++; + memRef.m_msg_counter = m_msg_counter; + Time arrival_time = memRef.m_time; + uint64 at = arrival_time; + bool is_mem_read = memRef.m_is_mem_read; + physical_address_t addr = memRef.m_addr; + int bank = getBank(addr); + if (m_debug) { + cprintf("New memory request%7d: %#08x %c arrived at %10d bank = %3x\n", + m_msg_counter, addr, is_mem_read? 'R':'W', at, bank); + } -bool MemoryControl::isReady () { - return ((!m_response_queue.empty()) && - (m_response_queue.front().m_time <= g_eventQueue_ptr->getTime())); + m_profiler_ptr->profileMemReq(bank); + m_input_queue.push_back(memRef); + if (!m_awakened) { + g_eventQueue_ptr->scheduleEvent(this, 1); + m_awakened = 1; + } } -void MemoryControl::setConsumer (Consumer* consumer_ptr) { - m_consumer_ptr = consumer_ptr; +// dequeue, peek, and isReady are used to transfer completed requests +// back to the directory +void +MemoryControl::dequeue() +{ + assert(isReady()); + m_response_queue.pop_front(); } -void MemoryControl::print (ostream& out) const { +const Message* +MemoryControl::peek() +{ + MemoryNode node = peekNode(); + Message* msg_ptr = node.m_msgptr.ref(); + assert(msg_ptr != NULL); + return msg_ptr; } - -void MemoryControl::printConfig (ostream& out) { - out << "Memory Control " << name() << ":" << endl; - out << " Ruby cycles per memory cycle: " << m_mem_bus_cycle_multiplier << endl; - out << " Basic read latency: " << m_mem_ctl_latency << endl; - if (m_mem_fixed_delay) { - out << " Fixed Latency mode: Added cycles = " << m_mem_fixed_delay << endl; - } else { - out << " Bank busy time: " << m_bank_busy_time << " memory cycles" << endl; - out << " Memory channel busy time: " << m_basic_bus_busy_time << endl; - out << " Dead cycles between reads to different ranks: " << m_rank_rank_delay << endl; - out << " Dead cycle between a read and a write: " << m_read_write_delay << endl; - out << " tFaw (four-activate) window: " << m_tFaw << endl; - } - out << " Banks per rank: " << m_banks_per_rank << endl; - out << " Ranks per DIMM: " << m_ranks_per_dimm << endl; - out << " DIMMs per channel: " << m_dimms_per_channel << endl; - out << " LSB of bank field in address: " << m_bank_bit_0 << endl; - out << " LSB of rank field in address: " << m_rank_bit_0 << endl; - out << " LSB of DIMM field in address: " << m_dimm_bit_0 << endl; - out << " Max size of each bank queue: " << m_bank_queue_size << endl; - out << " Refresh period (within one bank): " << m_refresh_period << endl; - out << " Arbitration randomness: " << m_mem_random_arbitrate << endl; +MemoryNode +MemoryControl::peekNode() +{ + assert(isReady()); + MemoryNode req = m_response_queue.front(); + uint64 returnTime = req.m_time; + if (m_debug) { + cprintf("Old memory request%7d: %#08x %c peeked at %10d\n", + req.m_msg_counter, req.m_addr, req.m_is_mem_read ? 'R':'W', + returnTime); + } + return req; } +bool +MemoryControl::isReady() +{ + return ((!m_response_queue.empty()) && + (m_response_queue.front().m_time <= g_eventQueue_ptr->getTime())); +} -void MemoryControl::setDebug (int debugFlag) { - m_debug = debugFlag; +void +MemoryControl::setConsumer(Consumer* consumer_ptr) +{ + m_consumer_ptr = consumer_ptr; } -void MemoryControl::clearStats() const +void +MemoryControl::print(ostream& out) const { - m_profiler_ptr->clearStats(); } -void MemoryControl::printStats(ostream& out) const +void +MemoryControl::printConfig(ostream& out) { - m_profiler_ptr->printStats(out); + out << "Memory Control " << name() << ":" << endl; + out << " Ruby cycles per memory cycle: " << m_mem_bus_cycle_multiplier + << endl; + out << " Basic read latency: " << m_mem_ctl_latency << endl; + if (m_mem_fixed_delay) { + out << " Fixed Latency mode: Added cycles = " << m_mem_fixed_delay + << endl; + } else { + out << " Bank busy time: " << m_bank_busy_time << " memory cycles" + << endl; + out << " Memory channel busy time: " << m_basic_bus_busy_time << endl; + out << " Dead cycles between reads to different ranks: " + << m_rank_rank_delay << endl; + out << " Dead cycle between a read and a write: " + << m_read_write_delay << endl; + out << " tFaw (four-activate) window: " << m_tFaw << endl; + } + out << " Banks per rank: " << m_banks_per_rank << endl; + out << " Ranks per DIMM: " << m_ranks_per_dimm << endl; + out << " DIMMs per channel: " << m_dimms_per_channel << endl; + out << " LSB of bank field in address: " << m_bank_bit_0 << endl; + out << " LSB of rank field in address: " << m_rank_bit_0 << endl; + out << " LSB of DIMM field in address: " << m_dimm_bit_0 << endl; + out << " Max size of each bank queue: " << m_bank_queue_size << endl; + out << " Refresh period (within one bank): " << m_refresh_period << endl; + out << " Arbitration randomness: " << m_mem_random_arbitrate << endl; } +void +MemoryControl::setDebug(int debugFlag) +{ + m_debug = debugFlag; +} -// **************************************************************** +void +MemoryControl::clearStats() const +{ + m_profiler_ptr->clearStats(); +} -// PRIVATE METHODS +void +MemoryControl::printStats(ostream& out) const +{ + m_profiler_ptr->printStats(out); +} // Queue up a completed request to send back to directory +void +MemoryControl::enqueueToDirectory(MemoryNode req, int latency) +{ + Time arrival_time = g_eventQueue_ptr->getTime() + + (latency * m_mem_bus_cycle_multiplier); + req.m_time = arrival_time; + m_response_queue.push_back(req); -void MemoryControl::enqueueToDirectory (MemoryNode req, int latency) { - Time arrival_time = g_eventQueue_ptr->getTime() - + (latency * m_mem_bus_cycle_multiplier); - req.m_time = arrival_time; - m_response_queue.push_back(req); - - // schedule the wake up - g_eventQueue_ptr->scheduleEventAbsolute(m_consumer_ptr, arrival_time); + // schedule the wake up + g_eventQueue_ptr->scheduleEventAbsolute(m_consumer_ptr, arrival_time); } - - // getBank returns an integer that is unique for each // bank across this memory controller. - -int MemoryControl::getBank (physical_address_t addr) { - 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 +MemoryControl::getBank(physical_address_t addr) +{ + 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; } // getRank returns an integer that is unique for each rank // and independent of individual bank. - -int MemoryControl::getRank (int bank) { - int rank = (bank / m_banks_per_rank); - assert (rank < (m_ranks_per_dimm * m_dimms_per_channel)); - return rank; +int +MemoryControl::getRank(int bank) +{ + int rank = (bank / m_banks_per_rank); + assert (rank < (m_ranks_per_dimm * m_dimms_per_channel)); + return rank; } - // queueReady determines if the head item in a bank queue // can be issued this cycle +bool +MemoryControl::queueReady(int bank) +{ + if ((m_bankBusyCounter[bank] > 0) && !m_mem_fixed_delay) { + m_profiler_ptr->profileMemBankBusy(); +#if 0 + if (m_debug) + printf(" bank %x busy %d\n", bank, m_bankBusyCounter[bank]); +#endif + return false; + } -bool MemoryControl::queueReady (int bank) { - if ((m_bankBusyCounter[bank] > 0) && !m_mem_fixed_delay) { - m_profiler_ptr->profileMemBankBusy(); - //if (m_debug) printf(" bank %x busy %d\n", bank, m_bankBusyCounter[bank]); - return false; - } - if (m_mem_random_arbitrate >= 2) { - if ((random() % 100) < m_mem_random_arbitrate) { - m_profiler_ptr->profileMemRandBusy(); - return false; + if (m_mem_random_arbitrate >= 2) { + if ((random() % 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; -} + if (m_mem_fixed_delay) + return true; -// issueRefresh checks to see if this bank has a refresh scheduled -// and, if so, does the refresh and returns true + if ((m_ageCounter > (2 * m_bank_busy_time)) && !m_oldRequest[bank]) { + m_profiler_ptr->profileMemNotOld(); + return false; + } -bool MemoryControl::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: - - //if (m_debug) { - //uint64 current_time = g_eventQueue_ptr->getTime(); - //printf(" Refresh bank %3x at %lld\n", bank, current_time); - //} - 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; -} + 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; + } -// Mark the activate in the tFaw shift register -void MemoryControl::markTfaw (int rank) { - if (m_tFaw) { - m_tfaw_shift[rank] |= (1 << (m_tFaw-1)); - m_tfaw_count[rank]++; - } -} + 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; + } -// 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. + if (!write && (rank != m_busBusy_WhichRank) + && (m_busBusyCounter_ReadNewRank > 0)) { + m_profiler_ptr->profileMemDataBusBusy(); + return false; + } -void MemoryControl::issueRequest (int bank) { - int rank = getRank(bank); - MemoryNode req = m_bankQueues[bank].front(); - m_bankQueues[bank].pop_front(); - if (m_debug) { - uint64 current_time = g_eventQueue_ptr->getTime(); - printf(" Mem issue request%7d: 0x%08llx %c at %10lld bank =%3x\n", - req.m_msg_counter, req.m_addr, req.m_is_mem_read? 'R':'W', current_time, bank); - } - if (req.m_msgptr.ref() != NULL) { // don't enqueue L3 writebacks - enqueueToDirectory(req, 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(); + return true; +} + +// issueRefresh checks to see if this bank has a refresh scheduled +// and, if so, does the refresh and returns true +bool +MemoryControl::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: +#if 0 + if (m_debug) { + uint64 current_time = g_eventQueue_ptr->getTime(); + printf(" Refresh bank %3x at %lld\n", bank, current_time); + } +#endif + + 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 +MemoryControl::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 +MemoryControl::issueRequest(int bank) +{ + int rank = getRank(bank); + MemoryNode req = m_bankQueues[bank].front(); + m_bankQueues[bank].pop_front(); + if (m_debug) { + uint64 current_time = g_eventQueue_ptr->getTime(); + cprintf(" Mem issue request%7d: %#08x %c at %10d " + "bank=%3x\n", + req.m_msg_counter, req.m_addr, req.m_is_mem_read? 'R':'W', + current_time, bank); + } + if (req.m_msgptr.ref() != NULL) { // don't enqueue L3 writebacks + enqueueToDirectory(req, 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; + } +} // executeCycle: This function is called once per memory clock cycle // to simulate all the periodic hardware. +void +MemoryControl::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++; + } -void MemoryControl::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; - assert (m_need_refresh < 10); // Are we overrunning our ability to refresh? - 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) { + // 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++) { - if (!m_bankQueues[bank].empty()) m_oldRequest[bank] = 1; + anyOld |= m_oldRequest[bank]; } - m_ageCounter = 0; - } - - // If randomness desired, re-randomize round-robin position each cycle - if (m_mem_random_arbitrate) { - m_roundRobin = random() % m_total_banks; - } - - - // 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 (!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() % m_total_banks; } - if (qs > 0) { - m_idleCount = IDLECOUNT_MAX_VALUE; // we're not idle if anything is queued - queueHeads++; - if (queueReady(m_roundRobin)) { - issueRequest(m_roundRobin); - banksIssued++; - if (m_mem_fixed_delay) { - m_profiler_ptr->profileMemWaitCycles(m_mem_fixed_delay); + + // 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()) { - m_idleCount = IDLECOUNT_MAX_VALUE; // we're not idle if anything is pending - 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); + + // 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()); } - m_profiler_ptr->profileMemInputQ(m_input_queue.size()); - } } - // wakeup: This function is called once per memory controller clock cycle. - -void MemoryControl::wakeup () { - - // execute everything - executeCycle(); - - m_idleCount--; - if (m_idleCount <= 0) { - m_awakened = 0; - } else { - // Reschedule ourselves so that we run every memory cycle: - g_eventQueue_ptr->scheduleEvent(this, m_mem_bus_cycle_multiplier); - } +void +MemoryControl::wakeup() +{ + // execute everything + executeCycle(); + + m_idleCount--; + if (m_idleCount <= 0) { + m_awakened = 0; + } else { + // Reschedule ourselves so that we run every memory cycle: + g_eventQueue_ptr->scheduleEvent(this, m_mem_bus_cycle_multiplier); + } } MemoryControl * diff --git a/src/mem/ruby/system/MemoryControl.hh b/src/mem/ruby/system/MemoryControl.hh index b96055cb1..d42c1e6e0 100644 --- a/src/mem/ruby/system/MemoryControl.hh +++ b/src/mem/ruby/system/MemoryControl.hh @@ -1,4 +1,3 @@ - /* * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood * All rights reserved. @@ -27,34 +26,24 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -/* - * MemoryControl.hh - * - * Description: See MemoryControl.cc - * - * $Id: $ - * - */ +#ifndef __MEM_RUBY_SYSTEM_MEMORY_CONTROL_HH__ +#define __MEM_RUBY_SYSTEM_MEMORY_CONTROL_HH__ -#ifndef MEMORY_CONTROL_H -#define MEMORY_CONTROL_H +#include <list> -#include "mem/ruby/common/Global.hh" #include "mem/gems_common/Map.hh" -#include "mem/ruby/common/Address.hh" -#include "mem/ruby/profiler/MemCntrlProfiler.hh" -#include "mem/ruby/system/System.hh" -#include "mem/ruby/slicc_interface/Message.hh" #include "mem/gems_common/util.hh" -#include "mem/ruby/system/MemoryNode.hh" -// Note that "MemoryMsg" is in the "generated" directory: #include "mem/protocol/MemoryMsg.hh" +#include "mem/ruby/common/Address.hh" #include "mem/ruby/common/Consumer.hh" +#include "mem/ruby/common/Global.hh" +#include "mem/ruby/profiler/MemCntrlProfiler.hh" +#include "mem/ruby/slicc_interface/Message.hh" #include "mem/ruby/system/AbstractMemOrCache.hh" -#include "sim/sim_object.hh" +#include "mem/ruby/system/MemoryNode.hh" +#include "mem/ruby/system/System.hh" #include "params/RubyMemoryControl.hh" - -#include <list> +#include "sim/sim_object.hh" // This constant is part of the definition of tFAW; see // the comments in header to MemoryControl.cc @@ -64,124 +53,117 @@ class Consumer; -class MemoryControl : public SimObject, public Consumer, public AbstractMemOrCache { -public: - - // Constructors +class MemoryControl : + public SimObject, public Consumer, public AbstractMemOrCache +{ + public: typedef RubyMemoryControlParams Params; MemoryControl(const Params *p); - void init(); - - // Destructor - ~MemoryControl (); - - // Public Methods - - void wakeup() ; - - void setConsumer (Consumer* consumer_ptr); - Consumer* getConsumer () { return m_consumer_ptr; }; - void setDescription (const string& name) { m_description = name; }; - string getDescription () { return m_description; }; - - // Called from the directory: - void enqueue (const MsgPtr& message, int latency ); - void enqueueMemRef (MemoryNode& memRef); - void dequeue (); - const Message* peek (); - MemoryNode peekNode (); - bool isReady(); - bool areNSlotsAvailable (int n) { return true; }; // infinite queue length - - //// Called from L3 cache: - //void writeBack(physical_address_t addr); - - void printConfig (ostream& out); - void print (ostream& out) const; - void setDebug (int debugFlag); - void clearStats() const; - void printStats(ostream& out) 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; } - -private: - - void enqueueToDirectory (MemoryNode req, int latency); - int getBank (physical_address_t addr); - int getRank (int bank); - bool queueReady (int bank); - void issueRequest (int bank); - bool issueRefresh (int bank); - void markTfaw (int rank); - void executeCycle (); - - // Private copy constructor and assignment operator - MemoryControl (const MemoryControl& obj); - MemoryControl& operator=(const MemoryControl& obj); - - // data members - Consumer* m_consumer_ptr; // Consumer to signal a wakeup() - string m_description; - int m_msg_counter; - int m_awakened; - - int m_mem_bus_cycle_multiplier; - 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; - int m_mem_ctl_latency; - int m_refresh_period; - int m_mem_random_arbitrate; - int m_tFaw; - int m_mem_fixed_delay; - - int m_total_banks; - int m_total_ranks; - int m_refresh_period_system; - - // queues where memory requests live - - list<MemoryNode> m_response_queue; - list<MemoryNode> m_input_queue; - list<MemoryNode>* m_bankQueues; - - // Each entry indicates number of address-bus cycles until bank - // is reschedulable: - int* m_bankBusyCounter; - int* m_oldRequest; - - uint64* 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 - int m_debug; // turn on printf's - - MemCntrlProfiler* m_profiler_ptr; + void init(); + + ~MemoryControl(); + + void wakeup(); + + void setConsumer(Consumer* consumer_ptr); + Consumer* getConsumer() { return m_consumer_ptr; }; + void setDescription(const string& name) { m_description = name; }; + string getDescription() { return m_description; }; + + // Called from the directory: + void enqueue(const MsgPtr& message, int latency ); + void enqueueMemRef(MemoryNode& memRef); + void dequeue(); + const Message* peek(); + MemoryNode peekNode(); + bool isReady(); + bool areNSlotsAvailable(int n) { return true; }; // infinite queue length + + //// Called from L3 cache: + //void writeBack(physical_address_t addr); + + void printConfig(ostream& out); + void print(ostream& out) const; + void setDebug(int debugFlag); + void clearStats() const; + void printStats(ostream& out) 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; } + + private: + void enqueueToDirectory(MemoryNode req, int latency); + int getBank(physical_address_t addr); + int getRank(int bank); + bool queueReady(int bank); + void issueRequest(int bank); + bool issueRefresh(int bank); + void markTfaw(int rank); + void executeCycle(); + + // Private copy constructor and assignment operator + MemoryControl (const MemoryControl& obj); + MemoryControl& operator=(const MemoryControl& obj); + + // data members + Consumer* m_consumer_ptr; // Consumer to signal a wakeup() + string m_description; + int m_msg_counter; + int m_awakened; + + int m_mem_bus_cycle_multiplier; + 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; + int m_mem_ctl_latency; + int m_refresh_period; + int m_mem_random_arbitrate; + int m_tFaw; + int m_mem_fixed_delay; + + int m_total_banks; + int m_total_ranks; + int m_refresh_period_system; + + // queues where memory requests live + list<MemoryNode> m_response_queue; + list<MemoryNode> m_input_queue; + list<MemoryNode>* m_bankQueues; + + // Each entry indicates number of address-bus cycles until bank + // is reschedulable: + int* m_bankBusyCounter; + int* m_oldRequest; + + uint64* 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 + int m_debug; // turn on printf's + + MemCntrlProfiler* m_profiler_ptr; }; -#endif // MEMORY_CONTROL_H - +#endif // __MEM_RUBY_SYSTEM_MEMORY_CONTROL_HH__ diff --git a/src/mem/ruby/system/MemoryNode.cc b/src/mem/ruby/system/MemoryNode.cc index 5b74f497a..07262fba0 100644 --- a/src/mem/ruby/system/MemoryNode.cc +++ b/src/mem/ruby/system/MemoryNode.cc @@ -30,11 +30,12 @@ using namespace std; -void MemoryNode::print(ostream& out) const +void +MemoryNode::print(ostream& out) const { - out << "["; - out << m_time << ", "; - out << m_msg_counter << ", "; - out << m_msgptr << "; "; - out << "]"; + out << "["; + out << m_time << ", "; + out << m_msg_counter << ", "; + out << m_msgptr << "; "; + out << "]"; } diff --git a/src/mem/ruby/system/MemoryNode.hh b/src/mem/ruby/system/MemoryNode.hh index 2c2b987ae..10648b715 100644 --- a/src/mem/ruby/system/MemoryNode.hh +++ b/src/mem/ruby/system/MemoryNode.hh @@ -35,68 +35,59 @@ * message is enqueued to be sent back to the directory. */ -#ifndef MEMORYNODE_H -#define MEMORYNODE_H +#ifndef __MEM_RUBY_SYSTEM_MEMORYNODE_HH__ +#define __MEM_RUBY_SYSTEM_MEMORYNODE_HH__ #include <iostream> +#include "mem/protocol/MemoryRequestType.hh" #include "mem/ruby/common/Global.hh" #include "mem/ruby/slicc_interface/Message.hh" -#include "mem/protocol/MemoryRequestType.hh" - -class MemoryNode { - -public: - // Constructors - -// old one: - MemoryNode(const Time& time, int counter, const MsgPtr& msgptr, const physical_address_t addr, const bool is_mem_read) { - m_time = time; - m_msg_counter = counter; - m_msgptr = msgptr; - m_addr = addr; - m_is_mem_read = is_mem_read; - m_is_dirty_wb = !is_mem_read; - } - -// new one: - MemoryNode(const Time& time, const MsgPtr& msgptr, const physical_address_t addr, const bool is_mem_read, const bool is_dirty_wb) { - m_time = time; - m_msg_counter = 0; - m_msgptr = msgptr; - m_addr = addr; - m_is_mem_read = is_mem_read; - m_is_dirty_wb = is_dirty_wb; - } - // Destructor - ~MemoryNode() {}; - - // Public Methods - void print(std::ostream& out) const; - - // Data Members (m_ prefix) (all public -- this is really more a struct) - - Time m_time; - int m_msg_counter; - MsgPtr m_msgptr; - physical_address_t m_addr; - bool m_is_mem_read; - bool m_is_dirty_wb; +class MemoryNode +{ + public: + // old constructor + MemoryNode(const Time& time, int counter, const MsgPtr& msgptr, + const physical_address_t addr, const bool is_mem_read) + { + m_time = time; + m_msg_counter = counter; + m_msgptr = msgptr; + m_addr = addr; + m_is_mem_read = is_mem_read; + m_is_dirty_wb = !is_mem_read; + } + + // new constructor + MemoryNode(const Time& time, const MsgPtr& msgptr, + const physical_address_t addr, const bool is_mem_read, + const bool is_dirty_wb) + { + m_time = time; + m_msg_counter = 0; + m_msgptr = msgptr; + m_addr = addr; + m_is_mem_read = is_mem_read; + m_is_dirty_wb = is_dirty_wb; + } + + void print(std::ostream& out) const; + + Time m_time; + int m_msg_counter; + MsgPtr m_msgptr; + physical_address_t m_addr; + bool m_is_mem_read; + bool m_is_dirty_wb; }; -// Output operator declaration -std::ostream& operator<<(std::ostream& out, const MemoryNode& obj); - -// ******************* Definitions ******************* - -// Output operator definition -extern inline -std::ostream& operator<<(std::ostream& out, const MemoryNode& obj) +inline std::ostream& +operator<<(std::ostream& out, const MemoryNode& obj) { - obj.print(out); - out << std::flush; - return out; + obj.print(out); + out << std::flush; + return out; } -#endif //MEMORYNODE_H +#endif // __MEM_RUBY_SYSTEM_MEMORYNODE_HH__ diff --git a/src/mem/ruby/system/MemoryVector.hh b/src/mem/ruby/system/MemoryVector.hh index e450059fd..15cea168d 100644 --- a/src/mem/ruby/system/MemoryVector.hh +++ b/src/mem/ruby/system/MemoryVector.hh @@ -26,8 +26,8 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef MEMORYVECTOR_H -#define MEMORYVECTOR_H +#ifndef __MEM_RUBY_SYSTEM_MEMORYVECTOR_HH__ +#define __MEM_RUBY_SYSTEM_MEMORYVECTOR_HH__ #include "mem/ruby/common/Address.hh" @@ -36,117 +36,121 @@ class DirectoryMemory; /** * MemoryVector holds memory data (DRAM only) */ -class MemoryVector { - public: - MemoryVector(); - MemoryVector(uint32 size); - ~MemoryVector(); - friend class DirectoryMemory; +class MemoryVector +{ + public: + MemoryVector(); + MemoryVector(uint32 size); + ~MemoryVector(); + friend class DirectoryMemory; - void setSize(uint32 size); // destructive + void setSize(uint32 size); // destructive - void write(const Address & paddr, uint8* data, int len); - uint8* read(const Address & paddr, uint8* data, int len); + void write(const Address & paddr, uint8* data, int len); + uint8* read(const Address & paddr, uint8* data, int len); -private: - uint8* getBlockPtr(const PhysAddress & addr); + private: + uint8* getBlockPtr(const PhysAddress & addr); - uint32 m_size; - uint8** m_pages; - uint32 m_num_pages; - const uint32 m_page_offset_mask; + uint32 m_size; + uint8** m_pages; + uint32 m_num_pages; + const uint32 m_page_offset_mask; }; inline MemoryVector::MemoryVector() - : m_page_offset_mask(4095) + : m_page_offset_mask(4095) { - m_size = 0; - m_num_pages = 0; - m_pages = NULL; + m_size = 0; + m_num_pages = 0; + m_pages = NULL; } inline MemoryVector::MemoryVector(uint32 size) - : m_page_offset_mask(4095) + : m_page_offset_mask(4095) { - setSize(size); + setSize(size); } inline MemoryVector::~MemoryVector() { - for (int i=0; i<m_num_pages; i++) { - if (m_pages[i] != 0) { - delete [] m_pages[i]; + for (int i = 0; i < m_num_pages; i++) { + if (m_pages[i] != 0) { + delete [] m_pages[i]; + } } - } - delete [] m_pages; + delete [] m_pages; } -inline -void MemoryVector::setSize(uint32 size) +inline void +MemoryVector::setSize(uint32 size) { - if (m_pages != NULL){ - for (int i=0; i<m_num_pages; i++) { - if (m_pages[i] != 0) { - delete [] m_pages[i]; - } + if (m_pages != NULL){ + for (int i = 0; i < m_num_pages; i++) { + if (m_pages[i] != 0) { + delete [] m_pages[i]; + } + } + delete [] m_pages; } - delete [] m_pages; - } - m_size = size; - assert(size%4096 == 0); - m_num_pages = size >> 12; - m_pages = new uint8*[m_num_pages]; - memset(m_pages, 0, m_num_pages * sizeof(uint8*)); + m_size = size; + assert(size%4096 == 0); + m_num_pages = size >> 12; + m_pages = new uint8*[m_num_pages]; + memset(m_pages, 0, m_num_pages * sizeof(uint8*)); } -inline -void MemoryVector::write(const Address & paddr, uint8* data, int len) +inline void +MemoryVector::write(const Address & paddr, uint8* data, int len) { - assert(paddr.getAddress() + len <= m_size); - uint32 page_num = paddr.getAddress() >> 12; - if (m_pages[page_num] == 0) { - bool all_zeros = true; - for (int i=0;i<len;i++) { - if (data[i] != 0) { - all_zeros = false; - break; - } + assert(paddr.getAddress() + len <= m_size); + uint32 page_num = paddr.getAddress() >> 12; + if (m_pages[page_num] == 0) { + bool all_zeros = true; + for (int i = 0; i < len;i++) { + if (data[i] != 0) { + all_zeros = false; + break; + } + } + if (all_zeros) + return; + m_pages[page_num] = new uint8[4096]; + memset(m_pages[page_num], 0, 4096); + uint32 offset = paddr.getAddress() & m_page_offset_mask; + memcpy(&m_pages[page_num][offset], data, len); + } else { + memcpy(&m_pages[page_num][paddr.getAddress()&m_page_offset_mask], + data, len); } - if (all_zeros) return; - m_pages[page_num] = new uint8[4096]; - memset(m_pages[page_num], 0, 4096); - uint32 offset = paddr.getAddress() & m_page_offset_mask; - memcpy(&m_pages[page_num][offset], data, len); - } else { - memcpy(&m_pages[page_num][paddr.getAddress()&m_page_offset_mask], data, len); - } } -inline -uint8* MemoryVector::read(const Address & paddr, uint8* data, int len) +inline uint8* +MemoryVector::read(const Address & paddr, uint8* data, int len) { - assert(paddr.getAddress() + len <= m_size); - uint32 page_num = paddr.getAddress() >> 12; - if (m_pages[page_num] == 0) { - memset(data, 0, len); - } else { - memcpy(data, &m_pages[page_num][paddr.getAddress()&m_page_offset_mask], len); - } - return data; + assert(paddr.getAddress() + len <= m_size); + uint32 page_num = paddr.getAddress() >> 12; + if (m_pages[page_num] == 0) { + memset(data, 0, len); + } else { + memcpy(data, &m_pages[page_num][paddr.getAddress()&m_page_offset_mask], + len); + } + return data; } -inline -uint8* MemoryVector::getBlockPtr(const PhysAddress & paddr) +inline uint8* +MemoryVector::getBlockPtr(const PhysAddress & paddr) { - uint32 page_num = paddr.getAddress() >> 12; - if (m_pages[page_num] == 0) { - m_pages[page_num] = new uint8[4096]; - memset(m_pages[page_num], 0, 4096); - } - return &m_pages[page_num][paddr.getAddress()&m_page_offset_mask]; + uint32 page_num = paddr.getAddress() >> 12; + if (m_pages[page_num] == 0) { + m_pages[page_num] = new uint8[4096]; + memset(m_pages[page_num], 0, 4096); + } + return &m_pages[page_num][paddr.getAddress()&m_page_offset_mask]; } -#endif // MEMORYVECTOR_H +#endif // __MEM_RUBY_SYSTEM_MEMORYVECTOR_HH__ diff --git a/src/mem/ruby/system/NodeID.hh b/src/mem/ruby/system/NodeID.hh index 6191ad489..4ce8d8a8d 100644 --- a/src/mem/ruby/system/NodeID.hh +++ b/src/mem/ruby/system/NodeID.hh @@ -1,4 +1,3 @@ - /* * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood * All rights reserved. @@ -27,26 +26,20 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -/* - * NodeID.hh - * - * Description: - * - * $Id: NodeID.hh,v 3.3 2003/12/04 15:01:39 xu Exp $ - * - */ - -#ifndef NODEID_H -#define NODEID_H +#ifndef __MEM_RUBY_SYSTEM_NODEID_HH__ +#define __MEM_RUBY_SYSTEM_NODEID_HH__ #include <string> -#include "mem/ruby/common/Global.hh" #include "mem/gems_common/util.hh" +#include "mem/ruby/common/Global.hh" typedef int NodeID; -extern inline -std::string NodeIDToString (NodeID node) { return int_to_string(node); } +inline std::string +NodeIDToString(NodeID node) +{ + return int_to_string(node); +} -#endif //NODEID_H +#endif // __MEM_RUBY_SYSTEM_NODEID_HH__ diff --git a/src/mem/ruby/system/PerfectCacheMemory.hh b/src/mem/ruby/system/PerfectCacheMemory.hh index 6561d028b..f1fb8b2e9 100644 --- a/src/mem/ruby/system/PerfectCacheMemory.hh +++ b/src/mem/ruby/system/PerfectCacheMemory.hh @@ -1,4 +1,3 @@ - /* * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood * All rights reserved. @@ -27,215 +26,188 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -/* - * PerfectCacheMemory.hh - * - * Description: - * - * $Id$ - * - */ - -#ifndef PERFECTCACHEMEMORY_H -#define PERFECTCACHEMEMORY_H +#ifndef __MEM_RUBY_SYSTEM_PERFECTCACHEMEMORY_HH__ +#define __MEM_RUBY_SYSTEM_PERFECTCACHEMEMORY_HH__ -#include "mem/ruby/common/Global.hh" #include "mem/gems_common/Map.hh" #include "mem/protocol/AccessPermission.hh" #include "mem/ruby/common/Address.hh" +#include "mem/ruby/common/Global.hh" template<class ENTRY> -class PerfectCacheLineState { -public: - PerfectCacheLineState() { m_permission = AccessPermission_NUM; } - AccessPermission m_permission; - ENTRY m_entry; +struct PerfectCacheLineState +{ + PerfectCacheLineState() { m_permission = AccessPermission_NUM; } + AccessPermission m_permission; + ENTRY m_entry; }; template<class ENTRY> -extern inline -ostream& operator<<(ostream& out, const PerfectCacheLineState<ENTRY>& obj) +inline ostream& +operator<<(ostream& out, const PerfectCacheLineState<ENTRY>& obj) { - return out; + return out; } template<class ENTRY> -class PerfectCacheMemory { -public: - - // Constructors - PerfectCacheMemory(); - - // Destructor - //~PerfectCacheMemory(); - - // Public Methods +class PerfectCacheMemory +{ + public: + PerfectCacheMemory(); - static void printConfig(ostream& out); + static void printConfig(ostream& out); - // perform a cache access and see if we hit or not. Return true on - // a hit. - bool tryCacheAccess(const CacheMsg& msg, bool& block_stc, ENTRY*& entry); + // perform a cache access and see if we hit or not. Return true + // on a hit. + bool tryCacheAccess(const CacheMsg& msg, bool& block_stc, ENTRY*& entry); - // tests to see if an address is present in the cache - bool isTagPresent(const Address& address) const; + // tests to see if an address is present in the cache + bool isTagPresent(const Address& address) const; - // Returns true if there is: - // a) a tag match on this address or there is - // b) an Invalid line in the same cache "way" - bool cacheAvail(const Address& address) const; + // Returns true if there is: + // a) a tag match on this address or there is + // b) an Invalid line in the same cache "way" + bool cacheAvail(const Address& address) const; - // find an Invalid entry and sets the tag appropriate for the address - void allocate(const Address& address); + // find an Invalid entry and sets the tag appropriate for the address + void allocate(const Address& address); - void deallocate(const Address& address); + void deallocate(const Address& address); - // Returns with the physical address of the conflicting cache line - Address cacheProbe(const Address& newAddress) const; + // Returns with the physical address of the conflicting cache line + Address cacheProbe(const Address& newAddress) const; - // looks an address up in the cache - ENTRY& lookup(const Address& address); - const ENTRY& lookup(const Address& address) const; + // looks an address up in the cache + ENTRY& lookup(const Address& address); + const ENTRY& lookup(const Address& address) const; - // Get/Set permission of cache block - AccessPermission getPermission(const Address& address) const; - void changePermission(const Address& address, AccessPermission new_perm); + // Get/Set permission of cache block + AccessPermission getPermission(const Address& address) const; + void changePermission(const Address& address, AccessPermission new_perm); - // Print cache contents - void print(ostream& out) const; -private: - // Private Methods + // Print cache contents + void print(ostream& out) const; - // Private copy constructor and assignment operator - PerfectCacheMemory(const PerfectCacheMemory& obj); - PerfectCacheMemory& operator=(const PerfectCacheMemory& obj); + private: + // Private copy constructor and assignment operator + PerfectCacheMemory(const PerfectCacheMemory& obj); + PerfectCacheMemory& operator=(const PerfectCacheMemory& obj); - // Data Members (m_prefix) - Map<Address, PerfectCacheLineState<ENTRY> > m_map; + // Data Members (m_prefix) + Map<Address, PerfectCacheLineState<ENTRY> > m_map; }; -// Output operator declaration -//ostream& operator<<(ostream& out, const PerfectCacheMemory<ENTRY>& obj); - -// ******************* Definitions ******************* - -// Output operator definition template<class ENTRY> -extern inline -ostream& operator<<(ostream& out, const PerfectCacheMemory<ENTRY>& obj) +inline ostream& +operator<<(ostream& out, const PerfectCacheMemory<ENTRY>& obj) { - obj.print(out); - out << flush; - return out; + obj.print(out); + out << flush; + return out; } - -// **************************************************************** - template<class ENTRY> -extern inline +inline PerfectCacheMemory<ENTRY>::PerfectCacheMemory() { } -// STATIC METHODS - template<class ENTRY> -extern inline -void PerfectCacheMemory<ENTRY>::printConfig(ostream& out) +inline void +PerfectCacheMemory<ENTRY>::printConfig(ostream& out) { } -// PUBLIC METHODS - template<class ENTRY> -extern inline -bool PerfectCacheMemory<ENTRY>::tryCacheAccess(const CacheMsg& msg, bool& block_stc, ENTRY*& entry) +inline bool +PerfectCacheMemory<ENTRY>::tryCacheAccess(const CacheMsg& msg, + bool& block_stc, ENTRY*& entry) { - ERROR_MSG("not implemented"); + ERROR_MSG("not implemented"); } // tests to see if an address is present in the cache template<class ENTRY> -extern inline -bool PerfectCacheMemory<ENTRY>::isTagPresent(const Address& address) const +inline bool +PerfectCacheMemory<ENTRY>::isTagPresent(const Address& address) const { - return m_map.exist(line_address(address)); + return m_map.exist(line_address(address)); } template<class ENTRY> -extern inline -bool PerfectCacheMemory<ENTRY>::cacheAvail(const Address& address) const +inline bool +PerfectCacheMemory<ENTRY>::cacheAvail(const Address& address) const { - return true; + return true; } // find an Invalid or already allocated entry and sets the tag // appropriate for the address template<class ENTRY> -extern inline -void PerfectCacheMemory<ENTRY>::allocate(const Address& address) +inline void +PerfectCacheMemory<ENTRY>::allocate(const Address& address) { - PerfectCacheLineState<ENTRY> line_state; - line_state.m_permission = AccessPermission_Busy; - line_state.m_entry = ENTRY(); - m_map.add(line_address(address), line_state); + PerfectCacheLineState<ENTRY> line_state; + line_state.m_permission = AccessPermission_Busy; + line_state.m_entry = ENTRY(); + m_map.add(line_address(address), line_state); } // deallocate entry template<class ENTRY> -extern inline -void PerfectCacheMemory<ENTRY>::deallocate(const Address& address) +inline void +PerfectCacheMemory<ENTRY>::deallocate(const Address& address) { - m_map.erase(line_address(address)); + m_map.erase(line_address(address)); } // Returns with the physical address of the conflicting cache line template<class ENTRY> -extern inline -Address PerfectCacheMemory<ENTRY>::cacheProbe(const Address& newAddress) const +inline Address +PerfectCacheMemory<ENTRY>::cacheProbe(const Address& newAddress) const { - ERROR_MSG("cacheProbe called in perfect cache"); + ERROR_MSG("cacheProbe called in perfect cache"); } // looks an address up in the cache template<class ENTRY> -extern inline -ENTRY& PerfectCacheMemory<ENTRY>::lookup(const Address& address) +inline ENTRY& +PerfectCacheMemory<ENTRY>::lookup(const Address& address) { - return m_map.lookup(line_address(address)).m_entry; + return m_map.lookup(line_address(address)).m_entry; } // looks an address up in the cache template<class ENTRY> -extern inline -const ENTRY& PerfectCacheMemory<ENTRY>::lookup(const Address& address) const +inline const ENTRY& +PerfectCacheMemory<ENTRY>::lookup(const Address& address) const { - return m_map.lookup(line_address(address)).m_entry; + return m_map.lookup(line_address(address)).m_entry; } template<class ENTRY> -extern inline -AccessPermission PerfectCacheMemory<ENTRY>::getPermission(const Address& address) const +inline AccessPermission +PerfectCacheMemory<ENTRY>::getPermission(const Address& address) const { - return m_map.lookup(line_address(address)).m_permission; + return m_map.lookup(line_address(address)).m_permission; } template<class ENTRY> -extern inline -void PerfectCacheMemory<ENTRY>::changePermission(const Address& address, AccessPermission new_perm) +inline void +PerfectCacheMemory<ENTRY>::changePermission(const Address& address, + AccessPermission new_perm) { - Address line_address = address; - line_address.makeLineAddress(); - PerfectCacheLineState<ENTRY>& line_state = m_map.lookup(line_address); - AccessPermission old_perm = line_state.m_permission; - line_state.m_permission = new_perm; + Address line_address = address; + line_address.makeLineAddress(); + PerfectCacheLineState<ENTRY>& line_state = m_map.lookup(line_address); + AccessPermission old_perm = line_state.m_permission; + line_state.m_permission = new_perm; } template<class ENTRY> -extern inline -void PerfectCacheMemory<ENTRY>::print(ostream& out) const +inline void +PerfectCacheMemory<ENTRY>::print(ostream& out) const { } -#endif //PERFECTCACHEMEMORY_H +#endif // __MEM_RUBY_SYSTEM_PERFECTCACHEMEMORY_HH__ diff --git a/src/mem/ruby/system/PersistentTable.cc b/src/mem/ruby/system/PersistentTable.cc index 58b67ea60..1d971ae21 100644 --- a/src/mem/ruby/system/PersistentTable.cc +++ b/src/mem/ruby/system/PersistentTable.cc @@ -1,4 +1,3 @@ - /* * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood * All rights reserved. @@ -27,178 +26,187 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include "mem/ruby/system/PersistentTable.hh" #include "mem/gems_common/util.hh" +#include "mem/ruby/system/PersistentTable.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}; - +#if 0 +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}; +#endif PersistentTable::PersistentTable() { - m_map_ptr = new Map<Address, PersistentTableEntry>; + m_map_ptr = new Map<Address, PersistentTableEntry>; } PersistentTable::~PersistentTable() { - delete m_map_ptr; - m_map_ptr = NULL; + delete m_map_ptr; + m_map_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; - - // 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); +#if 0 + if (locker == m_chip_ptr->getID()) + cout << "Chip " << m_chip_ptr->getID() << ": " << llocker + << " requesting lock for " << address << endl; + + MachineID locker = (MachineID) persistent_randomize[llocker]; +#endif + + 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); + + // + // 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) { + entry.m_request_to_write.add(locker); + } + assert(entry.m_marked.isSubset(entry.m_starving)); } - m_map_ptr->add(address, entry); - } else { +} + +void +PersistentTable::persistentRequestUnlock(const Address& address, + MachineID unlocker) +{ +#if 0 + if (unlocker == m_chip_ptr->getID()) + cout << "Chip " << m_chip_ptr->getID() << ": " << uunlocker + << " requesting unlock for " << address << endl; + + MachineID unlocker = (MachineID) persistent_randomize[uunlocker]; +#endif + + assert(address == line_address(address)); + assert(m_map_ptr->exist(address)); PersistentTableEntry& entry = m_map_ptr->lookup(address); // - // Make sure we're not already in the locked set + // Make sure we're in the locked set // - assert(!(entry.m_starving.isElement(locker))); - - entry.m_starving.add(locker); - if (type == AccessType_Write) { - entry.m_request_to_write.add(locker); - } + assert(entry.m_starving.isElement(unlocker)); + 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)); - } -} -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); - - // - // 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); - 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); - } + // Deallocate if empty + if (entry.m_starving.isEmpty()) { + assert(entry.m_marked.isEmpty()); + m_map_ptr->erase(address); + } } -bool PersistentTable::okToIssueStarving(const Address& address, - MachineID machId) const +bool +PersistentTable::okToIssueStarving(const Address& address, + MachineID machId) const { - assert(address == line_address(address)); - if (!m_map_ptr->exist(address)) { - // - // 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()); - } + assert(address == line_address(address)); + if (!m_map_ptr->exist(address)) { + // 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(); + } } -MachineID PersistentTable::findSmallest(const Address& address) const +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); - return entry.m_starving.smallestElement(); + assert(address == line_address(address)); + assert(m_map_ptr->exist(address)); + const PersistentTableEntry& entry = m_map_ptr->lookup(address); + return entry.m_starving.smallestElement(); } -AccessType PersistentTable::typeOfSmallest(const Address& address) const +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(entry.m_starving.smallestElement())) { - return AccessType_Write; - } else { - return AccessType_Read; - } + 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(entry.m_starving.smallestElement())) { + return AccessType_Write; + } else { + return AccessType_Read; + } } -void PersistentTable::markEntries(const Address& address) +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(address == line_address(address)); + if (m_map_ptr->exist(address)) { + PersistentTableEntry& entry = m_map_ptr->lookup(address); - // - // None should be marked - // - assert(entry.m_marked.isEmpty()); + // None should be marked + assert(entry.m_marked.isEmpty()); - // - // Mark all the nodes currently in the table - // - entry.m_marked = entry.m_starving; - } + // Mark all the nodes currently in the table + entry.m_marked = entry.m_starving; + } } -bool PersistentTable::isLocked(const Address& address) const +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)); + 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 +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; - } + 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 +PersistentTable::countReadStarvingForAddress(const Address& address) const { - 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; - } + 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; + } } -void PersistentTable::print(ostream& out) const +void +PersistentTable::print(ostream& out) const { } diff --git a/src/mem/ruby/system/PersistentTable.hh b/src/mem/ruby/system/PersistentTable.hh index 8cbb48817..defcae2b8 100644 --- a/src/mem/ruby/system/PersistentTable.hh +++ b/src/mem/ruby/system/PersistentTable.hh @@ -1,4 +1,3 @@ - /* * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood * All rights reserved. @@ -27,76 +26,74 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef PersistentTable_H -#define PersistentTable_H +#ifndef __MEM_RUBY_SYSTEM_PERSISTENTTABLE_HH__ +#define __MEM_RUBY_SYSTEM_PERSISTENTTABLE_HH__ -#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/Address.hh" +#include "mem/ruby/common/Global.hh" #include "mem/ruby/common/NetDest.hh" +#include "mem/ruby/system/MachineID.hh" -class PersistentTableEntry { -public: - void print(ostream& out) const {} +class PersistentTableEntry +{ + public: + void print(ostream& out) const {} - NetDest m_starving; - NetDest m_marked; - NetDest m_request_to_write; + NetDest m_starving; + NetDest m_marked; + NetDest m_request_to_write; }; -class PersistentTable { -public: - // Constructors - PersistentTable(); +class PersistentTable +{ + public: + // Constructors + PersistentTable(); - // Destructor - ~PersistentTable(); + // 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, MachineID machID) 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; + // Public Methods + void persistentRequestLock(const Address& address, MachineID locker, + AccessType type); + void persistentRequestUnlock(const Address& address, MachineID unlocker); + 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); + bool isLocked(const Address& addr) const; + int countStarvingForAddress(const Address& addr) const; + int countReadStarvingForAddress(const Address& addr) const; - static void printConfig(ostream& out) {} + static void printConfig(ostream& out) {} - void print(ostream& out) const; -private: - // Private Methods + void print(ostream& out) const; - // Private copy constructor and assignment operator - PersistentTable(const PersistentTable& obj); - PersistentTable& operator=(const PersistentTable& obj); + private: + // Private copy constructor and assignment operator + PersistentTable(const PersistentTable& obj); + PersistentTable& operator=(const PersistentTable& obj); - // Data Members (m_prefix) - Map<Address, PersistentTableEntry>* m_map_ptr; + // Data Members (m_prefix) + Map<Address, PersistentTableEntry>* m_map_ptr; }; -// ******************* Definitions ******************* - -// Output operator definition -extern inline -ostream& operator<<(ostream& out, const PersistentTable& obj) +inline ostream& +operator<<(ostream& out, const PersistentTable& obj) { - obj.print(out); - out << flush; - return out; + obj.print(out); + out << flush; + return out; } -// Output operator definition -extern inline -ostream& operator<<(ostream& out, const PersistentTableEntry& obj) +inline ostream& +operator<<(ostream& out, const PersistentTableEntry& obj) { - obj.print(out); - out << flush; - return out; + obj.print(out); + out << flush; + return out; } -#endif //PersistentTable_H +#endif // __MEM_RUBY_SYSTEM_PERSISTENTTABLE_HH__ diff --git a/src/mem/ruby/system/PseudoLRUPolicy.hh b/src/mem/ruby/system/PseudoLRUPolicy.hh index 61bf72c3e..1e1e68188 100644 --- a/src/mem/ruby/system/PseudoLRUPolicy.hh +++ b/src/mem/ruby/system/PseudoLRUPolicy.hh @@ -26,8 +26,8 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef PSEUDOLRUPOLICY_H -#define PSEUDOLRUPOLICY_H +#ifndef __MEM_RUBY_SYSTEM_PSEUDOLRUPOLICY_HH__ +#define __MEM_RUBY_SYSTEM_PSEUDOLRUPOLICY_HH__ #include "mem/ruby/system/AbstractReplacementPolicy.hh" @@ -44,94 +44,97 @@ * 2 is one below the associativy, and most fair when it is one above. */ -class PseudoLRUPolicy : public AbstractReplacementPolicy { - public: - - PseudoLRUPolicy(Index num_sets, Index assoc); - ~PseudoLRUPolicy(); - - void touch(Index set, Index way, Time time); - Index getVictim(Index set) const; - - private: - unsigned int m_effective_assoc; /** nearest (to ceiling) power of 2 */ - unsigned int m_num_levels; /** number of levels in the tree */ - uint64* m_trees; /** bit representation of the trees, one for each set */ +class PseudoLRUPolicy : public AbstractReplacementPolicy +{ + public: + PseudoLRUPolicy(Index num_sets, Index assoc); + ~PseudoLRUPolicy(); + + void touch(Index set, Index way, Time time); + Index getVictim(Index set) const; + + private: + unsigned int m_effective_assoc; /** nearest (to ceiling) power of 2 */ + unsigned int m_num_levels; /** number of levels in the tree */ + uint64* m_trees; /** bit representation of the + * trees, one for each set */ }; inline PseudoLRUPolicy::PseudoLRUPolicy(Index num_sets, Index assoc) - : AbstractReplacementPolicy(num_sets, assoc) + : AbstractReplacementPolicy(num_sets, assoc) { - int num_tree_nodes; - - // associativity cannot exceed capacity of tree representation - assert(num_sets > 0 && assoc > 1 && assoc <= (Index) sizeof(uint64)*4); - - m_trees = NULL; - m_num_levels = 0; - - m_effective_assoc = 1; - while(m_effective_assoc < assoc){ - m_effective_assoc <<= 1; // effective associativity is ceiling power of 2 - } - assoc = m_effective_assoc; - while(true){ - assoc /= 2; - if(!assoc) break; - m_num_levels++; - } - assert(m_num_levels < sizeof(unsigned int)*4); - num_tree_nodes = (1 << m_num_levels) - 1; - m_trees = new uint64[m_num_sets]; - for(unsigned int i=0; i< m_num_sets; i++){ - m_trees[i] = 0; - } + int num_tree_nodes; + + // associativity cannot exceed capacity of tree representation + assert(num_sets > 0 && assoc > 1 && assoc <= (Index) sizeof(uint64)*4); + + m_trees = NULL; + m_num_levels = 0; + + m_effective_assoc = 1; + while (m_effective_assoc < assoc) { + // effective associativity is ceiling power of 2 + m_effective_assoc <<= 1; + } + assoc = m_effective_assoc; + while (true) { + assoc /= 2; + if(!assoc) break; + m_num_levels++; + } + assert(m_num_levels < sizeof(unsigned int)*4); + num_tree_nodes = (1 << m_num_levels) - 1; + m_trees = new uint64[m_num_sets]; + for (unsigned i = 0; i < m_num_sets; i++) { + m_trees[i] = 0; + } } inline PseudoLRUPolicy::~PseudoLRUPolicy() { - if(m_trees != NULL) - delete[] m_trees; + if (m_trees != NULL) + delete[] m_trees; } -inline -void PseudoLRUPolicy::touch(Index set, Index index, Time time){ - assert(index >= 0 && index < m_assoc); - assert(set >= 0 && set < m_num_sets); - - int tree_index = 0; - int node_val; - for(int i=m_num_levels -1; i>=0; i--){ - node_val = (index >> i)&1; - if(node_val) - m_trees[set] |= node_val << tree_index; - else - m_trees[set] &= ~(1 << tree_index); - tree_index = node_val ? (tree_index*2)+2 : (tree_index*2)+1; - } - m_last_ref_ptr[set][index] = time; +inline void +PseudoLRUPolicy::touch(Index set, Index index, Time time) +{ + assert(index >= 0 && index < m_assoc); + assert(set >= 0 && set < m_num_sets); + + int tree_index = 0; + int node_val; + for (int i = m_num_levels - 1; i >= 0; i--) { + node_val = (index >> i)&1; + if (node_val) + m_trees[set] |= node_val << tree_index; + else + m_trees[set] &= ~(1 << tree_index); + tree_index = node_val ? (tree_index*2)+2 : (tree_index*2)+1; + } + m_last_ref_ptr[set][index] = time; } -inline -Index PseudoLRUPolicy::getVictim(Index set) const { - // assert(m_assoc != 0); - - Index index = 0; - - int tree_index = 0; - int node_val; - for(unsigned int i=0;i<m_num_levels;i++){ - node_val = (m_trees[set]>>tree_index)&1; - index += node_val?0:(m_effective_assoc >> (i+1)); - tree_index = node_val? (tree_index*2)+1 : (tree_index*2)+2; - } - assert(index >= 0 && index < m_effective_assoc); - - /* return either the found index or the max possible index */ - /* NOTE: this is not a fair replacement when assoc is not a power of 2 */ - return (index > (m_assoc-1)) ? m_assoc-1:index; +inline Index +PseudoLRUPolicy::getVictim(Index set) const +{ + // assert(m_assoc != 0); + Index index = 0; + + int tree_index = 0; + int node_val; + for (unsigned i = 0; i < m_num_levels; i++){ + node_val = (m_trees[set] >> tree_index) & 1; + index += node_val ? 0 : (m_effective_assoc >> (i + 1)); + tree_index = node_val ? (tree_index * 2) + 1 : (tree_index * 2) + 2; + } + assert(index >= 0 && index < m_effective_assoc); + + /* return either the found index or the max possible index */ + /* NOTE: this is not a fair replacement when assoc is not a power of 2 */ + return (index > (m_assoc - 1)) ? m_assoc - 1 : index; } -#endif // PSEUDOLRUPOLICY_H +#endif // __MEM_RUBY_SYSTEM_PSEUDOLRUPOLICY_HH__ diff --git a/src/mem/ruby/system/RubyPort.cc b/src/mem/ruby/system/RubyPort.cc index 480c13ad8..87a98185c 100644 --- a/src/mem/ruby/system/RubyPort.cc +++ b/src/mem/ruby/system/RubyPort.cc @@ -1,4 +1,3 @@ - /* * Copyright (c) 2009 Advanced Micro Devices, Inc. * All rights reserved. @@ -27,10 +26,10 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +#include "cpu/rubytest/RubyTester.hh" #include "mem/physical.hh" -#include "mem/ruby/system/RubyPort.hh" #include "mem/ruby/slicc_interface/AbstractController.hh" -#include "cpu/rubytest/RubyTester.hh" +#include "mem/ruby/system/RubyPort.hh" RubyPort::RubyPort(const Params *p) : MemObject(p) @@ -39,7 +38,7 @@ RubyPort::RubyPort(const Params *p) assert(m_version != -1); physmem = p->physmem; - + m_controller = NULL; m_mandatory_q_ptr = NULL; @@ -48,7 +47,8 @@ RubyPort::RubyPort(const Params *p) physMemPort = NULL; } -void RubyPort::init() +void +RubyPort::init() { assert(m_controller != NULL); m_mandatory_q_ptr = m_controller->getMandatoryQueue(); @@ -59,38 +59,38 @@ RubyPort::getPort(const std::string &if_name, int idx) { if (if_name == "port") { return new M5Port(csprintf("%s-port%d", name(), idx), this); - } else if (if_name == "pio_port") { - // + } + + if (if_name == "pio_port") { // ensure there is only one pio port - // assert(pio_port == NULL); - pio_port = new PioPort(csprintf("%s-pio-port%d", name(), idx), - this); + pio_port = new PioPort(csprintf("%s-pio-port%d", name(), idx), this); return pio_port; - } else if (if_name == "physMemPort") { - // + } + + if (if_name == "physMemPort") { // RubyPort should only have one port to physical memory - // assert (physMemPort == NULL); - physMemPort = new M5Port(csprintf("%s-physMemPort", name()), - this); - + physMemPort = new M5Port(csprintf("%s-physMemPort", name()), this); + return physMemPort; - } else if (if_name == "functional") { - // - // Calls for the functional port only want to access functional memory. - // Therefore, directly pass these calls ports to physmem. - // + } + + if (if_name == "functional") { + // Calls for the functional port only want to access + // functional memory. Therefore, directly pass these calls + // ports to physmem. assert(physmem != NULL); return physmem->getPort(if_name, idx); } + return NULL; } -RubyPort::PioPort::PioPort(const std::string &_name, +RubyPort::PioPort::PioPort(const std::string &_name, RubyPort *_port) : SimpleTimingPort(_name, _port) { @@ -98,7 +98,7 @@ RubyPort::PioPort::PioPort(const std::string &_name, ruby_port = _port; } -RubyPort::M5Port::M5Port(const std::string &_name, +RubyPort::M5Port::M5Port(const std::string &_name, RubyPort *_port) : SimpleTimingPort(_name, _port) { @@ -113,7 +113,6 @@ RubyPort::PioPort::recvAtomic(PacketPtr pkt) return 0; } - Tick RubyPort::M5Port::recvAtomic(PacketPtr pkt) { @@ -125,48 +124,39 @@ RubyPort::M5Port::recvAtomic(PacketPtr pkt) bool RubyPort::PioPort::recvTiming(PacketPtr pkt) { - // - // In FS mode, ruby memory will receive pio responses from devices and - // it must forward these responses back to the particular CPU. - // - DPRINTF(MemoryAccess, - "Pio response for address %#x\n", - pkt->getAddr()); + // In FS mode, ruby memory will receive pio responses from devices + // and it must forward these responses back to the particular CPU. + DPRINTF(MemoryAccess, "Pio response for address %#x\n", pkt->getAddr()); assert(pkt->isResponse()); - // // First we must retrieve the request port from the sender State - // - RubyPort::SenderState *senderState = + RubyPort::SenderState *senderState = safe_cast<RubyPort::SenderState *>(pkt->senderState); M5Port *port = senderState->port; assert(port != NULL); - + // pop the sender state from the packet pkt->senderState = senderState->saved; delete senderState; - + port->sendTiming(pkt); - + return true; } bool RubyPort::M5Port::recvTiming(PacketPtr pkt) { - DPRINTF(MemoryAccess, - "Timing access caught for address %#x\n", - pkt->getAddr()); + DPRINTF(MemoryAccess, + "Timing access caught for address %#x\n", pkt->getAddr()); //dsm: based on SimpleTimingPort::recvTiming(pkt); - // - // The received packets should only be M5 requests, which should never - // get nacked. There used to be code to hanldle nacks here, but - // I'm pretty sure it didn't work correctly with the drain code, + // The received packets should only be M5 requests, which should never + // get nacked. There used to be code to hanldle nacks here, but + // I'm pretty sure it didn't work correctly with the drain code, // so that would need to be fixed if we ever added it back. - // assert(pkt->isRequest()); if (pkt->memInhibitAsserted()) { @@ -177,34 +167,26 @@ RubyPort::M5Port::recvTiming(PacketPtr pkt) return true; } - // // Save the port in the sender state object to be used later to // route the response - // pkt->senderState = new SenderState(this, pkt->senderState); - // // Check for pio requests and directly send them to the dedicated // pio port. - // if (!isPhysMemAddress(pkt->getAddr())) { assert(ruby_port->pio_port != NULL); - DPRINTF(MemoryAccess, + DPRINTF(MemoryAccess, "Request for address 0x%#x is assumed to be a pio request\n", pkt->getAddr()); return ruby_port->pio_port->sendTiming(pkt); } - // // For DMA and CPU requests, translate them to ruby requests before // sending them to our assigned ruby port. - // RubyRequestType type = RubyRequestType_NULL; - // // If valid, copy the pc to the ruby request - // Addr pc = 0; if (pkt->req->hasPC()) { pc = pkt->req->getPC(); @@ -224,47 +206,38 @@ RubyPort::M5Port::recvTiming(PacketPtr pkt) if (pkt->req->isInstFetch()) { type = RubyRequestType_IFETCH; } else { - type = RubyRequestType_LD; + type = RubyRequestType_LD; } } else if (pkt->isWrite()) { type = RubyRequestType_ST; } else if (pkt->isReadWrite()) { - // - // Fix me. This conditional will never be executed because - // isReadWrite() is just an OR of isRead() and isWrite(). - // Furthermore, just because the packet is a read/write request does - // not necessary mean it is a read-modify-write atomic operation. - // + // Fix me. This conditional will never be executed + // because isReadWrite() is just an OR of isRead() and + // isWrite(). Furthermore, just because the packet is a + // read/write request does not necessary mean it is a + // read-modify-write atomic operation. type = RubyRequestType_RMW_Write; } else { panic("Unsupported ruby packet type\n"); } } - RubyRequest ruby_request(pkt->getAddr(), - pkt->getPtr<uint8_t>(), - pkt->getSize(), - pc, - type, - RubyAccessMode_Supervisor, - pkt); + RubyRequest ruby_request(pkt->getAddr(), pkt->getPtr<uint8_t>(), + pkt->getSize(), pc, type, + RubyAccessMode_Supervisor, pkt); // Submit the ruby request RequestStatus requestStatus = ruby_port->makeRequest(ruby_request); - // // If the request successfully issued or the SC request completed because // exclusive permission was lost, then we should return true. // Otherwise, we need to delete the senderStatus we just created and return // false. - // if ((requestStatus == RequestStatus_Issued) || (requestStatus == RequestStatus_LlscFailed)) { - // // The communicate to M5 whether the SC command succeeded by seting the // packet's extra data. - // if (pkt->isLLSC() && pkt->isWrite()) { if (requestStatus == RequestStatus_LlscFailed) { DPRINTF(MemoryAccess, "SC failed and request completed\n"); @@ -276,11 +249,10 @@ RubyPort::M5Port::recvTiming(PacketPtr pkt) return true; } - DPRINTF(MemoryAccess, + DPRINTF(MemoryAccess, "Request for address #x did not issue because %s\n", - pkt->getAddr(), - RequestStatus_to_string(requestStatus)); - + pkt->getAddr(), RequestStatus_to_string(requestStatus)); + SenderState* senderState = safe_cast<SenderState*>(pkt->senderState); pkt->senderState = senderState->saved; delete senderState; @@ -290,14 +262,12 @@ RubyPort::M5Port::recvTiming(PacketPtr pkt) void RubyPort::ruby_hit_callback(PacketPtr pkt) { - // // Retrieve the request port from the sender State - // - RubyPort::SenderState *senderState = + RubyPort::SenderState *senderState = safe_cast<RubyPort::SenderState *>(pkt->senderState); M5Port *port = senderState->port; assert(port != NULL); - + // pop the sender state from the packet pkt->senderState = senderState->saved; delete senderState; @@ -308,11 +278,9 @@ RubyPort::ruby_hit_callback(PacketPtr pkt) void RubyPort::M5Port::hitCallback(PacketPtr pkt) { - bool needsResponse = pkt->needsResponse(); - DPRINTF(MemoryAccess, "Hit callback needs response %d\n", - needsResponse); + DPRINTF(MemoryAccess, "Hit callback needs response %d\n", needsResponse); ruby_port->physMemPort->sendAtomic(pkt); @@ -349,9 +317,9 @@ RubyPort::M5Port::isPhysMemAddress(Addr addr) AddrRangeList physMemAddrList; bool snoop = false; ruby_port->physMemPort->getPeerAddressRanges(physMemAddrList, snoop); - for(AddrRangeIter iter = physMemAddrList.begin(); - iter != physMemAddrList.end(); - iter++) { + for (AddrRangeIter iter = physMemAddrList.begin(); + iter != physMemAddrList.end(); + iter++) { if (addr >= iter->start && addr <= iter->end) { DPRINTF(MemoryAccess, "Request found in %#llx - %#llx range\n", iter->start, iter->end); diff --git a/src/mem/ruby/system/RubyPort.hh b/src/mem/ruby/system/RubyPort.hh index 3a862e068..4038c6007 100644 --- a/src/mem/ruby/system/RubyPort.hh +++ b/src/mem/ruby/system/RubyPort.hh @@ -1,4 +1,3 @@ - /* * Copyright (c) 2009 Advanced Micro Devices, Inc. * All rights reserved. @@ -27,18 +26,17 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef RUBYPORT_H -#define RUBYPORT_H +#ifndef __MEM_RUBY_SYSTEM_RUBYPORT_HH__ +#define __MEM_RUBY_SYSTEM_RUBYPORT_HH__ -#include "mem/ruby/libruby.hh" +#include <cassert> #include <string> -#include <assert.h> #include "mem/mem_object.hh" -#include "mem/tport.hh" #include "mem/physical.hh" #include "mem/protocol/RequestStatus.hh" - +#include "mem/ruby/libruby.hh" +#include "mem/tport.hh" #include "params/RubyPort.hh" using namespace std; @@ -46,17 +44,16 @@ using namespace std; class MessageBuffer; class AbstractController; -class RubyPort : public MemObject { -public: - +class RubyPort : public MemObject +{ + public: class M5Port : public SimpleTimingPort { - + private: RubyPort *ruby_port; public: - M5Port(const std::string &_name, - RubyPort *_port); + M5Port(const std::string &_name, RubyPort *_port); bool sendTiming(PacketPtr pkt); void hitCallback(PacketPtr pkt); @@ -72,12 +69,11 @@ public: class PioPort : public SimpleTimingPort { - + private: RubyPort *ruby_port; public: - PioPort(const std::string &_name, - RubyPort *_port); + PioPort(const std::string &_name, RubyPort *_port); bool sendTiming(PacketPtr pkt); protected: @@ -92,8 +88,7 @@ public: M5Port* port; Packet::SenderState *saved; - SenderState(M5Port* _port, - Packet::SenderState *sender_state = NULL) + SenderState(M5Port* _port, Packet::SenderState *sender_state = NULL) : port(_port), saved(sender_state) {} }; @@ -114,17 +109,17 @@ public: // void setController(AbstractController* _cntrl) { m_controller = _cntrl; } -protected: - const string m_name; - void ruby_hit_callback(PacketPtr pkt); - void hit(PacketPtr pkt); + protected: + const string m_name; + void ruby_hit_callback(PacketPtr pkt); + void hit(PacketPtr pkt); - int m_version; - AbstractController* m_controller; - MessageBuffer* m_mandatory_q_ptr; + int m_version; + AbstractController* m_controller; + MessageBuffer* m_mandatory_q_ptr; PioPort* pio_port; -private: + private: uint16_t m_port_id; uint64_t m_request_cnt; @@ -133,4 +128,4 @@ private: PhysicalMemory* physmem; }; -#endif +#endif // __MEM_RUBY_SYSTEM_RUBYPORT_HH__ diff --git a/src/mem/ruby/system/Sequencer.cc b/src/mem/ruby/system/Sequencer.cc index d6dba08f9..a473ccf44 100644 --- a/src/mem/ruby/system/Sequencer.cc +++ b/src/mem/ruby/system/Sequencer.cc @@ -1,4 +1,3 @@ - /* * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood * All rights reserved. @@ -27,22 +26,21 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include "mem/ruby/libruby.hh" -#include "mem/ruby/common/Global.hh" -#include "mem/ruby/system/Sequencer.hh" -#include "mem/ruby/system/System.hh" -#include "mem/protocol/Protocol.hh" -#include "mem/ruby/profiler/Profiler.hh" -#include "mem/ruby/system/CacheMemory.hh" +#include "cpu/rubytest/RubyTester.hh" +#include "mem/gems_common/Map.hh" #include "mem/protocol/CacheMsg.hh" -#include "mem/ruby/recorder/Tracer.hh" -#include "mem/ruby/common/SubBlock.hh" #include "mem/protocol/Protocol.hh" -#include "mem/gems_common/Map.hh" +#include "mem/protocol/Protocol.hh" #include "mem/ruby/buffers/MessageBuffer.hh" +#include "mem/ruby/common/Global.hh" +#include "mem/ruby/common/SubBlock.hh" +#include "mem/ruby/libruby.hh" +#include "mem/ruby/profiler/Profiler.hh" +#include "mem/ruby/recorder/Tracer.hh" #include "mem/ruby/slicc_interface/AbstractController.hh" -#include "cpu/rubytest/RubyTester.hh" - +#include "mem/ruby/system/CacheMemory.hh" +#include "mem/ruby/system/Sequencer.hh" +#include "mem/ruby/system/System.hh" #include "params/RubySequencer.hh" Sequencer * @@ -50,7 +48,7 @@ RubySequencerParams::create() { return new Sequencer(this); } - + Sequencer::Sequencer(const Params *p) : RubyPort(p), deadlockCheckEvent(this) { @@ -58,7 +56,7 @@ Sequencer::Sequencer(const Params *p) m_store_waiting_on_store_cycles = 0; m_load_waiting_on_store_cycles = 0; m_load_waiting_on_load_cycles = 0; - + m_outstanding_count = 0; m_max_outstanding_requests = 0; @@ -78,478 +76,524 @@ Sequencer::Sequencer(const Params *p) assert(m_dataCache_ptr != NULL); } -Sequencer::~Sequencer() { - +Sequencer::~Sequencer() +{ } -void Sequencer::wakeup() { - // Check for deadlock of any of the requests - Time current_time = g_eventQueue_ptr->getTime(); - - // Check across all outstanding requests - int total_outstanding = 0; - - Vector<Address> keys = m_readRequestTable.keys(); - for (int i=0; i<keys.size(); i++) { - 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(m_version); - WARN_EXPR(request->ruby_request.paddr); - WARN_EXPR(keys.size()); - WARN_EXPR(current_time); - WARN_EXPR(request->issue_time); - WARN_EXPR(current_time - request->issue_time); - ERROR_MSG("Aborting"); +void +Sequencer::wakeup() +{ + // Check for deadlock of any of the requests + Time current_time = g_eventQueue_ptr->getTime(); + + // Check across all outstanding requests + int total_outstanding = 0; + + Vector<Address> keys = m_readRequestTable.keys(); + for (int i = 0; i < keys.size(); i++) { + 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(m_version); + WARN_EXPR(request->ruby_request.paddr); + WARN_EXPR(keys.size()); + WARN_EXPR(current_time); + WARN_EXPR(request->issue_time); + WARN_EXPR(current_time - request->issue_time); + ERROR_MSG("Aborting"); + } } - } - - keys = m_writeRequestTable.keys(); - for (int i=0; i<keys.size(); i++) { - 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(m_version); - WARN_EXPR(current_time); - WARN_EXPR(request->issue_time); - WARN_EXPR(current_time - request->issue_time); - WARN_EXPR(keys.size()); - ERROR_MSG("Aborting"); + + keys = m_writeRequestTable.keys(); + for (int i = 0; i < keys.size(); i++) { + 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(m_version); + WARN_EXPR(current_time); + WARN_EXPR(request->issue_time); + WARN_EXPR(current_time - request->issue_time); + WARN_EXPR(keys.size()); + ERROR_MSG("Aborting"); + } } - } - total_outstanding += m_writeRequestTable.size() + m_readRequestTable.size(); - assert(m_outstanding_count == total_outstanding); + total_outstanding += m_writeRequestTable.size(); + total_outstanding += m_readRequestTable.size(); - if (m_outstanding_count > 0) { // If there are still outstanding requests, keep checking - schedule(deadlockCheckEvent, - (m_deadlock_threshold * g_eventQueue_ptr->getClock()) + curTick); - } + assert(m_outstanding_count == total_outstanding); + + if (m_outstanding_count > 0) { + // If there are still outstanding requests, keep checking + schedule(deadlockCheckEvent, + m_deadlock_threshold * g_eventQueue_ptr->getClock() + + curTick); + } } -void Sequencer::printStats(ostream & out) const { - out << "Sequencer: " << m_name << endl; - out << " store_waiting_on_load_cycles: " << m_store_waiting_on_load_cycles << endl; - out << " store_waiting_on_store_cycles: " << m_store_waiting_on_store_cycles << endl; - out << " load_waiting_on_load_cycles: " << m_load_waiting_on_load_cycles << endl; - out << " load_waiting_on_store_cycles: " << m_load_waiting_on_store_cycles << endl; +void +Sequencer::printStats(ostream & out) const +{ + out << "Sequencer: " << m_name << endl + << " store_waiting_on_load_cycles: " + << m_store_waiting_on_load_cycles << endl + << " store_waiting_on_store_cycles: " + << m_store_waiting_on_store_cycles << endl + << " load_waiting_on_load_cycles: " + << m_load_waiting_on_load_cycles << endl + << " load_waiting_on_store_cycles: " + << m_load_waiting_on_store_cycles << endl; } -void Sequencer::printProgress(ostream& out) const{ - /* - int total_demand = 0; - out << "Sequencer Stats Version " << m_version << endl; - out << "Current time = " << g_eventQueue_ptr->getTime() << endl; - out << "---------------" << endl; - out << "outstanding requests" << endl; - - Vector<Address> rkeys = m_readRequestTable.keys(); - int read_size = rkeys.size(); - out << "proc " << m_version << " Read Requests = " << read_size << endl; - // print the request table - for(int i=0; i < read_size; ++i){ - SequencerRequest * request = m_readRequestTable.lookup(rkeys[i]); - out << "\tRequest[ " << i << " ] = " << request->type << " Address " << rkeys[i] << " Posted " << request->issue_time << " PF " << PrefetchBit_No << endl; - total_demand++; - } - - Vector<Address> wkeys = m_writeRequestTable.keys(); - int write_size = wkeys.size(); - out << "proc " << m_version << " Write Requests = " << write_size << endl; - // print the request table - for(int i=0; i < write_size; ++i){ - CacheMsg & request = m_writeRequestTable.lookup(wkeys[i]); - out << "\tRequest[ " << i << " ] = " << request.getType() << " Address " << wkeys[i] << " Posted " << request.getTime() << " PF " << request.getPrefetch() << endl; - if( request.getPrefetch() == PrefetchBit_No ){ +void +Sequencer::printProgress(ostream& out) const +{ +#if 0 + int total_demand = 0; + out << "Sequencer Stats Version " << m_version << endl; + out << "Current time = " << g_eventQueue_ptr->getTime() << endl; + out << "---------------" << endl; + out << "outstanding requests" << endl; + + Vector<Address> rkeys = m_readRequestTable.keys(); + int read_size = rkeys.size(); + out << "proc " << m_version << " Read Requests = " << read_size << endl; + + // print the request table + for (int i = 0; i < read_size; ++i) { + SequencerRequest *request = m_readRequestTable.lookup(rkeys[i]); + out << "\tRequest[ " << i << " ] = " << request->type + << " Address " << rkeys[i] + << " Posted " << request->issue_time + << " PF " << PrefetchBit_No << endl; total_demand++; - } - } + } - out << endl; + Vector<Address> wkeys = m_writeRequestTable.keys(); + int write_size = wkeys.size(); + out << "proc " << m_version << " Write Requests = " << write_size << endl; + + // print the request table + for (int i = 0; i < write_size; ++i){ + CacheMsg &request = m_writeRequestTable.lookup(wkeys[i]); + out << "\tRequest[ " << i << " ] = " << request.getType() + << " Address " << wkeys[i] + << " Posted " << request.getTime() + << " PF " << request.getPrefetch() << endl; + if (request.getPrefetch() == PrefetchBit_No) { + total_demand++; + } + } - out << "Total Number Outstanding: " << m_outstanding_count << endl; - out << "Total Number Demand : " << total_demand << endl; - out << "Total Number Prefetches : " << m_outstanding_count - total_demand << endl; - out << endl; - out << endl; - */ + out << endl; + + out << "Total Number Outstanding: " << m_outstanding_count << endl + << "Total Number Demand : " << total_demand << endl + << "Total Number Prefetches : " << m_outstanding_count - total_demand + << endl << endl << endl; +#endif } -void Sequencer::printConfig(ostream& out) const { - out << "Seqeuncer config: " << m_name << endl; - out << " controller: " << m_controller->getName() << endl; - out << " version: " << m_version << endl; - out << " max_outstanding_requests: " << m_max_outstanding_requests << endl; - out << " deadlock_threshold: " << m_deadlock_threshold << endl; +void +Sequencer::printConfig(ostream& out) const +{ + out << "Seqeuncer config: " << m_name << endl + << " controller: " << m_controller->getName() << endl + << " version: " << m_version << endl + << " max_outstanding_requests: " << m_max_outstanding_requests << endl + << " deadlock_threshold: " << m_deadlock_threshold << endl; } // Insert the request on the correct request table. Return true if // the entry was already present. -bool Sequencer::insertRequest(SequencerRequest* request) { - int total_outstanding = m_writeRequestTable.size() + m_readRequestTable.size(); - - assert(m_outstanding_count == total_outstanding); - - // See if we should schedule a deadlock check - if (deadlockCheckEvent.scheduled() == false) { - schedule(deadlockCheckEvent, m_deadlock_threshold + curTick); - } - - Address line_addr(request->ruby_request.paddr); - line_addr.makeLineAddress(); - if ((request->ruby_request.type == RubyRequestType_ST) || - (request->ruby_request.type == RubyRequestType_RMW_Read) || - (request->ruby_request.type == RubyRequestType_RMW_Write) || - (request->ruby_request.type == RubyRequestType_Locked_Read) || - (request->ruby_request.type == RubyRequestType_Locked_Write)) { - if (m_writeRequestTable.exist(line_addr)) { - m_writeRequestTable.lookup(line_addr) = request; - // return true; - assert(0); // drh5: isn't this an error? do you lose the initial request? +bool +Sequencer::insertRequest(SequencerRequest* request) +{ + int total_outstanding = + m_writeRequestTable.size() + m_readRequestTable.size(); + + assert(m_outstanding_count == total_outstanding); + + // See if we should schedule a deadlock check + if (deadlockCheckEvent.scheduled() == false) { + schedule(deadlockCheckEvent, m_deadlock_threshold + curTick); } - m_writeRequestTable.allocate(line_addr); - m_writeRequestTable.lookup(line_addr) = request; - m_outstanding_count++; - } else { - if (m_readRequestTable.exist(line_addr)) { - m_readRequestTable.lookup(line_addr) = request; - // return true; - assert(0); // drh5: isn't this an error? do you lose the initial request? + + Address line_addr(request->ruby_request.paddr); + line_addr.makeLineAddress(); + if ((request->ruby_request.type == RubyRequestType_ST) || + (request->ruby_request.type == RubyRequestType_RMW_Read) || + (request->ruby_request.type == RubyRequestType_RMW_Write) || + (request->ruby_request.type == RubyRequestType_Locked_Read) || + (request->ruby_request.type == RubyRequestType_Locked_Write)) { + if (m_writeRequestTable.exist(line_addr)) { + m_writeRequestTable.lookup(line_addr) = request; + // return true; + + // drh5: isn't this an error? do you lose the initial request? + assert(0); + } + m_writeRequestTable.allocate(line_addr); + m_writeRequestTable.lookup(line_addr) = request; + m_outstanding_count++; + } else { + if (m_readRequestTable.exist(line_addr)) { + m_readRequestTable.lookup(line_addr) = request; + // return true; + + // drh5: isn't this an error? do you lose the initial request? + assert(0); + } + m_readRequestTable.allocate(line_addr); + m_readRequestTable.lookup(line_addr) = request; + m_outstanding_count++; } - m_readRequestTable.allocate(line_addr); - m_readRequestTable.lookup(line_addr) = request; - m_outstanding_count++; - } - g_system_ptr->getProfiler()->sequencerRequests(m_outstanding_count); + g_system_ptr->getProfiler()->sequencerRequests(m_outstanding_count); - total_outstanding = m_writeRequestTable.size() + m_readRequestTable.size(); - assert(m_outstanding_count == total_outstanding); + total_outstanding = m_writeRequestTable.size() + m_readRequestTable.size(); + assert(m_outstanding_count == total_outstanding); - return false; + return false; } -void Sequencer::removeRequest(SequencerRequest* srequest) { - - assert(m_outstanding_count == m_writeRequestTable.size() + m_readRequestTable.size()); - - const RubyRequest & ruby_request = srequest->ruby_request; - Address line_addr(ruby_request.paddr); - line_addr.makeLineAddress(); - if ((ruby_request.type == RubyRequestType_ST) || - (ruby_request.type == RubyRequestType_RMW_Read) || - (ruby_request.type == RubyRequestType_RMW_Write) || - (ruby_request.type == RubyRequestType_Locked_Read) || - (ruby_request.type == RubyRequestType_Locked_Write)) { - m_writeRequestTable.deallocate(line_addr); - } else { - m_readRequestTable.deallocate(line_addr); - } - m_outstanding_count--; - - assert(m_outstanding_count == m_writeRequestTable.size() + m_readRequestTable.size()); -} +void +Sequencer::removeRequest(SequencerRequest* srequest) +{ + assert(m_outstanding_count == + m_writeRequestTable.size() + m_readRequestTable.size()); + + const RubyRequest & ruby_request = srequest->ruby_request; + Address line_addr(ruby_request.paddr); + line_addr.makeLineAddress(); + if ((ruby_request.type == RubyRequestType_ST) || + (ruby_request.type == RubyRequestType_RMW_Read) || + (ruby_request.type == RubyRequestType_RMW_Write) || + (ruby_request.type == RubyRequestType_Locked_Read) || + (ruby_request.type == RubyRequestType_Locked_Write)) { + m_writeRequestTable.deallocate(line_addr); + } else { + m_readRequestTable.deallocate(line_addr); + } + m_outstanding_count--; -void Sequencer::writeCallback(const Address& address, DataBlock& data) { + assert(m_outstanding_count == m_writeRequestTable.size() + m_readRequestTable.size()); +} - assert(address == line_address(address)); - assert(m_writeRequestTable.exist(line_address(address))); +void +Sequencer::writeCallback(const Address& address, DataBlock& data) +{ + assert(address == line_address(address)); + assert(m_writeRequestTable.exist(line_address(address))); - SequencerRequest* request = m_writeRequestTable.lookup(address); + SequencerRequest* request = m_writeRequestTable.lookup(address); - removeRequest(request); + removeRequest(request); - assert((request->ruby_request.type == RubyRequestType_ST) || - (request->ruby_request.type == RubyRequestType_RMW_Read) || - (request->ruby_request.type == RubyRequestType_RMW_Write) || - (request->ruby_request.type == RubyRequestType_Locked_Read) || - (request->ruby_request.type == RubyRequestType_Locked_Write)); + assert((request->ruby_request.type == RubyRequestType_ST) || + (request->ruby_request.type == RubyRequestType_RMW_Read) || + (request->ruby_request.type == RubyRequestType_RMW_Write) || + (request->ruby_request.type == RubyRequestType_Locked_Read) || + (request->ruby_request.type == RubyRequestType_Locked_Write)); - if (request->ruby_request.type == RubyRequestType_Locked_Read) { - m_dataCache_ptr->setLocked(address, m_version); - } - else if (request->ruby_request.type == RubyRequestType_RMW_Read) { - m_controller->blockOnQueue(address, m_mandatory_q_ptr); - } - else if (request->ruby_request.type == RubyRequestType_RMW_Write) { - m_controller->unblock(address); - } + if (request->ruby_request.type == RubyRequestType_Locked_Read) { + m_dataCache_ptr->setLocked(address, m_version); + } else if (request->ruby_request.type == RubyRequestType_RMW_Read) { + m_controller->blockOnQueue(address, m_mandatory_q_ptr); + } else if (request->ruby_request.type == RubyRequestType_RMW_Write) { + m_controller->unblock(address); + } - hitCallback(request, data); + hitCallback(request, data); } -void Sequencer::readCallback(const Address& address, DataBlock& data) { - - assert(address == line_address(address)); - assert(m_readRequestTable.exist(line_address(address))); +void +Sequencer::readCallback(const Address& address, DataBlock& data) +{ + assert(address == line_address(address)); + assert(m_readRequestTable.exist(line_address(address))); - SequencerRequest* request = m_readRequestTable.lookup(address); - removeRequest(request); + SequencerRequest* request = m_readRequestTable.lookup(address); + removeRequest(request); - assert((request->ruby_request.type == RubyRequestType_LD) || - (request->ruby_request.type == RubyRequestType_RMW_Read) || - (request->ruby_request.type == RubyRequestType_IFETCH)); + assert((request->ruby_request.type == RubyRequestType_LD) || + (request->ruby_request.type == RubyRequestType_RMW_Read) || + (request->ruby_request.type == RubyRequestType_IFETCH)); - hitCallback(request, data); + hitCallback(request, data); } -void Sequencer::hitCallback(SequencerRequest* srequest, DataBlock& data) { - const RubyRequest & ruby_request = srequest->ruby_request; - Address request_address(ruby_request.paddr); - Address request_line_address(ruby_request.paddr); - request_line_address.makeLineAddress(); - RubyRequestType type = ruby_request.type; - Time issued_time = srequest->issue_time; - - // Set this cache entry to the most recently used - if (type == RubyRequestType_IFETCH) { - if (m_instCache_ptr->isTagPresent(request_line_address) ) - m_instCache_ptr->setMRU(request_line_address); - } else { - if (m_dataCache_ptr->isTagPresent(request_line_address) ) - m_dataCache_ptr->setMRU(request_line_address); - } - - assert(g_eventQueue_ptr->getTime() >= issued_time); - Time miss_latency = g_eventQueue_ptr->getTime() - issued_time; - - // Profile the miss latency for all non-zero demand misses - if (miss_latency != 0) { - g_system_ptr->getProfiler()->missLatency(miss_latency, type); +void +Sequencer::hitCallback(SequencerRequest* srequest, DataBlock& data) +{ + const RubyRequest & ruby_request = srequest->ruby_request; + Address request_address(ruby_request.paddr); + Address request_line_address(ruby_request.paddr); + request_line_address.makeLineAddress(); + RubyRequestType type = ruby_request.type; + Time issued_time = srequest->issue_time; + + // Set this cache entry to the most recently used + if (type == RubyRequestType_IFETCH) { + if (m_instCache_ptr->isTagPresent(request_line_address)) + m_instCache_ptr->setMRU(request_line_address); + } else { + if (m_dataCache_ptr->isTagPresent(request_line_address)) + m_dataCache_ptr->setMRU(request_line_address); + } + + assert(g_eventQueue_ptr->getTime() >= issued_time); + Time miss_latency = g_eventQueue_ptr->getTime() - issued_time; - if (Debug::getProtocolTrace()) { - g_system_ptr->getProfiler()->profileTransition("Seq", m_version, Address(ruby_request.paddr), - "", "Done", "", int_to_string(miss_latency)+" cycles"); + // Profile the miss latency for all non-zero demand misses + if (miss_latency != 0) { + g_system_ptr->getProfiler()->missLatency(miss_latency, type); + + if (Debug::getProtocolTrace()) { + g_system_ptr->getProfiler()-> + profileTransition("Seq", m_version, + Address(ruby_request.paddr), "", "Done", "", + csprintf("%d cycles", miss_latency)); + } } - } - /* - if (request.getPrefetch() == PrefetchBit_Yes) { - return; // Ignore the prefetch - } - */ - - // update the data - if (ruby_request.data != NULL) { - if ((type == RubyRequestType_LD) || - (type == RubyRequestType_IFETCH) || - (type == RubyRequestType_RMW_Read) || - (type == RubyRequestType_Locked_Read)) { - - memcpy(ruby_request.data, - data.getData(request_address.getOffset(), ruby_request.len), - ruby_request.len); - - } else { +#if 0 + if (request.getPrefetch() == PrefetchBit_Yes) { + return; // Ignore the prefetch + } +#endif - data.setData(ruby_request.data, - request_address.getOffset(), - ruby_request.len); + // update the data + if (ruby_request.data != NULL) { + if ((type == RubyRequestType_LD) || + (type == RubyRequestType_IFETCH) || + (type == RubyRequestType_RMW_Read) || + (type == RubyRequestType_Locked_Read)) { + + memcpy(ruby_request.data, + data.getData(request_address.getOffset(), ruby_request.len), + ruby_request.len); + } else { + data.setData(ruby_request.data, request_address.getOffset(), + ruby_request.len); + } + } else { + DPRINTF(MemoryAccess, + "WARNING. Data not transfered from Ruby to M5 for type %s\n", + RubyRequestType_to_string(type)); + } + // If using the RubyTester, update the RubyTester sender state's + // subBlock with the recieved data. The tester will later access + // this state. + // Note: RubyPort will access it's sender state before the + // RubyTester. + if (m_usingRubyTester) { + RubyPort::SenderState *requestSenderState = + safe_cast<RubyPort::SenderState*>(ruby_request.pkt->senderState); + RubyTester::SenderState* testerSenderState = + safe_cast<RubyTester::SenderState*>(requestSenderState->saved); + testerSenderState->subBlock->mergeFrom(data); } - } else { - DPRINTF(MemoryAccess, - "WARNING. Data not transfered from Ruby to M5 for type %s\n", - RubyRequestType_to_string(type)); - } - - // - // If using the RubyTester, update the RubyTester sender state's subBlock - // with the recieved data. The tester will later access this state. - // Note: RubyPort will access it's sender state before the RubyTester. - // - if (m_usingRubyTester) { - RubyTester::SenderState* testerSenderState; - testerSenderState = safe_cast<RubyTester::SenderState*>( \ - safe_cast<RubyPort::SenderState*>(ruby_request.pkt->senderState)->saved); - testerSenderState->subBlock->mergeFrom(data); - } - - ruby_hit_callback(ruby_request.pkt); - delete srequest; + + ruby_hit_callback(ruby_request.pkt); + delete srequest; } // Returns true if the sequencer already has a load or store outstanding -RequestStatus Sequencer::getRequestStatus(const RubyRequest& request) { - bool is_outstanding_store = m_writeRequestTable.exist(line_address(Address(request.paddr))); - bool is_outstanding_load = m_readRequestTable.exist(line_address(Address(request.paddr))); - if ( is_outstanding_store ) { - if ((request.type == RubyRequestType_LD) || - (request.type == RubyRequestType_IFETCH) || - (request.type == RubyRequestType_RMW_Read)) { - m_store_waiting_on_load_cycles++; - } else { - m_store_waiting_on_store_cycles++; +RequestStatus +Sequencer::getRequestStatus(const RubyRequest& request) +{ + bool is_outstanding_store = + m_writeRequestTable.exist(line_address(Address(request.paddr))); + bool is_outstanding_load = + m_readRequestTable.exist(line_address(Address(request.paddr))); + if (is_outstanding_store) { + if ((request.type == RubyRequestType_LD) || + (request.type == RubyRequestType_IFETCH) || + (request.type == RubyRequestType_RMW_Read)) { + m_store_waiting_on_load_cycles++; + } else { + m_store_waiting_on_store_cycles++; + } + return RequestStatus_Aliased; + } else if (is_outstanding_load) { + if ((request.type == RubyRequestType_ST) || + (request.type == RubyRequestType_RMW_Write)) { + m_load_waiting_on_store_cycles++; + } else { + m_load_waiting_on_load_cycles++; + } + return RequestStatus_Aliased; } - return RequestStatus_Aliased; - } else if ( is_outstanding_load ) { - if ((request.type == RubyRequestType_ST) || - (request.type == RubyRequestType_RMW_Write) ) { - m_load_waiting_on_store_cycles++; - } else { - m_load_waiting_on_load_cycles++; + + if (m_outstanding_count >= m_max_outstanding_requests) { + return RequestStatus_BufferFull; } - return RequestStatus_Aliased; - } - - if (m_outstanding_count >= m_max_outstanding_requests) { - return RequestStatus_BufferFull; - } - - return RequestStatus_Ready; -} -bool Sequencer::empty() const { - return (m_writeRequestTable.size() == 0) && (m_readRequestTable.size() == 0); + return RequestStatus_Ready; } +bool +Sequencer::empty() const +{ + return m_writeRequestTable.size() == 0 && m_readRequestTable.size() == 0; +} -RequestStatus Sequencer::makeRequest(const RubyRequest & request) +RequestStatus +Sequencer::makeRequest(const RubyRequest &request) { - assert(Address(request.paddr).getOffset() + request.len <= - RubySystem::getBlockSizeBytes()); - RequestStatus status = getRequestStatus(request); - if (status == RequestStatus_Ready) { - SequencerRequest *srequest = new SequencerRequest(request, - g_eventQueue_ptr->getTime()); + assert(Address(request.paddr).getOffset() + request.len <= + RubySystem::getBlockSizeBytes()); + RequestStatus status = getRequestStatus(request); + if (status != RequestStatus_Ready) + return status; + + SequencerRequest *srequest = + new SequencerRequest(request, g_eventQueue_ptr->getTime()); bool found = insertRequest(srequest); - if (!found) { - if (request.type == RubyRequestType_Locked_Write) { - // - // NOTE: it is OK to check the locked flag here as the mandatory queue - // will be checked first ensuring that nothing comes between checking - // the flag and servicing the store. - // - if (!m_dataCache_ptr->isLocked(line_address(Address(request.paddr)), - m_version)) { - removeRequest(srequest); - if (Debug::getProtocolTrace()) { - - g_system_ptr->getProfiler()->profileTransition("Seq", - m_version, - Address(request.paddr), - "", - "SC Fail", - "", - RubyRequestType_to_string(request.type)); + if (found) { + panic("Sequencer::makeRequest should never be called if the " + "request is already outstanding\n"); + return RequestStatus_NULL; + } + if (request.type == RubyRequestType_Locked_Write) { + // NOTE: it is OK to check the locked flag here as the + // mandatory queue will be checked first ensuring that nothing + // comes between checking the flag and servicing the store. + + Address line_addr = line_address(Address(request.paddr)); + if (!m_dataCache_ptr->isLocked(line_addr, m_version)) { + removeRequest(srequest); + if (Debug::getProtocolTrace()) { + g_system_ptr->getProfiler()-> + profileTransition("Seq", m_version, + Address(request.paddr), + "", "SC Fail", "", + RubyRequestType_to_string(request.type)); } return RequestStatus_LlscFailed; - } - else { - m_dataCache_ptr->clearLocked(line_address(Address(request.paddr))); + } else { + m_dataCache_ptr->clearLocked(line_addr); } - } - issueRequest(request); + } + issueRequest(request); - // TODO: issue hardware prefetches here - return RequestStatus_Issued; + // TODO: issue hardware prefetches here + return RequestStatus_Issued; +} + +void +Sequencer::issueRequest(const RubyRequest& request) +{ + // TODO: get rid of CacheMsg, CacheRequestType, and + // AccessModeTYpe, & have SLICC use RubyRequest and subtypes + // natively + CacheRequestType ctype; + switch(request.type) { + case RubyRequestType_IFETCH: + ctype = CacheRequestType_IFETCH; + break; + case RubyRequestType_LD: + ctype = CacheRequestType_LD; + break; + case RubyRequestType_ST: + ctype = CacheRequestType_ST; + break; + case RubyRequestType_Locked_Read: + case RubyRequestType_Locked_Write: + ctype = CacheRequestType_ATOMIC; + break; + case RubyRequestType_RMW_Read: + ctype = CacheRequestType_ATOMIC; + break; + case RubyRequestType_RMW_Write: + ctype = CacheRequestType_ATOMIC; + break; + default: + assert(0); } - else { - panic("Sequencer::makeRequest should never be called if the request"\ - "is already outstanding\n"); - return RequestStatus_NULL; + + AccessModeType amtype; + switch(request.access_mode){ + case RubyAccessMode_User: + amtype = AccessModeType_UserMode; + break; + case RubyAccessMode_Supervisor: + amtype = AccessModeType_SupervisorMode; + break; + case RubyAccessMode_Device: + amtype = AccessModeType_UserMode; + break; + default: + assert(0); } - } else { - return status; - } -} -void Sequencer::issueRequest(const RubyRequest& request) { - - // TODO: get rid of CacheMsg, CacheRequestType, and AccessModeTYpe, & have SLICC use RubyRequest and subtypes natively - CacheRequestType ctype; - switch(request.type) { - case RubyRequestType_IFETCH: - ctype = CacheRequestType_IFETCH; - break; - case RubyRequestType_LD: - ctype = CacheRequestType_LD; - break; - case RubyRequestType_ST: - ctype = CacheRequestType_ST; - break; - case RubyRequestType_Locked_Read: - case RubyRequestType_Locked_Write: - ctype = CacheRequestType_ATOMIC; - break; - case RubyRequestType_RMW_Read: - ctype = CacheRequestType_ATOMIC; - break; - case RubyRequestType_RMW_Write: - ctype = CacheRequestType_ATOMIC; - break; - default: - assert(0); - } - AccessModeType amtype; - switch(request.access_mode){ - case RubyAccessMode_User: - amtype = AccessModeType_UserMode; - break; - case RubyAccessMode_Supervisor: - amtype = AccessModeType_SupervisorMode; - break; - case RubyAccessMode_Device: - amtype = AccessModeType_UserMode; - break; - default: - assert(0); - } - Address line_addr(request.paddr); - line_addr.makeLineAddress(); - CacheMsg msg(line_addr, Address(request.paddr), ctype, Address(request.pc), amtype, request.len, PrefetchBit_No, request.proc_id); - - if (Debug::getProtocolTrace()) { - g_system_ptr->getProfiler()->profileTransition("Seq", m_version, Address(request.paddr), - "", "Begin", "", RubyRequestType_to_string(request.type)); - } - - if (g_system_ptr->getTracer()->traceEnabled()) { - g_system_ptr->getTracer()->traceRequest(this, line_addr, Address(request.pc), - request.type, g_eventQueue_ptr->getTime()); - } - - Time latency = 0; // initialzed to an null value - - if (request.type == RubyRequestType_IFETCH) - latency = m_instCache_ptr->getLatency(); - else - latency = m_dataCache_ptr->getLatency(); - - // Send the message to the cache controller - assert(latency > 0); - - assert(m_mandatory_q_ptr != NULL); - m_mandatory_q_ptr->enqueue(msg, latency); -} -/* -bool Sequencer::tryCacheAccess(const Address& addr, CacheRequestType type, - AccessModeType access_mode, - int size, DataBlock*& data_ptr) { - if (type == CacheRequestType_IFETCH) { - return m_instCache_ptr->tryCacheAccess(line_address(addr), type, data_ptr); - } else { - return m_dataCache_ptr->tryCacheAccess(line_address(addr), type, data_ptr); - } + Address line_addr(request.paddr); + line_addr.makeLineAddress(); + CacheMsg msg(line_addr, Address(request.paddr), ctype, + Address(request.pc), amtype, request.len, PrefetchBit_No, + request.proc_id); + + if (Debug::getProtocolTrace()) { + g_system_ptr->getProfiler()-> + profileTransition("Seq", m_version, Address(request.paddr), + "", "Begin", "", + RubyRequestType_to_string(request.type)); + } + + if (g_system_ptr->getTracer()->traceEnabled()) { + g_system_ptr->getTracer()-> + traceRequest(this, line_addr, Address(request.pc), + request.type, g_eventQueue_ptr->getTime()); + } + + Time latency = 0; // initialzed to an null value + + if (request.type == RubyRequestType_IFETCH) + latency = m_instCache_ptr->getLatency(); + else + latency = m_dataCache_ptr->getLatency(); + + // Send the message to the cache controller + assert(latency > 0); + + assert(m_mandatory_q_ptr != NULL); + m_mandatory_q_ptr->enqueue(msg, latency); } -*/ -void Sequencer::print(ostream& out) const { - out << "[Sequencer: " << m_version - << ", outstanding requests: " << m_outstanding_count; +#if 0 +bool +Sequencer::tryCacheAccess(const Address& addr, CacheRequestType type, + AccessModeType access_mode, + int size, DataBlock*& data_ptr) +{ + CacheMemory *cache = + (type == CacheRequestType_IFETCH) ? m_instCache_ptr : m_dataCache_ptr; - out << ", read request table: " << m_readRequestTable - << ", write request table: " << m_writeRequestTable; - out << "]"; + return cache->tryCacheAccess(line_address(addr), type, data_ptr); +} +#endif + +void +Sequencer::print(ostream& out) const +{ + out << "[Sequencer: " << m_version + << ", outstanding requests: " << m_outstanding_count + << ", read request table: " << m_readRequestTable + << ", write request table: " << m_writeRequestTable + << "]"; } -// this can be called from setState whenever coherence permissions are upgraded -// when invoked, coherence violations will be checked for the given block -void Sequencer::checkCoherence(const Address& addr) { +// this can be called from setState whenever coherence permissions are +// upgraded when invoked, coherence violations will be checked for the +// given block +void +Sequencer::checkCoherence(const Address& addr) +{ #ifdef CHECK_COHERENCE - g_system_ptr->checkGlobalCoherenceInvariant(addr); + g_system_ptr->checkGlobalCoherenceInvariant(addr); #endif } - diff --git a/src/mem/ruby/system/Sequencer.hh b/src/mem/ruby/system/Sequencer.hh index 333ca5f24..69fd3b771 100644 --- a/src/mem/ruby/system/Sequencer.hh +++ b/src/mem/ruby/system/Sequencer.hh @@ -1,4 +1,3 @@ - /* * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood * All rights reserved. @@ -27,25 +26,18 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -/* - * $Id: Sequencer.hh 1.70 2006/09/27 14:56:41-05:00 bobba@s1-01.cs.wisc.edu $ - * - * Description: - * - */ - -#ifndef SEQUENCER_H -#define SEQUENCER_H +#ifndef __MEM_RUBY_SYSTEM_SEQUENCER_HH__ +#define __MEM_RUBY_SYSTEM_SEQUENCER_HH__ -#include "mem/ruby/common/Global.hh" -#include "mem/ruby/common/Consumer.hh" -#include "mem/protocol/CacheRequestType.hh" +#include "mem/gems_common/Map.hh" #include "mem/protocol/AccessModeType.hh" +#include "mem/protocol/CacheRequestType.hh" #include "mem/protocol/GenericMachineType.hh" #include "mem/protocol/PrefetchBit.hh" -#include "mem/ruby/system/RubyPort.hh" -#include "mem/gems_common/Map.hh" #include "mem/ruby/common/Address.hh" +#include "mem/ruby/common/Consumer.hh" +#include "mem/ruby/common/Global.hh" +#include "mem/ruby/system/RubyPort.hh" class DataBlock; class CacheMsg; @@ -54,109 +46,100 @@ class CacheMemory; class RubySequencerParams; -struct SequencerRequest { - RubyRequest ruby_request; - Time issue_time; +struct SequencerRequest +{ + RubyRequest ruby_request; + Time issue_time; - SequencerRequest(const RubyRequest & _ruby_request, - Time _issue_time) - : ruby_request(_ruby_request), - issue_time(_issue_time) - {} + SequencerRequest(const RubyRequest & _ruby_request, Time _issue_time) + : ruby_request(_ruby_request), issue_time(_issue_time) + {} }; std::ostream& operator<<(std::ostream& out, const SequencerRequest& obj); -class Sequencer : public RubyPort, public Consumer { -public: +class Sequencer : public RubyPort, public Consumer +{ + public: typedef RubySequencerParams Params; - // Constructors - Sequencer(const Params *); - - // Destructor - ~Sequencer(); + Sequencer(const Params *); + ~Sequencer(); - // Public Methods - void wakeup(); // Used only for deadlock detection + // Public Methods + void wakeup(); // Used only for deadlock detection - void printConfig(ostream& out) const; + void printConfig(ostream& out) const; - void printProgress(ostream& out) const; + void printProgress(ostream& out) const; - void writeCallback(const Address& address, DataBlock& data); - void readCallback(const Address& address, DataBlock& data); + void writeCallback(const Address& address, DataBlock& data); + void readCallback(const Address& address, DataBlock& data); - RequestStatus makeRequest(const RubyRequest & request); - RequestStatus getRequestStatus(const RubyRequest& request); - bool empty() const; + RequestStatus makeRequest(const RubyRequest & request); + RequestStatus getRequestStatus(const RubyRequest& request); + bool empty() const; - void print(ostream& out) const; - void printStats(ostream & out) const; - void checkCoherence(const Address& address); + void print(ostream& out) const; + void printStats(ostream & out) const; + void checkCoherence(const Address& address); - // bool getRubyMemoryValue(const Address& addr, char* value, unsigned int size_in_bytes); - // bool setRubyMemoryValue(const Address& addr, char *value, unsigned int size_in_bytes); + void removeRequest(SequencerRequest* request); - void removeRequest(SequencerRequest* request); -private: - // Private Methods - bool tryCacheAccess(const Address& addr, CacheRequestType type, const Address& pc, AccessModeType access_mode, int size, DataBlock*& data_ptr); - void issueRequest(const RubyRequest& request); + private: + bool tryCacheAccess(const Address& addr, CacheRequestType type, + const Address& pc, AccessModeType access_mode, + int size, DataBlock*& data_ptr); + void issueRequest(const RubyRequest& request); - void hitCallback(SequencerRequest* request, DataBlock& data); - bool insertRequest(SequencerRequest* request); + void hitCallback(SequencerRequest* request, DataBlock& data); + bool insertRequest(SequencerRequest* request); - // Private copy constructor and assignment operator - Sequencer(const Sequencer& obj); - Sequencer& operator=(const Sequencer& obj); + // Private copy constructor and assignment operator + Sequencer(const Sequencer& obj); + Sequencer& operator=(const Sequencer& obj); -private: - int m_max_outstanding_requests; - int m_deadlock_threshold; + private: + int m_max_outstanding_requests; + int m_deadlock_threshold; - CacheMemory* m_dataCache_ptr; - CacheMemory* m_instCache_ptr; + CacheMemory* m_dataCache_ptr; + CacheMemory* m_instCache_ptr; - Map<Address, SequencerRequest*> m_writeRequestTable; - Map<Address, SequencerRequest*> m_readRequestTable; - // Global outstanding request count, across all request tables - int m_outstanding_count; - bool m_deadlock_check_scheduled; + Map<Address, SequencerRequest*> m_writeRequestTable; + Map<Address, SequencerRequest*> m_readRequestTable; + // Global outstanding request count, across all request tables + int m_outstanding_count; + bool m_deadlock_check_scheduled; - int m_store_waiting_on_load_cycles; - int m_store_waiting_on_store_cycles; - int m_load_waiting_on_store_cycles; - int m_load_waiting_on_load_cycles; + int m_store_waiting_on_load_cycles; + int m_store_waiting_on_store_cycles; + int m_load_waiting_on_store_cycles; + int m_load_waiting_on_load_cycles; - bool m_usingRubyTester; + bool m_usingRubyTester; - class SequencerWakeupEvent : public Event - { - Sequencer *m_sequencer_ptr; + class SequencerWakeupEvent : public Event + { + private: + Sequencer *m_sequencer_ptr; - public: - SequencerWakeupEvent(Sequencer *_seq) : m_sequencer_ptr(_seq) {} - void process() { m_sequencer_ptr->wakeup(); } - const char *description() const { return "Sequencer deadlock check"; } - }; + public: + SequencerWakeupEvent(Sequencer *_seq) : m_sequencer_ptr(_seq) {} + void process() { m_sequencer_ptr->wakeup(); } + const char *description() const { return "Sequencer deadlock check"; } + }; - SequencerWakeupEvent deadlockCheckEvent; + SequencerWakeupEvent deadlockCheckEvent; }; -// Output operator declaration -ostream& operator<<(ostream& out, const Sequencer& obj); - -// ******************* Definitions ******************* - -// Output operator definition -extern inline -ostream& operator<<(ostream& out, const Sequencer& obj) +inline ostream& +operator<<(ostream& out, const Sequencer& obj) { - obj.print(out); - out << flush; - return out; + obj.print(out); + out << flush; + return out; } -#endif //SEQUENCER_H +#endif // __MEM_RUBY_SYSTEM_SEQUENCER_HH__ diff --git a/src/mem/ruby/system/SparseMemory.cc b/src/mem/ruby/system/SparseMemory.cc index c351f9e60..6271d24c3 100644 --- a/src/mem/ruby/system/SparseMemory.cc +++ b/src/mem/ruby/system/SparseMemory.cc @@ -1,4 +1,3 @@ - /* * Copyright (c) 2009 Advanced Micro Devices, Inc. * All rights reserved. @@ -29,10 +28,6 @@ #include "mem/ruby/system/SparseMemory.hh" - -// **************************************************************** - - SparseMemory::SparseMemory(int number_of_bits, int number_of_levels) { int even_level_bits; @@ -81,22 +76,16 @@ SparseMemory::recursivelyRemoveTables(SparseMapType* curTable, int curLevel) SparseMapType::iterator iter; for (iter = curTable->begin(); iter != curTable->end(); iter++) { - SparseMemEntry_t* entryStruct = &((*iter).second); + SparseMemEntry* entryStruct = &((*iter).second); if (curLevel != (m_number_of_levels - 1)) { - // - // If the not at the last level, analyze those lower level tables first, - // then delete those next tables - // - SparseMapType* nextTable; - nextTable = (SparseMapType*)(entryStruct->entry); + // If the not at the last level, analyze those lower level + // tables first, then delete those next tables + SparseMapType* nextTable = (SparseMapType*)(entryStruct->entry); recursivelyRemoveTables(nextTable, (curLevel + 1)); delete nextTable; - } else { - // // If at the last level, delete the directory entry - // Directory_Entry* dirEntry; dirEntry = (Directory_Entry*)(entryStruct->entry); delete dirEntry; @@ -104,15 +93,10 @@ SparseMemory::recursivelyRemoveTables(SparseMapType* curTable, int curLevel) entryStruct->entry = NULL; } - // // Once all entries have been deleted, erase the entries - // curTable->erase(curTable->begin(), curTable->end()); } - -// PUBLIC METHODS - // tests to see if an address is present in the memory bool SparseMemory::exist(const Address& address) const @@ -120,22 +104,19 @@ SparseMemory::exist(const Address& address) const SparseMapType* curTable = m_map_head; 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. - // + // 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; assert(address == line_address(address)); DEBUG_EXPR(CACHE_COMP, HighPrio, address); for (int level = 0; level < m_number_of_levels; level++) { - // // Create the appropriate sub 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. - // + // 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[level]; curAddress.setAddress(address.bitSelect(lowBit, highBit - 1)); @@ -144,15 +125,11 @@ SparseMemory::exist(const Address& address) const DEBUG_EXPR(CACHE_COMP, HighPrio, highBit - 1); DEBUG_EXPR(CACHE_COMP, HighPrio, curAddress); - // // Adjust the highBit value for the next level - // highBit -= m_number_of_bits_per_level[level]; - // - // If the address is found, move on to the next level. Otherwise, - // return not found - // + // If the address is found, move on to the next level. + // Otherwise, return not found if (curTable->count(curAddress) != 0) { curTable = (SparseMapType*)(((*curTable)[curAddress]).entry); } else { @@ -176,43 +153,34 @@ SparseMemory::add(const Address& address) Address curAddress; SparseMapType* curTable = m_map_head; - SparseMemEntry_t* entryStruct = NULL; + SparseMemEntry* entryStruct = NULL; - // - // 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. - // + // 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; void* newEntry = NULL; for (int level = 0; level < m_number_of_levels; 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. - // + // 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[level]; curAddress.setAddress(address.bitSelect(lowBit, highBit - 1)); - // // Adjust the highBit value for the next level - // highBit -= m_number_of_bits_per_level[level]; - // // if the address exists in the cur table, move on. Otherwise // create a new table. - // if (curTable->count(curAddress) != 0) { curTable = (SparseMapType*)(((*curTable)[curAddress]).entry); - } else { - + } else { m_adds_per_level[level]++; - // + // if the last level, add a directory entry. Otherwise add a map. - // if (level == (m_number_of_levels - 1)) { Directory_Entry* tempDirEntry = new Directory_Entry(); tempDirEntry->getDataBlk().clear(); @@ -222,17 +190,13 @@ SparseMemory::add(const Address& address) newEntry = (void*)(tempMap); } - // - // Create the pointer container SparseMemEntry_t and add it to the - // table. - // - entryStruct = new SparseMemEntry_t; + // Create the pointer container SparseMemEntry and add it + // to the table. + entryStruct = new SparseMemEntry; entryStruct->entry = newEntry; (*curTable)[curAddress] = *entryStruct; - // // Move to the next level of the heirarchy - // curTable = (SparseMapType*)newEntry; } } @@ -244,20 +208,17 @@ SparseMemory::add(const Address& address) // recursively search table hierarchy for the lowest level table. // remove the lowest entry and any empty tables above it. int -SparseMemory::recursivelyRemoveLevels( - const Address& address, - curNextInfo& curInfo) +SparseMemory::recursivelyRemoveLevels(const Address& address, + CurNextInfo& curInfo) { Address curAddress; - curNextInfo nextInfo; - SparseMemEntry_t* entryStruct; + CurNextInfo nextInfo; + SparseMemEntry* entryStruct; - // // 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. - // + // 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. curAddress.setAddress(address.bitSelect(curInfo.lowBit, curInfo.highBit - 1)); @@ -272,9 +233,7 @@ SparseMemory::recursivelyRemoveLevels( entryStruct = &((*(curInfo.curTable))[curAddress]); if (curInfo.level < (m_number_of_levels - 1)) { - // // set up next level's info - // nextInfo.curTable = (SparseMapType*)(entryStruct->entry); nextInfo.level = curInfo.level + 1; @@ -284,15 +243,11 @@ SparseMemory::recursivelyRemoveLevels( nextInfo.lowBit = curInfo.lowBit - m_number_of_bits_per_level[curInfo.level + 1]; - // // recursively search the table hierarchy - // int tableSize = recursivelyRemoveLevels(address, nextInfo); - // - // If this table below is now empty, we must delete it and erase it from - // our table. - // + // If this table below is now empty, we must delete it and + // erase it from our table. if (tableSize == 0) { m_removes_per_level[curInfo.level]++; delete nextInfo.curTable; @@ -300,10 +255,9 @@ SparseMemory::recursivelyRemoveLevels( curInfo.curTable->erase(curAddress); } } else { - // - // if this is the last level, we have reached the Directory Entry and thus - // we should delete it including the SparseMemEntry container struct. - // + // if this is the last level, we have reached the Directory + // Entry and thus we should delete it including the + // SparseMemEntry container struct. Directory_Entry* dirEntry; dirEntry = (Directory_Entry*)(entryStruct->entry); entryStruct->entry = NULL; @@ -323,26 +277,21 @@ SparseMemory::remove(const Address& address) m_total_removes++; - curNextInfo nextInfo; + CurNextInfo nextInfo; - // // Initialize table pointer and level value - // nextInfo.curTable = m_map_head; nextInfo.level = 0; - // - // 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. - // + // 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. nextInfo.highBit = m_total_number_of_bits + RubySystem::getBlockSizeBits(); nextInfo.lowBit = nextInfo.highBit - m_number_of_bits_per_level[0];; - // - // recursively search the table hierarchy for empty tables starting from the - // level 0. Note we do not check the return value because the head table is - // never deleted; - // + // recursively search the table hierarchy for empty tables + // starting from the level 0. Note we do not check the return + // value because the head table is never deleted; recursivelyRemoveLevels(address, nextInfo); assert(!exist(address)); @@ -362,20 +311,17 @@ SparseMemory::lookup(const Address& address) SparseMapType* curTable = m_map_head; Directory_Entry* entry = NULL; - // - // 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. - // + // 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 level = 0; level < m_number_of_levels; 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. - // + // 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[level]; curAddress.setAddress(address.bitSelect(lowBit, highBit - 1)); @@ -384,21 +330,15 @@ SparseMemory::lookup(const Address& address) DEBUG_EXPR(CACHE_COMP, HighPrio, highBit - 1); DEBUG_EXPR(CACHE_COMP, HighPrio, curAddress); - // // Adjust the highBit value for the next level - // highBit -= m_number_of_bits_per_level[level]; - // // The entry should be in the table and valid - // curTable = (SparseMapType*)(((*curTable)[curAddress]).entry); assert(curTable != NULL); } - // // The last entry actually points to the Directory entry not a table - // entry = (Directory_Entry*)curTable; return entry; diff --git a/src/mem/ruby/system/SparseMemory.hh b/src/mem/ruby/system/SparseMemory.hh index 4a7ac98c2..6e3c8f926 100644 --- a/src/mem/ruby/system/SparseMemory.hh +++ b/src/mem/ruby/system/SparseMemory.hh @@ -1,4 +1,3 @@ - /* * Copyright (c) 2009 Advanced Micro Devices, Inc. * All rights reserved. @@ -27,39 +26,35 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +#ifndef __MEM_RUBY_SYSTEM_SPARSEMEMORY_HH__ +#define __MEM_RUBY_SYSTEM_SPARSEMEMORY_HH__ -#ifndef SPARSEMEMORY_H -#define SPARSEMEMORY_H - -#include "mem/ruby/common/Global.hh" #include "base/hashmap.hh" -#include "mem/ruby/common/Address.hh" #include "mem/protocol/Directory_Entry.hh" +#include "mem/ruby/common/Address.hh" +#include "mem/ruby/common/Global.hh" -typedef struct SparseMemEntry { +struct SparseMemEntry +{ void* entry; -} SparseMemEntry_t; +}; -typedef m5::hash_map<Address, SparseMemEntry_t> SparseMapType; +typedef m5::hash_map<Address, SparseMemEntry> SparseMapType; -typedef struct curNextInfo { +struct CurNextInfo +{ SparseMapType* curTable; int level; int highBit; int lowBit; }; -class SparseMemory { +class SparseMemory +{ public: - - // Constructors SparseMemory(int number_of_bits, int number_of_levels); - - // Destructor ~SparseMemory(); - // Public Methods - void printConfig(ostream& out) { } bool exist(const Address& address) const; @@ -83,7 +78,7 @@ class SparseMemory { void recursivelyRemoveTables(SparseMapType* currentTable, int level); // recursive search for address and remove associated entries - int recursivelyRemoveLevels(const Address& address, curNextInfo& curInfo); + int recursivelyRemoveLevels(const Address& address, CurNextInfo& curInfo); // Data Members (m_prefix) SparseMapType* m_map_head; @@ -98,17 +93,12 @@ class SparseMemory { uint64_t* m_removes_per_level; }; -// Output operator declaration -ostream& operator<<(ostream& out, const SparseMemEntry& obj); - -// Output operator definition -extern inline -ostream& operator<<(ostream& out, const SparseMemEntry& obj) +inline ostream& +operator<<(ostream& out, const SparseMemEntry& obj) { out << "SparseMemEntry"; out << flush; return out; } - -#endif //SPARSEMEMORY_H +#endif // __MEM_RUBY_SYSTEM_SPARSEMEMORY_HH__ diff --git a/src/mem/ruby/system/System.cc b/src/mem/ruby/system/System.cc index 69dbf69c4..ef4b66290 100644 --- a/src/mem/ruby/system/System.cc +++ b/src/mem/ruby/system/System.cc @@ -1,4 +1,3 @@ - /* * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood * All rights reserved. @@ -27,25 +26,15 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -/* - * RubySystem.cc - * - * Description: See System.hh - * - * $Id$ - * - */ - - -#include "mem/ruby/system/System.hh" +#include "base/output.hh" +#include "mem/ruby/buffers/MessageBuffer.hh" #include "mem/ruby/common/Address.hh" -#include "mem/ruby/profiler/Profiler.hh" #include "mem/ruby/network/Network.hh" +#include "mem/ruby/profiler/Profiler.hh" #include "mem/ruby/recorder/Tracer.hh" -#include "mem/ruby/buffers/MessageBuffer.hh" -#include "mem/ruby/system/MemoryVector.hh" #include "mem/ruby/slicc_interface/AbstractController.hh" -#include "base/output.hh" +#include "mem/ruby/system/MemoryVector.hh" +#include "mem/ruby/system/System.hh" int RubySystem::m_random_seed; bool RubySystem::m_randomization; @@ -103,68 +92,68 @@ RubySystem::RubySystem(const Params *p) registerExitCallback(rubyExitCB); } - -void RubySystem::init() +void +RubySystem::init() { - m_profiler_ptr->clearStats(); + m_profiler_ptr->clearStats(); } - RubySystem::~RubySystem() { - delete m_network_ptr; - delete m_profiler_ptr; - delete m_tracer_ptr; - if (m_mem_vec_ptr != NULL) { - delete m_mem_vec_ptr; - } + delete m_network_ptr; + delete m_profiler_ptr; + delete m_tracer_ptr; + if (m_mem_vec_ptr) + delete m_mem_vec_ptr; } -void RubySystem::printSystemConfig(ostream & out) +void +RubySystem::printSystemConfig(ostream & out) { - out << "RubySystem config:" << endl; - out << " random_seed: " << m_random_seed << endl; - out << " randomization: " << m_randomization << endl; - out << " cycle_period: " << m_clock << endl; - out << " block_size_bytes: " << m_block_size_bytes << endl; - out << " block_size_bits: " << m_block_size_bits << endl; - out << " memory_size_bytes: " << m_memory_size_bytes << endl; - out << " memory_size_bits: " << m_memory_size_bits << endl; - + out << "RubySystem config:" << endl + << " random_seed: " << m_random_seed << endl + << " randomization: " << m_randomization << endl + << " cycle_period: " << m_clock << endl + << " block_size_bytes: " << m_block_size_bytes << endl + << " block_size_bits: " << m_block_size_bits << endl + << " memory_size_bytes: " << m_memory_size_bytes << endl + << " memory_size_bits: " << m_memory_size_bits << endl; } -void RubySystem::printConfig(ostream& out) +void +RubySystem::printConfig(ostream& out) { - out << "\n================ Begin RubySystem Configuration Print ================\n\n"; - printSystemConfig(out); - m_network_ptr->printConfig(out); - m_profiler_ptr->printConfig(out); - out << "\n================ End RubySystem Configuration Print ================\n\n"; + out << "\n================ Begin RubySystem Configuration Print ================\n\n"; + printSystemConfig(out); + m_network_ptr->printConfig(out); + m_profiler_ptr->printConfig(out); + out << "\n================ End RubySystem Configuration Print ================\n\n"; } -void RubySystem::printStats(ostream& out) +void +RubySystem::printStats(ostream& out) { + const time_t T = time(NULL); + tm *localTime = localtime(&T); + char buf[100]; + strftime(buf, 100, "%b/%d/%Y %H:%M:%S", localTime); - const time_t T = time(NULL); - tm *localTime = localtime(&T); - char buf[100]; - strftime(buf, 100, "%b/%d/%Y %H:%M:%S", localTime); - - out << "Real time: " << buf << endl; + out << "Real time: " << buf << endl; - m_profiler_ptr->printStats(out); - m_network_ptr->printStats(out); + m_profiler_ptr->printStats(out); + m_network_ptr->printStats(out); } -void RubySystem::clearStats() const +void +RubySystem::clearStats() const { - m_profiler_ptr->clearStats(); - m_network_ptr->clearStats(); + m_profiler_ptr->clearStats(); + m_network_ptr->clearStats(); } -void RubySystem::recordCacheContents(CacheRecorder& tr) const +void +RubySystem::recordCacheContents(CacheRecorder& tr) const { - } #ifdef CHECK_COHERENCE @@ -176,48 +165,46 @@ void RubySystem::recordCacheContents(CacheRecorder& tr) const // in setState. The SLICC spec must also define methods "isBlockShared" // and "isBlockExclusive" that are specific to that protocol // -void RubySystem::checkGlobalCoherenceInvariant(const Address& addr ) { - /* - NodeID exclusive = -1; - bool sharedDetected = false; - NodeID lastShared = -1; - - for (int i = 0; i < m_chip_vector.size(); i++) { - - if (m_chip_vector[i]->isBlockExclusive(addr)) { - if (exclusive != -1) { - // coherence violation - WARN_EXPR(exclusive); - WARN_EXPR(m_chip_vector[i]->getID()); - WARN_EXPR(addr); - WARN_EXPR(g_eventQueue_ptr->getTime()); - ERROR_MSG("Coherence Violation Detected -- 2 exclusive chips"); - } - else if (sharedDetected) { - WARN_EXPR(lastShared); - WARN_EXPR(m_chip_vector[i]->getID()); - WARN_EXPR(addr); - WARN_EXPR(g_eventQueue_ptr->getTime()); - ERROR_MSG("Coherence Violation Detected -- exclusive chip with >=1 shared"); - } - else { - exclusive = m_chip_vector[i]->getID(); - } - } - else if (m_chip_vector[i]->isBlockShared(addr)) { - sharedDetected = true; - lastShared = m_chip_vector[i]->getID(); - - if (exclusive != -1) { - WARN_EXPR(lastShared); - WARN_EXPR(exclusive); - WARN_EXPR(addr); - WARN_EXPR(g_eventQueue_ptr->getTime()); - ERROR_MSG("Coherence Violation Detected -- exclusive chip with >=1 shared"); - } +void +RubySystem::checkGlobalCoherenceInvariant(const Address& addr) +{ +#if 0 + NodeID exclusive = -1; + bool sharedDetected = false; + NodeID lastShared = -1; + + for (int i = 0; i < m_chip_vector.size(); i++) { + if (m_chip_vector[i]->isBlockExclusive(addr)) { + if (exclusive != -1) { + // coherence violation + WARN_EXPR(exclusive); + WARN_EXPR(m_chip_vector[i]->getID()); + WARN_EXPR(addr); + WARN_EXPR(g_eventQueue_ptr->getTime()); + ERROR_MSG("Coherence Violation Detected -- 2 exclusive chips"); + } else if (sharedDetected) { + WARN_EXPR(lastShared); + WARN_EXPR(m_chip_vector[i]->getID()); + WARN_EXPR(addr); + WARN_EXPR(g_eventQueue_ptr->getTime()); + ERROR_MSG("Coherence Violation Detected -- exclusive chip with >=1 shared"); + } else { + exclusive = m_chip_vector[i]->getID(); + } + } else if (m_chip_vector[i]->isBlockShared(addr)) { + sharedDetected = true; + lastShared = m_chip_vector[i]->getID(); + + if (exclusive != -1) { + WARN_EXPR(lastShared); + WARN_EXPR(exclusive); + WARN_EXPR(addr); + WARN_EXPR(g_eventQueue_ptr->getTime()); + ERROR_MSG("Coherence Violation Detected -- exclusive chip with >=1 shared"); + } + } } - } - */ +#endif } #endif @@ -231,7 +218,8 @@ RubySystemParams::create() * virtual process function that is invoked when the callback * queue is executed. */ -void RubyExitCallback::process() +void +RubyExitCallback::process() { std::ostream *os = simout.create(stats_filename); RubySystem::printConfig(*os); diff --git a/src/mem/ruby/system/System.hh b/src/mem/ruby/system/System.hh index 7868da4b6..ccec2d61c 100644 --- a/src/mem/ruby/system/System.hh +++ b/src/mem/ruby/system/System.hh @@ -1,4 +1,3 @@ - /* * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood * All rights reserved. @@ -28,32 +27,27 @@ */ /* - * System.hh - * - * Description: Contains all of the various parts of the system we are - * simulating. Performs allocation, deallocation, and setup of all - * the major components of the system - * - * $Id$ - * + * Contains all of the various parts of the system we are simulating. + * Performs allocation, deallocation, and setup of all the major + * components of the system */ -#ifndef SYSTEM_H -#define SYSTEM_H +#ifndef __MEM_RUBY_SYSTEM_SYSTEM_HH__ +#define __MEM_RUBY_SYSTEM_SYSTEM_HH__ -#include "mem/ruby/system/RubyPort.hh" -#include "mem/ruby/common/Global.hh" +#include "base/callback.hh" #include "mem/gems_common/Vector.hh" +#include "mem/ruby/common/Global.hh" #include "mem/ruby/eventqueue/RubyEventQueue.hh" -#include "sim/sim_object.hh" +#include "mem/ruby/system/RubyPort.hh" #include "params/RubySystem.hh" -#include "base/callback.hh" +#include "sim/sim_object.hh" -class Profiler; -class Network; class CacheRecorder; -class Tracer; class MemoryVector; +class Network; +class Profiler; +class Tracer; /* * This defines the number of longs (32-bits on 32 bit machines, @@ -68,83 +62,103 @@ class MemoryVector; */ const int NUMBER_WORDS_PER_SET = 1; -class RubySystem : public SimObject { -public: +class RubySystem : public SimObject +{ + public: typedef RubySystemParams Params; RubySystem(const Params *p); - // Destructor - ~RubySystem(); - - // config accessors - static int getRandomSeed() { return m_random_seed; } - static int getRandomization() { return m_randomization; } - static int getBlockSizeBytes() { return m_block_size_bytes; } - static int getBlockSizeBits() { return m_block_size_bits; } - static uint64 getMemorySizeBytes() { return m_memory_size_bytes; } - static int getMemorySizeBits() { return m_memory_size_bits; } - - // Public Methods - static Network* getNetwork() { assert(m_network_ptr != NULL); return m_network_ptr; } - static RubyEventQueue* getEventQueue() { return g_eventQueue_ptr; } - Profiler* getProfiler() {assert(m_profiler_ptr != NULL); return m_profiler_ptr; } - static Tracer* getTracer() { assert(m_tracer_ptr != NULL); return m_tracer_ptr; } - static MemoryVector* getMemoryVector() { assert(m_mem_vec_ptr != NULL); return m_mem_vec_ptr;} - - void recordCacheContents(CacheRecorder& tr) const; - static void printConfig(ostream& out); - static void printStats(ostream& out); - void clearStats() const; - - uint64 getInstructionCount(int thread) { return 1; } - static uint64 getCycleCount(int thread) { return g_eventQueue_ptr->getTime(); } - - void print(ostream& out) const; - /* -#ifdef CHECK_COHERENCE - void checkGlobalCoherenceInvariant(const Address& addr); -#endif - */ - -private: - // Private copy constructor and assignment operator - RubySystem(const RubySystem& obj); - RubySystem& operator=(const RubySystem& obj); - - void init(); - - static void printSystemConfig(ostream& out); - -private: - // configuration parameters - static int m_random_seed; - static bool m_randomization; - static Tick m_clock; - static int m_block_size_bytes; - static int m_block_size_bits; - static uint64 m_memory_size_bytes; - static int m_memory_size_bits; - - // Data Members (m_ prefix) - static Network* m_network_ptr; - -public: - static Profiler* m_profiler_ptr; - static Tracer* m_tracer_ptr; - static MemoryVector* m_mem_vec_ptr; -}; + ~RubySystem(); + + // config accessors + static int getRandomSeed() { return m_random_seed; } + static int getRandomization() { return m_randomization; } + static int getBlockSizeBytes() { return m_block_size_bytes; } + static int getBlockSizeBits() { return m_block_size_bits; } + static uint64 getMemorySizeBytes() { return m_memory_size_bytes; } + static int getMemorySizeBits() { return m_memory_size_bits; } + + // Public Methods + static Network* + getNetwork() + { + assert(m_network_ptr != NULL); + return m_network_ptr; + } -// Output operator declaration -ostream& operator<<(ostream& out, const RubySystem& obj); + static RubyEventQueue* + getEventQueue() + { + return g_eventQueue_ptr; + } -// ******************* Definitions ******************* + Profiler* + getProfiler() + { + assert(m_profiler_ptr != NULL); + return m_profiler_ptr; + } + + static Tracer* + getTracer() + { + assert(m_tracer_ptr != NULL); + return m_tracer_ptr; + } + + static MemoryVector* + getMemoryVector() + { + assert(m_mem_vec_ptr != NULL); + return m_mem_vec_ptr; + } + + void recordCacheContents(CacheRecorder& tr) const; + static void printConfig(ostream& out); + static void printStats(ostream& out); + void clearStats() const; + + uint64 getInstructionCount(int thread) { return 1; } + static uint64 + getCycleCount(int thread) + { + return g_eventQueue_ptr->getTime(); + } -// Output operator definition -inline -ostream& operator<<(ostream& out, const RubySystem& obj) + void print(ostream& out) const; + + private: + // Private copy constructor and assignment operator + RubySystem(const RubySystem& obj); + RubySystem& operator=(const RubySystem& obj); + + void init(); + + static void printSystemConfig(ostream& out); + + private: + // configuration parameters + static int m_random_seed; + static bool m_randomization; + static Tick m_clock; + static int m_block_size_bytes; + static int m_block_size_bits; + static uint64 m_memory_size_bytes; + static int m_memory_size_bits; + + static Network* m_network_ptr; + + public: + static Profiler* m_profiler_ptr; + static Tracer* m_tracer_ptr; + static MemoryVector* m_mem_vec_ptr; +}; + +inline ostream& +operator<<(ostream& out, const RubySystem& obj) { -// obj.print(out); - out << flush; - return out; + //obj.print(out); + out << flush; + return out; } class RubyExitCallback : public Callback @@ -153,22 +167,17 @@ class RubyExitCallback : public Callback string stats_filename; public: - /** - * virtualize the destructor to make sure that the correct one - * gets called. - */ - virtual ~RubyExitCallback() {} RubyExitCallback(const string& _stats_filename) { - stats_filename = _stats_filename; + stats_filename = _stats_filename; } virtual void process(); }; -#endif //SYSTEM_H +#endif // __MEM_RUBY_SYSTEM_SYSTEM_HH__ diff --git a/src/mem/ruby/system/TBETable.hh b/src/mem/ruby/system/TBETable.hh index 2b00f7a06..d21946abd 100644 --- a/src/mem/ruby/system/TBETable.hh +++ b/src/mem/ruby/system/TBETable.hh @@ -1,4 +1,3 @@ - /* * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood * All rights reserved. @@ -27,141 +26,115 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -/* - * TBETable.hh - * - * Description: - * - * $Id$ - * - */ - -#ifndef TBETABLE_H -#define TBETABLE_H +#ifndef __MEM_RUBY_SYSTEM_TBETABLE_HH__ +#define __MEM_RUBY_SYSTEM_TBETABLE_HH__ -#include "mem/ruby/common/Global.hh" #include "mem/gems_common/Map.hh" #include "mem/ruby/common/Address.hh" +#include "mem/ruby/common/Global.hh" #include "mem/ruby/profiler/Profiler.hh" #include "mem/ruby/system/System.hh" template<class ENTRY> -class TBETable { -public: - - // Constructors - TBETable(int number_of_TBEs); - - - // Destructor - //~TBETable(); - - // Public Methods - - void printConfig(ostream& out) { out << "TBEs_per_TBETable: " << m_number_of_TBEs << endl; } - - bool isPresent(const Address& address) const; - void allocate(const Address& address); - void deallocate(const Address& address); - bool areNSlotsAvailable(int n) const { return (m_number_of_TBEs - m_map.size()) >= n; } - - ENTRY& lookup(const Address& address); - const ENTRY& lookup(const Address& address) const; - - // Print cache contents - void print(ostream& out) const; -private: - // Private Methods - - // Private copy constructor and assignment operator - TBETable(const TBETable& obj); - TBETable& operator=(const TBETable& obj); - - // Data Members (m_prefix) - Map<Address, ENTRY> m_map; - -private: - int m_number_of_TBEs; -}; - -// Output operator declaration -//ostream& operator<<(ostream& out, const TBETable<ENTRY>& obj); - -// ******************* Definitions ******************* - -// Output operator definition -template<class ENTRY> -extern inline -ostream& operator<<(ostream& out, const TBETable<ENTRY>& obj) +class TBETable { - obj.print(out); - out << flush; - return out; -} - - -// **************************************************************** - + public: + TBETable(int number_of_TBEs) + : m_number_of_TBEs(number_of_TBEs) + { + } + + void + printConfig(ostream& out) + { + out << "TBEs_per_TBETable: " << m_number_of_TBEs << endl; + } + + bool isPresent(const Address& address) const; + void allocate(const Address& address); + void deallocate(const Address& address); + bool + areNSlotsAvailable(int n) const + { + return (m_number_of_TBEs - m_map.size()) >= n; + } + + ENTRY& lookup(const Address& address); + const ENTRY& lookup(const Address& address) const; + + // Print cache contents + void print(ostream& out) const; + + private: + // Private copy constructor and assignment operator + TBETable(const TBETable& obj); + TBETable& operator=(const TBETable& obj); + + // Data Members (m_prefix) + Map<Address, ENTRY> m_map; + + private: + int m_number_of_TBEs; +}; template<class ENTRY> -extern inline -TBETable<ENTRY>::TBETable(int number_of_TBEs) +inline ostream& +operator<<(ostream& out, const TBETable<ENTRY>& obj) { - m_number_of_TBEs = number_of_TBEs; + obj.print(out); + out << flush; + return out; } -// PUBLIC METHODS - -// tests to see if an address is present in the cache template<class ENTRY> -extern inline -bool TBETable<ENTRY>::isPresent(const Address& address) const +inline bool +TBETable<ENTRY>::isPresent(const Address& address) const { - assert(address == line_address(address)); - assert(m_map.size() <= m_number_of_TBEs); - return m_map.exist(address); + assert(address == line_address(address)); + assert(m_map.size() <= m_number_of_TBEs); + return m_map.exist(address); } template<class ENTRY> -extern inline -void TBETable<ENTRY>::allocate(const Address& address) +inline void +TBETable<ENTRY>::allocate(const Address& address) { - assert(isPresent(address) == false); - assert(m_map.size() < m_number_of_TBEs); - m_map.add(address, ENTRY()); + assert(isPresent(address) == false); + assert(m_map.size() < m_number_of_TBEs); + m_map.add(address, ENTRY()); } template<class ENTRY> -extern inline -void TBETable<ENTRY>::deallocate(const Address& address) +inline void +TBETable<ENTRY>::deallocate(const Address& address) { - assert(isPresent(address) == true); - assert(m_map.size() > 0); - m_map.erase(address); + assert(isPresent(address) == true); + assert(m_map.size() > 0); + m_map.erase(address); } // looks an address up in the cache template<class ENTRY> -extern inline -ENTRY& TBETable<ENTRY>::lookup(const Address& address) +inline ENTRY& +TBETable<ENTRY>::lookup(const Address& address) { - assert(isPresent(address) == true); - return m_map.lookup(address); + assert(isPresent(address) == true); + return m_map.lookup(address); } // looks an address up in the cache template<class ENTRY> -extern inline -const ENTRY& TBETable<ENTRY>::lookup(const Address& address) const +inline const ENTRY& +TBETable<ENTRY>::lookup(const Address& address) const { - assert(isPresent(address) == true); - return m_map.lookup(address); + assert(isPresent(address) == true); + return m_map.lookup(address); } template<class ENTRY> -extern inline -void TBETable<ENTRY>::print(ostream& out) const +inline void +TBETable<ENTRY>::print(ostream& out) const { } -#endif //TBETABLE_H +#endif // __MEM_RUBY_SYSTEM_TBETABLE_HH__ diff --git a/src/mem/ruby/system/TimerTable.cc b/src/mem/ruby/system/TimerTable.cc index 5d496da04..eba04e3e3 100644 --- a/src/mem/ruby/system/TimerTable.cc +++ b/src/mem/ruby/system/TimerTable.cc @@ -1,4 +1,3 @@ - /* * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood * All rights reserved. @@ -27,101 +26,101 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -/* - * $Id$ - */ - #include "mem/ruby/common/Global.hh" -#include "mem/ruby/system/TimerTable.hh" #include "mem/ruby/eventqueue/RubyEventQueue.hh" +#include "mem/ruby/system/TimerTable.hh" TimerTable::TimerTable() { - m_consumer_ptr = NULL; - m_next_valid = false; - m_next_address = Address(0); - m_next_time = 0; + m_consumer_ptr = NULL; + m_next_valid = false; + m_next_address = Address(0); + m_next_time = 0; } - -bool TimerTable::isReady() const +bool +TimerTable::isReady() const { - if (m_map.size() == 0) { - return false; - } + if (m_map.size() == 0) { + return false; + } - if (!m_next_valid) { - updateNext(); - } - assert(m_next_valid); - return (g_eventQueue_ptr->getTime() >= m_next_time); + if (!m_next_valid) { + updateNext(); + } + assert(m_next_valid); + return (g_eventQueue_ptr->getTime() >= m_next_time); } -const Address& TimerTable::readyAddress() const +const Address& +TimerTable::readyAddress() const { - assert(isReady()); + assert(isReady()); - if (!m_next_valid) { - updateNext(); - } - assert(m_next_valid); - return m_next_address; + if (!m_next_valid) { + updateNext(); + } + assert(m_next_valid); + return m_next_address; } -void TimerTable::set(const Address& address, Time relative_latency) +void +TimerTable::set(const Address& address, Time relative_latency) { - assert(address == line_address(address)); - assert(relative_latency > 0); - assert(m_map.exist(address) == false); - Time ready_time = g_eventQueue_ptr->getTime() + relative_latency; - m_map.add(address, ready_time); - assert(m_consumer_ptr != NULL); - g_eventQueue_ptr->scheduleEventAbsolute(m_consumer_ptr, ready_time); - m_next_valid = false; - - // Don't always recalculate the next ready address - if (ready_time <= m_next_time) { + assert(address == line_address(address)); + assert(relative_latency > 0); + assert(m_map.exist(address) == false); + Time ready_time = g_eventQueue_ptr->getTime() + relative_latency; + m_map.add(address, ready_time); + assert(m_consumer_ptr != NULL); + g_eventQueue_ptr->scheduleEventAbsolute(m_consumer_ptr, ready_time); m_next_valid = false; - } + + // Don't always recalculate the next ready address + if (ready_time <= m_next_time) { + m_next_valid = false; + } } -void TimerTable::unset(const Address& address) +void +TimerTable::unset(const Address& address) { - assert(address == line_address(address)); - assert(m_map.exist(address) == true); - m_map.remove(address); + assert(address == line_address(address)); + assert(m_map.exist(address) == true); + m_map.remove(address); - // Don't always recalculate the next ready address - if (address == m_next_address) { - m_next_valid = false; - } + // Don't always recalculate the next ready address + if (address == m_next_address) { + m_next_valid = false; + } } -void TimerTable::print(ostream& out) const +void +TimerTable::print(ostream& out) const { } - -void TimerTable::updateNext() const +void +TimerTable::updateNext() const { - if (m_map.size() == 0) { - assert(m_next_valid == false); - return; - } - - Vector<Address> addresses = m_map.keys(); - m_next_address = addresses[0]; - m_next_time = m_map.lookup(m_next_address); + if (m_map.size() == 0) { + assert(m_next_valid == false); + return; + } - // Search for the minimum time - int size = addresses.size(); - for (int i=1; i<size; i++) { - Address maybe_next_address = addresses[i]; - Time maybe_next_time = m_map.lookup(maybe_next_address); - if (maybe_next_time < m_next_time) { - m_next_time = maybe_next_time; - m_next_address= maybe_next_address; + Vector<Address> addresses = m_map.keys(); + m_next_address = addresses[0]; + m_next_time = m_map.lookup(m_next_address); + + // Search for the minimum time + int size = addresses.size(); + for (int i=1; i<size; i++) { + Address maybe_next_address = addresses[i]; + Time maybe_next_time = m_map.lookup(maybe_next_address); + if (maybe_next_time < m_next_time) { + m_next_time = maybe_next_time; + m_next_address= maybe_next_address; + } } - } - m_next_valid = true; + m_next_valid = true; } diff --git a/src/mem/ruby/system/TimerTable.hh b/src/mem/ruby/system/TimerTable.hh index eda84069d..96b4b0b15 100644 --- a/src/mem/ruby/system/TimerTable.hh +++ b/src/mem/ruby/system/TimerTable.hh @@ -1,4 +1,3 @@ - /* * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood * All rights reserved. @@ -27,70 +26,69 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -/* - * TimerTable.hh - * - * Description: - * - * $Id$ - * - */ +#ifndef __MEM_RUBY_SYSTEM_TIMERTABLE_HH__ +#define __MEM_RUBY_SYSTEM_TIMERTABLE_HH__ -#ifndef TIMERTABLE_H -#define TIMERTABLE_H +#include <cassert> -#include "mem/ruby/common/Global.hh" #include "mem/gems_common/Map.hh" #include "mem/ruby/common/Address.hh" +#include "mem/ruby/common/Global.hh" + class Consumer; -class TimerTable { -public: +class TimerTable +{ + public: + TimerTable(); - // Constructors - TimerTable(); + static void printConfig(ostream& out) {} - // Destructor - //~TimerTable(); + void + setConsumer(Consumer* consumer_ptr) + { + assert(m_consumer_ptr == NULL); + m_consumer_ptr = consumer_ptr; + } - // Class Methods - static void printConfig(ostream& out) {} + void + setDescription(const string& name) + { + m_name = name; + } - // Public Methods - void setConsumer(Consumer* consumer_ptr) { ASSERT(m_consumer_ptr==NULL); m_consumer_ptr = consumer_ptr; } - void setDescription(const string& name) { m_name = name; } + bool isReady() const; + const Address& readyAddress() const; + bool isSet(const Address& address) const { return m_map.exist(address); } + void set(const Address& address, Time relative_latency); + void unset(const Address& address); + void print(ostream& out) const; - bool isReady() const; - const Address& readyAddress() const; - bool isSet(const Address& address) const { return m_map.exist(address); } - void set(const Address& address, Time relative_latency); - void unset(const Address& address); - void print(ostream& out) const; -private: - // Private Methods - void updateNext() const; + private: + void updateNext() const; - // Private copy constructor and assignment operator - TimerTable(const TimerTable& obj); - TimerTable& operator=(const TimerTable& obj); + // Private copy constructor and assignment operator + TimerTable(const TimerTable& obj); + TimerTable& operator=(const TimerTable& obj); - // Data Members (m_prefix) - Map<Address, Time> m_map; - mutable bool m_next_valid; - mutable Time m_next_time; // Only valid if m_next_valid is true - mutable Address m_next_address; // Only valid if m_next_valid is true - Consumer* m_consumer_ptr; // Consumer to signal a wakeup() - string m_name; + // Data Members (m_prefix) + Map<Address, Time> m_map; + mutable bool m_next_valid; + mutable Time m_next_time; // Only valid if m_next_valid is true + mutable Address m_next_address; // Only valid if m_next_valid is true + Consumer* m_consumer_ptr; // Consumer to signal a wakeup() + string m_name; }; // ******************* Definitions ******************* // Output operator definition -extern inline -ostream& operator<<(ostream& out, const TimerTable& obj) +inline ostream& +operator<<(ostream& out, const TimerTable& obj) { - obj.print(out); - out << flush; - return out; + obj.print(out); + out << flush; + return out; } -#endif //TIMERTABLE_H + +#endif // __MEM_RUBY_SYSTEM_TIMERTABLE_HH__ |