Exemplo n.º 1
0
    def draw(self):

        name = self.name

        o = self.origin

        pad_x = self.size.x

        if pad_x > self.pitch * 9 / 10:

            pad_x = self.pitch * 9 / 10

            warnings.warn("Pad size too large, capped to pitch*9/10")

        pad_cell=pg.rectangle(size=(pad_x,self.size.y),\
        layer=self.layer)

        pad_cell.move(origin=(0,0),\
        destination=o.coord)

        cell = Device(self.name)

        dp = Point(self.pitch, 0)
        pad_gnd_sx = cell << pad_cell
        pad_sig = cell << pad_cell
        pad_sig.move(origin=o.coord,\
        destination=(o+dp).coord)

        pad_gnd_dx = cell << pad_cell
        pad_gnd_dx.move(origin=o.coord,\
        destination=(o+dp*2).coord)

        cell.add_port(Port(name='sig',\
        midpoint=(o+Point(pad_x/2+self.pitch,self.size.y)).coord,\
        width=pad_x,\
        orientation=90))

        cell.add_port(Port(name='gnd_left',\
        midpoint=(o+Point(pad_x/2,self.size.y)).coord,\
        width=pad_x,\
        orientation=90))

        cell.add_port(Port(name='gnd_right',\
        midpoint=(o+Point(pad_x/2+2*self.pitch,self.size.y)).coord,\
        width=pad_x,\
        orientation=90))

        return cell
Exemplo n.º 2
0
        def draw(self):

            supercell=cls.draw(self)

            cell=pt.Device(self.name)

            master_ref=cell.add_ref(supercell,alias='Device')

            add_passivation(cell,
                self.passivation_margin,
                self.passivation_scale,
                self.passivation_layer,
                self.passivation_absolute_mode)

            r=st.get_corners(cell)

            if issubclass(cls,pc.SMD):

                bottom_port=Port(
                    name='S_1',
                    width=self.size.x,
                    orientation=270,
                    midpoint=r.s.coord)

                top_port=Port(
                    name='N_2',
                    width=self.size.x,
                    orientation=90,
                    midpoint=r.n.coord)

                cell.add_port(top_port)
                cell.add_port(bottom_port)

                cell.add(pr.route_quad(
                    bottom_port,
                    master_ref.ports['S_1'],
                    layer=self.layer))

                cell.add(pr.route_quad(
                    top_port,
                    master_ref.ports['N_2'],
                    layer=self.layer))

            else:

                ppt.copy_ports(supercell,cell)

            return cell
Exemplo n.º 3
0
def get_centroid_ports(*ports):
    '''Calculate port with matching orientation and with as input ports, and midpoint at the
        centroid of the input ports midpoint.

    Attributes:
    ----------
        *ports : dl.Port

    Returns:
    -------
        dl.Port.
    '''

    if not ports:

        raise ValueError(f"st.get_centroid_ports(): no ports passed")

    if isinstance(ports, Port):

        return ports

    else:

        ports_centroid = get_centroid(*[Point(x.midpoint) for x in ports])

        ports_width = np.average([x.width for x in ports])

        ports_orientation = np.average([x.orientation for x in ports])

        return Port(orientation=ports_orientation,
                    width=ports_width,
                    midpoint=ports_centroid.coord)
Exemplo n.º 4
0
    def draw(self):

        if self.shape == 'square':

            cell=pg.rectangle(size=(self.size,self.size),\
                layer=self.layer)

        elif self.shape == 'circle':

            cell=pg.circle(radius=self.size/2,\
            layer=self.layer)

        else:

            raise ValueError("Via shape can be \'square\' or \'circle\'")

        cell.move(origin=(0,0),\
            destination=self.origin.coord)

        cell.add_port(Port(name='conn',\
        midpoint=cell.center,\
        width=cell.xmax-cell.xmin,\
        orientation=90))

        return cell
