pub struct BabyModel {
    pub main_store: [i32; 32],
    pub accumulator: i32,
    pub instruction_address: u16,
    pub instruction: u16,
}
Expand description

The model containing the data in all the registers and memory to be operated upon.

Fields§

§main_store: [i32; 32]

The memory (RAM), this is just 32 words of 32 bits, originally famously stored on a Williams Tube.

§accumulator: i32

The register where all mathematical results are stored (negations and subtractions).

§instruction_address: u16

The memory address of the instruction currently being executed (program counter).

§instruction: u16

The 16 bit instruction being executed (instruction register).

Implementations§

source§

impl BabyModel

source

pub fn new() -> BabyModel

Creates a new model with all zeros.

source

pub fn new_with_program(main_store: [i32; 32]) -> BabyModel

Creates a new model with a specified memory.

Initialised as to start executing at the start of the memory, specified memory can contain program code to be executed.

§Parameters
  • main_store - The custom memory to be initialised with.
source

pub fn new_example_program() -> BabyModel

Creates a new model with an example program loaded into memory.

This program will add 5 to 5, storing the result in the accumulator and end.

§Example
use baby_emulator::core::BabyModel;
 
let mut model = BabyModel::new_example_program();
loop {
    model = match model.execute() {
        Ok(m) => m,
        Err(_) => break
    }
}
println!("{}", model.core_dump());
source

pub fn execute(&self) -> InstrResult

Executes the instruction in the instruction register.

Decodes the instruction value in the instruction register and performs the relevant operation on the data within the model, will return all the updated data in a new [Ok(BabyModel)] assuming no errors encountered.

§Returns
  • Ok(BabyModel): A new model instance with all data updated as per the instruction, loaded with the next instruction.
  • Err(BabyErrors): An enum detailing errors encountered when executing the instruction.
§Example
use baby_emulator::core::BabyModel;
 
let mut model = BabyModel::new_example_program();
loop {
    model = match model.execute() {
        Ok(m) => m,
        Err(_) => break
    }
}
println!("{}", model.core_dump());
source

pub fn decode_instruction(&self) -> (i32, BabyInstruction)

Decodes the instruction in BabyModel.instruction from the numeric value to BabyInstruction and the i32 value pointed to by the instruction operand.

source

pub fn run_loop(&self, max_iter: usize) -> (BabyModel, BabyErrors)

Executes the instructions in memory until an error is thrown or a limmit is hit.

Kepps calling BabyModel::execute on each sucesssive iteration until either an error is thrown (such as BabyErrors::Stop) or the number of iterations hits the max_iter value.

Returns a tuple of the model in its final state plus the error thrown, error will be BabyErrors::IterationExceeded if iterations exceeded.

§Parameters
  • max_iter - The maximum number of iterations of executing successive instructions.
§Example
use baby_emulator::core::BabyModel;
use baby_emulator::core::errors::BabyErrors;
use baby_emulator::core::errors::BabyError;
 
let model = BabyModel::new_example_program();
match model.run_loop(100) {
    (model, BabyErrors::Stop(_)) => println!("{}", model.core_dump()),
    (_, err) => println!("{}", err.get_descriptor())
}
source

pub fn dispatch_instruction( &self, instruction: BabyInstruction, operand_value: i32 ) -> InstrResult

Takes a BabyInstruction and a dereferenced operand value i32 and calls the correct instruction method.

Returns the result of the method call, if BabyInstruction::Stop is will return BabyErrors::Stop.

§Parameters
  • instruction - The instruction to execute.
  • operand_value - The value from memory referenced by the actual operand.
source

pub fn jump(&self, address: i32) -> BabyModel

Carries out a jump to a specified address.

Will update the BabyModel.instruction_address least significant 5 bits to the last significant 5 bits of address, means jumping cannot be indexed outside of the memory, program execution will then proceed from this address.

§Parameters
  • address - The memory address to jump to.
source

pub fn relative_jump(&self, offset: i32) -> BabyModel

Carries out a jump to the instruction address plus an offset.

This will add the BabyModel.instruction_address to the offset, then set the BabyModel.instruction_address equal to the least significant 5 bits of the result, this allows the jump to “loop” back to the start of the memory, program execution will then proceed from this address.

§Parameters
  • offset - The value to offset the BabyModel.instruction_address to.
source

pub fn negate(&self, value: i32) -> BabyModel

Negates a value and stores it into the accumulator.

Negates (adds or removes the “-”) the specified value and stores it in the accumulator, returning the updated model.

Adds 1 to the BabyModel.instruction_address and keeps only the least significant 5 bits as to only index within the allocated memory.

§Parameters
  • value - The value to negate.
source

pub fn store(&self, address: i32) -> BabyModel

Stores the accumulator at a specified address in memory.

Takes the least significant 5 bits of address uses this to index into the memory, as to not index outside of the memory and stores the value in BabyModel.accumulator.

Adds 1 to the BabyModel.instruction_address and keeps only the least significant 5 bits as to only index within the allocated memory.

§Parameters
  • address - The address to store the accumulator to.
source

pub fn subtract(&self, value: i32) -> BabyModel

Subtracts the specified value from the accumulator.

Subtracts the specified value from the accumulator, storing the result back to the accumulator.

Adds 1 to the BabyModel.instruction_address and keeps only the least significant 5 bits as to only index within the allocated memory, using this to get the next instruction from the memory and storing it in BabyModel.instruction register.

§Parameters
  • value - The value to subtract from the accumulator.
source

pub fn test(&self) -> BabyModel

Skips the next instruction address if the accumulator is negative.

Adds 1 to the BabyModel.instruction_address if the BabyModel.accumulator is not negative and 2 if it is and keeps only the least significant 5 bits as to only index within the allocated memory, using this to get the next instruction from the memory and storing it in BabyModel.instruction register.

§Parameters
  • value - The value to subtract from the accumulator.
source

pub fn core_dump(&self) -> String

Generates a string representation of current state of the model.

Generates a formatted string representation of all the registers and memory addresses in the model, able to be printed to the console.

§Example
use baby_emulator::core::BabyModel;
use baby_emulator::core::errors::BabyErrors;
use baby_emulator::core::errors::BabyError;
 
let model = BabyModel::new_example_program();
match model.run_loop(100) {
    (model, BabyErrors::Stop(_)) => println!("{}", model.core_dump()),
    (_, err) => println!("{}", err.get_descriptor())
}

Trait Implementations§

source§

impl Clone for BabyModel

source§

fn clone(&self) -> BabyModel

Returns a copy of the value. Read more
1.0.0 · source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
source§

impl Debug for BabyModel

source§

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

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

impl PartialEq for BabyModel

source§

fn eq(&self, other: &BabyModel) -> bool

This method tests for self and other values to be equal, and is used by ==.
1.0.0 · source§

fn ne(&self, other: &Rhs) -> bool

This method tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.
source§

impl StructuralPartialEq for BabyModel

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> ToOwned for T
where T: Clone,

§

type Owned = T

The resulting type after obtaining ownership.
source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
source§

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

§

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>,

§

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.