Example #1
0
        def draw(self):
            def mirror_label(str):

                if 'N_' in str:

                    return str.replace('N_', 'S_')

                if 'E_' in str:

                    return str.replace('E_', 'W_')

                if 'S_' in str:

                    return str.replace('S_', 'N_')

                if 'W_' in str:

                    return str.replace('W_', 'E_')

                return str

            cell = Device(name=self.name)

            probe_cell = super().draw()

            p1 = cell.add_ref(probe_cell, alias='Port1')

            p2 = cell.add_ref(probe_cell, alias='Port2')

            p2.rotate(center=(p1.x, p1.ymax), angle=180)

            p2.move(destination=self.offset.coord)

            for n, p in p1.ports.items():

                cell.add_port(port=p, name=n + '_1')

            for n, p in p2.ports.items():

                if 'LX' in n:

                    cell.add_port(port=p,
                                  name=mirror_label(n + '_2').replace(
                                      'LX', 'RX'))

                else:

                    if 'RX' in n:

                        cell.add_port(port=p,
                                      name=mirror_label(n + '_2').replace(
                                          'RX', 'LX'))

                    else:

                        cell.add_port(port=p, name=mirror_label(n + '_2'))

            return cell
Example #2
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
Example #3
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
Example #4
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")
Example #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"))
Example #6
0
        def draw(self):

            self._setup_routings()

            device_cell=cls.draw(self)

            probe_cell=self.probe.draw()

            cell=Device(name=self.name)

            cell.add_ref(device_cell, alias=self.name+"Device")

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

            self._move_probe_ref(probe_ref)

            cell.add_ref(self._draw_probe_routing(),alias=self.name+"GndTrace")

            return cell
Example #7
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
Example #8
0
        def draw(self):

            device_cell=cls.draw(self)

            cell=Device(name=self.name)

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

            self._setup_probe(device_ref)

            probe_cell=self.probe.draw()

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

            for tag in ('top','bottom'):

                self._add_signal_connection(cell,tag)

            self._move_probe_ref(cell)

            self._setup_ground_routing(device_ref,probe_ref,'side')

            routing_cell=self._draw_ground_routing()

            self._setup_signal_routing(cell)

            routing_cell.add(self._draw_device_grounds(device_ref,probe_ref,'side'))

            routing_cell.add(self._draw_ground_extensions(cell))

            cell.add_ref(routing_cell,alias="GroundTrace")

            routing_cell.add(self._draw_ground_extensions(cell))

            _add_default_ground_vias(self,routing_cell)

            routing_cell.add(self._draw_signal_routing())

            return cell
Example #9
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
Example #10
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
Example #11
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
Example #12
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)
Example #13
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
Example #14
0
def route_manhattan90(port1, port2, bendType='circular', layer=0, radius=20):
    #this is a subroutine of route_manhattan() and should not be used by itself.
    Total = Device()
    width = port1.width
    #first map into uniform plane with normal x,y coords
    #allows each situation to be put into uniform cases of quadrants for routing.
    #this is because bends change direction and positioning.
    if port1.orientation == 0:
        p2 = [port2.midpoint[0], port2.midpoint[1]]
        p1 = [port1.midpoint[0], port1.midpoint[1]]
    if port1.orientation == 90:
        p2 = [port2.midpoint[1], -port2.midpoint[0]]
        p1 = [port1.midpoint[1], -port1.midpoint[0]]
    if port1.orientation == 180:
        p2 = [-port2.midpoint[0], -port2.midpoint[1]]
        p1 = [-port1.midpoint[0], -port1.midpoint[1]]
    if port1.orientation == 270:
        p2 = [-port2.midpoint[1], port2.midpoint[0]]
        p1 = [-port1.midpoint[1], port1.midpoint[0]]

    #create placeholder ports based on the imaginary coordinates we created
    Total.add_port(name='t1', midpoint=[0, 0], orientation=0, width=width)

    #CHECK THIS

    #first quadrant target, route upward
    if (p2[1] > p1[1]) & (p2[0] > p1[0]):
        Total.add_port(name='t2',
                       midpoint=list(np.subtract(p2, p1)),
                       orientation=-90,
                       width=width)
        if bendType == 'circular':
            B1 = _arc(radius=radius,
                      width=width,
                      layer=layer,
                      angle_resolution=1,
                      start_angle=0,
                      theta=90)
            radiusEff = radius
        if bendType == 'gradual':
            B1 = _gradual_bend(radius=radius,
                               width=width,
                               layer=layer,
                               start_angle=0,
                               direction='ccw')
            radiusEff = B1.xsize - width / 2
        b1 = Total.add_ref(B1)
        b1.connect(port=b1.ports[1], destination=Total.ports['t1'])
        b1.move([p2[0] - p1[0] - radiusEff, 0])

        R1 = route_basic(port1=Total.ports['t1'],
                         port2=b1.ports[1],
                         layer=layer)
        R2 = route_basic(port1=b1.ports[2],
                         port2=Total.ports['t2'],
                         layer=layer)
        r1 = Total.add_ref(R1)
        r2 = Total.add_ref(R2)
        Total.add_port(name=1, port=r1.ports[1])
        Total.add_port(name=2, port=r2.ports[2])

    #fourth quadrant target, route downward
    if (p2[1] < p1[1]) & (p2[0] > p1[0]):
        Total.add_port(name='t2',
                       midpoint=list(np.subtract(p2, p1)),
                       orientation=90,
                       width=width)
        if bendType == 'circular':
            B1 = _arc(radius=radius,
                      width=width,
                      layer=layer,
                      angle_resolution=1,
                      start_angle=0,
                      theta=-90)
            radiusEff = radius
        if bendType == 'gradual':
            B1 = _gradual_bend(radius=radius,
                               width=width,
                               layer=layer,
                               start_angle=0,
                               direction='cw')
            radiusEff = B1.xsize - width / 2
        b1 = Total.add_ref(B1)
        b1.connect(port=b1.ports[1], destination=Total.ports['t1'])
        b1.move([p2[0] - p1[0] - radiusEff, 0])
        R1 = route_basic(port1=Total.ports['t1'],
                         port2=b1.ports[1],
                         layer=layer)
        R2 = route_basic(port1=b1.ports[2],
                         port2=Total.ports['t2'],
                         layer=layer)
        r1 = Total.add_ref(R1)
        r2 = Total.add_ref(R2)
        Total.add_port(name=1, port=r1.ports[1])
        Total.add_port(name=2, port=r2.ports[2])
    Total.rotate(angle=port1.orientation, center=p1)
    Total.move(origin=Total.ports['t1'], destination=port1)

    return Total
