diff options
| Commit | 2653f4e53f9e878b8c4d09088fd79b4e22a48865 (patch) | |
|---|---|---|
| Author | 2025-02-14 16:06:45 +0200 | |
| Committer | 2025-02-14 16:06:45 +0200 | |
| Files | a82289da31eb8eed58d0383eb9495416f7cd9180 /vm/src | |
| tonkobali-2653f4e53f9e878b8c4d09088fd79b4e22a48865.tar tonkobali-2653f4e53f9e878b8c4d09088fd79b4e22a48865.tar.gz tonkobali-2653f4e53f9e878b8c4d09088fd79b4e22a48865.zip | ||
| Parent | c8955f48580db8067765f76c8967e44dbb06517a (diff) | |
feat(vm): Add ability to store data in memory and to start execution after halt
5 files changed, 47 insertions, 20 deletions
| -rw-r--r-- | vm/src/main.rs | 8 | ||||
| -rw-r--r-- | vm/src/vm/mod.rs | 29 | ||||
| -rw-r--r-- | vm/src/vm/primitive.rs | 5 | ||||
| -rw-r--r-- | vm/src/vmm/command.rs | 22 | ||||
| -rw-r--r-- | vm/src/vmm/mod.rs | 3 |
diff --git a/vm/src/main.rs b/vm/src/main.rs index 1753eb3..fa4a3c5 100644 --- a/vm/src/main.rs +++ b/vm/src/main.rs @@ -27,13 +27,7 @@ fn main() { } else { VirtualMachine::create(args.tick_gap) }; - - let _vm_handle = { - let vm = Arc::clone(&vm); - thread::spawn(move || { - vm.start(); - }) - }; + vm.spawn(); let mut monitor = VirtualMachineMonitor::new(args.refresh); monitor.start(vm); diff --git a/vm/src/vm/mod.rs b/vm/src/vm/mod.rs index 9c92551..000e350 100644 --- a/vm/src/vm/mod.rs +++ b/vm/src/vm/mod.rs @@ -5,7 +5,7 @@ use std::{ sync::{ Arc, Mutex }, thread, time, fs }; -use primitive::{spa, PrimitiveVirtualMachine}; +use primitive::PrimitiveVirtualMachine; use memory::Word; pub(crate) type VirtualMachine = Arc<Mutex<PrimitiveVirtualMachine>>; @@ -14,8 +14,11 @@ pub(crate) trait VirtualMachineInterface { fn create(tick_gap: u64) -> VirtualMachine; fn create_from_file(tick_gap: u64, path: &str) -> VirtualMachine; + fn spawn(&self); fn start(&self); + fn is_halted(&self) -> bool; fn set_start(&mut self, index: Word); + fn set_word(&mut self, index: usize, value: Word); fn get_word(&self, index: usize) -> Word; } @@ -37,6 +40,13 @@ impl VirtualMachineInterface for VirtualMachine { create_with_memory(tick_gap, numbers) } + fn spawn(&self) { + let vm = Arc::clone(&self); + thread::spawn(move || { + vm.start(); + }); + } + fn start(&self) { let tick_gap = { let vm = (*self).lock().unwrap(); @@ -46,9 +56,8 @@ impl VirtualMachineInterface for VirtualMachine { loop { { let mut vm = (*self).lock().unwrap(); - vm.step(); - if vm.is_halted() { - break; + if ! vm.is_halted() { + vm.step(); } } thread::sleep(time::Duration::from_millis(tick_gap)); @@ -57,7 +66,17 @@ impl VirtualMachineInterface for VirtualMachine { fn set_start(&mut self, index: Word) { let mut vm = (*self).lock().unwrap(); - vm.set_word(spa::PROGRAM_COUNTER, index); + vm.start_again(index); + } + + fn is_halted(&self) -> bool { + let vm = (*self).lock().unwrap(); + vm.is_halted() + } + + fn set_word(&mut self, index: usize, value: Word) { + let mut vm = (*self).lock().unwrap(); + vm.set_word(index, value); } fn get_word(&self, index: usize) -> Word { diff --git a/vm/src/vm/primitive.rs b/vm/src/vm/primitive.rs index e9d0d66..43f217f 100644 --- a/vm/src/vm/primitive.rs +++ b/vm/src/vm/primitive.rs @@ -84,6 +84,11 @@ impl PrimitiveVirtualMachine { *self.mem.get_mut(index) = value; } + pub fn start_again(&mut self, pc: Word) { + *self.pc_mut() = pc; + self.halted = false; + } + 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 2688b5f..0811da3 100644 --- a/vm/src/vmm/command.rs +++ b/vm/src/vmm/command.rs @@ -21,17 +21,27 @@ pub(super) fn parse_and_exec(input: String, vm: &mut VirtualMachine) -> Result<( } match args[0] { - "s" | "start" => { + "r" | "run" => { expects_n_args(&args, 1)?; + if ! vm.is_halted() { + return Err(format!("Machine already running!")); + } vm.set_start(args[1].parse().unwrap()); }, + "s" | "store" => { + expects_n_args(&args, 2)?; + + vm.set_word(args[1].parse().unwrap(), args[2].parse().unwrap()); + }, "q" | "quit" | "e" | "exit" => return Err(String::new()), _ => { - if let Some(num) = args[0].parse::<usize>().ok() { - println!("{}", vm.get_word(num)); - } - else { - return Err(format!("Unknown command '{}'!", args[0])); + for arg in args { + if let Some(num) = arg.parse::<usize>().ok() { + println!("{}", vm.get_word(num)); + } + else { + return Err(format!("Unknown command '{}'!", arg)); + } } }, } diff --git a/vm/src/vmm/mod.rs b/vm/src/vmm/mod.rs index afd8840..9ad250f 100644 --- a/vm/src/vmm/mod.rs +++ b/vm/src/vmm/mod.rs @@ -4,7 +4,7 @@ use std::{ thread, time, sync::mpsc, io::{ stdout, stdin, Write } }; use command::parse_and_exec; -use super::vm::VirtualMachine; +use super::vm::{ VirtualMachine, VirtualMachineInterface }; pub(crate) struct VirtualMachineMonitor { refresh_rate: u64, @@ -50,7 +50,6 @@ impl VirtualMachineMonitor { } { - let vm = (*vm).lock().unwrap(); if vm.is_halted() { print!(above!("HALTED!")); } |
