Enable Execution trace
Generate the trace file with CLI
```
kelvin_sim --trace <elf file>
```
PiperOrigin-RevId: 560821841
diff --git a/sim/kelvin_top.cc b/sim/kelvin_top.cc
index 1deb21c..9955c3f 100644
--- a/sim/kelvin_top.cc
+++ b/sim/kelvin_top.cc
@@ -1,7 +1,13 @@
#include "sim/kelvin_top.h"
+#include <sys/stat.h>
+
+#include <cerrno>
#include <cstdint>
#include <cstring>
+#include <fstream>
+#include <iomanip>
+#include <ios>
#include <iostream>
#include <string>
#include <thread> // NOLINT(build/c++11): built with c++17
@@ -31,13 +37,17 @@
#include "mpact/sim/util/memory/flat_demand_memory.h"
ABSL_FLAG(bool, use_semihost, false, "Use semihost in the simulation");
+ABSL_FLAG(bool, trace, false, "Dump executed instruction trace");
+ABSL_FLAG(std::string, trace_path, "/tmp/kelvin_trace.txt",
+ "Path to save trace");
namespace kelvin::sim {
constexpr char kKelvinName[] = "Kelvin";
// Local helper function used to execute instructions.
-static inline bool ExecuteInstruction(mpact::sim::util::Instruction *inst) {
+static inline bool ExecuteInstruction(mpact::sim::util::Instruction *inst,
+ std::fstream *trace = nullptr) {
for (auto *resource : inst->ResourceHold()) {
if (!resource->IsFree()) {
return false;
@@ -46,9 +56,12 @@
for (auto *resource : inst->ResourceAcquire()) {
resource->Acquire();
}
- // Comment out instruction logging during execution.
- // LOG(INFO) << "[" << std::hex << inst->address() << "] " <<
- // inst->AsString();
+ if (trace != nullptr) {
+ // TODO(hcindyl): Use protobuf to store the serialized trace.
+ *trace << "["
+ << "0x" << std::setfill('0') << std::setw(8) << std::hex
+ << inst->address() << "] " << inst->AsString() << std::endl;
+ }
inst->Execute(nullptr);
return true;
@@ -326,6 +339,22 @@
// be executed.
uint64_t next_pc = pc_operand->AsUint64(0);
uint64_t next_seq_pc;
+
+ std::fstream trace_file;
+ if (absl::GetFlag(FLAGS_trace)) {
+ std::string trace_path = absl::GetFlag(FLAGS_trace_path);
+ std::string trace_dir =
+ trace_path.substr(0, trace_path.find_last_of('/'));
+ int res = mkdir(trace_dir.c_str(), 0777);
+ if (res == 0 || errno == EEXIST) {
+ trace_file.open(absl::GetFlag(FLAGS_trace_path), std::ios_base::out);
+ std::cout << "Dump trace file at " << absl::GetFlag(FLAGS_trace_path)
+ << std::endl;
+ } else {
+ std::cerr << "Failed to create " << trace_dir << std::endl;
+ }
+ }
+
while (!halted_) {
pc = next_pc;
auto *inst = decode_cache_->GetDecodedInstruction(pc);
@@ -334,8 +363,9 @@
// executed will overwrite this.
SetPc(next_seq_pc);
bool executed = false;
+ std::fstream *trace_ptr = trace_file.is_open() ? &trace_file : nullptr;
do {
- executed = ExecuteInstruction(inst);
+ executed = ExecuteInstruction(inst, trace_ptr);
counter_num_cycles_.Increment(1);
state_->AdvanceDelayLines();
} while (!executed);
@@ -355,6 +385,10 @@
SetPc(next_pc);
}
run_status_ = RunStatus::kHalted;
+
+ if (trace_file.is_open()) {
+ trace_file.close();
+ }
// Notify that the run has completed.
run_halted_->Notify();
}).detach();