Example #15
0
def _gradual_bend(
    radius=20,
    width=1.0,
    angular_coverage=15,
    num_steps=10,
    angle_resolution=0.1,
    start_angle=0,
    direction='ccw',
    layer=0,
):
    """
    creates a 90-degree bent waveguide
    the bending radius is gradually increased until it reaches the minimum
    value of the radius at the "angular coverage" angle.
    it essentially creates a smooth transition to a bent waveguide mode.
    user can control number of steps provided.
    direction determined by start angle and cw or ccw switch
    ############
    with the default 10 "num_steps" and 15 degree coverage, effective radius is about 1.5*radius.
    """
    angular_coverage = np.deg2rad(angular_coverage)
    D = Device()

    #determines the increment in radius through its inverse from 0 to 1/r
    inc_rad = (radius**-1) / (num_steps)
    angle_step = angular_coverage / num_steps

    #construct a series of sub-arcs with equal angles but gradually decreasing bend radius
    arcs = []
    for x in xrange(num_steps):
        A = _arc(radius=1 / ((x + 1) * inc_rad),
                 width=width,
                 theta=np.rad2deg(angle_step),
                 start_angle=x * np.rad2deg(angle_step),
                 angle_resolution=angle_resolution,
                 layer=layer)
        a = D.add_ref(A)
        arcs.append(a)
        if x > 0:
            a.connect(port=1, destination=prevPort)
        prevPort = a.ports[2]
    D.add_port(name=1, port=arcs[0].ports[1])

    #now connect a regular bend for the normal curved portion
    B = _arc(radius=radius,
             width=width,
             theta=45 - np.rad2deg(angular_coverage),
             start_angle=angular_coverage,
             angle_resolution=angle_resolution,
             layer=layer)
    b = D.add_ref(B)
    b.connect(port=1, destination=prevPort)
    prevPort = b.ports[2]
    D.add_port(name=2, port=prevPort)

    #now create the overall structure
    Total = Device()

    #clone the half-curve into two objects and connect for a 90 deg bend.
    D1 = Total.add_ref(D)
    D2 = Total.add_ref(D)
    D2.reflect(p1=[0, 0], p2=[1, 1])
    D2.connect(port=2, destination=D1.ports[2])
    Total.xmin = 0
    Total.ymin = 0

    #orient to default settings...
    Total.reflect(p1=[0, 0], p2=[1, 1])
    Total.reflect(p1=[0, 0], p2=[1, 0])

    #orient to user-provided settings
    if direction == 'cw':
        Total.reflect(p1=[0, 0], p2=[1, 0])
    Total.rotate(angle=start_angle, center=Total.center)
    Total.center = [0, 0]
    Total.add_port(name=1, port=D1.ports[1])
    Total.add_port(name=2, port=D2.ports[1])

    return Total
