From bf4dbdfd4eb9051b4fe6e0781aa0e23c9d120fd3 Mon Sep 17 00:00:00 2001 From: Andrey Khmuro Date: Mon, 9 Oct 2023 16:30:37 +0200 Subject: [PATCH] refactor: improve analyze tool --- miden/Cargo.toml | 2 +- miden/src/tools/mod.rs | 112 +++++++++++++++++++++++++++-------- processor/src/debug.rs | 26 +++++++- processor/src/lib.rs | 2 +- processor/src/trace/utils.rs | 18 +++++- 5 files changed, 129 insertions(+), 31 deletions(-) diff --git a/miden/Cargo.toml b/miden/Cargo.toml index 487f2d17a9..32253f4684 100644 --- a/miden/Cargo.toml +++ b/miden/Cargo.toml @@ -64,5 +64,5 @@ escargot = "0.5.7" num-bigint = "0.4" predicates = "3.0" test-utils = { package = "miden-test-utils", path = "../test-utils" } -vm-core = { package = "miden-core", path = "../core", version = "0.7" } winter-fri = { package = "winter-fri", version = "0.6" } +vm-core = { package = "miden-core", path = "../core", version = "0.7" } diff --git a/miden/src/tools/mod.rs b/miden/src/tools/mod.rs index 23bc7a9f93..9e9a766293 100644 --- a/miden/src/tools/mod.rs +++ b/miden/src/tools/mod.rs @@ -2,7 +2,7 @@ use super::{cli::InputFile, ProgramError}; use clap::Parser; use core::fmt; use miden::{utils::collections::Vec, Assembler, DefaultHost, Host, Operation, StackInputs}; -use processor::AsmOpInfo; +use processor::{AsmOpInfo, TraceLenSummary}; use std::{fs, path::PathBuf}; use stdlib::StdLibrary; @@ -36,6 +36,23 @@ impl Analyze { let execution_details: ExecutionDetails = analyze(program.as_str(), stack_inputs, host) .expect("Could not retrieve execution details"); + let program_name = self + .assembly_file + .file_name() + .expect("provided file path is incorrect") + .to_str() + .unwrap(); + + println!("============================================================"); + print!("Analyzed {} program", program_name); + if let Some(input_path) = &self.input_file { + let input_name = input_path + .file_name() + .expect("provided input path is incorrect") + .to_str() + .unwrap(); + println!(" with {}", input_name); + } println!("{}", execution_details); @@ -49,20 +66,15 @@ impl Analyze { /// Contains details of executing a program, used for program analysis. #[derive(Debug, Default, Eq, PartialEq)] pub struct ExecutionDetails { - /// Number of VM cycles it took to execute the entire program. - total_vm_cycles: u32, /// Number of noops executed as part of a program. total_noops: usize, /// Statistics about individual assembly operations executed by the VM, see [AsmOpStats]. asm_op_stats: Vec, + /// Information about VM components trace lengths. + trace_len_summary: TraceLenSummary, } impl ExecutionDetails { - /// Returns total vm cycles to execute a program - pub fn total_vm_cycles(&self) -> u32 { - self.total_vm_cycles - } - /// Returns total noops executed as part of a program pub fn total_noops(&self) -> usize { self.total_noops @@ -74,6 +86,11 @@ impl ExecutionDetails { &self.asm_op_stats } + /// Returns [TraceLenSummary] that contains the data about lengths of the trace parts. + pub fn trace_len_summary(&self) -> TraceLenSummary { + self.trace_len_summary + } + // STATE MUTATORS // -------------------------------------------------------------------------------------------- @@ -82,11 +99,6 @@ impl ExecutionDetails { self.total_noops += 1; } - /// Sets the total vm cycles to the provided value - pub fn set_total_vm_cycles(&mut self, total_vm_cycles: u32) { - self.total_vm_cycles = total_vm_cycles; - } - /// Records a new occurrence of asmop in the sorted asmop stats vector of this program info. /// If the asmop is already in the list, increments its frequency by one. /// If the asmop is not already in the list, add it at the appropriate index to keep the @@ -115,30 +127,76 @@ impl ExecutionDetails { } } } + + /// Sets the information about lengths of the trace parts. + pub fn set_trace_len_summary(&mut self, extended_cycles_info: &TraceLenSummary) { + self.trace_len_summary = *extended_cycles_info; + } } impl fmt::Display for ExecutionDetails { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - let total_vm_cycles = self.total_vm_cycles(); + // calculate the percentage of padded rows + let padding_percentage = (self.trace_len_summary().padded_trace_len() + - self.trace_len_summary().trace_len()) + * 100 + / self.trace_len_summary().padded_trace_len(); + + writeln!( + f, + "\nVM cycles: {} extended to {} steps ({}% padding). +├── Stack rows: {} +├── Range checker rows: {} +└── Chiplets rows: {} + ├── Hash chiplet rows: {} + ├── Bitwise chiplet rows: {} + ├── Memory chiplet rows: {} + └── Kernel ROM rows: {}\n", + self.trace_len_summary().trace_len(), + self.trace_len_summary().padded_trace_len(), + padding_percentage, + self.trace_len_summary().main_trace_len(), + self.trace_len_summary().range_trace_len(), + self.trace_len_summary().chiplets_trace_len().trace_len(), + self.trace_len_summary().chiplets_trace_len().hash_chiplet_len(), + self.trace_len_summary().chiplets_trace_len().bitwise_chiplet_len(), + self.trace_len_summary().chiplets_trace_len().memory_chiplet_len(), + self.trace_len_summary().chiplets_trace_len().kernel_rom_len(), + )?; let total_noops = self.total_noops(); let asm_op_stats = self.asm_op_stats(); - writeln!(f, "Total Number of VM Cycles: {}\n", total_vm_cycles)?; - writeln!(f, "Total Number of NOOPs executed: {}\n", total_noops)?; + + // calculate the total length of pading for the `AsmOp` column + let padding = + asm_op_stats.iter().try_fold(20, |max, value| Ok(value.op().len().max(max)))?; + writeln!( f, - "{0: <20} | {1: <20} | {2: <20} | {3: <20}", - "AsmOp", "Frequency", "Total Cycles", "Avg Instruction Cycles" + "{0: (System, Decoder, Stack, Chiplets, Option) { (self.system, self.decoder, self.stack, self.chiplets, self.error) } + + pub fn trace_len_summary(&self) -> &TraceLenSummary { + &self.trace_len_summary + } + + /// Returns an instance of [TraceLenSummary] based on provided data. + fn build_trace_len_summary( + system: &System, + range: &mut RangeChecker, + chiplets: &Chiplets, + ) -> TraceLenSummary { + let clk = system.clk(); + let range_table_len = range.get_number_range_checker_rows(); + chiplets.append_range_checks(range); + + TraceLenSummary::new(clk as usize, range_table_len, ChipletsLengths::new(chiplets)) + } } impl Iterator for VmStateIterator { diff --git a/processor/src/lib.rs b/processor/src/lib.rs index 0b3f9c2a20..45dc1fed8e 100644 --- a/processor/src/lib.rs +++ b/processor/src/lib.rs @@ -51,8 +51,8 @@ mod chiplets; use chiplets::Chiplets; mod trace; -pub use trace::ExecutionTrace; use trace::TraceFragment; +pub use trace::{ChipletsLengths, ExecutionTrace, TraceLenSummary}; mod errors; pub use errors::{ExecutionError, Ext2InttError}; diff --git a/processor/src/trace/utils.rs b/processor/src/trace/utils.rs index db6abee587..705fa314ba 100644 --- a/processor/src/trace/utils.rs +++ b/processor/src/trace/utils.rs @@ -247,7 +247,7 @@ impl HintCycle for u64 { /// - `range_trace_len` contains the length of the range checker trace. /// - `chiplets_trace_len` contains the trace lengths of the all chiplets (hash, bitwise, memory, /// kernel ROM) -#[derive(Debug)] +#[derive(Debug, Default, Eq, PartialEq, Clone, Copy)] pub struct TraceLenSummary { main_trace_len: usize, range_trace_len: usize, @@ -297,7 +297,7 @@ impl TraceLenSummary { /// Contains trace lengths of all chilplets: hash, bitwise, memory and kernel ROM trace /// lengths. -#[derive(Clone, Copy, Debug)] +#[derive(Default, Clone, Copy, Debug, PartialEq, Eq)] pub struct ChipletsLengths { hash_chiplet_len: usize, bitwise_chiplet_len: usize, @@ -315,6 +315,20 @@ impl ChipletsLengths { } } + pub fn from_parts( + hash_len: usize, + bitwise_len: usize, + memory_len: usize, + kernel_len: usize, + ) -> Self { + ChipletsLengths { + hash_chiplet_len: hash_len, + bitwise_chiplet_len: bitwise_len, + memory_chiplet_len: memory_len, + kernel_rom_len: kernel_len, + } + } + /// Returns the length of the hash chiplet trace pub fn hash_chiplet_len(&self) -> usize { self.hash_chiplet_len