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//}