Esempio n. 1
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
Esempio n. 2
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
Esempio n. 3
0
    def cell(width_sig=width_sig, width_gnd1=width_gnd1,
             width_gnd2=width_gnd2,
             gap1=gap1, height_tap=height_tap, gap2=gap2,
             length_pad=length_pad, width_pad_sig=width_pad_sig,
             width_pad_gnd=width_pad_gnd):
        """Create and return a GSG RF cell.

        Args:
            ??

        Returns:
            Cell
        """
        with nd.Cell(name=pdk._hash_name) as C:
            C.groupname = groupname
            C.default_pins('a0', 'a0')
            pdk.addBBmap(name)

            nd.Pin(name='a0', xs=xs['a0'], width=pinwidth['a0'], remark='electrical').put(0, 0, 180)
            #nd.Pin(name='b0', xs=xs['b0'], width=pinwidth['b0']).put(0, 0, 180)

            bb_length = length_pad+height_tap
            pdk.put_stub([])
            pdk.cellname(C.cell_name, bb_length).put(-0.25*bb_length, 0, 180, 'a0')
            pdk.parameters(pdk._hash_params).put(-0.25*bb_length, 0, 180, 'a0')

            boundary = 10
            nd.Pin(name='rc', xs=None, width=None).\
                put(length_pad+height_tap+boundary, 0, 0)
            heightRectangle = length_pad+boundary
            widthRectangle  = 2*width_pad_gnd+width_sig+2*gap2+2*boundary
            widthTaper      = width_gnd1+width_gnd2+width_sig+2*gap1+2*boundary

            if width_gnd2 == None:
                width_gnd2 = width_pad_gnd

            # outline of the BB
            angle = -degrees(atan(height_tap/(0.5*(widthRectangle-widthTaper))))
            outline = geom.trapezoid(length=widthTaper, height=height_tap,
                angle1=angle, angle2=angle, position=4)
            nd.Polygon(layer='bbox', points=outline).put(0, 0, -90)

            outline = geom.box(length=heightRectangle, width=widthRectangle)
            nd.Polygon(layer='bbox', points=outline).put(height_tap, 0, 0)

            # Ground Taper
            outline = geom.tetragon(length=width_gnd1, height=height_tap,
                dx=gap2-gap1, x=width_pad_gnd, position=4)
            nd.Polygon(layer=layer, points=outline).\
                put(0, gap1+0.5*(width_sig+width_gnd1), -90)
            # Ground Pad
            outline = geom.rectangle(length=width_pad_gnd,
                    height=length_pad, position=7)
            nd.Polygon(layer=layer, points=outline).\
                put(height_tap, gap2+0.5*width_sig, -90)

            # Signal Line
            outline = geom.box(length=height_tap, width=width_sig)
            nd.Polygon(layer=layer, points=outline).put(0, 0, 0)
            # Signal Pad
            outline = geom.rectangle(length=width_pad_sig,
                    height=length_pad, position=4)
            nd.Polygon(layer=layer, points=outline).put(height_tap, 0, -90)

            # Ground Taper
            outline = geom.tetragon(length=width_gnd2, height=height_tap,
                dx=-gap2-width_pad_gnd+gap1+width_gnd2, x=width_pad_gnd,
                position=4)
            nd.Polygon(layer=layer, points=outline).\
                put(0, -gap1-0.5*(width_sig+width_gnd2), -90)
            # Ground Pad
            outline = geom.rectangle(length=width_pad_gnd, height=length_pad, position=1)
            nd.Polygon(layer=layer, points=outline).\
                put(height_tap, -gap2-0.5*width_sig, -90)
        return C
