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