16145Snate@binkert.org/*
26145Snate@binkert.org * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood
36145Snate@binkert.org * All rights reserved.
46145Snate@binkert.org *
56145Snate@binkert.org * Redistribution and use in source and binary forms, with or without
66145Snate@binkert.org * modification, are permitted provided that the following conditions are
76145Snate@binkert.org * met: redistributions of source code must retain the above copyright
86145Snate@binkert.org * notice, this list of conditions and the following disclaimer;
96145Snate@binkert.org * redistributions in binary form must reproduce the above copyright
106145Snate@binkert.org * notice, this list of conditions and the following disclaimer in the
116145Snate@binkert.org * documentation and/or other materials provided with the distribution;
126145Snate@binkert.org * neither the name of the copyright holders nor the names of its
136145Snate@binkert.org * contributors may be used to endorse or promote products derived from
146145Snate@binkert.org * this software without specific prior written permission.
156145Snate@binkert.org *
166145Snate@binkert.org * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
176145Snate@binkert.org * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
186145Snate@binkert.org * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
196145Snate@binkert.org * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
206145Snate@binkert.org * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
216145Snate@binkert.org * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
226145Snate@binkert.org * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
236145Snate@binkert.org * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
246145Snate@binkert.org * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
256145Snate@binkert.org * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
266145Snate@binkert.org * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
276145Snate@binkert.org */
286145Snate@binkert.org
2911793Sbrandon.potter@amd.com#include "mem/ruby/profiler/AddressProfiler.hh"
3011793Sbrandon.potter@amd.com
317454Snate@binkert.org#include <vector>
327454Snate@binkert.org
337454Snate@binkert.org#include "base/stl_helpers.hh"
347048Snate@binkert.org#include "mem/ruby/profiler/Profiler.hh"
3514184Sgabeblack@google.com#include "mem/ruby/protocol/RubyRequest.hh"
367048Snate@binkert.org
377055Snate@binkert.orgusing namespace std;
387048Snate@binkert.orgtypedef AddressProfiler::AddressMap AddressMap;
396145Snate@binkert.org
407454Snate@binkert.orgusing m5::stl_helpers::operator<<;
417454Snate@binkert.org
426145Snate@binkert.org// Helper functions
437048Snate@binkert.orgAccessTraceForAddress&
4411025Snilay@cs.wisc.edulookupTraceForAddress(Addr addr, AddressMap& record_map)
457048Snate@binkert.org{
467455Snate@binkert.org    // we create a static default object here that is used to insert
477455Snate@binkert.org    // since the insertion will create a copy of the object in the
487455Snate@binkert.org    // process.  Perhaps this is optimizing early, but it doesn't seem
497455Snate@binkert.org    // like it could hurt.
507455Snate@binkert.org    static const AccessTraceForAddress dflt;
517455Snate@binkert.org
527455Snate@binkert.org    pair<AddressMap::iterator, bool> r =
537455Snate@binkert.org        record_map.insert(make_pair(addr, dflt));
547455Snate@binkert.org    AddressMap::iterator i = r.first;
557455Snate@binkert.org    AccessTraceForAddress &access_trace = i->second;
567455Snate@binkert.org    if (r.second) {
577455Snate@binkert.org        // there was nothing there and the insert succeed, so we need
587455Snate@binkert.org        // to actually set the address.
597455Snate@binkert.org        access_trace.setAddress(addr);
607048Snate@binkert.org    }
617455Snate@binkert.org
627455Snate@binkert.org    return access_trace;
637048Snate@binkert.org}
646145Snate@binkert.org
657048Snate@binkert.orgvoid
667455Snate@binkert.orgprintSorted(ostream& out, int num_of_sequencers, const AddressMap &record_map,
6710919Sbrandon.potter@amd.com            string description, Profiler *profiler)
687048Snate@binkert.org{
697048Snate@binkert.org    const int records_printed = 100;
707048Snate@binkert.org
7111061Snilay@cs.wisc.edu    uint64_t misses = 0;
727456Snate@binkert.org    std::vector<const AccessTraceForAddress *> sorted;
737455Snate@binkert.org
747455Snate@binkert.org    AddressMap::const_iterator i = record_map.begin();
757455Snate@binkert.org    AddressMap::const_iterator end = record_map.end();
767455Snate@binkert.org    for (; i != end; ++i) {
777455Snate@binkert.org        const AccessTraceForAddress* record = &i->second;
787048Snate@binkert.org        misses += record->getTotal();
797456Snate@binkert.org        sorted.push_back(record);
807048Snate@binkert.org    }
817456Snate@binkert.org    sort(sorted.begin(), sorted.end(), AccessTraceForAddress::less_equal);
827048Snate@binkert.org
837455Snate@binkert.org    out << "Total_entries_" << description << ": " << record_map.size()
847455Snate@binkert.org        << endl;
8510919Sbrandon.potter@amd.com    if (profiler->getAllInstructions())
867048Snate@binkert.org        out << "Total_Instructions_" << description << ": " << misses << endl;
877048Snate@binkert.org    else
887048Snate@binkert.org        out << "Total_data_misses_" << description << ": " << misses << endl;
897048Snate@binkert.org
907048Snate@binkert.org    out << "total | load store atomic | user supervisor | sharing | touched-by"
917048Snate@binkert.org        << endl;
927048Snate@binkert.org
937048Snate@binkert.org    Histogram remaining_records(1, 100);
947048Snate@binkert.org    Histogram all_records(1, 100);
957048Snate@binkert.org    Histogram remaining_records_log(-1);
967048Snate@binkert.org    Histogram all_records_log(-1);
977048Snate@binkert.org
987048Snate@binkert.org    // Allows us to track how many lines where touched by n processors
9911061Snilay@cs.wisc.edu    std::vector<int64_t> m_touched_vec;
10011061Snilay@cs.wisc.edu    std::vector<int64_t> m_touched_weighted_vec;
1017454Snate@binkert.org    m_touched_vec.resize(num_of_sequencers+1);
1027454Snate@binkert.org    m_touched_weighted_vec.resize(num_of_sequencers+1);
1039550Sandreas.hansson@arm.com    for (int j = 0; j < m_touched_vec.size(); j++) {
1049550Sandreas.hansson@arm.com        m_touched_vec[j] = 0;
1059550Sandreas.hansson@arm.com        m_touched_weighted_vec[j] = 0;
1067048Snate@binkert.org    }
1077048Snate@binkert.org
1087048Snate@binkert.org    int counter = 0;
1097456Snate@binkert.org    int max = sorted.size();
1107456Snate@binkert.org    while (counter < max && counter < records_printed) {
1117456Snate@binkert.org        const AccessTraceForAddress* record = sorted[counter];
1127048Snate@binkert.org        double percent = 100.0 * (record->getTotal() / double(misses));
1137048Snate@binkert.org        out << description << " | " << percent << " % " << *record << endl;
1147048Snate@binkert.org        all_records.add(record->getTotal());
1157048Snate@binkert.org        all_records_log.add(record->getTotal());
1167048Snate@binkert.org        counter++;
1177048Snate@binkert.org        m_touched_vec[record->getTouchedBy()]++;
1187048Snate@binkert.org        m_touched_weighted_vec[record->getTouchedBy()] += record->getTotal();
1197048Snate@binkert.org    }
1207048Snate@binkert.org
1217456Snate@binkert.org    while (counter < max) {
1227456Snate@binkert.org        const AccessTraceForAddress* record = sorted[counter];
1237048Snate@binkert.org        all_records.add(record->getTotal());
1247048Snate@binkert.org        remaining_records.add(record->getTotal());
1257048Snate@binkert.org        all_records_log.add(record->getTotal());
1267048Snate@binkert.org        remaining_records_log.add(record->getTotal());
1277048Snate@binkert.org        m_touched_vec[record->getTouchedBy()]++;
1287048Snate@binkert.org        m_touched_weighted_vec[record->getTouchedBy()] += record->getTotal();
1297048Snate@binkert.org    }
1307048Snate@binkert.org    out << endl;
1317048Snate@binkert.org    out << "all_records_" << description << ": "
1327048Snate@binkert.org        << all_records << endl
1337048Snate@binkert.org        << "all_records_log_" << description << ": "
1347048Snate@binkert.org        << all_records_log << endl
1357048Snate@binkert.org        << "remaining_records_" << description << ": "
1367048Snate@binkert.org        << remaining_records << endl
1377048Snate@binkert.org        << "remaining_records_log_" << description << ": "
1387048Snate@binkert.org        << remaining_records_log << endl
1397048Snate@binkert.org        << "touched_by_" << description << ": "
1407048Snate@binkert.org        << m_touched_vec << endl
1417048Snate@binkert.org        << "touched_by_weighted_" << description << ": "
1427048Snate@binkert.org        << m_touched_weighted_vec << endl
1437048Snate@binkert.org        << endl;
1447048Snate@binkert.org}
1456896SBrad.Beckmann@amd.com
14610919Sbrandon.potter@amd.comAddressProfiler::AddressProfiler(int num_of_sequencers, Profiler *profiler)
14710919Sbrandon.potter@amd.com    : m_profiler(profiler)
1486145Snate@binkert.org{
1497048Snate@binkert.org    m_num_of_sequencers = num_of_sequencers;
1507048Snate@binkert.org    clearStats();
1516145Snate@binkert.org}
1526145Snate@binkert.org
1536145Snate@binkert.orgAddressProfiler::~AddressProfiler()
1546145Snate@binkert.org{
1556145Snate@binkert.org}
1566145Snate@binkert.org
1577048Snate@binkert.orgvoid
1587048Snate@binkert.orgAddressProfiler::setHotLines(bool hot_lines)
1597048Snate@binkert.org{
1607048Snate@binkert.org    m_hot_lines = hot_lines;
1616285Snate@binkert.org}
1626285Snate@binkert.org
1637048Snate@binkert.orgvoid
1647048Snate@binkert.orgAddressProfiler::setAllInstructions(bool all_instructions)
1656145Snate@binkert.org{
1667048Snate@binkert.org    m_all_instructions = all_instructions;
1676145Snate@binkert.org}
1686145Snate@binkert.org
1697048Snate@binkert.orgvoid
1707048Snate@binkert.orgAddressProfiler::printStats(ostream& out) const
1716145Snate@binkert.org{
1727048Snate@binkert.org    if (m_hot_lines) {
1737048Snate@binkert.org        out << endl;
1747048Snate@binkert.org        out << "AddressProfiler Stats" << endl;
1757048Snate@binkert.org        out << "---------------------" << endl;
1767048Snate@binkert.org
1777048Snate@binkert.org        out << endl;
1787048Snate@binkert.org        out << "sharing_misses: " << m_sharing_miss_counter << endl;
1797048Snate@binkert.org        out << "getx_sharing_histogram: " << m_getx_sharing_histogram << endl;
1807048Snate@binkert.org        out << "gets_sharing_histogram: " << m_gets_sharing_histogram << endl;
1817048Snate@binkert.org
1827048Snate@binkert.org        out << endl;
1837048Snate@binkert.org        out << "Hot Data Blocks" << endl;
1847048Snate@binkert.org        out << "---------------" << endl;
1857048Snate@binkert.org        out << endl;
1867048Snate@binkert.org        printSorted(out, m_num_of_sequencers, m_dataAccessTrace,
18710919Sbrandon.potter@amd.com                    "block_address", m_profiler);
1887048Snate@binkert.org
1897048Snate@binkert.org        out << endl;
1907048Snate@binkert.org        out << "Hot MacroData Blocks" << endl;
1917048Snate@binkert.org        out << "--------------------" << endl;
1927048Snate@binkert.org        out << endl;
1937048Snate@binkert.org        printSorted(out, m_num_of_sequencers, m_macroBlockAccessTrace,
19410919Sbrandon.potter@amd.com                    "macroblock_address", m_profiler);
1957048Snate@binkert.org
1967048Snate@binkert.org        out << "Hot Instructions" << endl;
1977048Snate@binkert.org        out << "----------------" << endl;
1987048Snate@binkert.org        out << endl;
1997048Snate@binkert.org        printSorted(out, m_num_of_sequencers, m_programCounterAccessTrace,
20010919Sbrandon.potter@amd.com                    "pc_address", m_profiler);
2017048Snate@binkert.org    }
2027048Snate@binkert.org
2037048Snate@binkert.org    if (m_all_instructions) {
2047048Snate@binkert.org        out << endl;
2057048Snate@binkert.org        out << "All Instructions Profile:" << endl;
2067048Snate@binkert.org        out << "-------------------------" << endl;
2077048Snate@binkert.org        out << endl;
2087048Snate@binkert.org        printSorted(out, m_num_of_sequencers, m_programCounterAccessTrace,
20910919Sbrandon.potter@amd.com                    "pc_address", m_profiler);
2107048Snate@binkert.org        out << endl;
2117048Snate@binkert.org    }
2127048Snate@binkert.org
2137048Snate@binkert.org    if (m_retryProfileHisto.size() > 0) {
2147048Snate@binkert.org        out << "Retry Profile" << endl;
2157048Snate@binkert.org        out << "-------------" << endl;
2167048Snate@binkert.org        out << endl;
2177048Snate@binkert.org        out << "retry_histogram_absolute: " << m_retryProfileHisto << endl;
2187048Snate@binkert.org        out << "retry_histogram_write: " << m_retryProfileHistoWrite << endl;
2197048Snate@binkert.org        out << "retry_histogram_read: " << m_retryProfileHistoRead << endl;
2207048Snate@binkert.org
2217048Snate@binkert.org        out << "retry_histogram_percent: ";
2227048Snate@binkert.org        m_retryProfileHisto.printPercent(out);
2237048Snate@binkert.org        out << endl;
2247048Snate@binkert.org
2257048Snate@binkert.org        printSorted(out, m_num_of_sequencers, m_retryProfileMap,
22610919Sbrandon.potter@amd.com                    "block_address", m_profiler);
2277048Snate@binkert.org        out << endl;
2287048Snate@binkert.org    }
2296145Snate@binkert.org}
2306145Snate@binkert.org
2317048Snate@binkert.orgvoid
2327048Snate@binkert.orgAddressProfiler::clearStats()
2336145Snate@binkert.org{
2347048Snate@binkert.org    // Clear the maps
2357048Snate@binkert.org    m_sharing_miss_counter = 0;
2367455Snate@binkert.org    m_dataAccessTrace.clear();
2377455Snate@binkert.org    m_macroBlockAccessTrace.clear();
2387455Snate@binkert.org    m_programCounterAccessTrace.clear();
2397455Snate@binkert.org    m_retryProfileMap.clear();
2407048Snate@binkert.org    m_retryProfileHisto.clear();
2417048Snate@binkert.org    m_retryProfileHistoRead.clear();
2427048Snate@binkert.org    m_retryProfileHistoWrite.clear();
2437048Snate@binkert.org    m_getx_sharing_histogram.clear();
2447048Snate@binkert.org    m_gets_sharing_histogram.clear();
2456145Snate@binkert.org}
2466145Snate@binkert.org
2477048Snate@binkert.orgvoid
24811025Snilay@cs.wisc.eduAddressProfiler::profileGetX(Addr datablock, Addr PC,
2497048Snate@binkert.org                             const Set& owner, const Set& sharers,
2507048Snate@binkert.org                             NodeID requestor)
2516145Snate@binkert.org{
2527048Snate@binkert.org    Set indirection_set;
2537048Snate@binkert.org    indirection_set.addSet(sharers);
2547048Snate@binkert.org    indirection_set.addSet(owner);
2557048Snate@binkert.org    indirection_set.remove(requestor);
2567048Snate@binkert.org    int num_indirections = indirection_set.count();
2576145Snate@binkert.org
2587048Snate@binkert.org    m_getx_sharing_histogram.add(num_indirections);
2597048Snate@binkert.org    bool indirection_miss = (num_indirections > 0);
2606145Snate@binkert.org
2618165Snilay@cs.wisc.edu    addTraceSample(datablock, PC, RubyRequestType_ST, RubyAccessMode(0),
2627048Snate@binkert.org                   requestor, indirection_miss);
2636145Snate@binkert.org}
2646145Snate@binkert.org
2657048Snate@binkert.orgvoid
26611025Snilay@cs.wisc.eduAddressProfiler::profileGetS(Addr datablock, Addr PC,
2677048Snate@binkert.org                             const Set& owner, const Set& sharers,
2687048Snate@binkert.org                             NodeID requestor)
2696145Snate@binkert.org{
2707048Snate@binkert.org    Set indirection_set;
2717048Snate@binkert.org    indirection_set.addSet(owner);
2727048Snate@binkert.org    indirection_set.remove(requestor);
2737048Snate@binkert.org    int num_indirections = indirection_set.count();
2747048Snate@binkert.org
2757048Snate@binkert.org    m_gets_sharing_histogram.add(num_indirections);
2767048Snate@binkert.org    bool indirection_miss = (num_indirections > 0);
2777048Snate@binkert.org
2788165Snilay@cs.wisc.edu    addTraceSample(datablock, PC, RubyRequestType_LD, RubyAccessMode(0),
2797048Snate@binkert.org                   requestor, indirection_miss);
2807048Snate@binkert.org}
2817048Snate@binkert.org
2827048Snate@binkert.orgvoid
28311025Snilay@cs.wisc.eduAddressProfiler::addTraceSample(Addr data_addr, Addr pc_addr,
2848165Snilay@cs.wisc.edu                                RubyRequestType type,
2858164Snilay@cs.wisc.edu                                RubyAccessMode access_mode, NodeID id,
2867048Snate@binkert.org                                bool sharing_miss)
2877048Snate@binkert.org{
2887048Snate@binkert.org    if (m_all_instructions) {
2897048Snate@binkert.org        if (sharing_miss) {
2907048Snate@binkert.org            m_sharing_miss_counter++;
2917048Snate@binkert.org        }
2927048Snate@binkert.org
2937048Snate@binkert.org        // record data address trace info
29411025Snilay@cs.wisc.edu        data_addr = makeLineAddress(data_addr);
2957048Snate@binkert.org        lookupTraceForAddress(data_addr, m_dataAccessTrace).
2967048Snate@binkert.org            update(type, access_mode, id, sharing_miss);
2977048Snate@binkert.org
2987048Snate@binkert.org        // record macro data address trace info
2997048Snate@binkert.org
3007048Snate@binkert.org        // 6 for datablock, 4 to make it 16x more coarse
30111025Snilay@cs.wisc.edu        Addr macro_addr = maskLowOrderBits(data_addr, 10);
3027048Snate@binkert.org        lookupTraceForAddress(macro_addr, m_macroBlockAccessTrace).
3037048Snate@binkert.org            update(type, access_mode, id, sharing_miss);
3047048Snate@binkert.org
3057048Snate@binkert.org        // record program counter address trace info
3067048Snate@binkert.org        lookupTraceForAddress(pc_addr, m_programCounterAccessTrace).
3077048Snate@binkert.org            update(type, access_mode, id, sharing_miss);
3086145Snate@binkert.org    }
3096145Snate@binkert.org
3107048Snate@binkert.org    if (m_all_instructions) {
3117048Snate@binkert.org        // This code is used if the address profiler is an
3127048Snate@binkert.org        // all-instructions profiler record program counter address
3137048Snate@binkert.org        // trace info
3147048Snate@binkert.org        lookupTraceForAddress(pc_addr, m_programCounterAccessTrace).
3157048Snate@binkert.org            update(type, access_mode, id, sharing_miss);
3167048Snate@binkert.org    }
3176145Snate@binkert.org}
3186145Snate@binkert.org
3197048Snate@binkert.orgvoid
32011025Snilay@cs.wisc.eduAddressProfiler::profileRetry(Addr data_addr, AccessType type, int count)
3216145Snate@binkert.org{
3227048Snate@binkert.org    m_retryProfileHisto.add(count);
3237048Snate@binkert.org    if (type == AccessType_Read) {
3247048Snate@binkert.org        m_retryProfileHistoRead.add(count);
3257048Snate@binkert.org    } else {
3267048Snate@binkert.org        m_retryProfileHistoWrite.add(count);
3277048Snate@binkert.org    }
3287048Snate@binkert.org    if (count > 1) {
3297048Snate@binkert.org        lookupTraceForAddress(data_addr, m_retryProfileMap).addSample(count);
3307048Snate@binkert.org    }
3316145Snate@binkert.org}
332