Exemplo n.º 1
0
def add_pads(cell, pad, tag='top', exact=False):
    ''' add pad designs to a cell, connecting it to selected ports.

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

        pad : pt.LayoutPart

        tags : str (or iterable of str)
            used to find ports
    '''
    if not isinstance(tag, str):

        ports = []

        for t in tag:

            ports.extend(pt._find_ports(cell, t, depth=0, exact=exact))

    else:

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

    pad_cell = Device()

    for port in ports:

        pad.port = port

        pad_ref = pad_cell.add_ref(pad.draw())

        pad_ref.connect('conn', destination=port)

    cell.add_ref(pad_cell, alias="Pad")
Exemplo n.º 2
0
    def _import_gds(self):
        gdsii_lib = gdspy.GdsLibrary()
        gdsii_lib.read_gds(self.filename)
        top_level_cells = gdsii_lib.top_level()
        cellname = self.cellname
        if cellname is not None:
            if cellname not in gdsii_lib.cell_dict:
                raise ValueError(
                    'The requested cell (named %s) is not present in file %s' %
                    (cellname, self.filename))
            topcell = gdsii_lib.cell_dict[cellname]
        elif cellname is None and len(top_level_cells) == 1:
            topcell = top_level_cells[0]
        elif cellname is None and len(top_level_cells) > 1:
            areas = []
            for cell in top_level_cells:
                areas.append(cell.area())
            ind = areas.index(max(areas))
            topcell = top_level_cells[ind]

        D = Device('import_gds')
        polygons = topcell.get_polygons(by_spec=True)

        for layer_in_gds, polys in polygons.items():
            D.add_polygon(polys, layer=layer_in_gds)
        return D
Exemplo n.º 3
0
def _make_poly_connection(p1, p2, layer):

    d = Device()

    try:

        for l in layer:

            d.add_polygon([
                p1.endpoints[0], p1.endpoints[1], p2.endpoints[1],
                p2.endpoints[0]
            ],
                          layer=l)
            d.add_polygon([
                p1.endpoints[0], p1.endpoints[1], p2.endpoints[0],
                p2.endpoints[1]
            ],
                          layer=l)

    except:

        d.add_polygon([
            p1.endpoints[0], p1.endpoints[1], p2.endpoints[1], p2.endpoints[0]
        ],
                      layer=layer)
        d.add_polygon([
            p1.endpoints[0], p1.endpoints[1], p2.endpoints[1], p2.endpoints[0]
        ],
                      layer=l)

    return join(d)
Exemplo n.º 4
0
    def draw(self):

        cell = Device(name=self.name)

        lfe_cell = LFERes.draw(self)

        cell.add_ref(lfe_cell, alias='TopCell')

        idt_bottom = copy(self.idt)

        idt_bottom.layer = self.bottom_layer

        idt_ref = cell.add_ref(idt_bottom.draw(), alias='BottomIDT')

        p_bott = idt_ref.ports['bottom']

        p_bott_coord = Point(p_bott.midpoint)

        idt_ref.mirror(p1=(p_bott_coord-Point(p_bott.width/2,0)).coord,\
            p2=(p_bott_coord+Point(p_bott.width/2,0)).coord)

        idt_ref.move(origin=(idt_ref.xmin,idt_ref.ymax),\
            destination=(idt_ref.xmin,idt_ref.ymax+self.idt.length+self.idt.y_offset))

        bus_bottom = copy(self.bus)

        bus_bottom.layer = self.bottom_layer

        bus_ref = cell.add_ref(bus_bottom.draw(), alias='BottomBus')

        bus_ref.move(origin=(0,0),\
        destination=(0,-self.bus.size.y))

        anchor_bottom = copy(self.anchor)

        anchor_bottom.layer = self.bottom_layer

        anchor_bottom.etch_choice = False

        anchor_ref = cell.add_ref(anchor_bottom.draw(),
                                  alias="BottomAnchor_Top")

        anchor_ref.connect(anchor_ref.ports['conn'],\
            destination=idt_ref.ports['top'],\
            overlap=-self.bus.size.y)

        anchor_ref_2 = cell.add_ref(anchor_bottom.draw(),
                                    alias="BottomAnchor_Bottom")

        anchor_ref_2.connect(anchor_ref_2.ports['conn'],\
            destination=idt_ref.ports['bottom'],\
            overlap=-self.bus.size.y)

        for p_value in lfe_cell.ports.values():

            cell.add_port(p_value)

        return cell
