Skip to main content

klayout_core/
library.rs

1//! Library: top-level container.
2//!
3//! Owns the layer table, the cell arena, and the dedup caches. `Send + Sync`
4//! by construction so `Library::build` can be called concurrently from
5//! multiple threads. Internal state uses `RwLock` for the layer table and
6//! cell arena (append-only, so reads dominate) and `DashMap` for dedup
7//! lookups.
8
9use crate::cell::{Cell, CellBuilder, CellId, CellName};
10use crate::component::{BuildCtx, Component};
11use crate::hash::{ContentHash, ParamHash};
12use crate::layer::{LayerIndex, LayerInfo, LayerTable};
13use dashmap::DashMap;
14use parking_lot::RwLock;
15use smol_str::SmolStr;
16use std::sync::Arc;
17
18pub struct Library {
19    name: SmolStr,
20    dbu: i64,
21    grid: i64,
22    layers: RwLock<LayerTable>,
23    cells: RwLock<Vec<Arc<Cell>>>,
24    by_hash: DashMap<ContentHash, CellId>,
25    by_name: DashMap<CellName, CellId>,
26    by_params: DashMap<ParamHash, CellId>,
27}
28
29impl Library {
30    /// Create a new library. `dbu` is database units per micron (e.g. 1000
31    /// for a 1 nm grid). `grid` is the manufacturing grid in DBU; coordinates
32    /// not on this grid are rejected by the (future) grid-check pass.
33    pub fn new(name: impl Into<SmolStr>, dbu: i64) -> Self {
34        Self {
35            name: name.into(),
36            dbu,
37            grid: 1,
38            layers: RwLock::new(LayerTable::new()),
39            cells: RwLock::new(Vec::new()),
40            by_hash: DashMap::new(),
41            by_name: DashMap::new(),
42            by_params: DashMap::new(),
43        }
44    }
45
46    pub fn name(&self) -> &str {
47        &self.name
48    }
49
50    pub fn dbu(&self) -> i64 {
51        self.dbu
52    }
53
54    pub fn grid(&self) -> i64 {
55        self.grid
56    }
57
58    pub fn set_grid(&mut self, grid: i64) {
59        assert!(grid >= 1, "grid must be >= 1");
60        self.grid = grid;
61    }
62
63    pub fn layer(&self, info: LayerInfo) -> LayerIndex {
64        self.layers.write().get_or_insert(info)
65    }
66
67    pub fn layer_info(&self, idx: LayerIndex) -> LayerInfo {
68        self.layers.read().info(idx).clone()
69    }
70
71    pub fn layer_by_gds(&self, layer: u16, datatype: u16) -> Option<LayerIndex> {
72        self.layers.read().by_gds(layer, datatype)
73    }
74
75    pub fn layer_by_name(&self, name: &str) -> Option<LayerIndex> {
76        self.layers.read().by_name(name)
77    }
78
79    /// Freeze a builder and insert into the library, returning a `CellId`.
80    /// If a cell with the same `ContentHash` already exists, the existing
81    /// `CellId` is returned and the builder is discarded.
82    pub fn insert(&self, builder: CellBuilder) -> CellId {
83        let cell = builder.freeze(self);
84        if let Some(existing) = self.by_hash.get(&cell.content_hash()) {
85            return *existing;
86        }
87        let mut cells = self.cells.write();
88        let slot = cells.len();
89        let id = CellId::from_slot(slot);
90        let arc = Arc::new(cell);
91        let hash = arc.content_hash();
92        let name = arc.name().clone();
93        cells.push(arc);
94        drop(cells);
95        self.by_hash.insert(hash, id);
96        if !name.is_empty() {
97            self.by_name.entry(name).or_insert(id);
98        }
99        id
100    }
101
102    pub fn get(&self, id: CellId) -> Arc<Cell> {
103        self.cells.read()[id.slot()].clone()
104    }
105
106    pub fn try_get(&self, id: CellId) -> Option<Arc<Cell>> {
107        self.cells.read().get(id.slot()).cloned()
108    }
109
110    pub fn by_name(&self, name: &str) -> Option<CellId> {
111        let key = CellName::new(name);
112        self.by_name.get(&key).map(|v| *v)
113    }
114
115    pub fn by_content(&self, hash: ContentHash) -> Option<CellId> {
116        self.by_hash.get(&hash).map(|v| *v)
117    }
118
119    pub fn cell_count(&self) -> usize {
120        self.cells.read().len()
121    }
122
123    pub fn build<C: Component>(&self, c: &C) -> CellId {
124        let pk = c.param_hash();
125        if let Some(id) = self.by_params.get(&pk) {
126            return *id;
127        }
128        let ctx = BuildCtx::new(self);
129        let mut builder = c.build(&ctx);
130        if builder.name().is_empty() {
131            builder.set_name(c.cell_name());
132        }
133        let id = self.insert(builder);
134        self.by_params.insert(pk, id);
135        id
136    }
137
138    /// Cells with no parents in this library. Walks all cells and subtracts
139    /// any referenced as instance children.
140    pub fn top_cells(&self) -> Vec<CellId> {
141        let cells = self.cells.read();
142        let mut is_child = vec![false; cells.len()];
143        for c in cells.iter() {
144            for inst in c.instances() {
145                is_child[inst.cell.slot()] = true;
146            }
147        }
148        cells
149            .iter()
150            .enumerate()
151            .filter_map(|(i, _)| {
152                if !is_child[i] {
153                    Some(CellId::from_slot(i))
154                } else {
155                    None
156                }
157            })
158            .collect()
159    }
160
161    pub fn all_cells(&self) -> Vec<(CellId, Arc<Cell>)> {
162        self.cells
163            .read()
164            .iter()
165            .enumerate()
166            .map(|(i, c)| (CellId::from_slot(i), c.clone()))
167            .collect()
168    }
169}