Barretenberg
The ZK-SNARK library at the core of Aztec
Loading...
Searching...
No Matches
memory_manager.cpp
Go to the documentation of this file.
5
6using namespace bb::avm2::testing;
7
8namespace {
9
20template <std::ranges::input_range Range, typename Predicate>
21std::optional<std::ranges::range_value_t<Range>> get_nth_filtered(Range&& range, Predicate predicate, size_t index)
22{
23 auto filtered = range | std::views::filter(predicate);
24
25 auto count = std::ranges::distance(filtered);
26 if (count == 0) {
27 return std::nullopt;
28 }
29
30 return *std::ranges::next(filtered.begin(), static_cast<long>(index % static_cast<size_t>(count)));
31}
32
33uint32_t get_max_variable_address(AddressingMode mode, uint32_t base_offset, uint32_t max_operand_address)
34{
35 switch (mode) {
37 return max_operand_address;
39 return base_offset + max_operand_address;
43 }
44}
45
46uint32_t get_min_variable_address(AddressingMode mode, uint32_t base_offset)
47{
48 switch (mode) {
50 return base_offset;
54 return 0;
55 }
56}
57
58uint32_t trimmed_pointer_address(uint32_t pointer_address_seed, uint32_t max_operand_address)
59{
60 return pointer_address_seed % (max_operand_address + 1);
61}
62
63uint32_t trimmed_relative_pointer_address(uint32_t pointer_address_seed,
64 uint32_t base_offset,
65 uint32_t max_operand_address)
66{
67 return base_offset + (pointer_address_seed % (max_operand_address + 1));
68}
69
70} // namespace
71
73{
74 if (this != &other) {
77 }
78 return *this;
79}
80
85
87{
88 // if address is already set
90 auto stored_tag = memory_address_to_tag[address];
91 // if address is already set to the same tag, do nothing
92 if (stored_tag == tag) {
93 return;
94 }
95 // if address is already set to different tag, remove address from stored_variables
96 stored_variables[stored_tag].erase(
97 std::remove(stored_variables[stored_tag].begin(), stored_variables[stored_tag].end(), address),
98 stored_variables[stored_tag].end());
99 }
101 stored_variables[tag].push_back(address);
102}
103
105 uint32_t absolute_address,
106 uint32_t max_operand_address)
107{
108 ResolvedAddress resolved_address = {
109 .absolute_address = absolute_address,
110 };
111 switch (variable.mode) {
113 uint32_t trimmed_pointer_address_value =
114 trimmed_pointer_address(variable.pointer_address_seed, max_operand_address);
115 resolved_address.pointer_address = trimmed_pointer_address_value;
116 resolved_address.operand_address = trimmed_pointer_address_value;
117 break;
118 }
120 resolved_address.operand_address = absolute_address - base_offset;
121 resolved_address.via_relative = true;
122 break;
124 uint32_t trimmed_pointer_address_value =
125 trimmed_relative_pointer_address(variable.pointer_address_seed, base_offset, max_operand_address);
126 resolved_address.pointer_address = trimmed_pointer_address_value;
127 // Relative addressing target is the pointer
128 resolved_address.operand_address = trimmed_pointer_address_value - base_offset;
129 resolved_address.via_relative = true;
130 break;
131 }
133 // We can't change the absolute address, or it won't find anything useful there.
134 resolved_address.operand_address = absolute_address;
135 break;
136 }
137 BB_ASSERT_LTE(resolved_address.operand_address, max_operand_address);
138 return resolved_address;
139}
140
142{
143
144 ResolvedAddress resolved_address = {
145 .absolute_address = address.address,
146 };
147 switch (address.mode) {
149 // Trim the pointer to max_operand_address bits for it to be reachable by the instruction
150 uint32_t trimmed_pointer_address_value =
151 trimmed_pointer_address(address.pointer_address_seed, max_operand_address);
152 resolved_address.pointer_address = trimmed_pointer_address_value;
153 resolved_address.operand_address = trimmed_pointer_address_value;
154 break;
155 }
157 resolved_address.operand_address = address.address - base_offset;
158 resolved_address.via_relative = true;
159 break;
161 // Relative addressing target is the pointer
162 uint32_t trimmed_pointer_address_value =
163 trimmed_relative_pointer_address(address.pointer_address_seed, base_offset, max_operand_address);
164 resolved_address.pointer_address = trimmed_pointer_address_value;
165
166 resolved_address.operand_address = trimmed_pointer_address_value - base_offset;
167 resolved_address.via_relative = true;
168 break;
169 }
171 resolved_address.operand_address = resolved_address.absolute_address;
172 break;
173 }
174 BB_ASSERT_LTE(resolved_address.operand_address, max_operand_address);
175 return resolved_address;
176}
177
179{
180 switch (mode) {
182 operand = operand.indirect();
183 break;
185 operand = operand.relative();
186 break;
188 operand = operand.indirect();
189 operand = operand.relative();
190 break;
192 break;
193 }
194 return operand;
195}
196
204
207{
208 auto actual_address = get_variable_address(address.tag,
209 address.index,
210 get_min_variable_address(address.mode, base_offset),
211 get_max_variable_address(address.mode, base_offset, 255));
212 if (!actual_address.has_value()) {
213 return std::nullopt;
214 }
215 auto resolved_address = resolve_address(address, actual_address.value(), 255);
216
217 auto operand = OperandBuilder::from<uint8_t>(static_cast<uint8_t>(resolved_address.operand_address));
218
219 return std::make_pair(resolved_address, get_memory_address_operand(operand, address.mode));
220}
221
224{
225 auto resolved_address = resolve_address(address, 255);
226
227 auto operand = OperandBuilder::from<uint8_t>(static_cast<uint8_t>(resolved_address.operand_address));
228 return std::make_pair(resolved_address, get_memory_address_operand(operand, address.mode));
229}
230
238
241{
242 auto actual_address = get_variable_address(address.tag,
243 address.index,
244 get_min_variable_address(address.mode, base_offset),
245 get_max_variable_address(address.mode, base_offset, 65535));
246 if (!actual_address.has_value()) {
247 return std::nullopt;
248 }
249
250 auto resolved_address = resolve_address(address, actual_address.value(), 65535);
251
252 auto operand = OperandBuilder::from<uint16_t>(static_cast<uint16_t>(resolved_address.operand_address));
253 return std::make_pair(resolved_address, get_memory_address_operand(operand, address.mode));
254}
255
258{
259 auto resolved_address = resolve_address(address, 65535);
260
261 auto operand = OperandBuilder::from<uint16_t>(static_cast<uint16_t>(resolved_address.operand_address));
262 return std::make_pair(resolved_address, get_memory_address_operand(operand, address.mode));
263}
264
266 uint32_t index,
267 uint32_t min_value,
268 uint32_t max_value)
269{
270 return get_nth_filtered(
271 this->stored_variables[tag],
272 [min_value, max_value](uint32_t val) { return val >= min_value && val <= max_value; },
273 index);
274}
275
277{
278 auto value = get_variable_address(tag, index, 0, 255);
279 if (!value.has_value()) {
280 return std::nullopt;
281 }
282 return static_cast<uint8_t>(value.value());
283}
284
286{
287 auto value = get_variable_address(tag, index, 0, 65535);
288 if (!value.has_value()) {
289 return std::nullopt;
290 }
291 return static_cast<uint16_t>(value.value());
292}
293
298
300{
301 if (storage_addresses.empty()) {
302 return std::nullopt;
303 }
304 return storage_addresses[slot_offset_index % storage_addresses.size()];
305}
306
307void MemoryManager::set_base_offset(uint32_t base_offset)
308{
309 this->base_offset = base_offset;
310}
#define BB_ASSERT_LTE(left, right,...)
Definition assert.hpp:158
#define AVM_HIGHEST_MEM_ADDRESS
bb::avm2::testing::OperandBuilder get_memory_address_operand(bb::avm2::testing::OperandBuilder operand, AddressingMode mode)
std::optional< uint16_t > get_memory_offset_16(bb::avm2::MemoryTag tag, uint32_t address_index)
std::map< bb::avm2::MemoryTag, std::vector< uint32_t > > stored_variables
MemoryManager & operator=(const MemoryManager &other)
std::optional< std::pair< ResolvedAddress, bb::avm2::testing::OperandBuilder > > get_resolved_address_and_operand_8(ParamRef address)
std::map< uint32_t, bb::avm2::MemoryTag > memory_address_to_tag
ResolvedAddress resolve_address(VariableRef address, uint32_t absolute_address, uint32_t max_operand_address)
std::optional< bb::avm2::FF > get_slot(uint16_t slot_offset_index)
bool is_memory_address_set(uint16_t address)
void set_memory_address(bb::avm2::MemoryTag tag, uint32_t address)
void append_slot(bb::avm2::FF slot)
void set_base_offset(uint32_t base_offset)
std::optional< uint8_t > get_memory_offset_8(bb::avm2::MemoryTag tag, uint32_t address_index)
std::optional< uint32_t > get_variable_address(bb::avm2::MemoryTag tag, uint32_t index, uint32_t min_value, uint32_t max_value)
std::vector< bb::avm2::FF > storage_addresses
std::optional< std::pair< ResolvedAddress, bb::avm2::testing::OperandBuilder > > get_resolved_address_and_operand_16(ParamRef address)
AddressingMode
std::variant< VariableRef, AddressRef > ParamRef
AvmFlavorSettings::FF FF
Definition field.hpp:10
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept
Definition tuple.hpp:13
Output of resolving an address in the memory manager In order to resolve a given absolute address wit...
uint32_t operand_address
uint32_t absolute_address
std::optional< uint32_t > pointer_address
AddressingModeWrapper mode
uint16_t pointer_address_seed
A seed for the generation of the pointer address Used for Indirect/IndirectRelative modes only.