def __init__(self, name, size, border_layers):
        if not (type(border_layers) == list):
            border_layers = [border_layers]
        Cell.__init__(self, name)
        self.size_x, self.size_y = size
        # Create the border of the cell
        for l in border_layers:
            self.border = Box((-self.size_x / 2., -self.size_y / 2.),
                              (self.size_x / 2., self.size_y / 2.),
                              1,
                              layer=l)
            self.add(self.border)  # Add border to the frame

        self.align_markers = None
def make_theory_cell(wafer_orient='111'):
    ''' Makes the theory cell and returns ir as a cell'''

    # Pitch Dependence
    PitchDep = Cell('PitchDependence')
    arrayHeight = 5.
    arrayWidth = arrayHeight * 2.
    arraySpacing = 10.
    spacing = 0.5

    length = [arrayWidth]
    widths = [0.050, 0.100, 0.150, 0.200, 0.250]
    wire_spacings = [0.100, 0.200, 0.400]

    for j, width in enumerate(widths):
        for i, wire_spacing in enumerate(wire_spacings):
            PitchDep.add(makeSlitArray2(wire_spacing + width, spacing, width,
                                        length, 0, arrayHeight, arrayWidth,
                                        arraySpacing, l_smBeam),
                         origin=(i * 30, j * 20))

    TopCell = Cell('GrowthTheoryTopCell')
    TopCell.add(PitchDep, origin=(0., 0.))
    # # TODO: Add the branched growth shapes

    return TopCell
    def add_chip_labels(self):
        wafer_lbl = PATTERN + "\n" + WAFER_ID
        text = Label(wafer_lbl, 40., layer=l_lgBeam)
        text.translate(tuple(np.array(-text.bounding_box.mean(0))))  # Center justify label
        chip_lbl_cell = Cell('chip_label')
        chip_lbl_cell.add(text)

        center_x, center_y = (5000, 5000)
        for block in self.blocks:
            block.add(chip_lbl_cell, origin=(center_x, center_y - 300))
            block.add(chip_lbl_cell, origin=(center_x, center_y - 4500))
            block.add(chip_lbl_cell, origin=(center_x + 4500, center_y), rotation= 90)
            block.add(chip_lbl_cell, origin=(center_x, center_y + 4500), rotation= 180)
            block.add(chip_lbl_cell, origin=(center_x - 4500, center_y), rotation= 270)
    def add_subdicing_marks(self, length, width, layers):
        if type(layers) is not list:
            layers = [layers]

        for l in layers:
            mark_cell = Cell("SubdicingMark")
            line = Path([[0, 0], [0, length]], width=width, layer=l)
            mark_cell.add(line)

            for block in self.blocks:
                block.add(mark_cell, origin=(self.block_size[0] / 2., 0), rotation=0)
                block.add(mark_cell, origin=(0, self.block_size[1] / 2.), rotation=-90)
                block.add(mark_cell, origin=(self.block_size[0], self.block_size[1] / 2.), rotation=90)
                block.add(mark_cell, origin=(self.block_size[0] / 2., self.block_size[1]), rotation=180)
 def make_many_shapes(self, array_size, shape_areas, pitch, shapes, skew, layer):
     offset_x = array_size * 1.25
     offset_y = array_size * 1.25
     cur_y = 0
     many_shape_cell = Cell('ManyShapes')
     for area in shape_areas:
         cur_x = 0
         for shape in shapes:
             write_top_labels = cur_y == 0
             write_side_labels = cur_x == 0
             s_array = self.make_shape_array(array_size, area, pitch, shape, layer, skew, toplabels=write_top_labels,
                                             sidelabels=write_side_labels)
             many_shape_cell.add(s_array, origin=(cur_x - array_size / 2., cur_y - array_size / 2.))
             cur_x += offset_x
         cur_y -= offset_y
     self.add(many_shape_cell, origin=(-offset_x * (len(shapes) - 1) / 2., offset_y * (len(skews) - 1) / 2.))
    def make_branch_device_array(self, spacing, _widths, array_height, array_width,
                                 array_spacing, len_inner, len_outer, n_membranes, layers):
        if not (type(layers) == list):
            layers = [layers]
        if not (type(_widths) == list):
            _widths = [_widths]
        for l in layers:
            i = -1
            j = 0
            manydevices = Cell("ManyDevices")
            for width in _widths:
                device = self.make_branch_device(width, spacing, len_inner, len_outer, n_membranes, l)
                [[x_min, y_min], [x_max, y_max]] = device.bounding_box
                x_size = abs(x_max - x_min)
                y_size = abs(y_max - y_min)

                i += 1
                if i % 3 == 0:
                    j += 1  # Move to array to next line
                    i = 0  # Restart at left

                nx = int(array_width / (x_size + spacing))
                ny = int(array_height / (y_size + spacing))

                devices = CellArray(device, nx, ny, (x_size + spacing, y_size + spacing))
                devices.translate((-(nx - 1) * (x_size + spacing) / 2., -(ny - 1) * (y_size + spacing) / 2.))
                device_array = Cell("DeviceArray")
                device_array.add(devices)
                # Make the labels for each array of devices
                text = Label('w/s/l\n%i/%.1f/%i' % (width * 1000, spacing, len_outer), 5)
                lbl_vertical_offset = 1.40
                if j % 2 == 0:
                    text.translate(
                        tuple(np.array(-text.bounding_box.mean(0)) + np.array((
                            0, -array_height / lbl_vertical_offset))))  # Center justify label
                else:
                    text.translate(
                        tuple(np.array(-text.bounding_box.mean(0)) + np.array((
                            0, array_height / lbl_vertical_offset))))  # Center justify label
                # TODO: Finish this below
                device_array.add(text)
                manydevices.add(device_array, origin=(
                    (array_width + array_spacing) * i, (array_height + 2. * array_spacing) * j - array_spacing / 2.))

            self.add(manydevices,
                     origin=(-i * (array_width + array_spacing) / 2, -(j + 1.5) * (array_height + array_spacing) / 2))
Example #7
0
    def add_theory_cells(self):

        theory_cells = Cell('TheoryCells')
        theory_cells.add(make_theory_cell(wafer_orient='100'), origin=(-400, 0))
        theory_cells.add(make_theory_cell_3br(), origin=(0, 0))
        theory_cells.add(make_theory_cell_4br(), origin=(400, 0))

        center_x, center_y = (self.block_size[0] / 2., self.block_size[1] / 2.)
        for block in self.blocks:
            block.add(theory_cells, origin=(center_x, center_y - 4000))
def make_many_shapes(array_size, shape_areas, pitch, shapes, layer):
    offset_x = array_size * 1.25
    offset_y = array_size * 1.25
    cur_y = 0
    many_shape_cell = Cell('ManyShapes')
    for area in shape_areas:
        cur_x = 0
        for shape in shapes:
            write_labels = cur_y == 0
            s_array = make_shape_array(array_size,
                                       area,
                                       pitch,
                                       shape,
                                       layer,
                                       labels=write_labels)
            many_shape_cell.add(s_array, origin=(cur_x, cur_y))
            cur_x += offset_x
        cur_y -= offset_y
    return many_shape_cell
    def add_theory_cell(self):

        theory_cells = Cell('TheoryCells')
        theory_cells.add(make_theory_cell(), origin=(-400, 0))
        theory_cells.add(make_theory_cell_3br(), origin=(0, 0))
        theory_cells.add(make_theory_cell_4br(), origin=(400, 0))

        # Add it in all the cells
        for (i, pt) in enumerate(self.block_pts):
            origin = (pt + np.array([0.5, 0.5])) * self.block_size
            origin += np.array([0, -2000])
            self.add(theory_cells, origin=origin)
    def add_theory_cell(self):

        theory_cell = make_theory_cell()
        theory_cells = Cell('TheoryCells')
        for x, y in self.upCenters:
            theory_cells.add(theory_cell, origin=(x, y - 1500))
        for x, y in self.downCenters:
            if self.symmetric_chips:
                theory_cells.add(theory_cell,
                                 origin=(x, y + 1500),
                                 rotation=180)
            theory_cells.add(theory_cell, origin=(x, y + 1500))
        self.add(theory_cells)
    def make_tapered_cross(self, nw1, nw2, tw1, tw2, l1, l2, tl1, tl2, layer):
        cross_cell = Cell(
            'TaperedCross_NW{:.0f}_TW{:.0f}_L{:.0f}_TL{:.0f}xNW{:.0f}_TW{:.0f}_L{:.0f}_TL{:.0f}'
            .format(nw1 * 1000, tw1 * 1000, l1, tl1, nw2 * 1000, tw2 * 1000,
                    l2, tl2))
        l1 += tw2
        l2 += tw1
        tl1 += tw2
        tl2 += tl1

        cross_pts = [(tw2 / 2., tw1 / 2.), (tl1, nw1 / 2.),
                     (l1 / 2., nw1 / 2.), (l1 / 2., -nw1 / 2.),
                     (tl1, -nw1 / 2.), (tw2 / 2., -tw1 / 2.),
                     (nw2 / 2., -tl2 / 2.), (nw2 / 2., -l2 / 2.),
                     (-nw2 / 2., -l2 / 2.), (-nw2 / 2., -tl2 / 2.),
                     (-tw2 / 2., -tw1 / 2.)]
        cross_pts.extend(tuple(map(tuple, (-np.array(cross_pts)).tolist())))
        membrane = Boundary(cross_pts, layer=layer)  # Create gdsCAD shape
        cross_cell.add(membrane)
        return cross_cell
    def add_tem_nanowires(self):
        size = 500
        y_offset = 1000
        shapes_big = make_shape_array(size,
                                      0.02,
                                      0.5,
                                      'Tris_right',
                                      l_smBeam,
                                      labels=False)
        shapes_small = make_shape_array(size,
                                        0.005,
                                        0.5,
                                        'Tris_right',
                                        l_smBeam,
                                        labels=False)
        tem_shapes = Cell('TEMShapes')
        # tem_shapes.add(shapes_big, origin=(2200 - size / 2., y_offset - size / 2.))
        tem_shapes.add(shapes_small, origin=(-size / 2., -size / 2.))

        self.block_up.add(tem_shapes, origin=(-2200, y_offset))
        self.block_down.add(tem_shapes, origin=(2200, -y_offset))