Exemplo n.º 5
0
def add_vias(cell: Device,
             bbox,
             via: pt.LayoutPart,
             spacing: float = 0,
             tolerance: float = 0):
    ''' adds via pattern to cell with constraints.

    Parameters:
    -----------

    cell : Device
        where the vias will be located

    bbox : iterable
        x,y coordinates of box ll and ur to define vias patterns size

    via : pt.LayoutPart

    spacing : float

    tolerance : float (default 0)
        if not 0, used to determine via distance from target object border

    Returns:
    --------
    cell_out : Device
    '''

    bbox_cell = pg.bbox(bbox)

    nvias_x = int(np.floor(bbox_cell.xsize / (via.size + spacing)))

    nvias_y = int(np.floor(bbox_cell.ysize / (via.size + spacing)))

    if nvias_x == 0 or nvias_y == 0:

        return

    via_cell = pt.draw_array(via.draw(),
                             nvias_x,
                             nvias_y,
                             row_spacing=spacing,
                             column_spacing=spacing)

    via_cell.move(origin=(via_cell.x, via_cell.y),
                  destination=(bbox_cell.x, bbox_cell.y))

    tbr = []

    for elem in via_cell.references:

        if not pt.is_cell_inside(elem, cell, tolerance):

            tbr.append(elem)

    via_cell.remove(tbr)

    cell.absorb(cell.add_ref(via_cell, alias="Vias"))
Exemplo n.º 6
0
def mask_names(
        names=("Bottom Electrode", "Top Electrode", "Via Layer", "Etch Layer",
               "PartialEtch Layer", "Pad Layer"),
        layers=(pt.LayoutDefault.layerBottom, pt.LayoutDefault.layerTop,
                pt.LayoutDefault.layerVias, pt.LayoutDefault.layerEtch,
                pt.LayoutDefault.layerPartialEtch, pt.LayoutDefault.layerPad),
        size=250):
    """ Prints array of strings on different layers.

        Mostly useful for Layer Sorting on masks.

        Parameters
        ----------
            names : iterable of str

            layers : iterable of int

            size : float

        Returns
        -------
            cell : phidl.Device.
    """

    text = pc.Text()

    text['Size'] = size

    if not len(names) == len(layers):

        raise ValueError("Unbalanced mask names/layers combo")

    else:

        text_cells = []

        for label, layer in zip(names, layers):

            text['Label'] = label

            text['Layer'] = (layer, )

            text_cells.append(text.draw())

        g = Group(text_cells)

        g.distribute(direction='x', spacing=size)

        cell_name = Device(name='Mask Names')

        for x in text_cells:

            cell_name.absorb(cell_name << x)

        return cell_name
Exemplo n.º 7
0
    def _draw_unit_cell(self):

        o = self.origin

        rect=pg.rectangle(size=(self.coverage*self.pitch,self.length),\
            layer=self.layer)

        rect.move(origin=(0, 0), destination=o.coord)

        unitcell = Device()

        r1 = unitcell << rect

        unitcell.absorb(r1)

        r2 = unitcell << rect

        r2.move(origin=o.coord,\
        destination=(o+Point(self.pitch,self.y_offset)).coord)

        r3 = unitcell << rect

        r3.move(origin=o.coord,\
            destination=(o+Point(2*self.pitch,0)).coord)

        unitcell.absorb(r2)

        unitcell.absorb(r3)

        unitcell.name = "UnitCell"

        del rect

        return unitcell
