miden_processor/fast/
io_ops.rs

1use vm_core::Word;
2
3use super::{DOUBLE_WORD_SIZE, ExecutionError, FastProcessor, Felt, WORD_SIZE_FELT};
4use crate::{AdviceProvider, ErrorContext, Host, ProcessState};
5
6impl FastProcessor {
7    /// Analogous to `Process::op_push`.
8    pub fn op_push(&mut self, element: Felt) {
9        self.increment_stack_size();
10        self.stack_write(0, element);
11    }
12
13    /// Analogous to `Process::op_advpop`.
14    pub fn op_advpop(&mut self, op_idx: usize, host: &mut impl Host) -> Result<(), ExecutionError> {
15        let value = host
16            .advice_provider_mut()
17            .pop_stack(ProcessState::new_fast(self, op_idx), &ErrorContext::default())?;
18        self.increment_stack_size();
19        self.stack_write(0, value);
20        Ok(())
21    }
22
23    /// Analogous to `Process::op_advpopw`.
24    pub fn op_advpopw(
25        &mut self,
26        op_idx: usize,
27        host: &mut impl Host,
28    ) -> Result<(), ExecutionError> {
29        let word: Word = host
30            .advice_provider_mut()
31            .pop_stack_word(ProcessState::new_fast(self, op_idx), &ErrorContext::default())?;
32        self.stack_write_word(0, &word);
33
34        Ok(())
35    }
36
37    /// Analogous to `Process::op_mloadw`.
38    pub fn op_mloadw(&mut self, op_idx: usize) -> Result<(), ExecutionError> {
39        let addr = self.stack_get(0);
40        self.decrement_stack_size();
41
42        let word = *self.memory.read_word(self.ctx, addr, self.clk + op_idx)?;
43        self.stack_write_word(0, &word);
44
45        Ok(())
46    }
47
48    /// Analogous to `Process::op_mstorew`.
49    pub fn op_mstorew(&mut self, op_idx: usize) -> Result<(), ExecutionError> {
50        let addr = self.stack_get(0);
51        let word = self.stack_get_word(1);
52        self.decrement_stack_size();
53
54        self.memory.write_word(self.ctx, addr, self.clk + op_idx, word)?;
55        Ok(())
56    }
57
58    /// Analogous to `Process::op_mload`.
59    pub fn op_mload(&mut self) -> Result<(), ExecutionError> {
60        let element = {
61            let addr = self.stack_get(0);
62            self.memory.read_element(self.ctx, addr)?
63        };
64
65        self.stack_write(0, element);
66
67        Ok(())
68    }
69
70    /// Analogous to `Process::op_mstore`.
71    pub fn op_mstore(&mut self) -> Result<(), ExecutionError> {
72        let addr = self.stack_get(0);
73        let value = self.stack_get(1);
74        self.decrement_stack_size();
75
76        self.memory.write_element(self.ctx, addr, value)?;
77
78        Ok(())
79    }
80
81    /// Analogous to `Process::op_mstream`.
82    pub fn op_mstream(&mut self, op_idx: usize) -> Result<(), ExecutionError> {
83        // The stack index where the memory address to load the words from is stored.
84        const MEM_ADDR_STACK_IDX: usize = 12;
85
86        // load two words from memory
87        let addr_first_word = self.stack_get(MEM_ADDR_STACK_IDX);
88        let addr_second_word = addr_first_word + WORD_SIZE_FELT;
89        let words = [
90            *self.memory.read_word(self.ctx, addr_first_word, self.clk + op_idx)?,
91            *self.memory.read_word(self.ctx, addr_second_word, self.clk + op_idx)?,
92        ];
93
94        // Replace the stack elements with the elements from memory (in stack order). The word at
95        // address `addr + 4` is at the top of the stack.
96        self.stack_write_word(0, &words[1]);
97        self.stack_write_word(4, &words[0]);
98
99        // increment the address by 8 (2 words)
100        self.stack_write(MEM_ADDR_STACK_IDX, addr_first_word + DOUBLE_WORD_SIZE);
101
102        Ok(())
103    }
104
105    /// Analogous to `Process::op_pipe`.
106    pub fn op_pipe(&mut self, op_idx: usize, host: &mut impl Host) -> Result<(), ExecutionError> {
107        // The stack index where the memory address to load the words from is stored.
108        const MEM_ADDR_STACK_IDX: usize = 12;
109
110        let addr_first_word = self.stack_get(MEM_ADDR_STACK_IDX);
111        let addr_second_word = addr_first_word + WORD_SIZE_FELT;
112
113        // pop two words from the advice stack
114        let words = host
115            .advice_provider_mut()
116            .pop_stack_dword(ProcessState::new_fast(self, op_idx), &ErrorContext::default())?;
117
118        // write the words to memory
119        self.memory.write_word(self.ctx, addr_first_word, self.clk + op_idx, words[0])?;
120        self.memory
121            .write_word(self.ctx, addr_second_word, self.clk + op_idx, words[1])?;
122
123        // replace the elements on the stack with the word elements (in stack order)
124        self.stack_write_word(0, &words[1]);
125        self.stack_write_word(4, &words[0]);
126
127        // increment the address by 8 (2 words)
128        self.stack_write(MEM_ADDR_STACK_IDX, addr_first_word + DOUBLE_WORD_SIZE);
129
130        Ok(())
131    }
132}