Example #13
0
 def makeAlignMarkers(self, t, w, position, layers, cross=False):
     if not (type(layers) == list): layers = [layers]
     self.aMarkers = Cell("AlignMarkers")
     for l in layers:
         if not (cross):
             am1 = Rectangle((-w / 2., -w / 2.), (w / 2., w / 2.), layer=l)
         elif cross:
             h = w
             crosspts = [(-t / 2., t / 2.), (-t / 2., h / 2.), (t / 2., h / 2.),
                         (t / 2., t / 2.), (w / 2., t / 2.), (w / 2., -t / 2.),
                         (t / 2., -t / 2.), (t / 2., -h / 2.),
                         (-t / 2., -h / 2.), (-t / 2., -t / 2.),
                         (-w / 2., -t / 2.), (-w / 2., t / 2.)]
             am1 = Boundary(crosspts, layer=l)  # Create gdsCAD shape
             # am1 = Polygon(crosspts) #Create shapely polygon for later calculation
         am1 = am1.translate(tuple(position))  # 850,850
         am2 = am1.copy().scale((-1, 1))  # Reflect in x-axis
         am3 = am1.copy().scale((1, -1))  # Reflect in y-axis
         am4 = am1.copy().scale((-1, -1))  # Reflect in both x and y-axis
         self.aMarkers.add([am1, am2, am3, am4])
         self.add(self.aMarkers)
    def make_many_shapes(self, array_size, shape_areas, pitches, shape, skew,
                         layer):
        """

        :param array_size:
        :param shape_areas:
        :param pitches:
        :param shape:
        :param skew:
        :param layer:
        :return:
        """
        if (type(shape) == list):
            shape = shape[0]
        offset_x = array_size * 1.25
        offset_y = array_size * 1.25
        cur_y = 0
        many_shape_cell = Cell('ManyShapes')
        for area in shape_areas:
            cur_x = 0
            for pitch in pitches:
                write_top_labels = cur_y == 0
                write_side_labels = cur_x == 0
                s_array = self.make_shape_array(array_size,
                                                area,
                                                pitch,
                                                shape,
                                                layer,
                                                skew,
                                                toplabels=write_top_labels,
                                                sidelabels=write_side_labels)
                many_shape_cell.add(s_array,
                                    origin=(cur_x - array_size / 2.,
                                            cur_y - array_size / 2.))
                cur_x += offset_x
            cur_y -= offset_y
        self.add(many_shape_cell,
                 origin=(-offset_x * (len(pitches) - 1) / 2.,
                         offset_y * (len(shape_areas) - 1) / 2.))
    def add_theory_cell(self):

        theory_cells = Cell('TheoryCells')
        theory_cells.add(make_theory_cell(), origin=(-200, 0))
        theory_cells.add(make_theory_cell_br(), origin=(200, 0))

        self.block_up.add(theory_cells, origin=(0, 1300))
        self.block_down.add(theory_cells, origin=(0, -1300))
    def make_align_markers(self,
                           t,
                           w,
                           position,
                           layers,
                           cross=False,
                           auto_marks=False):
        if not (type(layers) == list):
            layers = [layers]
        self.align_markers = Cell("AlignMarkers")
        self.align_marker = Cell("AlignMarker")
        for l in layers:
            if not cross:
                am0 = Rectangle((-w / 2., -w / 2.), (w / 2., w / 2.), layer=l)
                self.align_marker.add(am0)
            elif cross:
                crosspts = [(0, 0), (w / 2., 0), (w / 2., t), (t, t),
                            (t, w / 2), (0, w / 2), (0, 0)]
                crosspts.extend(
                    tuple(map(tuple, (-np.array(crosspts)).tolist())))

                #                crosspts = [(-t / 2., t / 2.), (-t / 2., h / 2.), (t / 2., h / 2.),
                #                            (t / 2., t / 2.), (w / 2., t / 2.), (w / 2., -t / 2.),
                #                            (t / 2., -t / 2.), (t / 2., -h / 2.),
                #                            (-t / 2., -h / 2.), (-t / 2., -t / 2.),
                #                            (-w / 2., -t / 2.), (-w / 2., t / 2.)]
                am0 = Boundary(crosspts, layer=l)  # Create gdsCAD shape
                self.align_marker.add(am0)
                # am1 = Polygon(crosspts) #Create shapely polygon for later calculation

            if auto_marks:  # automatic alignment marks for the e-beam tool
                auto_mark_rect = Rectangle((-10., -10.), (10., 10.), layer=l)
                auto_mark = Cell("AutoMark")
                auto_mark.add(auto_mark_rect)
                self.align_marker.add(auto_mark, origin=(100, 100))
                self.align_marker.add(auto_mark, origin=(-100, 100))
                self.align_marker.add(auto_mark, origin=(100, -100))
                self.align_marker.add(auto_mark, origin=(-100, -100))

            self.align_markers.add(self.align_marker,
                                   origin=tuple(np.array(position) * [1, 1]))
            self.align_markers.add(self.align_marker,
                                   origin=tuple(np.array(position) * [-1, 1]))
            self.align_markers.add(self.align_marker,
                                   origin=tuple(np.array(position) * [1, -1]))
            self.align_markers.add(self.align_marker,
                                   origin=tuple(np.array(position) * [-1, -1]))
            self.add(self.align_markers)
