Extracted fibonacci code into binary file
System and binary selection upon start
This commit is contained in:
parent
e7c98f0c47
commit
dd93e33087
4 changed files with 871 additions and 150 deletions
261
src/main.rs
261
src/main.rs
|
|
@ -1,132 +1,242 @@
|
|||
use rusty_emu::systems::intel_mcs_4::IntelMcs4;
|
||||
use std::env;
|
||||
use std::fs;
|
||||
use std::process;
|
||||
use std::thread;
|
||||
use std::time::{Duration, Instant};
|
||||
|
||||
fn main() {
|
||||
println!("Intel MCS-4 Emulator - Fibonacci Sequence Example");
|
||||
println!("=================================================");
|
||||
// Parse command line arguments
|
||||
let args: Vec<String> = env::args().collect();
|
||||
let mut system_type = "mcs4".to_string();
|
||||
let mut program_file = "fibonacci.bin".to_string();
|
||||
|
||||
// Create the MCS-4 system
|
||||
let mut mcs4 = IntelMcs4::new();
|
||||
|
||||
// Load the Fibonacci program
|
||||
let fibonacci_program = compile_fibonacci_program();
|
||||
|
||||
// Split program between ROMs
|
||||
let rom1_size = 256;
|
||||
let rom1_data = if fibonacci_program.len() > rom1_size {
|
||||
fibonacci_program[..rom1_size].to_vec()
|
||||
} else {
|
||||
fibonacci_program.clone()
|
||||
};
|
||||
|
||||
let rom2_data = if fibonacci_program.len() > rom1_size {
|
||||
fibonacci_program[rom1_size..].to_vec()
|
||||
} else {
|
||||
vec![0; 256]
|
||||
};
|
||||
|
||||
println!("Loading Fibonacci program into ROM...");
|
||||
if let Err(e) = mcs4.load_program(rom1_data, rom2_data) {
|
||||
eprintln!("Failed to load program: {}", e);
|
||||
return;
|
||||
let mut i = 1;
|
||||
while i < args.len() {
|
||||
match args[i].as_str() {
|
||||
"-s" | "--system" => {
|
||||
if i + 1 < args.len() {
|
||||
system_type = args[i + 1].clone();
|
||||
i += 2;
|
||||
} else {
|
||||
eprintln!("Error: --system requires a value");
|
||||
print_usage(&args[0]);
|
||||
process::exit(1);
|
||||
}
|
||||
}
|
||||
"-f" | "--file" => {
|
||||
if i + 1 < args.len() {
|
||||
program_file = args[i + 1].clone();
|
||||
i += 2;
|
||||
} else {
|
||||
eprintln!("Error: --file requires a value");
|
||||
print_usage(&args[0]);
|
||||
process::exit(1);
|
||||
}
|
||||
}
|
||||
"-h" | "--help" => {
|
||||
print_usage(&args[0]);
|
||||
return;
|
||||
}
|
||||
_ => {
|
||||
eprintln!("Unknown argument: {}", args[i]);
|
||||
print_usage(&args[0]);
|
||||
process::exit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Initialize RAM with Fibonacci seeds
|
||||
let initial_data = [0x00, 0x01];
|
||||
if let Err(e) = mcs4.load_ram_data(&initial_data, 0) {
|
||||
eprintln!("Failed to initialize RAM: {}", e);
|
||||
return;
|
||||
}
|
||||
println!("Intel MCS-4 Emulator");
|
||||
println!("===================");
|
||||
println!("System: {}", system_type);
|
||||
println!("Program: {}", program_file);
|
||||
|
||||
mcs4.reset_system();
|
||||
// Load program data
|
||||
let program_data = match load_program_data(&program_file) {
|
||||
Ok(data) => data,
|
||||
Err(e) => {
|
||||
eprintln!("Failed to load program: {}", e);
|
||||
process::exit(1);
|
||||
}
|
||||
};
|
||||
|
||||
// Create and configure the system
|
||||
let system = match create_system(&system_type, &program_data) {
|
||||
Ok(sys) => sys,
|
||||
Err(e) => {
|
||||
eprintln!("Failed to create system: {}", e);
|
||||
process::exit(1);
|
||||
}
|
||||
};
|
||||
|
||||
// Display system information
|
||||
let info = mcs4.get_system_info();
|
||||
let info = system.get_system_info();
|
||||
println!("\nSystem Information:");
|
||||
println!(" CPU Speed: {} Hz", info.cpu_speed);
|
||||
println!(" ROM Size: {} bytes", info.rom_size);
|
||||
println!(" RAM Size: {} nibbles", info.ram_size);
|
||||
println!(" Components: {}", info.component_count);
|
||||
|
||||
println!("\nStarting Fibonacci sequence calculation...");
|
||||
println!("\nStarting execution...");
|
||||
println!("Press Ctrl+C to stop execution");
|
||||
println!();
|
||||
|
||||
// Run the Fibonacci demo
|
||||
run_fibonacci_demo(mcs4);
|
||||
// Run the system
|
||||
run_system_demo(system);
|
||||
}
|
||||
|
||||
fn compile_fibonacci_program() -> Vec<u8> {
|
||||
// Simple program that just runs and lets the CPU simulate Fibonacci
|
||||
fn print_usage(program_name: &str) {
|
||||
println!("Usage: {} [OPTIONS]", program_name);
|
||||
println!();
|
||||
println!("Options:");
|
||||
println!(" -s, --system <SYSTEM> System type to run (default: mcs4)");
|
||||
println!(" -f, --file <FILE> Program binary file to load (default: fibonacci.bin)");
|
||||
println!(" -h, --help Show this help message");
|
||||
println!();
|
||||
println!("Examples:");
|
||||
println!(" {} -s mcs4 -f fibonacci.bin", program_name);
|
||||
println!(" {} --system mcs4 --file myprogram.bin", program_name);
|
||||
}
|
||||
|
||||
fn load_program_data(filename: &str) -> Result<Vec<u8>, String> {
|
||||
println!("DEBUG: Attempting to load program from: {}", filename);
|
||||
match fs::read(filename) {
|
||||
Ok(data) => {
|
||||
println!("DEBUG: Successfully loaded {} bytes from {}", data.len(), filename);
|
||||
Ok(data)
|
||||
}
|
||||
Err(e) => {
|
||||
// If file doesn't exist, try to use default program
|
||||
if filename == "fibonacci.bin" {
|
||||
println!("DEBUG: File {} not found ({}), using default fibonacci program", filename, e);
|
||||
let default_program = get_default_fibonacci_program();
|
||||
println!("DEBUG: Default program size: {} bytes", default_program.len());
|
||||
Ok(default_program)
|
||||
} else {
|
||||
println!("DEBUG: Failed to read file {}: {}", filename, e);
|
||||
Err(format!("Failed to read file {}: {}", filename, e))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn get_default_fibonacci_program() -> Vec<u8> {
|
||||
// Fibonacci program for Intel 4004
|
||||
// This implements a simple Fibonacci sequence generator
|
||||
vec![
|
||||
0xF0, // LDM 0
|
||||
0xF1, // LDM 1
|
||||
0x30, // SRC 0
|
||||
0x31, // SRC 1
|
||||
0x60, // JUN 0
|
||||
0x00, // Address
|
||||
// Pad with zeros
|
||||
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 run_fibonacci_demo(mcs4: IntelMcs4) {
|
||||
fn create_system(system_type: &str, program_data: &[u8]) -> Result<IntelMcs4, String> {
|
||||
match system_type {
|
||||
"mcs4" => {
|
||||
let system = IntelMcs4::new();
|
||||
|
||||
// Split program between ROMs
|
||||
let rom1_size = 256;
|
||||
let rom1_data = if program_data.len() > rom1_size {
|
||||
program_data[..rom1_size].to_vec()
|
||||
} else {
|
||||
program_data.to_vec()
|
||||
};
|
||||
|
||||
let rom2_data = if program_data.len() > rom1_size {
|
||||
program_data[rom1_size..].to_vec()
|
||||
} else {
|
||||
vec![0; 256]
|
||||
};
|
||||
|
||||
// Load program into ROMs
|
||||
let mut system = system;
|
||||
system.load_program(rom1_data, rom2_data)
|
||||
.map_err(|e| format!("Failed to load program: {}", e))?;
|
||||
|
||||
// Initialize RAM with some data for the program
|
||||
let initial_data = [0x00, 0x01];
|
||||
system.load_ram_data(&initial_data, 0)
|
||||
.map_err(|e| format!("Failed to initialize RAM: {}", e))?;
|
||||
|
||||
system.reset_system();
|
||||
Ok(system)
|
||||
}
|
||||
_ => Err(format!("Unknown system type: {}", system_type))
|
||||
}
|
||||
}
|
||||
|
||||
fn run_system_demo(system: IntelMcs4) {
|
||||
let start_time = Instant::now();
|
||||
|
||||
println!("Cycle | Fibonacci | Accumulator | PC");
|
||||
println!("------|-----------|-------------|------");
|
||||
println!("Cycle | Accumulator | PC");
|
||||
println!("------|-------------|------");
|
||||
|
||||
// Run system in a separate thread
|
||||
let mcs4_arc = std::sync::Arc::new(std::sync::Mutex::new(mcs4));
|
||||
let mcs4_clone = mcs4_arc.clone();
|
||||
let system_arc = std::sync::Arc::new(std::sync::Mutex::new(system));
|
||||
let system_clone = system_arc.clone();
|
||||
|
||||
let handle = thread::spawn(move || {
|
||||
if let Ok(mut system) = mcs4_clone.lock() {
|
||||
if let Ok(mut system) = system_clone.lock() {
|
||||
system.run();
|
||||
}
|
||||
});
|
||||
|
||||
// Monitor CPU state in main thread
|
||||
let mut last_fibonacci = 0;
|
||||
let mut iteration = 0;
|
||||
|
||||
while iteration < 20 {
|
||||
// Run for 20 iterations
|
||||
thread::sleep(Duration::from_millis(200));
|
||||
|
||||
if let Ok(system) = mcs4_arc.lock() {
|
||||
if let Ok(system) = system_arc.lock() {
|
||||
if let Ok(state) = system.get_cpu_state() {
|
||||
let current_fibonacci = state.accumulator;
|
||||
|
||||
if current_fibonacci != last_fibonacci {
|
||||
println!(
|
||||
"{:5} | {:9} | {:11} | {:04X}",
|
||||
state.cycle_count,
|
||||
current_fibonacci,
|
||||
state.accumulator,
|
||||
state.program_counter
|
||||
);
|
||||
last_fibonacci = current_fibonacci;
|
||||
iteration += 1;
|
||||
}
|
||||
println!(
|
||||
"{:5} | {:11} | {:04X}",
|
||||
state.cycle_count,
|
||||
state.accumulator,
|
||||
state.program_counter
|
||||
);
|
||||
iteration += 1;
|
||||
}
|
||||
}
|
||||
|
||||
if iteration >= 15 {
|
||||
// Stop after 15 Fibonacci numbers
|
||||
if let Ok(mut system) = mcs4_arc.lock() {
|
||||
if let Ok(mut system) = system_arc.lock() {
|
||||
system.stop();
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Wait for system thread to finish
|
||||
let _ = handle.join();
|
||||
|
||||
let duration = start_time.elapsed();
|
||||
println!("\nExecution completed in {:?}", duration);
|
||||
println!("Fibonacci demo finished.");
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
|
@ -135,7 +245,8 @@ mod tests {
|
|||
|
||||
#[test]
|
||||
fn test_fibonacci_program() {
|
||||
let program = compile_fibonacci_program();
|
||||
let program = get_default_fibonacci_program();
|
||||
assert!(!program.is_empty());
|
||||
println!("Fibonacci program size: {} bytes", program.len());
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue