Skip to content

Commit

Permalink
add test for rv64fd. but wip.
Browse files Browse the repository at this point in the history
  • Loading branch information
Clo91eaf committed Mar 21, 2024
1 parent 1063fc5 commit d4b05b7
Show file tree
Hide file tree
Showing 4 changed files with 137 additions and 0 deletions.
1 change: 1 addition & 0 deletions src/cpu.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2080,6 +2080,7 @@ impl Cpu {
// fadd.d

self.fpg.write(rd, self.fpg.read(rs1) + self.fpg.read(rs2));
self.fpg.fflags(rd);
}
0x04 => {
// fsub.s
Expand Down
13 changes: 13 additions & 0 deletions src/cpu/csr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,19 @@ const _FFLAGS: CsrAddress = 0x001;
/// Floating-point dynamic rounding mode.
const _FRB: CsrAddress = 0x002;
/// Floating-point control and status register (frm + fflags).
/// | 31 .. 8 | 7 .. 5 | 4 | 3 | 2 | 1 | 0 |
/// |Reserved | frm | NV| DZ| OF| UF| NX|
/// frm: Rounding mode, including:
/// 000: Round to Nearest, ties to Even (RTE)
/// 001: Round towards Zero (RTZ)
/// 010: Round Down (RDN)
/// 011: Round Up (RUP)
/// 100: Round to Nearest, ties to Max Magnitude (RMM)
/// NV: Invalid Operation, most about NaN operation.
/// DZ: Division by Zero, like 1/0.
/// OF: Overflow, like 2^63.
/// UF: Underflow, like 2^-64.
/// NX: Inexact, like 1/3.
pub const FCSR: CsrAddress = 0x003;

// User Counter/Timers.
Expand Down
20 changes: 20 additions & 0 deletions src/cpu/fpg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,26 @@ impl Fpg {
pub fn write(&mut self, index: u64, value: f64) {
self.fpg[index as usize] = value;
}

/// Check fcsr flag.
/// Floating-point control and status register (frm + fflags).
/// | 31 .. 8 | 7 .. 5 | 4 | 3 | 2 | 1 | 0 |
/// |Reserved | frm | NV| DZ| OF| UF| NX|
/// NV: Invalid Operation, most about NaN operation.
/// DZ: Division by Zero, like 1/0.
/// OF: Overflow, like 2^63.
/// UF: Underflow, like 2^-64.
/// NX: Inexact, like 1/3.
pub fn fflags(&self, index: u64) -> [bool; 5] {
let f = self.fpg[index as usize];
[
false,
self.fpg[index as usize].is_infinite() && f.is_sign_negative(),
self.fpg[index as usize].is_infinite() && f.is_sign_positive(),
self.fpg[index as usize].is_infinite(),
self.fpg[index as usize].is_nan(),
]
}
}

impl fmt::Display for Fpg {
Expand Down
103 changes: 103 additions & 0 deletions tests/riscv-tests-rv64ud.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
mod rv64ud_p {

use std::fs::File;
use std::io::prelude::*;
use std::path::PathBuf;

use hemu::{bus::DRAM_BASE, cpu::Mode, emulator::Emulator};
#[macro_export]
macro_rules! add_test_p {
($name: ident) => {
#[test]
fn $name() -> anyhow::Result<()> {
let mut root = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
root.push("dependencies/tests/bin/riscv-tests/rv64ud");
root.push(("rv64ud-p-".to_owned() + stringify!($name)).replace("__", ""));

let mut file = File::open(root.as_path())?;
let mut data = Vec::new();
file.read_to_end(&mut data)?;

let mut emu = Emulator::new();
emu.initialize_dram(data);
emu.initialize_pc(DRAM_BASE);

emu.start();

// Test result is stored at a0 (x10), a function argument and a return value.
// The riscv-tests set a0 to 0 when all tests pass.
assert_eq!(0, emu.cpu.gpr.read(10));

// All tests start the user mode and finish with the instruction `ecall`, independently
// of it succeeds or fails.
assert_eq!(Mode::Machine, emu.cpu.mode);
Ok(())
}
};
}

add_test_p!(fadd);
add_test_p!(fclass);
add_test_p!(fcmp);
add_test_p!(fcvt);
add_test_p!(fcvt_w);
add_test_p!(fdiv);
add_test_p!(fmadd);
add_test_p!(fmin);
add_test_p!(ldst);
add_test_p!(__move);
add_test_p!(recoding);
add_test_p!(structural);
}

mod rv64ud_v {
use std::fs::File;
use std::io::prelude::*;
use std::path::PathBuf;

use hemu::{bus::DRAM_BASE, cpu::Mode, emulator::Emulator};
#[macro_export]
macro_rules! add_test_v {
($name: ident) => {
#[test]
fn $name() -> anyhow::Result<()> {
let mut root = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
root.push("dependencies/tests/bin/riscv-tests/rv64ud");
root.push(("rv64ud-v-".to_owned() + stringify!($name)).replace("__", ""));

let mut file = File::open(root.as_path())?;
let mut data = Vec::new();
file.read_to_end(&mut data)?;

let mut emu = Emulator::new();
emu.initialize_dram(data);
emu.initialize_pc(DRAM_BASE);

emu.start();

// https://github.com/riscv/riscv-test-env/blob/4fabfb4e0d3eacc1dc791da70e342e4b68ea7e46/v/riscv_test.h#L45
// #define RVTEST_PASS li a0, 1; scall
// when all tests pass, a0 is set to 1
// #define RVTEST_FAIL sll a0, TESTNUM, 1; 1:beqz a0, 1b; or a0, a0, 1; scall;
// when test x fails, a0 is set to 2 * x + 1
// and if no test is run, the test will loo.
assert_eq!(1, emu.cpu.gpr.read(10));

assert_eq!(Mode::Supervisor, emu.cpu.mode);
Ok(())
}
};
}
add_test_v!(fadd);
add_test_v!(fclass);
add_test_v!(fcmp);
add_test_v!(fcvt);
add_test_v!(fcvt_w);
add_test_v!(fdiv);
add_test_v!(fmadd);
add_test_v!(fmin);
add_test_v!(ldst);
add_test_v!(__move);
add_test_v!(recoding);
add_test_v!(structural);
}

0 comments on commit d4b05b7

Please sign in to comment.