Example #17
0
    def add_block_labels(self, layers, quasi_unique_labels=False):
        if type(layers) is not list:
            layers = [layers]

        txtSize = 800

        if quasi_unique_labels:
            unique_label_string = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890'
            possible_labels = [
                "".join(x)
                for x in itertools.product(unique_label_string, repeat=2)
            ]

            blockids_set = set()
            while len(blockids_set) < len(self.blocks):
                blockids_set.add(random_choice(possible_labels))

            blockids = list(blockids_set)
            for i, block in enumerate(self.blocks):
                blocklabel = Cell('LBL_B_' + blockids[i])
                for l in layers:
                    txt = Label(blockids[i], txtSize, layer=l)
                    bbox = txt.bounding_box
                    offset = (0, 0)
                    txt.translate(
                        -np.mean(bbox, 0))  # Center text around origin
                    txt.translate(offset)  # Translate it to bottom of wafer
                    blocklabel.add(txt)
                    block.add(blocklabel,
                              origin=(self.block_size[0] / 2.,
                                      self.block_size[1] / 2.))

        else:
            for (i, pt) in enumerate(self.block_pts):
                origin = (pt + np.array([0.5, 0.5])) * self.block_size
                blk_lbl = self.blockcols[pt[0]] + self.blockrows[pt[1]]
                for l in layers:
                    txt = Label(blk_lbl, txtSize, layer=l_lgBeam)
                    bbox = txt.bounding_box
                    offset = np.array(pt)
                    txt.translate(
                        -np.mean(bbox, 0))  # Center text around origin
                    lbl_cell = Cell("lbl_" + blk_lbl)
                    lbl_cell.add(txt)
                    origin += np.array([0, 2000])  # Translate it up by 2mm
                    self.add(lbl_cell, origin=origin)
 def processCheck_Slits(self, position, arrayWidth, slitWidth, pitch,
                        length, rotation, layers):
     if not (type(layers) == list): layers = [layers]
     Nx = int(arrayWidth / pitch)
     Ny = 1
     for l in layers:
         # Define the slits
         slit = Cell("Slits")
         rect = Rectangle((-slitWidth / 2., -length / 2.),
                          (slitWidth / 2., length / 2.),
                          layer=l)
         slit.add(rect)
         slits = CellArray(slit, Nx, Ny, (pitch, 0))
         slits.translate((-(Nx) * (pitch) / 2., 0.))
         slits.translate(position)
         slitarray = Cell("ProcessCheckingSlits")
         slitarray.add(slits)
     self.add(slitarray)
    def add_theory_cell(self):

        theory_cells = Cell('TheoryCells')
        theory_cells.add(make_theory_cell(), origin=(-200, 0))
        theory_cells.add(make_theory_cell_br(), origin=(200, 0))

        for x, y in self.upCenters:
            self.add(theory_cells, origin=(x, y + 1300))
        for x, y in self.downCenters:
            self.add(theory_cells, origin=(
                x, y - 1300
            ))  # Don't rotate because of directionality of branched membranes
Example #20
0
    def add_theory_cells(self):
        theory_cells = Cell('TheoryCells')
        theory_cells.add(make_theory_cell(wafer_orient='100'), origin=(70, 0))
        # theory_cells.add(make_theory_cell_3br(), origin=(0, 0))
        # theory_cells.add(make_theory_cell_4br(), origin=(400, 0))

        theory_cells.add(make_theory_cell(wafer_orient='100'), origin=(20, -400), rotation=45)
        # theory_cells.add(make_theory_cell_3br(), origin=(-50, -400), rotation=45)
        # theory_cells.add(make_theory_cell_4br(), origin=(370, -400), rotation=45)

        center_x, center_y = (5000, 5000)
        for block in self.blocks:
            block.add(theory_cells, origin=(center_x, center_y - 1700))
Example #21
0
    def add_dashed_dicing_marks(self, layers):
        if type(layers) is not list:
            layers = [layers]
        width = 10. / 2
        dashlength = 2000
        r = self.wafer_r
        rng = np.floor(self.wafer_r / self.block_size).astype(int)
        dmarks = Cell('DIC_MRKS')
        for l in layers:
            for x in np.arange(-rng[0], rng[0] + 1) * self.block_size[0]:
                y = np.sqrt(r**2 - x**2)
                vm = dashed_line([x, y], [x, -y], dashlength, width, layer=l)
                dmarks.add(vm)

            for y in np.arange(-rng[1], rng[1] + 1) * self.block_size[1]:
                x = np.sqrt(r**2 - y**2)
                hm = dashed_line([x, y], [-x, y], dashlength, width, layer=l)
                dmarks.add(hm)
        self.add(dmarks)
    def add_cleave_xsection_nws(self):
        pitches = [0.5, 1., 2., 4.]
        widths = [10., 20., 40., 60., 100., 160., 240.]
        n_membranes = 10
        length = 50
        spacing = 10

        cleave_xsection_cell = Cell("CleaveCrossSection")

        y_offset = 0
        for pitch in pitches:
            for width in widths:
                nm_cell = Cell("P{:.0f}W{:.0f}".format(pitch, width))
                slit = Path([(-length / 2., 0), (length / 2., 0)],
                            width=width / 1000.,
                            layer=l_smBeam)
                nm_cell.add(slit)
                nm_cell_array = Cell("P{:.0f}W{:.0f}_Array".format(
                    pitch, width))
                tmp = CellArray(nm_cell, 1.0, n_membranes, [0, pitch])
                nm_cell_array.add(tmp)
                cleave_xsection_cell.add(nm_cell_array,
                                         origin=(0, y_offset +
                                                 pitch * n_membranes))
                y_offset += pitch * n_membranes + spacing

                text = Label("P{:.1f}W{:.0f}".format(pitch, width),
                             1.0,
                             layer=l_smBeam)
                text.translate(tuple(np.array(
                    -text.bounding_box.mean(0))))  # Center justify label
                txt_cell = Cell("lbl_P{:.1f}W{:.0f}".format(pitch, width))
                txt_cell.add(text)
                cleave_xsection_cell.add(txt_cell,
                                         origin=(length * 0.75,
                                                 y_offset - 8.0))
                cleave_xsection_cell.add(txt_cell,
                                         origin=(-length * 0.75,
                                                 y_offset - 8.0))

            y_offset += spacing * 3

        center_x, center_y = (5000, 5000)
        for block in self.blocks:
            block.add(cleave_xsection_cell,
                      origin=(center_x + 1150, center_y - 463))
            block.add(cleave_xsection_cell,
                      origin=(center_x - 350, center_y + 350),
                      rotation=45.)
            block.add(cleave_xsection_cell,
                      origin=(center_x + 463, center_y - 1150),
                      rotation=90.)
