Пример #1
0
def compass(size=200, layer=1):
    """Show compass image to identify the sample direction.

    Args:
        size (double): size (wxh) of the bounding box.
        layer (int | str | tuple): layer (or list of layers) to draw in.

    Returns:
        cell containing the compass.
    """
    s = size/182
    quart = [(0,0), (s,0), (s,s), (16*s,16*s), (s/2,70*s), (-s/2,70*s),
            (-16*s,16*s), (-15*s,15*s), (-s,65*s), (0,65*s)]
    p = 75 * s
    h = 20 * s

    with nd.Cell("compass_"+nd.md5(layer)) as C:
        for lay in nd.make_iter(layer):
            nd.Polygon(layer=lay, points=quart).put(0,0,0)
            nd.Polygon(layer=lay, points=quart).put(0,0,90)
            nd.Polygon(layer=lay, points=quart).put(0,0,180)
            nd.Polygon(layer=lay, points=quart).put(0,0,270)
            nd.text('E', layer=lay, height=h, align='lc').put(p, 0)
            nd.text('N', layer=lay, height=h, align='cb').put(0, 71*s)
            nd.text('W', layer=lay, height=h, align='rc').put(-p, 0)
            nd.text('S', layer=lay, height=h, align='ct').put(0, -p)
    return C
Пример #2
0
def soa(length=100):
    """Parametrized SOA whitebox generation."""
    angle = 70.0
    width_active = 30.0
    width = 2.0
    name = 'wb_shallow.soa_{}'.format(length)

    with nd.Cell(name=name, instantiate=False) as C:
        bb = bbbb.soa(length=length).put(0, 0, 0)
        bb.raise_pins(namesin=['a0'])

        #active
        paral = geom.parallelogram2(
            length=length,
            height=width_active,
            angle=angle,
            position=2,
            shift=(0 + 0.5 * width_active / tan(radians(angle)), 0))
        active = nd.Polygon(layer=50, points=paral).put(0, 0, 0)

        #pad
        rect = geom.rectangle(length=length,
                              height=200,
                              position=2,
                              shift=(0, 30))
        metal = nd.Polygon(layer=10, points=rect).put(0, 0, 0)

        #waveguide
        nd.strt(width=3, length=length, xs='wb_soa').put(0, 0, 0)

    return C
Пример #3
0
def xsection_transition(length, width, layer1, layer2):
    with nd.Cell('icon', instantiate=False) as icon:
        rect = geom.box(0.25 * length, 0.50 * width)
        nd.Polygon(points=rect, layer=layer1).put(0.25 * length)
        nd.Polygon(points=rect, layer=layer2).put(0.50 * length)
        nd.Pin('cc').put(0.5 * length)
    return icon
Пример #4
0
    def getcell(self):
        with nd.Cell(name=self.name) as dha_cell:
            inpin = nd.Pin(name='a0').put(self.start[0], self.start[1],
                                          self.start[2])
            nd.Pin(name='b0').put(self.end[0], self.end[1], self.end[2])
            a, b = self.outline()

            if self.return_path == True:
                nd.Polygon(nd.util.polyline2polygon(xy=self.points,
                                                    width=self.ww),
                           layer=self.layer).put()
                nd.Polyline(width=self.owidth, points=a,
                            layer=self.olayer).put(inpin.rotate(180))
                nd.Polyline(width=self.owidth, points=b,
                            layer=self.olayer).put(inpin.rotate(180))
            else:
                nd.Polygon(nd.util.polyline2polygon(xy=self.points,
                                                    width=self.ww),
                           layer=self.layer).put()
                nd.Polygon(nd.util.polyline2polygon(xy=a, width=self.owidth),
                           layer=self.olayer).put(inpin.rotate(180))
                nd.Polygon(nd.util.polyline2polygon(xy=b, width=self.owidth),
                           layer=self.olayer).put(inpin.rotate(180))

        return dha_cell
Пример #5
0
    def icon_gsg(pitch=100, height=None):
        """Create an icon with a gsg diode symbol.

        The icon scales with the pitch and the height.

        Args:
            pitch (float): pitch beteween ground and signal
            height (float): height of the icon

        Returns:
            Cell: diode gsg icon
        """
        if height is None:
            height = 2 * pitch

        ratio = 0.3
        w_line = 0.1 * ratio * height
        radius = 0.15 * ratio * height
        height = height - 2 * radius - 2 * w_line

        with nd.Cell('icon_gsg', instantiate=False) as icon:
            # define shapes
            outline = [(-0.5 * ratio * height, 0.5 * ratio * height),
                       (0.5 * ratio * height, 0.5 * ratio * height),
                       (0, -0.5 * ratio * height)]
            diode_triangle = nd.Polygon(points=outline, layer=layer)

            outline = geom.rectangle(ratio * height, w_line, position=5)
            diode_base = nd.Polygon(points=outline, layer=layer)

            outline = geom.ring(radius=radius, width=w_line, N=20)
            ring = nd.Polygon(points=outline, layer=layer)

            outline = geom.rectangle(w_line, height, position=5)
            pole = nd.Polygon(points=outline, layer=layer)

            outline = geom.rectangle(2 * pitch, w_line, position=5)
            gnd = nd.Polygon(points=outline, layer=layer)

            # put shapes
            gnd.put(0, -0.5 * (height - w_line))
            diode_triangle.put(0)
            diode_base.put(0, -0.5 * ratio * (height - w_line))
            pole.put(0)
            pole.put(pitch - 0.5 * w_line)
            pole.put(-pitch + 0.5 * w_line)
            ringpos = 0.5 * (height + radius + w_line)
            ring.put(0, ringpos)
            ring.put(pitch - 0.5 * w_line, ringpos)
            ring.put(-pitch + 0.5 * w_line, ringpos)

            # add pins
            nd.Pin('cc').put(0)
            nd.Pin('top').put(0, ringpos + radius + w_line, -90)
        return icon
