Skip to content

Commit b630fd6

Browse files
authored
feat(avm): Sorting of memory entries (#16336)
2 parents 28539c2 + 4d2f659 commit b630fd6

File tree

5 files changed

+119
-8
lines changed

5 files changed

+119
-8
lines changed
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
#include "barretenberg/vm2/simulation/events/memory_event.hpp"
2+
3+
namespace bb::avm2::simulation {
4+
5+
static_assert(MemoryMode::READ < MemoryMode::WRITE, "MemoryMode::READ must be less than MemoryMode::WRITE");
6+
7+
// Sorting order precedence is: space_id, addr, execution_clk, mode.
8+
bool MemoryEvent::operator<(MemoryEvent const& other) const
9+
{
10+
return std::make_tuple(space_id, addr, execution_clk, mode) <
11+
std::make_tuple(other.space_id, other.addr, other.execution_clk, other.mode);
12+
}
13+
14+
} // namespace bb::avm2::simulation

barretenberg/cpp/src/barretenberg/vm2/simulation/events/memory_event.hpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,12 @@ struct MemoryEvent {
1717
MemoryAddress addr;
1818
MemoryValue value;
1919
uint32_t space_id;
20+
21+
/**
22+
* @brief A comparator to be used by sorting algorithm (std::sort()). We sort first by
23+
* ascending space_id, followed by address, then by clk and finally read/write.
24+
*/
25+
bool operator<(MemoryEvent const& other) const;
2026
};
2127

2228
} // namespace bb::avm2::simulation

barretenberg/cpp/src/barretenberg/vm2/tracegen/keccakf1600_trace.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -797,6 +797,6 @@ const InteractionDefinition KeccakF1600TraceBuilder::interactions =
797797
.add<lookup_keccakf1600_src_abs_diff_positive_settings, InteractionType::LookupGeneric>()
798798
.add<lookup_keccakf1600_dst_abs_diff_positive_settings, InteractionType::LookupGeneric>()
799799
// Keccak slice memory to memory sub-trace
800-
.add<lookup_keccak_memory_slice_to_mem_settings, InteractionType::LookupSequential>();
800+
.add<lookup_keccak_memory_slice_to_mem_settings, InteractionType::LookupGeneric>();
801801

802802
} // namespace bb::avm2::tracegen

barretenberg/cpp/src/barretenberg/vm2/tracegen/memory_trace.cpp

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#include "barretenberg/vm2/tracegen/memory_trace.hpp"
22

33
#include <memory>
4+
#include <vector>
45

56
#include "barretenberg/vm2/common/field.hpp"
67
#include "barretenberg/vm2/tracegen/lib/interaction_def.hpp"
@@ -10,19 +11,29 @@ namespace bb::avm2::tracegen {
1011
void MemoryTraceBuilder::process(const simulation::EventEmitterInterface<simulation::MemoryEvent>::Container& events,
1112
TraceContainer& trace)
1213
{
14+
// Create a vector of pointers to avoid copying the events
15+
std::vector<const simulation::MemoryEvent*> event_ptrs;
16+
event_ptrs.reserve(events.size());
17+
18+
for (const auto& event : events) {
19+
event_ptrs.push_back(&event);
20+
}
21+
22+
std::ranges::sort(event_ptrs, [](const auto* lhs, const auto* rhs) { return lhs->operator<(*rhs); });
23+
1324
using C = Column;
1425

1526
uint32_t row = 0;
16-
for (const auto& event : events) {
27+
for (const auto* event_ptr : event_ptrs) {
1728
trace.set(row,
1829
{ {
1930
{ C::memory_sel, 1 },
20-
{ C::memory_clk, event.execution_clk },
21-
{ C::memory_address, event.addr },
22-
{ C::memory_value, event.value },
23-
{ C::memory_tag, static_cast<uint8_t>(event.value.get_tag()) },
24-
{ C::memory_rw, event.mode == simulation::MemoryMode::WRITE ? 1 : 0 },
25-
{ C::memory_space_id, event.space_id },
31+
{ C::memory_clk, event_ptr->execution_clk },
32+
{ C::memory_address, event_ptr->addr },
33+
{ C::memory_value, event_ptr->value },
34+
{ C::memory_tag, static_cast<uint8_t>(event_ptr->value.get_tag()) },
35+
{ C::memory_rw, event_ptr->mode == simulation::MemoryMode::WRITE ? 1 : 0 },
36+
{ C::memory_space_id, event_ptr->space_id },
2637
} });
2738
row++;
2839
}
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
#include <gmock/gmock.h>
2+
#include <gtest/gtest.h>
3+
4+
#include "barretenberg/vm2/simulation/events/memory_event.hpp"
5+
#include "barretenberg/vm2/testing/macros.hpp"
6+
#include "barretenberg/vm2/tracegen/memory_trace.hpp"
7+
#include "barretenberg/vm2/tracegen/test_trace_container.hpp"
8+
9+
namespace bb::avm2::tracegen {
10+
namespace {
11+
12+
using R = TestTraceContainer::Row;
13+
using C = Column;
14+
using simulation::MemoryEvent;
15+
16+
TEST(MemoryTraceGenTest, Sorting)
17+
{
18+
TestTraceContainer trace;
19+
20+
// We use .value field to check that the events are sorted correctly. The values
21+
// are set to be in increasing order once the events are sorted.
22+
std::vector<MemoryEvent> events = {
23+
{
24+
.execution_clk = UINT32_MAX,
25+
.mode = simulation::MemoryMode::WRITE,
26+
.addr = 20,
27+
.value = MemoryValue::from_tag(MemoryTag::U8, 5),
28+
.space_id = 1001,
29+
},
30+
{
31+
.execution_clk = 20,
32+
.mode = simulation::MemoryMode::WRITE,
33+
.addr = 5,
34+
.value = MemoryValue::from_tag(MemoryTag::U8, 2),
35+
.space_id = 1000,
36+
},
37+
{
38+
.execution_clk = UINT32_MAX,
39+
.mode = simulation::MemoryMode::READ,
40+
.addr = 20,
41+
.value = MemoryValue::from_tag(MemoryTag::U8, 4),
42+
.space_id = 1001,
43+
},
44+
{
45+
.execution_clk = 10,
46+
.mode = simulation::MemoryMode::WRITE,
47+
.addr = 6,
48+
.value = MemoryValue::from_tag(MemoryTag::U8, 3),
49+
.space_id = 1000,
50+
},
51+
{
52+
.execution_clk = 20,
53+
.mode = simulation::MemoryMode::READ,
54+
.addr = 5,
55+
.value = MemoryValue::from_tag(MemoryTag::U8, 1),
56+
.space_id = 1000,
57+
},
58+
{
59+
.execution_clk = 15,
60+
.mode = simulation::MemoryMode::WRITE,
61+
.addr = 5,
62+
.value = MemoryValue::from_tag(MemoryTag::U8, 0),
63+
.space_id = 1000,
64+
},
65+
};
66+
67+
MemoryTraceBuilder memory_trace_builder;
68+
memory_trace_builder.process(events, trace);
69+
70+
const auto& rows = trace.as_rows();
71+
72+
ASSERT_EQ(rows.size(), 6);
73+
74+
for (uint32_t i = 0; i < trace.as_rows().size(); i++) {
75+
EXPECT_THAT(rows.at(i), ROW_FIELD_EQ(memory_value, i));
76+
}
77+
}
78+
79+
} // namespace
80+
} // namespace bb::avm2::tracegen

0 commit comments

Comments
 (0)