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