risc0_circuit_rv32im/execute/
segment.rs1use std::cell::Cell;
16
17use anyhow::Result;
18use derive_more::Debug;
19use risc0_binfmt::MemoryImage;
20use serde::{Deserialize, Serialize};
21
22use crate::{
23 execute::{testutil, Executor},
24 Rv32imV2Claim, MAX_INSN_CYCLES, MAX_INSN_CYCLES_LOWER_PO2,
25};
26
27use super::{Syscall, SyscallContext};
28
29#[derive(Clone, Debug, Serialize, Deserialize)]
30#[non_exhaustive]
31pub struct Segment {
32 pub partial_image: MemoryImage,
34
35 pub claim: Rv32imV2Claim,
36
37 #[debug("{}", read_record.len())]
39 pub read_record: Vec<Vec<u8>>,
40
41 #[debug("{}", write_record.len())]
43 pub write_record: Vec<u32>,
44
45 pub suspend_cycle: u32,
47
48 pub paging_cycles: u32,
50
51 pub segment_threshold: u32,
52
53 pub po2: u32,
54
55 pub index: u64,
56}
57
58impl Segment {
59 pub fn encode(&self) -> Result<Vec<u8>> {
60 Ok(postcard::to_stdvec(self)?)
61 }
62
63 pub fn decode(bytes: &[u8]) -> Result<Self> {
64 Ok(postcard::from_bytes(bytes)?)
65 }
66
67 pub fn execute(&self) -> Result<()> {
68 let handler = SegmentSyscallHandler {
69 segment: self,
70 read_pos: Cell::new(0),
71 write_pos: Cell::new(0),
72 };
73
74 let max_insn_cycles = if self.po2 >= 15 {
75 MAX_INSN_CYCLES
76 } else {
77 MAX_INSN_CYCLES_LOWER_PO2
78 };
79 Executor::new(self.partial_image.clone(), &handler, None, vec![]).run(
80 self.po2 as usize,
81 max_insn_cycles,
82 testutil::DEFAULT_SESSION_LIMIT,
83 |_| Ok(()),
84 )?;
85 Ok(())
86 }
87}
88
89struct SegmentSyscallHandler<'a> {
90 segment: &'a Segment,
91 read_pos: Cell<usize>,
92 write_pos: Cell<usize>,
93}
94
95impl Syscall for SegmentSyscallHandler<'_> {
96 fn host_read(&self, _ctx: &mut dyn SyscallContext, _fd: u32, buf: &mut [u8]) -> Result<u32> {
97 let pos = self.read_pos.replace(self.read_pos.get() + 1);
98 let read_record = &self.segment.read_record[pos];
99 buf.copy_from_slice(read_record);
100 Ok(read_record.len() as u32)
101 }
102
103 fn host_write(&self, _ctx: &mut dyn SyscallContext, _fd: u32, _buf: &[u8]) -> Result<u32> {
104 let pos = self.write_pos.replace(self.read_pos.get() + 1);
105 Ok(self.segment.write_record[pos])
106 }
107}