Exemplo n.º 8
0
def _arc(radius=10,
         width=0.5,
         theta=45,
         start_angle=0,
         angle_resolution=2.5,
         layer=0):
    """ Creates an arc of arclength ``theta`` starting at angle ``start_angle`` """
    inner_radius = radius - width / 2
    outer_radius = radius + width / 2
    angle1 = (start_angle) * pi / 180
    angle2 = (start_angle + theta) * pi / 180
    t = np.linspace(angle1, angle2, np.ceil(abs(theta) / angle_resolution))
    inner_points_x = (inner_radius * cos(t)).tolist()
    inner_points_y = (inner_radius * sin(t)).tolist()
    outer_points_x = (outer_radius * cos(t)).tolist()
    outer_points_y = (outer_radius * sin(t)).tolist()
    xpts = inner_points_x + outer_points_x[::-1]
    ypts = inner_points_y + outer_points_y[::-1]

    D = Device('arc')
    D.add_polygon(points=(xpts, ypts), layer=layer)
    D.add_port(name=1,
               midpoint=(radius * cos(angle1), radius * sin(angle1)),
               width=width,
               orientation=start_angle - 90 + 180 * (theta < 0))
    D.add_port(name=2,
               midpoint=(radius * cos(angle2), radius * sin(angle2)),
               width=width,
               orientation=start_angle + theta + 90 - 180 * (theta < 0))
    D.info['length'] = (abs(theta) * pi / 180) * radius
    return D
Exemplo n.º 9
0
        def draw(self):

            cell = Device(self.name)

            d_ref = cell.add_ref(cls.draw(self), alias='Device')

            pt._copy_ports(d_ref, cell)

            add_pads(cell, self.pad, side)

            return cell
Exemplo n.º 10
0
def route_manhattan_auto(ports, bendType='circular', layer=0, radius=20):
    """ routes a one-dimensional array of ports using manhattan algorithm
    and give it a series of ports to route to in a continuous list.
    accepts same parameters as ordinary route_manhattan to determine bending """
    Total = Device()
    for x in xrange(int(np.floor(len(ports) / 2)) + 1):
        R = route_manhattan(port1=ports[x],
                            port2=ports[x + 1],
                            bendType=bendType,
                            layer=layer,
                            radius=radius)
        r = Total.add_ref(R)

    return Total
Exemplo n.º 11
0
def point_path(points=[(0, 0), (4, 0), (4, 8)], width=1, layer=0):
    points = np.asarray(points)
    dxdy = points[1:] - points[:-1]
    angles = (np.arctan2(dxdy[:, 1], dxdy[:, 0])).tolist()
    angles = np.array([angles[0]] + angles + [angles[-1]])
    diff_angles = (angles[1:] - angles[:-1])
    mean_angles = (angles[1:] + angles[:-1]) / 2
    dx = width / 2 * np.cos((mean_angles - pi / 2)) / np.cos((diff_angles / 2))
    dy = width / 2 * np.sin((mean_angles - pi / 2)) / np.cos((diff_angles / 2))
    left_points = points.T - np.array([dx, dy])
    right_points = points.T + np.array([dx, dy])
    all_points = np.concatenate([left_points.T, right_points.T[::-1]])

    D = Device()
    D.add_polygon(all_points, layer=layer)
    D.add_port(name=1,
               midpoint=points[0],
               width=width,
               orientation=angles[0] * 180 / pi + 180)
    D.add_port(name=2,
               midpoint=points[-1],
               width=width,
               orientation=angles[-1] * 180 / pi)
    return D


