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