Sequencer.cc revision 6850
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" 446145Snate@binkert.org 456285Snate@binkert.org//Sequencer::Sequencer(int core_id, MessageBuffer* mandatory_q) 466145Snate@binkert.org 476355Spdudnik@gmail.com#define LLSC_FAIL -2 486850Spdudnik@gmail.comlong int already = 0; 496285Snate@binkert.orgSequencer::Sequencer(const string & name) 506285Snate@binkert.org :RubyPort(name) 516285Snate@binkert.org{ 526285Snate@binkert.org} 536285Snate@binkert.org 546285Snate@binkert.orgvoid Sequencer::init(const vector<string> & argv) 556285Snate@binkert.org{ 566145Snate@binkert.org m_deadlock_check_scheduled = false; 576145Snate@binkert.org m_outstanding_count = 0; 586145Snate@binkert.org 596285Snate@binkert.org m_max_outstanding_requests = 0; 606285Snate@binkert.org m_deadlock_threshold = 0; 616285Snate@binkert.org m_version = -1; 626285Snate@binkert.org m_instCache_ptr = NULL; 636285Snate@binkert.org m_dataCache_ptr = NULL; 646285Snate@binkert.org m_controller = NULL; 656846Spdudnik@cs.wisc.edu m_atomic_reads = 0; 666846Spdudnik@cs.wisc.edu m_atomic_writes = 0; 676285Snate@binkert.org for (size_t i=0; i<argv.size(); i+=2) { 686285Snate@binkert.org if ( argv[i] == "controller") { 696285Snate@binkert.org m_controller = RubySystem::getController(argv[i+1]); // args[i] = "L1Cache" 706285Snate@binkert.org m_mandatory_q_ptr = m_controller->getMandatoryQueue(); 716285Snate@binkert.org } else if ( argv[i] == "icache") 726285Snate@binkert.org m_instCache_ptr = RubySystem::getCache(argv[i+1]); 736285Snate@binkert.org else if ( argv[i] == "dcache") 746285Snate@binkert.org m_dataCache_ptr = RubySystem::getCache(argv[i+1]); 756285Snate@binkert.org else if ( argv[i] == "version") 766285Snate@binkert.org m_version = atoi(argv[i+1].c_str()); 776285Snate@binkert.org else if ( argv[i] == "max_outstanding_requests") 786285Snate@binkert.org m_max_outstanding_requests = atoi(argv[i+1].c_str()); 796285Snate@binkert.org else if ( argv[i] == "deadlock_threshold") 806285Snate@binkert.org m_deadlock_threshold = atoi(argv[i+1].c_str()); 816285Snate@binkert.org else { 826285Snate@binkert.org cerr << "WARNING: Sequencer: Unkown configuration parameter: " << argv[i] << endl; 836285Snate@binkert.org assert(false); 846285Snate@binkert.org } 856145Snate@binkert.org } 866285Snate@binkert.org assert(m_max_outstanding_requests > 0); 876285Snate@binkert.org assert(m_deadlock_threshold > 0); 886285Snate@binkert.org assert(m_version > -1); 896285Snate@binkert.org assert(m_instCache_ptr != NULL); 906285Snate@binkert.org assert(m_dataCache_ptr != NULL); 916285Snate@binkert.org assert(m_controller != NULL); 926145Snate@binkert.org} 936145Snate@binkert.org 946145Snate@binkert.orgSequencer::~Sequencer() { 956285Snate@binkert.org 966145Snate@binkert.org} 976145Snate@binkert.org 986145Snate@binkert.orgvoid Sequencer::wakeup() { 996145Snate@binkert.org // Check for deadlock of any of the requests 1006145Snate@binkert.org Time current_time = g_eventQueue_ptr->getTime(); 1016145Snate@binkert.org 1026145Snate@binkert.org // Check across all outstanding requests 1036145Snate@binkert.org int total_outstanding = 0; 1046285Snate@binkert.org 1056285Snate@binkert.org Vector<Address> keys = m_readRequestTable.keys(); 1066285Snate@binkert.org for (int i=0; i<keys.size(); i++) { 1076285Snate@binkert.org SequencerRequest* request = m_readRequestTable.lookup(keys[i]); 1086285Snate@binkert.org if (current_time - request->issue_time >= m_deadlock_threshold) { 1096285Snate@binkert.org WARN_MSG("Possible Deadlock detected"); 1106285Snate@binkert.org WARN_EXPR(request); 1116285Snate@binkert.org WARN_EXPR(m_version); 1126825Spdudnik@gmail.com WARN_EXPR(request->ruby_request.paddr); 1136285Snate@binkert.org WARN_EXPR(keys.size()); 1146285Snate@binkert.org WARN_EXPR(current_time); 1156285Snate@binkert.org WARN_EXPR(request->issue_time); 1166285Snate@binkert.org WARN_EXPR(current_time - request->issue_time); 1176285Snate@binkert.org ERROR_MSG("Aborting"); 1186145Snate@binkert.org } 1196285Snate@binkert.org } 1206145Snate@binkert.org 1216285Snate@binkert.org keys = m_writeRequestTable.keys(); 1226285Snate@binkert.org for (int i=0; i<keys.size(); i++) { 1236285Snate@binkert.org SequencerRequest* request = m_writeRequestTable.lookup(keys[i]); 1246285Snate@binkert.org if (current_time - request->issue_time >= m_deadlock_threshold) { 1256285Snate@binkert.org WARN_MSG("Possible Deadlock detected"); 1266285Snate@binkert.org WARN_EXPR(request); 1276285Snate@binkert.org WARN_EXPR(m_version); 1286285Snate@binkert.org WARN_EXPR(current_time); 1296285Snate@binkert.org WARN_EXPR(request->issue_time); 1306285Snate@binkert.org WARN_EXPR(current_time - request->issue_time); 1316285Snate@binkert.org WARN_EXPR(keys.size()); 1326285Snate@binkert.org ERROR_MSG("Aborting"); 1336145Snate@binkert.org } 1346285Snate@binkert.org } 1356285Snate@binkert.org total_outstanding += m_writeRequestTable.size() + m_readRequestTable.size(); 1366285Snate@binkert.org 1376145Snate@binkert.org assert(m_outstanding_count == total_outstanding); 1386145Snate@binkert.org 1396145Snate@binkert.org if (m_outstanding_count > 0) { // If there are still outstanding requests, keep checking 1406285Snate@binkert.org g_eventQueue_ptr->scheduleEvent(this, m_deadlock_threshold); 1416145Snate@binkert.org } else { 1426145Snate@binkert.org m_deadlock_check_scheduled = false; 1436145Snate@binkert.org } 1446145Snate@binkert.org} 1456145Snate@binkert.org 1466145Snate@binkert.orgvoid Sequencer::printProgress(ostream& out) const{ 1476285Snate@binkert.org /* 1486145Snate@binkert.org int total_demand = 0; 1496145Snate@binkert.org out << "Sequencer Stats Version " << m_version << endl; 1506145Snate@binkert.org out << "Current time = " << g_eventQueue_ptr->getTime() << endl; 1516145Snate@binkert.org out << "---------------" << endl; 1526145Snate@binkert.org out << "outstanding requests" << endl; 1536145Snate@binkert.org 1546285Snate@binkert.org Vector<Address> rkeys = m_readRequestTable.keys(); 1556285Snate@binkert.org int read_size = rkeys.size(); 1566285Snate@binkert.org out << "proc " << m_version << " Read Requests = " << read_size << endl; 1576285Snate@binkert.org // print the request table 1586285Snate@binkert.org for(int i=0; i < read_size; ++i){ 1596285Snate@binkert.org SequencerRequest * request = m_readRequestTable.lookup(rkeys[i]); 1606285Snate@binkert.org out << "\tRequest[ " << i << " ] = " << request->type << " Address " << rkeys[i] << " Posted " << request->issue_time << " PF " << PrefetchBit_No << endl; 1616285Snate@binkert.org total_demand++; 1626285Snate@binkert.org } 1636145Snate@binkert.org 1646285Snate@binkert.org Vector<Address> wkeys = m_writeRequestTable.keys(); 1656285Snate@binkert.org int write_size = wkeys.size(); 1666285Snate@binkert.org out << "proc " << m_version << " Write Requests = " << write_size << endl; 1676285Snate@binkert.org // print the request table 1686285Snate@binkert.org for(int i=0; i < write_size; ++i){ 1696285Snate@binkert.org CacheMsg & request = m_writeRequestTable.lookup(wkeys[i]); 1706145Snate@binkert.org out << "\tRequest[ " << i << " ] = " << request.getType() << " Address " << wkeys[i] << " Posted " << request.getTime() << " PF " << request.getPrefetch() << endl; 1716145Snate@binkert.org if( request.getPrefetch() == PrefetchBit_No ){ 1726145Snate@binkert.org total_demand++; 1736145Snate@binkert.org } 1746285Snate@binkert.org } 1756145Snate@binkert.org 1766285Snate@binkert.org out << endl; 1776285Snate@binkert.org 1786145Snate@binkert.org out << "Total Number Outstanding: " << m_outstanding_count << endl; 1796145Snate@binkert.org out << "Total Number Demand : " << total_demand << endl; 1806145Snate@binkert.org out << "Total Number Prefetches : " << m_outstanding_count - total_demand << endl; 1816145Snate@binkert.org out << endl; 1826145Snate@binkert.org out << endl; 1836285Snate@binkert.org */ 1846145Snate@binkert.org} 1856145Snate@binkert.org 1866285Snate@binkert.orgvoid Sequencer::printConfig(ostream& out) const { 1876285Snate@binkert.org out << "Seqeuncer config: " << m_name << endl; 1886285Snate@binkert.org out << " controller: " << m_controller->getName() << endl; 1896285Snate@binkert.org out << " version: " << m_version << endl; 1906285Snate@binkert.org out << " max_outstanding_requests: " << m_max_outstanding_requests << endl; 1916285Snate@binkert.org out << " deadlock_threshold: " << m_deadlock_threshold << endl; 1926145Snate@binkert.org} 1936145Snate@binkert.org 1946145Snate@binkert.org// Insert the request on the correct request table. Return true if 1956145Snate@binkert.org// the entry was already present. 1966285Snate@binkert.orgbool Sequencer::insertRequest(SequencerRequest* request) { 1976285Snate@binkert.org int total_outstanding = m_writeRequestTable.size() + m_readRequestTable.size(); 1986285Snate@binkert.org 1996145Snate@binkert.org assert(m_outstanding_count == total_outstanding); 2006145Snate@binkert.org 2016145Snate@binkert.org // See if we should schedule a deadlock check 2026145Snate@binkert.org if (m_deadlock_check_scheduled == false) { 2036285Snate@binkert.org g_eventQueue_ptr->scheduleEvent(this, m_deadlock_threshold); 2046145Snate@binkert.org m_deadlock_check_scheduled = true; 2056145Snate@binkert.org } 2066145Snate@binkert.org 2076285Snate@binkert.org Address line_addr(request->ruby_request.paddr); 2086285Snate@binkert.org line_addr.makeLineAddress(); 2096285Snate@binkert.org if ((request->ruby_request.type == RubyRequestType_ST) || 2106355Spdudnik@gmail.com (request->ruby_request.type == RubyRequestType_RMW_Read) || 2116355Spdudnik@gmail.com (request->ruby_request.type == RubyRequestType_RMW_Write) || 2126350Spdudnik@gmail.com (request->ruby_request.type == RubyRequestType_Locked_Read) || 2136350Spdudnik@gmail.com (request->ruby_request.type == RubyRequestType_Locked_Write)) { 2146285Snate@binkert.org if (m_writeRequestTable.exist(line_addr)) { 2156285Snate@binkert.org m_writeRequestTable.lookup(line_addr) = request; 2166285Snate@binkert.org // return true; 2176285Snate@binkert.org assert(0); // drh5: isn't this an error? do you lose the initial request? 2186145Snate@binkert.org } 2196285Snate@binkert.org m_writeRequestTable.allocate(line_addr); 2206285Snate@binkert.org m_writeRequestTable.lookup(line_addr) = request; 2216145Snate@binkert.org m_outstanding_count++; 2226145Snate@binkert.org } else { 2236285Snate@binkert.org if (m_readRequestTable.exist(line_addr)) { 2246285Snate@binkert.org m_readRequestTable.lookup(line_addr) = request; 2256285Snate@binkert.org // return true; 2266285Snate@binkert.org assert(0); // drh5: isn't this an error? do you lose the initial request? 2276145Snate@binkert.org } 2286285Snate@binkert.org m_readRequestTable.allocate(line_addr); 2296285Snate@binkert.org m_readRequestTable.lookup(line_addr) = request; 2306145Snate@binkert.org m_outstanding_count++; 2316145Snate@binkert.org } 2326145Snate@binkert.org 2336145Snate@binkert.org g_system_ptr->getProfiler()->sequencerRequests(m_outstanding_count); 2346145Snate@binkert.org 2356285Snate@binkert.org total_outstanding = m_writeRequestTable.size() + m_readRequestTable.size(); 2366285Snate@binkert.org assert(m_outstanding_count == total_outstanding); 2376145Snate@binkert.org 2386145Snate@binkert.org return false; 2396145Snate@binkert.org} 2406145Snate@binkert.org 2416285Snate@binkert.orgvoid Sequencer::removeRequest(SequencerRequest* srequest) { 2426145Snate@binkert.org 2436285Snate@binkert.org assert(m_outstanding_count == m_writeRequestTable.size() + m_readRequestTable.size()); 2446285Snate@binkert.org 2456285Snate@binkert.org const RubyRequest & ruby_request = srequest->ruby_request; 2466285Snate@binkert.org Address line_addr(ruby_request.paddr); 2476285Snate@binkert.org line_addr.makeLineAddress(); 2486285Snate@binkert.org if ((ruby_request.type == RubyRequestType_ST) || 2496355Spdudnik@gmail.com (ruby_request.type == RubyRequestType_RMW_Read) || 2506355Spdudnik@gmail.com (ruby_request.type == RubyRequestType_RMW_Write) || 2516350Spdudnik@gmail.com (ruby_request.type == RubyRequestType_Locked_Read) || 2526350Spdudnik@gmail.com (ruby_request.type == RubyRequestType_Locked_Write)) { 2536285Snate@binkert.org m_writeRequestTable.deallocate(line_addr); 2546145Snate@binkert.org } else { 2556285Snate@binkert.org m_readRequestTable.deallocate(line_addr); 2566145Snate@binkert.org } 2576145Snate@binkert.org m_outstanding_count--; 2586145Snate@binkert.org 2596285Snate@binkert.org assert(m_outstanding_count == m_writeRequestTable.size() + m_readRequestTable.size()); 2606145Snate@binkert.org} 2616145Snate@binkert.org 2626145Snate@binkert.orgvoid Sequencer::writeCallback(const Address& address, DataBlock& data) { 2636145Snate@binkert.org 2646145Snate@binkert.org assert(address == line_address(address)); 2656285Snate@binkert.org assert(m_writeRequestTable.exist(line_address(address))); 2666145Snate@binkert.org 2676285Snate@binkert.org SequencerRequest* request = m_writeRequestTable.lookup(address); 2686846Spdudnik@cs.wisc.edu 2696145Snate@binkert.org removeRequest(request); 2706145Snate@binkert.org 2716285Snate@binkert.org assert((request->ruby_request.type == RubyRequestType_ST) || 2726355Spdudnik@gmail.com (request->ruby_request.type == RubyRequestType_RMW_Read) || 2736355Spdudnik@gmail.com (request->ruby_request.type == RubyRequestType_RMW_Write) || 2746350Spdudnik@gmail.com (request->ruby_request.type == RubyRequestType_Locked_Read) || 2756350Spdudnik@gmail.com (request->ruby_request.type == RubyRequestType_Locked_Write)); 2766347Spdudnik@gmail.com // POLINA: the assumption is that atomics are only on data cache and not instruction cache 2776350Spdudnik@gmail.com if (request->ruby_request.type == RubyRequestType_Locked_Read) { 2786347Spdudnik@gmail.com m_dataCache_ptr->setLocked(address, m_version); 2796347Spdudnik@gmail.com } 2806506Spdudnik@gmail.com else if (request->ruby_request.type == RubyRequestType_RMW_Read) { 2816506Spdudnik@gmail.com m_controller->set_atomic(address); 2826506Spdudnik@gmail.com } 2836506Spdudnik@gmail.com else if (request->ruby_request.type == RubyRequestType_RMW_Write) { 2846846Spdudnik@cs.wisc.edu m_controller->clear_atomic(address); 2856506Spdudnik@gmail.com } 2866145Snate@binkert.org 2876285Snate@binkert.org hitCallback(request, data); 2886145Snate@binkert.org} 2896145Snate@binkert.org 2906145Snate@binkert.orgvoid Sequencer::readCallback(const Address& address, DataBlock& data) { 2916145Snate@binkert.org 2926285Snate@binkert.org assert(address == line_address(address)); 2936285Snate@binkert.org assert(m_readRequestTable.exist(line_address(address))); 2946145Snate@binkert.org 2956285Snate@binkert.org SequencerRequest* request = m_readRequestTable.lookup(address); 2966285Snate@binkert.org removeRequest(request); 2976285Snate@binkert.org 2986285Snate@binkert.org assert((request->ruby_request.type == RubyRequestType_LD) || 2996381Sdrh5@cs.wisc.edu (request->ruby_request.type == RubyRequestType_RMW_Read) || 3006285Snate@binkert.org (request->ruby_request.type == RubyRequestType_IFETCH)); 3016285Snate@binkert.org 3026285Snate@binkert.org hitCallback(request, data); 3036145Snate@binkert.org} 3046145Snate@binkert.org 3056285Snate@binkert.orgvoid Sequencer::hitCallback(SequencerRequest* srequest, DataBlock& data) { 3066285Snate@binkert.org const RubyRequest & ruby_request = srequest->ruby_request; 3076285Snate@binkert.org Address request_address(ruby_request.paddr); 3086285Snate@binkert.org Address request_line_address(ruby_request.paddr); 3096285Snate@binkert.org request_line_address.makeLineAddress(); 3106285Snate@binkert.org RubyRequestType type = ruby_request.type; 3116285Snate@binkert.org Time issued_time = srequest->issue_time; 3126145Snate@binkert.org 3136145Snate@binkert.org // Set this cache entry to the most recently used 3146285Snate@binkert.org if (type == RubyRequestType_IFETCH) { 3156285Snate@binkert.org if (m_instCache_ptr->isTagPresent(request_line_address) ) 3166285Snate@binkert.org m_instCache_ptr->setMRU(request_line_address); 3176145Snate@binkert.org } else { 3186285Snate@binkert.org if (m_dataCache_ptr->isTagPresent(request_line_address) ) 3196285Snate@binkert.org m_dataCache_ptr->setMRU(request_line_address); 3206145Snate@binkert.org } 3216145Snate@binkert.org 3226145Snate@binkert.org assert(g_eventQueue_ptr->getTime() >= issued_time); 3236145Snate@binkert.org Time miss_latency = g_eventQueue_ptr->getTime() - issued_time; 3246145Snate@binkert.org 3256285Snate@binkert.org // Profile the miss latency for all non-zero demand misses 3266285Snate@binkert.org if (miss_latency != 0) { 3276285Snate@binkert.org g_system_ptr->getProfiler()->missLatency(miss_latency, type); 3286285Snate@binkert.org 3296285Snate@binkert.org if (Debug::getProtocolTrace()) { 3306285Snate@binkert.org g_system_ptr->getProfiler()->profileTransition("Seq", m_version, Address(ruby_request.paddr), 3316285Snate@binkert.org "", "Done", "", int_to_string(miss_latency)+" cycles"); 3326285Snate@binkert.org } 3336285Snate@binkert.org } 3346285Snate@binkert.org /* 3356285Snate@binkert.org if (request.getPrefetch() == PrefetchBit_Yes) { 3366285Snate@binkert.org return; // Ignore the prefetch 3376285Snate@binkert.org } 3386285Snate@binkert.org */ 3396285Snate@binkert.org 3406285Snate@binkert.org // update the data 3416285Snate@binkert.org if (ruby_request.data != NULL) { 3426285Snate@binkert.org if ((type == RubyRequestType_LD) || 3436381Sdrh5@cs.wisc.edu (type == RubyRequestType_IFETCH) || 3446381Sdrh5@cs.wisc.edu (type == RubyRequestType_RMW_Read)) { 3456285Snate@binkert.org memcpy(ruby_request.data, data.getData(request_address.getOffset(), ruby_request.len), ruby_request.len); 3466285Snate@binkert.org } else { 3476285Snate@binkert.org data.setData(ruby_request.data, request_address.getOffset(), ruby_request.len); 3486285Snate@binkert.org } 3496145Snate@binkert.org } 3506846Spdudnik@cs.wisc.edu 3516285Snate@binkert.org m_hit_callback(srequest->id); 3526285Snate@binkert.org delete srequest; 3536285Snate@binkert.org} 3546285Snate@binkert.org 3556285Snate@binkert.org// Returns true if the sequencer already has a load or store outstanding 3566845Sdrh5@cs.wisc.eduint Sequencer::isReady(const RubyRequest& request) { 3576285Snate@binkert.org if (m_outstanding_count >= m_max_outstanding_requests) { 3586845Sdrh5@cs.wisc.edu return LIBRUBY_BUFFER_FULL; 3596145Snate@binkert.org } 3606145Snate@binkert.org 3616285Snate@binkert.org if( m_writeRequestTable.exist(line_address(Address(request.paddr))) || 3626285Snate@binkert.org m_readRequestTable.exist(line_address(Address(request.paddr))) ){ 3636285Snate@binkert.org //cout << "OUTSTANDING REQUEST EXISTS " << p << " VER " << m_version << endl; 3646145Snate@binkert.org //printProgress(cout); 3656845Sdrh5@cs.wisc.edu return LIBRUBY_ALIASED_REQUEST; 3666145Snate@binkert.org } 3676845Sdrh5@cs.wisc.edu 3686845Sdrh5@cs.wisc.edu return 1; 3696145Snate@binkert.org} 3706145Snate@binkert.org 3716285Snate@binkert.orgbool Sequencer::empty() const { 3726285Snate@binkert.org return (m_writeRequestTable.size() == 0) && (m_readRequestTable.size() == 0); 3736145Snate@binkert.org} 3746145Snate@binkert.org 3756349Spdudnik@gmail.com 3766285Snate@binkert.orgint64_t Sequencer::makeRequest(const RubyRequest & request) 3776285Snate@binkert.org{ 3786285Snate@binkert.org assert(Address(request.paddr).getOffset() + request.len <= RubySystem::getBlockSizeBytes()); 3796845Sdrh5@cs.wisc.edu int ready = isReady(request); 3806845Sdrh5@cs.wisc.edu if (ready > 0) { 3816285Snate@binkert.org int64_t id = makeUniqueRequestID(); 3826285Snate@binkert.org SequencerRequest *srequest = new SequencerRequest(request, id, g_eventQueue_ptr->getTime()); 3836285Snate@binkert.org bool found = insertRequest(srequest); 3846825Spdudnik@gmail.com if (!found) { 3856350Spdudnik@gmail.com if (request.type == RubyRequestType_Locked_Write) { 3866355Spdudnik@gmail.com // NOTE: it is OK to check the locked flag here as the mandatory queue will be checked first 3876355Spdudnik@gmail.com // ensuring that nothing comes between checking the flag and servicing the store 3886349Spdudnik@gmail.com if (!m_dataCache_ptr->isLocked(line_address(Address(request.paddr)), m_version)) { 3896355Spdudnik@gmail.com return LLSC_FAIL; 3906349Spdudnik@gmail.com } 3916349Spdudnik@gmail.com else { 3926349Spdudnik@gmail.com m_dataCache_ptr->clearLocked(line_address(Address(request.paddr))); 3936349Spdudnik@gmail.com } 3946349Spdudnik@gmail.com } 3956285Snate@binkert.org issueRequest(request); 3966145Snate@binkert.org 3976285Snate@binkert.org // TODO: issue hardware prefetches here 3986285Snate@binkert.org return id; 3996825Spdudnik@gmail.com } 4006825Spdudnik@gmail.com else { 4016825Spdudnik@gmail.com assert(0); 4026825Spdudnik@gmail.com } 4036145Snate@binkert.org } 4046285Snate@binkert.org else { 4056845Sdrh5@cs.wisc.edu return ready; 4066145Snate@binkert.org } 4076145Snate@binkert.org} 4086145Snate@binkert.org 4096285Snate@binkert.orgvoid Sequencer::issueRequest(const RubyRequest& request) { 4106285Snate@binkert.org 4116285Snate@binkert.org // TODO: get rid of CacheMsg, CacheRequestType, and AccessModeTYpe, & have SLICC use RubyRequest and subtypes natively 4126285Snate@binkert.org CacheRequestType ctype; 4136285Snate@binkert.org switch(request.type) { 4146285Snate@binkert.org case RubyRequestType_IFETCH: 4156846Spdudnik@cs.wisc.edu if (m_atomic_reads > 0 && m_atomic_writes == 0) { 4166846Spdudnik@cs.wisc.edu m_controller->reset_atomics(); 4176850Spdudnik@gmail.com m_atomic_writes = 0; 4186850Spdudnik@gmail.com m_atomic_reads = 0; 4196846Spdudnik@cs.wisc.edu } 4206846Spdudnik@cs.wisc.edu else if (m_atomic_writes > 0) { 4216846Spdudnik@cs.wisc.edu assert(m_atomic_reads > m_atomic_writes); 4226846Spdudnik@cs.wisc.edu cerr << "WARNING: Expected: " << m_atomic_reads << " RMW_Writes, but only received: " << m_atomic_writes << endl; 4236846Spdudnik@cs.wisc.edu assert(false); 4246846Spdudnik@cs.wisc.edu } 4256285Snate@binkert.org ctype = CacheRequestType_IFETCH; 4266285Snate@binkert.org break; 4276285Snate@binkert.org case RubyRequestType_LD: 4286846Spdudnik@cs.wisc.edu if (m_atomic_reads > 0 && m_atomic_writes == 0) { 4296846Spdudnik@cs.wisc.edu m_controller->reset_atomics(); 4306850Spdudnik@gmail.com m_atomic_writes = 0; 4316850Spdudnik@gmail.com m_atomic_reads = 0; 4326846Spdudnik@cs.wisc.edu } 4336846Spdudnik@cs.wisc.edu else if (m_atomic_writes > 0) { 4346846Spdudnik@cs.wisc.edu assert(m_atomic_reads > m_atomic_writes); 4356846Spdudnik@cs.wisc.edu cerr << "WARNING: Expected: " << m_atomic_reads << " RMW_Writes, but only received: " << m_atomic_writes << endl; 4366846Spdudnik@cs.wisc.edu assert(false); 4376846Spdudnik@cs.wisc.edu } 4386285Snate@binkert.org ctype = CacheRequestType_LD; 4396285Snate@binkert.org break; 4406285Snate@binkert.org case RubyRequestType_ST: 4416846Spdudnik@cs.wisc.edu if (m_atomic_reads > 0 && m_atomic_writes == 0) { 4426846Spdudnik@cs.wisc.edu m_controller->reset_atomics(); 4436850Spdudnik@gmail.com m_atomic_writes = 0; 4446850Spdudnik@gmail.com m_atomic_reads = 0; 4456846Spdudnik@cs.wisc.edu } 4466846Spdudnik@cs.wisc.edu else if (m_atomic_writes > 0) { 4476846Spdudnik@cs.wisc.edu assert(m_atomic_reads > m_atomic_writes); 4486846Spdudnik@cs.wisc.edu cerr << "WARNING: Expected: " << m_atomic_reads << " RMW_Writes, but only received: " << m_atomic_writes << endl; 4496846Spdudnik@cs.wisc.edu assert(false); 4506846Spdudnik@cs.wisc.edu } 4516285Snate@binkert.org ctype = CacheRequestType_ST; 4526285Snate@binkert.org break; 4536350Spdudnik@gmail.com case RubyRequestType_Locked_Read: 4546350Spdudnik@gmail.com case RubyRequestType_Locked_Write: 4556846Spdudnik@cs.wisc.edu ctype = CacheRequestType_ATOMIC; 4566846Spdudnik@cs.wisc.edu break; 4576355Spdudnik@gmail.com case RubyRequestType_RMW_Read: 4586846Spdudnik@cs.wisc.edu assert(m_atomic_writes == 0); 4596846Spdudnik@cs.wisc.edu m_atomic_reads++; 4606846Spdudnik@cs.wisc.edu ctype = CacheRequestType_ATOMIC; 4616846Spdudnik@cs.wisc.edu break; 4626355Spdudnik@gmail.com case RubyRequestType_RMW_Write: 4636846Spdudnik@cs.wisc.edu assert(m_atomic_reads > 0); 4646846Spdudnik@cs.wisc.edu assert(m_atomic_writes < m_atomic_reads); 4656846Spdudnik@cs.wisc.edu m_atomic_writes++; 4666846Spdudnik@cs.wisc.edu if (m_atomic_reads == m_atomic_writes) { 4676846Spdudnik@cs.wisc.edu m_atomic_reads = 0; 4686846Spdudnik@cs.wisc.edu m_atomic_writes = 0; 4696846Spdudnik@cs.wisc.edu } 4706355Spdudnik@gmail.com ctype = CacheRequestType_ATOMIC; 4716355Spdudnik@gmail.com break; 4726285Snate@binkert.org default: 4736285Snate@binkert.org assert(0); 4746145Snate@binkert.org } 4756285Snate@binkert.org AccessModeType amtype; 4766285Snate@binkert.org switch(request.access_mode){ 4776285Snate@binkert.org case RubyAccessMode_User: 4786285Snate@binkert.org amtype = AccessModeType_UserMode; 4796285Snate@binkert.org break; 4806285Snate@binkert.org case RubyAccessMode_Supervisor: 4816285Snate@binkert.org amtype = AccessModeType_SupervisorMode; 4826285Snate@binkert.org break; 4836285Snate@binkert.org case RubyAccessMode_Device: 4846285Snate@binkert.org amtype = AccessModeType_UserMode; 4856285Snate@binkert.org break; 4866285Snate@binkert.org default: 4876285Snate@binkert.org assert(0); 4886285Snate@binkert.org } 4896285Snate@binkert.org Address line_addr(request.paddr); 4906285Snate@binkert.org line_addr.makeLineAddress(); 4916505Spdudnik@gmail.com CacheMsg msg(line_addr, Address(request.paddr), ctype, Address(request.pc), amtype, request.len, PrefetchBit_No, request.proc_id); 4926285Snate@binkert.org 4936285Snate@binkert.org if (Debug::getProtocolTrace()) { 4946285Snate@binkert.org g_system_ptr->getProfiler()->profileTransition("Seq", m_version, Address(request.paddr), 4956285Snate@binkert.org "", "Begin", "", RubyRequestType_to_string(request.type)); 4966285Snate@binkert.org } 4976285Snate@binkert.org 4986285Snate@binkert.org if (g_system_ptr->getTracer()->traceEnabled()) { 4996285Snate@binkert.org g_system_ptr->getTracer()->traceRequest(m_name, line_addr, Address(request.pc), 5006285Snate@binkert.org request.type, g_eventQueue_ptr->getTime()); 5016285Snate@binkert.org } 5026285Snate@binkert.org 5036285Snate@binkert.org Time latency = 0; // initialzed to an null value 5046285Snate@binkert.org 5056285Snate@binkert.org if (request.type == RubyRequestType_IFETCH) 5066285Snate@binkert.org latency = m_instCache_ptr->getLatency(); 5076285Snate@binkert.org else 5086285Snate@binkert.org latency = m_dataCache_ptr->getLatency(); 5096285Snate@binkert.org 5106285Snate@binkert.org // Send the message to the cache controller 5116285Snate@binkert.org assert(latency > 0); 5126285Snate@binkert.org 5136285Snate@binkert.org 5146285Snate@binkert.org m_mandatory_q_ptr->enqueue(msg, latency); 5156285Snate@binkert.org} 5166285Snate@binkert.org/* 5176285Snate@binkert.orgbool Sequencer::tryCacheAccess(const Address& addr, CacheRequestType type, 5186285Snate@binkert.org AccessModeType access_mode, 5196285Snate@binkert.org int size, DataBlock*& data_ptr) { 5206285Snate@binkert.org if (type == CacheRequestType_IFETCH) { 5216285Snate@binkert.org return m_instCache_ptr->tryCacheAccess(line_address(addr), type, data_ptr); 5226285Snate@binkert.org } else { 5236285Snate@binkert.org return m_dataCache_ptr->tryCacheAccess(line_address(addr), type, data_ptr); 5246145Snate@binkert.org } 5256145Snate@binkert.org} 5266285Snate@binkert.org*/ 5276145Snate@binkert.org 5286145Snate@binkert.orgvoid Sequencer::print(ostream& out) const { 5296285Snate@binkert.org out << "[Sequencer: " << m_version 5306145Snate@binkert.org << ", outstanding requests: " << m_outstanding_count; 5316145Snate@binkert.org 5326285Snate@binkert.org out << ", read request table: " << m_readRequestTable 5336285Snate@binkert.org << ", write request table: " << m_writeRequestTable; 5346145Snate@binkert.org out << "]"; 5356145Snate@binkert.org} 5366145Snate@binkert.org 5376145Snate@binkert.org// this can be called from setState whenever coherence permissions are upgraded 5386145Snate@binkert.org// when invoked, coherence violations will be checked for the given block 5396145Snate@binkert.orgvoid Sequencer::checkCoherence(const Address& addr) { 5406145Snate@binkert.org#ifdef CHECK_COHERENCE 5416145Snate@binkert.org g_system_ptr->checkGlobalCoherenceInvariant(addr); 5426145Snate@binkert.org#endif 5436145Snate@binkert.org} 5446145Snate@binkert.org 545