From 226981b2a65ee4c544bc595d7718de8225fda0b0 Mon Sep 17 00:00:00 2001 From: Polina Dudnik Date: Mon, 13 Jul 2009 11:13:29 -0500 Subject: [PATCH 01/19] Reintegrated Derek's functional implementation of atomics with a minor change: don't clear lock on failure --- src/mem/ruby/common/DataBlock.hh | 18 +++++++++++++ src/mem/ruby/libruby.cc | 12 ++++++--- src/mem/ruby/libruby.hh | 3 ++- src/mem/ruby/system/CacheMemory.hh | 43 ++++++++++++++++++++++++++++++ src/mem/ruby/system/Sequencer.cc | 28 ++++++++++++++++--- 5 files changed, 96 insertions(+), 8 deletions(-) diff --git a/src/mem/ruby/common/DataBlock.hh b/src/mem/ruby/common/DataBlock.hh index 2a0811f76..c7dba8ae8 100644 --- a/src/mem/ruby/common/DataBlock.hh +++ b/src/mem/ruby/common/DataBlock.hh @@ -56,6 +56,9 @@ class DataBlock { uint8 getByte(int whichByte) const; const uint8* getData(int offset, int len) const; void setByte(int whichByte, uint8 data); + const uint8* getBlock() const; + uint8* copyData(uint8* dest, int offset, int size) const; + void setBlock(uint8* data) { setData(data, 0, System::getBlockSizeBytes()); } void setData(uint8* data, int offset, int len); void copyPartial(const DataBlock & dblk, int offset, int len); bool equal(const DataBlock& obj) const; @@ -146,6 +149,21 @@ void DataBlock::copyPartial(const DataBlock & dblk, int offset, int len) setData(&dblk.m_data[offset], offset, len); } +inline +const uint8* DataBlock::getBlock() const +{ + return m_data; +} + +inline +uint8* DataBlock::copyData(uint8* dest, int offset, int size) const +{ + assert(offset + size <= RubySystem::getBlockSizeBytes()); + memcpy(dest, m_data + offset, size); + return dest; +} + + // ******************* Definitions ******************* // Output operator definition diff --git a/src/mem/ruby/libruby.cc b/src/mem/ruby/libruby.cc index 987f4fd10..d21b29dec 100644 --- a/src/mem/ruby/libruby.cc +++ b/src/mem/ruby/libruby.cc @@ -19,8 +19,10 @@ string RubyRequestType_to_string(const RubyRequestType& obj) return "LD"; case RubyRequestType_ST: return "ST"; - case RubyRequestType_RMW: - return "RMW"; + case RubyRequestType_RMW_Read: + return "RMW_Read"; + case RubyRequestType_RMW_Write: + return "RMW_Write"; case RubyRequestType_NULL: default: assert(0); @@ -36,8 +38,10 @@ RubyRequestType string_to_RubyRequestType(std::string str) return RubyRequestType_LD; else if (str == "ST") return RubyRequestType_ST; - else if (str == "RMW") - return RubyRequestType_RMW; + else if (str == "RMW_Read") + return RubyRequestType_RMW_Read; + else if (str == "RMW_Write") + return RubyRequestType_RMW_Write; else assert(0); return RubyRequestType_NULL; diff --git a/src/mem/ruby/libruby.hh b/src/mem/ruby/libruby.hh index 5916c98e6..8edcfa0fc 100644 --- a/src/mem/ruby/libruby.hh +++ b/src/mem/ruby/libruby.hh @@ -11,7 +11,8 @@ enum RubyRequestType { RubyRequestType_IFETCH, RubyRequestType_LD, RubyRequestType_ST, - RubyRequestType_RMW + RubyRequestType_RMW_Read, + RubyRequestType_RMW_Write }; enum RubyAccessMode { 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: From 86ce60e5cd9524b4130d361e1f7ea0a2ba266e5b Mon Sep 17 00:00:00 2001 From: Polina Dudnik Date: Mon, 13 Jul 2009 11:25:23 -0500 Subject: [PATCH 02/19] Forgot to replace one of the RubyRequest_RMW --- src/mem/ruby/system/Sequencer.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) 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; From faf823f947f2318687f9c9e2e05ba6ab919abe14 Mon Sep 17 00:00:00 2001 From: Polina Dudnik Date: Mon, 13 Jul 2009 11:34:38 -0500 Subject: [PATCH 03/19] Moved the lock check and clearing the lock into makeRequest --- src/mem/ruby/system/Sequencer.cc | 23 ++++++++++------------- 1 file changed, 10 insertions(+), 13 deletions(-) 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 From 7606c71ea593f46843a0fa91983ae89139271728 Mon Sep 17 00:00:00 2001 From: Polina Dudnik Date: Mon, 13 Jul 2009 11:37:56 -0500 Subject: [PATCH 04/19] Replaced RMW with Locked. RMW will be used for the coherence-aided atomics other than LLSC --- src/mem/ruby/libruby.cc | 16 ++++++++-------- src/mem/ruby/libruby.hh | 4 ++-- src/mem/ruby/recorder/TraceRecord.cc | 5 ++++- src/mem/ruby/system/DMASequencer.cc | 3 ++- src/mem/ruby/system/Sequencer.cc | 20 ++++++++++---------- 5 files changed, 26 insertions(+), 22 deletions(-) diff --git a/src/mem/ruby/libruby.cc b/src/mem/ruby/libruby.cc index d21b29dec..d35600960 100644 --- a/src/mem/ruby/libruby.cc +++ b/src/mem/ruby/libruby.cc @@ -19,10 +19,10 @@ string RubyRequestType_to_string(const RubyRequestType& obj) return "LD"; case RubyRequestType_ST: return "ST"; - case RubyRequestType_RMW_Read: - return "RMW_Read"; - case RubyRequestType_RMW_Write: - return "RMW_Write"; + case RubyRequestType_Locked_Read: + return "Locked_Read"; + case RubyRequestType_Locked_Write: + return "Locked_Write"; case RubyRequestType_NULL: default: assert(0); @@ -38,10 +38,10 @@ RubyRequestType string_to_RubyRequestType(std::string str) return RubyRequestType_LD; else if (str == "ST") return RubyRequestType_ST; - else if (str == "RMW_Read") - return RubyRequestType_RMW_Read; - else if (str == "RMW_Write") - return RubyRequestType_RMW_Write; + else if (str == "Locked_Read") + return RubyRequestType_Locked_Read; + else if (str == "Locked_Write") + return RubyRequestType_Locked_Write; else assert(0); return RubyRequestType_NULL; diff --git a/src/mem/ruby/libruby.hh b/src/mem/ruby/libruby.hh index 8edcfa0fc..85de794f1 100644 --- a/src/mem/ruby/libruby.hh +++ b/src/mem/ruby/libruby.hh @@ -11,8 +11,8 @@ enum RubyRequestType { RubyRequestType_IFETCH, RubyRequestType_LD, RubyRequestType_ST, - RubyRequestType_RMW_Read, - RubyRequestType_RMW_Write + RubyRequestType_Locked_Read, + RubyRequestType_Locked_Write }; enum RubyAccessMode { diff --git a/src/mem/ruby/recorder/TraceRecord.cc b/src/mem/ruby/recorder/TraceRecord.cc index 1521d2a3f..6cc33665b 100644 --- a/src/mem/ruby/recorder/TraceRecord.cc +++ b/src/mem/ruby/recorder/TraceRecord.cc @@ -47,7 +47,10 @@ TraceRecord::TraceRecord(const string & sequencer_name, const Address& data_addr // Don't differentiate between store misses and atomic requests in // the trace - if (m_type == RubyRequestType_RMW) { + if (m_type == RubyRequestType_Locked_Read) { + m_type = RubyRequestType_ST; + } + if (m_type == RubyRequestType_Locked_Write) { m_type = RubyRequestType_ST; } } 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: From c66af9f47400a7768de7cd6cb47fe757a601e445 Mon Sep 17 00:00:00 2001 From: Polina Dudnik Date: Mon, 13 Jul 2009 11:59:13 -0500 Subject: [PATCH 05/19] Minor fixes for compiling --- src/mem/ruby/common/DataBlock.hh | 2 +- src/mem/ruby/system/CacheMemory.hh | 2 ++ src/mem/rubymem.cc | 4 ++-- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/mem/ruby/common/DataBlock.hh b/src/mem/ruby/common/DataBlock.hh index c7dba8ae8..01194c0ac 100644 --- a/src/mem/ruby/common/DataBlock.hh +++ b/src/mem/ruby/common/DataBlock.hh @@ -58,7 +58,7 @@ class DataBlock { void setByte(int whichByte, uint8 data); const uint8* getBlock() const; uint8* copyData(uint8* dest, int offset, int size) const; - void setBlock(uint8* data) { setData(data, 0, System::getBlockSizeBytes()); } + void setBlock(uint8* data) { setData(data, 0, RubySystem::getBlockSizeBytes()); } void setData(uint8* data, int offset, int len); void copyPartial(const DataBlock & dblk, int offset, int len); bool equal(const DataBlock& obj) const; 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); } diff --git a/src/mem/rubymem.cc b/src/mem/rubymem.cc index 62685a71b..a4aec4c0a 100644 --- a/src/mem/rubymem.cc +++ b/src/mem/rubymem.cc @@ -230,8 +230,8 @@ RubyMemory::Port::recvTiming(PacketPtr pkt) } } else if (pkt->isWrite()) { type = RubyRequestType_ST; - } else if (pkt->isReadWrite()) { - type = RubyRequestType_RMW; +// } else if (pkt->isReadWrite()) { +// type = RubyRequestType_RMW; } RubyRequest ruby_request(pkt->getAddr(), pkt->getPtr(), From 7a6bf67e47196fb9e6f3cac049203107381f7723 Mon Sep 17 00:00:00 2001 From: Polina Dudnik Date: Mon, 13 Jul 2009 12:06:23 -0500 Subject: [PATCH 06/19] Added atomics implementation which would work for MI_example --- src/mem/slicc/symbols/StateMachine.cc | 112 ++++++++++++++++++++++++-- 1 file changed, 106 insertions(+), 6 deletions(-) diff --git a/src/mem/slicc/symbols/StateMachine.cc b/src/mem/slicc/symbols/StateMachine.cc index f2a40d3d7..896b37a91 100644 --- a/src/mem/slicc/symbols/StateMachine.cc +++ b/src/mem/slicc/symbols/StateMachine.cc @@ -759,6 +759,17 @@ void StateMachine::printCWakeup(ostream& out, string component) out << "#include \"mem/protocol/Types.hh\"" << endl; out << "#include \"mem/ruby/system/System.hh\"" << endl; out << endl; + if (strncmp(component.c_str(), "L1Cache", 7) == 0) { + out << "NodeID servicing_atomic = -1;" << endl; + out << endl; + out << "Address locked_read_request = Address(-1);" << endl; + out << endl; + out << "NodeID servicing_locked_read = -1;" << endl; + out << endl; + } + else { + cout << component << endl << flush; + } out << "void " << component << "_Controller::wakeup()" << endl; out << "{" << endl; // out << " DEBUG_EXPR(GENERATED_COMP, MedPrio,*this);" << endl; @@ -775,14 +786,103 @@ void StateMachine::printCWakeup(ostream& out, string component) out << " }" << endl; // InPorts + // + // Find the position of the mandatory queue in the vector so that we can print it out first + int j = -1; + if (strncmp(component.c_str(), "L1Cache", 7) == 0) { + for(int i=0; i < m_in_ports.size(); i++) { + const Var* port = m_in_ports[i]; + assert(port->existPair("c_code_in_port")); + if (port->toString().find("mandatoryQueue_in") != string::npos) { + assert (j == -1); + j = i; + } + else { + cout << port->toString() << endl << flush; + } + } + + assert(j != -1); + + // print out the mandatory queue here + const Var* port = m_in_ports[j]; + assert(port->existPair("c_code_in_port")); + out << " // " + << component << "InPort " << port->toString() + << endl; + string output = port->lookupPair("c_code_in_port"); + string::size_type pos = output.find("TransitionResult result = doTransition((L1Cache_mandatory_request_type_to_event(((*in_msg_ptr)).m_Type)), L1Cache_getState(addr), addr);"); + assert(pos != string::npos); + string atomics_string = "\n \ + bool postpone = false; \n \ + if ((((*in_msg_ptr)).m_Type) == CacheRequestType_ATOMIC) { \n \ + if (servicing_atomic == -1) { \n \ + if (locked_read_request == Address(-1) && (servicing_locked_read == -1)) { \n \ + assert(addr != Address(-1)); \n \ + locked_read_request = addr; \n \ + servicing_locked_read = m_version; \n \ + } \n \ + else if ((addr == locked_read_request) && (servicing_locked_read == m_version)) { \n \ + assert (servicing_atomic == -1); \n \ + servicing_atomic = m_version; \n \ + } \n \ + else { \n \ + postpone = true; \n \ + g_eventQueue_ptr->scheduleEvent(this, 1); \n \ + } \n \ + } \n \ + else { \n \ + postpone = true; \n \ + g_eventQueue_ptr->scheduleEvent(this, 1); \n \ + } \n \ + } \n \ + if (servicing_atomic == m_version) { \n \ + servicing_atomic = -1; \n \ + locked_read_request = Address(-1); \n \ + servicing_locked_read = -1; \n \ + } \n \ + if (!postpone) { \n \ + "; + + + + output.insert(pos, atomics_string); + string::size_type next_pos = output.find("// Cannot do anything with this transition, go check next doable transition (mostly likely of next port)", pos); + assert(next_pos != string::npos); + string complete = "\n}"; + output.insert(next_pos, complete); + //out << port->lookupPair("c_code_in_port"); + out << output; + out << endl; + } for(int i=0; i < m_in_ports.size(); i++) { const Var* port = m_in_ports[i]; - assert(port->existPair("c_code_in_port")); - out << " // " - << component << "InPort " << port->toString() - << endl; - out << port->lookupPair("c_code_in_port"); - out << endl; + // don't print out mandatory queue twice + if (i != j) { + if (strncmp(component.c_str(), "L1Cache", 7) == 0) { + if (port->toString().find("forwardRequestNetwork_in") != string::npos) { + out << "if (servicing_atomic != m_version && servicing_locked_read != m_version) {" << endl; + } + else if (port->toString().find("responseNetwork_in") != string::npos) { + out << "// NOTE: this will only work if the WB_ACK always comes before issuing a request for which this line was replaced" << endl; + out << "if (servicing_atomic == -1 || servicing_atomic == m_version) {" << endl; + } + } + assert(port->existPair("c_code_in_port")); + out << " // " + << component << "InPort " << port->toString() + << endl; + out << port->lookupPair("c_code_in_port"); + if (strncmp(component.c_str(), "L1Cache", 7) == 0) { + if (port->toString().find("forwardRequestNetwork_in") != string::npos) { + out << "}" << endl; + } + else if (port->toString().find("responseNetwork_in") != string::npos) { + out << "}" << endl; + } + } + out << endl; + } } out << " break; // If we got this far, we have nothing left todo" << endl; From b28058917c7bd324ca2b080a0a5f7ba617ea4c40 Mon Sep 17 00:00:00 2001 From: Polina Dudnik Date: Mon, 13 Jul 2009 12:11:17 -0500 Subject: [PATCH 07/19] 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(-) 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); From 9a675a0391aa0c0463baf8bac0b9209b675306a8 Mon Sep 17 00:00:00 2001 From: Polina Dudnik Date: Mon, 13 Jul 2009 12:50:10 -0500 Subject: [PATCH 08/19] Changes to add tracing and replaying command-line options Trace is automatically ended upon a manual checkpoint --- src/mem/ruby/libruby.cc | 15 +++++++++++++++ src/mem/ruby/libruby.hh | 14 ++++++++++++++ src/mem/ruby/recorder/Tracer.cc | 9 +++++---- src/mem/ruby/system/System.hh | 2 +- 4 files changed, 35 insertions(+), 5 deletions(-) diff --git a/src/mem/ruby/libruby.cc b/src/mem/ruby/libruby.cc index d35600960..185797f59 100644 --- a/src/mem/ruby/libruby.cc +++ b/src/mem/ruby/libruby.cc @@ -9,6 +9,7 @@ #include "mem/ruby/eventqueue/RubyEventQueue.hh" #include "mem/ruby/system/MemoryVector.hh" #include "mem/ruby/common/Address.hh" +#include "mem/ruby/recorder/Tracer.hh" string RubyRequestType_to_string(const RubyRequestType& obj) { @@ -204,6 +205,20 @@ void libruby_print_stats(std::ostream & out) { RubySystem::printStats(out); } +void libruby_playback_trace(char * trace_filename) +{ + RubySystem::getTracer()->playbackTrace(trace_filename); +} + +void libruby_start_tracing(char * record_filename) { + // start the trace + RubySystem::getTracer()->startTrace(record_filename); +} + +void libruby_stop_tracing() { + // start the trace + RubySystem::getTracer()->stopTrace(); +} uint64_t libruby_get_time() { return RubySystem::getCycleCount(0); diff --git a/src/mem/ruby/libruby.hh b/src/mem/ruby/libruby.hh index 85de794f1..5eb5e965c 100644 --- a/src/mem/ruby/libruby.hh +++ b/src/mem/ruby/libruby.hh @@ -102,6 +102,20 @@ void libruby_print_config(std::ostream & out); */ void libruby_print_stats(std::ostream & out); +/** + * does not return until done + */ +void libruby_playback_trace(char * trace_filename); + +/* + * enables the tracer and opens the trace file + */ +void libruby_start_tracing(char * record_filename); + +/* + * closes the trace file + */ +void libruby_stop_tracing(); /** * get time diff --git a/src/mem/ruby/recorder/Tracer.cc b/src/mem/ruby/recorder/Tracer.cc index d2df544d8..5b1e4274b 100644 --- a/src/mem/ruby/recorder/Tracer.cc +++ b/src/mem/ruby/recorder/Tracer.cc @@ -92,10 +92,11 @@ void Tracer::startTrace(string filename) void Tracer::stopTrace() { - assert(m_enabled == true); - m_trace_file.close(); - cout << "Request trace file closed." << endl; - m_enabled = false; + if (m_enabled == true) { + m_trace_file.close(); + cout << "Request trace file closed." << endl; + m_enabled = false; + } } void Tracer::traceRequest(const string & sequencer_name, const Address& data_addr, const Address& pc_addr, RubyRequestType type, Time time) 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; From 5f551d9ca2b61fc97b9530334e538195a84589b3 Mon Sep 17 00:00:00 2001 From: Polina Dudnik Date: Mon, 13 Jul 2009 17:22:29 -0500 Subject: [PATCH 09/19] 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/common/DataBlock.hh | 18 ------------------ src/mem/ruby/libruby.cc | 8 ++++++++ src/mem/ruby/libruby.hh | 4 +++- src/mem/ruby/recorder/TraceRecord.cc | 2 +- src/mem/ruby/system/DMASequencer.cc | 2 ++ src/mem/ruby/system/Sequencer.cc | 19 +++++++++++++++++-- 6 files changed, 31 insertions(+), 22 deletions(-) diff --git a/src/mem/ruby/common/DataBlock.hh b/src/mem/ruby/common/DataBlock.hh index 01194c0ac..2a0811f76 100644 --- a/src/mem/ruby/common/DataBlock.hh +++ b/src/mem/ruby/common/DataBlock.hh @@ -56,9 +56,6 @@ class DataBlock { uint8 getByte(int whichByte) const; const uint8* getData(int offset, int len) const; void setByte(int whichByte, uint8 data); - const uint8* getBlock() const; - uint8* copyData(uint8* dest, int offset, int size) const; - void setBlock(uint8* data) { setData(data, 0, RubySystem::getBlockSizeBytes()); } void setData(uint8* data, int offset, int len); void copyPartial(const DataBlock & dblk, int offset, int len); bool equal(const DataBlock& obj) const; @@ -149,21 +146,6 @@ void DataBlock::copyPartial(const DataBlock & dblk, int offset, int len) setData(&dblk.m_data[offset], offset, len); } -inline -const uint8* DataBlock::getBlock() const -{ - return m_data; -} - -inline -uint8* DataBlock::copyData(uint8* dest, int offset, int size) const -{ - assert(offset + size <= RubySystem::getBlockSizeBytes()); - memcpy(dest, m_data + offset, size); - return dest; -} - - // ******************* Definitions ******************* // Output operator definition diff --git a/src/mem/ruby/libruby.cc b/src/mem/ruby/libruby.cc index 185797f59..b867fec34 100644 --- a/src/mem/ruby/libruby.cc +++ b/src/mem/ruby/libruby.cc @@ -24,6 +24,10 @@ string RubyRequestType_to_string(const RubyRequestType& obj) return "Locked_Read"; case RubyRequestType_Locked_Write: return "Locked_Write"; + case RubyRequestType_RMW_Read: + return "RMW_Read"; + case RubyRequestType_RMW_Write: + return "RMW_Write"; case RubyRequestType_NULL: default: assert(0); @@ -43,6 +47,10 @@ RubyRequestType string_to_RubyRequestType(std::string str) return RubyRequestType_Locked_Read; else if (str == "Locked_Write") return RubyRequestType_Locked_Write; + else if (str == "RMW_Read") + return RubyRequestType_RMW_Read; + else if (str == "RMW_Write") + return RubyRequestType_RMW_Write; else assert(0); return RubyRequestType_NULL; diff --git a/src/mem/ruby/libruby.hh b/src/mem/ruby/libruby.hh index 5eb5e965c..94018e9b9 100644 --- a/src/mem/ruby/libruby.hh +++ b/src/mem/ruby/libruby.hh @@ -12,7 +12,9 @@ enum RubyRequestType { RubyRequestType_LD, RubyRequestType_ST, RubyRequestType_Locked_Read, - RubyRequestType_Locked_Write + RubyRequestType_Locked_Write, + RubyRequestType_RMW_Read, + RubyRequestType_RMW_Write }; enum RubyAccessMode { diff --git a/src/mem/ruby/recorder/TraceRecord.cc b/src/mem/ruby/recorder/TraceRecord.cc index 6cc33665b..8f426d690 100644 --- a/src/mem/ruby/recorder/TraceRecord.cc +++ b/src/mem/ruby/recorder/TraceRecord.cc @@ -50,7 +50,7 @@ TraceRecord::TraceRecord(const string & sequencer_name, const Address& data_addr if (m_type == RubyRequestType_Locked_Read) { m_type = RubyRequestType_ST; } - if (m_type == RubyRequestType_Locked_Write) { + else if (m_type == RubyRequestType_Locked_Write) { m_type = RubyRequestType_ST; } } 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); } From 289cd003263b5ea38c9e513d7246bede2ca7539d Mon Sep 17 00:00:00 2001 From: Polina Dudnik Date: Mon, 13 Jul 2009 18:39:32 -0500 Subject: [PATCH 10/19] Changed the state machine to generate code such that multiple processors can make atomic requests at once --- src/mem/slicc/symbols/StateMachine.cc | 114 ++++++++++++++------------ 1 file changed, 62 insertions(+), 52 deletions(-) diff --git a/src/mem/slicc/symbols/StateMachine.cc b/src/mem/slicc/symbols/StateMachine.cc index 896b37a91..64c7ae24a 100644 --- a/src/mem/slicc/symbols/StateMachine.cc +++ b/src/mem/slicc/symbols/StateMachine.cc @@ -282,13 +282,16 @@ void StateMachine::printControllerH(ostream& out, string component) out << " void printStats(ostream& out) const { s_profiler.dumpStats(out); }" << endl; out << " void clearStats() { s_profiler.clearStats(); }" << endl; out << "private:" << endl; - //added by SS // found_to_mem = 0; std::vector::const_iterator it; for(it=m_latency_vector.begin();it!=m_latency_vector.end();it++){ out << " int m_" << (*it)->c_str() << ";" << endl; } + if (strncmp(component.c_str(), "L1Cache", 7) == 0) { + out << " bool servicing_atomic;" << endl; + out << " Address locked_read_request;" << endl; + } out << " int m_number_of_TBEs;" << endl; out << " TransitionResult doTransition(" << component << "_Event event, " << component @@ -399,7 +402,11 @@ void StateMachine::printControllerC(ostream& out, string component) << "_Controller(const string & name)" << endl; out << " : m_name(name)" << endl; out << "{ " << endl; - out << " m_num_controllers++; " << endl; + if (strncmp(component.c_str(), "L1Cache", 7) == 0) { + out << " servicing_atomic = false;" << endl; + out << " locked_read_request = Address(-1);" << endl; + } + out << " m_num_controllers++; " << endl; for(int i=0; i < numObjects(); i++) { const Var* var = m_objs[i]; if ( var->cIdent().find("mandatoryQueue") != string::npos) @@ -738,6 +745,23 @@ void StateMachine::printControllerC(ostream& out, string component) } } + // add here: + if (strncmp(component.c_str(), "L1Cache", 7) == 0) { + if (c_code_string.find("writeCallback") != string::npos) { + string::size_type pos = c_code_string.find("(((*m_L1Cache_sequencer_ptr)).writeCallback"); + assert(pos != string::npos); + string atomics_string = "\n if (servicing_atomic) { \n \ + servicing_atomic = false; \n \ + locked_read_request = Address(-1); \n \ + } \n \ + else if (!servicing_atomic) { \n \ + if (addr == locked_read_request) { \n \ + servicing_atomic = true; \n \ + } \n \ + } \n "; + c_code_string.insert(pos, atomics_string); + } + } out << c_code_string; out << "}" << endl; @@ -759,17 +783,6 @@ void StateMachine::printCWakeup(ostream& out, string component) out << "#include \"mem/protocol/Types.hh\"" << endl; out << "#include \"mem/ruby/system/System.hh\"" << endl; out << endl; - if (strncmp(component.c_str(), "L1Cache", 7) == 0) { - out << "NodeID servicing_atomic = -1;" << endl; - out << endl; - out << "Address locked_read_request = Address(-1);" << endl; - out << endl; - out << "NodeID servicing_locked_read = -1;" << endl; - out << endl; - } - else { - cout << component << endl << flush; - } out << "void " << component << "_Controller::wakeup()" << endl; out << "{" << endl; // out << " DEBUG_EXPR(GENERATED_COMP, MedPrio,*this);" << endl; @@ -814,42 +827,38 @@ void StateMachine::printCWakeup(ostream& out, string component) string::size_type pos = output.find("TransitionResult result = doTransition((L1Cache_mandatory_request_type_to_event(((*in_msg_ptr)).m_Type)), L1Cache_getState(addr), addr);"); assert(pos != string::npos); string atomics_string = "\n \ - bool postpone = false; \n \ - if ((((*in_msg_ptr)).m_Type) == CacheRequestType_ATOMIC) { \n \ - if (servicing_atomic == -1) { \n \ - if (locked_read_request == Address(-1) && (servicing_locked_read == -1)) { \n \ - assert(addr != Address(-1)); \n \ - locked_read_request = addr; \n \ - servicing_locked_read = m_version; \n \ - } \n \ - else if ((addr == locked_read_request) && (servicing_locked_read == m_version)) { \n \ - assert (servicing_atomic == -1); \n \ - servicing_atomic = m_version; \n \ - } \n \ - else { \n \ - postpone = true; \n \ - g_eventQueue_ptr->scheduleEvent(this, 1); \n \ - } \n \ - } \n \ - else { \n \ - postpone = true; \n \ - g_eventQueue_ptr->scheduleEvent(this, 1); \n \ - } \n \ - } \n \ - if (servicing_atomic == m_version) { \n \ - servicing_atomic = -1; \n \ - locked_read_request = Address(-1); \n \ - servicing_locked_read = -1; \n \ - } \n \ - if (!postpone) { \n \ - "; + bool postpone = false; \n \ + if ((((*in_msg_ptr)).m_Type) == CacheRequestType_ATOMIC) { \n \ + if (!servicing_atomic) { \n \ + if (locked_read_request == Address(-1)) { \n \ + locked_read_request = addr; \n \ + } \n \ + else if (addr == locked_read_request) { \n \ + assert (servicing_atomic); \n \ + //servicing_atomic = m_version; \n \ + } \n \ + else { \n \ + postpone = true; \n \ + g_eventQueue_ptr->scheduleEvent(this, 1); \n \ + } \n \ + } \n \ + else if (addr != locked_read_request) { \n \ + postpone = true; \n \ + g_eventQueue_ptr->scheduleEvent(this, 1); \n \ + } \n \ + } \n \ + if (!postpone) { \n \ + "; output.insert(pos, atomics_string); - string::size_type next_pos = output.find("// Cannot do anything with this transition, go check next doable transition (mostly likely of next port)", pos); + string foo = "// Cannot do anything with this transition, go check next doable transition (mostly likely of next port)\n"; + string::size_type next_pos = output.find(foo, pos); + next_pos = next_pos + foo.length(); + assert(next_pos != string::npos); - string complete = "\n}"; + string complete = " }\n"; output.insert(next_pos, complete); //out << port->lookupPair("c_code_in_port"); out << output; @@ -861,11 +870,15 @@ void StateMachine::printCWakeup(ostream& out, string component) if (i != j) { if (strncmp(component.c_str(), "L1Cache", 7) == 0) { if (port->toString().find("forwardRequestNetwork_in") != string::npos) { - out << "if (servicing_atomic != m_version && servicing_locked_read != m_version) {" << endl; - } - else if (port->toString().find("responseNetwork_in") != string::npos) { - out << "// NOTE: this will only work if the WB_ACK always comes before issuing a request for which this line was replaced" << endl; - out << "if (servicing_atomic == -1 || servicing_atomic == m_version) {" << endl; + out << " bool postpone = false;" << endl; + out << " if ((((*m_L1Cache_forwardToCache_ptr)).isReady())) {" << endl; + out << " const RequestMsg* in_msg_ptr;" << endl; + out << " in_msg_ptr = dynamic_cast(((*m_L1Cache_forwardToCache_ptr)).peek());" << endl; + out << " if ((servicing_atomic && locked_read_request == ((*in_msg_ptr)).m_Address)) {" << endl; + out << " postpone = true;" << endl; + out << " }" << endl; + out << " }" << endl; + out << " if (!postpone) {" << endl; } } assert(port->existPair("c_code_in_port")); @@ -877,9 +890,6 @@ void StateMachine::printCWakeup(ostream& out, string component) if (port->toString().find("forwardRequestNetwork_in") != string::npos) { out << "}" << endl; } - else if (port->toString().find("responseNetwork_in") != string::npos) { - out << "}" << endl; - } } out << endl; } From fce4412d76481f0e60b1611349fe49bfe8110ee9 Mon Sep 17 00:00:00 2001 From: Jack Whitham Date: Tue, 14 Jul 2009 21:03:33 -0700 Subject: [PATCH 11/19] ARM: Fix the "open" flag constants. --- src/arch/arm/linux/linux.hh | 46 ++++++++++++++++++------------------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/src/arch/arm/linux/linux.hh b/src/arch/arm/linux/linux.hh index e0545761d..16bcee47a 100644 --- a/src/arch/arm/linux/linux.hh +++ b/src/arch/arm/linux/linux.hh @@ -47,22 +47,22 @@ class ArmLinux : public Linux //@{ /// open(2) flag values. - static const int TGT_O_RDONLY = 0x00000000; //!< O_RDONLY - static const int TGT_O_WRONLY = 0x00000001; //!< O_WRONLY - static const int TGT_O_RDWR = 0x00000002; //!< O_RDWR - static const int TGT_O_CREAT = 0x00000100; //!< O_CREAT - static const int TGT_O_EXCL = 0x00000200; //!< O_EXCL - static const int TGT_O_NOCTTY = 0x00000400; //!< O_NOCTTY - static const int TGT_O_TRUNC = 0x00001000; //!< O_TRUNC - static const int TGT_O_APPEND = 0x00002000; //!< O_APPEND - static const int TGT_O_NONBLOCK = 0x00004000; //!< O_NONBLOCK - static const int TGT_O_SYNC = 0x00010000; //!< O_SYNC - static const int TGT_FASYNC = 0x00020000; //!< FASYNC - static const int TGT_O_DIRECT = 0x00040000; //!< O_DIRECT - static const int TGT_O_LARGEFILE = 0x00100000; //!< O_LARGEFILE - static const int TGT_O_DIRECTORY = 0x00200000; //!< O_DIRECTORY - static const int TGT_O_NOFOLLOW = 0x00400000; //!< O_NOFOLLOW - static const int TGT_O_NOATIME = 0x01000000; //!< O_NOATIME + static const int TGT_O_RDONLY = 00000000; //!< O_RDONLY + static const int TGT_O_WRONLY = 00000001; //!< O_WRONLY + static const int TGT_O_RDWR = 00000002; //!< O_RDWR + static const int TGT_O_CREAT = 00000100; //!< O_CREAT + static const int TGT_O_EXCL = 00000200; //!< O_EXCL + static const int TGT_O_NOCTTY = 00000400; //!< O_NOCTTY + static const int TGT_O_TRUNC = 00001000; //!< O_TRUNC + static const int TGT_O_APPEND = 00002000; //!< O_APPEND + static const int TGT_O_NONBLOCK = 00004000; //!< O_NONBLOCK + static const int TGT_O_SYNC = 00010000; //!< O_SYNC + static const int TGT_FASYNC = 00020000; //!< FASYNC + static const int TGT_O_DIRECTORY = 00040000; //!< O_DIRECTORY + static const int TGT_O_NOFOLLOW = 00100000; //!< O_NOFOLLOW + static const int TGT_O_DIRECT = 00200000; //!< O_DIRECT + static const int TGT_O_LARGEFILE = 00400000; //!< O_LARGEFILE + static const int TGT_O_NOATIME = 01000000; //!< O_NOATIME //@} /// For mmap(). @@ -70,13 +70,13 @@ class ArmLinux : public Linux //@{ /// For getsysinfo(). - static const unsigned GSI_PLATFORM_NAME = 103; //!< platform name as string - static const unsigned GSI_CPU_INFO = 59; //!< CPU information - static const unsigned GSI_PROC_TYPE = 60; //!< get proc_type - static const unsigned GSI_MAX_CPU = 30; //!< max # cpu's on this machine - static const unsigned GSI_CPUS_IN_BOX = 55; //!< number of CPUs in system - static const unsigned GSI_PHYSMEM = 19; //!< Physical memory in KB - static const unsigned GSI_CLK_TCK = 42; //!< clock freq in Hz + static const unsigned GSI_PLATFORM_NAME = 103; //!< platform name as string + static const unsigned GSI_CPU_INFO = 59; //!< CPU information + static const unsigned GSI_PROC_TYPE = 60; //!< get proc_type + static const unsigned GSI_MAX_CPU = 30; //!< max # cpu's on this machine + static const unsigned GSI_CPUS_IN_BOX = 55; //!< number of CPUs in system + static const unsigned GSI_PHYSMEM = 19; //!< Physical memory in KB + static const unsigned GSI_CLK_TCK = 42; //!< clock freq in Hz //@} //@{ From 23a405f5d8f025784bf447f49a3d1e938577ef2b Mon Sep 17 00:00:00 2001 From: Polina Dudnik Date: Wed, 15 Jul 2009 10:46:22 -0500 Subject: [PATCH 12/19] Tester update --- src/mem/ruby/common/Driver.hh | 17 +- src/mem/ruby/tester/DetermGETXGenerator.cc | 120 +++++++---- src/mem/ruby/tester/DetermGETXGenerator.hh | 92 +++++--- src/mem/ruby/tester/DetermInvGenerator.cc | 102 +++++---- src/mem/ruby/tester/DetermInvGenerator.hh | 91 +++++--- .../ruby/tester/DetermSeriesGETSGenerator.cc | 91 +++++--- .../ruby/tester/DetermSeriesGETSGenerator.hh | 90 +++++--- src/mem/ruby/tester/DeterministicDriver.cc | 109 ++++++---- src/mem/ruby/tester/DeterministicDriver.hh | 102 +++++---- src/mem/ruby/tester/Driver_Tester.cc | 44 ---- src/mem/ruby/tester/Driver_Tester.hh | 82 ------- src/mem/ruby/tester/EventQueue_Tester.hh | 118 ---------- src/mem/ruby/tester/Global_Tester.hh | 74 ------- src/mem/ruby/tester/RaceyDriver.cc | 87 +++++--- src/mem/ruby/tester/RaceyDriver.hh | 92 +++++--- src/mem/ruby/tester/RaceyPseudoThread.cc | 67 +++--- src/mem/ruby/tester/RaceyPseudoThread.hh | 49 ++--- src/mem/ruby/tester/SpecifiedGenerator.cc | 79 ++++--- src/mem/ruby/tester/SpecifiedGenerator.hh | 88 +++++--- src/mem/ruby/tester/Tester_Globals.hh | 66 ++++++ src/mem/ruby/tester/main.cc | 79 ++++--- src/mem/ruby/tester/main.hh | 84 +++++--- src/mem/ruby/tester/test_framework.cc | 203 +++++++++--------- src/mem/ruby/tester/test_framework.hh | 84 +++++--- src/mem/rubymem.cc | 4 +- tests/quick/40.m5threads-test-atomic/test.py | 0 26 files changed, 1145 insertions(+), 969 deletions(-) delete mode 100644 src/mem/ruby/tester/Driver_Tester.cc delete mode 100644 src/mem/ruby/tester/Driver_Tester.hh delete mode 100644 src/mem/ruby/tester/EventQueue_Tester.hh delete mode 100644 src/mem/ruby/tester/Global_Tester.hh create mode 100644 src/mem/ruby/tester/Tester_Globals.hh mode change 100644 => 100755 tests/quick/40.m5threads-test-atomic/test.py diff --git a/src/mem/ruby/common/Driver.hh b/src/mem/ruby/common/Driver.hh index 9aa756386..9d17fcadb 100644 --- a/src/mem/ruby/common/Driver.hh +++ b/src/mem/ruby/common/Driver.hh @@ -40,13 +40,8 @@ #include "mem/ruby/common/Global.hh" #include "mem/ruby/common/Consumer.hh" #include "mem/ruby/system/NodeID.hh" -#include "mem/protocol/CacheRequestType.hh" +#include "mem/ruby/common/Address.hh" -class RubySystem; -class SubBlock; -class Address; -class MachineID; -class SimicsHypervisor; class Driver { public: @@ -58,15 +53,12 @@ public: // Public Methods virtual void get_network_config() {} - virtual void dmaHitCallback() = 0; - virtual void hitCallback(NodeID proc, SubBlock& data, CacheRequestType type, int thread) = 0; // Called by sequencer - virtual void conflictCallback(NodeID proc, SubBlock& data, CacheRequestType type, int thread) { assert(0); }; // Called by sequencer + virtual void dmaHitCallback() {}; + virtual void hitCallback(int64_t id) = 0; // Called by sequencer + virtual void go() = 0; virtual integer_t getInstructionCount(int procID) const { return 1; } virtual integer_t getCycleCount(int procID) const { return 1; } virtual void addThreadDependency(int procID, int requestor_thread, int conflict_thread) const { assert(0);} - virtual int inTransaction(int procID, int thread ) const{ - cout << "Driver.hh inTransaction " << endl; -return false; } //called by Sequencer virtual void printDebug(){} //called by Sequencer virtual void printStats(ostream& out) const = 0; @@ -74,7 +66,6 @@ return false; } //called by Sequencer virtual void printConfig(ostream& out) const = 0; - //virtual void abortCallback(NodeID proc){} virtual integer_t readPhysicalMemory(int procID, physical_address_t address, int len ){ ASSERT(0); return 0; } diff --git a/src/mem/ruby/tester/DetermGETXGenerator.cc b/src/mem/ruby/tester/DetermGETXGenerator.cc index 6692fb80c..1eb9cb3ee 100644 --- a/src/mem/ruby/tester/DetermGETXGenerator.cc +++ b/src/mem/ruby/tester/DetermGETXGenerator.cc @@ -1,31 +1,58 @@ /* - * 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. - */ + Copyright (C) 1999-2008 by Mark D. Hill and David A. Wood for the + Wisconsin Multifacet Project. Contact: gems@cs.wisc.edu + http://www.cs.wisc.edu/gems/ + + -------------------------------------------------------------------- + + This file is part of the Ruby Multiprocessor Memory System Simulator, + a component of the Multifacet GEMS (General Execution-driven + Multiprocessor Simulator) software toolset originally developed at + the University of Wisconsin-Madison. + + Ruby was originally developed primarily by Milo Martin and Daniel + Sorin with contributions from Ross Dickson, Carl Mauer, and Manoj + Plakal. + + Substantial further development of Multifacet GEMS at the + University of Wisconsin was performed by Alaa Alameldeen, Brad + Beckmann, Jayaram Bobba, Ross Dickson, Dan Gibson, Pacia Harper, + Derek Hower, Milo Martin, Michael Marty, Carl Mauer, Michelle Moravan, + Kevin Moore, Andrew Phelps, Manoj Plakal, Daniel Sorin, Haris Volos, + Min Xu, and Luke Yen. + -------------------------------------------------------------------- + + If your use of this software contributes to a published paper, we + request that you (1) cite our summary paper that appears on our + website (http://www.cs.wisc.edu/gems/) and (2) e-mail a citation + for your published paper to gems@cs.wisc.edu. + + If you redistribute derivatives of this software, we request that + you notify us and either (1) ask people to register with us at our + website (http://www.cs.wisc.edu/gems/) or (2) collect registration + information and periodically send it to us. + + -------------------------------------------------------------------- + + Multifacet GEMS is free software; you can redistribute it and/or + modify it under the terms of version 2 of the GNU General Public + License as published by the Free Software Foundation. + + Multifacet GEMS is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with the Multifacet GEMS; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307, USA + + The GNU General Public License is contained in the file LICENSE. + +### END HEADER ### +*/ /* * $Id$ @@ -38,7 +65,8 @@ #include "mem/ruby/tester/DetermGETXGenerator.hh" #include "mem/protocol/DetermGETXGeneratorStatus.hh" #include "mem/ruby/tester/DeterministicDriver.hh" -#include "mem/ruby/tester/Global_Tester.hh" +#include "mem/ruby/tester/Tester_Globals.hh" +#include "mem/ruby/common/Global.hh" #include "mem/ruby/tester/SpecifiedGenerator.hh" //#include "DMAController.hh" #include "mem/ruby/libruby.hh" @@ -48,9 +76,11 @@ DetermGETXGenerator::DetermGETXGenerator(NodeID node, DeterministicDriver * driv { m_status = DetermGETXGeneratorStatus_Thinking; m_last_transition = 0; + counter = 0; m_node = node; - m_address = Address(9999); // initialize to null value + m_address = Address(1); // initialize to null value m_counter = 0; + issued_load = false; parent_driver = driver; // don't know exactly when this node needs to request so just guess randomly parent_driver->eventQueue->scheduleEvent(this, 1+(random() % 200)); @@ -68,7 +98,9 @@ void DetermGETXGenerator::wakeup() // determine if this node is next for the GETX round robin request if (m_status == DetermGETXGeneratorStatus_Thinking) { if (parent_driver->isStoreReady(m_node)) { - pickAddress(); + if (!issued_load) { + pickAddress(); + } m_status = DetermGETXGeneratorStatus_Store_Pending; // Store Pending m_last_transition = parent_driver->eventQueue->getTime(); initiateStore(); // GETX @@ -85,13 +117,13 @@ void DetermGETXGenerator::wakeup() void DetermGETXGenerator::performCallback(NodeID proc, Address address) { assert(proc == m_node); - assert(address == m_address); + assert(address == m_address); DEBUG_EXPR(TESTER_COMP, LowPrio, proc); DEBUG_EXPR(TESTER_COMP, LowPrio, m_status); DEBUG_EXPR(TESTER_COMP, LowPrio, address); - if (m_status == DetermGETXGeneratorStatus_Store_Pending) { + if (m_status == DetermGETXGeneratorStatus_Store_Pending) { parent_driver->recordStoreLatency(parent_driver->eventQueue->getTime() - m_last_transition); parent_driver->storeCompleted(m_node, address); // advance the store queue @@ -104,7 +136,7 @@ void DetermGETXGenerator::performCallback(NodeID proc, Address address) parent_driver->reportDone(); m_status = DetermGETXGeneratorStatus_Done; m_last_transition = parent_driver->eventQueue->getTime(); - } + } } else { WARN_EXPR(m_status); @@ -132,7 +164,6 @@ void DetermGETXGenerator::pickAddress() void DetermGETXGenerator::initiateStore() { DEBUG_MSG(TESTER_COMP, MedPrio, "initiating Store"); - uint8_t *write_data = new uint8_t[64]; for(int i=0; i < 64; i++) { write_data[i] = m_node; @@ -141,12 +172,29 @@ void DetermGETXGenerator::initiateStore() char name [] = "Sequencer_"; char port_name [13]; sprintf(port_name, "%s%d", name, m_node); - - int64_t request_id = libruby_issue_request(libruby_get_port_by_name(port_name), RubyRequest(m_address.getAddress(), write_data, 64, 0, RubyRequestType_ST, RubyAccessMode_Supervisor)); + int64_t request_id; + if (counter%10 == 0) { + if (!issued_load) { + cerr << m_node << " RMW_Read to address: " << m_address.getAddress() << endl << flush; + request_id = libruby_issue_request(libruby_get_port_by_name(port_name), RubyRequest(m_address.getAddress(), write_data, 64, 0, RubyRequestType_RMW_Read, RubyAccessMode_Supervisor)); + issued_load = true; + } + else { + cerr << m_node << " RMW_Write to address: " << m_address.getAddress() << endl << flush; + request_id = libruby_issue_request(libruby_get_port_by_name(port_name), RubyRequest(m_address.getAddress(), write_data, 64, 0, RubyRequestType_RMW_Write, RubyAccessMode_Supervisor)); + issued_load = false; + counter++; + } + } + else { + cerr << m_node << " ST to address: " << m_address.getAddress() << endl << flush; + request_id = libruby_issue_request(libruby_get_port_by_name(port_name), RubyRequest(m_address.getAddress(), write_data, 64, 0, RubyRequestType_ST, RubyAccessMode_Supervisor)); + counter++; + } // delete [] write_data; - ASSERT(parent_driver->requests.find(request_id) == parent_driver->requests.end()); + ASSERT(parent_driver->requests.find(request_id) == parent_driver->requests.end()); parent_driver->requests.insert(make_pair(request_id, make_pair(m_node, m_address))); } diff --git a/src/mem/ruby/tester/DetermGETXGenerator.hh b/src/mem/ruby/tester/DetermGETXGenerator.hh index 82e616e4b..7d7e9ea70 100644 --- a/src/mem/ruby/tester/DetermGETXGenerator.hh +++ b/src/mem/ruby/tester/DetermGETXGenerator.hh @@ -1,36 +1,63 @@ /* - * 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. - */ + Copyright (C) 1999-2008 by Mark D. Hill and David A. Wood for the + Wisconsin Multifacet Project. Contact: gems@cs.wisc.edu + http://www.cs.wisc.edu/gems/ + + -------------------------------------------------------------------- + + This file is part of the Ruby Multiprocessor Memory System Simulator, + a component of the Multifacet GEMS (General Execution-driven + Multiprocessor Simulator) software toolset originally developed at + the University of Wisconsin-Madison. + + Ruby was originally developed primarily by Milo Martin and Daniel + Sorin with contributions from Ross Dickson, Carl Mauer, and Manoj + Plakal. + + Substantial further development of Multifacet GEMS at the + University of Wisconsin was performed by Alaa Alameldeen, Brad + Beckmann, Jayaram Bobba, Ross Dickson, Dan Gibson, Pacia Harper, + Derek Hower, Milo Martin, Michael Marty, Carl Mauer, Michelle Moravan, + Kevin Moore, Andrew Phelps, Manoj Plakal, Daniel Sorin, Haris Volos, + Min Xu, and Luke Yen. + -------------------------------------------------------------------- + + If your use of this software contributes to a published paper, we + request that you (1) cite our summary paper that appears on our + website (http://www.cs.wisc.edu/gems/) and (2) e-mail a citation + for your published paper to gems@cs.wisc.edu. + + If you redistribute derivatives of this software, we request that + you notify us and either (1) ask people to register with us at our + website (http://www.cs.wisc.edu/gems/) or (2) collect registration + information and periodically send it to us. + + -------------------------------------------------------------------- + + Multifacet GEMS is free software; you can redistribute it and/or + modify it under the terms of version 2 of the GNU General Public + License as published by the Free Software Foundation. + + Multifacet GEMS is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with the Multifacet GEMS; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307, USA + + The GNU General Public License is contained in the file LICENSE. + +### END HEADER ### +*/ /* * $Id$ * - * Description: + * Description: * */ @@ -40,11 +67,12 @@ #ifndef DETERMGETXGENERATOR_H #define DETERMGETXGENERATOR_H -#include "mem/ruby/tester/Global_Tester.hh" +#include "mem/ruby/tester/Tester_Globals.hh" #include "mem/ruby/common/Consumer.hh" #include "mem/protocol/DetermGETXGeneratorStatus.hh" -#include "Address_Tester.hh" #include "mem/ruby/tester/SpecifiedGenerator.hh" +#include "mem/ruby/common/Global.hh" +#include "mem/ruby/common/Address.hh" class DeterministicDriver; class DMAController; @@ -56,7 +84,7 @@ public: // Destructor ~DetermGETXGenerator(); - + // Public Methods void wakeup(); void performCallback(NodeID proc, Address address); @@ -80,8 +108,10 @@ private: // Data Members (m_ prefix) DetermGETXGeneratorStatus m_status; int m_counter; + bool issued_load; Address m_address; NodeID m_node; + long int counter; Time m_last_transition; }; @@ -91,7 +121,7 @@ ostream& operator<<(ostream& out, const DetermGETXGenerator& obj); // ******************* Definitions ******************* // Output operator definition -extern inline +extern inline ostream& operator<<(ostream& out, const DetermGETXGenerator& obj) { obj.print(out); diff --git a/src/mem/ruby/tester/DetermInvGenerator.cc b/src/mem/ruby/tester/DetermInvGenerator.cc index eebe18057..73ef8b66a 100644 --- a/src/mem/ruby/tester/DetermInvGenerator.cc +++ b/src/mem/ruby/tester/DetermInvGenerator.cc @@ -1,31 +1,58 @@ /* - * 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. - */ + Copyright (C) 1999-2008 by Mark D. Hill and David A. Wood for the + Wisconsin Multifacet Project. Contact: gems@cs.wisc.edu + http://www.cs.wisc.edu/gems/ + + -------------------------------------------------------------------- + + This file is part of the Ruby Multiprocessor Memory System Simulator, + a component of the Multifacet GEMS (General Execution-driven + Multiprocessor Simulator) software toolset originally developed at + the University of Wisconsin-Madison. + + Ruby was originally developed primarily by Milo Martin and Daniel + Sorin with contributions from Ross Dickson, Carl Mauer, and Manoj + Plakal. + + Substantial further development of Multifacet GEMS at the + University of Wisconsin was performed by Alaa Alameldeen, Brad + Beckmann, Jayaram Bobba, Ross Dickson, Dan Gibson, Pacia Harper, + Derek Hower, Milo Martin, Michael Marty, Carl Mauer, Michelle Moravan, + Kevin Moore, Andrew Phelps, Manoj Plakal, Daniel Sorin, Haris Volos, + Min Xu, and Luke Yen. + -------------------------------------------------------------------- + + If your use of this software contributes to a published paper, we + request that you (1) cite our summary paper that appears on our + website (http://www.cs.wisc.edu/gems/) and (2) e-mail a citation + for your published paper to gems@cs.wisc.edu. + + If you redistribute derivatives of this software, we request that + you notify us and either (1) ask people to register with us at our + website (http://www.cs.wisc.edu/gems/) or (2) collect registration + information and periodically send it to us. + + -------------------------------------------------------------------- + + Multifacet GEMS is free software; you can redistribute it and/or + modify it under the terms of version 2 of the GNU General Public + License as published by the Free Software Foundation. + + Multifacet GEMS is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with the Multifacet GEMS; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307, USA + + The GNU General Public License is contained in the file LICENSE. + +### END HEADER ### +*/ /* * $Id$ @@ -36,10 +63,11 @@ // then Invalidates them with a GETX. The GETS and GETX request are generated one // at a time in round-robin fashion 0...1...2...etc. +#include "mem/ruby/common/Global.hh" #include "mem/ruby/tester/DetermInvGenerator.hh" #include "mem/protocol/DetermInvGeneratorStatus.hh" #include "mem/ruby/tester/DeterministicDriver.hh" -#include "mem/ruby/tester/Global_Tester.hh" +#include "mem/ruby/tester/Tester_Globals.hh" //#include "DMAController.hh" #include "mem/ruby/libruby.hh" @@ -75,7 +103,7 @@ void DetermInvGenerator::wakeup() } else { // I'll check again later m_driver.eventQueue->scheduleEvent(this, thinkTime()); } - } else if (m_status == DetermInvGeneratorStatus_Load_Complete) { + } else if (m_status == DetermInvGeneratorStatus_Load_Complete) { if (m_driver.isStoreReady(m_node, m_address)) { // do a store in this transaction or start the next one if (m_driver.isLoadReady((0), m_address)) { // everyone is in S for this address i.e. back to node 0 m_status = DetermInvGeneratorStatus_Store_Pending; @@ -98,13 +126,13 @@ void DetermInvGenerator::wakeup() void DetermInvGenerator::performCallback(NodeID proc, Address address) { assert(proc == m_node); - assert(address == m_address); + assert(address == m_address); DEBUG_EXPR(TESTER_COMP, LowPrio, proc); DEBUG_EXPR(TESTER_COMP, LowPrio, m_status); DEBUG_EXPR(TESTER_COMP, LowPrio, address); - if (m_status == DetermInvGeneratorStatus_Load_Pending) { + if (m_status == DetermInvGeneratorStatus_Load_Pending) { m_driver.recordLoadLatency(m_driver.eventQueue->getTime() - m_last_transition); //NodeID firstByte = data.readByte(); // dummy read @@ -121,9 +149,9 @@ void DetermInvGenerator::performCallback(NodeID proc, Address address) m_driver.reportDone(); m_status = DetermInvGeneratorStatus_Done; m_last_transition = m_driver.eventQueue->getTime(); - } + } - } else if (m_status == DetermInvGeneratorStatus_Store_Pending) { + } else if (m_status == DetermInvGeneratorStatus_Store_Pending) { m_driver.recordStoreLatency(m_driver.eventQueue->getTime() - m_last_transition); //data.writeByte(m_node); m_driver.storeCompleted(m_node, address); // advance the store queue @@ -137,7 +165,7 @@ void DetermInvGenerator::performCallback(NodeID proc, Address address) m_driver.reportDone(); m_status = DetermInvGeneratorStatus_Done; m_last_transition = m_driver.eventQueue->getTime(); - } + } } else { WARN_EXPR(m_status); ERROR_MSG("Invalid status"); @@ -174,7 +202,7 @@ void DetermInvGenerator::pickLoadAddress() void DetermInvGenerator::initiateLoad() { DEBUG_MSG(TESTER_COMP, MedPrio, "initiating Load"); - // sequencer()->makeRequest(CacheMsg(m_address, m_address, CacheRequestType_LD, Address(1), AccessModeType_UserMode, 1, PrefetchBit_No, Address(0), 0 /* only 1 SMT thread */)); + // sequencer()->makeRequest(CacheMsg(m_address, m_address, CacheRequestType_LD, Address(1), AccessModeType_UserMode, 1, PrefetchBit_No, Address(0), 0 /* only 1 SMT thread */)); uint8_t * read_data = new uint8_t[64]; char name [] = "Sequencer_"; @@ -185,7 +213,7 @@ void DetermInvGenerator::initiateLoad() //delete [] read_data; - ASSERT(m_driver.requests.find(request_id) == m_driver.requests.end()); + ASSERT(m_driver.requests.find(request_id) == m_driver.requests.end()); m_driver.requests.insert(make_pair(request_id, make_pair(m_node, m_address))); } @@ -193,7 +221,7 @@ void DetermInvGenerator::initiateLoad() void DetermInvGenerator::initiateStore() { DEBUG_MSG(TESTER_COMP, MedPrio, "initiating Store"); - // sequencer()->makeRequest(CacheMsg(m_address, m_address, CacheRequestType_ST, Address(3), AccessModeType_UserMode, 1, PrefetchBit_No, Address(0), 0 /* only 1 SMT thread */)); + // sequencer()->makeRequest(CacheMsg(m_address, m_address, CacheRequestType_ST, Address(3), AccessModeType_UserMode, 1, PrefetchBit_No, Address(0), 0 /* only 1 SMT thread */)); uint8_t *write_data = new uint8_t[64]; for(int i=0; i < 64; i++) { write_data[i] = m_node; @@ -207,7 +235,7 @@ void DetermInvGenerator::initiateStore() //delete [] write_data; - ASSERT(m_driver.requests.find(request_id) == m_driver.requests.end()); + ASSERT(m_driver.requests.find(request_id) == m_driver.requests.end()); m_driver.requests.insert(make_pair(request_id, make_pair(m_node, m_address))); } diff --git a/src/mem/ruby/tester/DetermInvGenerator.hh b/src/mem/ruby/tester/DetermInvGenerator.hh index 6127c3af4..fc334c0e3 100644 --- a/src/mem/ruby/tester/DetermInvGenerator.hh +++ b/src/mem/ruby/tester/DetermInvGenerator.hh @@ -1,36 +1,63 @@ /* - * 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. - */ + Copyright (C) 1999-2008 by Mark D. Hill and David A. Wood for the + Wisconsin Multifacet Project. Contact: gems@cs.wisc.edu + http://www.cs.wisc.edu/gems/ + + -------------------------------------------------------------------- + + This file is part of the Ruby Multiprocessor Memory System Simulator, + a component of the Multifacet GEMS (General Execution-driven + Multiprocessor Simulator) software toolset originally developed at + the University of Wisconsin-Madison. + + Ruby was originally developed primarily by Milo Martin and Daniel + Sorin with contributions from Ross Dickson, Carl Mauer, and Manoj + Plakal. + + Substantial further development of Multifacet GEMS at the + University of Wisconsin was performed by Alaa Alameldeen, Brad + Beckmann, Jayaram Bobba, Ross Dickson, Dan Gibson, Pacia Harper, + Derek Hower, Milo Martin, Michael Marty, Carl Mauer, Michelle Moravan, + Kevin Moore, Andrew Phelps, Manoj Plakal, Daniel Sorin, Haris Volos, + Min Xu, and Luke Yen. + -------------------------------------------------------------------- + + If your use of this software contributes to a published paper, we + request that you (1) cite our summary paper that appears on our + website (http://www.cs.wisc.edu/gems/) and (2) e-mail a citation + for your published paper to gems@cs.wisc.edu. + + If you redistribute derivatives of this software, we request that + you notify us and either (1) ask people to register with us at our + website (http://www.cs.wisc.edu/gems/) or (2) collect registration + information and periodically send it to us. + + -------------------------------------------------------------------- + + Multifacet GEMS is free software; you can redistribute it and/or + modify it under the terms of version 2 of the GNU General Public + License as published by the Free Software Foundation. + + Multifacet GEMS is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with the Multifacet GEMS; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307, USA + + The GNU General Public License is contained in the file LICENSE. + +### END HEADER ### +*/ /* * $Id$ * - * Description: + * Description: * */ @@ -41,8 +68,10 @@ #ifndef DETERMINVGENERATOR_H #define DETERMINVGENERATOR_H -#include "mem/ruby/tester/Global_Tester.hh" +#include "mem/ruby/tester/Tester_Globals.hh" #include "mem/ruby/common/Consumer.hh" +#include "mem/ruby/common/Address.hh" +#include "mem/ruby/common/Global.hh" #include "mem/protocol/DetermInvGeneratorStatus.hh" #include "Address_Tester.hh" #include "mem/ruby/tester/SpecifiedGenerator.hh" @@ -56,7 +85,7 @@ public: // Destructor ~DetermInvGenerator(); - + // Public Methods void wakeup(); void performCallback(NodeID proc, Address address); @@ -71,7 +100,7 @@ private: void initiateStore(); void pickLoadAddress(); void pickStoreAddress(); - + // copy constructor and assignment operator DetermInvGenerator(const DetermInvGenerator& obj); DetermInvGenerator& operator=(const DetermInvGenerator& obj); @@ -92,7 +121,7 @@ ostream& operator<<(ostream& out, const DetermInvGenerator& obj); // ******************* Definitions ******************* // Output operator definition -extern inline +extern inline ostream& operator<<(ostream& out, const DetermInvGenerator& obj) { obj.print(out); diff --git a/src/mem/ruby/tester/DetermSeriesGETSGenerator.cc b/src/mem/ruby/tester/DetermSeriesGETSGenerator.cc index 38688f10d..47a4eda0d 100644 --- a/src/mem/ruby/tester/DetermSeriesGETSGenerator.cc +++ b/src/mem/ruby/tester/DetermSeriesGETSGenerator.cc @@ -1,31 +1,58 @@ /* - * 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. - */ + Copyright (C) 1999-2008 by Mark D. Hill and David A. Wood for the + Wisconsin Multifacet Project. Contact: gems@cs.wisc.edu + http://www.cs.wisc.edu/gems/ + + -------------------------------------------------------------------- + + This file is part of the Ruby Multiprocessor Memory System Simulator, + a component of the Multifacet GEMS (General Execution-driven + Multiprocessor Simulator) software toolset originally developed at + the University of Wisconsin-Madison. + + Ruby was originally developed primarily by Milo Martin and Daniel + Sorin with contributions from Ross Dickson, Carl Mauer, and Manoj + Plakal. + + Substantial further development of Multifacet GEMS at the + University of Wisconsin was performed by Alaa Alameldeen, Brad + Beckmann, Jayaram Bobba, Ross Dickson, Dan Gibson, Pacia Harper, + Derek Hower, Milo Martin, Michael Marty, Carl Mauer, Michelle Moravan, + Kevin Moore, Andrew Phelps, Manoj Plakal, Daniel Sorin, Haris Volos, + Min Xu, and Luke Yen. + -------------------------------------------------------------------- + + If your use of this software contributes to a published paper, we + request that you (1) cite our summary paper that appears on our + website (http://www.cs.wisc.edu/gems/) and (2) e-mail a citation + for your published paper to gems@cs.wisc.edu. + + If you redistribute derivatives of this software, we request that + you notify us and either (1) ask people to register with us at our + website (http://www.cs.wisc.edu/gems/) or (2) collect registration + information and periodically send it to us. + + -------------------------------------------------------------------- + + Multifacet GEMS is free software; you can redistribute it and/or + modify it under the terms of version 2 of the GNU General Public + License as published by the Free Software Foundation. + + Multifacet GEMS is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with the Multifacet GEMS; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307, USA + + The GNU General Public License is contained in the file LICENSE. + +### END HEADER ### +*/ /* * $Id$ @@ -44,7 +71,7 @@ DetermSeriesGETSGenerator::DetermSeriesGETSGenerator(NodeID node, DeterministicD m_node = node; m_address = Address(9999); // initialize to null value m_counter = 0; - + // don't know exactly when this node needs to request so just guess randomly m_driver.eventQueue->scheduleEvent(this, 1+(random() % 200)); @@ -79,13 +106,13 @@ void DetermSeriesGETSGenerator::wakeup() void DetermSeriesGETSGenerator::performCallback(NodeID proc, Address address) { assert(proc == m_node); - assert(address == m_address); + assert(address == m_address); DEBUG_EXPR(TESTER_COMP, LowPrio, proc); DEBUG_EXPR(TESTER_COMP, LowPrio, m_status); DEBUG_EXPR(TESTER_COMP, LowPrio, address); - if (m_status == DetermSeriesGETSGeneratorStatus_Load_Pending) { + if (m_status == DetermSeriesGETSGeneratorStatus_Load_Pending) { m_driver.recordLoadLatency(m_driver.eventQueue->getTime() - m_last_transition); //data.writeByte(m_node); m_driver.loadCompleted(m_node, address); // advance the load queue @@ -100,7 +127,7 @@ void DetermSeriesGETSGenerator::performCallback(NodeID proc, Address address) m_driver.reportDone(); m_status = DetermSeriesGETSGeneratorStatus_Done; m_last_transition = m_driver.eventQueue->getTime(); - } + } } else { WARN_EXPR(m_status); @@ -128,7 +155,7 @@ void DetermSeriesGETSGenerator::pickAddress() void DetermSeriesGETSGenerator::initiateLoad() { DEBUG_MSG(TESTER_COMP, MedPrio, "initiating Load"); - //sequencer()->makeRequest(CacheMsg(m_address, m_address, CacheRequestType_IFETCH, Address(3), AccessModeType_UserMode, 1, PrefetchBit_No, Address(0), 0 /* only 1 SMT thread */)); + //sequencer()->makeRequest(CacheMsg(m_address, m_address, CacheRequestType_IFETCH, Address(3), AccessModeType_UserMode, 1, PrefetchBit_No, Address(0), 0 /* only 1 SMT thread */)); uint8_t *read_data = new uint8_t[64]; @@ -140,7 +167,7 @@ void DetermSeriesGETSGenerator::initiateLoad() //delete [] read_data; - ASSERT(m_driver.requests.find(request_id) == m_driver.requests.end()); + ASSERT(m_driver.requests.find(request_id) == m_driver.requests.end()); m_driver.requests.insert(make_pair(request_id, make_pair(m_node, m_address))); } diff --git a/src/mem/ruby/tester/DetermSeriesGETSGenerator.hh b/src/mem/ruby/tester/DetermSeriesGETSGenerator.hh index 225e45a11..e2034bde1 100644 --- a/src/mem/ruby/tester/DetermSeriesGETSGenerator.hh +++ b/src/mem/ruby/tester/DetermSeriesGETSGenerator.hh @@ -1,36 +1,63 @@ /* - * 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. - */ + Copyright (C) 1999-2008 by Mark D. Hill and David A. Wood for the + Wisconsin Multifacet Project. Contact: gems@cs.wisc.edu + http://www.cs.wisc.edu/gems/ + + -------------------------------------------------------------------- + + This file is part of the Ruby Multiprocessor Memory System Simulator, + a component of the Multifacet GEMS (General Execution-driven + Multiprocessor Simulator) software toolset originally developed at + the University of Wisconsin-Madison. + + Ruby was originally developed primarily by Milo Martin and Daniel + Sorin with contributions from Ross Dickson, Carl Mauer, and Manoj + Plakal. + + Substantial further development of Multifacet GEMS at the + University of Wisconsin was performed by Alaa Alameldeen, Brad + Beckmann, Jayaram Bobba, Ross Dickson, Dan Gibson, Pacia Harper, + Derek Hower, Milo Martin, Michael Marty, Carl Mauer, Michelle Moravan, + Kevin Moore, Andrew Phelps, Manoj Plakal, Daniel Sorin, Haris Volos, + Min Xu, and Luke Yen. + -------------------------------------------------------------------- + + If your use of this software contributes to a published paper, we + request that you (1) cite our summary paper that appears on our + website (http://www.cs.wisc.edu/gems/) and (2) e-mail a citation + for your published paper to gems@cs.wisc.edu. + + If you redistribute derivatives of this software, we request that + you notify us and either (1) ask people to register with us at our + website (http://www.cs.wisc.edu/gems/) or (2) collect registration + information and periodically send it to us. + + -------------------------------------------------------------------- + + Multifacet GEMS is free software; you can redistribute it and/or + modify it under the terms of version 2 of the GNU General Public + License as published by the Free Software Foundation. + + Multifacet GEMS is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with the Multifacet GEMS; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307, USA + + The GNU General Public License is contained in the file LICENSE. + +### END HEADER ### +*/ /* * $Id$ * - * Description: + * Description: * */ @@ -42,10 +69,11 @@ #ifndef DETERMSERIESGETSGENERATOR_H #define DETERMSERIESGETSGENERATOR_H -#include "mem/ruby/tester/Global_Tester.hh" +#include "mem/ruby/tester/Tester_Globals.hh" #include "mem/ruby/common/Consumer.hh" +#include "mem/ruby/common/Address.hh" +#include "mem/ruby/common/Global.hh" #include "mem/protocol/DetermSeriesGETSGeneratorStatus.hh" -#include "Address_Tester.hh" #include "mem/ruby/tester/SpecifiedGenerator.hh" class DeterministicDriver; @@ -57,7 +85,7 @@ public: // Destructor ~DetermSeriesGETSGenerator(); - + // Public Methods void wakeup(); void performCallback(NodeID proc, Address address); @@ -89,7 +117,7 @@ ostream& operator<<(ostream& out, const DetermSeriesGETSGenerator& obj); // ******************* Definitions ******************* // Output operator definition -extern inline +extern inline ostream& operator<<(ostream& out, const DetermSeriesGETSGenerator& obj) { obj.print(out); diff --git a/src/mem/ruby/tester/DeterministicDriver.cc b/src/mem/ruby/tester/DeterministicDriver.cc index 54b5f5e0d..b6eb79497 100644 --- a/src/mem/ruby/tester/DeterministicDriver.cc +++ b/src/mem/ruby/tester/DeterministicDriver.cc @@ -1,40 +1,68 @@ /* - * 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. - */ + Copyright (C) 1999-2008 by Mark D. Hill and David A. Wood for the + Wisconsin Multifacet Project. Contact: gems@cs.wisc.edu + http://www.cs.wisc.edu/gems/ + + -------------------------------------------------------------------- + + This file is part of the Ruby Multiprocessor Memory System Simulator, + a component of the Multifacet GEMS (General Execution-driven + Multiprocessor Simulator) software toolset originally developed at + the University of Wisconsin-Madison. + + Ruby was originally developed primarily by Milo Martin and Daniel + Sorin with contributions from Ross Dickson, Carl Mauer, and Manoj + Plakal. + + Substantial further development of Multifacet GEMS at the + University of Wisconsin was performed by Alaa Alameldeen, Brad + Beckmann, Jayaram Bobba, Ross Dickson, Dan Gibson, Pacia Harper, + Derek Hower, Milo Martin, Michael Marty, Carl Mauer, Michelle Moravan, + Kevin Moore, Andrew Phelps, Manoj Plakal, Daniel Sorin, Haris Volos, + Min Xu, and Luke Yen. + -------------------------------------------------------------------- + + If your use of this software contributes to a published paper, we + request that you (1) cite our summary paper that appears on our + website (http://www.cs.wisc.edu/gems/) and (2) e-mail a citation + for your published paper to gems@cs.wisc.edu. + + If you redistribute derivatives of this software, we request that + you notify us and either (1) ask people to register with us at our + website (http://www.cs.wisc.edu/gems/) or (2) collect registration + information and periodically send it to us. + + -------------------------------------------------------------------- + + Multifacet GEMS is free software; you can redistribute it and/or + modify it under the terms of version 2 of the GNU General Public + License as published by the Free Software Foundation. + + Multifacet GEMS is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with the Multifacet GEMS; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307, USA + + The GNU General Public License is contained in the file LICENSE. + +### END HEADER ### +*/ /* * $Id$ * */ -#include "mem/ruby/tester/Global_Tester.hh" +#include "mem/ruby/common/Global.hh" +#include "mem/ruby/tester/Tester_Globals.hh" #include "mem/ruby/tester/DeterministicDriver.hh" -#include "mem/ruby/tester/EventQueue_Tester.hh" +#include "mem/ruby/eventqueue/RubyEventQueue.hh" //#include "DMAGenerator.hh" #include "mem/ruby/tester/DetermGETXGenerator.hh" @@ -42,20 +70,19 @@ DeterministicDriver::DeterministicDriver(string generator_type, int num_completions, int num_procs, Time g_think_time, Time g_wait_time, int g_tester_length) { - eventQueue = new RubyEventQueue; + eventQueue = new RubyEventQueue; m_finish_time = 0; m_last_issue = -11; m_done_counter = 0; m_loads_completed = 0; m_stores_completed = 0; - + m_numCompletionsPerNode = num_completions; m_num_procs = num_procs; m_think_time = g_think_time; m_wait_time = g_wait_time; m_tester_length = g_tester_length; - - + m_last_progress_vector.setSize(num_procs); for (int i=0; iperformCallback(proc, address); - + m_last_progress_vector[proc] = eventQueue->getTime(); requests.erase(request_id); @@ -153,7 +180,7 @@ bool DeterministicDriver::isLoadReady(NodeID node) } bool DeterministicDriver::isLoadReady(NodeID node, Address addr) -{ +{ return isAddrReady(node, m_load_vector, addr); } @@ -163,7 +190,7 @@ bool DeterministicDriver::isAddrReady(NodeID node, Vector addr_vector) for (int i=0; i= m_numCompletionsPerNode*node) && // is this node next - (eventQueue->getTime() >= m_last_issue + 10)) { // controll rate of requests + (eventQueue->getTime() >= m_last_issue + 10)) { // controll rate of requests return true; } } @@ -180,7 +207,7 @@ bool DeterministicDriver::isAddrReady(NodeID node, Vector addr_vector, A if (((addr_vector[addr_number]+1)%m_num_procs == node) && (m_loads_completed+m_stores_completed >= m_numCompletionsPerNode*node) && // is this node next - (eventQueue->getTime() >= m_last_issue + 10)) { // controll rate of requests + (eventQueue->getTime() >= m_last_issue + 10)) { // controll rate of requests return true; } else { return false; @@ -203,7 +230,7 @@ void DeterministicDriver::setNextAddr(NodeID node, Address addr, Vector& { // mark the addr vector that this proc was the last to use the particular address int addr_number = addr.getAddress()/DATA_BLOCK_BYTES; - addr_vector[addr_number] = node; + addr_vector[addr_number] = node; } Address DeterministicDriver::getNextLoadAddr(NodeID node) @@ -221,16 +248,18 @@ Address DeterministicDriver::getNextAddr(NodeID node, Vector addr_vector // This method deterministically picks the next addr the node should acquirer // The addrs cycle through according to NodeID 0->1->...->lastID->0... - + Address addr; - + // should only be called if we know a addr is ready for the node ASSERT(isAddrReady(node, addr_vector)); for (int addr_number=0; addr_number -#include "mem/ruby/tester/Global_Tester.hh" +#include "mem/ruby/common/Global.hh" +#include "mem/ruby/tester/Tester_Globals.hh" #include "mem/ruby/common/Histogram.hh" // includes global, but doesn't use anything, so it should be fine #include "mem/protocol/CacheRequestType.hh" // includes global, but doesn't use anything, so it should be fine -#include "Address_Tester.hh" // we redefined the address +#include "mem/ruby/common/Address.hh" // we redefined the address #include "mem/ruby/tester/DetermGETXGenerator.hh" // this is our file #include "mem/ruby/tester/DetermSeriesGETSGenerator.hh" // this is our file #include "mem/ruby/tester/DetermInvGenerator.hh" // this is our file #include "mem/ruby/libruby.hh" -#include "mem/ruby/tester/Driver_Tester.hh" +#include "mem/ruby/common/Driver.hh" #include "mem/ruby/common/Consumer.hh" -#include "mem/ruby/tester/EventQueue_Tester.hh" +#include "mem/ruby/eventqueue/RubyEventQueue.hh" #include "mem/protocol/SpecifiedGeneratorType.hh" //class DMAGenerator; -class DeterministicDriver : public Driver_Tester, public Consumer { +class DeterministicDriver : public Driver, public Consumer { public: friend class DetermGETXGenerator; friend class DetermSeriesGETSGenerator; @@ -62,7 +90,7 @@ public: // Destructor ~DeterministicDriver(); - + // Public Methods void go(); bool isStoreReady(NodeID node); @@ -100,7 +128,7 @@ private: bool isAddrReady(NodeID node, Vector addr_vector, Address addr); void setNextAddr(NodeID node, Address addr, Vector& addr_vector); - + // Data Members (m_ prefix) Vector