diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/gate.rs | 401 | ||||
| -rw-r--r-- | src/gate_ui.rs | 140 | ||||
| -rw-r--r-- | src/input_layout.rs | 25 | ||||
| -rw-r--r-- | src/main.rs | 109 | ||||
| -rw-r--r-- | src/output_layout.rs | 25 | ||||
| -rw-r--r-- | src/pin.rs | 41 | ||||
| -rw-r--r-- | src/types.rs | 9 | ||||
| -rw-r--r-- | src/wire.rs | 7 |
8 files changed, 561 insertions, 196 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!() } } diff --git a/src/gate_ui.rs b/src/gate_ui.rs new file mode 100644 index 0000000..f74b9fa --- /dev/null +++ b/src/gate_ui.rs @@ -0,0 +1,140 @@ +use crate::wire::*; +use macroquad::prelude::*; + +pub struct Rec { + x: f32, + y: f32, + w: f32, + h: f32, + color: Color, +} + +#[derive(Default, Debug, PartialEq)] +enum State { + #[default] + Idle, + DragStart, + Dragging, + DragStop, +} + +#[derive(Debug, Clone)] +pub struct Connection { + wire: Option<Box<Wire>>, + pub pos: (f32, f32), + pub radius: f32, + pub color: Color, + pub on: bool, +} + +impl Rec { + pub fn new(x: f32, y: f32, w: f32, h: f32, color: Color) -> Self { + Rec { x, y, w, h, color } + } + + 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 + } + + fn draw(&self) { + draw_rectangle(self.x, self.y, self.w, self.h, self.color); + } +} + +impl Connection { + pub fn new(radius: f32, pos: (f32, f32), color: Color, on: bool) -> Connection { + Connection { + wire: None, + pos, + radius, + color, + on, + } + } + + pub fn draw(&self) { + draw_circle( + self.pos.0, + self.pos.1, + self.radius, + if self.on { self.color } else { GRAY }, + ); + } + + fn contains(&self, pos: (f32, f32)) -> bool { + pos.0 <= self.pos.0 + self.radius + && pos.1 <= self.pos.1 + self.radius + && pos.0 >= self.pos.0 - self.radius + && pos.1 >= self.pos.1 - self.radius + } +} + +pub struct Gate<'a> { + rect: Rec, + input: Vec<Connection>, + output: Connection, + label: &'a str, + state: State, +} + +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(), + } + } + + 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; + } + + 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(); + } + _ => { + self.draw_helper(); + } + } + } + + fn draw_helper(&mut self) { + // draws the structure of the gate + self.rect.draw(); + + // 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(); + } + + // 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(); + } +} diff --git a/src/input_layout.rs b/src/input_layout.rs deleted file mode 100644 index 2b086a3..0000000 --- a/src/input_layout.rs +++ /dev/null @@ -1,25 +0,0 @@ -use crate::gate::*; -use macroquad::prelude::*; - -pub struct InputLayout { - inputs: Vec<Connection>, -} - -impl InputLayout { - pub fn new(inputs: Vec<Connection>) -> Self { - InputLayout { inputs } - } - pub fn draw(&self) { - let playground_offset_x: f32 = screen_width() / 20.; - let playground_offset_y: f32 = screen_height() / 14.; - let playground_height: f32 = screen_height() - playground_offset_y * 2.0; - for (cnt, node) in self.inputs.iter().enumerate() { - draw_circle( - playground_offset_x, - playground_height / 3.0 + 25. + (30. * cnt as f32), - node.radius, - if node.on { node.color } else { GRAY }, - ); - } - } -} diff --git a/src/main.rs b/src/main.rs index 6b95a83..a70ace9 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,52 +1,77 @@ -use macroquad::prelude::*; +#![allow(dead_code)] mod gate; -mod input_layout; -mod output_layout; -mod wire; -use gate::*; -use input_layout::*; -use output_layout::*; -use wire::*; - -#[macroquad::main("lgsim")] -async fn main() { - let mut gate = Gate::new( - Rec::new(500., 500., 120., 80., RED), - vec![Connection::new(10., (0.0, 0.0), GREEN, false); 2], - "GATE", - Connection::new(10., (0.0, 0.0), GREEN, false), - ); +mod pin; +mod types; +use crate::gate::*; +use crate::pin::*; +use crate::types::*; +use std::vec; + +// Define a struct to represent the Circuit +#[derive(Debug, Clone)] +struct Circuit { + chips: Chips, +} - let input_layout = InputLayout::new(vec![Connection::new(10., (0.0, 0.0), GREEN, false); 16]); - let output_layout = OutputLayout::new(vec![Connection::new(10., (0.0, 0.0), GREEN, false); 16]); +impl Circuit { + fn new() -> Circuit { + Circuit { chips: Vec::new() } + } + + fn add_chip(&mut self, chip: Chip) -> usize { + self.chips.push(chip); + 0 + } - loop { - let playground_offset_x: f32 = screen_width() / 20.; - let playground_offset_y: f32 = screen_height() / 14.; - let playground_width: f32 = screen_width() - playground_offset_x * 2.0; - let playground_height: f32 = screen_height() - playground_offset_y * 2.0; - clear_background(color_u8!(27, 27, 27, 255)); + fn connect_chip(&mut self, from: usize, to: usize) { + todo!() + } - // Process keys, mouse etc. + fn simulate(&mut self) { + todo!(); + } +} - draw_rectangle_lines( - playground_offset_x, - playground_offset_y, - playground_width, - playground_height, - 6., - WHITE, - ); +fn main() { + let mut _chip = Chip::new(); + let a: u8 = 1; + let b: u8 = 1; + 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); - // Draw things before egui - input_layout.draw(); - output_layout.draw(); - gate.draw(); + let mut xor = Chip::new(); - // egui_macroquad::draw(); + 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); - // Draw things after egui + // let dag = xor.gate_dag(); + let mut sorted = xor.pins(); + sorted.sort_by(|&x, &y| x.id.cmp(&y.id)); - next_frame().await; - } + // println!("pins: {:#?}", sorted); + // println!("connections: {:#?}", xor.connections); + // println!("dag: {:#?}", dag); + println!( + "Gate: {:?}\n output = {:?}", + &mut gate_8.evaluate(), + gate_8.clone(), + ); } + +// #[macroquad::main("lgsim")] +// async fn main() { +// } diff --git a/src/output_layout.rs b/src/output_layout.rs deleted file mode 100644 index efe4875..0000000 --- a/src/output_layout.rs +++ /dev/null @@ -1,25 +0,0 @@ -use crate::gate::*; -use macroquad::prelude::*; - -pub struct OutputLayout { - outputs: Vec<Connection>, -} - -impl OutputLayout { - pub fn new(outputs: Vec<Connection>) -> Self { - OutputLayout { outputs } - } - pub fn draw(&self) { - let playground_offset_x: f32 = screen_width() / 20.; - let playground_offset_y: f32 = screen_height() / 14.; - let playground_height: f32 = screen_height() - playground_offset_y * 2.0; - for (cnt, node) in self.outputs.iter().enumerate() { - draw_circle( - screen_width() - playground_offset_x, - playground_height / 3.0 + 25. + (30. * cnt as f32), - node.radius, - if node.on { node.color } else { GRAY }, - ); - } - } -} diff --git a/src/pin.rs b/src/pin.rs new file mode 100644 index 0000000..2602d26 --- /dev/null +++ b/src/pin.rs @@ -0,0 +1,41 @@ +use crate::types::*; + +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +pub enum PinType { + Undetermined, + ChipInput, + GateInput, + GateOutput, + ChipOutput, +} + +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +pub struct Pin { + pub id: usize, + pub kind: PinType, + pub gate_id: usize, + pub val: Option<PinValue>, +} + +impl Pin { + pub fn new(kind: PinType, gate_id: usize, val: PinValue) -> Self { + static mut ID: usize = 0; + unsafe { + ID += 1; + match kind { + PinType::Undetermined => Pin { + id: ID, + gate_id, + kind, + val: None, + }, + _ => Pin { + id: ID, + gate_id, + kind, + val: Some(val), + }, + } + } + } +} diff --git a/src/types.rs b/src/types.rs new file mode 100644 index 0000000..5425649 --- /dev/null +++ b/src/types.rs @@ -0,0 +1,9 @@ +use crate::gate::*; +use crate::pin::*; +use std::collections::HashMap; + +pub type PinValue = u8; +pub type Pins = Vec<Pin>; +pub type Gates = Vec<Gate>; +pub type Chips = Vec<Chip>; +pub type Connections = HashMap<Pin, Vec<Pin>>; diff --git a/src/wire.rs b/src/wire.rs deleted file mode 100644 index 70e2a2c..0000000 --- a/src/wire.rs +++ /dev/null @@ -1,7 +0,0 @@ -use crate::gate::*; - -#[derive(Clone, Debug)] -pub struct Wire { - src: Connection, - dst: Connection, -} |