Пример #6
0
def marker2(layera=1, layerb=None, layerc=None):

    """TU/e-Smart alignment marker 2.

    This is the second (marker2) of two matching markers.

    Args:
        layera (int | str | tuple): layer (or list of layers) in which
            marker pattern is written. Default 1.
        layerb (int | str | tuple): layer (or list of layers) in which the
            background is defined. Default None.
        layerc (int | str | tuple): layer (or list of layers) in which an
            extra box around the marker is drawn for visibility in dark
            field masks. Default None.

    Returns:
        function: function generating a cell with this specific marker.

    Example:
        Place marker centered at (0,0) in layer 5 with darkfield box::

            import nazca as nd

            m2 = nd.marker2(layera=5, layerc=5)
            m2.put()

            nd.export_plt()
    """
    with nd.Cell(name='marker2_'+nd.md5((layera,layerb,layerc))) as C:
        poly = (((-55,-75), (-55,-55), (-75,-55), (-75,55),
            (-55,55), (-55,75), (-5,75), (-5,55), (-40,55),
            (-40,40), (-55,40), (-55,30), (-40,30), (-40,15),
            (-30,15), (-30,30), (-15,30), (-15,40), (-30,40),
            (-30,55), (-5,55), (-5,-16), (-39,-16), (-39,-31),
            (-54,-31), (-54,-39), (-39,-39), (-39,-54), (-31,-54),
            (-31,-39), (-16,-39), (-16,-31), (-31,-31), (-31,-16),
            (-5,-16), (-5,-75),), ((30,15), (30,30), (15,30),
            (15,40), (30,40), (30,55), (40,55), (40,40), (55,40),
            (55,30), (40,30), (40,15),), ((31,-54), (31,-39),
            (16,-39), (16,-31), (31,-31), (31,-16), (39,-16),
            (39,-31), (54,-31), (54,-39), (39,-39), (39,-54),),
            ((55,-75), (55,-55), (75,-55), (75,-75),), ((55,55),
            (55,75), (75,75), (75,55),))
        nd.Pin(name='a0', xs=None).put(0,0,180)
        nd.Pin(name='b0', xs=None).put(0,0,0)
        for p in poly:
            for lay in nd.make_iter(layera):
                nd.Polygon(layer=lay, points=p).put()
        for lay in nd.make_iter(layerb):
            nd.Polygon(layer=lay,
                points=geom.rectangle(180, 180, position=5)).put()
        for lay in nd.make_iter(layerc):
            nd.Polygon(layer=lay,
                points=geom.frame(60, 240,240)).put(-90,-90)
    return C
Пример #7
0
def marker1(layera=1, layerb=None):
    """TU/e-Smart alignment marker 1.

    This is the first (marker1) of two matching markers.

    Args:
        layera (int | str | tuple): layer (or list of layers) in which
            marker pattern is written.
        layerb (int | str | tuple): layer (or list of layers) in which the
            background is defined.

    Returns:
        function: marker cell.

    Example:
        Place marker centered at (0,0) in layer 1 with background layer 12::

            import nazca as nd

            m1 = nd.marker1(layera=1, layerb=12)
            m1.put()

            nd.export_plt()
    """
    with nd.Cell(name='marker1_'+nd.md5((layera,layerb))) as C:
        poly = (((-75,55), (-75,75), (75,75), (75,55), (65,55),
            (65,65), (-65,65), (-65,55),), ((-37.5,17.5),
                (-37.5,32.5), (-52.5,32.5), (-52.5,37.5),
                (-37.5,37.5), (-37.5,52.5), (-32.5,52.5),
                (-32.5,37.5), (-17.5,37.5), (-17.5,32.5),
                (-32.5,32.5), (-32.5,17.5),), ((32.5,17.5),
                (32.5,32.5), (17.5,32.5), (17.5,37.5), (32.5,37.5),
                (32.5,52.5), (37.5,52.5), (37.5,37.5), (52.5,37.5),
                (52.5,32.5), (37.5,32.5), (37.5,17.5),),
                ((-38.5,-53.5), (-38.5,-38.5), (-53.5,-38.5),
                (-53.5,-31.5), (-38.5,-31.5), (-38.5,-16.5),
                (-31.5,-16.5), (-31.5,-31.5), (-16.5,-31.5),
                (-16.5,-38.5), (-31.5,-38.5), (-31.5,-53.5),),
                ((31.5,-53.5), (31.5,-38.5), (16.5,-38.5),
                (16.5,-31.5), (31.5,-31.5), (31.5,-16.5),
                (38.5,-16.5), (38.5,-31.5), (53.5,-31.5),
                (53.5,-38.5), (38.5,-38.5), (38.5,-53.5),),
                ((-75,-75), (-75,-55), (-65,-55), (-65,-65),
                (65,-65), (65,-55), (75,-55), (75,-75),))
        nd.Pin(name='a0', xs=None).put(0,0,180)
        nd.Pin(name='b0', xs=None).put(0,0,0)
        for p in poly:
            for lay in nd.make_iter(layera):
                nd.Polygon(layer=lay, points=p).put()
        for lay in nd.make_iter(layerb):
            nd.Polygon(layer=lay,
                points=geom.rectangle(180, 180, position=5)).put()
    return C