Esempio n. 4
0
    def cell(self):
        """Create a Cell with DC, RF, Optical fiber postitions.

        Returns:
            Cell: package cell
        """
        with nd.Cell(name=self.name) as C:

            for arr in self.pads:

                count = arr['count']
                #Placing PAD IOs
                IOcountmax = round(\
                    (self.die_length - 2*arr['edge_sep_side']) / arr['pitch'])
                if count is not None and count < IOcountmax:
                    IOcount = count
                else:
                    IOcount = IOcountmax

                pin = arr['edge'] + arr['type']
                if arr['edge'] == 'left':
                    x0, y0, a0 = 0, 0, 90
                elif arr['edge'] == 'top':
                    x0, y0, a0 = 0, self.die_height, 0
                elif arr['edge'] == 'right':
                    x0, y0, a0 = self.die_length, self.die_height, -90
                elif arr['edge'] == 'bottom':
                    x0, y0, a0 = self.die_length, 0, 180
                else:
                    print("Edge not recognized in Package2: '{}'".format(
                        arr['edge']))

                #PAD positions
                for n in range(0, IOcount):
                    pinID = pin_naming[pin].format(n)
                    if arr['center']:
                        if arr['edge'] in ['top', 'bottom']:
                            dist_edge = self.die_length -\
                                (IOcount-1)*arr['pitch'] - 2*arr['edge_sep_side']
                        elif arr['edge'] in ['left', 'right']:
                            dist_edge = self.die_height -\
                                (IOcount-1)*arr['pitch'] - 2*arr['edge_sep_side']
                    else:
                        dist_edge = 0

                    #place metal io pins
                    start = nd.Pin().put(x0, y0, a0)
                    p = nd.Pin(pinID).put(
                        start.move(
                            n * arr['pitch'] + arr['edge_sep_side'] +
                            0.5 * dist_edge, -arr['edge_sep_front'], -90))
                    self.arrow.put(p)
                    text = nd.text(pinID,
                                   layer=annotationlayer,
                                   height=textheight,
                                   align='rc')
                    text.put(p.move(textmove))

            #Fiber positions
            dist_edgey = self.die_height - self.cleave - self.fiberarea
            faa_len = self.cleave + 50

            if self.show_fiberarea:
                farea = geom.box(width=self.fiberarea, length=faa_len)
                poly = nd.Polygon(layer=fiberIOlayer, points=farea)
                poly.put(-faa_len - 0.5 * self.cleave,
                         0.5 * dist_edgey + 0.5 * self.fiberarea, 0)
            else:
                print(
                    'Set show_fiberarea == True to see the fiber allowed area for this package.'
                )

        return C
