# Node ID b01d667ec4311e9b72c22f0d2bba1b29a507d12c # Parent ef2bd7e9922ce18df530628e53dedb887378aa28 diff --git a/src/mem/packet.cc b/src/mem/packet.cc --- a/src/mem/packet.cc +++ b/src/mem/packet.cc @@ -338,7 +338,7 @@ void Packet::print(ostream &o, const int verbosity, const string &prefix) const { - ccprintf(o, "%s[%x:%x] %s\n", prefix, + ccprintf(o, "%s[%x:%x] %s", prefix, getAddr(), getAddr() + getSize() - 1, cmdString()); } diff --git a/src/mem/protocol/RubySlicc_Exports.sm b/src/mem/protocol/RubySlicc_Exports.sm --- a/src/mem/protocol/RubySlicc_Exports.sm +++ b/src/mem/protocol/RubySlicc_Exports.sm @@ -269,15 +269,6 @@ Both, desc="Both"; } -// Request Status -enumeration(RequestStatus, desc="...", default="RequestStatus_NULL") { - Ready, desc="The sequencer is ready and the request does not alias"; - 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"; - NULL, desc=""; -} - // LinkDirection enumeration(LinkDirection, desc="...") { In, desc="Inward link direction"; diff --git a/src/mem/ruby/system/DMASequencer.hh b/src/mem/ruby/system/DMASequencer.hh --- a/src/mem/ruby/system/DMASequencer.hh +++ b/src/mem/ruby/system/DMASequencer.hh @@ -54,7 +54,7 @@ DMASequencer(const Params *); void init(); /* external interface */ - RequestStatus makeRequest(PacketPtr pkt); + bool makeRequest(PacketPtr pkt); bool busy() { return m_is_busy;} int outstandingCount() const { return (m_is_busy ? 1 : 0); } bool isDeadlockEventScheduled() const { return false; } diff --git a/src/mem/ruby/system/DMASequencer.cc b/src/mem/ruby/system/DMASequencer.cc --- a/src/mem/ruby/system/DMASequencer.cc +++ b/src/mem/ruby/system/DMASequencer.cc @@ -46,11 +46,11 @@ m_data_block_mask = ~ (~0 << RubySystem::getBlockSizeBits()); } -RequestStatus +bool DMASequencer::makeRequest(PacketPtr pkt) { if (m_is_busy) { - return RequestStatus_BufferFull; + return false; } uint64_t paddr = pkt->getAddr(); @@ -88,7 +88,7 @@ m_mandatory_q_ptr->enqueue(msg); active_request.bytes_issued += msg->getLen(); - return RequestStatus_Issued; + return true; } void diff --git a/src/mem/ruby/system/RubyPort.hh b/src/mem/ruby/system/RubyPort.hh --- a/src/mem/ruby/system/RubyPort.hh +++ b/src/mem/ruby/system/RubyPort.hh @@ -45,7 +45,6 @@ #include #include -#include "mem/protocol/RequestStatus.hh" #include "mem/ruby/buffers/MessageBuffer.hh" #include "mem/ruby/system/System.hh" #include "mem/mem_object.hh" @@ -150,7 +149,7 @@ BaseSlavePort &getSlavePort(const std::string &if_name, PortID idx = InvalidPortID); - virtual RequestStatus makeRequest(PacketPtr pkt) = 0; + virtual bool makeRequest(PacketPtr pkt) = 0; virtual int outstandingCount() const = 0; virtual bool isDeadlockEventScheduled() const = 0; virtual void descheduleDeadlockEvent() = 0; diff --git a/src/mem/ruby/system/RubyPort.cc b/src/mem/ruby/system/RubyPort.cc --- a/src/mem/ruby/system/RubyPort.cc +++ b/src/mem/ruby/system/RubyPort.cc @@ -247,13 +247,14 @@ RubySystem::getBlockSizeBytes()); // Submit the ruby request - RequestStatus requestStatus = ruby_port->makeRequest(pkt); + bool requestStatusOK = ruby_port->makeRequest(pkt); - // If the request successfully issued then we should return true. - // Otherwise, we need to tell the port to retry at a later point - // and return false. - if (requestStatus == RequestStatus_Issued) { - DPRINTF(RubyPort, "Request %s 0x%x issued\n", pkt->cmdString(), + // If the request successfully processed (issued or buffered for + // future handling) then we should return true. Otherwise, we + // need to tell the port to retry at a later point and return + // false. + if (requestStatusOK) { + DPRINTF(RubyPort, "Request %s 0x%x status OK\n", pkt->cmdString(), pkt->getAddr()); return true; } @@ -266,8 +267,7 @@ ruby_port->addToRetryList(this); } - DPRINTF(RubyPort, "Request for address %#x did not issued because %s\n", - pkt->getAddr(), RequestStatus_to_string(requestStatus)); + DPRINTF(RubyPort, "Request for address %#x not issued\n", pkt->getAddr()); return false; } diff --git a/src/mem/ruby/system/RubyPortProxy.hh b/src/mem/ruby/system/RubyPortProxy.hh --- a/src/mem/ruby/system/RubyPortProxy.hh +++ b/src/mem/ruby/system/RubyPortProxy.hh @@ -80,9 +80,9 @@ * functional accesses). * * @param pkt The packet to serve to Ruby - * @returns always a NULL status + * @returns panics, does not return */ - RequestStatus makeRequest(PacketPtr pkt); + bool makeRequest(PacketPtr pkt); /** * Pure virtual member in the super class that we are forced to diff --git a/src/mem/ruby/system/RubyPortProxy.cc b/src/mem/ruby/system/RubyPortProxy.cc --- a/src/mem/ruby/system/RubyPortProxy.cc +++ b/src/mem/ruby/system/RubyPortProxy.cc @@ -53,14 +53,13 @@ // Merely override to not care about the m_controller being NULL } -RequestStatus +bool RubyPortProxy::makeRequest(PacketPtr pkt) { // This sequencer should only be used through the functional // accesses made by the system port and so simply fail if this // happens. panic("RubyPortProxy::makeRequest should not be called"); - return RequestStatus_NULL; } RubyPortProxy* 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) {} }; @@ -63,7 +65,6 @@ // Public Methods void wakeup(); // Used only for deadlock detection - void printProgress(std::ostream& out) const; void resetStats(); void collateStats(); void regStats(); @@ -84,7 +85,7 @@ const Cycles forwardRequestTime = Cycles(0), const Cycles firstResponseTime = Cycles(0)); - RequestStatus makeRequest(PacketPtr pkt); + bool makeRequest(PacketPtr pkt); bool empty() const; int outstandingCount() const { return m_outstanding_count; } @@ -98,7 +99,6 @@ void checkCoherence(const Address& address); void markRemoved(); - void removeRequest(SequencerRequest* request); void evictionCallback(const Address& address); void invalidateSC(const Address& address); @@ -166,7 +166,9 @@ Cycles forwardRequestTime, Cycles firstResponseTime, Cycles completionTime); - RequestStatus insertRequest(PacketPtr pkt, RubyRequestType request_type); + void insertRequest(PacketPtr pkt, RubyRequestType request_type, + RubyRequestType secondary_type); + bool handleLlsc(const Address& address, SequencerRequest* request); // Private copy constructor and assignment operator @@ -180,19 +182,22 @@ 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 std::list RequestList; + + class RequestTableEntry { + public: + RequestList reqList; + bool inLockedRMW; + }; + + 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; //! Histogram for number of outstanding requests per cycle. 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 @@ -87,39 +87,30 @@ // 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; + auto aliasedIt = m_RequestTable.begin(); + auto aliasedIt_end = m_RequestTable.end(); + for (; aliasedIt != aliasedIt_end; ++aliasedIt) { + RequestList &req_list = aliasedIt->second.reqList; + auto it = req_list.begin(); + auto it_end = req_list.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_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())); + Tick issue_tick = (*it)->issue_time * clockPeriod(); + + panic("Possible Deadlock detected. Aborting!\n" + " version: %d request.paddr: 0x%x m_RequestTable: %d " + " current time: %u issue_time: %d difference: %d\n" + " packet: %s\n", + m_version, (*it)->pkt->getAddr(), req_list.size(), + curTick(), issue_tick, curTick() - issue_tick, + (*it)->pkt->print()); + } + + total_outstanding += req_list.size(); } - 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(); - assert(m_outstanding_count == total_outstanding); if (m_outstanding_count > 0) { @@ -156,65 +147,12 @@ } } + +// Insert the request on the correct request table, and issue if appropriate. void -Sequencer::printProgress(ostream& out) const +Sequencer::insertRequest(PacketPtr pkt, RubyRequestType primary_type, + RubyRequestType secondary_type) { -#if 0 - int total_demand = 0; - out << "Sequencer Stats Version " << m_version << endl; - out << "Current time = " << g_system_ptr->getTime() << endl; - out << "---------------" << endl; - out << "outstanding requests" << endl; - - out << "proc " << m_Read - << " version Requests = " << m_readRequestTable.size() << endl; - - // 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++; - } - } - - 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; -#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) -{ - assert(m_outstanding_count == - (m_writeRequestTable.size() + m_readRequestTable.size())); - // See if we should schedule a deadlock check if (!deadlockCheckEvent.scheduled() && getDrainState() != Drainable::Draining) { @@ -223,108 +161,72 @@ 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 - RequestTable::value_type default_entry(line_addr, - (SequencerRequest*) NULL); - 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)) { + SequencerRequest *new_req = + new SequencerRequest(pkt, primary_type, secondary_type, curCycle()); - // 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; - } + // Check if there is any outstanding read request for the same cache line. + RequestTableEntry &entry = m_RequestTable[line_addr]; + RequestList &req_list = entry.reqList; - 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++; + bool issue; // should we issue or defer the request? + + if (entry.inLockedRMW) { + // if we're in the middle of a locked RMW sequence (between the R and + // W), only issue the request if it's the second half (the W) + if (primary_type == RubyRequestType_Locked_RMW_Write) { + issue = true; + req_list.push_front(new_req); + entry.inLockedRMW = false; // no longer waiting for W } else { - // There is an outstanding write request for the cache line - m_store_waiting_on_store++; - return RequestStatus_Aliased; + // if not the second half of the RMW, queue for later + issue = false; + req_list.push_back(new_req); } } 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; - } + // issue request iff no other outstanding requests for this block + issue = req_list.empty(); + req_list.push_back(new_req); } + if (issue) { + DPRINTF(RubySequencer, "insertRequest: issuing request for %x\n", + line_addr.getAddress()); + + issueRequest(pkt, secondary_type); + } else { + DPRINTF(RubySequencer, "insertRequest: appended entry %d for %x\n", + req_list.size(), line_addr.getAddress()); + } + + m_outstanding_count++; m_outstandReqHist.sample(m_outstanding_count); - assert(m_outstanding_count == - (m_writeRequestTable.size() + m_readRequestTable.size())); - - return RequestStatus_Ready; } void 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) { + auto i = m_RequestTable.find(address); + + if (i == m_RequestTable.end()) + return; // no match, nothing to do + + RequestList &req_list = i->second.reqList; + auto it = req_list.begin(); + auto it_end = req_list.end(); + for (; it != it_end; ++it) { + // The controller has lost the coherence permissions, + // hence the lock on the cache line maintained by the + // cache should be cleared. + if ((*it)->m_type == RubyRequestType_Store_Conditional) { m_dataCache_ptr->clearLocked(address); + break; // only need to do it once } } } @@ -353,9 +255,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) { // @@ -427,44 +328,65 @@ 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))); + auto table_iter = m_RequestTable.find(address); + assert(table_iter != m_RequestTable.end()); + RequestTableEntry &entry = table_iter->second; + RequestList &req_list = entry.reqList; + assert(!req_list.empty()); - RequestTable::iterator i = m_writeRequestTable.find(address); - assert(i != m_writeRequestTable.end()); - SequencerRequest* request = i->second; + DPRINTF(RubySequencer, "writeCallback for %x, %d requests\n", + address.getAddress(), req_list.size()); - m_writeRequestTable.erase(i); - markRemoved(); + while (!req_list.empty()) { + SequencerRequest *request = req_list.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)); + // 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); - // - // 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); + assert(!entry.inLockedRMW); + entry.inLockedRMW = true; + } else if (request->m_type == RubyRequestType_Locked_RMW_Write) { + m_controller->unblock(address); + // should have been cleared when Locked_RMW_Write was issued + assert(!entry.inLockedRMW); + } - 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); + hitCallback(request, data, success, mach, externalHit, + initialRequestTime, forwardRequestTime, + firstResponseTime); + } else { + // handle read request + hitCallback(request, data, true, mach, externalHit, + initialRequestTime, forwardRequestTime, + firstResponseTime); + } + + req_list.pop_front(); + markRemoved(); } - hitCallback(request, data, success, mach, externalHit, - initialRequestTime, forwardRequestTime, firstResponseTime); + // since we've satisfied all the requests, free the table entry, unless we + // need to keep it around for the inLockedRMW flag + assert(req_list.empty()); + if (!entry.inLockedRMW) + m_RequestTable.erase(table_iter); } void @@ -474,21 +396,57 @@ 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_readRequestTable.find(address); - assert(i != m_readRequestTable.end()); - SequencerRequest* request = i->second; + auto table_iter = m_RequestTable.find(address); + assert(table_iter != m_RequestTable.end()); + RequestTableEntry &entry = table_iter->second; + RequestList &req_list = entry.reqList; + assert(!req_list.empty()); - m_readRequestTable.erase(i); - markRemoved(); + DPRINTF(RubySequencer, "readCallback for %x, %d requests\n", + address.getAddress(), req_list.size()); - assert((request->m_type == RubyRequestType_LD) || - (request->m_type == RubyRequestType_IFETCH)); + while (!req_list.empty()) { + SequencerRequest *request = req_list.front(); - hitCallback(request, data, true, mach, externalHit, - initialRequestTime, forwardRequestTime, firstResponseTime); + // check for a write + if ((request->m_type != RubyRequestType_LD) && + (request->m_type != RubyRequestType_IFETCH)) { + + DPRINTF(RubySequencer, + "readCallback(%x): reissuing %s (%s) with %d requests\n", + address, + RubyRequestType_to_string(request->m_type), + RubyRequestType_to_string(request->m_second_type), + req_list.size()); + + // If we issued a Locked_RMW_Write here, we'd need to clear the + // inLockedRMW flag... but that shouldn't be possible (since the + // Locked_RMW_Read goes through writeCallback()). + assert(request->m_type != RubyRequestType_Locked_RMW_Write); + + // Write request: reissue request to the cache hierarchy + issueRequest(request->pkt, request->m_second_type); + return; + } + + hitCallback(request, data, true, mach, externalHit, + initialRequestTime, forwardRequestTime, + firstResponseTime); + + req_list.pop_front(); + markRemoved(); + } + + // if we fell out of the loop, we've satisfied all the requests, + // so free the table entry + assert(req_list.empty()); + m_RequestTable.erase(table_iter); } void @@ -578,14 +536,16 @@ bool Sequencer::empty() const { - return m_writeRequestTable.empty() && m_readRequestTable.empty(); + return m_RequestTable.empty(); } -RequestStatus +bool Sequencer::makeRequest(PacketPtr pkt) { + DPRINTF(RubySequencer, "makeRequest: %s\n", pkt->print()); + if (m_outstanding_count >= m_max_outstanding_requests) { - return RequestStatus_BufferFull; + return false; } RubyRequestType primary_type = RubyRequestType_NULL; @@ -656,14 +616,9 @@ } } - RequestStatus status = insertRequest(pkt, primary_type); - if (status != RequestStatus_Ready) - return status; - - issueRequest(pkt, secondary_type); - - // TODO: issue hardware prefetches here - return RequestStatus_Issued; + // insertRequest() will buffer or issue the request as appropriate + insertRequest(pkt, primary_type, secondary_type); + return true; } void @@ -706,29 +661,31 @@ m_mandatory_q_ptr->enqueue(msg, latency); } -template -std::ostream & -operator<<(ostream &out, const m5::hash_map &map) -{ - typename m5::hash_map::const_iterator i = map.begin(); - typename m5::hash_map::const_iterator end = map.end(); - - out << "["; - for (; i != end; ++i) - out << " " << i->first << "=" << i->second; - out << " ]"; - - return out; -} - void Sequencer::print(ostream& out) const { out << "[Sequencer: " << m_version - << ", outstanding requests: " << m_outstanding_count - << ", read request table: " << m_readRequestTable - << ", write request table: " << m_writeRequestTable - << "]"; + << ", outstanding requests: " << m_outstanding_count << endl; + + // print the request table + auto table_it = m_RequestTable.begin(); + auto table_it_end = m_RequestTable.end(); + + for (; table_it != table_it_end; ++table_it) { + const RequestList &req_list = table_it->second.reqList; + + auto list_it = req_list.begin(); + auto list_it_end = req_list.end(); + for (; list_it != list_it_end; ++list_it) { + SequencerRequest *request = *list_it; + out << "\t" << request->m_type + << " Address " << request->pkt->getAddr() + << " Posted " << request->issue_time + << endl; + } + } + + out << "]"; } // this can be called from setState whenever coherence permissions are @@ -748,7 +705,6 @@ SequencerRequestType_to_string(requestType)); } - void Sequencer::evictionCallback(const Address& address) { @@ -758,23 +714,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.