def __radd__(self, other): from spira.yevon.gdsii.elem_list import ElementList if isinstance(other, list): l = ElementList(other) l.append(self) return l elif isinstance(other, __Element__): return ElementList([other, self]) else: raise TypeError( "Wrong type of argument for addition in __Element__: " + str(type(other)))
def __and__(self, other): el = ElementList() for e1 in self.elements: for e2 in other.elements: # e1 = deepcopy(e1) # e2 = deepcopy(e2) # shape1 = e1.shape.transform_copy(e1.transformation) # shape2 = e2.shape.transform_copy(e2.transformation) shape1 = deepcopy(e1.shape).transform(e1.transformation) shape2 = deepcopy(e2.shape).transform(e2.transformation) # if shape1 != shape2: # if e1.shape != e2.shape: # if (e1.shape != e2.shape) and (e1.layer == e2.layer): # if (e1.shape != e2.shape) and (e1.layer.process == e2.layer.process): if (shape1 != shape2) and (e1.layer.process == e2.layer.process): shapes = shape1 & shape2 # print(shape1.points) # print(shape2.points) # print(shapes) # print('') for shape in shapes: el += Polygon(shape=shape, layer=e1.layer) # polygons = e1.intersection(e2) # for p in polygons: # p.layer.purpose = RDD.PURPOSE.INTERSECTED # for p in polygons: # el += p self.elements = el return self
def __filter___Cell____(self, item): from spira.yevon.utils import clipping from spira.yevon.gdsii.cell import Cell ports = PortList() elems = ElementList() for e in item.elements.polygons: e.shape = clipping.simplify_points(e.points) elems += e # points = clipping.simplify_points(e.points) # elems += e.copy(shape=points) # p = e.__class__(shape=points, layer=e.layer, transformation=e.transformation) # elems += e.__class__(shape=points, layer=e.layer, transformation=e.transformation) for e in item.elements.sref: elems += e for e in item.elements.labels: elems += e for p in item.ports: ports += p cell = Cell(elements=elems, ports=ports) # cell = item.__class__(elements=elems, ports=ports) return cell
def write_gdsii_mask(self, **kwargs): elems = ElementList() for pg in self.process_elements: for e in pg.elements: elems += e D = Cell(name=self.name + '_VMODEL', elements=elems) D.gdsii_output()
def filter_Cell(self, item): from copy import deepcopy from spira.yevon.gdsii.cell import Cell elems = ElementList() if self.width is None: for p1 in deepcopy(item.elements.polygons): if p1.layer.purpose in self.purposes: for edge in p1.edges: shape = ShapeEdge(original_shape=edge.line_shape, edge_width=edge.width, edge_type=self.edge_type) elems += edge.copy(shape=shape) elems += p1 else: for p1 in deepcopy(item.elements.polygons): if p1.layer.purpose in self.purposes: for edge in p1.edges: shape = ShapeEdge(original_shape=edge.line_shape, edge_width=self.width, edge_type=self.edge_type) elems += edge.copy(shape=shape) elems += p1 cell = Cell(elements=elems) return cell
def view_derived_overlap_elements(self, **kwargs): elems = ElementList() for pg in self.derived_overlap_elements: for e in pg.elements: elems += e name = '{}_{}'.format(self.name, 'DERIVED_OVERLAP_ELEMENTS') D = Cell(name=name, elements=elems) D.gdsii_view()
def __or__(self, other): if self.layer == other.layer: s1 = self.shape.transform_copy(self.transformation) s2 = other.shape.transform_copy(other.transformation) shapes = s1.__or__(s2) elems = [Polygon(shape=s, layer=self.layer) for s in shapes] return elems return ElementList([self, other])
def filter_Port(self, item): elems = ElementList() elems += self._create_label(item) if item.purpose.symbol == 'C': elems += self._contact_template(item) else: elems += self._edge_template(item) elems += self._create_arrow(item) cell = Cell(elements=elems) return cell
def filter_Polygon(self, item): elems = ElementList() for p in item.ports: el = self.filter_Port(p).elements # FIXME: We have to use this for PCells. elems += el.transform(item.transformation) # FIXME: Have to use this for GDS files. # elems += el cell = Cell(elements=elems) return cell
def reference_metal_blocks(S): from copy import deepcopy elems = ElementList() for layer in RDD.get_physical_layers_by_purpose(purposes=['METAL', 'GND']): layer = deepcopy(layer) if S.reference.is_layer_in_cell(layer): bbox_shape = S.bbox_info.bounding_box() layer.purpose = RDD.PURPOSE.BOUNDARY_BOX elems += Polygon(shape=bbox_shape, layer=layer) return elems
def get_process_polygons(elements, operation='or'): elems = ElementList() for process in RDD.VMODEL.PROCESS_FLOW.active_processes: for layer in RDD.get_physical_layers_by_process(processes=process): LF = LayerFilterAllow(layers=[layer]) el = LF(elements.polygons) if operation == 'or': pg = PolygonGroup(elements=el, layer=layer).merge elif operation == 'and': pg = PolygonGroup(elements=el, layer=layer).intersect elems += pg return elems
def __init__(self, name=None, elements=None, ports=None, library=None, **kwargs): super().__init__(**kwargs) if name is not None: s = '{}_{}'.format(name, Cell._next_uid) self.__dict__['__name__'] = s Cell.name.__set__(self, s) self.uid = Cell._next_uid Cell._next_uid += 1 if library is not None: self.library = library if elements is not None: self.elements = ElementList(elements) if ports is not None: self.ports = PortList(ports)
def gdsii_output_electrical_connection(self): elems = ElementList() overlap_elems, edges = self.edges for e in overlap_elems: elems += e for edge in edges: elems += edge.outside for e in self.cell.elements: elems += e D = Cell(name='_ELECTRICAL_CONNECT', elements=elems) D.gdsii_output()
def intersect(self): elems = ElementList() el1 = deepcopy(self.elements) el2 = deepcopy(self.elements) for i, e1 in enumerate(el1): for j, e2 in enumerate(el2): if e1.shape != e2.shape: polygons = e1 & e2 for p in polygons: p.layer.purpose = RDD.PURPOSE.INTERSECTED for p in polygons: elems += p self.elements = elems return self
def union(self): elems = ElementList() if len(self.elements) > 1: points = [] for e in self.elements: shape = e.shape.transform(e.transformation).snap_to_grid() points.append(shape.points) merged_points = clipping.boolean(subj=points, clip_type='or') for uid, pts in enumerate(merged_points): elems += Polygon(shape=pts, layer=self.layer) else: elems = self.elements self.elements = elems return self
def get_derived_elements(elements, mapping, store_as_edge=False): """ Given a list of elements and a list of tuples (DerivedLayer, PPLayer), create new elements according to the boolean operations of the DerivedLayer and place these elements on the specified PPLayer. """ derived_layers = mapping.keys() export_layers = mapping.values() elems = ElementList() for derived_layer, export_layer in zip(derived_layers, export_layers): pg = _derived_elements(elems=elements, derived_layer=derived_layer) for p in pg.elements: if store_as_edge is True: elems += Edge(shape=p.shape, layer=deepcopy(export_layer)) else: elems += Polygon(shape=p.shape, layer=deepcopy(export_layer)) return elems
def wrap_references(cell, c2dmap, devices): for e in cell.elements.sref: if isinstance(e.reference, Device): D = deepcopy(e.reference) D.elements.transform(e.transformation) D.ports.transform(e.transformation) devices[D] = D.elements D.elements = ElementList() S = deepcopy(e) S.reference = D c2dmap[cell] += S else: S = deepcopy(e) S.reference = c2dmap[e.reference] c2dmap[cell] += S
def __filter___Cell____(self, item): from copy import deepcopy from spira.yevon.gdsii.cell import Cell elems = ElementList() for p1 in deepcopy(item.elements): if p1.layer.purpose == RDD.PURPOSE.METAL: for edge in p1.edges: e = EdgeAdapter(original_edge=edge, edge_type=self.edge_type) # print(e) elems += e # elems += edge.outside.transform(edge.transformation) elems += p1 cell = Cell(elements=elems) return cell
def get_process_polygons(elements, operation='or'): from spira.yevon.gdsii.polygon_group import PolygonGroup from spira.yevon.filters.layer_filter import LayerFilterAllow elems = ElementList() for process in RDD.VMODEL.PROCESS_FLOW.active_processes: for layer in RDD.get_physical_layers_by_process(processes=process): LF = LayerFilterAllow(layers=[layer]) el = LF(elements.polygons) if operation == 'or': pg = PolygonGroup(elements=el, layer=layer).union elif operation == 'and': pg = PolygonGroup(elements=el, layer=layer).intersect elif operation == 'not': pg = PolygonGroup(elements=el, layer=layer).difference elems += pg return elems
def wrap_references(self, cell, c2dmap, devices): from spira.yevon.gdsii.pcell import Device for e in cell.elements.sref: if isinstance(e.reference, Device): D = deepcopy(e.reference) D.elements.transform(e.transformation) D.ports.transform(e.transformation) devices[D] = D.elements D.elements = ElementList() S = deepcopy(e) S.reference = D c2dmap[cell] += S else: S = deepcopy(e) S.reference = c2dmap[e.reference] c2dmap[cell] += S
def RouteManhattan(ports, layer, width=None, corners='miter', bend_radius=1): """ """ elems = ElementList() if isinstance(ports, list): list1 = [p for p in ports if (p.alias[0] == 'D')] else: list1 = ports.get_ports_by_type('D') list2 = [p.flip() for p in list1] n = 2 iter1 = iter(list1) pl = [] for x in list2: pl.extend([next(iter1) for _ in range(n - 1)]) pl.append(x) pl.extend(iter1) pl.insert(0, ports[0]) pl.append(ports[-1]) for x in range(len(pl) - 1): p1, p2 = pl[x], pl[x + 1] angle = ug.angle_diff(p2.orientation, p1.orientation) if angle not in [90, 180, 270]: raise ValueError('Angle must be in 90 degree angles.') if (angle == 180) and (p1.midpoint != p2.midpoint): elems += Route180(port1=p1, port2=p2, width=width, layer=layer, corners=corners, bend_radius=bend_radius) elif (angle == 90) or (angle == 270): elems += Route90(port1=p1, port2=p2, width=width, layer=layer, corners=corners, bend_radius=bend_radius) return elems
def __xor__(self, other): pts1, pts2 = [], [] for e in self.elements: s1 = e.shape.transform_copy(e.transformation) pts1.append(s1.points) for e in other.elements: s1 = e.shape.transform_copy(e.transformation) pts2.append(s1.points) self.elements = ElementList() if (len(pts1) > 0) and (len(pts2) > 0): p1 = gdspy.PolygonSet(polygons=pts1) p2 = gdspy.PolygonSet(polygons=pts2) ply = gdspy.boolean(p1, p2, operation='not') for points in ply.polygons: self.elements += Polygon(shape=points, layer=self.layer) return self
def generate_edges(shape, layer): """ Generates edge objects for each shape segment. """ xpts = list(shape.x_coords) ypts = list(shape.y_coords) n = len(xpts) xpts.append(xpts[0]) ypts.append(ypts[0]) clockwise = 0 for i in range(0, n): clockwise += ((xpts[i + 1] - xpts[i]) * (ypts[i + 1] + ypts[i])) if layer.name == 'BBOX': bbox = True else: bbox = False edges = ElementList() for i in range(0, n): name = '{}_e{}'.format(layer.name, i) x = np.sign(clockwise) * (xpts[i + 1] - xpts[i]) y = np.sign(clockwise) * (ypts[i] - ypts[i + 1]) orientation = (np.arctan2(x, y) * constants.RAD2DEG) midpoint = [(xpts[i + 1] + xpts[i]) / 2, (ypts[i + 1] + ypts[i]) / 2] width = np.abs( np.sqrt((xpts[i + 1] - xpts[i])**2 + (ypts[i + 1] - ypts[i])**2)) layer = RDD.GDSII.IMPORT_LAYER_MAP[layer] inward_extend = RDD[layer.process.symbol].MIN_SIZE / 2 outward_extend = RDD[layer.process.symbol].MIN_SIZE / 2 edge = Edge(width=width, inward_extend=inward_extend, outward_extend=outward_extend, process=layer.process) T = Rotation(orientation + 90) + Translation(midpoint) edge.transform(T) edges += edge return edges
def filter_Cell(self, item): from spira.yevon.gdsii.cell import Cell ports = PortList() elems = ElementList() for e in item.derived_merged_elements: elems += e for e in item.elements.sref: elems += e for e in item.elements.labels: elems += e for p in item.ports: if p.purpose.symbol == 'P': ports += p if p.purpose.symbol == 'T': ports += p cell = Cell(elements=elems, ports=ports) return cell
def filter_Cell(self, item): from spira.yevon.utils import clipping from spira.yevon.gdsii.cell import Cell ports = PortList() elems = ElementList() for e in item.elements.polygons: e.shape = clipping.simplify_points(e.points) elems += e for e in item.elements.sref: elems += e for e in item.elements.labels: elems += e for p in item.ports: ports += p cell = Cell(elements=elems, ports=ports) return cell
def __filter___Cell____(self, item): from spira.yevon.gdsii.cell import Cell ports = PortList() elems = ElementList() # for pg in item.process_elements: # for e in pg.elements: # elems += e for e in item.process_elements: elems += e for e in item.elements.sref: elems += e for e in item.elements.labels: elems += e for p in item.ports: ports += p cell = Cell(elements=elems, ports=ports) return cell
def __filter___Cell____(self, item): from spira.yevon.gdsii.cell import Cell from spira.yevon.utils import clipping from spira.yevon.vmodel.virtual import virtual_connect from shapely.geometry import Polygon as ShapelyPolygon ports = PortList() elems = ElementList() v_model = virtual_connect(device=item) for e in v_model.connected_elements: elems += e for e in item.elements.sref: elems += e for e in item.elements.labels: elems += e for p in item.ports: ports += p cell = Cell(elements=elems, ports=ports) return cell
def filter_Cell(self, item): from spira.yevon.utils import clipping from spira.yevon.gdsii.cell import Cell from spira.yevon.geometry.ports import Port from spira.yevon.vmodel.virtual import virtual_connect from shapely.geometry import Polygon as ShapelyPolygon # ports = PortList() elems = ElementList() v_model = virtual_connect(device=item) for e1 in v_model.derived_contacts: ps = e1.layer.process.symbol for e2 in item.elements: for m in ['BOT_LAYER', 'TOP_LAYER']: if ps in RDD.VIAS.keys: if e2.layer == RDD.VIAS[ps].LAYER_STACK[m]: if e2.encloses(e1.center): port = Port( name='{}:Cv'.format(ps), midpoint=e1.center, process=e1.layer.process) e2.ports += port elems += item.elements for e in item.elements.sref: elems += e for e in item.elements.labels: elems += e # for p in item.ports: # ports += p # cell = Cell(elements=elems, ports=ports) cell = Cell(elements=elems) return cell
def filter_Cell(self, item): from spira.yevon.gdsii.cell import Cell ports = PortList() elems = ElementList() c2dmap, devices = {}, {} for cell in item.dependencies(): # FIXME: Why can I not use Cell? # ERC Port doesn't connect. D = item.__class__(name=cell.name, elements=deepcopy(cell.elements.polygons), ports=deepcopy(cell.ports)) c2dmap.update({cell: D}) for cell in item.dependencies(): self.wrap_references(cell, c2dmap, devices) D = c2dmap[item] for e in D.elements.polygons: if e.layer.purpose.symbol == 'METAL': e.layer.purpose = RDD.PURPOSE.CIRCUIT_METAL # e.layer.purpose = RDD.PURPOSE.METAL for d in D.dependencies(): if d in devices.keys(): d.elements = devices[d] for e in d.elements.polygons: if e.layer.purpose.symbol == 'METAL': e.layer.purpose = RDD.PURPOSE.DEVICE_METAL # e.layer.purpose = RDD.PURPOSE.METAL return D
def __and__(self, other): el = ElementList() for e1 in self.elements: for e2 in other.elements: shape1 = e1.shape.transform_copy(e1.transformation) shape2 = e2.shape.transform_copy(e2.transformation) # if (shape1 != shape2) and (e1.layer.process == e2.layer.process): # shapes = shape1 & shape2 # for shape in shapes: # el += Polygon(shape=shape, layer=e1.layer) # # FIXME: We need this for virtual contact connections. # if shape1 != shape2: # shapes = shape1 & shape2 # for shape in shapes: # el += Polygon(shape=shape, layer=e1.layer) shapes = shape1 & shape2 for shape in shapes: el += Polygon(shape=shape, layer=e1.layer) self.elements = el return self