Пример #8
0
def nonius(layer=1):
    """Nonius structure"""
    with nd.Cell(name='nonius_'+nd.md5(layer)) as C:
        for lay in nd.make_iter(layer):
            l = [20, 20, 30, 20, 20, 20, 20, 30, 20, 20]
            for i in range(10):
                nd.Polygon(layer=lay, points=
                    nd.geometries.rectangle(l[i], 5.9-0.2*i, position=2)).put(
                        0, -45.05+10*i)
            l = [30, 20, 20, 20, 20, 30, 20, 20, 20, 20, 30]
            for i in range(11):
                nd.Polygon(layer=lay, points=
                    nd.geometries.rectangle(l[i], 6-0.2*i, position=8)).put(
                        0, -50+10*i)
    return C
Пример #9
0
 def icon_pad(length, width, bufx=bufx, bufy=bufy):
     length, width, bufx, bufy = calc_buf(length, width, bufx, bufy)
     with nd.Cell('icon', instantiate=False) as icon:
         pad = geom.rounded_rect(length=length, height=width, position=5)
         nd.Polygon(layer=layer, points=pad).put(0)
         nd.Pin('cc').put(0)
     return icon
Пример #10
0
def icon_strt(length, width, layer, bufx=None, bufy=None):
    length, width, bufx, bufy = calc_buf(length, width, bufx, bufy)
    with nd.Cell('icon', instantiate=False) as icon:
        rect = geom.box(length, width)
        nd.Polygon(points=rect, layer=layer).put(0)
        nd.Pin('cc').put(0.5 * length)
    return icon
Пример #11
0
    def cell(length=length, angle=angle):
        anglerad = radians(angle)
        """Create a trapezoidal IO cell.

        Returns:
            Cell
        """
        with nd.Cell(hashme=True, instantiate=False) as C:
            #When instantiate is True, cell put in (0,0,0)
            nd.Pin(name='a0', xs=xs['a0'], width=pinwidth['a0']).put(0, 0, 180)
            nd.Pin(name='b0', xs=xs['b0'], width=pinwidth['b0']).\
                put(length/cos(anglerad)-0.5*width*tan(abs(anglerad)))

            pdk.put_stub(['b0'])
            pdk.cellname(length=0.5 * length).put(-0.1 * length, 0, 180, 'a0')

            for lay, grow, acc in nd.layeriter(xs['a0']):
                outline = nd.geom.trapezoid(length=length / cos(anglerad) +
                                            grow * tan(abs(anglerad)),
                                            height=width + 2 * grow,
                                            angle1=90 + angle,
                                            angle2=90,
                                            position=2)
                nd.Polygon(layer=lay, points=outline).put(0)
            cfg.cp = C.pin['b0']
            C.groupname = groupname
        return C
Пример #12
0
    def cell(length=length, angle=angle):
        anglerad = radians(angle)
        """Create a trapezoidal IO cell.

        Returns:
            Cell
        """
        with nd.Cell(hashme=True, instantiate=False) as C:
            """When instantiate is True, cell put in (0, 0, 0)"""
            nd.Pin(name='a0', xs=xs['a0'], width=pinwidth['a0']).put(0, 0, 180)
            nd.Pin(name='b0', xs=xs['b0'], width=pinwidth['b0']).\
                put(0.5*length*(1.0+1.0/cos(anglerad)))

            pdk.put_stub(['a0', 'b0'])
            pdk.cellname(length=0.5 * length).put(C.pin['a0'].rot(180))

            temp_a = tan(anglerad) + 0.5 * width * tan(anglerad)
            temp_b = length / cos(anglerad) + length
            for lay, grow, acc in nd.layeriter(xs['a0']):
                outline = [(0, 0.5 * width + grow),
                           (0.5 * temp_b - (width + grow) * temp_a,
                            0.5 * width + grow),
                           (0.5 * temp_b + grow * temp_a, -0.5 * width - grow),
                           (0, -0.5 * width - grow)]
                nd.Polygon(layer=lay, points=outline).put(0)
            cfg.cp = C.pin['b0']
        C.groupname = groupname
        return C
