Skip to content

Commit

Permalink
merge master
Browse files Browse the repository at this point in the history
  • Loading branch information
mcalancea committed Dec 2, 2024
2 parents bb388a2 + a88b95b commit 171ca51
Show file tree
Hide file tree
Showing 55 changed files with 967 additions and 1,041 deletions.
17 changes: 9 additions & 8 deletions Cargo.lock

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

4 changes: 4 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,12 @@ members = [
resolver = "2"

[workspace.package]
categories = ["cryptography", "zk", "blockchain", "ceno"]
edition = "2021"
keywords = ["cryptography", "zk", "blockchain", "ceno"]
license = "MIT OR Apache-2.0"
readme = "README.md"
repository = "https://github.com/scroll-tech/ceno"
version = "0.1.0"

[workspace.dependencies]
Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@ Please see [the slightly outdated paper](https://eprint.iacr.org/2024/387) for a

🚧 This project is currently under construction and not suitable for use in production. 🚧

If you are unfamiliar with the RISC-V instruction set, please have a look at the [RISC-V instruction set reference](https://github.com/jameslzhu/riscv-card/blob/master/riscv-card.pdf).
If you are unfamiliar with the RISC-V instruction set, please have a look at the [RISC-V instruction set reference](https://github.com/jameslzhu/riscv-card/releases/download/latest/riscv-card.pdf).

## Local build requirements

Ceno is built in Rust, so [installing the Rust toolchain](https://www.rust-lang.org/tools/install) is a pre-requisite, if you want to develop on your local machine. We also use [cargo-make](https://sagiegurari.github.io/cargo-make/) to build Ceno. You can install cargo-make with the following command:
Ceno is built in Rust, so [installing the Rust toolchain](https://www.rust-lang.org/tools/install) is a pre-requisite if you want to develop on your local machine. We also use [cargo-make](https://sagiegurari.github.io/cargo-make/) to build Ceno. You can install cargo-make with the following command:

```sh
cargo install cargo-make
Expand Down
6 changes: 6 additions & 0 deletions ceno_emul/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,12 +1,18 @@
[package]
categories.workspace = true
description = "A Risc-V emulator for Ceno"
edition.workspace = true
keywords.workspace = true
license.workspace = true
name = "ceno_emul"
readme.workspace = true
repository.workspace = true
version.workspace = true

[dependencies]
anyhow = { version = "1.0", default-features = false }
elf = "0.7"
itertools.workspace = true
num-derive.workspace = true
num-traits.workspace = true
strum.workspace = true
Expand Down
31 changes: 30 additions & 1 deletion ceno_emul/src/addr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,10 @@
// See the License for the specific language governing permissions and
// limitations under the License.

use std::{fmt, ops};
use std::{
fmt,
ops::{self, Range},
};

pub const WORD_SIZE: usize = 4;
pub const PC_WORD_SIZE: usize = 4;
Expand Down Expand Up @@ -192,3 +195,29 @@ impl ops::AddAssign<u32> for ByteAddr {
self.0 += rhs;
}
}

pub trait IterAddresses {
fn iter_addresses(&self) -> impl ExactSizeIterator<Item = Addr>;
}

impl IterAddresses for Range<Addr> {
fn iter_addresses(&self) -> impl ExactSizeIterator<Item = Addr> {
self.clone().step_by(WORD_SIZE)
}
}

impl<'a, T: GetAddr> IterAddresses for &'a [T] {
fn iter_addresses(&self) -> impl ExactSizeIterator<Item = Addr> {
self.iter().map(T::get_addr)
}
}

pub trait GetAddr {
fn get_addr(&self) -> Addr;
}

impl GetAddr for Addr {
fn get_addr(&self) -> Addr {
*self
}
}
1 change: 1 addition & 0 deletions ceno_emul/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
#![deny(clippy::cargo)]
mod addr;
pub use addr::*;

Expand Down
79 changes: 24 additions & 55 deletions ceno_emul/src/platform.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
use std::ops::Range;

use crate::addr::{Addr, RegIdx};

/// The Platform struct holds the parameters of the VM.
Expand All @@ -7,74 +9,41 @@ use crate::addr::{Addr, RegIdx};
/// - codes of environment calls.
#[derive(Clone, Debug)]
pub struct Platform {
pub rom_start: Addr,
pub rom_end: Addr,
pub ram_start: Addr,
pub ram_end: Addr,
pub rom: Range<Addr>,
pub ram: Range<Addr>,
pub public_io: Range<Addr>,
pub hints: Range<Addr>,
pub stack_top: Addr,
/// If true, ecall instructions are no-op instead of trap. Testing only.
pub unsafe_ecall_nop: bool,
}

pub const CENO_PLATFORM: Platform = Platform {
rom_start: 0x2000_0000,
rom_end: 0x3000_0000 - 1,
ram_start: 0x8000_0000,
ram_end: 0xFFFF_0000 - 1,
rom: 0x2000_0000..0x3000_0000,
ram: 0x8000_0000..0xFFFF_0000,
public_io: 0x3000_1000..0x3000_2000,
hints: 0x4000_0000..0x5000_0000,
stack_top: 0xC0000000,
unsafe_ecall_nop: false,
};

impl Platform {
// Virtual memory layout.

pub const fn rom_start(&self) -> Addr {
self.rom_start
}

pub const fn rom_end(&self) -> Addr {
self.rom_end
}

pub fn is_rom(&self, addr: Addr) -> bool {
(self.rom_start()..=self.rom_end()).contains(&addr)
}

// TODO figure out a proper region for public io
pub const fn public_io_start(&self) -> Addr {
0x3000_1000
}

pub const fn public_io_end(&self) -> Addr {
0x3000_2000 - 1
}

pub const fn ram_start(&self) -> Addr {
if cfg!(feature = "forbid_overflow") {
// -1<<11 == 0x800 is the smallest negative 'immediate'
// offset we can have in memory instructions.
// So if we stay away from it, we are safe.
assert!(self.ram_start >= 0x800);
}
self.ram_start
}

pub const fn ram_end(&self) -> Addr {
if cfg!(feature = "forbid_overflow") {
// (1<<11) - 1 == 0x7ff is the largest positive 'immediate'
// offset we can have in memory instructions.
// So if we stay away from it, we are safe.
assert!(self.ram_end < -(1_i32 << 11) as u32)
}
self.ram_end
self.rom.contains(&addr)
}

pub fn is_ram(&self, addr: Addr) -> bool {
(self.ram_start()..=self.ram_end()).contains(&addr)
self.ram.contains(&addr)
}

pub fn is_pub_io(&self, addr: Addr) -> bool {
(self.public_io_start()..=self.public_io_end()).contains(&addr)
self.public_io.contains(&addr)
}

pub fn is_hints(&self, addr: Addr) -> bool {
self.hints.contains(&addr)
}

/// Virtual address of a register.
Expand All @@ -91,13 +60,13 @@ impl Platform {
// Startup.

pub const fn pc_base(&self) -> Addr {
self.rom_start()
self.rom.start
}

// Permissions.

pub fn can_read(&self, addr: Addr) -> bool {
self.is_rom(addr) || self.is_ram(addr) || self.is_pub_io(addr)
self.is_rom(addr) || self.is_ram(addr) || self.is_pub_io(addr) || self.is_hints(addr)
}

pub fn can_write(&self, addr: Addr) -> bool {
Expand Down Expand Up @@ -139,17 +108,17 @@ impl Platform {
#[cfg(test)]
mod tests {
use super::*;
use crate::VMState;
use crate::{VMState, WORD_SIZE};

#[test]
fn test_no_overlap() {
let p = CENO_PLATFORM;
assert!(p.can_execute(p.pc_base()));
// ROM and RAM do not overlap.
assert!(!p.is_rom(p.ram_start()));
assert!(!p.is_rom(p.ram_end()));
assert!(!p.is_ram(p.rom_start()));
assert!(!p.is_ram(p.rom_end()));
assert!(!p.is_rom(p.ram.start));
assert!(!p.is_rom(p.ram.end - WORD_SIZE as Addr));
assert!(!p.is_ram(p.rom.start));
assert!(!p.is_ram(p.rom.end - WORD_SIZE as Addr));
// Registers do not overlap with ROM or RAM.
for reg in [
Platform::register_vma(0),
Expand Down
3 changes: 2 additions & 1 deletion ceno_emul/src/rv32im.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
// limitations under the License.

use anyhow::{Result, anyhow};
use itertools::enumerate;
use num_derive::ToPrimitive;
use std::sync::OnceLock;
use strum_macros::EnumIter;
Expand Down Expand Up @@ -403,7 +404,7 @@ struct FastDecodeTable {
impl FastDecodeTable {
fn new() -> Self {
let mut table: FastInstructionTable = [0; 1 << 10];
for (isa_idx, insn) in RV32IM_ISA.iter().enumerate() {
for (isa_idx, insn) in enumerate(&RV32IM_ISA) {
Self::add_insn(&mut table, insn, isa_idx);
}
Self { table }
Expand Down
2 changes: 1 addition & 1 deletion ceno_emul/src/tracer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -199,7 +199,7 @@ impl StepRecord {
Some(value),
Some(Change::new(value, value)),
Some(WriteOp {
addr: CENO_PLATFORM.ram_start().into(),
addr: CENO_PLATFORM.ram.start.into(),
value: Change {
before: value,
after: value,
Expand Down
7 changes: 4 additions & 3 deletions ceno_emul/src/vm_state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use std::collections::HashMap;

use super::rv32im::EmuContext;
use crate::{
PC_STEP_SIZE, Program,
PC_STEP_SIZE, Program, WORD_SIZE,
addr::{ByteAddr, RegIdx, Word, WordAddr},
platform::Platform,
rv32im::{DecodedInstruction, Emulator, TrapCause},
Expand Down Expand Up @@ -44,7 +44,7 @@ impl VMState {
};

// init memory from program.image
for (&addr, &value) in program.image.iter() {
for (&addr, &value) in &program.image {
vm.init_memory(ByteAddr(addr).waddr(), value);
}

Expand Down Expand Up @@ -123,7 +123,8 @@ impl EmuContext for VMState {
// Read two registers, write one register, write one memory word, and branch.
tracing::warn!("ecall ignored: syscall_id={}", function);
self.store_register(DecodedInstruction::RD_NULL as RegIdx, 0)?;
let addr = self.platform.ram_start().into();
// Example ecall effect - any writable address will do.
let addr = (self.platform.stack_top - WORD_SIZE as u32).into();
self.store_memory(addr, self.peek_memory(addr))?;
self.set_pc(ByteAddr(self.pc) + PC_STEP_SIZE);
Ok(true)
Expand Down
2 changes: 1 addition & 1 deletion ceno_emul/tests/test_elf.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ fn test_ceno_rt_mem() -> Result<()> {
let mut state = VMState::new_from_elf(CENO_PLATFORM, program_elf)?;
let _steps = run(&mut state)?;

let value = state.peek_memory(CENO_PLATFORM.ram_start().into());
let value = state.peek_memory(CENO_PLATFORM.ram.start.into());
assert_eq!(value, 6765, "Expected Fibonacci 20, got {}", value);
Ok(())
}
Expand Down
5 changes: 5 additions & 0 deletions ceno_rt/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
[package]
categories.workspace = true
description = "Ceno runtime library"
edition.workspace = true
keywords.workspace = true
license.workspace = true
name = "ceno_rt"
readme = "README.md"
repository.workspace = true
version.workspace = true

[dependencies]
Expand Down
1 change: 1 addition & 0 deletions ceno_rt/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
#![deny(clippy::cargo)]
#![feature(strict_overflow_ops)]
#![no_std]

Expand Down
5 changes: 5 additions & 0 deletions ceno_zkvm/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
[package]
categories.workspace = true
description = "Ceno ZKVM"
edition.workspace = true
keywords.workspace = true
license.workspace = true
name = "ceno_zkvm"
readme.workspace = true
repository.workspace = true
version.workspace = true

[dependencies]
Expand Down
Loading

0 comments on commit 171ca51

Please sign in to comment.