From 449612ac19a1d7364f7130f6b785b1aebb933694 Mon Sep 17 00:00:00 2001 From: zxq5 Date: Tue, 24 Jun 2025 18:07:11 +0100 Subject: [PATCH] added step(n) feature to emulator, allowing for stepping n instructions at a time --- emulator/src/emulator/system/emulator.rs | 50 +++++++++++-------- emulator/src/emulator/system/model.rs | 2 +- emulator/src/emulator/system/processor/mod.rs | 3 -- emulator/src/emulator/ui/control_unit.rs | 34 +++++++++++-- 4 files changed, 59 insertions(+), 30 deletions(-) diff --git a/emulator/src/emulator/system/emulator.rs b/emulator/src/emulator/system/emulator.rs index 40e4b57..ff4762c 100644 --- a/emulator/src/emulator/system/emulator.rs +++ b/emulator/src/emulator/system/emulator.rs @@ -27,6 +27,7 @@ pub fn run_emulator( println!("INFO: Starting emulator."); let mut running = Running::Paused; + let mut step = 0; let mut addr; let mut history = Vec::<(u32, Instruction)>::new(); let size = 256; @@ -39,7 +40,7 @@ pub fn run_emulator( let mut update = false; loop { - let cmd = if running == Running::Running { + let cmd = if running == Running::Running || step > 0 { match cmd_rx.try_recv() { Ok(cmd) => Some(cmd), Err(mpsc::TryRecvError::Empty) => { @@ -96,26 +97,8 @@ pub fn run_emulator( processor.reset(); } - Command::Step => { - update = true; - - running = Running::Paused; - - // Execute one cycle. - match processor.cycle() { - Ok((addr, instruction)) => { - history.push((addr, instruction)); - } - Err(why) => { - let pcx = processor.get(Register::Pcx); - eprintln!( - "Could not decode instruction at {pcx:x}. Reason: {why}" - ); - continue; - } - } - - instruction_count += 1; + Command::Step(x) => { + step = x; } Command::Write(offset, data) => { update = true; @@ -200,6 +183,31 @@ pub fn run_emulator( } } + if step > 0 { + step -= 1; + update = true; + running = Running::Paused; + + // Execute one cycle. + match processor.cycle() { + Ok((addr, instruction)) => { + history.push((addr, instruction)); + } + Err(why) => { + let pcx = processor.get(Register::Pcx); + report_err( + state_tx, + &format!( + "Could not decode instruction at {pcx:x}. Reason: {why}" + ), + &mut processor, + ); + } + } + instruction_count += 1; + continue; + } + if running == Running::Running { update = true; diff --git a/emulator/src/emulator/system/model.rs b/emulator/src/emulator/system/model.rs index f31ad12..e674b2a 100644 --- a/emulator/src/emulator/system/model.rs +++ b/emulator/src/emulator/system/model.rs @@ -21,7 +21,7 @@ pub enum Command { // set emulator state. Start, Stop, - Step, + Step(usize), Reset(usize), Interrupt(Interrupt), Write(Address, Vec), diff --git a/emulator/src/emulator/system/processor/mod.rs b/emulator/src/emulator/system/processor/mod.rs index aa4f425..3e9a37a 100644 --- a/emulator/src/emulator/system/processor/mod.rs +++ b/emulator/src/emulator/system/processor/mod.rs @@ -64,10 +64,7 @@ impl Processor { let instruction = Instruction::decode(val) .map_err(|_| ProcessorError::InvalidInstruction(val))?; - log(&instruction.to_string()); - instruction.execute(self)?; - Ok((addr, instruction)) } diff --git a/emulator/src/emulator/ui/control_unit.rs b/emulator/src/emulator/ui/control_unit.rs index 75c2c3b..bb32679 100644 --- a/emulator/src/emulator/ui/control_unit.rs +++ b/emulator/src/emulator/ui/control_unit.rs @@ -7,12 +7,18 @@ use common::{instructions::Register, prelude::Instruction}; pub struct ControlPanel { visible: bool, + step_amount_input: String, + step_amount: usize, } impl ControlPanel { #[allow(clippy::must_use_candidate)] - pub const fn new() -> Self { - Self { visible: false } + pub fn new() -> Self { + Self { + visible: false, + step_amount_input: String::from("1"), + step_amount: 1, + } } } @@ -59,9 +65,12 @@ impl Component for ControlPanel { // Step if ui.button("Step").clicked() { - state.cmd_sender.send(Command::Step).unwrap_or_else(|_| { - state.error_log.push("Failed to send command".to_string()); - }); + state + .cmd_sender + .send(Command::Step(self.step_amount)) + .unwrap_or_else(|_| { + state.error_log.push("Failed to send command".to_string()); + }); } // Resets the emulator and all attached devices @@ -98,6 +107,21 @@ impl Component for ControlPanel { state.send(Command::RegisterRequest); state.send(Command::RunningRequest); + state.send(Command::InstructionCountRequest); + + if ui + .text_edit_singleline(&mut self.step_amount_input) + .changed() + { + self.step_amount = if let Ok(amount) = self.step_amount_input.parse() { + amount + } else { + state + .error_log + .push("Unable to parse step amount".to_string()); + 1 + } + } // Status info ui.label(format!(