Пример #13
0
    def icon_grating(length=100, width=20, bufx=None, bufy=None):
        """Create an icon for a grating.

        Args:
            length (float): length of the grating icon
            width (float): width of the grating icon

        Returns:
            Cell: grating icon
        """
        length, width, bufx, bufy = calc_buf(length, width, bufx, bufy)
        Nmin = 3
        h = width
        w = 0.4 * width

        if length < 2 * Nmin * w:
            w = length / 6
            N = 3
        else:
            N = int(length / (2 * w))

        with nd.Cell('icon', instantiate=False) as icon:
            t, u, v = w / 4, w / 2, h / 2
            cross = [(u, t), (u, v), (-u, v), (-u, t), (-w, t), (-w, -t),
                     (-u, -t), (-u, -v), (u, -v), (u, -t), (w, -t), (w, t)]
            for i in range(N):
                nd.Polygon(points=cross, layer=layer).put(0 + i * w * 2)

            nd.Pin('cc').put((N - 1) * w)
        return icon
Пример #14
0
    def icon_ssc(length=100, width=20, bufx=None, bufy=None):
        """Create an icon for a grating.

        Args:
            length (float): length of the grating icon
            width (float): width of the grating icon

        Returns:
            Cell: grating icon
        """
        length, width, bufx, bufy = calc_buf(length, width, bufx, bufy)

        N = 20
        dx = length / N
        wout = width
        win = 0.1 * wout
        wi = 0.5 * win
        wo = 0.5 * (wout - win)
        x, y1, y2 = [], [], []
        for i in range(N):
            x.append(i * dx)
            dy = wi + (wo / (N - 1)) * i * i / (N - 1)
            y1.append(dy)
            y2.append(-dy)
        X = x + x[::-1]
        Y = y1 + y2[::-1]
        outline = list(zip(X, Y))

        with nd.Cell('icon', instantiate=False) as icon:
            nd.Polygon(points=outline, layer=layer).put(0)
            nd.Pin('cc').put(0.5 * length)
            nd.Pin('a0').put(0, 0, 180)
            nd.Pin('b0').put(length, 0, 0)
        return icon
Пример #15
0
    def cell(diameter=diameter):
        """Create a DCpad cell.

        Args:
            diameter (float): diameter of circular debt

        Returns:
            Cell
        """
        with nd.Cell(hashme=True) as C:
            C.groupname = groupname
            pdk.addBBmap(name)
            bb_width = diameter + 2*buf_width
            bb_length = diameter + 2*buf_length

            C.default_pins('c0', 'c0')
            nd.Pin(name='c0', xs=xs['c0'], width=pinwidth['c0'], remark='electrical').\
                put(0.5*bb_length, 0, 180)

            pdk.put_stub('c0', length=pinwidth['c0'], shape='circle')
            pdk.put_boundingbox('org', bb_length, bb_width)

            for lay, grow, acc in nd.layeriter(xs['c0']):
                pad = nd.geom.circle(radius=0.5*diameter, N=100)
                nd.Polygon(layer=lay, points=pad).\
                    put('cc')

        return C
Пример #16
0
    def cell(length=length, width=width):
        """Create a DCpad_lw cell.

        Args:
            length (float): length of the pad in um
            width (float): width of the pad in um

        Returns:
            Cell: dcpad element
        """
        with nd.Cell(hashme=True) as C:
            C.groupname = groupname
            C.default_pins('c0','c0')
            buf = 10
            bb_width = width + buf
            bb_length = length + buf
            nd.Pin(name='c0', xs=xs['c0'], width=pinwidth['c0'], remark='electrical').\
                put(0.5*bb_length, 0, 180)
            pdk.put_stub('c0', length=pinwidth['c0'], shape='circle')
            pdk.put_boundingbox('org', bb_length, bb_width)

            for lay, grow, acc in nd.layeriter(xs['c0']):
                pad = nd.geom.rounded_rect(
                    length=length+grow, height=width, position=5)
                nd.Polygon(layer=lay, points=pad).\
                    put(C.pin['c0'])
        return C
