From 226981b2a65ee4c544bc595d7718de8225fda0b0 Mon Sep 17 00:00:00 2001 From: Polina Dudnik Date: Mon, 13 Jul 2009 11:13:29 -0500 Subject: Reintegrated Derek's functional implementation of atomics with a minor change: don't clear lock on failure --- src/mem/ruby/system/CacheMemory.hh | 43 ++++++++++++++++++++++++++++++++++++++ src/mem/ruby/system/Sequencer.cc | 28 ++++++++++++++++++++++--- 2 files changed, 68 insertions(+), 3 deletions(-) (limited to 'src/mem/ruby/system') diff --git a/src/mem/ruby/system/CacheMemory.hh b/src/mem/ruby/system/CacheMemory.hh index 941073ad2..cde5b6d94 100644 --- a/src/mem/ruby/system/CacheMemory.hh +++ b/src/mem/ruby/system/CacheMemory.hh @@ -116,6 +116,9 @@ public: void setMemoryValue(const Address& addr, char* value, unsigned int size_in_bytes ); + void setLocked (const Address& addr, int context); + void clearLocked (const Address& addr); + bool isLocked (const Address& addr, int context); // Print cache contents void print(ostream& out) const; void printData(ostream& out) const; @@ -147,6 +150,7 @@ private: // The first index is the # of cache lines. // The second index is the the amount associativity. Vector > m_cache; + Vector > m_locked; AbstractReplacementPolicy *m_replacementPolicy_ptr; @@ -252,10 +256,13 @@ void CacheMemory::init(const vector & argv) assert(false); m_cache.setSize(m_cache_num_sets); + m_locked.setSize(m_cache_num_sets); for (int i = 0; i < m_cache_num_sets; i++) { m_cache[i].setSize(m_cache_assoc); + m_locked[i].setSize(m_cache_assoc); for (int j = 0; j < m_cache_assoc; j++) { m_cache[i][j] = NULL; + m_locked[i][j] = -1; } } } @@ -474,6 +481,7 @@ void CacheMemory::allocate(const Address& address, AbstractCacheEntry* entry) m_cache[cacheSet][i] = entry; // Init entry m_cache[cacheSet][i]->m_Address = address; m_cache[cacheSet][i]->m_Permission = AccessPermission_Invalid; + m_locked[cacheSet][i] = -1; m_replacementPolicy_ptr->touch(cacheSet, i, g_eventQueue_ptr->getTime()); @@ -494,6 +502,7 @@ void CacheMemory::deallocate(const Address& address) if (location != -1){ delete m_cache[cacheSet][location]; m_cache[cacheSet][location] = NULL; + m_locked[cacheSet][location] = -1; } } @@ -542,6 +551,7 @@ void CacheMemory::changePermission(const Address& address, AccessPermission new_ { assert(address == line_address(address)); lookup(address).m_Permission = new_perm; + m_locked[cacheSet][loc] = -1; assert(getPermission(address) == new_perm); } @@ -630,5 +640,38 @@ void CacheMemory::setMemoryValue(const Address& addr, char* value, // entry = lookup(line_address(addr)); } +inline +void +CacheMemory::setLocked(const Address& address, int context) +{ + assert(address == line_address(address)); + Index cacheSet = addressToCacheSet(address); + int loc = findTagInSet(cacheSet, address); + assert(loc != -1); + m_locked[cacheSet][loc] = context; +} + +inline +void +CacheMemory::clearLocked(const Address& address) +{ + assert(address == line_address(address)); + Index cacheSet = addressToCacheSet(address); + int loc = findTagInSet(cacheSet, address); + assert(loc != -1); + m_locked[cacheSet][loc] = -1; +} + +inline +bool +CacheMemory::isLocked(const Address& address, int context) +{ + assert(address == line_address(address)); + Index cacheSet = addressToCacheSet(address); + int loc = findTagInSet(cacheSet, address); + assert(loc != -1); + return m_locked[cacheSet][loc] == context; +} + #endif //CACHEMEMORY_H diff --git a/src/mem/ruby/system/Sequencer.cc b/src/mem/ruby/system/Sequencer.cc index 97416d2d3..d7d4ba8e0 100644 --- a/src/mem/ruby/system/Sequencer.cc +++ b/src/mem/ruby/system/Sequencer.cc @@ -237,7 +237,8 @@ void Sequencer::removeRequest(SequencerRequest* srequest) { Address line_addr(ruby_request.paddr); line_addr.makeLineAddress(); if ((ruby_request.type == RubyRequestType_ST) || - (ruby_request.type == RubyRequestType_RMW)) { + (ruby_request.type == RubyRequestType_RMW_Read) || + (ruby_request.type == RubyRequestType_RMW_Write)) { m_writeRequestTable.deallocate(line_addr); } else { m_readRequestTable.deallocate(line_addr); @@ -256,7 +257,25 @@ void Sequencer::writeCallback(const Address& address, DataBlock& data) { removeRequest(request); assert((request->ruby_request.type == RubyRequestType_ST) || - (request->ruby_request.type == RubyRequestType_RMW)); + (request->ruby_request.type == RubyRequestType_RMW_Read) || + (request->ruby_request.type == RubyRequestType_RMW_Write)); + // POLINA: the assumption is that atomics are only on data cache and not instruction cache + if (request->ruby_request.type == RubyRequestType_RMW_Read) { + m_dataCache_ptr->setLocked(address, m_version); + } + else if (request->ruby_request.type == RubyRequestType_RMW_Write) { + if (m_dataCache_ptr->isLocked(address, m_version)) { + // if we are holding the lock for this + request->ruby_request.atomic_success = true; + m_dataCache_ptr->clearLocked(address); + } + else { + // if we are not holding the lock for this + request->ruby_request.atomic_success = false; + } + + // can have livelock + } hitCallback(request, data); } @@ -379,7 +398,10 @@ void Sequencer::issueRequest(const RubyRequest& request) { case RubyRequestType_ST: ctype = CacheRequestType_ST; break; - case RubyRequestType_RMW: + case RubyRequestType_RMW_Read: + ctype = CacheRequestType_ATOMIC; + break; + case RubyRequestType_RMW_Write: ctype = CacheRequestType_ATOMIC; break; default: -- cgit v1.2.3 From 86ce60e5cd9524b4130d361e1f7ea0a2ba266e5b Mon Sep 17 00:00:00 2001 From: Polina Dudnik Date: Mon, 13 Jul 2009 11:25:23 -0500 Subject: Forgot to replace one of the RubyRequest_RMW --- src/mem/ruby/system/Sequencer.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src/mem/ruby/system') diff --git a/src/mem/ruby/system/Sequencer.cc b/src/mem/ruby/system/Sequencer.cc index d7d4ba8e0..dc65d6fc6 100644 --- a/src/mem/ruby/system/Sequencer.cc +++ b/src/mem/ruby/system/Sequencer.cc @@ -201,7 +201,8 @@ bool Sequencer::insertRequest(SequencerRequest* request) { Address line_addr(request->ruby_request.paddr); line_addr.makeLineAddress(); if ((request->ruby_request.type == RubyRequestType_ST) || - (request->ruby_request.type == RubyRequestType_RMW)) { + (request->ruby_request.type == RubyRequestType_RMW_Read) || + (request->ruby_request.type == RubyRequestType_RMW_Write)) { if (m_writeRequestTable.exist(line_addr)) { m_writeRequestTable.lookup(line_addr) = request; // return true; -- cgit v1.2.3 From faf823f947f2318687f9c9e2e05ba6ab919abe14 Mon Sep 17 00:00:00 2001 From: Polina Dudnik Date: Mon, 13 Jul 2009 11:34:38 -0500 Subject: Moved the lock check and clearing the lock into makeRequest --- src/mem/ruby/system/Sequencer.cc | 23 ++++++++++------------- 1 file changed, 10 insertions(+), 13 deletions(-) (limited to 'src/mem/ruby/system') diff --git a/src/mem/ruby/system/Sequencer.cc b/src/mem/ruby/system/Sequencer.cc index dc65d6fc6..db60bb11a 100644 --- a/src/mem/ruby/system/Sequencer.cc +++ b/src/mem/ruby/system/Sequencer.cc @@ -264,19 +264,6 @@ void Sequencer::writeCallback(const Address& address, DataBlock& data) { if (request->ruby_request.type == RubyRequestType_RMW_Read) { m_dataCache_ptr->setLocked(address, m_version); } - else if (request->ruby_request.type == RubyRequestType_RMW_Write) { - if (m_dataCache_ptr->isLocked(address, m_version)) { - // if we are holding the lock for this - request->ruby_request.atomic_success = true; - m_dataCache_ptr->clearLocked(address); - } - else { - // if we are not holding the lock for this - request->ruby_request.atomic_success = false; - } - - // can have livelock - } hitCallback(request, data); } @@ -367,6 +354,8 @@ bool Sequencer::empty() const { return (m_writeRequestTable.size() == 0) && (m_readRequestTable.size() == 0); } + +// -2 means that the LLSC failed int64_t Sequencer::makeRequest(const RubyRequest & request) { assert(Address(request.paddr).getOffset() + request.len <= RubySystem::getBlockSizeBytes()); @@ -375,6 +364,14 @@ int64_t Sequencer::makeRequest(const RubyRequest & request) SequencerRequest *srequest = new SequencerRequest(request, id, g_eventQueue_ptr->getTime()); bool found = insertRequest(srequest); if (!found) + if (request.type == RubyRequestType_RMW_Write) { + if (!m_dataCache_ptr->isLocked(line_address(Address(request.paddr)), m_version)) { + return -2; + } + else { + m_dataCache_ptr->clearLocked(line_address(Address(request.paddr))); + } + } issueRequest(request); // TODO: issue hardware prefetches here -- cgit v1.2.3 From 7606c71ea593f46843a0fa91983ae89139271728 Mon Sep 17 00:00:00 2001 From: Polina Dudnik Date: Mon, 13 Jul 2009 11:37:56 -0500 Subject: Replaced RMW with Locked. RMW will be used for the coherence-aided atomics other than LLSC --- src/mem/ruby/system/DMASequencer.cc | 3 ++- src/mem/ruby/system/Sequencer.cc | 20 ++++++++++---------- 2 files changed, 12 insertions(+), 11 deletions(-) (limited to 'src/mem/ruby/system') diff --git a/src/mem/ruby/system/DMASequencer.cc b/src/mem/ruby/system/DMASequencer.cc index 4aa092113..ec5e0b49f 100644 --- a/src/mem/ruby/system/DMASequencer.cc +++ b/src/mem/ruby/system/DMASequencer.cc @@ -46,7 +46,8 @@ int64_t DMASequencer::makeRequest(const RubyRequest & request) break; case RubyRequestType_NULL: case RubyRequestType_IFETCH: - case RubyRequestType_RMW: + case RubyRequestType_Locked_Read: + case RubyRequestType_Locked_Write: assert(0); } diff --git a/src/mem/ruby/system/Sequencer.cc b/src/mem/ruby/system/Sequencer.cc index db60bb11a..c3a8e9424 100644 --- a/src/mem/ruby/system/Sequencer.cc +++ b/src/mem/ruby/system/Sequencer.cc @@ -201,8 +201,8 @@ bool Sequencer::insertRequest(SequencerRequest* request) { Address line_addr(request->ruby_request.paddr); line_addr.makeLineAddress(); if ((request->ruby_request.type == RubyRequestType_ST) || - (request->ruby_request.type == RubyRequestType_RMW_Read) || - (request->ruby_request.type == RubyRequestType_RMW_Write)) { + (request->ruby_request.type == RubyRequestType_Locked_Read) || + (request->ruby_request.type == RubyRequestType_Locked_Write)) { if (m_writeRequestTable.exist(line_addr)) { m_writeRequestTable.lookup(line_addr) = request; // return true; @@ -238,8 +238,8 @@ void Sequencer::removeRequest(SequencerRequest* srequest) { Address line_addr(ruby_request.paddr); line_addr.makeLineAddress(); if ((ruby_request.type == RubyRequestType_ST) || - (ruby_request.type == RubyRequestType_RMW_Read) || - (ruby_request.type == RubyRequestType_RMW_Write)) { + (ruby_request.type == RubyRequestType_Locked_Read) || + (ruby_request.type == RubyRequestType_Locked_Write)) { m_writeRequestTable.deallocate(line_addr); } else { m_readRequestTable.deallocate(line_addr); @@ -258,10 +258,10 @@ void Sequencer::writeCallback(const Address& address, DataBlock& data) { removeRequest(request); assert((request->ruby_request.type == RubyRequestType_ST) || - (request->ruby_request.type == RubyRequestType_RMW_Read) || - (request->ruby_request.type == RubyRequestType_RMW_Write)); + (request->ruby_request.type == RubyRequestType_Locked_Read) || + (request->ruby_request.type == RubyRequestType_Locked_Write)); // POLINA: the assumption is that atomics are only on data cache and not instruction cache - if (request->ruby_request.type == RubyRequestType_RMW_Read) { + if (request->ruby_request.type == RubyRequestType_Locked_Read) { m_dataCache_ptr->setLocked(address, m_version); } @@ -364,7 +364,7 @@ int64_t Sequencer::makeRequest(const RubyRequest & request) SequencerRequest *srequest = new SequencerRequest(request, id, g_eventQueue_ptr->getTime()); bool found = insertRequest(srequest); if (!found) - if (request.type == RubyRequestType_RMW_Write) { + if (request.type == RubyRequestType_Locked_Write) { if (!m_dataCache_ptr->isLocked(line_address(Address(request.paddr)), m_version)) { return -2; } @@ -396,10 +396,10 @@ void Sequencer::issueRequest(const RubyRequest& request) { case RubyRequestType_ST: ctype = CacheRequestType_ST; break; - case RubyRequestType_RMW_Read: + case RubyRequestType_Locked_Read: ctype = CacheRequestType_ATOMIC; break; - case RubyRequestType_RMW_Write: + case RubyRequestType_Locked_Write: ctype = CacheRequestType_ATOMIC; break; default: -- cgit v1.2.3 From c66af9f47400a7768de7cd6cb47fe757a601e445 Mon Sep 17 00:00:00 2001 From: Polina Dudnik Date: Mon, 13 Jul 2009 11:59:13 -0500 Subject: Minor fixes for compiling --- src/mem/ruby/system/CacheMemory.hh | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src/mem/ruby/system') diff --git a/src/mem/ruby/system/CacheMemory.hh b/src/mem/ruby/system/CacheMemory.hh index cde5b6d94..625d5ce59 100644 --- a/src/mem/ruby/system/CacheMemory.hh +++ b/src/mem/ruby/system/CacheMemory.hh @@ -551,6 +551,8 @@ void CacheMemory::changePermission(const Address& address, AccessPermission new_ { assert(address == line_address(address)); lookup(address).m_Permission = new_perm; + Index cacheSet = addressToCacheSet(address); + int loc = findTagInSet(cacheSet, address); m_locked[cacheSet][loc] = -1; assert(getPermission(address) == new_perm); } -- cgit v1.2.3 From b28058917c7bd324ca2b080a0a5f7ba617ea4c40 Mon Sep 17 00:00:00 2001 From: Polina Dudnik Date: Mon, 13 Jul 2009 12:11:17 -0500 Subject: Locked requests should actually be converted to ST rather than ATOMIC, because ATOMIC is for RMW. --- src/mem/ruby/system/Sequencer.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/mem/ruby/system') diff --git a/src/mem/ruby/system/Sequencer.cc b/src/mem/ruby/system/Sequencer.cc index c3a8e9424..eb694fa13 100644 --- a/src/mem/ruby/system/Sequencer.cc +++ b/src/mem/ruby/system/Sequencer.cc @@ -397,10 +397,10 @@ void Sequencer::issueRequest(const RubyRequest& request) { ctype = CacheRequestType_ST; break; case RubyRequestType_Locked_Read: - ctype = CacheRequestType_ATOMIC; + ctype = CacheRequestType_ST; break; case RubyRequestType_Locked_Write: - ctype = CacheRequestType_ATOMIC; + ctype = CacheRequestType_ST; break; default: assert(0); -- cgit v1.2.3 From 9a675a0391aa0c0463baf8bac0b9209b675306a8 Mon Sep 17 00:00:00 2001 From: Polina Dudnik Date: Mon, 13 Jul 2009 12:50:10 -0500 Subject: Changes to add tracing and replaying command-line options Trace is automatically ended upon a manual checkpoint --- src/mem/ruby/system/System.hh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/mem/ruby/system') diff --git a/src/mem/ruby/system/System.hh b/src/mem/ruby/system/System.hh index 40c425ad7..8cbeb2b0e 100644 --- a/src/mem/ruby/system/System.hh +++ b/src/mem/ruby/system/System.hh @@ -106,7 +106,7 @@ public: 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; } + static Tracer* getTracer() { assert(m_tracer_ptr != NULL); return m_tracer_ptr; } static MemoryVector* getMemoryVector() { assert(m_mem_vec_ptr != NULL); return m_mem_vec_ptr;} void recordCacheContents(CacheRecorder& tr) const; -- cgit v1.2.3 From 5f551d9ca2b61fc97b9530334e538195a84589b3 Mon Sep 17 00:00:00 2001 From: Polina Dudnik Date: Mon, 13 Jul 2009 17:22:29 -0500 Subject: 1. Got rid of unused functions in DirectoryMemory 2. Reintroduced RMW_Read and RMW_Write 3. Defined -2 in the Sequencer as well as made a note about mandatory queue Did not address the issues in the slicc because remaking the atomics altogether to allow multiple processors to issue atomic requests at once --- src/mem/ruby/system/DMASequencer.cc | 2 ++ src/mem/ruby/system/Sequencer.cc | 19 +++++++++++++++++-- 2 files changed, 19 insertions(+), 2 deletions(-) (limited to 'src/mem/ruby/system') diff --git a/src/mem/ruby/system/DMASequencer.cc b/src/mem/ruby/system/DMASequencer.cc index ec5e0b49f..8f7b1c912 100644 --- a/src/mem/ruby/system/DMASequencer.cc +++ b/src/mem/ruby/system/DMASequencer.cc @@ -48,6 +48,8 @@ int64_t DMASequencer::makeRequest(const RubyRequest & request) case RubyRequestType_IFETCH: case RubyRequestType_Locked_Read: case RubyRequestType_Locked_Write: + case RubyRequestType_RMW_Read: + case RubyRequestType_RMW_Write: assert(0); } diff --git a/src/mem/ruby/system/Sequencer.cc b/src/mem/ruby/system/Sequencer.cc index eb694fa13..1587aa5fa 100644 --- a/src/mem/ruby/system/Sequencer.cc +++ b/src/mem/ruby/system/Sequencer.cc @@ -43,6 +43,8 @@ //Sequencer::Sequencer(int core_id, MessageBuffer* mandatory_q) +#define LLSC_FAIL -2 + Sequencer::Sequencer(const string & name) :RubyPort(name) { @@ -201,6 +203,8 @@ bool Sequencer::insertRequest(SequencerRequest* request) { Address line_addr(request->ruby_request.paddr); line_addr.makeLineAddress(); if ((request->ruby_request.type == RubyRequestType_ST) || + (request->ruby_request.type == RubyRequestType_RMW_Read) || + (request->ruby_request.type == RubyRequestType_RMW_Write) || (request->ruby_request.type == RubyRequestType_Locked_Read) || (request->ruby_request.type == RubyRequestType_Locked_Write)) { if (m_writeRequestTable.exist(line_addr)) { @@ -238,6 +242,8 @@ void Sequencer::removeRequest(SequencerRequest* srequest) { Address line_addr(ruby_request.paddr); line_addr.makeLineAddress(); if ((ruby_request.type == RubyRequestType_ST) || + (ruby_request.type == RubyRequestType_RMW_Read) || + (ruby_request.type == RubyRequestType_RMW_Write) || (ruby_request.type == RubyRequestType_Locked_Read) || (ruby_request.type == RubyRequestType_Locked_Write)) { m_writeRequestTable.deallocate(line_addr); @@ -258,6 +264,8 @@ void Sequencer::writeCallback(const Address& address, DataBlock& data) { removeRequest(request); assert((request->ruby_request.type == RubyRequestType_ST) || + (request->ruby_request.type == RubyRequestType_RMW_Read) || + (request->ruby_request.type == RubyRequestType_RMW_Write) || (request->ruby_request.type == RubyRequestType_Locked_Read) || (request->ruby_request.type == RubyRequestType_Locked_Write)); // POLINA: the assumption is that atomics are only on data cache and not instruction cache @@ -355,7 +363,6 @@ bool Sequencer::empty() const { } -// -2 means that the LLSC failed int64_t Sequencer::makeRequest(const RubyRequest & request) { assert(Address(request.paddr).getOffset() + request.len <= RubySystem::getBlockSizeBytes()); @@ -365,8 +372,10 @@ int64_t Sequencer::makeRequest(const RubyRequest & request) bool found = insertRequest(srequest); if (!found) if (request.type == RubyRequestType_Locked_Write) { + // NOTE: it is OK to check the locked flag here as the mandatory queue will be checked first + // ensuring that nothing comes between checking the flag and servicing the store if (!m_dataCache_ptr->isLocked(line_address(Address(request.paddr)), m_version)) { - return -2; + return LLSC_FAIL; } else { m_dataCache_ptr->clearLocked(line_address(Address(request.paddr))); @@ -402,6 +411,12 @@ void Sequencer::issueRequest(const RubyRequest& request) { case RubyRequestType_Locked_Write: ctype = CacheRequestType_ST; break; + case RubyRequestType_RMW_Read: + ctype = CacheRequestType_ATOMIC; + break; + case RubyRequestType_RMW_Write: + ctype = CacheRequestType_ATOMIC; + break; default: assert(0); } -- cgit v1.2.3