summaryrefslogtreecommitdiff
path: root/src/gate.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/gate.rs')
-rw-r--r--src/gate.rs401
1 files changed, 304 insertions, 97 deletions
diff --git a/src/gate.rs b/src/gate.rs
index 1d869e1..87ae219 100644
--- a/src/gate.rs
+++ b/src/gate.rs
@@ -1,133 +1,340 @@
-use crate::wire::*;
-use macroquad::prelude::*;
+use crate::pin::*;
+use crate::types::*;
+use std::collections::HashMap;
-pub struct Rec {
- x: f32,
- y: f32,
- w: f32,
- h: f32,
- color: Color,
+#[derive(Debug)]
+pub enum GateType {
+ And,
+ Or,
+ Not,
+ Buffer,
+ Chip,
}
-#[derive(Default, Debug, PartialEq)]
-enum State {
- #[default]
- Idle,
- DragStart,
- Dragging,
- DragStop,
+#[derive(Debug, Clone, PartialEq)]
+pub enum Gate {
+ And(AndGate),
+ Or(OrGate),
+ Not(NotGate),
+ Buffer(BufferGate),
+ Chip(Chip),
}
-#[derive(Debug, Clone)]
-pub struct Connection {
- wire: Option<Box<Wire>>,
- pub pos: (f32, f32),
- pub radius: f32,
- pub color: Color,
- pub on: bool,
+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 Rec {
- pub fn new(x: f32, y: f32, w: f32, h: f32, color: Color) -> Self {
- Rec { x, y, w, h, color }
+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
+ }
+}
- fn contains(&self, pos: (f32, f32)) -> bool {
- pos.0 >= self.x && pos.0 <= self.x + self.w && pos.1 >= self.y && pos.1 <= self.y + self.h
+impl PartialEq for NotGate {
+ fn eq(&self, other: &Self) -> bool {
+ self.id == other.id
}
+}
- fn draw(&self) {
- draw_rectangle(self.x, self.y, self.w, self.h, self.color);
+impl PartialEq for BufferGate {
+ fn eq(&self, other: &Self) -> bool {
+ self.id == other.id
}
}
-impl Connection {
- pub fn new(radius: f32, pos: (f32, f32), color: Color, on: bool) -> Connection {
- Connection {
- wire: None,
- pos,
- radius,
- color,
- on,
+#[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),
+ }
}
}
- pub fn draw(&self) {
- draw_circle(
- self.pos.0,
- self.pos.1,
- self.radius,
- if self.on { self.color } else { GRAY },
- );
+ 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
}
}
-pub struct Gate<'a> {
- rect: Rec,
- input: Vec<Connection>,
- output: Connection,
- label: &'a str,
- state: State,
+#[derive(Debug, Clone)]
+pub struct OrGate {
+ id: usize,
+ input: Pins,
+ output: Pin,
}
-impl<'a> Gate<'a> {
- pub fn new(rect: Rec, input: Vec<Connection>, label: &'a str, output: Connection) -> Gate {
- Gate {
- rect,
- input,
- output,
- label,
- state: State::default(),
+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),
}
}
- pub fn draw(&mut self) {
- if is_mouse_button_pressed(MouseButton::Left) && self.rect.contains(mouse_position()) {
- self.state = State::DragStart;
- } else if is_mouse_button_down(MouseButton::Left)
- && self.rect.contains(mouse_position())
- && self.state == State::DragStart
- || self.state == State::Dragging
- {
- self.state = State::Dragging;
- }
- if is_mouse_button_released(MouseButton::Left) {
- self.state = State::DragStop;
- }
+ 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,
+}
- match self.state {
- State::Dragging => {
- self.rect.x = mouse_position().0 - self.rect.w / 2.0;
- self.rect.y = mouse_position().1 - self.rect.h / 2.0;
- self.draw_helper();
+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),
}
- _ => {
- self.draw_helper();
+ } 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 draw_helper(&mut self) {
- // draws the structure of the gate
- self.rect.draw();
+ 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
+ }
+}
- // draws input
- for (cnt, node) in self.input.iter_mut().enumerate() {
- node.pos = (self.rect.x, self.rect.y + 25. + (30. * cnt as f32));
- node.draw();
+#[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) {
+ self.connections
+ .entry(to.input()[to_pin_idx])
+ .and_modify(|val| val.push(*from.output()))
+ .or_insert_with(|| vec![*from.output()]);
+ // self.connections
+ // .entry(to.input()[to_pin_idx].id)
+ // .or_insert(vec![from.output().id]);
+ from.evaluate();
+ to.input_mut()[to_pin_idx] =
+ Pin::new(PinType::GateInput, to.id(), from.output().val.unwrap());
+ 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
+ }
+
+ // fn gate_dag(&self) -> HashMap<&Pin, Vec<&Pin>> {
+ // let mut dag = HashMap::new();
+ // for connection in &self.connections {
+ // for pin in *connection.1 {
+ // dag.entry(*connection.0)
+ // .and_modify(|val: &mut Vec<&Pin>| val.push(pin))
+ // .or_insert_with(|| vec![pin]);
+ // }
+ // }
+ // dag
+ // }
- // draws label
- draw_text(
- self.label,
- self.rect.x + self.rect.w / 2.0,
- self.rect.y + self.rect.h / 2.0,
- 20.0,
- WHITE,
- );
-
- // draws output
- self.output.pos = (self.rect.x + self.rect.w, self.rect.y + self.rect.h / 2.);
- self.output.draw();
+ fn simulate(&self) -> bool {
+ todo!()
}
}