Files
fail/src/plugins/tracing/TracingPlugin.cc
Horst Schirmeier 64034e29b4 tracing: bugfix: advance prevtime only if delta was recorded
This change implements what the source-code comment already promised but
didn't keep: As we only record time deltas instead of absolute time values,
prevtime must not be overwritten unless the current delta was really added
to the trace.  This has caused timing information to be stored incorrectly
if certain events were skipped (e.g., because they didn't match the memory
map configured by the user).

Change-Id: Id40271d117dd91b1122136c62329d64174f304b0
2013-10-17 19:07:35 +02:00

136 lines
3.5 KiB
C++

#include <iostream>
#include <assert.h>
#include "sal/SALInst.hpp"
#include "sal/Register.hpp"
#include "sal/Memory.hpp"
#include "sal/Listener.hpp"
#include "TracingPlugin.hpp"
using namespace std;
using namespace fail;
bool TracingPlugin::run()
{
MemoryManager& mm = simulator.getMemoryManager();
MemAccessListener ev_mem(ANY_ADDR);
BPSingleListener ev_step(ANY_ADDR);
BaseListener *ev = 0;
// ev_step is added in the first loop iteration
if (m_memonly || !m_iponly) {
simulator.addListener(&ev_mem);
}
if(m_protoStreamFile) {
ps = new ProtoOStream(m_protoStreamFile);
}
UniformRegisterSet *extended_trace_regs =
simulator.getCPU(0).getRegisterSetOfType(RT_TRACE);
// the first event gets an absolute time stamp, all others a delta to their
// predecessor
simtime_t prevtime = 0, curtime;
simtime_diff_t deltatime;
bool first = true;
while (true) {
curtime = simulator.getTimerTicks();
deltatime = curtime - prevtime;
if (ev == &ev_step || (first && (m_iponly || !m_memonly))) {
first = false;
simulator.addListener(&ev_step);
address_t ip = simulator.getCPU(0).getInstructionPointer();
if (m_ipMap && !m_ipMap->isMatching(ip)) {
continue;
}
if (m_os)
*m_os << "[Tracing] IP " << hex << ip << "\n";
if (m_protoStreamFile) {
Trace_Event e;
e.set_ip(ip);
// only store deltas != 0
if (deltatime != 0) {
e.set_time_delta(deltatime);
// do this only if the last delta was written
// (no, e.g., memory map mismatch)
prevtime = curtime;
}
ps->writeMessage(&e);
}
} else if (ev == &ev_mem) {
simulator.addListener(&ev_mem);
address_t ip = ev_mem.getTriggerInstructionPointer();
address_t addr = ev_mem.getTriggerAddress();
size_t width = ev_mem.getTriggerWidth();
if ((m_ipMap && !m_ipMap->isMatching(ip)) ||
(m_memMap && !m_memMap->isMatching(addr, width))) {
continue;
}
if (m_os)
*m_os << hex << "[Tracing] MEM "
<< ((ev_mem.getTriggerAccessType() &
MemAccessEvent::MEM_READ) ? "R " : "W ")
<< addr << " width " << width << " IP " << ip << "\n";
if (m_protoStreamFile) {
Trace_Event e;
e.set_ip(ip);
e.set_memaddr(addr);
e.set_width(width);
e.set_accesstype(
(ev_mem.getTriggerAccessType() & MemAccessEvent::MEM_READ) ?
e.READ : e.WRITE);
// only store deltas != 0
if (deltatime != 0) {
e.set_time_delta(deltatime);
// do this only if the last delta was written
// (no, e.g., memory map mismatch)
prevtime = curtime;
}
/* When we're doing a full trace, we log more data in
the case of a memory event */
if (m_full_trace) {
Trace_Event_Extended &ext = *e.mutable_trace_ext();
// Read the accessed data
assert(width <= 8);
uint64_t data = 0;
mm.getBytes(addr, width, &data);
ext.set_data(data);
for (UniformRegisterSet::iterator it = extended_trace_regs->begin();
it != extended_trace_regs->end(); ++it) {
Trace_Event_Extended_Registers *er = ext.add_registers();
er->set_id((*it)->getId());
er->set_value(simulator.getCPU(0).getRegisterContent(*it));
if (er->value() <= mm.getPoolSize() - 4) {
uint32_t value_deref;
mm.getBytes(er->value(), 4, &value_deref);
er->set_value_deref(value_deref);
}
}
}
ps->writeMessage(&e);
}
} else if (!first) {
if (m_os)
*m_os << "[Tracing] SOMETHING IS SERIOUSLY WRONG\n";
}
ev = simulator.resume();
}
return true;
}