AddressProfiler.cc revision 6896
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
306145Snate@binkert.org/*
316284Snate@binkert.org * AddressProfiler.cc
326145Snate@binkert.org *
336284Snate@binkert.org * Description: See AddressProfiler.hh
346145Snate@binkert.org *
356145Snate@binkert.org * $Id$
366145Snate@binkert.org *
376145Snate@binkert.org */
386145Snate@binkert.org
396154Snate@binkert.org#include "mem/ruby/profiler/AddressProfiler.hh"
406154Snate@binkert.org#include "mem/protocol/CacheMsg.hh"
416154Snate@binkert.org#include "mem/ruby/profiler/AccessTraceForAddress.hh"
426154Snate@binkert.org#include "mem/gems_common/PrioHeap.hh"
436154Snate@binkert.org#include "mem/gems_common/Map.hh"
446154Snate@binkert.org#include "mem/ruby/system/System.hh"
456154Snate@binkert.org#include "mem/ruby/profiler/Profiler.hh"
466145Snate@binkert.org
476145Snate@binkert.org// Helper functions
486896SBrad.Beckmann@amd.comstatic AccessTraceForAddress& lookupTraceForAddress(const Address& addr,
496896SBrad.Beckmann@amd.com                                                    Map<Address,
506896SBrad.Beckmann@amd.com                                                    AccessTraceForAddress>* record_map);
516145Snate@binkert.org
526896SBrad.Beckmann@amd.comstatic void printSorted(ostream& out,
536896SBrad.Beckmann@amd.com                        int num_of_sequencers,
546896SBrad.Beckmann@amd.com                        const Map<Address, AccessTraceForAddress>* record_map,
556896SBrad.Beckmann@amd.com                        string description);
566896SBrad.Beckmann@amd.com
576896SBrad.Beckmann@amd.comAddressProfiler::AddressProfiler(int num_of_sequencers)
586145Snate@binkert.org{
596145Snate@binkert.org  m_dataAccessTrace = new Map<Address, AccessTraceForAddress>;
606145Snate@binkert.org  m_macroBlockAccessTrace = new Map<Address, AccessTraceForAddress>;
616145Snate@binkert.org  m_programCounterAccessTrace = new Map<Address, AccessTraceForAddress>;
626145Snate@binkert.org  m_retryProfileMap = new Map<Address, AccessTraceForAddress>;
636896SBrad.Beckmann@amd.com  m_num_of_sequencers = num_of_sequencers;
646145Snate@binkert.org  clearStats();
656145Snate@binkert.org}
666145Snate@binkert.org
676145Snate@binkert.orgAddressProfiler::~AddressProfiler()
686145Snate@binkert.org{
696145Snate@binkert.org  delete m_dataAccessTrace;
706145Snate@binkert.org  delete m_macroBlockAccessTrace;
716145Snate@binkert.org  delete m_programCounterAccessTrace;
726145Snate@binkert.org  delete m_retryProfileMap;
736145Snate@binkert.org}
746145Snate@binkert.org
756285Snate@binkert.orgvoid AddressProfiler::setHotLines(bool hot_lines){
766285Snate@binkert.org  m_hot_lines = hot_lines;
776285Snate@binkert.org}
786285Snate@binkert.orgvoid AddressProfiler::setAllInstructions(bool all_instructions){
796285Snate@binkert.org  m_all_instructions = all_instructions;
806285Snate@binkert.org}
816285Snate@binkert.org
826145Snate@binkert.orgvoid AddressProfiler::printStats(ostream& out) const
836145Snate@binkert.org{
846285Snate@binkert.org  if (m_hot_lines) {
856145Snate@binkert.org    out << endl;
866145Snate@binkert.org    out << "AddressProfiler Stats" << endl;
876145Snate@binkert.org    out << "---------------------" << endl;
886145Snate@binkert.org
896145Snate@binkert.org    out << endl;
906145Snate@binkert.org    out << "sharing_misses: " << m_sharing_miss_counter << endl;
916145Snate@binkert.org    out << "getx_sharing_histogram: " << m_getx_sharing_histogram << endl;
926145Snate@binkert.org    out << "gets_sharing_histogram: " << m_gets_sharing_histogram << endl;
936145Snate@binkert.org
946145Snate@binkert.org    out << endl;
956145Snate@binkert.org    out << "Hot Data Blocks" << endl;
966145Snate@binkert.org    out << "---------------" << endl;
976145Snate@binkert.org    out << endl;
986896SBrad.Beckmann@amd.com    printSorted(out, m_num_of_sequencers, m_dataAccessTrace, "block_address");
996145Snate@binkert.org
1006145Snate@binkert.org    out << endl;
1016145Snate@binkert.org    out << "Hot MacroData Blocks" << endl;
1026145Snate@binkert.org    out << "--------------------" << endl;
1036145Snate@binkert.org    out << endl;
1046896SBrad.Beckmann@amd.com    printSorted(out, m_num_of_sequencers, m_macroBlockAccessTrace, "macroblock_address");
1056145Snate@binkert.org
1066145Snate@binkert.org    out << "Hot Instructions" << endl;
1076145Snate@binkert.org    out << "----------------" << endl;
1086145Snate@binkert.org    out << endl;
1096896SBrad.Beckmann@amd.com    printSorted(out, m_num_of_sequencers, m_programCounterAccessTrace, "pc_address");
1106145Snate@binkert.org  }
1116145Snate@binkert.org
1126285Snate@binkert.org  if (m_all_instructions){
1136145Snate@binkert.org    out << endl;
1146145Snate@binkert.org    out << "All Instructions Profile:" << endl;
1156145Snate@binkert.org    out << "-------------------------" << endl;
1166145Snate@binkert.org    out << endl;
1176896SBrad.Beckmann@amd.com    printSorted(out, m_num_of_sequencers, m_programCounterAccessTrace, "pc_address");
1186145Snate@binkert.org    out << endl;
1196145Snate@binkert.org  }
1206145Snate@binkert.org
1216145Snate@binkert.org  if (m_retryProfileHisto.size() > 0) {
1226145Snate@binkert.org    out << "Retry Profile" << endl;
1236145Snate@binkert.org    out << "-------------" << endl;
1246145Snate@binkert.org    out << endl;
1256145Snate@binkert.org    out << "retry_histogram_absolute: " << m_retryProfileHisto << endl;
1266145Snate@binkert.org    out << "retry_histogram_write: " << m_retryProfileHistoWrite << endl;
1276145Snate@binkert.org    out << "retry_histogram_read: " << m_retryProfileHistoRead << endl;
1286145Snate@binkert.org
1296145Snate@binkert.org    out << "retry_histogram_percent: ";
1306145Snate@binkert.org    m_retryProfileHisto.printPercent(out);
1316145Snate@binkert.org    out << endl;
1326145Snate@binkert.org
1336896SBrad.Beckmann@amd.com    printSorted(out, m_num_of_sequencers, m_retryProfileMap, "block_address");
1346145Snate@binkert.org    out << endl;
1356145Snate@binkert.org  }
1366145Snate@binkert.org
1376145Snate@binkert.org}
1386145Snate@binkert.org
1396145Snate@binkert.orgvoid AddressProfiler::clearStats()
1406145Snate@binkert.org{
1416145Snate@binkert.org  // Clear the maps
1426145Snate@binkert.org  m_sharing_miss_counter = 0;
1436145Snate@binkert.org  m_dataAccessTrace->clear();
1446145Snate@binkert.org  m_macroBlockAccessTrace->clear();
1456145Snate@binkert.org  m_programCounterAccessTrace->clear();
1466145Snate@binkert.org  m_retryProfileMap->clear();
1476145Snate@binkert.org  m_retryProfileHisto.clear();
1486145Snate@binkert.org  m_retryProfileHistoRead.clear();
1496145Snate@binkert.org  m_retryProfileHistoWrite.clear();
1506145Snate@binkert.org  m_getx_sharing_histogram.clear();
1516145Snate@binkert.org  m_gets_sharing_histogram.clear();
1526145Snate@binkert.org}
1536145Snate@binkert.org
1546145Snate@binkert.orgvoid AddressProfiler::profileGetX(const Address& datablock, const Address& PC, const Set& owner, const Set& sharers, NodeID requestor)
1556145Snate@binkert.org{
1566145Snate@binkert.org  Set indirection_set;
1576145Snate@binkert.org  indirection_set.addSet(sharers);
1586145Snate@binkert.org  indirection_set.addSet(owner);
1596145Snate@binkert.org  indirection_set.remove(requestor);
1606145Snate@binkert.org  int num_indirections = indirection_set.count();
1616145Snate@binkert.org
1626145Snate@binkert.org  m_getx_sharing_histogram.add(num_indirections);
1636145Snate@binkert.org  bool indirection_miss = (num_indirections > 0);
1646145Snate@binkert.org
1656145Snate@binkert.org  addTraceSample(datablock, PC, CacheRequestType_ST, AccessModeType(0), requestor, indirection_miss);
1666145Snate@binkert.org}
1676145Snate@binkert.org
1686145Snate@binkert.orgvoid AddressProfiler::profileGetS(const Address& datablock, const Address& PC, const Set& owner, const Set& sharers, NodeID requestor)
1696145Snate@binkert.org{
1706145Snate@binkert.org  Set indirection_set;
1716145Snate@binkert.org  indirection_set.addSet(owner);
1726145Snate@binkert.org  indirection_set.remove(requestor);
1736145Snate@binkert.org  int num_indirections = indirection_set.count();
1746145Snate@binkert.org
1756145Snate@binkert.org  m_gets_sharing_histogram.add(num_indirections);
1766145Snate@binkert.org  bool indirection_miss = (num_indirections > 0);
1776145Snate@binkert.org
1786145Snate@binkert.org  addTraceSample(datablock, PC, CacheRequestType_LD, AccessModeType(0), requestor, indirection_miss);
1796145Snate@binkert.org}
1806145Snate@binkert.org
1816145Snate@binkert.orgvoid AddressProfiler::addTraceSample(Address data_addr, Address pc_addr, CacheRequestType type, AccessModeType access_mode, NodeID id, bool sharing_miss)
1826145Snate@binkert.org{
1836285Snate@binkert.org  if (m_all_instructions) {
1846145Snate@binkert.org    if (sharing_miss) {
1856145Snate@binkert.org      m_sharing_miss_counter++;
1866145Snate@binkert.org    }
1876145Snate@binkert.org
1886145Snate@binkert.org    // record data address trace info
1896145Snate@binkert.org    data_addr.makeLineAddress();
1906145Snate@binkert.org    lookupTraceForAddress(data_addr, m_dataAccessTrace).update(type, access_mode, id, sharing_miss);
1916145Snate@binkert.org
1926145Snate@binkert.org    // record macro data address trace info
1936145Snate@binkert.org    Address macro_addr(data_addr.maskLowOrderBits(10)); // 6 for datablock, 4 to make it 16x more coarse
1946145Snate@binkert.org    lookupTraceForAddress(macro_addr, m_macroBlockAccessTrace).update(type, access_mode, id, sharing_miss);
1956145Snate@binkert.org
1966145Snate@binkert.org    // record program counter address trace info
1976145Snate@binkert.org    lookupTraceForAddress(pc_addr, m_programCounterAccessTrace).update(type, access_mode, id, sharing_miss);
1986145Snate@binkert.org  }
1996145Snate@binkert.org
2006285Snate@binkert.org  if (m_all_instructions) {
2016145Snate@binkert.org    // This code is used if the address profiler is an all-instructions profiler
2026145Snate@binkert.org    // record program counter address trace info
2036145Snate@binkert.org    lookupTraceForAddress(pc_addr, m_programCounterAccessTrace).update(type, access_mode, id, sharing_miss);
2046145Snate@binkert.org  }
2056145Snate@binkert.org}
2066145Snate@binkert.org
2076145Snate@binkert.orgvoid AddressProfiler::profileRetry(const Address& data_addr, AccessType type, int count)
2086145Snate@binkert.org{
2096145Snate@binkert.org  m_retryProfileHisto.add(count);
2106145Snate@binkert.org  if (type == AccessType_Read) {
2116145Snate@binkert.org    m_retryProfileHistoRead.add(count);
2126145Snate@binkert.org  } else {
2136145Snate@binkert.org    m_retryProfileHistoWrite.add(count);
2146145Snate@binkert.org  }
2156145Snate@binkert.org  if (count > 1) {
2166145Snate@binkert.org    lookupTraceForAddress(data_addr, m_retryProfileMap).addSample(count);
2176145Snate@binkert.org  }
2186145Snate@binkert.org}
2196145Snate@binkert.org
2206145Snate@binkert.org// ***** Normal Functions ******
2216145Snate@binkert.org
2226896SBrad.Beckmann@amd.comstatic void printSorted(ostream& out,
2236896SBrad.Beckmann@amd.com                        int num_of_sequencers,
2246896SBrad.Beckmann@amd.com                        const Map<Address, AccessTraceForAddress>* record_map,
2256896SBrad.Beckmann@amd.com                        string description)
2266145Snate@binkert.org{
2276145Snate@binkert.org  const int records_printed = 100;
2286145Snate@binkert.org
2296145Snate@binkert.org  uint64 misses = 0;
2306145Snate@binkert.org  PrioHeap<AccessTraceForAddress*> heap;
2316145Snate@binkert.org  Vector<Address> keys = record_map->keys();
2326145Snate@binkert.org  for(int i=0; i<keys.size(); i++){
2336145Snate@binkert.org    AccessTraceForAddress* record = &(record_map->lookup(keys[i]));
2346145Snate@binkert.org    misses += record->getTotal();
2356145Snate@binkert.org    heap.insert(record);
2366145Snate@binkert.org  }
2376145Snate@binkert.org
2386145Snate@binkert.org  out << "Total_entries_" << description << ": " << keys.size() << endl;
2396285Snate@binkert.org  if (g_system_ptr->getProfiler()->getAllInstructions())
2406145Snate@binkert.org    out << "Total_Instructions_" << description << ": " << misses << endl;
2416145Snate@binkert.org  else
2426145Snate@binkert.org    out << "Total_data_misses_" << description << ": " << misses << endl;
2436145Snate@binkert.org
2446145Snate@binkert.org  out << "total | load store atomic | user supervisor | sharing | touched-by" << endl;
2456145Snate@binkert.org
2466145Snate@binkert.org  Histogram remaining_records(1, 100);
2476145Snate@binkert.org  Histogram all_records(1, 100);
2486145Snate@binkert.org  Histogram remaining_records_log(-1);
2496145Snate@binkert.org  Histogram all_records_log(-1);
2506145Snate@binkert.org
2516145Snate@binkert.org  // Allows us to track how many lines where touched by n processors
2526145Snate@binkert.org  Vector<int64> m_touched_vec;
2536145Snate@binkert.org  Vector<int64> m_touched_weighted_vec;
2546896SBrad.Beckmann@amd.com  m_touched_vec.setSize(num_of_sequencers+1);
2556896SBrad.Beckmann@amd.com  m_touched_weighted_vec.setSize(num_of_sequencers+1);
2566145Snate@binkert.org  for (int i=0; i<m_touched_vec.size(); i++) {
2576145Snate@binkert.org    m_touched_vec[i] = 0;
2586145Snate@binkert.org    m_touched_weighted_vec[i] = 0;
2596145Snate@binkert.org  }
2606145Snate@binkert.org
2616145Snate@binkert.org  int counter = 0;
2626145Snate@binkert.org  while((heap.size() > 0) && (counter < records_printed)) {
2636145Snate@binkert.org    AccessTraceForAddress* record = heap.extractMin();
2646145Snate@binkert.org    double percent = 100.0*(record->getTotal()/double(misses));
2656145Snate@binkert.org    out << description << " | " << percent << " % " << *record << endl;
2666145Snate@binkert.org    all_records.add(record->getTotal());
2676145Snate@binkert.org    all_records_log.add(record->getTotal());
2686145Snate@binkert.org    counter++;
2696145Snate@binkert.org    m_touched_vec[record->getTouchedBy()]++;
2706145Snate@binkert.org    m_touched_weighted_vec[record->getTouchedBy()] += record->getTotal();
2716145Snate@binkert.org  }
2726145Snate@binkert.org
2736145Snate@binkert.org  while(heap.size() > 0) {
2746145Snate@binkert.org    AccessTraceForAddress* record = heap.extractMin();
2756145Snate@binkert.org    all_records.add(record->getTotal());
2766145Snate@binkert.org    remaining_records.add(record->getTotal());
2776145Snate@binkert.org    all_records_log.add(record->getTotal());
2786145Snate@binkert.org    remaining_records_log.add(record->getTotal());
2796145Snate@binkert.org    m_touched_vec[record->getTouchedBy()]++;
2806145Snate@binkert.org    m_touched_weighted_vec[record->getTouchedBy()] += record->getTotal();
2816145Snate@binkert.org  }
2826145Snate@binkert.org  out << endl;
2836145Snate@binkert.org  out << "all_records_" << description << ": " << all_records << endl;
2846145Snate@binkert.org  out << "all_records_log_" << description << ": " << all_records_log << endl;
2856145Snate@binkert.org  out << "remaining_records_" << description << ": " << remaining_records << endl;
2866145Snate@binkert.org  out << "remaining_records_log_" << description << ": " << remaining_records_log << endl;
2876145Snate@binkert.org  out << "touched_by_" << description << ": " << m_touched_vec << endl;
2886145Snate@binkert.org  out << "touched_by_weighted_" << description << ": " << m_touched_weighted_vec << endl;
2896145Snate@binkert.org  out << endl;
2906145Snate@binkert.org}
2916145Snate@binkert.org
2926145Snate@binkert.orgstatic AccessTraceForAddress& lookupTraceForAddress(const Address& addr, Map<Address, AccessTraceForAddress>* record_map)
2936145Snate@binkert.org{
2946145Snate@binkert.org  if(record_map->exist(addr) == false){
2956145Snate@binkert.org    record_map->add(addr, AccessTraceForAddress(addr));
2966145Snate@binkert.org  }
2976145Snate@binkert.org  return record_map->lookup(addr);
2986145Snate@binkert.org}
299