diff --git a/crates/prover/benches/prover_bench.rs b/crates/prover/benches/prover_bench.rs index b41d759..73bf93e 100644 --- a/crates/prover/benches/prover_bench.rs +++ b/crates/prover/benches/prover_bench.rs @@ -2,138 +2,120 @@ //! //! Run with: cargo bench -p zp1-prover -use criterion::{black_box, criterion_group, criterion_main, Criterion, BenchmarkId}; -use zp1_primitives::{M31, QM31, CirclePoint}; +use criterion::{black_box, criterion_group, criterion_main, BenchmarkId, Criterion}; +use zp1_primitives::{CirclePoint, M31, QM31}; use zp1_prover::parallel::{ - parallel_lde, parallel_merkle_tree, parallel_fri_fold, - parallel_batch_inverse, parallel_evaluate_poly, + parallel_batch_inverse, parallel_evaluate_poly, parallel_fri_fold, parallel_lde, + parallel_merkle_tree, }; fn bench_parallel_lde(c: &mut Criterion) { let mut group = c.benchmark_group("LDE"); - + for log_size in [10, 12, 14, 16] { let size = 1 << log_size; let column: Vec = (0..size).map(|i| M31::new(i as u32)).collect(); let columns = vec![column]; - + group.bench_with_input( BenchmarkId::new("parallel", format!("2^{}", log_size)), &columns, - |b, cols| { - b.iter(|| parallel_lde(black_box(cols), 4)) - }, + |b, cols| b.iter(|| parallel_lde(black_box(cols), 4)), ); } - + group.finish(); } fn bench_merkle_tree(c: &mut Criterion) { let mut group = c.benchmark_group("MerkleTree"); - + for log_size in [10, 12, 14, 16] { let size = 1 << log_size; let values: Vec = (0..size).map(|i| M31::new(i as u32)).collect(); - + group.bench_with_input( BenchmarkId::new("parallel", format!("2^{}", log_size)), &values, - |b, vals| { - b.iter(|| parallel_merkle_tree(black_box(vals))) - }, + |b, vals| b.iter(|| parallel_merkle_tree(black_box(vals))), ); } - + group.finish(); } fn bench_fri_fold(c: &mut Criterion) { let mut group = c.benchmark_group("FRI_Fold"); - + for log_size in [10, 12, 14, 16] { let size = 1 << log_size; - let values: Vec = (0..size) - .map(|i| M31::new(i as u32)) - .collect(); + let values: Vec = (0..size).map(|i| M31::new(i as u32)).collect(); let alpha = M31::new(12345); - + group.bench_with_input( BenchmarkId::new("parallel", format!("2^{}", log_size)), &values, - |b, vals| { - b.iter(|| parallel_fri_fold(black_box(vals), black_box(alpha))) - }, + |b, vals| b.iter(|| parallel_fri_fold(black_box(vals), black_box(alpha))), ); } - + group.finish(); } fn bench_batch_inverse(c: &mut Criterion) { let mut group = c.benchmark_group("BatchInverse"); - + for log_size in [10, 12, 14, 16] { let size = 1 << log_size; let values: Vec = (1..=size).map(|i| M31::new(i as u32)).collect(); - + group.bench_with_input( BenchmarkId::new("parallel", format!("2^{}", log_size)), &values, - |b, vals| { - b.iter(|| parallel_batch_inverse(black_box(vals))) - }, + |b, vals| b.iter(|| parallel_batch_inverse(black_box(vals))), ); } - + group.finish(); } fn bench_poly_eval(c: &mut Criterion) { let mut group = c.benchmark_group("PolyEval"); - + for log_degree in [8, 10, 12] { let degree = 1 << log_degree; let coeffs: Vec = (0..degree).map(|i| M31::new(i as u32)).collect(); let num_points = 1024; let points: Vec = (0..num_points).map(|i| M31::new(i as u32)).collect(); - + group.bench_with_input( BenchmarkId::new("parallel", format!("deg=2^{},pts=1024", log_degree)), &(&coeffs, &points), - |b, (c, p)| { - b.iter(|| parallel_evaluate_poly(black_box(*c), black_box(*p))) - }, + |b, (c, p)| b.iter(|| parallel_evaluate_poly(black_box(*c), black_box(*p))), ); } - + group.finish(); } fn bench_m31_ops(c: &mut Criterion) { let mut group = c.benchmark_group("M31"); - + let a = M31::new(123456789); let b = M31::new(987654321); - - group.bench_function("add", |bench| { - bench.iter(|| black_box(a) + black_box(b)) - }); - - group.bench_function("mul", |bench| { - bench.iter(|| black_box(a) * black_box(b)) - }); - - group.bench_function("inv", |bench| { - bench.iter(|| black_box(a).inv()) - }); - + + group.bench_function("add", |bench| bench.iter(|| black_box(a) + black_box(b))); + + group.bench_function("mul", |bench| bench.iter(|| black_box(a) * black_box(b))); + + group.bench_function("inv", |bench| bench.iter(|| black_box(a).inv())); + group.finish(); } fn bench_qm31_ops(c: &mut Criterion) { let mut group = c.benchmark_group("QM31"); - + let a = QM31::new( M31::new(123456789), M31::new(987654321), @@ -146,32 +128,26 @@ fn bench_qm31_ops(c: &mut Criterion) { M31::new(555555555), M31::new(666666666), ); - - group.bench_function("add", |bench| { - bench.iter(|| black_box(a) + black_box(b)) - }); - - group.bench_function("mul", |bench| { - bench.iter(|| black_box(a) * black_box(b)) - }); - - group.bench_function("inv", |bench| { - bench.iter(|| black_box(a).inv()) - }); - + + group.bench_function("add", |bench| bench.iter(|| black_box(a) + black_box(b))); + + group.bench_function("mul", |bench| bench.iter(|| black_box(a) * black_box(b))); + + group.bench_function("inv", |bench| bench.iter(|| black_box(a).inv())); + group.finish(); } fn bench_circle_fft(c: &mut Criterion) { use zp1_primitives::CircleFFT; - + let mut group = c.benchmark_group("CircleFFT"); - + for log_size in [8, 10, 12] { let size = 1 << log_size; let values: Vec = (0..size).map(|i| M31::new(i as u32)).collect(); let fft = CircleFFT::new(log_size); - + group.bench_with_input( BenchmarkId::new("fft", format!("2^{}", log_size)), &values, @@ -183,7 +159,7 @@ fn bench_circle_fft(c: &mut Criterion) { }) }, ); - + group.bench_with_input( BenchmarkId::new("ifft", format!("2^{}", log_size)), &values, @@ -196,7 +172,7 @@ fn bench_circle_fft(c: &mut Criterion) { }, ); } - + group.finish(); } @@ -204,21 +180,21 @@ fn bench_circle_fft(c: &mut Criterion) { fn bench_gpu_ntt(c: &mut Criterion) { use zp1_prover::gpu::{get_backend_for_device, DeviceType}; - + let mut group = c.benchmark_group("GPU_NTT"); - + // Get backends (CPU always available, Metal on macOS) let cpu_backend = get_backend_for_device(DeviceType::Cpu).unwrap(); - + #[cfg(target_os = "macos")] let metal_backend = get_backend_for_device(DeviceType::Metal).ok(); #[cfg(not(target_os = "macos"))] let metal_backend: Option> = None; - + for log_size in [10, 12, 14] { let size = 1 << log_size; let values: Vec = (0..size).map(|i| i as u32 % ((1 << 31) - 1)).collect(); - + // CPU benchmark group.bench_with_input( BenchmarkId::new("CPU", format!("2^{}", log_size)), @@ -231,7 +207,7 @@ fn bench_gpu_ntt(c: &mut Criterion) { }) }, ); - + // Metal benchmark (macOS only) if let Some(ref backend) = metal_backend { group.bench_with_input( @@ -247,67 +223,59 @@ fn bench_gpu_ntt(c: &mut Criterion) { ); } } - + group.finish(); } fn bench_gpu_lde(c: &mut Criterion) { use zp1_prover::gpu::{get_backend_for_device, DeviceType}; - + let mut group = c.benchmark_group("GPU_LDE"); - + let cpu_backend = get_backend_for_device(DeviceType::Cpu).unwrap(); - + #[cfg(target_os = "macos")] let metal_backend = get_backend_for_device(DeviceType::Metal).ok(); #[cfg(not(target_os = "macos"))] let metal_backend: Option> = None; - + for log_size in [8, 10, 12] { let size = 1 << log_size; let coeffs: Vec = (0..size).map(|i| i as u32 % ((1 << 31) - 1)).collect(); let blowup = 4; - + // CPU benchmark group.bench_with_input( BenchmarkId::new("CPU", format!("2^{}", log_size)), &coeffs, - |b, c| { - b.iter(|| { - cpu_backend.lde(black_box(c), black_box(blowup)).unwrap() - }) - }, + |b, c| b.iter(|| cpu_backend.lde(black_box(c), black_box(blowup)).unwrap()), ); - + // Metal benchmark (macOS only) if let Some(ref backend) = metal_backend { group.bench_with_input( BenchmarkId::new("Metal", format!("2^{}", log_size)), &coeffs, - |b, c| { - b.iter(|| { - backend.lde(black_box(c), black_box(blowup)).unwrap() - }) - }, + |b, c| b.iter(|| backend.lde(black_box(c), black_box(blowup)).unwrap()), ); } } - + group.finish(); } fn bench_gpu_merkle(c: &mut Criterion) { use zp1_prover::gpu::{get_backend_for_device, DeviceType}; - + let mut group = c.benchmark_group("GPU_Merkle"); - + let cpu_backend = get_backend_for_device(DeviceType::Cpu).unwrap(); - + #[cfg(target_os = "macos")] let metal_backend = get_backend_for_device(DeviceType::Metal).ok(); #[cfg(not(target_os = "macos"))] let metal_backend: Option> = None; - + for log_size in [10, 12, 14] { let size = 1 << log_size; let leaves: Vec<[u8; 32]> = (0..size) @@ -317,53 +285,45 @@ fn bench_gpu_merkle(c: &mut Criterion) { h }) .collect(); - + // CPU benchmark group.bench_with_input( BenchmarkId::new("CPU", format!("2^{}", log_size)), &leaves, - |b, l| { - b.iter(|| { - cpu_backend.merkle_tree(black_box(l)).unwrap() - }) - }, + |b, l| b.iter(|| cpu_backend.merkle_tree(black_box(l)).unwrap()), ); - + // Metal benchmark (macOS only) if let Some(ref backend) = metal_backend { group.bench_with_input( BenchmarkId::new("Metal", format!("2^{}", log_size)), &leaves, - |b, l| { - b.iter(|| { - backend.merkle_tree(black_box(l)).unwrap() - }) - }, + |b, l| b.iter(|| backend.merkle_tree(black_box(l)).unwrap()), ); } } - + group.finish(); } fn bench_gpu_batch_eval(c: &mut Criterion) { use zp1_prover::gpu::{get_backend_for_device, DeviceType}; - + let mut group = c.benchmark_group("GPU_BatchEval"); - + let cpu_backend = get_backend_for_device(DeviceType::Cpu).unwrap(); - + #[cfg(target_os = "macos")] let metal_backend = get_backend_for_device(DeviceType::Metal).ok(); #[cfg(not(target_os = "macos"))] let metal_backend: Option> = None; - + for log_degree in [8, 10, 12] { let degree = 1 << log_degree; let coeffs: Vec = (0..degree).map(|i| i as u32 % ((1 << 31) - 1)).collect(); let num_points = 1024; let points: Vec = (0..num_points).map(|i| i as u32).collect(); - + // CPU benchmark group.bench_with_input( BenchmarkId::new("CPU", format!("deg=2^{},pts=1024", log_degree)), @@ -371,11 +331,13 @@ fn bench_gpu_batch_eval(c: &mut Criterion) { |b, (c, p)| { let mut results = vec![0u32; num_points]; b.iter(|| { - cpu_backend.batch_evaluate(black_box(*c), black_box(*p), &mut results).unwrap() + cpu_backend + .batch_evaluate(black_box(*c), black_box(*p), &mut results) + .unwrap() }) }, ); - + // Metal benchmark (macOS only) if let Some(ref backend) = metal_backend { group.bench_with_input( @@ -384,13 +346,15 @@ fn bench_gpu_batch_eval(c: &mut Criterion) { |b, (c, p)| { let mut results = vec![0u32; num_points]; b.iter(|| { - backend.batch_evaluate(black_box(*c), black_box(*p), &mut results).unwrap() + backend + .batch_evaluate(black_box(*c), black_box(*p), &mut results) + .unwrap() }) }, ); } } - + group.finish(); } @@ -410,4 +374,3 @@ criterion_group!( bench_gpu_batch_eval, ); criterion_main!(benches); - diff --git a/crates/prover/examples/demo_benchmark.rs b/crates/prover/examples/demo_benchmark.rs index a4378f7..c26f707 100644 --- a/crates/prover/examples/demo_benchmark.rs +++ b/crates/prover/examples/demo_benchmark.rs @@ -1,5 +1,5 @@ //! ZP1 Prover Benchmark -//! +//! //! Compares sequential vs parallel proving performance. use std::time::Instant; @@ -13,7 +13,7 @@ fn main() { let log_trace_len = 10; // 1024 rows (use 8 for faster demo) let trace_len = 1 << log_trace_len; let num_cols = 77; - + let config = StarkConfig { log_trace_len, blowup_factor: 4, @@ -22,8 +22,11 @@ fn main() { security_bits: 80, entry_point: 0x1000, }; - - println!("Config: {} rows × {} cols, {}x blowup", trace_len, num_cols, config.blowup_factor); + + println!( + "Config: {} rows × {} cols, {}x blowup", + trace_len, num_cols, config.blowup_factor + ); // Generate trace with valid range-checked values let trace_columns: Vec> = (0..num_cols) @@ -39,16 +42,16 @@ fn main() { // Sequential let mut prover = StarkProver::new(config.clone()); prover.enable_range_checks(); - + let t0 = Instant::now(); let proof = prover.prove(trace_columns.clone(), &public_inputs); let seq_time = t0.elapsed(); - // Parallel + // Parallel let mut prover = StarkProver::new(config); prover.enable_range_checks(); prover.enable_parallel(); - + let t0 = Instant::now(); let _proof_par = prover.prove(trace_columns, &public_inputs); let par_time = t0.elapsed(); @@ -56,8 +59,12 @@ fn main() { // Results println!("\nSequential: {:?}", seq_time); println!("Parallel: {:?}", par_time); - println!("Speedup: {:.2}x", seq_time.as_secs_f64() / par_time.as_secs_f64()); - println!("\nProof: {} FRI layers, {} queries", + println!( + "Speedup: {:.2}x", + seq_time.as_secs_f64() / par_time.as_secs_f64() + ); + println!( + "\nProof: {} FRI layers, {} queries", proof.fri_proof.layer_commitments.len(), proof.query_proofs.len() ); diff --git a/crates/tests/src/encode.rs b/crates/tests/src/encode.rs index dc95115..db77d61 100644 --- a/crates/tests/src/encode.rs +++ b/crates/tests/src/encode.rs @@ -23,7 +23,14 @@ pub fn beq(rs1: u32, rs2: u32, offset: i32) -> u32 { let imm11 = (offset >> 11) & 1; let imm10_5 = (offset >> 5) & 0x3F; let imm4_1 = (offset >> 1) & 0xF; - (imm12 << 31) | (imm10_5 << 25) | (rs2 << 20) | (rs1 << 15) | (0b000 << 12) | (imm4_1 << 8) | (imm11 << 7) | 0b1100011 + (imm12 << 31) + | (imm10_5 << 25) + | (rs2 << 20) + | (rs1 << 15) + | (0b000 << 12) + | (imm4_1 << 8) + | (imm11 << 7) + | 0b1100011 } /// BNE rs1, rs2, offset - B-type encoding @@ -33,7 +40,14 @@ pub fn bne(rs1: u32, rs2: u32, offset: i32) -> u32 { let imm11 = (offset >> 11) & 1; let imm10_5 = (offset >> 5) & 0x3F; let imm4_1 = (offset >> 1) & 0xF; - (imm12 << 31) | (imm10_5 << 25) | (rs2 << 20) | (rs1 << 15) | (0b001 << 12) | (imm4_1 << 8) | (imm11 << 7) | 0b1100011 + (imm12 << 31) + | (imm10_5 << 25) + | (rs2 << 20) + | (rs1 << 15) + | (0b001 << 12) + | (imm4_1 << 8) + | (imm11 << 7) + | 0b1100011 } /// JAL rd, offset - J-type encoding @@ -65,7 +79,7 @@ mod tests { // ADDI x1, x0, 5 let instr = addi(1, 0, 5); assert_eq!(instr & 0x7F, 0b0010011); // opcode - assert_eq!((instr >> 7) & 0x1F, 1); // rd + assert_eq!((instr >> 7) & 0x1F, 1); // rd assert_eq!((instr >> 15) & 0x1F, 0); // rs1 assert_eq!((instr >> 20) & 0xFFF, 5); // imm } @@ -75,7 +89,7 @@ mod tests { // ADD x3, x1, x2 let instr = add(3, 1, 2); assert_eq!(instr & 0x7F, 0b0110011); // opcode - assert_eq!((instr >> 7) & 0x1F, 3); // rd + assert_eq!((instr >> 7) & 0x1F, 3); // rd assert_eq!((instr >> 15) & 0x1F, 1); // rs1 assert_eq!((instr >> 20) & 0x1F, 2); // rs2 } diff --git a/crates/tests/src/lib.rs b/crates/tests/src/lib.rs index 1811061..99e99f1 100644 --- a/crates/tests/src/lib.rs +++ b/crates/tests/src/lib.rs @@ -8,5 +8,5 @@ //! 5. Verify the proof pub mod encode; -pub mod programs; pub mod pipeline; +pub mod programs; diff --git a/crates/tests/src/pipeline.rs b/crates/tests/src/pipeline.rs index ad44f83..5e4c5ba 100644 --- a/crates/tests/src/pipeline.rs +++ b/crates/tests/src/pipeline.rs @@ -16,7 +16,8 @@ pub fn execute_and_trace(program: &[u8], max_steps: usize) -> TraceColumns { // Create CPU and load program let mut cpu = Cpu::new(); cpu.enable_tracing(); - cpu.load_program(0x1000, program).expect("Failed to load program"); + cpu.load_program(0x1000, program) + .expect("Failed to load program"); // Execute until halt or max steps for _ in 0..max_steps { @@ -72,7 +73,7 @@ mod tests { fn test_prove_simple_trace() { // Build a minimal trace (just a counting column) let trace_len = 16; // Small power of 2 - // Create 77 columns to satisfy CpuTraceRow::from_slice + // Create 77 columns to satisfy CpuTraceRow::from_slice let mut columns = vec![vec![M31::ZERO; trace_len]; 77]; // Fill first column with incrementing values @@ -95,14 +96,25 @@ mod tests { let proof = prover.prove(columns, &public_inputs); // Check proof structure - assert_ne!(proof.trace_commitment, [0u8; 32], "Trace commitment should be non-zero"); - assert_ne!(proof.composition_commitment, [0u8; 32], "Composition commitment should be non-zero"); - assert!(!proof.fri_proof.layer_commitments.is_empty(), "Should have FRI layers"); + assert_ne!( + proof.trace_commitment, [0u8; 32], + "Trace commitment should be non-zero" + ); + assert_ne!( + proof.composition_commitment, [0u8; 32], + "Composition commitment should be non-zero" + ); + assert!( + !proof.fri_proof.layer_commitments.is_empty(), + "Should have FRI layers" + ); assert_eq!(proof.query_proofs.len(), 10, "Should have 10 query proofs"); - println!("Generated proof with {} FRI layers, {} queries", - proof.fri_proof.layer_commitments.len(), - proof.query_proofs.len()); + println!( + "Generated proof with {} FRI layers, {} queries", + proof.fri_proof.layer_commitments.len(), + proof.query_proofs.len() + ); } #[test] @@ -151,8 +163,14 @@ mod tests { assert_eq!(proof.query_proofs.len(), 15); println!("Full pipeline test passed!"); - println!(" Trace commitment: {:02x?}...", &proof.trace_commitment[..4]); - println!(" Composition commitment: {:02x?}...", &proof.composition_commitment[..4]); + println!( + " Trace commitment: {:02x?}...", + &proof.trace_commitment[..4] + ); + println!( + " Composition commitment: {:02x?}...", + &proof.composition_commitment[..4] + ); println!(" FRI layers: {}", proof.fri_proof.layer_commitments.len()); println!(" Query proofs: {}", proof.query_proofs.len()); } @@ -184,8 +202,8 @@ mod tests { #[test] fn test_fri_folding() { - use zp1_prover::fri::{FriConfig, FriProver}; use zp1_prover::channel::ProverChannel; + use zp1_prover::fri::{FriConfig, FriProver}; // Create polynomial evaluations let n = 32; @@ -206,12 +224,17 @@ mod tests { // Check we got layers assert!(!layers.is_empty(), "Should have FRI layers"); - assert!(!proof.layer_commitments.is_empty(), "Should have commitments"); + assert!( + !proof.layer_commitments.is_empty(), + "Should have commitments" + ); assert!(!proof.final_poly.is_empty(), "Should have final polynomial"); - println!("FRI produced {} layers, final poly degree {}", - layers.len(), - proof.final_poly.len() - 1); + println!( + "FRI produced {} layers, final poly degree {}", + layers.len(), + proof.final_poly.len() - 1 + ); } #[test] @@ -254,7 +277,7 @@ mod tests { println!("Circle FFT basic test: domain size = {}", domain.size); println!("FFT created with log_size = {}", log_size); assert!(coeffs.len() == 16); - + // The FFT struct exists and can be created drop(fft); // Just verify construction works } @@ -284,7 +307,10 @@ mod tests { let proof = prover.prove(columns, &public_inputs); assert_ne!(proof.trace_commitment, [0u8; 32]); - println!("Large trace (2^{} = {} rows) proved successfully!", log_size, trace_len); + println!( + "Large trace (2^{} = {} rows) proved successfully!", + log_size, trace_len + ); println!(" {} FRI layers", proof.fri_proof.layer_commitments.len()); println!(" {} query proofs", proof.query_proofs.len()); } @@ -308,7 +334,10 @@ mod tests { let padded_len = trace_len.next_power_of_two(); let log_trace_len = padded_len.trailing_zeros() as usize; - println!("Fibonacci trace: {} rows (padded to {})", trace_len, padded_len); + println!( + "Fibonacci trace: {} rows (padded to {})", + trace_len, padded_len + ); // 3. Configure prover with appropriate size let config = StarkConfig { @@ -333,7 +362,7 @@ mod tests { // 5. Verify proof structure assert_ne!(proof.trace_commitment, [0u8; 32]); assert!(!proof.fri_proof.layer_commitments.is_empty()); - + println!("Fibonacci pipeline test passed!"); println!(" Commitment: {:02x?}...", &proof.trace_commitment[..4]); } diff --git a/crates/tests/src/programs.rs b/crates/tests/src/programs.rs index ea7dc46..739e2ef 100644 --- a/crates/tests/src/programs.rs +++ b/crates/tests/src/programs.rs @@ -15,11 +15,11 @@ use crate::encode; /// ``` pub fn counting_program() -> Vec { vec![ - encode::addi(1, 0, 0), // x1 = 0 - encode::addi(2, 0, 5), // x2 = 5 - encode::addi(1, 1, 1), // x1 += 1 (loop body) - encode::bne(1, 2, -4), // if x1 != x2, jump back 4 bytes - encode::ecall(), // halt + encode::addi(1, 0, 0), // x1 = 0 + encode::addi(2, 0, 5), // x2 = 5 + encode::addi(1, 1, 1), // x1 += 1 (loop body) + encode::bne(1, 2, -4), // if x1 != x2, jump back 4 bytes + encode::ecall(), // halt ] } @@ -40,26 +40,26 @@ pub fn counting_program() -> Vec { /// ``` pub fn fibonacci_program() -> Vec { vec![ - encode::addi(1, 0, 0), // x1 = 0 (fib_prev) - encode::addi(2, 0, 1), // x2 = 1 (fib_curr) - encode::addi(3, 0, 6), // x3 = 6 iterations - encode::add(4, 1, 2), // x4 = x1 + x2 - encode::add(1, 2, 0), // x1 = x2 (shift) - encode::add(2, 4, 0), // x2 = x4 (shift) - encode::addi(3, 3, -1), // x3 -= 1 - encode::bne(3, 0, -16), // if x3 != 0, loop back 16 bytes - encode::ecall(), // halt + encode::addi(1, 0, 0), // x1 = 0 (fib_prev) + encode::addi(2, 0, 1), // x2 = 1 (fib_curr) + encode::addi(3, 0, 6), // x3 = 6 iterations + encode::add(4, 1, 2), // x4 = x1 + x2 + encode::add(1, 2, 0), // x1 = x2 (shift) + encode::add(2, 4, 0), // x2 = x4 (shift) + encode::addi(3, 3, -1), // x3 -= 1 + encode::bne(3, 0, -16), // if x3 != 0, loop back 16 bytes + encode::ecall(), // halt ] } /// Simple arithmetic program. pub fn arithmetic_program() -> Vec { vec![ - encode::addi(1, 0, 10), // x1 = 10 - encode::addi(2, 0, 20), // x2 = 20 - encode::add(3, 1, 2), // x3 = x1 + x2 = 30 - encode::sub(4, 2, 1), // x4 = x2 - x1 = 10 - encode::ecall(), // halt + encode::addi(1, 0, 10), // x1 = 10 + encode::addi(2, 0, 20), // x2 = 20 + encode::add(3, 1, 2), // x3 = x1 + x2 = 30 + encode::sub(4, 2, 1), // x4 = x2 - x1 = 10 + encode::ecall(), // halt ] }