From 79adce86bd66d2332c8a544ee6f70f458eb82e7e Mon Sep 17 00:00:00 2001 From: Adrian Conlon Date: Wed, 7 Apr 2021 21:35:33 +0100 Subject: [PATCH] Add 6809 profiling --- MC6809/inc/Disassembly.h | 88 +++++++++++++++---------------- MC6809/inc/ProfileLineEventArgs.h | 22 ++++++++ MC6809/inc/Profiler.h | 41 ++++++++++++++ MC6809/src/MC6809.vcxproj | 3 ++ MC6809/src/MC6809.vcxproj.filters | 9 ++++ MC6809/src/Profiler.cpp | 41 ++++++++++++++ MC6809/test/Board.cpp | 17 ++++++ MC6809/test/Board.h | 2 + MC6809/test/Configuration.h | 4 ++ 9 files changed, 183 insertions(+), 44 deletions(-) create mode 100644 MC6809/inc/ProfileLineEventArgs.h create mode 100644 MC6809/inc/Profiler.h create mode 100644 MC6809/src/Profiler.cpp diff --git a/MC6809/inc/Disassembly.h b/MC6809/inc/Disassembly.h index 0ebaff8..157d5e7 100644 --- a/MC6809/inc/Disassembly.h +++ b/MC6809/inc/Disassembly.h @@ -12,11 +12,24 @@ namespace EightBit { public: Disassembly(Bus& bus, mc6809& processor); - bool ignore(); + [[nodiscard]] bool ignore(); - std::string trace(uint16_t current); - std::string trace(register16_t current); - std::string trace(); + [[nodiscard]] std::string trace(uint16_t current); + [[nodiscard]] std::string disassemble(uint16_t current); + + [[nodiscard]] std::string trace(register16_t current); + [[nodiscard]] std::string disassemble(register16_t current); + + [[nodiscard]] std::string trace(); + [[nodiscard]] std::string disassemble(); + + static [[nodiscard]] std::string dump_Flags(uint8_t value); + static [[nodiscard]] std::string dump_ByteValue(uint8_t value); + static [[nodiscard]] std::string dump_RelativeValue(int8_t value); + static [[nodiscard]] std::string dump_WordValue(uint16_t value); + static [[nodiscard]] std::string dump_WordValue(register16_t value); + static [[nodiscard]] std::string dump_RelativeValue(int16_t value); + static [[nodiscard]] std::string dump_RelativeValue(register16_t value); private: Bus& m_bus; @@ -27,63 +40,50 @@ namespace EightBit { bool m_prefix10 = false; bool m_prefix11 = false; - static std::string dump_Flags(uint8_t value); - static std::string dump_ByteValue(uint8_t value); - static std::string dump_RelativeValue(int8_t value); - static std::string dump_WordValue(uint16_t value); - static std::string dump_WordValue(register16_t value); - static std::string dump_RelativeValue(int16_t value); - static std::string dump_RelativeValue(register16_t value); - - std::string disassemble(uint16_t current); - std::string disassemble(register16_t current); - std::string disassemble(); - static void dump(std::ostream& out, int value, int width); - mc6809& CPU() { return m_cpu; } + [[nodiscard]] mc6809& CPU() { return m_cpu; } + [[nodiscard]] Bus& BUS() { return m_bus; } - uint8_t getByte(uint16_t address); - uint16_t getWord(uint16_t address); + [[nodiscard]] uint8_t getByte(uint16_t address); + [[nodiscard]] uint16_t getWord(uint16_t address); - std::string disassembleUnprefixed(); - std::string disassemble10(); - std::string disassemble11(); + [[nodiscard]] std::string disassembleUnprefixed(); + [[nodiscard]] std::string disassemble10(); + [[nodiscard]] std::string disassemble11(); // - std::string RR(int which); - std::string wrapIndirect(std::string what, bool indirect); + [[nodiscard]] std::string RR(int which); + [[nodiscard]] std::string wrapIndirect(std::string what, bool indirect); - std::string Address_direct(std::string mnemomic); - std::string Address_indexed(std::string mnemomic); - std::string Address_extended(std::string mnemomic); - std::string Address_relative_byte(std::string mnemomic); - std::string Address_relative_word(std::string mnemomic); + [[nodiscard]] std::string Address_direct(std::string mnemomic); + [[nodiscard]] std::string Address_indexed(std::string mnemomic); + [[nodiscard]] std::string Address_extended(std::string mnemomic); + [[nodiscard]] std::string Address_relative_byte(std::string mnemomic); + [[nodiscard]] std::string Address_relative_word(std::string mnemomic); - std::string AM_immediate_byte(std::string mnemomic); - std::string AM_immediate_word(std::string mnemomic); + [[nodiscard]] std::string AM_immediate_byte(std::string mnemomic); + [[nodiscard]] std::string AM_immediate_word(std::string mnemomic); // - std::string branchShort(std::string mnemomic); - std::string branchLong(std::string mnemomic); + [[nodiscard]] std::string branchShort(std::string mnemomic); + [[nodiscard]] std::string branchLong(std::string mnemomic); // - std::string referenceTransfer8(int specifier); - std::string referenceTransfer16(int specifier); - std::string tfr(std::string mnemomic); + [[nodiscard]] std::string referenceTransfer8(int specifier); + [[nodiscard]] std::string referenceTransfer16(int specifier); + [[nodiscard]] std::string tfr(std::string mnemomic); // - std::string pulS(); - std::string pulU(); - std::string pshS(); - std::string pshU(); - std::string pulX(std::string mnemomic, std::string upon); - std::string pshX(std::string mnemomic, std::string upon); - - Bus& BUS() { return m_bus; } + [[nodiscard]] std::string pulS(); + [[nodiscard]] std::string pulU(); + [[nodiscard]] std::string pshS(); + [[nodiscard]] std::string pshU(); + [[nodiscard]] std::string pulX(std::string mnemomic, std::string upon); + [[nodiscard]] std::string pshX(std::string mnemomic, std::string upon); }; } \ No newline at end of file diff --git a/MC6809/inc/ProfileLineEventArgs.h b/MC6809/inc/ProfileLineEventArgs.h new file mode 100644 index 0000000..7101120 --- /dev/null +++ b/MC6809/inc/ProfileLineEventArgs.h @@ -0,0 +1,22 @@ +#pragma once + +#include +#include + +namespace EightBit { + class ProfileLineEventArgs + { + private: + int m_address; + std::string m_source; + uint64_t m_cycles; + + public: + ProfileLineEventArgs(int address, std::string source, uint64_t cycles) + : m_address(address), m_source(source), m_cycles(cycles) {} + + int address() const { return m_address; } + const std::string& source() const { return m_source; } + uint64_t cycles() const { return m_cycles; } + }; +} \ No newline at end of file diff --git a/MC6809/inc/Profiler.h b/MC6809/inc/Profiler.h new file mode 100644 index 0000000..d9f97a0 --- /dev/null +++ b/MC6809/inc/Profiler.h @@ -0,0 +1,41 @@ +#pragma once + +#include +#include +#include + +#include +#include + +#include "ProfileLineEventArgs.h" + +namespace EightBit { + + class Disassembly; + class mc6809; + + class Profiler { + public: + std::array instructionCounts; + std::array addressProfiles; + std::array addressCounts; + + mc6809& processor; + Disassembly& disassembler; + + Profiler(mc6809& processor, Disassembly& disassembler); + + Signal StartingOutput; + Signal FinishedOutput; + + Signal EmitLine; + + void addInstruction(uint8_t instruction); + void addAddress(uint16_t address, int cycles); + + void Generate(); + + private: + void EmitProfileInformation(); + }; +} \ No newline at end of file diff --git a/MC6809/src/MC6809.vcxproj b/MC6809/src/MC6809.vcxproj index 79e36e3..a52e78a 100644 --- a/MC6809/src/MC6809.vcxproj +++ b/MC6809/src/MC6809.vcxproj @@ -21,11 +21,14 @@ + + + Create Create diff --git a/MC6809/src/MC6809.vcxproj.filters b/MC6809/src/MC6809.vcxproj.filters index 9e68e67..b5eeffa 100644 --- a/MC6809/src/MC6809.vcxproj.filters +++ b/MC6809/src/MC6809.vcxproj.filters @@ -20,6 +20,12 @@ Header Files + + Header Files + + + Header Files + @@ -31,5 +37,8 @@ Source Files + + Source Files + \ No newline at end of file diff --git a/MC6809/src/Profiler.cpp b/MC6809/src/Profiler.cpp new file mode 100644 index 0000000..af46199 --- /dev/null +++ b/MC6809/src/Profiler.cpp @@ -0,0 +1,41 @@ +#include "stdafx.h" +#include "Profiler.h" + +#include "Disassembly.h" + +EightBit::Profiler::Profiler(mc6809& targetProcessor, Disassembly& disassemblerTarget) +: processor(targetProcessor), + disassembler(disassemblerTarget) { + instructionCounts.fill(0); + addressProfiles.fill(0); + addressCounts.fill(0); +} + +void EightBit::Profiler::Generate() { + StartingOutput.fire(); + EmitProfileInformation(); + StartingOutput.fire(); +} + +void EightBit::Profiler::EmitProfileInformation() { + // For each memory address + for (int address = 0; address < 0x10000; ++address) { + // If there are any cycles associated + auto cycles = addressProfiles[address]; + if (cycles > 0) { + // Dump a profile/disassembly line + auto source = disassembler.disassemble(address); + ProfileLineEventArgs event(address, source, cycles); + EmitLine.fire(event); + } + } +} + +void EightBit::Profiler::addInstruction(uint8_t instruction) { + ++instructionCounts[instruction]; +} + +void EightBit::Profiler::addAddress(uint16_t address, int cycles) { + addressCounts[address]++; + addressProfiles[address] += cycles; +} diff --git a/MC6809/test/Board.cpp b/MC6809/test/Board.cpp index 0c3299d..6d2157e 100644 --- a/MC6809/test/Board.cpp +++ b/MC6809/test/Board.cpp @@ -27,6 +27,14 @@ void Board::raisePOWER() { } void Board::lowerPOWER() { + + if (m_configuration.isProfileMode()) { + m_profiler.EmitLine.connect([this](EightBit::ProfileLineEventArgs line) { + std::cout << EightBit::Disassembly::dump_WordValue(line.address()) << " " << line.source() << std::endl; + }); + m_profiler.Generate(); + } + ACIA().lowerPOWER(); CPU().lowerPOWER(); EightBit::Bus::lowerPOWER(); @@ -71,6 +79,15 @@ void Board::initialise() { } }); + if (m_configuration.isProfileMode()) { + m_cpu.ExecutingInstruction.connect([this](EightBit::mc6809& cpu) { + m_profiler.addInstruction(peek(cpu.PC())); + }); + m_cpu.ExecutedInstruction.connect([this](EightBit::mc6809& cpu) { + m_profiler.addAddress(cpu.PC().word, cpu.cycles()); + }); + } + if (m_configuration.isDebugMode()) { // MC6809 disassembly wiring CPU().ExecutingInstruction.connect([this] (EightBit::mc6809& cpu) { diff --git a/MC6809/test/Board.h b/MC6809/test/Board.h index b581054..cc38469 100644 --- a/MC6809/test/Board.h +++ b/MC6809/test/Board.h @@ -11,6 +11,7 @@ #include #include #include +#include class Board : public EightBit::Bus { public: @@ -38,6 +39,7 @@ private: EightBit::mc6809 m_cpu = *this; EightBit::Disassembly m_disassembler = { *this, m_cpu }; + EightBit::Profiler m_profiler = { m_cpu, m_disassembler }; uint64_t m_totalCycleCount = 0UL; int64_t m_frameCycleCount = 0L; diff --git a/MC6809/test/Configuration.h b/MC6809/test/Configuration.h index 2613a4d..4ebed5b 100644 --- a/MC6809/test/Configuration.h +++ b/MC6809/test/Configuration.h @@ -14,6 +14,9 @@ public: bool isDebugMode() const { return m_debugMode; } void setDebugMode(bool value) { m_debugMode = value; } + bool isProfileMode() const { return m_profileMode; } + void setProfileMode(bool value) { m_profileMode = value; } + bool terminatesEarly() const { return m_terminatesEarly; } void setTerminatesEarly(bool value) { m_terminatesEarly = value; } @@ -21,6 +24,7 @@ public: private: bool m_debugMode = false; + bool m_profileMode = false; bool m_terminatesEarly = false; std::string m_romDirectory = "roms\\searle"; };