Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

28 changes: 28 additions & 0 deletions crates/execution/ab-riscv-interpreter-compliance-tests/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
[package]
name = "ab-riscv-interpreter-compliance-tests"
description = "Compliance tests for RISC-V interpreter"
license = "0BSD"
version = "0.0.1"
authors = ["Nazar Mokrynskyi <nazar@mokrynskyi.com>"]
edition = "2024"
include = [
"/src",
"/build.rs",
"/Cargo.toml",
"/tests",
]
links = "ab-riscv-interpreter-compliance-tests"

[package.metadata.docs.rs]
all-features = true

[dependencies]
ab-riscv-interpreter = { workspace = true }
ab-riscv-macros = { workspace = true, features = ["proc-macro"] }
ab-riscv-primitives = { workspace = true }

[build-dependencies]
ab-riscv-macros = { workspace = true, features = ["build"] }

[lints]
workspace = true
52 changes: 52 additions & 0 deletions crates/execution/ab-riscv-interpreter-compliance-tests/build.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
use ab_riscv_macros::process_instruction_macros;
use std::error::Error;
use std::path::PathBuf;
use std::process::Command;
use std::{env, fs};

const TAG: &str = "ctp-release-e9514aa-2025-12-28";
const COMMIT: &str = "281d71ef3d61e32111217b20305ea3ef9b1582e2";
const URL: &str = "https://github.com/riscv-non-isa/riscv-arch-test";

fn main() -> Result<(), Box<dyn Error>> {
process_instruction_macros()?;

let out_dir = PathBuf::from(env::var("OUT_DIR").expect("Always set by Cargo; qed"));
let dest = out_dir.join("riscv-arch-test");

if dest.exists() {
if let Ok(output) = Command::new("git")
.current_dir(&dest)
.args(["rev-parse", "HEAD"])
.output()
&& output.status.success()
&& output.stdout.trim_ascii() == COMMIT.as_bytes()
{
return Ok(());
}

println!(
"cargo::warning=`riscv-arch-test` commit mismatch or invalid repo; removing and \
re-cloning"
);
let _ = fs::remove_dir_all(&dest);
}

let output = Command::new("git")
.args(["clone", "--depth", "1", "--branch", TAG, "--quiet", URL])
.arg(&dest)
.output()?;

if !output.status.success() {
println!("cargo::error=`riscv-arch-test` clone failed:");
for line in String::from_utf8_lossy(&output.stdout).lines() {
println!("cargo::error={line}");
}
for line in String::from_utf8_lossy(&output.stderr).lines() {
println!("cargo::error={line}");
}
return Err("`riscv-arch-test` clone failed".into());
}

Ok(())
}
12 changes: 12 additions & 0 deletions crates/execution/ab-riscv-interpreter-compliance-tests/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
//! Compliance tests for RISC-V interpreter
#![feature(const_trait_impl, const_try, const_try_residual, try_blocks)]
#![expect(incomplete_features, reason = "generic_const_exprs")]
// TODO: This feature is not actually used in this crate, but is added as a workaround for
// https://github.com/rust-lang/rust/issues/141492
#![feature(generic_const_exprs)]
#![no_std]

pub mod rv64;

/// Path to the `riscv-arch-test` repo
pub const RISCV_ARCH_TEST_REPO_PATH: &str = concat!(env!("OUT_DIR"), "/riscv-arch-test");
71 changes: 71 additions & 0 deletions crates/execution/ab-riscv-interpreter-compliance-tests/src/rv64.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
use ab_riscv_interpreter::rv64::b::zbc::clmul_internal;
use ab_riscv_interpreter::rv64::{Rv64InterpreterState, Rv64SystemInstructionHandler};
use ab_riscv_interpreter::{ExecutableInstruction, ExecutionError, ProgramCounter, VirtualMemory};
use ab_riscv_macros::{instruction, instruction_execution};
use ab_riscv_primitives::instruction::Instruction;
use ab_riscv_primitives::instruction::rv64::b::zba::Rv64ZbaInstruction;
use ab_riscv_primitives::instruction::rv64::b::zbb::Rv64ZbbInstruction;
use ab_riscv_primitives::instruction::rv64::b::zbc::Rv64ZbcInstruction;
use ab_riscv_primitives::instruction::rv64::b::zbs::Rv64ZbsInstruction;
use ab_riscv_primitives::registers::Register;
use core::fmt;
use core::ops::ControlFlow;

/// B(Zba+Zbb+Zbs)+Zbc
#[instruction(inherit = [Rv64BInstruction, Rv64ZbcInstruction])]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum FullRv64BInstruction<Reg> {}

#[instruction]
impl<Reg> const Instruction for FullRv64BInstruction<Reg>
where
Reg: [const] Register<Type = u64>,
{
type Reg = Reg;

#[inline(always)]
fn try_decode(instruction: u32) -> Option<Self> {
None
}

#[inline(always)]
fn alignment() -> u8 {
size_of::<u32>() as u8
}

#[inline(always)]
fn size(&self) -> u8 {
size_of::<u32>() as u8
}
}

#[instruction]
impl<Reg> fmt::Display for FullRv64BInstruction<Reg>
where
Reg: fmt::Display + Copy,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {}
}
}

#[instruction_execution]
impl<Reg, Memory, PC, InstructionHandler, CustomError>
ExecutableInstruction<
Rv64InterpreterState<Reg, Memory, PC, InstructionHandler, CustomError>,
CustomError,
> for FullRv64BInstruction<Reg>
where
Reg: Register<Type = u64>,
[(); Reg::N]:,
Memory: VirtualMemory,
PC: ProgramCounter<Reg::Type, Memory, CustomError>,
InstructionHandler: Rv64SystemInstructionHandler<Reg, Memory, PC, CustomError>,
{
fn execute(
self,
state: &mut Rv64InterpreterState<Reg, Memory, PC, InstructionHandler, CustomError>,
) -> Result<ControlFlow<()>, ExecutionError<Reg::Type, Self, CustomError>> {
Ok(ControlFlow::Continue(()))
}
}
Loading