use libttl::chips::{Chip7400, Chip7404, Chip7408, Chip7432};
use libttl::circuit::Circuit;
use libttl::logic_level::{and, or, nand};
use libttl::LogicLevel::{High, Low}; use std::ops::Not;
fn main() -> Result<(), Box<dyn std::error::Error>> {
println!("Building Multi-Gate Logic Unit Circuit...");
let mut circuit = Circuit::new();
println!("Adding Chips:");
let chip_and_idx = circuit.add_chip(Box::new(Chip7408::new())); println!(" Idx {}: 7408 (AND)", chip_and_idx);
let chip_or_idx = circuit.add_chip(Box::new(Chip7432::new())); println!(" Idx {}: 7432 (OR)", chip_or_idx);
let chip_nand_idx = circuit.add_chip(Box::new(Chip7400::new())); println!(" Idx {}: 7400 (NAND)", chip_nand_idx);
let chip_not_idx = circuit.add_chip(Box::new(Chip7404::new())); println!(" Idx {}: 7404 (NOT)", chip_not_idx);
const INPUT_A_PIN_AND: usize = 1;
const INPUT_B_PIN_AND: usize = 2;
const INPUT_A_PIN_OR: usize = 1;
const INPUT_B_PIN_OR: usize = 2;
const INPUT_A_PIN_NAND: usize = 1;
const INPUT_B_PIN_NAND: usize = 2;
const INPUT_A_PIN_NOT: usize = 1; const INPUT_SEL_PIN_NOT: usize = 3;
const AND_RESULT_PIN: usize = 3; const OR_RESULT_PIN: usize = 3; const NAND_RESULT_PIN: usize = 3; const NOT_A_RESULT_PIN: usize = 2; const SEL_BAR_RESULT_PIN: usize = 4;
const MUX_AND_TERM_IN1: usize = 4; const MUX_AND_TERM_IN2: usize = 5; const MUX_AND_TERM_OUT: usize = 6;
const MUX_OR_TERM_IN1: usize = 10; const MUX_OR_TERM_IN2: usize = 9; const MUX_OR_TERM_OUT: usize = 8;
const MUX_FINAL_OR_IN1: usize = 4; const MUX_FINAL_OR_IN2: usize = 5; const FINAL_OUTPUT_PIN: usize = 6;
println!("\nWiring Circuit...");
circuit.add_wire(chip_and_idx, AND_RESULT_PIN, chip_and_idx, MUX_AND_TERM_IN1)?;
circuit.add_wire(chip_or_idx, OR_RESULT_PIN, chip_and_idx, MUX_OR_TERM_IN1)?;
circuit.add_wire(chip_not_idx, SEL_BAR_RESULT_PIN, chip_and_idx, MUX_AND_TERM_IN2)?;
circuit.add_wire(chip_and_idx, MUX_AND_TERM_OUT, chip_or_idx, MUX_FINAL_OR_IN1)?;
circuit.add_wire(chip_and_idx, MUX_OR_TERM_OUT, chip_or_idx, MUX_FINAL_OR_IN2)?;
println!("Wiring Complete.");
let inputs = [
(Low, Low, Low), (Low, High, Low), (High, Low, Low), (High, High, Low), (Low, Low, High), (Low, High, High), (High, Low, High), (High, High, High), ];
println!("\n--- Running Simulation ---");
println!(" A | B | SEL || Expected | Actual Output | (AND) | (OR) | (NAND)| (!A) | (!SEL)");
for (a, b, sel) in inputs {
circuit.set_external_input(chip_and_idx, INPUT_A_PIN_AND, a)?;
circuit.set_external_input(chip_or_idx, INPUT_A_PIN_OR, a)?;
circuit.set_external_input(chip_nand_idx, INPUT_A_PIN_NAND, a)?;
circuit.set_external_input(chip_not_idx, INPUT_A_PIN_NOT, a)?;
circuit.set_external_input(chip_and_idx, INPUT_B_PIN_AND, b)?;
circuit.set_external_input(chip_or_idx, INPUT_B_PIN_OR, b)?;
circuit.set_external_input(chip_nand_idx, INPUT_B_PIN_NAND, b)?;
circuit.set_external_input(chip_not_idx, INPUT_SEL_PIN_NOT, sel)?; circuit.set_external_input(chip_and_idx, MUX_OR_TERM_IN2, sel)?;
circuit.run(5);
let and_res = circuit.get_output_level(chip_and_idx, AND_RESULT_PIN)?;
let or_res = circuit.get_output_level(chip_or_idx, OR_RESULT_PIN)?;
let nand_res = circuit.get_output_level(chip_nand_idx, NAND_RESULT_PIN)?;
let not_a_res = circuit.get_output_level(chip_not_idx, NOT_A_RESULT_PIN)?;
let sel_bar_res = circuit.get_output_level(chip_not_idx, SEL_BAR_RESULT_PIN)?;
let final_output = circuit.get_output_level(chip_or_idx, FINAL_OUTPUT_PIN)?;
let expected_output = match sel {
Low => and(a, b), High => or(a, b), };
println!(
" {} | {} | {} || {} | {} | {} | {} | {} | {} | {}",
if a == High { '1' } else { '0' },
if b == High { '1' } else { '0' },
if sel == High { '1' } else { '0' },
if expected_output == High { '1' } else { '0' },
if final_output == High { '1' } else { '0' },
if and_res == High { '1' } else { '0' },
if or_res == High { '1' } else { '0' },
if nand_res == High { '1' } else { '0' },
if not_a_res == High { '1' } else { '0' },
if sel_bar_res == High { '1' } else { '0' }
);
assert_eq!(final_output, expected_output, "Mismatch for A={:?}, B={:?}, SEL={:?}", a, b, sel);
assert_eq!(and_res, and(a,b), "AND calculation failed");
assert_eq!(or_res, or(a,b), "OR calculation failed");
assert_eq!(nand_res, nand(a,b), "NAND calculation failed");
assert_eq!(not_a_res, a.not(), "NOT A calculation failed");
assert_eq!(sel_bar_res, sel.not(), "NOT SEL calculation failed");
}
println!("\nMulti-Gate Logic Unit simulation complete and verified.");
Ok(())
}