Exemplo n.º 5
0
    def draw(self):
        ''' Generates layout cell based on current parameters.

        'top' and 'bottom' ports are included in the cell.

        Returns
        -------
        cell : phidl.Device.
        '''

        unitcell = self._draw_unit_cell()

        cell = Device(self.name)

        cell.name = self.name

        cell.add_array(unitcell,columns=self.n,rows=1,\
            spacing=(self.pitch*2,0))

        cell.flatten()

        totx = self.pitch * (self.n * 2 + 1) - self.pitch * (1 - self.coverage)

        midx = totx / 2

        finger_dist=Point(self.pitch*1,\
        self.length+self.y_offset)

        cell = join(cell)

        cell.name = self.name

        cell.add_port(Port(name='bottom',\
        midpoint=(self.origin+\
        Point(midx,0)).coord,\
        width=totx,
        orientation=-90))

        cell.add_port(Port(name='top',\
        midpoint=(self.origin+\
        Point(midx,self.length+self.y_offset)).coord,\
        width=totx,
        orientation=90))

        del unitcell

        return cell
Exemplo n.º 6
0
    def draw(self):
        ''' Generates layout cell based on current parameters.

        'top' and 'bottom' ports is included in the cell.

        Returns
        -------
        cell : phidl.Device.
        '''
        o = self.origin

        b_main = Bus()

        b_main.origin = o

        b_main.layer = self.layer

        b_main.size = Point(self.x, self.active_area.y)

        b_main.distance = Point(self.active_area.x + self.x, 0)

        main_etch = b_main.draw()

        etch = Device(self.name)

        etch.absorb(etch << main_etch)

        port_up=Port('top',\
        midpoint=(o+Point(self.x+self.active_area.x/2,self.active_area.y)).coord,\
        width=self.active_area.x,\
        orientation=-90)

        port_down=Port('bottom',\
        midpoint=(o+Point(self.x+self.active_area.x/2,0)).coord,\
        width=self.active_area.x,\
        orientation=90)

        etch.add_port(port_up)
        etch.add_port(port_down)

        del main_etch

        return etch
Exemplo n.º 7
0
        def draw(self):

            supercell = cls.draw(self)

            cell = pt.Device(self.name)

            master_ref = cell.add_ref(supercell, alias='Device')

            add_passivation(cell, self.passivation_margin,
                            self.passivation_scale, self.passivation_layer)

            if issubclass(cls, pc.SMD):

                bottom_port = Port(name='S_1',
                                   width=self.size.x,
                                   orientation=270,
                                   midpoint=s.coord)

                top_port = Port(name='N_2',
                                width=self.size.x,
                                orientation=90,
                                midpoint=n.coord)

                cell.add_port(top_port)
                cell.add_port(bottom_port)

                cell.add(
                    pt._make_poly_connection(bottom_port,
                                             master_ref.ports['S_1'],
                                             layer=self.layer))

                cell.add(
                    pt._make_poly_connection(top_port,
                                             master_ref.ports['N_2'],
                                             layer=self.layer))

            else:

                pt._copy_ports(supercell, cell)

            return cell
Exemplo n.º 8
0
def _get_centroid_ports(ports):

    if not ports:

        raise ValueError(
            f"pt._get_centroid_ports(): no ports with tag {tag} in device {cell.name}"
        )

    ports_centroid = _get_centroid(*[Point(x.midpoint) for x in ports])

    ports_width = np.average([x.width for x in ports])

    ports_orientation = np.average([x.orientation for x in ports])

    return Port(orientation=ports_orientation,
                width=ports_width,
                midpoint=ports_centroid.coord)
Exemplo n.º 9
0
        def draw(self):

            cell=Device(name=self.name)

            super_ref=cell.add_ref(cls.draw(self))

            nvias_x,nvias_y=self.n_vias

            unit_cell=self._draw_padded_via()

            viacell=join(CellArray(unit_cell,\
                columns=nvias_x,rows=nvias_y,\
                spacing=(unit_cell.xsize,unit_cell.ysize)))

            viacell.add_port(Port(name='conn',\
                midpoint=(viacell.x,viacell.ymax),\
                width=viacell.xsize,\
                orientation=90))

            for sides in side:

                for p_name in super_ref.ports.keys():

                    if re.search(sides,p_name):

                        p=super_ref.ports[p_name]

                        pad=pg.compass(size=(p.width,self.via_distance),layer=self.pad_layers[0])

                        if sides=='top':

                            self._attach_instance(cell, pad, pad.ports['S'], viacell,p)

                        if sides=='bottom':

                            self._attach_instance(cell, pad, pad.ports['N'], viacell,p)

            for p_name,p_value in super_ref.ports.items():

                cell.add_port(p_value)

            return cell
