Skip to content

Commit 8ac0e39

Browse files
authored
chore(emu): Update README.md (#14)
1 parent a5af083 commit 8ac0e39

File tree

3 files changed

+270
-1
lines changed

3 files changed

+270
-1
lines changed

Cargo.lock

Lines changed: 160 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/emu/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ tracing.workspace = true
2929
tracing-subscriber.workspace = true
3030
rstest.workspace = true
3131
criterion.workspace = true
32+
const-hex = { version = "1.15.0", features = ["hex"] }
3233

3334
[features]
3435
default = [ "64-bit", "a", "c", "m" ]

crates/emu/README.md

Lines changed: 109 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,111 @@
11
# `brisc`
22

3-
This crate contains the RISC-V emulator.
3+
This crate contains a simple RISC-V emulator.
4+
5+
## Features
6+
7+
### RISC-V Extensions
8+
9+
With no features enabled, this crate serves a VM emulating the `rv32i` ISA. However, it can be extended with the
10+
following features:
11+
* `64-bit` - Enable the 64-bit RISC-V architecture and accompanying instructions.
12+
* `m` - Standard Extension for Integer Multiplication and Division.
13+
* `a` - Standard Extension for Atomic Instructions
14+
* `c` - Standard Extension for Compressed Instructions.
15+
16+
## Usage
17+
18+
```rust
19+
use brisc_emu::{cfg::EmuConfig, st::StEmu};
20+
use brisc_hw::{
21+
errors::PipelineResult,
22+
kernel::Kernel,
23+
memory::{Memory, SimpleMemory},
24+
pipeline::PipelineRegister,
25+
XWord, REG_A0, REG_A1, REG_A2,
26+
};
27+
28+
/// .section .data
29+
/// hello_msg:
30+
/// .ascii "Hello, world!\n"
31+
/// hello_len = . - hello_msg
32+
///
33+
/// .section .text
34+
/// .global _start
35+
///
36+
/// _start:
37+
/// # write system call
38+
/// # a0 = file descriptor (1 for stdout)
39+
/// # a1 = buffer address
40+
/// # a2 = number of bytes to write
41+
/// # a7 = system call number (64 for write)
42+
///
43+
/// li a0, 1 # stdout file descriptor
44+
/// la a1, hello_msg # load address of message
45+
/// li a2, hello_len # length of message
46+
/// li a7, 64 # write system call number
47+
/// ecall # invoke system call
48+
///
49+
/// # exit system call
50+
/// # a0 = exit status
51+
/// # a7 = system call number (93 for exit)
52+
///
53+
/// li a0, 0 # exit status 0 (success)
54+
/// li a7, 93 # exit system call number
55+
/// ecall # invoke system call
56+
const HELLO_WORLD_ELF: &str = "7f454c460201010000000000000000000200f30001000000e8000100000000004000000000000000380100000000000004000000400038000300400004000300030000700400000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000001000000050000000000000000000000000001000000000000000100000000000c010000000000000c01000000000000001000000000000001000000060000000c010000000000000c110100000000000c110100000000000e000000000000000e0000000000000000100000000000001305100097150000938505021306e0009308000473000000130500009308d0057300000048656c6c6f2c20776f726c64210a002e7368737472746162002e74657874002e646174610000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b000000010000000600000000000000e800010000000000e8000000000000002400000000000000000000000000000004000000000000000000000000000000110000000100000003000000000000000c110100000000000c010000000000000e000000000000000000000000000000010000000000000000000000000000000100000003000000000000000000000000000000000000001a010000000000001700000000000000000000000000000001000000000000000000000000000000";
57+
58+
#[derive(Default)]
59+
struct ExampleKernel;
60+
61+
impl Kernel for ExampleKernel {
62+
fn syscall<M: Memory>(
63+
&mut self,
64+
sysno: XWord,
65+
mem: &mut M,
66+
p_reg: &mut PipelineRegister,
67+
) -> PipelineResult<XWord> {
68+
match sysno {
69+
0x5D => {
70+
let exit_code = p_reg.registers[REG_A0 as usize];
71+
p_reg.exit_code = exit_code;
72+
p_reg.exit = true;
73+
}
74+
0x40 => {
75+
let fd = p_reg.registers[REG_A0 as usize];
76+
let ptr = p_reg.registers[REG_A1 as usize];
77+
let len = p_reg.registers[REG_A2 as usize];
78+
79+
let raw_msg = mem.read_memory_range(ptr, len).unwrap();
80+
let msg = String::from_utf8_lossy(&raw_msg);
81+
82+
match fd {
83+
1 => println!("{msg}"),
84+
2 => eprintln!("{msg}"),
85+
_ => panic!("Unknown file descriptor: {msg}"),
86+
}
87+
}
88+
_ => panic!("Unknown system call: {sysno}"),
89+
}
90+
91+
Ok(0)
92+
}
93+
}
94+
95+
#[derive(Default)]
96+
struct ExampleEmuConfig;
97+
98+
impl EmuConfig for ExampleEmuConfig {
99+
type Memory = SimpleMemory;
100+
type Kernel = ExampleKernel;
101+
}
102+
103+
let elf = const_hex::decode(HELLO_WORLD_ELF).unwrap();
104+
let mut emu = StEmu::<ExampleEmuConfig>::builder()
105+
.with_kernel(ExampleKernel)
106+
.with_elf(&elf)
107+
.unwrap()
108+
.build();
109+
110+
emu.run().unwrap();
111+
```

0 commit comments

Comments
 (0)