From 5f3ab1f46a88a9f41e554ef50e2aa33376a97503 Mon Sep 17 00:00:00 2001 From: Stephen Horn Date: Sun, 26 May 2024 14:22:27 -0500 Subject: [PATCH] Adding memory access counting, but currently not counting IO access --- src/main.cpp | 2 + src/memory.cpp | 189 +++++++++++++++++++++++++++++++------------------ src/memory.h | 2 + 3 files changed, 125 insertions(+), 68 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index d9c79f1..9e69fff 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -389,6 +389,8 @@ void main_shutdown() { nvram_dirty = false; } + memory_dump_usage_counts(); + boxmon_system_shutdown(); sdcard_shutdown(); audio_close(); diff --git a/src/memory.cpp b/src/memory.cpp index ac56263..e00faff 100644 --- a/src/memory.cpp +++ b/src/memory.cpp @@ -5,6 +5,7 @@ #include "memory.h" +#include #include #include #include @@ -35,7 +36,13 @@ uint8_t rom_bank_register; #define RAM_WRITE_BLOCKS (((RAM_SIZE) + 0x3f) >> 6) static uint64_t *RAM_written; -static uint8_t addr_ym = 0; +static uint64_t *RAM_read_counts; +static uint64_t *RAM_write_counts; + +static uint64_t *ROM_read_counts; +static uint64_t *ROM_write_counts; + +static uint8_t addr_ym = 0; static uint64_t clock_snap = 0UL; static uint64_t clock_base = 0UL; @@ -117,17 +124,27 @@ void memory_init(const memory_init_params &init_params) RAM = new uint8_t[ram_size]; if (Memory_params.randomize) { srand((uint32_t)SDL_GetPerformanceCounter()); - for (uint32_t i = 0; i < RAM_SIZE; ++i) { + for (uint32_t i = 0; i < ram_size; ++i) { RAM[i] = rand(); } } else { - memset(RAM, 0, RAM_SIZE); + memset(RAM, 0, ram_size); } const uint32_t ram_write_blocks = RAM_WRITE_BLOCKS; RAM_written = new uint64_t[RAM_WRITE_BLOCKS]; memset(RAM_written, 0, RAM_WRITE_BLOCKS * sizeof(uint64_t)); + RAM_read_counts = new uint64_t[RAM_SIZE]; + RAM_write_counts = new uint64_t[RAM_SIZE]; + ROM_read_counts = new uint64_t[ROM_SIZE]; + ROM_write_counts = new uint64_t[ROM_SIZE]; + + memset(RAM_read_counts, 0, RAM_SIZE * sizeof(uint64_t)); + memset(RAM_write_counts, 0, RAM_SIZE * sizeof(uint64_t)); + memset(ROM_read_counts, 0, ROM_SIZE * sizeof(uint64_t)); + memset(ROM_write_counts, 0, ROM_SIZE * sizeof(uint64_t)); + build_memory_map(memmap_table_hi, memory_map_hi); build_memory_map(memmap_table_io, memory_map_io); @@ -170,7 +187,7 @@ static uint8_t real_ram_read(uint16_t address) if ((RAM_written[real_address >> 6] & ((uint64_t)1 << (real_address & 0x3f))) == 0 && Memory_params.enable_uninitialized_access_warning) { printf("Warning: %02X:%04X accessed uninitialized RAM address %02X:%04X\n", bank6502(debug_state6502.pc), debug_state6502.pc, address < 0xa000 ? 0 : ramBank, address); } - + ++RAM_read_counts[real_address]; return RAM[real_address]; } @@ -186,10 +203,12 @@ static void real_ram_write(uint16_t address, uint8_t value) RAM_written[real_address >> 6] |= (uint64_t)1 << (real_address & 0x3f); + ++RAM_write_counts[real_address]; RAM[real_address] = value; - if (address == 1) + if (address == 1) { ROM_BANK = value; + } } // @@ -204,12 +223,14 @@ static uint8_t debug_rom_read(uint16_t address, uint8_t bank) static uint8_t real_rom_read(uint16_t address) { - return ROM[(ROM_BANK << 14) + address - 0xc000]; + const int real_address = (ROM_BANK << 14) + address - 0xc000; + ++ROM_read_counts[real_address]; + return ROM[real_address]; } static void debug_rom_write(uint16_t address, uint8_t bank, uint8_t value) { - if (bank >= NUM_ROM_BANKS) { + if (bank <= NUM_ROM_BANKS) { ROM[((uint32_t)bank << 14) + address - 0xc000] = value; } } @@ -217,9 +238,10 @@ static void debug_rom_write(uint16_t address, uint8_t bank, uint8_t value) static void real_rom_write(uint16_t address, uint8_t value) { const int romBank = effective_rom_bank(); - if (romBank >= NUM_ROM_BANKS) { + if (romBank <= NUM_ROM_BANKS) { const int real_address = (romBank << 14) + address - 0xc000; + ++ROM_write_counts[real_address]; ROM[real_address] = value; // printf("Writing to hidden ram at addr: $%hx, bank $%hhx\n", address, romBank); @@ -241,7 +263,7 @@ uint8_t debug_emu_read(uint8_t reg) case 5: return gif_recorder_get_state(); case 6: return wav_recorder_get_state(); case 7: return Options.no_keybinds ? 1 : 0; - case 8: return (clock_snap >> 0) & 0xff; // don't do snapshotting here because no state should be changed + case 8: return (clock_snap >> 0) & 0xff; // don't do snapshotting here because no state should be changed case 9: return (clock_snap >> 8) & 0xff; case 10: return (clock_snap >> 16) & 0xff; case 11: return (clock_snap >> 24) & 0xff; @@ -264,9 +286,9 @@ uint8_t real_emu_read(uint8_t reg) case 5: return gif_recorder_get_state(); case 6: return wav_recorder_get_state(); case 7: return Options.no_keybinds ? 1 : 0; - case 8: - clock_snap = clockticks6502 - clock_base; - return (clock_snap >> 0) & 0xff; + case 8: + clock_snap = clockticks6502 - clock_base; + return (clock_snap >> 0) & 0xff; case 9: return (clock_snap >> 8) & 0xff; case 10: return (clock_snap >> 16) & 0xff; case 11: return (clock_snap >> 24) & 0xff; @@ -299,15 +321,15 @@ void emu_write(uint8_t reg, uint8_t value) case 9: printf("User debug 1: $%02x\n", value); break; case 10: printf("User debug 2: $%02x\n", value); break; case 11: { - if (value == 0x09 || value == 0x0a || value == 0x0d || (value >= 0x20 && value < 0x7f)) { - putchar(value); - } else if (value >= 0xa1) { - print_iso8859_15_char((char) value); - } else { - printf("\xef\xbf\xbd"); // � - } - fflush(stdout); - break; + if (value == 0x09 || value == 0x0a || value == 0x0d || (value >= 0x20 && value < 0x7f)) { + putchar(value); + } else if (value >= 0xa1) { + print_iso8859_15_char((char)value); + } else { + printf("\xef\xbf\xbd"); // � + } + fflush(stdout); + break; } default: break; // printf("WARN: Invalid register %x\n", DEVICE_EMULATOR + reg); } @@ -362,7 +384,13 @@ static uint8_t real_read(uint16_t address) { switch (MAP[(address >> (BYTE * 8)) & 0xff]) { case MEMMAP_NULL: return 0; - case MEMMAP_DIRECT: return RAM[address]; + case MEMMAP_DIRECT: { + if ((RAM_written[address >> 6] & ((uint64_t)1 << (address & 0x3f))) == 0 && Memory_params.enable_uninitialized_access_warning) { + printf("Warning: %02X:%04X accessed uninitialized RAM address %02X:%04X\n", bank6502(debug_state6502.pc), debug_state6502.pc, 0, address); + } + ++RAM_read_counts[address]; + return RAM[address]; + } case MEMMAP_RAMBANK: return real_ram_read(address); break; case MEMMAP_ROMBANK: return real_rom_read(address); break; case MEMMAP_IO: return real_read(address); @@ -403,6 +431,8 @@ static void real_write(uint16_t address, uint8_t value) switch (MAP[(address >> (BYTE * 8)) & 0xff]) { case MEMMAP_NULL: break; case MEMMAP_DIRECT: + RAM_written[address >> 6] |= (uint64_t)1 << (address & 0x3f); + ++RAM_write_counts[address]; RAM[address] = value; if (address == 1) ROM_BANK = value; @@ -480,54 +510,9 @@ void memory_save(x16file *f, bool dump_ram, bool dump_bank) { if (dump_ram) { x16write_memdump(f, "LOMEM", RAM, 0, 0xa000); - - //std::stringstream ss; - //ss << "[LOMEM]"; - //ss << std::hex; - //for (int i = 0; i < 0xa000; ++i) { - // if ((i & 0xf) == 0) { - // ss << std::setw(0) << "\n"; - // ss << std::setw(4) << std::setfill('0') << i; - // ss << std::setw(0) << " "; - // } else if ((i & 0x7) == 0) { - // ss << std::setw(0) << " "; - // } else { - // ss << std::setw(0) << " "; - // } - // ss << std::setw(2) << std::setfill('0') << static_cast(RAM[i]); - //} - //ss << std::setw(0) << "\n\n"; - //x16write(f, ss.str()); - - // x16write(f, &RAM[0], sizeof(uint8_t), 0xa000); } if (dump_bank) { x16write_bankdump(f, "BANKMEM", RAM + 0xa000, 0xa000, 0xc000, Options.num_ram_banks); - - //std::stringstream ss; - //ss << "[BANKMEM]"; - //ss << std::hex; - - //for (int b = 0; b < Options.num_ram_banks; ++b) { - // for (int i = 0xa000; i <= 0xffff; ++i) { - // if ((i & 0xf) == 0) { - // ss << std::setw(0) << "\n"; - // ss << std::setw(2) << std::setfill('0') << 0; - // ss << std::setw(0) << ":"; - // ss << std::setw(4) << std::setfill('0') << i; - // ss << std::setw(0) << " "; - // } else if ((i & 0x7) == 0) { - // ss << std::setw(0) << " "; - // } else { - // ss << std::setw(0) << " "; - // } - // ss << std::setw(2) << std::setfill('0') << static_cast(debug_read6502(static_cast(i), static_cast(b))); - // } - //} - //ss << std::setw(0) << "\n\n"; - //x16write(f, ss.str()); - - // x16write(f, &RAM[0xa000], sizeof(uint8_t), (Options.num_ram_banks * 8192)); } } @@ -539,7 +524,7 @@ void memory_set_bank(uint16_t address, uint8_t bank) { if (address >= 0xc000) { memory_set_rom_bank(bank); - } else if(address >= 0xa000) { + } else if (address >= 0xa000) { memory_set_ram_bank(bank); } } @@ -574,3 +559,71 @@ uint8_t memory_get_current_bank(uint16_t address) return 0; } } + +void memory_dump_usage_counts() +{ + x16file *dumpfile = x16open("memory_dump.txt", "w"); + if (dumpfile == nullptr) { + printf("Warning: Could not dump memory to memory_dump.txt.\n"); + return; + } + x16write(dumpfile, "--- begin of memory usage statistics dump ---\n"); + x16write(dumpfile, "Usage counts of all memory locations. Locations not printed have count zero.\n"); + x16write(dumpfile, "Tip: use 'sort -r -n -k 3' to sort it so it shows the most used at the top.\n"); + x16write(dumpfile, "system RAM reads:\n"); + int addr; + for (addr = 0; addr < 0xa000; ++addr) { + if (RAM_read_counts[addr] > 0) { + x16write(dumpfile, std::format("r {0:04x} {1}\n", addr, RAM_read_counts[addr])); + } + } + x16write(dumpfile, "\nsystem RAM writes:\n"); + for (addr = 0; addr < 0xa000; ++addr) { + if (RAM_write_counts[addr] > 0) { + x16write(dumpfile, std::format("w {0:04x} {1}\n", addr, RAM_write_counts[addr])); + } + } + x16write(dumpfile, "\nbanked RAM reads:\n"); + int bank; + for (bank = 0; bank < 256; ++bank) { + for (addr = 0xa000; addr < 0xc000; ++addr) { + const int ramBank = bank % Options.num_ram_banks; + const int real_address = (ramBank << 13) + addr; + if (RAM_read_counts[real_address] > 0) { + x16write(dumpfile, std::format("r {0:02x}:{1:04x} {2}\n", bank, addr, RAM_read_counts[real_address])); + } + } + } + x16write(dumpfile, "\nbanked RAM writes:\n"); + for (bank = 0; bank < 256; ++bank) { + for (addr = 0xa000; addr < 0xc000; ++addr) { + const int ramBank = bank % Options.num_ram_banks; + const int real_address = (ramBank << 13) + addr; + if (RAM_write_counts[real_address] > 0) { + x16write(dumpfile, std::format("w {0:02x}:{1:04x} {2}\n", bank, addr, RAM_write_counts[real_address])); + } + } + } + x16write(dumpfile, "\nbanked ROM reads:\n"); + for (bank = 0; bank < 256; ++bank) { + for (addr = 0xc000; addr < 0x10000; ++addr) { + const int romBank = bank % TOTAL_ROM_BANKS; + const int real_address = (romBank << 14) + addr - 0xc000; + if (ROM_read_counts[real_address] > 0) { + x16write(dumpfile, std::format("r {0:02x}:{1:04x} {2}\n", bank, addr, ROM_read_counts[real_address])); + } + } + } + x16write(dumpfile, "\nbanked ROM / 'Bonk RAM' writes:\n"); + for (bank = 0; bank < 256; ++bank) { + for (addr = 0xc000; addr < 0x10000; ++addr) { + const int romBank = bank % TOTAL_ROM_BANKS; + const int real_address = (romBank << 14) + addr - 0xc000; + if (ROM_write_counts[real_address] > 0) { + x16write(dumpfile, std::format("w {0:02x}:{1:04x} {2}\n", bank, addr, ROM_write_counts[real_address])); + } + } + } + x16write(dumpfile, "--- end of memory usage statistics dump ---\n"); + x16close(dumpfile); +} \ No newline at end of file diff --git a/src/memory.h b/src/memory.h index c1e722a..446fbc3 100644 --- a/src/memory.h +++ b/src/memory.h @@ -41,4 +41,6 @@ uint8_t memory_get_rom_bank(); uint8_t memory_get_current_bank(uint16_t address); +void memory_dump_usage_counts(); + #endif