Пример #17
0
    def icon_mmi(length=None, width=None, bufx=None, bufy=None):
        length, width, bufx, bufy = calc_buf(length, width, bufx, bufy)

        Nin0 = 0.5 * (Nin - 1)
        Nout0 = 0.5 * (Nout - 1)
        w_mmi = scale_width * width
        w_in = w_mmi / (2.0 * max(Nin + 0.5, Nout + 0.5))
        w_pitch = 2 * w_in
        l_in = w_in

        p = []  # list of points (x, y)
        p.append((bufx + l_in, -0.5 * w_mmi))  #bottom left
        for i in range(Nin):
            p.append((bufx + l_in, (-Nin0 + i) * w_pitch - 0.5 * w_in))
            p.append((bufx, (-Nin0 + i) * w_pitch - 0.5 * w_in))
            p.append((bufx, (-Nin0 + i) * w_pitch + 0.5 * w_in))
            p.append((bufx + l_in, (-Nin0 + i) * w_pitch + 0.5 * w_in))
        p.append((bufx + l_in, +0.5 * w_mmi))
        p.append((bufx + length - l_in, +0.5 * w_mmi))
        for i in range(Nout - 1, -1, -1):
            p.append(
                (bufx + length - l_in, (-Nout0 + i) * w_pitch + 0.5 * w_in))
            p.append((bufx + length, (-Nout0 + i) * w_pitch + 0.5 * w_in))
            p.append((bufx + length, (-Nout0 + i) * w_pitch - 0.5 * w_in))
            p.append(
                (bufx + length - l_in, (-Nout0 + i) * w_pitch - 0.5 * w_in))
        p.append((bufx + length - l_in, -0.5 * w_mmi))

        with nd.Cell('icon', instantiate=False) as icon:
            nd.Polygon(points=p, layer=layer).put(0)
            nd.Pin('cc').put(0.5 * length)
        return icon
def place_rects(rect_name, rect_length, rect_width, rect_angles, rect_x_coords,
                rect_y_coords):
    try:
        rect_width[0]
    except TypeError:
        rect_width = num.array([rect_width])
    with nd.Cell(rect_name) as rect_array:
        for u in num.arange(rect_y_coords.size):
            for v in num.arange(rect_angles.size):
                # (c, s) = (num.cos(rect_angles[v]*num.pi/180),
                #           num.sin(rect_angles[v]*num.pi/180))
                # rotation = num.array(((c, -s), (s, c)))
                rect_pts = num.array([[0, 0, rect_width[u], rect_width[u]],
                                      [0, rect_length, rect_length, 0]])
                rect_pts = num.transpose(
                    num.dot(rotation_mat(rect_angles[v]), rect_pts))
                rect_pts = geom.transform(points=rect_pts,
                                          move=(rect_x_coords[v],
                                                rect_y_coords[u], 0))
                nd.Polygon(points=rect_pts, layer='layer3').put(0)
            message = 'Angle = ' + num.array2string(rect_angles[0]) + \
                      ' to ' + num.array2string(rect_angles[-1]) + ', width = '
            if rect_width.size == 1:
                message += rect_width
            else:
                message += num.array2string(rect_width[u])
            nd.text(text=message, height=20, layer='layer3', align='rb') \
                .put(int(rect_x_coords[-2]  + 250 ),
                     int(rect_y_coords[u]) + 100)
    rect_array.put(0)
    return rect_array
Пример #19
0
    def cell(length=length,
             width1=width1,
             width2=width2,
             xs=xs,
             layer=layer,
             name=name):
        """
        Create a taper element.

        Args:
            length (float): length of taper
            width1 (float): start width of taper
            width2 (float): end width of taper
            xs (str): xsection of taper
            layer (int | str): layer number or layername

        Returns:
            Cell: taper element
        """

        #nonlocal name
        if name is None:
            name = 'taper'
        # Cellname with md5 hash
        #h = md5('{}{}{}{}'.format(length, width1, width2, xs))
        #fullname = name="{}_{}".format(name, h)
        #if fullname in cfg.cellnames.keys():
        #    return cfg.cellnames[fullname]

        with Cell(name=name, cnt=True) as taper:
            taper.instantiate = False
            if abs(length) < gridsize / 2:
                return taper  # Empty taper
            if width1 > width2:
                pin = ['b0', 'a0']
                width1, width2 = width2, width1
            else:
                pin = ['a0', 'b0']

            nd.Pin(name=pin[0], width=width1, xs=xs, show=True).put(0, 0, 180)
            nd.Pin(name=pin[1], width=width2, xs=xs,
                   show=True).put(length, 0, 0)
            taper.length_geo = length

            for lay, growx, growy, acc in layeriter(xs, layer, dogrowy=True):
                # Set widths for this layer
                twidth1 = width1 + 2 * growx
                twidth2 = width2 + 2 * growx
                outline = [(0 - growy, twidth1 / 2),
                           (length + growy, twidth2 / 2),
                           (length + growy, -twidth2 / 2),
                           (0 - growy, -twidth1 / 2)]
                nd.Polygon(layer=lay, points=outline).put()
        return taper
