Skip to content

Commit

Permalink
Add an option to produce a textfile trace of instructions executed
Browse files Browse the repository at this point in the history
  • Loading branch information
breqdev committed Dec 30, 2023
1 parent 8e222b8 commit bcc1088
Show file tree
Hide file tree
Showing 7 changed files with 69 additions and 2 deletions.
6 changes: 6 additions & 0 deletions src/cpu/mod.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,14 @@
use crate::trace::TraceHandler;

pub mod mos6502;

pub trait Cpu {
/// Reset this CPU, clearing internal state.
fn reset(&mut self);

/// Attach the given handler to receive trace events from this CPU.
fn attach_trace_handler(&mut self, trace: Box<dyn TraceHandler>);

/// Return the number of cycles elapsed since the system last reset.
fn get_cycle_count(&self) -> u64;

Expand Down
7 changes: 7 additions & 0 deletions src/cpu/mos6502/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ mod execute;
mod fetch;
mod registers;
use crate::memory::{ActiveInterrupt, Memory};
use crate::trace::TraceHandler;
use execute::Execute;
use fetch::Fetch;
use registers::{flags, Registers};
Expand All @@ -25,6 +26,7 @@ pub struct Mos6502 {
cycle_count: u64,
cycles_since_poll: u64,
variant: Mos6502Variant,
trace: Option<Box<dyn TraceHandler>>,
}

/// Read and write from the system's memory.
Expand Down Expand Up @@ -144,6 +146,7 @@ impl Mos6502 {
cycle_count: 0,
cycles_since_poll: 0,
variant,
trace: None,
}
}
}
Expand All @@ -161,6 +164,10 @@ impl Cpu for Mos6502 {
self.cycle_count
}

fn attach_trace_handler(&mut self, trace: Box<dyn TraceHandler>) {
self.trace = Some(trace);
}

Check warning on line 169 in src/cpu/mos6502/mod.rs

View check run for this annotation

Codecov / codecov/patch

src/cpu/mos6502/mod.rs#L167-L169

Added lines #L167 - L169 were not covered by tests

/// Execute a single instruction.
fn tick(&mut self) -> u8 {
let opcode = self.fetch();
Expand Down
3 changes: 3 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,9 @@ pub mod roms;
/// Systems are created by a [`systems::SystemBuilder`]. A system is created with some roms, configuration, and platform. For instance, the `build` implementation on [`systems::pet::PetSystemBuilder`] takes in [`systems::pet::PetSystemRoms`], [`systems::pet::PetSystemConfig`], and an `Arc<dyn PlatformProvider>`.

Check warning on line 31 in src/lib.rs

View workflow job for this annotation

GitHub Actions / WASM Build, Docs Build, and Web Deploy

unresolved link to `systems::SystemBuilder`

Check warning on line 31 in src/lib.rs

View workflow job for this annotation

GitHub Actions / WASM Build, Docs Build, and Web Deploy

unresolved link to `systems::pet::PetSystemBuilder`
pub mod systems;

/// Traces log the state of the system as it runs (e.g., to a file). This is useful for debugging.
pub mod trace;

mod time;

#[cfg(target_arch = "wasm32")]
Expand Down
13 changes: 11 additions & 2 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,11 +51,16 @@ struct Args {

#[clap(short, long, value_parser, default_value = "symbolic")]
key_mapping: KeyMappingArg,

#[clap(short, long, value_parser, default_value = "false")]
trace: bool,

Check warning on line 56 in src/main.rs

View check run for this annotation

Codecov / codecov/patch

src/main.rs#L56

Added line #L56 was not covered by tests
}

#[cfg(not(target_arch = "wasm32"))]
fn main() {
use libnoentiendo::{cpu::mos6502::Mos6502Variant, systems::klaus::KlausSystemConfig};
use libnoentiendo::{
cpu::mos6502::Mos6502Variant, systems::klaus::KlausSystemConfig, trace::file::FileTraceHandler,
};

Check warning on line 63 in src/main.rs

View check run for this annotation

Codecov / codecov/patch

src/main.rs#L61-L63

Added lines #L61 - L63 were not covered by tests

let args = Args::parse();

Expand All @@ -74,7 +79,7 @@ fn main() {
KeyMappingArg::Physical => KeyMappingStrategy::Physical,
};

let system = match args.system {
let mut system = match args.system {

Check warning on line 82 in src/main.rs

View check run for this annotation

Codecov / codecov/patch

src/main.rs#L82

Added line #L82 was not covered by tests
SystemArg::Basic => BasicSystem::build(romfile.unwrap(), (), platform.provider()),
SystemArg::Easy => Easy6502System::build(romfile.unwrap(), (), platform.provider()),
SystemArg::Klaus => KlausSystem::build(
Expand Down Expand Up @@ -105,5 +110,9 @@ fn main() {
),
};

if args.trace {
system.attach_trace_handler(Box::new(FileTraceHandler::new("./cpu.trace".to_owned())));
}

Check warning on line 115 in src/main.rs

View check run for this annotation

Codecov / codecov/patch

src/main.rs#L113-L115

Added lines #L113 - L115 were not covered by tests

platform.run(system);
}
5 changes: 5 additions & 0 deletions src/systems/mod.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use crate::{
cpu::Cpu,
platform::{PlatformProvider, WindowConfig},
trace::TraceHandler,
};
use instant::Duration;
use std::sync::Arc;
Expand All @@ -27,6 +28,10 @@ pub trait System {
/// Return a mutable reference to the CPU used in this system.
fn get_cpu_mut(&mut self) -> Box<&mut dyn Cpu>;

fn attach_trace_handler(&mut self, handler: Box<dyn TraceHandler>) {
self.get_cpu_mut().attach_trace_handler(handler);
}

Check warning on line 33 in src/systems/mod.rs

View check run for this annotation

Codecov / codecov/patch

src/systems/mod.rs#L31-L33

Added lines #L31 - L33 were not covered by tests

/// Advance the system by one tick.
fn tick(&mut self) -> Duration;

Expand Down
23 changes: 23 additions & 0 deletions src/trace/file.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
use crate::trace::{CpuTrace, TraceHandler};
use std::{fs::File, io::Write};

pub struct FileTraceHandler {
file: File,
}

impl FileTraceHandler {
pub fn new(filename: String) -> Self {
Self {
file: File::create(filename).expect("Invalid filename"),
}
}

Check warning on line 13 in src/trace/file.rs

View check run for this annotation

Codecov / codecov/patch

src/trace/file.rs#L9-L13

Added lines #L9 - L13 were not covered by tests
}

impl TraceHandler for FileTraceHandler {
fn handle(&mut self, trace: &CpuTrace) {
self
.file
.write_all(format!("{:04X}: {:02X}\n", trace.address, trace.opcode).as_bytes())
.unwrap();
}

Check warning on line 22 in src/trace/file.rs

View check run for this annotation

Codecov / codecov/patch

src/trace/file.rs#L17-L22

Added lines #L17 - L22 were not covered by tests
}
14 changes: 14 additions & 0 deletions src/trace/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
#[cfg(not(target_arch = "wasm32"))]
pub mod file;

/// Trace information provided after each instruction by the CPU.
pub struct CpuTrace {
pub address: u16,
pub opcode: u8,
}

/// An item which can handle a CPU trace (e.g. logging to a file)
pub trait TraceHandler {
/// Handle a trace event.
fn handle(&mut self, trace: &CpuTrace);
}

0 comments on commit bcc1088

Please sign in to comment.