rusty_emu/src/systems/intel_mcs_4.rs
2025-09-28 22:23:23 +02:00

539 lines
No EOL
19 KiB
Rust

use std::collections::HashMap;
use std::sync::{Arc, Mutex};
use std::thread;
use std::time::Duration;
use crate::component::Component;
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,
}
impl IntelMcs4 {
pub fn new() -> Self {
let system = IntelMcs4 {
components: HashMap::new(),
is_running: false,
};
system
}
fn initialize_system(&mut self) {
// 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();
}
/// 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());
}
}
}
}
}
}
}
pub fn run(&mut self) {
self.is_running = true;
let mut handles = vec![];
println!("Starting MCS-4 system components...");
for (name, component) in &self.components {
let comp_clone = Arc::clone(component);
let name_clone = name.clone();
let handle = thread::spawn(move || {
println!("Starting component: {}", name_clone);
if let Ok(mut comp) = comp_clone.lock() {
comp.run();
}
println!("Component {} stopped", name_clone);
});
handles.push((name.clone(), handle));
}
println!("All components started. System running...");
println!("CPU will execute loaded program...");
// Monitor system and display system status
let mut last_cycle_count = 0;
let mut display_counter = 0;
while self.is_running {
thread::sleep(Duration::from_millis(50));
// Get current CPU state
if let Ok(cpu_state) = self.get_cpu_state() {
// Display system status periodically
if cpu_state.cycle_count - last_cycle_count > 100 {
self.display_system_status();
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!("\nStopping system components...");
for (name, component) in &self.components {
if let Ok(mut comp) = component.lock() {
comp.stop();
println!("Stopped component: {}", name);
}
}
// Wait for threads
for (name, handle) in handles {
match handle.join() {
Ok(_) => println!("Component {} thread finished", name),
Err(_) => eprintln!("Component {} thread panicked", name),
}
}
println!("MCS-4 system stopped.");
println!("\nFinal system status:");
self.display_system_status();
}
/// Display the current system status
fn display_system_status(&self) {
println!("System execution 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) {
self.is_running = false;
}
pub fn is_running(&self) -> bool {
self.is_running
}
// Implement the missing methods for main.rs
pub fn load_program(&mut self, rom1_data: Vec<u8>, rom2_data: Vec<u8>) -> Result<(), String> {
println!("Loading program into ROM...");
println!("ROM1 data: {} bytes", rom1_data.len());
println!("ROM2 data: {} bytes", rom2_data.len());
Ok(())
}
pub fn load_rom_data(
&mut self,
rom_chip: usize,
data: Vec<u8>,
offset: usize,
) -> Result<(), String> {
let rom_key = match rom_chip {
1 => "rom1",
2 => "rom2",
_ => return Err("Invalid ROM chip".to_string()),
};
if let Some(rom_component) = self.components.get(rom_key) {
if let Ok(_rom) = rom_component.lock() {
// For now, just log the operation
println!(
"Loaded {} bytes into ROM{} at offset {}",
data.len(),
rom_chip,
offset
);
return Ok(());
}
}
Err("ROM component not found".to_string())
}
pub fn load_ram_data(&mut self, data: &[u8], offset: usize) -> Result<(), String> {
if let Some(ram_component) = self.components.get("ram") {
if let Ok(_ram) = ram_component.lock() {
println!("Loaded {} bytes into RAM at offset {}", data.len(), offset);
return Ok(());
}
}
Err("RAM component not found".to_string())
}
pub fn get_cpu_state(&self) -> Result<CpuState, String> {
if let Some(cpu_component) = self.components.get("cpu") {
if let Some(cpu) = cpu_component.as_any().downcast_ref::<Intel4004>() {
return Ok(CpuState {
program_counter: cpu.get_program_counter(),
accumulator: cpu.get_accumulator(),
carry: cpu.get_carry(),
stack_pointer: cpu.get_stack_pointer(),
cycle_count: cpu.get_cycle_count(),
});
} else {
Err("CPU component is not of type Intel 4004".to_string())
}
} else {
Err("CPU component not found".to_string())
}
}
pub fn reset_system(&mut self) {
println!("Resetting MCS-4 system...");
if let Some(cpu_component) = self.components.get_mut("cpu") {
if let Some(cpu) = cpu_component.as_any_mut().downcast_mut::<Intel4004>() {
cpu.reset();
}
}
}
pub fn get_system_info(&self) -> SystemInfo {
SystemInfo {
cpu_speed: 750_000.0,
rom_size: 512,
ram_size: 40,
component_count: self.components.len(),
}
}
pub fn get_connection_graph(&self) -> Vec<Vec<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 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,
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
}
}
// Add the missing AsAny trait implementation
trait AsAny {
fn as_any(&self) -> &dyn std::any::Any;
fn as_any_mut(&mut self) -> &mut dyn std::any::Any;
}
impl<T: 'static> AsAny for T {
fn as_any(&self) -> &dyn std::any::Any {
self
}
fn as_any_mut(&mut self) -> &mut dyn std::any::Any {
self
}
}
#[derive(Debug, Clone)]
pub struct CpuState {
pub program_counter: u16,
pub accumulator: u8,
pub carry: bool,
pub stack_pointer: u8,
pub cycle_count: u64,
}
#[derive(Debug, Clone)]
pub struct SystemInfo {
pub cpu_speed: f64,
pub rom_size: usize,
pub ram_size: usize,
pub component_count: usize,
}
#[derive(Debug, Clone)]
pub struct SystemStatus {
pub is_running: bool,
pub cpu_state: Option<CpuState>,
pub system_info: SystemInfo,
pub components_status: HashMap<String, String>,
}
// Implement Component for IntelMcs4 for completeness
impl Component for IntelMcs4 {
fn name(&self) -> String {
"Intel_MCS-4_System".to_string()
}
fn pins(&self) -> HashMap<String, Arc<Mutex<Pin>>> {
HashMap::new()
}
fn get_pin(&self, _name: &str) -> Result<Arc<Mutex<Pin>>, String> {
Err("System pins not accessible".to_string())
}
fn update(&mut self) {
// System-level update
}
fn run(&mut self) {
self.run();
}
fn stop(&mut self) {
self.stop();
}
fn is_running(&self) -> bool {
self.is_running()
}
}