diff options
Diffstat (limited to 'src/gate.rs')
| -rw-r--r-- | src/gate.rs | 401 |
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!() } } |
