5#include "absl/strings/str_format.h"
12 bool track_reads,
bool track_writes,
14 const std::string& description) {
24 ? absl::StrFormat(
"Watch $%06X-$%06X", start_address, end_address)
29 LOG_INFO(
"Watchpoint",
"Added watchpoint #%d: %s (R=%d, W=%d, Break=%d)",
30 wp.
id, wp.
description.c_str(), track_reads, track_writes, break_on_access);
38 LOG_INFO(
"Watchpoint",
"Removed watchpoint #%d",
id);
46 it->second.enabled = enabled;
47 LOG_INFO(
"Watchpoint",
"Watchpoint #%d %s",
id, enabled ?
"enabled" :
"disabled");
52 uint8_t old_value, uint8_t new_value,
53 uint64_t cycle_count) {
54 bool should_break =
false;
57 if (!wp.enabled || !
IsInRange(wp, address)) {
62 bool should_log = (is_write && wp.track_writes) || (!is_write && wp.track_reads);
75 log.
description = absl::StrFormat(
"%s at $%06X: $%02X -> $%02X (PC=$%06X)",
76 is_write ?
"WRITE" :
"READ",
77 address, old_value, new_value, pc);
79 wp.history.push_back(log);
83 wp.history.pop_front();
87 if (wp.break_on_access) {
97 std::vector<Watchpoint> result;
100 result.push_back(wp);
102 std::sort(result.begin(), result.end(),
108 uint32_t address,
int max_entries)
const {
109 std::vector<AccessLog> result;
113 for (
const auto& log : wp.history) {
114 if (log.address == address) {
115 result.push_back(log);
116 if (result.size() >=
static_cast<size_t>(max_entries)) {
136 LOG_INFO(
"Watchpoint",
"Cleared all watchpoint history");
140 std::ofstream out(filepath);
141 if (!out.is_open()) {
146 out <<
"Watchpoint,PC,Address,Type,OldValue,NewValue,Cycle,Description\n";
149 for (
const auto& log : wp.history) {
150 out << absl::StrFormat(
"%d,$%06X,$%06X,%s,$%02X,$%02X,%llu,\"%s\"\n",
151 id, log.pc, log.address,
152 log.is_write ?
"WRITE" :
"READ",
153 log.old_value, log.new_value, log.cycle_count,
159 LOG_INFO(
"Watchpoint",
"Exported watchpoint history to %s", filepath.c_str());
uint32_t AddWatchpoint(uint32_t start_address, uint32_t end_address, bool track_reads, bool track_writes, bool break_on_access=false, const std::string &description="")
Add a memory watchpoint.
bool ExportHistoryToCSV(const std::string &filepath) const
Export access history to CSV.
std::vector< Watchpoint > GetAllWatchpoints() const
Get all watchpoints.
std::unordered_map< uint32_t, Watchpoint > watchpoints_
std::vector< AccessLog > GetHistory(uint32_t address, int max_entries=100) const
Get access history for a specific address.
bool IsInRange(const Watchpoint &wp, uint32_t address) const
void ClearAll()
Clear all watchpoints.
bool OnMemoryAccess(uint32_t pc, uint32_t address, bool is_write, uint8_t old_value, uint8_t new_value, uint64_t cycle_count)
Check if memory access should break/log.
void ClearHistory()
Clear history for all watchpoints.
void SetEnabled(uint32_t id, bool enabled)
Enable or disable a watchpoint.
void RemoveWatchpoint(uint32_t id)
Remove a watchpoint.
#define LOG_INFO(category, format,...)
Main namespace for the application.
static constexpr size_t kMaxHistorySize