Example #23
0
    def make_slit_array(self, _pitches, spacing, _widths, _lengths, rot_angle,
                        array_height, array_width, array_spacing, layers):
        if not (type(layers) == list):
            layers = [layers]
        if not (type(_pitches) == list):
            _pitches = [_pitches]
        if not (type(_lengths) == list):
            _lengths = [_lengths]
        if not (type(_widths) == list):
            _widths = [_widths]
        manyslits = i = j = None
        for l in layers:
            i = -1
            j = -1
            manyslits = Cell("SlitArray")
            pitch = _pitches[0]
            for length in _lengths:
                j += 1
                i = -1

                for width in _widths:
                    # for pitch in pitches:
                    i += 1
                    if i % 3 == 0:
                        j += 1  # Move to array to next line
                        i = 0  # Restart at left

                    nx = int(array_width / (length + spacing))
                    ny = int(array_height / pitch)
                    # Define the slits
                    slit = Cell("Slits")
                    rect = Rectangle((-length / 2., -width / 2.),
                                     (length / 2., width / 2.),
                                     layer=l)
                    slit.add(rect)
                    slits = CellArray(slit, nx, ny, (length + spacing, pitch))
                    slits.translate((-(nx - 1) * (length + spacing) / 2.,
                                     -(ny - 1) * pitch / 2.))
                    slit_array = Cell("SlitArray")
                    slit_array.add(slits)
                    text = Label('w/p/l\n%i/%i/%i' %
                                 (width * 1000, pitch, length),
                                 5,
                                 layer=l)
                    lbl_vertical_offset = 1.35
                    if j % 2 == 0:
                        text.translate(
                            tuple(
                                np.array(-text.bounding_box.mean(0)) +
                                np.array((0,
                                          -array_height / lbl_vertical_offset))
                            ))  # Center justify label
                    else:
                        text.translate(
                            tuple(
                                np.array(-text.bounding_box.mean(0)) +
                                np.array((0, array_height / lbl_vertical_offset
                                          ))))  # Center justify label
                    slit_array.add(text)
                    manyslits.add(
                        slit_array,
                        origin=((array_width + array_spacing) * i,
                                (array_height + 2. * array_spacing) * j -
                                array_spacing / 2.))

        # This is an ugly hack to center rotated slits, should fix this properly...
        hacky_offset_x = 200 if rot_angle == 45 else 0  # TODO: fix this ugly thing
        hacky_offset_y = -25 if rot_angle == 45 else 0

        self.add(manyslits,
                 origin=(-i * (array_width + array_spacing) / 2 +
                         hacky_offset_x, -(j + 1.5) *
                         (array_height + array_spacing) / 2 + hacky_offset_y),
                 rotation=rot_angle)
Example #24
0
    def make_align_markers(self,
                           t,
                           w,
                           position,
                           layers,
                           joy_markers=False,
                           camps_markers=False):
        if not (type(layers) == list):
            layers = [layers]
        top_mk_cell = Cell('AlignmentMark')
        for l in layers:
            if not joy_markers:
                am0 = Rectangle((-w / 2., -w / 2.), (w / 2., w / 2.), layer=l)
                rect_mk_cell = Cell("RectMarker")
                rect_mk_cell.add(am0)
                top_mk_cell.add(rect_mk_cell)
            elif joy_markers:
                crosspts = [(0, 0), (w / 2., 0), (w / 2., t), (t, t),
                            (t, w / 2), (0, w / 2), (0, 0)]
                crosspts.extend(
                    tuple(map(tuple, (-np.array(crosspts)).tolist())))
                am0 = Boundary(crosspts, layer=l)  # Create gdsCAD shape
                joy_mk_cell = Cell("JOYMarker")
                joy_mk_cell.add(am0)
                top_mk_cell.add(joy_mk_cell)

            if camps_markers:
                emw = 20.  # 20 um e-beam marker width
                camps_mk = Rectangle((-emw / 2., -emw / 2.),
                                     (emw / 2., emw / 2.),
                                     layer=l)
                camps_mk_cell = Cell("CAMPSMarker")
                camps_mk_cell.add(camps_mk)
                top_mk_cell.add(camps_mk_cell, origin=[100., 100.])
                top_mk_cell.add(camps_mk_cell, origin=[100., -100.])
                top_mk_cell.add(camps_mk_cell, origin=[-100., 100.])
                top_mk_cell.add(camps_mk_cell, origin=[-100., -100.])

            self.align_markers = Cell("AlignMarkers")
            self.align_markers.add(top_mk_cell,
                                   origin=np.array(position) *
                                   np.array([1, -1]))
            self.align_markers.add(top_mk_cell,
                                   origin=np.array(position) *
                                   np.array([-1, -1]))
            self.align_markers.add(top_mk_cell,
                                   origin=np.array(position) *
                                   np.array([1, 1]))
            self.align_markers.add(top_mk_cell,
                                   origin=np.array(position) *
                                   np.array([-1, 1]))
            self.add(self.align_markers)
