Sequencer.cc revision 7023
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) ||
3377023SBrad.Beckmann@amd.com        (type == RubyRequestType_RMW_Read) ||
3387023SBrad.Beckmann@amd.com        (type == RubyRequestType_Locked_Read)) {
3397023SBrad.Beckmann@amd.com
3407023SBrad.Beckmann@amd.com        memcpy(ruby_request.data,
3417023SBrad.Beckmann@amd.com               data.getData(request_address.getOffset(), ruby_request.len),
3427023SBrad.Beckmann@amd.com               ruby_request.len);
3437023SBrad.Beckmann@amd.com
3446285Snate@binkert.org    } else {
3457023SBrad.Beckmann@amd.com
3467023SBrad.Beckmann@amd.com        data.setData(ruby_request.data,
3477023SBrad.Beckmann@amd.com                     request_address.getOffset(),
3487023SBrad.Beckmann@amd.com                     ruby_request.len);
3497023SBrad.Beckmann@amd.com
3506285Snate@binkert.org    }
3517023SBrad.Beckmann@amd.com  } else {
3527023SBrad.Beckmann@amd.com      DPRINTF(MemoryAccess,
3537023SBrad.Beckmann@amd.com              "WARNING.  Data not transfered from Ruby to M5 for type %s\n",
3547023SBrad.Beckmann@amd.com              RubyRequestType_to_string(type));
3556145Snate@binkert.org  }
3566145Snate@binkert.org
3576899SBrad.Beckmann@amd.com  //
3586899SBrad.Beckmann@amd.com  // If using the RubyTester, update the RubyTester sender state's subBlock
3596899SBrad.Beckmann@amd.com  // with the recieved data.  The tester will later access this state.
3606899SBrad.Beckmann@amd.com  // Note: RubyPort will access it's sender state before the RubyTester.
3616899SBrad.Beckmann@amd.com  //
3626899SBrad.Beckmann@amd.com  if (m_usingRubyTester) {
3636899SBrad.Beckmann@amd.com      RubyTester::SenderState* testerSenderState;
3646922SBrad.Beckmann@amd.com      testerSenderState = safe_cast<RubyTester::SenderState*>( \
3656922SBrad.Beckmann@amd.com          safe_cast<RubyPort::SenderState*>(ruby_request.pkt->senderState)->saved);
3666899SBrad.Beckmann@amd.com      testerSenderState->subBlock->mergeFrom(data);
3676899SBrad.Beckmann@amd.com  }
3686899SBrad.Beckmann@amd.com
3696922SBrad.Beckmann@amd.com  ruby_hit_callback(ruby_request.pkt);
3706285Snate@binkert.org  delete srequest;
3716285Snate@binkert.org}
3726285Snate@binkert.org
3736285Snate@binkert.org// Returns true if the sequencer already has a load or store outstanding
3746922SBrad.Beckmann@amd.comRequestStatus Sequencer::getRequestStatus(const RubyRequest& request) {
3756859Sdrh5@cs.wisc.edu  bool is_outstanding_store = m_writeRequestTable.exist(line_address(Address(request.paddr)));
3766859Sdrh5@cs.wisc.edu  bool is_outstanding_load = m_readRequestTable.exist(line_address(Address(request.paddr)));
3776859Sdrh5@cs.wisc.edu  if ( is_outstanding_store ) {
3786859Sdrh5@cs.wisc.edu    if ((request.type == RubyRequestType_LD) ||
3796859Sdrh5@cs.wisc.edu        (request.type == RubyRequestType_IFETCH) ||
3806859Sdrh5@cs.wisc.edu        (request.type == RubyRequestType_RMW_Read)) {
3816859Sdrh5@cs.wisc.edu      m_store_waiting_on_load_cycles++;
3826859Sdrh5@cs.wisc.edu    } else {
3836859Sdrh5@cs.wisc.edu      m_store_waiting_on_store_cycles++;
3846859Sdrh5@cs.wisc.edu    }
3856922SBrad.Beckmann@amd.com    return RequestStatus_Aliased;
3866859Sdrh5@cs.wisc.edu  } else if ( is_outstanding_load ) {
3876859Sdrh5@cs.wisc.edu    if ((request.type == RubyRequestType_ST) ||
3886859Sdrh5@cs.wisc.edu        (request.type == RubyRequestType_RMW_Write) ) {
3896859Sdrh5@cs.wisc.edu      m_load_waiting_on_store_cycles++;
3906859Sdrh5@cs.wisc.edu    } else {
3916859Sdrh5@cs.wisc.edu      m_load_waiting_on_load_cycles++;
3926859Sdrh5@cs.wisc.edu    }
3936922SBrad.Beckmann@amd.com    return RequestStatus_Aliased;
3946145Snate@binkert.org  }
3956145Snate@binkert.org
3966510Spdudnik@gmail.com  if (m_outstanding_count >= m_max_outstanding_requests) {
3976922SBrad.Beckmann@amd.com    return RequestStatus_BufferFull;
3986145Snate@binkert.org  }
3996845Sdrh5@cs.wisc.edu
4006922SBrad.Beckmann@amd.com  return RequestStatus_Ready;
4016145Snate@binkert.org}
4026145Snate@binkert.org
4036285Snate@binkert.orgbool Sequencer::empty() const {
4046285Snate@binkert.org  return (m_writeRequestTable.size() == 0) && (m_readRequestTable.size() == 0);
4056145Snate@binkert.org}
4066145Snate@binkert.org
4076349Spdudnik@gmail.com
4086922SBrad.Beckmann@amd.comRequestStatus Sequencer::makeRequest(const RubyRequest & request)
4096285Snate@binkert.org{
4106922SBrad.Beckmann@amd.com  assert(Address(request.paddr).getOffset() + request.len <=
4116922SBrad.Beckmann@amd.com         RubySystem::getBlockSizeBytes());
4126922SBrad.Beckmann@amd.com  RequestStatus status = getRequestStatus(request);
4136922SBrad.Beckmann@amd.com  if (status == RequestStatus_Ready) {
4146922SBrad.Beckmann@amd.com    SequencerRequest *srequest = new SequencerRequest(request,
4156922SBrad.Beckmann@amd.com                                                  g_eventQueue_ptr->getTime());
4166285Snate@binkert.org    bool found = insertRequest(srequest);
4176825Spdudnik@gmail.com    if (!found) {
4186350Spdudnik@gmail.com      if (request.type == RubyRequestType_Locked_Write) {
4197023SBrad.Beckmann@amd.com          //
4207023SBrad.Beckmann@amd.com          // NOTE: it is OK to check the locked flag here as the mandatory queue
4217023SBrad.Beckmann@amd.com          // will be checked first ensuring that nothing comes between checking
4227023SBrad.Beckmann@amd.com          // the flag and servicing the store.
4237023SBrad.Beckmann@amd.com          //
4247023SBrad.Beckmann@amd.com          if (!m_dataCache_ptr->isLocked(line_address(Address(request.paddr)),
4257023SBrad.Beckmann@amd.com                                         m_version)) {
4267023SBrad.Beckmann@amd.com              removeRequest(srequest);
4277023SBrad.Beckmann@amd.com              if (Debug::getProtocolTrace()) {
4287023SBrad.Beckmann@amd.com
4297023SBrad.Beckmann@amd.com                  g_system_ptr->getProfiler()->profileTransition("Seq",
4307023SBrad.Beckmann@amd.com                                     m_version,
4317023SBrad.Beckmann@amd.com                                     Address(request.paddr),
4327023SBrad.Beckmann@amd.com                                     "",
4337023SBrad.Beckmann@amd.com                                     "SC Fail",
4347023SBrad.Beckmann@amd.com                                     "",
4357023SBrad.Beckmann@amd.com                                     RubyRequestType_to_string(request.type));
4367023SBrad.Beckmann@amd.com
4377023SBrad.Beckmann@amd.com            }
4387023SBrad.Beckmann@amd.com            return RequestStatus_LlscFailed;
4397023SBrad.Beckmann@amd.com       }
4406349Spdudnik@gmail.com        else {
4416349Spdudnik@gmail.com          m_dataCache_ptr->clearLocked(line_address(Address(request.paddr)));
4426349Spdudnik@gmail.com        }
4436349Spdudnik@gmail.com      }
4446285Snate@binkert.org      issueRequest(request);
4456145Snate@binkert.org
4466859Sdrh5@cs.wisc.edu      // TODO: issue hardware prefetches here
4476922SBrad.Beckmann@amd.com      return RequestStatus_Issued;
4486825Spdudnik@gmail.com    }
4496825Spdudnik@gmail.com    else {
4506922SBrad.Beckmann@amd.com        panic("Sequencer::makeRequest should never be called if the request"\
4516922SBrad.Beckmann@amd.com              "is already outstanding\n");
4526922SBrad.Beckmann@amd.com        return RequestStatus_NULL;
4536825Spdudnik@gmail.com    }
4546859Sdrh5@cs.wisc.edu  } else {
4556922SBrad.Beckmann@amd.com    return status;
4566145Snate@binkert.org  }
4576145Snate@binkert.org}
4586145Snate@binkert.org
4596285Snate@binkert.orgvoid Sequencer::issueRequest(const RubyRequest& request) {
4606285Snate@binkert.org
4616285Snate@binkert.org  // TODO: get rid of CacheMsg, CacheRequestType, and AccessModeTYpe, & have SLICC use RubyRequest and subtypes natively
4626285Snate@binkert.org  CacheRequestType ctype;
4636285Snate@binkert.org  switch(request.type) {
4646285Snate@binkert.org  case RubyRequestType_IFETCH:
4656285Snate@binkert.org    ctype = CacheRequestType_IFETCH;
4666285Snate@binkert.org    break;
4676285Snate@binkert.org  case RubyRequestType_LD:
4686285Snate@binkert.org    ctype = CacheRequestType_LD;
4696285Snate@binkert.org    break;
4706285Snate@binkert.org  case RubyRequestType_ST:
4716285Snate@binkert.org    ctype = CacheRequestType_ST;
4726285Snate@binkert.org    break;
4736350Spdudnik@gmail.com  case RubyRequestType_Locked_Read:
4746350Spdudnik@gmail.com  case RubyRequestType_Locked_Write:
4756846Spdudnik@cs.wisc.edu    ctype = CacheRequestType_ATOMIC;
4766285Snate@binkert.org    break;
4776355Spdudnik@gmail.com  case RubyRequestType_RMW_Read:
4786355Spdudnik@gmail.com    ctype = CacheRequestType_ATOMIC;
4796355Spdudnik@gmail.com    break;
4806355Spdudnik@gmail.com  case RubyRequestType_RMW_Write:
4816355Spdudnik@gmail.com    ctype = CacheRequestType_ATOMIC;
4826355Spdudnik@gmail.com    break;
4836285Snate@binkert.org  default:
4846285Snate@binkert.org    assert(0);
4856145Snate@binkert.org  }
4866285Snate@binkert.org  AccessModeType amtype;
4876285Snate@binkert.org  switch(request.access_mode){
4886285Snate@binkert.org  case RubyAccessMode_User:
4896285Snate@binkert.org    amtype = AccessModeType_UserMode;
4906285Snate@binkert.org    break;
4916285Snate@binkert.org  case RubyAccessMode_Supervisor:
4926285Snate@binkert.org    amtype = AccessModeType_SupervisorMode;
4936285Snate@binkert.org    break;
4946285Snate@binkert.org  case RubyAccessMode_Device:
4956285Snate@binkert.org    amtype = AccessModeType_UserMode;
4966285Snate@binkert.org    break;
4976285Snate@binkert.org  default:
4986285Snate@binkert.org    assert(0);
4996285Snate@binkert.org  }
5006285Snate@binkert.org  Address line_addr(request.paddr);
5016285Snate@binkert.org  line_addr.makeLineAddress();
5026505Spdudnik@gmail.com  CacheMsg msg(line_addr, Address(request.paddr), ctype, Address(request.pc), amtype, request.len, PrefetchBit_No, request.proc_id);
5036285Snate@binkert.org
5046285Snate@binkert.org  if (Debug::getProtocolTrace()) {
5056285Snate@binkert.org    g_system_ptr->getProfiler()->profileTransition("Seq", m_version, Address(request.paddr),
5066285Snate@binkert.org                                                   "", "Begin", "", RubyRequestType_to_string(request.type));
5076285Snate@binkert.org  }
5086285Snate@binkert.org
5096285Snate@binkert.org  if (g_system_ptr->getTracer()->traceEnabled()) {
5106890SBrad.Beckmann@amd.com    g_system_ptr->getTracer()->traceRequest(this, line_addr, Address(request.pc),
5116285Snate@binkert.org                                            request.type, g_eventQueue_ptr->getTime());
5126285Snate@binkert.org  }
5136285Snate@binkert.org
5146285Snate@binkert.org  Time latency = 0;  // initialzed to an null value
5156285Snate@binkert.org
5166285Snate@binkert.org  if (request.type == RubyRequestType_IFETCH)
5176285Snate@binkert.org    latency = m_instCache_ptr->getLatency();
5186285Snate@binkert.org  else
5196285Snate@binkert.org    latency = m_dataCache_ptr->getLatency();
5206285Snate@binkert.org
5216285Snate@binkert.org  // Send the message to the cache controller
5226285Snate@binkert.org  assert(latency > 0);
5236285Snate@binkert.org
5246876Ssteve.reinhardt@amd.com  assert(m_mandatory_q_ptr != NULL);
5256285Snate@binkert.org  m_mandatory_q_ptr->enqueue(msg, latency);
5266285Snate@binkert.org}
5276285Snate@binkert.org/*
5286285Snate@binkert.orgbool Sequencer::tryCacheAccess(const Address& addr, CacheRequestType type,
5296285Snate@binkert.org                               AccessModeType access_mode,
5306285Snate@binkert.org                               int size, DataBlock*& data_ptr) {
5316285Snate@binkert.org  if (type == CacheRequestType_IFETCH) {
5326285Snate@binkert.org    return m_instCache_ptr->tryCacheAccess(line_address(addr), type, data_ptr);
5336285Snate@binkert.org  } else {
5346285Snate@binkert.org    return m_dataCache_ptr->tryCacheAccess(line_address(addr), type, data_ptr);
5356145Snate@binkert.org  }
5366145Snate@binkert.org}
5376285Snate@binkert.org*/
5386145Snate@binkert.org
5396145Snate@binkert.orgvoid Sequencer::print(ostream& out) const {
5406285Snate@binkert.org  out << "[Sequencer: " << m_version
5416145Snate@binkert.org      << ", outstanding requests: " << m_outstanding_count;
5426145Snate@binkert.org
5436285Snate@binkert.org  out << ", read request table: " << m_readRequestTable
5446285Snate@binkert.org      << ", write request table: " << m_writeRequestTable;
5456145Snate@binkert.org  out << "]";
5466145Snate@binkert.org}
5476145Snate@binkert.org
5486145Snate@binkert.org// this can be called from setState whenever coherence permissions are upgraded
5496145Snate@binkert.org// when invoked, coherence violations will be checked for the given block
5506145Snate@binkert.orgvoid Sequencer::checkCoherence(const Address& addr) {
5516145Snate@binkert.org#ifdef CHECK_COHERENCE
5526145Snate@binkert.org  g_system_ptr->checkGlobalCoherenceInvariant(addr);
5536145Snate@binkert.org#endif
5546145Snate@binkert.org}
5556145Snate@binkert.org
556