Пример #20
0
def cornerUL(layera=1, layerb=None):

    """Fiducial marker ┌ with upper left corner for machine vision.

    This marker is not symmetric and can be used to specify the orientation
    of the chip.

    Args:
        layer1 (int | str | tuple): layer (or list of layers) in which the
            shape is written.
        layer2 (int | str | tuple): layer (or list of layers) in which the
            etch background is defined.

    Returns:
        Cell: cell with this marker.

    Example:
        Place marker centered at (0,0) in layer 1 with background layer 12.

            import nazca as nd

            f1 = nd.cornerUL(layera=1, layer2=12)
            f1.put()

            nd.export_plt()
    """
    with nd.Cell(name='Fiducial_cornerUL_'+nd.md5((layera,layerb))) as C:
        for lay in nd.make_iter(layera):
            nd.Polygon(layer=lay,
                    points=geom.rectangle(10, 125, position=5)).\
                            put(-67.5,0)
            nd.Polygon(layer=lay,
                    points=geom.rectangle(125, 10, position=5)).\
                            put(0,67.5)
        for lay in nd.make_iter(layerb):
            nd.Polygon(layer=lay,
                    points=geom.rectangle(200, 200, position=5)).put()
        nd.Pin(name='a0', xs=None).put(0,0,180)
        nd.Pin(name='b0', xs=None).put(0,0,0)
    return C
Пример #21
0
    def icon_diode(length=0, width=None, bufx=None, bufy=None):
        """Create an icon with a diode symbol.

        Returns:
            Cell: diode icon
        """
        length, width, bufx, bufy = calc_buf(length, width, bufx, bufy)
        ratio = 0.3
        w_line = 0.1 * ratio * width
        with nd.Cell('icon', instantiate=False) as icon:
            dio1 = [(-0.5 * ratio * width, 0.5 * ratio * width),
                    (0.5 * ratio * width, 0.5 * ratio * width),
                    (0, -0.5 * ratio * width)]
            dio2 = geom.rectangle(ratio * width, w_line, position=5)
            dio3 = geom.rectangle(w_line, width, position=5)
            nd.Polygon(points=dio1, layer=layer).put(0.5 * length)
            nd.Polygon(points=dio2,
                       layer=layer).put(0.5 * length,
                                        -0.5 * ratio * (width - w_line))
            nd.Polygon(points=dio3, layer=layer).put(0.5 * length)
            nd.Pin('cc').put(0.5 * length)
        return icon
Пример #22
0
    def cell(length=length,
             width=width,
             xs=xs,
             layer=layer,
             edge1=edge1,
             edge2=edge2,
             name=name):
        """Create a straight waveguide element.

        Args:
            length (float): length of waveguide
            width (float): width of waveguide
            xs (str): xsection of waveguide
            layer (int | str): layer number or layername
            edge1 (function): optional function F(t) describing edge1 of the waveguide
            edge2 (function): optional function G(t) describing edge2 of the waveguide

        Returns:
            Cell: straight element
        """

        if name is None:
            name = 'straight'
        #assert width is not None
        if width is None:
            width = 0.0
        with Cell(name=name, cnt=True) as guide:
            guide.instantiate = False
            nd.Pin(name='a0', width=width, xs=xs, show=True).put(0, 0, 180)
            nd.Pin(name='b0', width=width, xs=xs, show=True).put(length, 0, 0)
            guide.length_geo = length

            for lay, growx, growy, acc in layeriter(xs, layer, dogrowy=True):
                if edge1 is None:
                    outline = [(0 - growy, 0.5 * width + growx),
                               (length + growy, 0.5 * width + growx),
                               (length + growy, -0.5 * width - growx),
                               (0 - growy, -0.5 * width - growx)]
                else:
                    if edge2 is None:
                        edge2 = edge1
                    Fp1 = []
                    Fp2 = []
                    for t in np.linspace(0, 1, 20):
                        Fp1.append((length * t, edge1(t) + growx))
                        Fp2.append((length * t, -edge2(t) - growx))
                    outline = Fp1 + list(reversed(Fp2))
                if abs(length) > min_length:
                    nd.Polygon(layer=lay, points=outline).put(0)
        return guide
Пример #23
0
def target(layera=1, layerb=None):

    """Fiducial marker 'target' for machine vision.

    Args:
        layera (layer): layer in which the target is written.
        layerb (layer): layer in which etch background is defined (trench).
        name (string): cell name.

    Returns:
        Cell: cell with this marker.

    Example:
        Place marker centered at (0,0) in layer 1 with background
        layer 12.

            import nazca as nd

            f1 = nd.target(layera=1, layerb=12)
            f1.put()

            nd.export_plt()
    """
    with nd.Cell(name='Fiducial_target_'+nd.md5((layera,layerb))) as C:
        nd.Polygon(layer=layera,
                points=geom.rectangle(200, 10, position=5)).put()
        nd.Polygon(layer=layera,
                points=geom.rectangle(10, 200, position=5)).put()
        nd.Polygon(layer=layera,
                points=geom.ring(radius=35, width=10, N=41)).put()
        nd.Polygon(layer=layera,
                points=geom.ring(radius=70, width=10, N=81)).put()
        nd.Polygon(layer=layerb,
                points=geom.rectangle(225, 225, position=5)).put()
        nd.Pin(name='a0', xs=None).put(0,0,180)
        nd.Pin(name='b0', xs=None).put(0,0,0)
    return C