Exemplo n.º 10
0
def shift_port(port, dist):
    '''Returns new port with translated midpoint.

    Attributes:
    ----------
        port : dl.Port

        dist : float

    Returns:
        dl.Port.
    '''

    port_mid_norm = Point(port.normal[1]) - Point(port.normal[0])

    midpoint_projected = Point(port.midpoint) + port_mid_norm * dist

    new_port = Port(name=port.name + 'shifted',
                    orientation=port.orientation,
                    width=port.width,
                    midpoint=midpoint_projected.coord)

    return new_port
Exemplo n.º 11
0
def draw_array(cell: Device,
               x: int,
               y: int,
               row_spacing: float = 0,
               column_spacing: float = 0) -> Device:
    ''' returns a spaced matrix of identical cells, copying ports in the original cells.

    Parameters
    ----------
    cell : phidl.Device

    x : int
        columns of copies

    y : int
        rows of copies

    row_spacing: float

    column_spacing: float

    Returns
    -------
    cell : phidl.Device.
    '''

    new_cell = pg.Device(cell.name + "array")

    cell_size = Point(cell.size) + Point(column_spacing, row_spacing)

    cellmat = []

    ports = []

    for j in range(y):

        cellvec = []

        for i in range(x):

            cellvec.append(
                new_cell.add_ref(cell, alias=cell.name + str(i) + str(j)))

            cellvec[i].move(destination=(Point(cell_size.x * i, cell_size.y *
                                               j)).coord)

            for p in cellvec[i].ports.values():

                ports.append(Port(name=p.name+str(i),\
                    midpoint=p.midpoint,\
                    width=p.width,\
                    orientation=p.orientation))

        cellmat.append(cellvec)

    for p in ports:

        new_cell.add_port(p)

    del cellmat

    return new_cell
Exemplo n.º 12
0
class LayoutDefault:
    '''container of pirel constants.'''

    origin = Point(0, 0)
    layerSi = 0
    layerBottom = 1
    layerTop = 2
    layerPad = 3
    layerEtch = 4
    layerVias = 5
    layerPartialEtch = 6
    layerBackSide = 7
    layerMask = 99

    #text

    TextParams={'font':"BebasNeue-Regular.otf",'size':125.0,'location':'top',\
        'distance':Point(0,100),'label':"default",'layer':layerTop}

    #IDT

    IDT_y = 200.0
    IDTpitch = 20.0
    IDTcoverage = 0.7
    IDTy_offset = 10.0
    IDTlayer = layerTop
    IDTn = 4

    #Bus

    Bussize = Point(IDTpitch * 2 * IDTn, IDTpitch * 2)
    Busdistance = Point(0, IDT_y + IDTy_offset)

    #EtchPit

    EtchPit_x = Bussize.x / 4
    EtchPitactive_area=Point(Bussize.x,\
        IDT_y+IDTy_offset+2*Bussize.y)
    EtchPitlayer = layerEtch

    #Anchor
    Anchorsize=Point(IDTpitch*IDTn/4,\
        2*Bussize.y)
    Anchor_metalized = Point(Anchorsize.x - 4, Anchorsize.y + 4)
    Anchoretch_x = EtchPit_x
    Anchorx_offset = 0.0
    Anchorlayer = IDTlayer
    Anchoretch_layer = EtchPitlayer
    Anchoretch_choice = True

    #LFERes
    LFEResactive_area_margin = 0.5
    #FBERes

    FBEResplatelayer = layerBottom
    #GSProbe
    GSProbepitch = 150.0
    GSProbepad_size = Point(80, 80)

    GSProbelayer = layerTop
    GSProberouting = True
    GSProbespacing = Point(20, 30)

    #Via

    Vialayer = layerVias
    Viashape = 'circle'
    Viasize = 20

    #GSGProbe

    GSGProbelayer = layerTop
    GSGProbepitch = 200.0
    GSGProbesize = Point(100, 100)

    GSProbelayer = GSGProbelayer
    GSProbepitch = GSGProbepitch
    GSProbesize = GSGProbesize

    #TFERes

    TFEResbottomlayer = layerBottom

    #Routing

    Routingtrace_width = 80.0

    Routingclearance = ((0, 250), (300, 550))

    Routinglayer = layerTop

    Routingports=(Port(name='1',midpoint=(450,0),\
        width=50,orientation=90),\
            Port(name='2',midpoint=(100,550),\
            width=50,orientation=90),)

    Routingside = 'auto'

    #MultiRouting

    MultiRoutingsources = (Routingports[0], )
    MultiRoutingdestinations=(Port(name='2',midpoint=(100,550),\
        width=50,orientation=90),\
            Port(name='3',midpoint=(200,80),\
            width=50,orientation=-90))
    #GSGProbe_LargePad
    GSGProbe_LargePadground_size = 200.0

    #ParametricArray

    Arrayx_spacing = 50.0
    Arrayx_param = {"IDTPitch": [_ for _ in range(1, 4)]}
    Arraylabels_top = ["IDTP" + str(x) for x in range(1, 4)]
    Arraylabels_bottom = [str(x) for x in range(1, 4)]

    #ParametricMatrix
    Matrixy_param = {"IDTLength": [_ for _ in range(100, 400, 100)]}
    Matrixy_spacing = Arrayx_spacing
    Matrixlabels_top=[ ["IDTP"+str(x)+y for x in range(1,4)]\
        for y in ["L"+str(z) for z in range(100,400,100)]]
    Matrixlabels_bottom=[ [str(x)+str(y) for x in range(1,4)] \
        for y in range(100,400,100)]

    #Stack
    Stackn = 4

    #Pad

    Padsize = 80.0
    Padlayer = IDTlayer
    Paddistance = 30.0
    Padport=Port(name='top',midpoint=(50,50),width=100,\
        orientation=-90)

    #array

    arraybusextlength = 30.0

    #addVia

    addVia_over_via = 2.0
    addVia_via_area = Point(100, 100)
    addVia_via_distance = 40
