11917SN/A/* 21917SN/A * Copyright (c) 2005 The Regents of The University of Michigan 31917SN/A * All rights reserved. 41917SN/A * 51917SN/A * Redistribution and use in source and binary forms, with or without 61917SN/A * modification, are permitted provided that the following conditions are 71917SN/A * met: redistributions of source code must retain the above copyright 81917SN/A * notice, this list of conditions and the following disclaimer; 91917SN/A * redistributions in binary form must reproduce the above copyright 101917SN/A * notice, this list of conditions and the following disclaimer in the 111917SN/A * documentation and/or other materials provided with the distribution; 121917SN/A * neither the name of the copyright holders nor the names of its 131917SN/A * contributors may be used to endorse or promote products derived from 141917SN/A * this software without specific prior written permission. 151917SN/A * 161917SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 171917SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 181917SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 191917SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 201917SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 211917SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 221917SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 231917SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 241917SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 251917SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 261917SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 272665Ssaidi@eecs.umich.edu * 282665Ssaidi@eecs.umich.edu * Authors: Nathan Binkert 291917SN/A */ 301917SN/A 3111793Sbrandon.potter@amd.com#include "cpu/profile.hh" 3211793Sbrandon.potter@amd.com 331917SN/A#include <string> 341917SN/A 351917SN/A#include "base/bitfield.hh" 361981SN/A#include "base/callback.hh" 3711793Sbrandon.potter@amd.com#include "base/loader/symtab.hh" 381981SN/A#include "base/statistics.hh" 391917SN/A#include "base/trace.hh" 401917SN/A#include "cpu/base.hh" 412680Sktlim@umich.edu#include "cpu/thread_context.hh" 421917SN/A 431917SN/Ausing namespace std; 441917SN/A 451917SN/AProfileNode::ProfileNode() 461917SN/A : count(0) 471917SN/A{ } 481917SN/A 491917SN/Avoid 501917SN/AProfileNode::dump(const string &symbol, uint64_t id, const SymbolTable *symtab, 511917SN/A ostream &os) const 521917SN/A{ 531917SN/A ccprintf(os, "%#x %s %d ", id, symbol, count); 541917SN/A ChildList::const_iterator i, end = children.end(); 551917SN/A for (i = children.begin(); i != end; ++i) { 561977SN/A const ProfileNode *node = i->second; 571977SN/A ccprintf(os, "%#x ", (intptr_t)node); 581917SN/A } 591917SN/A 601917SN/A ccprintf(os, "\n"); 611917SN/A 621917SN/A for (i = children.begin(); i != end; ++i) { 631917SN/A Addr addr = i->first; 641917SN/A string symbol; 651917SN/A if (addr == 1) 661917SN/A symbol = "user"; 671917SN/A else if (addr == 2) 681917SN/A symbol = "console"; 691917SN/A else if (addr == 3) 701917SN/A symbol = "unknown"; 711917SN/A else if (!symtab->findSymbol(addr, symbol)) 721917SN/A panic("could not find symbol for address %#x\n", addr); 731917SN/A 741977SN/A const ProfileNode *node = i->second; 751977SN/A node->dump(symbol, (intptr_t)node, symtab, os); 761917SN/A } 771917SN/A} 781917SN/A 791917SN/Avoid 801917SN/AProfileNode::clear() 811917SN/A{ 821917SN/A count = 0; 831917SN/A ChildList::iterator i, end = children.end(); 841977SN/A for (i = children.begin(); i != end; ++i) 851977SN/A i->second->clear(); 861917SN/A} 871917SN/A 881917SN/AFunctionProfile::FunctionProfile(const SymbolTable *_symtab) 891981SN/A : reset(0), symtab(_symtab) 901917SN/A{ 911981SN/A reset = new MakeCallback<FunctionProfile, &FunctionProfile::clear>(this); 921981SN/A Stats::registerResetCallback(reset); 931917SN/A} 941917SN/A 951917SN/AFunctionProfile::~FunctionProfile() 961917SN/A{ 971981SN/A if (reset) 981981SN/A delete reset; 991917SN/A} 1001917SN/A 1011917SN/AProfileNode * 1021977SN/AFunctionProfile::consume(const vector<Addr> &stack) 1031917SN/A{ 1041917SN/A ProfileNode *current = ⊤ 1051977SN/A for (int i = 0, size = stack.size(); i < size; ++i) { 1061977SN/A ProfileNode *&ptr = current->children[stack[size - i - 1]]; 1071977SN/A if (ptr == NULL) 1081977SN/A ptr = new ProfileNode; 1091977SN/A 1101977SN/A current = ptr; 1111977SN/A } 1121917SN/A 1131917SN/A return current; 1141917SN/A} 1151917SN/A 1161917SN/Avoid 1171917SN/AFunctionProfile::clear() 1181917SN/A{ 1191917SN/A top.clear(); 1201917SN/A pc_count.clear(); 1211917SN/A} 1221917SN/A 1231917SN/Avoid 1242680Sktlim@umich.eduFunctionProfile::dump(ThreadContext *tc, ostream &os) const 1251917SN/A{ 1261917SN/A ccprintf(os, ">>>PC data\n"); 1271917SN/A map<Addr, Counter>::const_iterator i, end = pc_count.end(); 1281917SN/A for (i = pc_count.begin(); i != end; ++i) { 1291917SN/A Addr pc = i->first; 1301917SN/A Counter count = i->second; 1311917SN/A 1321917SN/A std::string symbol; 1331917SN/A if (pc == 1) 1341917SN/A ccprintf(os, "user %d\n", count); 1351917SN/A else if (symtab->findSymbol(pc, symbol) && !symbol.empty()) 1361917SN/A ccprintf(os, "%s %d\n", symbol, count); 1371917SN/A else 1381917SN/A ccprintf(os, "%#x %d\n", pc, count); 1391917SN/A } 1401917SN/A 1411917SN/A ccprintf(os, ">>>function data\n"); 1421917SN/A top.dump("top", 0, symtab, os); 1431917SN/A} 1441917SN/A 1451917SN/Avoid 1461917SN/AFunctionProfile::sample(ProfileNode *node, Addr pc) 1471917SN/A{ 1481917SN/A node->count++; 1491917SN/A 1501917SN/A Addr symaddr; 1511917SN/A if (symtab->findNearestAddr(pc, symaddr)) { 1521917SN/A pc_count[symaddr]++; 1531917SN/A } else { 1541917SN/A // record PC even if we don't have a symbol to avoid 1551917SN/A // silently biasing the histogram 1561917SN/A pc_count[pc]++; 1571917SN/A } 1581917SN/A} 159