Profiler.cc revision 9496
110923SN/A/*
210923SN/A * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood
310923SN/A * All rights reserved.
410923SN/A *
510923SN/A * Redistribution and use in source and binary forms, with or without
610923SN/A * modification, are permitted provided that the following conditions are
710923SN/A * met: redistributions of source code must retain the above copyright
810923SN/A * notice, this list of conditions and the following disclaimer;
910923SN/A * redistributions in binary form must reproduce the above copyright
1010923SN/A * notice, this list of conditions and the following disclaimer in the
1110923SN/A * documentation and/or other materials provided with the distribution;
1210923SN/A * neither the name of the copyright holders nor the names of its
1310923SN/A * contributors may be used to endorse or promote products derived from
1410923SN/A * this software without specific prior written permission.
1510923SN/A *
1610923SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
1710923SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
1810923SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
1910923SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
2010923SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
2110923SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
2210923SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2310923SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2410923SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2510923SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
2610923SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2710923SN/A */
2810923SN/A
2910923SN/A/*
3010923SN/A   This file has been modified by Kevin Moore and Dan Nussbaum of the
3110923SN/A   Scalable Systems Research Group at Sun Microsystems Laboratories
3210923SN/A   (http://research.sun.com/scalable/) to support the Adaptive
3310923SN/A   Transactional Memory Test Platform (ATMTP).
3410923SN/A
3510923SN/A   Please send email to atmtp-interest@sun.com with feedback, questions, or
3610923SN/A   to request future announcements about ATMTP.
3710923SN/A
3810923SN/A   ----------------------------------------------------------------------
3910923SN/A
4010923SN/A   File modification date: 2008-02-23
4111290Sgabor.dozsa@arm.com
4210923SN/A   ----------------------------------------------------------------------
4310923SN/A*/
4411290Sgabor.dozsa@arm.com
4510923SN/A// Allows use of times() library call, which determines virtual runtime
4610923SN/A#include <sys/resource.h>
4710923SN/A#include <sys/times.h>
4810923SN/A#include <sys/types.h>
4910923SN/A#include <unistd.h>
5010923SN/A
5110923SN/A#include <algorithm>
5210923SN/A#include <fstream>
5310923SN/A
5410923SN/A#include "base/stl_helpers.hh"
5510923SN/A#include "base/str.hh"
5610923SN/A#include "mem/protocol/MachineType.hh"
5711290Sgabor.dozsa@arm.com#include "mem/protocol/RubyRequest.hh"
5811290Sgabor.dozsa@arm.com#include "mem/ruby/network/Network.hh"
5910923SN/A#include "mem/ruby/profiler/AddressProfiler.hh"
6011290Sgabor.dozsa@arm.com#include "mem/ruby/profiler/Profiler.hh"
6111263SN/A#include "mem/ruby/system/System.hh"
6211263SN/A
6311263SN/Ausing namespace std;
6411263SN/Ausing m5::stl_helpers::operator<<;
6511263SN/A
6611263SN/Astatic double process_memory_total();
6710923SN/Astatic double process_memory_resident();
6810923SN/A
6910923SN/AProfiler::Profiler(const Params *p)
7010923SN/A    : SimObject(p), m_event(this)
7110923SN/A{
7210923SN/A    m_inst_profiler_ptr = NULL;
7310923SN/A    m_address_profiler_ptr = NULL;
7411290Sgabor.dozsa@arm.com
7511290Sgabor.dozsa@arm.com    m_real_time_start_time = time(NULL); // Not reset in clearStats()
7610923SN/A    m_stats_period = 1000000; // Default
7711290Sgabor.dozsa@arm.com    m_periodic_output_file_ptr = &cerr;
7811290Sgabor.dozsa@arm.com
7910923SN/A    m_hot_lines = p->hot_lines;
8010923SN/A    m_all_instructions = p->all_instructions;
8110923SN/A
8210923SN/A    m_num_of_sequencers = p->num_of_sequencers;
8310923SN/A
8411290Sgabor.dozsa@arm.com    m_hot_lines = false;
8511290Sgabor.dozsa@arm.com    m_all_instructions = false;
8611290Sgabor.dozsa@arm.com
8711290Sgabor.dozsa@arm.com    m_address_profiler_ptr = new AddressProfiler(m_num_of_sequencers);
8811290Sgabor.dozsa@arm.com    m_address_profiler_ptr->setHotLines(m_hot_lines);
8911290Sgabor.dozsa@arm.com    m_address_profiler_ptr->setAllInstructions(m_all_instructions);
9011290Sgabor.dozsa@arm.com
9111290Sgabor.dozsa@arm.com    if (m_all_instructions) {
9211290Sgabor.dozsa@arm.com        m_inst_profiler_ptr = new AddressProfiler(m_num_of_sequencers);
9310923SN/A        m_inst_profiler_ptr->setHotLines(m_hot_lines);
9411290Sgabor.dozsa@arm.com        m_inst_profiler_ptr->setAllInstructions(m_all_instructions);
9511290Sgabor.dozsa@arm.com    }
9611290Sgabor.dozsa@arm.com
9711290Sgabor.dozsa@arm.com    p->ruby_system->registerProfiler(this);
9811290Sgabor.dozsa@arm.com}
9911290Sgabor.dozsa@arm.com
10011290Sgabor.dozsa@arm.comProfiler::~Profiler()
10110923SN/A{
10210923SN/A    if (m_periodic_output_file_ptr != &cerr) {
10311290Sgabor.dozsa@arm.com        delete m_periodic_output_file_ptr;
10410923SN/A    }
10510923SN/A}
10610923SN/A
10710923SN/Avoid
10811290Sgabor.dozsa@arm.comProfiler::wakeup()
10910923SN/A{
11010923SN/A    // FIXME - avoid the repeated code
11110923SN/A
11211290Sgabor.dozsa@arm.com    vector<int64_t> perProcCycleCount(m_num_of_sequencers);
11310923SN/A
11410923SN/A    for (int i = 0; i < m_num_of_sequencers; i++) {
11510923SN/A        perProcCycleCount[i] =
11610923SN/A            g_system_ptr->getTime() - m_cycles_executed_at_start[i] + 1;
11710923SN/A        // The +1 allows us to avoid division by zero
11810923SN/A    }
11910923SN/A
12010923SN/A    ostream &out = *m_periodic_output_file_ptr;
12110923SN/A
12211290Sgabor.dozsa@arm.com    out << "ruby_cycles: " << g_system_ptr->getTime()-m_ruby_start << endl
12311290Sgabor.dozsa@arm.com        << "mbytes_resident: " << process_memory_resident() << endl
12410923SN/A        << "mbytes_total: " << process_memory_total() << endl;
12511290Sgabor.dozsa@arm.com
12611290Sgabor.dozsa@arm.com    if (process_memory_total() > 0) {
12711290Sgabor.dozsa@arm.com        out << "resident_ratio: "
12810923SN/A            << process_memory_resident() / process_memory_total() << endl;
12910923SN/A    }
13010923SN/A
13111290Sgabor.dozsa@arm.com    out << "miss_latency: " << m_allMissLatencyHistogram << endl;
13210923SN/A
13311290Sgabor.dozsa@arm.com    out << endl;
13411290Sgabor.dozsa@arm.com
13511290Sgabor.dozsa@arm.com    if (m_all_instructions) {
13610923SN/A        m_inst_profiler_ptr->printStats(out);
13710923SN/A    }
13810923SN/A
13911290Sgabor.dozsa@arm.com    //g_system_ptr->getNetwork()->printStats(out);
14010923SN/A    schedule(m_event, g_system_ptr->clockEdge(Cycles(m_stats_period)));
14111290Sgabor.dozsa@arm.com}
14211290Sgabor.dozsa@arm.com
14310923SN/Avoid
14410923SN/AProfiler::setPeriodicStatsFile(const string& filename)
14510923SN/A{
14611290Sgabor.dozsa@arm.com    cout << "Recording periodic statistics to file '" << filename << "' every "
14710923SN/A         << m_stats_period << " Ruby cycles" << endl;
14811290Sgabor.dozsa@arm.com
14911290Sgabor.dozsa@arm.com    if (m_periodic_output_file_ptr != &cerr) {
15010923SN/A        delete m_periodic_output_file_ptr;
15110923SN/A    }
15210923SN/A
15311290Sgabor.dozsa@arm.com    m_periodic_output_file_ptr = new ofstream(filename.c_str());
15410923SN/A    schedule(m_event, g_system_ptr->clockEdge(Cycles(1)));
15511290Sgabor.dozsa@arm.com}
15611290Sgabor.dozsa@arm.com
15710923SN/Avoid
15810923SN/AProfiler::setPeriodicStatsInterval(int64_t period)
15910923SN/A{
16011290Sgabor.dozsa@arm.com    cout << "Recording periodic statistics every " << m_stats_period
16110923SN/A         << " Ruby cycles" << endl;
16210923SN/A
16310923SN/A    m_stats_period = period;
16410923SN/A    schedule(m_event, g_system_ptr->clockEdge(Cycles(1)));
16511290Sgabor.dozsa@arm.com}
16610923SN/A
16710923SN/Avoid
16810923SN/AProfiler::print(ostream& out) const
16910923SN/A{
17011290Sgabor.dozsa@arm.com    out << "[Profiler]";
17110923SN/A}
17210923SN/A
17310923SN/Avoid
17410923SN/AProfiler::printRequestProfile(ostream &out)
17510923SN/A{
17610923SN/A    out << "Request vs. RubySystem State Profile" << endl;
17710923SN/A    out << "--------------------------------" << endl;
17810923SN/A    out << endl;
17910923SN/A
18011290Sgabor.dozsa@arm.com    map<string, uint64_t> m_requestProfileMap;
18110923SN/A    uint64_t m_requests = 0;
18210923SN/A
18310923SN/A    for (uint32_t i = 0; i < MachineType_NUM; i++) {
18410923SN/A        for (map<uint32_t, AbstractController*>::iterator it =
18510923SN/A                  g_abs_controls[i].begin();
18610923SN/A             it != g_abs_controls[i].end(); ++it) {
18710923SN/A
18810923SN/A            AbstractController *ctr = (*it).second;
18910923SN/A            map<string, uint64_t> mp = ctr->getRequestProfileMap();
19010923SN/A
19110923SN/A            for (map<string, uint64_t>::iterator jt = mp.begin();
19211290Sgabor.dozsa@arm.com                 jt != mp.end(); ++jt) {
19310923SN/A
19410923SN/A                map<string, uint64_t>::iterator kt =
19511290Sgabor.dozsa@arm.com                    m_requestProfileMap.find((*jt).first);
19610923SN/A                if (kt != m_requestProfileMap.end()) {
19710923SN/A                    (*kt).second += (*jt).second;
19810923SN/A                } else {
19910923SN/A                    m_requestProfileMap[(*jt).first] = (*jt).second;
20010923SN/A                }
20110923SN/A            }
20210923SN/A
20310923SN/A            m_requests += ctr->getRequestCount();
20410923SN/A        }
20511290Sgabor.dozsa@arm.com    }
20611290Sgabor.dozsa@arm.com
20710923SN/A    map<string, uint64_t>::const_iterator i = m_requestProfileMap.begin();
20810923SN/A    map<string, uint64_t>::const_iterator end = m_requestProfileMap.end();
20910923SN/A    for (; i != end; ++i) {
21010923SN/A        const string &key = i->first;
21110923SN/A        uint64_t count = i->second;
21210923SN/A
21310923SN/A        double percent = (100.0 * double(count)) / double(m_requests);
21410923SN/A        vector<string> items;
21511290Sgabor.dozsa@arm.com        tokenize(items, key, ':');
21610923SN/A        vector<string>::iterator j = items.begin();
21710923SN/A        vector<string>::iterator end = items.end();
21811290Sgabor.dozsa@arm.com        for (; j != end; ++i)
21910923SN/A            out << setw(10) << *j;
22011290Sgabor.dozsa@arm.com        out << setw(11) << count;
22110923SN/A        out << setw(14) << percent << endl;
22210923SN/A    }
22311290Sgabor.dozsa@arm.com    out << endl;
22410923SN/A}
22510923SN/A
22611290Sgabor.dozsa@arm.comvoid
22710923SN/AProfiler::printStats(ostream& out, bool short_stats)
22810923SN/A{
22910923SN/A    out << endl;
23010923SN/A    if (short_stats) {
23111290Sgabor.dozsa@arm.com        out << "SHORT ";
23210923SN/A    }
23310923SN/A    out << "Profiler Stats" << endl;
23411290Sgabor.dozsa@arm.com    out << "--------------" << endl;
23510923SN/A
23610923SN/A    time_t real_time_current = time(NULL);
23711290Sgabor.dozsa@arm.com    double seconds = difftime(real_time_current, m_real_time_start_time);
23810923SN/A    double minutes = seconds / 60.0;
23910923SN/A    double hours = minutes / 60.0;
24010923SN/A    double days = hours / 24.0;
24111290Sgabor.dozsa@arm.com    Time ruby_cycles = g_system_ptr->getTime()-m_ruby_start;
24210923SN/A
24310923SN/A    if (!short_stats) {
24411290Sgabor.dozsa@arm.com        out << "Elapsed_time_in_seconds: " << seconds << endl;
24510923SN/A        out << "Elapsed_time_in_minutes: " << minutes << endl;
24610923SN/A        out << "Elapsed_time_in_hours: " << hours << endl;
24710923SN/A        out << "Elapsed_time_in_days: " << days << endl;
24810923SN/A        out << endl;
24911290Sgabor.dozsa@arm.com    }
25010923SN/A
25110923SN/A    // print the virtual runtimes as well
25211290Sgabor.dozsa@arm.com    struct tms vtime;
25310923SN/A    times(&vtime);
25410923SN/A    seconds = (vtime.tms_utime + vtime.tms_stime) / 100.0;
25510923SN/A    minutes = seconds / 60.0;
25610923SN/A    hours = minutes / 60.0;
25711290Sgabor.dozsa@arm.com    days = hours / 24.0;
25811290Sgabor.dozsa@arm.com    out << "Virtual_time_in_seconds: " << seconds << endl;
25910923SN/A    out << "Virtual_time_in_minutes: " << minutes << endl;
26010923SN/A    out << "Virtual_time_in_hours:   " << hours << endl;
26111290Sgabor.dozsa@arm.com    out << "Virtual_time_in_days:    " << days << endl;
26211290Sgabor.dozsa@arm.com    out << endl;
26310923SN/A
26411290Sgabor.dozsa@arm.com    out << "Ruby_current_time: " << g_system_ptr->getTime() << endl;
26510923SN/A    out << "Ruby_start_time: " << m_ruby_start << endl;
26610923SN/A    out << "Ruby_cycles: " << ruby_cycles << endl;
26710923SN/A    out << endl;
268
269    if (!short_stats) {
270        out << "mbytes_resident: " << process_memory_resident() << endl;
271        out << "mbytes_total: " << process_memory_total() << endl;
272        if (process_memory_total() > 0) {
273            out << "resident_ratio: "
274                << process_memory_resident()/process_memory_total() << endl;
275        }
276        out << endl;
277    }
278
279    vector<int64_t> perProcCycleCount(m_num_of_sequencers);
280
281    for (int i = 0; i < m_num_of_sequencers; i++) {
282        perProcCycleCount[i] =
283            g_system_ptr->getTime() - m_cycles_executed_at_start[i] + 1;
284        // The +1 allows us to avoid division by zero
285    }
286
287    out << "ruby_cycles_executed: " << perProcCycleCount << endl;
288
289    out << endl;
290
291    if (!short_stats) {
292        out << "Busy Controller Counts:" << endl;
293        for (uint32_t i = 0; i < MachineType_NUM; i++) {
294            uint32_t size = MachineType_base_count((MachineType)i);
295
296            for (uint32_t j = 0; j < size; j++) {
297                MachineID machID;
298                machID.type = (MachineType)i;
299                machID.num = j;
300
301                AbstractController *ctr =
302                    (*(g_abs_controls[i].find(j))).second;
303                out << machID << ":" << ctr->getFullyBusyCycles() << "  ";
304                if ((j + 1) % 8 == 0) {
305                    out << endl;
306                }
307            }
308            out << endl;
309        }
310        out << endl;
311
312        out << "Busy Bank Count:" << m_busyBankCount << endl;
313        out << endl;
314
315        out << "sequencer_requests_outstanding: "
316            << m_sequencer_requests << endl;
317        out << endl;
318    }
319
320    if (!short_stats) {
321        out << "All Non-Zero Cycle Demand Cache Accesses" << endl;
322        out << "----------------------------------------" << endl;
323        out << "miss_latency: " << m_allMissLatencyHistogram << endl;
324        for (int i = 0; i < m_missLatencyHistograms.size(); i++) {
325            if (m_missLatencyHistograms[i].size() > 0) {
326                out << "miss_latency_" << RubyRequestType(i) << ": "
327                    << m_missLatencyHistograms[i] << endl;
328            }
329        }
330        for (int i = 0; i < m_machLatencyHistograms.size(); i++) {
331            if (m_machLatencyHistograms[i].size() > 0) {
332                out << "miss_latency_" << GenericMachineType(i) << ": "
333                    << m_machLatencyHistograms[i] << endl;
334            }
335        }
336
337        out << "miss_latency_wCC_issue_to_initial_request: "
338            << m_wCCIssueToInitialRequestHistogram << endl;
339        out << "miss_latency_wCC_initial_forward_request: "
340            << m_wCCInitialRequestToForwardRequestHistogram << endl;
341        out << "miss_latency_wCC_forward_to_first_response: "
342            << m_wCCForwardRequestToFirstResponseHistogram << endl;
343        out << "miss_latency_wCC_first_response_to_completion: "
344            << m_wCCFirstResponseToCompleteHistogram << endl;
345        out << "imcomplete_wCC_Times: " << m_wCCIncompleteTimes << endl;
346        out << "miss_latency_dir_issue_to_initial_request: "
347            << m_dirIssueToInitialRequestHistogram << endl;
348        out << "miss_latency_dir_initial_forward_request: "
349            << m_dirInitialRequestToForwardRequestHistogram << endl;
350        out << "miss_latency_dir_forward_to_first_response: "
351            << m_dirForwardRequestToFirstResponseHistogram << endl;
352        out << "miss_latency_dir_first_response_to_completion: "
353            << m_dirFirstResponseToCompleteHistogram << endl;
354        out << "imcomplete_dir_Times: " << m_dirIncompleteTimes << endl;
355
356        for (int i = 0; i < m_missMachLatencyHistograms.size(); i++) {
357            for (int j = 0; j < m_missMachLatencyHistograms[i].size(); j++) {
358                if (m_missMachLatencyHistograms[i][j].size() > 0) {
359                    out << "miss_latency_" << RubyRequestType(i)
360                        << "_" << GenericMachineType(j) << ": "
361                        << m_missMachLatencyHistograms[i][j] << endl;
362                }
363            }
364        }
365
366        out << endl;
367
368        out << "All Non-Zero Cycle SW Prefetch Requests" << endl;
369        out << "------------------------------------" << endl;
370        out << "prefetch_latency: " << m_allSWPrefetchLatencyHistogram << endl;
371        for (int i = 0; i < m_SWPrefetchLatencyHistograms.size(); i++) {
372            if (m_SWPrefetchLatencyHistograms[i].size() > 0) {
373                out << "prefetch_latency_" << RubyRequestType(i) << ": "
374                    << m_SWPrefetchLatencyHistograms[i] << endl;
375            }
376        }
377        for (int i = 0; i < m_SWPrefetchMachLatencyHistograms.size(); i++) {
378            if (m_SWPrefetchMachLatencyHistograms[i].size() > 0) {
379                out << "prefetch_latency_" << GenericMachineType(i) << ": "
380                    << m_SWPrefetchMachLatencyHistograms[i] << endl;
381            }
382        }
383        out << "prefetch_latency_L2Miss:"
384            << m_SWPrefetchL2MissLatencyHistogram << endl;
385
386        if (m_all_sharing_histogram.size() > 0) {
387            out << "all_sharing: " << m_all_sharing_histogram << endl;
388            out << "read_sharing: " << m_read_sharing_histogram << endl;
389            out << "write_sharing: " << m_write_sharing_histogram << endl;
390
391            out << "all_sharing_percent: ";
392            m_all_sharing_histogram.printPercent(out);
393            out << endl;
394
395            out << "read_sharing_percent: ";
396            m_read_sharing_histogram.printPercent(out);
397            out << endl;
398
399            out << "write_sharing_percent: ";
400            m_write_sharing_histogram.printPercent(out);
401            out << endl;
402
403            int64 total_miss = m_cache_to_cache +  m_memory_to_cache;
404            out << "all_misses: " << total_miss << endl;
405            out << "cache_to_cache_misses: " << m_cache_to_cache << endl;
406            out << "memory_to_cache_misses: " << m_memory_to_cache << endl;
407            out << "cache_to_cache_percent: "
408                << 100.0 * (double(m_cache_to_cache) / double(total_miss))
409                << endl;
410            out << "memory_to_cache_percent: "
411                << 100.0 * (double(m_memory_to_cache) / double(total_miss))
412                << endl;
413            out << endl;
414        }
415
416        if (m_outstanding_requests.size() > 0) {
417            out << "outstanding_requests: ";
418            m_outstanding_requests.printPercent(out);
419            out << endl;
420            out << endl;
421        }
422    }
423
424    if (!short_stats) {
425        printRequestProfile(out);
426
427        out << "filter_action: " << m_filter_action_histogram << endl;
428
429        if (!m_all_instructions) {
430            m_address_profiler_ptr->printStats(out);
431        }
432
433        if (m_all_instructions) {
434            m_inst_profiler_ptr->printStats(out);
435        }
436
437        out << endl;
438        out << "Message Delayed Cycles" << endl;
439        out << "----------------------" << endl;
440        out << "Total_delay_cycles: " <<   m_delayedCyclesHistogram << endl;
441        out << "Total_nonPF_delay_cycles: "
442            << m_delayedCyclesNonPFHistogram << endl;
443        for (int i = 0; i < m_delayedCyclesVCHistograms.size(); i++) {
444            out << "  virtual_network_" << i << "_delay_cycles: "
445                << m_delayedCyclesVCHistograms[i] << endl;
446        }
447
448        printResourceUsage(out);
449    }
450}
451
452void
453Profiler::printResourceUsage(ostream& out) const
454{
455    out << endl;
456    out << "Resource Usage" << endl;
457    out << "--------------" << endl;
458
459    int64_t pagesize = getpagesize(); // page size in bytes
460    out << "page_size: " << pagesize << endl;
461
462    rusage usage;
463    getrusage (RUSAGE_SELF, &usage);
464
465    out << "user_time: " << usage.ru_utime.tv_sec << endl;
466    out << "system_time: " << usage.ru_stime.tv_sec << endl;
467    out << "page_reclaims: " << usage.ru_minflt << endl;
468    out << "page_faults: " << usage.ru_majflt << endl;
469    out << "swaps: " << usage.ru_nswap << endl;
470    out << "block_inputs: " << usage.ru_inblock << endl;
471    out << "block_outputs: " << usage.ru_oublock << endl;
472}
473
474void
475Profiler::clearStats()
476{
477    m_ruby_start = g_system_ptr->getTime();
478    m_real_time_start_time = time(NULL);
479
480    m_cycles_executed_at_start.resize(m_num_of_sequencers);
481    for (int i = 0; i < m_num_of_sequencers; i++) {
482        if (g_system_ptr == NULL) {
483            m_cycles_executed_at_start[i] = 0;
484        } else {
485            m_cycles_executed_at_start[i] = g_system_ptr->getTime();
486        }
487    }
488
489    m_busyBankCount = 0;
490
491    m_delayedCyclesHistogram.clear();
492    m_delayedCyclesNonPFHistogram.clear();
493    int size = Network::getNumberOfVirtualNetworks();
494    m_delayedCyclesVCHistograms.resize(size);
495    for (int i = 0; i < size; i++) {
496        m_delayedCyclesVCHistograms[i].clear();
497    }
498
499    m_missLatencyHistograms.resize(RubyRequestType_NUM);
500    for (int i = 0; i < m_missLatencyHistograms.size(); i++) {
501        m_missLatencyHistograms[i].clear(200);
502    }
503    m_machLatencyHistograms.resize(GenericMachineType_NUM+1);
504    for (int i = 0; i < m_machLatencyHistograms.size(); i++) {
505        m_machLatencyHistograms[i].clear(200);
506    }
507    m_missMachLatencyHistograms.resize(RubyRequestType_NUM);
508    for (int i = 0; i < m_missLatencyHistograms.size(); i++) {
509        m_missMachLatencyHistograms[i].resize(GenericMachineType_NUM+1);
510        for (int j = 0; j < m_missMachLatencyHistograms[i].size(); j++) {
511            m_missMachLatencyHistograms[i][j].clear(200);
512        }
513    }
514    m_allMissLatencyHistogram.clear(200);
515    m_wCCIssueToInitialRequestHistogram.clear(200);
516    m_wCCInitialRequestToForwardRequestHistogram.clear(200);
517    m_wCCForwardRequestToFirstResponseHistogram.clear(200);
518    m_wCCFirstResponseToCompleteHistogram.clear(200);
519    m_wCCIncompleteTimes = 0;
520    m_dirIssueToInitialRequestHistogram.clear(200);
521    m_dirInitialRequestToForwardRequestHistogram.clear(200);
522    m_dirForwardRequestToFirstResponseHistogram.clear(200);
523    m_dirFirstResponseToCompleteHistogram.clear(200);
524    m_dirIncompleteTimes = 0;
525
526    m_SWPrefetchLatencyHistograms.resize(RubyRequestType_NUM);
527    for (int i = 0; i < m_SWPrefetchLatencyHistograms.size(); i++) {
528        m_SWPrefetchLatencyHistograms[i].clear(200);
529    }
530    m_SWPrefetchMachLatencyHistograms.resize(GenericMachineType_NUM+1);
531    for (int i = 0; i < m_SWPrefetchMachLatencyHistograms.size(); i++) {
532        m_SWPrefetchMachLatencyHistograms[i].clear(200);
533    }
534    m_allSWPrefetchLatencyHistogram.clear(200);
535
536    m_sequencer_requests.clear();
537    m_read_sharing_histogram.clear();
538    m_write_sharing_histogram.clear();
539    m_all_sharing_histogram.clear();
540    m_cache_to_cache = 0;
541    m_memory_to_cache = 0;
542
543    m_outstanding_requests.clear();
544    m_outstanding_persistent_requests.clear();
545
546    // Flush the prefetches through the system - used so that there
547    // are no outstanding requests after stats are cleared
548    //g_eventQueue_ptr->triggerAllEvents();
549
550    // update the start time
551    m_ruby_start = g_system_ptr->getTime();
552}
553
554void
555Profiler::addAddressTraceSample(const RubyRequest& msg, NodeID id)
556{
557    if (msg.getType() != RubyRequestType_IFETCH) {
558        // Note: The following line should be commented out if you
559        // want to use the special profiling that is part of the GS320
560        // protocol
561
562        // NOTE: Unless PROFILE_HOT_LINES is enabled, nothing will be
563        // profiled by the AddressProfiler
564        m_address_profiler_ptr->
565            addTraceSample(msg.getLineAddress(), msg.getProgramCounter(),
566                           msg.getType(), msg.getAccessMode(), id, false);
567    }
568}
569
570void
571Profiler::profileSharing(const Address& addr, AccessType type,
572                         NodeID requestor, const Set& sharers,
573                         const Set& owner)
574{
575    Set set_contacted(owner);
576    if (type == AccessType_Write) {
577        set_contacted.addSet(sharers);
578    }
579    set_contacted.remove(requestor);
580    int number_contacted = set_contacted.count();
581
582    if (type == AccessType_Write) {
583        m_write_sharing_histogram.add(number_contacted);
584    } else {
585        m_read_sharing_histogram.add(number_contacted);
586    }
587    m_all_sharing_histogram.add(number_contacted);
588
589    if (number_contacted == 0) {
590        m_memory_to_cache++;
591    } else {
592        m_cache_to_cache++;
593    }
594}
595
596void
597Profiler::profileMsgDelay(uint32_t virtualNetwork, Time delayCycles)
598{
599    assert(virtualNetwork < m_delayedCyclesVCHistograms.size());
600    m_delayedCyclesHistogram.add(delayCycles);
601    m_delayedCyclesVCHistograms[virtualNetwork].add(delayCycles);
602    if (virtualNetwork != 0) {
603        m_delayedCyclesNonPFHistogram.add(delayCycles);
604    }
605}
606
607void
608Profiler::profilePFWait(Time waitTime)
609{
610    m_prefetchWaitHistogram.add(waitTime);
611}
612
613void
614Profiler::bankBusy()
615{
616    m_busyBankCount++;
617}
618
619// non-zero cycle demand request
620void
621Profiler::missLatency(Time cycles,
622                      RubyRequestType type,
623                      const GenericMachineType respondingMach)
624{
625    m_allMissLatencyHistogram.add(cycles);
626    m_missLatencyHistograms[type].add(cycles);
627    m_machLatencyHistograms[respondingMach].add(cycles);
628    m_missMachLatencyHistograms[type][respondingMach].add(cycles);
629}
630
631void
632Profiler::missLatencyWcc(Time issuedTime,
633                         Time initialRequestTime,
634                         Time forwardRequestTime,
635                         Time firstResponseTime,
636                         Time completionTime)
637{
638    if ((issuedTime <= initialRequestTime) &&
639        (initialRequestTime <= forwardRequestTime) &&
640        (forwardRequestTime <= firstResponseTime) &&
641        (firstResponseTime <= completionTime)) {
642        m_wCCIssueToInitialRequestHistogram.add(initialRequestTime - issuedTime);
643
644        m_wCCInitialRequestToForwardRequestHistogram.add(forwardRequestTime -
645                                                         initialRequestTime);
646
647        m_wCCForwardRequestToFirstResponseHistogram.add(firstResponseTime -
648                                                        forwardRequestTime);
649
650        m_wCCFirstResponseToCompleteHistogram.add(completionTime -
651                                                  firstResponseTime);
652    } else {
653        m_wCCIncompleteTimes++;
654    }
655}
656
657void
658Profiler::missLatencyDir(Time issuedTime,
659                         Time initialRequestTime,
660                         Time forwardRequestTime,
661                         Time firstResponseTime,
662                         Time completionTime)
663{
664    if ((issuedTime <= initialRequestTime) &&
665        (initialRequestTime <= forwardRequestTime) &&
666        (forwardRequestTime <= firstResponseTime) &&
667        (firstResponseTime <= completionTime)) {
668        m_dirIssueToInitialRequestHistogram.add(initialRequestTime - issuedTime);
669
670        m_dirInitialRequestToForwardRequestHistogram.add(forwardRequestTime -
671                                                         initialRequestTime);
672
673        m_dirForwardRequestToFirstResponseHistogram.add(firstResponseTime -
674                                                        forwardRequestTime);
675
676        m_dirFirstResponseToCompleteHistogram.add(completionTime -
677                                                  firstResponseTime);
678    } else {
679        m_dirIncompleteTimes++;
680    }
681}
682
683// non-zero cycle prefetch request
684void
685Profiler::swPrefetchLatency(Time cycles,
686                            RubyRequestType type,
687                            const GenericMachineType respondingMach)
688{
689    m_allSWPrefetchLatencyHistogram.add(cycles);
690    m_SWPrefetchLatencyHistograms[type].add(cycles);
691    m_SWPrefetchMachLatencyHistograms[respondingMach].add(cycles);
692    if (respondingMach == GenericMachineType_Directory ||
693        respondingMach == GenericMachineType_NUM) {
694        m_SWPrefetchL2MissLatencyHistogram.add(cycles);
695    }
696}
697
698// Helper function
699static double
700process_memory_total()
701{
702    // 4kB page size, 1024*1024 bytes per MB,
703    const double MULTIPLIER = 4096.0 / (1024.0 * 1024.0);
704    ifstream proc_file;
705    proc_file.open("/proc/self/statm");
706    int total_size_in_pages = 0;
707    int res_size_in_pages = 0;
708    proc_file >> total_size_in_pages;
709    proc_file >> res_size_in_pages;
710    return double(total_size_in_pages) * MULTIPLIER; // size in megabytes
711}
712
713static double
714process_memory_resident()
715{
716    // 4kB page size, 1024*1024 bytes per MB,
717    const double MULTIPLIER = 4096.0 / (1024.0 * 1024.0);
718    ifstream proc_file;
719    proc_file.open("/proc/self/statm");
720    int total_size_in_pages = 0;
721    int res_size_in_pages = 0;
722    proc_file >> total_size_in_pages;
723    proc_file >> res_size_in_pages;
724    return double(res_size_in_pages) * MULTIPLIER; // size in megabytes
725}
726
727void
728Profiler::rubyWatch(int id)
729{
730    uint64 tr = 0;
731    Address watch_address = Address(tr);
732
733    DPRINTFN("%7s %3s RUBY WATCH %d\n", g_system_ptr->getTime(), id,
734        watch_address);
735
736    // don't care about success or failure
737    m_watch_address_set.insert(watch_address);
738}
739
740bool
741Profiler::watchAddress(Address addr)
742{
743    return m_watch_address_set.count(addr) > 0;
744}
745
746Profiler *
747RubyProfilerParams::create()
748{
749    return new Profiler(this);
750}
751