Example #25
0
class Frame(Cell):
    """
    Make a frame for writing to with ebeam lithography
    Params:
    -name of the frame, just like when naming a cell
    -size: the size of the frame as an array [xsize,ysize]
    """
    def __init__(self, name, size, border_layers):
        if not (type(border_layers) == list):
            border_layers = [border_layers]
        Cell.__init__(self, name)
        self.size_x, self.size_y = size
        # Create the border of the cell
        for l in border_layers:
            self.border = Box((-self.size_x / 2., -self.size_y / 2.),
                              (self.size_x / 2., self.size_y / 2.),
                              1,
                              layer=l)
            self.add(self.border)  # Add border to the frame

        self.align_markers = None

    def make_align_markers(self,
                           t,
                           w,
                           position,
                           layers,
                           joy_markers=False,
                           camps_markers=False):
        if not (type(layers) == list):
            layers = [layers]
        top_mk_cell = Cell('AlignmentMark')
        for l in layers:
            if not joy_markers:
                am0 = Rectangle((-w / 2., -w / 2.), (w / 2., w / 2.), layer=l)
                rect_mk_cell = Cell("RectMarker")
                rect_mk_cell.add(am0)
                top_mk_cell.add(rect_mk_cell)
            elif joy_markers:
                crosspts = [(0, 0), (w / 2., 0), (w / 2., t), (t, t),
                            (t, w / 2), (0, w / 2), (0, 0)]
                crosspts.extend(
                    tuple(map(tuple, (-np.array(crosspts)).tolist())))
                am0 = Boundary(crosspts, layer=l)  # Create gdsCAD shape
                joy_mk_cell = Cell("JOYMarker")
                joy_mk_cell.add(am0)
                top_mk_cell.add(joy_mk_cell)

            if camps_markers:
                emw = 20.  # 20 um e-beam marker width
                camps_mk = Rectangle((-emw / 2., -emw / 2.),
                                     (emw / 2., emw / 2.),
                                     layer=l)
                camps_mk_cell = Cell("CAMPSMarker")
                camps_mk_cell.add(camps_mk)
                top_mk_cell.add(camps_mk_cell, origin=[100., 100.])
                top_mk_cell.add(camps_mk_cell, origin=[100., -100.])
                top_mk_cell.add(camps_mk_cell, origin=[-100., 100.])
                top_mk_cell.add(camps_mk_cell, origin=[-100., -100.])

            self.align_markers = Cell("AlignMarkers")
            self.align_markers.add(top_mk_cell,
                                   origin=np.array(position) *
                                   np.array([1, -1]))
            self.align_markers.add(top_mk_cell,
                                   origin=np.array(position) *
                                   np.array([-1, -1]))
            self.align_markers.add(top_mk_cell,
                                   origin=np.array(position) *
                                   np.array([1, 1]))
            self.align_markers.add(top_mk_cell,
                                   origin=np.array(position) *
                                   np.array([-1, 1]))
            self.add(self.align_markers)

    def make_slit_array(self, _pitches, spacing, _widths, _lengths, rot_angle,
                        array_height, array_width, array_spacing, layers):
        if not (type(layers) == list):
            layers = [layers]
        if not (type(_pitches) == list):
            _pitches = [_pitches]
        if not (type(_lengths) == list):
            _lengths = [_lengths]
        if not (type(_widths) == list):
            _widths = [_widths]
        manyslits = i = j = None
        for l in layers:
            i = -1
            j = -1
            manyslits = Cell("SlitArray")
            pitch = _pitches[0]
            for length in _lengths:
                j += 1
                i = -1

                for width in _widths:
                    # for pitch in pitches:
                    i += 1
                    if i % 3 == 0:
                        j += 1  # Move to array to next line
                        i = 0  # Restart at left

                    nx = int(array_width / (length + spacing))
                    ny = int(array_height / pitch)
                    # Define the slits
                    slit = Cell("Slits")
                    rect = Rectangle((-length / 2., -width / 2.),
                                     (length / 2., width / 2.),
                                     layer=l)
                    slit.add(rect)
                    slits = CellArray(slit, nx, ny, (length + spacing, pitch))
                    slits.translate((-(nx - 1) * (length + spacing) / 2.,
                                     -(ny - 1) * pitch / 2.))
                    slit_array = Cell("SlitArray")
                    slit_array.add(slits)
                    text = Label('w/p/l\n%i/%i/%i' %
                                 (width * 1000, pitch, length),
                                 5,
                                 layer=l)
                    lbl_vertical_offset = 1.35
                    if j % 2 == 0:
                        text.translate(
                            tuple(
                                np.array(-text.bounding_box.mean(0)) +
                                np.array((0,
                                          -array_height / lbl_vertical_offset))
                            ))  # Center justify label
                    else:
                        text.translate(
                            tuple(
                                np.array(-text.bounding_box.mean(0)) +
                                np.array((0, array_height / lbl_vertical_offset
                                          ))))  # Center justify label
                    slit_array.add(text)
                    manyslits.add(
                        slit_array,
                        origin=((array_width + array_spacing) * i,
                                (array_height + 2. * array_spacing) * j -
                                array_spacing / 2.))

        # This is an ugly hack to center rotated slits, should fix this properly...
        hacky_offset_x = 200 if rot_angle == 45 else 0  # TODO: fix this ugly thing
        hacky_offset_y = -25 if rot_angle == 45 else 0

        self.add(manyslits,
                 origin=(-i * (array_width + array_spacing) / 2 +
                         hacky_offset_x, -(j + 1.5) *
                         (array_height + array_spacing) / 2 + hacky_offset_y),
                 rotation=rot_angle)
