Barretenberg
The ZK-SNARK library at the core of Aztec
Loading...
Searching...
No Matches
instruction_spec.test.cpp
Go to the documentation of this file.
1#include <gmock/gmock.h>
2#include <gtest/gtest.h>
3
7
8namespace bb::avm2 {
9namespace {
10
11size_t compute_instruction_size(WireOpCode wire_opcode,
12 const std::unordered_map<WireOpCode, std::vector<simulation::OperandType>>& wire_format,
14{
15 size_t instr_size = 1; // Take into account the opcode byte
16 for (const auto& operand_type : wire_format.at(wire_opcode)) {
17 instr_size += operand_type_sizes.at(operand_type);
18 }
19
20 return instr_size;
21}
22
23// Test checking that the hardcoded size for each instruction specified in WIRE_INSTRUCTION_SPEC
24// is correct. This test would fail only when we change the wire format of an instruction.
25TEST(InstructionSpecTest, CheckAllInstructionSizes)
26{
28 const auto& operand_type_sizes = simulation::testonly::get_operand_type_sizes();
29
30 for (int i = 0; i < static_cast<int>(WireOpCode::LAST_OPCODE_SENTINEL); i++) {
31 const auto wire_opcode = static_cast<WireOpCode>(i);
32 const auto computed_size = compute_instruction_size(wire_opcode, wire_format, operand_type_sizes);
33 EXPECT_EQ(WIRE_INSTRUCTION_SPEC.at(wire_opcode).size_in_bytes, computed_size)
34 << "Incorrect size_in_bytes field for " << wire_opcode << " in WIRE_INSTRUCTION_SPEC.";
35 }
36}
37
38// Test checking that the hardcoded tag related fields in WIRE_INSTRUCTION_SPEC
39// are correct. This test would fail only when we change the wire format of an instruction.
40TEST(InstructionSpecTest, CheckAllInstructionsTagInformation)
41{
43
44 for (int i = 0; i < static_cast<int>(WireOpCode::LAST_OPCODE_SENTINEL); i++) {
45 const auto wire_opcode = static_cast<WireOpCode>(i);
46 const auto& operands = wire_format.at(wire_opcode);
47 const auto tag_counts = std::count(operands.begin(), operands.end(), simulation::OperandType::TAG);
48 const auto& wire_instruction_spec = WIRE_INSTRUCTION_SPEC.at(wire_opcode);
49
50 if (wire_instruction_spec.tag_operand_idx.has_value()) {
51 EXPECT_EQ(tag_counts, 1);
52 if (wire_instruction_spec.tag_operand_idx.value() == 2) {
53 EXPECT_EQ(operands.at(2), simulation::OperandType::TAG);
54 } else {
55 EXPECT_EQ(operands.at(3), simulation::OperandType::TAG);
56 }
57 } else {
58 EXPECT_EQ(tag_counts, 0);
59 }
60 }
61}
62
63// Test checking that every wire opcode (except for LAST_OPCODE_SENTINEL) has an entry in WIRE_INSTRUCTION_SPEC
64// and contains a valid exec opcode that this one has an entry in EXEC_INSTRUCTION_SPEC.
65// Check also that the set of these exec opcodes contain all the values defined in the ExecutionOpCode enum.
66TEST(InstructionSpecTest, CheckWireOpCodeAndExecOpcodeConsistency)
67{
68 std::set<ExecutionOpCode> exec_opcodes;
69 for (int i = 0; i < static_cast<int>(WireOpCode::LAST_OPCODE_SENTINEL); i++) {
70 const auto wire_opcode = static_cast<WireOpCode>(i);
71 const auto& wire_instruction_spec = WIRE_INSTRUCTION_SPEC.at(wire_opcode);
72 EXPECT_TRUE(EXEC_INSTRUCTION_SPEC.contains(wire_instruction_spec.exec_opcode));
73
74 exec_opcodes.insert(wire_instruction_spec.exec_opcode);
75 }
76
77 for (int i = 0; i <= static_cast<int>(ExecutionOpCode::MAX); i++) {
78 const auto exec_opcode = static_cast<ExecutionOpCode>(i);
79 EXPECT_TRUE(exec_opcodes.contains(exec_opcode));
80 }
81}
82
83// Compute the maximum size of instruction in bytes and enforces it to be equal to DECOMPOSE_WINDOW_SIZE.
84TEST(InstructionSpecTest, CheckDecomposeWindowSize)
85{
86 // We cannot use a static assert in the code as MAX_INSTRUCTION_SIZE is not a constexpr.
87 static const uint32_t MAX_INSTRUCTION_SIZE =
88 std::ranges::max_element(
91 [](const auto& a, const auto& b) { return a.second.size_in_bytes < b.second.size_in_bytes; })
92 ->second.size_in_bytes;
93
94 EXPECT_EQ(DECOMPOSE_WINDOW_SIZE, MAX_INSTRUCTION_SIZE);
95}
96
97} // namespace
98} // namespace bb::avm2
FF a
FF b
const std::unordered_map< OperandType, uint32_t > & get_operand_type_sizes()
const std::unordered_map< WireOpCode, std::vector< OperandType > > & get_instruction_wire_formats()
TEST(EmitUnencryptedLogTest, Basic)
constexpr uint32_t DECOMPOSE_WINDOW_SIZE
const std::unordered_map< WireOpCode, WireInstructionSpec > WIRE_INSTRUCTION_SPEC
const std::unordered_map< ExecutionOpCode, ExecInstructionSpec > EXEC_INSTRUCTION_SPEC
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept
Definition tuple.hpp:13