diff options
-rw-r--r-- | src/mem/packet.hh | 24 | ||||
-rw-r--r-- | src/mem/protocol/RubySlicc_Exports.sm | 2 | ||||
-rw-r--r-- | src/mem/ruby/system/CacheMemory.cc | 4 | ||||
-rw-r--r-- | src/mem/ruby/system/RubyPort.cc | 49 | ||||
-rw-r--r-- | src/mem/ruby/system/Sequencer.cc | 63 | ||||
-rw-r--r-- | src/mem/ruby/system/Sequencer.hh | 1 |
6 files changed, 101 insertions, 42 deletions
diff --git a/src/mem/packet.hh b/src/mem/packet.hh index 2c94da8bd..390d9672f 100644 --- a/src/mem/packet.hh +++ b/src/mem/packet.hh @@ -463,6 +463,30 @@ class Packet : public FastAlloc, public Printable Addr getOffset(int blkSize) const { return getAddr() & (Addr)(blkSize - 1); } /** + * It has been determined that the SC packet should successfully update + * memory. Therefore, convert this SC packet to a normal write. + */ + void + convertScToWrite() + { + assert(isLLSC()); + assert(isWrite()); + cmd = MemCmd::WriteReq; + } + + /** + * When ruby is in use, Ruby will monitor the cache line and thus M5 + * phys memory should treat LL ops as normal reads. + */ + void + convertLlToRead() + { + assert(isLLSC()); + assert(isRead()); + cmd = MemCmd::ReadReq; + } + + /** * Constructor. Note that a Request object must be constructed * first, but the Requests's physical address and size fields need * not be valid. The command and destination addresses must be diff --git a/src/mem/protocol/RubySlicc_Exports.sm b/src/mem/protocol/RubySlicc_Exports.sm index d29620d16..4cea7c379 100644 --- a/src/mem/protocol/RubySlicc_Exports.sm +++ b/src/mem/protocol/RubySlicc_Exports.sm @@ -53,7 +53,6 @@ enumeration(AccessPermission, desc="...", default="AccessPermission_NotPresent") Read_Write, desc="Read/Write"; Invalid, desc="Invalid"; NotPresent, desc="NotPresent"; - OnHold, desc="Holding a place in dnuca cache"; ReadUpgradingToWrite, desc="Read only, but trying to get Read/Write"; Stale, desc="local L1 has a modified copy, assume L2 copy is stale data"; } @@ -345,6 +344,5 @@ enumeration(RequestStatus, desc="...", default="RequestStatus_NULL") { Issued, desc="The sequencer successfully issued the request"; BufferFull, desc="Can not issue because the sequencer is full"; Aliased, desc="This request aliased with a currently outstanding request"; - LlscFailed, desc="The write failed in the Load-Link Store-Conditional pair"; NULL, desc=""; } diff --git a/src/mem/ruby/system/CacheMemory.cc b/src/mem/ruby/system/CacheMemory.cc index 9102d1963..604113238 100644 --- a/src/mem/ruby/system/CacheMemory.cc +++ b/src/mem/ruby/system/CacheMemory.cc @@ -353,7 +353,9 @@ CacheMemory::changePermission(const Address& address, lookup(address).m_Permission = new_perm; Index cacheSet = addressToCacheSet(address); int loc = findTagInSet(cacheSet, address); - if (new_perm != AccessPermission_Read_Write) { + if ((new_perm == AccessPermission_Invalid) || + (new_perm == AccessPermission_NotPresent) || + (new_perm == AccessPermission_Stale)) { DPRINTF(RubyCache, "Permission clearing lock for addr: %x\n", address); m_locked[cacheSet][loc] = -1; } diff --git a/src/mem/ruby/system/RubyPort.cc b/src/mem/ruby/system/RubyPort.cc index 87a98185c..a8edb03b2 100644 --- a/src/mem/ruby/system/RubyPort.cc +++ b/src/mem/ruby/system/RubyPort.cc @@ -229,23 +229,10 @@ RubyPort::M5Port::recvTiming(PacketPtr pkt) // Submit the ruby request RequestStatus requestStatus = ruby_port->makeRequest(ruby_request); - // If the request successfully issued or the SC request completed because - // exclusive permission was lost, then we should return true. + // If the request successfully issued then we should return true. // Otherwise, we need to delete the senderStatus we just created and return // false. - if ((requestStatus == RequestStatus_Issued) || - (requestStatus == RequestStatus_LlscFailed)) { - - // The communicate to M5 whether the SC command succeeded by seting the - // packet's extra data. - if (pkt->isLLSC() && pkt->isWrite()) { - if (requestStatus == RequestStatus_LlscFailed) { - DPRINTF(MemoryAccess, "SC failed and request completed\n"); - pkt->req->setExtraData(0); - } else { - pkt->req->setExtraData(1); - } - } + if (requestStatus == RequestStatus_Issued) { return true; } @@ -280,9 +267,39 @@ RubyPort::M5Port::hitCallback(PacketPtr pkt) { bool needsResponse = pkt->needsResponse(); + // + // All responses except failed SC operations access M5 physical memory + // + bool accessPhysMem = true; + + if (pkt->isLLSC()) { + if (pkt->isWrite()) { + if (pkt->req->getExtraData() != 0) { + // + // Successful SC packets convert to normal writes + // + pkt->convertScToWrite(); + } else { + // + // Failed SC packets don't access physical memory and thus + // the RubyPort itself must convert it to a response. + // + accessPhysMem = false; + pkt->makeAtomicResponse(); + } + } else { + // + // All LL packets convert to normal loads so that M5 PhysMem does + // not lock the blocks. + // + pkt->convertLlToRead(); + } + } DPRINTF(MemoryAccess, "Hit callback needs response %d\n", needsResponse); - ruby_port->physMemPort->sendAtomic(pkt); + if (accessPhysMem) { + ruby_port->physMemPort->sendAtomic(pkt); + } // turn packet around to go back to requester if response expected if (needsResponse) { diff --git a/src/mem/ruby/system/Sequencer.cc b/src/mem/ruby/system/Sequencer.cc index e4f85908f..600f95d10 100644 --- a/src/mem/ruby/system/Sequencer.cc +++ b/src/mem/ruby/system/Sequencer.cc @@ -41,6 +41,7 @@ #include "mem/ruby/system/CacheMemory.hh" #include "mem/ruby/system/Sequencer.hh" #include "mem/ruby/system/System.hh" +#include "mem/packet.hh" #include "params/RubySequencer.hh" using namespace std; @@ -303,6 +304,38 @@ Sequencer::removeRequest(SequencerRequest* srequest) } void +Sequencer::handleLlscWrites(const Address& address, SequencerRequest* request) +{ + if (request->ruby_request.type == RubyRequestType_Locked_Write) { + if (!m_dataCache_ptr->isLocked(address, m_version)) { + // + // For failed SC requests, indicate the failure to the cpu by + // setting the extra data to zero. + // + request->ruby_request.pkt->req->setExtraData(0); + } else { + // + // For successful SC requests, indicate the success to the cpu by + // setting the extra data to one. + // + request->ruby_request.pkt->req->setExtraData(1); + } + m_dataCache_ptr->clearLocked(address); + } else if (request->ruby_request.type == RubyRequestType_Locked_Read) { + // + // Note: To fully follow Alpha LLSC semantics, should the LL clear any + // previously locked cache lines? + // + m_dataCache_ptr->setLocked(address, m_version); + } else if (m_dataCache_ptr->isLocked(address, m_version)) { + // + // Normal writes should clear the locked address + // + m_dataCache_ptr->clearLocked(address); + } +} + +void Sequencer::writeCallback(const Address& address, DataBlock& data) { writeCallback(address, GenericMachineType_NULL, data); @@ -329,9 +362,13 @@ Sequencer::writeCallback(const Address& address, (request->ruby_request.type == RubyRequestType_Locked_Read) || (request->ruby_request.type == RubyRequestType_Locked_Write)); - if (request->ruby_request.type == RubyRequestType_Locked_Read) { - m_dataCache_ptr->setLocked(address, m_version); - } else if (request->ruby_request.type == RubyRequestType_RMW_Read) { + // + // For Alpha, properly handle LL, SC, and write requests with respect to + // locked cache blocks. + // + handleLlscWrites(address, request); + + if (request->ruby_request.type == RubyRequestType_RMW_Read) { m_controller->blockOnQueue(address, m_mandatory_q_ptr); } else if (request->ruby_request.type == RubyRequestType_RMW_Write) { m_controller->unblock(address); @@ -504,26 +541,6 @@ Sequencer::makeRequest(const RubyRequest &request) return RequestStatus_NULL; } - if (request.type == RubyRequestType_Locked_Write) { - // NOTE: it is OK to check the locked flag here as the - // mandatory queue will be checked first ensuring that nothing - // comes between checking the flag and servicing the store. - - Address line_addr = line_address(Address(request.paddr)); - if (!m_dataCache_ptr->isLocked(line_addr, m_version)) { - removeRequest(srequest); - if (Debug::getProtocolTrace()) { - g_system_ptr->getProfiler()-> - profileTransition("Seq", m_version, - Address(request.paddr), - "", "SC Fail", "", - RubyRequestType_to_string(request.type)); - } - return RequestStatus_LlscFailed; - } else { - m_dataCache_ptr->clearLocked(line_addr); - } - } issueRequest(request); // TODO: issue hardware prefetches here diff --git a/src/mem/ruby/system/Sequencer.hh b/src/mem/ruby/system/Sequencer.hh index fd6b390c2..c298e27dd 100644 --- a/src/mem/ruby/system/Sequencer.hh +++ b/src/mem/ruby/system/Sequencer.hh @@ -109,6 +109,7 @@ class Sequencer : public RubyPort, public Consumer bool insertRequest(SequencerRequest* request); + void handleLlscWrites(const Address& address, SequencerRequest* request); // Private copy constructor and assignment operator Sequencer(const Sequencer& obj); |