Skip to content

Commit

Permalink
feat(scir): SCIR lib imports merge only the instantiated cell (#437)
Browse files Browse the repository at this point in the history
  • Loading branch information
rahulk29 authored Jul 26, 2024
1 parent 21fec8b commit 7a0b285
Show file tree
Hide file tree
Showing 3 changed files with 67 additions and 3 deletions.
28 changes: 27 additions & 1 deletion libs/scir/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
//! Zero-width buses are not supported.
#![warn(missing_docs)]

use std::collections::HashMap;
use std::collections::{HashMap, HashSet, VecDeque};
use std::fmt::{Display, Formatter};
use std::ops::{Deref, DerefMut};

Expand Down Expand Up @@ -1045,6 +1045,32 @@ impl<S: Schema + ?Sized> LibraryBuilder<S> {
self.cells.iter().map(|(id, cell)| (*id, cell))
}

/// The list of cell IDs instantiated by the given root cells.
///
/// The list returned will include the root cell IDs.
pub(crate) fn cells_used_by(&self, roots: impl IntoIterator<Item = CellId>) -> Vec<CellId> {
let mut stack = VecDeque::new();
let mut visited = HashSet::new();
for root in roots {
stack.push_back(root);
}

while let Some(id) = stack.pop_front() {
if visited.contains(&id) {
continue;
}
visited.insert(id);
let cell = self.cell(id);
for (_, inst) in cell.instances() {
if let ChildId::Cell(c) = inst.child {
stack.push_back(c);
}
}
}

visited.drain().collect()
}

/// Gets the primitive with the given ID.
///
/// # Panics
Expand Down
40 changes: 39 additions & 1 deletion libs/scir/src/merge.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,10 @@ struct Merger<'a, S: Schema + ?Sized> {
names: Names<CellId>,
dst: &'a mut LibraryBuilder<S>,
src: LibraryBuilder<S>,
/// The list of source cell IDs to merge into `dst`.
///
/// If [`None`], all source cells will be merged.
merge_cells: Option<Vec<CellId>>,
}

impl<'a, S: Schema + ?Sized> Merger<'a, S> {
Expand All @@ -30,14 +34,39 @@ impl<'a, S: Schema + ?Sized> Merger<'a, S> {
names: Names::with_capacity(src.cells.len() + dst.cells.len()),
dst,
src,
merge_cells: None,
}
}

#[inline]
fn merge_cells(
dst: &'a mut LibraryBuilder<S>,
src: LibraryBuilder<S>,
cells: impl IntoIterator<Item = CellId>,
) -> Self {
Self {
cell_mapping: HashMap::with_capacity(src.cells.len()),
primitive_mapping: HashMap::with_capacity(src.primitives.len()),
names: Names::with_capacity(src.cells.len() + dst.cells.len()),
dst,
src,
merge_cells: Some(cells.into_iter().collect()),
}
}

fn merge(mut self) -> MergedMapping {
for (id, cell) in self.dst.cells() {
self.names.reserve_name(id, cell.name());
}
let mut cells: Vec<_> = self.src.cells.drain(..).collect();
let mut cells: Vec<_> = if let Some(cells) = self.merge_cells.as_ref() {
self.src
.cells_used_by(cells.iter().copied())
.iter()
.map(|&id| (id, self.src.cell(id).clone()))
.collect()
} else {
self.src.cells.drain(..).collect()
};
let primitives: Vec<_> = self.src.primitives.drain(..).collect();
for (id, cell) in cells.iter_mut() {
self.assign_cell_identifiers(*id, cell);
Expand Down Expand Up @@ -119,4 +148,13 @@ impl<S: Schema + ?Sized> LibraryBuilder<S> {
pub fn merge(&mut self, other: Self) -> MergedMapping {
Merger::new(self, other).merge()
}

/// Merges the given cells from another SCIR library into the current library.
pub fn merge_cells(
&mut self,
other: Self,
cells: impl IntoIterator<Item = CellId>,
) -> MergedMapping {
Merger::merge_cells(self, other, cells).merge()
}
}
2 changes: 1 addition & 1 deletion substrate/src/schematic/conv.rs
Original file line number Diff line number Diff line change
Expand Up @@ -557,7 +557,7 @@ impl<S: Schema + ?Sized> RawCell<S> {
cell: id,
port_map,
}) => {
let map = lib_ctx.lib.merge((**lib).clone());
let map = lib_ctx.lib.merge_cells((**lib).clone(), [*id]);
let id = map.new_cell_id(*id);
let mut conv = ScirCellConversion::new();
conv.cell_id = Some(id);
Expand Down

0 comments on commit 7a0b285

Please sign in to comment.