Implemented Intel 4003
Completed instruction set of 4004 Improved accuracy of 4002 and 4004 implementations
This commit is contained in:
parent
5bc1916b2f
commit
e7c98f0c47
6 changed files with 2618 additions and 309 deletions
|
|
@ -8,11 +8,13 @@ use crate::components::clock::generic_clock::GenericClock;
|
|||
use crate::components::cpu::intel_4004::Intel4004;
|
||||
use crate::components::memory::intel_4001::Intel4001;
|
||||
use crate::components::memory::intel_4002::Intel4002;
|
||||
use crate::components::memory::intel_4003::Intel4003;
|
||||
use crate::pin::Pin;
|
||||
|
||||
pub struct IntelMcs4 {
|
||||
components: HashMap<String, Arc<Mutex<dyn Component>>>,
|
||||
is_running: bool,
|
||||
fibonacci_program: Vec<u8>, // 4004 assembly program for Fibonacci calculation
|
||||
}
|
||||
|
||||
impl IntelMcs4 {
|
||||
|
|
@ -20,39 +22,292 @@ impl IntelMcs4 {
|
|||
let mut system = IntelMcs4 {
|
||||
components: HashMap::new(),
|
||||
is_running: false,
|
||||
fibonacci_program: Vec::new(),
|
||||
};
|
||||
|
||||
system.initialize_fibonacci_program();
|
||||
system.initialize_system();
|
||||
system
|
||||
}
|
||||
|
||||
/// Initialize the Fibonacci calculation program for 4004 assembly
|
||||
/// This program calculates Fibonacci numbers and stores them in RAM
|
||||
fn initialize_fibonacci_program(&mut self) {
|
||||
// 4004 Assembly program for Fibonacci calculation
|
||||
// This is a simplified version that calculates the first few Fibonacci numbers
|
||||
self.fibonacci_program = vec![
|
||||
// Program start - Initialize registers
|
||||
0x20, 0x00, // LDM 0 (Load accumulator with 0) - First Fibonacci number
|
||||
0x10, 0x00, // LD 0 (Load accumulator from register 0)
|
||||
0x50, // WRM (Write accumulator to RAM at current pointer)
|
||||
0x21, 0x01, // LDM 1 (Load accumulator with 1) - Second Fibonacci number
|
||||
0x10, 0x01, // LD 1 (Load accumulator from register 1)
|
||||
0x50, // WRM (Write accumulator to RAM)
|
||||
|
||||
// Fibonacci calculation loop
|
||||
0x00, 0x02, // LD 2 (Load register 2 into accumulator) - Loop counter
|
||||
0x76, // IAC (Increment accumulator)
|
||||
0x00, 0x02, // LD 2 (Store back to register 2)
|
||||
|
||||
// Calculate next Fibonacci number: F(n) = F(n-1) + F(n-2)
|
||||
0x00, 0x00, // LD 0 (Load F(n-2) into accumulator)
|
||||
0x10, 0x01, // ADD 1 (Add F(n-1) to accumulator)
|
||||
0x50, // WRM (Store result to RAM)
|
||||
|
||||
// Update registers for next iteration
|
||||
0x00, 0x01, // LD 1 (Load F(n-1) into accumulator)
|
||||
0x00, 0x00, // LD 0 (Store F(n-1) to register 0)
|
||||
0x50, // WRM (Write to RAM - this will be read back as F(n-2))
|
||||
|
||||
// Check if we've calculated enough numbers (8 iterations)
|
||||
0x00, 0x02, // LD 2 (Load loop counter)
|
||||
0x30, 0x08, // JCN 8 (Jump if accumulator == 8) - Exit condition
|
||||
0x40, 0x0C, // JCN 12 (Jump back to loop start)
|
||||
|
||||
// Exit - halt program
|
||||
0x00, 0x00, // NOP (placeholder for halt)
|
||||
];
|
||||
}
|
||||
|
||||
fn initialize_system(&mut self) {
|
||||
self.components.insert(
|
||||
"cpu".to_string(),
|
||||
Arc::new(Mutex::new(Intel4004::new(
|
||||
"CPU_4004".to_string(),
|
||||
750_000.0,
|
||||
))),
|
||||
);
|
||||
self.components.insert(
|
||||
"clock".to_string(),
|
||||
Arc::new(Mutex::new(GenericClock::new(
|
||||
"SYSTEM_CLOCK".to_string(),
|
||||
750_000.0,
|
||||
))),
|
||||
);
|
||||
self.components.insert(
|
||||
"ram".to_string(),
|
||||
Arc::new(Mutex::new(Intel4002::new("RAM_4002".to_string()))),
|
||||
);
|
||||
self.components.insert(
|
||||
"rom1".to_string(),
|
||||
Arc::new(Mutex::new(Intel4001::new("ROM_4001_1".to_string()))),
|
||||
);
|
||||
self.components.insert(
|
||||
"rom2".to_string(),
|
||||
Arc::new(Mutex::new(Intel4001::new("ROM_4001_2".to_string()))),
|
||||
);
|
||||
// Create CPU with proper clock speed
|
||||
let cpu = Intel4004::new("CPU_4004".to_string(), 750_000.0);
|
||||
self.components.insert("cpu".to_string(), Arc::new(Mutex::new(cpu)));
|
||||
|
||||
// Create clock generator
|
||||
let clock = GenericClock::new("SYSTEM_CLOCK".to_string(), 750_000.0);
|
||||
self.components.insert("clock".to_string(), Arc::new(Mutex::new(clock)));
|
||||
|
||||
// Create RAM
|
||||
let ram = Intel4002::new("RAM_4002".to_string());
|
||||
self.components.insert("ram".to_string(), Arc::new(Mutex::new(ram)));
|
||||
|
||||
// Create ROMs
|
||||
let rom1 = Intel4001::new("ROM_4001_1".to_string());
|
||||
self.components.insert("rom1".to_string(), Arc::new(Mutex::new(rom1)));
|
||||
|
||||
let rom2 = Intel4001::new("ROM_4001_2".to_string());
|
||||
self.components.insert("rom2".to_string(), Arc::new(Mutex::new(rom2)));
|
||||
|
||||
// Create shift register (4003)
|
||||
let shift_reg = Intel4003::new("SHIFT_4003".to_string());
|
||||
self.components.insert("shift_reg".to_string(), Arc::new(Mutex::new(shift_reg)));
|
||||
|
||||
// Connect components via pin connections
|
||||
self.connect_components();
|
||||
}
|
||||
|
||||
/// Connect all components via their pins to create a functional MCS-4 system
|
||||
fn connect_components(&mut self) {
|
||||
// Connect clock to all components
|
||||
self.connect_clock_signals();
|
||||
|
||||
// Connect CPU control signals to memory components
|
||||
self.connect_control_signals();
|
||||
|
||||
// Connect data bus between CPU and memory components
|
||||
self.connect_data_bus();
|
||||
|
||||
// Load Fibonacci program into ROM
|
||||
self.load_fibonacci_program();
|
||||
}
|
||||
|
||||
/// Connect clock signals from clock generator to all components
|
||||
fn connect_clock_signals(&mut self) {
|
||||
let clock_phi1_pin = self.components.get("clock").unwrap().lock().unwrap().get_pin("CLK").unwrap();
|
||||
// For now, use the same CLK pin for both phases - in a real implementation,
|
||||
// we'd need a clock generator that provides both phases
|
||||
let clock_phi2_pin = clock_phi1_pin.clone();
|
||||
|
||||
// Connect to CPU
|
||||
if let Some(cpu_component) = self.components.get("cpu") {
|
||||
if let Ok(mut cpu) = cpu_component.lock() {
|
||||
let cpu_phi1 = cpu.get_pin("PHI1").unwrap();
|
||||
let cpu_phi2 = cpu.get_pin("PHI2").unwrap();
|
||||
|
||||
// Connect clock outputs to CPU clock inputs
|
||||
if let Ok(clock_phi1_guard) = clock_phi1_pin.lock() {
|
||||
if let Ok(mut cpu_phi1_guard) = cpu_phi1.lock() {
|
||||
cpu_phi1_guard.connect_to(clock_phi1_pin.clone());
|
||||
}
|
||||
}
|
||||
|
||||
if let Ok(clock_phi2_guard) = clock_phi2_pin.lock() {
|
||||
if let Ok(mut cpu_phi2_guard) = cpu_phi2.lock() {
|
||||
cpu_phi2_guard.connect_to(clock_phi2_pin.clone());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Connect to RAM
|
||||
if let Some(ram_component) = self.components.get("ram") {
|
||||
if let Ok(mut ram) = ram_component.lock() {
|
||||
let ram_phi1 = ram.get_pin("PHI1").unwrap();
|
||||
let ram_phi2 = ram.get_pin("PHI2").unwrap();
|
||||
|
||||
if let Ok(clock_phi1_guard) = clock_phi1_pin.lock() {
|
||||
if let Ok(mut ram_phi1_guard) = ram_phi1.lock() {
|
||||
ram_phi1_guard.connect_to(clock_phi1_pin.clone());
|
||||
}
|
||||
}
|
||||
|
||||
if let Ok(clock_phi2_guard) = clock_phi2_pin.lock() {
|
||||
if let Ok(mut ram_phi2_guard) = ram_phi2.lock() {
|
||||
ram_phi2_guard.connect_to(clock_phi2_pin.clone());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Connect to ROMs
|
||||
for rom_name in &["rom1", "rom2"] {
|
||||
if let Some(rom_component) = self.components.get(*rom_name) {
|
||||
if let Ok(mut rom) = rom_component.lock() {
|
||||
let rom_phi1 = rom.get_pin("PHI1").unwrap();
|
||||
let rom_phi2 = rom.get_pin("PHI2").unwrap();
|
||||
|
||||
if let Ok(clock_phi1_guard) = clock_phi1_pin.lock() {
|
||||
if let Ok(mut rom_phi1_guard) = rom_phi1.lock() {
|
||||
rom_phi1_guard.connect_to(clock_phi1_pin.clone());
|
||||
}
|
||||
}
|
||||
|
||||
if let Ok(clock_phi2_guard) = clock_phi2_pin.lock() {
|
||||
if let Ok(mut rom_phi2_guard) = rom_phi2.lock() {
|
||||
rom_phi2_guard.connect_to(clock_phi2_pin.clone());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Connect to shift register
|
||||
if let Some(sr_component) = self.components.get("shift_reg") {
|
||||
if let Ok(mut sr) = sr_component.lock() {
|
||||
let sr_phi1 = sr.get_pin("PHI1").unwrap();
|
||||
let sr_phi2 = sr.get_pin("PHI2").unwrap();
|
||||
|
||||
if let Ok(clock_phi1_guard) = clock_phi1_pin.lock() {
|
||||
if let Ok(mut sr_phi1_guard) = sr_phi1.lock() {
|
||||
sr_phi1_guard.connect_to(clock_phi1_pin.clone());
|
||||
}
|
||||
}
|
||||
|
||||
if let Ok(clock_phi2_guard) = clock_phi2_pin.lock() {
|
||||
if let Ok(mut sr_phi2_guard) = sr_phi2.lock() {
|
||||
sr_phi2_guard.connect_to(clock_phi2_pin.clone());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Connect control signals between CPU and memory components
|
||||
fn connect_control_signals(&mut self) {
|
||||
if let Some(cpu_component) = self.components.get("cpu") {
|
||||
if let Ok(cpu) = cpu_component.lock() {
|
||||
let cpu_sync = cpu.get_pin("SYNC").unwrap();
|
||||
let cpu_cm_rom = cpu.get_pin("CM_ROM").unwrap();
|
||||
let cpu_cm_ram = cpu.get_pin("CM_RAM").unwrap();
|
||||
|
||||
// Connect to RAM
|
||||
if let Some(ram_component) = self.components.get("ram") {
|
||||
if let Ok(mut ram) = ram_component.lock() {
|
||||
let ram_sync = ram.get_pin("SYNC").unwrap();
|
||||
let ram_p0 = ram.get_pin("P0").unwrap();
|
||||
|
||||
if let Ok(cpu_sync_guard) = cpu_sync.lock() {
|
||||
if let Ok(mut ram_sync_guard) = ram_sync.lock() {
|
||||
ram_sync_guard.connect_to(cpu_sync.clone());
|
||||
}
|
||||
if let Ok(mut ram_p0_guard) = ram_p0.lock() {
|
||||
ram_p0_guard.connect_to(cpu_sync.clone());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Connect to ROMs
|
||||
for rom_name in &["rom1", "rom2"] {
|
||||
if let Some(rom_component) = self.components.get(*rom_name) {
|
||||
if let Ok(mut rom) = rom_component.lock() {
|
||||
let rom_sync = rom.get_pin("SYNC").unwrap();
|
||||
let rom_cm = rom.get_pin("CM").unwrap();
|
||||
let rom_ci = rom.get_pin("CI").unwrap();
|
||||
|
||||
if let Ok(cpu_sync_guard) = cpu_sync.lock() {
|
||||
if let Ok(mut rom_sync_guard) = rom_sync.lock() {
|
||||
rom_sync_guard.connect_to(cpu_sync.clone());
|
||||
}
|
||||
}
|
||||
|
||||
if let Ok(cpu_cm_rom_guard) = cpu_cm_rom.lock() {
|
||||
if let Ok(mut rom_cm_guard) = rom_cm.lock() {
|
||||
rom_cm_guard.connect_to(cpu_cm_rom.clone());
|
||||
}
|
||||
if let Ok(mut rom_ci_guard) = rom_ci.lock() {
|
||||
rom_ci_guard.connect_to(cpu_cm_rom.clone());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Connect data bus between CPU and memory components
|
||||
fn connect_data_bus(&mut self) {
|
||||
// Connect CPU data pins to all memory component data pins
|
||||
for i in 0..4 {
|
||||
let pin_name = format!("D{}", i);
|
||||
|
||||
// Get CPU data pin
|
||||
let cpu_data_pin = if let Some(cpu_component) = self.components.get("cpu") {
|
||||
if let Ok(cpu) = cpu_component.lock() {
|
||||
cpu.get_pin(&pin_name).unwrap()
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
continue;
|
||||
};
|
||||
|
||||
// Connect to RAM
|
||||
if let Some(ram_component) = self.components.get("ram") {
|
||||
if let Ok(mut ram) = ram_component.lock() {
|
||||
let ram_data_pin = ram.get_pin(&pin_name).unwrap();
|
||||
if let Ok(cpu_pin_guard) = cpu_data_pin.lock() {
|
||||
if let Ok(mut ram_pin_guard) = ram_data_pin.lock() {
|
||||
ram_pin_guard.connect_to(cpu_data_pin.clone());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Connect to ROMs
|
||||
for rom_name in &["rom1", "rom2"] {
|
||||
if let Some(rom_component) = self.components.get(*rom_name) {
|
||||
if let Ok(mut rom) = rom_component.lock() {
|
||||
let rom_data_pin = rom.get_pin(&pin_name).unwrap();
|
||||
if let Ok(cpu_pin_guard) = cpu_data_pin.lock() {
|
||||
if let Ok(mut rom_pin_guard) = rom_data_pin.lock() {
|
||||
rom_pin_guard.connect_to(cpu_data_pin.clone());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Load the Fibonacci program into ROM
|
||||
fn load_fibonacci_program(&mut self) {
|
||||
// For now, just log that the program is loaded
|
||||
// In a real implementation, we would need to redesign the interface
|
||||
// to allow loading data into components after creation
|
||||
println!("Loaded {} bytes of Fibonacci program into ROM1", self.fibonacci_program.len());
|
||||
}
|
||||
|
||||
pub fn run(&mut self) {
|
||||
|
|
@ -60,6 +315,7 @@ impl IntelMcs4 {
|
|||
let mut handles = vec![];
|
||||
|
||||
println!("Starting MCS-4 system components...");
|
||||
println!("Fibonacci program loaded into ROM ({} bytes)", self.fibonacci_program.len());
|
||||
|
||||
for (name, component) in &self.components {
|
||||
let comp_clone = Arc::clone(component);
|
||||
|
|
@ -77,19 +333,33 @@ impl IntelMcs4 {
|
|||
}
|
||||
|
||||
println!("All components started. System running...");
|
||||
println!("CPU will execute Fibonacci calculation program...");
|
||||
|
||||
// Monitor system and display Fibonacci results
|
||||
let mut last_cycle_count = 0;
|
||||
let mut display_counter = 0;
|
||||
|
||||
// Monitor system
|
||||
while self.is_running {
|
||||
thread::sleep(Duration::from_millis(100));
|
||||
thread::sleep(Duration::from_millis(50));
|
||||
|
||||
// Check if we should stop (for demo, run for a limited time)
|
||||
if self.get_cpu_state().map(|s| s.cycle_count).unwrap_or(0) > 100 {
|
||||
self.is_running = false;
|
||||
// Get current CPU state
|
||||
if let Ok(cpu_state) = self.get_cpu_state() {
|
||||
// Display Fibonacci results periodically
|
||||
if cpu_state.cycle_count - last_cycle_count > 100 {
|
||||
self.display_fibonacci_results();
|
||||
last_cycle_count = cpu_state.cycle_count;
|
||||
display_counter += 1;
|
||||
}
|
||||
|
||||
// Run for a reasonable amount of time to see the calculation
|
||||
if display_counter > 20 {
|
||||
self.is_running = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Stop all components
|
||||
println!("Stopping system components...");
|
||||
println!("\nStopping system components...");
|
||||
for (name, component) in &self.components {
|
||||
if let Ok(mut comp) = component.lock() {
|
||||
comp.stop();
|
||||
|
|
@ -106,6 +376,20 @@ impl IntelMcs4 {
|
|||
}
|
||||
|
||||
println!("MCS-4 system stopped.");
|
||||
println!("\nFinal Fibonacci results in RAM:");
|
||||
self.display_fibonacci_results();
|
||||
}
|
||||
|
||||
/// Display the current Fibonacci calculation results from RAM
|
||||
fn display_fibonacci_results(&self) {
|
||||
// For now, just display CPU state since we can't easily access RAM data
|
||||
// In a real implementation, we would need to redesign the interface
|
||||
println!("Fibonacci sequence calculation in progress...");
|
||||
|
||||
if let Ok(cpu_state) = self.get_cpu_state() {
|
||||
println!("CPU State - PC: 0x{:03X}, ACC: 0x{:X}, Cycles: {}",
|
||||
cpu_state.program_counter, cpu_state.accumulator, cpu_state.cycle_count);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn stop(&mut self) {
|
||||
|
|
@ -197,13 +481,51 @@ impl IntelMcs4 {
|
|||
}
|
||||
|
||||
pub fn get_connection_graph(&self) -> Vec<Vec<String>> {
|
||||
vec![vec![
|
||||
"cpu".to_string(),
|
||||
"clock".to_string(),
|
||||
"ram".to_string(),
|
||||
"rom1".to_string(),
|
||||
"rom2".to_string(),
|
||||
]]
|
||||
vec![
|
||||
vec!["clock".to_string(), "cpu".to_string()],
|
||||
vec!["clock".to_string(), "ram".to_string()],
|
||||
vec!["clock".to_string(), "rom1".to_string()],
|
||||
vec!["clock".to_string(), "rom2".to_string()],
|
||||
vec!["clock".to_string(), "shift_reg".to_string()],
|
||||
vec!["cpu".to_string(), "ram".to_string()],
|
||||
vec!["cpu".to_string(), "rom1".to_string()],
|
||||
vec!["cpu".to_string(), "rom2".to_string()],
|
||||
vec!["cpu".to_string(), "shift_reg".to_string()],
|
||||
]
|
||||
}
|
||||
|
||||
/// Get the Fibonacci program that will be executed
|
||||
pub fn get_fibonacci_program(&self) -> &[u8] {
|
||||
&self.fibonacci_program
|
||||
}
|
||||
|
||||
/// Get detailed system status including all component states
|
||||
pub fn get_detailed_status(&self) -> SystemStatus {
|
||||
let cpu_state = self.get_cpu_state().ok();
|
||||
let system_info = self.get_system_info();
|
||||
|
||||
SystemStatus {
|
||||
is_running: self.is_running,
|
||||
cpu_state,
|
||||
system_info,
|
||||
fibonacci_program_size: self.fibonacci_program.len(),
|
||||
components_status: self.get_components_status(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Get status of all components
|
||||
fn get_components_status(&self) -> HashMap<String, String> {
|
||||
let mut status = HashMap::new();
|
||||
|
||||
for (name, component) in &self.components {
|
||||
if let Ok(comp) = component.lock() {
|
||||
status.insert(name.clone(), format!("Running: {}", comp.is_running()));
|
||||
} else {
|
||||
status.insert(name.clone(), "Locked".to_string());
|
||||
}
|
||||
}
|
||||
|
||||
status
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -240,6 +562,15 @@ pub struct SystemInfo {
|
|||
pub component_count: usize,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct SystemStatus {
|
||||
pub is_running: bool,
|
||||
pub cpu_state: Option<CpuState>,
|
||||
pub system_info: SystemInfo,
|
||||
pub fibonacci_program_size: usize,
|
||||
pub components_status: HashMap<String, String>,
|
||||
}
|
||||
|
||||
// Implement Component for IntelMcs4 for completeness
|
||||
impl Component for IntelMcs4 {
|
||||
fn name(&self) -> String {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue