diff options
| author | omagdy7 <omar.professional8777@gmail.com> | 2023-11-29 00:13:13 +0200 |
|---|---|---|
| committer | omagdy7 <omar.professional8777@gmail.com> | 2023-11-29 00:13:13 +0200 |
| commit | f8e2ec0f8ddfa44def90d8d3d1532877d251ece2 (patch) | |
| tree | 434fc365d665fdd776d4ecea008ed6dfb9cfa10c | |
| parent | fb4ba46a7fa9055a7848d8e0fa3daed2ce0b014f (diff) | |
| download | lgsim-f8e2ec0f8ddfa44def90d8d3d1532877d251ece2.tar.xz lgsim-f8e2ec0f8ddfa44def90d8d3d1532877d251ece2.zip | |
Added full implementation of simulating a Chip
| -rw-r--r-- | ' | 361 | ||||
| -rw-r--r-- | src/gate.rs | 141 | ||||
| -rw-r--r-- | src/main.rs | 66 | ||||
| -rw-r--r-- | src/pin.rs | 1 |
4 files changed, 131 insertions, 438 deletions
@@ -1,361 +0,0 @@ -use crate::pin::*; -use crate::types::*; -use std::collections::HashMap; -use std::collections::HashSet; - -#[derive(Debug)] -pub enum GateType { - And, - Or, - Not, - Buffer, - Chip, -} - -#[derive(Debug, Clone, PartialEq)] -pub enum Gate { - And(AndGate), - Or(OrGate), - Not(NotGate), - Buffer(BufferGate), - Chip(Chip), -} - -impl Gate { - pub fn new(gate_type: GateType, input: Vec<PinValue>, kind: PinType) -> Self { - static mut ID: usize = 0; - unsafe { - ID += 1; - match gate_type { - GateType::And => Gate::And(AndGate::new(input, ID, kind)), - GateType::Or => Gate::Or(OrGate::new(input, ID)), - GateType::Not => Gate::Not(NotGate::new(input, ID)), - GateType::Buffer => Gate::Buffer(BufferGate::new(input, ID)), - GateType::Chip => Gate::Chip(Chip::new()), - } - } - } - - pub fn evaluate(&mut self) -> bool { - match self { - Gate::And(gate) => gate.evaluate(), - - Gate::Or(gate) => gate.evaluate(), - - Gate::Not(gate) => gate.evaluate(), - - Gate::Buffer(gate) => gate.evaluate(), - - Gate::Chip(chip) => chip.simulate(), - } - } - - fn input(&self) -> &Pins { - match self { - Gate::And(gate) => &gate.input, - - Gate::Or(gate) => &gate.input, - - Gate::Not(gate) => &gate.input, - - Gate::Buffer(gate) => &gate.input, - - Gate::Chip(chip) => &chip.input, - } - } - - fn input_mut(&mut self) -> &mut Pins { - match self { - Gate::And(gate) => &mut gate.input, - - Gate::Or(gate) => &mut gate.input, - - Gate::Not(gate) => &mut gate.input, - - Gate::Buffer(gate) => &mut gate.input, - - Gate::Chip(chip) => &mut chip.input, - } - } - - fn output(&self) -> &Pin { - match self { - Gate::And(gate) => &gate.output, - - Gate::Or(gate) => &gate.output, - - Gate::Not(gate) => &gate.output, - - Gate::Buffer(gate) => &gate.output, - - Gate::Chip(_) => todo!(), - } - } - - fn id(&self) -> usize { - match self { - Gate::And(gate) => gate.id, - - Gate::Or(gate) => gate.id, - - Gate::Not(gate) => gate.id, - - Gate::Buffer(gate) => gate.id, - - Gate::Chip(_) => 0, - } - } -} - -impl PartialEq for AndGate { - fn eq(&self, other: &Self) -> bool { - self.id == other.id - } -} - -impl PartialEq for OrGate { - fn eq(&self, other: &Self) -> bool { - self.id == other.id - } -} - -impl PartialEq for NotGate { - fn eq(&self, other: &Self) -> bool { - self.id == other.id - } -} - -impl PartialEq for BufferGate { - fn eq(&self, other: &Self) -> bool { - self.id == other.id - } -} - -#[derive(Debug, Clone)] -pub struct AndGate { - id: usize, - input: Pins, - output: Pin, -} - -impl AndGate { - fn new(input: Vec<PinValue>, id: usize, kind: PinType) -> Self { - if input.is_empty() { - let pin_1 = Pin::new(PinType::Undetermined, id, 42); - let pin_2 = Pin::new(PinType::Undetermined, id, 42); - Self { - id, - input: vec![pin_1, pin_2], - output: Pin::new(PinType::Undetermined, id, 42), - } - } else if input.len() == 1 { - let pin_1 = Pin::new(kind, id, input[0]); - Self { - id, - input: vec![pin_1, Pin::new(PinType::Undetermined, id, 42)], - output: Pin::new(PinType::Undetermined, id, 42), - } - } else { - let pin_1 = Pin::new(kind, id, input[0]); - let pin_2 = Pin::new(kind, id, input[1]); - Self { - id, - input: vec![pin_1, pin_2], - output: Pin::new(PinType::Undetermined, id, 42), - } - } - } - - fn evaluate(&mut self) -> bool { - let res = (self.input[0].val.unwrap() & self.input[1].val.unwrap()) == 1; - self.output.val = Some(res as u8); - self.output.kind = PinType::GateOutput; - res - } -} - -#[derive(Debug, Clone)] -pub struct OrGate { - id: usize, - input: Pins, - output: Pin, -} - -impl OrGate { - fn new(input: Vec<PinValue>, id: usize) -> Self { - let pin_1 = Pin::new(PinType::ChipInput, id, input[0]); - let pin_2 = Pin::new(PinType::ChipInput, id, input[1]); - Self { - id, - input: vec![pin_1, pin_2], - output: Pin::new(PinType::Undetermined, id, 42), - } - } - - fn evaluate(&mut self) -> bool { - let res = (self.input[0].val.unwrap() | self.input[1].val.unwrap()) == 1; - self.output.val = Some(res as u8); - self.output.kind = PinType::GateOutput; - res - } -} - -#[derive(Debug, Clone)] -pub struct NotGate { - id: usize, - input: Pins, - output: Pin, -} - -impl NotGate { - fn new(input: Vec<PinValue>, id: usize) -> Self { - if input.is_empty() { - let pin_1 = Pin::new(PinType::Undetermined, id, 42); - Self { - id, - input: vec![pin_1], - output: Pin::new(PinType::Undetermined, id, 42), - } - } else { - let pin_1 = Pin::new(PinType::ChipInput, id, input[0]); - Self { - id, - input: vec![pin_1], - output: Pin::new(PinType::Undetermined, id, 42), - } - } - } - - fn evaluate(&mut self) -> bool { - let res = !(self.input[0].val.unwrap() == 1); - self.output.val = Some(res as u8); - self.output.kind = PinType::GateOutput; - res - } -} - -#[derive(Debug, Clone, Eq)] -pub struct BufferGate { - id: usize, - input: Pins, - output: Pin, -} - -impl BufferGate { - fn new(input: Vec<PinValue>, id: usize) -> Self { - let pin_1 = Pin::new(PinType::ChipInput, id, input[0]); - Self { - id, - input: vec![pin_1], - output: Pin::new(PinType::Undetermined, id, 42), - } - } - - fn evaluate(&mut self) -> bool { - let res = self.input[0].val.unwrap() == 1; - self.output.val = Some(res as u8); - self.output.kind = PinType::GateOutput; - res - } -} - -#[derive(Debug, Clone, PartialEq)] -pub struct Chip { - gates: Gates, - pub connections: Connections, - input: Pins, - output: Pins, -} - -impl Chip { - pub fn new() -> Chip { - Chip { - gates: Gates::new(), - connections: HashMap::new(), - input: Pins::new(), - output: Pins::new(), - } - } - - fn add_input(&mut self, pin: Pin) { - self.input.push(pin); - } - - fn add_output(&mut self, pin: Pin) { - self.output.push(pin); - } - - fn add_gate(&mut self, gate: Gate) -> usize { - let id = gate.id(); - self.gates.push(gate); - id - } - - pub fn connect_gate(&mut self, from: &mut Gate, to: &mut Gate, to_pin_idx: usize) { - from.evaluate(); - to.input_mut()[to_pin_idx] = - Pin::new(PinType::GateInput, to.id(), from.output().val.unwrap()); - self.connections - .entry(to.input()[to_pin_idx]) - .and_modify(|val| val.push(*from.output())) - .or_insert_with(|| vec![*from.output()]); - if !self.gates.contains(&from) { - // TODO: Remove this clone - self.add_gate(from.clone()); - } - if !self.gates.contains(&to) { - // TODO: Remove this clone - self.add_gate(to.clone()); - } - } - - pub fn pins(&self) -> Vec<&Pin> { - let mut pins = vec![]; - for gate in &self.gates { - for pin in gate.input() { - pins.push(pin); - } - pins.push(gate.output()); - } - pins - } - - pub fn gate_dag(&self) -> HashMap<usize, Vec<usize>> { - let mut dag = HashMap::new(); - for connection in &self.connections { - for pin in connection.1 { - dag.entry(connection.0.gate_id) - .and_modify(|val: &mut Vec<usize>| val.push(pin.gate_id)) - .or_insert_with(|| vec![pin.gate_id]); - } - } - dag - } - - fn simulate_helper(&self, visited: &mut HashSet<usize>) { - let dag = self.gate_dag(); - for pair in dag { - for child in pair.1 { - if (visited.contains(&child)) { - println!(child); - } else { - todo!(); - } - } - println!(""); - return false; - } - todo!() - } - - fn simulate(&self) -> bool { - let dag = self.gate_dag(); - for pair in dag { - for child in pair.1 { - print!("{:?}", child); - } - println!(""); - } - todo!() - } -} diff --git a/src/gate.rs b/src/gate.rs index 3925a45..8afe056 100644 --- a/src/gate.rs +++ b/src/gate.rs @@ -123,7 +123,6 @@ impl PartialEq for NotGate { } } - #[derive(Debug, Clone)] pub struct AndGate { id: usize, @@ -307,94 +306,134 @@ impl Chip { } } - fn add_input(&mut self, pin: Pin) { - self.input.push(pin); + pub fn add_input(&mut self, pin: Pin) { + self.pins.insert(pin.id, pin); + self.input.push(pin.id); } - fn add_output(&mut self, pin: Pin) { - self.output.push(pin); + pub fn add_output(&mut self, pin: Pin) { + self.pins.insert(pin.id, pin); + self.output.push(pin.id); } - fn add_gate(&mut self, gate: Gate) -> usize { + pub fn add_gate(&mut self, gate: Gate) -> usize { + // the output of a gate depends on its inputs + for pin_in in gate.input() { + self.connections + .entry(*gate.output()) + .and_modify(|val| val.push(*pin_in)) + .or_insert_with(|| vec![*pin_in]); + } let id = gate.id(); - self.gates.push(gate); + self.gates.insert(id, gate); id } - pub fn connect_gate(&mut self, from: &mut Gate, to: &mut Gate, to_pin_idx: usize) { - to.input_mut()[to_pin_idx] = Pin::new(PinType::GateInput, to.id(), 42); - self.connections - .entry(to.input()[to_pin_idx]) - .and_modify(|val| val.push(*from.output())) - .or_insert_with(|| vec![*from.output()]); - if !self.gates.contains(&from) { - // TODO: Remove this clone - self.add_gate(from.clone()); + pub fn connect_gate(&mut self, from: usize, to: usize, to_pin_idx: usize) { + let from_pin_id = self.gates.get(&from).unwrap().output().clone(); + let to_gate = self.gates.get_mut(&to).unwrap(); + let mut id = 42; + if to_gate.input().len() < 2 { + id = to_gate.add_input(0, &mut self.connections) } - if !self.gates.contains(&to) { - // TODO: Remove this clone - self.add_gate(to.clone()); + + // the inputs of some gate depends on the output of some other gate + self.connections + .entry(to_gate.input()[to_pin_idx]) + .and_modify(|val| val.push(from_pin_id)) + .or_insert_with(|| vec![from_pin_id]); + } + + pub fn pins(&self) -> HashMap<usize, &Pin> { + let mut pins = HashMap::new(); + for (_, gate) in &self.gates { + for (id, pin) in gate.pins() { + pins.insert(*id, pin); + } } + pins } - pub fn pins(&self) -> HashMap<usize, Vec<&Pin>> { + pub fn pins_mut(&mut self) -> HashMap<usize, &mut Pin> { let mut pins = HashMap::new(); - for gate in &self.gates { - for pin in gate.input() { - pins.entry(pin.id) - .and_modify(|val: &mut Vec<&Pin>| val.push(pin)) - .or_insert_with(|| vec![pin]); + for (_, gate) in &mut self.gates { + for (id, pin) in gate.pins_mut() { + pins.entry(*id).or_insert_with(|| pin); } - pins.entry(gate.output().id) - .and_modify(|val: &mut Vec<&Pin>| val.push(gate.output())) - .or_insert_with(|| vec![gate.output()]); } pins } pub fn gate_dag(&self) -> HashMap<usize, Vec<usize>> { + let pins = self.pins(); let mut dag = HashMap::new(); for connection in &self.connections { for pin in connection.1 { - dag.entry(connection.0.gate_id) - .and_modify(|val: &mut Vec<usize>| val.push(pin.gate_id)) - .or_insert_with(|| vec![pin.gate_id]); + match pins.get(connection.0).unwrap().kind { + PinType::GateInput => { + dag.entry(pins.get(connection.0).unwrap().gate_id) + .and_modify(|val: &mut Vec<usize>| { + val.push(pins.get(pin).unwrap().gate_id) + }) + .or_insert_with(|| vec![pins.get(pin).unwrap().gate_id]); + } + _ => {} + } } } dag } - pub fn pin_dag(&self) -> HashMap<usize, Vec<usize>> { - let mut gate_dag = self.gate_dag(); - let mut dag = HashMap::new(); - for (id, children) in gate_dag { - // dag.entry() - // .and_modify(|val: &mut Vec<usize>| val.push(pin.gate_id)) - // .or_insert_with(|| vec![pin.gate_id]); - } - dag + pub fn pin_dag(&self) -> &HashMap<usize, Vec<usize>> { + &self.connections + } + + fn set_gate_pin(&mut self, gate_id: usize, pin_id: &usize, val: Option<PinValue>) { + println!( + "Propagating: gate_{} with pin_{} to val = {:?}", + gate_id, pin_id, val + ); + self.gates.get_mut(&gate_id).unwrap().set_pin(pin_id, val); } fn simulate_helper( &mut self, - gate: usize, + gate_id: usize, visited: &mut HashSet<usize>, dag: &HashMap<usize, Vec<usize>>, ) { - visited.insert(gate); - if dag.contains_key(&gate) { - for child in dag.get(&gate).unwrap() { + visited.insert(gate_id); + if dag.contains_key(&gate_id) { + for child in dag.get(&gate_id).unwrap() { if !visited.contains(child) { self.simulate_helper(*child, visited, dag); } } - let pos = self.gates.iter().position(|g| g.id() == gate).unwrap(); - self.gates[pos].evaluate(); - println!("{}", gate); + self.gates.get_mut(&gate_id).unwrap().evaluate(); + self.propagate(gate_id); } else { - println!("{}", gate); - let pos = self.gates.iter().position(|g| g.id() == gate).unwrap(); - self.gates[pos].evaluate(); + self.gates.get_mut(&gate_id).unwrap().evaluate(); + self.propagate(gate_id); + } + } + + // TODO: Optimize this function specially the unecessary calling of self.pins() + fn propagate(&mut self, gate_id: usize) { + let pin_dag = self.pin_dag().clone(); + let pin_out_id = self.gates.get(&gate_id).unwrap().output().clone(); + let pin_out_val = { + let pins = self.pins(); + pins.get(&pin_out_id).unwrap().val + }; + let propagated_pins = pin_dag + .iter() + .filter(|(_, pins)| pins.contains(&pin_out_id)); + for (pin_id, _) in propagated_pins { + let pins = self.pins(); + if let Some(pin) = pins.get(&pin_id).cloned() { + let gate_id = pin.gate_id; + self.set_gate_pin(gate_id, pin_id, pin_out_val); + } } } @@ -406,6 +445,6 @@ impl Chip { self.simulate_helper(*child, &mut visited, &dag); } } - false + self.gates.get_mut(&8).unwrap().evaluate() } } diff --git a/src/main.rs b/src/main.rs index 9acda46..222af4b 100644 --- a/src/main.rs +++ b/src/main.rs @@ -10,40 +10,54 @@ use std::vec; fn main() { let mut _chip = Chip::new(); - let a: u8 = 0; - let b: u8 = 1; + let a: u8 = 1; + let b: u8 = 0; let input: Vec<PinValue> = vec![a, b]; println!("input: {:?}", input); - let mut gate_1 = Gate::new(GateType::And, input, PinType::ChipInput); - let mut gate_2 = Gate::new(GateType::Not, vec![], PinType::GateInput); - let mut gate_3 = Gate::new(GateType::And, vec![a], PinType::GateInput); - let mut gate_4 = Gate::new(GateType::Not, vec![], PinType::GateInput); - let mut gate_5 = Gate::new(GateType::And, vec![b], PinType::GateInput); - let mut gate_6 = Gate::new(GateType::Not, vec![], PinType::GateInput); - let mut gate_7 = Gate::new(GateType::And, vec![], PinType::GateInput); - let mut gate_8 = Gate::new(GateType::Not, vec![], PinType::GateInput); + let gate_1 = Gate::new(GateType::And, input, PinType::GateInput); + let gate_2 = Gate::new(GateType::Not, vec![], PinType::GateInput); + let gate_3 = Gate::new(GateType::And, vec![a], PinType::GateInput); + let gate_4 = Gate::new(GateType::Not, vec![], PinType::GateInput); + let gate_5 = Gate::new(GateType::And, vec![b], PinType::GateInput); + let gate_6 = Gate::new(GateType::Not, vec![], PinType::GateInput); + let gate_7 = Gate::new(GateType::And, vec![], PinType::GateInput); + let gate_8 = Gate::new(GateType::Not, vec![], PinType::GateInput); + + let gate_1_id = gate_1.id(); + let gate_2_id = gate_2.id(); + let gate_3_id = gate_3.id(); + let gate_4_id = gate_4.id(); + let gate_5_id = gate_5.id(); + let gate_6_id = gate_6.id(); + let gate_7_id = gate_7.id(); + let gate_8_id = gate_8.id(); let mut xor = Chip::new(); - xor.connect_gate(&mut gate_1, &mut gate_2, 0); - xor.connect_gate(&mut gate_2, &mut gate_3, 1); - xor.connect_gate(&mut gate_2, &mut gate_5, 1); - xor.connect_gate(&mut gate_3, &mut gate_4, 0); - xor.connect_gate(&mut gate_5, &mut gate_6, 0); - xor.connect_gate(&mut gate_4, &mut gate_7, 0); - xor.connect_gate(&mut gate_6, &mut gate_7, 1); - xor.connect_gate(&mut gate_7, &mut gate_8, 0); + xor.add_gate(gate_1); + xor.add_gate(gate_2); + xor.add_gate(gate_3); + xor.add_gate(gate_4); + xor.add_gate(gate_5); + xor.add_gate(gate_6); + xor.add_gate(gate_7); + xor.add_gate(gate_8); + + xor.connect_gate(gate_1_id, gate_2_id, 0); + xor.connect_gate(gate_2_id, gate_3_id, 1); + xor.connect_gate(gate_2_id, gate_5_id, 1); + xor.connect_gate(gate_3_id, gate_4_id, 0); + xor.connect_gate(gate_5_id, gate_6_id, 0); + xor.connect_gate(gate_4_id, gate_7_id, 0); + xor.connect_gate(gate_6_id, gate_7_id, 1); + xor.connect_gate(gate_7_id, gate_8_id, 0); let dag = xor.gate_dag(); + let output = xor.simulate(); + println!("Output: {:?}", output); + // println!("connections: {:#?}", xor.connections); + // println!("pins: {:?}", xor.pin_dag()); // println!("pins: {:#?}", xor.pins()); - println!("dag: {:#?}", dag); - // println!("dag: {:#?}", xor.gates); - // xor.simulate(); - // println!( - // "Output: {:?}\n Gate = {:?}", - // &mut gate_8.evaluate(), - // gate_8.clone(), - // ); } // #[macroquad::main("lgsim")] @@ -22,6 +22,7 @@ impl Pin { static mut ID: usize = 0; unsafe { ID += 1; + // println!("Creating pin with id: {} and gate_id: {}", ID, gate_id); match kind { PinType::Undetermined => Pin { id: ID, |
