lc3_ensemble::sim

Struct Simulator

source
pub struct Simulator {
    pub mem: MemArray,
    pub reg_file: RegFile,
    pub pc: u16,
    pub frame_stack: FrameStack,
    pub instructions_run: u64,
    pub observer: ChangeObserver,
    pub flags: SimFlags,
    pub breakpoints: HashSet<Breakpoint>,
    pub device_handler: DeviceHandler,
    /* private fields */
}
Expand description

Executes assembled code.

Fields§

§mem: MemArray

The simulator’s memory.

Note that this is held in the heap, as it is too large for the stack.

§reg_file: RegFile

The simulator’s register file.

§pc: u16

The program counter.

§frame_stack: FrameStack

The frame stack.

§instructions_run: u64

The number of instructions successfully run since this Simulator was initialized.

This can be set to 0 to reset the counter.

§observer: ChangeObserver

Tracks changes in simulator state.

§flags: SimFlags

Configuration settings for the simulator.

These are preserved between resets.

See SimFlags for more details on what configuration settings are available.

§breakpoints: HashSet<Breakpoint>

Breakpoints for the simulator.

§device_handler: DeviceHandler

All external devices connected to the system (IO and interrupting devices).

Implementations§

source§

impl Simulator

source

pub fn new(flags: SimFlags) -> Self

Creates a new simulator with the provided initializers and with the OS loaded, but without a loaded object file.

source

pub fn reset(&mut self)

Resets the simulator.

This resets the state of the Simulator back to before any execution calls, while preserving configuration and debug state.

Note that this function preserves:

  • Flags
  • Breakpoints
  • External interrupts
  • MCR reference (i.e., anything with access to the Simulator’s MCR can still control it)
  • IO (however, note that it does not reset IO state, which must be manually reset)

This also does not reload object files. Any object file data has to be reloaded into the Simulator.

source

pub fn read_mem(&mut self, addr: u16, ctx: MemAccessCtx) -> Result<Word, SimErr>

Fallibly reads the word at the provided index, erroring if not possible.

This accepts a MemAccessCtx, that describes the parameters of the memory access. The simulator provides a default MemAccessCtx under Simulator::default_mem_ctx.

The flags are used as follows:

  • privileged: if false, this access errors if the address is a memory location outside of the user range.
  • strict: not used for read

Note that this method is used for simulating a read to memory-mapped IO. If you would like to query the memory’s state, consider using index on MemArray.

source

pub fn write_mem( &mut self, addr: u16, data: Word, ctx: MemAccessCtx, ) -> Result<(), SimErr>

Fallibly writes the word at the provided index, erroring if not possible.

This accepts a MemAccessCtx, that describes the parameters of the memory access. The simulator provides a default MemAccessCtx under Simulator::default_mem_ctx.

The flags are used as follows:

  • privileged: if false, this access errors if the address is a memory location outside of the user range.
  • strict: If true, all accesses that would cause a memory location to be set with uninitialized data causes an error.

Note that this method is used for simulating a write to memory-mapped IO. If you would like to edit the memory’s state, consider using index_mut on MemArray.

source

pub fn load_obj_file(&mut self, obj: &ObjectFile)

Loads an object file into this simulator.

source

pub fn psr(&self) -> &PSR

Gets a reference to the PSR.

source

pub fn mcr(&self) -> &MCR

Gets a reference to the MCR.

source

pub fn prefetch_pc(&self) -> u16

Gets the value of the prefetch PC.

This function is useful as it returns the location of the currently executing instruction in memory.

source

pub fn hit_breakpoint(&self) -> bool

Indicates whether the last execution of the simulator hit a breakpoint.

source

pub fn hit_halt(&self) -> bool

Indicates whether the last execution of the simulator resulted in a HALT successfully occurring.

This is defined as:

  • HALT being executed while virtual HALTs are enabled
  • MCR being set to x0000 during the execution of the program.
source

pub fn default_mem_ctx(&self) -> MemAccessCtx

Computes the default memory access context, which are the default flags to use (see Simulator::read_mem and Simulator::write_mem).

source

pub fn call_subroutine(&mut self, addr: u16) -> Result<(), SimErr>

Calls a subroutine.

This does all the steps for calling a subroutine, namely:

  • Setting the PC to the subroutine’s start address
  • Setting R7 to the original PC (return address)
  • Adding information to the frame stack
source

pub fn run_while( &mut self, tripwire: impl FnMut(&mut Simulator) -> bool, ) -> Result<(), SimErr>

Runs until the tripwire condition returns false (or any of the typical breaks occur).

The typical break conditions are:

  • HALT is executed
  • the MCR is set to false
  • A breakpoint matches
source

pub fn run(&mut self) -> Result<(), SimErr>

Execute the program.

This blocks until the program ends. If you would like to limit the maximum number of steps to execute, consider Simulator::run_with_limit.

source

pub fn run_with_limit(&mut self, max_steps: u64) -> Result<(), SimErr>

Execute the program with a limit on how many steps to execute.

This blocks until the program ends or until the number of steps to execute has been hit.

source

pub fn step_in(&mut self) -> Result<(), SimErr>

Simulate one step, executing one instruction.

source

pub fn step_over(&mut self) -> Result<(), SimErr>

Simulate one step, executing one instruction and running through entire subroutines as a single step.

source

pub fn step_out(&mut self) -> Result<(), SimErr>

Run through the simulator’s execution until the subroutine is exited.

Trait Implementations§

source§

impl Debug for Simulator

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
source§

impl Default for Simulator

source§

fn default() -> Self

Returns the “default value” for a type. Read more

Auto Trait Implementations§

Blanket Implementations§

source§

impl<T> Any for T
where T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

source§

impl<T, U> Into<U> for T
where U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

source§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
source§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

source§

fn vzip(self) -> V