Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@

- Added `procedure_names` to `DebugInfo` for storing procedure name mappings by MAST root digest, enabling debuggers to resolve human-readable procedure names during execution (#[2474](https://github.com/0xMiden/miden-vm/pull/2474)).

#### Fixes

- `FastProcessor` now correctly returns an error if the maximum number of cycles was exceeded during execution ([#2537](https://github.com/0xMiden/miden-vm/pull/2537))

#### Changes

- Added `--kernel` flag to CLI commands (`run`, `prove`, `verify`, `debug`) to allow loading custom kernels from `.masm` or `.masp` files ([#2363](https://github.com/0xMiden/miden-vm/pull/2363)).
Expand Down
2 changes: 0 additions & 2 deletions air/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,4 @@ pub enum ExecutionOptionsError {
InvalidHashFunction { hash_function: String },
#[error("core trace fragment size must be greater than 0")]
CoreTraceFragmentSizeTooSmall,
#[error("core trace fragment size {0} must be a power of two")]
CoreTraceFragmentSizeNotPowerOfTwo(usize),
}
34 changes: 2 additions & 32 deletions air/src/options.rs
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ impl ExecutionOptions {
/// Returns an error if:
/// - `max_cycles` is outside the valid range
/// - `expected_cycles` exceeds `max_cycles`
/// - `core_trace_fragment_size` is zero or not a power of two
/// - `core_trace_fragment_size` is zero
pub fn new(
max_cycles: Option<u32>,
expected_cycles: u32,
Expand Down Expand Up @@ -156,11 +156,6 @@ impl ExecutionOptions {
if core_trace_fragment_size == 0 {
return Err(ExecutionOptionsError::CoreTraceFragmentSizeTooSmall);
}
if !core_trace_fragment_size.is_power_of_two() {
return Err(ExecutionOptionsError::CoreTraceFragmentSizeNotPowerOfTwo(
core_trace_fragment_size,
));
}

Ok(ExecutionOptions {
max_cycles,
Expand All @@ -173,17 +168,14 @@ impl ExecutionOptions {

/// Sets the fragment size for core trace generation.
///
/// Returns an error if the size is zero or not a power of two.
/// Returns an error if the size is zero.
pub fn with_core_trace_fragment_size(
mut self,
size: usize,
) -> Result<Self, ExecutionOptionsError> {
if size == 0 {
return Err(ExecutionOptionsError::CoreTraceFragmentSizeTooSmall);
}
if !size.is_power_of_two() {
return Err(ExecutionOptionsError::CoreTraceFragmentSizeNotPowerOfTwo(size));
}
self.core_trace_fragment_size = size;
Ok(self)
}
Expand Down Expand Up @@ -266,21 +258,6 @@ mod tests {
assert!(matches!(opts, Err(ExecutionOptionsError::CoreTraceFragmentSizeTooSmall)));
}

#[test]
fn non_power_of_two_fragment_size_fails() {
let opts = ExecutionOptions::new(None, 64, 1000, false, false);
assert!(matches!(
opts,
Err(ExecutionOptionsError::CoreTraceFragmentSizeNotPowerOfTwo(1000))
));

let opts = ExecutionOptions::new(None, 64, 3, false, false);
assert!(matches!(
opts,
Err(ExecutionOptionsError::CoreTraceFragmentSizeNotPowerOfTwo(3))
));
}

#[test]
fn with_core_trace_fragment_size_validates() {
// Valid size should succeed
Expand All @@ -291,12 +268,5 @@ mod tests {
// Zero should fail
let result = ExecutionOptions::default().with_core_trace_fragment_size(0);
assert!(matches!(result, Err(ExecutionOptionsError::CoreTraceFragmentSizeTooSmall)));

// Non-power-of-two should fail
let result = ExecutionOptions::default().with_core_trace_fragment_size(100);
assert!(matches!(
result,
Err(ExecutionOptionsError::CoreTraceFragmentSizeNotPowerOfTwo(100))
));
}
}
15 changes: 9 additions & 6 deletions crates/test-utils/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -387,12 +387,15 @@ impl Test {
let fast_stack_result = {
let stack_inputs: Vec<Felt> = self.stack_inputs.clone().into_iter().rev().collect();
let advice_inputs: AdviceInputs = self.advice_inputs.clone();
let fast_processor = if self.in_debug_mode {
FastProcessor::new_debug(&stack_inputs, advice_inputs)
} else {
FastProcessor::new_with_advice_inputs(&stack_inputs, advice_inputs)
};
fast_processor.execute_for_trace_sync(&program, &mut host, FRAGMENT_SIZE)
let fast_processor = FastProcessor::new_with_options(
&stack_inputs,
advice_inputs,
miden_air::ExecutionOptions::default()
.with_debugging(self.in_debug_mode)
.with_core_trace_fragment_size(FRAGMENT_SIZE)
.unwrap(),
);
fast_processor.execute_for_trace_sync(&program, &mut host)
};

// compare fast and slow processors' stack outputs
Expand Down
11 changes: 6 additions & 5 deletions miden-vm/benches/build_trace.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,18 +65,19 @@ fn build_trace(c: &mut Criterion) {
.with_library(&CoreLibrary::default())
.unwrap();

let processor = FastProcessor::new_with_advice_inputs(
let processor = FastProcessor::new_with_options(
&stack_inputs,
advice_inputs.clone(),
ExecutionOptions::default()
.with_core_trace_fragment_size(TRACE_FRAGMENT_SIZE)
.unwrap(),
);

(host, program.clone(), processor)
},
|(mut host, program, processor)| async move {
let (execution_output, trace_generation_context) = processor
.execute_for_trace(&program, &mut host, TRACE_FRAGMENT_SIZE)
.await
.unwrap();
let (execution_output, trace_generation_context) =
processor.execute_for_trace(&program, &mut host).await.unwrap();

let trace = parallel::build_trace(
execution_output,
Expand Down
13 changes: 7 additions & 6 deletions miden-vm/benches/program_execution_for_trace.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use std::hint::black_box;

use criterion::{BatchSize, Criterion, criterion_group, criterion_main};
use miden_core_lib::CoreLibrary;
use miden_processor::{AdviceInputs, fast::FastProcessor};
use miden_processor::{AdviceInputs, ExecutionOptions, fast::FastProcessor};
use miden_vm::{Assembler, DefaultHost, StackInputs, internal::InputFile};
use tokio::runtime::Runtime;
use walkdir::WalkDir;
Expand Down Expand Up @@ -61,18 +61,19 @@ fn program_execution_for_trace(c: &mut Criterion) {
.with_library(&CoreLibrary::default())
.unwrap();

let processor = FastProcessor::new_with_advice_inputs(
let processor = FastProcessor::new_with_options(
&stack_inputs,
advice_inputs.clone(),
ExecutionOptions::default()
.with_core_trace_fragment_size(TRACE_FRAGMENT_SIZE)
.unwrap(),
);

(host, program.clone(), processor)
},
|(mut host, program, processor)| async move {
let out = processor
.execute_for_trace(&program, &mut host, TRACE_FRAGMENT_SIZE)
.await
.unwrap();
let out =
processor.execute_for_trace(&program, &mut host).await.unwrap();
black_box(out);
},
BatchSize::SmallInput,
Expand Down
6 changes: 3 additions & 3 deletions miden-vm/src/cli/run.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use miden_core_lib::CoreLibrary;
use miden_processor::{
DefaultHost, ExecutionOptions, ExecutionTrace, fast::FastProcessor, parallel::build_trace,
};
use miden_vm::{DEFAULT_CORE_TRACE_FRAGMENT_SIZE, internal::InputFile};
use miden_vm::internal::InputFile;
use tracing::instrument;

use super::{
Expand Down Expand Up @@ -154,7 +154,7 @@ fn run_masp_program(params: &RunCmd) -> Result<(ExecutionTrace, [u8; 32]), Repor
};

let (execution_output, trace_generation_context) = processor
.execute_for_trace_sync(&program, &mut host, DEFAULT_CORE_TRACE_FRAGMENT_SIZE)
.execute_for_trace_sync(&program, &mut host)
.wrap_err("Failed to execute program")?;

let trace = build_trace(
Expand Down Expand Up @@ -225,7 +225,7 @@ fn run_masm_program(params: &RunCmd) -> Result<(ExecutionTrace, [u8; 32]), Repor
};

let (execution_output, trace_generation_context) = processor
.execute_for_trace_sync(&program, &mut host, DEFAULT_CORE_TRACE_FRAGMENT_SIZE)
.execute_for_trace_sync(&program, &mut host)
.wrap_err("Failed to execute program")?;

let trace = build_trace(
Expand Down
15 changes: 11 additions & 4 deletions miden-vm/tests/integration/prove_verify.rs
Original file line number Diff line number Diff line change
Expand Up @@ -201,7 +201,9 @@ mod fast_parallel {

use miden_assembly::{Assembler, DefaultSourceManager};
use miden_core::Felt;
use miden_processor::{AdviceInputs, StackInputs, fast::FastProcessor, parallel::build_trace};
use miden_processor::{
AdviceInputs, ExecutionOptions, StackInputs, fast::FastProcessor, parallel::build_trace,
};
use miden_prover::{
ExecutionProof, HashFunction, ProcessorAir, config, execution_trace_to_row_major, stark,
};
Expand Down Expand Up @@ -237,10 +239,15 @@ mod fast_parallel {
// Convert stack inputs for fast processor (reversed order)
let stack_inputs_vec: Vec<Felt> = stack_inputs.clone().into_iter().rev().collect();

let fast_processor =
FastProcessor::new_with_advice_inputs(&stack_inputs_vec, advice_inputs.clone());
let fast_processor = FastProcessor::new_with_options(
&stack_inputs_vec,
advice_inputs.clone(),
ExecutionOptions::default()
.with_core_trace_fragment_size(FRAGMENT_SIZE)
.unwrap(),
);
let (execution_output, trace_context) = fast_processor
.execute_for_trace_sync(&program, &mut host, FRAGMENT_SIZE)
.execute_for_trace_sync(&program, &mut host)
.expect("Fast processor execution failed");

let fast_stack_outputs = execution_output.stack.clone();
Expand Down
29 changes: 18 additions & 11 deletions processor/src/chiplets/tests.rs
Original file line number Diff line number Diff line change
@@ -1,21 +1,24 @@
use alloc::vec::Vec;

use miden_air::trace::{
CHIPLETS_RANGE, CHIPLETS_WIDTH,
chiplets::{
NUM_BITWISE_SELECTORS, NUM_KERNEL_ROM_SELECTORS, NUM_MEMORY_SELECTORS,
bitwise::{BITWISE_XOR, OP_CYCLE_LEN, TRACE_WIDTH as BITWISE_TRACE_WIDTH},
hasher::{HASH_CYCLE_LEN, LINEAR_HASH, RETURN_STATE},
kernel_rom::TRACE_WIDTH as KERNEL_ROM_TRACE_WIDTH,
memory::TRACE_WIDTH as MEMORY_TRACE_WIDTH,
use miden_air::{
ExecutionOptions,
trace::{
CHIPLETS_RANGE, CHIPLETS_WIDTH,
chiplets::{
NUM_BITWISE_SELECTORS, NUM_KERNEL_ROM_SELECTORS, NUM_MEMORY_SELECTORS,
bitwise::{BITWISE_XOR, OP_CYCLE_LEN, TRACE_WIDTH as BITWISE_TRACE_WIDTH},
hasher::{HASH_CYCLE_LEN, LINEAR_HASH, RETURN_STATE},
kernel_rom::TRACE_WIDTH as KERNEL_ROM_TRACE_WIDTH,
memory::TRACE_WIDTH as MEMORY_TRACE_WIDTH,
},
},
};
use miden_core::{
Felt, ONE, Program, Word, ZERO,
mast::{BasicBlockNodeBuilder, MastForest, MastForestContributor},
};

use crate::{DefaultHost, Kernel, Operation, fast::FastProcessor};
use crate::{AdviceInputs, DefaultHost, Kernel, Operation, fast::FastProcessor};

type ChipletsTrace = [Vec<Felt>; CHIPLETS_WIDTH];

Expand Down Expand Up @@ -117,7 +120,11 @@ fn build_trace(
kernel: Kernel,
) -> (ChipletsTrace, usize) {
let stack_inputs: Vec<Felt> = stack_inputs.iter().map(|v| Felt::new(*v)).collect();
let processor = FastProcessor::new(&stack_inputs);
let processor = FastProcessor::new_with_options(
&stack_inputs,
AdviceInputs::default(),
ExecutionOptions::default().with_core_trace_fragment_size(1 << 10).unwrap(),
);

let mut host = DefaultHost::default();
let program = {
Expand All @@ -132,7 +139,7 @@ fn build_trace(
};

let (execution_output, trace_generation_context) =
processor.execute_for_trace_sync(&program, &mut host, 1 << 10).unwrap();
processor.execute_for_trace_sync(&program, &mut host).unwrap();
let trace = crate::parallel::build_trace(
execution_output,
trace_generation_context,
Expand Down
40 changes: 19 additions & 21 deletions processor/src/fast/basic_block.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,12 +44,12 @@ impl FastProcessor {
self.execute_before_enter_decorators(node_id, current_forest, host)?;

// Corresponds to the row inserted for the BASIC BLOCK operation added to the trace.
self.increment_clk(tracer, stopper).map_break(|_| {
BreakReason::Stopped(Some(Continuation::ResumeBasicBlock {
self.increment_clk_with_continuation(tracer, stopper, || {
Some(Continuation::ResumeBasicBlock {
node_id,
batch_index: 0,
op_idx_in_batch: 0,
}))
})
})?;

// execute first batch
Expand Down Expand Up @@ -117,17 +117,17 @@ impl FastProcessor {

// Corresponds to the RESPAN operation added to the trace.
//
// Note: in `map_break()`, the continuation encodes resuming from the start of the
// batch *after* the RESPAN operation. This is because the continuation encodes what
// happens *after* the clock is incremented. In other words, if we were to put a
// `Continuation::Respan` here instead, the next call to `FastProcessor::step()`
// would re-execute the RESPAN (over, and over).
self.increment_clk(tracer, stopper).map_break(|_| {
BreakReason::Stopped(Some(Continuation::ResumeBasicBlock {
// Note: in the continuation closure, the continuation encodes resuming from the
// start of the batch *after* the RESPAN operation. This is because the continuation
// encodes what happens *after* the clock is incremented. In other words, if we were
// to put a `Continuation::Respan` here instead, the next call to
// `FastProcessor::step()` would re-execute the RESPAN (over, and over).
self.increment_clk_with_continuation(tracer, stopper, || {
Some(Continuation::ResumeBasicBlock {
node_id,
batch_index,
op_idx_in_batch: 0,
}))
})
})?;
}

Expand Down Expand Up @@ -232,7 +232,7 @@ impl FastProcessor {
for (op_idx_in_batch, op) in batch.ops().iter().enumerate().skip(start_op_idx) {
let op_idx_in_block = batch_offset_in_block + op_idx_in_batch;

if self.in_debug_mode {
if self.should_execute_decorators() {
#[cfg(test)]
self.record_decorator_retrieval();

Expand All @@ -257,7 +257,7 @@ impl FastProcessor {
// performance improvement).
{
let err_ctx =
err_ctx!(current_forest, node_id, host, self.in_debug_mode, op_idx_in_block);
err_ctx!(current_forest, node_id, host, self.in_debug_mode(), op_idx_in_block);
match op {
Operation::Emit => self.op_emit(host, &err_ctx).await?,
_ => {
Expand All @@ -271,15 +271,13 @@ impl FastProcessor {
}
}

self.increment_clk(tracer, stopper).map_break(|_| {
let continuation = get_continuation_after_executing_operation(
self.increment_clk_with_continuation(tracer, stopper, || {
Some(get_continuation_after_executing_operation(
basic_block,
node_id,
batch_index,
op_idx_in_batch,
);

BreakReason::Stopped(Some(continuation))
))
})?;
}

Expand All @@ -306,8 +304,8 @@ impl FastProcessor {
);

// Corresponds to the row inserted for the END operation added to the trace.
self.increment_clk(tracer, stopper).map_break(|_| {
BreakReason::Stopped(Some(Continuation::AfterExitDecoratorsBasicBlock(node_id)))
self.increment_clk_with_continuation(tracer, stopper, || {
Some(Continuation::AfterExitDecoratorsBasicBlock(node_id))
})?;

self.execute_end_of_block_decorators(basic_block_node, node_id, current_forest, host)?;
Expand All @@ -327,7 +325,7 @@ impl FastProcessor {
current_forest: &Arc<MastForest>,
host: &mut impl AsyncHost,
) -> ControlFlow<BreakReason> {
if self.in_debug_mode {
if self.should_execute_decorators() {
#[cfg(test)]
self.record_decorator_retrieval();

Expand Down
Loading