prjunnamed_netlist/
rewrite.rs

1use std::{
2    borrow::Cow,
3    cell::RefCell,
4    collections::{HashMap, HashSet},
5};
6
7use crate::{design::TopoSortItem, Cell, ControlNet, Design, MetaItemRef, Net, Trit, Value};
8
9pub enum RewriteResult<'a> {
10    None,
11    Cell(Cell),
12    CellMeta(Cell, MetaItemRef<'a>),
13    Value(Value),
14}
15
16impl From<Value> for RewriteResult<'_> {
17    fn from(value: Value) -> Self {
18        RewriteResult::Value(value)
19    }
20}
21
22impl From<Net> for RewriteResult<'_> {
23    fn from(net: Net) -> Self {
24        RewriteResult::Value(net.into())
25    }
26}
27
28impl From<ControlNet> for RewriteResult<'_> {
29    fn from(cnet: ControlNet) -> Self {
30        match cnet {
31            ControlNet::Pos(net) => RewriteResult::Value(net.into()),
32            ControlNet::Neg(net) => RewriteResult::Cell(Cell::Not(net.into())),
33        }
34    }
35}
36
37impl From<Cell> for RewriteResult<'_> {
38    fn from(cell: Cell) -> Self {
39        RewriteResult::Cell(cell)
40    }
41}
42
43pub enum RewriteNetSource<'a> {
44    Const(Trit),
45    Opaque,
46    Cell(Cow<'a, Cell>, MetaItemRef<'a>, usize),
47}
48
49pub trait RewriteRuleset {
50    fn rewrite<'a>(
51        &self,
52        cell: &Cell,
53        meta: MetaItemRef<'a>,
54        output: Option<&Value>,
55        rewriter: &Rewriter<'a>,
56    ) -> RewriteResult<'a> {
57        let _ = (cell, meta, output, rewriter);
58        RewriteResult::None
59    }
60    fn cell_added(&self, design: &Design, cell: &Cell, output: &Value) {
61        let _ = (design, cell, output);
62    }
63    fn net_replaced(&self, design: &Design, from: Net, to: Net) {
64        let _ = (design, from, to);
65    }
66}
67
68pub struct Rewriter<'a> {
69    design: &'a Design,
70    rules: &'a [&'a dyn RewriteRuleset],
71    processed: RefCell<HashSet<Net>>,
72    cache: RefCell<HashMap<Cell, Value>>,
73}
74
75impl<'a> Rewriter<'a> {
76    pub fn find_cell(&self, net: Net) -> RewriteNetSource<'a> {
77        if !self.processed.borrow().contains(&net) && !net.is_const() {
78            return RewriteNetSource::Opaque;
79        }
80        match self.design.find_new_cell(net) {
81            Ok((cell, meta, bit)) => RewriteNetSource::Cell(cell, meta, bit),
82            Err(trit) => RewriteNetSource::Const(trit),
83        }
84    }
85
86    fn process_cell(&self, cell: &Cell, meta: MetaItemRef<'a>, output: Option<&Value>) -> RewriteResult<'a> {
87        let mut replacement_cell = None;
88        let mut replacement_meta = None;
89        'outer: loop {
90            for &rule in self.rules {
91                let cur_cell = replacement_cell.as_ref().unwrap_or(cell);
92                let cur_meta = replacement_meta.unwrap_or(meta);
93                let _guard = self.design.use_metadata(cur_meta);
94                match rule.rewrite(cur_cell, cur_meta, output, self) {
95                    RewriteResult::None => (),
96                    RewriteResult::Cell(new_cell) => {
97                        replacement_cell = Some(new_cell);
98                        continue 'outer;
99                    }
100                    RewriteResult::CellMeta(new_cell, new_meta) => {
101                        replacement_cell = Some(new_cell);
102                        replacement_meta = Some(new_meta);
103                        continue 'outer;
104                    }
105                    RewriteResult::Value(value) => {
106                        return RewriteResult::Value(value);
107                    }
108                }
109            }
110            break;
111        }
112        let cell = replacement_cell.as_ref().unwrap_or(cell);
113        if let Some(value) = self.cache.borrow().get(&cell) {
114            let meta = replacement_meta.unwrap_or(meta);
115            self.design.append_metadata_by_net(value[0], meta);
116            RewriteResult::Value(value.clone())
117        } else {
118            match (replacement_cell, replacement_meta) {
119                (None, _) => RewriteResult::None,
120                (Some(cell), None) => RewriteResult::Cell(cell),
121                (Some(cell), Some(meta)) => RewriteResult::CellMeta(cell, meta),
122            }
123        }
124    }
125
126    pub fn add_cell(&self, cell: Cell) -> Value {
127        self.add_cell_meta(cell, self.design.get_use_metadata())
128    }
129
130    pub fn add_cell_meta(&self, cell: Cell, meta: MetaItemRef<'_>) -> Value {
131        self.add_cell_meta_output(cell, meta, None)
132    }
133
134    fn add_cell_meta_output(&self, cell: Cell, meta: MetaItemRef<'_>, output: Option<&Value>) -> Value {
135        let (cell, meta) = match self.process_cell(&cell, meta, output) {
136            RewriteResult::None => (cell, meta),
137            RewriteResult::Cell(new_cell) => (new_cell, meta),
138            RewriteResult::CellMeta(new_cell, new_meta) => (new_cell, new_meta),
139            RewriteResult::Value(value) => return value,
140        };
141        let value = self.design.add_cell_with_metadata_ref(cell.clone(), meta);
142        for &rule in self.rules {
143            rule.cell_added(self.design, &cell, &value);
144        }
145        for net in &value {
146            self.processed.borrow_mut().insert(net);
147        }
148        if !cell.has_effects(self.design) {
149            self.cache.borrow_mut().insert(cell, value.clone());
150        }
151        value
152    }
153
154    fn run(&mut self) {
155        let worklist = self.design.topo_sort();
156        for item in worklist {
157            match item {
158                TopoSortItem::Cell(cell_ref) => {
159                    let output = cell_ref.output();
160                    let mut cell = cell_ref.get().into_owned();
161                    cell.visit_mut(|net| *net = self.design.map_net_new(*net));
162                    match self.process_cell(&cell, cell_ref.metadata(), Some(&output)) {
163                        RewriteResult::None => {
164                            for &rule in self.rules {
165                                rule.cell_added(self.design, &cell, &output);
166                            }
167                            if !cell.has_effects(self.design) {
168                                self.cache.borrow_mut().insert(cell, output.clone());
169                            }
170                            for net in output {
171                                self.processed.borrow_mut().insert(net);
172                            }
173                        }
174                        RewriteResult::Cell(new_cell) => {
175                            cell_ref.replace(new_cell.clone());
176                            for &rule in self.rules {
177                                rule.cell_added(self.design, &new_cell, &output);
178                            }
179                            if !new_cell.has_effects(self.design) {
180                                self.cache.borrow_mut().insert(new_cell, output.clone());
181                            }
182                            for net in output {
183                                self.processed.borrow_mut().insert(net);
184                            }
185                        }
186                        RewriteResult::CellMeta(new_cell, new_meta) => {
187                            cell_ref.replace(new_cell.clone());
188                            for &rule in self.rules {
189                                rule.cell_added(self.design, &new_cell, &output);
190                            }
191                            cell_ref.append_metadata(new_meta);
192                            if !new_cell.has_effects(self.design) {
193                                self.cache.borrow_mut().insert(new_cell, output.clone());
194                            }
195                            for net in output {
196                                self.processed.borrow_mut().insert(net);
197                            }
198                        }
199                        RewriteResult::Value(value) => {
200                            assert_eq!(value.len(), output.len());
201                            for (net, new_net) in output.iter().zip(value) {
202                                self.design.replace_net(net, new_net);
203                                for &rule in self.rules {
204                                    rule.net_replaced(self.design, net, new_net);
205                                }
206                                self.processed.borrow_mut().insert(net);
207                            }
208                            cell_ref.unalive();
209                        }
210                    }
211                }
212                TopoSortItem::CellBit(cell, bit) => {
213                    let mut slice = cell.get().slice(bit..bit + 1).unwrap();
214                    slice.visit_mut(|net| *net = self.design.map_net_new(*net));
215                    let net = cell.output()[bit];
216                    let new_value = self.add_cell_meta_output(slice, cell.metadata(), Some(&net.into()));
217                    let new_net = new_value[0];
218                    self.design.replace_net(net, new_net);
219                    for &rule in self.rules {
220                        rule.net_replaced(self.design, net, new_net);
221                    }
222                    self.processed.borrow_mut().insert(net);
223                }
224            }
225        }
226    }
227}
228
229impl Design {
230    pub fn rewrite(&mut self, rules: &[&dyn RewriteRuleset]) {
231        assert!(!self.is_changed());
232        let mut rewriter = Rewriter {
233            design: self,
234            rules,
235            processed: RefCell::new(HashSet::new()),
236            cache: RefCell::new(HashMap::new()),
237        };
238        rewriter.run();
239        self.compact();
240    }
241}