diff --git a/src/mem/ruby/system/Sequencer.hh b/src/mem/ruby/system/Sequencer.hh --- a/src/mem/ruby/system/Sequencer.hh +++ b/src/mem/ruby/system/Sequencer.hh @@ -30,6 +30,7 @@ #define __MEM_RUBY_SYSTEM_SEQUENCER_HH__ #include +#include #include "base/hashmap.hh" #include "mem/protocol/MachineType.hh" @@ -44,11 +45,12 @@ { PacketPtr pkt; RubyRequestType m_type; + RubyRequestType m_second_type; Cycles issue_time; - SequencerRequest(PacketPtr _pkt, RubyRequestType _m_type, - Cycles _issue_time) - : pkt(_pkt), m_type(_m_type), issue_time(_issue_time) + RubyRequestType _m_second_type, Cycles _issue_time) + : pkt(_pkt), m_type(_m_type), m_second_type(_m_second_type), + issue_time(_issue_time) {} }; @@ -152,21 +154,21 @@ private: void issueRequest(PacketPtr pkt, RubyRequestType type); - void hitCallback(SequencerRequest* request, DataBlock& data, + void hitCallback(SequencerRequest* srequest, DataBlock& data, bool llscSuccess, const MachineType mach, const bool externalHit, const Cycles initialRequestTime, const Cycles forwardRequestTime, const Cycles firstResponseTime); - void recordMissLatency(const Cycles t, const RubyRequestType type, + void recordMissLatency(SequencerRequest* srequest, bool llscSuccess, const MachineType respondingMach, - bool isExternalHit, Cycles issuedTime, - Cycles initialRequestTime, - Cycles forwardRequestTime, Cycles firstResponseTime, - Cycles completionTime); + bool isExternalHit, Cycles initialRequestTime, + Cycles forwardRequestTime, + Cycles firstResponseTime); - RequestStatus insertRequest(PacketPtr pkt, RubyRequestType request_type); + RequestStatus insertRequest(PacketPtr pkt, RubyRequestType primary_type, + RubyRequestType secondary_type); bool handleLlsc(const Address& address, SequencerRequest* request); // Private copy constructor and assignment operator @@ -180,20 +182,16 @@ CacheMemory* m_dataCache_ptr; CacheMemory* m_instCache_ptr; - typedef m5::hash_map RequestTable; - RequestTable m_writeRequestTable; - RequestTable m_readRequestTable; + //RequestTable contains both read and write requests, handles aliasing + typedef m5::hash_map*> RequestTable; + RequestTable m_RequestTable; + // Global outstanding request count, across all request tables int m_outstanding_count; bool m_deadlock_check_scheduled; - //! Counters for recording aliasing information. - Stats::Scalar m_store_waiting_on_load; - Stats::Scalar m_store_waiting_on_store; - Stats::Scalar m_load_waiting_on_store; - Stats::Scalar m_load_waiting_on_load; - bool m_usingNetworkTester; + bool coalesce_reqs; //! Histogram for number of outstanding requests per cycle. Stats::Histogram m_outstandReqHist; # Node ID 1e05089bc9916a586e0560ed61a6189304217fc9 # Parent 544a69f92a4f2df0e6398b23c348eb481e2a72f7 diff --git a/src/mem/ruby/system/Sequencer.cc b/src/mem/ruby/system/Sequencer.cc --- a/src/mem/ruby/system/Sequencer.cc +++ b/src/mem/ruby/system/Sequencer.cc @@ -1,5 +1,6 @@ /* * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood + * Copyright (c) 2013 Advanced Micro Devices, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -68,6 +69,7 @@ assert(m_dataCache_ptr != NULL); m_usingNetworkTester = p->using_network_tester; + coalesce_reqs = p->coalesce_reqs; } Sequencer::~Sequencer() @@ -85,38 +87,23 @@ // Check across all outstanding requests int total_outstanding = 0; - RequestTable::iterator read = m_readRequestTable.begin(); - RequestTable::iterator read_end = m_readRequestTable.end(); - for (; read != read_end; ++read) { - SequencerRequest* request = read->second; - if (current_time - request->issue_time < m_deadlock_threshold) - continue; - - 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, - Address(request->pkt->getAddr()), m_readRequestTable.size(), - current_time * clockPeriod(), request->issue_time * clockPeriod(), - (current_time * clockPeriod()) - (request->issue_time * clockPeriod())); - } - - RequestTable::iterator write = m_writeRequestTable.begin(); - RequestTable::iterator write_end = m_writeRequestTable.end(); - for (; write != write_end; ++write) { - SequencerRequest* request = write->second; - if (current_time - request->issue_time < m_deadlock_threshold) - continue; - - 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, - Address(request->pkt->getAddr()), m_writeRequestTable.size(), - current_time * clockPeriod(), request->issue_time * clockPeriod(), - (current_time * clockPeriod()) - (request->issue_time * clockPeriod())); - } - - total_outstanding += m_writeRequestTable.size(); - total_outstanding += m_readRequestTable.size(); + RequestTable::iterator aliasedIt = m_RequestTable.begin(); + RequestTable::iterator aliasedIt_end = m_RequestTable.end(); + for (; aliasedIt != aliasedIt_end; ++aliasedIt) { + list::iterator it = aliasedIt->second->begin(); + list::iterator it_end = aliasedIt->second->end(); + for (; it != it_end; ++it) { + if (current_time - (*it)->issue_time < m_deadlock_threshold) + continue; + panic("Possible Deadlock detected. Aborting!\n" + "version: %d request.paddr: 0x%x m_RequestTable: %d " + "current time: %u issue_time: %d difference: %d\n", m_version, + Address((*it)->pkt->getAddr()), aliasedIt->second->size(), + current_time * clockPeriod(), (*it)->issue_time * clockPeriod(), + (current_time * clockPeriod()) - ((*it)->issue_time * clockPeriod())); + } + total_outstanding += aliasedIt->second->size(); + } assert(m_outstanding_count == total_outstanding); @@ -164,55 +151,47 @@ out << "---------------" << endl; out << "outstanding requests" << endl; - out << "proc " << m_Read - << " version Requests = " << m_readRequestTable.size() << endl; + // print the request table + RequestTable::iterator aliasedIt = m_RequestTable.begin(); + RequestTable::iterator aliasedIt_end = m_RequestTable.end(); + int i = 0; - // print the request table - RequestTable::iterator read = m_readRequestTable.begin(); - RequestTable::iterator read_end = m_readRequestTable.end(); - for (; read != read_end; ++read) { - SequencerRequest* request = read->second; - out << "\tRequest[ " << i << " ] = " << request->type - << " Address " << rkeys[i] - << " Posted " << request->issue_time - << " PF " << PrefetchBit_No << endl; - total_demand++; - } - - out << "proc " << m_version - << " Write Requests = " << m_writeRequestTable.size << endl; - - // print the request table - RequestTable::iterator write = m_writeRequestTable.begin(); - RequestTable::iterator write_end = m_writeRequestTable.end(); - for (; write != write_end; ++write) { - SequencerRequest* request = write->second; - out << "\tRequest[ " << i << " ] = " << request.getType() - << " Address " << wkeys[i] - << " Posted " << request.getTime() - << " PF " << request.getPrefetch() << endl; - if (request.getPrefetch() == PrefetchBit_No) { - total_demand++; + for (; aliasedIt != aliasedIt_end; ++aliasedIt) { + list::iterator it = aliasedIt->second->begin(); + list::iterator it_end = aliasedIt->second->end(); + for (; it != it_end; ++it) { + SequencerRequest* request = *it; + // handle write + if ((request->m_type != RubyRequestType_LD) && + (request->m_type != RubyRequestType_IFETCH)) { + out << "\tRequest[ " << i << " ] = " << request->m_type + << " Address " << request->pkt->getAddr() + << " Posted " << request->issue_time + << endl; + } + // handle read + else { + out << "\tRequest[ " << i << " ] = " << request->m_type + << " Address " << request->pkt->getAddr() + << " Posted " << request->issue_time + << endl; + } + i++; } } out << endl; - out << "Total Number Outstanding: " << m_outstanding_count << endl - << "Total Number Demand : " << total_demand << endl - << "Total Number Prefetches : " << m_outstanding_count - total_demand - << endl << endl << endl; + out << "Total Number Outstanding: " << m_outstanding_count << endl; #endif } // Insert the request on the correct request table. Return true if // the entry was already present. RequestStatus -Sequencer::insertRequest(PacketPtr pkt, RubyRequestType request_type) +Sequencer::insertRequest(PacketPtr pkt, RubyRequestType primary_type, + RubyRequestType secondary_type) { - assert(m_outstanding_count == - (m_writeRequestTable.size() + m_readRequestTable.size())); - // See if we should schedule a deadlock check if (!deadlockCheckEvent.scheduled() && getDrainState() != Drainable::Draining) { @@ -221,63 +200,33 @@ Address line_addr(pkt->getAddr()); line_addr.makeLineAddress(); - // Create a default entry, mapping the address to NULL, the cast is - // there to make gcc 4.4 happy + + + // Check if there is any outstanding read request for the same cache line. + RequestTable::iterator s = m_RequestTable.find(line_addr); + if (s != m_RequestTable.end()) { + if (coalesce_reqs) { + s->second->push_back(new SequencerRequest(pkt, primary_type, + secondary_type, curCycle())); + m_outstanding_count++; + } + return RequestStatus_Aliased; + } + + // Create a default entry RequestTable::value_type default_entry(line_addr, - (SequencerRequest*) NULL); + new std::list()); - 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++; - return RequestStatus_Aliased; - } - - pair r = - m_writeRequestTable.insert(default_entry); - if (r.second) { - RequestTable::iterator i = r.first; - i->second = new SequencerRequest(pkt, request_type, curCycle()); - m_outstanding_count++; - } else { - // There is an outstanding write request for the cache line - m_store_waiting_on_store++; - return RequestStatus_Aliased; - } - } 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++; - return RequestStatus_Aliased; - } - - pair r = - m_readRequestTable.insert(default_entry); - - if (r.second) { - RequestTable::iterator i = r.first; - i->second = new SequencerRequest(pkt, request_type, curCycle()); - m_outstanding_count++; - } else { - // There is an outstanding read request for the cache line - m_load_waiting_on_load++; - return RequestStatus_Aliased; - } + pair r = + m_RequestTable.insert(default_entry); + if (r.second) { + RequestTable::iterator i = r.first; + i->second->push_back(new SequencerRequest(pkt, primary_type, + secondary_type, curCycle())); + m_outstanding_count++; } m_outstandReqHist.sample(m_outstanding_count); - assert(m_outstanding_count == - (m_writeRequestTable.size() + m_readRequestTable.size())); return RequestStatus_Ready; } @@ -286,43 +235,23 @@ Sequencer::markRemoved() { m_outstanding_count--; - assert(m_outstanding_count == - m_writeRequestTable.size() + m_readRequestTable.size()); -} - -void -Sequencer::removeRequest(SequencerRequest* srequest) -{ - assert(m_outstanding_count == - m_writeRequestTable.size() + m_readRequestTable.size()); - - Address line_addr(srequest->pkt->getAddr()); - line_addr.makeLineAddress(); - 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); - } - - markRemoved(); } void Sequencer::invalidateSC(const Address& address) { - RequestTable::iterator i = m_writeRequestTable.find(address); - if (i != m_writeRequestTable.end()) { - SequencerRequest* request = i->second; - // The controller has lost the coherence permissions, hence the lock - // on the cache line maintained by the cache should be cleared. - if (request->m_type == RubyRequestType_Store_Conditional) { - m_dataCache_ptr->clearLocked(address); + RequestTable::iterator i = m_RequestTable.find(address); + if (i != m_RequestTable.end()) { + list::iterator it = i->second->begin(); + list::iterator it_end = i->second->end(); + for (; it != it_end; ++it) { + SequencerRequest* request = *it; + // The controller has lost the coherence permissions, hence the + // lock on the cache line maintained by the cache should be + // cleared. + if (request->m_type == RubyRequestType_Store_Conditional) { + m_dataCache_ptr->clearLocked(address); + } } } } @@ -351,9 +280,8 @@ // request->pkt->req->setExtraData(1); } - // + // Independent of success, all SC operations must clear the lock - // m_dataCache_ptr->clearLocked(address); } else if (request->m_type == RubyRequestType_Load_Linked) { // @@ -372,48 +300,69 @@ } void -Sequencer::recordMissLatency(const Cycles cycles, const RubyRequestType type, +Sequencer::recordMissLatency(SequencerRequest* srequest, bool llscSuccess, const MachineType respondingMach, - bool isExternalHit, Cycles issuedTime, - Cycles initialRequestTime, + bool isExternalHit, Cycles initialRequestTime, Cycles forwardRequestTime, - Cycles firstResponseTime, Cycles completionTime) + Cycles firstResponseTime) { - m_latencyHist.sample(cycles); - m_typeLatencyHist[type]->sample(cycles); + PacketPtr pkt = srequest->pkt; + Address request_address(pkt->getAddr()); + RubyRequestType type = srequest->m_type; + Cycles issued_time = srequest->issue_time; + Cycles completion_time = curCycle(); + + assert(curCycle() >= issued_time); + Cycles total_lat = completion_time - issued_time; + + if (initialRequestTime < issued_time) { + // if the request was combined in the protocol with an earlier request + // for the same address, it is possible that it will return an + // initialRequestTime corresponding the earlier request. Since Cycles + // is unsigned, we can't let this request get profiled below. + + total_lat = Cycles(0); + } + + DPRINTFR(ProtocolTrace, "%15s %3s %10s%20s %6s>%-6s %s %d cycles\n", + curTick(), m_version, "Seq", llscSuccess ? "Done" : "SC_Failed", + "", "", request_address, total_lat); + + m_latencyHist.sample(total_lat); + m_typeLatencyHist[type]->sample(total_lat); if (isExternalHit) { - m_missLatencyHist.sample(cycles); - m_missTypeLatencyHist[type]->sample(cycles); + m_missLatencyHist.sample(total_lat); + m_missTypeLatencyHist[type]->sample(total_lat); if (respondingMach != MachineType_NUM) { - m_missMachLatencyHist[respondingMach]->sample(cycles); - m_missTypeMachLatencyHist[type][respondingMach]->sample(cycles); + m_missMachLatencyHist[respondingMach]->sample(total_lat); + m_missTypeMachLatencyHist[type][respondingMach]->sample(total_lat); - if ((issuedTime <= initialRequestTime) && + if ((issued_time <= initialRequestTime) && (initialRequestTime <= forwardRequestTime) && (forwardRequestTime <= firstResponseTime) && - (firstResponseTime <= completionTime)) { + (firstResponseTime <= completion_time)) { m_IssueToInitialDelayHist[respondingMach]->sample( - initialRequestTime - issuedTime); + initialRequestTime - issued_time); m_InitialToForwardDelayHist[respondingMach]->sample( forwardRequestTime - initialRequestTime); m_ForwardToFirstResponseDelayHist[respondingMach]->sample( firstResponseTime - forwardRequestTime); m_FirstResponseToCompletionDelayHist[respondingMach]->sample( - completionTime - firstResponseTime); + completion_time - firstResponseTime); } else { m_IncompleteTimes[respondingMach]++; } } } else { - m_hitLatencyHist.sample(cycles); - m_hitTypeLatencyHist[type]->sample(cycles); + m_hitLatencyHist.sample(total_lat); + m_hitTypeLatencyHist[type]->sample(total_lat); if (respondingMach != MachineType_NUM) { - m_hitMachLatencyHist[respondingMach]->sample(cycles); - m_hitTypeMachLatencyHist[type][respondingMach]->sample(cycles); + m_hitMachLatencyHist[respondingMach]->sample(total_lat); + m_hitTypeMachLatencyHist[type][respondingMach]->sample(total_lat); } } } @@ -425,44 +374,102 @@ const Cycles forwardRequestTime, const Cycles firstResponseTime) { + // + // Free the whole list as we assume we have had the exclusive access + // to this cache line when response for the write comes back + // assert(address == line_address(address)); - assert(m_writeRequestTable.count(line_address(address))); + RequestTable::iterator i = m_RequestTable.find(address); + assert(i != m_RequestTable.end()); - RequestTable::iterator i = m_writeRequestTable.find(address); - assert(i != m_writeRequestTable.end()); - SequencerRequest* request = i->second; + // Perform hitCallback on every cpu request made to this cache block while + // ruby request was outstanding. Since only 1 ruby request was made, + // profile the ruby latency once. + SequencerRequest* request; + bool ruby_request = true; + int aliased_stores = 0; + int aliased_loads = 0; + while (!i->second->empty()) { + request = i->second->front(); + if(ruby_request) { + 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)); + } - m_writeRequestTable.erase(i); - markRemoved(); + // Since the list only contains pointers, it is safe to delete the + // element while still using the request pointer + i->second->pop_front(); - 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)); + // Without coalescing, we can safely remove the table entry. This is + // important because hitCallback() will try retries and we do not want + // the retries to mistakenly think they alias with this request which + // is now complete + if (!coalesce_reqs) { + std::list *p_to_delete_list = i->second; + m_RequestTable.erase(i); + delete(p_to_delete_list); + } - // - // For Alpha, properly handle LL, SC, and write requests with respect to - // locked cache blocks. - // - // Not valid for Network_test protocl - // - bool success = true; - if(!m_usingNetworkTester) - success = handleLlsc(address, request); + // handle write request + if ((request->m_type != RubyRequestType_LD) && + (request->m_type != RubyRequestType_IFETCH)) { + // + // For Alpha, properly handle LL, SC, and write requests with + // respect to locked cache blocks. + // + // Not valid for Network_test protocl + // + bool success = true; + if(!m_usingNetworkTester) + success = handleLlsc(address, request); + if (request->m_type == RubyRequestType_Locked_RMW_Read) { + m_controller->blockOnQueue(address, m_mandatory_q_ptr); + } else if (request->m_type == RubyRequestType_Locked_RMW_Write) { + m_controller->unblock(address); + } - if (request->m_type == RubyRequestType_Locked_RMW_Read) { - m_controller->blockOnQueue(address, m_mandatory_q_ptr); - } else if (request->m_type == RubyRequestType_Locked_RMW_Write) { - m_controller->unblock(address); + if (ruby_request) { + recordMissLatency(request, success, mach, externalHit, + initialRequestTime, forwardRequestTime, + firstResponseTime); + } else { + aliased_stores++; + } + hitCallback(request, data, success, mach, externalHit, + initialRequestTime, forwardRequestTime, + firstResponseTime); + } + // handle read request + else { + assert(!ruby_request); + aliased_loads++; + hitCallback(request, data, true, mach, externalHit, + initialRequestTime, forwardRequestTime, + firstResponseTime); + } + + markRemoved(); + ruby_request = false; + + // without coalescing, we should only execute this loop once + if (!coalesce_reqs) { + return; + } } - hitCallback(request, data, success, mach, externalHit, - initialRequestTime, forwardRequestTime, firstResponseTime); + // free all outstanding requests corresponding to this address + if (coalesce_reqs && i->second->empty()) { + std::list *p_to_delete_list = i->second; + m_RequestTable.erase(i); + delete(p_to_delete_list); + } } void @@ -472,21 +479,74 @@ Cycles forwardRequestTime, Cycles firstResponseTime) { + // + // Free up read requests until we hit the first Write request + // or end of the corresponding list. + // assert(address == line_address(address)); - assert(m_readRequestTable.count(line_address(address))); + RequestTable::iterator i = m_RequestTable.find(address); + assert(i != m_RequestTable.end()); - RequestTable::iterator i = m_readRequestTable.find(address); - assert(i != m_readRequestTable.end()); - SequencerRequest* request = i->second; - m_readRequestTable.erase(i); - markRemoved(); + // Perform hitCallback on every cpu request made to this cache block while + // ruby request was outstanding. Since only 1 ruby request was made, + // profile the ruby latency once. + SequencerRequest* request; + bool ruby_request = true; + int aliased_loads = 0; + while (!i->second->empty()) { + request = i->second->front(); + if (ruby_request) { + assert((request->m_type == RubyRequestType_LD) || + (request->m_type == RubyRequestType_IFETCH)); + } else { + aliased_loads++; + } + if ((request->m_type != RubyRequestType_LD) && + (request->m_type != RubyRequestType_IFETCH)) { + // Write request: reissue request to the cache hierarchy + issueRequest(request->pkt, request->m_second_type); + break; + } - assert((request->m_type == RubyRequestType_LD) || - (request->m_type == RubyRequestType_IFETCH)); + // Since the list only contains pointers, it is safe to delete the + // element while still using the request pointer + i->second->pop_front(); - hitCallback(request, data, true, mach, externalHit, - initialRequestTime, forwardRequestTime, firstResponseTime); + // Without coalescing, we can safely remove the table entry. This is + // important because hitCallback() will try retries and we do not want + // the retries to mistakenly think they alias with this request which + // is now complete + if (!coalesce_reqs) { + std::list *p_to_delete_list = i->second; + m_RequestTable.erase(i); + delete(p_to_delete_list); + } + + if (ruby_request) { + recordMissLatency(request, true, mach, externalHit, + initialRequestTime, forwardRequestTime, + firstResponseTime); + } + hitCallback(request, data, true, mach, externalHit, + initialRequestTime, forwardRequestTime, + firstResponseTime); + + markRemoved(); + ruby_request = false; + + // without coalescing, we should only execute this loop once + if (!coalesce_reqs) { + return; + } + } + + // free all outstanding requests corresponding to this address + if (i->second->empty()) { + std::list *p_to_delete_list = i->second; + m_RequestTable.erase(i); + delete(p_to_delete_list); + } } void @@ -502,7 +562,6 @@ Address request_line_address(pkt->getAddr()); request_line_address.makeLineAddress(); RubyRequestType type = srequest->m_type; - Cycles issued_time = srequest->issue_time; // Set this cache entry to the most recently used if (type == RubyRequestType_IFETCH) { @@ -511,18 +570,10 @@ m_dataCache_ptr->setMRU(request_line_address); } - assert(curCycle() >= issued_time); - Cycles total_latency = curCycle() - issued_time; - // Profile the latency for all demand accesses. - recordMissLatency(total_latency, type, mach, externalHit, issued_time, + recordMissLatency(srequest, llscSuccess, mach, externalHit, initialRequestTime, forwardRequestTime, - firstResponseTime, curCycle()); - - DPRINTFR(ProtocolTrace, "%15s %3s %10s%20s %6s>%-6s %s %d cycles\n", - curTick(), m_version, "Seq", - llscSuccess ? "Done" : "SC_Failed", "", "", - request_address, total_latency); + firstResponseTime); // update the data unless it is a non-data-carrying flush if (RubySystem::getWarmupEnabled()) { @@ -575,7 +626,7 @@ bool Sequencer::empty() const { - return m_writeRequestTable.empty() && m_readRequestTable.empty(); + return m_RequestTable.empty(); } RequestStatus @@ -653,11 +704,20 @@ } } - RequestStatus status = insertRequest(pkt, primary_type); - if (status != RequestStatus_Ready) + RequestStatus status = insertRequest(pkt, primary_type, secondary_type); + + // Only when coalescing is disabled should the Alias status be returned + // and the port be notified that the request failed. Otherwise Aliased + // requests will be considered sucessfully issued. + if (status != RequestStatus_Ready && + (!coalesce_reqs || (status != RequestStatus_Aliased))) { return status; + } - issueRequest(pkt, secondary_type); + // non-aliased with any existing request in the RequestTable, just issue + // to the cache + if (status != RequestStatus_Aliased) + issueRequest(pkt, secondary_type); // TODO: issue hardware prefetches here return RequestStatus_Issued; @@ -727,8 +787,7 @@ { out << "[Sequencer: " << m_version << ", outstanding requests: " << m_outstanding_count - << ", read request table: " << m_readRequestTable - << ", write request table: " << m_writeRequestTable + << ", request table: " << m_RequestTable << "]"; } @@ -749,7 +808,6 @@ SequencerRequestType_to_string(requestType)); } - void Sequencer::evictionCallback(const Address& address) { @@ -759,23 +817,6 @@ void Sequencer::regStats() { - m_store_waiting_on_load - .name(name() + ".store_waiting_on_load") - .desc("Number of times a store aliased with a pending load") - .flags(Stats::nozero); - m_store_waiting_on_store - .name(name() + ".store_waiting_on_store") - .desc("Number of times a store aliased with a pending store") - .flags(Stats::nozero); - m_load_waiting_on_load - .name(name() + ".load_waiting_on_load") - .desc("Number of times a load aliased with a pending load") - .flags(Stats::nozero); - m_load_waiting_on_store - .name(name() + ".load_waiting_on_store") - .desc("Number of times a load aliased with a pending store") - .flags(Stats::nozero); - // These statistical variables are not for display. // The profiler will collate these across different // sequencers and display those collated statistics. diff --git a/src/mem/ruby/system/Sequencer.py b/src/mem/ruby/system/Sequencer.py --- a/src/mem/ruby/system/Sequencer.py +++ b/src/mem/ruby/system/Sequencer.py @@ -67,6 +67,8 @@ deadlock_threshold = Param.Cycles(500000, "max outstanding cycles for a request before deadlock/livelock declared") using_network_tester = Param.Bool(False, "") + coalesce_reqs = Param.Bool(True, + "Coalesces alaised requests to the same cache block") class DMASequencer(MemObject): type = 'DMASequencer'