Example #16
0
def route_manhattan180(port1, port2, bendType='circular', layer=0, radius=20):
    #this is a subroutine of route_manhattan() and should not be used by itself.
    Total = Device()
    width = port1.width
    #first map into uniform plane with normal x,y coords
    #allows each situation to be put into uniform cases of quadrants for routing.
    #this is because bends change direction and positioning.
    if port1.orientation == 0:
        p2 = [port2.midpoint[0], port2.midpoint[1]]
        p1 = [port1.midpoint[0], port1.midpoint[1]]
    if port1.orientation == 90:
        p2 = [port2.midpoint[1], -port2.midpoint[0]]
        p1 = [port1.midpoint[1], -port1.midpoint[0]]
    if port1.orientation == 180:
        p2 = [-port2.midpoint[0], -port2.midpoint[1]]
        p1 = [-port1.midpoint[0], -port1.midpoint[1]]
    if port1.orientation == 270:
        p2 = [-port2.midpoint[1], port2.midpoint[0]]
        p1 = [-port1.midpoint[1], port1.midpoint[0]]

    #create placeholder ports based on the imaginary coordinates we created
    Total.add_port(name='t1', midpoint=[0, 0], orientation=0, width=width)
    if (port1.orientation != port2.orientation):
        Total.add_port(name='t2',
                       midpoint=list(np.subtract(p2, p1)),
                       orientation=180,
                       width=width)
    else:
        Total.add_port(name='t2',
                       midpoint=list(np.subtract(p2, p1)),
                       orientation=0,
                       width=width)

    if port1.orientation == port2.orientation:
        #first quadrant target
        if (p2[1] > p1[1]) & (p2[0] > p1[0]):
            if bendType == 'circular':
                B1 = _arc(radius=radius,
                          width=width,
                          layer=layer,
                          angle_resolution=1,
                          start_angle=0,
                          theta=90)
                B2 = _arc(radius=radius,
                          width=width,
                          layer=layer,
                          angle_resolution=1,
                          start_angle=90,
                          theta=90)
                radiusEff = radius
            if bendType == 'gradual':
                B1 = _gradual_bend(radius=radius,
                                   width=width,
                                   layer=layer,
                                   start_angle=0,
                                   direction='ccw')
                B2 = _gradual_bend(radius=radius,
                                   width=width,
                                   layer=layer,
                                   start_angle=90,
                                   direction='ccw')
                radiusEff = B1.xsize - width / 2
            b1 = Total.add_ref(B1)
            b2 = Total.add_ref(B2)

            b1.connect(port=b1.ports[1], destination=Total.ports['t1'])
            b1.move([p2[0] - p1[0], 0])
            b2.connect(port=b2.ports[1], destination=b1.ports[2])
            b2.move([0, p2[1] - p1[1] - radiusEff * 2])
            R1 = route_basic(port1=Total.ports['t1'],
                             port2=b1.ports[1],
                             layer=layer)
            r1 = Total.add_ref(R1)
            R2 = route_basic(port1=b1.ports[2], port2=b2.ports[1], layer=layer)
            r2 = Total.add_ref(R2)
            Total.add_port(name=1, port=r1.ports[1])
            Total.add_port(name=2, port=b2.ports[2])
        #second quadrant target
        if (p2[1] > p1[1]) & (p2[0] < p1[0]):
            if bendType == 'circular':
                B1 = _arc(radius=radius,
                          width=width,
                          layer=layer,
                          angle_resolution=1,
                          start_angle=0,
                          theta=90)
                B2 = _arc(radius=radius,
                          width=width,
                          layer=layer,
                          angle_resolution=1,
                          start_angle=90,
                          theta=90)
                radiusEff = radius
            if bendType == 'gradual':
                B1 = _gradual_bend(radius=radius,
                                   width=width,
                                   layer=layer,
                                   start_angle=0,
                                   direction='ccw')
                B2 = _gradual_bend(radius=radius,
                                   width=width,
                                   layer=layer,
                                   start_angle=90,
                                   direction='ccw')
                radiusEff = B1.xsize - width / 2
            b1 = Total.add_ref(B1)
            b2 = Total.add_ref(B2)
            b1.connect(port=b1.ports[1], destination=Total.ports['t1'])

            b2.connect(port=b2.ports[1], destination=b1.ports[2])
            b2.move([0, p2[1] - p1[1] - radiusEff * 2])
            R1 = route_basic(port1=b1.ports[2], port2=b2.ports[1], layer=layer)
            r1 = Total.add_ref(R1)
            R2 = route_basic(port1=b2.ports[2],
                             port2=Total.ports['t2'],
                             layer=layer)
            r2 = Total.add_ref(R2)
            Total.add_port(name=1, port=b1.ports[1])
            Total.add_port(name=2, port=r2.ports[2])
        #third quadrant target
        if (p2[1] < p1[1]) & (p2[0] < p1[0]):
            if bendType == 'circular':
                B1 = _arc(radius=radius,
                          width=width,
                          layer=layer,
                          angle_resolution=1,
                          start_angle=0,
                          theta=-90)
                B2 = _arc(radius=radius,
                          width=width,
                          layer=layer,
                          angle_resolution=1,
                          start_angle=-90,
                          theta=-90)
                radiusEff = radius
            if bendType == 'gradual':
                B1 = _gradual_bend(radius=radius,
                                   width=width,
                                   layer=layer,
                                   start_angle=0,
                                   direction='cw')
                B2 = _gradual_bend(radius=radius,
                                   width=width,
                                   layer=layer,
                                   start_angle=-90,
                                   direction='cw')
                radiusEff = B1.xsize - width / 2
            b1 = Total.add_ref(B1)
            b2 = Total.add_ref(B2)
            b1.connect(port=b1.ports[1], destination=Total.ports['t1'])

            b2.connect(port=b2.ports[1], destination=b1.ports[2])
            b2.move([0, p2[1] - p1[1] + radiusEff * 2])
            R1 = route_basic(port1=b1.ports[2], port2=b2.ports[1], layer=layer)
            r1 = Total.add_ref(R1)
            R2 = route_basic(port1=b2.ports[2],
                             port2=Total.ports['t2'],
                             layer=layer)
            r2 = Total.add_ref(R2)
            Total.add_port(name=1, port=b1.ports[1])
            Total.add_port(name=2, port=r2.ports[2])
        #fourth quadrant target
        if (p2[1] < p1[1]) & (p2[0] > p1[0]):
            if bendType == 'circular':
                B1 = _arc(radius=radius,
                          width=width,
                          layer=layer,
                          angle_resolution=1,
                          start_angle=0,
                          theta=-90)
                B2 = _arc(radius=radius,
                          width=width,
                          layer=layer,
                          angle_resolution=1,
                          start_angle=-90,
                          theta=-90)
                radiusEff = radius
            if bendType == 'gradual':
                B1 = _gradual_bend(radius=radius,
                                   width=width,
                                   layer=layer,
                                   start_angle=0,
                                   direction='cw')
                B2 = _gradual_bend(radius=radius,
                                   width=width,
                                   layer=layer,
                                   start_angle=-90,
                                   direction='cw')
                radiusEff = B1.xsize - width / 2
            b1 = Total.add_ref(B1)
            b2 = Total.add_ref(B2)

            b1.connect(port=b1.ports[1], destination=Total.ports['t1'])
            b1.move([p2[0] - p1[0], 0])
            b2.connect(port=b2.ports[1], destination=b1.ports[2])
            b2.move([0, p2[1] - p1[1] + radiusEff * 2])
            R1 = route_basic(port1=Total.ports['t1'],
                             port2=b1.ports[1],
                             layer=layer)
            r1 = Total.add_ref(R1)
            R2 = route_basic(port1=b1.ports[2], port2=b2.ports[1], layer=layer)
            r2 = Total.add_ref(R2)
            Total.add_port(name=1, port=r1.ports[1])
            Total.add_port(name=2, port=b2.ports[2])

    #other port orientations are not supported:
    elif np.round(np.abs(np.mod(port1.orientation - port2.orientation, 360)),
                  3) != 180:
        raise ValueError(
            '[DEVICE] route() error: Ports do not face each other (orientations must be 180 apart)'
        )
    #otherwise, they are 180 degrees apart:
    else:
        #first quadrant target
        if (p2[1] > p1[1]) & (p2[0] > p1[0]):
            if bendType == 'circular':
                B1 = _arc(radius=radius,
                          width=width,
                          layer=layer,
                          angle_resolution=1,
                          start_angle=0,
                          theta=90)
                B2 = _arc(radius=radius,
                          width=width,
                          layer=layer,
                          angle_resolution=1,
                          start_angle=90,
                          theta=-90)
                radiusEff = radius
            if bendType == 'gradual':
                B1 = _gradual_bend(radius=radius,
                                   width=width,
                                   layer=layer,
                                   start_angle=0,
                                   direction='ccw')
                B2 = _gradual_bend(radius=radius,
                                   width=width,
                                   layer=layer,
                                   start_angle=90,
                                   direction='cw')
                radiusEff = B1.xsize - width / 2
            b1 = Total.add_ref(B1)
            b2 = Total.add_ref(B2)

            b1.connect(port=b1.ports[1], destination=Total.ports['t1'])
            b1.move([p2[0] - p1[0] - radiusEff * 2, 0])
            b2.connect(port=b2.ports[1], destination=b1.ports[2])
            b2.move([0, p2[1] - p1[1] - radiusEff * 2])
            R1 = route_basic(port1=Total.ports['t1'],
                             port2=b1.ports[1],
                             layer=layer)
            r1 = Total.add_ref(R1)
            R2 = route_basic(port1=b1.ports[2], port2=b2.ports[1], layer=layer)
            r2 = Total.add_ref(R2)
            Total.add_port(name=1, port=r1.ports[1])
            Total.add_port(name=2, port=b2.ports[2])
        #second quadrant target
        if (p2[1] > p1[1]) & (p2[0] < p1[0]):
            if bendType == 'circular':
                B1 = _arc(radius=radius,
                          width=width,
                          layer=layer,
                          angle_resolution=1,
                          start_angle=0,
                          theta=90)
                B2 = _arc(radius=radius,
                          width=width,
                          layer=layer,
                          angle_resolution=1,
                          start_angle=90,
                          theta=90)
                B3 = _arc(radius=radius,
                          width=width,
                          layer=layer,
                          angle_resolution=1,
                          start_angle=180,
                          theta=-90)
                B4 = _arc(radius=radius,
                          width=width,
                          layer=layer,
                          angle_resolution=1,
                          start_angle=90,
                          theta=-90)
                radiusEff = radius
            if bendType == 'gradual':
                B1 = _gradual_bend(radius=radius,
                                   width=width,
                                   layer=layer,
                                   start_angle=0,
                                   direction='ccw')
                B2 = _gradual_bend(radius=radius,
                                   width=width,
                                   layer=layer,
                                   start_angle=90,
                                   direction='ccw')
                B3 = _gradual_bend(radius=radius,
                                   width=width,
                                   layer=layer,
                                   start_angle=180,
                                   direction='cw')
                B4 = _gradual_bend(radius=radius,
                                   width=width,
                                   layer=layer,
                                   start_angle=90,
                                   direction='cw')
                radiusEff = B1.xsize - width / 2
            b1 = Total.add_ref(B1)
            b2 = Total.add_ref(B2)
            b3 = Total.add_ref(B3)
            b4 = Total.add_ref(B4)

            b1.connect(port=b1.ports[1], destination=Total.ports['t1'])

            b2.connect(port=b2.ports[1], destination=b1.ports[2])
            b2.move([0, p2[1] - p1[1] - radiusEff * 4])
            R1 = route_basic(port1=b1.ports[2], port2=b2.ports[1], layer=layer)
            r1 = Total.add_ref(R1)
            b3.connect(port=b3.ports[1], destination=b2.ports[2])
            b3.move([p2[0] - p1[0], 0])
            R2 = route_basic(port1=b2.ports[2], port2=b3.ports[1], layer=layer)
            r2 = Total.add_ref(R2)

            b4.connect(port=b4.ports[1], destination=b3.ports[2])

            Total.add_port(name=1, port=r1.ports[1])
            Total.add_port(name=2, port=b4.ports[2])
        #third quadrant target
        if (p2[1] < p1[1]) & (p2[0] < p1[0]):
            if bendType == 'circular':
                B1 = _arc(radius=radius,
                          width=width,
                          layer=layer,
                          angle_resolution=1,
                          start_angle=0,
                          theta=-90)
                B2 = _arc(radius=radius,
                          width=width,
                          layer=layer,
                          angle_resolution=1,
                          start_angle=-90,
                          theta=-90)
                B3 = _arc(radius=radius,
                          width=width,
                          layer=layer,
                          angle_resolution=1,
                          start_angle=-180,
                          theta=90)
                B4 = _arc(radius=radius,
                          width=width,
                          layer=layer,
                          angle_resolution=1,
                          start_angle=-90,
                          theta=90)
                radiusEff = radius
            if bendType == 'gradual':
                B1 = _gradual_bend(radius=radius,
                                   width=width,
                                   layer=layer,
                                   start_angle=0,
                                   direction='cw')
                B2 = _gradual_bend(radius=radius,
                                   width=width,
                                   layer=layer,
                                   start_angle=-90,
                                   direction='cw')
                B3 = _gradual_bend(radius=radius,
                                   width=width,
                                   layer=layer,
                                   start_angle=-180,
                                   direction='ccw')
                B4 = _gradual_bend(radius=radius,
                                   width=width,
                                   layer=layer,
                                   start_angle=-90,
                                   direction='ccw')
                radiusEff = B1.xsize - width / 2
            b1 = Total.add_ref(B1)
            b2 = Total.add_ref(B2)
            b3 = Total.add_ref(B3)
            b4 = Total.add_ref(B4)

            b1.connect(port=b1.ports[1], destination=Total.ports['t1'])

            b2.connect(port=b2.ports[1], destination=b1.ports[2])
            b2.move([0, p2[1] - p1[1] + radiusEff * 4])
            R1 = route_basic(port1=b1.ports[2], port2=b2.ports[1], layer=layer)
            r1 = Total.add_ref(R1)
            b3.connect(port=b3.ports[1], destination=b2.ports[2])
            b3.move([p2[0] - p1[0], 0])
            R2 = route_basic(port1=b2.ports[2], port2=b3.ports[1], layer=layer)
            r2 = Total.add_ref(R2)

            b4.connect(port=b4.ports[1], destination=b3.ports[2])

            Total.add_port(name=1, port=r1.ports[1])
            Total.add_port(name=2, port=b4.ports[2])
        #fourth quadrant target
        if (p2[1] < p1[1]) & (p2[0] > p1[0]):
            if bendType == 'circular':
                B1 = _arc(radius=radius,
                          width=width,
                          layer=layer,
                          angle_resolution=1,
                          start_angle=0,
                          theta=-90)
                B2 = _arc(radius=radius,
                          width=width,
                          layer=layer,
                          angle_resolution=1,
                          start_angle=-90,
                          theta=90)
                radiusEff = radius
            if bendType == 'gradual':
                B1 = _gradual_bend(radius=radius,
                                   width=width,
                                   layer=layer,
                                   start_angle=0,
                                   direction='cw')
                B2 = _gradual_bend(radius=radius,
                                   width=width,
                                   layer=layer,
                                   start_angle=-90,
                                   direction='ccw')
                radiusEff = B1.xsize - width / 2
            b1 = Total.add_ref(B1)
            b2 = Total.add_ref(B2)

            b1.connect(port=b1.ports[1], destination=Total.ports['t1'])
            b1.move([p2[0] - p1[0] - radiusEff * 2, 0])
            b2.connect(port=b2.ports[1], destination=b1.ports[2])
            b2.move([0, p2[1] - p1[1] + radiusEff * 2])
            R1 = route_basic(port1=Total.ports['t1'],
                             port2=b1.ports[1],
                             layer=layer)
            r1 = Total.add_ref(R1)
            R2 = route_basic(port1=b1.ports[2], port2=b2.ports[1], layer=layer)
            r2 = Total.add_ref(R2)
            Total.add_port(name=1, port=r1.ports[1])
            Total.add_port(name=2, port=b2.ports[2])

    Total.rotate(angle=port1.orientation, center=p1)
    Total.move(origin=Total.ports['t1'], destination=port1)
    return Total