Esempio n. 5
0
    def cell(self):
        """Create a Cell with DC, RF, Optical fiber postitions.

        Returns:
            Cell: package cell
        """
        with nd.Cell(name=self.name) as C:

            #Placing PAD IOs
            IOcountmax = round(
                (self.die_length - 2 * self.DCside) / self.DCpitch)
            if self.DCcount is not None and self.DCcount < IOcountmax:
                IOcount = self.DCcount
            else:
                IOcount = IOcountmax

            #DC PAD positions
            for n in range(0, IOcount):
                pinIDT = DCtopname.format(n)
                pinIDB = DCbotname.format(n)

                if self.DCcenter:
                    dist_edgex = 0.5 * (self.die_length -
                                        (IOcount - 1) * self.DCpitch)
                else:
                    dist_edgex = self.DCside

                #Top DC ports
                p = nd.Pin(pinIDT).put(
                    dist_edgex + n * self.DCpitch - 0.5 * self.cleave,
                    self.die_height - self.DCedge - 0.5 * self.cleave, -90)
                self.arrow.put(p)
                text = nd.text(pinIDT,
                               layer=annotationlayer,
                               height=textheight,
                               align='rc')
                text.put(p.move(textmove))

                #Bottom DC ports
                p = nd.Pin(pinIDB).put(
                    dist_edgex + n * self.DCpitch - 0.5 * self.cleave,
                    self.DCedge - 0.5 * self.cleave, 90)
                self.arrow.put(p)
                text = nd.text(pinIDB,
                               layer=annotationlayer,
                               height=textheight,
                               align='rc')
                text.put(p.move(textmove))

            #DC PAD positions double row
            if self.double_row_DC:
                for ndr in range(0, IOcount - 1):
                    n = ndr + IOcountmax
                    pinIDT = DCtopname.format(n)
                    pinIDB = DCbotname.format(n)

                    if self.DCcenter == True:
                        dist_edgex = self.die_length - self.cleave -\
                            (IOcount-1)*self.DCpitch-2*self.DCside
                    else:
                        dist_edgex = 0

                    if self.DCx_doublerow == None:
                        self.DCx_doublerow = 0.5 * self.DCpitch

                    if self.DCy_doublerow == None:
                        self.DCy_doublerow = 1.0 * self.DCpitch

                    #Top DC ports
                    p = nd.Pin(pinIDT).put(
                        ndr * self.DCpitch + self.DCside + 0.5 * dist_edgex +
                        self.DCx_doublerow, self.die_height - self.cleave -
                        self.DCedge - self.DCy_doublerow, -90)
                    self.arrow.put(p)
                    text = nd.text(pinIDT,
                                   layer=annotationlayer,
                                   height=textheight,
                                   align='rc')
                    text.put(p.move(textmove))

                    #Bottom DC ports
                    p = nd.Pin(pinIDB).put(
                        ndr * self.DCpitch + self.DCside + 0.5 * dist_edgex +
                        self.DCx_doublerow, self.DCedge + self.DCy_doublerow,
                        90)
                    self.arrow.put(p)
                    text = nd.text(pinIDB,
                                   layer=annotationlayer,
                                   height=textheight,
                                   align='rc')
                    text.put(p.move(textmove))

            #RF PAD positions
            IOcountmax = round(
                (self.die_height - 2 * self.RFside) / self.RFpitch)
            if self.RFcount is not None and self.RFcount < IOcountmax:
                IOcount = self.RFcount
            else:
                IOcount = IOcountmax

            for n in range(0, IOcount):
                piRFn = RFname.format(n)

                if self.RFcenter:
                    dist_edgey = self.die_height-self.cleave -\
                        (IOcount-1)*self.RFpitch-2*self.RFside
                else:
                    dist_edgey = 0

                p = nd.Pin(piRFn).put(
                    self.die_length - self.cleave - self.RFedge,
                    n * self.RFpitch + self.RFside + 0.5 * dist_edgey, 180)
                self.arrow.put(p)
                text = nd.text(piRFn,
                               layer=annotationlayer,
                               height=textheight,
                               align='rc')
                text.put(p.move(textmove))

            #RF PAD positions double row
            if self.double_row_RF:
                for ndr in range(0, IOcount - 1):
                    n = ndr + IOcountmax
                    piRFn = RFname.format(n)

                    if self.RFcenter == True:
                        dist_edgey = self.die_height-self.cleave -\
                            (IOcount-1)*self.RFpitch-2*self.RFside
                    else:
                        dist_edgey = 0

                    if self.RFx_doublerow == None:
                        self.RFx_doublerow = 1.0 * self.RFpitch

                    if self.RFy_doublerow == None:
                        self.RFy_doublerow = 0.5 * self.RFpitch

                    p = nd.Pin(piRFn).put(\
                        self.die_length-self.cleave-self.RFedge-self.RFx_doublerow,
                        ndr*self.RFpitch+self.RFside+0.5*dist_edgey+self.RFy_doublerow,
                        180)
                    self.arrow.put(p)
                    text = nd.text(piRFn,
                                   layer=annotationlayer,
                                   height=textheight,
                                   align='rc')
                    text.put(p.move(textmove))

            #Fiber positions
            dist_edgey = self.die_height - self.cleave - self.fiberarea
            faa_len = self.cleave + 50

            if self.show_fiberarea:
                farea = geom.box(width=self.fiberarea, length=faa_len)
                poly = nd.Polygon(layer=fiberIOlayer, points=farea)
                poly.put(-faa_len - 0.5 * self.cleave,
                         0.5 * dist_edgey + 0.5 * self.fiberarea, 0)
            else:
                print(
                    'Set show_fiberarea == True to see the fiber allowed area for this package.'
                )

        return C
