libreda_db/flat_view.rs
1// Copyright (c) 2020-2021 Thomas Kramer.
2// SPDX-FileCopyrightText: 2022 Thomas Kramer
3//
4// SPDX-License-Identifier: AGPL-3.0-or-later
5
6//! Wrapper around a netlist which provides an on-the-fly flat view of a certain cell.
7//! The presented view is flattened until leaf cells.
8//! Internally this works by using component IDs that are actually paths through the hierarchy.
9
10use crate::traits::{HierarchyBase, HierarchyIds};
11use std::{
12 collections::{HashMap, HashSet},
13 sync::Arc,
14};
15
16/// Wrapper around ID types.
17/// This wrapper makes sure that the flat view uses other ID types than the
18/// underlying hierarchical view.
19#[derive(Clone, Debug, Hash, PartialEq)]
20pub struct FlatId<T>(T);
21
22/// Wrapper around a netlist which provides an on-the-fly flat view of a certain cell.
23/// The presented view is flattened until leaf cells.
24/// Internally this works by using component IDs that are actually paths through the hierarchy.
25///
26/// Names are constructed by concatenating the names of the path elements
27/// with a separator string in between.
28///
29/// # Example
30///
31/// ```
32/// use libreda_db::prelude::{Chip, HierarchyBase, HierarchyEdit, FlatView};
33///
34/// // Create a simple hierarchy.
35/// let mut chip = Chip::new();
36/// let top = chip.create_cell("TOP".into());
37/// let intermediate = chip.create_cell("INTERMEDIATE".into());
38/// let leaf1 = chip.create_cell("LEAF1".into());
39/// let leaf2 = chip.create_cell("LEAF2".into());
40///
41/// // The intermediate cell contains two instances of leaf1 and one instance of leaf2.
42/// chip.create_cell_instance(&intermediate, &leaf1, Some("leaf1_inst1".into()));
43/// chip.create_cell_instance(&intermediate, &leaf1, Some("leaf1_inst2".into()));
44/// chip.create_cell_instance(&intermediate, &leaf2, Some("leaf2_inst1".into()));
45///
46/// // Create two instances of the intermediate cell in the TOP cell.
47/// chip.create_cell_instance(&top, &intermediate, Some("intermediate1".into()));
48/// chip.create_cell_instance(&top, &intermediate, Some("intermediate2".into()));
49///
50/// // Create the flat view.
51///
52/// let flat = FlatView::new_with_separator(&chip, ":".to_string());
53/// let flat_top = flat.cell_by_name("TOP").expect("TOP not found in flat view.");
54/// // There are 2 instances of the intermediate cell which contains 3 leaf cells,
55/// // so now the flattened top should contain 2*3 instances.
56/// assert_eq!(flat.num_child_instances(&flat_top), 2*3);
57///
58/// // Get a cell instance with the path string.
59/// let inst = flat.cell_instance_by_name(&flat_top, "intermediate1:leaf1_inst1").expect("Instance not found.");
60/// // Instance names are assembled from the path.
61/// assert_eq!(flat.cell_instance_name(&inst).unwrap().as_str(), "intermediate1:leaf1_inst1");
62///
63/// // There should be 4 instances of the LEAF1 cell now.
64/// assert_eq!(flat.each_cell_reference(&leaf1).count(), 2*2);
65/// ```
66pub struct FlatView<'a, N> {
67 /// Sequence used to separate path elements when creating qualified names.
68 /// Names of the original netlist are not allowed to contain the path separator.
69 path_separator: String,
70 /// Underlying netlist data structure.
71 base: &'a N,
72}
73
74impl<'a, N: HierarchyBase> FlatView<'a, N> {
75 /// Create a new flat view of `base`.
76 /// Use "/" as a path separator in names.
77 pub fn new(base: &'a N) -> Self {
78 Self {
79 path_separator: "/".to_string(),
80 base,
81 }
82 }
83
84 /// Create a new flat view of `base`.
85 /// Use a custom path separator in concatenated names.
86 pub fn new_with_separator(base: &'a N, path_separator: String) -> Self {
87 Self {
88 path_separator,
89 base,
90 }
91 }
92
93 fn cell_is_leaf(&self, cell: &N::CellId) -> bool {
94 self.base.num_child_instances(cell) == 0
95 }
96
97 fn cell_exists_in_flat_view(&self, cell: &N::CellId) -> bool {
98 !self.cell_is_flattened(cell)
99 }
100
101 /// Check if the cell got flattened and does not
102 /// exist in the flat view.
103 fn cell_is_flattened(&self, cell: &N::CellId) -> bool {
104 let is_top = self.base.num_dependent_cells(cell) == 0;
105 let is_leaf = self.cell_is_leaf(cell);
106 !is_top && !is_leaf
107 }
108}
109
110type HierarchyPath<T> = Arc<Vec<T>>;
111
112impl<'a, N: HierarchyIds> HierarchyIds for FlatView<'a, N> {
113 type CellId = N::CellId;
114 type CellInstId = HierarchyPath<N::CellInstId>;
115}
116
117impl<'a, N: HierarchyBase> HierarchyBase for FlatView<'a, N> {
118 type NameType = N::NameType;
119
120 fn cell_by_name(&self, name: &str) -> Option<Self::CellId> {
121 let cell = self.base.cell_by_name(name);
122 cell.filter(|cell| self.cell_exists_in_flat_view(cell))
123 }
124
125 fn cell_instance_by_name(
126 &self,
127 parent_cell: &Self::CellId,
128 name: &str,
129 ) -> Option<Self::CellInstId> {
130 let path = name.split(&self.path_separator);
131 let mut parent_cell = parent_cell.clone();
132 let mut current_inst = vec![];
133 // Resolve the path.
134 // For each path element...
135 for name in path {
136 // Find the child in the current parent.
137 let inst = self.base.cell_instance_by_name(&parent_cell, name);
138 if let Some(inst) = inst {
139 // Descend into the child.
140 parent_cell = self.base.template_cell(&inst);
141 current_inst.push(inst);
142 } else {
143 // No child could be found.
144 current_inst.clear();
145 break;
146 }
147 }
148 if current_inst.is_empty() {
149 None
150 } else {
151 Some(current_inst.into())
152 }
153 }
154
155 fn cell_name(&self, cell: &Self::CellId) -> Self::NameType {
156 let name = self.base.cell_name(cell);
157
158 if self.cell_is_flattened(cell) {
159 panic!("Cell does not exist in flat view: {}", &name);
160 }
161 name
162 }
163
164 fn cell_instance_name(&self, cell_inst: &Self::CellInstId) -> Option<Self::NameType> {
165 // Try to find the name of each path element.
166 let path_names: Option<Vec<_>> = cell_inst
167 .iter()
168 .map(|inst| self.base.cell_instance_name(inst))
169 .collect();
170 // If a name could be found for each element
171 // join them with the path separator.
172 path_names.map(|names| names.join(&self.path_separator).into())
173 }
174
175 fn parent_cell(&self, cell_instance: &Self::CellInstId) -> Self::CellId {
176 self.base.parent_cell(&cell_instance[0])
177 }
178
179 fn template_cell(&self, cell_instance: &Self::CellInstId) -> Self::CellId {
180 self.base
181 .template_cell(&cell_instance[cell_instance.len() - 1])
182 }
183
184 fn for_each_cell<F>(&self, mut f: F)
185 where
186 F: FnMut(Self::CellId),
187 {
188 self.base.for_each_cell(|c| {
189 // Iterate over top-level and leaf cells only.
190 if self.cell_exists_in_flat_view(&c) {
191 f(c);
192 }
193 })
194 }
195
196 fn for_each_cell_instance<F>(&self, cell: &Self::CellId, mut f: F)
197 where
198 F: FnMut(Self::CellInstId),
199 {
200 // Depth-first traversal of the dependency graph.
201 // Start with the top-level instances.
202 let mut stack = vec![self.base.each_cell_instance(cell)];
203
204 // Path through the hierarchy to the current cell.
205 let mut path = Arc::new(vec![]);
206
207 // Work through all the levels until none is left.
208 while let Some(mut insts) = stack.pop() {
209 // Take the next instance from the current level...
210 if let Some(inst) = insts.next() {
211 // ... and directly push the current level again on the stack.
212 stack.push(insts);
213 let template = self.base.template_cell(&inst);
214 Arc::make_mut(&mut path).push(inst);
215
216 if self.base.num_child_instances(&template) == 0 {
217 // Leaf cell.
218 f(Arc::clone(&path))
219 } else {
220 // Push new level.
221 let sub_insts = self.base.each_cell_instance(&template);
222 stack.push(sub_insts);
223 }
224 } else {
225 // insts is empty. We go a level up.
226 Arc::make_mut(&mut path).pop();
227 }
228 }
229 }
230
231 fn for_each_cell_dependency<F>(&self, cell: &Self::CellId, mut f: F)
232 where
233 F: FnMut(Self::CellId),
234 {
235 let mut visited = HashSet::new();
236 let mut stack = self.base.each_cell_dependency_vec(cell);
237 while let Some(dep) = stack.pop() {
238 if !visited.contains(&dep) {
239 // Find child dependencies.
240 stack.extend(self.base.each_cell_dependency(&dep));
241 // Visit the dependency.
242 if self.cell_exists_in_flat_view(&dep) {
243 f(dep.clone());
244 }
245 // Remember we visited this dependency already.
246 visited.insert(dep);
247 }
248 }
249 }
250
251 fn for_each_dependent_cell<F>(&self, cell: &Self::CellId, mut f: F)
252 where
253 F: FnMut(Self::CellId),
254 {
255 // Only top-level cells can be dependent cells in the flat view.
256 let mut visited = HashSet::new();
257 let mut stack = self.base.each_dependent_cell_vec(cell);
258 while let Some(dep) = stack.pop() {
259 if !visited.contains(&dep) {
260 visited.insert(dep.clone());
261 if self.cell_exists_in_flat_view(&dep) {
262 f(dep);
263 } else {
264 // Follow towards the root.
265 stack.extend(self.base.each_dependent_cell(&dep));
266 }
267 }
268 }
269 }
270
271 fn for_each_cell_reference<F>(&self, cell: &Self::CellId, mut f: F)
272 where
273 F: FnMut(Self::CellInstId),
274 {
275 assert!(
276 self.cell_exists_in_flat_view(cell),
277 "Cell does not exist in flat view: {}",
278 self.base.cell_name(cell)
279 );
280
281 let mut references = vec![self.base.each_cell_reference(cell)];
282 let mut path = Arc::new(vec![]);
283
284 while let Some(mut refs) = references.pop() {
285 if let Some(r) = refs.next() {
286 references.push(refs);
287 let parent = self.base.parent_cell(&r);
288 Arc::make_mut(&mut path).insert(0, r.clone());
289 if self.cell_exists_in_flat_view(&parent) {
290 // Reached the top.
291 f(Arc::clone(&path));
292 } else {
293 // Get parent references.
294 references.push(self.base.each_cell_reference(&parent));
295 }
296 } else {
297 // Worked through all references on this level.
298 if !path.is_empty() {
299 Arc::make_mut(&mut path).remove(0);
300 }
301 }
302 }
303 }
304
305 fn num_child_instances(&self, cell: &Self::CellId) -> usize {
306 let num_non_flat_children = self.base.num_child_instances(cell);
307 if num_non_flat_children == 0 {
308 0
309 } else {
310 // Count how many times each cell is instantiated.
311 let mut counted_cells: HashMap<N::CellId, usize> = Default::default();
312 self.base.for_each_cell_instance(cell, |inst| {
313 let template = self.base.template_cell(&inst);
314 *counted_cells.entry(template).or_insert(0) += 1;
315 });
316
317 // Compute recursively the number of children.
318 counted_cells
319 .into_iter()
320 .map(|(cell, num)| num * self.base.num_child_instances(&cell))
321 .sum()
322 }
323 }
324
325 fn num_cells(&self) -> usize {
326 let mut count = 0;
327 self.for_each_cell(|_| count += 1);
328 count
329 }
330}
331
332// On-the-fly flattening of nets is not solved yet.
333// The main difficulty is: Many nets might now be fused together into one net. How can this be uniquely and efficiently represented?
334// impl<'a, N: NetlistBase> NetlistBase for FlatView<'a, N> {
335// type PinId = N::PinId;
336// type PinInstId = (Self::CellInstId, N::PinInstId);
337// // Pin instances need to be extended with the path through the hierarhcy.
338// type NetId = (Self::CellInstId, N::NetId);
339//
340// fn template_pin(&self, (_, pin_instance): &Self::PinInstId) -> Self::PinId {
341// self.base.template_pin(pin_instance)
342// }
343//
344// fn pin_direction(&self, pin: &Self::PinId) -> Direction {
345// self.base.pin_direction(pin)
346// }
347//
348// fn pin_name(&self, pin: &Self::PinId) -> Self::NameType {
349// self.base.pin_name(pin)
350// }
351//
352// fn pin_by_name(&self, parent_circuit: &Self::CellId, name: &str) -> Option<Self::PinId> {
353// self.base.pin_by_name(parent_circuit, name)
354// }
355//
356// fn parent_cell_of_pin(&self, pin: &Self::PinId) -> Self::CellId {
357// self.base.parent_cell_of_pin(pin)
358// }
359//
360// fn parent_of_pin_instance(&self, (cell_inst, _pin_inst): &Self::PinInstId) -> Self::CellInstId {
361// cell_inst.clone()
362// }
363//
364// fn parent_cell_of_net(&self, (path, net): &Self::NetId) -> Self::CellId {
365// if let Some(instance) = path.iter().nth(0) {
366// // The parent of the flattened net is equal to the parent of the first
367// // cell instance in the path.
368// self.base.parent_cell(instance)
369// } else {
370// // The net lives in the top-cell.
371// self.base.parent_cell_of_net(net)
372// }
373// }
374//
375// fn net_of_pin(&self, pin: &Self::PinId) -> Option<Self::NetId> {
376// let net = self.base.net_of_pin(pin);
377// net.map(
378// |n| (vec![], n)
379// )
380// }
381//
382// fn net_of_pin_instance(&self, (path, pin_instance): &Self::PinInstId) -> Option<Self::NetId> {
383// let non_flattened_net = self.base.net_of_pin_instance(pin_instance);
384// non_flattened_net.map(
385// |n| (path.clone(), n)
386// )
387// }
388//
389// fn net_zero(&self, parent_circuit: &Self::CellId) -> Self::NetId {
390// (vec![], self.base.net_zero(parent_circuit))
391// }
392//
393// fn net_one(&self, parent_circuit: &Self::CellId) -> Self::NetId {
394// (vec![], self.base.net_one(parent_circuit))
395// }
396//
397// fn net_by_name(&self, parent_circuit: &Self::CellId, name: &str) -> Option<Self::NetId> {
398// // Find last path separator after which comes the net name.
399//
400// if let Some(last_separator_pos) = name.rfind(self.path_separator.as_str()) {
401// let path_string = &name[0..last_separator_pos];
402// let net_name = &name[last_separator_pos + 1..name.len()];
403//
404// // Resolve cell instance.
405// if let Some(cell_inst) = self.cell_instance_by_name(parent_circuit, path_string) {
406// let template = self.base.template_cell(&cell_inst[cell_inst.len() - 1]);
407// let net = self.base.net_by_name(&template, net_name);
408// net.map(
409// |n| (cell_inst, n)
410// )
411// } else {
412// // Cell instance not found.
413// None
414// }
415// } else {
416// // No separator in net name. Look directly in the top cell.
417// let net = self.base.net_by_name(parent_circuit, name);
418// net.map(
419// |n| (vec![], n)
420// )
421// }
422// }
423//
424// fn net_name(&self, (path, net): &Self::NetId) -> Option<Self::NameType> {
425// if let Some(net_name) = self.base.net_name(net) {
426// // Try to find the name of each path element.
427// let path_names: Option<Vec<_>> = path.iter()
428// .map(|inst| self.base.cell_instance_name(inst))
429// .collect();
430// // If a name could be found for each element
431// // join them with the path separator.
432// path_names.map(|mut names| {
433// names.push(net_name);
434// names.join(&self.path_separator).into()
435// })
436// } else {
437// None
438// }
439// }
440//
441// fn for_each_pin<F>(&self, circuit: &Self::CellId, f: F) where F: FnMut(Self::PinId) {
442// self.base.for_each_pin(circuit, f)
443// }
444//
445// fn for_each_pin_instance<F>(&self, circuit_inst: &Self::CellInstId, mut f: F) where F: FnMut(Self::PinInstId) {
446// let hierarchical_inst = &circuit_inst[circuit_inst.len() - 1];
447// self.base.for_each_pin_instance(hierarchical_inst, |p| {
448// f((circuit_inst.clone(), p))
449// })
450// }
451//
452// fn for_each_internal_net<F>(&self, circuit: &Self::CellId, f: F) where F: FnMut(Self::NetId) {
453// unimplemented!()
454// }
455//
456// fn num_pins(&self, cell: &Self::CellId) -> usize {
457// self.base.num_pins(cell)
458// }
459//
460// fn for_each_pin_of_net<F>(&self, net: &Self::NetId, f: F) where F: FnMut(Self::PinId) {
461// unimplemented!()
462// }
463//
464// fn for_each_pin_instance_of_net<F>(&self, net: &Self::NetId, f: F) where F: FnMut(Self::PinInstId) {
465// unimplemented!()
466// }
467//
468// fn num_internal_nets(&self, parent: &Self::CellId) -> usize {
469// unimplemented!()
470// }
471// }
472
473#[cfg(test)]
474mod tests_with_hierarchy {
475 use crate::flat_view::FlatView;
476 use crate::prelude::Chip;
477 use crate::prelude::*;
478
479 fn create_test_chip() -> Chip {
480 let mut chip = Chip::new();
481 let top1 = chip.create_cell("TOP1".into());
482 let top2 = chip.create_cell("TOP2".into());
483 let intermediate = chip.create_cell("INTERMEDIATE".into());
484 let leaf1 = chip.create_cell("LEAF1".into());
485 let leaf2 = chip.create_cell("LEAF2".into());
486
487 chip.create_cell_instance(&intermediate, &leaf1, Some("leaf1_inst1".into()));
488 chip.create_cell_instance(&intermediate, &leaf1, Some("leaf1_inst2".into()));
489 chip.create_cell_instance(&intermediate, &leaf2, Some("leaf2_inst1".into()));
490 chip.create_cell_instance(&intermediate, &leaf2, Some("leaf2_inst2".into()));
491
492 chip.create_cell_instance(&top1, &intermediate, Some("intermediate_inst1".into()));
493 chip.create_cell_instance(&top1, &intermediate, Some("intermediate_inst2".into()));
494
495 // Create instances inanother cell with same names as in TOP1.
496 chip.create_cell_instance(&top2, &leaf1, Some("leaf1_inst1".into()));
497 chip.create_cell_instance(&top2, &leaf2, Some("leaf2_inst1".into()));
498 chip.create_cell_instance(&top2, &leaf2, Some("leaf2_inst2".into()));
499 chip
500 }
501
502 #[test]
503 fn test_num_cells() {
504 let chip = create_test_chip();
505 let flatview = FlatView::new(&chip);
506 assert_eq!(flatview.num_cells(), 4); // Two top cells, two leaf cells.
507 }
508
509 #[test]
510 fn test_access_top_cell() {
511 let chip = create_test_chip();
512
513 let flatview = FlatView::new(&chip);
514 let top1 = flatview.cell_by_name("TOP1").expect("Cell not found.");
515 assert_eq!(flatview.num_child_instances(&top1), 2 * 4);
516 assert_eq!(flatview.num_dependent_cells(&top1), 0);
517 assert_eq!(flatview.num_cell_dependencies(&top1), 2);
518 assert_eq!(flatview.each_cell_instance(&top1).count(), 8);
519 }
520
521 #[test]
522 fn test_find_template_cell() {
523 let chip = create_test_chip();
524 let flatview = FlatView::new(&chip);
525 let top1 = flatview.cell_by_name("TOP1").expect("Cell not found.");
526 let leaf1 = flatview.cell_by_name("LEAF1").expect("Cell not found.");
527
528 // Template
529 assert_eq!(
530 &flatview.template_cell(
531 &flatview
532 .cell_instance_by_name(&top1, "intermediate_inst1/leaf1_inst1",)
533 .unwrap()
534 ),
535 &leaf1
536 );
537 }
538
539 #[test]
540 fn test_find_instance_by_name() {
541 let chip = create_test_chip();
542 let flatview = FlatView::new(&chip);
543 let top1 = flatview.cell_by_name("TOP1").expect("Cell not found.");
544
545 // Find by name.
546 {
547 let names = vec![
548 "intermediate_inst1/leaf1_inst1",
549 "intermediate_inst2/leaf1_inst1",
550 "intermediate_inst2/leaf2_inst1",
551 "intermediate_inst2/leaf2_inst2",
552 ];
553 for name in names {
554 let inst = flatview
555 .cell_instance_by_name(&top1, name)
556 .expect("instance not found");
557 assert_eq!(flatview.cell_instance_name(&inst), Some(name.into()));
558
559 // Parent
560 assert_eq!(&flatview.parent_cell(&inst), &top1);
561 }
562 }
563 }
564
565 #[test]
566 fn test_count_references() {
567 let chip = create_test_chip();
568 let flatview = FlatView::new(&chip);
569 let top1 = flatview.cell_by_name("TOP1").expect("Cell not found.");
570 let leaf1 = flatview.cell_by_name("LEAF1").expect("Cell not found.");
571 let leaf2 = flatview.cell_by_name("LEAF2").expect("Cell not found.");
572
573 // References.
574 assert_eq!(flatview.num_cell_references(&leaf1), 2 * 2 + 1);
575 assert_eq!(flatview.num_cell_references(&leaf2), 2 * 2 + 2);
576 assert_eq!(flatview.num_cell_references(&top1), 0);
577 }
578
579 #[test]
580 fn test_another_top_cell() {
581 // TOP2 contains instances with same name as in TOP1.
582 let chip = create_test_chip();
583 let flatview = FlatView::new(&chip);
584 let top2 = flatview.cell_by_name("TOP2").expect("Cell not found.");
585
586 assert_eq!(flatview.num_dependent_cells(&top2), 0);
587 assert_eq!(flatview.num_cell_dependencies(&top2), 2);
588 assert_eq!(flatview.each_cell_instance(&top2).count(), 3);
589 }
590}
591
592//#[cfg(test)]
593//mod tests_with_netlist {
594// use crate::flat_view::FlatView;
595// use crate::prelude::Chip;
596// use crate::prelude::*;
597//
598// fn create_test_netlist() -> Chip {
599// let mut chip = Chip::new();
600// let top = chip.create_cell("TOP".into());
601// let sub = chip.create_cell("SUB".into());
602// chip.create_net(&sub, Some("A".into()));
603//
604// let inst_sub1 = chip.create_cell_instance(&top, &sub, Some("sub1".into()));
605// let inst_sub2 = chip.create_cell_instance(&top, &sub, Some("sub2".into()));
606//
607// chip
608// }
609//
610// #[test]
611// fn test_net_by_name() {
612// let chip = create_test_netlist();
613// let flatview = FlatView::new(&chip);
614// let top = flatview.cell_by_name("TOP").expect("Cell not found.");
615// assert!(flatview.net_by_name(&top, "sub1/A").is_some());
616// assert!(flatview.net_by_name(&top, "sub2/A").is_some());
617// }
618//}