Example #17
0
def route_manhattan(port1, port2, bendType='circular', layer=0, radius=20):
    #route along cardinal directions between any two ports placed diagonally
    #from each other

    Total = Device()
    width = port1.width
    #first map into uniform plane with normal x,y coords
    #allows each situation to be put into uniform cases of quadrants for routing.
    #this is because bends change direction and positioning.
    if port1.orientation == 0:
        p2 = [port2.midpoint[0], port2.midpoint[1]]
        p1 = [port1.midpoint[0], port1.midpoint[1]]
    if port1.orientation == 90:
        p2 = [port2.midpoint[1], -port2.midpoint[0]]
        p1 = [port1.midpoint[1], -port1.midpoint[0]]
    if port1.orientation == 180:
        p2 = [-port2.midpoint[0], -port2.midpoint[1]]
        p1 = [-port1.midpoint[0], -port1.midpoint[1]]
    if port1.orientation == 270:
        p2 = [-port2.midpoint[1], port2.midpoint[0]]
        p1 = [-port1.midpoint[1], port1.midpoint[0]]

    Total.add_port(name=1, port=port1)
    Total.add_port(name=2, port=port2)

    if p2[1] == p1[1] or p2[0] == p1[0]:
        raise ValueError('Error - ports must be at different x AND y values.')

    #if it is parallel or anti-parallel, route with 180 option
    if (np.round(np.abs(np.mod(port1.orientation - port2.orientation, 360)), 3)
            == 180) or (np.round(
                np.abs(np.mod(port1.orientation - port2.orientation, 360)), 3)
                        == 0):
        R1 = route_manhattan180(port1=port1,
                                port2=port2,
                                bendType=bendType,
                                layer=layer,
                                radius=radius)
        r1 = Total.add_ref(R1)

    else:
        #first quadrant case
        if (p2[1] > p1[1]) & (p2[0] > p1[0]):
            #simple 90 degree single-bend case
            if port2.orientation == port1.orientation - 90 or port2.orientation == port1.orientation + 270:
                R1 = route_manhattan90(port1=port1,
                                       port2=port2,
                                       bendType=bendType,
                                       layer=layer,
                                       radius=radius)
                r1 = Total.add_ref(R1)
            elif port2.orientation == port1.orientation + 90 or port2.orientation == port1.orientation - 270:
                if bendType == 'circular':
                    B1 = _arc(radius=radius,
                              width=width,
                              layer=layer,
                              angle_resolution=1,
                              start_angle=port1.orientation,
                              theta=90)
                    radiusEff = radius
                if bendType == 'gradual':
                    B1 = _gradual_bend(radius=radius,
                                       width=width,
                                       layer=layer,
                                       start_angle=port1.orientation,
                                       direction='ccw')
                    radiusEff = B1.xsize - width / 2
                b1 = Total.add_ref(B1)
                b1.connect(port=1, destination=port1)

                R1 = route_manhattan180(port1=b1.ports[2],
                                        port2=port2,
                                        bendType=bendType,
                                        layer=layer,
                                        radius=radius)
                r1 = Total.add_ref(R1)
        #second quadrant case
        if (p2[1] > p1[1]) & (p2[0] < p1[0]):
            if np.abs(port1.orientation - port2.orientation) == 90 or np.abs(
                    port1.orientation - port2.orientation) == 270:
                if bendType == 'circular':
                    B1 = _arc(radius=radius,
                              width=width,
                              layer=layer,
                              angle_resolution=1,
                              start_angle=port1.orientation,
                              theta=90)
                    radiusEff = radius
                if bendType == 'gradual':
                    B1 = _gradual_bend(radius=radius,
                                       width=width,
                                       layer=layer,
                                       start_angle=port1.orientation,
                                       direction='ccw')
                    radiusEff = B1.xsize - width / 2
                b1 = Total.add_ref(B1)
                b1.connect(port=1, destination=port1)
                R1 = route_manhattan180(port1=b1.ports[2],
                                        port2=port2,
                                        bendType=bendType,
                                        layer=layer,
                                        radius=radius)
                r1 = Total.add_ref(R1)
        #third quadrant case
        if (p2[1] < p1[1]) & (p2[0] < p1[0]):
            if np.abs(port1.orientation - port2.orientation) == 90 or np.abs(
                    port1.orientation - port2.orientation) == 270:
                if bendType == 'circular':
                    B1 = _arc(radius=radius,
                              width=width,
                              layer=layer,
                              angle_resolution=1,
                              start_angle=port1.orientation,
                              theta=-90)
                    radiusEff = radius
                if bendType == 'gradual':
                    B1 = _gradual_bend(radius=radius,
                                       width=width,
                                       layer=layer,
                                       start_angle=port1.orientation,
                                       direction='cw')
                    radiusEff = B1.xsize - width / 2
                b1 = Total.add_ref(B1)
                b1.connect(port=1, destination=port1)
                R1 = route_manhattan180(port1=b1.ports[2],
                                        port2=port2,
                                        bendType=bendType,
                                        layer=layer,
                                        radius=radius)
                r1 = Total.add_ref(R1)
        #fourth quadrant case
        if (p2[1] < p1[1]) & (p2[0] > p1[0]):
            #simple 90 degree single-bend case
            if port2.orientation == port1.orientation + 90 or port2.orientation == port1.orientation - 270:
                R1 = route_manhattan90(port1=port1,
                                       port2=port2,
                                       bendType=bendType,
                                       layer=layer,
                                       radius=radius)
                r1 = Total.add_ref(R1)
            elif port2.orientation == port1.orientation - 90 or port2.orientation == port1.orientation + 270:
                if bendType == 'circular':
                    B1 = _arc(radius=radius,
                              width=width,
                              layer=layer,
                              angle_resolution=1,
                              start_angle=port1.orientation,
                              theta=-90)
                    radiusEff = radius
                if bendType == 'gradual':
                    B1 = _gradual_bend(radius=radius,
                                       width=width,
                                       layer=layer,
                                       start_angle=port1.orientation,
                                       direction='cw')
                    radiusEff = B1.xsize - width / 2
                b1 = Total.add_ref(B1)
                b1.connect(port=1, destination=port1)
                R1 = route_manhattan180(port1=b1.ports[2],
                                        port2=port2,
                                        bendType=bendType,
                                        layer=layer,
                                        radius=radius)
                r1 = Total.add_ref(R1)
    return Total
