Sequencer.cc revision 8717:5c253f1031d7
12810SN/A/* 29614Srene.dejong@arm.com * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood 38856Sandreas.hansson@arm.com * All rights reserved. 48856Sandreas.hansson@arm.com * 58856Sandreas.hansson@arm.com * Redistribution and use in source and binary forms, with or without 68856Sandreas.hansson@arm.com * modification, are permitted provided that the following conditions are 78856Sandreas.hansson@arm.com * met: redistributions of source code must retain the above copyright 88856Sandreas.hansson@arm.com * notice, this list of conditions and the following disclaimer; 98856Sandreas.hansson@arm.com * redistributions in binary form must reproduce the above copyright 108856Sandreas.hansson@arm.com * notice, this list of conditions and the following disclaimer in the 118856Sandreas.hansson@arm.com * documentation and/or other materials provided with the distribution; 128856Sandreas.hansson@arm.com * neither the name of the copyright holders nor the names of its 138856Sandreas.hansson@arm.com * contributors may be used to endorse or promote products derived from 142810SN/A * this software without specific prior written permission. 152810SN/A * 162810SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 172810SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 182810SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 192810SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 202810SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 212810SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 222810SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 232810SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 242810SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 252810SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 262810SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 272810SN/A */ 282810SN/A 292810SN/A#include "base/misc.hh" 302810SN/A#include "base/str.hh" 312810SN/A#include "config/the_isa.hh" 322810SN/A#if THE_ISA == X86_ISA 332810SN/A#include "arch/x86/insts/microldstop.hh" 342810SN/A#endif // X86_ISA 352810SN/A#include "cpu/testers/rubytest/RubyTester.hh" 362810SN/A#include "debug/MemoryAccess.hh" 372810SN/A#include "debug/ProtocolTrace.hh" 382810SN/A#include "debug/RubySequencer.hh" 392810SN/A#include "mem/protocol/PrefetchBit.hh" 402810SN/A#include "mem/protocol/RubyAccessMode.hh" 412810SN/A#include "mem/ruby/buffers/MessageBuffer.hh" 422810SN/A#include "mem/ruby/common/Global.hh" 432810SN/A#include "mem/ruby/profiler/Profiler.hh" 442810SN/A#include "mem/ruby/slicc_interface/RubyRequest.hh" 452810SN/A#include "mem/ruby/system/CacheMemory.hh" 462810SN/A#include "mem/ruby/system/Sequencer.hh" 472810SN/A#include "mem/ruby/system/System.hh" 4811486Snikos.nikoleris@arm.com#include "mem/packet.hh" 4911486Snikos.nikoleris@arm.com#include "params/RubySequencer.hh" 508232Snate@binkert.org 519152Satgutier@umich.eduusing namespace std; 5211486Snikos.nikoleris@arm.com 5311486Snikos.nikoleris@arm.comSequencer * 549795Sandreas.hansson@arm.comRubySequencerParams::create() 559795Sandreas.hansson@arm.com{ 5610263Satgutier@umich.edu return new Sequencer(this); 578786Sgblack@eecs.umich.edu} 582810SN/A 592810SN/ASequencer::Sequencer(const Params *p) 602810SN/A : RubyPort(p), deadlockCheckEvent(this) 618856Sandreas.hansson@arm.com{ 628856Sandreas.hansson@arm.com m_store_waiting_on_load_cycles = 0; 638856Sandreas.hansson@arm.com m_store_waiting_on_store_cycles = 0; 648922Swilliam.wang@arm.com m_load_waiting_on_store_cycles = 0; 6512084Sspwilson2@wisc.edu m_load_waiting_on_load_cycles = 0; 6612084Sspwilson2@wisc.edu 678856Sandreas.hansson@arm.com m_outstanding_count = 0; 688856Sandreas.hansson@arm.com 694475SN/A m_deadlock_threshold = 0; 7011053Sandreas.hansson@arm.com m_instCache_ptr = NULL; 715034SN/A m_dataCache_ptr = NULL; 7210360Sandreas.hansson@arm.com 7311377Sandreas.hansson@arm.com m_instCache_ptr = p->icache; 7411377Sandreas.hansson@arm.com m_dataCache_ptr = p->dcache; 7511053Sandreas.hansson@arm.com m_max_outstanding_requests = p->max_outstanding_requests; 7611722Ssophiane.senni@gmail.com m_deadlock_threshold = p->deadlock_threshold; 7711722Ssophiane.senni@gmail.com 7811722Ssophiane.senni@gmail.com assert(m_max_outstanding_requests > 0); 7911722Ssophiane.senni@gmail.com assert(m_deadlock_threshold > 0); 809263Smrinmoy.ghosh@arm.com assert(m_instCache_ptr != NULL); 815034SN/A assert(m_dataCache_ptr != NULL); 8211331Sandreas.hansson@arm.com 8310884Sandreas.hansson@arm.com m_usingNetworkTester = p->using_network_tester; 844626SN/A} 8510360Sandreas.hansson@arm.com 8611484Snikos.nikoleris@arm.comSequencer::~Sequencer() 875034SN/A{ 888883SAli.Saidi@ARM.com} 898833Sdam.sunwoo@arm.com 904458SN/Avoid 9111377Sandreas.hansson@arm.comSequencer::wakeup() 9211377Sandreas.hansson@arm.com{ 9311377Sandreas.hansson@arm.com // Check for deadlock of any of the requests 9411377Sandreas.hansson@arm.com Time current_time = g_eventQueue_ptr->getTime(); 9511377Sandreas.hansson@arm.com 9611377Sandreas.hansson@arm.com // Check across all outstanding requests 9711331Sandreas.hansson@arm.com int total_outstanding = 0; 9811331Sandreas.hansson@arm.com 992810SN/A RequestTable::iterator read = m_readRequestTable.begin(); 1002810SN/A RequestTable::iterator read_end = m_readRequestTable.end(); 1013013SN/A for (; read != read_end; ++read) { 1028856Sandreas.hansson@arm.com SequencerRequest* request = read->second; 1032810SN/A if (current_time - request->issue_time < m_deadlock_threshold) 1043013SN/A continue; 10510714Sandreas.hansson@arm.com 1062810SN/A panic("Possible Deadlock detected. Aborting!\n" 1079614Srene.dejong@arm.com "version: %d request.paddr: 0x%x m_readRequestTable: %d " 1089614Srene.dejong@arm.com "current time: %u issue_time: %d difference: %d\n", m_version, 1099614Srene.dejong@arm.com Address(request->pkt->getAddr()), m_readRequestTable.size(), 11010345SCurtis.Dunham@arm.com current_time, request->issue_time, 11110714Sandreas.hansson@arm.com current_time - request->issue_time); 11210345SCurtis.Dunham@arm.com } 1139614Srene.dejong@arm.com 1142810SN/A RequestTable::iterator write = m_writeRequestTable.begin(); 1152810SN/A RequestTable::iterator write_end = m_writeRequestTable.end(); 1162810SN/A for (; write != write_end; ++write) { 1178856Sandreas.hansson@arm.com SequencerRequest* request = write->second; 1182810SN/A if (current_time - request->issue_time < m_deadlock_threshold) 1193013SN/A continue; 12010714Sandreas.hansson@arm.com 1213013SN/A panic("Possible Deadlock detected. Aborting!\n" 1228856Sandreas.hansson@arm.com "version: %d request.paddr: 0x%x m_writeRequestTable: %d " 12310714Sandreas.hansson@arm.com "current time: %u issue_time: %d difference: %d\n", m_version, 1248922Swilliam.wang@arm.com Address(request->pkt->getAddr()), m_writeRequestTable.size(), 1252897SN/A current_time, request->issue_time, 1262810SN/A current_time - request->issue_time); 1272810SN/A } 12810344Sandreas.hansson@arm.com 12910344Sandreas.hansson@arm.com total_outstanding += m_writeRequestTable.size(); 13010344Sandreas.hansson@arm.com total_outstanding += m_readRequestTable.size(); 13110714Sandreas.hansson@arm.com 13210344Sandreas.hansson@arm.com assert(m_outstanding_count == total_outstanding); 13310344Sandreas.hansson@arm.com 13410344Sandreas.hansson@arm.com if (m_outstanding_count > 0) { 13510713Sandreas.hansson@arm.com // If there are still outstanding requests, keep checking 13610344Sandreas.hansson@arm.com schedule(deadlockCheckEvent, 1372844SN/A m_deadlock_threshold * g_eventQueue_ptr->getClock() + 1382810SN/A curTick()); 1392858SN/A } 1402858SN/A} 1418856Sandreas.hansson@arm.com 1428922Swilliam.wang@arm.comvoid 1438711Sandreas.hansson@arm.comSequencer::printStats(ostream & out) const 14411331Sandreas.hansson@arm.com{ 1452858SN/A out << "Sequencer: " << m_name << endl 1462858SN/A << " store_waiting_on_load_cycles: " 1479294Sandreas.hansson@arm.com << m_store_waiting_on_load_cycles << endl 1489294Sandreas.hansson@arm.com << " store_waiting_on_store_cycles: " 1498922Swilliam.wang@arm.com << m_store_waiting_on_store_cycles << endl 1508922Swilliam.wang@arm.com << " load_waiting_on_load_cycles: " 1518922Swilliam.wang@arm.com << m_load_waiting_on_load_cycles << endl 1528922Swilliam.wang@arm.com << " load_waiting_on_store_cycles: " 1538922Swilliam.wang@arm.com << m_load_waiting_on_store_cycles << endl; 1548922Swilliam.wang@arm.com} 1558922Swilliam.wang@arm.com 1568922Swilliam.wang@arm.comvoid 1579294Sandreas.hansson@arm.comSequencer::printProgress(ostream& out) const 1589294Sandreas.hansson@arm.com{ 1598922Swilliam.wang@arm.com#if 0 1608922Swilliam.wang@arm.com int total_demand = 0; 1618922Swilliam.wang@arm.com out << "Sequencer Stats Version " << m_version << endl; 1628922Swilliam.wang@arm.com out << "Current time = " << g_eventQueue_ptr->getTime() << endl; 1638922Swilliam.wang@arm.com out << "---------------" << endl; 1648922Swilliam.wang@arm.com out << "outstanding requests" << endl; 1658922Swilliam.wang@arm.com 1664628SN/A out << "proc " << m_Read 16710821Sandreas.hansson@arm.com << " version Requests = " << m_readRequestTable.size() << endl; 16810821Sandreas.hansson@arm.com 16910821Sandreas.hansson@arm.com // print the request table 17010821Sandreas.hansson@arm.com RequestTable::iterator read = m_readRequestTable.begin(); 17110821Sandreas.hansson@arm.com RequestTable::iterator read_end = m_readRequestTable.end(); 17210821Sandreas.hansson@arm.com for (; read != read_end; ++read) { 17310821Sandreas.hansson@arm.com SequencerRequest* request = read->second; 17410821Sandreas.hansson@arm.com out << "\tRequest[ " << i << " ] = " << request->type 17510821Sandreas.hansson@arm.com << " Address " << rkeys[i] 17610821Sandreas.hansson@arm.com << " Posted " << request->issue_time 17710821Sandreas.hansson@arm.com << " PF " << PrefetchBit_No << endl; 1782858SN/A total_demand++; 1792810SN/A } 1802810SN/A 18111522Sstephan.diestelhorst@arm.com out << "proc " << m_version 18211522Sstephan.diestelhorst@arm.com << " Write Requests = " << m_writeRequestTable.size << endl; 1832810SN/A 1842810SN/A // print the request table 1852810SN/A RequestTable::iterator write = m_writeRequestTable.begin(); 1864022SN/A RequestTable::iterator write_end = m_writeRequestTable.end(); 1874022SN/A for (; write != write_end; ++write) { 1884022SN/A SequencerRequest* request = write->second; 1892810SN/A out << "\tRequest[ " << i << " ] = " << request.getType() 1902810SN/A << " Address " << wkeys[i] 1918833Sdam.sunwoo@arm.com << " Posted " << request.getTime() 1922810SN/A << " PF " << request.getPrefetch() << endl; 1932810SN/A if (request.getPrefetch() == PrefetchBit_No) { 1942810SN/A total_demand++; 1952810SN/A } 1968833Sdam.sunwoo@arm.com } 1978833Sdam.sunwoo@arm.com 1988833Sdam.sunwoo@arm.com out << endl; 1992810SN/A 2002810SN/A out << "Total Number Outstanding: " << m_outstanding_count << endl 2014871SN/A << "Total Number Demand : " << total_demand << endl 2024871SN/A << "Total Number Prefetches : " << m_outstanding_count - total_demand 2034871SN/A << endl << endl << endl; 2044871SN/A#endif 20511455Sandreas.hansson@arm.com} 20610885Sandreas.hansson@arm.com 2074871SN/Avoid 2084871SN/ASequencer::printConfig(ostream& out) const 2094871SN/A{ 2104871SN/A out << "Seqeuncer config: " << m_name << endl 2114871SN/A << " controller: " << m_controller->getName() << endl 2122810SN/A << " version: " << m_version << endl 2132810SN/A << " max_outstanding_requests: " << m_max_outstanding_requests << endl 2142810SN/A << " deadlock_threshold: " << m_deadlock_threshold << endl; 2158833Sdam.sunwoo@arm.com} 2162810SN/A 2174871SN/A// Insert the request on the correct request table. Return true if 2188833Sdam.sunwoo@arm.com// the entry was already present. 2198833Sdam.sunwoo@arm.comRequestStatus 2208833Sdam.sunwoo@arm.comSequencer::insertRequest(PacketPtr pkt, RubyRequestType request_type) 2212810SN/A{ 2222810SN/A assert(m_outstanding_count == 2232810SN/A (m_writeRequestTable.size() + m_readRequestTable.size())); 2242810SN/A 2258833Sdam.sunwoo@arm.com // See if we should schedule a deadlock check 2262810SN/A if (deadlockCheckEvent.scheduled() == false) { 2274871SN/A schedule(deadlockCheckEvent, m_deadlock_threshold + curTick()); 2288833Sdam.sunwoo@arm.com } 2298833Sdam.sunwoo@arm.com 2308833Sdam.sunwoo@arm.com Address line_addr(pkt->getAddr()); 2312810SN/A line_addr.makeLineAddress(); 2322810SN/A if ((request_type == RubyRequestType_ST) || 2334022SN/A (request_type == RubyRequestType_RMW_Read) || 2344022SN/A (request_type == RubyRequestType_RMW_Write) || 2354022SN/A (request_type == RubyRequestType_Load_Linked) || 2362810SN/A (request_type == RubyRequestType_Store_Conditional) || 2372810SN/A (request_type == RubyRequestType_Locked_RMW_Read) || 2388833Sdam.sunwoo@arm.com (request_type == RubyRequestType_Locked_RMW_Write) || 2392810SN/A (request_type == RubyRequestType_FLUSH)) { 2402810SN/A 2412810SN/A // Check if there is any outstanding read request for the same 2422810SN/A // cache line. 2438833Sdam.sunwoo@arm.com if (m_readRequestTable.count(line_addr) > 0) { 2448833Sdam.sunwoo@arm.com m_store_waiting_on_load_cycles++; 2458833Sdam.sunwoo@arm.com return RequestStatus_Aliased; 2462810SN/A } 2472810SN/A 2482810SN/A pair<RequestTable::iterator, bool> r = 2492810SN/A m_writeRequestTable.insert(RequestTable::value_type(line_addr, 0)); 2502810SN/A if (r.second) { 2518833Sdam.sunwoo@arm.com RequestTable::iterator i = r.first; 2522810SN/A i->second = new SequencerRequest(pkt, request_type, 2534871SN/A g_eventQueue_ptr->getTime()); 2548833Sdam.sunwoo@arm.com m_outstanding_count++; 2558833Sdam.sunwoo@arm.com } else { 2568833Sdam.sunwoo@arm.com // There is an outstanding write request for the cache line 2572810SN/A m_store_waiting_on_store_cycles++; 2582810SN/A return RequestStatus_Aliased; 2592810SN/A } 2602810SN/A } else { 2618833Sdam.sunwoo@arm.com // Check if there is any outstanding write request for the same 2622810SN/A // cache line. 2634871SN/A if (m_writeRequestTable.count(line_addr) > 0) { 2648833Sdam.sunwoo@arm.com m_load_waiting_on_store_cycles++; 2658833Sdam.sunwoo@arm.com return RequestStatus_Aliased; 2668833Sdam.sunwoo@arm.com } 2672810SN/A 2682810SN/A pair<RequestTable::iterator, bool> r = 2694022SN/A m_readRequestTable.insert(RequestTable::value_type(line_addr, 0)); 2704022SN/A 2714022SN/A if (r.second) { 2722810SN/A RequestTable::iterator i = r.first; 2732810SN/A i->second = new SequencerRequest(pkt, request_type, 2748833Sdam.sunwoo@arm.com g_eventQueue_ptr->getTime()); 2752810SN/A m_outstanding_count++; 2762810SN/A } else { 2772810SN/A // There is an outstanding read request for the cache line 2782810SN/A m_load_waiting_on_load_cycles++; 2798833Sdam.sunwoo@arm.com return RequestStatus_Aliased; 2808833Sdam.sunwoo@arm.com } 2818833Sdam.sunwoo@arm.com } 2822810SN/A 2832810SN/A g_system_ptr->getProfiler()->sequencerRequests(m_outstanding_count); 2842810SN/A assert(m_outstanding_count == 2852810SN/A (m_writeRequestTable.size() + m_readRequestTable.size())); 2862810SN/A 2878833Sdam.sunwoo@arm.com return RequestStatus_Ready; 2882810SN/A} 2894871SN/A 2908833Sdam.sunwoo@arm.comvoid 2918833Sdam.sunwoo@arm.comSequencer::markRemoved() 2928833Sdam.sunwoo@arm.com{ 2932810SN/A m_outstanding_count--; 2942810SN/A assert(m_outstanding_count == 2952810SN/A m_writeRequestTable.size() + m_readRequestTable.size()); 2962810SN/A} 2978833Sdam.sunwoo@arm.com 2982810SN/Avoid 2994871SN/ASequencer::removeRequest(SequencerRequest* srequest) 3008833Sdam.sunwoo@arm.com{ 3018833Sdam.sunwoo@arm.com assert(m_outstanding_count == 3028833Sdam.sunwoo@arm.com m_writeRequestTable.size() + m_readRequestTable.size()); 3032810SN/A 3042810SN/A Address line_addr(srequest->pkt->getAddr()); 3054022SN/A line_addr.makeLineAddress(); 3064022SN/A if ((srequest->m_type == RubyRequestType_ST) || 3074022SN/A (srequest->m_type == RubyRequestType_RMW_Read) || 3082810SN/A (srequest->m_type == RubyRequestType_RMW_Write) || 3092810SN/A (srequest->m_type == RubyRequestType_Load_Linked) || 3102810SN/A (srequest->m_type == RubyRequestType_Store_Conditional) || 3112810SN/A (srequest->m_type == RubyRequestType_Locked_RMW_Read) || 3122810SN/A (srequest->m_type == RubyRequestType_Locked_RMW_Write)) { 3132810SN/A m_writeRequestTable.erase(line_addr); 3148833Sdam.sunwoo@arm.com } else { 3152810SN/A m_readRequestTable.erase(line_addr); 3168833Sdam.sunwoo@arm.com } 3178833Sdam.sunwoo@arm.com 3188833Sdam.sunwoo@arm.com markRemoved(); 3192810SN/A} 3202810SN/A 3212810SN/Abool 3222810SN/ASequencer::handleLlsc(const Address& address, SequencerRequest* request) 3232810SN/A{ 3248833Sdam.sunwoo@arm.com // 3252810SN/A // The success flag indicates whether the LLSC operation was successful. 3262810SN/A // LL ops will always succeed, but SC may fail if the cache line is no 3278833Sdam.sunwoo@arm.com // longer locked. 3288833Sdam.sunwoo@arm.com // 3298833Sdam.sunwoo@arm.com bool success = true; 3302810SN/A if (request->m_type == RubyRequestType_Store_Conditional) { 3312810SN/A if (!m_dataCache_ptr->isLocked(address, m_version)) { 3322810SN/A // 3332810SN/A // For failed SC requests, indicate the failure to the cpu by 3348833Sdam.sunwoo@arm.com // setting the extra data to zero. 3352810SN/A // 3362810SN/A request->pkt->req->setExtraData(0); 3378833Sdam.sunwoo@arm.com success = false; 3388833Sdam.sunwoo@arm.com } else { 3398833Sdam.sunwoo@arm.com // 3402810SN/A // For successful SC requests, indicate the success to the cpu by 3412810SN/A // setting the extra data to one. 3424022SN/A // 3434022SN/A request->pkt->req->setExtraData(1); 3444022SN/A } 3452810SN/A // 3462810SN/A // Independent of success, all SC operations must clear the lock 3472810SN/A // 3482810SN/A m_dataCache_ptr->clearLocked(address); 3492810SN/A } else if (request->m_type == RubyRequestType_Load_Linked) { 3502810SN/A // 3518833Sdam.sunwoo@arm.com // Note: To fully follow Alpha LLSC semantics, should the LL clear any 3522810SN/A // previously locked cache lines? 3538833Sdam.sunwoo@arm.com // 3548833Sdam.sunwoo@arm.com m_dataCache_ptr->setLocked(address, m_version); 3558833Sdam.sunwoo@arm.com } else if ((m_dataCache_ptr->isTagPresent(address)) && 3562810SN/A (m_dataCache_ptr->isLocked(address, m_version))) { 3572810SN/A // 3582810SN/A // Normal writes should clear the locked address 3592810SN/A // 3602810SN/A m_dataCache_ptr->clearLocked(address); 3618833Sdam.sunwoo@arm.com } 3622810SN/A return success; 3632810SN/A} 3648833Sdam.sunwoo@arm.com 3658833Sdam.sunwoo@arm.comvoid 3668833Sdam.sunwoo@arm.comSequencer::writeCallback(const Address& address, DataBlock& data) 3672810SN/A{ 3682810SN/A writeCallback(address, GenericMachineType_NULL, data); 3692810SN/A} 3702810SN/A 3718833Sdam.sunwoo@arm.comvoid 3722810SN/ASequencer::writeCallback(const Address& address, 3732810SN/A GenericMachineType mach, 3748833Sdam.sunwoo@arm.com DataBlock& data) 3758833Sdam.sunwoo@arm.com{ 3768833Sdam.sunwoo@arm.com writeCallback(address, mach, data, 0, 0, 0); 3772810SN/A} 3782810SN/A 3794022SN/Avoid 3804022SN/ASequencer::writeCallback(const Address& address, 3814022SN/A GenericMachineType mach, 3822810SN/A DataBlock& data, 3832810SN/A Time initialRequestTime, 3842810SN/A Time forwardRequestTime, 3852810SN/A Time firstResponseTime) 3862810SN/A{ 3872810SN/A assert(address == line_address(address)); 3882810SN/A assert(m_writeRequestTable.count(line_address(address))); 3892810SN/A 3908833Sdam.sunwoo@arm.com RequestTable::iterator i = m_writeRequestTable.find(address); 3918833Sdam.sunwoo@arm.com assert(i != m_writeRequestTable.end()); 3928833Sdam.sunwoo@arm.com SequencerRequest* request = i->second; 3938833Sdam.sunwoo@arm.com 3942810SN/A m_writeRequestTable.erase(i); 3952810SN/A markRemoved(); 3962810SN/A 3972810SN/A assert((request->m_type == RubyRequestType_ST) || 3982810SN/A (request->m_type == RubyRequestType_ATOMIC) || 3998833Sdam.sunwoo@arm.com (request->m_type == RubyRequestType_RMW_Read) || 4002810SN/A (request->m_type == RubyRequestType_RMW_Write) || 4012810SN/A (request->m_type == RubyRequestType_Load_Linked) || 4028833Sdam.sunwoo@arm.com (request->m_type == RubyRequestType_Store_Conditional) || 4038833Sdam.sunwoo@arm.com (request->m_type == RubyRequestType_Locked_RMW_Read) || 4048833Sdam.sunwoo@arm.com (request->m_type == RubyRequestType_Locked_RMW_Write) || 4052810SN/A (request->m_type == RubyRequestType_FLUSH)); 4062810SN/A 4072810SN/A 4082810SN/A // 4098833Sdam.sunwoo@arm.com // For Alpha, properly handle LL, SC, and write requests with respect to 4102810SN/A // locked cache blocks. 4112810SN/A // 4128833Sdam.sunwoo@arm.com // Not valid for Network_test protocl 4138833Sdam.sunwoo@arm.com // 4148833Sdam.sunwoo@arm.com bool success = true; 4152810SN/A if(!m_usingNetworkTester) 4162810SN/A success = handleLlsc(address, request); 4172810SN/A 4182810SN/A if (request->m_type == RubyRequestType_Locked_RMW_Read) { 4192810SN/A m_controller->blockOnQueue(address, m_mandatory_q_ptr); 4202810SN/A } else if (request->m_type == RubyRequestType_Locked_RMW_Write) { 4212810SN/A m_controller->unblock(address); 4222810SN/A } 4232810SN/A 4242810SN/A hitCallback(request, mach, data, success, 4252810SN/A initialRequestTime, forwardRequestTime, firstResponseTime); 4262810SN/A} 4272810SN/A 4282810SN/Avoid 4292810SN/ASequencer::readCallback(const Address& address, DataBlock& data) 4302810SN/A{ 4312810SN/A readCallback(address, GenericMachineType_NULL, data); 4322810SN/A} 4332810SN/A 4342810SN/Avoid 4352810SN/ASequencer::readCallback(const Address& address, 4362810SN/A GenericMachineType mach, 4372810SN/A DataBlock& data) 4382810SN/A{ 4392810SN/A readCallback(address, mach, data, 0, 0, 0); 4402810SN/A} 4412810SN/A 44211436SRekai.GonzalezAlberquilla@arm.comvoid 44311436SRekai.GonzalezAlberquilla@arm.comSequencer::readCallback(const Address& address, 44411436SRekai.GonzalezAlberquilla@arm.com GenericMachineType mach, 44511436SRekai.GonzalezAlberquilla@arm.com DataBlock& data, 44611436SRekai.GonzalezAlberquilla@arm.com Time initialRequestTime, 44711436SRekai.GonzalezAlberquilla@arm.com Time forwardRequestTime, 4484626SN/A Time firstResponseTime) 4498833Sdam.sunwoo@arm.com{ 4504626SN/A assert(address == line_address(address)); 4514626SN/A assert(m_readRequestTable.count(line_address(address))); 4528833Sdam.sunwoo@arm.com 4534626SN/A RequestTable::iterator i = m_readRequestTable.find(address); 4548833Sdam.sunwoo@arm.com assert(i != m_readRequestTable.end()); 4558833Sdam.sunwoo@arm.com SequencerRequest* request = i->second; 4568833Sdam.sunwoo@arm.com 4574626SN/A m_readRequestTable.erase(i); 4584626SN/A markRemoved(); 4594626SN/A 4604626SN/A assert((request->m_type == RubyRequestType_LD) || 4614626SN/A (request->m_type == RubyRequestType_IFETCH)); 4624626SN/A 4634626SN/A hitCallback(request, mach, data, true, 4644626SN/A initialRequestTime, forwardRequestTime, firstResponseTime); 4658833Sdam.sunwoo@arm.com} 4664626SN/A 4674626SN/Avoid 4684626SN/ASequencer::hitCallback(SequencerRequest* srequest, 4694626SN/A GenericMachineType mach, 4708833Sdam.sunwoo@arm.com DataBlock& data, 4718833Sdam.sunwoo@arm.com bool success, 4728833Sdam.sunwoo@arm.com Time initialRequestTime, 4734626SN/A Time forwardRequestTime, 4744626SN/A Time firstResponseTime) 4754626SN/A{ 4764626SN/A PacketPtr pkt = srequest->pkt; 4774626SN/A Address request_address(pkt->getAddr()); 4788833Sdam.sunwoo@arm.com Address request_line_address(pkt->getAddr()); 4794626SN/A request_line_address.makeLineAddress(); 4804871SN/A RubyRequestType type = srequest->m_type; 4818833Sdam.sunwoo@arm.com Time issued_time = srequest->issue_time; 4828833Sdam.sunwoo@arm.com 4838833Sdam.sunwoo@arm.com // Set this cache entry to the most recently used 4844626SN/A if (type == RubyRequestType_IFETCH) { 4854626SN/A if (m_instCache_ptr->isTagPresent(request_line_address)) 4864626SN/A m_instCache_ptr->setMRU(request_line_address); 4874626SN/A } else { 4888833Sdam.sunwoo@arm.com if (m_dataCache_ptr->isTagPresent(request_line_address)) 4894626SN/A m_dataCache_ptr->setMRU(request_line_address); 4904871SN/A } 4918833Sdam.sunwoo@arm.com 4928833Sdam.sunwoo@arm.com assert(g_eventQueue_ptr->getTime() >= issued_time); 4938833Sdam.sunwoo@arm.com Time miss_latency = g_eventQueue_ptr->getTime() - issued_time; 4944626SN/A 4954626SN/A // Profile the miss latency for all non-zero demand misses 4964626SN/A if (miss_latency != 0) { 4974626SN/A g_system_ptr->getProfiler()->missLatency(miss_latency, type, mach); 4984626SN/A 4994626SN/A if (mach == GenericMachineType_L1Cache_wCC) { 5004626SN/A g_system_ptr->getProfiler()->missLatencyWcc(issued_time, 5018833Sdam.sunwoo@arm.com initialRequestTime, 5024626SN/A forwardRequestTime, 5034626SN/A firstResponseTime, 5044626SN/A g_eventQueue_ptr->getTime()); 5054626SN/A } 5068833Sdam.sunwoo@arm.com 5078833Sdam.sunwoo@arm.com if (mach == GenericMachineType_Directory) { 5088833Sdam.sunwoo@arm.com g_system_ptr->getProfiler()->missLatencyDir(issued_time, 5094626SN/A initialRequestTime, 5104626SN/A forwardRequestTime, 5114626SN/A firstResponseTime, 5124626SN/A g_eventQueue_ptr->getTime()); 5134626SN/A } 5148833Sdam.sunwoo@arm.com 5154626SN/A DPRINTFR(ProtocolTrace, "%15s %3s %10s%20s %6s>%-6s %s %d cycles\n", 5164871SN/A curTick(), m_version, "Seq", 5178833Sdam.sunwoo@arm.com success ? "Done" : "SC_Failed", "", "", 5188833Sdam.sunwoo@arm.com request_address, miss_latency); 5198833Sdam.sunwoo@arm.com } 5204626SN/A 5214626SN/A // update the data 5224626SN/A if (g_system_ptr->m_warmup_enabled) { 5234626SN/A assert(pkt->getPtr<uint8_t>(false) != NULL); 5248833Sdam.sunwoo@arm.com data.setData(pkt->getPtr<uint8_t>(false), 5254626SN/A request_address.getOffset(), pkt->getSize()); 5264871SN/A } else if (pkt->getPtr<uint8_t>(true) != NULL) { 5278833Sdam.sunwoo@arm.com if ((type == RubyRequestType_LD) || 5288833Sdam.sunwoo@arm.com (type == RubyRequestType_IFETCH) || 5298833Sdam.sunwoo@arm.com (type == RubyRequestType_RMW_Read) || 5304626SN/A (type == RubyRequestType_Locked_RMW_Read) || 5314626SN/A (type == RubyRequestType_Load_Linked)) { 5324626SN/A memcpy(pkt->getPtr<uint8_t>(true), 5334626SN/A data.getData(request_address.getOffset(), pkt->getSize()), 5344626SN/A pkt->getSize()); 5354626SN/A } else { 5364626SN/A data.setData(pkt->getPtr<uint8_t>(true), 5378833Sdam.sunwoo@arm.com request_address.getOffset(), pkt->getSize()); 5384626SN/A } 5394626SN/A } else { 5404626SN/A DPRINTF(MemoryAccess, 5414626SN/A "WARNING. Data not transfered from Ruby to M5 for type %s\n", 5428833Sdam.sunwoo@arm.com RubyRequestType_to_string(type)); 5438833Sdam.sunwoo@arm.com } 5448833Sdam.sunwoo@arm.com 5454626SN/A // If using the RubyTester, update the RubyTester sender state's 5464626SN/A // subBlock with the recieved data. The tester will later access 5474626SN/A // this state. 5484626SN/A // Note: RubyPort will access it's sender state before the 5494626SN/A // RubyTester. 5508833Sdam.sunwoo@arm.com if (m_usingRubyTester) { 5514626SN/A RubyPort::SenderState *requestSenderState = 5524871SN/A safe_cast<RubyPort::SenderState*>(pkt->senderState); 5538833Sdam.sunwoo@arm.com RubyTester::SenderState* testerSenderState = 5548833Sdam.sunwoo@arm.com safe_cast<RubyTester::SenderState*>(requestSenderState->saved); 5558833Sdam.sunwoo@arm.com testerSenderState->subBlock->mergeFrom(data); 5564626SN/A } 5574626SN/A 5584626SN/A delete srequest; 5594626SN/A 5608833Sdam.sunwoo@arm.com if (g_system_ptr->m_warmup_enabled) { 5614626SN/A delete pkt; 5624871SN/A g_system_ptr->m_cache_recorder->enqueueNextFetchRequest(); 5634871SN/A } else if (g_system_ptr->m_cooldown_enabled) { 5648833Sdam.sunwoo@arm.com delete pkt; 5658833Sdam.sunwoo@arm.com g_system_ptr->m_cache_recorder->enqueueNextFlushRequest(); 5668833Sdam.sunwoo@arm.com } else { 5674626SN/A ruby_hit_callback(pkt); 5684626SN/A } 5694626SN/A} 5704626SN/A 5714626SN/Abool 5724626SN/ASequencer::empty() const 5734626SN/A{ 5748833Sdam.sunwoo@arm.com return m_writeRequestTable.empty() && m_readRequestTable.empty(); 5754626SN/A} 5764626SN/A 5774626SN/ARequestStatus 5784626SN/ASequencer::makeRequest(PacketPtr pkt) 5798833Sdam.sunwoo@arm.com{ 5808833Sdam.sunwoo@arm.com if (m_outstanding_count >= m_max_outstanding_requests) { 5818833Sdam.sunwoo@arm.com return RequestStatus_BufferFull; 5824626SN/A } 5834626SN/A 5844626SN/A RubyRequestType primary_type = RubyRequestType_NULL; 5854626SN/A RubyRequestType secondary_type = RubyRequestType_NULL; 5864626SN/A 5878833Sdam.sunwoo@arm.com if (pkt->isLLSC()) { 5884626SN/A // 5894871SN/A // Alpha LL/SC instructions need to be handled carefully by the cache 5904871SN/A // coherence protocol to ensure they follow the proper semantics. In 5918833Sdam.sunwoo@arm.com // particular, by identifying the operations as atomic, the protocol 5928833Sdam.sunwoo@arm.com // should understand that migratory sharing optimizations should not 5938833Sdam.sunwoo@arm.com // be performed (i.e. a load between the LL and SC should not steal 5944626SN/A // away exclusive permission). 5954626SN/A // 5964626SN/A if (pkt->isWrite()) { 5974626SN/A DPRINTF(RubySequencer, "Issuing SC\n"); 5984626SN/A primary_type = RubyRequestType_Store_Conditional; 5994626SN/A } else { 6004626SN/A DPRINTF(RubySequencer, "Issuing LL\n"); 6018833Sdam.sunwoo@arm.com assert(pkt->isRead()); 6024626SN/A primary_type = RubyRequestType_Load_Linked; 6034626SN/A } 6044626SN/A secondary_type = RubyRequestType_ATOMIC; 6054626SN/A } else if (pkt->req->isLocked()) { 6068833Sdam.sunwoo@arm.com // 60711483Snikos.nikoleris@arm.com // x86 locked instructions are translated to store cache coherence 60811483Snikos.nikoleris@arm.com // requests because these requests should always be treated as read 6098833Sdam.sunwoo@arm.com // exclusive operations and should leverage any migratory sharing 6104626SN/A // optimization built into the protocol. 6114626SN/A // 6124626SN/A if (pkt->isWrite()) { 6134626SN/A DPRINTF(RubySequencer, "Issuing Locked RMW Write\n"); 6144626SN/A primary_type = RubyRequestType_Locked_RMW_Write; 6158833Sdam.sunwoo@arm.com } else { 6164626SN/A DPRINTF(RubySequencer, "Issuing Locked RMW Read\n"); 6174871SN/A assert(pkt->isRead()); 6184871SN/A primary_type = RubyRequestType_Locked_RMW_Read; 6194871SN/A } 6208833Sdam.sunwoo@arm.com secondary_type = RubyRequestType_ST; 6218833Sdam.sunwoo@arm.com } else { 6228833Sdam.sunwoo@arm.com if (pkt->isRead()) { 6234626SN/A if (pkt->req->isInstFetch()) { 6244626SN/A primary_type = secondary_type = RubyRequestType_IFETCH; 6254626SN/A } else { 6264626SN/A#if THE_ISA == X86_ISA 6274626SN/A uint32_t flags = pkt->req->getFlags(); 6284626SN/A bool storeCheck = flags & 6294626SN/A (TheISA::StoreCheck << TheISA::FlagShift); 6304626SN/A#else 6314626SN/A bool storeCheck = false; 6324626SN/A#endif // X86_ISA 6334626SN/A if (storeCheck) { 6344626SN/A primary_type = RubyRequestType_RMW_Read; 6354626SN/A secondary_type = RubyRequestType_ST; 6364626SN/A } else { 6374626SN/A primary_type = secondary_type = RubyRequestType_LD; 6384626SN/A } 6394626SN/A } 6404626SN/A } else if (pkt->isWrite()) { 6414626SN/A // 6424626SN/A // Note: M5 packets do not differentiate ST from RMW_Write 6434626SN/A // 6444626SN/A primary_type = secondary_type = RubyRequestType_ST; 6454626SN/A } else if (pkt->isFlush()) { 6464626SN/A primary_type = secondary_type = RubyRequestType_FLUSH; 6474626SN/A } else { 6484626SN/A panic("Unsupported ruby packet type\n"); 6494626SN/A } 6504626SN/A } 6514626SN/A 6524626SN/A RequestStatus status = insertRequest(pkt, primary_type); 6534626SN/A if (status != RequestStatus_Ready) 6544626SN/A return status; 6554626SN/A 6564626SN/A issueRequest(pkt, secondary_type); 6574626SN/A 6584626SN/A // TODO: issue hardware prefetches here 6594626SN/A return RequestStatus_Issued; 6604626SN/A} 6614626SN/A 6624626SN/Avoid 6634626SN/ASequencer::issueRequest(PacketPtr pkt, RubyRequestType secondary_type) 6644626SN/A{ 6654626SN/A int proc_id = -1; 6664626SN/A if (pkt != NULL && pkt->req->hasContextId()) { 6674626SN/A proc_id = pkt->req->contextId(); 6688833Sdam.sunwoo@arm.com } 6698833Sdam.sunwoo@arm.com 6708833Sdam.sunwoo@arm.com // If valid, copy the pc to the ruby request 6718833Sdam.sunwoo@arm.com Addr pc = 0; 6724626SN/A if (pkt->req->hasPC()) { 6734626SN/A pc = pkt->req->getPC(); 6744626SN/A } 6754626SN/A 6764626SN/A RubyRequest *msg = new RubyRequest(pkt->getAddr(), 6778833Sdam.sunwoo@arm.com pkt->getPtr<uint8_t>(true), 6784626SN/A pkt->getSize(), pc, secondary_type, 6794626SN/A RubyAccessMode_Supervisor, pkt, 6808833Sdam.sunwoo@arm.com PrefetchBit_No, proc_id); 6818833Sdam.sunwoo@arm.com 6828833Sdam.sunwoo@arm.com DPRINTFR(ProtocolTrace, "%15s %3s %10s%20s %6s>%-6s %s %s\n", 6834626SN/A curTick(), m_version, "Seq", "Begin", "", "", 6844626SN/A msg->getPhysicalAddress(), 6854626SN/A RubyRequestType_to_string(secondary_type)); 6864626SN/A 6878833Sdam.sunwoo@arm.com Time latency = 0; // initialzed to an null value 6884626SN/A 6894626SN/A if (secondary_type == RubyRequestType_IFETCH) 6908833Sdam.sunwoo@arm.com latency = m_instCache_ptr->getLatency(); 6918833Sdam.sunwoo@arm.com else 6928833Sdam.sunwoo@arm.com latency = m_dataCache_ptr->getLatency(); 6934626SN/A 6944626SN/A // Send the message to the cache controller 6954626SN/A assert(latency > 0); 6964626SN/A 6974626SN/A assert(m_mandatory_q_ptr != NULL); 6984626SN/A m_mandatory_q_ptr->enqueue(msg, latency); 6994626SN/A} 7004626SN/A 7014626SN/Atemplate <class KEY, class VALUE> 7024626SN/Astd::ostream & 7034626SN/Aoperator<<(ostream &out, const m5::hash_map<KEY, VALUE> &map) 7044626SN/A{ 7054626SN/A typename m5::hash_map<KEY, VALUE>::const_iterator i = map.begin(); 7068833Sdam.sunwoo@arm.com typename m5::hash_map<KEY, VALUE>::const_iterator end = map.end(); 7078833Sdam.sunwoo@arm.com 70811483Snikos.nikoleris@arm.com out << "["; 70911483Snikos.nikoleris@arm.com for (; i != end; ++i) 7108833Sdam.sunwoo@arm.com out << " " << i->first << "=" << i->second; 7114626SN/A out << " ]"; 7124626SN/A 7134626SN/A return out; 7144626SN/A} 7154626SN/A 7168833Sdam.sunwoo@arm.comvoid 7174626SN/ASequencer::print(ostream& out) const 7184626SN/A{ 7198833Sdam.sunwoo@arm.com out << "[Sequencer: " << m_version 7208833Sdam.sunwoo@arm.com << ", outstanding requests: " << m_outstanding_count 7218833Sdam.sunwoo@arm.com << ", read request table: " << m_readRequestTable 7224626SN/A << ", write request table: " << m_writeRequestTable 7234626SN/A << "]"; 7244626SN/A} 7254626SN/A 7268833Sdam.sunwoo@arm.com// this can be called from setState whenever coherence permissions are 7274626SN/A// upgraded when invoked, coherence violations will be checked for the 7284626SN/A// given block 7298833Sdam.sunwoo@arm.comvoid 7308833Sdam.sunwoo@arm.comSequencer::checkCoherence(const Address& addr) 7318833Sdam.sunwoo@arm.com{ 7324626SN/A#ifdef CHECK_COHERENCE 7334626SN/A g_system_ptr->checkGlobalCoherenceInvariant(addr); 7344626SN/A#endif 7354626SN/A} 7364626SN/A 7374626SN/Avoid 7384626SN/ASequencer::evictionCallback(const Address& address) 7394626SN/A{ 7404626SN/A ruby_eviction_callback(address); 7414626SN/A} 7424626SN/A