miden_processor/fast/
io_ops.rs

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