#include <sstream>
#include <iostream>
-#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"
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)
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
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<BaseCPU, &BaseCPU::enableFunctionTrace>(this,
+ true);
+ e->schedule(_function_trace_start);
+ }
+ }
}
+
+void
+BaseCPU::enableFunctionTrace()
+{
+ functionTracingEnabled = true;
+}
+
+BaseCPU::~BaseCPU()
+{
+ if (functionTracingEnabled)
+ closeOutputStream(functionTraceStream);
+}
+
+
void
BaseCPU::init()
{
#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)
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();
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<BaseCPU *> cpuList; //!< Static global cpu list
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,
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)
{
if (traceData)
traceData->finalize();
+ traceFunctions(xc->regs.pc);
+
} // if (fault == No_Fault)
if (fault != No_Fault) {
Param<bool> defer_registration;
Param<int> multiplier;
+ Param<bool> function_trace;
+ Param<Tick> function_trace_start;
END_DECLARE_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)
(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,
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
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
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