def normalize(self, dimension, origin=ap.SOUTH_WEST): """Makes all components the same size on some dimension""" if not self.cells: return max_width = max(cell.bbox().width() for cell in self.cells) max_height = max(cell.bbox().height() for cell in self.cells) for cell in self.cells: bbox = cell.bbox() if not (bbox.width() == max_width and bbox.height == max_height): dx = max_width - bbox.width() if dimension in (ap.WIDTH, ap.BOTH) else 0 dy = (max_height - bbox.height() if dimension in (ap.HEIGHT, ap.BOTH) else 0) if origin == ap.SOUTH_WEST: box = pya.Box(bbox.left, bbox.bottom, bbox.right + dx, bbox.top + dy) elif origin == ap.SOUTH_EAST: box = pya.Box(bbox.left - dx, bbox.bottom, bbox.right, bbox.top + dy) elif origin == ap.NORTH_WEST: box = pya.Box(bbox.left, bbox.bottom - dy, bbox.right + dx, bbox.top) elif origin == ap.NORTH_EAST: box = pya.Box(bbox.left - dx, bbox.bottom - dy, bbox.right, bbox.top) layer = cell.layout().layer(ap.DEVREC_LAYER, 0) cell.shapes(layer).insert(box)
def produce_impl(self): squares = [2, 5, 10, 20] width = self.w * 1000 length = max(squares) * self.w * 1000 fox_bloat = 40000 ito_bloat = 10000 pad = pya.Box(pya.Point(0, 0), pya.Point(80000, 80000)) self.cell.shapes(self.nno_layer).insert(pad) pads = [pad] for s in squares: length = s * self.w * 1000 newpad = pad.moved(length + 80000, 0) pads.append(newpad) fox_extent_box = pya.Box(0, 0, 160000 + max(squares) * self.w * 1000, 80000).enlarge(pya.Point( fox_bloat, fox_bloat)) fox_box = pya.Polygon(fox_extent_box) fox_box_cutout = pya.Region( pya.Box(pya.Point(80000, 40000 - width / 2), pya.Point(80000 + length, 40000 + width / 2))) for p in pads: fox_box_cutout.insert(p) self.cell.shapes(self.nno_layer).insert(p) fox_box = pya.Region(fox_box) - fox_box_cutout self.cell.shapes(self.fox_layer).insert(fox_box) ito_extent_box = fox_extent_box.dup() ito_extent_box.enlarge(pya.Point(ito_bloat, ito_bloat)) ito_iso = pya.Polygon(ito_extent_box) ito_iso.insert_hole(fox_extent_box) self.cell.shapes(self.ito_layer).insert(ito_iso) self.cell.shapes(self.hfoetch_layer).insert(ito_extent_box)
def demo(): a = pya.Region() a.insert(pya.Box(0, 0, 100, 1000)) b = pya.Region() b.insert(pya.Box(200, 0, 300, 1000)) c = pya.Region() c.insert(pya.Box(0, 0, 500, 500)) print("c", c.width_check(200)) # width check (w < 200 DBU) # simple version -> more options available for the complex variant of this method too_small = a.width_check(200) # space check (here: separation between a and b, s < 200 DBU) too_close = a.separation_check(b, 200) # NOTE: "too_small" and "too_close" are pya.EdgePairs collections of error markers print("too_small is: ", too_small) print("too_close is: ", too_close)
def make_dicing_lanes(self): """Make the dicing lanes""" container = self.create_cell("DicingLanes") instance = pya.CellInstArray(container.cell_index(), pya.Trans(0, 0)) self.cell(self.name).insert(instance) lw = self.lane_width / 2 for dicing_layer in ap.DICING_LAYERS: layer = self.layer(dicing_layer[0], dicing_layer[1]) for row in range(1, self.rows): y = row * (self.chip_height + self.spacing) - self.spacing / 2 box = pya.Box(0, y - lw, self.max_width, y + lw) container.shapes(layer).insert(box) for col in range(1, self.cols): x = col * (self.chip_width + self.spacing) - self.spacing / 2 for row in range(self.rows): y1 = row * (self.chip_height + self.spacing) y2 = (row + 1) * (self.chip_height + self.spacing) - self.spacing box = pya.Box(x - lw, y1, x + lw, y2) container.shapes(layer).insert(box) # on the corners, line has half the width lw = self.lane_width / 4 for row in [0, self.rows]: y = row * (self.chip_height + self.spacing) - self.spacing / 2 box = pya.Box(0, y - lw, self.max_width, y + lw) container.shapes(layer).insert(box) for col in [0, self.cols]: x = col * (self.chip_width + self.spacing) - self.spacing / 2 for row in range(self.rows): y1 = row * (self.chip_height + self.spacing) y2 = (row + 1) * (self.chip_height + self.spacing) - self.spacing box = pya.Box(x - lw, y1, x + lw, y2) container.shapes(layer).insert(box)
def pad(self, padding=ap.PADDING): """ add padding to a cell """ for cell in self.cells: layer = cell.layout().layer(ap.DEVREC_LAYER, 0) bbox = cell.bbox() cell.shapes(layer).insert(bbox) box = pya.Box( bbox.left - padding, bbox.bottom - padding, bbox.right + padding, bbox.top + padding, ) cell.shapes(layer).insert(box)
def inside(self, bbox): """Check that something is inside the mask""" mask = pya.Box(0, 0, self.max_width + 1, self.max_height + 1) return mask.contains(bbox)
def draw_boundary(self, layer: int = ap.DEVREC_LAYER) -> None: """Draw a box into the topcell""" layer = self.layer(layer, 0) self.cell(self.name).shapes(layer).insert( pya.Box(0, 0, self.max_width, self.max_height) )
def test_2(self): # Some smoke test v = db.Box() self.assertEqual(str(v), "()") v = db.Box(1, 2, 3, 4) self.assertEqual(str(v), "(1,2;3,4)")
import os import klayout.db as pya path = os.path.dirname(os.path.abspath(__file__)) print(path) layout = pya.Layout() # create layers to use in our layout. LayerInfo takes layer#, datatype, text label as inputs ito = pya.LayerInfo(1, 0, "ITO Opening 1/0") nno = pya.LayerInfo(2, 0, "NNO Pad 2/0") fox = pya.LayerInfo(3, 0, "Field Oxide 3/0") hfoetch = pya.LayerInfo(4, 0, "HfO2 Etch 4/0") # assign layers to layout for l in [ito, nno, fox, hfoetch]: layout.layer(l) top = layout.create_cell("TOP") top.shapes(ito.layer).insert(pya.Box([0, 0], [1000,1000])) layout.write(os.path.join(path, 'test.gds'))