Skip to content

Commit

Permalink
unify riscv and nvm memory
Browse files Browse the repository at this point in the history
This patch unifies the memory implementation of the RISC-V
and NVM virtual machines. The riscv crate now depends on the
vm crate memory modules. Some code in the vm crate had to be
moved to the riscv crate to avoid circular dependencies.
  • Loading branch information
govereau committed Apr 5, 2024
1 parent f6b5030 commit 378a213
Show file tree
Hide file tree
Showing 21 changed files with 91 additions and 244 deletions.
1 change: 1 addition & 0 deletions network/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ ark-ec.workspace = true
ark-serialize.workspace = true

nexus-config = { path = "../config" }
nexus-riscv = { path = "../riscv" }
nexus-vm = { path = "../vm" }
nexus-prover = { path = "../prover" }
hex = "0.4.3"
Expand Down
3 changes: 2 additions & 1 deletion network/src/bin/pcdnode/post.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@ use crate::{
api::NexusAPI::{Error, NexusProof, Program, Query},
request_work, WorkerState, LOG_TARGET,
};
use nexus_vm::{eval::NexusVM, memory::trie::MerkleTrie, riscv::translate_elf_bytes, trace::trace};
use nexus_riscv::nvm::translate_elf_bytes;
use nexus_vm::{eval::NexusVM, memory::trie::MerkleTrie, trace::trace};

