summaryrefslogtreecommitdiff
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
parentfb4ba46a7fa9055a7848d8e0fa3daed2ce0b014f (diff)
downloadlgsim-f8e2ec0f8ddfa44def90d8d3d1532877d251ece2.tar.xz
lgsim-f8e2ec0f8ddfa44def90d8d3d1532877d251ece2.zip
Added full implementation of simulating a Chip
-rw-r--r--'361
-rw-r--r--src/gate.rs141
-rw-r--r--src/main.rs66
-rw-r--r--src/pin.rs1
4 files changed, 131 insertions, 438 deletions
diff --git a/' b/'
deleted file mode 100644
index 3334efe..0000000
--- a/'
+++ /dev/null
@@ -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")]
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,