AddressProfiler.cc revision 6145
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/*
316145Snate@binkert.org * AddressProfiler.C
326145Snate@binkert.org *
336145Snate@binkert.org * Description: See AddressProfiler.h
346145Snate@binkert.org *
356145Snate@binkert.org * $Id$
366145Snate@binkert.org *
376145Snate@binkert.org */
386145Snate@binkert.org
396145Snate@binkert.org#include "AddressProfiler.hh"
406145Snate@binkert.org#include "CacheMsg.hh"
416145Snate@binkert.org#include "AccessTraceForAddress.hh"
426145Snate@binkert.org#include "PrioHeap.hh"
436145Snate@binkert.org#include "Map.hh"
446145Snate@binkert.org#include "System.hh"
456145Snate@binkert.org#include "Profiler.hh"
466145Snate@binkert.org
476145Snate@binkert.org// Helper functions
486145Snate@binkert.orgstatic AccessTraceForAddress& lookupTraceForAddress(const Address& addr, Map<Address, AccessTraceForAddress>* record_map);
496145Snate@binkert.orgstatic void printSorted(ostream& out, const Map<Address, AccessTraceForAddress>* record_map, string description);
506145Snate@binkert.org
516145Snate@binkert.orgAddressProfiler::AddressProfiler()
526145Snate@binkert.org{
536145Snate@binkert.org  m_dataAccessTrace = new Map<Address, AccessTraceForAddress>;
546145Snate@binkert.org  m_macroBlockAccessTrace = new Map<Address, AccessTraceForAddress>;
556145Snate@binkert.org  m_programCounterAccessTrace = new Map<Address, AccessTraceForAddress>;
566145Snate@binkert.org  m_retryProfileMap = new Map<Address, AccessTraceForAddress>;
576145Snate@binkert.org  m_persistentPredictionProfileMap = new Map<Address, AccessTraceForAddress>;
586145Snate@binkert.org  clearStats();
596145Snate@binkert.org}
606145Snate@binkert.org
616145Snate@binkert.orgAddressProfiler::~AddressProfiler()
626145Snate@binkert.org{
636145Snate@binkert.org  delete m_dataAccessTrace;
646145Snate@binkert.org  delete m_macroBlockAccessTrace;
656145Snate@binkert.org  delete m_programCounterAccessTrace;
666145Snate@binkert.org  delete m_retryProfileMap;
676145Snate@binkert.org  delete m_persistentPredictionProfileMap;
686145Snate@binkert.org}
696145Snate@binkert.org
706145Snate@binkert.orgvoid AddressProfiler::printStats(ostream& out) const
716145Snate@binkert.org{
726145Snate@binkert.org  if (PROFILE_HOT_LINES) {
736145Snate@binkert.org    out << endl;
746145Snate@binkert.org    out << "AddressProfiler Stats" << endl;
756145Snate@binkert.org    out << "---------------------" << endl;
766145Snate@binkert.org
776145Snate@binkert.org    out << endl;
786145Snate@binkert.org    out << "sharing_misses: " << m_sharing_miss_counter << endl;
796145Snate@binkert.org    out << "getx_sharing_histogram: " << m_getx_sharing_histogram << endl;
806145Snate@binkert.org    out << "gets_sharing_histogram: " << m_gets_sharing_histogram << endl;
816145Snate@binkert.org
826145Snate@binkert.org    out << endl;
836145Snate@binkert.org    out << "Hot Data Blocks" << endl;
846145Snate@binkert.org    out << "---------------" << endl;
856145Snate@binkert.org    out << endl;
866145Snate@binkert.org    printSorted(out, m_dataAccessTrace, "block_address");
876145Snate@binkert.org
886145Snate@binkert.org    out << endl;
896145Snate@binkert.org    out << "Hot MacroData Blocks" << endl;
906145Snate@binkert.org    out << "--------------------" << endl;
916145Snate@binkert.org    out << endl;
926145Snate@binkert.org    printSorted(out, m_macroBlockAccessTrace, "macroblock_address");
936145Snate@binkert.org
946145Snate@binkert.org    out << "Hot Instructions" << endl;
956145Snate@binkert.org    out << "----------------" << endl;
966145Snate@binkert.org    out << endl;
976145Snate@binkert.org    printSorted(out, m_programCounterAccessTrace, "pc_address");
986145Snate@binkert.org  }
996145Snate@binkert.org
1006145Snate@binkert.org  if (PROFILE_ALL_INSTRUCTIONS){
1016145Snate@binkert.org    out << endl;
1026145Snate@binkert.org    out << "All Instructions Profile:" << endl;
1036145Snate@binkert.org    out << "-------------------------" << endl;
1046145Snate@binkert.org    out << endl;
1056145Snate@binkert.org    printSorted(out, m_programCounterAccessTrace, "pc_address");
1066145Snate@binkert.org    out << endl;
1076145Snate@binkert.org  }
1086145Snate@binkert.org
1096145Snate@binkert.org  if (m_retryProfileHisto.size() > 0) {
1106145Snate@binkert.org    out << "Retry Profile" << endl;
1116145Snate@binkert.org    out << "-------------" << endl;
1126145Snate@binkert.org    out << endl;
1136145Snate@binkert.org    out << "retry_histogram_absolute: " << m_retryProfileHisto << endl;
1146145Snate@binkert.org    out << "retry_histogram_write: " << m_retryProfileHistoWrite << endl;
1156145Snate@binkert.org    out << "retry_histogram_read: " << m_retryProfileHistoRead << endl;
1166145Snate@binkert.org
1176145Snate@binkert.org    out << "retry_histogram_percent: ";
1186145Snate@binkert.org    m_retryProfileHisto.printPercent(out);
1196145Snate@binkert.org    out << endl;
1206145Snate@binkert.org
1216145Snate@binkert.org    out << "retry_histogram_per_instruction: ";
1226145Snate@binkert.org    m_retryProfileHisto.printWithMultiplier(out, 1.0 / double(g_system_ptr->getProfiler()->getTotalInstructionsExecuted()));
1236145Snate@binkert.org    out << endl;
1246145Snate@binkert.org
1256145Snate@binkert.org    printSorted(out, m_retryProfileMap, "block_address");
1266145Snate@binkert.org    out << endl;
1276145Snate@binkert.org  }
1286145Snate@binkert.org
1296145Snate@binkert.org  if (m_persistentPredictionProfileHisto.size() > 0) {
1306145Snate@binkert.org    out << "Persistent Prediction Profile" << endl;
1316145Snate@binkert.org    out << "-------------" << endl;
1326145Snate@binkert.org    out << endl;
1336145Snate@binkert.org    out << "persistent prediction_histogram: " << m_persistentPredictionProfileHisto << endl;
1346145Snate@binkert.org
1356145Snate@binkert.org    out << "persistent prediction_histogram_percent: ";
1366145Snate@binkert.org    m_persistentPredictionProfileHisto.printPercent(out);
1376145Snate@binkert.org    out << endl;
1386145Snate@binkert.org
1396145Snate@binkert.org    out << "persistentPrediction_histogram_per_instruction: ";
1406145Snate@binkert.org    m_persistentPredictionProfileHisto.printWithMultiplier(out, 1.0 / double(g_system_ptr->getProfiler()->getTotalInstructionsExecuted()));
1416145Snate@binkert.org    out << endl;
1426145Snate@binkert.org
1436145Snate@binkert.org    printSorted(out, m_persistentPredictionProfileMap, "block_address");
1446145Snate@binkert.org    out << endl;
1456145Snate@binkert.org  }
1466145Snate@binkert.org}
1476145Snate@binkert.org
1486145Snate@binkert.orgvoid AddressProfiler::clearStats()
1496145Snate@binkert.org{
1506145Snate@binkert.org  // Clear the maps
1516145Snate@binkert.org  m_sharing_miss_counter = 0;
1526145Snate@binkert.org  m_dataAccessTrace->clear();
1536145Snate@binkert.org  m_macroBlockAccessTrace->clear();
1546145Snate@binkert.org  m_programCounterAccessTrace->clear();
1556145Snate@binkert.org  m_retryProfileMap->clear();
1566145Snate@binkert.org  m_retryProfileHisto.clear();
1576145Snate@binkert.org  m_retryProfileHistoRead.clear();
1586145Snate@binkert.org  m_retryProfileHistoWrite.clear();
1596145Snate@binkert.org  m_getx_sharing_histogram.clear();
1606145Snate@binkert.org  m_gets_sharing_histogram.clear();
1616145Snate@binkert.org}
1626145Snate@binkert.org
1636145Snate@binkert.orgvoid AddressProfiler::profileGetX(const Address& datablock, const Address& PC, const Set& owner, const Set& sharers, NodeID requestor)
1646145Snate@binkert.org{
1656145Snate@binkert.org  Set indirection_set;
1666145Snate@binkert.org  indirection_set.addSet(sharers);
1676145Snate@binkert.org  indirection_set.addSet(owner);
1686145Snate@binkert.org  indirection_set.remove(requestor);
1696145Snate@binkert.org  int num_indirections = indirection_set.count();
1706145Snate@binkert.org
1716145Snate@binkert.org  m_getx_sharing_histogram.add(num_indirections);
1726145Snate@binkert.org  bool indirection_miss = (num_indirections > 0);
1736145Snate@binkert.org
1746145Snate@binkert.org  addTraceSample(datablock, PC, CacheRequestType_ST, AccessModeType(0), requestor, indirection_miss);
1756145Snate@binkert.org}
1766145Snate@binkert.org
1776145Snate@binkert.orgvoid AddressProfiler::profileGetS(const Address& datablock, const Address& PC, const Set& owner, const Set& sharers, NodeID requestor)
1786145Snate@binkert.org{
1796145Snate@binkert.org  Set indirection_set;
1806145Snate@binkert.org  indirection_set.addSet(owner);
1816145Snate@binkert.org  indirection_set.remove(requestor);
1826145Snate@binkert.org  int num_indirections = indirection_set.count();
1836145Snate@binkert.org
1846145Snate@binkert.org  m_gets_sharing_histogram.add(num_indirections);
1856145Snate@binkert.org  bool indirection_miss = (num_indirections > 0);
1866145Snate@binkert.org
1876145Snate@binkert.org  addTraceSample(datablock, PC, CacheRequestType_LD, AccessModeType(0), requestor, indirection_miss);
1886145Snate@binkert.org}
1896145Snate@binkert.org
1906145Snate@binkert.orgvoid AddressProfiler::addTraceSample(Address data_addr, Address pc_addr, CacheRequestType type, AccessModeType access_mode, NodeID id, bool sharing_miss)
1916145Snate@binkert.org{
1926145Snate@binkert.org  if (PROFILE_HOT_LINES) {
1936145Snate@binkert.org    if (sharing_miss) {
1946145Snate@binkert.org      m_sharing_miss_counter++;
1956145Snate@binkert.org    }
1966145Snate@binkert.org
1976145Snate@binkert.org    // record data address trace info
1986145Snate@binkert.org    data_addr.makeLineAddress();
1996145Snate@binkert.org    lookupTraceForAddress(data_addr, m_dataAccessTrace).update(type, access_mode, id, sharing_miss);
2006145Snate@binkert.org
2016145Snate@binkert.org    // record macro data address trace info
2026145Snate@binkert.org    Address macro_addr(data_addr.maskLowOrderBits(10)); // 6 for datablock, 4 to make it 16x more coarse
2036145Snate@binkert.org    lookupTraceForAddress(macro_addr, m_macroBlockAccessTrace).update(type, access_mode, id, sharing_miss);
2046145Snate@binkert.org
2056145Snate@binkert.org    // record program counter address trace info
2066145Snate@binkert.org    lookupTraceForAddress(pc_addr, m_programCounterAccessTrace).update(type, access_mode, id, sharing_miss);
2076145Snate@binkert.org  }
2086145Snate@binkert.org
2096145Snate@binkert.org  if (PROFILE_ALL_INSTRUCTIONS) {
2106145Snate@binkert.org    // This code is used if the address profiler is an all-instructions profiler
2116145Snate@binkert.org    // record program counter address trace info
2126145Snate@binkert.org    lookupTraceForAddress(pc_addr, m_programCounterAccessTrace).update(type, access_mode, id, sharing_miss);
2136145Snate@binkert.org  }
2146145Snate@binkert.org}
2156145Snate@binkert.org
2166145Snate@binkert.orgvoid AddressProfiler::profileRetry(const Address& data_addr, AccessType type, int count)
2176145Snate@binkert.org{
2186145Snate@binkert.org  m_retryProfileHisto.add(count);
2196145Snate@binkert.org  if (type == AccessType_Read) {
2206145Snate@binkert.org    m_retryProfileHistoRead.add(count);
2216145Snate@binkert.org  } else {
2226145Snate@binkert.org    m_retryProfileHistoWrite.add(count);
2236145Snate@binkert.org  }
2246145Snate@binkert.org  if (count > 1) {
2256145Snate@binkert.org    lookupTraceForAddress(data_addr, m_retryProfileMap).addSample(count);
2266145Snate@binkert.org  }
2276145Snate@binkert.org}
2286145Snate@binkert.org
2296145Snate@binkert.orgvoid AddressProfiler::profilePersistentPrediction(const Address& data_addr, AccessType type)
2306145Snate@binkert.org{
2316145Snate@binkert.org  m_persistentPredictionProfileHisto.add(1);
2326145Snate@binkert.org  lookupTraceForAddress(data_addr, m_persistentPredictionProfileMap).addSample(1);
2336145Snate@binkert.org}
2346145Snate@binkert.org
2356145Snate@binkert.org// ***** Normal Functions ******
2366145Snate@binkert.org
2376145Snate@binkert.orgstatic void printSorted(ostream& out, const Map<Address, AccessTraceForAddress>* record_map, string description)
2386145Snate@binkert.org{
2396145Snate@binkert.org  const int records_printed = 100;
2406145Snate@binkert.org
2416145Snate@binkert.org  uint64 misses = 0;
2426145Snate@binkert.org  PrioHeap<AccessTraceForAddress*> heap;
2436145Snate@binkert.org  Vector<Address> keys = record_map->keys();
2446145Snate@binkert.org  for(int i=0; i<keys.size(); i++){
2456145Snate@binkert.org    AccessTraceForAddress* record = &(record_map->lookup(keys[i]));
2466145Snate@binkert.org    misses += record->getTotal();
2476145Snate@binkert.org    heap.insert(record);
2486145Snate@binkert.org  }
2496145Snate@binkert.org
2506145Snate@binkert.org  out << "Total_entries_" << description << ": " << keys.size() << endl;
2516145Snate@binkert.org  if (PROFILE_ALL_INSTRUCTIONS)
2526145Snate@binkert.org    out << "Total_Instructions_" << description << ": " << misses << endl;
2536145Snate@binkert.org  else
2546145Snate@binkert.org    out << "Total_data_misses_" << description << ": " << misses << endl;
2556145Snate@binkert.org
2566145Snate@binkert.org  out << "total | load store atomic | user supervisor | sharing | touched-by" << endl;
2576145Snate@binkert.org
2586145Snate@binkert.org  Histogram remaining_records(1, 100);
2596145Snate@binkert.org  Histogram all_records(1, 100);
2606145Snate@binkert.org  Histogram remaining_records_log(-1);
2616145Snate@binkert.org  Histogram all_records_log(-1);
2626145Snate@binkert.org
2636145Snate@binkert.org  // Allows us to track how many lines where touched by n processors
2646145Snate@binkert.org  Vector<int64> m_touched_vec;
2656145Snate@binkert.org  Vector<int64> m_touched_weighted_vec;
2666145Snate@binkert.org  m_touched_vec.setSize(RubyConfig::numberOfProcessors()+1);
2676145Snate@binkert.org  m_touched_weighted_vec.setSize(RubyConfig::numberOfProcessors()+1);
2686145Snate@binkert.org  for (int i=0; i<m_touched_vec.size(); i++) {
2696145Snate@binkert.org    m_touched_vec[i] = 0;
2706145Snate@binkert.org    m_touched_weighted_vec[i] = 0;
2716145Snate@binkert.org  }
2726145Snate@binkert.org
2736145Snate@binkert.org  int counter = 0;
2746145Snate@binkert.org  while((heap.size() > 0) && (counter < records_printed)) {
2756145Snate@binkert.org    AccessTraceForAddress* record = heap.extractMin();
2766145Snate@binkert.org    double percent = 100.0*(record->getTotal()/double(misses));
2776145Snate@binkert.org    out << description << " | " << percent << " % " << *record << endl;
2786145Snate@binkert.org    all_records.add(record->getTotal());
2796145Snate@binkert.org    all_records_log.add(record->getTotal());
2806145Snate@binkert.org    counter++;
2816145Snate@binkert.org    m_touched_vec[record->getTouchedBy()]++;
2826145Snate@binkert.org    m_touched_weighted_vec[record->getTouchedBy()] += record->getTotal();
2836145Snate@binkert.org  }
2846145Snate@binkert.org
2856145Snate@binkert.org  while(heap.size() > 0) {
2866145Snate@binkert.org    AccessTraceForAddress* record = heap.extractMin();
2876145Snate@binkert.org    all_records.add(record->getTotal());
2886145Snate@binkert.org    remaining_records.add(record->getTotal());
2896145Snate@binkert.org    all_records_log.add(record->getTotal());
2906145Snate@binkert.org    remaining_records_log.add(record->getTotal());
2916145Snate@binkert.org    m_touched_vec[record->getTouchedBy()]++;
2926145Snate@binkert.org    m_touched_weighted_vec[record->getTouchedBy()] += record->getTotal();
2936145Snate@binkert.org  }
2946145Snate@binkert.org  out << endl;
2956145Snate@binkert.org  out << "all_records_" << description << ": " << all_records << endl;
2966145Snate@binkert.org  out << "all_records_log_" << description << ": " << all_records_log << endl;
2976145Snate@binkert.org  out << "remaining_records_" << description << ": " << remaining_records << endl;
2986145Snate@binkert.org  out << "remaining_records_log_" << description << ": " << remaining_records_log << endl;
2996145Snate@binkert.org  out << "touched_by_" << description << ": " << m_touched_vec << endl;
3006145Snate@binkert.org  out << "touched_by_weighted_" << description << ": " << m_touched_weighted_vec << endl;
3016145Snate@binkert.org  out << endl;
3026145Snate@binkert.org}
3036145Snate@binkert.org
3046145Snate@binkert.orgstatic AccessTraceForAddress& lookupTraceForAddress(const Address& addr, Map<Address, AccessTraceForAddress>* record_map)
3056145Snate@binkert.org{
3066145Snate@binkert.org  if(record_map->exist(addr) == false){
3076145Snate@binkert.org    record_map->add(addr, AccessTraceForAddress(addr));
3086145Snate@binkert.org  }
3096145Snate@binkert.org  return record_map->lookup(addr);
3106145Snate@binkert.org}
311