From aa43768665e1a1c33643c43cfa8a74c9b4e45166 Mon Sep 17 00:00:00 2001 From: fcarreiro Date: Fri, 24 Jan 2025 11:04:49 +0000 Subject: [PATCH] feat(avm): interactive debugger --- .../barretenberg/vm/avm/generated/columns.hpp | 5 +- .../vm/avm/generated/full_row.hpp | 4 +- .../barretenberg/vm/avm/trace/execution.cpp | 4 +- .../cpp/src/barretenberg/vm2/debugger.cpp | 225 ++++++++++++++++++ .../cpp/src/barretenberg/vm2/debugger.hpp | 39 +++ .../barretenberg/vm2/generated/columns.hpp | 5 +- .../barretenberg/vm2/generated/full_row.hpp | 4 +- .../src/barretenberg/vm2/proving_helper.cpp | 15 +- .../vm2/tracegen/lib/trace_conversion.cpp | 39 +++ .../vm2/tracegen/lib/trace_conversion.hpp | 16 ++ .../vm2/tracegen/test_trace_container.cpp | 46 ++-- .../vm2/tracegen/test_trace_container.hpp | 2 + .../vm2/tracegen/trace_container.cpp | 3 +- .../vm2/tracegen/trace_container.hpp | 5 +- .../src/barretenberg/vm2/tracegen_helper.cpp | 2 +- .../bb-pil-backend/templates/columns.hpp.hbs | 5 +- .../bb-pil-backend/templates/full_row.hpp.hbs | 4 +- 17 files changed, 370 insertions(+), 53 deletions(-) create mode 100644 barretenberg/cpp/src/barretenberg/vm2/debugger.cpp create mode 100644 barretenberg/cpp/src/barretenberg/vm2/debugger.hpp create mode 100644 barretenberg/cpp/src/barretenberg/vm2/tracegen/lib/trace_conversion.cpp create mode 100644 barretenberg/cpp/src/barretenberg/vm2/tracegen/lib/trace_conversion.hpp diff --git a/barretenberg/cpp/src/barretenberg/vm/avm/generated/columns.hpp b/barretenberg/cpp/src/barretenberg/vm/avm/generated/columns.hpp index 31353b7e734..56fc84a925f 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm/generated/columns.hpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm/generated/columns.hpp @@ -27,10 +27,11 @@ enum class Column { AVM_UNSHIFTED_ENTITIES }; // C++ doesn't allow enum extension, so we'll have to cast. enum class ColumnAndShifts { AVM_ALL_ENTITIES, - // Sentinel. - NUM_COLUMNS, + SENTINEL_DO_NOT_USE, }; +constexpr auto NUM_COLUMNS_WITH_SHIFTS = 813; +constexpr auto NUM_COLUMNS_WITHOUT_SHIFTS = 764; constexpr auto TO_BE_SHIFTED_COLUMNS_ARRAY = []() { return std::array{ AVM_TO_BE_SHIFTED_COLUMNS }; }(); constexpr auto SHIFTED_COLUMNS_ARRAY = []() { return std::array{ AVM_SHIFTED_COLUMNS }; }(); static_assert(TO_BE_SHIFTED_COLUMNS_ARRAY.size() == SHIFTED_COLUMNS_ARRAY.size()); diff --git a/barretenberg/cpp/src/barretenberg/vm/avm/generated/full_row.hpp b/barretenberg/cpp/src/barretenberg/vm/avm/generated/full_row.hpp index 61400c6fa84..4f77ffad75c 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm/generated/full_row.hpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm/generated/full_row.hpp @@ -20,13 +20,13 @@ template struct AvmFullRow { // Risky but oh so efficient. FF& get_column(ColumnAndShifts col) { - static_assert(sizeof(*this) == sizeof(FF) * static_cast(ColumnAndShifts::NUM_COLUMNS)); + static_assert(sizeof(*this) == sizeof(FF) * static_cast(ColumnAndShifts::SENTINEL_DO_NOT_USE)); return reinterpret_cast(this)[static_cast(col)]; } const FF& get_column(ColumnAndShifts col) const { - static_assert(sizeof(*this) == sizeof(FF) * static_cast(ColumnAndShifts::NUM_COLUMNS)); + static_assert(sizeof(*this) == sizeof(FF) * static_cast(ColumnAndShifts::SENTINEL_DO_NOT_USE)); return reinterpret_cast(this)[static_cast(col)]; } }; diff --git a/barretenberg/cpp/src/barretenberg/vm/avm/trace/execution.cpp b/barretenberg/cpp/src/barretenberg/vm/avm/trace/execution.cpp index 41f09569136..97c3560e8fe 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm/trace/execution.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm/trace/execution.cpp @@ -151,8 +151,8 @@ void show_trace_info(const auto& trace) size_t total_entries = 0; size_t fullness = 0; // 0 to 100. }; - std::vector column_stats(static_cast(avm::ColumnAndShifts::NUM_COLUMNS)); - bb::parallel_for(static_cast(avm::ColumnAndShifts::NUM_COLUMNS), [&](size_t col) { + std::vector column_stats(avm::NUM_COLUMNS_WITH_SHIFTS); + bb::parallel_for(avm::NUM_COLUMNS_WITH_SHIFTS, [&](size_t col) { size_t non_zero_entries = 0; ssize_t last_non_zero_row = -1; for (uint32_t row_n = 0; row_n < trace.size(); row_n++) { diff --git a/barretenberg/cpp/src/barretenberg/vm2/debugger.cpp b/barretenberg/cpp/src/barretenberg/vm2/debugger.cpp new file mode 100644 index 00000000000..c87ad35ec64 --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/vm2/debugger.cpp @@ -0,0 +1,225 @@ +#include "barretenberg/vm2/debugger.hpp" + +#include +#include +#include +#include +#include + +#include "barretenberg/numeric/uint256/uint256.hpp" +#include "barretenberg/vm2/common/field.hpp" +#include "barretenberg/vm2/generated/columns.hpp" +#include "barretenberg/vm2/generated/flavor.hpp" +#include "barretenberg/vm2/generated/full_row.hpp" +#include "barretenberg/vm2/tracegen/lib/trace_conversion.hpp" + +namespace bb::avm2 { +namespace { + +template std::string field_to_string(const FF& ff) +{ + std::ostringstream os; + os << ff; + std::string raw = os.str(); + auto first_not_zero = raw.find_first_not_of('0', 2); + std::string result = "0x" + (first_not_zero != std::string::npos ? raw.substr(first_not_zero) : "0"); + return result; +} + +std::vector get_command() +{ + std::string line; + std::getline(std::cin, line); + // Split the line into words. + return bb::detail::split_and_trim(line, ' '); +} + +std::string str_replace(const std::string& s, const std::string& search, const std::string& replace) +{ + size_t pos = 0; + std::string res = s; + while ((pos = res.find(search, pos)) != std::string::npos) { + res.replace(pos, search.length(), replace); + pos += replace.length(); + } + return res; +} + +std::string to_binary(uint64_t n, bool leading_zeroes = true) +{ + std::string result; + for (int i = 0; i < 64; ++i) { + result = ((n & 1) ? "1" : "0") + result; + n >>= 1; + } + if (!leading_zeroes) { + size_t first_one = result.find('1'); + if (first_one != std::string::npos) { + result = result.substr(first_one); + } else { + result = "0"; + } + } + return result; +} + +void help() +{ + std::cout << "Commands:" << std::endl; + std::cout << " ' - increment row" << std::endl; + std::cout << " , - decrement row" << std::endl; + std::cout << " @ - jump to row" << std::endl; + std::cout << " . [...column_regex] - print column values" << std::endl; + std::cout << " /set - set column" << std::endl; + std::cout << " /prefix - set column prefix" << std::endl; + std::cout << " /noprefix - clear column prefix" << std::endl; + std::cout << " /testrelation [subrelation_name_or_number] - test relation" << std::endl; + std::cout << " exit, e, q - exit" << std::endl; +} + +} // namespace + +void InteractiveDebugger::run(uint32_t starting_row) +{ + row = starting_row; + std::cout << "Entering interactive debugging mode at row " << row << "..." << std::endl; + while (true) { + // Print prompt with current row. + std::cout << this->row << "> "; + auto command = get_command(); + if (command.empty()) { + continue; + } + if (command[0] == "'") { + row++; + } else if (command[0] == ",") { + if (row > 0) { + row--; + } else { + std::cout << "Cannot decrement row below 0." << std::endl; + } + } else if (command[0].starts_with("@")) { + row = static_cast(std::stoi(command[0].substr(1))); + } else if (command[0] == "exit" || command[0] == "e" || command[0] == "q") { + break; + } else if (command[0] == "/set" || command[0] == "/s") { + if (command.size() != 3) { + std::cout << "Usage: /set " << std::endl; + } else { + set_column(command[1], command[2]); + } + } else if (command[0] == "/prefix" || command[0] == "/p") { + if (command.size() != 2) { + std::cout << "Usage: /prefix " << std::endl; + } else { + prefix = command[1]; + } + } else if (command[0] == "/noprefix" || command[0] == "/np") { + prefix = ""; + } else if (command[0] == "/testrelation" || command[0] == "/tr") { + if (command.size() != 2 && command.size() != 3) { + std::cout << "Usage: /testrelation [subrelation_name_or_number]" << std::endl; + } else { + test_relation(command[1], command.size() == 3 ? std::make_optional(command[2]) : std::nullopt); + } + } else if (command[0].starts_with(".")) { + // Remove dot from first column name. + command[0].erase(0, 1); + // Print columns. + print_columns(command); + } else { + help(); + } + } +} + +void InteractiveDebugger::print_columns(const std::vector& regexes) +{ + bool found = false; + std::string joined_regex; + for (const auto& str : regexes) { + joined_regex += prefix + str_replace(str, "'", "_shift") + "|"; + } + joined_regex.pop_back(); // Remove trailing '|'. + std::regex re; + try { + re.assign(joined_regex); + } catch (std::regex_error& e) { + std::cout << "Invalid regex: " << e.what() << std::endl; + return; + } + // We use the full row to have the shifts as well. + const auto full_row = tracegen::get_full_row(trace, row); + for (size_t i = 0; i < COLUMN_NAMES.size(); ++i) { + if (std::regex_match(COLUMN_NAMES[i], re)) { + auto val = full_row.get_column(static_cast(i)); + std::cout << COLUMN_NAMES[i] << ": " << field_to_string(val); + // If the value is small enough, print it as decimal and binary. + if (val == FF(static_cast(val))) { + uint64_t n = static_cast(val); + std::cout << " (" << n << ", " << to_binary(n, /*leading_zeroes=*/false) << "b)"; + } + std::cout << std::endl; + found = true; + } + } + if (!found) { + std::cout << "No columns matched: " << joined_regex << std::endl; + } +} + +void InteractiveDebugger::set_column(const std::string& column_name, const std::string& value) +{ + std::string final_name = prefix + column_name; + for (size_t i = 0; i < COLUMN_NAMES.size(); ++i) { + // We match both names, for copy-pasting ease. + if (COLUMN_NAMES[i] == final_name || COLUMN_NAMES[i] == column_name) { + trace.set(static_cast(i), row, std::stoi(value)); + std::cout << "Column " << COLUMN_NAMES[i] << " set to value " << value << std::endl; + return; + } + } + std::cout << "Column " << column_name << " not found." << std::endl; +} + +void InteractiveDebugger::test_relation(const std::string& relation_name, std::optional subrelation_name) +{ + bool found = false; + bool failed = false; + + bb::constexpr_for<0, std::tuple_size_v, 1>([&]() { + using Relation = std::tuple_element_t; + + if (Relation::NAME != relation_name) { + return; + } + found = true; + + typename Relation::SumcheckArrayOfValuesOverSubrelations result{}; + Relation::accumulate(result, tracegen::get_full_row(trace, row), {}, 1); + for (size_t j = 0; j < result.size(); ++j) { + if (!result[j].is_zero() && + (!subrelation_name || Relation::get_subrelation_label(j) == *subrelation_name)) { + std::cout << format("Relation ", + Relation::NAME, + ", subrelation ", + Relation::get_subrelation_label(j), + " failed at row ", + row) + << std::endl; + failed = true; + return; + } + } + }); + + if (!found) { + std::cout << "Relation " << relation_name << " not found." << std::endl; + } else if (!failed) { + std::cout << "Relation " << relation_name << " (" + << (subrelation_name.has_value() ? *subrelation_name : "all subrelations") << ")" + << " passed!" << std::endl; + } +} + +} // namespace bb::avm2 \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/vm2/debugger.hpp b/barretenberg/cpp/src/barretenberg/vm2/debugger.hpp new file mode 100644 index 00000000000..81f99f08c40 --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/vm2/debugger.hpp @@ -0,0 +1,39 @@ +#pragma once + +#include +#include + +#include "barretenberg/vm2/tracegen/trace_container.hpp" + +namespace bb::avm2 { + +/** + * An interactive debugger for the AVM2. + * + * (1) To use it in tests add the following after you construct the trace: + * + * auto container = TestTraceContainer::from_rows(trace); + * InteractiveDebugger debugger(container); + * debugger.run(); + * + * (2) To use it to debug `avm2_check_circuit` failures just set the `AVM_DEBUG` environment variable. + */ +class InteractiveDebugger { + public: + InteractiveDebugger(tracegen::TraceContainer& trace) + : trace(trace) + {} + + void run(uint32_t starting_row = 0); + + private: + tracegen::TraceContainer& trace; + uint32_t row = 0; + std::string prefix; + + void print_columns(const std::vector& regex); + void set_column(const std::string& column_name, const std::string& value); + void test_relation(const std::string& relation_name, std::optional subrelation_name); +}; + +} // namespace bb::avm2 \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/vm2/generated/columns.hpp b/barretenberg/cpp/src/barretenberg/vm2/generated/columns.hpp index 12582638eeb..a3ad0f02b94 100644 --- a/barretenberg/cpp/src/barretenberg/vm2/generated/columns.hpp +++ b/barretenberg/cpp/src/barretenberg/vm2/generated/columns.hpp @@ -27,10 +27,11 @@ enum class Column { AVM2_UNSHIFTED_ENTITIES }; // C++ doesn't allow enum extension, so we'll have to cast. enum class ColumnAndShifts { AVM2_ALL_ENTITIES, - // Sentinel. - NUM_COLUMNS, + SENTINEL_DO_NOT_USE, }; +constexpr auto NUM_COLUMNS_WITH_SHIFTS = 50; +constexpr auto NUM_COLUMNS_WITHOUT_SHIFTS = 49; constexpr auto TO_BE_SHIFTED_COLUMNS_ARRAY = []() { return std::array{ AVM2_TO_BE_SHIFTED_COLUMNS }; }(); constexpr auto SHIFTED_COLUMNS_ARRAY = []() { return std::array{ AVM2_SHIFTED_COLUMNS }; }(); static_assert(TO_BE_SHIFTED_COLUMNS_ARRAY.size() == SHIFTED_COLUMNS_ARRAY.size()); diff --git a/barretenberg/cpp/src/barretenberg/vm2/generated/full_row.hpp b/barretenberg/cpp/src/barretenberg/vm2/generated/full_row.hpp index 4d56c9fefa7..d6ffc66568a 100644 --- a/barretenberg/cpp/src/barretenberg/vm2/generated/full_row.hpp +++ b/barretenberg/cpp/src/barretenberg/vm2/generated/full_row.hpp @@ -20,13 +20,13 @@ template struct AvmFullRow { // Risky but oh so efficient. FF& get_column(ColumnAndShifts col) { - static_assert(sizeof(*this) == sizeof(FF) * static_cast(ColumnAndShifts::NUM_COLUMNS)); + static_assert(sizeof(*this) == sizeof(FF) * static_cast(ColumnAndShifts::SENTINEL_DO_NOT_USE)); return reinterpret_cast(this)[static_cast(col)]; } const FF& get_column(ColumnAndShifts col) const { - static_assert(sizeof(*this) == sizeof(FF) * static_cast(ColumnAndShifts::NUM_COLUMNS)); + static_assert(sizeof(*this) == sizeof(FF) * static_cast(ColumnAndShifts::SENTINEL_DO_NOT_USE)); return reinterpret_cast(this)[static_cast(col)]; } }; diff --git a/barretenberg/cpp/src/barretenberg/vm2/proving_helper.cpp b/barretenberg/cpp/src/barretenberg/vm2/proving_helper.cpp index 16ecc1ffcfb..cddbb65eecd 100644 --- a/barretenberg/cpp/src/barretenberg/vm2/proving_helper.cpp +++ b/barretenberg/cpp/src/barretenberg/vm2/proving_helper.cpp @@ -1,6 +1,8 @@ #include "barretenberg/vm2/proving_helper.hpp" +#include #include +#include #include "barretenberg/common/serialize.hpp" #include "barretenberg/common/thread.hpp" @@ -8,6 +10,7 @@ #include "barretenberg/vm/stats.hpp" #include "barretenberg/vm2/common/constants.hpp" #include "barretenberg/vm2/constraining/check_circuit.hpp" +#include "barretenberg/vm2/debugger.hpp" #include "barretenberg/vm2/generated/prover.hpp" #include "barretenberg/vm2/generated/verifier.hpp" @@ -137,12 +140,20 @@ bool AvmProvingHelper::check_circuit(tracegen::TraceContainer&& trace) const size_t num_rows = trace.get_num_rows_without_clk() + 1; info("Running check circuit over ", num_rows, " rows."); + // Go into interactive debug mode if requested. + if (getenv("AVM_DEBUG") != nullptr) { + InteractiveDebugger debugger(trace); + debugger.run(); + } + + // Warning: this destroys the trace. auto polynomials = AVM_TRACK_TIME_V("proving/prove:compute_polynomials", compute_polynomials(trace)); try { AVM_TRACK_TIME("proving/check_circuit", constraining::run_check_circuit(polynomials, num_rows)); - } catch (const std::exception& e) { + } catch (std::runtime_error& e) { + // FIXME: This exception is never caught because it's thrown in a different thread. + // Execution never gets here! info("Circuit check failed: ", e.what()); - return false; } return true; diff --git a/barretenberg/cpp/src/barretenberg/vm2/tracegen/lib/trace_conversion.cpp b/barretenberg/cpp/src/barretenberg/vm2/tracegen/lib/trace_conversion.cpp new file mode 100644 index 00000000000..f5264af4e27 --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/vm2/tracegen/lib/trace_conversion.cpp @@ -0,0 +1,39 @@ +#include "barretenberg/vm2/tracegen/lib/trace_conversion.hpp" + +#include + +#include "barretenberg/vm2/generated/columns.hpp" + +namespace bb::avm2::tracegen { + +std::optional shift_column(Column c) +{ + static std::unordered_map shifts = []() { + std::unordered_map shifts; + for (size_t i = 0; i < TO_BE_SHIFTED_COLUMNS_ARRAY.size(); ++i) { + shifts[TO_BE_SHIFTED_COLUMNS_ARRAY[i]] = SHIFTED_COLUMNS_ARRAY[i]; + } + return shifts; + }(); + + auto it = shifts.find(c); + return it == shifts.end() ? std::nullopt : std::make_optional(it->second); +} + +AvmFullRow get_full_row(const TraceContainer& trace, uint32_t row) +{ + AvmFullRow full_row; + // Write unshifted columns. + for (size_t col = 0; col < trace.num_columns(); ++col) { + full_row.get_column(static_cast(col)) = trace.get(static_cast(col), row); + } + // Write the shifted values. + for (const auto& col : TO_BE_SHIFTED_COLUMNS_ARRAY) { + auto value = trace.get(static_cast(col), row + 1); + auto shifted = shift_column(col); + full_row.get_column(shifted.value()) = value; + } + return full_row; +} + +} // namespace bb::avm2::tracegen \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/vm2/tracegen/lib/trace_conversion.hpp b/barretenberg/cpp/src/barretenberg/vm2/tracegen/lib/trace_conversion.hpp new file mode 100644 index 00000000000..a2c5d0682d8 --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/vm2/tracegen/lib/trace_conversion.hpp @@ -0,0 +1,16 @@ +#pragma once + +#include + +#include "barretenberg/vm2/common/field.hpp" +#include "barretenberg/vm2/generated/columns.hpp" +#include "barretenberg/vm2/generated/full_row.hpp" +#include "barretenberg/vm2/tracegen/trace_container.hpp" + +namespace bb::avm2::tracegen { + +std::optional shift_column(Column c); +// This is expensive. Only use in debugging and testing. +AvmFullRow get_full_row(const TraceContainer& trace, uint32_t row); + +} // namespace bb::avm2::tracegen \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/vm2/tracegen/test_trace_container.cpp b/barretenberg/cpp/src/barretenberg/vm2/tracegen/test_trace_container.cpp index 898ddb57604..8e5caa93d4a 100644 --- a/barretenberg/cpp/src/barretenberg/vm2/tracegen/test_trace_container.cpp +++ b/barretenberg/cpp/src/barretenberg/vm2/tracegen/test_trace_container.cpp @@ -1,48 +1,30 @@ #include "barretenberg/vm2/tracegen/test_trace_container.hpp" +#include "barretenberg/vm2/generated/columns.hpp" +#include "barretenberg/vm2/tracegen/lib/trace_conversion.hpp" + namespace bb::avm2::tracegen { -namespace { -std::optional shift_column(Column c) +TestTraceContainer TestTraceContainer::from_rows(const RowTraceContainer& rows) { - static std::unordered_map shifts = []() { - std::unordered_map shifts; - for (size_t i = 0; i < TO_BE_SHIFTED_COLUMNS_ARRAY.size(); ++i) { - shifts[TO_BE_SHIFTED_COLUMNS_ARRAY[i]] = SHIFTED_COLUMNS_ARRAY[i]; + TestTraceContainer container; + for (uint32_t row = 0; row < rows.size(); ++row) { + const auto& full_row = rows[row]; + for (size_t i = 0; i < container.num_columns(); ++i) { + const auto column = static_cast(i); + container.set(column, row, full_row.get_column(static_cast(column))); } - return shifts; - }(); - - auto it = shifts.find(c); - return it == shifts.end() ? std::nullopt : std::make_optional(it->second); + } + return container; } -} // namespace - TestTraceContainer::RowTraceContainer TestTraceContainer::as_rows() const { - // Find the maximum size of any column. const uint32_t max_rows = get_num_rows(); - RowTraceContainer full_row_trace(max_rows); - // Write the values. - for (size_t col = 0; col < num_columns(); ++col) { - visit_column(static_cast(col), [&](size_t row, const FF& value) { - full_row_trace[row].get_column(static_cast(col)) = value; - }); - } - - // Write the shifted values. - for (const auto& col : TO_BE_SHIFTED_COLUMNS_ARRAY) { - visit_column(col, [&](size_t row, const FF& value) { - if (row == 0) { - return; - } - auto shifted = shift_column(col); - full_row_trace[row - 1].get_column(shifted.value()) = value; - }); + for (uint32_t i = 0; i < max_rows; ++i) { + full_row_trace[i] = get_full_row(*this, i); } - return full_row_trace; } diff --git a/barretenberg/cpp/src/barretenberg/vm2/tracegen/test_trace_container.hpp b/barretenberg/cpp/src/barretenberg/vm2/tracegen/test_trace_container.hpp index 94987f325c8..d6fa33157af 100644 --- a/barretenberg/cpp/src/barretenberg/vm2/tracegen/test_trace_container.hpp +++ b/barretenberg/cpp/src/barretenberg/vm2/tracegen/test_trace_container.hpp @@ -14,6 +14,8 @@ class TestTraceContainer : public TraceContainer { using Row = AvmFullRow; using RowTraceContainer = std::vector; + static TestTraceContainer from_rows(const RowTraceContainer& rows); + TestTraceContainer() = default; TestTraceContainer(const std::vector>>& values) { diff --git a/barretenberg/cpp/src/barretenberg/vm2/tracegen/trace_container.cpp b/barretenberg/cpp/src/barretenberg/vm2/tracegen/trace_container.cpp index 506575de3f5..76c9471120a 100644 --- a/barretenberg/cpp/src/barretenberg/vm2/tracegen/trace_container.cpp +++ b/barretenberg/cpp/src/barretenberg/vm2/tracegen/trace_container.cpp @@ -2,6 +2,7 @@ #include "barretenberg/common/log.hpp" #include "barretenberg/vm2/common/field.hpp" +#include "barretenberg/vm2/generated/columns.hpp" namespace bb::avm2::tracegen { namespace { @@ -13,7 +14,7 @@ constexpr auto clk_column = Column::precomputed_clk; } // namespace TraceContainer::TraceContainer() - : trace(std::make_unique>()) + : trace(std::make_unique>()) {} const FF& TraceContainer::get(Column col, uint32_t row) const diff --git a/barretenberg/cpp/src/barretenberg/vm2/tracegen/trace_container.hpp b/barretenberg/cpp/src/barretenberg/vm2/tracegen/trace_container.hpp index 7c432dbb9ba..8bd3029a220 100644 --- a/barretenberg/cpp/src/barretenberg/vm2/tracegen/trace_container.hpp +++ b/barretenberg/cpp/src/barretenberg/vm2/tracegen/trace_container.hpp @@ -45,7 +45,7 @@ class TraceContainer { // Maximum number of rows in any column (ignoring clk which is always 2^21). uint32_t get_num_rows_without_clk() const; // Number of columns (without shifts). - static constexpr size_t num_columns() { return NUM_COLUMNS; } + static constexpr size_t num_columns() { return NUM_COLUMNS_WITHOUT_SHIFTS; } // Free column memory. void clear_column(Column col); @@ -62,12 +62,11 @@ class TraceContainer { // (see serialization.hpp). unordered_flat_map rows; }; - static constexpr size_t NUM_COLUMNS = static_cast(ColumnAndShifts::NUM_COLUMNS); // We store the trace as a sparse matrix. // We use a unique_ptr to allocate the array in the heap vs the stack. // Even if the _content_ of each unordered_map is always heap-allocated, if we have 3k columns // we could unnecessarily put strain on the stack with sizeof(unordered_map) * 3k bytes. - std::unique_ptr> trace; + std::unique_ptr> trace; }; } // namespace bb::avm2::tracegen \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/vm2/tracegen_helper.cpp b/barretenberg/cpp/src/barretenberg/vm2/tracegen_helper.cpp index d9d68f5d4b7..a2379eb06f8 100644 --- a/barretenberg/cpp/src/barretenberg/vm2/tracegen_helper.cpp +++ b/barretenberg/cpp/src/barretenberg/vm2/tracegen_helper.cpp @@ -58,7 +58,7 @@ void print_trace_stats(const TraceContainer& trace) { unordered_flat_map namespace_column_sizes; uint64_t total_rows = 0; - for (size_t col = 0; col < static_cast(ColumnAndShifts::NUM_COLUMNS); ++col) { + for (size_t col = 0; col < trace.num_columns(); ++col) { const auto& column_rows = trace.get_column_rows(static_cast(col)); const std::string& column_name = COLUMN_NAMES.at(col); const auto namespace_name = column_name.substr(0, column_name.find('_')); diff --git a/bb-pilcom/bb-pil-backend/templates/columns.hpp.hbs b/bb-pilcom/bb-pil-backend/templates/columns.hpp.hbs index b0514608463..876335f3e7e 100644 --- a/bb-pilcom/bb-pil-backend/templates/columns.hpp.hbs +++ b/bb-pilcom/bb-pil-backend/templates/columns.hpp.hbs @@ -27,10 +27,11 @@ enum class Column { {{shoutySnakeCase name}}_UNSHIFTED_ENTITIES }; // C++ doesn't allow enum extension, so we'll have to cast. enum class ColumnAndShifts { {{shoutySnakeCase name}}_ALL_ENTITIES, - // Sentinel. - NUM_COLUMNS, + SENTINEL_DO_NOT_USE, }; +constexpr auto NUM_COLUMNS_WITH_SHIFTS = {{len all_cols_and_shifts}}; +constexpr auto NUM_COLUMNS_WITHOUT_SHIFTS = {{len all_cols}}; constexpr auto TO_BE_SHIFTED_COLUMNS_ARRAY = []() { return std::array{ {{shoutySnakeCase name}}_TO_BE_SHIFTED_COLUMNS }; }(); constexpr auto SHIFTED_COLUMNS_ARRAY = []() { return std::array{ {{shoutySnakeCase name}}_SHIFTED_COLUMNS }; }(); static_assert(TO_BE_SHIFTED_COLUMNS_ARRAY.size() == SHIFTED_COLUMNS_ARRAY.size()); diff --git a/bb-pilcom/bb-pil-backend/templates/full_row.hpp.hbs b/bb-pilcom/bb-pil-backend/templates/full_row.hpp.hbs index 8cefb412b05..e274bd99189 100644 --- a/bb-pilcom/bb-pil-backend/templates/full_row.hpp.hbs +++ b/bb-pilcom/bb-pil-backend/templates/full_row.hpp.hbs @@ -21,13 +21,13 @@ struct AvmFullRow { // Risky but oh so efficient. FF& get_column(ColumnAndShifts col) { - static_assert(sizeof(*this) == sizeof(FF) * static_cast(ColumnAndShifts::NUM_COLUMNS)); + static_assert(sizeof(*this) == sizeof(FF) * static_cast(ColumnAndShifts::SENTINEL_DO_NOT_USE)); return reinterpret_cast(this)[static_cast(col)]; } const FF& get_column(ColumnAndShifts col) const { - static_assert(sizeof(*this) == sizeof(FF) * static_cast(ColumnAndShifts::NUM_COLUMNS)); + static_assert(sizeof(*this) == sizeof(FF) * static_cast(ColumnAndShifts::SENTINEL_DO_NOT_USE)); return reinterpret_cast(this)[static_cast(col)]; } };