diff --git a/cpu/base_cpu.cc b/cpu/base_cpu.cc index e4dd744a6..7605ff3c3 100644 --- a/cpu/base_cpu.cc +++ b/cpu/base_cpu.cc @@ -30,10 +30,11 @@ #include #include -#include "cpu/base_cpu.hh" #include "base/cprintf.hh" -#include "cpu/exec_context.hh" +#include "base/loader/symtab.hh" #include "base/misc.hh" +#include "cpu/base_cpu.hh" +#include "cpu/exec_context.hh" #include "sim/param.hh" #include "sim/sim_events.hh" @@ -52,7 +53,8 @@ BaseCPU::BaseCPU(const string &_name, int _number_of_threads, bool _def_reg, Counter max_insts_all_threads, Counter max_loads_any_thread, Counter max_loads_all_threads, - System *_system, Tick freq) + System *_system, Tick freq, + bool _function_trace, Tick _function_trace_start) : SimObject(_name), frequency(freq), checkInterrupts(true), deferRegistration(_def_reg), number_of_threads(_number_of_threads), system(_system) @@ -61,7 +63,8 @@ BaseCPU::BaseCPU(const string &_name, int _number_of_threads, bool _def_reg, Counter max_insts_any_thread, Counter max_insts_all_threads, Counter max_loads_any_thread, - Counter max_loads_all_threads) + Counter max_loads_all_threads, + bool _function_trace, Tick _function_trace_start) : SimObject(_name), deferRegistration(_def_reg), number_of_threads(_number_of_threads) #endif @@ -126,8 +129,39 @@ BaseCPU::BaseCPU(const string &_name, int _number_of_threads, bool _def_reg, memset(interrupts, 0, sizeof(interrupts)); intstatus = 0; #endif + + functionTracingEnabled = false; + if (_function_trace) { + std::string filename = csprintf("ftrace.%s", name()); + functionTraceStream = makeOutputStream(filename); + currentFunctionStart = currentFunctionEnd = 0; + functionEntryTick = _function_trace_start; + + if (_function_trace_start == 0) { + functionTracingEnabled = true; + } else { + Event *e = + new EventWrapper(this, + true); + e->schedule(_function_trace_start); + } + } } + +void +BaseCPU::enableFunctionTrace() +{ + functionTracingEnabled = true; +} + +BaseCPU::~BaseCPU() +{ + if (functionTracingEnabled) + closeOutputStream(functionTraceStream); +} + + void BaseCPU::init() { @@ -267,4 +301,32 @@ BaseCPU::unserialize(Checkpoint *cp, const std::string §ion) #endif // FULL_SYSTEM +void +BaseCPU::traceFunctionsInternal(Addr pc) +{ + if (!debugSymbolTable) + return; + + // if pc enters different function, print new function symbol and + // update saved range. Otherwise do nothing. + if (pc < currentFunctionStart || pc >= currentFunctionEnd) { + string sym_str; + bool found = debugSymbolTable->findNearestSymbol(pc, sym_str, + currentFunctionStart, + currentFunctionEnd); + + if (!found) { + // no symbol found: use addr as label + sym_str = csprintf("0x%x", pc); + currentFunctionStart = pc; + currentFunctionEnd = pc + 1; + } + + ccprintf(*functionTraceStream, " (%d)\n%d: %s", + curTick - functionEntryTick, curTick, sym_str); + functionEntryTick = curTick; + } +} + + DEFINE_SIM_OBJECT_CLASS_NAME("BaseCPU", BaseCPU) diff --git a/cpu/base_cpu.hh b/cpu/base_cpu.hh index 8668c3216..baa956aa8 100644 --- a/cpu/base_cpu.hh +++ b/cpu/base_cpu.hh @@ -95,16 +95,18 @@ class BaseCPU : public SimObject BaseCPU(const std::string &_name, int _number_of_threads, bool _def_reg, Counter max_insts_any_thread, Counter max_insts_all_threads, Counter max_loads_any_thread, Counter max_loads_all_threads, - System *_system, Tick freq); + System *_system, Tick freq, + bool _function_trace = false, Tick _function_trace_start = 0); #else BaseCPU(const std::string &_name, int _number_of_threads, bool _def_reg, Counter max_insts_any_thread = 0, Counter max_insts_all_threads = 0, Counter max_loads_any_thread = 0, - Counter max_loads_all_threads = 0); + Counter max_loads_all_threads = 0, + bool _function_trace = false, Tick _function_trace_start = 0); #endif - virtual ~BaseCPU() {} + virtual ~BaseCPU(); virtual void init(); virtual void regStats(); @@ -166,6 +168,23 @@ class BaseCPU : public SimObject virtual Counter totalInstructions() const { return 0; } + // Function tracing + private: + bool functionTracingEnabled; + std::ostream *functionTraceStream; + Addr currentFunctionStart; + Addr currentFunctionEnd; + Tick functionEntryTick; + void enableFunctionTrace(); + void traceFunctionsInternal(Addr pc); + + protected: + void traceFunctions(Addr pc) + { + if (functionTracingEnabled) + traceFunctionsInternal(pc); + } + private: static std::vector cpuList; //!< Static global cpu list diff --git a/cpu/simple_cpu/simple_cpu.cc b/cpu/simple_cpu/simple_cpu.cc index 04783574f..d48f93663 100644 --- a/cpu/simple_cpu/simple_cpu.cc +++ b/cpu/simple_cpu/simple_cpu.cc @@ -123,11 +123,12 @@ SimpleCPU::SimpleCPU(const string &_name, FunctionalMemory *mem, MemInterface *icache_interface, MemInterface *dcache_interface, - bool _def_reg, Tick freq) + bool _def_reg, Tick freq, + bool _function_trace, Tick _function_trace_start) : BaseCPU(_name, /* number_of_threads */ 1, _def_reg, max_insts_any_thread, max_insts_all_threads, max_loads_any_thread, max_loads_all_threads, - _system, freq), + _system, freq, _function_trace, _function_trace_start), #else SimpleCPU::SimpleCPU(const string &_name, Process *_process, Counter max_insts_any_thread, @@ -136,10 +137,12 @@ SimpleCPU::SimpleCPU(const string &_name, Process *_process, Counter max_loads_all_threads, MemInterface *icache_interface, MemInterface *dcache_interface, - bool _def_reg) + bool _def_reg, + bool _function_trace, Tick _function_trace_start) : BaseCPU(_name, /* number_of_threads */ 1, _def_reg, max_insts_any_thread, max_insts_all_threads, - max_loads_any_thread, max_loads_all_threads), + max_loads_any_thread, max_loads_all_threads, + _function_trace, _function_trace_start), #endif tickEvent(this), xc(NULL), cacheCompletionEvent(this) { @@ -778,6 +781,8 @@ SimpleCPU::tick() if (traceData) traceData->finalize(); + traceFunctions(xc->regs.pc); + } // if (fault == No_Fault) if (fault != No_Fault) { @@ -836,6 +841,8 @@ BEGIN_DECLARE_SIM_OBJECT_PARAMS(SimpleCPU) Param defer_registration; Param multiplier; + Param function_trace; + Param function_trace_start; END_DECLARE_SIM_OBJECT_PARAMS(SimpleCPU) @@ -869,7 +876,9 @@ BEGIN_INIT_SIM_OBJECT_PARAMS(SimpleCPU) INIT_PARAM_DFLT(defer_registration, "defer registration with system " "(for sampling)", false), - INIT_PARAM_DFLT(multiplier, "clock multiplier", 1) + INIT_PARAM_DFLT(multiplier, "clock multiplier", 1), + INIT_PARAM_DFLT(function_trace, "Enable function trace", false), + INIT_PARAM_DFLT(function_trace_start, "Cycle to start function trace", 0) END_INIT_SIM_OBJECT_PARAMS(SimpleCPU) @@ -888,7 +897,8 @@ CREATE_SIM_OBJECT(SimpleCPU) (icache) ? icache->getInterface() : NULL, (dcache) ? dcache->getInterface() : NULL, defer_registration, - ticksPerSecond * mult); + ticksPerSecond * mult, + function_trace, function_trace_start); #else cpu = new SimpleCPU(getInstanceName(), workload, @@ -896,7 +906,8 @@ CREATE_SIM_OBJECT(SimpleCPU) max_loads_any_thread, max_loads_all_threads, (icache) ? icache->getInterface() : NULL, (dcache) ? dcache->getInterface() : NULL, - defer_registration); + defer_registration, + function_trace, function_trace_start); #endif // FULL_SYSTEM diff --git a/cpu/simple_cpu/simple_cpu.hh b/cpu/simple_cpu/simple_cpu.hh index 8ea100b22..341a0da23 100644 --- a/cpu/simple_cpu/simple_cpu.hh +++ b/cpu/simple_cpu/simple_cpu.hh @@ -142,7 +142,8 @@ class SimpleCPU : public BaseCPU Counter max_loads_any_thread, Counter max_loads_all_threads, AlphaITB *itb, AlphaDTB *dtb, FunctionalMemory *mem, MemInterface *icache_interface, MemInterface *dcache_interface, - bool _def_reg, Tick freq); + bool _def_reg, Tick freq, + bool _function_trace, Tick _function_trace_start); #else @@ -152,7 +153,8 @@ class SimpleCPU : public BaseCPU Counter max_loads_any_thread, Counter max_loads_all_threads, MemInterface *icache_interface, MemInterface *dcache_interface, - bool _def_reg); + bool _def_reg, + bool _function_trace, Tick _function_trace_start); #endif