Exemplo n.º 13
0
class LayoutDefault:
    '''container of pirel constants.'''

    origin = Point(0, 0)
    layerSi = 0
    layerBottom = 1
    layerTop = 2
    layerPad = 3
    layerEtch = 4
    layerVias = 5
    layerPartialEtch = 6
    layerBackSide = 7
    layerPassivation = layerPartialEtch
    layerMask = 99

    #text

    TextParams={'font':"BebasNeue-Regular.otf",'size':125.0,'location':'top',\
        'distance':Point(0,100),'label':"default",'layer':layerTop}

    #IDT

    IDT_y = 200.0
    IDTpitch = 20.0
    IDTcoverage = 0.7
    IDTy_offset = 10.0
    IDTlayer = layerTop
    IDTn = 4

    #Bus

    Bussize = Point(IDTpitch * 2 * IDTn, IDTpitch * 2)
    Busdistance = Point(0, IDT_y + IDTy_offset)

    #EtchPit

    EtchPit_x = Bussize.x / 4
    EtchPitactive_area=Point(Bussize.x,\
        IDT_y+IDTy_offset+2*Bussize.y)
    EtchPitlayer = layerEtch

    #Anchor
    Anchorsize=Point(IDTpitch*IDTn/4,\
        2*Bussize.y)
    Anchor_metalized = Point(Anchorsize.x - 4, Anchorsize.y + 4)
    Anchoretch_x = EtchPit_x
    Anchorx_offset = 0.0
    Anchorlayer = IDTlayer
    Anchoretch_layer = EtchPitlayer
    Anchoretch_choice = True

    #MultiAnchor
    MultiAnchorn = 1

    #LFERes
    LFEResactive_area_margin = 0.5
    #FBERes

    FBEResplatelayer = layerBottom

    #Via

    Vialayer = layerVias
    Viashape = 'square'
    Viasize = 20

    #Probe

    Probesiglayer = layerTop
    Probegroundlayer = {layerTop, layerBottom}
    Probepitch = 200.0
    Probesize = Point(100, 100)

    LargePadground_size = 250
    #TFERes

    TFEResbottomlayer = layerBottom

    #Routing

    Routingtrace_width = None
    Routingclearance = ((0, 0), (0, 0))
    Routinglayer = layerTop
    Routingports=(Port(name='1',midpoint=(450,0),\
        width=50,orientation=90),\
            Port(name='2',midpoint=(100,550),\
            width=50,orientation=90),)
    Routingtype = 'manhattan'
    Routingoverhang = 20
    Routingside = 'auto'

    #MultiRouting

    MultiRoutingsources = (Routingports[0], )
    MultiRoutinglayer = {layerBottom, layerTop}
    MultiRoutingdestinations=(Port(name='2',midpoint=(100,550),\
        width=50,orientation=90),\
            Port(name='3',midpoint=(200,80),\
            width=50,orientation=-90))
    #Probe_LargePad
    Probe_LargePadground_size = 200.0

    #ParametricArray

    Arrayx_spacing = 50.0
    Arrayx_param = {"IDTPitch": [_ for _ in range(1, 4)]}
    Arraylabels_top = ["IDTP" + str(x) for x in range(1, 4)]
    Arraylabels_bottom = [str(x) for x in range(1, 4)]

    #ParametricMatrix
    Matrixy_param = {"IDTLength": [_ for _ in range(100, 400, 100)]}
    Matrixy_spacing = Arrayx_spacing
    Matrixlabels_top=[ ["IDTP"+str(x)+y for x in range(1,4)]\
        for y in ["L"+str(z) for z in range(100,400,100)]]
    Matrixlabels_bottom=[ [str(x)+str(y) for x in range(1,4)] \
        for y in range(100,400,100)]

    #Stack
    Stackn = 4

    #Pad

    Padsize = 80.0
    Padlayer = IDTlayer
    Paddistance = 30.0
    Padport=Port(name='top',midpoint=(50,50),width=100,\
        orientation=-90)

    #TwoPortProbe

    TwoPortProbeoffset = Point(0, 200)

    #Text

    TextSize = 100
    TextLabel = 'Default'
    TextLayer = layerTop
    TextFont = str(
        pathlib.Path(__file__).parent / 'addOns' / 'BebasNeue-Regular.otf')

    #Npath

    NPathCommLength = 100
    NPathSpacing = Point(0, 0)

    #SMD

    SMDDistance = Point(0, 500)
    SMDSize = Point(200, 300)
    SMDLayer = layerTop

    #Passivation

    PassivationMargin = Point(1.5, 1.2)
    PassivationScale = Point(1.8, 1.5)
    PassivationLayer = layerPassivation
