From f3b4d10a05d902f34ccd3bee7154b46ee8320fb6 Mon Sep 17 00:00:00 2001 From: Nilay Vaish Date: Mon, 14 Nov 2011 17:44:35 -0600 Subject: Ruby: Process packet instead of RubyRequest in Sequencer This patch changes the implementation of Ruby's recvTiming() function so that it pushes a packet in to the Sequencer instead of a RubyRequest. This requires changes in the Sequencer's makeRequest() and issueRequest() functions, as they also need to operate on a Packet instead of RubyRequest. --- src/mem/ruby/recorder/TraceRecord.cc | 8 +- src/mem/ruby/system/DMASequencer.cc | 23 +-- src/mem/ruby/system/DMASequencer.hh | 2 +- src/mem/ruby/system/RubyPort.cc | 72 +------ src/mem/ruby/system/RubyPort.hh | 2 +- src/mem/ruby/system/Sequencer.cc | 378 +++++++++++++++++------------------ src/mem/ruby/system/Sequencer.hh | 17 +- 7 files changed, 206 insertions(+), 296 deletions(-) (limited to 'src/mem/ruby') diff --git a/src/mem/ruby/recorder/TraceRecord.cc b/src/mem/ruby/recorder/TraceRecord.cc index aa54ee53c..79186d33b 100644 --- a/src/mem/ruby/recorder/TraceRecord.cc +++ b/src/mem/ruby/recorder/TraceRecord.cc @@ -73,17 +73,15 @@ void TraceRecord::issueRequest() const { assert(m_sequencer_ptr != NULL); - - RubyRequest request(m_data_address.getAddress(), NULL, - RubySystem::getBlockSizeBytes(), m_pc_address.getAddress(), - m_type, RubyAccessMode_User, NULL); + Request req(m_data_address.getAddress(), 0, 0); + Packet *pkt = new Packet(&req, MemCmd(MemCmd::InvalidCmd), -1); // Clear out the sequencer while (!m_sequencer_ptr->empty()) { g_eventQueue_ptr->triggerEvents(g_eventQueue_ptr->getTime() + 100); } - m_sequencer_ptr->makeRequest(request); + m_sequencer_ptr->makeRequest(pkt); // Clear out the sequencer while (!m_sequencer_ptr->empty()) { diff --git a/src/mem/ruby/system/DMASequencer.cc b/src/mem/ruby/system/DMASequencer.cc index f8e4cf810..0e82ba3eb 100644 --- a/src/mem/ruby/system/DMASequencer.cc +++ b/src/mem/ruby/system/DMASequencer.cc @@ -48,27 +48,16 @@ DMASequencer::init() } RequestStatus -DMASequencer::makeRequest(const RubyRequest &request) +DMASequencer::makeRequest(PacketPtr pkt) { if (m_is_busy) { return RequestStatus_BufferFull; } - uint64_t paddr = request.m_PhysicalAddress.getAddress(); - uint8_t* data = request.data; - int len = request.m_Size; - bool write = false; - switch(request.m_Type) { - case RubyRequestType_LD: - write = false; - break; - case RubyRequestType_ST: - write = true; - break; - default: - panic("DMASequencer::makeRequest does not support RubyRequestType"); - return RequestStatus_NULL; - } + uint64_t paddr = pkt->getAddr(); + uint8_t* data = pkt->getPtr(true); + int len = pkt->getSize(); + bool write = pkt->isWrite(); assert(!m_is_busy); // only support one outstanding DMA request m_is_busy = true; @@ -79,7 +68,7 @@ DMASequencer::makeRequest(const RubyRequest &request) active_request.len = len; active_request.bytes_completed = 0; active_request.bytes_issued = 0; - active_request.pkt = request.pkt; + active_request.pkt = pkt; SequencerMsg *msg = new SequencerMsg; msg->getPhysicalAddress() = Address(paddr); diff --git a/src/mem/ruby/system/DMASequencer.hh b/src/mem/ruby/system/DMASequencer.hh index 61d7ef1c6..5f6b9f100 100644 --- a/src/mem/ruby/system/DMASequencer.hh +++ b/src/mem/ruby/system/DMASequencer.hh @@ -53,7 +53,7 @@ class DMASequencer : public RubyPort DMASequencer(const Params *); void init(); /* external interface */ - RequestStatus makeRequest(const RubyRequest & request); + RequestStatus makeRequest(PacketPtr pkt); bool busy() { return m_is_busy;} /* SLICC callback */ diff --git a/src/mem/ruby/system/RubyPort.cc b/src/mem/ruby/system/RubyPort.cc index c2661bcf2..f7bde739e 100644 --- a/src/mem/ruby/system/RubyPort.cc +++ b/src/mem/ruby/system/RubyPort.cc @@ -26,10 +26,6 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include "config/the_isa.hh" -#if THE_ISA == X86_ISA -#include "arch/x86/insts/microldstop.hh" -#endif // X86_ISA #include "cpu/testers/rubytest/RubyTester.hh" #include "debug/Ruby.hh" #include "mem/protocol/AccessPermission.hh" @@ -199,73 +195,11 @@ RubyPort::M5Port::recvTiming(PacketPtr pkt) return ruby_port->pio_port->sendTiming(pkt); } - // For DMA and CPU requests, translate them to ruby requests before - // sending them to our assigned ruby port. - RubyRequestType type = RubyRequestType_NULL; - - // If valid, copy the pc to the ruby request - Addr pc = 0; - if (pkt->req->hasPC()) { - pc = pkt->req->getPC(); - } - - if (pkt->isLLSC()) { - if (pkt->isWrite()) { - DPRINTF(RubyPort, "Issuing SC\n"); - type = RubyRequestType_Store_Conditional; - } else { - DPRINTF(RubyPort, "Issuing LL\n"); - assert(pkt->isRead()); - type = RubyRequestType_Load_Linked; - } - } else if (pkt->req->isLocked()) { - if (pkt->isWrite()) { - DPRINTF(RubyPort, "Issuing Locked RMW Write\n"); - type = RubyRequestType_Locked_RMW_Write; - } else { - DPRINTF(RubyPort, "Issuing Locked RMW Read\n"); - assert(pkt->isRead()); - type = RubyRequestType_Locked_RMW_Read; - } - } else { - if (pkt->isRead()) { - if (pkt->req->isInstFetch()) { - type = RubyRequestType_IFETCH; - } else { -#if THE_ISA == X86_ISA - uint32_t flags = pkt->req->getFlags(); - bool storeCheck = flags & - (TheISA::StoreCheck << TheISA::FlagShift); -#else - bool storeCheck = false; -#endif // X86_ISA - if (storeCheck) { - type = RubyRequestType_RMW_Read; - } else { - type = RubyRequestType_LD; - } - } - } else if (pkt->isWrite()) { - // - // Note: M5 packets do not differentiate ST from RMW_Write - // - type = RubyRequestType_ST; - } else if (pkt->isFlush()) { - type = RubyRequestType_FLUSH; - } else { - panic("Unsupported ruby packet type\n"); - } - } - - RubyRequest ruby_request(pkt->getAddr(), pkt->getPtr(true), - pkt->getSize(), pc, type, - RubyAccessMode_Supervisor, pkt); - - assert(ruby_request.m_PhysicalAddress.getOffset() + ruby_request.m_Size <= - RubySystem::getBlockSizeBytes()); + assert(Address(pkt->getAddr()).getOffset() + pkt->getSize() <= + RubySystem::getBlockSizeBytes()); // Submit the ruby request - RequestStatus requestStatus = ruby_port->makeRequest(ruby_request); + RequestStatus requestStatus = ruby_port->makeRequest(pkt); // If the request successfully issued then we should return true. // Otherwise, we need to delete the senderStatus we just created and return diff --git a/src/mem/ruby/system/RubyPort.hh b/src/mem/ruby/system/RubyPort.hh index e1ba2f7d1..88e865766 100644 --- a/src/mem/ruby/system/RubyPort.hh +++ b/src/mem/ruby/system/RubyPort.hh @@ -114,7 +114,7 @@ class RubyPort : public MemObject Port *getPort(const std::string &if_name, int idx); - virtual RequestStatus makeRequest(const RubyRequest & request) = 0; + virtual RequestStatus makeRequest(PacketPtr pkt) = 0; // // Called by the controller to give the sequencer a pointer. diff --git a/src/mem/ruby/system/Sequencer.cc b/src/mem/ruby/system/Sequencer.cc index 711ef12ed..9010178be 100644 --- a/src/mem/ruby/system/Sequencer.cc +++ b/src/mem/ruby/system/Sequencer.cc @@ -28,15 +28,21 @@ #include "base/misc.hh" #include "base/str.hh" +#include "config/the_isa.hh" +#if THE_ISA == X86_ISA +#include "arch/x86/insts/microldstop.hh" +#endif // X86_ISA #include "cpu/testers/rubytest/RubyTester.hh" #include "debug/MemoryAccess.hh" #include "debug/ProtocolTrace.hh" +#include "debug/RubySequencer.hh" +#include "mem/protocol/PrefetchBit.hh" +#include "mem/protocol/RubyAccessMode.hh" #include "mem/ruby/buffers/MessageBuffer.hh" #include "mem/ruby/common/Global.hh" #include "mem/ruby/common/SubBlock.hh" #include "mem/ruby/profiler/Profiler.hh" #include "mem/ruby/recorder/Tracer.hh" -#include "mem/ruby/slicc_interface/AbstractController.hh" #include "mem/ruby/slicc_interface/RubyRequest.hh" #include "mem/ruby/system/CacheMemory.hh" #include "mem/ruby/system/Sequencer.hh" @@ -62,7 +68,6 @@ Sequencer::Sequencer(const Params *p) m_outstanding_count = 0; - m_max_outstanding_requests = 0; m_deadlock_threshold = 0; m_instCache_ptr = NULL; m_dataCache_ptr = NULL; @@ -103,7 +108,7 @@ Sequencer::wakeup() panic("Possible Deadlock detected. Aborting!\n" "version: %d request.paddr: 0x%x m_readRequestTable: %d " "current time: %u issue_time: %d difference: %d\n", m_version, - request->ruby_request.m_PhysicalAddress, m_readRequestTable.size(), + Address(request->pkt->getAddr()), m_readRequestTable.size(), current_time, request->issue_time, current_time - request->issue_time); } @@ -118,7 +123,7 @@ Sequencer::wakeup() panic("Possible Deadlock detected. Aborting!\n" "version: %d request.paddr: 0x%x m_writeRequestTable: %d " "current time: %u issue_time: %d difference: %d\n", m_version, - request->ruby_request.m_PhysicalAddress, m_writeRequestTable.size(), + Address(request->pkt->getAddr()), m_writeRequestTable.size(), current_time, request->issue_time, current_time - request->issue_time); } @@ -213,8 +218,8 @@ Sequencer::printConfig(ostream& out) const // Insert the request on the correct request table. Return true if // the entry was already present. -bool -Sequencer::insertRequest(SequencerRequest* request) +RequestStatus +Sequencer::insertRequest(PacketPtr pkt, RubyRequestType request_type) { int total_outstanding = m_writeRequestTable.size() + m_readRequestTable.size(); @@ -226,52 +231,64 @@ Sequencer::insertRequest(SequencerRequest* request) schedule(deadlockCheckEvent, m_deadlock_threshold + curTick()); } - Address line_addr(request->ruby_request.m_PhysicalAddress); + Address line_addr(pkt->getAddr()); line_addr.makeLineAddress(); - if ((request->ruby_request.m_Type == RubyRequestType_ST) || - (request->ruby_request.m_Type == RubyRequestType_ATOMIC) || - (request->ruby_request.m_Type == RubyRequestType_RMW_Read) || - (request->ruby_request.m_Type == RubyRequestType_RMW_Write) || - (request->ruby_request.m_Type == RubyRequestType_Load_Linked) || - (request->ruby_request.m_Type == RubyRequestType_Store_Conditional) || - (request->ruby_request.m_Type == RubyRequestType_Locked_RMW_Read) || - (request->ruby_request.m_Type == RubyRequestType_Locked_RMW_Write) || - (request->ruby_request.m_Type == RubyRequestType_FLUSH)) { + if ((request_type == RubyRequestType_ST) || + (request_type == RubyRequestType_RMW_Read) || + (request_type == RubyRequestType_RMW_Write) || + (request_type == RubyRequestType_Load_Linked) || + (request_type == RubyRequestType_Store_Conditional) || + (request_type == RubyRequestType_Locked_RMW_Read) || + (request_type == RubyRequestType_Locked_RMW_Write) || + (request_type == RubyRequestType_FLUSH)) { + + // Check if there is any outstanding read request for the same + // cache line. + if (m_readRequestTable.count(line_addr) > 0) { + m_store_waiting_on_load_cycles++; + return RequestStatus_Aliased; + } + pair r = m_writeRequestTable.insert(RequestTable::value_type(line_addr, 0)); - bool success = r.second; - RequestTable::iterator i = r.first; - if (!success) { - i->second = request; - // return true; - - // drh5: isn't this an error? do you lose the initial request? - assert(0); + if (r.second) { + RequestTable::iterator i = r.first; + i->second = new SequencerRequest(pkt, request_type, + g_eventQueue_ptr->getTime()); + m_outstanding_count++; + } else { + // There is an outstanding write request for the cache line + m_store_waiting_on_store_cycles++; + return RequestStatus_Aliased; } - i->second = request; - m_outstanding_count++; } else { + // Check if there is any outstanding write request for the same + // cache line. + if (m_writeRequestTable.count(line_addr) > 0) { + m_load_waiting_on_store_cycles++; + return RequestStatus_Aliased; + } + pair r = m_readRequestTable.insert(RequestTable::value_type(line_addr, 0)); - bool success = r.second; - RequestTable::iterator i = r.first; - if (!success) { - i->second = request; - // return true; - - // drh5: isn't this an error? do you lose the initial request? - assert(0); + + if (r.second) { + RequestTable::iterator i = r.first; + i->second = new SequencerRequest(pkt, request_type, + g_eventQueue_ptr->getTime()); + m_outstanding_count++; + } else { + // There is an outstanding read request for the cache line + m_load_waiting_on_load_cycles++; + return RequestStatus_Aliased; } - i->second = request; - m_outstanding_count++; } g_system_ptr->getProfiler()->sequencerRequests(m_outstanding_count); - total_outstanding = m_writeRequestTable.size() + m_readRequestTable.size(); assert(m_outstanding_count == total_outstanding); - return false; + return RequestStatus_Ready; } void @@ -288,16 +305,15 @@ Sequencer::removeRequest(SequencerRequest* srequest) assert(m_outstanding_count == m_writeRequestTable.size() + m_readRequestTable.size()); - const RubyRequest & ruby_request = srequest->ruby_request; - Address line_addr(ruby_request.m_PhysicalAddress); + Address line_addr(srequest->pkt->getAddr()); line_addr.makeLineAddress(); - if ((ruby_request.m_Type == RubyRequestType_ST) || - (ruby_request.m_Type == RubyRequestType_RMW_Read) || - (ruby_request.m_Type == RubyRequestType_RMW_Write) || - (ruby_request.m_Type == RubyRequestType_Load_Linked) || - (ruby_request.m_Type == RubyRequestType_Store_Conditional) || - (ruby_request.m_Type == RubyRequestType_Locked_RMW_Read) || - (ruby_request.m_Type == RubyRequestType_Locked_RMW_Write)) { + if ((srequest->m_type == RubyRequestType_ST) || + (srequest->m_type == RubyRequestType_RMW_Read) || + (srequest->m_type == RubyRequestType_RMW_Write) || + (srequest->m_type == RubyRequestType_Load_Linked) || + (srequest->m_type == RubyRequestType_Store_Conditional) || + (srequest->m_type == RubyRequestType_Locked_RMW_Read) || + (srequest->m_type == RubyRequestType_Locked_RMW_Write)) { m_writeRequestTable.erase(line_addr); } else { m_readRequestTable.erase(line_addr); @@ -315,32 +331,33 @@ Sequencer::handleLlsc(const Address& address, SequencerRequest* request) // longer locked. // bool success = true; - if (request->ruby_request.m_Type == RubyRequestType_Store_Conditional) { + if (request->m_type == RubyRequestType_Store_Conditional) { 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); + request->pkt->req->setExtraData(0); success = false; } 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); + request->pkt->req->setExtraData(1); } // // Independent of success, all SC operations must clear the lock // m_dataCache_ptr->clearLocked(address); - } else if (request->ruby_request.m_Type == RubyRequestType_Load_Linked) { + } else if (request->m_type == RubyRequestType_Load_Linked) { // // 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->isTagPresent(address)) && (m_dataCache_ptr->isLocked(address, m_version))) { + } else if ((m_dataCache_ptr->isTagPresent(address)) && + (m_dataCache_ptr->isLocked(address, m_version))) { // // Normal writes should clear the locked address // @@ -381,15 +398,15 @@ Sequencer::writeCallback(const Address& address, m_writeRequestTable.erase(i); markRemoved(); - assert((request->ruby_request.m_Type == RubyRequestType_ST) || - (request->ruby_request.m_Type == RubyRequestType_ATOMIC) || - (request->ruby_request.m_Type == RubyRequestType_RMW_Read) || - (request->ruby_request.m_Type == RubyRequestType_RMW_Write) || - (request->ruby_request.m_Type == RubyRequestType_Load_Linked) || - (request->ruby_request.m_Type == RubyRequestType_Store_Conditional) || - (request->ruby_request.m_Type == RubyRequestType_Locked_RMW_Read) || - (request->ruby_request.m_Type == RubyRequestType_Locked_RMW_Write) || - (request->ruby_request.m_Type == RubyRequestType_FLUSH)); + assert((request->m_type == RubyRequestType_ST) || + (request->m_type == RubyRequestType_ATOMIC) || + (request->m_type == RubyRequestType_RMW_Read) || + (request->m_type == RubyRequestType_RMW_Write) || + (request->m_type == RubyRequestType_Load_Linked) || + (request->m_type == RubyRequestType_Store_Conditional) || + (request->m_type == RubyRequestType_Locked_RMW_Read) || + (request->m_type == RubyRequestType_Locked_RMW_Write) || + (request->m_type == RubyRequestType_FLUSH)); // @@ -402,9 +419,9 @@ Sequencer::writeCallback(const Address& address, if(!m_usingNetworkTester) success = handleLlsc(address, request); - if (request->ruby_request.m_Type == RubyRequestType_Locked_RMW_Read) { + if (request->m_type == RubyRequestType_Locked_RMW_Read) { m_controller->blockOnQueue(address, m_mandatory_q_ptr); - } else if (request->ruby_request.m_Type == RubyRequestType_Locked_RMW_Write) { + } else if (request->m_type == RubyRequestType_Locked_RMW_Write) { m_controller->unblock(address); } @@ -444,8 +461,8 @@ Sequencer::readCallback(const Address& address, m_readRequestTable.erase(i); markRemoved(); - assert((request->ruby_request.m_Type == RubyRequestType_LD) || - (request->ruby_request.m_Type == RubyRequestType_IFETCH)); + assert((request->m_type == RubyRequestType_LD) || + (request->m_type == RubyRequestType_IFETCH)); hitCallback(request, mach, data, true, initialRequestTime, forwardRequestTime, firstResponseTime); @@ -460,11 +477,11 @@ Sequencer::hitCallback(SequencerRequest* srequest, Time forwardRequestTime, Time firstResponseTime) { - const RubyRequest & ruby_request = srequest->ruby_request; - Address request_address(ruby_request.m_PhysicalAddress); - Address request_line_address(ruby_request.m_PhysicalAddress); + PacketPtr pkt = srequest->pkt; + Address request_address(pkt->getAddr()); + Address request_line_address(pkt->getAddr()); request_line_address.makeLineAddress(); - RubyRequestType type = ruby_request.m_Type; + RubyRequestType type = srequest->m_type; Time issued_time = srequest->issue_time; // Set this cache entry to the most recently used @@ -502,22 +519,22 @@ Sequencer::hitCallback(SequencerRequest* srequest, DPRINTFR(ProtocolTrace, "%15s %3s %10s%20s %6s>%-6s %s %d cycles\n", curTick(), m_version, "Seq", success ? "Done" : "SC_Failed", "", "", - ruby_request.m_PhysicalAddress, miss_latency); + request_address, miss_latency); } // update the data - if (ruby_request.data != NULL) { + if (pkt->getPtr(true) != NULL) { if ((type == RubyRequestType_LD) || (type == RubyRequestType_IFETCH) || (type == RubyRequestType_RMW_Read) || (type == RubyRequestType_Locked_RMW_Read) || (type == RubyRequestType_Load_Linked)) { - memcpy(ruby_request.data, - data.getData(request_address.getOffset(), ruby_request.m_Size), - ruby_request.m_Size); + memcpy(pkt->getPtr(true), + data.getData(request_address.getOffset(), pkt->getSize()), + pkt->getSize()); } else { - data.setData(ruby_request.data, request_address.getOffset(), - ruby_request.m_Size); + data.setData(pkt->getPtr(true), + request_address.getOffset(), pkt->getSize()); } } else { DPRINTF(MemoryAccess, @@ -532,50 +549,16 @@ Sequencer::hitCallback(SequencerRequest* srequest, // RubyTester. if (m_usingRubyTester) { RubyPort::SenderState *requestSenderState = - safe_cast(ruby_request.pkt->senderState); + safe_cast(pkt->senderState); RubyTester::SenderState* testerSenderState = safe_cast(requestSenderState->saved); testerSenderState->subBlock->mergeFrom(data); } - ruby_hit_callback(ruby_request.pkt); + ruby_hit_callback(pkt); delete srequest; } -// Returns true if the sequencer already has a load or store outstanding -RequestStatus -Sequencer::getRequestStatus(const RubyRequest& request) -{ - bool is_outstanding_store = - !!m_writeRequestTable.count(line_address(request.m_PhysicalAddress)); - bool is_outstanding_load = - !!m_readRequestTable.count(line_address(request.m_PhysicalAddress)); - if (is_outstanding_store) { - if ((request.m_Type == RubyRequestType_LD) || - (request.m_Type == RubyRequestType_IFETCH) || - (request.m_Type == RubyRequestType_RMW_Read)) { - m_store_waiting_on_load_cycles++; - } else { - m_store_waiting_on_store_cycles++; - } - return RequestStatus_Aliased; - } else if (is_outstanding_load) { - if ((request.m_Type == RubyRequestType_ST) || - (request.m_Type == RubyRequestType_RMW_Write)) { - m_load_waiting_on_store_cycles++; - } else { - m_load_waiting_on_load_cycles++; - } - return RequestStatus_Aliased; - } - - if (m_outstanding_count >= m_max_outstanding_requests) { - return RequestStatus_BufferFull; - } - - return RequestStatus_Ready; -} - bool Sequencer::empty() const { @@ -583,109 +566,118 @@ Sequencer::empty() const } RequestStatus -Sequencer::makeRequest(const RubyRequest &request) +Sequencer::makeRequest(PacketPtr pkt) { - assert(request.m_PhysicalAddress.getOffset() + request.m_Size <= - RubySystem::getBlockSizeBytes()); - RequestStatus status = getRequestStatus(request); - if (status != RequestStatus_Ready) - return status; + if (m_outstanding_count >= m_max_outstanding_requests) { + return RequestStatus_BufferFull; + } - SequencerRequest *srequest = - new SequencerRequest(request, g_eventQueue_ptr->getTime()); - bool found = insertRequest(srequest); - if (found) { - panic("Sequencer::makeRequest should never be called if the " - "request is already outstanding\n"); - return RequestStatus_NULL; + RubyRequestType primary_type = RubyRequestType_NULL; + RubyRequestType secondary_type = RubyRequestType_NULL; + + if (pkt->isLLSC()) { + // + // Alpha LL/SC instructions need to be handled carefully by the cache + // coherence protocol to ensure they follow the proper semantics. In + // particular, by identifying the operations as atomic, the protocol + // should understand that migratory sharing optimizations should not + // be performed (i.e. a load between the LL and SC should not steal + // away exclusive permission). + // + if (pkt->isWrite()) { + DPRINTF(RubySequencer, "Issuing SC\n"); + primary_type = RubyRequestType_Store_Conditional; + } else { + DPRINTF(RubySequencer, "Issuing LL\n"); + assert(pkt->isRead()); + primary_type = RubyRequestType_Load_Linked; + } + secondary_type = RubyRequestType_ATOMIC; + } else if (pkt->req->isLocked()) { + // + // x86 locked instructions are translated to store cache coherence + // requests because these requests should always be treated as read + // exclusive operations and should leverage any migratory sharing + // optimization built into the protocol. + // + if (pkt->isWrite()) { + DPRINTF(RubySequencer, "Issuing Locked RMW Write\n"); + primary_type = RubyRequestType_Locked_RMW_Write; + } else { + DPRINTF(RubySequencer, "Issuing Locked RMW Read\n"); + assert(pkt->isRead()); + primary_type = RubyRequestType_Locked_RMW_Read; + } + secondary_type = RubyRequestType_ST; + } else { + if (pkt->isRead()) { + if (pkt->req->isInstFetch()) { + primary_type = secondary_type = RubyRequestType_IFETCH; + } else { +#if THE_ISA == X86_ISA + uint32_t flags = pkt->req->getFlags(); + bool storeCheck = flags & + (TheISA::StoreCheck << TheISA::FlagShift); +#else + bool storeCheck = false; +#endif // X86_ISA + if (storeCheck) { + primary_type = RubyRequestType_RMW_Read; + secondary_type = RubyRequestType_ST; + } else { + primary_type = secondary_type = RubyRequestType_LD; + } + } + } else if (pkt->isWrite()) { + // + // Note: M5 packets do not differentiate ST from RMW_Write + // + primary_type = secondary_type = RubyRequestType_ST; + } else if (pkt->isFlush()) { + primary_type = secondary_type = RubyRequestType_FLUSH; + } else { + panic("Unsupported ruby packet type\n"); + } } - issueRequest(request); + RequestStatus status = insertRequest(pkt, primary_type); + if (status != RequestStatus_Ready) + return status; + + issueRequest(pkt, secondary_type); // TODO: issue hardware prefetches here return RequestStatus_Issued; } void -Sequencer::issueRequest(const RubyRequest& request) +Sequencer::issueRequest(PacketPtr pkt, RubyRequestType secondary_type) { - // TODO: Eliminate RubyRequest being copied again. - - RubyRequestType ctype = RubyRequestType_NUM; - switch(request.m_Type) { - case RubyRequestType_IFETCH: - ctype = RubyRequestType_IFETCH; - break; - case RubyRequestType_LD: - ctype = RubyRequestType_LD; - break; - case RubyRequestType_FLUSH: - ctype = RubyRequestType_FLUSH; - break; - case RubyRequestType_ST: - case RubyRequestType_RMW_Read: - case RubyRequestType_RMW_Write: - // - // x86 locked instructions are translated to store cache coherence - // requests because these requests should always be treated as read - // exclusive operations and should leverage any migratory sharing - // optimization built into the protocol. - // - case RubyRequestType_Locked_RMW_Read: - case RubyRequestType_Locked_RMW_Write: - ctype = RubyRequestType_ST; - break; - // - // Alpha LL/SC instructions need to be handled carefully by the cache - // coherence protocol to ensure they follow the proper semantics. In - // particular, by identifying the operations as atomic, the protocol - // should understand that migratory sharing optimizations should not be - // performed (i.e. a load between the LL and SC should not steal away - // exclusive permission). - // - case RubyRequestType_Load_Linked: - case RubyRequestType_Store_Conditional: - case RubyRequestType_ATOMIC: - ctype = RubyRequestType_ATOMIC; - break; - default: - assert(0); + int proc_id = -1; + if (pkt != NULL && pkt->req->hasContextId()) { + proc_id = pkt->req->contextId(); } - RubyAccessMode amtype = RubyAccessMode_NUM; - switch(request.m_AccessMode){ - case RubyAccessMode_User: - amtype = RubyAccessMode_User; - break; - case RubyAccessMode_Supervisor: - amtype = RubyAccessMode_Supervisor; - break; - case RubyAccessMode_Device: - amtype = RubyAccessMode_User; - break; - default: - assert(0); + // If valid, copy the pc to the ruby request + Addr pc = 0; + if (pkt->req->hasPC()) { + pc = pkt->req->getPC(); } - Address line_addr(request.m_PhysicalAddress); - line_addr.makeLineAddress(); - int proc_id = -1; - if (request.pkt != NULL && request.pkt->req->hasContextId()) { - proc_id = request.pkt->req->contextId(); - } - RubyRequest *msg = new RubyRequest(request.m_PhysicalAddress.getAddress(), - request.data, request.m_Size, - request.m_ProgramCounter.getAddress(), - ctype, amtype, request.pkt, + RubyRequest *msg = new RubyRequest(pkt->getAddr(), + pkt->getPtr(true), + pkt->getSize(), pc, secondary_type, + RubyAccessMode_Supervisor, pkt, PrefetchBit_No, proc_id); DPRINTFR(ProtocolTrace, "%15s %3s %10s%20s %6s>%-6s %s %s\n", curTick(), m_version, "Seq", "Begin", "", "", - request.m_PhysicalAddress, RubyRequestType_to_string(request.m_Type)); + msg->getPhysicalAddress(), + RubyRequestType_to_string(secondary_type)); Time latency = 0; // initialzed to an null value - if (request.m_Type == RubyRequestType_IFETCH) + if (secondary_type == RubyRequestType_IFETCH) latency = m_instCache_ptr->getLatency(); else latency = m_dataCache_ptr->getLatency(); diff --git a/src/mem/ruby/system/Sequencer.hh b/src/mem/ruby/system/Sequencer.hh index 0589d8bbc..7c2d0af13 100644 --- a/src/mem/ruby/system/Sequencer.hh +++ b/src/mem/ruby/system/Sequencer.hh @@ -33,12 +33,9 @@ #include "base/hashmap.hh" #include "mem/protocol/GenericMachineType.hh" -#include "mem/protocol/PrefetchBit.hh" -#include "mem/protocol/RubyAccessMode.hh" #include "mem/protocol/RubyRequestType.hh" #include "mem/ruby/common/Address.hh" #include "mem/ruby/common/Consumer.hh" -#include "mem/ruby/common/Global.hh" #include "mem/ruby/system/RubyPort.hh" class DataBlock; @@ -50,11 +47,12 @@ class RubySequencerParams; struct SequencerRequest { - RubyRequest ruby_request; + PacketPtr pkt; + RubyRequestType m_type; Time issue_time; - SequencerRequest(const RubyRequest & _ruby_request, Time _issue_time) - : ruby_request(_ruby_request), issue_time(_issue_time) + SequencerRequest(PacketPtr _pkt, RubyRequestType _m_type, Time _issue_time) + : pkt(_pkt), m_type(_m_type), issue_time(_issue_time) {} }; @@ -100,8 +98,7 @@ class Sequencer : public RubyPort, public Consumer Time forwardRequestTime, Time firstResponseTime); - RequestStatus makeRequest(const RubyRequest & request); - RequestStatus getRequestStatus(const RubyRequest& request); + RequestStatus makeRequest(PacketPtr pkt); bool empty() const; void print(std::ostream& out) const; @@ -112,7 +109,7 @@ class Sequencer : public RubyPort, public Consumer void removeRequest(SequencerRequest* request); private: - void issueRequest(const RubyRequest& request); + void issueRequest(PacketPtr pkt, RubyRequestType type); void hitCallback(SequencerRequest* request, GenericMachineType mach, @@ -122,7 +119,7 @@ class Sequencer : public RubyPort, public Consumer Time forwardRequestTime, Time firstResponseTime); - bool insertRequest(SequencerRequest* request); + RequestStatus insertRequest(PacketPtr pkt, RubyRequestType request_type); bool handleLlsc(const Address& address, SequencerRequest* request); -- cgit v1.2.3