Example #18
0
    def draw(self):

        self._set_relations()

        idt_cell = self.idt.draw()

        cell = Device(self.name)

        idt_ref = cell.add_ref(idt_cell, alias="IDT")

        idt_top_port = idt_ref.ports['top']

        idt_bottom_port = idt_ref.ports['bottom']

        bus_cell = self.bus.draw()

        bus_ref = cell.add_ref(bus_cell, alias="BUS")

        bus_ref.connect(port=bus_cell.ports['conn'],\
        destination=idt_bottom_port)

        etch_cell = self.etchpit.draw()

        etch_ref = cell.add_ref(etch_cell, alias='EtchPit')

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

        anchor_cell = self.anchor.draw()

        anchor_bottom = cell.add_ref(anchor_cell, alias='AnchorBottom')

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

        if not self._stretch_top_margin:

            anchor_top = cell.add_ref(anchor_cell, alias='AnchorTop')

        else:

            anchor_top_dev = deepcopy(self.anchor)

            anchor_top_dev.metalized = Point(anchor_top_dev.size.x - 2,
                                             anchor_top_dev.metalized.y)

            anchor_top = cell.add_ref(anchor_top_dev.draw(), alias='AnchorTop')

            del anchor_top_dev

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

        outport_top = anchor_top.ports['conn']

        outport_bottom = anchor_bottom.ports['conn']

        outport_top.name = 'top'
        outport_top.orientation = 90
        outport_bottom.name = 'bottom'
        outport_bottom.orientation = -90

        outport_top.midpoint=(\
            outport_top.x,\
            outport_top.y+self.anchor.metalized.y)
        outport_bottom.midpoint=(\
            outport_bottom.x,\
            outport_bottom.y-self.anchor.metalized.y)

        cell.add_port(outport_top)
        cell.add_port(outport_bottom)

        del idt_cell, bus_cell, etch_cell, anchor_cell

        return cell
