logic_o3/
logic.rs

1use core::panic;
2use std::{cell::RefCell, rc::Rc};
3
4pub struct Circuit {
5    component: Vec<LogicCircuit>,                // Vec[and1, or1, not1]
6    connection_path: Vec<(usize, usize, usize)>, // Vev[(from_comp_id, to_comp_id, to_input_index)]
7    input: Vec<Rc<RefCell<(bool, Vec<(usize, usize)>)>>>, // Vec[(Input_Binary , Vec[(to_id, to_input_index)])]
8    output: Vec<Rc<RefCell<(Vec<usize>, bool)>>>,         // Vec[(from_id, Output_Binary)]
9                                                          // update method require for change output
10}
11
12impl Circuit {
13    /// Create Circuit
14    pub fn new() -> Self {
15        Self {
16            component: vec![],
17            connection_path: vec![],
18            input: vec![],
19            output: vec![],
20        }
21    }
22    /// Add component AKA LogicCircuit
23    pub fn add_logic_gate(&mut self, new_comp: LogicCircuit) {
24        self.component.push(new_comp)
25    }
26    /// Connect Between Component
27    pub fn connection_scheme(&mut self, connection: (usize, usize, usize)) {
28        if self.component.len() < connection.0 {
29            dbg!(println!(
30                "WARNING: According your instructed FROM_ID is not Exist"
31            ))
32        }
33        self.connection_path.push(connection)
34    }
35    /// Add Input on Circuit
36    pub fn add_input(&mut self, no_of_input: usize) {
37        match no_of_input {
38            0 => dbg!(println!("WARNING: Number of Input Cannot be Zero")),
39            _ => {
40                for _ in 1..=no_of_input {
41                    self.input.push(Rc::new(RefCell::new((false, vec![]))))
42                }
43            }
44        }
45    }
46    /// Add Input with connection
47    pub fn add_input_connection(&mut self, connection: (bool, Vec<(usize, usize)>)) {
48        self.input.push(Rc::new(RefCell::new(connection)))
49    }
50    /// Change Input Signal
51    pub fn change_input_signal(&mut self, input_index: usize, change_to: bool) {
52        match *(*self.input[input_index]).borrow_mut() {
53            (ref mut signal, _) => *signal = change_to,
54        }
55    }
56    /// Add Input config to attach component AKA wiring between LogicCircuit and Input Signal
57    pub fn change_input_config(
58        &mut self,
59        connection: (bool, Vec<(usize, usize)>),
60        input_index: usize,
61    ) {
62        if self.input.len() < input_index {
63            dbg!(println!(
64                "WARNING: according your instructed input index is out of Bound"
65            ))
66        } else {
67            *(*self.input[input_index]).borrow_mut() = connection
68        }
69    }
70    /// Add Output Signal to know Output.
71    pub fn add_output_connection(&mut self, comp_id: usize) {
72        self.output
73            .push(Rc::new(RefCell::new((vec![comp_id], false))))
74    }
75    /// Adding more comp on specific Output
76    pub fn add_comp_onoutput(&mut self, comp_id: usize, output_index: usize) {
77        match *(*self.output[output_index]).borrow_mut() {
78            (ref mut x, _) => x.push(comp_id),
79        }
80    }
81    /// Know Number of output
82    pub fn know_no_output(&self) -> usize {
83        self.output.len()
84    }
85    /// Know Output on Specific component
86    pub fn know_output_comp(&self, comp_id: usize) -> bool {
87        *(*self.component[comp_id].output).borrow_mut()
88    }
89    /// Know Output of Circuit
90    pub fn know_output(&mut self) -> Vec<bool> {
91        let mut out = vec![];
92        for out_each in self.output.clone() {
93            match *(*out_each).borrow_mut() {
94                (_, output) => out.push(output),
95            }
96        }
97        out
98    }
99    /// Refresh The Cicuit to update Output
100    pub fn update(&mut self) {
101        let mut count = 0;
102        {
103            while count != self.input.len() {
104                match &(*(*self.input[count]).borrow_mut()) {
105                    (x, y) => {
106                        // KNOW: x is input boolean and y is input connection
107                        for i in y {
108                            // KNOW: i has two value tuples (id_component, index_component)
109                            self.component[i.0].change_input_config(i.1, *x);
110                            self.component[i.0].update()
111                        }
112                    }
113                }
114                count += 1;
115            }
116            count = 0;
117        }
118        {
119            while count != self.connection_path.len() {
120                match self.connection_path[count] {
121                    (from_comp, to_comp, to_pin_index) => {
122                        self.component[to_comp].input[to_pin_index] =
123                            Rc::clone(&self.component[from_comp].output);
124                        self.component[to_comp].update();
125                        // Due to borrowing Conflict
126                        // self.component[from_comp]
127                        //     .connect_head_to(&mut self.component[to_comp], to_pin_index);
128                    }
129                }
130                count += 1
131            }
132            count = 0
133        }
134        {
135            while count != self.output.len() {
136                match *(*self.output[count]).borrow_mut() {
137                    (ref mut x, ref mut out) => {
138                        let mut output = false;
139                        for by_comp in x {
140                            self.component[*by_comp].update();
141                            output = output || self.know_output_comp(*by_comp);
142                        }
143                        *out = output
144                    }
145                }
146                count += 1
147            }
148        }
149    }
150    //TODO: Add removing specific comp also destroy connected connection
151}
152
153pub enum LogicGate {
154    AND, // AND Gate
155    NOT, // NOT Gate
156    OR,  // OR Gate
157}
158
159pub struct LogicCircuit {
160    input: Vec<Rc<RefCell<bool>>>, // Input pin indexing like [true, false, false, false]
161    gate_type: LogicGate,          // Which Logic Gate
162    output: Rc<RefCell<bool>>,     // Single output pin
163}
164/// To Know LogicCircuit Current supply.
165impl ToString for LogicCircuit {
166    fn to_string(&self) -> String {
167        use LogicGate::{AND, NOT, OR};
168        let mut input = String::new();
169        for i in 1..=self.input.len() {
170            input.push_str(match *(*self.input[i - 1]).borrow() {
171                true => "\x1b[32m \x1b[0m",
172                _ => "\x1b[31m \x1b[0m",
173            })
174        }
175        match self.gate_type {
176            NOT => {
177                format!("{}󰣤 {}", input, {
178                    if *(*self.output).borrow() {
179                        "\x1b[32m\x1b[0m"
180                    } else {
181                        "\x1b[31m\x1b[0m"
182                    }
183                })
184            }
185            AND => {
186                format!("{}{}󰣡 {}", input, self.input.len(), {
187                    if *(*self.output).borrow() {
188                        "\x1b[32m\x1b[0m"
189                    } else {
190                        "\x1b[31m\x1b[0m"
191                    }
192                })
193            }
194            OR => {
195                format!("{}{}󰣥 {}", input, self.input.len(), {
196                    if *(*self.output).borrow() {
197                        "\x1b[32m\x1b[0m"
198                    } else {
199                        "\x1b[31m\x1b[0m"
200                    }
201                })
202            }
203        }
204    }
205}
206
207impl LogicCircuit {
208    /// Create LogicCircuit
209    pub fn new(logic_type: LogicGate) -> Self {
210        match logic_type {
211            LogicGate::NOT => LogicCircuit {
212                input: vec![Rc::new(RefCell::new(false))],
213                gate_type: logic_type,
214                output: RefCell::new(true).into(),
215            },
216            _ => {
217                let mut sample_gate = LogicCircuit {
218                    input: vec![Rc::new(RefCell::new(false)); 2],
219                    gate_type: logic_type,
220                    output: RefCell::new(false).into(),
221                };
222                sample_gate.update();
223                sample_gate
224            }
225        }
226    }
227    /// Add LogicCircuit with number of pins
228    pub fn new_with_pins(logic_type: LogicGate, number: usize) -> Self {
229        match number {
230            0 | 1 => panic!("Zero or One It sould not Exist"),
231            _ => match logic_type {
232                LogicGate::NOT => panic!(
233                    "NOT Gate Should have only single input pin 
234                \n So you can try new instead of new_with_pins"
235                ),
236                _ => {
237                    let mut sample_gate = LogicCircuit {
238                        input: vec![Rc::new(RefCell::new(false)); number],
239                        gate_type: logic_type,
240                        output: RefCell::new(false).into(),
241                    };
242                    sample_gate.update();
243                    sample_gate
244                }
245            },
246        }
247    }
248    /// To update the LogicCircuit
249    pub fn update(&mut self) {
250        use LogicGate::{AND, NOT, OR};
251        let input = |index: usize| *(*self.input[index]).borrow_mut();
252        let input_len = self.input.len();
253        match self.gate_type {
254            NOT => match input_len {
255                1 => *(*self.output).borrow_mut() = !input(0),
256                _ => panic!("Wrong Input Config"),
257            },
258            AND => match input_len {
259                0 | 1 => dbg!(println!("Zero and Single input doesn't exist in AND Gate")),
260                _ => {
261                    let mut step = 0;
262                    while self.input.len() != step + 1 {
263                        *(*self.output).borrow_mut() = input(step) && input(step + 1);
264                        step += 1
265                    }
266                }
267            },
268            OR => match input_len {
269                0 | 1 => dbg!(println!("Zero and Single input doesn't exist in AND Gate")),
270                _ => {
271                    let mut step = 0;
272                    while self.input.len() != step + 1 {
273                        *(*self.output).borrow_mut() = input(step) || input(step + 1);
274                        step += 1
275                    }
276                }
277            },
278        }
279    }
280    pub fn change_input_config(&mut self, index: usize, change_to: bool) {
281        self.input[index] = Rc::new(change_to.into());
282        self.update()
283    }
284    // Connect self output pin to other input gate pin
285    // KNOW: `self` is own LogicCircuit where `other` is other LogicCircuit where`index` represent
286    // other gate input pin index
287    #[deprecated]
288    pub fn connect_head_to(&mut self, other: &mut Self, index: usize) {
289        other.input[index] = Rc::clone(&self.output);
290        self.update();
291        other.update()
292    }
293}