From fb019dd3021bad8a1030fa3a47ee93350ef4088d Mon Sep 17 00:00:00 2001 From: clabby Date: Wed, 27 Aug 2025 11:09:58 -0400 Subject: [PATCH] chore(emu): Update `README.md` --- Cargo.lock | 160 ++++++++++++++++++++++++++++++++++++++++++ crates/emu/Cargo.toml | 1 + crates/emu/README.md | 110 ++++++++++++++++++++++++++++- 3 files changed, 270 insertions(+), 1 deletion(-) diff --git a/Cargo.lock b/Cargo.lock index 2d3db8a..efd633d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -35,11 +35,18 @@ version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" +[[package]] +name = "bitflags" +version = "2.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34efbcccd345379ca2868b2b2c9d3782e9cc58ba87bc7d79d5b53d9c9ae6f25d" + [[package]] name = "brisc-emu" version = "0.0.1" dependencies = [ "brisc-hw", + "const-hex", "criterion", "elf", "rstest", @@ -138,6 +145,28 @@ version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b94f61472cee1439c0b966b47e3aca9ae07e45d070759512cd390ea2bebc6675" +[[package]] +name = "const-hex" +version = "1.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dccd746bf9b1038c0507b7cec21eb2b11222db96a2902c96e8c185d6d20fb9c4" +dependencies = [ + "cfg-if", + "cpufeatures", + "hex", + "proptest", + "serde", +] + +[[package]] +name = "cpufeatures" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280" +dependencies = [ + "libc", +] + [[package]] name = "criterion" version = "0.5.1" @@ -272,6 +301,18 @@ dependencies = [ "slab", ] +[[package]] +name = "getrandom" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26145e563e54f2cadc477553f1ec5ee650b00862f0a58bcd12cbdc5f0ea2d2f4" +dependencies = [ + "cfg-if", + "libc", + "r-efi", + "wasi", +] + [[package]] name = "glob" version = "0.3.2" @@ -305,6 +346,12 @@ version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fc0fef456e4baa96da950455cd02c081ca953b141298e41db3fc7e36b1da849c" +[[package]] +name = "hex" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" + [[package]] name = "indexmap" version = "2.7.1" @@ -452,6 +499,15 @@ dependencies = [ "plotters-backend", ] +[[package]] +name = "ppv-lite86" +version = "0.2.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9" +dependencies = [ + "zerocopy", +] + [[package]] name = "proc-macro-crate" version = "3.2.0" @@ -470,6 +526,22 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "proptest" +version = "1.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6fcdab19deb5195a31cf7726a210015ff1496ba1464fd42cb4f537b8b01b471f" +dependencies = [ + "bitflags", + "lazy_static", + "num-traits", + "rand", + "rand_chacha", + "rand_xorshift", + "regex-syntax", + "unarray", +] + [[package]] name = "quote" version = "1.0.37" @@ -479,6 +551,50 @@ dependencies = [ "proc-macro2", ] +[[package]] +name = "r-efi" +version = "5.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" + +[[package]] +name = "rand" +version = "0.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6db2770f06117d490610c7488547d543617b21bfa07796d7a12f6f1bd53850d1" +dependencies = [ + "rand_chacha", + "rand_core", +] + +[[package]] +name = "rand_chacha" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb" +dependencies = [ + "ppv-lite86", + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38" +dependencies = [ + "getrandom", +] + +[[package]] +name = "rand_xorshift" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "513962919efc330f829edb2535844d1b912b0fbe2ca165d613e4e8788bb05a5a" +dependencies = [ + "rand_core", +] + [[package]] name = "rayon" version = "1.10.0" @@ -779,6 +895,12 @@ dependencies = [ "tracing-log", ] +[[package]] +name = "unarray" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eaea85b334db583fe3274d12b4cd1880032beab409c0d774be044d4480ab9a94" + [[package]] name = "unicode-ident" version = "1.0.13" @@ -801,6 +923,15 @@ dependencies = [ "winapi-util", ] +[[package]] +name = "wasi" +version = "0.14.2+wasi-0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9683f9a5a998d873c0d21fcbe3c083009670149a8fab228644b8bd36b2c48cb3" +dependencies = [ + "wit-bindgen-rt", +] + [[package]] name = "wasm-bindgen" version = "0.2.100" @@ -981,3 +1112,32 @@ checksum = "0e7f4ea97f6f78012141bcdb6a216b2609f0979ada50b20ca5b52dde2eac2bb1" dependencies = [ "memchr", ] + +[[package]] +name = "wit-bindgen-rt" +version = "0.39.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f42320e61fe2cfd34354ecb597f86f413484a798ba44a8ca1165c58d42da6c1" +dependencies = [ + "bitflags", +] + +[[package]] +name = "zerocopy" +version = "0.8.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1039dd0d3c310cf05de012d8a39ff557cb0d23087fd44cad61df08fc31907a2f" +dependencies = [ + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.8.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ecf5b4cc5364572d7f4c329661bcc82724222973f2cab6f050a4e5c22f75181" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] diff --git a/crates/emu/Cargo.toml b/crates/emu/Cargo.toml index c6452e6..7532892 100644 --- a/crates/emu/Cargo.toml +++ b/crates/emu/Cargo.toml @@ -29,6 +29,7 @@ tracing.workspace = true tracing-subscriber.workspace = true rstest.workspace = true criterion.workspace = true +const-hex = { version = "1.15.0", features = ["hex"] } [features] default = [ "64-bit", "a", "c", "m" ] diff --git a/crates/emu/README.md b/crates/emu/README.md index 2f9d23e..d8402a5 100644 --- a/crates/emu/README.md +++ b/crates/emu/README.md @@ -1,3 +1,111 @@ # `brisc` -This crate contains the RISC-V emulator. +This crate contains a simple RISC-V emulator. + +## Features + +### RISC-V Extensions + +With no features enabled, this crate serves a VM emulating the `rv32i` ISA. However, it can be extended with the +following features: +* `64-bit` - Enable the 64-bit RISC-V architecture and accompanying instructions. +* `m` - Standard Extension for Integer Multiplication and Division. +* `a` - Standard Extension for Atomic Instructions +* `c` - Standard Extension for Compressed Instructions. + +## Usage + +```rust +use brisc_emu::{cfg::EmuConfig, st::StEmu}; +use brisc_hw::{ + errors::PipelineResult, + kernel::Kernel, + memory::{Memory, SimpleMemory}, + pipeline::PipelineRegister, + XWord, REG_A0, REG_A1, REG_A2, +}; + +/// .section .data +/// hello_msg: +/// .ascii "Hello, world!\n" +/// hello_len = . - hello_msg +/// +/// .section .text +/// .global _start +/// +/// _start: +/// # write system call +/// # a0 = file descriptor (1 for stdout) +/// # a1 = buffer address +/// # a2 = number of bytes to write +/// # a7 = system call number (64 for write) +/// +/// li a0, 1 # stdout file descriptor +/// la a1, hello_msg # load address of message +/// li a2, hello_len # length of message +/// li a7, 64 # write system call number +/// ecall # invoke system call +/// +/// # exit system call +/// # a0 = exit status +/// # a7 = system call number (93 for exit) +/// +/// li a0, 0 # exit status 0 (success) +/// li a7, 93 # exit system call number +/// ecall # invoke system call +const HELLO_WORLD_ELF: &str = "7f454c460201010000000000000000000200f30001000000e8000100000000004000000000000000380100000000000004000000400038000300400004000300030000700400000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000001000000050000000000000000000000000001000000000000000100000000000c010000000000000c01000000000000001000000000000001000000060000000c010000000000000c110100000000000c110100000000000e000000000000000e0000000000000000100000000000001305100097150000938505021306e0009308000473000000130500009308d0057300000048656c6c6f2c20776f726c64210a002e7368737472746162002e74657874002e646174610000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b000000010000000600000000000000e800010000000000e8000000000000002400000000000000000000000000000004000000000000000000000000000000110000000100000003000000000000000c110100000000000c010000000000000e000000000000000000000000000000010000000000000000000000000000000100000003000000000000000000000000000000000000001a010000000000001700000000000000000000000000000001000000000000000000000000000000"; + +#[derive(Default)] +struct ExampleKernel; + +impl Kernel for ExampleKernel { + fn syscall( + &mut self, + sysno: XWord, + mem: &mut M, + p_reg: &mut PipelineRegister, + ) -> PipelineResult { + match sysno { + 0x5D => { + let exit_code = p_reg.registers[REG_A0 as usize]; + p_reg.exit_code = exit_code; + p_reg.exit = true; + } + 0x40 => { + let fd = p_reg.registers[REG_A0 as usize]; + let ptr = p_reg.registers[REG_A1 as usize]; + let len = p_reg.registers[REG_A2 as usize]; + + let raw_msg = mem.read_memory_range(ptr, len).unwrap(); + let msg = String::from_utf8_lossy(&raw_msg); + + match fd { + 1 => println!("{msg}"), + 2 => eprintln!("{msg}"), + _ => panic!("Unknown file descriptor: {msg}"), + } + } + _ => panic!("Unknown system call: {sysno}"), + } + + Ok(0) + } +} + +#[derive(Default)] +struct ExampleEmuConfig; + +impl EmuConfig for ExampleEmuConfig { + type Memory = SimpleMemory; + type Kernel = ExampleKernel; +} + +let elf = const_hex::decode(HELLO_WORLD_ELF).unwrap(); +let mut emu = StEmu::::builder() + .with_kernel(ExampleKernel) + .with_elf(&elf) + .unwrap() + .build(); + +emu.run().unwrap(); +```