Пример #24
0
    def cell(length=length, height=height, cleave=cleave, pitch=pitch):
        """Create a cell boundary.

        Returns:
            Cell
        """
        with nd.Cell(hashme=True) as C:
            pdk.parameters('hashme').put(0)

            #TODO: No foundry specific stuff here: remove.
            for lay, grow, acc in nd.layeriter(xs):
                frame = geom.frame(sizew=cleave,
                                   sizel=length,
                                   sizeh=height,
                                   grow=grow)
                nd.Polygon(layer=lay, points=frame).put(0)

            #Placing IOs
            amount_ios = round((height - cleave - pitch) / pitch)

            #IOs positions
            lay = 'AnnotationIO'
            for no in range(0, amount_ios):
                pinID = 'ioL{:03d}'.format(no)
                angle = 0

                p = nd.Pin(name=pinID).put(-cleave, pitch + no * pitch, angle)
                p = nd.Pin(name='ioL' + str(no)).put(-cleave,
                                                     pitch + no * pitch, angle)
                pdk.arrow.put(p)
                nd.text(pinID, layer=lay, height=0.15,
                        align='rc').put(p.move(-0.1))

            for no in range(0, amount_ios):
                mo = amount_ios + no
                pinID = 'ioR{:03d}'.format(no)
                angle = 0

                p = nd.Pin(name=pinID).put(length, pitch + no * pitch,
                                           180 + angle)
                p = nd.Pin(name='ioR' + str(no)).put(length,
                                                     pitch + no * pitch,
                                                     180 + angle)
                pdk.arrow.put(p)
                nd.text(pinID, layer=lay, height=0.15, align='lc').\
                    put(p.move(-0.1, 0, 180))

        C.groupname = groupname
        return C
def place_cross(cross_name, x, y, cross_w, cross_l):
    try:
        cross_w[0]
    except TypeError:
        cross_w = num.array([cross_w])
    with nd.Cell(name=cross_name) as xs:
        for u in num.arange(num.size(cross_w)):
            box_pts = num.array([[0, 0, cross_l, cross_l],
                                 [cross_w[u], 0, 0, cross_w[u]]])
            xs_box_h = geom.transform(
                points=num.transpose(box_pts),
                move=(+x, y + (cross_l - cross_w[u]) / 2 + u * (cross_l + 50),
                      0))
            xs_box_v = geom.transform(points=num.transpose(
                num.dot(rotation_mat(90), box_pts)),
                                      move=(+x + (cross_l + cross_w[u]) / 2,
                                            +y + u * (cross_l + 50), 0))
            xs_box_30 = geom.transform(
                points=num.transpose(num.dot(rotation_mat(30), box_pts)),
                move=(+x + (cross_l - cross_l * num.cos(num.pi / 6) +
                            cross_w[u] * num.sin(num.pi / 6)) / 2,
                      +y + (cross_l - cross_l * num.sin(num.pi / 6) -
                            cross_w[u] * num.cos(num.pi / 6)) / 2 + u *
                      (cross_l + 50), 0))
            xs_box_60 = geom.transform(
                points=num.transpose(num.dot(rotation_mat(60), box_pts)),
                move=(+x + (cross_l - cross_l * num.cos(num.pi / 3) +
                            cross_w[u] * num.sin(num.pi / 3)) / 2,
                      +y + (cross_l - cross_l * num.sin(num.pi / 3) -
                            cross_w[u] * num.cos(num.pi / 3)) / 2 + u *
                      (cross_l + 50), 0))
            xs_box_120 = geom.transform(xs_box_60,
                                        flipy=True,
                                        move=(0, +2 * y + cross_l + 2 * u *
                                              (cross_l + 50), 0))
            xs_box_150 = geom.transform(xs_box_30,
                                        flipx=True,
                                        move=(+2 * x + cross_l, 0, 0))
            nd.Polygon(points=xs_box_h, layer='layer3').put(0)
            nd.Polygon(points=xs_box_v, layer='layer3').put(0)
            nd.Polygon(points=xs_box_30, layer='layer3').put(0)
            nd.Polygon(points=xs_box_60, layer='layer3').put(0)
            nd.Polygon(points=xs_box_120, layer='layer3').put(0)
            nd.Polygon(points=xs_box_150, layer='layer3').put(0)
            message_txt = 'Height = ' + str(cross_l) + ', Width = ' + str(
                cross_w[u])
            nd.text(text=message_txt, height=20, layer='layer3') \
                .put(int(x - cross_l / 2 - 150), int(y + u * (cross_l + 50)))
    xs.put(0)
    return
Пример #26
0
def north(size=100, layer=1):
    """Show north pointer to identify the sample direction.

    Args:
        size (double): size (wxh) of the bounding box.
        layer (int | str | tuple): layer (or list of layers) to draw in.

    Returns:
        cell containing the pointer.
    """
    s = size/148

    pointer = [(-69*s,-74*s), (-70*s,-73*s), (-s,74*s), (s,74*s),
            (70*s,-73*s), (69*s,-74*s), (0,-33*s), (0,57*s), (-s,57*s),
            (-52*s,-52*s), (-51*s,-53*s), (0,-23*s), (0,-33*s)]

    with nd.Cell("north_"+nd.md5(layer)) as C:
        for lay in nd.make_iter(layer):
            nd.Polygon(layer=lay, points=pointer).put(0,0,0)
    return C
