Skip to content

Commit

Permalink
test: add Emulator::print_trace option to print the current stack
Browse files Browse the repository at this point in the history
and memory contents (only written to) on every step of the execution.
  • Loading branch information
greenhat committed Jul 9, 2024
1 parent e42373f commit 79d1c24
Show file tree
Hide file tree
Showing 4 changed files with 104 additions and 8 deletions.
59 changes: 59 additions & 0 deletions codegen/masm/src/emulator/memory.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
use std::{
fmt::Debug,
ops::{Index, IndexMut},
};

use miden_core::FieldElement;
use midenc_hir::Felt;
use rustc_hash::FxHashSet;

const EMPTY_WORD: [Felt; 4] = [Felt::ZERO; 4];

pub struct Memory {
memory: Vec<[Felt; 4]>,
set_memory_addrs: FxHashSet<usize>,
}

impl Memory {
pub fn new(memory_size: usize) -> Self {
Self {
memory: vec![EMPTY_WORD; memory_size],
set_memory_addrs: Default::default(),
}
}

pub fn len(&self) -> usize {
self.memory.len()
}

pub fn reset(&mut self) {
for addr in self.set_memory_addrs.iter() {
self.memory[*addr] = EMPTY_WORD;
}
self.set_memory_addrs = Default::default();
}
}

impl Index<usize> for Memory {
type Output = [Felt; 4];

fn index(&self, index: usize) -> &Self::Output {
&self.memory[index]
}
}

impl IndexMut<usize> for Memory {
fn index_mut(&mut self, index: usize) -> &mut Self::Output {
self.set_memory_addrs.insert(index);
&mut self.memory[index]
}
}

impl Debug for Memory {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
for addr in self.set_memory_addrs.iter() {
write!(f, "{}: {:?}, ", addr, self[*addr])?;
}
Ok(())
}
}
32 changes: 25 additions & 7 deletions codegen/masm/src/emulator/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,11 @@ mod breakpoints;
mod debug;
mod events;
mod functions;
mod memory;

use std::{cell::RefCell, cmp, rc::Rc, sync::Arc};

use memory::Memory;
use miden_assembly::{ast::ProcedureName, LibraryNamespace};
use midenc_hir::{
assert_matches, Felt, FieldElement, FunctionIdent, Ident, OperandStack, Stack, Symbol,
Expand Down Expand Up @@ -120,7 +122,7 @@ pub struct Emulator {
locals: FxHashMap<FunctionIdent, Addr>,
modules_loaded: FxHashMap<Ident, Arc<Module>>,
modules_pending: FxHashSet<Ident>,
memory: Vec<[Felt; 4]>,
memory: Memory,
stack: OperandStack<Felt>,
advice_stack: OperandStack<Felt>,
callstack: Vec<Activation>,
Expand All @@ -133,26 +135,31 @@ pub struct Emulator {
clk: usize,
clk_limit: usize,
entrypoint: Option<FunctionIdent>,
print_trace: bool,
}
impl Default for Emulator {
fn default() -> Self {
Self::new(Self::DEFAULT_HEAP_SIZE, Self::DEFAULT_HEAP_START, Self::DEFAULT_LOCALS_START)
Self::new(
Self::DEFAULT_HEAP_SIZE,
Self::DEFAULT_HEAP_START,
Self::DEFAULT_LOCALS_START,
false,
)
}
}
impl Emulator {
pub const DEFAULT_HEAP_SIZE: u32 = (4 * Self::PAGE_SIZE) / 16;
pub const DEFAULT_HEAP_START: u32 = (2 * Self::PAGE_SIZE) / 16;
pub const DEFAULT_LOCALS_START: u32 = (3 * Self::PAGE_SIZE) / 16;
const EMPTY_WORD: [Felt; 4] = [Felt::ZERO; 4];
const PAGE_SIZE: u32 = 64 * 1024;

/// Construct a new, empty emulator with:
///
/// * A linear memory heap of `memory_size` words
/// * The start of the usable heap set to `hp` (an address in words)
/// * The start of the reserved heap used for locals set to `lp` (an address in words)
pub fn new(memory_size: u32, hp: u32, lp: u32) -> Self {
let memory = vec![Self::EMPTY_WORD; memory_size as usize];
pub fn new(memory_size: u32, hp: u32, lp: u32, print_stack: bool) -> Self {
let memory = Memory::new(memory_size as usize);
Self {
status: Status::Init,
functions: Default::default(),
Expand All @@ -172,6 +179,7 @@ impl Emulator {
clk: 0,
clk_limit: usize::MAX,
entrypoint: None,
print_trace: print_stack,
}
}

Expand Down Expand Up @@ -572,7 +580,7 @@ impl Emulator {
pub fn stop(&mut self) {
self.callstack.clear();
self.stack.clear();
self.memory = vec![Self::EMPTY_WORD; self.memory.len()];
self.memory.reset();
self.hp = self.hp_start;
self.lp = self.lp_start;
self.step_over = None;
Expand Down Expand Up @@ -888,7 +896,12 @@ macro_rules! peek_u32 {
macro_rules! pop_addr {
($emu:ident) => {{
let addr = pop_u32!($emu, "expected valid 32-bit address, got {}") as usize;
assert!(addr < $emu.memory.len(), "out of bounds memory access");
assert!(
addr < $emu.memory.len(),
"out of bounds memory access, addr: {}, available memory: {}",
addr,
$emu.memory.len()
);
addr
}};
}
Expand Down Expand Up @@ -1242,6 +1255,11 @@ impl Emulator {
// control flow effect occurred to reach it
let ix_with_op = state.next();
if let Some(ix_with_op) = ix_with_op {
if self.print_trace {
eprintln!("stk: {}", self.stack.debug().pretty());
eprintln!("mem: {:?}", self.memory);
eprintln!("op>: {:?}", ix_with_op.op);
}
match ix_with_op.op {
Op::Padw => {
self.stack.padw();
Expand Down
8 changes: 7 additions & 1 deletion codegen/masm/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,13 +36,19 @@ struct TestByEmulationHarness {
}
#[allow(unused)]
impl TestByEmulationHarness {
pub fn with_emulator_config(memory_size: usize, hp: usize, lp: usize) -> Self {
pub fn with_emulator_config(
memory_size: usize,
hp: usize,
lp: usize,
print_stack: bool,
) -> Self {
let mut harness = Self {
context: TestContext::default(),
emulator: Emulator::new(
memory_size.try_into().expect("invalid memory size"),
hp.try_into().expect("invalid address"),
lp.try_into().expect("invalid address"),
print_stack,
),
};
harness.set_cycle_budget(2000);
Expand Down
13 changes: 13 additions & 0 deletions hir/src/asm/stack.rs
Original file line number Diff line number Diff line change
Expand Up @@ -458,6 +458,19 @@ impl<'a, E: StackElement, T: ?Sized + Stack<Element = E>> DebugStack<'a, T> {
self.limit = Some(n);
self
}

pub fn pretty(&self) -> String {
let mut s = String::new();
for (i, value) in self.stack.stack().iter().rev().enumerate() {
if let Some(limit) = self.limit {
if i >= limit {
break;
}
}
s.push_str(&format!("{:?} ", value.debug()));
}
s
}
}
impl<'a, E: StackElement, T: ?Sized + Stack<Element = E>> fmt::Debug for DebugStack<'a, T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
Expand Down

0 comments on commit 79d1c24

Please sign in to comment.