Sequencer.cc revision 6285
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
306154Snate@binkert.org#include "mem/ruby/common/Global.hh"
316154Snate@binkert.org#include "mem/ruby/system/Sequencer.hh"
326154Snate@binkert.org#include "mem/ruby/system/System.hh"
336154Snate@binkert.org#include "mem/protocol/Protocol.hh"
346154Snate@binkert.org#include "mem/ruby/profiler/Profiler.hh"
356154Snate@binkert.org#include "mem/ruby/system/CacheMemory.hh"
366285Snate@binkert.org#include "mem/protocol/CacheMsg.hh"
376285Snate@binkert.org#include "mem/ruby/recorder/Tracer.hh"
386154Snate@binkert.org#include "mem/ruby/common/SubBlock.hh"
396154Snate@binkert.org#include "mem/protocol/Protocol.hh"
406154Snate@binkert.org#include "mem/gems_common/Map.hh"
416285Snate@binkert.org#include "mem/ruby/buffers/MessageBuffer.hh"
426285Snate@binkert.org#include "mem/ruby/slicc_interface/AbstractController.hh"
436145Snate@binkert.org
446285Snate@binkert.org//Sequencer::Sequencer(int core_id, MessageBuffer* mandatory_q)
456145Snate@binkert.org
466285Snate@binkert.orgSequencer::Sequencer(const string & name)
476285Snate@binkert.org  :RubyPort(name)
486285Snate@binkert.org{
496285Snate@binkert.org}
506285Snate@binkert.org
516285Snate@binkert.orgvoid Sequencer::init(const vector<string> & argv)
526285Snate@binkert.org{
536145Snate@binkert.org  m_deadlock_check_scheduled = false;
546145Snate@binkert.org  m_outstanding_count = 0;
556145Snate@binkert.org
566285Snate@binkert.org  m_max_outstanding_requests = 0;
576285Snate@binkert.org  m_deadlock_threshold = 0;
586285Snate@binkert.org  m_version = -1;
596285Snate@binkert.org  m_instCache_ptr = NULL;
606285Snate@binkert.org  m_dataCache_ptr = NULL;
616285Snate@binkert.org  m_controller = NULL;
626285Snate@binkert.org  for (size_t i=0; i<argv.size(); i+=2) {
636285Snate@binkert.org    if ( argv[i] == "controller") {
646285Snate@binkert.org      m_controller = RubySystem::getController(argv[i+1]); // args[i] = "L1Cache"
656285Snate@binkert.org      m_mandatory_q_ptr = m_controller->getMandatoryQueue();
666285Snate@binkert.org    } else if ( argv[i] == "icache")
676285Snate@binkert.org      m_instCache_ptr = RubySystem::getCache(argv[i+1]);
686285Snate@binkert.org    else if ( argv[i] == "dcache")
696285Snate@binkert.org      m_dataCache_ptr = RubySystem::getCache(argv[i+1]);
706285Snate@binkert.org    else if ( argv[i] == "version")
716285Snate@binkert.org      m_version = atoi(argv[i+1].c_str());
726285Snate@binkert.org    else if ( argv[i] == "max_outstanding_requests")
736285Snate@binkert.org      m_max_outstanding_requests = atoi(argv[i+1].c_str());
746285Snate@binkert.org    else if ( argv[i] == "deadlock_threshold")
756285Snate@binkert.org      m_deadlock_threshold = atoi(argv[i+1].c_str());
766285Snate@binkert.org    else {
776285Snate@binkert.org      cerr << "WARNING: Sequencer: Unkown configuration parameter: " << argv[i] << endl;
786285Snate@binkert.org      assert(false);
796285Snate@binkert.org    }
806145Snate@binkert.org  }
816285Snate@binkert.org  assert(m_max_outstanding_requests > 0);
826285Snate@binkert.org  assert(m_deadlock_threshold > 0);
836285Snate@binkert.org  assert(m_version > -1);
846285Snate@binkert.org  assert(m_instCache_ptr != NULL);
856285Snate@binkert.org  assert(m_dataCache_ptr != NULL);
866285Snate@binkert.org  assert(m_controller != NULL);
876145Snate@binkert.org}
886145Snate@binkert.org
896145Snate@binkert.orgSequencer::~Sequencer() {
906285Snate@binkert.org
916145Snate@binkert.org}
926145Snate@binkert.org
936145Snate@binkert.orgvoid Sequencer::wakeup() {
946145Snate@binkert.org  // Check for deadlock of any of the requests
956145Snate@binkert.org  Time current_time = g_eventQueue_ptr->getTime();
966145Snate@binkert.org
976145Snate@binkert.org  // Check across all outstanding requests
986145Snate@binkert.org  int total_outstanding = 0;
996285Snate@binkert.org
1006285Snate@binkert.org  Vector<Address> keys = m_readRequestTable.keys();
1016285Snate@binkert.org  for (int i=0; i<keys.size(); i++) {
1026285Snate@binkert.org    SequencerRequest* request = m_readRequestTable.lookup(keys[i]);
1036285Snate@binkert.org    if (current_time - request->issue_time >= m_deadlock_threshold) {
1046285Snate@binkert.org      WARN_MSG("Possible Deadlock detected");
1056285Snate@binkert.org      WARN_EXPR(request);
1066285Snate@binkert.org      WARN_EXPR(m_version);
1076285Snate@binkert.org      WARN_EXPR(keys.size());
1086285Snate@binkert.org      WARN_EXPR(current_time);
1096285Snate@binkert.org      WARN_EXPR(request->issue_time);
1106285Snate@binkert.org      WARN_EXPR(current_time - request->issue_time);
1116285Snate@binkert.org      ERROR_MSG("Aborting");
1126145Snate@binkert.org    }
1136285Snate@binkert.org  }
1146145Snate@binkert.org
1156285Snate@binkert.org  keys = m_writeRequestTable.keys();
1166285Snate@binkert.org  for (int i=0; i<keys.size(); i++) {
1176285Snate@binkert.org    SequencerRequest* request = m_writeRequestTable.lookup(keys[i]);
1186285Snate@binkert.org    if (current_time - request->issue_time >= m_deadlock_threshold) {
1196285Snate@binkert.org      WARN_MSG("Possible Deadlock detected");
1206285Snate@binkert.org      WARN_EXPR(request);
1216285Snate@binkert.org      WARN_EXPR(m_version);
1226285Snate@binkert.org      WARN_EXPR(current_time);
1236285Snate@binkert.org      WARN_EXPR(request->issue_time);
1246285Snate@binkert.org      WARN_EXPR(current_time - request->issue_time);
1256285Snate@binkert.org      WARN_EXPR(keys.size());
1266285Snate@binkert.org      ERROR_MSG("Aborting");
1276145Snate@binkert.org    }
1286285Snate@binkert.org  }
1296285Snate@binkert.org  total_outstanding += m_writeRequestTable.size() + m_readRequestTable.size();
1306285Snate@binkert.org
1316145Snate@binkert.org  assert(m_outstanding_count == total_outstanding);
1326145Snate@binkert.org
1336145Snate@binkert.org  if (m_outstanding_count > 0) { // If there are still outstanding requests, keep checking
1346285Snate@binkert.org    g_eventQueue_ptr->scheduleEvent(this, m_deadlock_threshold);
1356145Snate@binkert.org  } else {
1366145Snate@binkert.org    m_deadlock_check_scheduled = false;
1376145Snate@binkert.org  }
1386145Snate@binkert.org}
1396145Snate@binkert.org
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
1966145Snate@binkert.org  if (m_deadlock_check_scheduled == false) {
1976285Snate@binkert.org    g_eventQueue_ptr->scheduleEvent(this, m_deadlock_threshold);
1986145Snate@binkert.org    m_deadlock_check_scheduled = true;
1996145Snate@binkert.org  }
2006145Snate@binkert.org
2016285Snate@binkert.org  Address line_addr(request->ruby_request.paddr);
2026285Snate@binkert.org  line_addr.makeLineAddress();
2036285Snate@binkert.org  if ((request->ruby_request.type == RubyRequestType_ST) ||
2046285Snate@binkert.org      (request->ruby_request.type == RubyRequestType_RMW)) {
2056285Snate@binkert.org    if (m_writeRequestTable.exist(line_addr)) {
2066285Snate@binkert.org      m_writeRequestTable.lookup(line_addr) = request;
2076285Snate@binkert.org      //      return true;
2086285Snate@binkert.org      assert(0); // drh5: isn't this an error?  do you lose the initial request?
2096145Snate@binkert.org    }
2106285Snate@binkert.org    m_writeRequestTable.allocate(line_addr);
2116285Snate@binkert.org    m_writeRequestTable.lookup(line_addr) = request;
2126145Snate@binkert.org    m_outstanding_count++;
2136145Snate@binkert.org  } else {
2146285Snate@binkert.org    if (m_readRequestTable.exist(line_addr)) {
2156285Snate@binkert.org      m_readRequestTable.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_readRequestTable.allocate(line_addr);
2206285Snate@binkert.org    m_readRequestTable.lookup(line_addr) = request;
2216145Snate@binkert.org    m_outstanding_count++;
2226145Snate@binkert.org  }
2236145Snate@binkert.org
2246145Snate@binkert.org  g_system_ptr->getProfiler()->sequencerRequests(m_outstanding_count);
2256145Snate@binkert.org
2266285Snate@binkert.org  total_outstanding = m_writeRequestTable.size() + m_readRequestTable.size();
2276285Snate@binkert.org  assert(m_outstanding_count == total_outstanding);
2286145Snate@binkert.org
2296145Snate@binkert.org  return false;
2306145Snate@binkert.org}
2316145Snate@binkert.org
2326285Snate@binkert.orgvoid Sequencer::removeRequest(SequencerRequest* srequest) {
2336145Snate@binkert.org
2346285Snate@binkert.org  assert(m_outstanding_count == m_writeRequestTable.size() + m_readRequestTable.size());
2356285Snate@binkert.org
2366285Snate@binkert.org  const RubyRequest & ruby_request = srequest->ruby_request;
2376285Snate@binkert.org  Address line_addr(ruby_request.paddr);
2386285Snate@binkert.org  line_addr.makeLineAddress();
2396285Snate@binkert.org  if ((ruby_request.type == RubyRequestType_ST) ||
2406285Snate@binkert.org      (ruby_request.type == RubyRequestType_RMW)) {
2416285Snate@binkert.org    m_writeRequestTable.deallocate(line_addr);
2426145Snate@binkert.org  } else {
2436285Snate@binkert.org    m_readRequestTable.deallocate(line_addr);
2446145Snate@binkert.org  }
2456145Snate@binkert.org  m_outstanding_count--;
2466145Snate@binkert.org
2476285Snate@binkert.org  assert(m_outstanding_count == m_writeRequestTable.size() + m_readRequestTable.size());
2486145Snate@binkert.org}
2496145Snate@binkert.org
2506145Snate@binkert.orgvoid Sequencer::writeCallback(const Address& address, DataBlock& data) {
2516145Snate@binkert.org
2526145Snate@binkert.org  assert(address == line_address(address));
2536285Snate@binkert.org  assert(m_writeRequestTable.exist(line_address(address)));
2546145Snate@binkert.org
2556285Snate@binkert.org  SequencerRequest* request = m_writeRequestTable.lookup(address);
2566145Snate@binkert.org  removeRequest(request);
2576145Snate@binkert.org
2586285Snate@binkert.org  assert((request->ruby_request.type == RubyRequestType_ST) ||
2596285Snate@binkert.org         (request->ruby_request.type == RubyRequestType_RMW));
2606145Snate@binkert.org
2616285Snate@binkert.org  hitCallback(request, data);
2626145Snate@binkert.org}
2636145Snate@binkert.org
2646145Snate@binkert.orgvoid Sequencer::readCallback(const Address& address, DataBlock& data) {
2656145Snate@binkert.org
2666285Snate@binkert.org  assert(address == line_address(address));
2676285Snate@binkert.org  assert(m_readRequestTable.exist(line_address(address)));
2686145Snate@binkert.org
2696285Snate@binkert.org  SequencerRequest* request = m_readRequestTable.lookup(address);
2706285Snate@binkert.org  removeRequest(request);
2716285Snate@binkert.org
2726285Snate@binkert.org  assert((request->ruby_request.type == RubyRequestType_LD) ||
2736285Snate@binkert.org         (request->ruby_request.type == RubyRequestType_IFETCH));
2746285Snate@binkert.org
2756285Snate@binkert.org  hitCallback(request, data);
2766145Snate@binkert.org}
2776145Snate@binkert.org
2786285Snate@binkert.orgvoid Sequencer::hitCallback(SequencerRequest* srequest, DataBlock& data) {
2796285Snate@binkert.org  const RubyRequest & ruby_request = srequest->ruby_request;
2806285Snate@binkert.org  int size = ruby_request.len;
2816285Snate@binkert.org  Address request_address(ruby_request.paddr);
2826285Snate@binkert.org  Address request_line_address(ruby_request.paddr);
2836285Snate@binkert.org  request_line_address.makeLineAddress();
2846285Snate@binkert.org  RubyRequestType type = ruby_request.type;
2856285Snate@binkert.org  Time issued_time = srequest->issue_time;
2866145Snate@binkert.org
2876145Snate@binkert.org  // Set this cache entry to the most recently used
2886285Snate@binkert.org  if (type == RubyRequestType_IFETCH) {
2896285Snate@binkert.org    if (m_instCache_ptr->isTagPresent(request_line_address) )
2906285Snate@binkert.org      m_instCache_ptr->setMRU(request_line_address);
2916145Snate@binkert.org  } else {
2926285Snate@binkert.org    if (m_dataCache_ptr->isTagPresent(request_line_address) )
2936285Snate@binkert.org      m_dataCache_ptr->setMRU(request_line_address);
2946145Snate@binkert.org  }
2956145Snate@binkert.org
2966145Snate@binkert.org  assert(g_eventQueue_ptr->getTime() >= issued_time);
2976145Snate@binkert.org  Time miss_latency = g_eventQueue_ptr->getTime() - issued_time;
2986145Snate@binkert.org
2996285Snate@binkert.org  // Profile the miss latency for all non-zero demand misses
3006285Snate@binkert.org  if (miss_latency != 0) {
3016285Snate@binkert.org    g_system_ptr->getProfiler()->missLatency(miss_latency, type);
3026285Snate@binkert.org
3036285Snate@binkert.org    if (Debug::getProtocolTrace()) {
3046285Snate@binkert.org      g_system_ptr->getProfiler()->profileTransition("Seq", m_version, Address(ruby_request.paddr),
3056285Snate@binkert.org                                                     "", "Done", "", int_to_string(miss_latency)+" cycles");
3066285Snate@binkert.org    }
3076285Snate@binkert.org  }
3086285Snate@binkert.org  /*
3096285Snate@binkert.org  if (request.getPrefetch() == PrefetchBit_Yes) {
3106285Snate@binkert.org    return; // Ignore the prefetch
3116285Snate@binkert.org  }
3126285Snate@binkert.org  */
3136285Snate@binkert.org
3146285Snate@binkert.org  // update the data
3156285Snate@binkert.org  if (ruby_request.data != NULL) {
3166285Snate@binkert.org    if ((type == RubyRequestType_LD) ||
3176285Snate@binkert.org        (type == RubyRequestType_IFETCH)) {
3186285Snate@binkert.org      memcpy(ruby_request.data, data.getData(request_address.getOffset(), ruby_request.len), ruby_request.len);
3196285Snate@binkert.org    } else {
3206285Snate@binkert.org      data.setData(ruby_request.data, request_address.getOffset(), ruby_request.len);
3216285Snate@binkert.org    }
3226145Snate@binkert.org  }
3236145Snate@binkert.org
3246285Snate@binkert.org  m_hit_callback(srequest->id);
3256285Snate@binkert.org  delete srequest;
3266285Snate@binkert.org}
3276285Snate@binkert.org
3286285Snate@binkert.org// Returns true if the sequencer already has a load or store outstanding
3296285Snate@binkert.orgbool Sequencer::isReady(const RubyRequest& request) const {
3306285Snate@binkert.org  // POLINA: check if we are currently flushing the write buffer, if so Ruby is returned as not ready
3316285Snate@binkert.org  // to simulate stalling of the front-end
3326285Snate@binkert.org  // Do we stall all the sequencers? If it is atomic instruction - yes!
3336285Snate@binkert.org  if (m_outstanding_count >= m_max_outstanding_requests) {
3346285Snate@binkert.org    return false;
3356145Snate@binkert.org  }
3366145Snate@binkert.org
3376285Snate@binkert.org  if( m_writeRequestTable.exist(line_address(Address(request.paddr))) ||
3386285Snate@binkert.org      m_readRequestTable.exist(line_address(Address(request.paddr))) ){
3396285Snate@binkert.org    //cout << "OUTSTANDING REQUEST EXISTS " << p << " VER " << m_version << endl;
3406145Snate@binkert.org    //printProgress(cout);
3416145Snate@binkert.org    return false;
3426145Snate@binkert.org  }
3436145Snate@binkert.org
3446145Snate@binkert.org  return true;
3456145Snate@binkert.org}
3466145Snate@binkert.org
3476285Snate@binkert.orgbool Sequencer::empty() const {
3486285Snate@binkert.org  return (m_writeRequestTable.size() == 0) && (m_readRequestTable.size() == 0);
3496145Snate@binkert.org}
3506145Snate@binkert.org
3516285Snate@binkert.orgint64_t Sequencer::makeRequest(const RubyRequest & request)
3526285Snate@binkert.org{
3536285Snate@binkert.org  assert(Address(request.paddr).getOffset() + request.len <= RubySystem::getBlockSizeBytes());
3546285Snate@binkert.org  if (isReady(request)) {
3556285Snate@binkert.org    int64_t id = makeUniqueRequestID();
3566285Snate@binkert.org    SequencerRequest *srequest = new SequencerRequest(request, id, g_eventQueue_ptr->getTime());
3576285Snate@binkert.org    bool found = insertRequest(srequest);
3586285Snate@binkert.org    if (!found)
3596285Snate@binkert.org      issueRequest(request);
3606145Snate@binkert.org
3616285Snate@binkert.org    // TODO: issue hardware prefetches here
3626285Snate@binkert.org    return id;
3636145Snate@binkert.org  }
3646285Snate@binkert.org  else {
3656285Snate@binkert.org    return -1;
3666145Snate@binkert.org  }
3676145Snate@binkert.org}
3686145Snate@binkert.org
3696285Snate@binkert.orgvoid Sequencer::issueRequest(const RubyRequest& request) {
3706285Snate@binkert.org
3716285Snate@binkert.org  // TODO: get rid of CacheMsg, CacheRequestType, and AccessModeTYpe, & have SLICC use RubyRequest and subtypes natively
3726285Snate@binkert.org  CacheRequestType ctype;
3736285Snate@binkert.org  switch(request.type) {
3746285Snate@binkert.org  case RubyRequestType_IFETCH:
3756285Snate@binkert.org    ctype = CacheRequestType_IFETCH;
3766285Snate@binkert.org    break;
3776285Snate@binkert.org  case RubyRequestType_LD:
3786285Snate@binkert.org    ctype = CacheRequestType_LD;
3796285Snate@binkert.org    break;
3806285Snate@binkert.org  case RubyRequestType_ST:
3816285Snate@binkert.org    ctype = CacheRequestType_ST;
3826285Snate@binkert.org    break;
3836285Snate@binkert.org  case RubyRequestType_RMW:
3846285Snate@binkert.org    ctype = CacheRequestType_ATOMIC;
3856285Snate@binkert.org    break;
3866285Snate@binkert.org  default:
3876285Snate@binkert.org    assert(0);
3886145Snate@binkert.org  }
3896285Snate@binkert.org  AccessModeType amtype;
3906285Snate@binkert.org  switch(request.access_mode){
3916285Snate@binkert.org  case RubyAccessMode_User:
3926285Snate@binkert.org    amtype = AccessModeType_UserMode;
3936285Snate@binkert.org    break;
3946285Snate@binkert.org  case RubyAccessMode_Supervisor:
3956285Snate@binkert.org    amtype = AccessModeType_SupervisorMode;
3966285Snate@binkert.org    break;
3976285Snate@binkert.org  case RubyAccessMode_Device:
3986285Snate@binkert.org    amtype = AccessModeType_UserMode;
3996285Snate@binkert.org    break;
4006285Snate@binkert.org  default:
4016285Snate@binkert.org    assert(0);
4026285Snate@binkert.org  }
4036285Snate@binkert.org  Address line_addr(request.paddr);
4046285Snate@binkert.org  line_addr.makeLineAddress();
4056285Snate@binkert.org  CacheMsg msg(line_addr, Address(request.paddr), ctype, Address(request.pc), amtype, request.len, PrefetchBit_No);
4066285Snate@binkert.org
4076285Snate@binkert.org  if (Debug::getProtocolTrace()) {
4086285Snate@binkert.org    g_system_ptr->getProfiler()->profileTransition("Seq", m_version, Address(request.paddr),
4096285Snate@binkert.org                                                   "", "Begin", "", RubyRequestType_to_string(request.type));
4106285Snate@binkert.org  }
4116285Snate@binkert.org
4126285Snate@binkert.org  if (g_system_ptr->getTracer()->traceEnabled()) {
4136285Snate@binkert.org    g_system_ptr->getTracer()->traceRequest(m_name, line_addr, Address(request.pc),
4146285Snate@binkert.org                                            request.type, g_eventQueue_ptr->getTime());
4156285Snate@binkert.org  }
4166285Snate@binkert.org
4176285Snate@binkert.org  Time latency = 0;  // initialzed to an null value
4186285Snate@binkert.org
4196285Snate@binkert.org  if (request.type == RubyRequestType_IFETCH)
4206285Snate@binkert.org    latency = m_instCache_ptr->getLatency();
4216285Snate@binkert.org  else
4226285Snate@binkert.org    latency = m_dataCache_ptr->getLatency();
4236285Snate@binkert.org
4246285Snate@binkert.org  // Send the message to the cache controller
4256285Snate@binkert.org  assert(latency > 0);
4266285Snate@binkert.org
4276285Snate@binkert.org
4286285Snate@binkert.org  m_mandatory_q_ptr->enqueue(msg, latency);
4296285Snate@binkert.org}
4306285Snate@binkert.org/*
4316285Snate@binkert.orgbool Sequencer::tryCacheAccess(const Address& addr, CacheRequestType type,
4326285Snate@binkert.org                               AccessModeType access_mode,
4336285Snate@binkert.org                               int size, DataBlock*& data_ptr) {
4346285Snate@binkert.org  if (type == CacheRequestType_IFETCH) {
4356285Snate@binkert.org    return m_instCache_ptr->tryCacheAccess(line_address(addr), type, data_ptr);
4366285Snate@binkert.org  } else {
4376285Snate@binkert.org    return m_dataCache_ptr->tryCacheAccess(line_address(addr), type, data_ptr);
4386145Snate@binkert.org  }
4396145Snate@binkert.org}
4406285Snate@binkert.org*/
4416145Snate@binkert.org
4426145Snate@binkert.orgvoid Sequencer::print(ostream& out) const {
4436285Snate@binkert.org  out << "[Sequencer: " << m_version
4446145Snate@binkert.org      << ", outstanding requests: " << m_outstanding_count;
4456145Snate@binkert.org
4466285Snate@binkert.org  out << ", read request table: " << m_readRequestTable
4476285Snate@binkert.org      << ", write request table: " << m_writeRequestTable;
4486145Snate@binkert.org  out << "]";
4496145Snate@binkert.org}
4506145Snate@binkert.org
4516145Snate@binkert.org// this can be called from setState whenever coherence permissions are upgraded
4526145Snate@binkert.org// when invoked, coherence violations will be checked for the given block
4536145Snate@binkert.orgvoid Sequencer::checkCoherence(const Address& addr) {
4546145Snate@binkert.org#ifdef CHECK_COHERENCE
4556145Snate@binkert.org  g_system_ptr->checkGlobalCoherenceInvariant(addr);
4566145Snate@binkert.org#endif
4576145Snate@binkert.org}
4586145Snate@binkert.org
4596285Snate@binkert.org/*
4606145Snate@binkert.orgbool Sequencer::getRubyMemoryValue(const Address& addr, char* value,
4616285Snate@binkert.org                                   unsigned int size_in_bytes )
4626285Snate@binkert.org{
4636285Snate@binkert.org    bool found = false;
4646285Snate@binkert.org    const Address lineAddr = line_address(addr);
4656285Snate@binkert.org    DataBlock data;
4666285Snate@binkert.org    PhysAddress paddr(addr);
4676285Snate@binkert.org    DataBlock* dataPtr = &data;
4686285Snate@binkert.org
4696285Snate@binkert.org    MachineID l2_mach = map_L2ChipId_to_L2Cache(addr, m_chip_ptr->getID() );
4706285Snate@binkert.org    int l2_ver = l2_mach.num%RubyConfig::numberOfL2CachePerChip();
4716285Snate@binkert.org
4726285Snate@binkert.org    if (Protocol::m_TwoLevelCache) {
4736285Snate@binkert.org      if(Protocol::m_CMP){
4746285Snate@binkert.org        assert(n->m_L2Cache_L2cacheMemory_vec[l2_ver] != NULL);
4756285Snate@binkert.org      }
4766285Snate@binkert.org      else{
4776285Snate@binkert.org        assert(n->m_L1Cache_cacheMemory_vec[m_version] != NULL);
4786285Snate@binkert.org      }
4796285Snate@binkert.org    }
4806285Snate@binkert.org
4816285Snate@binkert.org    if (n->m_L1Cache_L1IcacheMemory_vec[m_version]->tryCacheAccess(lineAddr, CacheRequestType_IFETCH, dataPtr)){
4826285Snate@binkert.org      n->m_L1Cache_L1IcacheMemory_vec[m_version]->getMemoryValue(addr, value, size_in_bytes);
4836285Snate@binkert.org      found = true;
4846285Snate@binkert.org    } else if (n->m_L1Cache_L1DcacheMemory_vec[m_version]->tryCacheAccess(lineAddr, CacheRequestType_LD, dataPtr)){
4856285Snate@binkert.org      n->m_L1Cache_L1DcacheMemory_vec[m_version]->getMemoryValue(addr, value, size_in_bytes);
4866285Snate@binkert.org      found = true;
4876285Snate@binkert.org    } else if (Protocol::m_CMP && n->m_L2Cache_L2cacheMemory_vec[l2_ver]->tryCacheAccess(lineAddr, CacheRequestType_LD, dataPtr)){
4886285Snate@binkert.org      n->m_L2Cache_L2cacheMemory_vec[l2_ver]->getMemoryValue(addr, value, size_in_bytes);
4896285Snate@binkert.org      found = true;
4906285Snate@binkert.org    // } else if (n->TBE_TABLE_MEMBER_VARIABLE->isPresent(lineAddr)){
4916285Snate@binkert.org//       ASSERT(n->TBE_TABLE_MEMBER_VARIABLE->isPresent(lineAddr));
4926285Snate@binkert.org//       L1Cache_TBE tbeEntry = n->TBE_TABLE_MEMBER_VARIABLE->lookup(lineAddr);
4936285Snate@binkert.org
4946285Snate@binkert.org//       int offset = addr.getOffset();
4956285Snate@binkert.org//       for(int i=0; i<size_in_bytes; ++i){
4966285Snate@binkert.org//         value[i] = tbeEntry.getDataBlk().getByte(offset + i);
4976285Snate@binkert.org//       }
4986285Snate@binkert.org
4996285Snate@binkert.org//       found = true;
5006285Snate@binkert.org    } else {
5016285Snate@binkert.org      // Address not found
5026285Snate@binkert.org      //cout << "  " << m_chip_ptr->getID() << " NOT IN CACHE, Value at Directory is: " << (int) value[0] << endl;
5036285Snate@binkert.org      n = dynamic_cast<Chip*>(g_system_ptr->getChip(map_Address_to_DirectoryNode(addr)/RubyConfig::numberOfDirectoryPerChip()));
5046285Snate@binkert.org      int dir_version = map_Address_to_DirectoryNode(addr)%RubyConfig::numberOfDirectoryPerChip();
5056285Snate@binkert.org      for(unsigned int i=0; i<size_in_bytes; ++i){
5066285Snate@binkert.org        int offset = addr.getOffset();
5076285Snate@binkert.org        value[i] = n->m_Directory_directory_vec[dir_version]->lookup(lineAddr).m_DataBlk.getByte(offset + i);
5086285Snate@binkert.org      }
5096285Snate@binkert.org      // Address not found
5106285Snate@binkert.org      //WARN_MSG("Couldn't find address");
5116285Snate@binkert.org      //WARN_EXPR(addr);
5126285Snate@binkert.org      found = false;
5136285Snate@binkert.org    }
5146285Snate@binkert.org    return true;
5156145Snate@binkert.org}
5166145Snate@binkert.org
5176145Snate@binkert.orgbool Sequencer::setRubyMemoryValue(const Address& addr, char *value,
5186145Snate@binkert.org                                   unsigned int size_in_bytes) {
5196145Snate@binkert.org  char test_buffer[64];
5206145Snate@binkert.org
5216285Snate@binkert.org  // idea here is that coherent cache should find the
5226285Snate@binkert.org  // latest data, the update it
5236285Snate@binkert.org  bool found = false;
5246285Snate@binkert.org  const Address lineAddr = line_address(addr);
5256285Snate@binkert.org  PhysAddress paddr(addr);
5266285Snate@binkert.org  DataBlock data;
5276285Snate@binkert.org  DataBlock* dataPtr = &data;
5286285Snate@binkert.org  Chip* n = dynamic_cast<Chip*>(m_chip_ptr);
5296285Snate@binkert.org
5306285Snate@binkert.org  MachineID l2_mach = map_L2ChipId_to_L2Cache(addr, m_chip_ptr->getID() );
5316285Snate@binkert.org  int l2_ver = l2_mach.num%RubyConfig::numberOfL2CachePerChip();
5326285Snate@binkert.org
5336285Snate@binkert.org  assert(n->m_L1Cache_L1IcacheMemory_vec[m_version] != NULL);
5346285Snate@binkert.org  assert(n->m_L1Cache_L1DcacheMemory_vec[m_version] != NULL);
5356285Snate@binkert.org  if (Protocol::m_TwoLevelCache) {
5366285Snate@binkert.org    if(Protocol::m_CMP){
5376285Snate@binkert.org      assert(n->m_L2Cache_L2cacheMemory_vec[l2_ver] != NULL);
5386285Snate@binkert.org    }
5396285Snate@binkert.org    else{
5406285Snate@binkert.org      assert(n->m_L1Cache_cacheMemory_vec[m_version] != NULL);
5416285Snate@binkert.org    }
5426285Snate@binkert.org  }
5436285Snate@binkert.org
5446285Snate@binkert.org  if (n->m_L1Cache_L1IcacheMemory_vec[m_version]->tryCacheAccess(lineAddr, CacheRequestType_IFETCH, dataPtr)){
5456285Snate@binkert.org    n->m_L1Cache_L1IcacheMemory_vec[m_version]->setMemoryValue(addr, value, size_in_bytes);
5466285Snate@binkert.org    found = true;
5476285Snate@binkert.org  } else if (n->m_L1Cache_L1DcacheMemory_vec[m_version]->tryCacheAccess(lineAddr, CacheRequestType_LD, dataPtr)){
5486285Snate@binkert.org    n->m_L1Cache_L1DcacheMemory_vec[m_version]->setMemoryValue(addr, value, size_in_bytes);
5496285Snate@binkert.org    found = true;
5506285Snate@binkert.org  } else if (Protocol::m_CMP && n->m_L2Cache_L2cacheMemory_vec[l2_ver]->tryCacheAccess(lineAddr, CacheRequestType_LD, dataPtr)){
5516285Snate@binkert.org    n->m_L2Cache_L2cacheMemory_vec[l2_ver]->setMemoryValue(addr, value, size_in_bytes);
5526285Snate@binkert.org    found = true;
5536285Snate@binkert.org  } else {
5546285Snate@binkert.org    // Address not found
5556285Snate@binkert.org    n = dynamic_cast<Chip*>(g_system_ptr->getChip(map_Address_to_DirectoryNode(addr)/RubyConfig::numberOfDirectoryPerChip()));
5566285Snate@binkert.org    int dir_version = map_Address_to_DirectoryNode(addr)%RubyConfig::numberOfDirectoryPerChip();
5576285Snate@binkert.org    for(unsigned int i=0; i<size_in_bytes; ++i){
5586285Snate@binkert.org      int offset = addr.getOffset();
5596285Snate@binkert.org      n->m_Directory_directory_vec[dir_version]->lookup(lineAddr).m_DataBlk.setByte(offset + i, value[i]);
5606285Snate@binkert.org    }
5616285Snate@binkert.org    found = false;
5626285Snate@binkert.org  }
5636285Snate@binkert.org
5646285Snate@binkert.org  if (found){
5656285Snate@binkert.org    found = getRubyMemoryValue(addr, test_buffer, size_in_bytes);
5666285Snate@binkert.org    assert(found);
5676285Snate@binkert.org    if(value[0] != test_buffer[0]){
5686285Snate@binkert.org      WARN_EXPR((int) value[0]);
5696285Snate@binkert.org      WARN_EXPR((int) test_buffer[0]);
5706285Snate@binkert.org      ERROR_MSG("setRubyMemoryValue failed to set value.");
5716285Snate@binkert.org    }
5726285Snate@binkert.org  }
5736285Snate@binkert.org
5746285Snate@binkert.org  return true;
5756285Snate@binkert.org}
5766285Snate@binkert.org*/
5776285Snate@binkert.org/*
5786285Snate@binkert.org
5796285Snate@binkert.orgvoid
5806285Snate@binkert.orgSequencer::rubyMemAccess(const uint64 paddr, char* data, const int len, const AccessType type)
5816285Snate@binkert.org{
5826285Snate@binkert.org  if ( type == AccessType_Read || type == AccessType_Write ) {
5836285Snate@binkert.org    // need to break up the packet data
5846285Snate@binkert.org    uint64 guest_ptr = paddr;
5856285Snate@binkert.org    Vector<DataBlock*> datablocks;
5866285Snate@binkert.org    while (paddr + len != guest_ptr) {
5876285Snate@binkert.org      Address addr(guest_ptr);
5886285Snate@binkert.org      Address line_addr = line_address(addr);
5896285Snate@binkert.org
5906285Snate@binkert.org      int bytes_copied;
5916285Snate@binkert.org      if (addr.getOffset() == 0) {
5926285Snate@binkert.org        bytes_copied = (guest_ptr + RubyConfig::dataBlockBytes() > paddr + len)?
5936285Snate@binkert.org          (paddr + len - guest_ptr):
5946285Snate@binkert.org          RubyConfig::dataBlockBytes();
5956285Snate@binkert.org      } else {
5966285Snate@binkert.org        bytes_copied = RubyConfig::dataBlockBytes() - addr.getOffset();
5976285Snate@binkert.org        if (guest_ptr + bytes_copied > paddr + len)
5986285Snate@binkert.org          bytes_copied = paddr + len - guest_ptr;
5996285Snate@binkert.org      }
6006285Snate@binkert.org
6016285Snate@binkert.org      // first we need to find all data blocks that have to be updated for a write
6026285Snate@binkert.org      // and the highest block for a read
6036285Snate@binkert.org     for(int i=0;i<RubyConfig::numberOfProcessors();i++) {
6046285Snate@binkert.org        if (Protocol::m_TwoLevelCache){
6056285Snate@binkert.org          if(m_chip_ptr->m_L1Cache_L1IcacheMemory_vec[i]->isTagPresent(line_address(addr)))
6066285Snate@binkert.org            datablocks.insertAtBottom(&m_chip_ptr->m_L1Cache_L1IcacheMemory_vec[i]->lookup(line_addr).getDataBlk());
6076285Snate@binkert.org          if(m_chip_ptr->m_L1Cache_L1DcacheMemory_vec[i]->isTagPresent(line_address(addr)))
6086285Snate@binkert.org            datablocks.insertAtBottom(&m_chip_ptr->m_L1Cache_L1DcacheMemory_vec[i]->lookup(line_addr).getDataBlk());
6096285Snate@binkert.org        } else {
6106285Snate@binkert.org          if(m_chip_ptr->m_L1Cache_cacheMemory_vec[i]->isTagPresent(line_address(addr)))
6116285Snate@binkert.org            datablocks.insertAtBottom(&m_chip_ptr->m_L1Cache_cacheMemory_vec[i]->lookup(line_addr).getDataBlk());
6126285Snate@binkert.org        }
6136285Snate@binkert.org      }
6146285Snate@binkert.org      if (Protocol::m_TwoLevelCache){
6156285Snate@binkert.org        int l2_bank = map_L2ChipId_to_L2Cache(addr, 0).num; // TODO: ONLY WORKS WITH CMP!!!
6166285Snate@binkert.org        if (m_chip_ptr->m_L2Cache_L2cacheMemory_vec[l2_bank]->isTagPresent(line_address(Address(paddr)))) {
6176285Snate@binkert.org          datablocks.insertAtBottom(&m_chip_ptr->m_L2Cache_L2cacheMemory_vec[l2_bank]->lookup(addr).getDataBlk());
6186285Snate@binkert.org        }
6196285Snate@binkert.org      }
6206285Snate@binkert.org      assert(dynamic_cast<Chip*>(m_chip_ptr)->m_Directory_directory_vec.size() > map_Address_to_DirectoryNode(addr));
6216285Snate@binkert.org      DirectoryMemory* dir = dynamic_cast<Chip*>(m_chip_ptr)->m_Directory_directory_vec[map_Address_to_DirectoryNode(addr)];
6226285Snate@binkert.org      Directory_Entry& entry = dir->lookup(line_addr);
6236285Snate@binkert.org      datablocks.insertAtBottom(&entry.getDataBlk());
6246285Snate@binkert.org
6256285Snate@binkert.org      if (pkt->isRead()){
6266285Snate@binkert.org        datablocks[0]->copyData(pkt_data, addr.getOffset(), bytes_copied);
6276285Snate@binkert.org      } else {// pkt->isWrite() {
6286285Snate@binkert.org        for (int i=0;i<datablocks.size();i++)
6296285Snate@binkert.org          datablocks[i]->setData(pkt_data, addr.getOffset(), bytes_copied);
6306285Snate@binkert.org      }
6316285Snate@binkert.org
6326285Snate@binkert.org      guest_ptr += bytes_copied;
6336285Snate@binkert.org      pkt_data += bytes_copied;
6346285Snate@binkert.org      datablocks.clear();
6356285Snate@binkert.org    }
6366145Snate@binkert.org}
6376153Sgibson@cs.wisc.edu
6386285Snate@binkert.org*/
639