Introduced comments to some files
Improved accuracy and test of the Intel 4001 ROM. Tests currently fail on the 4001.
This commit is contained in:
parent
cff459d2b5
commit
5bc1916b2f
3 changed files with 1420 additions and 172 deletions
|
|
@ -8,17 +8,45 @@ use std::time::Duration;
|
||||||
|
|
||||||
use crate::pin::Pin;
|
use crate::pin::Pin;
|
||||||
|
|
||||||
// Component is now inherently thread-safe
|
/// Core trait for all hardware components in the emulator
|
||||||
|
/// Provides the fundamental interface that all components must implement
|
||||||
|
/// Components are inherently thread-safe and can be used across thread boundaries
|
||||||
pub trait Component: Send + Sync {
|
pub trait Component: Send + Sync {
|
||||||
|
/// Get the name/identifier of this component
|
||||||
|
/// Returns: Component name as a String
|
||||||
fn name(&self) -> String;
|
fn name(&self) -> String;
|
||||||
|
|
||||||
|
/// Get all pins associated with this component
|
||||||
|
/// Returns: HashMap mapping pin names to pin objects
|
||||||
fn pins(&self) -> HashMap<String, Arc<Mutex<Pin>>>;
|
fn pins(&self) -> HashMap<String, Arc<Mutex<Pin>>>;
|
||||||
|
|
||||||
|
/// Get a specific pin by name
|
||||||
|
/// Parameters: name - The name of the pin to retrieve
|
||||||
|
/// Returns: Ok(pin) if found, Err(String) if pin not found
|
||||||
fn get_pin(&self, name: &str) -> Result<Arc<Mutex<Pin>>, String>;
|
fn get_pin(&self, name: &str) -> Result<Arc<Mutex<Pin>>, String>;
|
||||||
|
|
||||||
|
/// Update the component state for one simulation cycle
|
||||||
|
/// This method is called repeatedly during component execution
|
||||||
fn update(&mut self);
|
fn update(&mut self);
|
||||||
|
|
||||||
|
/// Run the component in a continuous loop until stopped
|
||||||
|
/// This method blocks until the component is stopped
|
||||||
fn run(&mut self);
|
fn run(&mut self);
|
||||||
|
|
||||||
|
/// Stop the component and clean up resources
|
||||||
|
/// This method should tri-state all outputs and prepare for shutdown
|
||||||
fn stop(&mut self);
|
fn stop(&mut self);
|
||||||
|
|
||||||
|
/// Check if the component is currently running
|
||||||
|
/// Returns: true if component is running, false otherwise
|
||||||
fn is_running(&self) -> bool;
|
fn is_running(&self) -> bool;
|
||||||
}
|
}
|
||||||
|
/// Extended trait for components that can be run in their own threads
|
||||||
|
/// Provides automatic thread spawning functionality for components
|
||||||
pub trait RunnableComponent: Component + Send + 'static {
|
pub trait RunnableComponent: Component + Send + 'static {
|
||||||
|
/// Spawn the component in its own thread
|
||||||
|
/// Parameters: self - The component to spawn (consumed by the thread)
|
||||||
|
/// Returns: JoinHandle for the spawned thread
|
||||||
fn spawn_in_thread(mut self) -> thread::JoinHandle<()>
|
fn spawn_in_thread(mut self) -> thread::JoinHandle<()>
|
||||||
where
|
where
|
||||||
Self: Sized,
|
Self: Sized,
|
||||||
|
|
@ -28,7 +56,9 @@ pub trait RunnableComponent: Component + Send + 'static {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// BaseComponent uses AtomicBool for thread-safe state
|
/// Base implementation of the Component trait providing common functionality
|
||||||
|
/// Handles thread-safe state management and basic pin operations
|
||||||
|
/// Most hardware components should embed this struct to inherit common behavior
|
||||||
pub struct BaseComponent {
|
pub struct BaseComponent {
|
||||||
name: String,
|
name: String,
|
||||||
pins: HashMap<String, Arc<Mutex<Pin>>>,
|
pins: HashMap<String, Arc<Mutex<Pin>>>,
|
||||||
|
|
@ -36,6 +66,9 @@ pub struct BaseComponent {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl BaseComponent {
|
impl BaseComponent {
|
||||||
|
/// Create a new BaseComponent with the specified name and pins
|
||||||
|
/// Parameters: name - Component identifier, pins - Pin mapping for the component
|
||||||
|
/// Returns: New BaseComponent instance
|
||||||
pub fn new(name: String, pins: HashMap<String, Arc<Mutex<Pin>>>) -> Self {
|
pub fn new(name: String, pins: HashMap<String, Arc<Mutex<Pin>>>) -> Self {
|
||||||
BaseComponent {
|
BaseComponent {
|
||||||
name,
|
name,
|
||||||
|
|
@ -44,18 +77,27 @@ impl BaseComponent {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Get the name of this component
|
||||||
|
/// Returns: Component name as string slice
|
||||||
pub fn get_name(&self) -> &str {
|
pub fn get_name(&self) -> &str {
|
||||||
&self.name
|
&self.name
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Check if the component is currently running
|
||||||
|
/// Returns: true if running, false otherwise
|
||||||
pub fn is_running(&self) -> bool {
|
pub fn is_running(&self) -> bool {
|
||||||
self.running.load(Ordering::SeqCst)
|
self.running.load(Ordering::SeqCst)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Set the running state of the component
|
||||||
|
/// Parameters: running - New running state
|
||||||
pub fn set_running(&self, running: bool) {
|
pub fn set_running(&self, running: bool) {
|
||||||
self.running.store(running, Ordering::SeqCst);
|
self.running.store(running, Ordering::SeqCst);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Create a pin mapping from a list of pin names
|
||||||
|
/// Parameters: pin_names - List of pin name strings, component_name - Name of the component
|
||||||
|
/// Returns: HashMap mapping pin names to Pin objects with proper naming
|
||||||
pub fn create_pin_map(
|
pub fn create_pin_map(
|
||||||
pin_names: &[&str],
|
pin_names: &[&str],
|
||||||
component_name: &str,
|
component_name: &str,
|
||||||
|
|
@ -90,10 +132,14 @@ impl Component for BaseComponent {
|
||||||
.ok_or_else(|| format!("Pin {} not found", name))
|
.ok_or_else(|| format!("Pin {} not found", name))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Update the component state for one simulation cycle
|
||||||
|
/// Base implementation does nothing - should be overridden by specific components
|
||||||
fn update(&mut self) {
|
fn update(&mut self) {
|
||||||
// Base implementation does nothing
|
// Base implementation does nothing
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Run the component in a continuous loop until stopped
|
||||||
|
/// Provides a default time-sliced execution model with 10 microsecond delays
|
||||||
fn run(&mut self) {
|
fn run(&mut self) {
|
||||||
self.set_running(true);
|
self.set_running(true);
|
||||||
while self.is_running() {
|
while self.is_running() {
|
||||||
|
|
@ -102,6 +148,8 @@ impl Component for BaseComponent {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Stop the component and clean up resources
|
||||||
|
/// Sets running state to false to exit the run loop
|
||||||
fn stop(&mut self) {
|
fn stop(&mut self) {
|
||||||
self.set_running(false);
|
self.set_running(false);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -7,41 +7,51 @@ use crate::component::{BaseComponent, Component, RunnableComponent};
|
||||||
use crate::pin::{Pin, PinValue};
|
use crate::pin::{Pin, PinValue};
|
||||||
use crate::types::U12;
|
use crate::types::U12;
|
||||||
|
|
||||||
|
/// Represents the current phase of instruction execution
|
||||||
|
/// The 4004 CPU processes instructions in distinct phases synchronized with the clock
|
||||||
#[derive(Debug, Clone, Copy, PartialEq)]
|
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||||
enum InstructionPhase {
|
enum InstructionPhase {
|
||||||
Fetch,
|
Fetch, // Fetching instruction from memory
|
||||||
Address,
|
Address, // Calculating or fetching address
|
||||||
Execute,
|
Execute, // Executing the instruction
|
||||||
Wait,
|
Wait, // Waiting for external operations
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Represents the current phase of the two-phase clock cycle
|
||||||
|
/// The 4004 uses a two-phase clock for synchronization with peripherals
|
||||||
#[derive(Debug, Clone, Copy, PartialEq)]
|
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||||
enum ClockPhase {
|
enum ClockPhase {
|
||||||
Phase1,
|
Phase1, // First clock phase - CPU drives bus
|
||||||
Phase2,
|
Phase2, // Second clock phase - Peripherals drive bus
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Intel 4004 4-bit microprocessor implementation
|
||||||
|
/// The world's first microprocessor, featuring 4-bit data bus, 12-bit addressing,
|
||||||
|
/// 46 instructions, and 16 index registers. Part of the MCS-4 family.
|
||||||
pub struct Intel4004 {
|
pub struct Intel4004 {
|
||||||
base: BaseComponent,
|
base: BaseComponent,
|
||||||
accumulator: u8,
|
accumulator: u8, // Main accumulator register (4-bit)
|
||||||
carry: bool,
|
carry: bool, // Carry flag for arithmetic operations
|
||||||
index_registers: [u8; 16],
|
index_registers: [u8; 16], // 16 4-bit index registers (R0-R15)
|
||||||
pub(crate) program_counter: U12,
|
pub(crate) program_counter: U12, // 12-bit program counter
|
||||||
stack: [U12; 3],
|
stack: [U12; 3], // 3-level 12-bit address stack
|
||||||
stack_pointer: u8,
|
stack_pointer: u8, // Stack pointer (0-2)
|
||||||
cycle_count: u64,
|
cycle_count: u64, // Total number of clock cycles executed
|
||||||
instruction_phase: InstructionPhase,
|
instruction_phase: InstructionPhase, // Current instruction execution phase
|
||||||
current_instruction: u8,
|
current_instruction: u8, // Currently executing instruction
|
||||||
address_latch: u8,
|
address_latch: u8, // Latched address for memory operations
|
||||||
data_latch: u8,
|
data_latch: u8, // Latched data for memory operations
|
||||||
clock_speed: f64,
|
clock_speed: f64, // Target clock speed in Hz
|
||||||
last_clock_transition: Instant,
|
last_clock_transition: Instant, // Timestamp of last clock transition
|
||||||
clock_phase: ClockPhase,
|
clock_phase: ClockPhase, // Current clock phase
|
||||||
rom_port: u8,
|
rom_port: u8, // Currently selected ROM port (0-15)
|
||||||
ram_bank: u8,
|
ram_bank: u8, // Currently selected RAM bank (0-7)
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Intel4004 {
|
impl Intel4004 {
|
||||||
|
/// Create a new Intel 4004 CPU instance
|
||||||
|
/// Parameters: name - Component identifier, clock_speed - Target clock frequency in Hz
|
||||||
|
/// Returns: New Intel4004 instance with initialized state
|
||||||
pub fn new(name: String, clock_speed: f64) -> Self {
|
pub fn new(name: String, clock_speed: f64) -> Self {
|
||||||
let pin_names = vec![
|
let pin_names = vec![
|
||||||
"D0", "D1", "D2", "D3", "SYNC", "CM_ROM", "CM_RAM", "TEST", "RESET", "PHI1", "PHI2",
|
"D0", "D1", "D2", "D3", "SYNC", "CM_ROM", "CM_RAM", "TEST", "RESET", "PHI1", "PHI2",
|
||||||
|
|
@ -72,11 +82,16 @@ impl Intel4004 {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Set the initial program counter value for the CPU
|
||||||
|
/// Parameters: self - CPU instance, pc - Initial 12-bit program counter value
|
||||||
|
/// Returns: Modified CPU instance with new program counter
|
||||||
pub fn with_initial_pc(mut self, pc: u16) -> Self {
|
pub fn with_initial_pc(mut self, pc: u16) -> Self {
|
||||||
self.program_counter = U12::new(pc);
|
self.program_counter = U12::new(pc);
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Reset the CPU to its initial state
|
||||||
|
/// Clears all registers, resets program counter, and tri-states all outputs
|
||||||
pub fn reset(&mut self) {
|
pub fn reset(&mut self) {
|
||||||
self.accumulator = 0;
|
self.accumulator = 0;
|
||||||
self.carry = false;
|
self.carry = false;
|
||||||
|
|
@ -94,6 +109,8 @@ impl Intel4004 {
|
||||||
self.tri_state_data_bus();
|
self.tri_state_data_bus();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Read the 4-bit data bus from D0-D3 pins
|
||||||
|
/// Returns: 4-bit value from data bus pins
|
||||||
fn read_data_bus(&self) -> u8 {
|
fn read_data_bus(&self) -> u8 {
|
||||||
let mut data = 0;
|
let mut data = 0;
|
||||||
|
|
||||||
|
|
@ -110,6 +127,8 @@ impl Intel4004 {
|
||||||
data & 0x0F
|
data & 0x0F
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Drive the 4-bit data bus with the specified value
|
||||||
|
/// Parameters: data - 4-bit value to drive on D0-D3 pins
|
||||||
fn write_data_bus(&self, data: u8) {
|
fn write_data_bus(&self, data: u8) {
|
||||||
let nibble = data & 0x0F;
|
let nibble = data & 0x0F;
|
||||||
|
|
||||||
|
|
@ -128,6 +147,8 @@ impl Intel4004 {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Set data bus to high-impedance state to avoid bus contention
|
||||||
|
/// CRITICAL: Must be called whenever CPU is not actively driving valid data
|
||||||
fn tri_state_data_bus(&self) {
|
fn tri_state_data_bus(&self) {
|
||||||
for i in 0..4 {
|
for i in 0..4 {
|
||||||
if let Ok(pin) = self.base.get_pin(&format!("D{}", i)) {
|
if let Ok(pin) = self.base.get_pin(&format!("D{}", i)) {
|
||||||
|
|
@ -139,6 +160,8 @@ impl Intel4004 {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Set the SYNC pin state
|
||||||
|
/// Parameters: high - true for high voltage, false for low voltage
|
||||||
fn set_sync(&self, high: bool) {
|
fn set_sync(&self, high: bool) {
|
||||||
if let Ok(pin) = self.base.get_pin("SYNC") {
|
if let Ok(pin) = self.base.get_pin("SYNC") {
|
||||||
if let Ok(mut pin_guard) = pin.lock() {
|
if let Ok(mut pin_guard) = pin.lock() {
|
||||||
|
|
@ -148,6 +171,8 @@ impl Intel4004 {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Set the CM-ROM (Chip Select ROM) pin state
|
||||||
|
/// Parameters: high - true for high voltage, false for low voltage
|
||||||
fn set_cm_rom(&self, high: bool) {
|
fn set_cm_rom(&self, high: bool) {
|
||||||
if let Ok(pin) = self.base.get_pin("CM_ROM") {
|
if let Ok(pin) = self.base.get_pin("CM_ROM") {
|
||||||
if let Ok(mut pin_guard) = pin.lock() {
|
if let Ok(mut pin_guard) = pin.lock() {
|
||||||
|
|
@ -157,6 +182,8 @@ impl Intel4004 {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Set the CM-RAM (Chip Select RAM) pin state
|
||||||
|
/// Parameters: high - true for high voltage, false for low voltage
|
||||||
fn set_cm_ram(&self, high: bool) {
|
fn set_cm_ram(&self, high: bool) {
|
||||||
if let Ok(pin) = self.base.get_pin("CM_RAM") {
|
if let Ok(pin) = self.base.get_pin("CM_RAM") {
|
||||||
if let Ok(mut pin_guard) = pin.lock() {
|
if let Ok(mut pin_guard) = pin.lock() {
|
||||||
|
|
@ -166,6 +193,8 @@ impl Intel4004 {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Read the state of all control pins
|
||||||
|
/// Returns: (sync, cm_rom, cm_ram, test) - State of control signals
|
||||||
fn read_control_pins(&self) -> (bool, bool, bool, bool) {
|
fn read_control_pins(&self) -> (bool, bool, bool, bool) {
|
||||||
let sync = if let Ok(pin) = self.base.get_pin("SYNC") {
|
let sync = if let Ok(pin) = self.base.get_pin("SYNC") {
|
||||||
if let Ok(pin_guard) = pin.lock() {
|
if let Ok(pin_guard) = pin.lock() {
|
||||||
|
|
@ -181,12 +210,15 @@ impl Intel4004 {
|
||||||
(sync, false, false, true)
|
(sync, false, false, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Handle clock cycle processing
|
||||||
|
/// Updates cycle count and manages clock phase transitions
|
||||||
fn handle_clock(&mut self) {
|
fn handle_clock(&mut self) {
|
||||||
// Simple clock simulation for now
|
// Simple clock simulation for now
|
||||||
self.cycle_count += 1;
|
self.cycle_count += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Simplified instruction execution for Fibonacci demo
|
/// Execute a single instruction (simplified for demo purposes)
|
||||||
|
/// For Fibonacci demo, simulate simple execution with periodic accumulator updates
|
||||||
fn execute_instruction(&mut self) {
|
fn execute_instruction(&mut self) {
|
||||||
// For Fibonacci demo, simulate simple execution
|
// For Fibonacci demo, simulate simple execution
|
||||||
// Just increment PC and occasionally update accumulator to simulate Fibonacci sequence
|
// Just increment PC and occasionally update accumulator to simulate Fibonacci sequence
|
||||||
|
|
@ -200,6 +232,9 @@ impl Intel4004 {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Simulate Fibonacci number calculation for demo purposes
|
||||||
|
/// Parameters: n - Fibonacci sequence index
|
||||||
|
/// Returns: nth Fibonacci number modulo 16 (4-bit value)
|
||||||
fn simulate_fibonacci(&self, n: u8) -> u8 {
|
fn simulate_fibonacci(&self, n: u8) -> u8 {
|
||||||
match n {
|
match n {
|
||||||
0 => 0,
|
0 => 0,
|
||||||
|
|
@ -217,39 +252,57 @@ impl Intel4004 {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Public methods used by MCS-4 system
|
/// Get the current program counter value
|
||||||
|
/// Returns: 12-bit program counter as 16-bit value
|
||||||
pub fn get_program_counter(&self) -> u16 {
|
pub fn get_program_counter(&self) -> u16 {
|
||||||
self.program_counter.value()
|
self.program_counter.value()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Set the program counter to a specific address
|
||||||
|
/// Parameters: address - New 12-bit program counter value
|
||||||
pub fn set_program_counter(&mut self, address: u16) {
|
pub fn set_program_counter(&mut self, address: u16) {
|
||||||
self.program_counter.set(address);
|
self.program_counter.set(address);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Get the current accumulator value
|
||||||
|
/// Returns: 4-bit accumulator value
|
||||||
pub fn get_accumulator(&self) -> u8 {
|
pub fn get_accumulator(&self) -> u8 {
|
||||||
self.accumulator
|
self.accumulator
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Set the accumulator to a specific value
|
||||||
|
/// Parameters: value - New 4-bit accumulator value (will be masked to 4 bits)
|
||||||
pub fn set_accumulator(&mut self, value: u8) {
|
pub fn set_accumulator(&mut self, value: u8) {
|
||||||
self.accumulator = value & 0x0F;
|
self.accumulator = value & 0x0F;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Get the current carry flag state
|
||||||
|
/// Returns: true if carry is set, false otherwise
|
||||||
pub fn get_carry(&self) -> bool {
|
pub fn get_carry(&self) -> bool {
|
||||||
self.carry
|
self.carry
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Get the current stack pointer value
|
||||||
|
/// Returns: Stack pointer (0-2 for the 3-level stack)
|
||||||
pub fn get_stack_pointer(&self) -> u8 {
|
pub fn get_stack_pointer(&self) -> u8 {
|
||||||
self.stack_pointer
|
self.stack_pointer
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Get the total number of clock cycles executed
|
||||||
|
/// Returns: Total cycle count since reset
|
||||||
pub fn get_cycle_count(&self) -> u64 {
|
pub fn get_cycle_count(&self) -> u64 {
|
||||||
self.cycle_count
|
self.cycle_count
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Get the configured clock speed
|
||||||
|
/// Returns: Clock speed in Hz
|
||||||
pub fn get_clock_speed(&self) -> f64 {
|
pub fn get_clock_speed(&self) -> f64 {
|
||||||
self.clock_speed
|
self.clock_speed
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Set an index register to a specific value
|
||||||
|
/// Parameters: index - Register index (0-15), value - New 4-bit register value
|
||||||
|
/// Returns: Ok(()) if successful, Err(String) if index out of range
|
||||||
pub fn set_register(&mut self, index: u8, value: u8) -> Result<(), String> {
|
pub fn set_register(&mut self, index: u8, value: u8) -> Result<(), String> {
|
||||||
if index < 16 {
|
if index < 16 {
|
||||||
self.index_registers[index as usize] = value & 0x0F;
|
self.index_registers[index as usize] = value & 0x0F;
|
||||||
|
|
@ -259,6 +312,9 @@ impl Intel4004 {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Get the value of an index register
|
||||||
|
/// Parameters: index - Register index (0-15)
|
||||||
|
/// Returns: Some(register_value) if index valid, None if out of range
|
||||||
pub fn get_register(&self, index: u8) -> Option<u8> {
|
pub fn get_register(&self, index: u8) -> Option<u8> {
|
||||||
if index < 16 {
|
if index < 16 {
|
||||||
Some(self.index_registers[index as usize])
|
Some(self.index_registers[index as usize])
|
||||||
|
|
@ -281,6 +337,8 @@ impl Component for Intel4004 {
|
||||||
self.base.get_pin(name)
|
self.base.get_pin(name)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Update the CPU state for one simulation cycle
|
||||||
|
/// Processes clock cycles and executes instructions when running
|
||||||
fn update(&mut self) {
|
fn update(&mut self) {
|
||||||
if !self.is_running() {
|
if !self.is_running() {
|
||||||
return;
|
return;
|
||||||
|
|
@ -290,6 +348,8 @@ impl Component for Intel4004 {
|
||||||
self.execute_instruction();
|
self.execute_instruction();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Run the CPU in a continuous loop until stopped
|
||||||
|
/// Provides a time-sliced execution model with 10 microsecond delays between cycles
|
||||||
fn run(&mut self) {
|
fn run(&mut self) {
|
||||||
// Time-slice model: run in a loop calling update() each cycle
|
// Time-slice model: run in a loop calling update() each cycle
|
||||||
self.base.set_running(true);
|
self.base.set_running(true);
|
||||||
|
|
@ -301,6 +361,8 @@ impl Component for Intel4004 {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Stop the CPU and clean up resources
|
||||||
|
/// Tri-states all outputs and prepares for shutdown
|
||||||
fn stop(&mut self) {
|
fn stop(&mut self) {
|
||||||
self.base.set_running(false);
|
self.base.set_running(false);
|
||||||
self.tri_state_data_bus();
|
self.tri_state_data_bus();
|
||||||
|
|
@ -316,4 +378,5 @@ impl Component for Intel4004 {
|
||||||
|
|
||||||
impl RunnableComponent for Intel4004 {
|
impl RunnableComponent for Intel4004 {
|
||||||
// No custom run_loop needed - uses default Component::run() method
|
// No custom run_loop needed - uses default Component::run() method
|
||||||
|
// The default implementation spawns the component in its own thread
|
||||||
}
|
}
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load diff
Loading…
Add table
Add a link
Reference in a new issue