Exemplo n.º 14
0
        def _draw_device_grounds(self, device_cell, probe_cell, label):

            output_cell = Device()

            lx_device_ports = []

            rx_device_ports = []

            gnd_ports = pt._find_ports(device_cell, 'Ground', depth=0)

            if not gnd_ports:

                return output_cell

            for p in gnd_ports:

                p_adj = Port(name=p.name,
                             midpoint=p.midpoint,
                             width=probe_cell['Port1'].size[1],
                             orientation=p.orientation)

                if "LX" in p.name:

                    lx_device_ports.append(p_adj)

                elif "RX" in p.name:

                    rx_device_ports.append(p_adj)

            r = pc.MultiRouting()

            r.layer = self.gndlefttrace.layer

            r.clearance = pt._bbox_to_tuple(self._bbox_mod(device_cell.bbox))

            r.trace_width = self.gnd_routing_width

            ## left connections

            if label == 'side':

                r.source = tuple(
                    pt._find_ports(probe_cell, 'GroundLXW', depth=0))

            elif label == 'straight':

                r.source = (probe_cell.ports['GroundLXN_1'], )

            r.destination = tuple(lx_device_ports)

            r.side = 'left'

            output_cell.absorb(output_cell << r.draw())

            ## right connections

            if label == 'side':

                r.source = tuple(
                    pt._find_ports(probe_cell, 'GroundRXE', depth=0))

            elif label == 'straight':

                r.source = (probe_cell.ports['GroundRXN_1'], )

            r.destination = tuple(rx_device_ports)

            r.side = 'right'

            output_cell.absorb(output_cell << r.draw())

            return output_cell
