Sequencer.cc revision 6922
16145Snate@binkert.org 26145Snate@binkert.org/* 36145Snate@binkert.org * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood 46145Snate@binkert.org * All rights reserved. 56145Snate@binkert.org * 66145Snate@binkert.org * Redistribution and use in source and binary forms, with or without 76145Snate@binkert.org * modification, are permitted provided that the following conditions are 86145Snate@binkert.org * met: redistributions of source code must retain the above copyright 96145Snate@binkert.org * notice, this list of conditions and the following disclaimer; 106145Snate@binkert.org * redistributions in binary form must reproduce the above copyright 116145Snate@binkert.org * notice, this list of conditions and the following disclaimer in the 126145Snate@binkert.org * documentation and/or other materials provided with the distribution; 136145Snate@binkert.org * neither the name of the copyright holders nor the names of its 146145Snate@binkert.org * contributors may be used to endorse or promote products derived from 156145Snate@binkert.org * this software without specific prior written permission. 166145Snate@binkert.org * 176145Snate@binkert.org * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 186145Snate@binkert.org * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 196145Snate@binkert.org * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 206145Snate@binkert.org * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 216145Snate@binkert.org * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 226145Snate@binkert.org * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 236145Snate@binkert.org * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 246145Snate@binkert.org * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 256145Snate@binkert.org * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 266145Snate@binkert.org * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 276145Snate@binkert.org * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 286145Snate@binkert.org */ 296145Snate@binkert.org 306845Sdrh5@cs.wisc.edu#include "mem/ruby/libruby.hh" 316154Snate@binkert.org#include "mem/ruby/common/Global.hh" 326154Snate@binkert.org#include "mem/ruby/system/Sequencer.hh" 336154Snate@binkert.org#include "mem/ruby/system/System.hh" 346154Snate@binkert.org#include "mem/protocol/Protocol.hh" 356154Snate@binkert.org#include "mem/ruby/profiler/Profiler.hh" 366154Snate@binkert.org#include "mem/ruby/system/CacheMemory.hh" 376285Snate@binkert.org#include "mem/protocol/CacheMsg.hh" 386285Snate@binkert.org#include "mem/ruby/recorder/Tracer.hh" 396154Snate@binkert.org#include "mem/ruby/common/SubBlock.hh" 406154Snate@binkert.org#include "mem/protocol/Protocol.hh" 416154Snate@binkert.org#include "mem/gems_common/Map.hh" 426285Snate@binkert.org#include "mem/ruby/buffers/MessageBuffer.hh" 436285Snate@binkert.org#include "mem/ruby/slicc_interface/AbstractController.hh" 446899SBrad.Beckmann@amd.com#include "cpu/rubytest/RubyTester.hh" 456145Snate@binkert.org 466876Ssteve.reinhardt@amd.com#include "params/RubySequencer.hh" 476876Ssteve.reinhardt@amd.com 486876Ssteve.reinhardt@amd.comSequencer * 496876Ssteve.reinhardt@amd.comRubySequencerParams::create() 506285Snate@binkert.org{ 516876Ssteve.reinhardt@amd.com return new Sequencer(this); 526285Snate@binkert.org} 536876Ssteve.reinhardt@amd.com 546876Ssteve.reinhardt@amd.comSequencer::Sequencer(const Params *p) 556886SBrad.Beckmann@amd.com : RubyPort(p), deadlockCheckEvent(this) 566876Ssteve.reinhardt@amd.com{ 576876Ssteve.reinhardt@amd.com m_store_waiting_on_load_cycles = 0; 586876Ssteve.reinhardt@amd.com m_store_waiting_on_store_cycles = 0; 596876Ssteve.reinhardt@amd.com m_load_waiting_on_store_cycles = 0; 606876Ssteve.reinhardt@amd.com m_load_waiting_on_load_cycles = 0; 616876Ssteve.reinhardt@amd.com 626876Ssteve.reinhardt@amd.com m_outstanding_count = 0; 636285Snate@binkert.org 646876Ssteve.reinhardt@amd.com m_max_outstanding_requests = 0; 656876Ssteve.reinhardt@amd.com m_deadlock_threshold = 0; 666876Ssteve.reinhardt@amd.com m_instCache_ptr = NULL; 676876Ssteve.reinhardt@amd.com m_dataCache_ptr = NULL; 686145Snate@binkert.org 696876Ssteve.reinhardt@amd.com m_instCache_ptr = p->icache; 706876Ssteve.reinhardt@amd.com m_dataCache_ptr = p->dcache; 716876Ssteve.reinhardt@amd.com m_max_outstanding_requests = p->max_outstanding_requests; 726876Ssteve.reinhardt@amd.com m_deadlock_threshold = p->deadlock_threshold; 736899SBrad.Beckmann@amd.com m_usingRubyTester = p->using_ruby_tester; 746899SBrad.Beckmann@amd.com 756876Ssteve.reinhardt@amd.com assert(m_max_outstanding_requests > 0); 766876Ssteve.reinhardt@amd.com assert(m_deadlock_threshold > 0); 776876Ssteve.reinhardt@amd.com assert(m_instCache_ptr != NULL); 786876Ssteve.reinhardt@amd.com assert(m_dataCache_ptr != NULL); 796145Snate@binkert.org} 806145Snate@binkert.org 816145Snate@binkert.orgSequencer::~Sequencer() { 826285Snate@binkert.org 836145Snate@binkert.org} 846145Snate@binkert.org 856145Snate@binkert.orgvoid Sequencer::wakeup() { 866145Snate@binkert.org // Check for deadlock of any of the requests 876145Snate@binkert.org Time current_time = g_eventQueue_ptr->getTime(); 886145Snate@binkert.org 896145Snate@binkert.org // Check across all outstanding requests 906145Snate@binkert.org int total_outstanding = 0; 916285Snate@binkert.org 926285Snate@binkert.org Vector<Address> keys = m_readRequestTable.keys(); 936285Snate@binkert.org for (int i=0; i<keys.size(); i++) { 946285Snate@binkert.org SequencerRequest* request = m_readRequestTable.lookup(keys[i]); 956285Snate@binkert.org if (current_time - request->issue_time >= m_deadlock_threshold) { 966285Snate@binkert.org WARN_MSG("Possible Deadlock detected"); 976510Spdudnik@gmail.com WARN_EXPR(request); 986285Snate@binkert.org WARN_EXPR(m_version); 996825Spdudnik@gmail.com WARN_EXPR(request->ruby_request.paddr); 1006285Snate@binkert.org WARN_EXPR(keys.size()); 1016285Snate@binkert.org WARN_EXPR(current_time); 1026285Snate@binkert.org WARN_EXPR(request->issue_time); 1036285Snate@binkert.org WARN_EXPR(current_time - request->issue_time); 1046285Snate@binkert.org ERROR_MSG("Aborting"); 1056145Snate@binkert.org } 1066285Snate@binkert.org } 1076145Snate@binkert.org 1086285Snate@binkert.org keys = m_writeRequestTable.keys(); 1096285Snate@binkert.org for (int i=0; i<keys.size(); i++) { 1106285Snate@binkert.org SequencerRequest* request = m_writeRequestTable.lookup(keys[i]); 1116285Snate@binkert.org if (current_time - request->issue_time >= m_deadlock_threshold) { 1126285Snate@binkert.org WARN_MSG("Possible Deadlock detected"); 1136510Spdudnik@gmail.com WARN_EXPR(request); 1146285Snate@binkert.org WARN_EXPR(m_version); 1156285Snate@binkert.org WARN_EXPR(current_time); 1166285Snate@binkert.org WARN_EXPR(request->issue_time); 1176285Snate@binkert.org WARN_EXPR(current_time - request->issue_time); 1186285Snate@binkert.org WARN_EXPR(keys.size()); 1196285Snate@binkert.org ERROR_MSG("Aborting"); 1206145Snate@binkert.org } 1216285Snate@binkert.org } 1226285Snate@binkert.org total_outstanding += m_writeRequestTable.size() + m_readRequestTable.size(); 1236285Snate@binkert.org 1246145Snate@binkert.org assert(m_outstanding_count == total_outstanding); 1256145Snate@binkert.org 1266145Snate@binkert.org if (m_outstanding_count > 0) { // If there are still outstanding requests, keep checking 1276886SBrad.Beckmann@amd.com schedule(deadlockCheckEvent, 1286886SBrad.Beckmann@amd.com (m_deadlock_threshold * g_eventQueue_ptr->getClock()) + curTick); 1296145Snate@binkert.org } 1306145Snate@binkert.org} 1316145Snate@binkert.org 1326859Sdrh5@cs.wisc.eduvoid Sequencer::printStats(ostream & out) const { 1336859Sdrh5@cs.wisc.edu out << "Sequencer: " << m_name << endl; 1346859Sdrh5@cs.wisc.edu out << " store_waiting_on_load_cycles: " << m_store_waiting_on_load_cycles << endl; 1356859Sdrh5@cs.wisc.edu out << " store_waiting_on_store_cycles: " << m_store_waiting_on_store_cycles << endl; 1366859Sdrh5@cs.wisc.edu out << " load_waiting_on_load_cycles: " << m_load_waiting_on_load_cycles << endl; 1376859Sdrh5@cs.wisc.edu out << " load_waiting_on_store_cycles: " << m_load_waiting_on_store_cycles << endl; 1386859Sdrh5@cs.wisc.edu} 1396859Sdrh5@cs.wisc.edu 1406145Snate@binkert.orgvoid Sequencer::printProgress(ostream& out) const{ 1416285Snate@binkert.org /* 1426145Snate@binkert.org int total_demand = 0; 1436145Snate@binkert.org out << "Sequencer Stats Version " << m_version << endl; 1446145Snate@binkert.org out << "Current time = " << g_eventQueue_ptr->getTime() << endl; 1456145Snate@binkert.org out << "---------------" << endl; 1466145Snate@binkert.org out << "outstanding requests" << endl; 1476145Snate@binkert.org 1486285Snate@binkert.org Vector<Address> rkeys = m_readRequestTable.keys(); 1496285Snate@binkert.org int read_size = rkeys.size(); 1506285Snate@binkert.org out << "proc " << m_version << " Read Requests = " << read_size << endl; 1516285Snate@binkert.org // print the request table 1526285Snate@binkert.org for(int i=0; i < read_size; ++i){ 1536285Snate@binkert.org SequencerRequest * request = m_readRequestTable.lookup(rkeys[i]); 1546285Snate@binkert.org out << "\tRequest[ " << i << " ] = " << request->type << " Address " << rkeys[i] << " Posted " << request->issue_time << " PF " << PrefetchBit_No << endl; 1556285Snate@binkert.org total_demand++; 1566285Snate@binkert.org } 1576145Snate@binkert.org 1586285Snate@binkert.org Vector<Address> wkeys = m_writeRequestTable.keys(); 1596285Snate@binkert.org int write_size = wkeys.size(); 1606285Snate@binkert.org out << "proc " << m_version << " Write Requests = " << write_size << endl; 1616285Snate@binkert.org // print the request table 1626285Snate@binkert.org for(int i=0; i < write_size; ++i){ 1636285Snate@binkert.org CacheMsg & request = m_writeRequestTable.lookup(wkeys[i]); 1646145Snate@binkert.org out << "\tRequest[ " << i << " ] = " << request.getType() << " Address " << wkeys[i] << " Posted " << request.getTime() << " PF " << request.getPrefetch() << endl; 1656145Snate@binkert.org if( request.getPrefetch() == PrefetchBit_No ){ 1666145Snate@binkert.org total_demand++; 1676145Snate@binkert.org } 1686285Snate@binkert.org } 1696145Snate@binkert.org 1706285Snate@binkert.org out << endl; 1716285Snate@binkert.org 1726145Snate@binkert.org out << "Total Number Outstanding: " << m_outstanding_count << endl; 1736145Snate@binkert.org out << "Total Number Demand : " << total_demand << endl; 1746145Snate@binkert.org out << "Total Number Prefetches : " << m_outstanding_count - total_demand << endl; 1756145Snate@binkert.org out << endl; 1766145Snate@binkert.org out << endl; 1776285Snate@binkert.org */ 1786145Snate@binkert.org} 1796145Snate@binkert.org 1806285Snate@binkert.orgvoid Sequencer::printConfig(ostream& out) const { 1816285Snate@binkert.org out << "Seqeuncer config: " << m_name << endl; 1826285Snate@binkert.org out << " controller: " << m_controller->getName() << endl; 1836285Snate@binkert.org out << " version: " << m_version << endl; 1846285Snate@binkert.org out << " max_outstanding_requests: " << m_max_outstanding_requests << endl; 1856285Snate@binkert.org out << " deadlock_threshold: " << m_deadlock_threshold << endl; 1866145Snate@binkert.org} 1876145Snate@binkert.org 1886145Snate@binkert.org// Insert the request on the correct request table. Return true if 1896145Snate@binkert.org// the entry was already present. 1906285Snate@binkert.orgbool Sequencer::insertRequest(SequencerRequest* request) { 1916285Snate@binkert.org int total_outstanding = m_writeRequestTable.size() + m_readRequestTable.size(); 1926285Snate@binkert.org 1936145Snate@binkert.org assert(m_outstanding_count == total_outstanding); 1946145Snate@binkert.org 1956145Snate@binkert.org // See if we should schedule a deadlock check 1966886SBrad.Beckmann@amd.com if (deadlockCheckEvent.scheduled() == false) { 1976893SBrad.Beckmann@amd.com schedule(deadlockCheckEvent, m_deadlock_threshold + curTick); 1986145Snate@binkert.org } 1996145Snate@binkert.org 2006285Snate@binkert.org Address line_addr(request->ruby_request.paddr); 2016285Snate@binkert.org line_addr.makeLineAddress(); 2026285Snate@binkert.org if ((request->ruby_request.type == RubyRequestType_ST) || 2036355Spdudnik@gmail.com (request->ruby_request.type == RubyRequestType_RMW_Read) || 2046355Spdudnik@gmail.com (request->ruby_request.type == RubyRequestType_RMW_Write) || 2056350Spdudnik@gmail.com (request->ruby_request.type == RubyRequestType_Locked_Read) || 2066350Spdudnik@gmail.com (request->ruby_request.type == RubyRequestType_Locked_Write)) { 2076285Snate@binkert.org if (m_writeRequestTable.exist(line_addr)) { 2086285Snate@binkert.org m_writeRequestTable.lookup(line_addr) = request; 2096285Snate@binkert.org // return true; 2106285Snate@binkert.org assert(0); // drh5: isn't this an error? do you lose the initial request? 2116145Snate@binkert.org } 2126285Snate@binkert.org m_writeRequestTable.allocate(line_addr); 2136285Snate@binkert.org m_writeRequestTable.lookup(line_addr) = request; 2146145Snate@binkert.org m_outstanding_count++; 2156145Snate@binkert.org } else { 2166285Snate@binkert.org if (m_readRequestTable.exist(line_addr)) { 2176285Snate@binkert.org m_readRequestTable.lookup(line_addr) = request; 2186285Snate@binkert.org // return true; 2196285Snate@binkert.org assert(0); // drh5: isn't this an error? do you lose the initial request? 2206145Snate@binkert.org } 2216285Snate@binkert.org m_readRequestTable.allocate(line_addr); 2226285Snate@binkert.org m_readRequestTable.lookup(line_addr) = request; 2236145Snate@binkert.org m_outstanding_count++; 2246145Snate@binkert.org } 2256145Snate@binkert.org 2266145Snate@binkert.org g_system_ptr->getProfiler()->sequencerRequests(m_outstanding_count); 2276145Snate@binkert.org 2286285Snate@binkert.org total_outstanding = m_writeRequestTable.size() + m_readRequestTable.size(); 2296285Snate@binkert.org assert(m_outstanding_count == total_outstanding); 2306145Snate@binkert.org 2316145Snate@binkert.org return false; 2326145Snate@binkert.org} 2336145Snate@binkert.org 2346285Snate@binkert.orgvoid Sequencer::removeRequest(SequencerRequest* srequest) { 2356145Snate@binkert.org 2366285Snate@binkert.org assert(m_outstanding_count == m_writeRequestTable.size() + m_readRequestTable.size()); 2376285Snate@binkert.org 2386285Snate@binkert.org const RubyRequest & ruby_request = srequest->ruby_request; 2396285Snate@binkert.org Address line_addr(ruby_request.paddr); 2406285Snate@binkert.org line_addr.makeLineAddress(); 2416285Snate@binkert.org if ((ruby_request.type == RubyRequestType_ST) || 2426355Spdudnik@gmail.com (ruby_request.type == RubyRequestType_RMW_Read) || 2436355Spdudnik@gmail.com (ruby_request.type == RubyRequestType_RMW_Write) || 2446350Spdudnik@gmail.com (ruby_request.type == RubyRequestType_Locked_Read) || 2456350Spdudnik@gmail.com (ruby_request.type == RubyRequestType_Locked_Write)) { 2466285Snate@binkert.org m_writeRequestTable.deallocate(line_addr); 2476145Snate@binkert.org } else { 2486285Snate@binkert.org m_readRequestTable.deallocate(line_addr); 2496145Snate@binkert.org } 2506145Snate@binkert.org m_outstanding_count--; 2516145Snate@binkert.org 2526285Snate@binkert.org assert(m_outstanding_count == m_writeRequestTable.size() + m_readRequestTable.size()); 2536145Snate@binkert.org} 2546145Snate@binkert.org 2556145Snate@binkert.orgvoid Sequencer::writeCallback(const Address& address, DataBlock& data) { 2566145Snate@binkert.org 2576145Snate@binkert.org assert(address == line_address(address)); 2586285Snate@binkert.org assert(m_writeRequestTable.exist(line_address(address))); 2596145Snate@binkert.org 2606285Snate@binkert.org SequencerRequest* request = m_writeRequestTable.lookup(address); 2616846Spdudnik@cs.wisc.edu 2626145Snate@binkert.org removeRequest(request); 2636145Snate@binkert.org 2646285Snate@binkert.org assert((request->ruby_request.type == RubyRequestType_ST) || 2656355Spdudnik@gmail.com (request->ruby_request.type == RubyRequestType_RMW_Read) || 2666355Spdudnik@gmail.com (request->ruby_request.type == RubyRequestType_RMW_Write) || 2676350Spdudnik@gmail.com (request->ruby_request.type == RubyRequestType_Locked_Read) || 2686350Spdudnik@gmail.com (request->ruby_request.type == RubyRequestType_Locked_Write)); 2696863Sdrh5@cs.wisc.edu 2706350Spdudnik@gmail.com if (request->ruby_request.type == RubyRequestType_Locked_Read) { 2716347Spdudnik@gmail.com m_dataCache_ptr->setLocked(address, m_version); 2726347Spdudnik@gmail.com } 2736506Spdudnik@gmail.com else if (request->ruby_request.type == RubyRequestType_RMW_Read) { 2746863Sdrh5@cs.wisc.edu m_controller->blockOnQueue(address, m_mandatory_q_ptr); 2756506Spdudnik@gmail.com } 2766506Spdudnik@gmail.com else if (request->ruby_request.type == RubyRequestType_RMW_Write) { 2776863Sdrh5@cs.wisc.edu m_controller->unblock(address); 2786506Spdudnik@gmail.com } 2796145Snate@binkert.org 2806285Snate@binkert.org hitCallback(request, data); 2816145Snate@binkert.org} 2826145Snate@binkert.org 2836145Snate@binkert.orgvoid Sequencer::readCallback(const Address& address, DataBlock& data) { 2846145Snate@binkert.org 2856285Snate@binkert.org assert(address == line_address(address)); 2866285Snate@binkert.org assert(m_readRequestTable.exist(line_address(address))); 2876145Snate@binkert.org 2886285Snate@binkert.org SequencerRequest* request = m_readRequestTable.lookup(address); 2896285Snate@binkert.org removeRequest(request); 2906285Snate@binkert.org 2916285Snate@binkert.org assert((request->ruby_request.type == RubyRequestType_LD) || 2926381Sdrh5@cs.wisc.edu (request->ruby_request.type == RubyRequestType_RMW_Read) || 2936285Snate@binkert.org (request->ruby_request.type == RubyRequestType_IFETCH)); 2946285Snate@binkert.org 2956285Snate@binkert.org hitCallback(request, data); 2966145Snate@binkert.org} 2976145Snate@binkert.org 2986285Snate@binkert.orgvoid Sequencer::hitCallback(SequencerRequest* srequest, DataBlock& data) { 2996285Snate@binkert.org const RubyRequest & ruby_request = srequest->ruby_request; 3006285Snate@binkert.org Address request_address(ruby_request.paddr); 3016285Snate@binkert.org Address request_line_address(ruby_request.paddr); 3026285Snate@binkert.org request_line_address.makeLineAddress(); 3036285Snate@binkert.org RubyRequestType type = ruby_request.type; 3046285Snate@binkert.org Time issued_time = srequest->issue_time; 3056145Snate@binkert.org 3066145Snate@binkert.org // Set this cache entry to the most recently used 3076285Snate@binkert.org if (type == RubyRequestType_IFETCH) { 3086285Snate@binkert.org if (m_instCache_ptr->isTagPresent(request_line_address) ) 3096285Snate@binkert.org m_instCache_ptr->setMRU(request_line_address); 3106145Snate@binkert.org } else { 3116285Snate@binkert.org if (m_dataCache_ptr->isTagPresent(request_line_address) ) 3126285Snate@binkert.org m_dataCache_ptr->setMRU(request_line_address); 3136145Snate@binkert.org } 3146145Snate@binkert.org 3156145Snate@binkert.org assert(g_eventQueue_ptr->getTime() >= issued_time); 3166145Snate@binkert.org Time miss_latency = g_eventQueue_ptr->getTime() - issued_time; 3176145Snate@binkert.org 3186285Snate@binkert.org // Profile the miss latency for all non-zero demand misses 3196285Snate@binkert.org if (miss_latency != 0) { 3206285Snate@binkert.org g_system_ptr->getProfiler()->missLatency(miss_latency, type); 3216285Snate@binkert.org 3226285Snate@binkert.org if (Debug::getProtocolTrace()) { 3236285Snate@binkert.org g_system_ptr->getProfiler()->profileTransition("Seq", m_version, Address(ruby_request.paddr), 3246285Snate@binkert.org "", "Done", "", int_to_string(miss_latency)+" cycles"); 3256285Snate@binkert.org } 3266285Snate@binkert.org } 3276285Snate@binkert.org /* 3286285Snate@binkert.org if (request.getPrefetch() == PrefetchBit_Yes) { 3296285Snate@binkert.org return; // Ignore the prefetch 3306285Snate@binkert.org } 3316285Snate@binkert.org */ 3326285Snate@binkert.org 3336285Snate@binkert.org // update the data 3346285Snate@binkert.org if (ruby_request.data != NULL) { 3356285Snate@binkert.org if ((type == RubyRequestType_LD) || 3366381Sdrh5@cs.wisc.edu (type == RubyRequestType_IFETCH) || 3376381Sdrh5@cs.wisc.edu (type == RubyRequestType_RMW_Read)) { 3386285Snate@binkert.org memcpy(ruby_request.data, data.getData(request_address.getOffset(), ruby_request.len), ruby_request.len); 3396285Snate@binkert.org } else { 3406285Snate@binkert.org data.setData(ruby_request.data, request_address.getOffset(), ruby_request.len); 3416285Snate@binkert.org } 3426145Snate@binkert.org } 3436145Snate@binkert.org 3446899SBrad.Beckmann@amd.com // 3456899SBrad.Beckmann@amd.com // If using the RubyTester, update the RubyTester sender state's subBlock 3466899SBrad.Beckmann@amd.com // with the recieved data. The tester will later access this state. 3476899SBrad.Beckmann@amd.com // Note: RubyPort will access it's sender state before the RubyTester. 3486899SBrad.Beckmann@amd.com // 3496899SBrad.Beckmann@amd.com if (m_usingRubyTester) { 3506899SBrad.Beckmann@amd.com RubyTester::SenderState* testerSenderState; 3516922SBrad.Beckmann@amd.com testerSenderState = safe_cast<RubyTester::SenderState*>( \ 3526922SBrad.Beckmann@amd.com safe_cast<RubyPort::SenderState*>(ruby_request.pkt->senderState)->saved); 3536899SBrad.Beckmann@amd.com testerSenderState->subBlock->mergeFrom(data); 3546899SBrad.Beckmann@amd.com } 3556899SBrad.Beckmann@amd.com 3566922SBrad.Beckmann@amd.com ruby_hit_callback(ruby_request.pkt); 3576285Snate@binkert.org delete srequest; 3586285Snate@binkert.org} 3596285Snate@binkert.org 3606285Snate@binkert.org// Returns true if the sequencer already has a load or store outstanding 3616922SBrad.Beckmann@amd.comRequestStatus Sequencer::getRequestStatus(const RubyRequest& request) { 3626859Sdrh5@cs.wisc.edu bool is_outstanding_store = m_writeRequestTable.exist(line_address(Address(request.paddr))); 3636859Sdrh5@cs.wisc.edu bool is_outstanding_load = m_readRequestTable.exist(line_address(Address(request.paddr))); 3646859Sdrh5@cs.wisc.edu if ( is_outstanding_store ) { 3656859Sdrh5@cs.wisc.edu if ((request.type == RubyRequestType_LD) || 3666859Sdrh5@cs.wisc.edu (request.type == RubyRequestType_IFETCH) || 3676859Sdrh5@cs.wisc.edu (request.type == RubyRequestType_RMW_Read)) { 3686859Sdrh5@cs.wisc.edu m_store_waiting_on_load_cycles++; 3696859Sdrh5@cs.wisc.edu } else { 3706859Sdrh5@cs.wisc.edu m_store_waiting_on_store_cycles++; 3716859Sdrh5@cs.wisc.edu } 3726922SBrad.Beckmann@amd.com return RequestStatus_Aliased; 3736859Sdrh5@cs.wisc.edu } else if ( is_outstanding_load ) { 3746859Sdrh5@cs.wisc.edu if ((request.type == RubyRequestType_ST) || 3756859Sdrh5@cs.wisc.edu (request.type == RubyRequestType_RMW_Write) ) { 3766859Sdrh5@cs.wisc.edu m_load_waiting_on_store_cycles++; 3776859Sdrh5@cs.wisc.edu } else { 3786859Sdrh5@cs.wisc.edu m_load_waiting_on_load_cycles++; 3796859Sdrh5@cs.wisc.edu } 3806922SBrad.Beckmann@amd.com return RequestStatus_Aliased; 3816145Snate@binkert.org } 3826145Snate@binkert.org 3836510Spdudnik@gmail.com if (m_outstanding_count >= m_max_outstanding_requests) { 3846922SBrad.Beckmann@amd.com return RequestStatus_BufferFull; 3856145Snate@binkert.org } 3866845Sdrh5@cs.wisc.edu 3876922SBrad.Beckmann@amd.com return RequestStatus_Ready; 3886145Snate@binkert.org} 3896145Snate@binkert.org 3906285Snate@binkert.orgbool Sequencer::empty() const { 3916285Snate@binkert.org return (m_writeRequestTable.size() == 0) && (m_readRequestTable.size() == 0); 3926145Snate@binkert.org} 3936145Snate@binkert.org 3946349Spdudnik@gmail.com 3956922SBrad.Beckmann@amd.comRequestStatus Sequencer::makeRequest(const RubyRequest & request) 3966285Snate@binkert.org{ 3976922SBrad.Beckmann@amd.com assert(Address(request.paddr).getOffset() + request.len <= 3986922SBrad.Beckmann@amd.com RubySystem::getBlockSizeBytes()); 3996922SBrad.Beckmann@amd.com RequestStatus status = getRequestStatus(request); 4006922SBrad.Beckmann@amd.com if (status == RequestStatus_Ready) { 4016922SBrad.Beckmann@amd.com SequencerRequest *srequest = new SequencerRequest(request, 4026922SBrad.Beckmann@amd.com g_eventQueue_ptr->getTime()); 4036285Snate@binkert.org bool found = insertRequest(srequest); 4046825Spdudnik@gmail.com if (!found) { 4056350Spdudnik@gmail.com if (request.type == RubyRequestType_Locked_Write) { 4066355Spdudnik@gmail.com // NOTE: it is OK to check the locked flag here as the mandatory queue will be checked first 4076355Spdudnik@gmail.com // ensuring that nothing comes between checking the flag and servicing the store 4086349Spdudnik@gmail.com if (!m_dataCache_ptr->isLocked(line_address(Address(request.paddr)), m_version)) { 4096922SBrad.Beckmann@amd.com return RequestStatus_LlscFailed; 4106349Spdudnik@gmail.com } 4116349Spdudnik@gmail.com else { 4126349Spdudnik@gmail.com m_dataCache_ptr->clearLocked(line_address(Address(request.paddr))); 4136349Spdudnik@gmail.com } 4146349Spdudnik@gmail.com } 4156285Snate@binkert.org issueRequest(request); 4166145Snate@binkert.org 4176859Sdrh5@cs.wisc.edu // TODO: issue hardware prefetches here 4186922SBrad.Beckmann@amd.com return RequestStatus_Issued; 4196825Spdudnik@gmail.com } 4206825Spdudnik@gmail.com else { 4216922SBrad.Beckmann@amd.com panic("Sequencer::makeRequest should never be called if the request"\ 4226922SBrad.Beckmann@amd.com "is already outstanding\n"); 4236922SBrad.Beckmann@amd.com return RequestStatus_NULL; 4246825Spdudnik@gmail.com } 4256859Sdrh5@cs.wisc.edu } else { 4266922SBrad.Beckmann@amd.com return status; 4276145Snate@binkert.org } 4286145Snate@binkert.org} 4296145Snate@binkert.org 4306285Snate@binkert.orgvoid Sequencer::issueRequest(const RubyRequest& request) { 4316285Snate@binkert.org 4326285Snate@binkert.org // TODO: get rid of CacheMsg, CacheRequestType, and AccessModeTYpe, & have SLICC use RubyRequest and subtypes natively 4336285Snate@binkert.org CacheRequestType ctype; 4346285Snate@binkert.org switch(request.type) { 4356285Snate@binkert.org case RubyRequestType_IFETCH: 4366285Snate@binkert.org ctype = CacheRequestType_IFETCH; 4376285Snate@binkert.org break; 4386285Snate@binkert.org case RubyRequestType_LD: 4396285Snate@binkert.org ctype = CacheRequestType_LD; 4406285Snate@binkert.org break; 4416285Snate@binkert.org case RubyRequestType_ST: 4426285Snate@binkert.org ctype = CacheRequestType_ST; 4436285Snate@binkert.org break; 4446350Spdudnik@gmail.com case RubyRequestType_Locked_Read: 4456350Spdudnik@gmail.com case RubyRequestType_Locked_Write: 4466846Spdudnik@cs.wisc.edu ctype = CacheRequestType_ATOMIC; 4476285Snate@binkert.org break; 4486355Spdudnik@gmail.com case RubyRequestType_RMW_Read: 4496355Spdudnik@gmail.com ctype = CacheRequestType_ATOMIC; 4506355Spdudnik@gmail.com break; 4516355Spdudnik@gmail.com case RubyRequestType_RMW_Write: 4526355Spdudnik@gmail.com ctype = CacheRequestType_ATOMIC; 4536355Spdudnik@gmail.com break; 4546285Snate@binkert.org default: 4556285Snate@binkert.org assert(0); 4566145Snate@binkert.org } 4576285Snate@binkert.org AccessModeType amtype; 4586285Snate@binkert.org switch(request.access_mode){ 4596285Snate@binkert.org case RubyAccessMode_User: 4606285Snate@binkert.org amtype = AccessModeType_UserMode; 4616285Snate@binkert.org break; 4626285Snate@binkert.org case RubyAccessMode_Supervisor: 4636285Snate@binkert.org amtype = AccessModeType_SupervisorMode; 4646285Snate@binkert.org break; 4656285Snate@binkert.org case RubyAccessMode_Device: 4666285Snate@binkert.org amtype = AccessModeType_UserMode; 4676285Snate@binkert.org break; 4686285Snate@binkert.org default: 4696285Snate@binkert.org assert(0); 4706285Snate@binkert.org } 4716285Snate@binkert.org Address line_addr(request.paddr); 4726285Snate@binkert.org line_addr.makeLineAddress(); 4736505Spdudnik@gmail.com CacheMsg msg(line_addr, Address(request.paddr), ctype, Address(request.pc), amtype, request.len, PrefetchBit_No, request.proc_id); 4746285Snate@binkert.org 4756285Snate@binkert.org if (Debug::getProtocolTrace()) { 4766285Snate@binkert.org g_system_ptr->getProfiler()->profileTransition("Seq", m_version, Address(request.paddr), 4776285Snate@binkert.org "", "Begin", "", RubyRequestType_to_string(request.type)); 4786285Snate@binkert.org } 4796285Snate@binkert.org 4806285Snate@binkert.org if (g_system_ptr->getTracer()->traceEnabled()) { 4816890SBrad.Beckmann@amd.com g_system_ptr->getTracer()->traceRequest(this, line_addr, Address(request.pc), 4826285Snate@binkert.org request.type, g_eventQueue_ptr->getTime()); 4836285Snate@binkert.org } 4846285Snate@binkert.org 4856285Snate@binkert.org Time latency = 0; // initialzed to an null value 4866285Snate@binkert.org 4876285Snate@binkert.org if (request.type == RubyRequestType_IFETCH) 4886285Snate@binkert.org latency = m_instCache_ptr->getLatency(); 4896285Snate@binkert.org else 4906285Snate@binkert.org latency = m_dataCache_ptr->getLatency(); 4916285Snate@binkert.org 4926285Snate@binkert.org // Send the message to the cache controller 4936285Snate@binkert.org assert(latency > 0); 4946285Snate@binkert.org 4956876Ssteve.reinhardt@amd.com assert(m_mandatory_q_ptr != NULL); 4966285Snate@binkert.org m_mandatory_q_ptr->enqueue(msg, latency); 4976285Snate@binkert.org} 4986285Snate@binkert.org/* 4996285Snate@binkert.orgbool Sequencer::tryCacheAccess(const Address& addr, CacheRequestType type, 5006285Snate@binkert.org AccessModeType access_mode, 5016285Snate@binkert.org int size, DataBlock*& data_ptr) { 5026285Snate@binkert.org if (type == CacheRequestType_IFETCH) { 5036285Snate@binkert.org return m_instCache_ptr->tryCacheAccess(line_address(addr), type, data_ptr); 5046285Snate@binkert.org } else { 5056285Snate@binkert.org return m_dataCache_ptr->tryCacheAccess(line_address(addr), type, data_ptr); 5066145Snate@binkert.org } 5076145Snate@binkert.org} 5086285Snate@binkert.org*/ 5096145Snate@binkert.org 5106145Snate@binkert.orgvoid Sequencer::print(ostream& out) const { 5116285Snate@binkert.org out << "[Sequencer: " << m_version 5126145Snate@binkert.org << ", outstanding requests: " << m_outstanding_count; 5136145Snate@binkert.org 5146285Snate@binkert.org out << ", read request table: " << m_readRequestTable 5156285Snate@binkert.org << ", write request table: " << m_writeRequestTable; 5166145Snate@binkert.org out << "]"; 5176145Snate@binkert.org} 5186145Snate@binkert.org 5196145Snate@binkert.org// this can be called from setState whenever coherence permissions are upgraded 5206145Snate@binkert.org// when invoked, coherence violations will be checked for the given block 5216145Snate@binkert.orgvoid Sequencer::checkCoherence(const Address& addr) { 5226145Snate@binkert.org#ifdef CHECK_COHERENCE 5236145Snate@binkert.org g_system_ptr->checkGlobalCoherenceInvariant(addr); 5246145Snate@binkert.org#endif 5256145Snate@binkert.org} 5266145Snate@binkert.org 527