summaryrefslogtreecommitdiff
path: root/src/mem/ruby/system
diff options
context:
space:
mode:
Diffstat (limited to 'src/mem/ruby/system')
-rw-r--r--src/mem/ruby/system/AbstractMemOrCache.hh1
-rw-r--r--src/mem/ruby/system/CacheMemory.hh381
-rw-r--r--src/mem/ruby/system/DMASequencer.cc130
-rw-r--r--src/mem/ruby/system/DMASequencer.hh49
-rw-r--r--src/mem/ruby/system/DirectoryMemory.cc165
-rw-r--r--src/mem/ruby/system/DirectoryMemory.hh37
-rw-r--r--src/mem/ruby/system/MemoryControl.cc156
-rw-r--r--src/mem/ruby/system/MemoryControl.hh20
-rw-r--r--src/mem/ruby/system/MemoryVector.hh81
-rw-r--r--src/mem/ruby/system/NodePersistentTable.cc193
-rw-r--r--src/mem/ruby/system/NodePersistentTable.hh99
-rw-r--r--src/mem/ruby/system/PersistentArbiter.cc165
-rw-r--r--src/mem/ruby/system/PersistentArbiter.hh107
-rw-r--r--src/mem/ruby/system/PersistentTable.cc194
-rw-r--r--src/mem/ruby/system/PersistentTable.hh99
-rw-r--r--src/mem/ruby/system/ProcessorInterface.hh45
-rw-r--r--src/mem/ruby/system/RubyPort.cc5
-rw-r--r--src/mem/ruby/system/RubyPort.hh60
-rw-r--r--src/mem/ruby/system/Sequencer.cc1212
-rw-r--r--src/mem/ruby/system/Sequencer.hh98
-rw-r--r--src/mem/ruby/system/StoreBuffer.cc302
-rw-r--r--src/mem/ruby/system/StoreBuffer.hh121
-rw-r--r--src/mem/ruby/system/StoreCache.cc178
-rw-r--r--src/mem/ruby/system/StoreCache.hh85
-rw-r--r--src/mem/ruby/system/System.cc384
-rw-r--r--src/mem/ruby/system/System.hh136
-rw-r--r--src/mem/ruby/system/TBETable.hh21
27 files changed, 1693 insertions, 2831 deletions
diff --git a/src/mem/ruby/system/AbstractMemOrCache.hh b/src/mem/ruby/system/AbstractMemOrCache.hh
index e56e1f505..641c117de 100644
--- a/src/mem/ruby/system/AbstractMemOrCache.hh
+++ b/src/mem/ruby/system/AbstractMemOrCache.hh
@@ -11,7 +11,6 @@
#define ABSTRACT_MEM_OR_CACHE_H
#include "mem/ruby/common/Global.hh"
-#include "mem/ruby/slicc_interface/AbstractChip.hh"
#include "mem/ruby/config/RubyConfig.hh"
#include "mem/ruby/common/Address.hh"
diff --git a/src/mem/ruby/system/CacheMemory.hh b/src/mem/ruby/system/CacheMemory.hh
index 22799ab13..4d46ac908 100644
--- a/src/mem/ruby/system/CacheMemory.hh
+++ b/src/mem/ruby/system/CacheMemory.hh
@@ -38,13 +38,10 @@
#ifndef CACHEMEMORY_H
#define CACHEMEMORY_H
-#include "mem/ruby/slicc_interface/AbstractChip.hh"
#include "mem/ruby/common/Global.hh"
#include "mem/protocol/AccessPermission.hh"
#include "mem/ruby/common/Address.hh"
-
-//dsm: PRUNED
-//#include "mem/ruby/recorder/CacheRecorder.hh"
+#include "mem/ruby/recorder/CacheRecorder.hh"
#include "mem/protocol/CacheRequestType.hh"
#include "mem/gems_common/Vector.hh"
#include "mem/ruby/common/DataBlock.hh"
@@ -52,18 +49,25 @@
#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/System.hh"
+#include "mem/ruby/slicc_interface/AbstractController.hh"
#include <vector>
-template<class ENTRY>
class CacheMemory {
public:
// Constructors
- CacheMemory(AbstractChip* chip_ptr, int numSetBits, int cacheAssoc, const MachineType machType, const string& description);
+ CacheMemory(const string & name);
+ void init(const vector<string> & argv);
// Destructor
~CacheMemory();
+ // factory
+ // static CacheMemory* createCache(int level, int num, char split_type, AbstractCacheEntry* (*entry_factory)());
+ // static CacheMemory* getCache(int cache_id);
+
// Public Methods
void printConfig(ostream& out);
@@ -82,7 +86,7 @@ public:
bool cacheAvail(const Address& address) const;
// find an unused entry and sets the tag appropriate for the address
- void allocate(const Address& address);
+ void allocate(const Address& address, AbstractCacheEntry* new_entry);
// Explicitly free up this address
void deallocate(const Address& address);
@@ -91,16 +95,18 @@ public:
Address cacheProbe(const Address& address) const;
// looks an address up in the cache
- ENTRY& lookup(const Address& address);
- const ENTRY& lookup(const Address& address) const;
+ AbstractCacheEntry& lookup(const Address& address);
+ const AbstractCacheEntry& 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);
+ int getLatency() const { return m_latency; }
+
// Hook for checkpointing the contents of the cache
void recordCacheContents(CacheRecorder& tr) const;
- void setAsInstructionCache(bool is_icache) { m_is_instruction_cache = is_icache; }
+ void setAsInstructionCache(bool is_icache) { m_is_instruction_only_cache = is_icache; }
// Set this address to most recently used
void setMRU(const Address& address);
@@ -129,15 +135,18 @@ private:
CacheMemory(const CacheMemory& obj);
CacheMemory& operator=(const CacheMemory& obj);
+private:
+ const string m_cache_name;
+ AbstractController* m_controller;
+ int m_latency;
+
// Data Members (m_prefix)
- AbstractChip* m_chip_ptr;
- MachineType m_machType;
- string m_description;
- bool m_is_instruction_cache;
+ 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.
- Vector<Vector<ENTRY> > m_cache;
+ Vector<Vector<AbstractCacheEntry*> > m_cache;
AbstractReplacementPolicy *m_replacementPolicy_ptr;
@@ -145,18 +154,55 @@ private:
int m_cache_num_set_bits;
int m_cache_assoc;
- bool is_locked; // for LL/SC
+ static Vector< CacheMemory* > m_all_caches;
};
+/*
+inline
+CacheMemory* CacheMemory::getCache(int cache_id)
+{
+ assert(cache_id < RubyConfig::getNumberOfCaches());
+ if (m_all_caches[cache_id] == NULL) {
+ cerr << "ERROR: Tried to obtain CacheMemory that hasn't been created yet." << endl;
+ assert(0);
+ }
+ return m_all_caches[cache_id];
+}
+inline
+CacheMemory* CacheMemory::createCache(int level, int num, char split_type_c, AbstractCacheEntry* (*entry_factory)())
+{
+ string split_type;
+ switch(split_type_c) {
+ case 'i':
+ split_type = "instruction"; break;
+ case 'd':
+ split_type = "data"; break;
+ default:
+ split_type = "unified"; break;
+ }
+ int cache_id = RubyConfig::getCacheIDFromParams(level, num, split_type);
+ assert(cache_id < RubyConfig::getNumberOfCaches());
+ if (m_all_caches.size() == 0) {
+ m_all_caches.setSize(RubyConfig::getNumberOfCaches());
+ for (int i=0; i<m_all_caches.size(); i++)
+ m_all_caches[i] = NULL;
+ }
+
+ string type = RubyConfig::getCacheType(cache_id);
+ if ( type == "SetAssociativeCache" ) {
+ m_all_caches[cache_id] = new CacheMemory(cache_id, entry_factory);
+ }
+ return m_all_caches[cache_id];
+}
+*/
// Output operator declaration
//ostream& operator<<(ostream& out, const CacheMemory<ENTRY>& obj);
// ******************* Definitions *******************
// Output operator definition
-template<class ENTRY>
inline
-ostream& operator<<(ostream& out, const CacheMemory<ENTRY>& obj)
+ostream& operator<<(ostream& out, const CacheMemory& obj)
{
obj.print(out);
out << flush;
@@ -166,112 +212,142 @@ ostream& operator<<(ostream& out, const CacheMemory<ENTRY>& obj)
// ****************************************************************
-template<class ENTRY>
inline
-CacheMemory<ENTRY>::CacheMemory(AbstractChip* chip_ptr, int numSetBits,
- int cacheAssoc, const MachineType machType, const string& description)
+CacheMemory::CacheMemory(const string & name)
+ : m_cache_name(name)
+{
+}
+inline
+void CacheMemory::init(const vector<string> & argv)
{
- //cout << "CacheMemory constructor numThreads = " << numThreads << endl;
- m_chip_ptr = chip_ptr;
- m_machType = machType;
- m_description = MachineType_to_string(m_machType)+"_"+description;
- m_cache_num_set_bits = numSetBits;
- m_cache_num_sets = 1 << numSetBits;
- m_cache_assoc = cacheAssoc;
- m_is_instruction_cache = false;
+ int cache_size = 0;
+ string policy;
+
+ m_controller = NULL;
+ for (uint32 i=0; i<argv.size(); i+=2) {
+ if (argv[i] == "size_kb") {
+ cache_size = atoi(argv[i+1].c_str());
+ } else if (argv[i] == "latency") {
+ m_latency = atoi(argv[i+1].c_str());
+ } else if (argv[i] == "assoc") {
+ m_cache_assoc = atoi(argv[i+1].c_str());
+ } else if (argv[i] == "replacement_policy") {
+ policy = argv[i+1];
+ } else if (argv[i] == "controller") {
+ m_controller = RubySystem::getController(argv[i+1]);
+ } else {
+ cerr << "WARNING: CacheMemory: Unknown configuration parameter: " << argv[i] << endl;
+ }
+ }
- m_cache.setSize(m_cache_num_sets);
- if(strcmp(g_REPLACEMENT_POLICY, "PSEDUO_LRU") == 0)
+ m_cache_num_sets = cache_size / m_cache_assoc;
+ m_cache_num_set_bits = log_int(m_cache_num_sets);
+
+ if(policy == "PSEUDO_LRU")
m_replacementPolicy_ptr = new PseudoLRUPolicy(m_cache_num_sets, m_cache_assoc);
- else if(strcmp(g_REPLACEMENT_POLICY, "LRU") == 0)
+ else if (policy == "LRU")
m_replacementPolicy_ptr = new LRUPolicy(m_cache_num_sets, m_cache_assoc);
else
assert(false);
+
+ m_cache.setSize(m_cache_num_sets);
for (int i = 0; i < m_cache_num_sets; i++) {
m_cache[i].setSize(m_cache_assoc);
for (int j = 0; j < m_cache_assoc; j++) {
- m_cache[i][j].m_Address.setAddress(0);
- m_cache[i][j].m_Permission = AccessPermission_NotPresent;
+ m_cache[i][j] = NULL;
}
}
+}
+/*
+inline
+CacheMemory::CacheMemory(int cache_id, AbstractCacheEntry* (*entry_factory)())
+{
+ string split_type;
+
+ m_cache_id = cache_id;
+ m_entry_factory = entry_factory;
+
+ m_cache_num_set_bits = RubyConfig::getNumberOfCacheSetBits(cache_id);
+ m_cache_num_sets = RubyConfig::getNumberOfCacheSets(cache_id);
+ m_cache_assoc = RubyConfig::getCacheAssoc(cache_id);
+ split_type = RubyConfig::getCacheSplitType(cache_id);
+ m_is_instruction_only_cache = m_is_data_only_cache = false;
+ if (split_type == "instruction")
+ m_is_instruction_only_cache = true;
+ else if (split_type == "data")
+ m_is_data_only_cache = true;
+ else
+ assert(split_type == "unified");
+ if(RubyConfig::getCacheReplacementPolicy(cache_id) == "PSEUDO_LRU")
+ m_replacementPolicy_ptr = new PseudoLRUPolicy(m_cache_num_sets, m_cache_assoc);
+ else if(RubyConfig::getCacheReplacementPolicy(cache_id) == "LRU")
+ m_replacementPolicy_ptr = new LRUPolicy(m_cache_num_sets, m_cache_assoc);
+ else
+ assert(false);
- // cout << "Before setting trans address list size" << endl;
- //create a trans address for each SMT thread
-// m_trans_address_list.setSize(numThreads);
-// for(ThreadID tid = 0; tid < numThreads; ++tid){
-// cout << "Setting list size for list " << tid << endl;
-// m_trans_address_list[tid].setSize(30);
-// }
- //cout << "CacheMemory constructor finished" << endl;
+ m_cache.setSize(m_cache_num_sets);
+ for (int i = 0; i < m_cache_num_sets; i++) {
+ m_cache[i].setSize(m_cache_assoc);
+ for (int j = 0; j < m_cache_assoc; j++) {
+ m_cache[i][j] = m_entry_factory();
+ }
+ }
}
-
-template<class ENTRY>
+*/
inline
-CacheMemory<ENTRY>::~CacheMemory()
+CacheMemory::~CacheMemory()
{
if(m_replacementPolicy_ptr != NULL)
delete m_replacementPolicy_ptr;
}
-template<class ENTRY>
inline
-void CacheMemory<ENTRY>::printConfig(ostream& out)
+void CacheMemory::printConfig(ostream& out)
{
- out << "Cache config: " << m_description << endl;
+ out << "Cache config: " << m_cache_name << endl;
+ if (m_controller != NULL)
+ out << " controller: " << m_controller->getName() << 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 * RubyConfig::dataBlockBytes() << endl;
+ out << " cache_set_size_bytes: " << cache_num_sets * RubySystem::getBlockSizeBytes() << endl;
out << " cache_set_size_Kbytes: "
- << double(cache_num_sets * RubyConfig::dataBlockBytes()) / (1<<10) << endl;
+ << double(cache_num_sets * RubySystem::getBlockSizeBytes()) / (1<<10) << endl;
out << " cache_set_size_Mbytes: "
- << double(cache_num_sets * RubyConfig::dataBlockBytes()) / (1<<20) << endl;
+ << double(cache_num_sets * RubySystem::getBlockSizeBytes()) / (1<<20) << endl;
out << " cache_size_bytes: "
- << cache_num_sets * RubyConfig::dataBlockBytes() * m_cache_assoc << endl;
+ << cache_num_sets * RubySystem::getBlockSizeBytes() * m_cache_assoc << endl;
out << " cache_size_Kbytes: "
- << double(cache_num_sets * RubyConfig::dataBlockBytes() * m_cache_assoc) / (1<<10) << endl;
+ << double(cache_num_sets * RubySystem::getBlockSizeBytes() * m_cache_assoc) / (1<<10) << endl;
out << " cache_size_Mbytes: "
- << double(cache_num_sets * RubyConfig::dataBlockBytes() * m_cache_assoc) / (1<<20) << endl;
+ << double(cache_num_sets * RubySystem::getBlockSizeBytes() * m_cache_assoc) / (1<<20) << endl;
}
// PRIVATE METHODS
// convert a Address to its location in the cache
-template<class ENTRY>
inline
-Index CacheMemory<ENTRY>::addressToCacheSet(const Address& address) const
+Index CacheMemory::addressToCacheSet(const Address& address) const
{
assert(address == line_address(address));
Index temp = -1;
- switch (m_machType) {
- case MACHINETYPE_L1CACHE_ENUM:
- temp = map_address_to_L1CacheSet(address, m_cache_num_set_bits);
- break;
- case MACHINETYPE_L2CACHE_ENUM:
- temp = map_address_to_L2CacheSet(address, m_cache_num_set_bits);
- break;
- default:
- ERROR_MSG("Don't recognize m_machType");
- }
- assert(temp < m_cache_num_sets);
- assert(temp >= 0);
- return temp;
+ 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.
-template<class ENTRY>
inline
-int CacheMemory<ENTRY>::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
for (int i=0; i < m_cache_assoc; i++) {
- if ((m_cache[cacheSet][i].m_Address == tag) &&
- (m_cache[cacheSet][i].m_Permission != AccessPermission_NotPresent)) {
+ if ((m_cache[cacheSet][i] != NULL) &&
+ (m_cache[cacheSet][i]->m_Address == tag) &&
+ (m_cache[cacheSet][i]->m_Permission != AccessPermission_NotPresent)) {
return i;
}
}
@@ -280,39 +356,37 @@ int CacheMemory<ENTRY>::findTagInSet(Index cacheSet, const Address& tag) const
// Given a cache index: returns the index of the tag in a set.
// returns -1 if the tag is not found.
-template<class ENTRY>
inline
-int CacheMemory<ENTRY>::findTagInSetIgnorePermissions(Index cacheSet, const Address& tag) const
+int CacheMemory::findTagInSetIgnorePermissions(Index cacheSet, const Address& tag) const
{
assert(tag == line_address(tag));
// search the set for the tags
for (int i=0; i < m_cache_assoc; i++) {
- if (m_cache[cacheSet][i].m_Address == tag)
+ if (m_cache[cacheSet][i] != NULL && m_cache[cacheSet][i]->m_Address == tag)
return i;
}
return -1; // Not found
}
// PUBLIC METHODS
-template<class ENTRY>
inline
-bool CacheMemory<ENTRY>::tryCacheAccess(const Address& address,
- CacheRequestType type,
- DataBlock*& data_ptr)
+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?
- ENTRY& entry = m_cache[cacheSet][loc];
+ AbstractCacheEntry* entry = m_cache[cacheSet][loc];
m_replacementPolicy_ptr->touch(cacheSet, loc, g_eventQueue_ptr->getTime());
- data_ptr = &(entry.getDataBlk());
+ data_ptr = &(entry->getDataBlk());
- if(entry.m_Permission == AccessPermission_Read_Write) {
+ if(entry->m_Permission == AccessPermission_Read_Write) {
return true;
}
- if ((entry.m_Permission == AccessPermission_Read_Only) &&
+ if ((entry->m_Permission == AccessPermission_Read_Only) &&
(type == CacheRequestType_LD || type == CacheRequestType_IFETCH)) {
return true;
}
@@ -322,31 +396,29 @@ bool CacheMemory<ENTRY>::tryCacheAccess(const Address& address,
return false;
}
-template<class ENTRY>
inline
-bool CacheMemory<ENTRY>::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?
- ENTRY& entry = m_cache[cacheSet][loc];
+ AbstractCacheEntry* entry = m_cache[cacheSet][loc];
m_replacementPolicy_ptr->touch(cacheSet, loc, g_eventQueue_ptr->getTime());
- data_ptr = &(entry.getDataBlk());
+ 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;
}
// tests to see if an address is present in the cache
-template<class ENTRY>
inline
-bool CacheMemory<ENTRY>::isTagPresent(const Address& address) const
+bool CacheMemory::isTagPresent(const Address& address) const
{
assert(address == line_address(address));
Index cacheSet = addressToCacheSet(address);
@@ -366,31 +438,29 @@ bool CacheMemory<ENTRY>::isTagPresent(const Address& address) const
// Returns true if there is:
// a) a tag match on this address or there is
// b) an unused line in the same cache "way"
-template<class ENTRY>
inline
-bool CacheMemory<ENTRY>::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++) {
- if (m_cache[cacheSet][i].m_Address == address) {
- // Already in the cache
- return true;
- }
-
- if (m_cache[cacheSet][i].m_Permission == AccessPermission_NotPresent) {
- // We found an empty entry
+ AbstractCacheEntry* entry = m_cache[cacheSet][i];
+ if (entry != NULL) {
+ if (entry->m_Address == address || // Already in the cache
+ entry->m_Permission == AccessPermission_NotPresent) { // We found an empty entry
+ return true;
+ }
+ } else {
return true;
}
}
return false;
}
-template<class ENTRY>
inline
-void CacheMemory<ENTRY>::allocate(const Address& address)
+void CacheMemory::allocate(const Address& address, AbstractCacheEntry* entry)
{
assert(address == line_address(address));
assert(!isTagPresent(address));
@@ -400,10 +470,11 @@ void CacheMemory<ENTRY>::allocate(const Address& address)
// Find the first open slot
Index cacheSet = addressToCacheSet(address);
for (int i=0; i < m_cache_assoc; i++) {
- if (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;
+ if (m_cache[cacheSet][i] == NULL ||
+ m_cache[cacheSet][i]->m_Permission == AccessPermission_NotPresent) {
+ m_cache[cacheSet][i] = entry; // Init entry
+ m_cache[cacheSet][i]->m_Address = address;
+ m_cache[cacheSet][i]->m_Permission = AccessPermission_Invalid;
m_replacementPolicy_ptr->touch(cacheSet, i, g_eventQueue_ptr->getTime());
@@ -413,63 +484,62 @@ void CacheMemory<ENTRY>::allocate(const Address& address)
ERROR_MSG("Allocate didn't find an available entry");
}
-template<class ENTRY>
inline
-void CacheMemory<ENTRY>::deallocate(const Address& address)
+void CacheMemory::deallocate(const Address& address)
{
assert(address == line_address(address));
assert(isTagPresent(address));
DEBUG_EXPR(CACHE_COMP, HighPrio, address);
- lookup(address).m_Permission = AccessPermission_NotPresent;
+ Index cacheSet = addressToCacheSet(address);
+ int location = findTagInSet(cacheSet, address);
+ if (location != -1){
+ delete m_cache[cacheSet][location];
+ m_cache[cacheSet][location] = NULL;
+ }
}
// Returns with the physical address of the conflicting cache line
-template<class ENTRY>
inline
-Address CacheMemory<ENTRY>::cacheProbe(const Address& address) const
+Address CacheMemory::cacheProbe(const Address& address) const
{
assert(address == line_address(address));
assert(!cacheAvail(address));
Index cacheSet = addressToCacheSet(address);
- return m_cache[cacheSet][m_replacementPolicy_ptr->getVictim(cacheSet)].m_Address;
+ return m_cache[cacheSet][m_replacementPolicy_ptr->getVictim(cacheSet)]->m_Address;
}
// looks an address up in the cache
-template<class ENTRY>
inline
-ENTRY& CacheMemory<ENTRY>::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];
+ return *m_cache[cacheSet][loc];
}
// looks an address up in the cache
-template<class ENTRY>
inline
-const ENTRY& CacheMemory<ENTRY>::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];
+ return *m_cache[cacheSet][loc];
}
-template<class ENTRY>
inline
-AccessPermission CacheMemory<ENTRY>::getPermission(const Address& address) const
+AccessPermission CacheMemory::getPermission(const Address& address) const
{
assert(address == line_address(address));
return lookup(address).m_Permission;
}
-template<class ENTRY>
inline
-void CacheMemory<ENTRY>::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;
@@ -477,9 +547,8 @@ void CacheMemory<ENTRY>::changePermission(const Address& address, AccessPermissi
}
// Sets the most recently used bit for a cache block
-template<class ENTRY>
inline
-void CacheMemory<ENTRY>::setMRU(const Address& address)
+void CacheMemory::setMRU(const Address& address)
{
Index cacheSet;
@@ -489,19 +558,15 @@ void CacheMemory<ENTRY>::setMRU(const Address& address)
g_eventQueue_ptr->getTime());
}
-template<class ENTRY>
inline
-void CacheMemory<ENTRY>::recordCacheContents(CacheRecorder& tr) const
+void CacheMemory::recordCacheContents(CacheRecorder& tr) const
{
-//dsm: Uses CacheRecorder, PRUNED
-assert(false);
-
-/* for (int i = 0; i < m_cache_num_sets; i++) {
+ 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;
+ AccessPermission perm = m_cache[i][j]->m_Permission;
CacheRequestType request_type = CacheRequestType_NULL;
if (perm == AccessPermission_Read_Only) {
- if (m_is_instruction_cache) {
+ if (m_is_instruction_only_cache) {
request_type = CacheRequestType_IFETCH;
} else {
request_type = CacheRequestType_LD;
@@ -511,55 +576,59 @@ assert(false);
}
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));
+ // tr.addRecord(m_chip_ptr->getID(), m_cache[i][j].m_Address,
+ // Address(0), request_type, m_replacementPolicy_ptr->getLastAccess(i, j));
}
}
- }*/
+ }
}
-template<class ENTRY>
inline
-void CacheMemory<ENTRY>::print(ostream& out) const
+void CacheMemory::print(ostream& out) const
{
- out << "Cache dump: " << m_description << endl;
+ 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++) {
- out << " Index: " << i
- << " way: " << j
- << " entry: " << m_cache[i][j] << endl;
+ 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;
+ }
}
}
}
-template<class ENTRY>
inline
-void CacheMemory<ENTRY>::printData(ostream& out) const
+void CacheMemory::printData(ostream& out) const
{
out << "printData() not supported" << endl;
}
-template<class ENTRY>
-void CacheMemory<ENTRY>::getMemoryValue(const Address& addr, char* value,
- unsigned int size_in_bytes ){
- ENTRY entry = lookup(line_address(addr));
+inline
+void CacheMemory::getMemoryValue(const Address& addr, char* value,
+ unsigned int size_in_bytes ){
+ AbstractCacheEntry& entry = lookup(line_address(addr));
unsigned int startByte = addr.getAddress() - line_address(addr).getAddress();
for(unsigned int i=0; i<size_in_bytes; ++i){
- value[i] = entry.m_DataBlk.getByte(i + startByte);
+ value[i] = entry.getDataBlk().getByte(i + startByte);
}
}
-template<class ENTRY>
-void CacheMemory<ENTRY>::setMemoryValue(const Address& addr, char* value,
- unsigned int size_in_bytes ){
- ENTRY& entry = lookup(line_address(addr));
+inline
+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.m_DataBlk.setByte(i + startByte, value[i]);
+ entry.getDataBlk().setByte(i + startByte, value[i]);
}
- entry = lookup(line_address(addr));
+ // entry = lookup(line_address(addr));
}
#endif //CACHEMEMORY_H
diff --git a/src/mem/ruby/system/DMASequencer.cc b/src/mem/ruby/system/DMASequencer.cc
new file mode 100644
index 000000000..4aa092113
--- /dev/null
+++ b/src/mem/ruby/system/DMASequencer.cc
@@ -0,0 +1,130 @@
+
+#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/DMARequestMsg.hh"
+#include "mem/protocol/DMARequestType.hh"
+#include "mem/protocol/DMAResponseMsg.hh"
+#include "mem/ruby/system/System.hh"
+
+DMASequencer::DMASequencer(const string & name)
+ : RubyPort(name)
+{
+}
+
+void DMASequencer::init(const vector<string> & argv)
+{
+ m_version = -1;
+ m_controller = NULL;
+ for (size_t i=0;i<argv.size();i+=2) {
+ if (argv[i] == "controller")
+ m_controller = RubySystem::getController(argv[i+1]);
+ else if (argv[i] == "version")
+ m_version = atoi(argv[i+1].c_str());
+ }
+ assert(m_controller != NULL);
+ assert(m_version != -1);
+
+ m_mandatory_q_ptr = m_controller->getMandatoryQueue();
+ m_is_busy = false;
+}
+
+int64_t 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_RMW:
+ assert(0);
+ }
+
+ assert(!m_is_busy);
+ 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.id = makeUniqueRequestID();
+
+ DMARequestMsg msg;
+ msg.getPhysicalAddress() = Address(paddr);
+ msg.getType() = write ? DMARequestType_WRITE : DMARequestType_READ;
+ msg.getOffset() = paddr & RubyConfig::dataBlockMask();
+ msg.getLen() = (msg.getOffset() + len) < RubySystem::getBlockSizeBytes() ?
+ (msg.getOffset() + len) :
+ RubySystem::getBlockSizeBytes() - msg.getOffset();
+ if (write) {
+ msg.getType() = DMARequestType_WRITE;
+ msg.getDataBlk().setData(data, 0, msg.getLen());
+ } else {
+ msg.getType() = DMARequestType_READ;
+ }
+ m_mandatory_q_ptr->enqueue(msg);
+ active_request.bytes_issued += msg.getLen();
+
+ return active_request.id;
+}
+
+void DMASequencer::issueNext()
+{
+ assert(m_is_busy == true);
+ active_request.bytes_completed = active_request.bytes_issued;
+ if (active_request.len == active_request.bytes_completed) {
+ m_hit_callback(active_request.id);
+ m_is_busy = false;
+ return;
+ }
+
+ DMARequestMsg msg;
+ msg.getPhysicalAddress() = Address(active_request.start_paddr + active_request.bytes_completed);
+ assert((msg.getPhysicalAddress().getAddress() & RubyConfig::dataBlockMask()) == 0);
+ msg.getOffset() = 0;
+ msg.getType() = active_request.write ? DMARequestType_WRITE : DMARequestType_READ;
+ 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() = DMARequestType_WRITE;
+ } else {
+ msg.getType() = DMARequestType_READ;
+ }
+ m_mandatory_q_ptr->enqueue(msg);
+ active_request.bytes_issued += msg.getLen();
+}
+
+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 & RubyConfig::dataBlockMask();
+ memcpy(&active_request.data[active_request.bytes_completed], dblk.getData(offset, len), len);
+ issueNext();
+}
+
+void DMASequencer::ackCallback()
+{
+ issueNext();
+}
+
+void DMASequencer::printConfig(ostream & out)
+{
+
+}
diff --git a/src/mem/ruby/system/DMASequencer.hh b/src/mem/ruby/system/DMASequencer.hh
new file mode 100644
index 000000000..2665549e3
--- /dev/null
+++ b/src/mem/ruby/system/DMASequencer.hh
@@ -0,0 +1,49 @@
+
+#ifndef DMASEQUENCER_H
+#define DMASEQUENCER_H
+
+#include <ostream>
+#include "mem/ruby/common/DataBlock.hh"
+#include "mem/ruby/system/RubyPort.hh"
+
+struct DMARequest {
+ uint64_t start_paddr;
+ int len;
+ bool write;
+ int bytes_completed;
+ int bytes_issued;
+ uint8* data;
+ int64_t id;
+};
+
+class MessageBuffer;
+class AbstractController;
+
+class DMASequencer :public RubyPort {
+public:
+ DMASequencer(const string & name);
+ void init(const vector<string> & argv);
+ /* external interface */
+ int64_t makeRequest(const RubyRequest & request);
+ // void issueRequest(uint64_t paddr, uint8* data, int len, bool rw);
+ bool busy() { return m_is_busy;}
+
+ /* SLICC callback */
+ void dataCallback(const DataBlock & dblk);
+ void ackCallback();
+
+ void printConfig(std::ostream & out);
+
+private:
+ void issueNext();
+
+private:
+ int m_version;
+ AbstractController* m_controller;
+ bool m_is_busy;
+ DMARequest active_request;
+ int num_active_requests;
+ MessageBuffer* m_mandatory_q_ptr;
+};
+
+#endif // DMACONTROLLER_H
diff --git a/src/mem/ruby/system/DirectoryMemory.cc b/src/mem/ruby/system/DirectoryMemory.cc
index 40b990e2d..294d57de2 100644
--- a/src/mem/ruby/system/DirectoryMemory.cc
+++ b/src/mem/ruby/system/DirectoryMemory.cc
@@ -37,118 +37,150 @@
*/
#include "mem/ruby/system/System.hh"
-#include "mem/ruby/common/Driver.hh"
#include "mem/ruby/system/DirectoryMemory.hh"
#include "mem/ruby/slicc_interface/RubySlicc_Util.hh"
#include "mem/ruby/config/RubyConfig.hh"
-#include "mem/protocol/Chip.hh"
+#include "mem/ruby/slicc_interface/AbstractController.hh"
+#include "mem/gems_common/util.hh"
-DirectoryMemory::DirectoryMemory(Chip* chip_ptr, int version)
+int DirectoryMemory::m_num_directories = 0;
+int DirectoryMemory::m_num_directories_bits = 0;
+int DirectoryMemory::m_total_size_bytes = 0;
+
+DirectoryMemory::DirectoryMemory(const string & name)
+ : m_name(name)
{
- m_chip_ptr = chip_ptr;
- m_version = version;
- // THIS DOESN'T SEEM TO WORK -- MRM
- // m_size = RubyConfig::memoryModuleBlocks()/RubyConfig::numberOfDirectory();
- m_size = RubyConfig::memoryModuleBlocks();
- assert(m_size > 0);
- /*********************************************************************
- // allocates an array of directory entry pointers & sets them to NULL
- m_entries = new Directory_Entry*[m_size];
- if (m_entries == NULL) {
- ERROR_MSG("Directory Memory: unable to allocate memory.");
+}
+
+void DirectoryMemory::init(const vector<string> & argv)
+{
+ m_controller = NULL;
+ for (vector<string>::const_iterator it = argv.begin(); it != argv.end(); it++) {
+ if ( (*it) == "version" )
+ m_version = atoi( (*(++it)).c_str() );
+ else if ( (*it) == "size_mb" ) {
+ m_size_bytes = atoi((*(++it)).c_str()) * (1<<20);
+ m_size_bits = log_int(m_size_bytes);
+ } else if ( (*it) == "controller" ) {
+ m_controller = RubySystem::getController((*(++it)));
+ } else
+ assert(0);
}
+ assert(m_controller != NULL);
- for (int i=0; i < m_size; i++) {
+ m_num_entries = m_size_bytes / RubySystem::getBlockSizeBytes();
+ 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;
}
DirectoryMemory::~DirectoryMemory()
{
- /*********************************************************************
// free up all the directory entries
- for (int i=0; i < m_size; i++) {
- if (m_entries[i] != NULL) {
- delete m_entries[i];
- m_entries[i] = NULL;
- }
- }
+ for (int i=0;i<m_num_entries;i++)
+ if (m_entries[i] != NULL)
+ delete m_entries;
+ if (m_entries != NULL)
+ delete [] m_entries;
+}
- // free up the array of directory entries
- delete[] m_entries;
- *//////////////////////////////////////////////////////////////////////
- m_entries.clear();
+void DirectoryMemory::printConfig(ostream& out) const
+{
+ out << "DirectoryMemory module config: " << m_name << endl;
+ out << " controller: " << m_controller->getName() << 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;
}
// Static method
-void DirectoryMemory::printConfig(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: " << RubySystem::getBlockSizeBits()+m_num_directories_bits-1
+ << "-" << RubySystem::getBlockSizeBits() << endl;
+ }
+ out << " total memory size bytes: " << m_total_size_bytes << endl;
+ out << " total memory size bits: " << log_int(m_total_size_bytes) << endl;
+
+}
+
+int DirectoryMemory::mapAddressToDirectoryVersion(PhysAddress address)
{
- out << "Memory config:" << endl;
- out << " memory_bits: " << RubyConfig::memorySizeBits() << endl;
- out << " memory_size_bytes: " << RubyConfig::memorySizeBytes() << endl;
- out << " memory_size_Kbytes: " << double(RubyConfig::memorySizeBytes()) / (1<<10) << endl;
- out << " memory_size_Mbytes: " << double(RubyConfig::memorySizeBytes()) / (1<<20) << endl;
- out << " memory_size_Gbytes: " << double(RubyConfig::memorySizeBytes()) / (1<<30) << endl;
-
- out << " module_bits: " << RubyConfig::memoryModuleBits() << endl;
- out << " module_size_lines: " << RubyConfig::memoryModuleBlocks() << endl;
- out << " module_size_bytes: " << RubyConfig::memoryModuleBlocks() * RubyConfig::dataBlockBytes() << endl;
- out << " module_size_Kbytes: " << double(RubyConfig::memoryModuleBlocks() * RubyConfig::dataBlockBytes()) / (1<<10) << endl;
- out << " module_size_Mbytes: " << double(RubyConfig::memoryModuleBlocks() * RubyConfig::dataBlockBytes()) / (1<<20) << endl;
+ if (m_num_directories_bits == 0) return 0;
+ int ret = address.bitSelect(RubySystem::getBlockSizeBits(),
+ RubySystem::getBlockSizeBits()+m_num_directories_bits-1);
+ return ret;
}
// Public method
bool DirectoryMemory::isPresent(PhysAddress address)
{
- return (map_Address_to_DirectoryNode(address) == m_chip_ptr->getID()*RubyConfig::numberOfDirectoryPerChip()+m_version);
+ bool ret = (mapAddressToDirectoryVersion(address) == m_version);
+ return ret;
}
-void DirectoryMemory::readPhysMem(uint64 address, int size, void * data)
+int DirectoryMemory::mapAddressToLocalIdx(PhysAddress address)
{
+ int ret = address.getAddress() >> (RubySystem::getBlockSizeBits() + m_num_directories_bits);
+ return ret;
}
Directory_Entry& DirectoryMemory::lookup(PhysAddress address)
{
assert(isPresent(address));
+ Directory_Entry* entry;
+ int idx = mapAddressToLocalIdx(address);
+ 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(m_chip_ptr->getID());
WARN_EXPR(address.getAddress());
WARN_EXPR(index);
WARN_EXPR(m_size);
ERROR_MSG("Directory Memory Assertion: accessing memory out of range.");
}
-
- map<Index, Directory_Entry*>::iterator iter = m_entries.find(index);
- Directory_Entry* entry = m_entries.find(index)->second;
+ Directory_Entry* entry = m_entries[index];
// allocate the directory entry on demand.
- if (iter == m_entries.end()) {
+ if (entry == NULL) {
entry = new Directory_Entry;
+ entry->getDataBlk().assign(m_ram->getBlockPtr(address));
- // entry->getProcOwner() = m_chip_ptr->getID(); // FIXME - This should not be hard coded
- // entry->getDirOwner() = true; // FIXME - This should not be hard-coded
-
- // load the data from physicalMemory when first initalizing
- physical_address_t physAddr = address.getAddress();
- int8 * dataArray = (int8 * )malloc(RubyConfig::dataBlockBytes() * sizeof(int8));
- readPhysMem(physAddr, RubyConfig::dataBlockBytes(), dataArray);
-
- for(int j=0; j < RubyConfig::dataBlockBytes(); j++) {
- entry->getDataBlk().setByte(j, dataArray[j]);
- }
- DEBUG_EXPR(NODE_COMP, MedPrio,entry->getDataBlk());
// store entry to the table
- m_entries.insert(make_pair(index, entry));
+ m_entries[index] = entry;
}
+
return (*entry);
}
+*/
-/*
void DirectoryMemory::invalidateBlock(PhysAddress address)
{
+ /*
assert(isPresent(address));
Index index = address.memoryModuleIndex();
@@ -161,16 +193,11 @@ void DirectoryMemory::invalidateBlock(PhysAddress address)
delete m_entries[index];
m_entries[index] = NULL;
}
-
+ */
}
-*/
void DirectoryMemory::print(ostream& out) const
{
- out << "Directory dump: " << endl;
- for(map<Index, Directory_Entry*>::const_iterator it = m_entries.begin(); it != m_entries.end(); ++it) {
- out << it->first << ": ";
- out << *(it->second) << endl;
- }
+
}
diff --git a/src/mem/ruby/system/DirectoryMemory.hh b/src/mem/ruby/system/DirectoryMemory.hh
index 6451ed459..6445ecc62 100644
--- a/src/mem/ruby/system/DirectoryMemory.hh
+++ b/src/mem/ruby/system/DirectoryMemory.hh
@@ -41,26 +41,34 @@
#include "mem/ruby/common/Global.hh"
#include "mem/ruby/common/Address.hh"
+#include "mem/ruby/system/MemoryVector.hh"
#include "mem/protocol/Directory_Entry.hh"
-#include <map>
-class Chip;
+class AbstractController;
class DirectoryMemory {
public:
// Constructors
- DirectoryMemory(Chip* chip_ptr, int version);
+ DirectoryMemory(const string & name);
+ void init(const vector<string> & argv);
+ // DirectoryMemory(int version);
// Destructor
~DirectoryMemory();
+ int mapAddressToLocalIdx(PhysAddress address);
+ static int mapAddressToDirectoryVersion(PhysAddress address);
+
+ int getSize() { return m_size_bytes; }
+
// Public Methods
- static void printConfig(ostream& out);
+ void printConfig(ostream& out) const;
+ static void printGlobalConfig(ostream & out);
bool isPresent(PhysAddress address);
- // dummy function
- void readPhysMem(uint64 address, int size, void * data);
Directory_Entry& lookup(PhysAddress address);
+ void invalidateBlock(PhysAddress address);
+
void print(ostream& out) const;
private:
@@ -70,11 +78,22 @@ private:
DirectoryMemory(const DirectoryMemory& obj);
DirectoryMemory& operator=(const DirectoryMemory& obj);
+private:
+ const string m_name;
+ AbstractController* m_controller;
// Data Members (m_ prefix)
- map<Index, Directory_Entry*> m_entries;
- Chip* m_chip_ptr;
- int m_size; // # of memory module blocks for this directory
+ Directory_Entry **m_entries;
+ // int m_size; // # of memory module blocks this directory is responsible for
+ uint32 m_size_bytes;
+ uint32 m_size_bits;
+ int m_num_entries;
int m_version;
+
+ static int m_num_directories;
+ static int m_num_directories_bits;
+ static int m_total_size_bytes;
+
+ MemoryVector* m_ram;
};
// Output operator declaration
diff --git a/src/mem/ruby/system/MemoryControl.cc b/src/mem/ruby/system/MemoryControl.cc
index 86c6526c8..f9159ed3e 100644
--- a/src/mem/ruby/system/MemoryControl.cc
+++ b/src/mem/ruby/system/MemoryControl.cc
@@ -110,21 +110,21 @@
*
*/
-#include <list>
-
-#include "base/cprintf.hh"
#include "mem/ruby/common/Global.hh"
#include "mem/gems_common/Map.hh"
#include "mem/ruby/common/Address.hh"
#include "mem/ruby/profiler/Profiler.hh"
-#include "mem/ruby/slicc_interface/AbstractChip.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/system/MemoryControl.hh"
+#include <list>
+
class Consumer;
// Value to reset watchdog timer to.
@@ -151,32 +151,66 @@ ostream& operator<<(ostream& out, const MemoryControl& obj)
// ****************************************************************
// CONSTRUCTOR
+MemoryControl::MemoryControl(const string & name)
+ : m_name(name)
+{
+ m_name = name;
+// printf ("MemoryControl name is %s \n", m_name.c_str());
+}
+
+void MemoryControl::init(const vector<string> & argv)
+{
+
+ for (vector<string>::const_iterator it = argv.begin(); it != argv.end(); it++) {
+ if ( (*it) == "version" )
+ m_version = atoi( (*(++it)).c_str() );
+ else if ( (*it) == "mem_bus_cycle_multiplier" ) {
+ m_mem_bus_cycle_multiplier = atoi((*(++it)).c_str());
+ } else if ( (*it) == "banks_per_rank" ) {
+ m_banks_per_rank = atoi((*(++it)).c_str());
+ } else if ( (*it) == "ranks_per_dimm" ) {
+ m_ranks_per_dimm = atoi((*(++it)).c_str());
+ } else if ( (*it) == "dimms_per_channel" ) {
+ m_dimms_per_channel = atoi((*(++it)).c_str());
+ } else if ( (*it) == "bank_bit_0" ) {
+ m_bank_bit_0 = atoi((*(++it)).c_str());
+ } else if ( (*it) == "rank_bit_0" ) {
+ m_rank_bit_0 = atoi((*(++it)).c_str());
+ } else if ( (*it) == "dimm_bit_0" ) {
+ m_dimm_bit_0 = atoi((*(++it)).c_str());
+ } else if ( (*it) == "bank_queue_size" ) {
+ m_bank_queue_size = atoi((*(++it)).c_str());
+ } else if ( (*it) == "bank_busy_time" ) {
+ m_bank_busy_time = atoi((*(++it)).c_str());
+ } else if ( (*it) == "rank_rank_delay" ) {
+ m_rank_rank_delay = atoi((*(++it)).c_str());
+ } else if ( (*it) == "read_write_delay" ) {
+ m_read_write_delay = atoi((*(++it)).c_str());
+ } else if ( (*it) == "basic_bus_busy_time" ) {
+ m_basic_bus_busy_time = atoi((*(++it)).c_str());
+ } else if ( (*it) == "mem_ctl_latency" ) {
+ m_mem_ctl_latency = atoi((*(++it)).c_str());
+ } else if ( (*it) == "refresh_period" ) {
+ m_refresh_period = atoi((*(++it)).c_str());
+ } else if ( (*it) == "tFaw" ) {
+ m_tFaw = atoi((*(++it)).c_str());
+ } else if ( (*it) == "mem_random_arbitrate" ) {
+ m_mem_random_arbitrate = atoi((*(++it)).c_str());
+ } else if ( (*it) == "mem_fixed_delay" ) {
+ m_mem_fixed_delay = atoi((*(++it)).c_str());
+ }
+// } else
+// assert(0);
+ }
+
-MemoryControl::MemoryControl (AbstractChip* chip_ptr, int version) {
- m_chip_ptr = chip_ptr;
- m_version = version;
+///////
+ //m_version = version;
m_msg_counter = 0;
m_debug = 0;
//if (m_version == 0) m_debug = 1;
- m_mem_bus_cycle_multiplier = RubyConfig::memBusCycleMultiplier();
- m_banks_per_rank = RubyConfig::banksPerRank();
- m_ranks_per_dimm = RubyConfig::ranksPerDimm();
- m_dimms_per_channel = RubyConfig::dimmsPerChannel();
- m_bank_bit_0 = RubyConfig::bankBit0();
- m_rank_bit_0 = RubyConfig::rankBit0();
- m_dimm_bit_0 = RubyConfig::dimmBit0();
- m_bank_queue_size = RubyConfig::bankQueueSize();
- m_bank_busy_time = RubyConfig::bankBusyTime();
- m_rank_rank_delay = RubyConfig::rankRankDelay();
- m_read_write_delay = RubyConfig::readWriteDelay();
- m_basic_bus_busy_time = RubyConfig::basicBusBusyTime();
- m_mem_ctl_latency = RubyConfig::memCtlLatency();
- m_refresh_period = RubyConfig::refreshPeriod();
- m_memRandomArbitrate = RubyConfig::memRandomArbitrate();
- m_tFaw = RubyConfig::tFaw();
- m_memFixedDelay = RubyConfig::memFixedDelay();
assert(m_tFaw <= 62); // must fit in a uint64 shift register
@@ -257,13 +291,15 @@ void MemoryControl::enqueueMemRef (MemoryNode& memRef) {
Time arrival_time = memRef.m_time;
uint64 at = arrival_time;
bool is_mem_read = memRef.m_is_mem_read;
+ bool dirtyWB = memRef.m_is_dirty_wb;
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);
+ 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);
}
- g_system_ptr->getProfiler()->profileMemReq(bank);
+// printf ("m_name is %s \n", m_name.c_str());
+ g_system_ptr->getProfiler()->profileMemReq(m_name, bank);
m_input_queue.push_back(memRef);
if (!m_awakened) {
g_eventQueue_ptr->scheduleEvent(this, 1);
@@ -295,7 +331,7 @@ MemoryNode MemoryControl::peekNode () {
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",
+ 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;
@@ -319,10 +355,10 @@ void MemoryControl::printConfig (ostream& out) {
out << "Memory Control " << m_version << ":" << endl;
out << " Ruby cycles per memory cycle: " << m_mem_bus_cycle_multiplier << endl;
out << " Basic read latency: " << m_mem_ctl_latency << endl;
- if (m_memFixedDelay) {
- out << " Fixed Latency mode: Added cycles = " << m_memFixedDelay << endl;
+ if (m_mem_fixed_delay) {
+ out << " Fixed Latency mode: Added cycles = " << m_mem_fixed_delay << endl;
} else {
- out << " Bank busy time: " << BANK_BUSY_TIME << " memory cycles" << endl;
+ 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;
@@ -336,7 +372,7 @@ void MemoryControl::printConfig (ostream& out) {
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_memRandomArbitrate << endl;
+ out << " Arbitration randomness: " << m_mem_random_arbitrate << endl;
}
@@ -389,20 +425,20 @@ int MemoryControl::getRank (int bank) {
// can be issued this cycle
bool MemoryControl::queueReady (int bank) {
- if ((m_bankBusyCounter[bank] > 0) && !m_memFixedDelay) {
- g_system_ptr->getProfiler()->profileMemBankBusy();
- //if (m_debug) cprintf(" bank %x busy %d\n", bank, m_bankBusyCounter[bank]);
+ if ((m_bankBusyCounter[bank] > 0) && !m_mem_fixed_delay) {
+ g_system_ptr->getProfiler()->profileMemBankBusy(m_name);
+ //if (m_debug) printf(" bank %x busy %d\n", bank, m_bankBusyCounter[bank]);
return false;
}
- if (m_memRandomArbitrate >= 2) {
- if ((random() % 100) < m_memRandomArbitrate) {
- g_system_ptr->getProfiler()->profileMemRandBusy();
+ if (m_mem_random_arbitrate >= 2) {
+ if ((random() % 100) < m_mem_random_arbitrate) {
+ g_system_ptr->getProfiler()->profileMemRandBusy(m_name);
return false;
}
}
- if (m_memFixedDelay) return true;
+ if (m_mem_fixed_delay) return true;
if ((m_ageCounter > (2 * m_bank_busy_time)) && !m_oldRequest[bank]) {
- g_system_ptr->getProfiler()->profileMemNotOld();
+ g_system_ptr->getProfiler()->profileMemNotOld(m_name);
return false;
}
if (m_busBusyCounter_Basic == m_basic_bus_busy_time) {
@@ -411,26 +447,26 @@ bool MemoryControl::queueReady (int bank) {
// 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.
- g_system_ptr->getProfiler()->profileMemArbWait(1);
+ g_system_ptr->getProfiler()->profileMemArbWait(m_name, 1);
return false;
}
if (m_busBusyCounter_Basic > 0) {
- g_system_ptr->getProfiler()->profileMemBusBusy();
+ g_system_ptr->getProfiler()->profileMemBusBusy(m_name);
return false;
}
int rank = getRank(bank);
if (m_tfaw_count[rank] >= ACTIVATE_PER_TFAW) {
- g_system_ptr->getProfiler()->profileMemTfawBusy();
+ g_system_ptr->getProfiler()->profileMemTfawBusy(m_name);
return false;
}
bool write = !m_bankQueues[bank].front().m_is_mem_read;
if (write && (m_busBusyCounter_Write > 0)) {
- g_system_ptr->getProfiler()->profileMemReadWriteBusy();
+ g_system_ptr->getProfiler()->profileMemReadWriteBusy(m_name);
return false;
}
if (!write && (rank != m_busBusy_WhichRank)
&& (m_busBusyCounter_ReadNewRank > 0)) {
- g_system_ptr->getProfiler()->profileMemDataBusBusy();
+ g_system_ptr->getProfiler()->profileMemDataBusBusy(m_name);
return false;
}
return true;
@@ -453,9 +489,9 @@ bool MemoryControl::issueRefresh (int bank) {
//if (m_debug) {
//uint64 current_time = g_eventQueue_ptr->getTime();
- //cprintf(" Refresh bank %3x at %d\n", bank, current_time);
+ //printf(" Refresh bank %3x at %lld\n", bank, current_time);
//}
- g_system_ptr->getProfiler()->profileMemRefresh();
+ g_system_ptr->getProfiler()->profileMemRefresh(m_name);
m_need_refresh--;
m_refresh_bank++;
if (m_refresh_bank >= m_total_banks) m_refresh_bank = 0;
@@ -488,23 +524,23 @@ void MemoryControl::issueRequest (int bank) {
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",
+ 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_memFixedDelay);
+ 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) {
- g_system_ptr->getProfiler()->profileMemRead();
+ g_system_ptr->getProfiler()->profileMemRead(m_name);
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 {
- g_system_ptr->getProfiler()->profileMemWrite();
+ g_system_ptr->getProfiler()->profileMemWrite(m_name);
m_busBusyCounter_Basic = m_basic_bus_busy_time;
m_busBusyCounter_Write = m_basic_bus_busy_time;
m_busBusyCounter_ReadNewRank = m_basic_bus_busy_time;
@@ -531,8 +567,8 @@ void MemoryControl::executeCycle () {
}
// After time period expires, latch an indication that we need a refresh.
- // Disable refresh if in memFixedDelay mode.
- if (!m_memFixedDelay) m_refresh_count--;
+ // 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?
@@ -553,7 +589,7 @@ void MemoryControl::executeCycle () {
}
// If randomness desired, re-randomize round-robin position each cycle
- if (m_memRandomArbitrate) {
+ if (m_mem_random_arbitrate) {
m_roundRobin = random() % m_total_banks;
}
@@ -562,7 +598,7 @@ void MemoryControl::executeCycle () {
// 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 memFixedDelay mode, we can issue
+ // how many are waiting. If in mem_fixed_delay mode, we can issue
// more than one request per cycle.
int queueHeads = 0;
@@ -573,7 +609,7 @@ void MemoryControl::executeCycle () {
issueRefresh(m_roundRobin);
int qs = m_bankQueues[m_roundRobin].size();
if (qs > 1) {
- g_system_ptr->getProfiler()->profileMemBankQ(qs-1);
+ g_system_ptr->getProfiler()->profileMemBankQ(m_name, qs-1);
}
if (qs > 0) {
m_idleCount = IDLECOUNT_MAX_VALUE; // we're not idle if anything is queued
@@ -581,15 +617,15 @@ void MemoryControl::executeCycle () {
if (queueReady(m_roundRobin)) {
issueRequest(m_roundRobin);
banksIssued++;
- if (m_memFixedDelay) {
- g_system_ptr->getProfiler()->profileMemWaitCycles(m_memFixedDelay);
+ if (m_mem_fixed_delay) {
+ g_system_ptr->getProfiler()->profileMemWaitCycles(m_name, m_mem_fixed_delay);
}
}
}
}
// memWaitCycles is a redundant catch-all for the specific counters in queueReady
- g_system_ptr->getProfiler()->profileMemWaitCycles(queueHeads - banksIssued);
+ g_system_ptr->getProfiler()->profileMemWaitCycles(m_name, 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
@@ -606,7 +642,7 @@ void MemoryControl::executeCycle () {
m_input_queue.pop_front();
m_bankQueues[bank].push_back(req);
}
- g_system_ptr->getProfiler()->profileMemInputQ(m_input_queue.size());
+ g_system_ptr->getProfiler()->profileMemInputQ(m_name, m_input_queue.size());
}
}
diff --git a/src/mem/ruby/system/MemoryControl.hh b/src/mem/ruby/system/MemoryControl.hh
index aef2edc5b..3419f8c40 100644
--- a/src/mem/ruby/system/MemoryControl.hh
+++ b/src/mem/ruby/system/MemoryControl.hh
@@ -43,7 +43,6 @@
#include "mem/gems_common/Map.hh"
#include "mem/ruby/common/Address.hh"
#include "mem/ruby/profiler/Profiler.hh"
-#include "mem/ruby/slicc_interface/AbstractChip.hh"
#include "mem/ruby/system/System.hh"
#include "mem/ruby/slicc_interface/Message.hh"
#include "mem/gems_common/util.hh"
@@ -67,7 +66,8 @@ class MemoryControl : public Consumer, public AbstractMemOrCache {
public:
// Constructors
- MemoryControl (AbstractChip* chip_ptr, int version);
+ MemoryControl(const string & name);
+ void init(const vector<string> & argv);
// Destructor
~MemoryControl ();
@@ -78,8 +78,8 @@ public:
void setConsumer (Consumer* consumer_ptr);
Consumer* getConsumer () { return m_consumer_ptr; };
- void setDescription (const string& name) { m_name = name; };
- string getDescription () { return m_name; };
+ void setDescription (const string& name) { m_description = name; };
+ string getDescription () { return m_description; };
// Called from the directory:
void enqueue (const MsgPtr& message, int latency );
@@ -97,6 +97,12 @@ public:
void print (ostream& out) const;
void setDebug (int debugFlag);
+
+ //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);
@@ -113,9 +119,9 @@ private:
MemoryControl& operator=(const MemoryControl& obj);
// data members
- AbstractChip* m_chip_ptr;
Consumer* m_consumer_ptr; // Consumer to signal a wakeup()
string m_name;
+ string m_description;
int m_version;
int m_msg_counter;
int m_awakened;
@@ -134,9 +140,9 @@ private:
int m_basic_bus_busy_time;
int m_mem_ctl_latency;
int m_refresh_period;
- int m_memRandomArbitrate;
+ int m_mem_random_arbitrate;
int m_tFaw;
- int m_memFixedDelay;
+ int m_mem_fixed_delay;
int m_total_banks;
int m_total_ranks;
diff --git a/src/mem/ruby/system/MemoryVector.hh b/src/mem/ruby/system/MemoryVector.hh
new file mode 100644
index 000000000..c5f3cea7f
--- /dev/null
+++ b/src/mem/ruby/system/MemoryVector.hh
@@ -0,0 +1,81 @@
+
+#ifndef MEMORYVECTOR_H
+#define MEMORYVECTOR_H
+
+#include "mem/ruby/common/Address.hh"
+
+class DirectoryMemory;
+
+/**
+ * MemoryVector holds memory data (DRAM only)
+ */
+class MemoryVector {
+ public:
+ MemoryVector();
+ MemoryVector(uint32 size);
+ ~MemoryVector();
+ friend class DirectoryMemory;
+
+ void setSize(uint32 size); // destructive
+
+ void write(const Address & paddr, uint8* data, int len);
+ uint8* read(const Address & paddr, uint8* data, int len);
+
+ private:
+ uint8* getBlockPtr(const Address & paddr);
+
+ uint32 m_size;
+ uint8* m_vec;
+};
+
+inline
+MemoryVector::MemoryVector()
+{
+ m_size = 0;
+ m_vec = NULL;
+}
+
+inline
+MemoryVector::MemoryVector(uint32 size)
+{
+ m_size = size;
+ m_vec = new uint8[size];
+}
+
+inline
+MemoryVector::~MemoryVector()
+{
+ delete [] m_vec;
+}
+
+inline
+void MemoryVector::setSize(uint32 size)
+{
+ m_size = size;
+ if (m_vec != NULL)
+ delete [] m_vec;
+ m_vec = new uint8[size];
+}
+
+inline
+void MemoryVector::write(const Address & paddr, uint8* data, int len)
+{
+ assert(paddr.getAddress() + len <= m_size);
+ memcpy(m_vec + paddr.getAddress(), data, len);
+}
+
+inline
+uint8* MemoryVector::read(const Address & paddr, uint8* data, int len)
+{
+ assert(paddr.getAddress() + len <= m_size);
+ memcpy(data, m_vec + paddr.getAddress(), len);
+ return data;
+}
+
+inline
+uint8* MemoryVector::getBlockPtr(const Address & paddr)
+{
+ return m_vec + paddr.getAddress();
+}
+
+#endif // MEMORYVECTOR_H
diff --git a/src/mem/ruby/system/NodePersistentTable.cc b/src/mem/ruby/system/NodePersistentTable.cc
deleted file mode 100644
index 4dd5c670f..000000000
--- a/src/mem/ruby/system/NodePersistentTable.cc
+++ /dev/null
@@ -1,193 +0,0 @@
-
-/*
- * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/*
- * $Id: NodePersistentTable.C 1.3 04/08/16 14:12:33-05:00 beckmann@c2-143.cs.wisc.edu $
- *
- */
-
-#include "mem/ruby/system/NodePersistentTable.hh"
-#include "mem/ruby/common/Set.hh"
-#include "mem/gems_common/Map.hh"
-#include "mem/ruby/common/Address.hh"
-#include "mem/ruby/slicc_interface/AbstractChip.hh"
-#include "mem/gems_common/util.hh"
-
-// randomize so that handoffs are not locality-aware
-// int persistent_randomize[] = {0, 4, 8, 12, 1, 5, 9, 13, 2, 6, 10, 14, 3, 7, 11, 15};
-int persistent_randomize[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15};
-
-
-class NodePersistentTableEntry {
-public:
- Set m_starving;
- Set m_marked;
- Set m_request_to_write;
-};
-
-NodePersistentTable::NodePersistentTable(AbstractChip* chip_ptr, int version)
-{
- m_chip_ptr = chip_ptr;
- m_map_ptr = new Map<Address, NodePersistentTableEntry>;
- m_version = version;
-}
-
-NodePersistentTable::~NodePersistentTable()
-{
- delete m_map_ptr;
- m_map_ptr = NULL;
- m_chip_ptr = NULL;
-}
-
-void NodePersistentTable::persistentRequestLock(const Address& address, NodeID llocker, AccessType type)
-{
-
- // if (locker == m_chip_ptr->getID() )
- // cout << "Chip " << m_chip_ptr->getID() << ": " << llocker << " requesting lock for " << address << endl;
-
- NodeID locker = (NodeID) persistent_randomize[llocker];
-
- assert(address == line_address(address));
- if (!m_map_ptr->exist(address)) {
- // Allocate if not present
- NodePersistentTableEntry entry;
- entry.m_starving.add(locker);
- if (type == AccessType_Write) {
- entry.m_request_to_write.add(locker);
- }
- m_map_ptr->add(address, entry);
- } else {
- NodePersistentTableEntry& entry = m_map_ptr->lookup(address);
- assert(!(entry.m_starving.isElement(locker))); // Make sure we're not already in the locked set
-
- entry.m_starving.add(locker);
- if (type == AccessType_Write) {
- entry.m_request_to_write.add(locker);
- }
- assert(entry.m_marked.isSubset(entry.m_starving));
- }
-}
-
-void NodePersistentTable::persistentRequestUnlock(const Address& address, NodeID uunlocker)
-{
- // if (unlocker == m_chip_ptr->getID() )
- // cout << "Chip " << m_chip_ptr->getID() << ": " << uunlocker << " requesting unlock for " << address << endl;
-
- NodeID unlocker = (NodeID) persistent_randomize[uunlocker];
-
- assert(address == line_address(address));
- assert(m_map_ptr->exist(address));
- NodePersistentTableEntry& entry = m_map_ptr->lookup(address);
- assert(entry.m_starving.isElement(unlocker)); // Make sure we're in the locked set
- assert(entry.m_marked.isSubset(entry.m_starving));
- entry.m_starving.remove(unlocker);
- entry.m_marked.remove(unlocker);
- entry.m_request_to_write.remove(unlocker);
- assert(entry.m_marked.isSubset(entry.m_starving));
-
- // Deallocate if empty
- if (entry.m_starving.isEmpty()) {
- assert(entry.m_marked.isEmpty());
- m_map_ptr->erase(address);
- }
-}
-
-bool NodePersistentTable::okToIssueStarving(const Address& address) const
-{
- assert(address == line_address(address));
- if (!m_map_ptr->exist(address)) {
- return true; // No entry present
- } else if (m_map_ptr->lookup(address).m_starving.isElement(m_chip_ptr->getID())) {
- return false; // We can't issue another lockdown until are previous unlock has occurred
- } else {
- return (m_map_ptr->lookup(address).m_marked.isEmpty());
- }
-}
-
-NodeID NodePersistentTable::findSmallest(const Address& address) const
-{
- assert(address == line_address(address));
- assert(m_map_ptr->exist(address));
- const NodePersistentTableEntry& entry = m_map_ptr->lookup(address);
- // cout << "Node " << m_chip_ptr->getID() << " returning " << persistent_randomize[entry.m_starving.smallestElement()] << " for findSmallest(" << address << ")" << endl;
- return (NodeID) persistent_randomize[entry.m_starving.smallestElement()];
-}
-
-AccessType NodePersistentTable::typeOfSmallest(const Address& address) const
-{
- assert(address == line_address(address));
- assert(m_map_ptr->exist(address));
- const NodePersistentTableEntry& 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 NodePersistentTable::markEntries(const Address& address)
-{
- assert(address == line_address(address));
- if (m_map_ptr->exist(address)) {
- NodePersistentTableEntry& entry = m_map_ptr->lookup(address);
- assert(entry.m_marked.isEmpty()); // None should be marked
- entry.m_marked = entry.m_starving; // Mark all the nodes currently in the table
- }
-}
-
-bool NodePersistentTable::isLocked(const Address& address) const
-{
- assert(address == line_address(address));
- // If an entry is present, it must be locked
- return (m_map_ptr->exist(address));
-}
-
-int NodePersistentTable::countStarvingForAddress(const Address& address) const
-{
- if (m_map_ptr->exist(address)) {
- NodePersistentTableEntry& entry = m_map_ptr->lookup(address);
- return (entry.m_starving.count());
- }
- else {
- return 0;
- }
-}
-
-int NodePersistentTable::countReadStarvingForAddress(const Address& address) const
-{
- if (m_map_ptr->exist(address)) {
- NodePersistentTableEntry& entry = m_map_ptr->lookup(address);
- return (entry.m_starving.count() - entry.m_request_to_write.count());
- }
- else {
- return 0;
- }
-}
-
-
diff --git a/src/mem/ruby/system/NodePersistentTable.hh b/src/mem/ruby/system/NodePersistentTable.hh
deleted file mode 100644
index d731b25ae..000000000
--- a/src/mem/ruby/system/NodePersistentTable.hh
+++ /dev/null
@@ -1,99 +0,0 @@
-
-/*
- * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/*
- * $Id: NodePersistentTable.hh 1.3 04/08/16 14:12:33-05:00 beckmann@c2-143.cs.wisc.edu $
- *
- * Description:
- *
- */
-
-#ifndef NodePersistentTable_H
-#define NodePersistentTable_H
-
-#include "mem/ruby/common/Global.hh"
-#include "mem/ruby/system/NodeID.hh"
-#include "mem/protocol/AccessType.hh"
-
-class AbstractChip;
-
-template <class KEY_TYPE, class VALUE_TYPE> class Map;
-class Address;
-class NodePersistentTableEntry;
-
-class NodePersistentTable {
-public:
- // Constructors
- NodePersistentTable(AbstractChip* chip_ptr, int version);
-
- // Destructor
- ~NodePersistentTable();
-
- // Public Methods
- void persistentRequestLock(const Address& address, NodeID locker, AccessType type);
- void persistentRequestUnlock(const Address& address, NodeID unlocker);
- bool okToIssueStarving(const Address& address) const;
- NodeID findSmallest(const Address& address) const;
- AccessType typeOfSmallest(const Address& address) const;
- void markEntries(const Address& address);
- bool isLocked(const Address& addr) const;
- int countStarvingForAddress(const Address& addr) const;
- int countReadStarvingForAddress(const Address& addr) const;
-
- static void printConfig(ostream& out) {}
-
- void print(ostream& out) const;
-private:
- // Private Methods
-
- // Private copy constructor and assignment operator
- NodePersistentTable(const NodePersistentTable& obj);
- NodePersistentTable& operator=(const NodePersistentTable& obj);
-
- // Data Members (m_prefix)
- Map<Address, NodePersistentTableEntry>* m_map_ptr;
- AbstractChip* m_chip_ptr;
- int m_version;
-};
-
-// Output operator declaration
-ostream& operator<<(ostream& out, const NodePersistentTable& obj);
-
-// ******************* Definitions *******************
-
-// Output operator definition
-extern inline
-ostream& operator<<(ostream& out, const NodePersistentTable& obj)
-{
- obj.print(out);
- out << flush;
- return out;
-}
-
-#endif //NodePersistentTable_H
diff --git a/src/mem/ruby/system/PersistentArbiter.cc b/src/mem/ruby/system/PersistentArbiter.cc
deleted file mode 100644
index b44393301..000000000
--- a/src/mem/ruby/system/PersistentArbiter.cc
+++ /dev/null
@@ -1,165 +0,0 @@
-
-/*
- * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "mem/ruby/system/PersistentArbiter.hh"
-#include "mem/ruby/common/Address.hh"
-#include "mem/ruby/slicc_interface/AbstractChip.hh"
-#include "mem/gems_common/util.hh"
-
-PersistentArbiter::PersistentArbiter(AbstractChip* chip_ptr)
-{
- m_chip_ptr = chip_ptr;
-
- // wastes entries, but who cares
- m_entries.setSize(RubyConfig::numberOfProcessors());
-
- for (int i = 0; i < m_entries.size(); i++) {
- m_entries[i].valid = false;
- }
-
- m_busy = false;
- m_locker = -1;
-
-}
-
-PersistentArbiter::~PersistentArbiter()
-{
- m_chip_ptr = NULL;
-}
-
-
-void PersistentArbiter::addLocker(NodeID id, Address addr, AccessType type) {
- //cout << "Arbiter " << getArbiterId() << " adding locker " << id << " " << addr << endl;
- assert(m_entries[id].valid == false);
- m_entries[id].valid = true;
- m_entries[id].address = addr;
- m_entries[id].type = type;
- m_entries[id].localId = id;
-
-}
-
-void PersistentArbiter::removeLocker(NodeID id) {
- //cout << "Arbiter " << getArbiterId() << " removing locker " << id << " " << m_entries[id].address << endl;
- assert(m_entries[id].valid == true);
- m_entries[id].valid = false;
-
- if (!lockersExist()) {
- m_busy = false;
- }
-}
-
-bool PersistentArbiter::successorRequestPresent(Address addr, NodeID id) {
- for (int i = (id + 1); i < m_entries.size(); i++) {
- if (m_entries[i].address == addr && m_entries[i].valid) {
- //cout << "m_entries[" << id << ", address " << m_entries[id].address << " is equal to " << addr << endl;
- return true;
- }
- }
- return false;
-}
-
-bool PersistentArbiter::lockersExist() {
- for (int i = 0; i < m_entries.size(); i++) {
- if (m_entries[i].valid == true) {
- return true;
- }
- }
- //cout << "no lockers found" << endl;
- return false;
-}
-
-void PersistentArbiter::advanceActiveLock() {
- assert(lockersExist());
-
- //cout << "arbiter advancing lock from " << m_locker;
- m_busy = false;
-
- if (m_locker < (m_entries.size() - 1)) {
- for (int i = (m_locker+1); i < m_entries.size(); i++) {
- if (m_entries[i].valid == true) {
- m_locker = i;
- m_busy = true;
- //cout << " to " << m_locker << endl;
- return;
- }
- }
- }
-
- if (!m_busy) {
- for (int i = 0; i < m_entries.size(); i++) {
- if (m_entries[i].valid == true) {
- m_locker = i;
- m_busy = true;
- //cout << " to " << m_locker << endl;
- return;
- }
- }
-
- assert(m_busy)
- }
-}
-
-Address PersistentArbiter::getActiveLockAddress() {
- assert( m_entries[m_locker].valid = true );
- return m_entries[m_locker].address;
-}
-
-
-NodeID PersistentArbiter::getArbiterId() {
- return m_chip_ptr->getID()*RubyConfig::numberOfProcsPerChip();
-}
-
-bool PersistentArbiter::isBusy() {
- return m_busy;
-}
-
-NodeID PersistentArbiter::getActiveLocalId() {
- assert( m_entries[m_locker].valid = true );
- return m_entries[m_locker].localId;
-}
-
-void PersistentArbiter::setIssuedAddress(Address addr) {
- m_issued_address = addr;
-}
-
-bool PersistentArbiter::isIssuedAddress(Address addr) {
- return (m_issued_address == addr);
-}
-
-void PersistentArbiter::print(ostream& out) const {
-
- out << "[";
- for (int i = 0; i < m_entries.size(); i++) {
- if (m_entries[i].valid == true) {
- out << "( " << m_entries[i].localId << ", " << m_entries[i].address << ") ";
- }
- }
- out << "]" << endl;
-
-}
diff --git a/src/mem/ruby/system/PersistentArbiter.hh b/src/mem/ruby/system/PersistentArbiter.hh
deleted file mode 100644
index 1ce05f51f..000000000
--- a/src/mem/ruby/system/PersistentArbiter.hh
+++ /dev/null
@@ -1,107 +0,0 @@
-
-/*
- * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/*
- * PersistentArbiter.hh
- *
- * Description:
- *
- * Used for hierarchical distributed persistent request scheme
- *
- */
-
-#ifndef PERSISTENTARBITER_H
-#define PERSISTENTARBITER_H
-
-#include "mem/ruby/common/Global.hh"
-#include "mem/gems_common/Vector.hh"
-#include "mem/ruby/slicc_interface/AbstractChip.hh"
-#include "mem/protocol/AccessPermission.hh"
-#include "mem/protocol/AccessType.hh"
-#include "mem/ruby/config/RubyConfig.hh"
-#include "mem/ruby/common/Address.hh"
-
-struct ArbiterEntry {
- bool valid;
- Address address;
- AccessType type;
- NodeID localId;
-};
-
-class PersistentArbiter {
-public:
-
- // Constructors
- PersistentArbiter(AbstractChip* chip_ptr);
-
- // Destructor
- ~PersistentArbiter();
-
- // Public Methods
-
- void addLocker(NodeID id, Address addr, AccessType type);
- void removeLocker(NodeID id);
- bool successorRequestPresent(Address addr, NodeID id);
- bool lockersExist();
- void advanceActiveLock();
- Address getActiveLockAddress();
- NodeID getArbiterId();
- bool isBusy();
-
- void setIssuedAddress(Address addr);
- bool isIssuedAddress(Address addr);
-
-
- Address getIssuedAddress() { return m_issued_address; }
-
- static void printConfig(ostream& out) {}
- void print(ostream& out) const;
-
- NodeID getActiveLocalId();
-
-private:
-
- Address m_issued_address;
- AbstractChip* m_chip_ptr;
- int m_locker;
- bool m_busy;
- Vector<ArbiterEntry> m_entries;
-};
-
-// Output operator definition
-extern inline
-ostream& operator<<(ostream& out, const PersistentArbiter& obj)
-{
- obj.print(out);
- out << flush;
- return out;
-}
-
-
-#endif //PERFECTCACHEMEMORY_H
diff --git a/src/mem/ruby/system/PersistentTable.cc b/src/mem/ruby/system/PersistentTable.cc
deleted file mode 100644
index 7f07251ce..000000000
--- a/src/mem/ruby/system/PersistentTable.cc
+++ /dev/null
@@ -1,194 +0,0 @@
-
-/*
- * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/*
- * $Id$
- *
- */
-
-#include "mem/ruby/system/PersistentTable.hh"
-#include "mem/ruby/common/NetDest.hh"
-#include "mem/gems_common/Map.hh"
-#include "mem/ruby/common/Address.hh"
-#include "mem/ruby/slicc_interface/AbstractChip.hh"
-#include "mem/gems_common/util.hh"
-
-// randomize so that handoffs are not locality-aware
-// int persistent_randomize[] = {0, 4, 8, 12, 1, 5, 9, 13, 2, 6, 10, 14, 3, 7, 11, 15};
-// int persistent_randomize[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15};
-
-
-class PersistentTableEntry {
-public:
- NetDest m_starving;
- NetDest m_marked;
- NetDest m_request_to_write;
-};
-
-PersistentTable::PersistentTable(AbstractChip* chip_ptr, int version)
-{
- m_chip_ptr = chip_ptr;
- m_map_ptr = new Map<Address, PersistentTableEntry>;
- m_version = version;
-}
-
-PersistentTable::~PersistentTable()
-{
- delete m_map_ptr;
- m_map_ptr = NULL;
- m_chip_ptr = NULL;
-}
-
-void PersistentTable::persistentRequestLock(const Address& address, MachineID locker, AccessType type)
-{
-
- // if (locker == m_chip_ptr->getID() )
- // cout << "Chip " << m_chip_ptr->getID() << ": " << llocker << " requesting lock for " << address << endl;
-
- // MachineID locker = (MachineID) persistent_randomize[llocker];
-
- assert(address == line_address(address));
- if (!m_map_ptr->exist(address)) {
- // Allocate if not present
- PersistentTableEntry entry;
- entry.m_starving.add(locker);
- if (type == AccessType_Write) {
- entry.m_request_to_write.add(locker);
- }
- m_map_ptr->add(address, entry);
- } else {
- PersistentTableEntry& entry = m_map_ptr->lookup(address);
- assert(!(entry.m_starving.isElement(locker))); // Make sure we're not already in the locked set
-
- entry.m_starving.add(locker);
- if (type == AccessType_Write) {
- entry.m_request_to_write.add(locker);
- }
- assert(entry.m_marked.isSubset(entry.m_starving));
- }
-}
-
-void PersistentTable::persistentRequestUnlock(const Address& address, MachineID unlocker)
-{
- // if (unlocker == m_chip_ptr->getID() )
- // cout << "Chip " << m_chip_ptr->getID() << ": " << uunlocker << " requesting unlock for " << address << endl;
-
- // MachineID unlocker = (MachineID) persistent_randomize[uunlocker];
-
- assert(address == line_address(address));
- assert(m_map_ptr->exist(address));
- PersistentTableEntry& entry = m_map_ptr->lookup(address);
- assert(entry.m_starving.isElement(unlocker)); // Make sure we're in the locked set
- assert(entry.m_marked.isSubset(entry.m_starving));
- entry.m_starving.remove(unlocker);
- entry.m_marked.remove(unlocker);
- entry.m_request_to_write.remove(unlocker);
- assert(entry.m_marked.isSubset(entry.m_starving));
-
- // Deallocate if empty
- if (entry.m_starving.isEmpty()) {
- assert(entry.m_marked.isEmpty());
- m_map_ptr->erase(address);
- }
-}
-
-bool PersistentTable::okToIssueStarving(const Address& address) const
-{
- assert(address == line_address(address));
- if (!m_map_ptr->exist(address)) {
- return true; // No entry present
- } else if (m_map_ptr->lookup(address).m_starving.isElement( (MachineID) {MachineType_L1Cache, m_version})) {
- return false; // We can't issue another lockdown until are previous unlock has occurred
- } else {
- return (m_map_ptr->lookup(address).m_marked.isEmpty());
- }
-}
-
-MachineID PersistentTable::findSmallest(const Address& address) const
-{
- assert(address == line_address(address));
- assert(m_map_ptr->exist(address));
- const PersistentTableEntry& entry = m_map_ptr->lookup(address);
- // cout << "Node " << m_chip_ptr->getID() << " returning " << persistent_randomize[entry.m_starving.smallestElement()] << " for findSmallest(" << address << ")" << endl;
- // return (MachineID) persistent_randomize[entry.m_starving.smallestElement()];
- return (MachineID) { MachineType_L1Cache, entry.m_starving.smallestElement() };
-}
-
-AccessType PersistentTable::typeOfSmallest(const Address& address) const
-{
- assert(address == line_address(address));
- assert(m_map_ptr->exist(address));
- const PersistentTableEntry& entry = m_map_ptr->lookup(address);
- if (entry.m_request_to_write.isElement((MachineID) {MachineType_L1Cache, entry.m_starving.smallestElement()})) {
- return AccessType_Write;
- } else {
- return AccessType_Read;
- }
-}
-
-void PersistentTable::markEntries(const Address& address)
-{
- assert(address == line_address(address));
- if (m_map_ptr->exist(address)) {
- PersistentTableEntry& entry = m_map_ptr->lookup(address);
- assert(entry.m_marked.isEmpty()); // None should be marked
- entry.m_marked = entry.m_starving; // Mark all the nodes currently in the table
- }
-}
-
-bool PersistentTable::isLocked(const Address& address) const
-{
- assert(address == line_address(address));
- // If an entry is present, it must be locked
- return (m_map_ptr->exist(address));
-}
-
-int PersistentTable::countStarvingForAddress(const Address& address) const
-{
- if (m_map_ptr->exist(address)) {
- PersistentTableEntry& entry = m_map_ptr->lookup(address);
- return (entry.m_starving.count());
- }
- else {
- return 0;
- }
-}
-
-int PersistentTable::countReadStarvingForAddress(const Address& address) const
-{
- if (m_map_ptr->exist(address)) {
- PersistentTableEntry& entry = m_map_ptr->lookup(address);
- return (entry.m_starving.count() - entry.m_request_to_write.count());
- }
- else {
- return 0;
- }
-}
-
-
diff --git a/src/mem/ruby/system/PersistentTable.hh b/src/mem/ruby/system/PersistentTable.hh
deleted file mode 100644
index 9f2e38fd7..000000000
--- a/src/mem/ruby/system/PersistentTable.hh
+++ /dev/null
@@ -1,99 +0,0 @@
-
-/*
- * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/*
- * $Id$
- *
- * Description:
- *
- */
-
-#ifndef PersistentTable_H
-#define PersistentTable_H
-
-#include "mem/ruby/common/Global.hh"
-#include "mem/ruby/system/MachineID.hh"
-#include "mem/protocol/AccessType.hh"
-
-class AbstractChip;
-
-template <class KEY_TYPE, class VALUE_TYPE> class Map;
-class Address;
-class PersistentTableEntry;
-
-class PersistentTable {
-public:
- // Constructors
- PersistentTable(AbstractChip* chip_ptr, int version);
-
- // Destructor
- ~PersistentTable();
-
- // Public Methods
- void persistentRequestLock(const Address& address, MachineID locker, AccessType type);
- void persistentRequestUnlock(const Address& address, MachineID unlocker);
- bool okToIssueStarving(const Address& address) const;
- MachineID findSmallest(const Address& address) const;
- AccessType typeOfSmallest(const Address& address) const;
- void markEntries(const Address& address);
- bool isLocked(const Address& addr) const;
- int countStarvingForAddress(const Address& addr) const;
- int countReadStarvingForAddress(const Address& addr) const;
-
- static void printConfig(ostream& out) {}
-
- void print(ostream& out) const;
-private:
- // Private Methods
-
- // Private copy constructor and assignment operator
- PersistentTable(const PersistentTable& obj);
- PersistentTable& operator=(const PersistentTable& obj);
-
- // Data Members (m_prefix)
- Map<Address, PersistentTableEntry>* m_map_ptr;
- AbstractChip* m_chip_ptr;
- int m_version;
-};
-
-// Output operator declaration
-ostream& operator<<(ostream& out, const PersistentTable& obj);
-
-// ******************* Definitions *******************
-
-// Output operator definition
-extern inline
-ostream& operator<<(ostream& out, const PersistentTable& obj)
-{
- obj.print(out);
- out << flush;
- return out;
-}
-
-#endif //PersistentTable_H
diff --git a/src/mem/ruby/system/ProcessorInterface.hh b/src/mem/ruby/system/ProcessorInterface.hh
new file mode 100644
index 000000000..d76e29f65
--- /dev/null
+++ b/src/mem/ruby/system/ProcessorInterface.hh
@@ -0,0 +1,45 @@
+
+struct ProcessorRequest {
+ vector<CacheRequest*> cache_requests;
+};
+
+class ProcessorInterface {
+
+public:
+
+ void read_atomic(const Address & paddr, void* data, int len) {
+ assert(paddr.getLineAddress() + RubyConfig::dataBlockBytes() >= paddr + len);
+ // for now, atomics can't span two blocks. Maybe fix this later
+ }
+
+ void read(const Address & paddr, const Address & rip, AccessModeType atype, void* data, const int len) {
+
+ // create the CacheRequests
+ ProcessorRequest* this_request = new ProcessorRequest;
+ Address split_addr = paddr;
+ int len_remaining = len;
+ while (split_addr.getAddress() < paddr.getAddress() + len) {
+ int split_len = (split_addr.getAddress() + len_remaining <= split_addr.getLineAddress() + RubyConfig::dataBlockBytes()) ?
+ len_remaining :
+ RubyConfig::dataBlockBytes() - split_addr.getOffset();
+ CacheRequest creq = new CacheRequest( line_address(split_addr),
+ split_addr,
+ CacheRequestType_LD,
+ rip,
+ atype,
+ split_len,
+ PretchBit_No,
+ laddr,
+ 0); // SMT thread id);
+ this_request->cache_requests.push_back(creq);
+ split_addr += split_len;
+ len_remaining -= split_len;
+ }
+ outstanding_requests.push_back(this_request);
+
+ }
+
+private:
+ vector<ProcessorRequest*> outstanding_requests;
+ Sequencer* m_sequencer;
+};
diff --git a/src/mem/ruby/system/RubyPort.cc b/src/mem/ruby/system/RubyPort.cc
new file mode 100644
index 000000000..2a5c5f479
--- /dev/null
+++ b/src/mem/ruby/system/RubyPort.cc
@@ -0,0 +1,5 @@
+
+#include "mem/ruby/system/RubyPort.hh"
+
+//void (*RubyPort::m_hit_callback)(int64_t) = NULL;
+uint16_t RubyPort::m_num_ports = 0;
diff --git a/src/mem/ruby/system/RubyPort.hh b/src/mem/ruby/system/RubyPort.hh
new file mode 100644
index 000000000..2f391070f
--- /dev/null
+++ b/src/mem/ruby/system/RubyPort.hh
@@ -0,0 +1,60 @@
+#ifndef RUBYPORT_H
+#define RUBYPORT_H
+
+#include "mem/ruby/libruby.hh"
+#include <string>
+#include <assert.h>
+
+using namespace std;
+
+class RubyPort {
+public:
+ RubyPort(const string & name)
+ : m_name(name)
+ {
+ m_port_id = m_num_ports++;
+ m_request_cnt = 0;
+ m_hit_callback = NULL;
+ assert(m_num_ports <= 2048); // see below for reason
+ }
+ virtual ~RubyPort() {}
+
+ virtual int64_t makeRequest(const RubyRequest & request) = 0;
+
+ void registerHitCallback(void (*hit_callback)(int64_t request_id)) {
+ assert(m_hit_callback == NULL); // can't assign hit_callback twice
+ m_hit_callback = hit_callback;
+ }
+
+protected:
+ const string m_name;
+ void (*m_hit_callback)(int64_t);
+
+ int64_t makeUniqueRequestID() {
+ // The request ID is generated by combining the port ID with a request count
+ // so that request IDs can be formed concurrently by multiple threads.
+ // IDs are formed as follows:
+ //
+ //
+ // 0 PortID Request Count
+ // +----+---------------+-----------------------------------------------------+
+ // | 63 | 62-48 | 47-0 |
+ // +----+---------------+-----------------------------------------------------+
+ //
+ //
+ // This limits the system to a maximum of 2^11 == 2048 components
+ // and 2^48 ~= 3x10^14 requests per component
+
+ int64_t id = (static_cast<uint64_t>(m_port_id) << 48) | m_request_cnt;
+ m_request_cnt++;
+ // assert((m_request_cnt & (1<<48)) == 0);
+ return id;
+ }
+
+private:
+ static uint16_t m_num_ports;
+ uint16_t m_port_id;
+ uint64_t m_request_cnt;
+};
+
+#endif
diff --git a/src/mem/ruby/system/Sequencer.cc b/src/mem/ruby/system/Sequencer.cc
index 82eef2901..ff5ce1506 100644
--- a/src/mem/ruby/system/Sequencer.cc
+++ b/src/mem/ruby/system/Sequencer.cc
@@ -27,909 +27,424 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-/*
- * $Id: Sequencer.C 1.131 2006/11/06 17:41:01-06:00 bobba@gratiano.cs.wisc.edu $
- *
- */
-
#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 "mem/ruby/config/RubyConfig.hh"
-//#include "mem/ruby/recorder/Tracer.hh"
-#include "mem/ruby/slicc_interface/AbstractChip.hh"
-#include "mem/protocol/Chip.hh"
-#include "mem/ruby/tester/Tester.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/packet.hh"
+#include "mem/ruby/buffers/MessageBuffer.hh"
+#include "mem/ruby/slicc_interface/AbstractController.hh"
-Sequencer::Sequencer(AbstractChip* chip_ptr, int version) {
- m_chip_ptr = chip_ptr;
- m_version = version;
+//Sequencer::Sequencer(int core_id, MessageBuffer* mandatory_q)
+Sequencer::Sequencer(const string & name)
+ :RubyPort(name)
+{
+}
+
+void Sequencer::init(const vector<string> & argv)
+{
m_deadlock_check_scheduled = false;
m_outstanding_count = 0;
- int smt_threads = RubyConfig::numberofSMTThreads();
- m_writeRequestTable_ptr = new Map<Address, CacheMsg>*[smt_threads];
- m_readRequestTable_ptr = new Map<Address, CacheMsg>*[smt_threads];
-
- m_packetTable_ptr = new Map<Address, Packet*>;
-
- for(int p=0; p < smt_threads; ++p){
- m_writeRequestTable_ptr[p] = new Map<Address, CacheMsg>;
- m_readRequestTable_ptr[p] = new Map<Address, CacheMsg>;
+ m_max_outstanding_requests = 0;
+ m_deadlock_threshold = 0;
+ m_version = -1;
+ m_instCache_ptr = NULL;
+ m_dataCache_ptr = NULL;
+ m_controller = NULL;
+ for (size_t i=0; i<argv.size(); i+=2) {
+ if ( argv[i] == "controller") {
+ m_controller = RubySystem::getController(argv[i+1]); // args[i] = "L1Cache"
+ m_mandatory_q_ptr = m_controller->getMandatoryQueue();
+ } else if ( argv[i] == "icache")
+ m_instCache_ptr = RubySystem::getCache(argv[i+1]);
+ else if ( argv[i] == "dcache")
+ m_dataCache_ptr = RubySystem::getCache(argv[i+1]);
+ else if ( argv[i] == "version")
+ m_version = atoi(argv[i+1].c_str());
+ else if ( argv[i] == "max_outstanding_requests")
+ m_max_outstanding_requests = atoi(argv[i+1].c_str());
+ else if ( argv[i] == "deadlock_threshold")
+ m_deadlock_threshold = atoi(argv[i+1].c_str());
+ else {
+ cerr << "WARNING: Sequencer: Unkown configuration parameter: " << argv[i] << endl;
+ assert(false);
+ }
}
-
+ assert(m_max_outstanding_requests > 0);
+ assert(m_deadlock_threshold > 0);
+ assert(m_version > -1);
+ assert(m_instCache_ptr != NULL);
+ assert(m_dataCache_ptr != NULL);
+ assert(m_controller != NULL);
}
Sequencer::~Sequencer() {
- int smt_threads = RubyConfig::numberofSMTThreads();
- for(int i=0; i < smt_threads; ++i){
- if(m_writeRequestTable_ptr[i]){
- delete m_writeRequestTable_ptr[i];
- }
- if(m_readRequestTable_ptr[i]){
- delete m_readRequestTable_ptr[i];
- }
- }
- if(m_writeRequestTable_ptr){
- delete [] m_writeRequestTable_ptr;
- }
- if(m_readRequestTable_ptr){
- delete [] m_readRequestTable_ptr;
- }
+
}
void Sequencer::wakeup() {
// Check for deadlock of any of the requests
Time current_time = g_eventQueue_ptr->getTime();
- bool deadlock = false;
// Check across all outstanding requests
- int smt_threads = RubyConfig::numberofSMTThreads();
int total_outstanding = 0;
- for(int p=0; p < smt_threads; ++p){
- Vector<Address> keys = m_readRequestTable_ptr[p]->keys();
- for (int i=0; i<keys.size(); i++) {
- CacheMsg& request = m_readRequestTable_ptr[p]->lookup(keys[i]);
- if (current_time - request.getTime() >= g_DEADLOCK_THRESHOLD) {
- WARN_MSG("Possible Deadlock detected");
- WARN_EXPR(request);
- WARN_EXPR(m_chip_ptr->getID());
- WARN_EXPR(m_version);
- WARN_EXPR(keys.size());
- WARN_EXPR(current_time);
- WARN_EXPR(request.getTime());
- WARN_EXPR(current_time - request.getTime());
- WARN_EXPR(*m_readRequestTable_ptr[p]);
- ERROR_MSG("Aborting");
- deadlock = true;
- }
- }
- keys = m_writeRequestTable_ptr[p]->keys();
- for (int i=0; i<keys.size(); i++) {
- CacheMsg& request = m_writeRequestTable_ptr[p]->lookup(keys[i]);
- if (current_time - request.getTime() >= g_DEADLOCK_THRESHOLD) {
- WARN_MSG("Possible Deadlock detected");
- WARN_EXPR(request);
- WARN_EXPR(m_chip_ptr->getID());
- WARN_EXPR(m_version);
- WARN_EXPR(current_time);
- WARN_EXPR(request.getTime());
- WARN_EXPR(current_time - request.getTime());
- WARN_EXPR(keys.size());
- WARN_EXPR(*m_writeRequestTable_ptr[p]);
- ERROR_MSG("Aborting");
- deadlock = true;
- }
- }
- total_outstanding += m_writeRequestTable_ptr[p]->size() + m_readRequestTable_ptr[p]->size();
- } // across all request tables
+ 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(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");
+ }
+ }
+ total_outstanding += m_writeRequestTable.size() + m_readRequestTable.size();
+
assert(m_outstanding_count == total_outstanding);
if (m_outstanding_count > 0) { // If there are still outstanding requests, keep checking
- g_eventQueue_ptr->scheduleEvent(this, g_DEADLOCK_THRESHOLD);
+ g_eventQueue_ptr->scheduleEvent(this, m_deadlock_threshold);
} else {
m_deadlock_check_scheduled = false;
}
}
-//returns the total number of requests
-int Sequencer::getNumberOutstanding(){
- return m_outstanding_count;
-}
-
-// returns the total number of demand requests
-int Sequencer::getNumberOutstandingDemand(){
- int smt_threads = RubyConfig::numberofSMTThreads();
- int total_demand = 0;
- for(int p=0; p < smt_threads; ++p){
- Vector<Address> keys = m_readRequestTable_ptr[p]->keys();
- for (int i=0; i< keys.size(); i++) {
- CacheMsg& request = m_readRequestTable_ptr[p]->lookup(keys[i]);
- if(request.getPrefetch() == PrefetchBit_No){
- total_demand++;
- }
- }
-
- keys = m_writeRequestTable_ptr[p]->keys();
- for (int i=0; i< keys.size(); i++) {
- CacheMsg& request = m_writeRequestTable_ptr[p]->lookup(keys[i]);
- if(request.getPrefetch() == PrefetchBit_No){
- total_demand++;
- }
- }
- }
-
- return total_demand;
-}
-
-int Sequencer::getNumberOutstandingPrefetch(){
- int smt_threads = RubyConfig::numberofSMTThreads();
- int total_prefetch = 0;
- for(int p=0; p < smt_threads; ++p){
- Vector<Address> keys = m_readRequestTable_ptr[p]->keys();
- for (int i=0; i< keys.size(); i++) {
- CacheMsg& request = m_readRequestTable_ptr[p]->lookup(keys[i]);
- if(request.getPrefetch() == PrefetchBit_Yes){
- total_prefetch++;
- }
- }
-
- keys = m_writeRequestTable_ptr[p]->keys();
- for (int i=0; i< keys.size(); i++) {
- CacheMsg& request = m_writeRequestTable_ptr[p]->lookup(keys[i]);
- if(request.getPrefetch() == PrefetchBit_Yes){
- total_prefetch++;
- }
- }
- }
-
- return total_prefetch;
-}
-
-bool Sequencer::isPrefetchRequest(const Address & lineaddr){
- int smt_threads = RubyConfig::numberofSMTThreads();
- for(int p=0; p < smt_threads; ++p){
- // check load requests
- Vector<Address> keys = m_readRequestTable_ptr[p]->keys();
- for (int i=0; i< keys.size(); i++) {
- CacheMsg& request = m_readRequestTable_ptr[p]->lookup(keys[i]);
- if(line_address(request.getAddress()) == lineaddr){
- if(request.getPrefetch() == PrefetchBit_Yes){
- return true;
- }
- else{
- return false;
- }
- }
- }
-
- // check store requests
- keys = m_writeRequestTable_ptr[p]->keys();
- for (int i=0; i< keys.size(); i++) {
- CacheMsg& request = m_writeRequestTable_ptr[p]->lookup(keys[i]);
- if(line_address(request.getAddress()) == lineaddr){
- if(request.getPrefetch() == PrefetchBit_Yes){
- return true;
- }
- else{
- return false;
- }
- }
- }
- }
- // we should've found a matching request
- cout << "isRequestPrefetch() ERROR request NOT FOUND : " << lineaddr << endl;
- printProgress(cout);
- assert(0);
-}
-
-AccessModeType Sequencer::getAccessModeOfRequest(Address addr, int thread){
- if(m_readRequestTable_ptr[thread]->exist(line_address(addr))){
- CacheMsg& request = m_readRequestTable_ptr[thread]->lookup(addr);
- return request.getAccessMode();
- } else if(m_writeRequestTable_ptr[thread]->exist(line_address(addr))){
- CacheMsg& request = m_writeRequestTable_ptr[thread]->lookup(addr);
- return request.getAccessMode();
- } else {
- printProgress(cout);
- ERROR_MSG("Request not found in RequestTables");
- }
-}
-
-Address Sequencer::getLogicalAddressOfRequest(Address addr, int thread){
- assert(thread >= 0);
- if(m_readRequestTable_ptr[thread]->exist(line_address(addr))){
- CacheMsg& request = m_readRequestTable_ptr[thread]->lookup(addr);
- return request.getLogicalAddress();
- } else if(m_writeRequestTable_ptr[thread]->exist(line_address(addr))){
- CacheMsg& request = m_writeRequestTable_ptr[thread]->lookup(addr);
- return request.getLogicalAddress();
- } else {
- printProgress(cout);
- WARN_MSG("Request not found in RequestTables");
- WARN_MSG(addr);
- WARN_MSG(thread);
- ASSERT(0);
- }
-}
-
-// returns the ThreadID of the request
-int Sequencer::getRequestThreadID(const Address & addr){
- int smt_threads = RubyConfig::numberofSMTThreads();
- int thread = -1;
- int num_found = 0;
- for(int p=0; p < smt_threads; ++p){
- if(m_readRequestTable_ptr[p]->exist(addr)){
- num_found++;
- thread = p;
- }
- if(m_writeRequestTable_ptr[p]->exist(addr)){
- num_found++;
- thread = p;
- }
- }
- if(num_found != 1){
- cout << "getRequestThreadID ERROR too many matching requests addr = " << addr << endl;
- printProgress(cout);
- }
- ASSERT(num_found == 1);
- ASSERT(thread != -1);
-
- return thread;
-}
-
-// given a line address, return the request's physical address
-Address Sequencer::getRequestPhysicalAddress(const Address & lineaddr){
- int smt_threads = RubyConfig::numberofSMTThreads();
- Address physaddr;
- int num_found = 0;
- for(int p=0; p < smt_threads; ++p){
- if(m_readRequestTable_ptr[p]->exist(lineaddr)){
- num_found++;
- physaddr = (m_readRequestTable_ptr[p]->lookup(lineaddr)).getAddress();
- }
- if(m_writeRequestTable_ptr[p]->exist(lineaddr)){
- num_found++;
- physaddr = (m_writeRequestTable_ptr[p]->lookup(lineaddr)).getAddress();
- }
- }
- if(num_found != 1){
- cout << "getRequestPhysicalAddress ERROR too many matching requests addr = " << lineaddr << endl;
- printProgress(cout);
- }
- ASSERT(num_found == 1);
-
- return physaddr;
-}
-
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;
- int smt_threads = RubyConfig::numberofSMTThreads();
- for(int p=0; p < smt_threads; ++p){
- Vector<Address> rkeys = m_readRequestTable_ptr[p]->keys();
- int read_size = rkeys.size();
- out << "proc " << m_chip_ptr->getID() << " thread " << p << " Read Requests = " << read_size << endl;
- // print the request table
- for(int i=0; i < read_size; ++i){
- CacheMsg & request = m_readRequestTable_ptr[p]->lookup(rkeys[i]);
- out << "\tRequest[ " << i << " ] = " << request.getType() << " Address " << rkeys[i] << " Posted " << request.getTime() << " PF " << request.getPrefetch() << endl;
- if( request.getPrefetch() == PrefetchBit_No ){
- total_demand++;
- }
- }
-
- Vector<Address> wkeys = m_writeRequestTable_ptr[p]->keys();
- int write_size = wkeys.size();
- out << "proc " << m_chip_ptr->getID() << " thread " << p << " Write Requests = " << write_size << endl;
- // print the request table
- for(int i=0; i < write_size; ++i){
- CacheMsg & request = m_writeRequestTable_ptr[p]->lookup(wkeys[i]);
+ 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 ){
total_demand++;
}
- }
-
- out << endl;
}
+
+ out << endl;
+
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;
-
+ */
}
-void Sequencer::printConfig(ostream& out) {
- if (TSO) {
- out << "sequencer: Sequencer - TSO" << endl;
- } else {
- out << "sequencer: Sequencer - SC" << endl;
- }
- out << " max_outstanding_requests: " << g_SEQUENCER_OUTSTANDING_REQUESTS << endl;
-}
-
-bool Sequencer::empty() const {
- return m_outstanding_count == 0;
+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;
}
// Insert the request on the correct request table. Return true if
// the entry was already present.
-bool Sequencer::insertRequest(const CacheMsg& request) {
- int thread = request.getThreadID();
- assert(thread >= 0);
- int total_outstanding = 0;
- int smt_threads = RubyConfig::numberofSMTThreads();
- for(int p=0; p < smt_threads; ++p){
- total_outstanding += m_writeRequestTable_ptr[p]->size() + m_readRequestTable_ptr[p]->size();
- }
+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 (m_deadlock_check_scheduled == false) {
- g_eventQueue_ptr->scheduleEvent(this, g_DEADLOCK_THRESHOLD);
+ g_eventQueue_ptr->scheduleEvent(this, m_deadlock_threshold);
m_deadlock_check_scheduled = true;
}
- if ((request.getType() == CacheRequestType_ST) ||
- (request.getType() == CacheRequestType_ATOMIC)) {
- if (m_writeRequestTable_ptr[thread]->exist(line_address(request.getAddress()))) {
- m_writeRequestTable_ptr[thread]->lookup(line_address(request.getAddress())) = request;
- return true;
+ Address line_addr(request->ruby_request.paddr);
+ line_addr.makeLineAddress();
+ if ((request->ruby_request.type == RubyRequestType_ST) ||
+ (request->ruby_request.type == RubyRequestType_RMW)) {
+ 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?
}
- m_writeRequestTable_ptr[thread]->allocate(line_address(request.getAddress()));
- m_writeRequestTable_ptr[thread]->lookup(line_address(request.getAddress())) = request;
+ m_writeRequestTable.allocate(line_addr);
+ m_writeRequestTable.lookup(line_addr) = request;
m_outstanding_count++;
} else {
- if (m_readRequestTable_ptr[thread]->exist(line_address(request.getAddress()))) {
- m_readRequestTable_ptr[thread]->lookup(line_address(request.getAddress())) = request;
- return true;
+ 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?
}
- m_readRequestTable_ptr[thread]->allocate(line_address(request.getAddress()));
- m_readRequestTable_ptr[thread]->lookup(line_address(request.getAddress())) = request;
+ m_readRequestTable.allocate(line_addr);
+ m_readRequestTable.lookup(line_addr) = request;
m_outstanding_count++;
}
g_system_ptr->getProfiler()->sequencerRequests(m_outstanding_count);
- total_outstanding = 0;
- for(int p=0; p < smt_threads; ++p){
- total_outstanding += m_writeRequestTable_ptr[p]->size() + m_readRequestTable_ptr[p]->size();
- }
-
+ total_outstanding = m_writeRequestTable.size() + m_readRequestTable.size();
assert(m_outstanding_count == total_outstanding);
+
return false;
}
-void Sequencer::removeRequest(const CacheMsg& request) {
- int thread = request.getThreadID();
- assert(thread >= 0);
- int total_outstanding = 0;
- int smt_threads = RubyConfig::numberofSMTThreads();
- for(int p=0; p < smt_threads; ++p){
- total_outstanding += m_writeRequestTable_ptr[p]->size() + m_readRequestTable_ptr[p]->size();
- }
- assert(m_outstanding_count == total_outstanding);
+void Sequencer::removeRequest(SequencerRequest* srequest) {
+
+ assert(m_outstanding_count == m_writeRequestTable.size() + m_readRequestTable.size());
- if ((request.getType() == CacheRequestType_ST) ||
- (request.getType() == CacheRequestType_ATOMIC)) {
- m_writeRequestTable_ptr[thread]->deallocate(line_address(request.getAddress()));
+ 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)) {
+ m_writeRequestTable.deallocate(line_addr);
} else {
- m_readRequestTable_ptr[thread]->deallocate(line_address(request.getAddress()));
+ m_readRequestTable.deallocate(line_addr);
}
m_outstanding_count--;
- total_outstanding = 0;
- for(int p=0; p < smt_threads; ++p){
- total_outstanding += m_writeRequestTable_ptr[p]->size() + m_readRequestTable_ptr[p]->size();
- }
- assert(m_outstanding_count == total_outstanding);
-}
-
-void Sequencer::writeCallback(const Address& address) {
- DataBlock data;
- writeCallback(address, data);
+ assert(m_outstanding_count == m_writeRequestTable.size() + m_readRequestTable.size());
}
void Sequencer::writeCallback(const Address& address, DataBlock& data) {
- // process oldest thread first
- int thread = -1;
- Time oldest_time = 0;
- int smt_threads = RubyConfig::numberofSMTThreads();
- for(int t=0; t < smt_threads; ++t){
- if(m_writeRequestTable_ptr[t]->exist(address)){
- CacheMsg & request = m_writeRequestTable_ptr[t]->lookup(address);
- if(thread == -1 || (request.getTime() < oldest_time) ){
- thread = t;
- oldest_time = request.getTime();
- }
- }
- }
- // make sure we found an oldest thread
- ASSERT(thread != -1);
-
- CacheMsg & request = m_writeRequestTable_ptr[thread]->lookup(address);
-
- writeCallback(address, data, GenericMachineType_NULL, PrefetchBit_No, thread);
-}
-
-void Sequencer::writeCallback(const Address& address, DataBlock& data, GenericMachineType respondingMach, PrefetchBit pf, int thread) {
assert(address == line_address(address));
- assert(thread >= 0);
- assert(m_writeRequestTable_ptr[thread]->exist(line_address(address)));
+ assert(m_writeRequestTable.exist(line_address(address)));
- writeCallback(address, data, respondingMach, thread);
-
-}
-
-void Sequencer::writeCallback(const Address& address, DataBlock& data, GenericMachineType respondingMach, int thread) {
- assert(address == line_address(address));
- assert(m_writeRequestTable_ptr[thread]->exist(line_address(address)));
- CacheMsg request = m_writeRequestTable_ptr[thread]->lookup(address);
- assert( request.getThreadID() == thread);
+ SequencerRequest* request = m_writeRequestTable.lookup(address);
removeRequest(request);
- assert((request.getType() == CacheRequestType_ST) ||
- (request.getType() == CacheRequestType_ATOMIC));
-
- hitCallback(request, data, respondingMach, thread);
+ assert((request->ruby_request.type == RubyRequestType_ST) ||
+ (request->ruby_request.type == RubyRequestType_RMW));
-}
-
-void Sequencer::readCallback(const Address& address) {
- DataBlock data;
- readCallback(address, data);
+ hitCallback(request, data);
}
void Sequencer::readCallback(const Address& address, DataBlock& data) {
- // process oldest thread first
- int thread = -1;
- Time oldest_time = 0;
- int smt_threads = RubyConfig::numberofSMTThreads();
- for(int t=0; t < smt_threads; ++t){
- if(m_readRequestTable_ptr[t]->exist(address)){
- CacheMsg & request = m_readRequestTable_ptr[t]->lookup(address);
- if(thread == -1 || (request.getTime() < oldest_time) ){
- thread = t;
- oldest_time = request.getTime();
- }
- }
- }
- // make sure we found an oldest thread
- ASSERT(thread != -1);
-
- CacheMsg & request = m_readRequestTable_ptr[thread]->lookup(address);
-
- readCallback(address, data, GenericMachineType_NULL, PrefetchBit_No, thread);
-}
-
-void Sequencer::readCallback(const Address& address, DataBlock& data, GenericMachineType respondingMach, PrefetchBit pf, int thread) {
assert(address == line_address(address));
- assert(m_readRequestTable_ptr[thread]->exist(line_address(address)));
+ assert(m_readRequestTable.exist(line_address(address)));
- readCallback(address, data, respondingMach, thread);
-}
-
-void Sequencer::readCallback(const Address& address, DataBlock& data, GenericMachineType respondingMach, int thread) {
- assert(address == line_address(address));
- assert(m_readRequestTable_ptr[thread]->exist(line_address(address)));
-
- CacheMsg request = m_readRequestTable_ptr[thread]->lookup(address);
- assert( request.getThreadID() == thread );
+ SequencerRequest* request = m_readRequestTable.lookup(address);
removeRequest(request);
- assert((request.getType() == CacheRequestType_LD) ||
- (request.getType() == CacheRequestType_IFETCH)
- );
+ assert((request->ruby_request.type == RubyRequestType_LD) ||
+ (request->ruby_request.type == RubyRequestType_IFETCH));
- hitCallback(request, data, respondingMach, thread);
+ hitCallback(request, data);
}
-void Sequencer::hitCallback(const CacheMsg& request, DataBlock& data, GenericMachineType respondingMach, int thread) {
- int size = request.getSize();
- Address request_address = request.getAddress();
- Address request_logical_address = request.getLogicalAddress();
- Address request_line_address = line_address(request_address);
- CacheRequestType type = request.getType();
- int threadID = request.getThreadID();
- Time issued_time = request.getTime();
- int logical_proc_no = ((m_chip_ptr->getID() * RubyConfig::numberOfProcsPerChip()) + m_version) * RubyConfig::numberofSMTThreads() + threadID;
-
- DEBUG_MSG(SEQUENCER_COMP, MedPrio, size);
+void Sequencer::hitCallback(SequencerRequest* srequest, DataBlock& data) {
+ const RubyRequest & ruby_request = srequest->ruby_request;
+ int size = ruby_request.len;
+ 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 == CacheRequestType_IFETCH) {
- if (Protocol::m_TwoLevelCache) {
- if (m_chip_ptr->m_L1Cache_L1IcacheMemory_vec[m_version]->isTagPresent(request_line_address)) {
- m_chip_ptr->m_L1Cache_L1IcacheMemory_vec[m_version]->setMRU(request_line_address);
- }
- }
- else {
- if (m_chip_ptr->m_L1Cache_cacheMemory_vec[m_version]->isTagPresent(request_line_address)) {
- m_chip_ptr->m_L1Cache_cacheMemory_vec[m_version]->setMRU(request_line_address);
- }
- }
+ if (type == RubyRequestType_IFETCH) {
+ if (m_instCache_ptr->isTagPresent(request_line_address) )
+ m_instCache_ptr->setMRU(request_line_address);
} else {
- if (Protocol::m_TwoLevelCache) {
- if (m_chip_ptr->m_L1Cache_L1DcacheMemory_vec[m_version]->isTagPresent(request_line_address)) {
- m_chip_ptr->m_L1Cache_L1DcacheMemory_vec[m_version]->setMRU(request_line_address);
- }
- }
- else {
- if (m_chip_ptr->m_L1Cache_cacheMemory_vec[m_version]->isTagPresent(request_line_address)) {
- m_chip_ptr->m_L1Cache_cacheMemory_vec[m_version]->setMRU(request_line_address);
- }
- }
+ 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 (PROTOCOL_DEBUG_TRACE) {
- g_system_ptr->getProfiler()->profileTransition("Seq", (m_chip_ptr->getID()*RubyConfig::numberOfProcsPerChip()+m_version), -1, request.getAddress(), "", "Done", "",
- int_to_string(miss_latency)+" cycles "+GenericMachineType_to_string(respondingMach)+" "+CacheRequestType_to_string(request.getType())+" "+PrefetchBit_to_string(request.getPrefetch()));
- }
-
- DEBUG_MSG(SEQUENCER_COMP, MedPrio, request_address);
- DEBUG_MSG(SEQUENCER_COMP, MedPrio, request.getPrefetch());
- if (request.getPrefetch() == PrefetchBit_Yes) {
- DEBUG_MSG(SEQUENCER_COMP, MedPrio, "return");
- g_system_ptr->getProfiler()->swPrefetchLatency(miss_latency, type, respondingMach);
- return; // Ignore the software prefetch, don't callback the driver
- }
-
// Profile the miss latency for all non-zero demand misses
if (miss_latency != 0) {
- g_system_ptr->getProfiler()->missLatency(miss_latency, type, respondingMach);
-
- }
-
- bool write =
- (type == CacheRequestType_ST) ||
- (type == CacheRequestType_ATOMIC);
+ g_system_ptr->getProfiler()->missLatency(miss_latency, type);
- if (TSO && write) {
- m_chip_ptr->m_L1Cache_storeBuffer_vec[m_version]->callBack(line_address(request.getAddress()), data,
- m_packetTable_ptr->lookup(request.getAddress()));
- } else {
-
- // Copy the correct bytes out of the cache line into the subblock
- SubBlock subblock(request_address, request_logical_address, size);
- subblock.mergeFrom(data); // copy the correct bytes from DataBlock in the SubBlock
-
- // Scan the store buffer to see if there are any outstanding stores we need to collect
- if (TSO) {
- m_chip_ptr->m_L1Cache_storeBuffer_vec[m_version]->updateSubBlock(subblock);
+ if (Debug::getProtocolTrace()) {
+ g_system_ptr->getProfiler()->profileTransition("Seq", m_version, Address(ruby_request.paddr),
+ "", "Done", "", int_to_string(miss_latency)+" cycles");
}
+ }
+ /*
+ if (request.getPrefetch() == PrefetchBit_Yes) {
+ return; // Ignore the prefetch
+ }
+ */
- // Call into the Driver and let it read and/or modify the sub-block
- Packet* pkt = m_packetTable_ptr->lookup(request.getAddress());
-
- // update data if this is a store/atomic
-
- /*
- if (pkt->req->isCondSwap()) {
- L1Cache_Entry entry = m_L1Cache_vec[m_version]->lookup(Address(pkt->req->physAddr()));
- DataBlk datablk = entry->getDataBlk();
- uint8_t *orig_data = datablk.getArray();
- if ( datablk.equal(pkt->req->getExtraData()) )
- datablk->setArray(pkt->getData());
- pkt->setData(orig_data);
- }
- */
-
- g_system_ptr->getDriver()->hitCallback(pkt);
- m_packetTable_ptr->remove(request.getAddress());
-
- // If the request was a Store or Atomic, apply the changes in the SubBlock to the DataBlock
- // (This is only triggered for the non-TSO case)
- if (write) {
- assert(!TSO);
- subblock.mergeTo(data); // copy the correct bytes from SubBlock into the DataBlock
+ // update the data
+ if (ruby_request.data != NULL) {
+ if ((type == RubyRequestType_LD) ||
+ (type == RubyRequestType_IFETCH)) {
+ 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);
}
}
-}
-void Sequencer::printDebug(){
- //notify driver of debug
- g_system_ptr->getDriver()->printDebug();
+ m_hit_callback(srequest->id);
+ delete srequest;
}
-//dsm: breaks build, delayed
// Returns true if the sequencer already has a load or store outstanding
-bool
-Sequencer::isReady(const Packet* pkt) const
-{
-
- int cpu_number = pkt->req->contextId();
- la_t logical_addr = pkt->req->getVaddr();
- pa_t physical_addr = pkt->req->getPaddr();
- CacheRequestType type_of_request;
- if ( pkt->req->isInstFetch() ) {
- type_of_request = CacheRequestType_IFETCH;
- } else if ( pkt->req->isLocked() || pkt->req->isSwap() ) {
- type_of_request = CacheRequestType_ATOMIC;
- } else if ( pkt->isRead() ) {
- type_of_request = CacheRequestType_LD;
- } else if ( pkt->isWrite() ) {
- type_of_request = CacheRequestType_ST;
- } else {
- assert(false);
+bool Sequencer::isReady(const RubyRequest& request) const {
+ // POLINA: check if we are currently flushing the write buffer, if so Ruby is returned as not ready
+ // to simulate stalling of the front-end
+ // Do we stall all the sequencers? If it is atomic instruction - yes!
+ if (m_outstanding_count >= m_max_outstanding_requests) {
+ return false;
}
- int thread = pkt->req->threadId();
-
- CacheMsg request(Address( physical_addr ),
- Address( physical_addr ),
- type_of_request,
- Address(0),
- AccessModeType_UserMode, // User/supervisor mode
- 0, // Size in bytes of request
- PrefetchBit_No, // Not a prefetch
- 0, // Version number
- Address(logical_addr), // Virtual Address
- thread // SMT thread
- );
- return isReady(request);
-}
-bool
-Sequencer::isReady(const CacheMsg& request) const
-{
- if (m_outstanding_count >= g_SEQUENCER_OUTSTANDING_REQUESTS) {
- //cout << "TOO MANY OUTSTANDING: " << m_outstanding_count << " " << g_SEQUENCER_OUTSTANDING_REQUESTS << " VER " << m_version << endl;
+ if( m_writeRequestTable.exist(line_address(Address(request.paddr))) ||
+ m_readRequestTable.exist(line_address(Address(request.paddr))) ){
+ //cout << "OUTSTANDING REQUEST EXISTS " << p << " VER " << m_version << endl;
//printProgress(cout);
return false;
}
- // This code allows reads to be performed even when we have a write
- // request outstanding for the line
- bool write =
- (request.getType() == CacheRequestType_ST) ||
- (request.getType() == CacheRequestType_ATOMIC);
-
- // LUKE - disallow more than one request type per address
- // INVARIANT: at most one request type per address, per processor
- int smt_threads = RubyConfig::numberofSMTThreads();
- for(int p=0; p < smt_threads; ++p){
- if( m_writeRequestTable_ptr[p]->exist(line_address(request.getAddress())) ||
- m_readRequestTable_ptr[p]->exist(line_address(request.getAddress())) ){
- //cout << "OUTSTANDING REQUEST EXISTS " << p << " VER " << m_version << endl;
- //printProgress(cout);
- return false;
- }
- }
-
- if (TSO) {
- return m_chip_ptr->m_L1Cache_storeBuffer_vec[m_version]->isReady();
- }
return true;
}
-//dsm: breaks build, delayed
-// Called by Driver (Simics or Tester).
-void
-Sequencer::makeRequest(Packet* pkt)
-{
- int cpu_number = pkt->req->contextId();
- la_t logical_addr = pkt->req->getVaddr();
- pa_t physical_addr = pkt->req->getPaddr();
- int request_size = pkt->getSize();
- CacheRequestType type_of_request;
- PrefetchBit prefetch;
- bool write = false;
- if ( pkt->req->isInstFetch() ) {
- type_of_request = CacheRequestType_IFETCH;
- } else if ( pkt->req->isLocked() || pkt->req->isSwap() ) {
- type_of_request = CacheRequestType_ATOMIC;
- write = true;
- } else if ( pkt->isRead() ) {
- type_of_request = CacheRequestType_LD;
- } else if ( pkt->isWrite() ) {
- type_of_request = CacheRequestType_ST;
- write = true;
- } else {
- assert(false);
- }
- if (pkt->req->isPrefetch()) {
- prefetch = PrefetchBit_Yes;
- } else {
- prefetch = PrefetchBit_No;
- }
- la_t virtual_pc = pkt->req->getPC();
- int isPriv = false; // TODO: get permission data
- int thread = pkt->req->threadId();
-
- AccessModeType access_mode = AccessModeType_UserMode; // TODO: get actual permission
-
- CacheMsg request(Address( physical_addr ),
- Address( physical_addr ),
- type_of_request,
- Address(virtual_pc),
- access_mode, // User/supervisor mode
- request_size, // Size in bytes of request
- prefetch,
- 0, // Version number
- Address(logical_addr), // Virtual Address
- thread // SMT thread
- );
-
- if ( TSO && write && !pkt->req->isPrefetch() ) {
- assert(m_chip_ptr->m_L1Cache_storeBuffer_vec[m_version]->isReady());
- m_chip_ptr->m_L1Cache_storeBuffer_vec[m_version]->insertStore(pkt, request);
- return;
- }
-
- m_packetTable_ptr->insert(Address( physical_addr ), pkt);
-
- doRequest(request);
-}
-
-bool Sequencer::doRequest(const CacheMsg& request) {
- bool hit = false;
- // Check the fast path
- DataBlock* data_ptr;
-
- int thread = request.getThreadID();
-
- hit = tryCacheAccess(line_address(request.getAddress()),
- request.getType(),
- request.getProgramCounter(),
- request.getAccessMode(),
- request.getSize(),
- data_ptr);
-
- if (hit && (request.getType() == CacheRequestType_IFETCH || !REMOVE_SINGLE_CYCLE_DCACHE_FAST_PATH) ) {
- DEBUG_MSG(SEQUENCER_COMP, MedPrio, "Fast path hit");
- hitCallback(request, *data_ptr, GenericMachineType_L1Cache, thread);
- return true;
- }
-
- if (TSO && (request.getType() == CacheRequestType_LD || request.getType() == CacheRequestType_IFETCH)) {
-
- // See if we can satisfy the load entirely from the store buffer
- SubBlock subblock(line_address(request.getAddress()), request.getSize());
- if (m_chip_ptr->m_L1Cache_storeBuffer_vec[m_version]->trySubBlock(subblock)) {
- DataBlock dummy;
- hitCallback(request, dummy, GenericMachineType_NULL, thread); // Call with an 'empty' datablock, since the data is in the store buffer
- return true;
- }
- }
-
- DEBUG_MSG(SEQUENCER_COMP, MedPrio, "Fast path miss");
- issueRequest(request);
- return hit;
+bool Sequencer::empty() const {
+ return (m_writeRequestTable.size() == 0) && (m_readRequestTable.size() == 0);
}
-void Sequencer::issueRequest(const CacheMsg& request) {
- bool found = insertRequest(request);
-
- if (!found) {
- CacheMsg msg = request;
- msg.getAddress() = line_address(request.getAddress()); // Make line address
-
- // Fast Path L1 misses are profiled here - all non-fast path misses are profiled within the generated protocol code
- if (!REMOVE_SINGLE_CYCLE_DCACHE_FAST_PATH) {
- g_system_ptr->getProfiler()->addPrimaryStatSample(msg, m_chip_ptr->getID());
- }
-
- if (PROTOCOL_DEBUG_TRACE) {
- g_system_ptr->getProfiler()->profileTransition("Seq", (m_chip_ptr->getID()*RubyConfig::numberOfProcsPerChip() + m_version), -1, msg.getAddress(),"", "Begin", "", CacheRequestType_to_string(request.getType()));
- }
-
-#if 0
- // Commented out by nate binkert because I removed the trace stuff
- if (g_system_ptr->getTracer()->traceEnabled()) {
- g_system_ptr->getTracer()->traceRequest((m_chip_ptr->getID()*RubyConfig::numberOfProcsPerChip()+m_version), msg.getAddress(), msg.getProgramCounter(),
- msg.getType(), g_eventQueue_ptr->getTime());
- }
-#endif
-
- Time latency = 0; // initialzed to an null value
-
- latency = SEQUENCER_TO_CONTROLLER_LATENCY;
-
- // Send the message to the cache controller
- assert(latency > 0);
- m_chip_ptr->m_L1Cache_mandatoryQueue_vec[m_version]->enqueue(msg, latency);
-
- } // !found
+int64_t Sequencer::makeRequest(const RubyRequest & request)
+{
+ assert(Address(request.paddr).getOffset() + request.len <= RubySystem::getBlockSizeBytes());
+ if (isReady(request)) {
+ int64_t id = makeUniqueRequestID();
+ SequencerRequest *srequest = new SequencerRequest(request, id, g_eventQueue_ptr->getTime());
+ bool found = insertRequest(srequest);
+ if (!found)
+ issueRequest(request);
+
+ // TODO: issue hardware prefetches here
+ return id;
+ }
+ else {
+ return -1;
+ }
+}
+
+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_RMW:
+ 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);
+
+ 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(m_name, 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);
+
+
+ m_mandatory_q_ptr->enqueue(msg, latency);
}
-
+/*
bool Sequencer::tryCacheAccess(const Address& addr, CacheRequestType type,
- const Address& pc, AccessModeType access_mode,
+ AccessModeType access_mode,
int size, DataBlock*& data_ptr) {
if (type == CacheRequestType_IFETCH) {
- if (Protocol::m_TwoLevelCache) {
- return m_chip_ptr->m_L1Cache_L1IcacheMemory_vec[m_version]->tryCacheAccess(line_address(addr), type, data_ptr);
- }
- else {
- return m_chip_ptr->m_L1Cache_cacheMemory_vec[m_version]->tryCacheAccess(line_address(addr), type, data_ptr);
- }
+ return m_instCache_ptr->tryCacheAccess(line_address(addr), type, data_ptr);
} else {
- if (Protocol::m_TwoLevelCache) {
- return m_chip_ptr->m_L1Cache_L1DcacheMemory_vec[m_version]->tryCacheAccess(line_address(addr), type, data_ptr);
- }
- else {
- return m_chip_ptr->m_L1Cache_cacheMemory_vec[m_version]->tryCacheAccess(line_address(addr), type, data_ptr);
- }
- }
-}
-
-void Sequencer::resetRequestTime(const Address& addr, int thread){
- assert(thread >= 0);
- //reset both load and store requests, if they exist
- if(m_readRequestTable_ptr[thread]->exist(line_address(addr))){
- CacheMsg& request = m_readRequestTable_ptr[thread]->lookup(addr);
- if( request.m_AccessMode != AccessModeType_UserMode){
- cout << "resetRequestType ERROR read request addr = " << addr << " thread = "<< thread << " is SUPERVISOR MODE" << endl;
- printProgress(cout);
- }
- //ASSERT(request.m_AccessMode == AccessModeType_UserMode);
- request.setTime(g_eventQueue_ptr->getTime());
+ return m_dataCache_ptr->tryCacheAccess(line_address(addr), type, data_ptr);
}
- if(m_writeRequestTable_ptr[thread]->exist(line_address(addr))){
- CacheMsg& request = m_writeRequestTable_ptr[thread]->lookup(addr);
- if( request.m_AccessMode != AccessModeType_UserMode){
- cout << "resetRequestType ERROR write request addr = " << addr << " thread = "<< thread << " is SUPERVISOR MODE" << endl;
- printProgress(cout);
- }
- //ASSERT(request.m_AccessMode == AccessModeType_UserMode);
- request.setTime(g_eventQueue_ptr->getTime());
- }
-}
-
-// removes load request from queue
-void Sequencer::removeLoadRequest(const Address & addr, int thread){
- removeRequest(getReadRequest(addr, thread));
-}
-
-void Sequencer::removeStoreRequest(const Address & addr, int thread){
- removeRequest(getWriteRequest(addr, thread));
-}
-
-// returns the read CacheMsg
-CacheMsg & Sequencer::getReadRequest( const Address & addr, int thread ){
- Address temp = addr;
- assert(thread >= 0);
- assert(temp == line_address(temp));
- assert(m_readRequestTable_ptr[thread]->exist(addr));
- return m_readRequestTable_ptr[thread]->lookup(addr);
-}
-
-CacheMsg & Sequencer::getWriteRequest( const Address & addr, int thread){
- Address temp = addr;
- assert(thread >= 0);
- assert(temp == line_address(temp));
- assert(m_writeRequestTable_ptr[thread]->exist(addr));
- return m_writeRequestTable_ptr[thread]->lookup(addr);
}
+*/
void Sequencer::print(ostream& out) const {
- out << "[Sequencer: " << m_chip_ptr->getID()
+ out << "[Sequencer: " << m_version
<< ", outstanding requests: " << m_outstanding_count;
- int smt_threads = RubyConfig::numberofSMTThreads();
- for(int p=0; p < smt_threads; ++p){
- out << ", read request table[ " << p << " ]: " << *m_readRequestTable_ptr[p]
- << ", write request table[ " << p << " ]: " << *m_writeRequestTable_ptr[p];
- }
+ out << ", read request table: " << m_readRequestTable
+ << ", write request table: " << m_writeRequestTable;
out << "]";
}
@@ -941,20 +456,183 @@ void Sequencer::checkCoherence(const Address& addr) {
#endif
}
+/*
bool Sequencer::getRubyMemoryValue(const Address& addr, char* value,
- unsigned int size_in_bytes ) {
- for(unsigned int i=0; i < size_in_bytes; i++) {
- std::cerr << __FILE__ << "(" << __LINE__ << "): Not implemented. " << std::endl;
- value[i] = 0; // _read_physical_memory( m_chip_ptr->getID()*RubyConfig::numberOfProcsPerChip()+m_version,
- // addr.getAddress() + i, 1 );
- }
- return false; // Do nothing?
+ unsigned int size_in_bytes )
+{
+ bool found = false;
+ const Address lineAddr = line_address(addr);
+ DataBlock data;
+ PhysAddress paddr(addr);
+ DataBlock* dataPtr = &data;
+
+ MachineID l2_mach = map_L2ChipId_to_L2Cache(addr, m_chip_ptr->getID() );
+ int l2_ver = l2_mach.num%RubyConfig::numberOfL2CachePerChip();
+
+ if (Protocol::m_TwoLevelCache) {
+ if(Protocol::m_CMP){
+ assert(n->m_L2Cache_L2cacheMemory_vec[l2_ver] != NULL);
+ }
+ else{
+ assert(n->m_L1Cache_cacheMemory_vec[m_version] != NULL);
+ }
+ }
+
+ if (n->m_L1Cache_L1IcacheMemory_vec[m_version]->tryCacheAccess(lineAddr, CacheRequestType_IFETCH, dataPtr)){
+ n->m_L1Cache_L1IcacheMemory_vec[m_version]->getMemoryValue(addr, value, size_in_bytes);
+ found = true;
+ } else if (n->m_L1Cache_L1DcacheMemory_vec[m_version]->tryCacheAccess(lineAddr, CacheRequestType_LD, dataPtr)){
+ n->m_L1Cache_L1DcacheMemory_vec[m_version]->getMemoryValue(addr, value, size_in_bytes);
+ found = true;
+ } else if (Protocol::m_CMP && n->m_L2Cache_L2cacheMemory_vec[l2_ver]->tryCacheAccess(lineAddr, CacheRequestType_LD, dataPtr)){
+ n->m_L2Cache_L2cacheMemory_vec[l2_ver]->getMemoryValue(addr, value, size_in_bytes);
+ found = true;
+ // } else if (n->TBE_TABLE_MEMBER_VARIABLE->isPresent(lineAddr)){
+// ASSERT(n->TBE_TABLE_MEMBER_VARIABLE->isPresent(lineAddr));
+// L1Cache_TBE tbeEntry = n->TBE_TABLE_MEMBER_VARIABLE->lookup(lineAddr);
+
+// int offset = addr.getOffset();
+// for(int i=0; i<size_in_bytes; ++i){
+// value[i] = tbeEntry.getDataBlk().getByte(offset + i);
+// }
+
+// found = true;
+ } else {
+ // Address not found
+ //cout << " " << m_chip_ptr->getID() << " NOT IN CACHE, Value at Directory is: " << (int) value[0] << endl;
+ n = dynamic_cast<Chip*>(g_system_ptr->getChip(map_Address_to_DirectoryNode(addr)/RubyConfig::numberOfDirectoryPerChip()));
+ int dir_version = map_Address_to_DirectoryNode(addr)%RubyConfig::numberOfDirectoryPerChip();
+ for(unsigned int i=0; i<size_in_bytes; ++i){
+ int offset = addr.getOffset();
+ value[i] = n->m_Directory_directory_vec[dir_version]->lookup(lineAddr).m_DataBlk.getByte(offset + i);
+ }
+ // Address not found
+ //WARN_MSG("Couldn't find address");
+ //WARN_EXPR(addr);
+ found = false;
+ }
+ return true;
}
bool Sequencer::setRubyMemoryValue(const Address& addr, char *value,
unsigned int size_in_bytes) {
char test_buffer[64];
- return false; // Do nothing?
+ // idea here is that coherent cache should find the
+ // latest data, the update it
+ bool found = false;
+ const Address lineAddr = line_address(addr);
+ PhysAddress paddr(addr);
+ DataBlock data;
+ DataBlock* dataPtr = &data;
+ Chip* n = dynamic_cast<Chip*>(m_chip_ptr);
+
+ MachineID l2_mach = map_L2ChipId_to_L2Cache(addr, m_chip_ptr->getID() );
+ int l2_ver = l2_mach.num%RubyConfig::numberOfL2CachePerChip();
+
+ assert(n->m_L1Cache_L1IcacheMemory_vec[m_version] != NULL);
+ assert(n->m_L1Cache_L1DcacheMemory_vec[m_version] != NULL);
+ if (Protocol::m_TwoLevelCache) {
+ if(Protocol::m_CMP){
+ assert(n->m_L2Cache_L2cacheMemory_vec[l2_ver] != NULL);
+ }
+ else{
+ assert(n->m_L1Cache_cacheMemory_vec[m_version] != NULL);
+ }
+ }
+
+ if (n->m_L1Cache_L1IcacheMemory_vec[m_version]->tryCacheAccess(lineAddr, CacheRequestType_IFETCH, dataPtr)){
+ n->m_L1Cache_L1IcacheMemory_vec[m_version]->setMemoryValue(addr, value, size_in_bytes);
+ found = true;
+ } else if (n->m_L1Cache_L1DcacheMemory_vec[m_version]->tryCacheAccess(lineAddr, CacheRequestType_LD, dataPtr)){
+ n->m_L1Cache_L1DcacheMemory_vec[m_version]->setMemoryValue(addr, value, size_in_bytes);
+ found = true;
+ } else if (Protocol::m_CMP && n->m_L2Cache_L2cacheMemory_vec[l2_ver]->tryCacheAccess(lineAddr, CacheRequestType_LD, dataPtr)){
+ n->m_L2Cache_L2cacheMemory_vec[l2_ver]->setMemoryValue(addr, value, size_in_bytes);
+ found = true;
+ } else {
+ // Address not found
+ n = dynamic_cast<Chip*>(g_system_ptr->getChip(map_Address_to_DirectoryNode(addr)/RubyConfig::numberOfDirectoryPerChip()));
+ int dir_version = map_Address_to_DirectoryNode(addr)%RubyConfig::numberOfDirectoryPerChip();
+ for(unsigned int i=0; i<size_in_bytes; ++i){
+ int offset = addr.getOffset();
+ n->m_Directory_directory_vec[dir_version]->lookup(lineAddr).m_DataBlk.setByte(offset + i, value[i]);
+ }
+ found = false;
+ }
+
+ if (found){
+ found = getRubyMemoryValue(addr, test_buffer, size_in_bytes);
+ assert(found);
+ if(value[0] != test_buffer[0]){
+ WARN_EXPR((int) value[0]);
+ WARN_EXPR((int) test_buffer[0]);
+ ERROR_MSG("setRubyMemoryValue failed to set value.");
+ }
+ }
+
+ return true;
+}
+*/
+/*
+
+void
+Sequencer::rubyMemAccess(const uint64 paddr, char* data, const int len, const AccessType type)
+{
+ if ( type == AccessType_Read || type == AccessType_Write ) {
+ // need to break up the packet data
+ uint64 guest_ptr = paddr;
+ Vector<DataBlock*> datablocks;
+ while (paddr + len != guest_ptr) {
+ Address addr(guest_ptr);
+ Address line_addr = line_address(addr);
+
+ int bytes_copied;
+ if (addr.getOffset() == 0) {
+ bytes_copied = (guest_ptr + RubyConfig::dataBlockBytes() > paddr + len)?
+ (paddr + len - guest_ptr):
+ RubyConfig::dataBlockBytes();
+ } else {
+ bytes_copied = RubyConfig::dataBlockBytes() - addr.getOffset();
+ if (guest_ptr + bytes_copied > paddr + len)
+ bytes_copied = paddr + len - guest_ptr;
+ }
+
+ // first we need to find all data blocks that have to be updated for a write
+ // and the highest block for a read
+ for(int i=0;i<RubyConfig::numberOfProcessors();i++) {
+ if (Protocol::m_TwoLevelCache){
+ if(m_chip_ptr->m_L1Cache_L1IcacheMemory_vec[i]->isTagPresent(line_address(addr)))
+ datablocks.insertAtBottom(&m_chip_ptr->m_L1Cache_L1IcacheMemory_vec[i]->lookup(line_addr).getDataBlk());
+ if(m_chip_ptr->m_L1Cache_L1DcacheMemory_vec[i]->isTagPresent(line_address(addr)))
+ datablocks.insertAtBottom(&m_chip_ptr->m_L1Cache_L1DcacheMemory_vec[i]->lookup(line_addr).getDataBlk());
+ } else {
+ if(m_chip_ptr->m_L1Cache_cacheMemory_vec[i]->isTagPresent(line_address(addr)))
+ datablocks.insertAtBottom(&m_chip_ptr->m_L1Cache_cacheMemory_vec[i]->lookup(line_addr).getDataBlk());
+ }
+ }
+ if (Protocol::m_TwoLevelCache){
+ int l2_bank = map_L2ChipId_to_L2Cache(addr, 0).num; // TODO: ONLY WORKS WITH CMP!!!
+ if (m_chip_ptr->m_L2Cache_L2cacheMemory_vec[l2_bank]->isTagPresent(line_address(Address(paddr)))) {
+ datablocks.insertAtBottom(&m_chip_ptr->m_L2Cache_L2cacheMemory_vec[l2_bank]->lookup(addr).getDataBlk());
+ }
+ }
+ assert(dynamic_cast<Chip*>(m_chip_ptr)->m_Directory_directory_vec.size() > map_Address_to_DirectoryNode(addr));
+ DirectoryMemory* dir = dynamic_cast<Chip*>(m_chip_ptr)->m_Directory_directory_vec[map_Address_to_DirectoryNode(addr)];
+ Directory_Entry& entry = dir->lookup(line_addr);
+ datablocks.insertAtBottom(&entry.getDataBlk());
+
+ if (pkt->isRead()){
+ datablocks[0]->copyData(pkt_data, addr.getOffset(), bytes_copied);
+ } else {// pkt->isWrite() {
+ for (int i=0;i<datablocks.size();i++)
+ datablocks[i]->setData(pkt_data, addr.getOffset(), bytes_copied);
+ }
+
+ guest_ptr += bytes_copied;
+ pkt_data += bytes_copied;
+ datablocks.clear();
+ }
}
+*/
diff --git a/src/mem/ruby/system/Sequencer.hh b/src/mem/ruby/system/Sequencer.hh
index 1ccfd97ce..254f5a092 100644
--- a/src/mem/ruby/system/Sequencer.hh
+++ b/src/mem/ruby/system/Sequencer.hh
@@ -44,19 +44,31 @@
#include "mem/protocol/AccessModeType.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"
class DataBlock;
-class AbstractChip;
class CacheMsg;
-class Address;
class MachineID;
-class Packet;
+class CacheMemory;
+class AbstractController;
-class Sequencer : public Consumer {
+struct SequencerRequest {
+ RubyRequest ruby_request;
+ int64_t id;
+ Time issue_time;
+
+ SequencerRequest(const RubyRequest & _ruby_request, int64_t _id, Time _issue_time)
+ : ruby_request(_ruby_request), id(_id), issue_time(_issue_time)
+ {}
+};
+
+class Sequencer : public Consumer, public RubyPort {
public:
// Constructors
- Sequencer(AbstractChip* chip_ptr, int version);
+ Sequencer(const string & name);
+ void init(const vector<string> & argv);
// Destructor
~Sequencer();
@@ -64,87 +76,53 @@ public:
// Public Methods
void wakeup(); // Used only for deadlock detection
- static void printConfig(ostream& out);
-
- // returns total number of outstanding request (includes prefetches)
- int getNumberOutstanding();
- // return only total number of outstanding demand requests
- int getNumberOutstandingDemand();
- // return only total number of outstanding prefetch requests
- int getNumberOutstandingPrefetch();
-
- // remove load/store request from queue
- void removeLoadRequest(const Address & addr, int thread);
- void removeStoreRequest(const Address & addr, int thread);
+ void printConfig(ostream& out) const;
void printProgress(ostream& out) const;
- // returns a pointer to the request in the request tables
- CacheMsg & getReadRequest( const Address & addr, int thread );
- CacheMsg & getWriteRequest( const Address & addr, int thread );
-
void writeCallback(const Address& address, DataBlock& data);
void readCallback(const Address& address, DataBlock& data);
- void writeCallback(const Address& address);
- void readCallback(const Address& address);
- void writeCallback(const Address& address, DataBlock& data, GenericMachineType respondingMach, PrefetchBit pf, int thread);
- void readCallback(const Address& address, DataBlock& data, GenericMachineType respondingMach, PrefetchBit pf, int thread);
- void writeCallback(const Address& address, DataBlock& data, GenericMachineType respondingMach, int thread);
- void readCallback(const Address& address, DataBlock& data, GenericMachineType respondingMach, int thread);
-
- // returns the thread ID of the request
- int getRequestThreadID(const Address & addr);
- // returns the physical address of the request
- Address getRequestPhysicalAddress(const Address & lineaddr);
- // returns whether a request is a prefetch request
- bool isPrefetchRequest(const Address & lineaddr);
-
- //notifies driver of debug print
- void printDebug();
// called by Tester or Simics
- void makeRequest(Packet* pkt);
- bool doRequest(const CacheMsg& request);
- void issueRequest(const CacheMsg& request);
- bool isReady(const Packet* pkt) const;
- bool isReady(const CacheMsg& request) const; // depricate this function
+ int64_t makeRequest(const RubyRequest & request);
+ bool isReady(const RubyRequest& request) const;
bool empty() const;
- void resetRequestTime(const Address& addr, int thread);
- Address getLogicalAddressOfRequest(Address address, int thread);
- AccessModeType getAccessModeOfRequest(Address address, int thread);
- //uint64 getSequenceNumberOfRequest(Address addr, int thread);
void print(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);
+ // 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(const CacheMsg& 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 conflictCallback(const CacheMsg& request, GenericMachineType respondingMach, int thread);
- void hitCallback(const CacheMsg& request, DataBlock& data, GenericMachineType respondingMach, int thread);
- bool insertRequest(const CacheMsg& request);
+ void issueRequest(const RubyRequest& 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);
- // Data Members (m_ prefix)
- AbstractChip* m_chip_ptr;
+private:
+ int m_max_outstanding_requests;
+ int m_deadlock_threshold;
+
+ AbstractController* m_controller;
+ MessageBuffer* m_mandatory_q_ptr;
+ CacheMemory* m_dataCache_ptr;
+ CacheMemory* m_instCache_ptr;
// indicates what processor on the chip this sequencer is associated with
int m_version;
+ int m_controller_type;
- // One request table per SMT thread
- Map<Address, CacheMsg>** m_writeRequestTable_ptr;
- Map<Address, CacheMsg>** m_readRequestTable_ptr;
-
- Map<Address, Packet*>* m_packetTable_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;
diff --git a/src/mem/ruby/system/StoreBuffer.cc b/src/mem/ruby/system/StoreBuffer.cc
deleted file mode 100644
index 280decdd8..000000000
--- a/src/mem/ruby/system/StoreBuffer.cc
+++ /dev/null
@@ -1,302 +0,0 @@
-
-/*
- * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/*
- * $Id$
- *
- */
-
-#include "mem/ruby/common/Global.hh"
-#include "mem/ruby/config/RubyConfig.hh"
-#include "mem/ruby/system/StoreBuffer.hh"
-#include "mem/ruby/slicc_interface/AbstractChip.hh"
-#include "mem/ruby/system/System.hh"
-#include "mem/ruby/common/Driver.hh"
-#include "mem/gems_common/Vector.hh"
-#include "mem/ruby/eventqueue/RubyEventQueue.hh"
-#include "mem/ruby/profiler/AddressProfiler.hh"
-#include "mem/ruby/system/Sequencer.hh"
-#include "mem/ruby/common/SubBlock.hh"
-#include "mem/ruby/profiler/Profiler.hh"
-#include "mem/packet.hh"
-
-// *** Begin Helper class ***
-struct StoreBufferEntry {
- StoreBufferEntry() {} // So we can allocate a vector of StoreBufferEntries
- StoreBufferEntry(const SubBlock& block, CacheRequestType type, const Address& pc, AccessModeType access_mode, int size, int thread) : m_subblock(block) {
- m_type = type;
- m_pc = pc;
- m_access_mode = access_mode;
- m_size = size;
- m_thread = thread;
- m_time = g_eventQueue_ptr->getTime();
- }
-
- void print(ostream& out) const
- {
- out << "[StoreBufferEntry: "
- << "SubBlock: " << m_subblock
- << ", Type: " << m_type
- << ", PC: " << m_pc
- << ", AccessMode: " << m_access_mode
- << ", Size: " << m_size
- << ", Thread: " << m_thread
- << ", Time: " << m_time
- << "]";
- }
-
- SubBlock m_subblock;
- CacheRequestType m_type;
- Address m_pc;
- AccessModeType m_access_mode;
- int m_size;
- int m_thread;
- Time m_time;
-};
-
-extern inline
-ostream& operator<<(ostream& out, const StoreBufferEntry& obj)
-{
- obj.print(out);
- out << flush;
- return out;
-}
-
-// *** End Helper class ***
-
-const int MAX_ENTRIES = 128;
-
-static void inc_index(int& index)
-{
- index++;
- if (index >= MAX_ENTRIES) {
- index = 0;
- }
-}
-
-StoreBuffer::StoreBuffer(AbstractChip* chip_ptr, int version) :
- m_store_cache()
-{
- m_chip_ptr = chip_ptr;
- m_version = version;
- m_queue_ptr = new Vector<StoreBufferEntry>(MAX_ENTRIES);
- m_queue_ptr->setSize(MAX_ENTRIES);
- m_pending = false;
- m_seen_atomic = false;
- m_head = 0;
- m_tail = 0;
- m_size = 0;
- m_deadlock_check_scheduled = false;
-}
-
-StoreBuffer::~StoreBuffer()
-{
- delete m_queue_ptr;
-}
-
-// Used only to check for deadlock
-void StoreBuffer::wakeup()
-{
- // Check for deadlock of any of the requests
- Time current_time = g_eventQueue_ptr->getTime();
-
- int queue_pointer = m_head;
- for (int i=0; i<m_size; i++) {
- if (current_time - (getEntry(queue_pointer).m_time) >= g_DEADLOCK_THRESHOLD) {
- WARN_EXPR(getEntry(queue_pointer));
- WARN_EXPR(m_chip_ptr->getID());
- WARN_EXPR(current_time);
- ERROR_MSG("Possible Deadlock detected");
- }
- inc_index(queue_pointer);
- }
-
- if (m_size > 0) { // If there are still outstanding requests, keep checking
- g_eventQueue_ptr->scheduleEvent(this, g_DEADLOCK_THRESHOLD);
- } else {
- m_deadlock_check_scheduled = false;
- }
-}
-
-void StoreBuffer::printConfig(ostream& out)
-{
- out << "Store buffer entries: " << MAX_ENTRIES << " (Only valid if TSO is enabled)" << endl;
-}
-
-// Handle an incoming store request, this method is responsible for
-// calling hitCallback as needed
-void
-StoreBuffer::insertStore(Packet* pkt, const CacheMsg& request)
-{
- Address addr = request.getAddress();
- CacheRequestType type = request.getType();
- Address pc = request.getProgramCounter();
- AccessModeType access_mode = request.getAccessMode();
- int size = request.getSize();
- int threadID = request.getThreadID();
-
- DEBUG_MSG(STOREBUFFER_COMP, MedPrio, "insertStore");
- DEBUG_EXPR(STOREBUFFER_COMP, MedPrio, g_eventQueue_ptr->getTime());
- assert((type == CacheRequestType_ST) || (type == CacheRequestType_ATOMIC));
- assert(isReady());
-
- // See if we should schedule a deadlock check
- if (m_deadlock_check_scheduled == false) {
- g_eventQueue_ptr->scheduleEvent(this, g_DEADLOCK_THRESHOLD);
- m_deadlock_check_scheduled = true;
- }
-
- // Perform the hit-callback for the store
- SubBlock subblock(addr, size);
- if(type == CacheRequestType_ST) {
- g_system_ptr->getDriver()->hitCallback(pkt);
- assert(subblock.getSize() != 0);
- } else {
- // wait to perform the hitCallback until later for Atomics
- }
-
- // Perform possible pre-fetch
- if(!isEmpty()) {
- Packet new_pkt(pkt);
- pkt->req->setFlags(Request::PREFETCH);
- m_chip_ptr->getSequencer(m_version)->makeRequest(&new_pkt);
- }
-
- // Update the StoreCache
- m_store_cache.add(subblock);
-
- // Enqueue the entry
- StoreBufferEntry entry(subblock, type, pc, access_mode, size, threadID); // FIXME
- enqueue(entry);
-
- if(type == CacheRequestType_ATOMIC) {
- m_seen_atomic = true;
- }
-
- processHeadOfQueue();
-}
-
-void StoreBuffer::callBack(const Address& addr, DataBlock& data, Packet* pkt)
-{
- DEBUG_MSG(STOREBUFFER_COMP, MedPrio, "callBack");
- DEBUG_EXPR(STOREBUFFER_COMP, MedPrio, g_eventQueue_ptr->getTime());
- assert(!isEmpty());
- assert(m_pending == true);
- assert(line_address(addr) == addr);
- assert(line_address(m_pending_address) == addr);
- assert(line_address(peek().m_subblock.getAddress()) == addr);
- CacheRequestType type = peek().m_type;
- //int threadID = peek().m_thread;
- assert((type == CacheRequestType_ST) || (type == CacheRequestType_ATOMIC));
- m_pending = false;
-
- // If oldest entry was ATOMIC, perform the callback
- if(type == CacheRequestType_ST) {
- // We already performed the call back for the store at insert time
- } else {
- // We waited to perform the hitCallback until now for Atomics
- peek().m_subblock.mergeFrom(data); // copy the correct bytes from DataBlock into the SubBlock for the Load part of the atomic Load/Store
- g_system_ptr->getDriver()->hitCallback(pkt);
- m_seen_atomic = false;
-
- /// FIXME - record the time spent in the store buffer - split out ST vs ATOMIC
- }
- assert(peek().m_subblock.getSize() != 0);
-
- // Apply the head entry to the datablock
- peek().m_subblock.mergeTo(data); // For both the Store and Atomic cases
-
- // Update the StoreCache
- m_store_cache.remove(peek().m_subblock);
-
- // Dequeue the entry from the store buffer
- dequeue();
-
- if (isEmpty()) {
- assert(m_store_cache.isEmpty());
- }
-
- if(type == CacheRequestType_ATOMIC) {
- assert(isEmpty());
- }
-
- // See if we can remove any more entries
- processHeadOfQueue();
-}
-
-void StoreBuffer::processHeadOfQueue()
-{
- if(!isEmpty() && !m_pending) {
- StoreBufferEntry& entry = peek();
- assert(m_pending == false);
- m_pending = true;
- m_pending_address = entry.m_subblock.getAddress();
- CacheMsg request(entry.m_subblock.getAddress(), entry.m_subblock.getAddress(), entry.m_type, entry.m_pc, entry.m_access_mode, entry.m_size, PrefetchBit_No, 0, Address(0), entry.m_thread);
- m_chip_ptr->getSequencer(m_version)->doRequest(request);
- }
-}
-
-bool StoreBuffer::isReady() const
-{
- return ((m_size < MAX_ENTRIES) && (!m_seen_atomic));
-}
-
-// Queue implementation methods
-
-StoreBufferEntry& StoreBuffer::peek()
-{
- return getEntry(m_head);
-}
-
-void StoreBuffer::dequeue()
-{
- assert(m_size > 0);
- m_size--;
- inc_index(m_head);
-}
-
-void StoreBuffer::enqueue(const StoreBufferEntry& entry)
-{
- // assert(isReady());
- (*m_queue_ptr)[m_tail] = entry;
- m_size++;
- g_system_ptr->getProfiler()->storeBuffer(m_size, m_store_cache.size());
- inc_index(m_tail);
-}
-
-StoreBufferEntry& StoreBuffer::getEntry(int index)
-{
- return (*m_queue_ptr)[index];
-}
-
-void StoreBuffer::print(ostream& out) const
-{
- out << "[StoreBuffer]";
-}
-
diff --git a/src/mem/ruby/system/StoreBuffer.hh b/src/mem/ruby/system/StoreBuffer.hh
deleted file mode 100644
index 2c9283f4b..000000000
--- a/src/mem/ruby/system/StoreBuffer.hh
+++ /dev/null
@@ -1,121 +0,0 @@
-
-/*
- * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/*
- * $Id$
- *
- * Description:
- *
- */
-
-#ifndef StoreBuffer_H
-#define StoreBuffer_H
-
-#include "mem/ruby/common/Global.hh"
-#include "mem/ruby/common/Consumer.hh"
-#include "mem/ruby/common/Address.hh"
-#include "mem/protocol/AccessModeType.hh"
-#include "mem/protocol/CacheRequestType.hh"
-#include "mem/ruby/system/StoreCache.hh"
-
-class CacheMsg;
-class DataBlock;
-class SubBlock;
-class StoreBufferEntry;
-class AbstractChip;
-class Packet;
-
-template <class TYPE> class Vector;
-
-class StoreBuffer : public Consumer {
-public:
- // Constructors
- StoreBuffer(AbstractChip* chip_ptr, int version);
-
- // Destructor
- ~StoreBuffer();
-
- // Public Methods
- void wakeup(); // Used only for deadlock detection
- void callBack(const Address& addr, DataBlock& data, Packet* pkt);
- void insertStore(Packet* pkt, const CacheMsg& request);
- void updateSubBlock(SubBlock& sub_block) const { m_store_cache.update(sub_block); }
- bool trySubBlock(const SubBlock& sub_block) const { assert(isReady()); return m_store_cache.check(sub_block); }
- void print(ostream& out) const;
- bool isEmpty() const { return (m_size == 0); }
- bool isReady() const;
-
- // Class methods
- static void printConfig(ostream& out);
-
-private:
- // Private Methods
- void processHeadOfQueue();
-
- StoreBufferEntry& peek();
- void dequeue();
- void enqueue(const StoreBufferEntry& entry);
- StoreBufferEntry& getEntry(int index);
-
- // Private copy constructor and assignment operator
- StoreBuffer(const StoreBuffer& obj);
- StoreBuffer& operator=(const StoreBuffer& obj);
-
- // Data Members (m_ prefix)
- int m_version;
-
- Vector<StoreBufferEntry>* m_queue_ptr;
- int m_head;
- int m_tail;
- int m_size;
-
- StoreCache m_store_cache;
-
- AbstractChip* m_chip_ptr;
- bool m_pending;
- Address m_pending_address;
- bool m_seen_atomic;
- bool m_deadlock_check_scheduled;
-};
-
-// Output operator declaration
-ostream& operator<<(ostream& out, const StoreBuffer& obj);
-
-// ******************* Definitions *******************
-
-// Output operator definition
-extern inline
-ostream& operator<<(ostream& out, const StoreBuffer& obj)
-{
- obj.print(out);
- out << flush;
- return out;
-}
-
-#endif //StoreBuffer_H
diff --git a/src/mem/ruby/system/StoreCache.cc b/src/mem/ruby/system/StoreCache.cc
deleted file mode 100644
index a11b2ac50..000000000
--- a/src/mem/ruby/system/StoreCache.cc
+++ /dev/null
@@ -1,178 +0,0 @@
-
-/*
- * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/*
- * $Id$
- *
- */
-
-#include "mem/ruby/system/StoreCache.hh"
-#include "mem/ruby/system/System.hh"
-#include "mem/ruby/common/Driver.hh"
-#include "mem/gems_common/Vector.hh"
-#include "mem/ruby/common/DataBlock.hh"
-#include "mem/ruby/common/SubBlock.hh"
-#include "mem/gems_common/Map.hh"
-
-// Helper class
-struct StoreCacheEntry {
- StoreCacheEntry() {
- m_byte_counters.setSize(RubyConfig::dataBlockBytes());
- for(int i=0; i<m_byte_counters.size(); i++) {
- m_byte_counters[i] = 0;
- }
- m_line_counter = 0;
-
- }
- Address m_addr;
- DataBlock m_datablock;
- Vector<int> m_byte_counters;
- int m_line_counter;
-};
-
-StoreCache::StoreCache()
-{
- m_internal_cache_ptr = new Map<Address, StoreCacheEntry>;
-}
-
-StoreCache::~StoreCache()
-{
- delete m_internal_cache_ptr;
-}
-
-bool StoreCache::isEmpty() const
-{
- return m_internal_cache_ptr->size() == 0;
-}
-
-int StoreCache::size() const { return m_internal_cache_ptr->size(); }
-
-void StoreCache::add(const SubBlock& block)
-{
- if (m_internal_cache_ptr->exist(line_address(block.getAddress())) == false) {
- m_internal_cache_ptr->allocate(line_address(block.getAddress()));
- }
-
- StoreCacheEntry& entry = m_internal_cache_ptr->lookup(line_address(block.getAddress()));
-
- // For each byte in entry change the bytes and inc. the counters
- int starting_offset = block.getAddress().getOffset();
- int size = block.getSize();
- for (int index=0; index < size; index++) {
- // Update counter
- entry.m_byte_counters[starting_offset+index]++;
-
- // Record data
- entry.m_datablock.setByte(starting_offset+index, block.getByte(index));
-
- DEBUG_EXPR(SEQUENCER_COMP, LowPrio, block.getAddress());
- DEBUG_EXPR(SEQUENCER_COMP, LowPrio, int(block.getByte(index)));
- DEBUG_EXPR(SEQUENCER_COMP, LowPrio, starting_offset+index);
- }
-
- // Increment the counter
- entry.m_line_counter++;
-}
-
-void StoreCache::remove(const SubBlock& block)
-{
- assert(m_internal_cache_ptr->exist(line_address(block.getAddress())));
-
- StoreCacheEntry& entry = m_internal_cache_ptr->lookup(line_address(block.getAddress()));
-
- // Decrement the byte counters
- int starting_offset = block.getAddress().getOffset();
- int size = block.getSize();
- for (int index=0; index < size; index++) {
- // Update counter
- entry.m_byte_counters[starting_offset+index]--;
- }
-
- // Decrement the line counter
- entry.m_line_counter--;
- assert(entry.m_line_counter >= 0);
-
- // Check to see if we should de-allocate this entry
- if (entry.m_line_counter == 0) {
- m_internal_cache_ptr->deallocate(line_address(block.getAddress()));
- }
-}
-
-bool StoreCache::check(const SubBlock& block) const
-{
- if (m_internal_cache_ptr->exist(line_address(block.getAddress())) == false) {
- return false;
- } else {
- // Lookup the entry
- StoreCacheEntry& entry = m_internal_cache_ptr->lookup(line_address(block.getAddress()));
-
- // See if all the bytes are valid
- int starting_offset = block.getAddress().getOffset();
- int size = block.getSize();
- for (int index=0; index < size; index++) {
- if (entry.m_byte_counters[starting_offset+index] > 0) {
- // So far so good
- } else {
- // not all the bytes were valid
- return false;
- }
- }
- }
- return true;
-}
-
-void StoreCache::update(SubBlock& block) const
-{
- if (m_internal_cache_ptr->exist(line_address(block.getAddress()))) {
- // Lookup the entry
- StoreCacheEntry& entry = m_internal_cache_ptr->lookup(line_address(block.getAddress()));
-
- // Copy all appropriate and valid bytes from the store cache to
- // the SubBlock
- int starting_offset = block.getAddress().getOffset();
- int size = block.getSize();
- for (int index=0; index < size; index++) {
-
- DEBUG_EXPR(SEQUENCER_COMP, LowPrio, block.getAddress());
- DEBUG_EXPR(SEQUENCER_COMP, LowPrio, int(entry.m_datablock.getByte(starting_offset+index)));
- DEBUG_EXPR(SEQUENCER_COMP, LowPrio, starting_offset+index);
-
- // If this byte is valid, copy the data into the sub-block
- if (entry.m_byte_counters[starting_offset+index] > 0) {
- block.setByte(index, entry.m_datablock.getByte(starting_offset+index));
- }
- }
- }
-}
-
-void StoreCache::print(ostream& out) const
-{
- out << "[StoreCache]";
-}
-
diff --git a/src/mem/ruby/system/StoreCache.hh b/src/mem/ruby/system/StoreCache.hh
deleted file mode 100644
index 81eecde38..000000000
--- a/src/mem/ruby/system/StoreCache.hh
+++ /dev/null
@@ -1,85 +0,0 @@
-
-/*
- * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/*
- * $Id$
- *
- * Description:
- *
- */
-
-#ifndef StoreCache_H
-#define StoreCache_H
-
-#include "mem/ruby/common/Global.hh"
-#include "mem/ruby/common/Address.hh"
-
-
-class DataBlock;
-class SubBlock;
-class StoreCacheEntry;
-
-template <class KEY_TYPE, class VALUE_TYPE> class Map;
-
-class StoreCache {
-public:
- // Constructors
- StoreCache();
-
- // Destructor
- ~StoreCache();
-
- // Public Methods
- void add(const SubBlock& block);
- void remove(const SubBlock& block);
- bool check(const SubBlock& block) const;
- void update(SubBlock& block) const;
- bool isEmpty() const;
- int size() const;
- void print(ostream& out) const;
-
-private:
- Map<Address, StoreCacheEntry>* m_internal_cache_ptr;
-};
-
-// Output operator declaration
-ostream& operator<<(ostream& out, const StoreCache& obj);
-
-// ******************* Definitions *******************
-
-// Output operator definition
-extern inline
-ostream& operator<<(ostream& out, const StoreCache& obj)
-{
- obj.print(out);
- out << flush;
- return out;
-}
-
-#endif //StoreCache_H
diff --git a/src/mem/ruby/system/System.cc b/src/mem/ruby/system/System.cc
index 0e1a29130..9d1119f01 100644
--- a/src/mem/ruby/system/System.cc
+++ b/src/mem/ruby/system/System.cc
@@ -38,134 +38,306 @@
#include "mem/ruby/system/System.hh"
+#include "mem/ruby/common/Address.hh"
#include "mem/ruby/profiler/Profiler.hh"
#include "mem/ruby/network/Network.hh"
-#include "mem/ruby/tester/Tester.hh"
-#include "mem/ruby/tester/SyntheticDriver.hh"
-#include "mem/ruby/tester/DeterministicDriver.hh"
-#include "mem/protocol/Chip.hh"
-//#include "mem/ruby/recorder/Tracer.hh"
+#include "mem/ruby/recorder/Tracer.hh"
#include "mem/protocol/Protocol.hh"
-
-RubySystem::RubySystem()
+#include "mem/ruby/buffers/MessageBuffer.hh"
+#include "mem/ruby/system/Sequencer.hh"
+#include "mem/ruby/system/DMASequencer.hh"
+#include "mem/ruby/system/MemoryVector.hh"
+#include "mem/protocol/ControllerFactory.hh"
+#include "mem/ruby/slicc_interface/AbstractController.hh"
+#include "mem/ruby/system/CacheMemory.hh"
+#include "mem/ruby/system/DirectoryMemory.hh"
+#include "mem/ruby/network/simple/Topology.hh"
+#include "mem/ruby/network/simple/SimpleNetwork.hh"
+#include "mem/ruby/system/RubyPort.hh"
+#include "mem/ruby/network/garnet-flexible-pipeline/GarnetNetwork.hh"
+#include "mem/ruby/network/garnet-fixed-pipeline/GarnetNetwork_d.hh"
+#include "mem/ruby/system/MemoryControl.hh"
+
+int RubySystem::m_random_seed;
+bool RubySystem::m_randomization;
+int RubySystem::m_tech_nm;
+int RubySystem::m_freq_mhz;
+int RubySystem::m_block_size_bytes;
+int RubySystem::m_block_size_bits;
+uint64 RubySystem::m_memory_size_bytes;
+int RubySystem::m_memory_size_bits;
+
+map< string, RubyPort* > RubySystem::m_ports;
+map< string, CacheMemory* > RubySystem::m_caches;
+map< string, DirectoryMemory* > RubySystem::m_directories;
+map< string, Sequencer* > RubySystem::m_sequencers;
+map< string, DMASequencer* > RubySystem::m_dma_sequencers;
+map< string, AbstractController* > RubySystem::m_controllers;
+map< string, MemoryControl* > RubySystem::m_memorycontrols;
+
+
+Network* RubySystem::m_network_ptr;
+map< string, Topology*> RubySystem::m_topologies;
+Profiler* RubySystem::m_profiler_ptr;
+Tracer* RubySystem::m_tracer_ptr;
+
+MemoryVector* RubySystem::m_mem_vec_ptr;
+
+
+RubySystem* RubySystem::create(const vector <RubyObjConf> & sys_conf)
{
- init();
- m_preinitialized_driver = false;
- createDriver();
-
- /* gem5:Binkert for decomissiong of tracer
- m_tracer_ptr = new Tracer;
- */
-
- /* gem5:Arka for decomissiong of log_tm
- if (XACT_MEMORY) {
- m_xact_isolation_checker = new XactIsolationChecker;
- m_xact_commit_arbiter = new XactCommitArbiter;
- m_xact_visualizer = new XactVisualizer;
- }
-*/
+ if (g_system_ptr == NULL)
+ return new RubySystem(sys_conf);
+ return g_system_ptr;
}
-RubySystem::RubySystem(Driver* _driver)
+void RubySystem::init(const vector<string> & argv)
{
- init();
- m_preinitialized_driver = true;
- m_driver_ptr = _driver;
-}
+ for (size_t i=0; i < argv.size(); i+=2) {
+ if (argv[i] == "random_seed") {
+ m_random_seed = atoi(argv[i+1].c_str());
+ srandom(m_random_seed);
+ } else if (argv[i] == "randomization") {
+ m_randomization = string_to_bool(argv[i+1]);
+ } else if (argv[i] == "tech_nm") {
+ m_tech_nm = atoi(argv[i+1].c_str());
+ } else if (argv[i] == "freq_mhz") {
+ m_freq_mhz = atoi(argv[i+1].c_str());
+ } else if (argv[i] == "block_size_bytes") {
+ m_block_size_bytes = atoi(argv[i+1].c_str());
+ assert(is_power_of_2(m_block_size_bytes));
+ m_block_size_bits = log_int(m_block_size_bytes);
+ } else if (argv[i] == "debug") {
+
+ } else if (argv[i] == "tracer") {
+
+ } else if (argv[i] == "profiler") {
+
+ // } else if (argv[i] == "MI_example") {
-RubySystem::~RubySystem()
-{
- for (int i = 0; i < m_chip_vector.size(); i++) {
- delete m_chip_vector[i];
+ } else {
+ cerr << "Error: Unknown RubySystem config parameter -- " << argv[i] << endl;
+ assert(0);
+ }
}
- if (!m_preinitialized_driver)
- delete m_driver_ptr;
- delete m_network_ptr;
- delete m_profiler_ptr;
- /* gem5:Binkert for decomissiong of tracer
- delete m_tracer_ptr;
- */
}
-void RubySystem::init()
+RubySystem::RubySystem(const vector <RubyObjConf> & sys_conf)
{
- DEBUG_MSG(SYSTEM_COMP, MedPrio,"initializing");
-
- m_driver_ptr = NULL;
- m_profiler_ptr = new Profiler;
+ // DEBUG_MSG(SYSTEM_COMP, MedPrio,"initializing");
+
+ for (size_t i=0;i<sys_conf.size(); i++) {
+ const string & type = sys_conf[i].type;
+ const string & name = sys_conf[i].name;
+ const vector<string> & argv = sys_conf[i].argv;
+ if (type == "RubySystem") {
+ init(argv); // initialize system-wide variables before doing anything else!
+ } else if (type == "Debug") {
+ g_debug_ptr = new Debug(name, argv);
+ }
+ }
- // NETWORK INITIALIZATION
- // create the network by calling a function that calls new
- m_network_ptr = Network::createNetwork(RubyConfig::numberOfChips());
+ assert( g_debug_ptr != NULL);
+ g_eventQueue_ptr = new RubyEventQueue;
+ g_system_ptr = this;
+ m_mem_vec_ptr = new MemoryVector;
+
+ /* object contruction is broken into two steps (Constructor and init) to avoid cyclic dependencies
+ * e.g. a sequencer needs a pointer to a controller and a controller needs a pointer to a sequencer
+ */
+
+ vector<string> memory_control_names;
+
+ for (size_t i=0;i<sys_conf.size(); i++) {
+ const string & type = sys_conf[i].type;
+ const string & name = sys_conf[i].name;
+ const vector<string> & argv = sys_conf[i].argv;
+ if (type == "RubySystem" || type == "Debug")
+ continue;
+ else if (type == "SetAssociativeCache")
+ m_caches[name] = new CacheMemory(name);
+ else if (type == "DirectoryMemory")
+ m_directories[name] = new DirectoryMemory(name);
+ else if (type == "Sequencer") {
+ m_sequencers[name] = new Sequencer(name);
+ m_ports[name] = m_sequencers[name];
+ } else if (type == "DMASequencer") {
+ m_dma_sequencers[name] = new DMASequencer(name);
+ m_ports[name] = m_dma_sequencers[name];
+ } else if (type == "Topology") {
+ assert(m_topologies.size() == 0); // only one toplogy at a time is supported right now
+ m_topologies[name] = new Topology(name);
+ } else if (type == "SimpleNetwork") {
+ assert(m_network_ptr == NULL); // only one network at a time is supported right now
+ m_network_ptr = new SimpleNetwork(name);
+ } else if (type.find("generated") == 0) {
+ string controller_type = type.substr(10);
+ m_controllers[name] = ControllerFactory::createController(controller_type, name);
+// printf ("ss: generated %s \n", controller_type);
+//added by SS
+ } else if (type == "Tracer") {
+ //m_tracers[name] = new Tracer(name);
+ m_tracer_ptr = new Tracer(name);
+ } else if (type == "Profiler") {
+ m_profiler_ptr = new Profiler(name);
+ } else if (type == "GarnetNetwork") {
+ assert(m_network_ptr == NULL); // only one network at a time is supported right now
+ m_network_ptr = new GarnetNetwork(name);
+ } else if (type == "GarnetNetwork_d") {
+ assert(m_network_ptr == NULL); // only one network at a time is supported right now
+ m_network_ptr = new GarnetNetwork_d(name);
+ } else if (type == "MemoryControl") {
+ m_memorycontrols[name] = new MemoryControl(name);
+ memory_control_names.push_back (name);
+ } else {
+ cerr << "Error: Unknown object type -- " << type << endl;
+ assert(0);
+ }
+ }
- DEBUG_MSG(SYSTEM_COMP, MedPrio,"Constructed network");
+ for (size_t i=0;i<sys_conf.size(); i++) {
+ string type = sys_conf[i].type;
+ string name = sys_conf[i].name;
+ const vector<string> & argv = sys_conf[i].argv;
+ if (type == "Topology")
+ m_topologies[name]->init(argv);
+ }
- // CHIP INITIALIZATION
- m_chip_vector.setSize(RubyConfig::numberOfChips());// create the vector of pointers to processors
- for(int i=0; i<RubyConfig::numberOfChips(); i++) { // for each chip
- // create the chip
- m_chip_vector[i] = new Chip(i, m_network_ptr);
- DEBUG_MSG(SYSTEM_COMP, MedPrio,"Constructed a chip");
+ for (size_t i=0;i<sys_conf.size(); i++) {
+ string type = sys_conf[i].type;
+ string name = sys_conf[i].name;
+ const vector<string> & argv = sys_conf[i].argv;
+ if (type == "SimpleNetwork" || type == "GarnetNetwork" || type == "GarnetNetwork_d"){
+ m_network_ptr->init(argv);
+ }
}
- // These must be after the chips are constructed
+ for (size_t i=0;i<sys_conf.size(); i++) {
+ string type = sys_conf[i].type;
+ string name = sys_conf[i].name;
+ const vector<string> & argv = sys_conf[i].argv;
+ if (type == "MemoryControl" ){
+ m_memorycontrols[name]->init(argv);
+ }
+ }
-#if 0
- if (!g_SIMICS) {
- if (g_SYNTHETIC_DRIVER && !g_DETERMINISTIC_DRIVER) {
- m_driver_ptr = new SyntheticDriver(this);
- } else if (!g_SYNTHETIC_DRIVER && g_DETERMINISTIC_DRIVER) {
- m_driver_ptr = new DeterministicDriver(this);
- } else if (g_SYNTHETIC_DRIVER && g_DETERMINISTIC_DRIVER) {
- ERROR_MSG("SYNTHETIC and DETERMINISTIC DRIVERS are exclusive and cannot be both enabled");
- } else {
- // normally make tester object, otherwise make an opal interface object.
- if (!OpalInterface::isOpalLoaded()) {
- m_driver_ptr = new Tester(this);
- } else {
- m_driver_ptr = new OpalInterface(this);
- }
+ for (size_t i=0;i<sys_conf.size(); i++) {
+ string type = sys_conf[i].type;
+ string name = sys_conf[i].name;
+ const vector<string> & argv = sys_conf[i].argv;
+ if (type == "RubySystem" || type == "Debug")
+ continue;
+ else if (type == "SetAssociativeCache")
+ m_caches[name]->init(argv);
+ else if (type == "DirectoryMemory")
+ m_directories[name]->init(argv);
+ else if (type == "MemoryControl")
+ continue;
+ else if (type == "Sequencer")
+ m_sequencers[name]->init(argv);
+ else if (type == "DMASequencer")
+ m_dma_sequencers[name]->init(argv);
+ else if (type == "Topology")
+ continue;
+ else if (type == "SimpleNetwork" || type == "GarnetNetwork" || type == "GarnetNetwork_d")
+ continue;
+ else if (type.find("generated") == 0) {
+ string controller_type = type.substr(11);
+ m_controllers[name]->init(m_network_ptr, argv);
}
- } else {
- // detect if opal is loaded or not
- if (OpalInterface::isOpalLoaded()) {
- m_driver_ptr = new OpalInterface(this);
- } else {
+//added by SS
+ else if (type == "Tracer")
+ //m_tracers[name]->init(argv);
+ m_tracer_ptr->init(argv);
+ else if (type == "Profiler")
+ m_profiler_ptr->init(argv, memory_control_names);
+// else if (type == "MI_example"){
+// }
+ else
assert(0);
- /* Need to allocate a driver here */
- // m_driver_ptr = new SimicsDriver(this);
- }
}
-#endif
+
+// m_profiler_ptr = new Profiler;
+
+ // calculate system-wide parameters
+ m_memory_size_bytes = 0;
+ DirectoryMemory* prev = NULL;
+ for (map< string, DirectoryMemory*>::const_iterator it = m_directories.begin();
+ it != m_directories.end(); it++) {
+ if (prev != NULL)
+ assert((*it).second->getSize() == prev->getSize()); // must be equal for proper address mapping
+ m_memory_size_bytes += (*it).second->getSize();
+ prev = (*it).second;
+ }
+ m_mem_vec_ptr->setSize(m_memory_size_bytes);
+ m_memory_size_bits = log_int(m_memory_size_bytes);
+
+// m_tracer_ptr = new Tracer;
DEBUG_MSG(SYSTEM_COMP, MedPrio,"finished initializing");
DEBUG_NEWLINE(SYSTEM_COMP, MedPrio);
}
-void RubySystem::createDriver()
+RubySystem::~RubySystem()
{
- if (g_SYNTHETIC_DRIVER && !g_DETERMINISTIC_DRIVER) {
- cerr << "Creating Synthetic Driver" << endl;
- m_driver_ptr = new SyntheticDriver(this);
- } else if (!g_SYNTHETIC_DRIVER && g_DETERMINISTIC_DRIVER) {
- cerr << "Creating Deterministic Driver" << endl;
- m_driver_ptr = new DeterministicDriver(this);
+ /*
+ for (int i=0; i < MachineType_base_level(MachineType_NUM); i++) {
+ for (int j=0; j < RubyConfig::getNumberOfControllersPerType(i); j++ ) {
+ delete m_controllers[i][j];
}
+ }
+ delete m_network_ptr;
+ delete m_profiler_ptr;
+ delete m_tracer_ptr;
+ */
+}
+
+void RubySystem::printSystemConfig(ostream & out)
+{
+ out << "RubySystem config:" << endl;
+ out << " random_seed: " << m_random_seed << endl;
+ out << " randomization: " << m_randomization << endl;
+ out << " tech_nm: " << m_tech_nm << endl;
+ out << " freq_mhz: " << m_freq_mhz << 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;
+
}
-void RubySystem::printConfig(ostream& out) const
+void RubySystem::printConfig(ostream& out)
{
out << "\n================ Begin RubySystem Configuration Print ================\n\n";
- RubyConfig::printConfiguration(out);
- out << endl;
- getChip(0)->printConfig(out);
+ // RubyConfig::printConfiguration(out);
+ // out << endl;
+ printSystemConfig(out);
+ for (map<string, AbstractController*>::const_iterator it = m_controllers.begin();
+ it != m_controllers.end(); it++) {
+ (*it).second->printConfig(out);
+ }
+ for (map<string, CacheMemory*>::const_iterator it = m_caches.begin();
+ it != m_caches.end(); it++) {
+ (*it).second->printConfig(out);
+ }
+ DirectoryMemory::printGlobalConfig(out);
+ for (map<string, DirectoryMemory*>::const_iterator it = m_directories.begin();
+ it != m_directories.end(); it++) {
+ (*it).second->printConfig(out);
+ }
+ for (map<string, Sequencer*>::const_iterator it = m_sequencers.begin();
+ it != m_sequencers.end(); it++) {
+ (*it).second->printConfig(out);
+ }
+
m_network_ptr->printConfig(out);
- m_driver_ptr->printConfig(out);
m_profiler_ptr->printConfig(out);
+
out << "\n================ End RubySystem Configuration Print ================\n\n";
}
void RubySystem::printStats(ostream& out)
{
+
const time_t T = time(NULL);
tm *localTime = localtime(&T);
char buf[100];
@@ -174,32 +346,30 @@ void RubySystem::printStats(ostream& out)
out << "Real time: " << buf << endl;
m_profiler_ptr->printStats(out);
- for(int i=0; i<RubyConfig::numberOfChips(); i++) { // for each chip
- for(int p=0; p<RubyConfig::numberOfProcsPerChip(); p++) {
- m_chip_vector[i]->m_L1Cache_mandatoryQueue_vec[p]->printStats(out);
- }
- }
m_network_ptr->printStats(out);
- m_driver_ptr->printStats(out);
- Chip::printStats(out);
+ for (map<string, AbstractController*>::const_iterator it = m_controllers.begin();
+ it != m_controllers.end(); it++) {
+ (*it).second->printStats(out);
+ }
}
void RubySystem::clearStats() const
{
+ /*
m_profiler_ptr->clearStats();
+ for (int i=0; i<m_rubyRequestQueues.size(); i++)
+ for (int j=0;j<m_rubyRequestQueues[i].size(); j++)
+ m_rubyRequestQueues[i][j]->clearStats();
m_network_ptr->clearStats();
- m_driver_ptr->clearStats();
- Chip::clearStats();
- for(int i=0; i<RubyConfig::numberOfChips(); i++) { // for each chip
- for(int p=0; p<RubyConfig::numberOfProcsPerChip(); p++) {
- m_chip_vector[i]->m_L1Cache_mandatoryQueue_vec[p]->clearStats();
- }
- }
+ for (int i=0; i < MachineType_base_level(MachineType_NUM); i++)
+ m_controllers[i][0]->clearStats();
+ */
}
void RubySystem::recordCacheContents(CacheRecorder& tr) const
{
- for (int i = 0; i < m_chip_vector.size(); i++) {
+ /*
+ for (int i = 0; i < m_chip_vector.size(); i++) {
for (int m_version = 0; m_version < RubyConfig::numberOfProcsPerChip(); m_version++) {
if (Protocol::m_TwoLevelCache) {
m_chip_vector[i]->m_L1Cache_L1IcacheMemory_vec[m_version]->setAsInstructionCache(true);
@@ -210,6 +380,7 @@ void RubySystem::recordCacheContents(CacheRecorder& tr) const
}
m_chip_vector[i]->recordCacheContents(tr);
}
+ */
}
#ifdef CHECK_COHERENCE
@@ -222,7 +393,7 @@ void RubySystem::recordCacheContents(CacheRecorder& tr) const
// and "isBlockExclusive" that are specific to that protocol
//
void RubySystem::checkGlobalCoherenceInvariant(const Address& addr ) {
-
+ /*
NodeID exclusive = -1;
bool sharedDetected = false;
NodeID lastShared = -1;
@@ -262,6 +433,7 @@ void RubySystem::checkGlobalCoherenceInvariant(const Address& addr ) {
}
}
}
+ */
}
#endif
diff --git a/src/mem/ruby/system/System.hh b/src/mem/ruby/system/System.hh
index bc493dd16..40c425ad7 100644
--- a/src/mem/ruby/system/System.hh
+++ b/src/mem/ruby/system/System.hh
@@ -41,81 +41,129 @@
#ifndef SYSTEM_H
#define SYSTEM_H
+#include "mem/ruby/system/RubyPort.hh"
#include "mem/ruby/common/Global.hh"
#include "mem/gems_common/Vector.hh"
-#include "mem/ruby/common/Address.hh"
-#include "mem/ruby/config/RubyConfig.hh"
-#include "mem/protocol/MachineType.hh"
-#include "mem/ruby/slicc_interface/AbstractChip.hh"
+#include "mem/ruby/eventqueue/RubyEventQueue.hh"
+#include <map>
class Profiler;
class Network;
-class Driver;
class CacheRecorder;
class Tracer;
class Sequencer;
-class XactIsolationChecker;
-class XactCommitArbiter;
-class XactVisualizer;
-class TransactionInterfaceManager;
+class DMASequencer;
+class MemoryVector;
+class AbstractController;
+class MessageBuffer;
+class CacheMemory;
+class DirectoryMemory;
+class Topology;
+class MemoryControl;
+
+struct RubyObjConf {
+ string type;
+ string name;
+ vector<string> argv;
+ RubyObjConf(string _type, string _name, vector<string> _argv)
+ : type(_type), name(_name), argv(_argv)
+ {}
+};
class RubySystem {
public:
- // Constructors
- RubySystem();
- RubySystem(Driver* _driver); // used when driver is already instantiated (e.g. M5's RubyMem)
-
+ static RubySystem* create(const vector <RubyObjConf> & sys_conf);
// Destructor
~RubySystem();
+ // config accessors
+ static int getRandomSeed() { return m_random_seed; }
+ static int getRandomization() { return m_randomization; }
+ static int getTechNm() { return m_tech_nm; }
+ static int getFreqMhz() { return m_freq_mhz; }
+ 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
- int getNumProcessors() { return RubyConfig::numberOfProcessors(); }
- int getNumMemories() { return RubyConfig::numberOfMemories(); }
- Profiler* getProfiler() { return m_profiler_ptr; }
- Driver* getDriver() { assert(m_driver_ptr != NULL); return m_driver_ptr; }
+ static RubyPort* getPortOnly(const string & name) {
+ assert(m_ports.count(name) == 1); return m_ports[name]; }
+ static RubyPort* getPort(const string & name, void (*hit_callback)(int64_t)) {
+ assert(m_ports.count(name) == 1); m_ports[name]->registerHitCallback(hit_callback); return m_ports[name]; }
+ static Network* getNetwork() { assert(m_network_ptr != NULL); return m_network_ptr; }
+ static Topology* getTopology(const string & name) { assert(m_topologies.count(name) == 1); return m_topologies[name]; }
+ static CacheMemory* getCache(const string & name) { assert(m_caches.count(name) == 1); return m_caches[name]; }
+ static DirectoryMemory* getDirectory(const string & name) { assert(m_directories.count(name) == 1); return m_directories[name]; }
+ static MemoryControl* getMemoryControl(const string & name) { assert(m_memorycontrols.count(name) == 1); return m_memorycontrols[name]; }
+ static Sequencer* getSequencer(const string & name) { assert(m_sequencers.count(name) == 1); return m_sequencers[name]; }
+ static DMASequencer* getDMASequencer(const string & name) { assert(m_dma_sequencers.count(name) == 1); return m_dma_sequencers[name]; }
+ static AbstractController* getController(const string & name) { assert(m_controllers.count(name) == 1); return m_controllers[name]; }
+
+ static RubyEventQueue* getEventQueue() { return g_eventQueue_ptr; }
+
+ static int getNumberOfDirectories() { return m_directories.size(); }
+ static int getNumberOfSequencers() { return m_sequencers.size(); }
+
+ Profiler* getProfiler() {assert(m_profiler_ptr != NULL); return m_profiler_ptr; }
Tracer* getTracer() { assert(m_tracer_ptr != NULL); return m_tracer_ptr; }
- Network* getNetwork() { assert(m_network_ptr != NULL); return m_network_ptr; }
- XactIsolationChecker* getXactIsolationChecker() { assert(m_xact_isolation_checker!= NULL); return m_xact_isolation_checker;}
- XactCommitArbiter* getXactCommitArbiter() { assert(m_xact_commit_arbiter!= NULL); return m_xact_commit_arbiter;}
- XactVisualizer* getXactVisualizer() { assert(m_xact_visualizer!= NULL); return m_xact_visualizer;}
-
- AbstractChip* getChip(int chipNumber) const { assert(m_chip_vector[chipNumber] != NULL); return m_chip_vector[chipNumber];}
- Sequencer* getSequencer(int procNumber) const {
- assert(procNumber < RubyConfig::numberOfProcessors());
- return m_chip_vector[procNumber/RubyConfig::numberOfProcsPerChip()]->getSequencer(procNumber%RubyConfig::numberOfProcsPerChip());
- }
- TransactionInterfaceManager* getTransactionInterfaceManager(int procNumber) const {
- return m_chip_vector[procNumber/RubyConfig::numberOfProcsPerChip()]->getTransactionInterfaceManager(procNumber%RubyConfig::numberOfProcsPerChip());
- }
+ static MemoryVector* getMemoryVector() { assert(m_mem_vec_ptr != NULL); return m_mem_vec_ptr;}
+
void recordCacheContents(CacheRecorder& tr) const;
- void printConfig(ostream& out) const;
- void printStats(ostream& out);
+ 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 Methods
- void init();
- void createDriver();
+ // Constructors
+ RubySystem(const vector <RubyObjConf> & cfg_file);
// Private copy constructor and assignment operator
RubySystem(const RubySystem& obj);
RubySystem& operator=(const RubySystem& obj);
+ void init(const vector<string> & argv);
+
+ static void printSystemConfig(ostream& out);
+
+private:
+ // configuration parameters
+ static int m_random_seed;
+ static bool m_randomization;
+ static int m_tech_nm;
+ static int m_freq_mhz;
+ 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)
- Network* m_network_ptr;
- Vector<AbstractChip*> m_chip_vector;
- Profiler* m_profiler_ptr;
- bool m_preinitialized_driver;
- Driver* m_driver_ptr;
- Tracer* m_tracer_ptr;
- XactIsolationChecker *m_xact_isolation_checker;
- XactCommitArbiter *m_xact_commit_arbiter;
- XactVisualizer *m_xact_visualizer;
+ static Network* m_network_ptr;
+ static map< string, Topology* > m_topologies;
+ static map< string, RubyPort* > m_ports;
+ static map< string, CacheMemory* > m_caches;
+ static map< string, DirectoryMemory* > m_directories;
+ static map< string, Sequencer* > m_sequencers;
+ static map< string, DMASequencer* > m_dma_sequencers;
+ static map< string, AbstractController* > m_controllers;
+ static map< string, MemoryControl* > m_memorycontrols;
+
+ //added by SS
+ //static map< string, Tracer* > m_tracers;
+
+ static Profiler* m_profiler_ptr;
+ static Tracer* m_tracer_ptr;
+ static MemoryVector* m_mem_vec_ptr;
};
// Output operator declaration
diff --git a/src/mem/ruby/system/TBETable.hh b/src/mem/ruby/system/TBETable.hh
index 2a0c78f06..7d2daa55a 100644
--- a/src/mem/ruby/system/TBETable.hh
+++ b/src/mem/ruby/system/TBETable.hh
@@ -43,7 +43,6 @@
#include "mem/gems_common/Map.hh"
#include "mem/ruby/common/Address.hh"
#include "mem/ruby/profiler/Profiler.hh"
-#include "mem/ruby/slicc_interface/AbstractChip.hh"
#include "mem/ruby/system/System.hh"
template<class ENTRY>
@@ -51,19 +50,20 @@ class TBETable {
public:
// Constructors
- TBETable(AbstractChip* chip_ptr);
+ TBETable(int number_of_TBEs);
+
// Destructor
//~TBETable();
// Public Methods
- static void printConfig(ostream& out) { out << "TBEs_per_TBETable: " << NUMBER_OF_TBES << endl; }
+ 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 (NUMBER_OF_TBES - m_map.size()) >= n; }
+ 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;
@@ -79,7 +79,9 @@ private:
// Data Members (m_prefix)
Map<Address, ENTRY> m_map;
- AbstractChip* m_chip_ptr;
+
+private:
+ int m_number_of_TBEs;
};
// Output operator declaration
@@ -100,11 +102,12 @@ ostream& operator<<(ostream& out, const TBETable<ENTRY>& obj)
// ****************************************************************
+
template<class ENTRY>
extern inline
-TBETable<ENTRY>::TBETable(AbstractChip* chip_ptr)
+TBETable<ENTRY>::TBETable(int number_of_TBEs)
{
- m_chip_ptr = chip_ptr;
+ m_number_of_TBEs = number_of_TBEs;
}
// PUBLIC METHODS
@@ -115,7 +118,7 @@ extern inline
bool TBETable<ENTRY>::isPresent(const Address& address) const
{
assert(address == line_address(address));
- assert(m_map.size() <= NUMBER_OF_TBES);
+ assert(m_map.size() <= m_number_of_TBEs);
return m_map.exist(address);
}
@@ -124,7 +127,7 @@ extern inline
void TBETable<ENTRY>::allocate(const Address& address)
{
assert(isPresent(address) == false);
- assert(m_map.size() < NUMBER_OF_TBES);
+ assert(m_map.size() < m_number_of_TBEs);
g_system_ptr->getProfiler()->L2tbeUsageSample(m_map.size());
m_map.add(address, ENTRY());
}