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