risc0_circuit_rv32im/execute/
platform.rs

1// Copyright 2025 RISC Zero, Inc.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15use num_derive::FromPrimitive;
16use risc0_binfmt::{ByteAddr, WordAddr};
17
18pub const WORD_SIZE: usize = 4;
19pub const PAGE_BYTES: usize = 1024;
20pub const MEMORY_BYTES: u64 = 1 << 32;
21pub const MEMORY_PAGES: usize = (MEMORY_BYTES / PAGE_BYTES as u64) as usize;
22pub const MERKLE_TREE_DEPTH: usize = MEMORY_PAGES.ilog2() as usize;
23pub const LOOKUP_TABLE_CYCLES: usize = ((1 << 8) + (1 << 16)) / 16;
24pub const CONTROL_DONE_CYCLES: usize = 1;
25pub const RESERVED_CYCLES: usize = LOOKUP_TABLE_CYCLES + CONTROL_DONE_CYCLES;
26
27pub const ZERO_PAGE_START_ADDR: ByteAddr = ByteAddr(0x0000_0000);
28pub const ZERO_PAGE_END_ADDR: ByteAddr = ByteAddr(0x0001_0000);
29pub const USER_START_ADDR: ByteAddr = ZERO_PAGE_END_ADDR;
30pub const USER_END_ADDR: ByteAddr = ByteAddr(0xc000_0000);
31pub const USER_BIGINT_END_ADDR: ByteAddr = ByteAddr(0xbfff_0000);
32pub const KERNEL_START_ADDR: ByteAddr = USER_END_ADDR;
33pub const KERNEL_END_ADDR: ByteAddr = ByteAddr(0xff00_0000);
34pub const MACHINE_REGS_ADDR: ByteAddr = ByteAddr(0xffff_0000);
35pub const USER_REGS_ADDR: ByteAddr = ByteAddr(0xffff_0080);
36pub const SAFE_WRITE_ADDR: ByteAddr = ByteAddr(0xffff_0100);
37pub const MEPC_ADDR: ByteAddr = ByteAddr(0xffff_0200);
38pub const SUSPEND_PC_ADDR: ByteAddr = ByteAddr(0xffff_0210);
39pub const SUSPEND_MODE_ADDR: ByteAddr = ByteAddr(0xffff_0214);
40pub const SUSPEND_CYCLE_LOW_ADDR: ByteAddr = ByteAddr(0xffff_0218);
41pub const SUSPEND_CYCLE_HIGH_ADDR: ByteAddr = ByteAddr(0xffff_021c);
42pub const GLOBAL_OUTPUT_ADDR: ByteAddr = ByteAddr(0xffff_0240);
43pub const GLOBAL_INPUT_ADDR: ByteAddr = ByteAddr(0xffff_0260);
44
45pub const ECALL_DISPATCH_ADDR: ByteAddr = ByteAddr(0xffff_1000);
46pub const TRAP_DISPATCH_ADDR: ByteAddr = ByteAddr(0xffff_2000);
47
48pub const MEMORY_END_ADDR: WordAddr = WordAddr(0x4000_0000);
49pub const MERKLE_TREE_START_ADDR: WordAddr = WordAddr(0x4000_0000);
50pub const MERKLE_TREE_END_ADDR: WordAddr = WordAddr(0x4400_0000);
51
52pub const REG_ZERO: usize = 0; // zero constant
53pub const REG_RA: usize = 1; // return address
54pub const REG_SP: usize = 2; // stack pointer
55pub const REG_GP: usize = 3; // global pointer
56pub const REG_TP: usize = 4; // thread pointer
57pub const REG_T0: usize = 5; // temporary
58pub const REG_T1: usize = 6; // temporary
59pub const REG_T2: usize = 7; // temporary
60pub const REG_S0: usize = 8; // saved register
61pub const REG_FP: usize = 8; // frame pointer
62pub const REG_S1: usize = 9; // saved register
63pub const REG_A0: usize = 10; // fn arg / return value
64pub const REG_A1: usize = 11; // fn arg / return value
65pub const REG_A2: usize = 12; // fn arg
66pub const REG_A3: usize = 13; // fn arg
67pub const REG_A4: usize = 14; // fn arg
68pub const REG_A5: usize = 15; // fn arg
69pub const REG_A6: usize = 16; // fn arg
70pub const REG_A7: usize = 17; // fn arg
71pub const REG_S2: usize = 18; // saved register
72pub const REG_S3: usize = 19; // saved register
73pub const REG_S4: usize = 20; // saved register
74pub const REG_S5: usize = 21; // saved register
75pub const REG_S6: usize = 22; // saved register
76pub const REG_S7: usize = 23; // saved register
77pub const REG_S8: usize = 24; // saved register
78pub const REG_S9: usize = 25; // saved register
79pub const REG_S10: usize = 26; // saved register
80pub const REG_S11: usize = 27; // saved register
81pub const REG_T3: usize = 28; // temporary
82pub const REG_T4: usize = 29; // temporary
83pub const REG_T5: usize = 30; // temporary
84pub const REG_T6: usize = 31; // temporary
85pub const REG_MAX: usize = 32; // maximum number of registers
86
87pub const HOST_ECALL_TERMINATE: u32 = 0;
88pub const HOST_ECALL_READ: u32 = 1;
89pub const HOST_ECALL_WRITE: u32 = 2;
90pub const HOST_ECALL_POSEIDON2: u32 = 3;
91pub const HOST_ECALL_SHA2: u32 = 4;
92pub const HOST_ECALL_BIGINT: u32 = 5;
93
94pub const PFLAG_IS_ELEM: u32 = 0x8000_0000;
95pub const PFLAG_CHECK_OUT: u32 = 0x4000_0000;
96
97#[derive(Clone, Copy, Debug, Default, Eq, FromPrimitive, PartialEq)]
98pub enum CycleState {
99    #[default]
100    LoadRoot = 0,
101    Resume = 1,
102    Suspend = 4,
103    StoreRoot = 5,
104    ControlTable = 6,
105    ControlDone = 7,
106    MachineEcall = 8,
107    Terminate = 9,
108    HostReadSetup = 10,
109    HostWrite = 11,
110    HostReadBytes = 12,
111    HostReadWords = 13,
112    PoseidonEntry = 16,
113    PoseidonLoadState = 17,
114    PoseidonLoadIn = 18,
115    PoseidonDoOut = 21,
116    PoseidonPaging = 22,
117    PoseidonStoreState = 23,
118    PoseidonExtRound = 24,
119    PoseidonIntRound = 25,
120    ShaEcall = 32,
121    ShaLoadState = 33,
122    ShaLoadData = 34,
123    ShaMix = 35,
124    ShaStoreState = 36,
125    BigIntEcall = 40,
126    BigIntStep = 41,
127    Decode = 48,
128}
129
130pub const SYSCALL_MAX: u32 = 512;
131
132pub const MAX_IO_BYTES: u32 = 1024;
133pub const MAX_IO_WORDS: u32 = 4;
134pub const MAX_SHA_COUNT: u32 = 10;
135
136/// Returns whether `addr` is within user memory bounds.
137pub fn is_user_memory(addr: ByteAddr) -> bool {
138    addr >= USER_START_ADDR && addr < USER_END_ADDR
139}
140
141/// Returns whether `addr` is within kernel memory bounds.
142pub fn is_kernel_memory(addr: ByteAddr) -> bool {
143    addr >= KERNEL_START_ADDR && addr < KERNEL_END_ADDR
144}
145
146pub mod major {
147    pub const MISC0: u8 = 0;
148    pub const MISC1: u8 = 1;
149    pub const MISC2: u8 = 2;
150    pub const MUL0: u8 = 3;
151    pub const DIV0: u8 = 4;
152    pub const MEM0: u8 = 5;
153    pub const MEM1: u8 = 6;
154    pub const CONTROL0: u8 = 7;
155    pub const ECALL0: u8 = 8;
156    pub const POSEIDON0: u8 = 9;
157    pub const POSEIDON1: u8 = 10;
158    pub const SHA0: u8 = 11;
159    pub const BIGINT0: u8 = 12;
160}
161
162pub mod control_minor {
163    pub const RESUME: u8 = 1;
164    pub const USER_ECALL: u8 = 2;
165    pub const MRET: u8 = 3;
166}
167
168pub mod ecall_minor {
169    pub const MACHINE_ECALL: u8 = 0;
170    pub const TERMINATE: u8 = 1;
171    pub const HOST_READ_SETUP: u8 = 2;
172    pub const HOST_WRITE: u8 = 3;
173    pub const HOST_READ_BYTES: u8 = 4;
174    pub const HOST_READ_WORDS: u8 = 5;
175}
176
177pub mod poseidon_minor {
178    pub const LOAD_STATE: u8 = 0;
179    pub const LOAD_DATA: u8 = 1;
180    pub const EXT_ROUND: u8 = 2;
181    pub const INT_ROUNDS: u8 = 3;
182    pub const STORE_STATE: u8 = 4;
183}
184
185pub mod tx {
186    pub const READ: u32 = 0;
187    pub const PAGE_IN: u32 = 1;
188    pub const PAGE_OUT: u32 = 2;
189}