Skip to content

Commit

Permalink
More documentation (#176)
Browse files Browse the repository at this point in the history
* Improve documentation
  • Loading branch information
fractasy authored Nov 29, 2024
1 parent cd11b3d commit 5211645
Show file tree
Hide file tree
Showing 29 changed files with 686 additions and 349 deletions.
40 changes: 40 additions & 0 deletions book/developer/doc.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
# Documentation

## Generating Zisk documentation
The Zisk project is documented to help users and developers.

In order to generate the Zisk documentation, execute the cargo doc command. We recommend using the
`--no-deps` flag to avoid generating documentation for all its external dependencies.

```sh
$ cargo doc --no-deps
```

This will generate a set of HTML files under the `target/doc` diretory.

## Viewing Zisk documentation

The Zisk documentation can be visualized using a web browser and navigating to
`target/doc/cargo_zisk/`.

If you are working with Zisk in a remote server (typical setup during development) then first you
must export the local files through HTTP, for example using an HTTP proxy:

```sh
$ python3 -m http.server --bind 0.0.0.0 8000
```

Now, you can browse to the server:

http://<IP>:8000/target/doc/cargo_zisk/

## Adding content

Some basic hints:
* Only public modules and public elements will appear in the cargo documentation
* In particular, remember to make documented modules public in lib.rs (`pub mod <module>;`)
* Documentation for a public module must start in the first line in the module file, starting with
`//! ...`
* Documentation for a public element must be placed right before it, starting with `/// ...`
* Wrap code with triple spike: `//! \`\`\``
* To avoid cargo doc to compile the code, use ignore after the priple spike: `//! \`\`\` ignore`
7 changes: 7 additions & 0 deletions core/src/bin/riscv2zisk.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,14 @@
//! Executable that performs a transpilation of a RISC-V ELF file to a Zisk ROM file.
use std::{env, process};

use zisk_core::Riscv2zisk;

/// Performs a transpilation of a RISC-V ELF file to a Zisk ROM file.
/// The binary accepts 2 arguments: the path of the input RISC-V ELF file, and the path of the
/// output Zisk rom file.
/// After parsing the arguments, the main function calls Riscv2zisk::runfile to perform the actual
/// work.
fn main() {
println!("riscv2zisk converts an ELF RISCV file into a ZISK ASM file");

Expand Down
5 changes: 3 additions & 2 deletions core/src/elf2rom.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
//use core::num;
//! Reads RISC-V data from and ELF file and converts it to a ZiskRom
use crate::{
zv2zisk::{add_entry_exit_jmp, add_zisk_code, add_zisk_init_data},
riscv2zisk_context::{add_entry_exit_jmp, add_zisk_code, add_zisk_init_data},
RoData, ZiskInst, ZiskRom, RAM_ADDR, RAM_SIZE, ROM_ADDR, ROM_ADDR_MAX, ROM_ENTRY,
};
use elf::{
Expand Down
27 changes: 18 additions & 9 deletions core/src/inst_context.rs
Original file line number Diff line number Diff line change
@@ -1,29 +1,38 @@
//! * Provides a context to execute a set of Zisk instructions.
//! * The context contains the state of the Zisk processor, modified by the execution of every
//! instruction.
//! * The state includes: memory, registers (a, b, c, flag, sp), program counter (pc), step and a
//! flag to mark the end of the program execution.
use crate::{Mem, ROM_ENTRY};

/// ZisK instruction context data container, storing the state of the execution
pub struct InstContext {
// Memory, including several read-only sections and one read-write section (input data)
// This memory is initialized before running the program with the input data, and modified by
// the program instructions during the execution. The RW data that has not been previously
// written is read as zero
/// Memory, including several read-only sections and one read-write section (input data)
/// This memory is initialized before running the program with the input data, and modified by
/// the program instructions during the execution. The RW data that has not been previously
/// written is read as zero
pub mem: Mem,

// Current values of registers a, b, c, and flag
/// Current value of register a
pub a: u64,
/// Current value of register b
pub b: u64,
/// Current value of register c
pub c: u64,
/// Current value of register flag
pub flag: bool,

// Value of sp register
/// Current value of register sp
pub sp: u64,

// Value of ROM program execution address, i.e. program counter (pc)
/// Current value of ROM program execution address, i.e. program counter (pc)
pub pc: u64,

// Current execution step: 0, 1, 2...
/// Current execution step: 0, 1, 2...
pub step: u64,

// End flag, set to true only by the last instruction to execute
/// End flag, set to true only by the last instruction to execute
pub end: bool,
}

Expand Down
79 changes: 66 additions & 13 deletions core/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,27 +1,80 @@
mod elf2rom;
mod inst_context;
mod mem;
mod mem_section;
mod riscv2zisk;
//! # Zero-Knowledge Proving
//!
//! * Proving a program execution using zero-knowledge has the following phases:
//! * Witness Computation
//! * Executes the program
//! * Plans the number and size of the secondary state machines instances required to contain
//! all the operations
//! * Generates field element traces of the execution for all the required state machine
//! instances
//! * Proof Generation
//! * Generates individual proofs for every state machine instance
//! * Aggregates individual proofs into aggregated proofs, recursively
//! * Generates final proof
//! * Proof Verification
//! * Authenticates the final proof
//!
//! # Proof Delegation
//!
//! * The Zisk main state machine processes the input data using the Zisk program and generates the
//! output data.
//! * This process performs some simple operations that can be proven by the main state machine
//! itself, and also some more complex operations that must be delegated to other specialized
//! state machines that can prove them more efficiently.
//! * These secondary state machines can be composed of several inner state machines that are more
//! specialized in proving some specific operations, again for efficiency reasons.
//! * The proof delegation between the different state machines requires that the client state
//! machines provide the required data to the server state machines to proof their operations.
//! * The required data depends on the type of proof delegation.
//! * Some secondary machines that are made of several, more specialized state machines, include a
//! state machine proxy to dispatch incoming required data and distribute it among the rest.
//! * The executor is the component in charge of calling the different state machines, in the right
//! order, collecting the required data from ones and providing it to the others, parallelizing
//! when possible.
//! * In order to parallelize this process as much and as soon as possible, a first execution of the
//! program is done, collecting the minimum trace required to split the execution in smaller parts
//! that can be re-executed again in parallel, and this time generating more information that will
//! feed the secondary state machines.
//!
//! # State machines map
//!
//! * Main
//! * Binary Proxy
//! * Binary Basic --> Binary Basic Table
//! * Binary Extension --> Binary Extension Table
//! * Rom
//! * Arith
//! * Memory Proxy
//! * Memory Aligned
//! * Memory Unaligned
//! * Memory Input
//!
//! The zisk_core crate contains basic structures and functionality used by several other modules:
//! opcodes, instructions and transpilation
pub mod elf2rom;
pub mod inst_context;
pub mod mem;
pub mod riscv2zisk;
pub mod riscv2zisk_context;
mod utils;
mod zisk_definitions;
mod zisk_inst;
mod zisk_inst_builder;
mod zisk_required_operation;
mod zisk_rom;
mod zv2zisk;
pub mod zisk_definitions;
pub mod zisk_inst;
pub mod zisk_inst_builder;
pub mod zisk_registers;
pub mod zisk_required_operation;
pub mod zisk_rom;

pub mod zisk_ops;

pub use elf2rom::*;
pub use inst_context::*;
pub use mem::*;
pub use mem_section::*;
pub use riscv2zisk::*;
pub use riscv2zisk_context::*;
pub use utils::*;
pub use zisk_definitions::*;
pub use zisk_inst::*;
pub use zisk_inst_builder::*;
pub use zisk_registers::*;
pub use zisk_required_operation::*;
pub use zisk_rom::*;
pub use zv2zisk::*;
123 changes: 121 additions & 2 deletions core/src/mem.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,125 @@
use crate::UART_ADDR;
//! Zisk program memory
//!
//! # Memory map
//!
//! * The Zisk processor memory stores data in little-endian format.
//! * The addressable memory space is divided into several regions described in the following map:
//!
//! `|--------------- ROM_ENTRY: first BIOS instruction ( 0x1000)`
//! `|`
//! `| Performs memory initialization, calls program at ROM_ADDR,`
//! `| and after returning it performs memory finalization.`
//! `| Contains ecall/system call management code.`
//! `|`
//! `|--------------- ROM_EXIT: last BIOS instruction (0x10000000)`
//! ` ...`
//! `|--------------- ROM_ADDR: first program instruction (0x80000000)`
//! `|`
//! `| Contains program instructions.`
//! `| Calls ecalls/system calls when required.`
//! `|`
//! `|--------------- INPUT_ADDR (0x90000000)`
//! `|`
//! `| Contains program input data.`
//! `|`
//! `|--------------- SYS_ADDR (= RAM_ADDR = REG_FIRST) (0xa0000000)`
//! `|`
//! `| Contains system address.`
//! `| The first 256 bytes contain 32 8-byte registers`
//! `| The address UART_ADDR is used as a standard output`
//! `|`
//! `|--------------- OUTPUT_ADDR (0xa0010000)`
//! `|`
//! `| Contains output data, which is written during`
//! `| program execution and read during memory finalization`
//! `|`
//! `|--------------- AVAILABLE_MEM_ADDR (0xa0020000)`
//! `|`
//! `| Contains program memory, available for normal R/W`
//! `| use during program execution.`
//! `|`
//! `|--------------- (0xb0000000)`
//! ` ...`
//!
//! ## ROM_ENTRY / ROM_ADDR / ROM_EXIT
//! * The program will start executing at the first BIOS address `ROM_ENTRY`.
//! * The first instructions do the basic program setup, including writing the input data into
//! memory, configuring the ecall (system call) program address, and configuring the program
//! completion return address.
//! * After the program setup, the program counter jumps to `ROM_ADDR`, executing the actual
//! program.
//! * During the execution, the program can make system calls that will jump to the configured ecall
//! program address, and return once the task has completed. The precompiled are implemented via
//! ecall.
//! * After the program is completed, the program counter will jump to the configured return
//! address, where the finalization tasks will happen, inluding reading the output data from
//! memory.
//! * The address before the last one will jump to `ROM_EXIT`, the last insctruction of the
//! execution.
//! * In general, setup and finalization instructions are located in low addresses, while the actual
//! program insctuctions are located in high addresses.
//!
//! ## INPUT_ADDR
//! * During the program initialization the input data for the program execution is copied in this
//! memory region, beginning with `INPUT_ADDR`.
//! * After the data has been written by the setup process, this data can only be read by the
//! program execution, i.e. it becomes a read-only (RO) memory region.
//!
//! ## SYS_ADDR / OUPUT_ADDR / AVAILABLE_MEM_ADDR
//! * This memory section can be written and read by the program execution many times, i.e. it is a
//! read-write (RW) memory region.
//! * The first RW memory region going from `SYS_ADDR` to `OUTPUT_ADDR` is reserved for the system
//! operation.
//! * The lower addresses of this region is used to store 32 registers of 8 bytes each, i.e. 256
//! bytes in total. These registers are the equivalent to the RISC-V registers.
//! * Any data of exactly 1-byte length written to UART_ADDR will be sent to the standard output of
//! the system.
//! * The second RW memory region going from `OUTPUT_ADDR` to `AVAILABLE_MEM_ADDR` is reserved to
//! copy the output data during the program execution.
//! * The third RW memory region going from `AVAILABLE_MEM_ADDR` onwards can be used during the
//! program execution a general purpose memory.
use crate::MemSection;
/// Fist input data memory address
pub const INPUT_ADDR: u64 = 0x90000000;
/// Maximum size of the input data
pub const MAX_INPUT_SIZE: u64 = 0x10000000; // 256M,
/// First globa RW memory address
pub const RAM_ADDR: u64 = 0xa0000000;
/// Size of the global RW memory
pub const RAM_SIZE: u64 = 0x10000000; // 256M
/// First system RW memory address
pub const SYS_ADDR: u64 = RAM_ADDR;
/// Size of the system RW memory
pub const SYS_SIZE: u64 = 0x10000;
/// First output RW memory address
pub const OUTPUT_ADDR: u64 = SYS_ADDR + SYS_SIZE;
/// Size of the output RW memory
pub const OUTPUT_MAX_SIZE: u64 = 0x10000; // 64K
/// First general purpose RW memory address
pub const AVAILABLE_MEM_ADDR: u64 = OUTPUT_ADDR + OUTPUT_MAX_SIZE;
/// Size of the general purpose RW memory address
pub const AVAILABLE_MEM_SIZE: u64 = RAM_SIZE - OUTPUT_MAX_SIZE - SYS_SIZE;
/// First BIOS instruction address, i.e. first instruction executed
pub const ROM_ENTRY: u64 = 0x1000;
/// Last BIOS instruction address, i.e. last instruction executed
pub const ROM_EXIT: u64 = 0x10000000;
/// First program ROM instruction address, i.e. first RISC-V transpiled instruction
pub const ROM_ADDR: u64 = 0x80000000;
/// Maximum program ROM instruction address
pub const ROM_ADDR_MAX: u64 = INPUT_ADDR - 1;
/// Zisk architecture ID
pub const ARCH_ID_ZISK: u64 = 0xFFFEEEE;
/// UART memory address; single bytes written here will be copied to the standard output
pub const UART_ADDR: u64 = SYS_ADDR + 512;

/// Memory section data, including a buffer (a vector of bytes) and start and end program
/// memory addresses.
#[derive(Default)]
pub struct MemSection {
pub start: u64,
pub end: u64,
pub buffer: Vec<u8>,
}

/// Memory structure, containing several read sections and one single write section
#[derive(Default)]
Expand Down
7 changes: 0 additions & 7 deletions core/src/mem_section.rs

This file was deleted.

5 changes: 5 additions & 0 deletions core/src/riscv2zisk.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
//! Converts a RISC-V program into a Zisk program.
//!
//! The input parameter is an ELF RISC-V file name, and the output parameter is a JSON Zisk ROM
//! file. Optionally, the Zisk ROM can also be saved in PIL-friendly format or in a binary format.
use crate::{elf2rom, elf2romfile, ZiskRom};
use std::error::Error;

Expand Down
Loading

0 comments on commit 5211645

Please sign in to comment.