Example #19
0
    def draw(self):

        cell = Device()

        cell.name = self.name

        supercell = LFERes.draw(self)

        super_ref = cell.add_ref(supercell)

        if self.plate_position == 'out, short':

            plate=pg.rectangle(size=(self.etchpit.active_area.x+8*self.idt.active_area_margin,self.idt.length-self.idt.y_offset/2),\
            layer=self.platelayer)

            plate_ref = cell.add_ref(plate, alias='Plate')

            transl_rel=Point(self.etchpit.x-4*self.idt.active_area_margin,self.anchor.size.y+2*self.anchor.etch_margin.y+self.bus.size.y\
                +self.idt.y_offset*3/4)

            lr_cell = get_corners(cell)[0]
            lr_plate = get_corners(plate_ref)[0]

            plate_ref.move(origin=lr_plate.coord,\
            destination=(lr_plate+lr_cell+transl_rel).coord)

            cell.absorb(plate_ref)

            del plate

        elif self.plate_position == 'in, short':

            plate=pg.rectangle(\
                size=(\
                    self.etchpit.active_area.x-\
                        2*self.idt.active_area_margin,\
                        self.idt.length-self.idt.y_offset/2),\
                layer=self.platelayer)

            plate_ref = cell.add_ref(plate, alias='Plate')

            transl_rel=Point(self.etchpit.x+\
                    self.idt.active_area_margin,\
                self.anchor.size.y+\
                2*self.anchor.etch_margin.y+\
                self.bus.size.y+\
                self.idt.y_offset*3/4)

            lr_cell = get_corners(cell)[0]
            lr_plate = get_corners(plate_ref)[0]

            plate_ref.move(origin=lr_plate.coord,\
            destination=(lr_plate+lr_cell+transl_rel).coord)

            cell.absorb(plate_ref)

            del plate

        elif self.plate_position == 'out, long':

            plate=pg.rectangle(\
                size=(self.etchpit.active_area.x+\
                        8*self.idt.active_area_margin,\
                    self.idt.length+\
                        2*self.bus.size.y+\
                        self.idt.y_offset),\
                layer=self.platelayer)

            plate_ref = cell.add_ref(plate, alias='Plate')

            transl_rel=Point(self.etchpit.x-\
                4*self.idt.active_area_margin,\
                    self.anchor.size.y+2*self.anchor.etch_margin.y)

            lr_cell = get_corners(cell)[0]
            lr_plate = get_corners(plate_ref)[0]

            plate_ref.move(origin=lr_plate.coord,\
            destination=(lr_plate+lr_cell+transl_rel).coord)

            cell.absorb(plate_ref)

            del plate

        elif self.plate_position == 'in, long':

            plate=pg.rectangle(\
                size=(\
                    self.etchpit.active_area.x-\
                        2*self.idt.active_area_margin,\
                        self.idt.length+\
                            2*self.bus.size.y+\
                            self.idt.y_offset),
                layer=self.platelayer)

            plate_ref = cell.add_ref(plate, alias='Plate')

            transl_rel=Point(self.etchpit.x+\
                    self.idt.active_area_margin,\
                        self.anchor.size.y+2*self.anchor.etch_margin.y)

            lr_cell = get_corners(cell)[0]
            lr_plate = get_corners(plate_ref)[0]

            plate_ref.move(origin=lr_plate.coord,\
            destination=(lr_plate+lr_cell+transl_rel).coord)

            cell.absorb(plate_ref)

            del plate

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

            cell.add_port(port, name)

        return cell