Esempio n. 6
0
    def cell(self):
        """Create a Cell with DC and RF postitions.

        Returns:
            Cell: cell for packaging"""
        # Optical positions come from foundry.
        l = self.length - self.cleave
        h = self.height - self.cleave

        with nd.Cell(name='{}_{}'.format(self.name, next(self.instnum))) as C:

            # Number of DC pads
            nNS = int((l - 2 * self.DCminside) / self.DCpitch) + 1
            nEW = int((h - 2 * self.DCminside) / self.DCpitch) + 1
            nDC = [nNS, nNS, nEW, nEW]

            # tuple in pins: start position of dc pins on all four sides.
            dc0 = (
                # Bottom
                nd.Pin('p0B').\
                    put(l/2-(nNS/2-0.5)*self.DCpitch, self.DC0edge, 90),
                # Top
                nd.Pin('p0T').\
                    put(l/2+(nNS/2-0.5)*self.DCpitch,  h-self.DC0edge, 270),
                # Left
                nd.Pin('p0L').\
                    put(self.DC0edge, h/2+(nEW/2-0.5)*self.DCpitch, 0),
                # Right
                nd.Pin('p0R').\
                    put(l-self.DC0edge, h/2-(nEW/2-0.5)*self.DCpitch, 180),
            )

            # Number of RF pads
            nNS = int((l - 2 * self.RFminside) / self.RFpitch)
            nEW = int((h - 2 * self.RFminside) / self.RFpitch)
            nRF = [nNS, nNS, nEW, nEW]

            # tuple in pins: start position of dc pins on all four sides.
            rf0 = (
                # Bottom
                nd.Pin('rfS').\
                    put(l/2-(nNS/2-0.5)*self.RFpitch, self.RFedge, 90),
                # Top
                nd.Pin('rfN').\
                    put(l/2+(nNS/2-0.5)*self.RFpitch, h-self.RFedge, 270),
                # Left
                nd.Pin('rfW').\
                    put(self.RFedge, h/2+(nEW/2-0.5)*self.RFpitch, 0),
                # Right
                nd.Pin('rfE').\
                    put(l-self.RFedge, h/2-(nEW/2-0.5)*self.RFpitch, 180),
            )

            # Place DC0 pins
            for pin, n, name, arrow in zip(dc0, nDC, DC0name, self.DC0):
                if not arrow:
                    continue  # Don't generate the pins
                for i in range(0, n):
                    loc = nd.Pin(name.format(i)).\
                        put(pin.move(0,-i*self.DCpitch,0))
                    self._put_arrow(loc, name, i)

            # Place DC1 pins
            for pin, n, name, arrow in zip(dc0, nDC, DC1name, self.DC1):
                if not arrow:
                    continue  # Don't generate the pins
                for i in range(0, n - 1):
                    loc = nd.Pin(name.format(i)).\
                        put(pin.move(self.DC1edge-self.DC0edge,
                            -(i+0.5)*self.DCpitch, 0))
                    self._put_arrow(loc, name, i)

            # Place RF pins
            for p, n, name, arrow in zip(rf0, nRF, RFname, self.RF):
                if not arrow:
                    continue  # Don't generate the pins
                for i in range(0, n):
                    loc = nd.Pin(name.format(i)).\
                        put(p.move(0,-i*self.RFpitch,0))
                    self._put_arrow(loc, name, i)

            #Fiber positions
            faalen = self.cleave + 50
            if self.fiberareaR:
                dist_edgey = self.height - self.cleave - self.fiberareaR
                farea = geom.box(width=self.fiberareaR, length=faalen)
                poly = nd.Polygon(layer=fiberIOlayer, points=farea)
                poly.put(self.length - 0.5 * self.cleave,
                         0.5 * dist_edgey + 0.5 * self.fiberareaR, 0)
            if self.fiberareaL:
                dist_edgey = self.height - self.cleave - self.fiberareaL
                farea = geom.box(width=self.fiberareaL, length=faalen)
                poly = nd.Polygon(layer=fiberIOlayer, points=farea)
                poly.put(-faalen - 0.5 * self.cleave,
                         0.5 * dist_edgey + 0.5 * self.fiberareaL, 0)

        return C
