You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
snarled/snarled/interfaces/masque.py

110 lines
3.5 KiB
Python

2 years ago
"""
Functionality for extracting geometry and label info from `masque` patterns.
"""
2 years ago
from typing import Sequence, Dict, List, Any, Tuple, Optional, Mapping
from collections import defaultdict
import numpy
from numpy.typing import NDArray
from masque import Pattern
from masque.file import oasis, gdsii
from masque.shapes import Polygon
from ..types import layer_t
from ..utils import connectivity2layers
def read_cell(
cell: Pattern,
2 years ago
connectivity: Sequence[Tuple[layer_t, Optional[layer_t], layer_t]],
label_mapping: Optional[Mapping[layer_t, layer_t]] = None,
) -> Tuple[
defaultdict[layer_t, List[NDArray[numpy.float64]]],
defaultdict[layer_t, List[Tuple[float, float, str]]]]:
2 years ago
"""
Extract `polys` and `labels` from a `masque.Pattern`.
This function extracts the data needed by `snarled.trace_connectivity`.
2 years ago
Args:
cell: A `masque` `Pattern` object. Usually your topcell.
connectivity: A sequence of 3-tuples specifying the layer connectivity.
Same as what is provided to `snarled.trace_connectivity`.
2 years ago
label_mapping: A mapping of `{label_layer: metal_layer}`. This allows labels
to refer to nets on metal layers without the labels themselves being on
that layer.
Returns:
`polys` and `labels` data structures, to be passed to `snarled.trace_connectivity`.
2 years ago
"""
2 years ago
metal_layers, via_layers = connectivity2layers(connectivity)
poly_layers = metal_layers | via_layers
if label_mapping is None:
label_mapping = {layer: layer for layer in metal_layers}
label_layers = {label_layer for label_layer in label_mapping.keys()}
cell = cell.deepcopy().subset(
2 years ago
shapes_func=lambda ss: ss.layer in poly_layers,
labels_func=lambda ll: ll.layer in label_layers,
subpatterns_func=lambda ss: True,
)
cell = cell.flatten()
2 years ago
polys = load_polys(cell, list(poly_layers))
2 years ago
metal_labels = defaultdict(list)
for label_layer, metal_layer in label_mapping.items():
labels = []
for ll in cell.labels:
if ll.layer != label_layer:
continue
if ll.repetition is None:
displacements = [(0, 0)]
else:
displacements = ll.repetition.displacements
for displacement in displacements:
offset = ll.offset + displacement
metal_labels[metal_layer].append(
(*offset, ll.string)
)
2 years ago
return polys, metal_labels
def load_polys(
cell: Pattern,
2 years ago
layers: Sequence[layer_t],
) -> defaultdict[layer_t, List[NDArray[numpy.float64]]]:
2 years ago
"""
Given a *flat* `masque.Pattern`, extract the polygon info into the format used by `snarled`.
2 years ago
Args:
cell: The `Pattern` object to extract from.
layers: The layers to extract.
Returns:
`{layer0: [poly0, [(x0, y0), (x1, y1), ...], poly2, ...]}`
`polys` structure usable by `snarled.trace_connectivity`.
2 years ago
"""
2 years ago
polys = defaultdict(list)
for ss in cell.shapes:
2 years ago
if ss.layer not in layers:
continue
assert(isinstance(ss, Polygon))
if ss.repetition is None:
displacements = [(0, 0)]
else:
displacements = ss.repetition.displacements
for displacement in displacements:
polys[ss.layer].append(
ss.vertices + ss.offset + displacement
)
return polys