1#[link(name = "spike-interfaces", kind = "static")]
2unsafe extern "C" {
3 pub fn spike_new_processor(mem_size: u64) -> u64;
4 pub fn spike_delete_processor(processor: u64);
5 pub fn spike_execute(processor: u64, instruction: u64) -> i32;
6 pub fn spike_get_reg(processor: u64, index: u64, content: *mut u64) -> i32;
7 pub fn spike_set_reg(processor: u64, index: u64, content: u64) -> i32;
8 pub fn spike_ld(processor: u64, addr: u64, len: u64, bytes: *mut u8) -> i32;
9 pub fn spike_sd(processor: u64, addr: u64, len: u64, bytes: *mut u8) -> i32;
10}
11
12#[derive(Debug)]
13pub struct Error(i32);
14
15impl std::fmt::Display for Error {
16 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
17 write!(f, "error({})", self.0)
18 }
19}
20
21impl std::error::Error for Error {}
22
23pub struct Spike {
24 addr: u64,
25}
26
27impl Spike {
28 pub fn new(mem_size: u64) -> Self {
29 unsafe { Self { addr: spike_new_processor(mem_size) } }
30 }
31
32 pub fn execute(&self, instruction: u64) -> Result<(), Error> {
33 let r = unsafe { spike_execute(self.addr, instruction) };
34 if r != 0 { Err(Error(r)) } else { Ok(()) }
35 }
36
37 pub fn get_reg(&self, index: u64) -> Result<u64, Error> {
38 let mut x = 0;
39 let r = unsafe { spike_get_reg(self.addr, index, &mut x) };
40 if r != 0 { Err(Error(r)) } else { Ok(x) }
41 }
42
43 pub fn set_reg(&self, index: u64, content: u64) -> Result<(), Error> {
44 let r = unsafe { spike_set_reg(self.addr, index, content) };
45 if r != 0 { Err(Error(r)) } else { Ok(()) }
46 }
47
48 pub fn ld(&self, addr: u64, len: u64, bytes: *mut u8) -> Result<(), Error> {
49 let r = unsafe { spike_ld(self.addr, addr, len, bytes) };
50 if r != 0 { Err(Error(r)) } else { Ok(()) }
51 }
52
53 pub fn sd(&self, addr: u64, len: u64, bytes: *mut u8) -> Result<(), Error> {
54 let r = unsafe { spike_sd(self.addr, addr, len, bytes) };
55 if r != 0 { Err(Error(r)) } else { Ok(()) }
56 }
57}
58
59impl Drop for Spike {
60 fn drop(&mut self) {
61 unsafe { spike_delete_processor(self.addr) }
62 }
63}