BasicImporter is renamed to MemoryImporter. An alias for BasicImporter in the cmdline interface will remain. The MemoryImporter does now only handle memory and IP events. The simulation time, dynamic instruction count and handling of open ECs is moved to Importer. Change-Id: I04eb0fd4b52fbf5b0ca9ab97778a62130cb626ee
58 lines
2.1 KiB
C++
58 lines
2.1 KiB
C++
#include "util/Logger.hpp"
|
|
#include "MemoryImporter.hpp"
|
|
|
|
using namespace fail;
|
|
static fail::Logger LOG("MemoryImporter");
|
|
|
|
|
|
bool MemoryImporter::handle_ip_event(simtime_t curtime, instruction_count_t instr, const Trace_Event &ev) {
|
|
return true;
|
|
}
|
|
|
|
bool MemoryImporter::handle_mem_event(simtime_t curtime, instruction_count_t instr,
|
|
const Trace_Event &ev) {
|
|
address_t from = ev.memaddr(), to = ev.memaddr() + ev.width();
|
|
// Iterate over all accessed bytes
|
|
// FIXME Keep complete trace information (access width)?
|
|
// advantages: may be used for pruning strategies, complete value would be visible; less DB entries
|
|
// disadvantages: may need splitting when width varies, lots of special case handling
|
|
// Probably implement this in a separate importer when necessary.
|
|
for (address_t data_address = from; data_address < to; ++data_address) {
|
|
// skip events outside a possibly supplied memory map
|
|
if (m_mm && !m_mm->isMatching(data_address)) {
|
|
continue;
|
|
}
|
|
margin_info_t left_margin = getOpenEC(data_address);
|
|
margin_info_t right_margin;
|
|
right_margin.time = curtime;
|
|
right_margin.dyninstr = instr; // !< The current instruction
|
|
right_margin.ip = ev.ip();
|
|
|
|
// skip zero-sized intervals: these can occur when an instruction
|
|
// accesses a memory location more than once (e.g., INC, CMPXCHG)
|
|
// FIXME: look at timing instead?
|
|
if (left_margin.dyninstr > right_margin.dyninstr) {
|
|
continue;
|
|
}
|
|
|
|
// we now have an interval-terminating R/W event to the memaddr
|
|
// we're currently looking at; the EC is defined by
|
|
// data_address, dynamic instruction start/end, the absolute PC at
|
|
// the end, and time start/end
|
|
access_info_t access;
|
|
access.access_type = ev.accesstype() == ev.READ ? 'R' : 'W';
|
|
access.data_address = data_address;
|
|
access.data_width = 1; // exactly one byte
|
|
if (!add_trace_event(left_margin, right_margin, access)) {
|
|
LOG << "add_trace_event failed" << std::endl;
|
|
return false;
|
|
}
|
|
|
|
// next interval must start at next instruction; the aforementioned
|
|
// skipping mechanism wouldn't work otherwise
|
|
newOpenEC(data_address, curtime + 1, instr + 1, ev.ip());
|
|
}
|
|
return true;
|
|
}
|
|
|