def make_pincell(layer=None, shape=None, size=None):
    """Create a cell to indicate a pin position.

    The cell contains a shape, e.g. an arrow, to point out a location in the layout.
    Available pin shapes are in a dictionary in cfg.pinshapes: {name: polygon}.
    The predefined shapes have been normalized to unit size.

    Args:
        layer (float): layer number to place the pin symbol/shape
        shape (str): name (dict key) of the pin symbol/shape.
        size (float): scaling factor of the pin symbol/shape

    Returns:
        Cell: cell with pin symbol
    """
    pinshape = cfg.pin_settings['bb_pin_shape']
    if layer is None:
        layer = cfg.pin_settings['bb_pin_layer']
    layer = nd.get_layer(layer)

    if shape is None:
        shape = pinshape

    if size is None:
        size = cfg.pin_settings['bb_pin_size']

    if shape not in cfg.pinshapes.keys():
        print("Warning: arrowtype '{}' not recognized.".format(shape))
        print("Available options are: {}.".format(cfg.pinshapes.keys()))
        print("Fall back type '{}' will be used.".format(pinshape))
        shape = pinshape

    name = "{}_{}_{}_{}".format('arrow', layer, shape, size)
    name = cfg.gds_cellname_cleanup(name)
    if name in cfg.cellnames.keys():
        return cfg.cellnames[name]
    with nd.Cell(name, instantiate=cfg.pin_instantiate,
                 store_pins=False) as arrow:
        outline = [(x * size, y * size) for x, y in cfg.pinshapes[shape]]
        nd.Polygon(layer=layer, points=outline).put(0)
    return arrow
def place_blks(block_name, block_height, block_width, block_angles,
               block_x_coords, block_y_coords):
    with nd.Cell(block_name) as blk_arr:
        for u in num.arange(block_width.size):
            for v in num.arange(block_angles.size):
                block_pts = geom.parallelogram(length=block_width[u],
                                               height=block_height,
                                               angle=block_angles[v],
                                               shift=(block_x_coords[v],
                                                      block_y_coords[u], 0))
                nd.Polygon(points=block_pts, layer='layer3').put(0)
            message = 'Angle = ' + num.array2string(block_angles[0]) + \
                      ' to ' + num.array2string(block_angles[-1]) + \
                      ', Width = ' + num.array2string(block_width[0]
                                                      * num.sin(num.pi/180
                                                                *block_angles[0]))
            nd.text(text=message, height=20, layer='layer3') \
                .put(int(block_x_coords[-1] + 0.5 * block_x_coords[0]),
                     int(block_y_coords[u]))
    blk_arr.put(0)
    return blk_arr
Пример #29
0
    def cell(width=width,
             distance=distance,
             offset=offset,
             xs=xs,
             layer=layer,
             name=name):
        """Create a cosine bend waveguide element.

        Args:
            width (float): width of the interconnect in um
            pin (Node): optional Node for modeling info
            xs (str): xsection of cbend
            offset (float): lateral offset of the cbend in um
            distance (float): total forward length of the cbend in um
            xs (str): xsection of waveguide
            layer (int | str): layer number or layername

        Returns:
            Cell: ccurve element
        """

        if name is None:
            name = 'ccurve'

        xya = (distance, offset, 0)  # End point
        # ccurve waveguide, cwg
        with Cell(name=name, cnt=True) as cwg:
            cwg.instantiate = False
            nd.Pin(name='a0', width=width, xs=xs, show=True).put(0, 0, 180)
            nd.Pin(name='b0', width=width, xs=xs, show=True).put(*xya)

            for lay, growx, growy, acc in layeriter(xs, layer, dogrowy=True):
                # sampled curve
                xy = curve2polyline(cbend_point, xya, acc, (distance, offset))
                # polygon of proper width
                xy = nd.util.polyline2polygon(xy, width + growx * 2)
                nd.Polygon(layer=lay, points=xy).put(0)
        return cwg
Пример #30
0
def whereami(text='here', size=100, pin=None):
    """Show current pointer position as arrow in the layout.

    Args:
        text (str): annotation text
        size (float): size of the annotation

    Returns:
        None
    """
    layer = 500
    nd.cp.push()
    if pin is None:
        pin = nd.cp.here()
    points = [(0, 0), (-0.5, 0.5), (-0.4, 0.25), (-1, 0.3), (-1, -0.3),
              (-0.4, -0.25), (-0.5, -0.5)]
    points = [(x * size, y * size) for x, y in points]
    with Cell('I am'.format(wherecnt)) as crisis:
        nd.Polygon(layer=layer, points=points).put(0)
        nd.text(text + ' ', height=size / 4, align='rc', layer=layer).put(0)

    crisis.put(pin)
    nd.cp.pop()