Initial commit
This commit is contained in:
106
dram_tracer.cpp
Normal file
106
dram_tracer.cpp
Normal file
@@ -0,0 +1,106 @@
|
||||
#include "dram_tracer.h"
|
||||
#include "build_options.h"
|
||||
#include "dram_tracer_create.h"
|
||||
#include "drmemtrace/trace_entry.h"
|
||||
|
||||
#include <cstdint>
|
||||
#include <filesystem>
|
||||
#include <fmt/core.h>
|
||||
#include <iostream>
|
||||
#include <tuple>
|
||||
#include <utility>
|
||||
|
||||
analysis_tool_t *dram_tracer_create(const std::string &output_dir)
|
||||
{
|
||||
return new dram_tracer(output_dir);
|
||||
}
|
||||
|
||||
dram_tracer::dram_tracer(std::string_view output_dir) : output_dir(output_dir)
|
||||
{}
|
||||
|
||||
bool dram_tracer::process_memref(const memref_t &memref)
|
||||
{
|
||||
// For online tracing we do not know beforehand how many threads there will be,
|
||||
// so we need to keep track of them dynamically.
|
||||
if (memref.marker.type == TRACE_TYPE_MARKER && memref.marker.marker_type == TRACE_MARKER_TYPE_TIMESTAMP &&
|
||||
memref.marker.tid != 0) {
|
||||
|
||||
tid_t tid = memref.marker.tid;
|
||||
|
||||
if (thread_ids.find(tid) == thread_ids.end()) {
|
||||
// Store all thread ids of the process in a set.
|
||||
thread_ids.emplace(memref.marker.tid);
|
||||
|
||||
// Create a new trace file for the thread.
|
||||
if (output_dir.empty())
|
||||
output_dir = fmt::format("dramsys.trace.{}.dir", memref.marker.pid);
|
||||
|
||||
std::filesystem::create_directory(output_dir);
|
||||
|
||||
if constexpr (build_options.binary_output) {
|
||||
trace_files.try_emplace(
|
||||
tid, output_dir / fmt::format("dramsys.trace.{}.{}.bin", memref.marker.pid, tid), std::ios::binary);
|
||||
} else {
|
||||
trace_files.try_emplace(
|
||||
tid, output_dir / fmt::format("dramsys.trace.{}.{}.trace", memref.marker.pid, tid), std::ios::out);
|
||||
|
||||
// Print a header as comment
|
||||
trace_files[tid] << "# instruction count,read/write,data size,data address\n"
|
||||
<< "# <timestamp>\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (type_is_instr(memref.instr.type)) {
|
||||
++instruction_counts[memref.instr.tid];
|
||||
} else if (memref.data.type == TRACE_TYPE_READ || memref.data.type == TRACE_TYPE_WRITE) {
|
||||
addr_t address = memref.data.addr;
|
||||
size_t size = memref.data.size;
|
||||
tid_t tid = memref.data.tid;
|
||||
|
||||
// One instruction can issue multiple data accesses, for example a read and a write.
|
||||
// Do not substract 1 in this case.
|
||||
instr_count_t instruction_count = instruction_counts[memref.data.tid] == 0
|
||||
? instruction_counts[memref.data.tid]
|
||||
: instruction_counts[memref.data.tid] - 1;
|
||||
|
||||
if constexpr (build_options.debug_output) {
|
||||
std::string_view access_string = memref.data.type == TRACE_TYPE_READ ? "Read" : "Write";
|
||||
fmt::print("[{}] {} at address 0x{:x} with size {} after {} instructions.\n", memref.data.tid,
|
||||
access_string, address, size, instruction_count);
|
||||
}
|
||||
|
||||
if constexpr (build_options.binary_output) {
|
||||
trace_files[tid] << BinaryTraceEntry(
|
||||
BinaryTraceEntry::DataRef(instruction_count, memref.data.type == TRACE_TYPE_WRITE, size, address));
|
||||
} else {
|
||||
std::string_view access_type = memref.data.type == TRACE_TYPE_READ ? "r" : "w";
|
||||
trace_files[tid] << fmt::format("{},{},{},{:x}\n", instruction_count, access_type, size, address);
|
||||
}
|
||||
|
||||
instruction_counts[memref.data.tid] = 0;
|
||||
++data_references;
|
||||
} else if (memref.marker.type == TRACE_TYPE_MARKER && memref.marker.marker_type == TRACE_MARKER_TYPE_TIMESTAMP) {
|
||||
// Each 32KB block of thread data has a timestamp, allowing reconstructing
|
||||
// the thread interleaving at that granularity.
|
||||
// We place the thread specific timestamp into the trace so that the thread player
|
||||
// can wait on other threads to progress at least to this point in time.
|
||||
|
||||
uint64_t timestamp = memref.marker.marker_value;
|
||||
tid_t tid = memref.marker.tid;
|
||||
|
||||
if constexpr (build_options.binary_output) {
|
||||
trace_files[tid] << BinaryTraceEntry(BinaryTraceEntry::Timestamp(timestamp));
|
||||
} else {
|
||||
trace_files[tid] << fmt::format("<{}>\n", timestamp);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool dram_tracer::print_results()
|
||||
{
|
||||
fmt::print("Traced {} data references in {} threads.\n", data_references, thread_ids.size());
|
||||
return true;
|
||||
}
|
||||
Reference in New Issue
Block a user