def put_boundingbox(pinname,
                    length,
                    width,
                    raise_pins=True,
                    outline=True,
                    align='lc',
                    name=True,
                    params=True,
                    move=(0, 0, 0)):
    """Create bounding box (bbox) cell inside the active cell.

    This function places a bbox cell and raises by default the bbox pins into
    the active cell. The bbox displays a bbox outline (can be switched off).
    By default it also adds the active cellname and parameters.

    Args:
        pin (str): pin to place bbox on (center left of bbox)
        length (float): length of the bbox
        with (float): width of the bbox
        raise_pins (bool): raise bbox pins into active cell (default = True)
        outline (bool): draw bbox outline (default = True)
        align (str): align the bbox on the specified bbox pin <pinname> (default = 'lc')
        name (bool): display the (active) cell name in the bbox. (default = True)
        params (bool): add parameter annotation to the bbox
        move (tuple): move the bbox placement by (float, float, float)

    Returns:
        None
    """
    cell = cfg.cells[-1]
    _paramsname = cell.cell_paramsname
    _parameters = cell.parameters
    with nd.Cell(name='bbox', instantiate=False) as bbox:
        outline = geom.box(length, width)
        nd.Polygon(layer='bbox', points=outline).put(0)

        stbs = cfg.bbox_stubs and outline
        nd.Pin('lb', type='bbox', show=stbs).put(0, -0.5 * width, 180)
        nd.Pin('lc', type='bbox', show=stbs).put(0, 0, 180)
        nd.Pin('lt', type='bbox', show=stbs).put(0, 0.5 * width, 180)

        nd.Pin('tl', type='bbox', show=stbs).put(0, 0.5 * width, 90)
        nd.Pin('tc', type='bbox', show=stbs).put(0.5 * length, 0.5 * width, 90)
        nd.Pin('tr', type='bbox', show=stbs).put(length, 0.5 * width, 90)

        nd.Pin('rt', type='bbox', show=stbs).put(length, 0.5 * width, 0)
        nd.Pin('rc', type='bbox', show=stbs).put(length, 0, 0)
        nd.Pin('rb', type='bbox', show=stbs).put(length, -0.5 * width, 0)

        nd.Pin('br', type='bbox', show=stbs).put(length, -0.5 * width, -90)
        nd.Pin('bc', type='bbox', show=stbs).put(0.5 * length, -0.5 * width,
                                                 -90)
        nd.Pin('bl', type='bbox', show=stbs).put(0, -0.5 * width, -90)

        nd.Pin('cc', type='bbox', show=cfg.bbox_stubs).put(0.5 * length, 0, 0)

        if stbs:
            nd.put_stub(['lb', 'tl', 'rt', 'br'],
                        pinshape='arrow_righthalf',
                        pinsize=cfg.pin_settings['bbox_pin_size'],
                        pinlayer=cfg.pin_settings['bbox_pin_layer'],
                        annotation_layer='bbox_pin_text')
            nd.put_stub(['lt', 'tr', 'rb', 'bl'],
                        pinshape='arrow_lefthalf',
                        pinsize=cfg.pin_settings['bbox_pin_size'],
                        pinlayer=cfg.pin_settings['bbox_pin_layer'],
                        annotation_layer='bbox_pin_text')
            nd.put_stub(['lc', 'tc', 'rc', 'bc'],
                        pinshape='arrow_full',
                        pinsize=cfg.pin_settings['bbox_pin_size'],
                        pinlayer=cfg.pin_settings['bbox_pin_layer'],
                        annotation_layer='bbox_pin_text')

        if name:
            cellname(cellname=_paramsname, length=length, width=width, align='cc').\
                put(bbox.pin['cc'])
        if params:
            parameters(parameters=_parameters).put(bbox.pin['cc'])

    # options to align the bbox in this cell w.r.t. to its pins:
    align_shift = {
        'lb': (0, 0.5 * width),
        'lc': (0, 0),
        'lt': (0, -0.5 * width),
        'rb': (-length, 0.5 * width),
        'rc': (-length, 0),
        'rt': (-length, -0.5 * width),
        'bc': (-0.5 * length, 0.5 * width),
        'cc': (-0.5 * length, 0),
        'tc': (-0.5 * length, -0.5 * width)
    }
    dx = align_shift[align][0]
    dy = align_shift[align][1]

    box = bbox.put(cfg.cells[-1].pin[pinname].move(dx, dy).move(*move))
    cell.length = length
    cell.width = width

    if raise_pins:
        box.raise_pins(bbox_pinnames, show=False)

    return None
