use crate::config::BackendKind;
use crate::tests::support::builder::instruction::{ECALL, FENCE_IORW, InstructionBuilder};
use crate::tests::support::multihart::{DATA_BASE, MultiHart};
const T0: u32 = 5;
const T1: u32 = 6;
const T2: u32 = 7;
const T3: u32 = 28;
const T4: u32 = 29;
const T5: u32 = 30;
const T6: u32 = 31;
const A0: u32 = 10;
const A1: u32 = 11;
const A2: u32 = 12;
const A3: u32 = 13;
const A7: u32 = 17;
const MHARTID: u32 = 0xF14;
const SYS_EXIT: i32 = 93;
pub fn program(harts: i32, iterations: i32) -> Vec<u32> {
let i = InstructionBuilder::new;
vec![
i().addi(T0, 0, 31).build(),
i().addi(T2, 0, 1).build(),
i().sll(T2, T2, T0).build(),
i().addi(T2, T2, 0x400).build(),
i().addi(T1, 0, iterations).build(),
i().addi(T3, 0, 1).build(),
i().addi(T4, T2, 16).build(),
i().lr_d(T5, T2).build(),
i().bne(T5, 0, -4).build(),
i().sc_d(T6, T2, T3).build(),
i().bne(T6, 0, -12).build(),
i().ld(T6, T2, 8).build(),
i().addi(T6, T6, 1).build(),
i().sd(T2, T6, 8).build(),
FENCE_IORW,
i().sd(T2, 0, 0).build(),
i().addi(T1, T1, -1).build(),
i().bne(T1, 0, -40).build(),
i().amoadd_d(0, T4, T3).build(),
i().csrrs(A1, MHARTID, 0).build(),
i().bne(A1, 0, 28).build(),
i().ld(A2, T2, 16).build(),
i().addi(A3, 0, harts).build(),
i().bne(A2, A3, -8).build(),
i().ld(A0, T2, 8).build(),
i().addi(A7, 0, SYS_EXIT).build(),
ECALL,
i().jal(0, 0).build(),
]
}
fn critical_section_is_exclusive(harts: usize, backend: BackendKind) {
let iterations = 100;
let mut system = MultiHart::new(harts, backend, &program(harts as i32, iterations));
let exit = system.run_until_exit(8_000_000);
let expected = (harts as u64) * (iterations as u64);
assert_eq!(exit, Some(expected), "{harts} harts on {backend:?}");
assert_eq!(system.read_u64(DATA_BASE), 0, "lock released at the end");
}
#[test]
fn two_inorder_harts_never_share_the_critical_section() {
critical_section_is_exclusive(2, BackendKind::InOrder);
}
#[test]
fn four_inorder_harts_never_share_the_critical_section() {
critical_section_is_exclusive(4, BackendKind::InOrder);
}
#[test]
fn two_o3_harts_never_share_the_critical_section() {
critical_section_is_exclusive(2, BackendKind::OutOfOrder);
}
#[test]
fn four_o3_harts_never_share_the_critical_section() {
critical_section_is_exclusive(4, BackendKind::OutOfOrder);
}