libreda_db/rw_reference_access/
hierarchy_reference_access.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#![allow(missing_docs)]
7
8use crate::traits::{HierarchyBase, HierarchyEdit};
9use std::hash::{Hash, Hasher};
10use std::sync::{Arc, RwLock, RwLockReadGuard, RwLockWriteGuard};
11
12/// Wrapper around a Netlist or Layout, etc. into a `Arc<RwLock<_>>` to provide
13/// save read and write access. Access is checked at runtime.
14/// If only read access is required, then it might be more efficient to use [`crate::reference_access`].
15///
16/// In contrast to the API of [`trait@HierarchyBase`] and others the object-like API avoids returning iterators
17/// but returns vectors of elements. This allows to keep the lock-time short.
18pub struct RwRefAccess<T> {
19    base: Arc<RwLock<T>>,
20}
21
22impl<T> RwRefAccess<T> {
23    pub fn new(base: T) -> Self {
24        Self {
25            base: Arc::new(RwLock::new(base)),
26        }
27    }
28
29    /// Get read access to the underlying data structure.
30    ///
31    /// Blocks when called during an ongoing write access.
32    pub fn read(&self) -> RwLockReadGuard<'_, T> {
33        self.base.read().expect("Failed to get read access.")
34    }
35
36    /// Get exclusive write access to the underlying data structure.
37    ///
38    /// Blocks if there is already a read or write lock.
39    ///
40    /// # Panics
41    /// Might panic if the current thread already holds a write lock.
42    pub fn write(&self) -> RwLockWriteGuard<'_, T> {
43        self.base.write().expect("Failed to get write access.")
44    }
45}
46
47impl<T> Clone for RwRefAccess<T> {
48    fn clone(&self) -> Self {
49        Self {
50            base: self.base.clone(),
51        }
52    }
53}
54
55impl<T> Eq for RwRefAccess<T> {}
56
57impl<T> PartialEq for RwRefAccess<T> {
58    fn eq(&self, other: &Self) -> bool {
59        Arc::ptr_eq(&self.base, &other.base)
60    }
61}
62
63impl<T> Hash for RwRefAccess<T> {
64    fn hash<H: Hasher>(&self, state: &mut H) {
65        Arc::as_ptr(&self.base).hash(state)
66    }
67}
68
69impl<H: HierarchyBase> RwRefAccess<H> {
70    /// Get a cell 'object' by its ID.
71    fn cell(&self, id: H::CellId) -> CellRef<H> {
72        CellRef {
73            base: self.clone(),
74            id,
75        }
76    }
77
78    /// Get a cell instance 'object' by its ID.
79    fn cell_inst(&self, id: H::CellInstId) -> CellInstRef<H> {
80        CellInstRef {
81            base: self.clone(),
82            id,
83        }
84    }
85
86    /// Get a vector with all cells.
87    pub fn each_cell(&self) -> Vec<CellRef<H>> {
88        self.read().each_cell().map(|id| self.cell(id)).collect()
89    }
90
91    /// Get the number of cells.
92    pub fn num_cells(&self) -> usize {
93        self.read().num_cells()
94    }
95
96    /// Find a cell by its name.
97    pub fn cell_by_name(&self, name: &str) -> Option<CellRef<H>> {
98        self.read().cell_by_name(name).map(|id| self.cell(id))
99    }
100}
101
102impl<H: HierarchyEdit> RwRefAccess<H> {
103    pub fn create_cell(&self, name: H::NameType) -> CellRef<H> {
104        let id = self.write().create_cell(name);
105        self.cell(id)
106    }
107
108    pub fn remove_cell(&self, cell: CellRef<H>) {
109        self.write().remove_cell(&cell.id)
110    }
111}
112
113/// A reference to a cell.
114/// This is just a wrapper around a netlist and a cell ID.
115#[derive(Clone)]
116pub struct CellRef<H: HierarchyBase> {
117    /// Reference to the parent data structure.
118    pub(super) base: RwRefAccess<H>,
119    /// ID of the corresponding cell.
120    pub(super) id: H::CellId,
121}
122
123impl<T: HierarchyBase> Eq for CellRef<T> {}
124
125impl<T: HierarchyBase> PartialEq for CellRef<T> {
126    fn eq(&self, other: &Self) -> bool {
127        self.base == other.base && self.id == other.id
128    }
129}
130
131impl<T: HierarchyBase> Hash for CellRef<T> {
132    fn hash<H: Hasher>(&self, state: &mut H) {
133        self.base.hash(state);
134        self.id.hash(state);
135    }
136}
137
138impl<H: HierarchyBase> CellRef<H> {
139    /// Access the base structure.
140    pub fn base(&self) -> &RwRefAccess<H> {
141        &self.base
142    }
143
144    /// Get the ID of this cell.
145    pub fn id(&self) -> H::CellId {
146        self.id.clone()
147    }
148
149    /// Get the name of the cell.
150    pub fn name(&self) -> H::NameType {
151        self.base.read().cell_name(&self.id)
152    }
153
154    /// Get the IDs of all cell instances in this cell.
155    pub fn each_cell_instance_id(&self) -> Vec<H::CellInstId> {
156        self.base.read().each_cell_instance_vec(&self.id)
157    }
158
159    /// Get all cell instances inside this cell.
160    pub fn each_cell_instance(&self) -> Vec<CellInstRef<H>> {
161        self.base
162            .read()
163            .each_cell_instance(&self.id)
164            .map(move |id| CellInstRef {
165                base: self.base.clone(),
166                id,
167            })
168            .collect()
169    }
170
171    /// Find a child instance by its name.
172    pub fn cell_instance_by_name(&self, name: &str) -> Option<CellInstRef<H>> {
173        self.base
174            .read()
175            .cell_instance_by_name(&self.id, name)
176            .map(|id| CellInstRef {
177                base: self.base.clone(),
178                id,
179            })
180    }
181
182    /// Get the IDs of all instances of this cell.
183    pub fn each_reference_id(&self) -> Vec<H::CellInstId> {
184        self.base.read().each_cell_reference_vec(&self.id)
185    }
186
187    /// Get all instances of this cell.
188    pub fn each_reference(&self) -> Vec<CellInstRef<H>> {
189        self.base
190            .read()
191            .each_cell_reference(&self.id)
192            .map(|id| CellInstRef {
193                base: self.base.clone(),
194                id,
195            })
196            .collect()
197    }
198
199    /// Get all dependencies of this cell.
200    pub fn each_cell_dependency(&self) -> Vec<CellRef<H>> {
201        self.base
202            .read()
203            .each_cell_dependency(&self.id)
204            .map(|id| CellRef {
205                base: self.base.clone(),
206                id,
207            })
208            .collect()
209    }
210
211    /// Get all cells that directly depend on this cell.
212    pub fn each_dependent_cell(&self) -> Vec<CellRef<H>> {
213        self.base
214            .read()
215            .each_dependent_cell(&self.id)
216            .map(|id| CellRef {
217                base: self.base.clone(),
218                id,
219            })
220            .collect()
221    }
222
223    /// Get the number of cell instances inside the `cell`.
224    pub fn num_child_instances(&self) -> usize {
225        self.base.read().num_child_instances(&self.id)
226    }
227}
228
229impl<H: HierarchyEdit> CellRef<H> {
230    pub fn create_instance(
231        &self,
232        template: &CellRef<H>,
233        name: Option<H::NameType>,
234    ) -> CellInstRef<H> {
235        let id = self
236            .base
237            .write()
238            .create_cell_instance(&self.id, &template.id, name);
239        self.base.cell_inst(id)
240    }
241
242    pub fn remove_instance(&self, inst: CellInstRef<H>) {
243        self.base.write().remove_cell_instance(&inst.id);
244    }
245}
246
247/// Default implementation for `CellInstRef`.
248/// This is just a wrapper around a netlist and a cell ID.
249#[derive(Clone, Hash)]
250pub struct CellInstRef<H: HierarchyBase> {
251    /// Reference to the parent netlist.
252    pub(super) base: RwRefAccess<H>,
253    /// ID of the corresponding cell instance.
254    pub(super) id: H::CellInstId,
255}
256
257impl<T: HierarchyBase> Eq for CellInstRef<T> {}
258
259impl<T: HierarchyBase> PartialEq for CellInstRef<T> {
260    fn eq(&self, other: &Self) -> bool {
261        self.base == other.base && self.id == other.id
262    }
263}
264
265impl<H: HierarchyBase> CellInstRef<H> {
266    /// Access the base structure.
267    pub fn base(&self) -> &RwRefAccess<H> {
268        &self.base
269    }
270
271    /// Get the ID of this cell instance.
272    pub fn id(&self) -> H::CellInstId {
273        self.id.clone()
274    }
275
276    /// Get the name of the cell instance.
277    pub fn name(&self) -> Option<H::NameType> {
278        self.base.read().cell_instance_name(&self.id)
279    }
280
281    /// Get the parent cell of this instance.
282    pub fn parent(&self) -> CellRef<H> {
283        CellRef {
284            base: self.base.clone(),
285            id: self.parent_id(),
286        }
287    }
288
289    /// Get the template cell of this instance.
290    pub fn template(&self) -> CellRef<H> {
291        CellRef {
292            base: self.base.clone(),
293            id: self.template_id(),
294        }
295    }
296
297    /// Get the ID of the parent cell of this instance.
298    pub fn parent_id(&self) -> H::CellId {
299        self.base.read().parent_cell(&self.id)
300    }
301
302    /// Get the ID of the template cell of this instance.
303    pub fn template_id(&self) -> H::CellId {
304        self.base.read().template_cell(&self.id)
305    }
306}
307
308#[cfg(test)]
309mod tests {
310    use crate::chip::Chip;
311    use crate::prelude::*;
312    use crate::rw_reference_access::RwRefAccess;
313    use std::collections::hash_map::DefaultHasher;
314    use std::hash::{Hash, Hasher};
315
316    /// Create a chip with two cells TOP and SUB. TOP contains an instance of SUB.
317    fn create_test_chip() -> RwRefAccess<Chip> {
318        let mut chip = Chip::new();
319        let top = chip.create_cell("TOP".into());
320        let sub = chip.create_cell("SUB".into());
321        let _inst1 = chip.create_cell_instance(&top, &sub, Some("inst1".into()));
322        RwRefAccess::new(chip)
323    }
324
325    #[test]
326    fn create_rw_refaccess_from_mutable_reference() {
327        let mut chip = Chip::new();
328        let _rw_chip = RwRefAccess::new(&mut chip);
329        // rw_chip.each_cell();
330    }
331
332    fn hash<T: Hash>(t: &T) -> u64 {
333        let mut s = DefaultHasher::new();
334        t.hash(&mut s);
335        s.finish()
336    }
337
338    #[test]
339    fn test_find_cell_by_name() {
340        let chip = create_test_chip();
341        let _top = chip.cell_by_name("TOP").unwrap();
342        let _sub = chip.cell_by_name("SUB").unwrap();
343    }
344
345    #[test]
346    fn test_find_cell_instance_by_name() {
347        let chip = create_test_chip();
348        let top = chip.cell_by_name("TOP").unwrap();
349        let _inst1 = top.cell_instance_by_name("inst1").unwrap();
350    }
351
352    #[test]
353    fn test_cell_equality() {
354        let chip = create_test_chip();
355        let top = chip.cell_by_name("TOP").unwrap();
356        let sub = chip.cell_by_name("SUB").unwrap();
357        assert!(top == top.clone());
358        assert!(top != sub);
359    }
360
361    #[test]
362    fn test_cell_hash() {
363        let chip = create_test_chip();
364        let top = chip.cell_by_name("TOP").unwrap();
365        let sub = chip.cell_by_name("SUB").unwrap();
366        assert_eq!(hash(&top), hash(&top.clone()));
367        assert_eq!(hash(&sub), hash(&sub.clone()));
368        assert_ne!(hash(&top), hash(&sub)); // This assertion is expected to fail with very small probability.
369    }
370
371    #[test]
372    fn test_cell_instance_equality() {
373        let chip = create_test_chip();
374        let top = chip.cell_by_name("TOP").unwrap();
375        let sub = chip.cell_by_name("SUB").unwrap();
376        let inst1 = top.cell_instance_by_name("inst1").unwrap();
377        let inst2 = top.create_instance(&sub, Some("inst2".into()));
378        assert!(inst1 == inst1.clone());
379        assert!(inst1 != inst2);
380    }
381
382    #[test]
383    fn test_create_cell() {
384        let chip = create_test_chip();
385        chip.create_cell("NEW".into());
386        chip.cell_by_name("NEW").unwrap();
387    }
388
389    #[test]
390    fn test_create_instance() {
391        let chip = create_test_chip();
392        let top = chip.cell_by_name("TOP").unwrap();
393        let sub = chip.cell_by_name("SUB").unwrap();
394        let inst = top.create_instance(&sub, Some("inst2".into()));
395        assert!(inst.template() == sub);
396        assert!(inst.parent() == top);
397    }
398
399    #[test]
400    fn test_access_child_instances() {
401        let chip = create_test_chip();
402        let top = chip.cell_by_name("TOP").unwrap();
403        let children = top.each_cell_instance();
404        assert_eq!(children.len(), 1);
405    }
406
407    #[test]
408    fn test_cell_dependencies() {
409        let chip = create_test_chip();
410        let top = chip.cell_by_name("TOP").unwrap();
411        let sub = chip.cell_by_name("SUB").unwrap();
412        assert_eq!(top.each_cell_dependency().len(), 1);
413        assert_eq!(sub.each_cell_dependency().len(), 0);
414    }
415
416    #[test]
417    fn test_dependent_cells() {
418        let chip = create_test_chip();
419        let top = chip.cell_by_name("TOP").unwrap();
420        let sub = chip.cell_by_name("SUB").unwrap();
421        assert_eq!(top.each_dependent_cell().len(), 0);
422        assert_eq!(sub.each_dependent_cell().len(), 1);
423    }
424}