Improve exception dumps and general debug info, make the emulator capable of running the riscv ISA tests, and perform some general fixes i found while making it pass the tests for RV64I
This commit is contained in:
12
run-riscv-tests.sh
Executable file
12
run-riscv-tests.sh
Executable file
@@ -0,0 +1,12 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
for f in $(cat torun.txt); do
|
||||||
|
result=$(cargo run $f 2>&1 | tail -n 1 | awk '{print $NF}')
|
||||||
|
if [[ $result != 0 ]]; then
|
||||||
|
testnum=$(( result >> 1 ))
|
||||||
|
echo $f: test $testnum failed
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
echo all tests passed
|
||||||
@@ -164,7 +164,7 @@ impl Core {
|
|||||||
let instr = Instruction(instr);
|
let instr = Instruction(instr);
|
||||||
|
|
||||||
if let Err(e) = find_and_exec(instr, self) {
|
if let Err(e) = find_and_exec(instr, self) {
|
||||||
eprintln!("instr: {:08x}", instr.0);
|
dbg!(instr);
|
||||||
return Err(e);
|
return Err(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -174,6 +174,7 @@ impl Core {
|
|||||||
fn throw_exception(&mut self, exception: Exception) {
|
fn throw_exception(&mut self, exception: Exception) {
|
||||||
eprintln!("Exception: {exception:?}");
|
eprintln!("Exception: {exception:?}");
|
||||||
dbg!(self.pc, self.x_regs);
|
dbg!(self.pc, self.x_regs);
|
||||||
|
dbg!(self.x_regs[10]);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn reset(&mut self, pc: u64) {
|
pub fn reset(&mut self, pc: u64) {
|
||||||
|
|||||||
@@ -6,9 +6,15 @@
|
|||||||
|
|
||||||
const MASK_REGISTER: u32 = 0x1f;
|
const MASK_REGISTER: u32 = 0x1f;
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy)]
|
#[derive(Clone, Copy)]
|
||||||
pub struct Instruction(pub u32);
|
pub struct Instruction(pub u32);
|
||||||
|
|
||||||
|
impl std::fmt::Debug for Instruction {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
f.write_fmt(format_args!("{:08x}", self.0))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
impl Instruction {
|
impl Instruction {
|
||||||
#[inline]
|
#[inline]
|
||||||
|
|||||||
@@ -131,6 +131,7 @@ pub(crate) fn find_and_exec(instr: Instruction, core: &mut Core) -> Result<(), E
|
|||||||
// FENCE is just implemented as a SeqCst fence always here
|
// FENCE is just implemented as a SeqCst fence always here
|
||||||
// I dont yet care about the potential performance issue this may bring
|
// I dont yet care about the potential performance issue this may bring
|
||||||
std::sync::atomic::fence(std::sync::atomic::Ordering::SeqCst);
|
std::sync::atomic::fence(std::sync::atomic::Ordering::SeqCst);
|
||||||
|
core.advance_pc();
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
_ => illegal(instr),
|
_ => illegal(instr),
|
||||||
@@ -142,7 +143,15 @@ pub(crate) fn find_and_exec(instr: Instruction, core: &mut Core) -> Result<(), E
|
|||||||
Err(ExceptionType::EnvironmentCallFromMMode.with_no_value())
|
Err(ExceptionType::EnvironmentCallFromMMode.with_no_value())
|
||||||
}
|
}
|
||||||
(0b000, 0b000000000001, 0, 0) => Err(ExceptionType::Breakpoint.with_no_value()),
|
(0b000, 0b000000000001, 0, 0) => Err(ExceptionType::Breakpoint.with_no_value()),
|
||||||
_ => illegal(instr),
|
_ => {
|
||||||
|
// Temporarily allowing unrecognized instructions here to be able to run
|
||||||
|
// the official ISA tests, which perform CSR operations but work just fine
|
||||||
|
// without them
|
||||||
|
eprintln!("Unrecognized instruction within SYSTEM opcode");
|
||||||
|
dbg!(instr);
|
||||||
|
core.advance_pc();
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
},
|
},
|
||||||
_ => illegal(instr),
|
_ => illegal(instr),
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ instr_op!(srl, srli, |x, shamt| x >> (shamt & 0b111111));
|
|||||||
instr_op!(
|
instr_op!(
|
||||||
srlw,
|
srlw,
|
||||||
srliw,
|
srliw,
|
||||||
|x, shamt| (x >> (shamt & 0b11111)) as i32 as i64 as u64
|
|x, shamt| (x as u32 >> (shamt & 0b11111)) as i32 as i64 as u64
|
||||||
);
|
);
|
||||||
instr_op!(sra, srai, |x, shamt| (x as i64 >> (shamt & 0b111111))
|
instr_op!(sra, srai, |x, shamt| (x as i64 >> (shamt & 0b111111))
|
||||||
as u64);
|
as u64);
|
||||||
@@ -64,8 +64,9 @@ pub fn jal(core: &mut Core, instr: Instruction) -> Result<(), Exception> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn jalr(core: &mut Core, instr: Instruction) -> Result<(), Exception> {
|
pub fn jalr(core: &mut Core, instr: Instruction) -> Result<(), Exception> {
|
||||||
|
let target = core.reg_read(instr.rs1()).wrapping_add(instr.imm_i()) & !1;
|
||||||
core.reg_write(instr.rd(), core.pc.wrapping_add(4));
|
core.reg_write(instr.rd(), core.pc.wrapping_add(4));
|
||||||
core.pc = core.reg_read(instr.rs1()).wrapping_add(instr.imm_i());
|
core.pc = target;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -263,8 +263,8 @@ impl Ram {
|
|||||||
if !addr.is_multiple_of(8) {
|
if !addr.is_multiple_of(8) {
|
||||||
let high_word_addr = addr.wrapping_add(4);
|
let high_word_addr = addr.wrapping_add(4);
|
||||||
|
|
||||||
let low_word = self.read_byte(addr)?;
|
let low_word = self.read_word(addr)?;
|
||||||
let high_word = self.read_byte(high_word_addr)?;
|
let high_word = self.read_word(high_word_addr)?;
|
||||||
|
|
||||||
return Ok((low_word as u64) | (high_word as u64) << 32);
|
return Ok((low_word as u64) | (high_word as u64) << 32);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user