diff --git a/Cargo.lock b/Cargo.lock index a333452..0ac46bb 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,6 +1,6 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. -version = 3 +version = 4 [[package]] name = "addr2line" @@ -54,10 +54,59 @@ dependencies = [ ] [[package]] -name = "anyhow" -version = "1.0.93" +name = "anstream" +version = "0.6.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c95c10ba0b00a02636238b814946408b1322d5ac4760326e6fb8ec956d85775" +checksum = "8acc5369981196006228e28809f761875c0327210a891e941f4c683b3a99529b" +dependencies = [ + "anstyle", + "anstyle-parse", + "anstyle-query", + "anstyle-wincon", + "colorchoice", + "is_terminal_polyfill", + "utf8parse", +] + +[[package]] +name = "anstyle" +version = "1.0.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55cc3b69f167a1ef2e161439aa98aed94e6028e5f9a59be9a6ffb47aef1651f9" + +[[package]] +name = "anstyle-parse" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b2d16507662817a6a20a9ea92df6652ee4f94f914589377d69f3b21bc5798a9" +dependencies = [ + "utf8parse", +] + +[[package]] +name = "anstyle-query" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "79947af37f4177cfead1110013d678905c37501914fba0efea834c3fe9a8d60c" +dependencies = [ + "windows-sys 0.59.0", +] + +[[package]] +name = "anstyle-wincon" +version = "3.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2109dbce0e72be3ec00bed26e6a7479ca384ad226efdd66db8fa2e3a38c83125" +dependencies = [ + "anstyle", + "windows-sys 0.59.0", +] + +[[package]] +name = "anyhow" +version = "1.0.94" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1fd03a028ef38ba2276dce7e33fcd6369c158a1bca17946c4b1b701891c1ff7" [[package]] name = "arbitrary" @@ -233,12 +282,66 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +[[package]] +name = "clap" +version = "4.5.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69371e34337c4c984bbe322360c2547210bf632eb2814bbe78a6e87a2935bd2b" +dependencies = [ + "clap_builder", + "clap_derive", +] + +[[package]] +name = "clap_builder" +version = "4.5.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e24c1b4099818523236a8ca881d2b45db98dadfb4625cf6608c12069fcbbde1" +dependencies = [ + "anstream", + "anstyle", + "clap_lex", + "strsim", +] + +[[package]] +name = "clap_derive" +version = "4.5.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ac6a0c7b1a9e9a5186361f67dfa1b88213572f427fb9ab038efb2bd8c582dab" +dependencies = [ + "heck 0.5.0", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "clap_lex" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "afb84c814227b90d6895e01398aee0d8033c00e7466aca416fb6a8e0eb19d8a7" + [[package]] name = "cobs" version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "67ba02a97a2bd10f4b59b25c7973101c79642302776489e030cd13cdab09ed15" +[[package]] +name = "colorchoice" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990" + +[[package]] +name = "common" +version = "0.1.0" +dependencies = [ + "extism-pdk", + "serde", +] + [[package]] name = "core-foundation-sys" version = "0.8.7" @@ -761,7 +864,11 @@ dependencies = [ name = "hecate" version = "0.1.0" dependencies = [ + "anyhow", + "clap", + "common", "extism", + "serde", "wasm-bindgen", ] @@ -978,6 +1085,12 @@ version = "2.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ddc24109865250148c2e0f3d25d4f0f479571723792d3802153c60922a4fb708" +[[package]] +name = "is_terminal_polyfill" +version = "1.70.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" + [[package]] name = "itertools" version = "0.12.1" @@ -1492,8 +1605,8 @@ dependencies = [ name = "rust-pdk-template" version = "0.1.0" dependencies = [ + "common", "extism-pdk", - "hecate", "serde", ] @@ -1680,6 +1793,12 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" +[[package]] +name = "strsim" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" + [[package]] name = "subtle" version = "2.6.1" @@ -1957,6 +2076,12 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" +[[package]] +name = "utf8parse" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" + [[package]] name = "uuid" version = "1.11.0" diff --git a/Cargo.toml b/Cargo.toml index af90e2b..2cd218a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,8 +4,12 @@ version = "0.1.0" edition = "2021" [dependencies] +anyhow = "1.0.94" +clap = { version = "4.5.22", features = ["derive"] } +common = { version = "0.1.0", path = "common" } extism = "1.9.1" +serde = { version = "1.0.215", features = ["derive"] } wasm-bindgen = "0.2.97" [workspace] -members = ["std_cpu"] \ No newline at end of file +members = ["common", "std_cpu"] diff --git a/common/Cargo.toml b/common/Cargo.toml new file mode 100644 index 0000000..a75233a --- /dev/null +++ b/common/Cargo.toml @@ -0,0 +1,8 @@ +[package] +name = "common" +version = "0.1.0" +edition = "2021" + +[dependencies] +extism-pdk = "1.3.0" +serde = { version = "1.0.215", features = ["derive"] } diff --git a/common/src/lib.rs b/common/src/lib.rs new file mode 100644 index 0000000..9e65919 --- /dev/null +++ b/common/src/lib.rs @@ -0,0 +1,62 @@ +use extism_pdk::*; +use serde::{Deserialize, Serialize}; + +#[derive(Serialize, Deserialize, ToBytes, FromBytes)] +#[encoding(Json)] +pub struct Init { + pub verbose: bool, + pub mem_size: usize, + pub registers: usize, +} + +#[derive(Serialize, Deserialize, ToBytes, FromBytes)] +#[encoding(Json)] +pub struct SetVerbose(pub bool); + +#[derive(Serialize, Deserialize, ToBytes, FromBytes)] +#[encoding(Json)] +pub struct SetMemory { + pub offset: usize, + pub memory: Vec, +} + +#[derive(Serialize, Deserialize, ToBytes, FromBytes)] +#[encoding(Json)] +pub enum RunResult { + Success, +} + +pub trait CpuTrait { + fn new() -> Self + where + Self: Sized; + + fn set_verbose(&mut self, verbose: bool); + + fn load_memory(&mut self, memory: &[u8]); + + fn execute(&mut self, run_mode: RunMode); + + fn get_registers(&self) -> &[u16]; + + fn get_memory(&self) -> &[u8]; +} + +#[derive(Serialize, Deserialize, ToBytes, FromBytes)] +#[encoding(Json)] +pub enum RunMode { + Run, // Run to completion + Debug(DebugMode), // Debug mode + StepOver, // Step over calls + StepInto, // Step into calls + StepOut, // Step out of calls + RunFor(usize), // Run for a specific number of cycles +} + +#[derive(Serialize, Deserialize, ToBytes, FromBytes)] +#[encoding(Json)] +pub enum DebugMode { + All, // Break on any breakpoint + Code, // Break on code breakpoints + Data, // Break on data breakpoints +} diff --git a/src/cpu_trait.rs b/src/cpu_trait.rs deleted file mode 100644 index ceaad51..0000000 --- a/src/cpu_trait.rs +++ /dev/null @@ -1,30 +0,0 @@ -pub trait CpuTrait { - fn new() -> Self - where - Self: Sized; - - fn set_verbose(&mut self, verbose: bool); - - fn load_memory(&mut self, memory: &[u8]); - - fn execute(&mut self, run_mode: RunMode); - - fn get_registers(&self) -> &[u16]; - - fn get_memory(&self) -> &[u8]; -} - -pub enum RunMode { - Run, // Run to completion - Debug(DebugMode), // Debug mode - StepOver, // Step over calls - StepInto, // Step into calls - StepOut, // Step out of calls - RunFor(usize), // Run for a specific number of cycles -} - -pub enum DebugMode { - All, // Break on any breakpoint - Code, // Break on code breakpoints - Data, // Break on data breakpoints -} diff --git a/src/lib.rs b/src/lib.rs index 4f420d4..302aff9 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,70 +1,41 @@ -mod cpu_trait; +use common::{RunMode, RunResult, SetVerbose}; +use extism::*; -pub use cpu_trait::{CpuTrait, DebugMode, RunMode}; +pub struct WasmCpu { + plugin: Plugin, +} - -#[wasm_bindgen] impl WasmCpu { - #[wasm_bindgen(constructor)] - pub fn new() -> Self { - WasmCpu { - memory: [0; 64 * 1024], - registers: [0; 8], - ip: 0, - sp: 0xFFFF, - flags: 0, - verbose: false, - } + pub fn new(manifest: Manifest) -> anyhow::Result { + let plugin = PluginBuilder::new(manifest).build()?; + Ok(WasmCpu { plugin }) + } + + pub fn from_path>(path: P) -> anyhow::Result { + let manifest = Manifest::new([Wasm::file(path)]); + Self::new(manifest) + } + + pub fn from_url(url: &str) -> anyhow::Result { + let manifest = Manifest::new([Wasm::url(url)]); + Self::new(manifest) } pub fn set_verbose(&mut self, verbose: bool) { - self.verbose = verbose; + self.plugin + .call::("set_verbose", SetVerbose(verbose)) + .unwrap() } pub fn load_memory(&mut self, memory: &[u8]) { - self.memory[..memory.len()].copy_from_slice(memory); + self.plugin + .call::<&[u8], ()>("load_memory", memory) + .unwrap() } - pub fn execute(&mut self, run_mode: RunMode) { - match run_mode { - RunMode::Run => self.run(), - RunMode::Debug(debug_mode) => self.debug(debug_mode), - RunMode::StepOver => self.step_over(), - RunMode::StepInto => self.step_into(), - RunMode::StepOut => self.step_out(), - RunMode::RunFor(cycles) => self.run_for(cycles), - } + pub fn execute(&mut self, run_mode: RunMode) -> RunResult { + self.plugin + .call::("execute", run_mode) + .unwrap() } - - fn run(&mut self) { - while self.ip < self.memory.len() as u16 { - self.step(); - } - } - - fn debug(&mut self, _debug_mode: DebugMode) { - // Implement debug functionality - } - - fn run_for(&mut self, cycles: usize) { - for _ in 0..cycles { - self.step(); - } - } - - fn step_over(&mut self) { - self.step(); // Placeholder for step-over functionality - } - - fn step_into(&mut self) { - self.step(); // Placeholder for step-into functionality - } - - fn step_out(&mut self) { - self.step(); // Placeholder for step-out functionality - } - - fn step(&mut self) { - // Fetch and execute instructions - } -} \ No newline at end of file +} diff --git a/src/main.rs b/src/main.rs index 932c8ac..fffd76e 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,28 +1,19 @@ -use wasmtime::*; -use crate::cpu_trait::{CpuTrait, RunMode, DebugMode}; +use std::path::PathBuf; -fn main() -> Result<(), Box> { - // Create an engine and module - let engine = Engine::default(); - let module = Module::from_file(&engine, "path/to/wasm_cpu.wasm")?; +use hecate::WasmCpu; +use clap::Parser; - // Create a linker and instantiate the module - let mut linker = Linker::new(&engine); - let instance = linker.instantiate(&module)?; +#[derive(Parser)] +struct Args { + cpu: PathBuf, + memory: PathBuf, +} - // Access the exported functions - let new = instance.get_func("new").unwrap().get0::()?; - let execute = instance.get_func("execute").unwrap().get1::()?; - - // Create a CPU instance - let cpu = new(); - - // Load memory into the CPU - let memory = instance.get_memory("memory").unwrap(); - memory.write(0, &[0x01, 0x02, 0x03])?; - - // Execute the CPU - execute(cpu, RunMode::Run.into()); +fn main() -> anyhow::Result<()> { + let Args { cpu, memory } = Args::parse(); + let mut cpu = WasmCpu::from_path(cpu)?; + let mem = std::fs::read(memory)?; + cpu.load_memory(&mem); Ok(()) } diff --git a/std_cpu/Cargo.toml b/std_cpu/Cargo.toml index 21660f0..fc38da2 100644 --- a/std_cpu/Cargo.toml +++ b/std_cpu/Cargo.toml @@ -9,5 +9,5 @@ crate-type = ["cdylib"] [dependencies] extism-pdk = "1.3.0" -hecate = { version = "0.1.0", path = ".." } serde = { version = "1", features = ["derive"] } +common = { version = "0.1.0", path = "../common" } diff --git a/std_cpu/src/lib.rs b/std_cpu/src/lib.rs index 32c35b3..8352fff 100644 --- a/std_cpu/src/lib.rs +++ b/std_cpu/src/lib.rs @@ -1,9 +1,11 @@ use extism_pdk::*; use serde::{Deserialize, Serialize}; -use hecate::cpu_trait::{CpuTrait, DebugMode, RunMode}; +use common::{DebugMode, Init, RunMode, RunResult, SetMemory, SetVerbose}; -pub struct WasmCpu { +#[derive(Serialize, Deserialize, ToBytes, FromBytes)] +#[encoding(Json)] +pub struct Cpu { memory: Vec, registers: Vec, ip: u16, @@ -12,14 +14,6 @@ pub struct WasmCpu { verbose: bool, } -#[derive(serde::Deserialize, FromBytes)] -#[encoding(Json)] -struct Init { - verbose: bool, - mem_size: usize, - registers: usize, -} - // start with something simple #[plugin_fn] pub fn init( @@ -29,23 +23,77 @@ pub fn init( registers, }: Init, ) -> FnResult<()> { - var::set_var!( + var::set( "cpu", - WasmCpu { + Cpu { memory: vec![0; mem_size], - registers: vec![0; 8], + registers: vec![0; registers], ip: 0, sp: 0xFFFF, flags: 0, verbose, - } - ); + }, + )?; Ok(()) } #[plugin_fn] -pub fn add(input: Add) -> FnResult { - Ok(Sum { - value: input.left + input.right, - }) +pub fn set_verbose(verbose: SetVerbose) -> FnResult<()> { + let mut cpu: Cpu = var::get("cpu")?.unwrap(); + cpu.verbose = verbose.0; + var::set("cpu", cpu)?; + Ok(()) +} + +#[plugin_fn] +pub fn load_memory(SetMemory { offset, memory }: SetMemory) -> FnResult<()> { + let mut cpu: Cpu = var::get("cpu")?.unwrap(); + cpu.memory[offset..memory.len()].copy_from_slice(&memory); + var::set("cpu", cpu)?; + Ok(()) +} + +#[plugin_fn] +pub fn execute(run_mode: RunMode) -> FnResult { + match run_mode { + RunMode::Run => run(), + RunMode::Debug(debug_mode) => debug(debug_mode), + RunMode::StepOver => step_over(), + RunMode::StepInto => step_into(), + RunMode::StepOut => step_out(), + RunMode::RunFor(cycles) => run_for(cycles), + } +} + +pub fn run() -> FnResult { + // while self.ip < self.memory.len() as u16 { + // } + Ok(RunResult::Success) +} + +pub fn debug(_debug_mode: DebugMode) -> FnResult { + // Implement debug functionality + Ok(RunResult::Success) +} + +pub fn run_for(cycles: usize) -> FnResult { + for _ in 0..cycles {} + Ok(RunResult::Success) +} + +pub fn step_over() -> FnResult { + Ok(RunResult::Success) +} + +pub fn step_into() -> FnResult { + Ok(RunResult::Success) +} + +pub fn step_out() -> FnResult { + Ok(RunResult::Success) +} + +pub fn step() -> FnResult { + // Fetch and execute instructions + Ok(RunResult::Success) }