1use crate::linked_lists::{ElementIndex, LinkedLists, ListIndex};
8use crate::network_simulator;
9use crate::traits::{BooleanSystem, NumInputs, NumOutputs, PartialBooleanSystem};
10use crate::truth_table::small_lut::truth_table_library;
11
12use crate::network::*;
13use crate::truth_table::small_lut::SmallTruthTable;
14use itertools::Itertools;
15use smallvec::SmallVec;
16
17use fnv::FnvHashMap;
18use std::hash::Hash;
19
20use super::SimplifyResult;
21
22#[derive(Clone, Default)]
24pub struct LogicNetwork<Node> {
25 storage: Vec<NodeWithReferences<Node>>,
26 primary_inputs: Vec<NodeId>,
27 primary_outputs: Vec<NodeId>,
28 hash_table: FnvHashMap<Node, NodeId>,
31
32 references: LinkedLists<NodeId>,
34 edges: LinkedLists<(NodeId, ElementIndex)>,
35}
36
37impl<Node> LogicNetwork<Node> {
38 pub fn new() -> Self {
40 Self {
41 storage: Default::default(),
42 primary_inputs: Default::default(),
43 primary_outputs: Default::default(),
44 hash_table: Default::default(),
45 references: Default::default(),
46 edges: Default::default(),
47 }
48 }
49}
50
51#[derive(Clone, Default)]
53struct NodeWithReferences<N> {
54 node: N,
56 references: ListIndex,
59 outgoing_edges: ListIndex,
60}
61
62impl<N> From<N> for NodeWithReferences<N> {
63 fn from(n: N) -> Self {
64 Self {
65 node: n,
66 references: ListIndex::Empty,
67 outgoing_edges: ListIndex::Empty,
68 }
69 }
70}
71
72#[derive(Clone, Copy, Hash, PartialEq, PartialOrd, Eq, Ord)]
76pub struct NodeId {
77 index: usize,
79}
80
81impl std::fmt::Debug for NodeId {
82 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
83 if self.is_constant() {
84 write!(
85 f,
86 "NodeId(constant = {})",
87 if self.is_zero() { "0" } else { "1" }
88 )
89 } else if self.is_input() {
90 write!(
91 f,
92 "NodeId(input({}), inverted = {})",
93 self.input_index().unwrap(),
94 self.is_inverted()
95 )
96 } else {
97 write!(
98 f,
99 "NodeId(index: {}, is_inverted: {})",
100 self.node_index().unwrap(),
101 self.is_inverted(),
102 )
103 }
104 }
105}
106
107impl NodeId {
108 pub(super) fn zero() -> Self {
110 Self { index: 0 }
111 }
112
113 pub(super) fn node_index(&self) -> Option<usize> {
116 (!self.is_constant() && !self.is_input()).then(|| {
117 let masked = self.index >> 1; masked - 1
119 })
120 }
121
122 pub fn input_index(&self) -> Option<usize> {
124 self.is_input().then(|| {
125 let input_marker_bit = 1 << (usize::BITS - 1);
126 (!input_marker_bit & self.index) >> 1 })
128 }
129
130 pub(super) fn new_node_id(index: usize) -> Self {
132 let index = index + 1; let index = index << 1; assert!(
135 index < (1 << (usize::BITS - 1)),
136 "index out of supported range"
137 );
138 Self { index }
139 }
140
141 pub(super) fn new_input_node(index: usize) -> Self {
143 let index = index << 1; assert!(
145 index < (1 << (usize::BITS - 1)),
146 "index out of supported range"
147 );
148 let input_marker_bit = 1 << (usize::BITS - 1);
149
150 Self {
151 index: index | input_marker_bit,
152 }
153 }
154
155 pub fn is_input(&self) -> bool {
157 let input_marker_bit = 1 << (usize::BITS - 1);
158 (self.index & input_marker_bit) != 0
159 }
160
161 pub fn is_constant(&self) -> bool {
163 self.is_zero() || self.is_one()
164 }
165
166 pub fn is_zero(&self) -> bool {
168 self.index == 0
169 }
170
171 pub fn is_one(&self) -> bool {
173 self.invert().index == 0
174 }
175}
176
177impl<Node> LogicNetwork<Node>
178where
179 Node: NetworkNode + Hash + MutNetworkNodeWithReferenceCount + IntoIterator<Item = NodeId>,
180{
181 fn insert_node(&mut self, node: Node) -> NodeId {
184 let index = self.storage.len();
192 self.storage.push(node.clone().into());
193 let new_id = NodeId::new_node_id(index);
194 let old_node = self.hash_table.insert(node.clone(), new_id);
195 debug_assert!(old_node.is_none(), "node already exists");
196
197 {
200 node.into_iter()
202 .dedup()
203 .filter_map(|fan_in_node_id| fan_in_node_id.node_index())
204 .for_each(|fan_in_node_index| {
205 self.insert_reverse_edge(new_id, fan_in_node_index);
206 })
207 }
208
209 new_id
210 }
211
212 fn insert_reverse_edge(&mut self, node_id: NodeId, fan_in_node: usize) {
214 self.storage[fan_in_node].node.reference();
216
217 let list_of_references = &mut self.storage[fan_in_node].references;
219 let edge_id = self.references.prepend(list_of_references, node_id);
220
221 let list_of_edges = &mut self.storage[fan_in_node].outgoing_edges;
222 self.edges
223 .prepend(list_of_edges, (NodeId::new_node_id(fan_in_node), edge_id));
224 }
225
226 fn simplify_node_with_hashtable(&self, node: Node) -> SimplifyResult<Node, NodeId> {
229 self.hash_table
230 .get(&node)
231 .map(|s| SimplifyResult::Simplified(*s, false))
232 .unwrap_or(SimplifyResult::new_node(node))
233 }
234}
235
236impl<Node> ReferenceCounted for LogicNetwork<Node>
237where
238 Node: NetworkNode<NodeId = NodeId> + NetworkNodeWithReferenceCount,
239{
240 fn num_references(&self, a: Self::Signal) -> usize {
241 if let Some(idx) = a.node_index() {
242 self.storage[idx].node.num_references()
243 } else {
244 0
246 }
247 }
248}
249
250impl<Node> LogicNetwork<Node> {
251 pub fn get_node(&self, node_id: NodeId) -> GeneralNode<&Node> {
253 if let Some(idx) = node_id.node_index() {
254 GeneralNode::Node(&self.storage[idx].node)
255 } else if let Some(idx) = node_id.input_index() {
256 GeneralNode::Input(idx)
257 } else {
258 assert!(node_id.is_constant());
259 GeneralNode::Constant(!node_id.is_zero())
260 }
261 }
262
263 pub fn get_logic_node_mut(&mut self, node_id: NodeId) -> Option<&mut Node> {
266 node_id.node_index().map(|idx| &mut self.storage[idx].node)
267 }
268}
269
270impl Edge for NodeId {}
271
272impl EdgeWithInversion for NodeId {
273 fn is_inverted(&self) -> bool {
274 self.index & 0b1 == 1
275 }
276
277 fn invert(self) -> Self {
278 Self {
279 index: self.index ^ 0b1,
280 }
281 }
282
283 fn non_inverted(self) -> Self {
285 Self {
286 index: self.index & !0b1,
287 }
288 }
289}
290
291#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq, Ord, PartialOrd)]
293pub enum GeneralNode<Node> {
294 Node(Node),
296 Input(usize),
298 Constant(bool),
300}
301
302impl<Node> GeneralNode<Node> {
303 pub fn to_logic_node(self) -> Option<Node> {
305 match self {
306 Self::Node(m) => Some(m),
307 _ => None,
308 }
309 }
310 pub fn to_constant(self) -> Option<bool> {
312 match self {
313 Self::Constant(c) => Some(c),
314 _ => None,
315 }
316 }
317 pub fn to_input(self) -> Option<usize> {
319 match self {
320 Self::Input(idx) => Some(idx),
321 _ => None,
322 }
323 }
324}
325
326impl<Node> Network for LogicNetwork<Node>
327where
328 Node: NetworkNode<NodeId = NodeId>,
329{
330 type Node = Node;
331 type NodeId = NodeId;
332 type Signal = NodeId;
333 type LogicValue = bool;
334 type NodeFunction = SmallTruthTable;
335
336 fn num_gates(&self) -> usize {
337 self.storage.len()
338 }
339
340 fn num_primary_inputs(&self) -> usize {
341 self.primary_inputs.len()
342 }
343
344 fn num_primary_outputs(&self) -> usize {
345 self.primary_outputs.len()
346 }
347
348 fn foreach_gate(&self, f: impl Fn(Self::Signal)) {
349 (0..self.storage.len()).map(NodeId::new_node_id).for_each(f)
350 }
351
352 fn foreach_node(&self, f: impl Fn(&Self::Node)) {
353 self.storage.iter().for_each(|n| f(&n.node));
354 }
355
356 fn get_constant(&self, value: Self::LogicValue) -> Self::Signal {
357 match value {
358 false => NodeId::zero(),
359 true => NodeId::zero().invert(),
360 }
361 }
362
363 fn get_constant_value(&self, signal: Self::Signal) -> Option<Self::LogicValue> {
364 if signal.is_zero() {
365 Some(false)
366 } else if signal.is_one() {
367 Some(true)
368 } else {
369 None
370 }
371 }
372
373 fn get_node_input(&self, node: &Self::Signal, input_index: usize) -> Self::Signal {
374 match self.get_node(*node) {
375 GeneralNode::Node(n) => n.get_input(input_index),
376 GeneralNode::Input(_) => panic!("primary input has no inputs"),
377 GeneralNode::Constant(_) => panic!("constant has no inputs"),
378 }
379 }
380
381 fn get_source_node(&self, signal: &Self::Signal) -> Self::NodeId {
382 signal.non_inverted()
383 }
384
385 fn get_primary_input(&self, index: usize) -> Self::Signal {
386 self.primary_inputs[index]
387 }
388
389 fn get_primary_output(&self, index: usize) -> Self::Signal {
390 self.primary_outputs[index]
391 }
392
393 fn is_constant(&self, signal: Self::Signal) -> bool {
394 signal.is_constant()
395 }
396
397 fn is_input(&self, signal: Self::Signal) -> bool {
398 signal.is_input()
399 }
400
401 fn node_function(&self, node: Self::Signal) -> Self::NodeFunction {
402 match self.get_node(node) {
403 GeneralNode::Node(n) => n.function(),
404 GeneralNode::Input(_) => truth_table_library::identity1(),
405 GeneralNode::Constant(c) => SmallTruthTable::new(|[]| c),
406 }
407 }
408
409 fn num_node_inputs(&self, node: &Self::Signal) -> usize {
410 match self.get_node(*node) {
411 GeneralNode::Node(n) => n.num_inputs(),
412 GeneralNode::Input(_) => 0,
413 GeneralNode::Constant(_) => 0,
414 }
415 }
416
417 fn get_node_output(&self, node: &Self::NodeId) -> Self::Signal {
418 *node
419 }
420}
421
422impl<Node> NumInputs for LogicNetwork<Node> {
423 fn num_inputs(&self) -> usize {
424 self.primary_inputs.len()
425 }
426}
427
428impl<Node> NumOutputs for LogicNetwork<Node> {
429 fn num_outputs(&self) -> usize {
430 self.primary_outputs.len()
431 }
432}
433
434impl<Node> PartialBooleanSystem for LogicNetwork<Node>
435where
436 Node: NetworkNode<NodeId = NodeId>,
437{
438 type LiteralId = NodeId;
439
440 type TermId = NodeId;
441
442 fn evaluate_term_partial(&self, term: &Self::TermId, input_values: &[bool]) -> Option<bool> {
443 Some(self.evaluate_term(term, input_values))
445 }
446}
447
448impl<Node> BooleanSystem for LogicNetwork<Node>
449where
450 Node: NetworkNode<NodeId = NodeId>,
451{
452 fn evaluate_term(&self, term: &Self::TermId, input_values: &[bool]) -> bool {
453 let simulator = network_simulator::RecursiveSim::new(self);
454
455 assert_eq!(input_values.len(), self.num_primary_inputs());
456
457 let outputs: SmallVec<[_; 1]> = simulator.simulate(&[*term], input_values).collect();
458
459 outputs[0]
460 }
461}
462
463impl<Node> NetworkEdit for LogicNetwork<Node>
464where
465 Node: NetworkNode<NodeId = NodeId>
466 + Hash
467 + Eq
468 + MutNetworkNodeWithReferenceCount
469 + IntoIterator<Item = NodeId>,
470{
471 fn create_primary_input(&mut self) -> Self::Signal {
472 let idx = self.primary_inputs.len();
473 let signal = NodeId::new_input_node(idx);
474 self.primary_inputs.push(signal);
475 signal
476 }
477
478 fn create_primary_output(&mut self, signal: Self::Signal) -> Self::Signal {
479 self.primary_outputs.push(signal);
480 signal
481 }
482
483 fn substitute(&mut self, old: Self::Signal, new: Self::Signal) {
484 if let Some(idx) = old.node_index() {
485 let list_of_references = &mut self.storage[idx].references;
486 let list_of_edges = &mut self.storage[idx].outgoing_edges;
487 } else {
488 todo!()
489 }
490 }
491
492 fn create_node(&mut self, node: Self::Node) -> Self::NodeId {
493 match self.simplify_node_with_hashtable(node) {
494 SimplifyResult::Node(n, inv) => self.insert_node(n).invert_if(inv),
495 SimplifyResult::Simplified(node_id, inv) => node_id.invert_if(inv),
496 }
497 }
498
499 fn foreach_node_mut(&mut self, f: impl Fn(&mut Self::Node)) {
500 self.storage.iter_mut().for_each(|n| f(&mut n.node))
501 }
502}
503
504