prjunnamed_pattern/
traits.rs

1use std::{
2    cell::{Ref, RefCell},
3    fmt::{Debug, Display},
4};
5
6use prjunnamed_netlist::{CellRef, Const, Design, Net, Trit, Value};
7
8pub trait NetOrValue: Sized + Clone + Debug + Display {
9    fn len(&self) -> usize;
10    fn iter(&self) -> impl Iterator<Item = Net>;
11    fn as_value(&self) -> Value {
12        Value::from_iter(self.iter())
13    }
14    fn as_const(&self) -> Option<Const>;
15    fn try_from(other: impl NetOrValue) -> Option<Self>;
16
17    #[must_use]
18    fn accumulate(capture: &mut Option<Self>, net: Net) -> bool;
19}
20
21impl NetOrValue for Net {
22    fn len(&self) -> usize {
23        1
24    }
25
26    fn as_const(&self) -> Option<Const> {
27        Net::as_const(*self).map(|trit| Const::from(trit))
28    }
29
30    fn iter(&self) -> impl Iterator<Item = Net> {
31        std::iter::once(*self)
32    }
33
34    fn try_from(other: impl NetOrValue) -> Option<Self> {
35        if other.len() == 1 {
36            other.iter().next()
37        } else {
38            None
39        }
40    }
41
42    fn accumulate(capture: &mut Option<Self>, net: Net) -> bool {
43        match capture {
44            Some(captured_net) if *captured_net == net => return true,
45            Some(_) => return false,
46            None => *capture = Some(net),
47        }
48        true
49    }
50}
51
52impl NetOrValue for Value {
53    fn len(&self) -> usize {
54        Value::len(self)
55    }
56
57    fn iter(&self) -> impl Iterator<Item = Net> {
58        self.iter()
59    }
60
61    fn as_const(&self) -> Option<Const> {
62        Value::as_const(self)
63    }
64
65    fn try_from(other: impl NetOrValue) -> Option<Self> {
66        Some(Value::from_iter(other.iter()))
67    }
68
69    fn accumulate(capture: &mut Option<Self>, net: Net) -> bool {
70        match capture {
71            Some(value) => *value = value.concat(net),
72            None => *capture = Some(Value::from(net)),
73        }
74        true
75    }
76}
77
78// Used to interpose accesses to the design in order to track which nets were examined.
79pub trait DesignDyn {
80    fn find_cell(&self, net: Net) -> Result<(CellRef<'_>, usize), Trit>;
81
82    fn inner(&self) -> &Design;
83}
84
85impl DesignDyn for Design {
86    #[inline]
87    fn find_cell(&self, net: Net) -> Result<(CellRef<'_>, usize), Trit> {
88        Design::find_cell(self, net)
89    }
90
91    fn inner(&self) -> &Design {
92        self
93    }
94}
95
96pub struct CellCollector<'a> {
97    inner: &'a dyn DesignDyn,
98    cells: RefCell<Vec<CellRef<'a>>>,
99}
100
101impl<'a> CellCollector<'a> {
102    pub fn new(design: &'a dyn DesignDyn) -> Self {
103        Self { inner: design, cells: RefCell::new(Vec::new()) }
104    }
105
106    pub fn cells(&self) -> Ref<'_, [CellRef<'a>]> {
107        Ref::map(self.cells.borrow(), |cells| &cells[..])
108    }
109
110    pub fn clear(&self) {
111        self.cells.borrow_mut().clear();
112    }
113}
114
115impl DesignDyn for CellCollector<'_> {
116    #[inline]
117    fn find_cell(&self, net: Net) -> Result<(CellRef<'_>, usize), Trit> {
118        match self.inner.find_cell(net) {
119            Ok((cell_ref, offset)) => {
120                self.cells.borrow_mut().push(cell_ref);
121                Ok((cell_ref, offset))
122            }
123            Err(trit) => Err(trit),
124        }
125    }
126
127    fn inner(&self) -> &Design {
128        self.inner.inner()
129    }
130}