Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 8 additions & 4 deletions libs/gds21/src/write.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,20 +13,24 @@ pub struct GdsWriter<'wr> {
impl<'wr> GdsWriter<'wr> {
/// Create new [GdsWriter] with destination file `fname`
pub fn open(fname: impl AsRef<Path>) -> GdsResult<Self> {
let file = BufWriter::new(File::create(fname)?);
Ok(Self::new(file))
Ok(Self::new(File::create(fname)?))
}
/// Create a new [GdsWriter] to destination `dest`
///
/// Writes to `dest` are buffered, since records are encoded a few bytes at a time.
pub fn new(dest: impl Write + 'wr) -> Self {
Self {
dest: Box::new(dest),
dest: Box::new(BufWriter::new(dest)),
}
}
/// Write [GdsLibrary] `lib` to our destination
pub fn write_lib(&mut self, lib: &GdsLibrary) -> GdsResult<()> {
// `write_lib` is our typicaly entry point when writing to file.
// It quickly dispatches most behavior off to our implementation of the [Encode] trait.
self.encode_lib(lib)
self.encode_lib(lib)?;
// Flush explicitly: dropping the buffer would discard any write error.
self.dest.flush()?;
Ok(())
}
/// Helper to write a sequence of [GdsRecord] references
fn write_records(&mut self, records: &[GdsRecord]) -> GdsResult<()> {
Expand Down
12 changes: 10 additions & 2 deletions substrate/src/layout/convert/gds.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,10 @@ pub struct GdsExporter<'a> {
layers: Arc<RwLock<Layers>>,
backtrace: Vec<ErrorContext>,
names_used: HashSet<ArcStr>,
/// The next suffix to try when renaming a cell with a given name.
///
/// Every lower suffix is already in `names_used`.
next_suffix: HashMap<ArcStr, usize>,
/// The top level cell.
///
/// The name of this cell will be preserved.
Expand Down Expand Up @@ -82,6 +86,7 @@ impl SubstrateCtx {
layers: data.layers(),
backtrace: Vec::new(),
names_used: HashSet::with_capacity(data.layouts().cells().count()),
next_suffix: HashMap::new(),
top: None,
export_set: ExportSet::All,
names: SecondaryMap::new(),
Expand All @@ -105,6 +110,7 @@ impl SubstrateCtx {
layers: data.layers(),
backtrace: Vec::new(),
names_used: HashSet::with_capacity(data.layouts().cells().count()),
next_suffix: HashMap::new(),
export_set: ExportSet::for_top(&top),
top: Some(top),
names: SecondaryMap::new(),
Expand Down Expand Up @@ -536,13 +542,15 @@ impl<'a> GdsExporter<'a> {
fn get_cell_name(&mut self, cell: &Arc<Cell>) -> ArcStr {
let name = cell.name();
let name = if self.names_used.contains(name) && !self.is_top(cell) {
let mut i = 1;
// Resume where the previous search for this name stopped. Scanning from 1
// every time is quadratic in the number of cells sharing a name.
let i = self.next_suffix.entry(name.clone()).or_insert(1);
loop {
let newname = arcstr::format!("{}_{}", name, i);
*i += 1;
if !self.names_used.contains(&newname) {
break newname;
}
i += 1;
}
} else {
name.clone()
Expand Down