From 6a1208bc339b0be13ba386e7ae806fd09ca34c3f Mon Sep 17 00:00:00 2001 From: jan Date: Sun, 27 Feb 2022 21:20:12 -0800 Subject: [PATCH] add some helper functions to libraries --- masque/library/device_library.py | 58 ++++++++++++++++++++++++++++++++ masque/library/library.py | 16 +++++++++ 2 files changed, 74 insertions(+) diff --git a/masque/library/device_library.py b/masque/library/device_library.py index b00ef8c..130d1aa 100644 --- a/masque/library/device_library.py +++ b/masque/library/device_library.py @@ -123,3 +123,61 @@ class DeviceLibrary: if name in other.cache: self.cache[name] = other.cache[name] return self + + def clear_cache(self: D) -> D: + """ + Clear the cache of this library. + This is usually used before modifying or deleting cells, e.g. when merging + with another library. + + Returns: + self + """ + self.cache = {} + return self + + def add_device( + self, + name: str, + fn: Callable[[], 'Device'], + dev2pat: Callable[['Device'], 'Pattern'], + prefix: str = '', + ) -> None: + """ + Convenience function for adding a device to the library. + + - The device is generated with the provided `fn()` + - Port info is written to the pattern using the provied dev2pat + - The pattern is renamed to match the provided `prefix + name` + - If `prefix` is non-empty, a wrapped copy is also added, named + `name` (no prefix). See `wrap_device()` for details. + + Adding devices with this function helps to + - Make sure Pattern names are reflective of what the devices are named + - Ensure port info is written into the `Pattern`, so that the `Device` + can be reconstituted from the layout. + - Simplify adding a prefix to all device names, to make it easier to + track their provenance and purpose, while also allowing for + generic device names which can later be swapped out with different + underlying implementations. + + Args: + name: Base name for the device. If a prefix is used, this is the + "generic" name (e.g. "L3_cavity" vs "2022_02_02_L3_cavity"). + fn: Function which is called to generate the device. + dev2pat: Post-processing function which is called to add the port + info into the device's pattern. + prefix: If present, the actual device is named `prefix + name`, and + a second device with name `name` is also added (containing only + this one). + """ + def build_dev() -> 'Device': + dev = fn() + dev.pattern = dev2pat(dev) + dev.pattern.rename(prefix + name) + return dev + + self[prefix + name] = build_dev + if prefix: + self.wrap_device(name, prefix + name) + diff --git a/masque/library/library.py b/masque/library/library.py index 4796b82..1d44738 100644 --- a/masque/library/library.py +++ b/masque/library/library.py @@ -7,6 +7,7 @@ from typing import Any, Tuple, Union, Iterator import logging from pprint import pformat from dataclasses import dataclass +import copy from ..error import LibraryError @@ -303,6 +304,21 @@ class Library: del self.secondary[key2] del self.cache[key2] + def copy(self: L, preserve_cache: bool = False) -> L: + """ + Create a copy of this `Library`. + + A shallow copy is made of the contained dicts. + Note that you should probably clear the cache (with `clear_cache()`) after copying. + + Returns: + A copy of self + """ + new = Library() + new.primary.update(self.primary) + new.secondary.update(self.secondary) + new.cache.update(self.cache) + return new def clear_cache(self: L) -> L: """