6#include "absl/strings/str_format.h"
14 bool track_reads,
bool track_writes,
16 const std::string& description) {
27 ? absl::StrFormat(
"Watch $%06X-$%06X", start_address, end_address)
32 LOG_INFO(
"Watchpoint",
"Added watchpoint #%d: %s (R=%d, W=%d, Break=%d)",
42 LOG_INFO(
"Watchpoint",
"Removed watchpoint #%d",
id);
50 it->second.enabled = enabled;
51 LOG_INFO(
"Watchpoint",
"Watchpoint #%d %s",
id,
52 enabled ?
"enabled" :
"disabled");
57 bool is_write, uint8_t old_value,
59 uint64_t cycle_count) {
60 bool should_break =
false;
63 if (!wp.enabled || !
IsInRange(wp, address)) {
69 (is_write && wp.track_writes) || (!is_write && wp.track_reads);
82 log.
description = absl::StrFormat(
"%s at $%06X: $%02X -> $%02X (PC=$%06X)",
83 is_write ?
"WRITE" :
"READ", address,
84 old_value, new_value, pc);
86 wp.history.push_back(log);
90 wp.history.pop_front();
94 if (wp.break_on_access) {
96 LOG_INFO(
"Watchpoint",
"Hit watchpoint #%d: %s",
id,
104std::vector<WatchpointManager::Watchpoint>
106 std::vector<Watchpoint> result;
109 result.push_back(wp);
112 result.begin(), result.end(),
118 uint32_t address,
int max_entries)
const {
119 std::vector<AccessLog> result;
123 for (
const auto& log : wp.history) {
124 if (log.address == address) {
125 result.push_back(log);
126 if (result.size() >=
static_cast<size_t>(max_entries)) {
138 LOG_INFO(
"Watchpoint",
"Cleared all watchpoints (%zu total)",
147 LOG_INFO(
"Watchpoint",
"Cleared all watchpoint history");
151 std::ofstream out(filepath);
152 if (!out.is_open()) {
157 out <<
"Watchpoint,PC,Address,Type,OldValue,NewValue,Cycle,Description\n";
160 for (
const auto& log : wp.history) {
161 out << absl::StrFormat(
"%d,$%06X,$%06X,%s,$%02X,$%02X,%llu,\"%s\"\n",
id,
163 log.is_write ?
"WRITE" :
"READ", log.old_value,
164 log.new_value, log.cycle_count, log.description);
169 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,...)
static constexpr size_t kMaxHistorySize