This commit is contained in:
Steve Biedermann 2024-12-02 15:44:49 +01:00
commit d5f621e44a
12 changed files with 3010 additions and 0 deletions

1
.gitignore vendored Normal file
View File

@ -0,0 +1 @@
/target

2770
Cargo.lock generated Normal file

File diff suppressed because it is too large Load Diff

11
Cargo.toml Normal file
View File

@ -0,0 +1,11 @@
[package]
name = "hecate"
version = "0.1.0"
edition = "2021"
[dependencies]
extism = "1.9.1"
wasm-bindgen = "0.2.97"
[workspace]
members = ["std_cpu"]

30
src/cpu_trait.rs Normal file
View File

@ -0,0 +1,30 @@
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
}

70
src/lib.rs Normal file
View File

@ -0,0 +1,70 @@
mod cpu_trait;
pub use cpu_trait::{CpuTrait, DebugMode, RunMode};
#[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 set_verbose(&mut self, verbose: bool) {
self.verbose = verbose;
}
pub fn load_memory(&mut self, memory: &[u8]) {
self.memory[..memory.len()].copy_from_slice(memory);
}
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),
}
}
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
}
}

28
src/main.rs Normal file
View File

@ -0,0 +1,28 @@
use wasmtime::*;
use crate::cpu_trait::{CpuTrait, RunMode, DebugMode};
fn main() -> Result<(), Box<dyn std::error::Error>> {
// Create an engine and module
let engine = Engine::default();
let module = Module::from_file(&engine, "path/to/wasm_cpu.wasm")?;
// Create a linker and instantiate the module
let mut linker = Linker::new(&engine);
let instance = linker.instantiate(&module)?;
// Access the exported functions
let new = instance.get_func("new").unwrap().get0::<i32>()?;
let execute = instance.get_func("execute").unwrap().get1::<i32, ()>()?;
// 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());
Ok(())
}

View File

@ -0,0 +1,2 @@
[build]
target = "wasm32-unknown-unknown"

2
std_cpu/.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
/target
Cargo.lock

13
std_cpu/Cargo.toml Normal file
View File

@ -0,0 +1,13 @@
[package]
name = "rust-pdk-template"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[lib]
crate-type = ["cdylib"]
[dependencies]
extism-pdk = "1.3.0"
hecate = { version = "0.1.0", path = ".." }
serde = { version = "1", features = ["derive"] }

28
std_cpu/LICENSE Normal file
View File

@ -0,0 +1,28 @@
BSD 3-Clause License
Copyright (c) 2024, Extism
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

4
std_cpu/README.md Normal file
View File

@ -0,0 +1,4 @@
# Extism Rust PDK Plugin
See more documentation at https://github.com/extism/rust-pdk and
[join us on Discord](https://extism.org/discord) for more help.

51
std_cpu/src/lib.rs Normal file
View File

@ -0,0 +1,51 @@
use extism_pdk::*;
use serde::{Deserialize, Serialize};
use hecate::cpu_trait::{CpuTrait, DebugMode, RunMode};
pub struct WasmCpu {
memory: Vec<u8>,
registers: Vec<u16>,
ip: u16,
sp: u16,
flags: u8,
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(
Init {
verbose,
mem_size,
registers,
}: Init,
) -> FnResult<()> {
var::set_var!(
"cpu",
WasmCpu {
memory: vec![0; mem_size],
registers: vec![0; 8],
ip: 0,
sp: 0xFFFF,
flags: 0,
verbose,
}
);
Ok(())
}
#[plugin_fn]
pub fn add(input: Add) -> FnResult<Sum> {
Ok(Sum {
value: input.left + input.right,
})
}