Skip to content

Commit

Permalink
More documentation
Browse files Browse the repository at this point in the history
  • Loading branch information
fractasy committed Nov 28, 2024
1 parent 99e161a commit 408ad17
Show file tree
Hide file tree
Showing 7 changed files with 103 additions and 67 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
12 changes: 8 additions & 4 deletions riscv/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
mod riscv_inst;
mod riscv_interpreter;
mod riscv_registers;
mod riscv_rvd;
//! RISC-V instruction structure and parser.
//! The riscv_interpreter function accepts a buffer of bytes (a slice of u8), parses it according to
//! the RISC-V spec, and generates a vector of RiscvInstruction's
pub mod riscv_inst;
pub mod riscv_interpreter;
pub mod riscv_registers;
pub mod riscv_rvd;

pub use riscv_inst::*;
pub use riscv_interpreter::*;
Expand Down
101 changes: 40 additions & 61 deletions riscv/src/riscv_inst.rs
Original file line number Diff line number Diff line change
@@ -1,38 +1,46 @@
/// RISC-V instruction definition
///
/// Contains RISCV instruction data, split by functionality
/// RISC-V comprises of a base user-level 32-bit integer instruction set. Called RV32I, it includes
/// 47 instructions, which can be grouped into six types: R-type: register-register
/// I-type: short immediates and loads
/// S-type: stores
/// B-type: conditional branches, a variation of S-type
/// U-type: long immediates
/// J-type: unconditional jumps, a variation of U-type
///
/// RV32I instruction formats showing immediate variants:
/// ```ignore
/// 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 09 08 07 06 05 04 03 02 01 00
/// | funct7 | rs2 | rs1 | funct3 | rd | opcode | R-type
/// | imm[11:0] | rs1 | funct3 | rd | opcode | I-type
/// | imm[11:5] | rs2 | rs1 | funct3 | imm[4:0] | opcode | S-type
/// |12| imm[10:5] | rs2 | rs1 | funct3 |imm[4:1] |11| opcode | B-type
/// | imm[31:12] | rd | opcode | U-type
/// |20| imm[10:1] |11| imm[19:12] | rd | opcode | J-type
/// ```
/// RV32I has x0 register hardwired to constant 0, plus x1-x31 general purpose registers.
/// All registers are 32 bits wide but in RV64I they become 64 bits wide.
/// RV32I is a load-store architecture. This means that only load and store instructions access
/// memory; arithmetic operations use only the registers. User space is 32-bit byte addressable and
/// little endian.
///
/// Correspondingly, RV64I is for 64-bit address space and RV128I is for 128-bit address space. The
/// need for RV128I is debatable and its specification is evolving. We also have RV32E for embedded
/// systems. RV32E has only 16 32-bit registers and makes the counters of RV32I optional.
///
/// See <https://devopedia.org/risc-v-instruction-sets>
//! RISC-V instruction definition
//!
//! Contains RISCV instruction data, split by functionality.
//! RISC-V comprises of a base user-level 32-bit integer instruction set. Called RV32I, it includes
//! 47 instructions, which can be grouped into six types:
//! * R-type: register-register
//! * I-type: short immediates and loads
//! * S-type: stores
//! * B-type: conditional branches, a variation of S-type
//! * U-type: long immediates
//! * J-type: unconditional jumps, a variation of U-type
//!
//! RV32I instruction formats showing immediate variants:
//! ```ignore
//! 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 09 08 07 06 05 04 03 02 01 00
//! | funct7 | rs2 | rs1 | funct3 | rd | opcode | R-type
//! | imm[11:0] | rs1 | funct3 | rd | opcode | I-type
//! | imm[11:5] | rs2 | rs1 | funct3 | imm[4:0] | opcode | S-type
//! |12| imm[10:5] | rs2 | rs1 | funct3 |imm[4:1] |11| opcode | B-type
//! | imm[31:12] | rd | opcode | U-type
//! |20| imm[10:1] |11| imm[19:12] | rd | opcode | J-type
//! ```
//! RV32I has x0 register hardwired to constant 0, plus x1-x31 general purpose registers.
//! All registers are 32 bits wide but in RV64I they become 64 bits wide.
//! RV32I is a load-store architecture. This means that only load and store instructions access
//! memory; arithmetic operations use only the registers.
//! User space is 32-bit byte addressable and little endian.
//!
//! Correspondingly, RV64I is for 64-bit address space and RV128I is for 128-bit address space. The
//! need for RV128I is debatable and its specification is evolving. We also have RV32E for embedded
//! systems. RV32E has only 16 32-bit registers and makes the counters of RV32I optional.
//!
//! See <https://devopedia.org/risc-v-instruction-sets>
/// RISC-V instruction data
#[derive(Default)]
pub struct RiscvInstruction {
/// Original instruction content (32 bits)
pub rvinst: u32,

/// Instruction type
pub t: String,

pub funct3: u32,
pub funct5: u32,
pub funct7: u32,
Expand All @@ -49,36 +57,7 @@ pub struct RiscvInstruction {
pub succ: u32,
}

/// Default constructor for RiscvInstruction structure
impl Default for RiscvInstruction {
fn default() -> Self {
Self::new()
}
}

impl RiscvInstruction {
/// RISCV instruction instance constructor, setting all values to zero
pub fn new() -> RiscvInstruction {
RiscvInstruction {
rvinst: 0,
t: String::new(),
funct3: 0,
funct5: 0,
funct7: 0,
rd: 0,
rs1: 0,
rs2: 0,
imm: 0,
imme: 0,
inst: String::new(),
aq: 0,
rl: 0,
csr: 0,
pred: 0,
succ: 0,
}
}

/// Creates a human-readable string containing RISCV data fields that are non-zero
pub fn to_text(&self) -> String {
let mut s = String::new();
Expand Down
4 changes: 3 additions & 1 deletion riscv/src/riscv_interpreter.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
//! Parses a 32-bits RISC-V instruction
use crate::{RiscvInstruction, Rvd, RvdOperation};

/// Convert 32-bits data chunk that contains a signed integer of a specified size in bits to a
Expand Down Expand Up @@ -67,7 +69,7 @@ pub fn riscv_interpreter(code: &[u32]) -> Vec<RiscvInstruction> {

// Create a RISCV instruction instance to be filled with data from the instruction and from
// the RVD info data
let mut i = RiscvInstruction::new();
let mut i = RiscvInstruction::default();

// Copy the original RISCV 32-bit instruction
i.rvinst = inst;

Check failure on line 75 in riscv/src/riscv_interpreter.rs

View workflow job for this annotation

GitHub Actions / Formatting & Clippy

field assignment outside of initializer for an instance created with Default::default()
Expand Down
4 changes: 3 additions & 1 deletion riscv/src/riscv_registers.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
/// Human-readable names of the 32 well-known RISCV registers, to be used in traces
//! RISC-V registers
/// Human-readable names of the 32 well-known RISC-V registers, to be used in traces
#[repr(usize)]
pub enum RiscVRegisters {
Zero = 0,
Expand Down
2 changes: 2 additions & 0 deletions riscv/src/riscv_rvd.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
//! RISC-V RVD
use std::collections::HashMap;

/// RVD operation, including a map to store nested operations, if any
Expand Down

0 comments on commit 408ad17

Please sign in to comment.