summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authoromagdy7 <omar.professional8777@gmail.com>2023-11-29 00:13:13 +0200
committeromagdy7 <omar.professional8777@gmail.com>2023-11-29 00:13:13 +0200
commitf8e2ec0f8ddfa44def90d8d3d1532877d251ece2 (patch)
tree434fc365d665fdd776d4ecea008ed6dfb9cfa10c /src
parentfb4ba46a7fa9055a7848d8e0fa3daed2ce0b014f (diff)
downloadlgsim-f8e2ec0f8ddfa44def90d8d3d1532877d251ece2.tar.xz
lgsim-f8e2ec0f8ddfa44def90d8d3d1532877d251ece2.zip
Added full implementation of simulating a Chip
Diffstat (limited to 'src')
-rw-r--r--src/gate.rs141
-rw-r--r--src/main.rs66
-rw-r--r--src/pin.rs1
3 files changed, 131 insertions, 77 deletions
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")]
diff --git a/src/pin.rs b/src/pin.rs
index 2602d26..0ee7523 100644
--- a/src/pin.rs
+++ b/src/pin.rs
@@ -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,