Example #20
0
def text(text='abcd', size=10, justify='left', layer=0, font="DEPLOF"):
    """ Creates geometries of text

    Parameters
    ----------
    text : str
        Text string to be written.
    size : int or float
        Size of the text
    justify : {'left', 'right', 'center'}
        Justification of the text.
    layer : int, array-like[2], or set
        Specific layer(s) to put polygon geometry on.
    font: str
        Font face to use. Default DEPLOF does not require additional libraries, otherwise
        freetype will be used to load fonts. Font can be given either by name (e.g. "Times New Roman"),
        or by file path. OTF or TTF fonts are supported.

    Returns
    -------
    t : Device
        A Device containing the text geometry.
    """
    t = Device('text')
    xoffset = 0
    yoffset = 0

    face = font
    if face == "DEPLOF":
        scaling = size / 1000

        for line in text.split('\n'):
            l = Device(name='textline')
            for c in line:
                ascii_val = ord(c)
                if c == ' ':
                    xoffset += 500 * scaling
                elif (33 <= ascii_val <= 126) or (ascii_val == 181):
                    for poly in _glyph[ascii_val]:
                        xpts = np.array(poly)[:, 0] * scaling
                        ypts = np.array(poly)[:, 1] * scaling
                        l.add_polygon([xpts + xoffset, ypts + yoffset],
                                      layer=layer)
                    xoffset += (_width[ascii_val] +
                                _indent[ascii_val]) * scaling
                else:
                    valid_chars = '!"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~ยต'
                    warnings.warn('[PHIDL] text(): Warning, some characters ignored, no geometry for character "%s" with ascii value %s. ' \
                                  'Valid characters: %s' % (chr(ascii_val), ascii_val, valid_chars))
            t.add_ref(l)
            yoffset -= 1500 * scaling
            xoffset = 0
    else:
        from .font import _get_font_by_name, _get_font_by_file, _get_glyph

        # Load the font
        # If we've passed a valid file, try to load that, otherwise search system fonts
        font = None
        if (face.endswith(".otf")
                or face.endswith(".ttf")) and os.path.exists(face):
            font = _get_font_by_file(face)
        else:
            try:
                font = _get_font_by_name(face)
            except ValueError:
                pass
        if font is None:
            raise ValueError((
                '[PHIDL] Failed to find font: "%s". ' +
                'Try specifying the exact (full) path to the .ttf or .otf file. '
                +
                'Otherwise, it might be resolved by rebuilding the matplotlib font cache'
            ) % (face))

        # Render each character
        for line in text.split('\n'):
            l = Device('textline')
            xoffset = 0
            for letter in line:
                letter_dev = Device("letter")
                letter_template, advance_x = _get_glyph(font, letter)
                for poly in letter_template.polygons:
                    letter_dev.add_polygon(poly.polygons, layer=layer)
                ref = l.add_ref(letter_dev)
                ref.move(destination=(xoffset, 0))
                ref.magnification = size
                xoffset += size * advance_x

            ref = t.add_ref(l)
            ref.move(destination=(0, yoffset))
            yoffset -= size

    justify = justify.lower()
    for l in t.references:
        if justify == 'left': pass
        if justify == 'right': l.xmax = 0
        if justify == 'center':
            l.move(origin=l.center, destination=(0, 0), axis='x')

    t.flatten()
    return t