pub fn manage_proof(
mut state: WorkerState,
Expand Down
1 change: 1 addition & 0 deletions prover/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ anyhow = "1.0"

zstd = { version = "0.12", default-features = false }

nexus-riscv = { path = "../riscv" }
nexus-vm = { path = "../vm" }
nexus-nova = { path = "../nova", features = ["spartan"] }
nexus-tui = { path = "../tools/tui" }
Expand Down
2 changes: 1 addition & 1 deletion prover/examples/prove.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
//! Run with `cargo run --release --example prove`.
use nexus_config::{vm::NovaImpl, VmConfig};
use nexus_vm::riscv::VMOpts;
use nexus_riscv::VMOpts;

use tracing::level_filters::LevelFilter;
use tracing_subscriber::EnvFilter;
Expand Down
12 changes: 12 additions & 0 deletions prover/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,15 @@ pub use ark_relations::r1cs::SynthesisError;
pub use ark_serialize::SerializationError;
pub use nexus_nova::nova::{pcd::compression::SpartanError, Error as NovaError};
pub use nexus_nova::r1cs::Error as R1CSError;
pub use nexus_riscv::error::VMError as RVError;
pub use nexus_vm::error::NexusVMError;

/// Errors related to proof generation
#[derive(Debug)]
pub enum ProofError {
/// A error occured loading program
VMError(RVError),

/// An error occured executing program
NexusVMError(NexusVMError),

Expand Down Expand Up @@ -48,6 +52,12 @@ pub enum ProofError {
}
use ProofError::*;

impl From<RVError> for ProofError {
fn from(x: RVError) -> ProofError {
VMError(x)
}
}

impl From<NexusVMError> for ProofError {
fn from(x: NexusVMError) -> ProofError {
NexusVMError(x)
Expand Down Expand Up @@ -91,6 +101,7 @@ impl From<SpartanError> for ProofError {
impl Error for ProofError {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
match self {
VMError(e) => Some(e),
NexusVMError(e) => Some(e),
IOError(e) => Some(e),
CircuitError(e) => Some(e),
Expand All @@ -110,6 +121,7 @@ impl Error for ProofError {
impl Display for ProofError {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
match self {
VMError(e) => write!(f, "{e}"),
NexusVMError(e) => write!(f, "{e}"),
IOError(e) => write!(f, "{e}"),
CircuitError(e) => write!(f, "{e}"),
Expand Down
7 changes: 2 additions & 5 deletions prover/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,8 @@ use std::path::Path;

use ark_serialize::{CanonicalDeserialize, CanonicalSerialize};

use nexus_vm::{
memory::trie::MerkleTrie,
riscv::{load_nvm, VMOpts},
trace::trace,
};
use nexus_riscv::{nvm::load_nvm, VMOpts};
use nexus_vm::{memory::trie::MerkleTrie, trace::trace};

use nexus_nova::nova::pcd::compression::SNARK;

Expand Down
2 changes: 1 addition & 1 deletion prover/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ use nexus_prover::{
types::{ComPCDNode, ComPP},
LOG_TARGET,
};
use nexus_vm::riscv::VMOpts;
use nexus_riscv::VMOpts;

#[derive(Debug, Parser)]
#[command(author, version, about, long_about = None)]
Expand Down
3 changes: 3 additions & 0 deletions riscv/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,6 @@ categories = { workspace = true }
clap.workspace = true
elf.workspace = true
thiserror = "1.0"
num-traits = "0.2"

nexus-vm = { path = "../vm" }
8 changes: 8 additions & 0 deletions riscv/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,14 @@ pub enum VMError {
/// An error occurred while parsing the ELF headers
#[error(transparent)]
ELFError(#[from] elf::ParseError),

/// ELF format not supported
#[error("ELF format not supported: {0}")]
ELFFormat(&'static str),

/// Nexus VM Error
#[error(transparent)]
NVMError(#[from] nexus_vm::error::NexusVMError),
}

/// Result type for VM functions that can produce errors
Expand Down
37 changes: 20 additions & 17 deletions riscv/src/vm/eval.rs → riscv/src/eval.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
//! A Virtual Machine for RISC-V
use super::memory::*;
use nexus_vm::{
instructions::Width,
memory::{paged::Paged, Memory},
};

use crate::error::*;
use crate::rv32::{parse::*, *};
use VMError::*;
Expand All @@ -14,7 +18,7 @@ pub struct VM {
/// ISA registers
pub regs: Regs,
/// machine memory
pub mem: Memory,
pub mem: Paged,
/// current instruction
pub inst: Inst,
/// internal result register
Expand All @@ -32,8 +36,7 @@ pub struct Regs {

impl VM {
pub fn new(pc: u32) -> Self {
let mem = Memory::default();
let mut vm = VM { mem, ..Self::default() };
let mut vm = Self::default();
vm.regs.pc = pc;
vm
}
Expand All @@ -58,7 +61,7 @@ impl VM {
pub fn init_memory(&mut self, addr: u32, bytes: &[u8]) -> Result<()> {
// slow, but simple
for (i, b) in bytes.iter().enumerate() {
self.mem.sb(addr + (i as u32), *b as u32);
self.mem.store(Width::B, addr + (i as u32), *b as u32)?;
}
Ok(())
}
Expand Down Expand Up @@ -101,8 +104,8 @@ fn alu_op(aop: AOP, x: u32, y: u32) -> u32 {

/// evaluate next instruction
pub fn eval_inst(vm: &mut VM) -> Result<()> {
let slice = vm.mem.rd_page(vm.regs.pc);
vm.inst = parse_inst(vm.regs.pc, slice)?;
let slice = vm.mem.load(Width::W, vm.regs.pc)?.0.to_le_bytes();
vm.inst = parse_inst(vm.regs.pc, &slice)?;

// initialize micro-architecture state
vm.Z = 0;
Expand Down Expand Up @@ -143,11 +146,11 @@ pub fn eval_inst(vm: &mut VM) -> Result<()> {

let addr = add32(X, imm);
match lop {
LB => vm.Z = vm.mem.lb(addr),
LH => vm.Z = vm.mem.lh(addr),
LW => vm.Z = vm.mem.lw(addr),
LBU => vm.Z = vm.mem.lbu(addr),
LHU => vm.Z = vm.mem.lhu(addr),
LB => vm.Z = vm.mem.load(Width::B, addr)?.0,
LH => vm.Z = vm.mem.load(Width::H, addr)?.0,
LW => vm.Z = vm.mem.load(Width::W, addr)?.0,
LBU => vm.Z = vm.mem.load(Width::BU, addr)?.0,
LHU => vm.Z = vm.mem.load(Width::HU, addr)?.0,
}
}
STORE { sop, rs1, rs2, imm } => {
Expand All @@ -156,10 +159,10 @@ pub fn eval_inst(vm: &mut VM) -> Result<()> {

let addr = add32(X, imm);
match sop {
SB => vm.mem.sb(addr, Y),
SH => vm.mem.sh(addr, Y),
SW => vm.mem.sw(addr, Y),
}
SB => vm.mem.store(Width::B, addr, Y)?,
SH => vm.mem.store(Width::H, addr, Y)?,
SW => vm.mem.store(Width::W, addr, Y)?,
};
}
ALUI { aop, rd, rs1, imm } => {
RD = rd;
Expand All @@ -182,7 +185,7 @@ pub fn eval_inst(vm: &mut VM) -> Result<()> {
if num == 1 {
let mut stdout = std::io::stdout();
for addr in a0..a0 + a1 {
let b = vm.mem.lb(addr);
let b = vm.mem.load(Width::B, addr)?.0;
stdout.write_all(&[b as u8])?;
}
let _ = stdout.flush();
Expand Down
8 changes: 5 additions & 3 deletions riscv/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,20 +1,22 @@
//! A RISC-V virtual machine designed for verified computing
#![allow(non_snake_case)]
#![allow(clippy::field_reassign_with_default)]

mod error;
pub mod error;
pub mod eval;
pub mod machines;
pub mod nvm;
pub mod rv32;
pub mod vm;

use clap::Args;
use elf::{abi::PT_LOAD, endian::LittleEndian, segment::ProgramHeader, ElfBytes};
use std::fs::read;
use std::path::PathBuf;

pub use error::*;
use eval::*;
use rv32::*;
use vm::eval::*;

// don't break API
pub use machines::{loop_vm, nop_vm};
Expand Down
3 changes: 2 additions & 1 deletion riscv/src/machines.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#![allow(clippy::identity_op)]

use crate::{Regs, VM};
use nexus_vm::{instructions::Width, memory::Memory};

/// An array of test machines, useful for debugging and developemnt.
#[allow(clippy::type_complexity)]
Expand Down Expand Up @@ -37,7 +38,7 @@ pub fn lookup_test_code(name: &str) -> Option<Vec<u32>> {
fn assemble(words: &[u32]) -> VM {
let mut vm = VM::new(0);
for (i, w) in words.iter().enumerate() {
vm.mem.sw(i as u32 * 4, *w);
vm.mem.store(Width::W, i as u32 * 4, *w).unwrap();
}
vm
}
Expand Down
36 changes: 16 additions & 20 deletions vm/src/riscv.rs → riscv/src/nvm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,28 +11,24 @@ use elf::{
ElfBytes,
};

pub use nexus_riscv::VMOpts;
use nexus_riscv::{
use nexus_vm::{
eval::NexusVM,
instructions::{Inst, Opcode, Opcode::*, Width::BU},
memory::Memory,
};

use crate::{
error::{Result, VMError::ELFFormat},
machines::{lookup_test_code, loop_code, nop_code},
rv32::{parse::parse_inst, Inst as RVInst, AOP, RV32},
VMError,
VMError, VMOpts,
};

use crate::error::{NexusVMError::ELFFormat, Result};
use crate::eval::NexusVM;
use crate::instructions::{Inst, Opcode, Opcode::*, Width::BU};
use crate::memory::Memory;

#[inline]
fn add32(a: u32, b: u32) -> u32 {
a.overflowing_add(b).0
}

#[inline]
fn sub32(a: u32, b: u32) -> u32 {
a.overflowing_sub(b).0
}

#[inline]
fn mul32(a: u32, b: u32) -> u32 {
a.overflowing_mul(b).0
Expand Down Expand Up @@ -269,22 +265,22 @@ pub fn load_nvm<M: Memory>(opts: &VMOpts) -> Result<NexusVM<M>> {
if let Some(vm) = lookup_test_code(m) {
translate_test_machine(&vm)
} else {
Err(VMError::UnknownMachine(m.clone()).into())
Err(VMError::UnknownMachine(m.clone()))
}
} else {
translate_elf(opts.file.as_ref().unwrap())
}
}

#[cfg(test)]
pub mod test {
mod test {
use super::*;
use crate::eval::eval;
use crate::memory::trie::MerkleTrie;
use nexus_riscv::machines::MACHINES;
use nexus_riscv::rv32::{AOP, BOP, LOP, SOP};
use crate::machines::MACHINES;
use crate::rv32::{AOP, BOP, LOP, SOP};
use nexus_vm::eval::eval;
use nexus_vm::memory::trie::MerkleTrie;

// this function is used by other test crates
// Generate a list of NVM test machines
pub fn test_machines() -> Vec<(&'static str, NexusVM<MerkleTrie>)> {
MACHINES
.iter()
Expand Down
4 changes: 0 additions & 4 deletions riscv/src/vm.rs

This file was deleted.

Loading

0 comments on commit 378a213

Please sign in to comment.