# quickplot(point_path())
Exemplo n.º 12
0
    def draw(self):
        ''' Generates layout cell based on current parameters.

        'conn' port is included in the cell.

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

        pad=pg.rectangle(size=self.size.coord,\
        layer=self.layer).move(origin=(0,0),\
        destination=o.coord)

        cell = Device(self.name)

        r1 = cell << pad
        cell.absorb(r1)
        r2 = cell << pad

        r2.move(origin=o.coord,\
        destination=(o+self.distance).coord)

        cell.absorb(r2)

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

        del pad

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

            self._set_relations()

            device_cell=cls.draw(self)

            probe_cell=self.probe.draw()

            cell=Device(name=self.name)

            cell.add_ref(device_cell, alias="Device")

            self._add_signal_connection(cell,'bottom')

            probe_ref=cell.add_ref(probe_cell, alias="Probe")

            self._move_probe_ref(cell)

            self._setup_signal_routing(cell)

            cell.absorb(cell<<self._draw_signal_routing())

            try:

                self._setup_ground_routing(
                    cell,
                    'straight')

                routing_cell=self._draw_ground_routing()

            except:

                self._setup_ground_routing(
                    cell,
                    'side')

                try:

                    routing_cell=self._draw_ground_routing()

                except:

                    import pdb; pdb.set_trace()

                    self._draw_ground_routing()

            _add_default_ground_vias(self,routing_cell)

            cell.add_ref(routing_cell,alias=self.name+"GroundTrace")

            return cell
Exemplo n.º 14
0
    def _draw_unit_cell(self):

        o = self.origin

        rect=pg.rectangle(size=(self.coverage*self.pitch,self.length),\
            layer=self.layer)

        rect.move(origin=(0, 0), destination=o.coord)

        unitcell = Device()

        r1 = unitcell << rect

        unitcell.absorb(r1)

        rect_partialetch=pg.rectangle(\
            size=(\
                (1-self.coverage)*self.pitch,self.length-self.y_offset),\
            layer=LayoutDefault.layerPartialEtch)

        rect_partialetch.move(origin=o.coord,\
            destination=(self.pitch*self.coverage,self.y_offset))

        rp1 = unitcell << rect_partialetch

        rp2 = unitcell << rect_partialetch

        rp2.move(destination=(self.pitch, 0))

        r2 = unitcell << rect

        r2.move(origin=o.coord,\
        destination=(o+Point(self.pitch,self.y_offset)).coord)

        r3 = unitcell << rect

        r3.move(origin=o.coord,\
            destination=(o+Point(2*self.pitch,0)).coord)

        unitcell.absorb(r2)

        unitcell.absorb(r3)

        unitcell.name = "UnitCell"

        del rect, rect_partialetch

        return unitcell
Exemplo n.º 15
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.º 16
0
def print_ports(device: Device):
    ''' print a list of ports in the cell.

    Parameters
    ----------
    device : phidl.Device.
    '''

    for i, p in enumerate(device.get_ports()):

        print(i, p, '\n')
Exemplo n.º 17
0
def add_utility_cell(cell,align_scale=[0.25,0.5,1],position=['top','left']):

    align_mark=alignment_marks_4layers(scale=align_scale)

    test_cell=resistivity_test_cell()

    align_via=Device('Align_Via')

    maskname_cell=mask_names()

    align_via.add_array(
        align_TE_on_via(),
        rows=3,
        columns=1,
        spacing=(0,350))

    align_via.flatten()

    g=Group([align_via,align_mark,test_cell])

    g.distribute(direction='x',spacing=100)

    g.align(alignment='y')

    g.move(origin=(g.center[0],g.ymax),
        destination=(cell.center[0],cell.ymax-300))

    maskname_cell.move(
        origin=(maskname_cell.x,maskname_cell.ymin),
        destination=(g.x,test_cell.ymax+150))

    utility_cell=Device(name="UtilityCell")

    if isinstance(position,str):

        position=[position]

    if 'top' in position:

        utility_cell<<align_mark
        utility_cell<<align_via
        utility_cell<<test_cell
        utility_cell<<maskname_cell

    if 'left' in position:

        t2=utility_cell<<align_mark
        t3=utility_cell<<align_via
        g=Group(t2,t3)

        g.rotate(angle=90,center=(t2.xmin,t2.ymin))

        g.move(origin=(t2.xmin,t2.center[1]),\
            destination=(cell.xmin,cell.center[1]))

    cell<<utility_cell
Exemplo n.º 18
0
def rename_ports_by_orientation(
    component: Device,
    layers_excluded: Tuple[Tuple[int, int], ...] = None,
    select_ports: Optional[Callable] = None,
    function=_rename_ports_facing_side,
    prefix: str = "o",
) -> Device:
    """Returns Component with port names based on port orientation (E, N, W, S)

    Args:
        component:
        layers_excluded:
        select_ports:
        function: to rename ports
        prefix: to add on each port name

    .. code::

             N0  N1
             |___|_
        W1 -|      |- E1
            |      |
        W0 -|______|- E0
             |   |
            S0   S1

    """

    layers_excluded = layers_excluded or []
    direction_ports = {x: [] for x in ["E", "N", "W", "S"]}

    ports = component.ports
    ports = select_ports(ports) if select_ports else ports

    ports_on_layer = [p for p in ports.values() if p.layer not in layers_excluded]

    for p in ports_on_layer:
        # Make sure we can backtrack the parent component from the port
        p.parent = component

        angle = p.orientation % 360
        if angle <= 45 or angle >= 315:
            direction_ports["E"].append(p)
        elif angle <= 135 and angle >= 45:
            direction_ports["N"].append(p)
        elif angle <= 225 and angle >= 135:
            direction_ports["W"].append(p)
        else:
            direction_ports["S"].append(p)

    function(direction_ports, prefix=prefix)
    component.ports = {p.name: p for p in component.ports.values()}
    return component
Exemplo n.º 19
0
def check(device: Device, joined=False, blocking=True):
    ''' Shows the device layout.

        If run by terminal, blocks script until window is closed.

        Parameters
        ----------
            device : phidl.Device

            joined : boolean (optional, default False)

                if true, returns a flattened/joined version of device

    '''
    set_quickplot_options(blocking=blocking)

    if joined:

        cell = Device()
        cell.absorb(cell << device)
        cell.flatten()
        qp(join(cell))

    else:

        qp(device)
Exemplo n.º 20
0
    def draw(self):

        c = Device(name=self.name)

        x = CrossSection()

        x.add(layer=self.layer, width=self.trace_width)

        for p in self.path:

            c << x.extrude(p, simplify=0.1)

        return c
Exemplo n.º 21
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.º 22
0
def add_compass(device: Device) -> Device:
    ''' add four ports at the bbox of a cell.

    Parameters
    ----------
    device : phidl.Device

    Returns
    -------
    device : phidl.Device.
    '''

    bound_cell=pg.compass(size=device.size).move(\
    origin=(0,0),destination=device.center)

    ports = port = bound_cell.get_ports()

    device.add_port(port=ports[0], name='N')
    device.add_port(port=ports[1], name='S')
    device.add_port(port=ports[2], name='E')
    device.add_port(port=ports[3], name='W')

    return device
Exemplo n.º 23
0
        def _draw_signal_routing(self):

            cell = Device()

            cell.add(self.sig1trace.draw())

            cell.add(self.sig2trace.draw())

            return cell
Exemplo n.º 24
0
def from_phidl(component: Device, **kwargs) -> Component:
    """Returns gf.Component from a phidl Device or function"""
    device = call_if_func(component, **kwargs)
    component = Component(name=device.name)
    component.info = copy.deepcopy(device.info)
    for ref in device.references:
        new_ref = ComponentReference(
            component=ref.parent,
            origin=ref.origin,
            rotation=ref.rotation,
            magnification=ref.magnification,
            x_reflection=ref.x_reflection,
        )
        new_ref.owner = component
        component.add(new_ref)
        for alias_name, alias_ref in device.aliases.items():
            if alias_ref == ref:
                component.aliases[alias_name] = new_ref

    for p in device.ports.values():
        component.add_port(port=Port(
            name=p.name,
            midpoint=p.midpoint,
            width=p.width,
            orientation=p.orientation,
            parent=p.parent,
        ))
    for poly in device.polygons:
        component.add_polygon(poly)
    for label in device.labels:
        component.add_label(
            text=label.text,
            position=label.position,
            layer=(label.layer, label.texttype),
        )
    return component
Exemplo n.º 25
0
        def _draw_ground_routing(self):

            if isinstance(self.probe, pc.GSGProbe):

                routing_cell = Device()

                routing_cell << self.gndlefttrace.draw()

                routing_cell << self.gndrighttrace.draw()

                return routing_cell

            else:

                raise ValueError("To be implemented")
Exemplo n.º 26
0
        def draw(self):

            cell=Device()

            cell.name=self.name

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

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

                self.pad.port=port

                pad_ref=cell.add_ref(self.pad.draw())

                pad_ref.connect(pad_ref.ports['conn'],
                    destination=port)

                cell.absorb(pad_ref)

                cell.add_port(port,name)

            return cell
Exemplo n.º 27
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.º 28
0
def auto_rename_ports_layer_orientation(
    component: Device,
    function=_rename_ports_facing_side,
    prefix: str = "",
) -> None:
    """Renames port names with layer_orientation  (1_0_W0)
    port orientation (E, N, W, S) numbering is clockwise

    .. code::

             N0  N1
             |___|_
        W1 -|      |- E1
            |      |
        W0 -|______|- E0
             |   |
            S0   S1

    """
    new_ports = {}
    ports = component.ports
    direction_ports = {x: [] for x in ["E", "N", "W", "S"]}
    layers = {port.layer for port in ports.values()}

    for layer in layers:
        ports_on_layer = [p for p in ports.values() if p.layer == layer]

        for p in ports_on_layer:
            p.name_original = p.name
            angle = p.orientation % 360
            if angle <= 45 or angle >= 315:
                direction_ports["E"].append(p)
            elif angle <= 135 and angle >= 45:
                direction_ports["N"].append(p)
            elif angle <= 225 and angle >= 135:
                direction_ports["W"].append(p)
            else:
                direction_ports["S"].append(p)

        function(direction_ports, prefix=f"{layer[0]}_{layer[1]}_")
        new_ports.update({p.name: p for p in ports_on_layer})

    component.ports = new_ports
Exemplo n.º 29
0
def attach_taper(cell : Device , port : Port , length : float , \
    width2 : float, layer=LayoutDefault.layerTop) :

    t = pg.taper(length=length, width1=port.width, width2=width2, layer=layer)

    t_ref = cell.add_ref(t)

    t_ref.connect(1, destination=port)

    new_port = t_ref.ports[2]

    new_port.name = port.name

    cell.absorb(t_ref)

    cell.remove(port)

    cell.add_port(new_port)
Exemplo n.º 30
0
def route_turn_manhattan(port1, port2, layer=0, radius=20):
    """
    Mahattan routing between two ports. If directions are not cardinal, adds a
    turn to make cardinal and then routes.
    
    Parameters
    ----------
    port1, port2: Port objects
        Ports to route to and from
    layer: int (default: 0)
        Layer to use for the routes
    radius: float (default: 20)
        Curve radius for bends
        
    Returns
    ----------
    Device object
    
    Notes
    ----------
    If direction is not cardinal, will route to nearest cardinal, then call
    route_manhattan.
    """

    D = Device()
    new_ports = []
    for port in (port1, port2):
        if port.orientation % 90 == 0:
            new_ports.append(port)
        else:
            turn_angle = get_turn_angle(port.orientation,
                                        to_cardinal(port.orientation))
            turn_route = turn(port,
                              radius=radius,
                              angle=turn_angle,
                              layer=layer)
            D.add_ref(turn_route)
            new_ports.append(turn_route.ports[2])

    #Manhattan on new ports
    route = route_manhattan(new_ports[0],
                            new_ports[1],
                            bendType='circular',
                            layer=layer,
                            radius=radius)

    D.add_ref(route)

    return D