Example #26
0
    def add_tem_membranes(self, widths, length, pitch, layer):
        tem_membranes = Cell('TEM_Membranes')
        n = 4
        curr_y = 0
        for width in widths:
            membrane = Path([(-length / 2., 0), (length / 2., 0)],
                            width=width,
                            layer=layer)
            membrane_cell = Cell('Membrane_w{:.0f}'.format(width * 1000))
            membrane_cell.add(membrane)
            membrane_array = CellArray(membrane_cell, 1, n, (0, pitch))
            membrane_array_cell = Cell('MembraneArray_w{:.0f}'.format(width *
                                                                      1000))
            membrane_array_cell.add(membrane_array)
            tem_membranes.add(membrane_array_cell, origin=(0, curr_y))
            curr_y += n * pitch

        n2 = 3
        tem_membranes2 = Cell('Many_TEM_Membranes')
        tem_membranes2.add(
            CellArray(tem_membranes, 1, n2, (0, n * len(widths) * pitch)))

        center_x, center_y = (5000, 5000)
        for block in self.blocks:
            block.add(tem_membranes2, origin=(center_x, center_y + 2000))
            block.add(tem_membranes2,
                      origin=(center_x, center_y + 1500),
                      rotation=45)
Example #27
0
    def add_prealignment_markers(self, layers, mrkr_size=7):
        if mrkr_size % 2 == 0:  # Number is even, but we need odd numbers
            mrkr_size += 1
        if type(layers) is not list:
            layers = [layers]

        for l in layers:
            rect_size = 10.  # 10 um large PAMM rectangles
            marker_rect = Rectangle([-rect_size / 2., -rect_size / 2.],
                                    [rect_size / 2., rect_size / 2.],
                                    layer=l)
            marker = Cell('10umMarker')
            marker.add(marker_rect)

            # Make one arm of the PAMM array
            marker_arm = Cell('PAMM_Arm')
            # Define the positions of the markers, they increase in spacing by 1 um each time:
            mrkr_positions = [
                75 * n + (n - 1) * n // 2
                for n in range(1, (mrkr_size - 1) // 2 + 1)
            ]
            for pos in mrkr_positions:
                marker_arm.add(marker, origin=[pos, 0])

            # Build the final PAMM Marker
            pamm_cell = Cell('PAMM_Marker')
            pamm_cell.add(marker)  # Center marker
            pamm_cell.add(marker_arm)  # Right arm
            pamm_cell.add(marker_arm, rotation=180)  # Left arm
            pamm_cell.add(marker_arm, rotation=90)  # Top arm
            pamm_cell.add(marker_arm, rotation=-90)  # Bottom arm
            for pos in mrkr_positions:
                pamm_cell.add(marker_arm, origin=[pos, 0],
                              rotation=90)  # Top arms
                pamm_cell.add(marker_arm, origin=[-pos, 0], rotation=90)
                pamm_cell.add(marker_arm, origin=[pos, 0],
                              rotation=-90)  # Bottom arms
                pamm_cell.add(marker_arm, origin=[-pos, 0], rotation=-90)

            # Make the 4 tick marks that mark the center of the array
            h = 30.
            w = 100.
            tick_mrk = Rectangle([-w / 2., -h / 2.], [w / 2, h / 2.], layer=l)
            tick_mrk_cell = Cell("TickMark")
            tick_mrk_cell.add(tick_mrk)
            pos = mrkr_positions[-1] + 75 + w / 2.
            pamm_cell.add(tick_mrk_cell, origin=[pos, 0])
            pamm_cell.add(tick_mrk_cell, origin=[-pos, 0])
            pamm_cell.add(tick_mrk_cell, origin=[0, pos], rotation=90)
            pamm_cell.add(tick_mrk_cell, origin=[0, -pos], rotation=90)

        center_x, center_y = (5000, 5000)
        for block in self.blocks:
            block.add(pamm_cell, origin=(center_x + 2000, center_y))
            block.add(pamm_cell, origin=(center_x - 2000, center_y))
Example #28
0
centerLeftAlignField.make_align_markers(2.,
                                        20., (180., 180.),
                                        l_lgBeam,
                                        joy_markers=True)
centerLeftAlignField.add(quantum_playground)

centerRightAlignField = Frame("CenterRightAlignField",
                              (smFrameSize, smFrameSize), [])
centerRightAlignField.make_align_markers(2.,
                                         20., (180., 180.),
                                         l_lgBeam,
                                         joy_markers=True)
centerRightAlignField.add(quantum_playground, rotation=45)

# Add everything together to a top cell
topCell = Cell("TopCell")
topCell.add(lgField)
smFrameSpacing = 400  # Spacing between the three small frames
dx = smFrameSpacing + smFrameSize
dy = smFrameSpacing + smFrameSize
topCell.add(smField1, origin=(-dx / 2., dy / 2.))
topCell.add(smField2, origin=(dx / 2., dy / 2.))
topCell.add(smField3, origin=(-dx / 2., -dy / 2.))
topCell.add(smField4, origin=(dx / 2., -dy / 2.))
topCell.add(centerLeftAlignField, origin=(-dx / 2, 0.))
topCell.add(centerRightAlignField, origin=(dx / 2, 0.))
topCell.add(centerAlignField, origin=(0., 0.))
topCell.spacing = np.array([4000., 4000.])

# %%Create the layout and output GDS file
layout = Layout('LIBRARY')
    def add_block_labels(self,
                         layers,
                         unique_ids=False,
                         save_ids=True,
                         load_ids=True):
        if type(layers) is not list:
            layers = [layers]

        txtSize = 1000
        blockids = []

        if not unique_ids:
            for (i, pt) in enumerate(self.block_pts):
                blockids.append(self.blockcols[pt[0]] + self.blockrows[pt[1]])
        else:
            existing_ids = {}
            existing_id_set = set()
            # Load the previously-used IDs from a JSON file
            if load_ids:
                master_db = '../../../ChipIDs_DB.json'
                if os.path.isfile(master_db):
                    with open(master_db, 'r') as f:
                        try:
                            existing_ids = json.load(f)
                            existing_id_set = set([
                                item for sublist in list(existing_ids.values())
                                for item in sublist
                            ])

                            # Check if wafer is in the loaded database
                            if load_ids and WAFER_ID in existing_ids:
                                blockids = existing_ids[WAFER_ID]

                        # If there is a reading error then proceed with a warning
                        except json.decoder.JSONDecodeError:
                            print(
                                "Json Error: Couldn't load chip IDs from database!"
                            )
                            existing_id_set = set()

            # If the IDs haven't already been set by loading them from the database
            if not blockids:
                # Generate some new IDs, but only use the ones that haven't previously been used
                unique_label_string = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890'
                possible_label_set = set([
                    "".join(x)
                    for x in itertools.product(unique_label_string, repeat=2)
                ])
                possible_label_set = possible_label_set - existing_id_set  # Remove chip lbls from the set of possible lbls

                blockids_set = set()
                while len(blockids_set) < len(self.blocks):
                    blockids_set.add(random_choice(list(possible_label_set)))

                blockids = list(blockids_set)

        # Save the labels to a file
        if save_ids:
            existing_ids.update({WAFER_ID: blockids})
            json_string = json.dumps(existing_ids)
            json_string = json_string.replace(
                "], ", "],\n")  # Make the file a bit easier to read in notepad
            with open(master_db, 'w') as f:
                f.write(json_string)

        # Write the labels to the cells
        for i, block in enumerate(self.blocks):
            blocklabel = Cell('LBL_B_' + blockids[i])
            for l in layers:
                txt = Label(blockids[i], txtSize, layer=l)
                bbox = txt.bounding_box
                offset = (0, 0)
                txt.translate(-np.mean(bbox, 0))  # Center text around origin
                txt.translate(offset)  # Translate it to bottom of wafer
                blocklabel.add(txt)
                block.add(blocklabel,
                          origin=(self.block_size[0] / 2.,
                                  self.block_size[1] / 2. - 400))
Example #30
0
    def make_slit_array(self, _pitches, spacing, _widths, _lengths, rot_angle,
                        array_height, array_width, array_spacing, layers):
        if not (type(layers) == list):
            layers = [layers]
        if not (type(_pitches) == list):
            _pitches = [_pitches]
        if not (type(_lengths) == list):
            _lengths = [_lengths]
        if not (type(_widths) == list):
            _widths = [_widths]
        manyslits = i = j = None
        for l in layers:
            i = -1
            j = -1
            manyslits = Cell("SlitArray")
            pitch = _pitches[0]
            for length in _lengths:
                j += 1
                i = -1

                for width in _widths:
                    # for pitch in pitches:
                    i += 1
                    if i % 3 == 0:
                        j += 1  # Move to array to next line
                        i = 0  # Restart at left

                    pitch_v = pitch / np.cos(np.deg2rad(rot_angle))
                    #                    widthV = width / np.cos(np.deg2rad(rotAngle))
                    nx = int(array_width / (length + spacing))
                    ny = int(array_height / pitch_v)
                    # Define the slits
                    slit = Cell("Slits")
                    rect = Rectangle((-length / 2., -width / 2.), (length / 2., width / 2.), layer=l)
                    rect = rect.copy().rotate(rot_angle)
                    slit.add(rect)
                    slits = CellArray(slit, nx, ny, (length + spacing, pitch_v))
                    slits.translate((-(nx - 1) * (length + spacing) / 2., -(ny - 1) * pitch_v / 2.))
                    slit_array = Cell("SlitArray")
                    slit_array.add(slits)
                    text = Label('w/p/l\n%i/%i/%i' % (width * 1000, pitch, length), 5, layer=l)
                    lbl_vertical_offset = 1.35
                    if j % 2 == 0:
                        text.translate(
                            tuple(np.array(-text.bounding_box.mean(0)) + np.array((
                                0, -array_height / lbl_vertical_offset))))  # Center justify label
                    else:
                        text.translate(
                            tuple(np.array(-text.bounding_box.mean(0)) + np.array((
                                0, array_height / lbl_vertical_offset))))  # Center justify label
                    slit_array.add(text)
                    manyslits.add(slit_array,
                                  origin=((array_width + array_spacing) * i, (
                                          array_height + 2. * array_spacing) * j - array_spacing / 2.))

        self.add(manyslits,
                 origin=(-i * (array_width + array_spacing) / 2, -(j + 1.5) * (
                         array_height + array_spacing) / 2))