def _makestub(xs_guide=None,
              width=0,
              length=2.0,
              shape=None,
              pinshape=None,
              pinsize=None,
              pinlayer=None,
              cell=None):
    """Create a stub in the logical layers.

    A stub is the stub of a xsection shape around a pin to visualize a connection.
    A pincell is added to the stub to indicate the pin position inside the stub.
    The new stub is added to the stubs dictionary: {name: stubcell}

    Args:
        xs_guide (str): name of xsection
        width (float): stub width
        thick (float): thickness of stub into cell (length)
        shape (str): shape of the stub: 'box' | 'circ' (default = 'box')
        pinshape (string): pinshape used in the stub
        pinsize (float): scaling factor of the pinshape (default = 1)
        cell (Cell): use the provided cell as stub instead of creating a new stub cell

    Returns:
        str: name of the stub
    """
    try:
        xs_logic = cfg.stubmap[xs_guide]
    except:
        # if no stub defined, use the xs as its own stub.
        if xs_guide is None:
            arrow = make_pincell(layer=pinlayer, shape=pinshape, size=pinsize)
            return arrow

        if xs_guide not in cfg.XSdict.keys():
            if xs_guide not in missing_xs:
                missing_xs.append(xs_guide)
                if xs_guide != cfg.default_xs_name:
                    print("Can not make a stub in undefined xsection '{0}'.\n"\
                       "  Possible causes: '{0}' is misspelled or not yet defined.\n"\
                       "  Will use xsection '{2}' instead and continue.\n"
                       "  To define a new xsection:\n"\
                       "      add_xsection(name='{0}')\n"\
                       "  or with layers info and adding a custom stub:\n"\
                       "      add_xsection(name='{0}', layer=1)\n"\
                       "      add_xsection(name='{1}', layer=2)\n"\
                       "      add_stub(xsection='{0}', stub='{1}')".\
                           format(xs_guide, 'stubname', cfg.default_xs_name))
                xs_guide = cfg.default_xs_name

        cfg.stubmap[xs_guide] = xs_guide
        xs_logic = xs_guide

    name = stubname(xs_guide, width, length, shape, pinshape, pinsize,
                    pinlayer)
    if name in stubs.keys():
        return name

    # make a new stub:
    stubshapes = ['box', 'circle']
    arrow = make_pincell(layer=pinlayer, shape=pinshape, size=pinsize)

    if width is None:
        width = 0

    with nd.Cell(name, instantiate=cfg.stub_instantiate,
                 store_pins=False) as C:
        arrow.put(0)

        if cell is not None:
            cell.put()
        else:
            for lay, growx, acc in nd.layeriter(xs_logic):
                if shape is 'circle':
                    outline = geom.circle(radius=0.5 * length, N=32)
                else:
                    outline = geom.box(width=width + 2 * growx, length=length)
                if width != 0:
                    nd.Polygon(layer=lay, points=outline).put(0, 0, 180)

                if shape not in stubshapes:
                    print(
                        "Warning: stub shape '{}' not recognized, possible options are {}."
                        .format(shape, stubshapes))
    stubs[name] = C
    return name  #name can have change to default_xs