Exemplo n.º 15
0
        def draw(self):

            cell=pt.Device(name=self.name)

            oldprobe=cell<<probe.draw(self)

            cell.absorb(oldprobe)

            groundpad=pg.compass(size=(self.ground_size,self.ground_size),\
            layer=self.layer)

            [_,_,ul,ur]=get_corners(groundpad)

            for name,p in oldprobe.ports.items():

                name=p.name

                if 'gnd' in name:

                    groundref=cell<<groundpad

                    if 'left' in name:

                        groundref.move(origin=ur.coord,\
                        destination=p.endpoints[1])

                        left_port=groundref.ports['N']

                    elif 'right' in name:

                        groundref.move(origin=ul.coord,\
                        destination=p.endpoints[0])

                        right_port=groundref.ports['N']

                    cell.absorb(groundref)

                else :

                    cell.add_port(p)

            for name,port in oldprobe.ports.items():

                if 'gnd' in name:

                    if 'left' in name:

                        if self.pad_position=='side':

                            left_port=Port(name=name,\
                                midpoint=(left_port.midpoint[0]+self.ground_size/2,\
                                left_port.midpoint[1]-self.ground_size/2),\
                                orientation=180,\
                                width=self.ground_size)

                        elif self.pad_position=='top':

                            left_port=Port(name=name,\
                                midpoint=(left_port.midpoint[0],\
                                left_port.midpoint[1]),\
                                orientation=90,\
                                width=self.ground_size)

                        else :

                            raise ValueError(f"New pad position is {self.pad_position} : not acceptable")

                        cell.add_port(left_port)

                    elif 'right' in name:

                        if self.pad_position=='side':

                            right_port=Port(name=name,\
                            midpoint=(right_port.midpoint[0]-self.ground_size/2,\
                                right_port.midpoint[1]-self.ground_size/2),\
                            orientation=0,\
                            width=self.ground_size)

                        elif self.pad_position=='top':

                            right_port=Port(name=name,\
                            midpoint=(right_port.midpoint[0],\
                                right_port.midpoint[1]),\
                            orientation=90,\
                            width=self.ground_size)

                        else :

                            raise ValueError(f"New pad position is {self.pad_position} : not acceptable")

                        cell.add_port(right_port)

            return cell
Exemplo n.º 16
0
from phidl import set_quickplot_options

set_quickplot_options(blocking=True)

distance = 50
width = 10
spacing = 50
n = 4

d = Device()

for i in range(n):

    d.add_port(
        Port(
            midpoint=(spacing * i, 0),
            # midpoint=(0,spacing*i),
            width=width,
            orientation=90,
            name='top_' + str(i)))

connector = connect_ports(d, tag='top', distance=distance)

d << connector

for p in connector.get_ports(depth=0):

    d.add_port(connector.ports[p.name])

qp(d)
Exemplo n.º 17
0
def connect_ports(cell: Device,
                  tag: str = 'top',
                  layers: tuple = (LayoutDefault.layerTop, ),
                  distance: float = 10.0,
                  metal_width: float = None):
    ''' connects all the ports in the cell with name matching a tag.

    Parameters:
    -----------
        cell : Device

        tag: str

        conn_dist: pt.Point
            offset from port location

        layer : tuple.


    Returns:
    ----------

        cell : Device
            contains routings and connection port

    '''

    import pirel.pcells as pc

    ports = pt._find_ports(cell, tag, depth=0)

    ports.sort(key=lambda x: x.midpoint[0])

    ports_centroid = pt._get_centroid_ports(ports)

    if len(ports) == 1:

        raise ValueError("pm.connect_ports() : len(ports) must be >1 ")

    if metal_width is None:

        metal_width = ports_centroid.width

    port_mid_norm = pt.Point(ports_centroid.normal[1]) - pt.Point(
        ports_centroid.normal[0])

    midpoint_projected = Point(
        ports_centroid.midpoint) + port_mid_norm * (distance + metal_width)

    pad_side = ports_centroid.width

    new_port = Port(name=tag,
                    orientation=ports_centroid.orientation,
                    width=ports_centroid.width,
                    midpoint=midpoint_projected.coord)

    output_cell = Device()

    for p in ports:

        straight_conn = output_cell << pt._draw_multilayer(
            'compass',
            layers,
            size=(p.width, abs(midpoint_projected.y - p.midpoint[1])))

        straight_conn.connect("S", p)

    cross_conn = output_cell << pt._draw_multilayer(
        'compass', layers, size=(output_cell.xsize, metal_width))

    cross_conn.connect('S', new_port, overlap=metal_width)

    output = pt.join(output_cell)

    output.add_port(new_port)

    return output