diff options
| Commit | e7656f12d0ab604c40df10d6777ddb8c608a5bfd (patch) | |
|---|---|---|
| Author | 2025-02-15 09:05:27 +0200 | |
| Committer | 2025-02-15 09:05:27 +0200 | |
| Files | f091122e6d24011b828030f35b5abeaa316c4b95 /vm/src | |
| tonkobali-e7656f12d0ab604c40df10d6777ddb8c608a5bfd.tar tonkobali-e7656f12d0ab604c40df10d6777ddb8c608a5bfd.tar.gz tonkobali-e7656f12d0ab604c40df10d6777ddb8c608a5bfd.zip | ||
| Parent | cde6e64005b8cc1b426b1aea15398eb7acb11d08 (diff) | |
feat(vm): Single-step mode
4 files changed, 115 insertions, 11 deletions
| -rw-r--r-- | vm/src/vm/mod.rs | 37 | ||||
| -rw-r--r-- | vm/src/vm/primitive.rs | 48 | ||||
| -rw-r--r-- | vm/src/vmm/command.rs | 31 | ||||
| -rw-r--r-- | vm/src/vmm/mod.rs | 10 |
diff --git a/vm/src/vm/mod.rs b/vm/src/vm/mod.rs index b5675ea..cec5eee 100644 --- a/vm/src/vm/mod.rs +++ b/vm/src/vm/mod.rs @@ -11,13 +11,24 @@ pub(crate) use memory::Word; pub(crate) type VirtualMachine = Arc<Mutex<PrimitiveVirtualMachine>>; pub(crate) trait VirtualMachineInterface { + /* Init */ fn create(tick_gap: u64) -> VirtualMachine; fn create_from_file(tick_gap: u64, path: &str) -> VirtualMachine; fn spawn(&self); + + /* Run mode */ fn start(&self); - fn is_halted(&self) -> bool; fn set_start(&mut self, index: Word); + fn set_halt(&mut self, value: bool); + fn is_halted(&self) -> bool; + + /* Single step mode */ + fn step(&mut self); + fn set_single_step(&mut self, value: bool); + fn is_single_step(&self) -> bool; + + /* IO */ fn set_word(&mut self, index: usize, value: Word); fn get_word(&self, index: usize) -> Word; } @@ -27,6 +38,7 @@ fn create_with_memory(tick_gap: u64, mem: &Vec<Word>) -> VirtualMachine { } impl VirtualMachineInterface for VirtualMachine { + /* Init */ fn create(tick_gap: u64) -> VirtualMachine { Arc::new(Mutex::new(PrimitiveVirtualMachine::new(tick_gap))) } @@ -47,6 +59,7 @@ impl VirtualMachineInterface for VirtualMachine { }); } + /* Run mode */ fn start(&self) { let tick_gap = { let vm = (*self).lock().unwrap(); @@ -69,11 +82,33 @@ impl VirtualMachineInterface for VirtualMachine { vm.start_again(index); } + fn set_halt(&mut self, value: bool) { + let mut vm = (*self).lock().unwrap(); + vm.set_halt(value); + } + fn is_halted(&self) -> bool { let vm = (*self).lock().unwrap(); vm.is_halted() } + /* Single step mode */ + fn step(&mut self) { + let mut vm = (*self).lock().unwrap(); + vm.step_next(); + } + + fn set_single_step(&mut self, value: bool) { + let mut vm = (*self).lock().unwrap(); + vm.set_single_step(value); + } + + fn is_single_step(&self) -> bool { + let vm = (*self).lock().unwrap(); + vm.is_single_step() + } + + /* IO */ fn set_word(&mut self, index: usize, value: Word) { let mut vm = (*self).lock().unwrap(); vm.set_word(index, value); diff --git a/vm/src/vm/primitive.rs b/vm/src/vm/primitive.rs index 9b63d20..ff17b4d 100644 --- a/vm/src/vm/primitive.rs +++ b/vm/src/vm/primitive.rs @@ -11,6 +11,13 @@ pub struct PrimitiveVirtualMachine { pub(crate) tick_gap: u64, pub(crate) mem: Memory, halted: bool, + single_step: bool, +} + +macro_rules! above { + ($str:expr) => { + print!("\x1B7\x1B[1F{}\x1B8", $str) + }; } impl PrimitiveVirtualMachine { @@ -25,12 +32,16 @@ impl PrimitiveVirtualMachine { pub fn new_with_memory(tick_gap: u64, mem: &Vec<Word>) -> PrimitiveVirtualMachine { PrimitiveVirtualMachine { halted: false, + single_step: false, tick_gap, mem: Memory::new_from(mem), } } + /* Run and single step modes */ pub fn step(&mut self) -> VirtualMachineStatus { + let pc = *self.pc(); + let mut addrs = Memory::parse_address(*self.current_word()); if addrs.len() == 1 { self.increment_pc(); @@ -44,6 +55,10 @@ impl PrimitiveVirtualMachine { ); } + if self.single_step { + above!(format!("{}: subleq {} {} {}", pc, addrs[0], addrs[1], addrs[2])); + } + let a = self.mem[addrs[0]]; let b = self.mem.get_mut(addrs[1]); let c = addrs[2] as Word; @@ -57,8 +72,7 @@ impl PrimitiveVirtualMachine { self.increment_pc(); } - - if *self.pc() == 0 { + if *self.pc() == 0 || self.single_step { self.halted = true; VirtualMachineStatus::Halt } @@ -67,23 +81,43 @@ impl PrimitiveVirtualMachine { } } + /* Run mode */ + pub fn set_halt(&mut self, value: bool) { + self.halted = value; + } + pub fn is_halted(&self) -> bool { self.halted } - pub fn get_word(&self, index: usize) -> Word { - self.mem[index] + pub fn start_again(&mut self, pc: Word) { + *self.pc_mut() = pc; + self.halted = false; } + /* Single step mode */ + pub fn set_single_step(&mut self, value: bool) { + self.single_step = value; + } + + pub fn is_single_step(&self) -> bool { + self.single_step + } + + pub fn step_next(&mut self) { + self.halted = false; + } + + /* IO */ pub fn set_word(&mut self, index: usize, value: Word) { *self.mem.get_mut(index) = value; } - pub fn start_again(&mut self, pc: Word) { - *self.pc_mut() = pc; - self.halted = false; + pub fn get_word(&self, index: usize) -> Word { + self.mem[index] } + /* Internal */ fn current_word(&self) -> &Word { &self.mem[*self.pc() as usize] } diff --git a/vm/src/vmm/command.rs b/vm/src/vmm/command.rs index 628a30f..6791663 100644 --- a/vm/src/vmm/command.rs +++ b/vm/src/vmm/command.rs @@ -71,6 +71,7 @@ pub(super) fn parse_and_exec(input: String, vm: &mut VirtualMachine) -> Result<( } match args[0] { + /* Run mode */ "r" | "run" => { expects_n_args(&args, 1)?; if ! vm.is_halted() { @@ -78,6 +79,36 @@ pub(super) fn parse_and_exec(input: String, vm: &mut VirtualMachine) -> Result<( } vm.set_start(args[1].parse().unwrap()); }, + + /* Single step mode */ + "s" | "single" => { + expects_n_args(&args, 1)?; + if ! vm.is_halted() { + return Err(format!("Machine already running!")); + } + if vm.is_single_step() { + return Err(format!("Machine already in single-step mode!")); + } + vm.set_single_step(true); + vm.set_start(args[1].parse().unwrap()); + }, + "c" | "continue" => { + expects_n_args(&args, 0)?; + if ! vm.is_single_step() { + return Err(format!("Machine not in single-step mode!")); + } + vm.set_single_step(false); + vm.set_halt(false); + }, + "n" | "next" => { + expects_n_args(&args, 0)?; + if ! vm.is_single_step() { + return Err(format!("Machine not in single-step mode!")); + } + vm.step(); + }, + + /* Other */ "q" | "quit" | "e" | "exit" => return Err(String::new()), _ => { for arg in args { diff --git a/vm/src/vmm/mod.rs b/vm/src/vmm/mod.rs index 0bfca73..6f42b4e 100644 --- a/vm/src/vmm/mod.rs +++ b/vm/src/vmm/mod.rs @@ -51,16 +51,20 @@ impl VirtualMachineMonitor { println!("{}", msg); } } + else if vm.is_single_step() { + println!(""); + } info!(); }, _ => {}, } - { - if vm.is_halted() { - } + if vm.is_single_step() { + info!("STEP"); } + else if vm.is_halted() { info!(error "HALTED"); + } let _ = stdout().flush(); thread::sleep(time::Duration::from_millis(self.refresh_rate)); |
