Sequencer.cc revision 11025
16019Shines@cs.fsu.edu/* 210037SARM gem5 Developers * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood 37414SAli.Saidi@ARM.com * All rights reserved. 47414SAli.Saidi@ARM.com * 57414SAli.Saidi@ARM.com * Redistribution and use in source and binary forms, with or without 67414SAli.Saidi@ARM.com * modification, are permitted provided that the following conditions are 77414SAli.Saidi@ARM.com * met: redistributions of source code must retain the above copyright 87414SAli.Saidi@ARM.com * notice, this list of conditions and the following disclaimer; 97414SAli.Saidi@ARM.com * redistributions in binary form must reproduce the above copyright 107414SAli.Saidi@ARM.com * notice, this list of conditions and the following disclaimer in the 117414SAli.Saidi@ARM.com * documentation and/or other materials provided with the distribution; 127414SAli.Saidi@ARM.com * neither the name of the copyright holders nor the names of its 137414SAli.Saidi@ARM.com * contributors may be used to endorse or promote products derived from 146019Shines@cs.fsu.edu * this software without specific prior written permission. 156019Shines@cs.fsu.edu * 166019Shines@cs.fsu.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 176019Shines@cs.fsu.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 186019Shines@cs.fsu.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 196019Shines@cs.fsu.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 206019Shines@cs.fsu.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 216019Shines@cs.fsu.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 226019Shines@cs.fsu.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 236019Shines@cs.fsu.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 246019Shines@cs.fsu.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 256019Shines@cs.fsu.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 266019Shines@cs.fsu.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 276019Shines@cs.fsu.edu */ 286019Shines@cs.fsu.edu 296019Shines@cs.fsu.edu#include "arch/x86/ldstflags.hh" 306019Shines@cs.fsu.edu#include "base/misc.hh" 316019Shines@cs.fsu.edu#include "base/str.hh" 326019Shines@cs.fsu.edu#include "cpu/testers/rubytest/RubyTester.hh" 336019Shines@cs.fsu.edu#include "debug/MemoryAccess.hh" 346019Shines@cs.fsu.edu#include "debug/ProtocolTrace.hh" 356019Shines@cs.fsu.edu#include "debug/RubySequencer.hh" 366019Shines@cs.fsu.edu#include "debug/RubyStats.hh" 376019Shines@cs.fsu.edu#include "mem/protocol/PrefetchBit.hh" 386019Shines@cs.fsu.edu#include "mem/protocol/RubyAccessMode.hh" 396019Shines@cs.fsu.edu#include "mem/ruby/profiler/Profiler.hh" 406019Shines@cs.fsu.edu#include "mem/ruby/slicc_interface/RubyRequest.hh" 417414SAli.Saidi@ARM.com#include "mem/ruby/system/Sequencer.hh" 426019Shines@cs.fsu.edu#include "mem/ruby/system/System.hh" 436019Shines@cs.fsu.edu#include "mem/packet.hh" 4411793Sbrandon.potter@amd.com#include "sim/system.hh" 4511793Sbrandon.potter@amd.com 466019Shines@cs.fsu.eduusing namespace std; 476019Shines@cs.fsu.edu 486019Shines@cs.fsu.eduSequencer * 496019Shines@cs.fsu.eduRubySequencerParams::create() 5012334Sgabeblack@google.com{ 516019Shines@cs.fsu.edu return new Sequencer(this); 528232Snate@binkert.org} 536019Shines@cs.fsu.edu 5412431Sgabeblack@google.comSequencer::Sequencer(const Params *p) 5511854Sbrandon.potter@amd.com : RubyPort(p), m_IncompleteTimes(MachineType_NUM), deadlockCheckEvent(this) 567678Sgblack@eecs.umich.edu{ 576019Shines@cs.fsu.edu m_outstanding_count = 0; 5811800Sbrandon.potter@amd.com 596019Shines@cs.fsu.edu m_instCache_ptr = p->icache; 606019Shines@cs.fsu.edu m_dataCache_ptr = p->dcache; 616019Shines@cs.fsu.edu m_data_cache_hit_latency = p->dcache_hit_latency; 626019Shines@cs.fsu.edu m_inst_cache_hit_latency = p->icache_hit_latency; 636019Shines@cs.fsu.edu m_max_outstanding_requests = p->max_outstanding_requests; 6411851Sbrandon.potter@amd.com m_deadlock_threshold = p->deadlock_threshold; 6511851Sbrandon.potter@amd.com 6612432Sgabeblack@google.com assert(m_max_outstanding_requests > 0); 6712432Sgabeblack@google.com assert(m_deadlock_threshold > 0); 6812431Sgabeblack@google.com assert(m_instCache_ptr != NULL); 696019Shines@cs.fsu.edu assert(m_dataCache_ptr != NULL); 7012431Sgabeblack@google.com assert(m_data_cache_hit_latency > 0); 7110037SARM gem5 Developers assert(m_inst_cache_hit_latency > 0); 7210037SARM gem5 Developers 7311851Sbrandon.potter@amd.com m_usingNetworkTester = p->using_network_tester; 7411851Sbrandon.potter@amd.com} 7511851Sbrandon.potter@amd.com 7610037SARM gem5 DevelopersSequencer::~Sequencer() 7711905SBrandon.Potter@amd.com{ 7811905SBrandon.Potter@amd.com} 7911905SBrandon.Potter@amd.com 8011905SBrandon.Potter@amd.comvoid 8111905SBrandon.Potter@amd.comSequencer::wakeup() 8211905SBrandon.Potter@amd.com{ 836019Shines@cs.fsu.edu assert(drainState() != DrainState::Draining); 8411905SBrandon.Potter@amd.com 8511905SBrandon.Potter@amd.com // Check for deadlock of any of the requests 866019Shines@cs.fsu.edu Cycles current_time = curCycle(); 876019Shines@cs.fsu.edu 8811851Sbrandon.potter@amd.com // Check across all outstanding requests 8911851Sbrandon.potter@amd.com int total_outstanding = 0; 9011851Sbrandon.potter@amd.com 9110037SARM gem5 Developers RequestTable::iterator read = m_readRequestTable.begin(); 9211905SBrandon.Potter@amd.com RequestTable::iterator read_end = m_readRequestTable.end(); 9311905SBrandon.Potter@amd.com for (; read != read_end; ++read) { 9411905SBrandon.Potter@amd.com SequencerRequest* request = read->second; 9511905SBrandon.Potter@amd.com if (current_time - request->issue_time < m_deadlock_threshold) 9611905SBrandon.Potter@amd.com continue; 9711905SBrandon.Potter@amd.com 9810037SARM gem5 Developers panic("Possible Deadlock detected. Aborting!\n" 9911905SBrandon.Potter@amd.com "version: %d request.paddr: 0x%x m_readRequestTable: %d " 10011905SBrandon.Potter@amd.com "current time: %u issue_time: %d difference: %d\n", m_version, 10110037SARM gem5 Developers request->pkt->getAddr(), m_readRequestTable.size(), 10210037SARM gem5 Developers current_time * clockPeriod(), request->issue_time * clockPeriod(), 1036019Shines@cs.fsu.edu (current_time * clockPeriod()) - (request->issue_time * clockPeriod())); 10411851Sbrandon.potter@amd.com } 1056019Shines@cs.fsu.edu 10611851Sbrandon.potter@amd.com RequestTable::iterator write = m_writeRequestTable.begin(); 10710318Sandreas.hansson@arm.com RequestTable::iterator write_end = m_writeRequestTable.end(); 1087640Sgblack@eecs.umich.edu for (; write != write_end; ++write) { 1097640Sgblack@eecs.umich.edu SequencerRequest* request = write->second; 1107640Sgblack@eecs.umich.edu if (current_time - request->issue_time < m_deadlock_threshold) 1117640Sgblack@eecs.umich.edu continue; 1127640Sgblack@eecs.umich.edu 1137640Sgblack@eecs.umich.edu panic("Possible Deadlock detected. Aborting!\n" 1147640Sgblack@eecs.umich.edu "version: %d request.paddr: 0x%x m_writeRequestTable: %d " 1157640Sgblack@eecs.umich.edu "current time: %u issue_time: %d difference: %d\n", m_version, 1167640Sgblack@eecs.umich.edu request->pkt->getAddr(), m_writeRequestTable.size(), 1177640Sgblack@eecs.umich.edu current_time * clockPeriod(), request->issue_time * clockPeriod(), 1187640Sgblack@eecs.umich.edu (current_time * clockPeriod()) - (request->issue_time * clockPeriod())); 1197640Sgblack@eecs.umich.edu } 1206019Shines@cs.fsu.edu 1216019Shines@cs.fsu.edu total_outstanding += m_writeRequestTable.size(); 1226019Shines@cs.fsu.edu total_outstanding += m_readRequestTable.size(); 12311851Sbrandon.potter@amd.com 1246019Shines@cs.fsu.edu assert(m_outstanding_count == total_outstanding); 12511851Sbrandon.potter@amd.com 12610318Sandreas.hansson@arm.com if (m_outstanding_count > 0) { 12710037SARM gem5 Developers // If there are still outstanding requests, keep checking 12810037SARM gem5 Developers schedule(deadlockCheckEvent, clockEdge(m_deadlock_threshold)); 12910037SARM gem5 Developers } 13010037SARM gem5 Developers} 13110037SARM gem5 Developers 13210037SARM gem5 Developersvoid Sequencer::resetStats() 13310037SARM gem5 Developers{ 13410037SARM gem5 Developers m_latencyHist.reset(); 13510037SARM gem5 Developers m_hitLatencyHist.reset(); 13610037SARM gem5 Developers m_missLatencyHist.reset(); 13710037SARM gem5 Developers for (int i = 0; i < RubyRequestType_NUM; i++) { 13810037SARM gem5 Developers m_typeLatencyHist[i]->reset(); 13910037SARM gem5 Developers m_hitTypeLatencyHist[i]->reset(); 14010037SARM gem5 Developers m_missTypeLatencyHist[i]->reset(); 14110037SARM gem5 Developers for (int j = 0; j < MachineType_NUM; j++) { 14210037SARM gem5 Developers m_hitTypeMachLatencyHist[i][j]->reset(); 14310037SARM gem5 Developers m_missTypeMachLatencyHist[i][j]->reset(); 14410037SARM gem5 Developers } 14510037SARM gem5 Developers } 14611851Sbrandon.potter@amd.com 14710037SARM gem5 Developers for (int i = 0; i < MachineType_NUM; i++) { 14810037SARM gem5 Developers m_missMachLatencyHist[i]->reset(); 14910037SARM gem5 Developers m_hitMachLatencyHist[i]->reset(); 15010037SARM gem5 Developers 1516400Sgblack@eecs.umich.edu m_IssueToInitialDelayHist[i]->reset(); 1526400Sgblack@eecs.umich.edu m_InitialToForwardDelayHist[i]->reset(); 1536400Sgblack@eecs.umich.edu m_ForwardToFirstResponseDelayHist[i]->reset(); 1546400Sgblack@eecs.umich.edu m_FirstResponseToCompletionDelayHist[i]->reset(); 1556400Sgblack@eecs.umich.edu 1566400Sgblack@eecs.umich.edu m_IncompleteTimes[i] = 0; 1576400Sgblack@eecs.umich.edu } 1586400Sgblack@eecs.umich.edu} 1596400Sgblack@eecs.umich.edu 1606400Sgblack@eecs.umich.eduvoid 1616400Sgblack@eecs.umich.eduSequencer::printProgress(ostream& out) const 16211389Sbrandon.potter@amd.com{ 16311389Sbrandon.potter@amd.com#if 0 16411389Sbrandon.potter@amd.com int total_demand = 0; 1656019Shines@cs.fsu.edu out << "Sequencer Stats Version " << m_version << endl; 1666019Shines@cs.fsu.edu out << "Current time = " << m_ruby_system->getTime() << endl; 1676019Shines@cs.fsu.edu out << "---------------" << endl; 1686400Sgblack@eecs.umich.edu out << "outstanding requests" << endl; 1696400Sgblack@eecs.umich.edu 1706400Sgblack@eecs.umich.edu out << "proc " << m_Read 1716400Sgblack@eecs.umich.edu << " version Requests = " << m_readRequestTable.size() << endl; 1726400Sgblack@eecs.umich.edu 1736400Sgblack@eecs.umich.edu // print the request table 1746400Sgblack@eecs.umich.edu RequestTable::iterator read = m_readRequestTable.begin(); 1756400Sgblack@eecs.umich.edu RequestTable::iterator read_end = m_readRequestTable.end(); 1766400Sgblack@eecs.umich.edu for (; read != read_end; ++read) { 1776400Sgblack@eecs.umich.edu SequencerRequest* request = read->second; 1786400Sgblack@eecs.umich.edu out << "\tRequest[ " << i << " ] = " << request->type 1797414SAli.Saidi@ARM.com << " Address " << rkeys[i] 1807414SAli.Saidi@ARM.com << " Posted " << request->issue_time 1817414SAli.Saidi@ARM.com << " PF " << PrefetchBit_No << endl; 1827414SAli.Saidi@ARM.com total_demand++; 1837414SAli.Saidi@ARM.com } 1846400Sgblack@eecs.umich.edu 1856400Sgblack@eecs.umich.edu out << "proc " << m_version 1866400Sgblack@eecs.umich.edu << " Write Requests = " << m_writeRequestTable.size << endl; 1876400Sgblack@eecs.umich.edu 1886400Sgblack@eecs.umich.edu // print the request table 1896400Sgblack@eecs.umich.edu RequestTable::iterator write = m_writeRequestTable.begin(); 1906400Sgblack@eecs.umich.edu RequestTable::iterator write_end = m_writeRequestTable.end(); 19110810Sbr@bsdpad.com for (; write != write_end; ++write) { 19210810Sbr@bsdpad.com SequencerRequest* request = write->second; 19310810Sbr@bsdpad.com out << "\tRequest[ " << i << " ] = " << request.getType() 19410810Sbr@bsdpad.com << " Address " << wkeys[i] 19510810Sbr@bsdpad.com << " Posted " << request.getTime() 19610810Sbr@bsdpad.com << " PF " << request.getPrefetch() << endl; 19710810Sbr@bsdpad.com if (request.getPrefetch() == PrefetchBit_No) { 19810810Sbr@bsdpad.com total_demand++; 19910810Sbr@bsdpad.com } 20010810Sbr@bsdpad.com } 20110810Sbr@bsdpad.com 20210810Sbr@bsdpad.com out << endl; 20310810Sbr@bsdpad.com 20410810Sbr@bsdpad.com out << "Total Number Outstanding: " << m_outstanding_count << endl 20510810Sbr@bsdpad.com << "Total Number Demand : " << total_demand << endl 20610810Sbr@bsdpad.com << "Total Number Prefetches : " << m_outstanding_count - total_demand 20710810Sbr@bsdpad.com << endl << endl << endl; 20810810Sbr@bsdpad.com#endif 20910810Sbr@bsdpad.com} 21010810Sbr@bsdpad.com 21110810Sbr@bsdpad.com// Insert the request on the correct request table. Return true if 21210810Sbr@bsdpad.com// the entry was already present. 21310810Sbr@bsdpad.comRequestStatus 21410810Sbr@bsdpad.comSequencer::insertRequest(PacketPtr pkt, RubyRequestType request_type) 21510810Sbr@bsdpad.com{ 21610810Sbr@bsdpad.com assert(m_outstanding_count == 21710810Sbr@bsdpad.com (m_writeRequestTable.size() + m_readRequestTable.size())); 21810810Sbr@bsdpad.com 21910810Sbr@bsdpad.com // See if we should schedule a deadlock check 22010810Sbr@bsdpad.com if (!deadlockCheckEvent.scheduled() && 22110810Sbr@bsdpad.com drainState() != DrainState::Draining) { 22210810Sbr@bsdpad.com schedule(deadlockCheckEvent, clockEdge(m_deadlock_threshold)); 22310810Sbr@bsdpad.com } 22410810Sbr@bsdpad.com 2256400Sgblack@eecs.umich.edu Addr line_addr = makeLineAddress(pkt->getAddr()); 22610318Sandreas.hansson@arm.com // Create a default entry, mapping the address to NULL, the cast is 2276400Sgblack@eecs.umich.edu // there to make gcc 4.4 happy 2286400Sgblack@eecs.umich.edu RequestTable::value_type default_entry(line_addr, 2296400Sgblack@eecs.umich.edu (SequencerRequest*) NULL); 2306400Sgblack@eecs.umich.edu 2316400Sgblack@eecs.umich.edu if ((request_type == RubyRequestType_ST) || 2326400Sgblack@eecs.umich.edu (request_type == RubyRequestType_RMW_Read) || 2336400Sgblack@eecs.umich.edu (request_type == RubyRequestType_RMW_Write) || 23411389Sbrandon.potter@amd.com (request_type == RubyRequestType_Load_Linked) || 23511389Sbrandon.potter@amd.com (request_type == RubyRequestType_Store_Conditional) || 23611389Sbrandon.potter@amd.com (request_type == RubyRequestType_Locked_RMW_Read) || 23711389Sbrandon.potter@amd.com (request_type == RubyRequestType_Locked_RMW_Write) || 2386400Sgblack@eecs.umich.edu (request_type == RubyRequestType_FLUSH)) { 2396400Sgblack@eecs.umich.edu 2406400Sgblack@eecs.umich.edu // Check if there is any outstanding read request for the same 2416400Sgblack@eecs.umich.edu // cache line. 2426400Sgblack@eecs.umich.edu if (m_readRequestTable.count(line_addr) > 0) { 2436400Sgblack@eecs.umich.edu m_store_waiting_on_load++; 2446400Sgblack@eecs.umich.edu return RequestStatus_Aliased; 2456400Sgblack@eecs.umich.edu } 2466400Sgblack@eecs.umich.edu 2476400Sgblack@eecs.umich.edu pair<RequestTable::iterator, bool> r = 2486400Sgblack@eecs.umich.edu m_writeRequestTable.insert(default_entry); 2496400Sgblack@eecs.umich.edu if (r.second) { 2506400Sgblack@eecs.umich.edu RequestTable::iterator i = r.first; 2516400Sgblack@eecs.umich.edu i->second = new SequencerRequest(pkt, request_type, curCycle()); 2526400Sgblack@eecs.umich.edu m_outstanding_count++; 2536400Sgblack@eecs.umich.edu } else { 2547414SAli.Saidi@ARM.com // There is an outstanding write request for the cache line 2556400Sgblack@eecs.umich.edu m_store_waiting_on_store++; 2566400Sgblack@eecs.umich.edu return RequestStatus_Aliased; 2577414SAli.Saidi@ARM.com } 2587414SAli.Saidi@ARM.com } else { 2597414SAli.Saidi@ARM.com // Check if there is any outstanding write request for the same 2606400Sgblack@eecs.umich.edu // cache line. 2616400Sgblack@eecs.umich.edu if (m_writeRequestTable.count(line_addr) > 0) { 2626400Sgblack@eecs.umich.edu m_load_waiting_on_store++; 2636400Sgblack@eecs.umich.edu return RequestStatus_Aliased; 2646400Sgblack@eecs.umich.edu } 2656400Sgblack@eecs.umich.edu 2666400Sgblack@eecs.umich.edu pair<RequestTable::iterator, bool> r = 2676400Sgblack@eecs.umich.edu m_readRequestTable.insert(default_entry); 2686400Sgblack@eecs.umich.edu 2696400Sgblack@eecs.umich.edu if (r.second) { 2706019Shines@cs.fsu.edu RequestTable::iterator i = r.first; 2716019Shines@cs.fsu.edu i->second = new SequencerRequest(pkt, request_type, curCycle()); 2726019Shines@cs.fsu.edu m_outstanding_count++; 2736019Shines@cs.fsu.edu } else { 2746400Sgblack@eecs.umich.edu // There is an outstanding read request for the cache line 2756400Sgblack@eecs.umich.edu m_load_waiting_on_load++; 2766400Sgblack@eecs.umich.edu return RequestStatus_Aliased; 2777414SAli.Saidi@ARM.com } 2786400Sgblack@eecs.umich.edu } 2796400Sgblack@eecs.umich.edu 2806400Sgblack@eecs.umich.edu m_outstandReqHist.sample(m_outstanding_count); 2816400Sgblack@eecs.umich.edu assert(m_outstanding_count == 2826400Sgblack@eecs.umich.edu (m_writeRequestTable.size() + m_readRequestTable.size())); 2836400Sgblack@eecs.umich.edu 2846400Sgblack@eecs.umich.edu return RequestStatus_Ready; 2856400Sgblack@eecs.umich.edu} 2866400Sgblack@eecs.umich.edu 2876400Sgblack@eecs.umich.eduvoid 2886400Sgblack@eecs.umich.eduSequencer::markRemoved() 2896400Sgblack@eecs.umich.edu{ 2906400Sgblack@eecs.umich.edu m_outstanding_count--; 2916400Sgblack@eecs.umich.edu assert(m_outstanding_count == 2926400Sgblack@eecs.umich.edu m_writeRequestTable.size() + m_readRequestTable.size()); 2936400Sgblack@eecs.umich.edu} 2946400Sgblack@eecs.umich.edu 2956400Sgblack@eecs.umich.eduvoid 2966400Sgblack@eecs.umich.eduSequencer::removeRequest(SequencerRequest* srequest) 2976400Sgblack@eecs.umich.edu{ 2986400Sgblack@eecs.umich.edu assert(m_outstanding_count == 2996400Sgblack@eecs.umich.edu m_writeRequestTable.size() + m_readRequestTable.size()); 3006400Sgblack@eecs.umich.edu 3016400Sgblack@eecs.umich.edu Addr line_addr = makeLineAddress(srequest->pkt->getAddr()); 3026400Sgblack@eecs.umich.edu if ((srequest->m_type == RubyRequestType_ST) || 30311905SBrandon.Potter@amd.com (srequest->m_type == RubyRequestType_RMW_Read) || 30411905SBrandon.Potter@amd.com (srequest->m_type == RubyRequestType_RMW_Write) || 30511905SBrandon.Potter@amd.com (srequest->m_type == RubyRequestType_Load_Linked) || 3066400Sgblack@eecs.umich.edu (srequest->m_type == RubyRequestType_Store_Conditional) || 3076400Sgblack@eecs.umich.edu (srequest->m_type == RubyRequestType_Locked_RMW_Read) || 30811905SBrandon.Potter@amd.com (srequest->m_type == RubyRequestType_Locked_RMW_Write)) { 30911905SBrandon.Potter@amd.com m_writeRequestTable.erase(line_addr); 3106400Sgblack@eecs.umich.edu } else { 3116400Sgblack@eecs.umich.edu m_readRequestTable.erase(line_addr); 31211905SBrandon.Potter@amd.com } 31310037SARM gem5 Developers 31410037SARM gem5 Developers markRemoved(); 31510037SARM gem5 Developers} 31610037SARM gem5 Developers 31710037SARM gem5 Developersvoid 31810037SARM gem5 DevelopersSequencer::invalidateSC(Addr address) 31910037SARM gem5 Developers{ 32010037SARM gem5 Developers RequestTable::iterator i = m_writeRequestTable.find(address); 32110037SARM gem5 Developers if (i != m_writeRequestTable.end()) { 3226400Sgblack@eecs.umich.edu SequencerRequest* request = i->second; 3236400Sgblack@eecs.umich.edu // The controller has lost the coherence permissions, hence the lock 3246400Sgblack@eecs.umich.edu // on the cache line maintained by the cache should be cleared. 3256400Sgblack@eecs.umich.edu if (request->m_type == RubyRequestType_Store_Conditional) { 3266400Sgblack@eecs.umich.edu m_dataCache_ptr->clearLocked(address); 3277414SAli.Saidi@ARM.com } 3286400Sgblack@eecs.umich.edu } 3296400Sgblack@eecs.umich.edu} 3306400Sgblack@eecs.umich.edu 3316400Sgblack@eecs.umich.edubool 3326400Sgblack@eecs.umich.eduSequencer::handleLlsc(Addr address, SequencerRequest* request) 33311905SBrandon.Potter@amd.com{ 3346400Sgblack@eecs.umich.edu // 3356400Sgblack@eecs.umich.edu // The success flag indicates whether the LLSC operation was successful. 3366400Sgblack@eecs.umich.edu // LL ops will always succeed, but SC may fail if the cache line is no 3376400Sgblack@eecs.umich.edu // longer locked. 33810037SARM gem5 Developers // 33910037SARM gem5 Developers bool success = true; 3406400Sgblack@eecs.umich.edu if (request->m_type == RubyRequestType_Store_Conditional) { 3416400Sgblack@eecs.umich.edu if (!m_dataCache_ptr->isLocked(address, m_version)) { 34210037SARM gem5 Developers // 3438852Sandreas.hansson@arm.com // For failed SC requests, indicate the failure to the cpu by 3446400Sgblack@eecs.umich.edu // setting the extra data to zero. 3456400Sgblack@eecs.umich.edu // 3466400Sgblack@eecs.umich.edu request->pkt->req->setExtraData(0); 3476400Sgblack@eecs.umich.edu success = false; 3486400Sgblack@eecs.umich.edu } else { 3496400Sgblack@eecs.umich.edu // 3508852Sandreas.hansson@arm.com // For successful SC requests, indicate the success to the cpu by 3516400Sgblack@eecs.umich.edu // setting the extra data to one. 3526400Sgblack@eecs.umich.edu // 3538852Sandreas.hansson@arm.com request->pkt->req->setExtraData(1); 3547414SAli.Saidi@ARM.com } 3557414SAli.Saidi@ARM.com // 3567414SAli.Saidi@ARM.com // Independent of success, all SC operations must clear the lock 3576400Sgblack@eecs.umich.edu // 3586019Shines@cs.fsu.edu m_dataCache_ptr->clearLocked(address); 3596019Shines@cs.fsu.edu } else if (request->m_type == RubyRequestType_Load_Linked) { 3606400Sgblack@eecs.umich.edu // 36110037SARM gem5 Developers // Note: To fully follow Alpha LLSC semantics, should the LL clear any 3628852Sandreas.hansson@arm.com // previously locked cache lines? 3636400Sgblack@eecs.umich.edu // 3648852Sandreas.hansson@arm.com m_dataCache_ptr->setLocked(address, m_version); 3656400Sgblack@eecs.umich.edu } else if ((m_dataCache_ptr->isTagPresent(address)) && 3666400Sgblack@eecs.umich.edu (m_dataCache_ptr->isLocked(address, m_version))) { 3676400Sgblack@eecs.umich.edu // 3686400Sgblack@eecs.umich.edu // Normal writes should clear the locked address 3698852Sandreas.hansson@arm.com // 3706400Sgblack@eecs.umich.edu m_dataCache_ptr->clearLocked(address); 3716019Shines@cs.fsu.edu } 3726400Sgblack@eecs.umich.edu return success; 3736400Sgblack@eecs.umich.edu} 3746019Shines@cs.fsu.edu 3758852Sandreas.hansson@arm.comvoid 3766019Shines@cs.fsu.eduSequencer::recordMissLatency(const Cycles cycles, const RubyRequestType type, 3776020Sgblack@eecs.umich.edu const MachineType respondingMach, 3786400Sgblack@eecs.umich.edu bool isExternalHit, Cycles issuedTime, 37911905SBrandon.Potter@amd.com Cycles initialRequestTime, 3806400Sgblack@eecs.umich.edu Cycles forwardRequestTime, 3816400Sgblack@eecs.umich.edu Cycles firstResponseTime, Cycles completionTime) 3826400Sgblack@eecs.umich.edu{ 3836400Sgblack@eecs.umich.edu m_latencyHist.sample(cycles); 3846400Sgblack@eecs.umich.edu m_typeLatencyHist[type]->sample(cycles); 3856400Sgblack@eecs.umich.edu 3866400Sgblack@eecs.umich.edu if (isExternalHit) { 3876400Sgblack@eecs.umich.edu m_missLatencyHist.sample(cycles); 3886400Sgblack@eecs.umich.edu m_missTypeLatencyHist[type]->sample(cycles); 3896400Sgblack@eecs.umich.edu 3906400Sgblack@eecs.umich.edu if (respondingMach != MachineType_NUM) { 3916400Sgblack@eecs.umich.edu m_missMachLatencyHist[respondingMach]->sample(cycles); 3926400Sgblack@eecs.umich.edu m_missTypeMachLatencyHist[type][respondingMach]->sample(cycles); 3936400Sgblack@eecs.umich.edu 3946400Sgblack@eecs.umich.edu if ((issuedTime <= initialRequestTime) && 3956400Sgblack@eecs.umich.edu (initialRequestTime <= forwardRequestTime) && 3966019Shines@cs.fsu.edu (forwardRequestTime <= firstResponseTime) && 3977720Sgblack@eecs.umich.edu (firstResponseTime <= completionTime)) { 3987720Sgblack@eecs.umich.edu 3997720Sgblack@eecs.umich.edu m_IssueToInitialDelayHist[respondingMach]->sample( 40010037SARM gem5 Developers initialRequestTime - issuedTime); 40110037SARM gem5 Developers m_InitialToForwardDelayHist[respondingMach]->sample( 40211389Sbrandon.potter@amd.com forwardRequestTime - initialRequestTime); 4037720Sgblack@eecs.umich.edu m_ForwardToFirstResponseDelayHist[respondingMach]->sample( 4046400Sgblack@eecs.umich.edu firstResponseTime - forwardRequestTime); 40511886Sbrandon.potter@amd.com m_FirstResponseToCompletionDelayHist[respondingMach]->sample( 40611905SBrandon.Potter@amd.com completionTime - firstResponseTime); 4076019Shines@cs.fsu.edu } else { 4086019Shines@cs.fsu.edu m_IncompleteTimes[respondingMach]++; 4096020Sgblack@eecs.umich.edu } 41011851Sbrandon.potter@amd.com } 4116020Sgblack@eecs.umich.edu } else { 4127441SAli.Saidi@ARM.com m_hitLatencyHist.sample(cycles); 4136701Sgblack@eecs.umich.edu m_hitTypeLatencyHist[type]->sample(cycles); 4146020Sgblack@eecs.umich.edu 4156020Sgblack@eecs.umich.edu if (respondingMach != MachineType_NUM) { 41610037SARM gem5 Developers m_hitMachLatencyHist[respondingMach]->sample(cycles); 41711851Sbrandon.potter@amd.com m_hitTypeMachLatencyHist[type][respondingMach]->sample(cycles); 41810037SARM gem5 Developers } 41910037SARM gem5 Developers } 42010037SARM gem5 Developers} 42110037SARM gem5 Developers 42210037SARM gem5 Developersvoid 42310037SARM gem5 DevelopersSequencer::writeCallback(Addr address, DataBlock& data, 42411851Sbrandon.potter@amd.com const bool externalHit, const MachineType mach, 4257441SAli.Saidi@ARM.com const Cycles initialRequestTime, 4267441SAli.Saidi@ARM.com const Cycles forwardRequestTime, 4277441SAli.Saidi@ARM.com const Cycles firstResponseTime) 4287441SAli.Saidi@ARM.com{ 4297441SAli.Saidi@ARM.com assert(address == makeLineAddress(address)); 4307441SAli.Saidi@ARM.com assert(m_writeRequestTable.count(makeLineAddress(address))); 4317441SAli.Saidi@ARM.com 4327441SAli.Saidi@ARM.com RequestTable::iterator i = m_writeRequestTable.find(address); 4337441SAli.Saidi@ARM.com assert(i != m_writeRequestTable.end()); 4347441SAli.Saidi@ARM.com SequencerRequest* request = i->second; 4357441SAli.Saidi@ARM.com 4367441SAli.Saidi@ARM.com m_writeRequestTable.erase(i); 4377441SAli.Saidi@ARM.com markRemoved(); 4387441SAli.Saidi@ARM.com 4397441SAli.Saidi@ARM.com assert((request->m_type == RubyRequestType_ST) || 4407441SAli.Saidi@ARM.com (request->m_type == RubyRequestType_ATOMIC) || 4417441SAli.Saidi@ARM.com (request->m_type == RubyRequestType_RMW_Read) || 44210037SARM gem5 Developers (request->m_type == RubyRequestType_RMW_Write) || 44311851Sbrandon.potter@amd.com (request->m_type == RubyRequestType_Load_Linked) || 44410037SARM gem5 Developers (request->m_type == RubyRequestType_Store_Conditional) || 44510037SARM gem5 Developers (request->m_type == RubyRequestType_Locked_RMW_Read) || 44610037SARM gem5 Developers (request->m_type == RubyRequestType_Locked_RMW_Write) || 44710037SARM gem5 Developers (request->m_type == RubyRequestType_FLUSH)); 4487441SAli.Saidi@ARM.com 4496020Sgblack@eecs.umich.edu // 45011851Sbrandon.potter@amd.com // For Alpha, properly handle LL, SC, and write requests with respect to 4516020Sgblack@eecs.umich.edu // locked cache blocks. 45210037SARM gem5 Developers // 4536020Sgblack@eecs.umich.edu // Not valid for Network_test protocl 4546020Sgblack@eecs.umich.edu // 4556020Sgblack@eecs.umich.edu bool success = true; 4566020Sgblack@eecs.umich.edu if(!m_usingNetworkTester) 45711851Sbrandon.potter@amd.com success = handleLlsc(address, request); 45810037SARM gem5 Developers 45910037SARM gem5 Developers if (request->m_type == RubyRequestType_Locked_RMW_Read) { 46010037SARM gem5 Developers m_controller->blockOnQueue(address, m_mandatory_q_ptr); 46110037SARM gem5 Developers } else if (request->m_type == RubyRequestType_Locked_RMW_Write) { 46210037SARM gem5 Developers m_controller->unblock(address); 46310037SARM gem5 Developers } 46411851Sbrandon.potter@amd.com 4656020Sgblack@eecs.umich.edu hitCallback(request, data, success, mach, externalHit, 46610810Sbr@bsdpad.com initialRequestTime, forwardRequestTime, firstResponseTime); 46710810Sbr@bsdpad.com} 46810810Sbr@bsdpad.com 46910810Sbr@bsdpad.comvoid 47010810Sbr@bsdpad.comSequencer::readCallback(Addr address, DataBlock& data, 47110810Sbr@bsdpad.com bool externalHit, const MachineType mach, 47210810Sbr@bsdpad.com Cycles initialRequestTime, 47310810Sbr@bsdpad.com Cycles forwardRequestTime, 47410810Sbr@bsdpad.com Cycles firstResponseTime) 47510810Sbr@bsdpad.com{ 47610810Sbr@bsdpad.com assert(address == makeLineAddress(address)); 47710223Ssteve.reinhardt@amd.com assert(m_readRequestTable.count(makeLineAddress(address))); 4786020Sgblack@eecs.umich.edu 47910037SARM gem5 Developers RequestTable::iterator i = m_readRequestTable.find(address); 48010037SARM gem5 Developers assert(i != m_readRequestTable.end()); 48111851Sbrandon.potter@amd.com SequencerRequest* request = i->second; 48210037SARM gem5 Developers 48310810Sbr@bsdpad.com m_readRequestTable.erase(i); 48410810Sbr@bsdpad.com markRemoved(); 48510810Sbr@bsdpad.com 48610810Sbr@bsdpad.com assert((request->m_type == RubyRequestType_LD) || 48710810Sbr@bsdpad.com (request->m_type == RubyRequestType_IFETCH)); 48810810Sbr@bsdpad.com 48910810Sbr@bsdpad.com hitCallback(request, data, true, mach, externalHit, 49010810Sbr@bsdpad.com initialRequestTime, forwardRequestTime, firstResponseTime); 49110810Sbr@bsdpad.com} 49210810Sbr@bsdpad.com 49310810Sbr@bsdpad.comvoid 49410223Ssteve.reinhardt@amd.comSequencer::hitCallback(SequencerRequest* srequest, DataBlock& data, 49510037SARM gem5 Developers bool llscSuccess, 496 const MachineType mach, const bool externalHit, 497 const Cycles initialRequestTime, 498 const Cycles forwardRequestTime, 499 const Cycles firstResponseTime) 500{ 501 PacketPtr pkt = srequest->pkt; 502 Addr request_address(pkt->getAddr()); 503 Addr request_line_address = makeLineAddress(pkt->getAddr()); 504 RubyRequestType type = srequest->m_type; 505 Cycles issued_time = srequest->issue_time; 506 507 // Set this cache entry to the most recently used 508 if (type == RubyRequestType_IFETCH) { 509 m_instCache_ptr->setMRU(request_line_address); 510 } else { 511 m_dataCache_ptr->setMRU(request_line_address); 512 } 513 514 assert(curCycle() >= issued_time); 515 Cycles total_latency = curCycle() - issued_time; 516 517 // Profile the latency for all demand accesses. 518 recordMissLatency(total_latency, type, mach, externalHit, issued_time, 519 initialRequestTime, forwardRequestTime, 520 firstResponseTime, curCycle()); 521 522 DPRINTFR(ProtocolTrace, "%15s %3s %10s%20s %6s>%-6s %#x %d cycles\n", 523 curTick(), m_version, "Seq", 524 llscSuccess ? "Done" : "SC_Failed", "", "", 525 request_address, total_latency); 526 527 // update the data unless it is a non-data-carrying flush 528 if (RubySystem::getWarmupEnabled()) { 529 data.setData(pkt->getConstPtr<uint8_t>(), 530 getOffset(request_address), pkt->getSize()); 531 } else if (!pkt->isFlush()) { 532 if ((type == RubyRequestType_LD) || 533 (type == RubyRequestType_IFETCH) || 534 (type == RubyRequestType_RMW_Read) || 535 (type == RubyRequestType_Locked_RMW_Read) || 536 (type == RubyRequestType_Load_Linked)) { 537 memcpy(pkt->getPtr<uint8_t>(), 538 data.getData(getOffset(request_address), pkt->getSize()), 539 pkt->getSize()); 540 DPRINTF(RubySequencer, "read data %s\n", data); 541 } else { 542 data.setData(pkt->getConstPtr<uint8_t>(), 543 getOffset(request_address), pkt->getSize()); 544 DPRINTF(RubySequencer, "set data %s\n", data); 545 } 546 } 547 548 // If using the RubyTester, update the RubyTester sender state's 549 // subBlock with the recieved data. The tester will later access 550 // this state. 551 if (m_usingRubyTester) { 552 DPRINTF(RubySequencer, "hitCallback %s 0x%x using RubyTester\n", 553 pkt->cmdString(), pkt->getAddr()); 554 RubyTester::SenderState* testerSenderState = 555 pkt->findNextSenderState<RubyTester::SenderState>(); 556 assert(testerSenderState); 557 testerSenderState->subBlock.mergeFrom(data); 558 } 559 560 delete srequest; 561 562 RubySystem *rs = m_ruby_system; 563 if (RubySystem::getWarmupEnabled()) { 564 assert(pkt->req); 565 delete pkt->req; 566 delete pkt; 567 rs->m_cache_recorder->enqueueNextFetchRequest(); 568 } else if (RubySystem::getCooldownEnabled()) { 569 delete pkt; 570 rs->m_cache_recorder->enqueueNextFlushRequest(); 571 } else { 572 ruby_hit_callback(pkt); 573 } 574} 575 576bool 577Sequencer::empty() const 578{ 579 return m_writeRequestTable.empty() && m_readRequestTable.empty(); 580} 581 582RequestStatus 583Sequencer::makeRequest(PacketPtr pkt) 584{ 585 if (m_outstanding_count >= m_max_outstanding_requests) { 586 return RequestStatus_BufferFull; 587 } 588 589 RubyRequestType primary_type = RubyRequestType_NULL; 590 RubyRequestType secondary_type = RubyRequestType_NULL; 591 592 if (pkt->isLLSC()) { 593 // 594 // Alpha LL/SC instructions need to be handled carefully by the cache 595 // coherence protocol to ensure they follow the proper semantics. In 596 // particular, by identifying the operations as atomic, the protocol 597 // should understand that migratory sharing optimizations should not 598 // be performed (i.e. a load between the LL and SC should not steal 599 // away exclusive permission). 600 // 601 if (pkt->isWrite()) { 602 DPRINTF(RubySequencer, "Issuing SC\n"); 603 primary_type = RubyRequestType_Store_Conditional; 604 } else { 605 DPRINTF(RubySequencer, "Issuing LL\n"); 606 assert(pkt->isRead()); 607 primary_type = RubyRequestType_Load_Linked; 608 } 609 secondary_type = RubyRequestType_ATOMIC; 610 } else if (pkt->req->isLockedRMW()) { 611 // 612 // x86 locked instructions are translated to store cache coherence 613 // requests because these requests should always be treated as read 614 // exclusive operations and should leverage any migratory sharing 615 // optimization built into the protocol. 616 // 617 if (pkt->isWrite()) { 618 DPRINTF(RubySequencer, "Issuing Locked RMW Write\n"); 619 primary_type = RubyRequestType_Locked_RMW_Write; 620 } else { 621 DPRINTF(RubySequencer, "Issuing Locked RMW Read\n"); 622 assert(pkt->isRead()); 623 primary_type = RubyRequestType_Locked_RMW_Read; 624 } 625 secondary_type = RubyRequestType_ST; 626 } else { 627 if (pkt->isRead()) { 628 if (pkt->req->isInstFetch()) { 629 primary_type = secondary_type = RubyRequestType_IFETCH; 630 } else { 631 bool storeCheck = false; 632 // only X86 need the store check 633 if (system->getArch() == Arch::X86ISA) { 634 uint32_t flags = pkt->req->getFlags(); 635 storeCheck = flags & 636 (X86ISA::StoreCheck << X86ISA::FlagShift); 637 } 638 if (storeCheck) { 639 primary_type = RubyRequestType_RMW_Read; 640 secondary_type = RubyRequestType_ST; 641 } else { 642 primary_type = secondary_type = RubyRequestType_LD; 643 } 644 } 645 } else if (pkt->isWrite()) { 646 // 647 // Note: M5 packets do not differentiate ST from RMW_Write 648 // 649 primary_type = secondary_type = RubyRequestType_ST; 650 } else if (pkt->isFlush()) { 651 primary_type = secondary_type = RubyRequestType_FLUSH; 652 } else { 653 panic("Unsupported ruby packet type\n"); 654 } 655 } 656 657 RequestStatus status = insertRequest(pkt, primary_type); 658 if (status != RequestStatus_Ready) 659 return status; 660 661 issueRequest(pkt, secondary_type); 662 663 // TODO: issue hardware prefetches here 664 return RequestStatus_Issued; 665} 666 667void 668Sequencer::issueRequest(PacketPtr pkt, RubyRequestType secondary_type) 669{ 670 assert(pkt != NULL); 671 ContextID proc_id = pkt->req->hasContextId() ? 672 pkt->req->contextId() : InvalidContextID; 673 674 // If valid, copy the pc to the ruby request 675 Addr pc = 0; 676 if (pkt->req->hasPC()) { 677 pc = pkt->req->getPC(); 678 } 679 680 // check if the packet has data as for example prefetch and flush 681 // requests do not 682 std::shared_ptr<RubyRequest> msg = 683 std::make_shared<RubyRequest>(clockEdge(), pkt->getAddr(), 684 pkt->isFlush() ? 685 nullptr : pkt->getPtr<uint8_t>(), 686 pkt->getSize(), pc, secondary_type, 687 RubyAccessMode_Supervisor, pkt, 688 PrefetchBit_No, proc_id); 689 690 DPRINTFR(ProtocolTrace, "%15s %3s %10s%20s %6s>%-6s %#x %s\n", 691 curTick(), m_version, "Seq", "Begin", "", "", 692 msg->getPhysicalAddress(), 693 RubyRequestType_to_string(secondary_type)); 694 695 // The Sequencer currently assesses instruction and data cache hit latency 696 // for the top-level caches at the beginning of a memory access. 697 // TODO: Eventually, this latency should be moved to represent the actual 698 // cache access latency portion of the memory access. This will require 699 // changing cache controller protocol files to assess the latency on the 700 // access response path. 701 Cycles latency(0); // Initialize to zero to catch misconfigured latency 702 if (secondary_type == RubyRequestType_IFETCH) 703 latency = m_inst_cache_hit_latency; 704 else 705 latency = m_data_cache_hit_latency; 706 707 // Send the message to the cache controller 708 assert(latency > 0); 709 710 assert(m_mandatory_q_ptr != NULL); 711 m_mandatory_q_ptr->enqueue(msg, latency); 712} 713 714template <class KEY, class VALUE> 715std::ostream & 716operator<<(ostream &out, const m5::hash_map<KEY, VALUE> &map) 717{ 718 typename m5::hash_map<KEY, VALUE>::const_iterator i = map.begin(); 719 typename m5::hash_map<KEY, VALUE>::const_iterator end = map.end(); 720 721 out << "["; 722 for (; i != end; ++i) 723 out << " " << i->first << "=" << i->second; 724 out << " ]"; 725 726 return out; 727} 728 729void 730Sequencer::print(ostream& out) const 731{ 732 out << "[Sequencer: " << m_version 733 << ", outstanding requests: " << m_outstanding_count 734 << ", read request table: " << m_readRequestTable 735 << ", write request table: " << m_writeRequestTable 736 << "]"; 737} 738 739// this can be called from setState whenever coherence permissions are 740// upgraded when invoked, coherence violations will be checked for the 741// given block 742void 743Sequencer::checkCoherence(Addr addr) 744{ 745#ifdef CHECK_COHERENCE 746 m_ruby_system->checkGlobalCoherenceInvariant(addr); 747#endif 748} 749 750void 751Sequencer::recordRequestType(SequencerRequestType requestType) { 752 DPRINTF(RubyStats, "Recorded statistic: %s\n", 753 SequencerRequestType_to_string(requestType)); 754} 755 756 757void 758Sequencer::evictionCallback(Addr address) 759{ 760 ruby_eviction_callback(address); 761} 762 763void 764Sequencer::regStats() 765{ 766 m_store_waiting_on_load 767 .name(name() + ".store_waiting_on_load") 768 .desc("Number of times a store aliased with a pending load") 769 .flags(Stats::nozero); 770 m_store_waiting_on_store 771 .name(name() + ".store_waiting_on_store") 772 .desc("Number of times a store aliased with a pending store") 773 .flags(Stats::nozero); 774 m_load_waiting_on_load 775 .name(name() + ".load_waiting_on_load") 776 .desc("Number of times a load aliased with a pending load") 777 .flags(Stats::nozero); 778 m_load_waiting_on_store 779 .name(name() + ".load_waiting_on_store") 780 .desc("Number of times a load aliased with a pending store") 781 .flags(Stats::nozero); 782 783 // These statistical variables are not for display. 784 // The profiler will collate these across different 785 // sequencers and display those collated statistics. 786 m_outstandReqHist.init(10); 787 m_latencyHist.init(10); 788 m_hitLatencyHist.init(10); 789 m_missLatencyHist.init(10); 790 791 for (int i = 0; i < RubyRequestType_NUM; i++) { 792 m_typeLatencyHist.push_back(new Stats::Histogram()); 793 m_typeLatencyHist[i]->init(10); 794 795 m_hitTypeLatencyHist.push_back(new Stats::Histogram()); 796 m_hitTypeLatencyHist[i]->init(10); 797 798 m_missTypeLatencyHist.push_back(new Stats::Histogram()); 799 m_missTypeLatencyHist[i]->init(10); 800 } 801 802 for (int i = 0; i < MachineType_NUM; i++) { 803 m_hitMachLatencyHist.push_back(new Stats::Histogram()); 804 m_hitMachLatencyHist[i]->init(10); 805 806 m_missMachLatencyHist.push_back(new Stats::Histogram()); 807 m_missMachLatencyHist[i]->init(10); 808 809 m_IssueToInitialDelayHist.push_back(new Stats::Histogram()); 810 m_IssueToInitialDelayHist[i]->init(10); 811 812 m_InitialToForwardDelayHist.push_back(new Stats::Histogram()); 813 m_InitialToForwardDelayHist[i]->init(10); 814 815 m_ForwardToFirstResponseDelayHist.push_back(new Stats::Histogram()); 816 m_ForwardToFirstResponseDelayHist[i]->init(10); 817 818 m_FirstResponseToCompletionDelayHist.push_back(new Stats::Histogram()); 819 m_FirstResponseToCompletionDelayHist[i]->init(10); 820 } 821 822 for (int i = 0; i < RubyRequestType_NUM; i++) { 823 m_hitTypeMachLatencyHist.push_back(std::vector<Stats::Histogram *>()); 824 m_missTypeMachLatencyHist.push_back(std::vector<Stats::Histogram *>()); 825 826 for (int j = 0; j < MachineType_NUM; j++) { 827 m_hitTypeMachLatencyHist[i].push_back(new Stats::Histogram()); 828 m_hitTypeMachLatencyHist[i][j]->init(10); 829 830 m_missTypeMachLatencyHist[i].push_back(new Stats::Histogram()); 831 m_missTypeMachLatencyHist[i][j]->init(10); 832 } 833 } 834} 835