Esempio n. 1
0
class Resistor(spira.PCell):

    width = spira.NumberParameter(default=spira.RDD.R1.MIN_WIDTH, doc='Width of the shunt resistance.')
    length = spira.NumberParameter(default=spira.RDD.R1.MIN_LENGTH, doc='Length of the shunt resistance.')

    p1 = spira.Parameter(fdef_name='create_p1')
    p2 = spira.Parameter(fdef_name='create_p2')

    def validate_parameters(self):
        if self.width > self.length:
            raise ValueError('`Width` cannot be larger than `length`.')
        return True

    def create_p1(self):
        return spira.Port(name='P1', midpoint=(-self.length/2,0), orientation=180, width=self.width, process=spira.RDD.PROCESS.R1)

    def create_p2(self):
        return spira.Port(name='P2', midpoint=(self.length/2,2), orientation=0, width=self.width, process=spira.RDD.PROCESS.R1)

    def create_elements(self, elems):
        elems += spira.RouteManhattan(ports=[self.p1, self.p2], layer=spira.RDD.PLAYER.R1.METAL)
        return elems

    def create_ports(self, ports):
        ports += [self.p1, self.p2]
        return ports
Esempio n. 2
0
class BoschVia(spira.Device):

    __name_prefix__ = 'Bosch_Standard'

    radius = spira.NumberParameter(default=RDD.B0.MIN_SIZE)

    m0_radius = spira.Parameter(
        fdef_name='create_m0_radius',
        doc='Radius of the ground layer around the via.')
    al_radius = spira.Parameter(
        fdef_name='create_al_radius',
        doc='Radius of the aluminum layer around the via.')

    def create_m0_radius(self):
        return (self.radius + 2 * RDD.Al.B0_MIN_SURROUND)

    def create_al_radius(self):
        return (self.radius + 2 * RDD.Al.B0_MIN_SURROUND)

    def create_elements(self, elems):
        elems += spira.Circle(box_size=(self.radius, self.radius),
                              layer=RDD.PLAYER.B0.VIA)
        elems += spira.Circle(box_size=(self.m0_radius, self.m0_radius),
                              layer=RDD.PLAYER.M0.METAL)
        elems += spira.Circle(box_size=(self.al_radius, self.al_radius),
                              layer=RDD.PLAYER.Al.METAL)
        return elems

    def create_ports(self, ports):

        return ports
Esempio n. 3
0
class HorizontalConnections(spira.Cell):

    ref_point = spira.Parameter(fdef_name='create_ref_point')

    def create_ref_point(self):
        return spira.Rectangle(p1=(-2.5, -2.5),
                               p2=(2.5, 2.5),
                               layer=spira.Layer(number=1))

    def get_ports(self):
        p1 = spira.Port(name='P1_M1',
                        midpoint=(50, 0),
                        orientation=135,
                        width=10)
        return [p1]

    def create_elements(self, elems):
        elems += self.ref_point
        pc = ProcessLayer()
        T = spira.Rotation(0)
        S = spira.SRef(pc, midpoint=(10, 0), transformation=T)
        p1 = self.get_ports()[0]
        S.connect(port=S.ports[0], destination=p1)
        elems += S
        return elems

    def create_ports(self, ports):
        ports += self.get_ports()
        return ports
Esempio n. 4
0
class HorizontalAlignment(spira.Cell):

    ref_point = spira.Parameter(fdef_name='create_ref_point')

    def create_ref_point(self):
        return spira.Rectangle(p1=(-2.5, -2.5),
                               p2=(2.5, 2.5),
                               layer=spira.Layer(number=1))

    def get_ports(self):
        p1 = spira.Port(name='P1_M1',
                        midpoint=(50, 0),
                        orientation=330,
                        width=10)
        return [p1]

    def create_elements(self, elems):
        elems += self.ref_point
        pc = ProcessLayer()
        S = spira.SRef(pc, midpoint=(0, 0))
        p1 = self.get_ports()[0]
        S.distance_alignment(port=pc.ports[0], destination=p1, distance=20)
        elems += S
        return elems

    def create_ports(self, ports):
        ports += self.get_ports()
        return ports
Esempio n. 5
0
class RotationReference(spira.Cell):

    ref_point = spira.Parameter(fdef_name='create_ref_point')
    t1 = spira.Parameter(fdef_name='create_t1')
    t2 = spira.Parameter(fdef_name='create_t2')
    t3 = spira.Parameter(fdef_name='create_t3')

    def create_ref_point(self):
        ply = spira.Rectangle(p1=(-2.5, -2.5),
                              p2=(2.5, 2.5),
                              layer=spira.Layer(number=1))
        return ply

    def create_t1(self):
        cell = spira.Cell()
        cell += spira.Rectangle(p1=(0, 0),
                                p2=(10, 50),
                                layer=spira.Layer(number=2))
        T = spira.Rotation(-30)
        S = spira.SRef(cell, transformation=T)
        return S

    def create_t2(self):
        cell = spira.Cell()
        cell += spira.Rectangle(p1=(0, 0),
                                p2=(10, 50),
                                layer=spira.Layer(number=3))
        T = spira.GenericTransform(rotation=-60)
        S = spira.SRef(cell, transformation=T)
        return S

    def create_t3(self):
        cell = spira.Cell()
        cell += spira.Rectangle(p1=(0, 0),
                                p2=(10, 50),
                                layer=spira.Layer(number=4))
        S = spira.SRef(cell)
        S.rotate(-90)
        return S

    def create_elements(self, elems):
        elems += self.ref_point
        elems += self.t1
        elems += self.t2
        elems += self.t3
        return elems
Esempio n. 6
0
class ProcessLayer(spira.Cell):

    ref_point = spira.Parameter(fdef_name='create_ref_point')
    t1 = spira.Parameter(fdef_name='create_t1')

    width = spira.NumberParameter(default=10)
    length = spira.NumberParameter(default=50)

    def get_transforms(self):
        # T = spira.Translation(Coord(10, 0)) + spira.Rotation(rotation=60)
        T = spira.Translation(Coord(10, 0))
        T += spira.Rotation(rotation=20)
        return T

    def create_ref_point(self):
        return spira.Rectangle(p1=(-2.5, -2.5),
                               p2=(2.5, 2.5),
                               layer=spira.Layer(number=1))

    def create_t1(self):
        T = self.get_transforms()
        ply = spira.Rectangle(p1=(0, 0),
                              p2=(self.width, self.length),
                              layer=spira.Layer(number=2))
        ply.transform(transformation=T)
        return ply

    def create_elements(self, elems):
        # elems += self.ref_point
        elems += self.t1
        return elems

    def create_ports(self, ports):
        T = self.get_transforms()
        p1 = spira.Port(name='P1_M1',
                        midpoint=(self.width / 2, 0),
                        orientation=-90,
                        width=self.width)
        p2 = spira.Port(name='P2_M1',
                        midpoint=(self.width / 2, self.length),
                        orientation=90,
                        width=self.width)
        ports += p1.transform_copy(T)
        ports += p2.transform_copy(T)
        return ports
Esempio n. 7
0
class TransformPolygon(spira.Cell):

    ref_point = spira.Parameter(fdef_name='create_ref_point')
    t1 = spira.Parameter(fdef_name='create_t1')
    t2 = spira.Parameter(fdef_name='create_t2')
    t3 = spira.Parameter(fdef_name='create_t3')

    def create_ref_point(self):
        return spira.Rectangle(p1=(-2.5, -2.5),
                               p2=(2.5, 2.5),
                               layer=spira.Layer(number=1))

    def create_t1(self):
        T = spira.Rotation(30) + spira.Translation(Coord(10, 0))
        ply = spira.Rectangle(p1=(0, 0),
                              p2=(10, 50),
                              layer=spira.Layer(number=2))
        ply.transform(transformation=T)
        return ply

    def create_t2(self):
        T = spira.GenericTransform(translation=(20, 0), rotation=60)
        ply = spira.Rectangle(p1=(0, 0),
                              p2=(10, 50),
                              layer=spira.Layer(number=3),
                              transformation=T)
        return ply

    def create_t3(self):
        ply = spira.Rectangle(p1=(0, 0),
                              p2=(10, 50),
                              layer=spira.Layer(number=4))
        ply.translate((30, 0))
        ply.rotate(90)
        # FIXME: Reflection is not working.
        ply.reflect(True)
        return ply

    def create_elements(self, elems):
        elems += self.ref_point
        elems += self.t1
        elems += self.t2
        elems += self.t3
        return elems
Esempio n. 8
0
class YtronCircuit(spira.Circuit):

    ytron = spira.Parameter(fdef_name='create_ytron')

    @spira.cache()
    def get_io_ports(self):
        p1 = spira.Port(name='P1_M1', midpoint=(-10, 10), orientation=0)
        p2 = spira.Port(name='P2_M1',
                        midpoint=(5, 10),
                        width=0.5,
                        orientation=270)
        p3 = spira.Port(name='P3_M1',
                        midpoint=(0, -10),
                        width=1,
                        orientation=90)
        return [p1, p2, p3]

    def create_ytron(self):
        shape = YtronShape(rho=0.5, theta=5)
        D = YtronDevice(shape=shape)
        return spira.SRef(alias='ytron', reference=D)

    def create_elements(self, elems):
        p1, p2, p3 = self.get_io_ports()

        elems += self.ytron

        # R = spira.RouteManhattan(
        elems += spira.RouteManhattan(ports=[self.ytron.ports['Pl_M1'], p1],
                                      width=self.ytron.ref.shape.arm_widths[0],
                                      layer=RDD.PLAYER.M1.METAL,
                                      corners=self.corners)

        # print(R[0].layer)
        # R[0].set(layer=RDD.PLAYER.M2.METAL)
        # print(R[0].layer)

        # elems += R

        elems += spira.RouteStraight(p1=p2,
                                     p2=self.ytron.ports['Pr_M1'],
                                     layer=RDD.PLAYER.M1.METAL,
                                     path_type='sine',
                                     width_type='sine')

        elems += spira.RouteStraight(p1=p3,
                                     p2=self.ytron.ports['Psrc_M1'],
                                     layer=RDD.PLAYER.M1.METAL,
                                     path_type='sine',
                                     width_type='sine')

        return elems

    def create_ports(self, ports):
        ports += self.get_io_ports()
        return ports
Esempio n. 9
0
class ResistorExtended(Resistor):

    p3 = spira.Parameter(fdef_name='create_p3')

    def create_p3(self):
        return spira.Port(name='P3', midpoint=(self.length,0), orientation=90, width=self.width, process=spira.RDD.PROCESS.R1)

    def create_elements(self, elems):
        elems = super().create_elements(elems)
        elems += spira.RouteManhattan(ports=[self.p2, self.p3], corners='round', layer=spira.RDD.PLAYER.R1.METAL)
        return elems
Esempio n. 10
0
class TranslatePolygon(spira.Cell):

    ref_point = spira.Parameter(fdef_name='create_ref_point')
    t1 = spira.Parameter(fdef_name='create_t1')
    t2 = spira.Parameter(fdef_name='create_t2')
    t3 = spira.Parameter(fdef_name='create_t3')

    def create_ref_point(self):
        return spira.Rectangle(p1=(-2.5, -2.5),
                               p2=(2.5, 2.5),
                               layer=spira.Layer(number=1))

    def create_t1(self):
        T = spira.Translation(Coord(-10, 0))
        ply = spira.Rectangle(p1=(0, 0),
                              p2=(10, 50),
                              layer=spira.Layer(number=2))
        ply.transform(T)
        return ply

    def create_t2(self):
        tf = spira.GenericTransform(translation=Coord(-22, 0))
        ply = spira.Rectangle(p1=(0, 0),
                              p2=(10, 50),
                              layer=spira.Layer(number=3),
                              transformation=tf)
        return ply

    def create_t3(self):
        ply = spira.Rectangle(p1=(0, 0),
                              p2=(10, 50),
                              layer=spira.Layer(number=4))
        ply.translate((-34, 0))
        return ply

    def create_elements(self, elems):
        elems += self.ref_point
        elems += self.t1
        elems += self.t2
        elems += self.t3
        return elems
Esempio n. 11
0
class ReflectPolygon(spira.Cell):

    ref_point = spira.Parameter(fdef_name='create_ref_point')
    t1 = spira.Parameter(fdef_name='create_t1')
    t2 = spira.Parameter(fdef_name='create_t2')
    t3 = spira.Parameter(fdef_name='create_t3')

    def create_ref_point(self):
        return spira.Rectangle(p1=(-2.5, -2.5),
                               p2=(2.5, 2.5),
                               layer=spira.Layer(number=1))

    def create_t1(self):
        T = spira.Reflection(True)
        ply = spira.Rectangle(p1=(0, 0),
                              p2=(10, 50),
                              layer=spira.Layer(number=2))
        ply.transform(T)
        return ply

    def create_t2(self):
        T = spira.GenericTransform(reflection=True)
        ply = spira.Rectangle(p1=(0, 0),
                              p2=(10, 50),
                              layer=spira.Layer(number=3),
                              transformation=T)
        return ply

    def create_t3(self):
        ply = spira.Rectangle(p1=(0, 0),
                              p2=(10, 50),
                              layer=spira.Layer(number=4))
        ply.reflect(True)
        return ply

    def create_elements(self, elems):
        elems += self.ref_point
        elems += self.t1
        elems += self.t2
        elems += self.t3
        return elems
Esempio n. 12
0
class RouteExample(spira.Cell):

    layer = spira.LayerParameter(default=spira.RDD.PLAYER.M1.METAL, doc='Layer to be used when creating the route object.')

    p1 = spira.Parameter(fdef_name='create_p1')
    p2 = spira.Parameter(fdef_name='create_p2')
    
    def create_p1(self):
        return spira.Port(name='P1', midpoint=(0,0), orientation=180, process=self.layer.process)

    def create_p2(self):
        return spira.Port(name='P2', midpoint=(20,10), orientation=0, process=self.layer.process)
 
    def create_elements(self, elems):
        elems += spira.RouteManhattan(ports=[self.p1, self.p2], layer=self.layer)
        return elems

    def create_ports(self, ports):
        ports += self.p1
        ports += self.p2
        return ports
Esempio n. 13
0
class TsvCircuit(spira.Circuit):
    """ Test circuit created for TSV fabrication. """

    d2 = spira.Parameter(fdef_name='create_d2')

    def create_d2(self):
        return spira.Port(name='Al:D2',
                          midpoint=(-1000, -5000),
                          orientation=0,
                          width=20)

    def create_elements(self, elems):

        r1 = Row()

        s1 = spira.SRef(r1)
        # s2 = spira.SRef(r1, midpoint=(2000, -1000))
        s2 = spira.SRef(r1, transformation=spira.Translation((2000, -1000)))

        elems += s1
        elems += s2

        print(s1.ports['Al:T2'])
        print(s2.ports['Al:T2'])

        d1 = spira.Port(name='Al:D1',
                        midpoint=(1000, 7000),
                        orientation=180,
                        width=20)
        # d2 = spira.Port(name='Al:D2', midpoint=(-1000, -5000), orientation=0, width=20)

        elems += spira.RouteManhattan(
            ports=[s1.ports['Al:T2'], d1, s2.ports['Al:T2']],
            width=20,
            layer=RDD.PLAYER.Al.METAL)

        elems += spira.RouteManhattan(ports=[s1.ports['Al:T1'], self.d2],
                                      width=20,
                                      layer=RDD.PLAYER.Al.METAL)

        return elems

    def create_ports(self, ports):

        print(self.elements)

        ports += self.d2

        return ports
Esempio n. 14
0
class PolygonCell(spira.Cell):

    res = spira.Parameter(fdef_name='create_res')
    
    def create_res(self):
        res = ResistorCell()
        s = spira.SRef(reference=res)
        return s

    def create_elements(self, elems):
        # elems += spira.SRef(reference=ResistorCell())
        elems += self.res
        elems += spira.Rectangle(alias='M3', p1=(-10, -15), p2=(10, 15), layer=RDD.PLAYER.M3.METAL)
        return elems

    def create_ports(self, ports):
        ports += self.res.ports['E0_M2'].copy(name='P0_M2')
        ports += self.res.ports['E2_M2'].copy(name='P1_M2')
        return ports
Esempio n. 15
0
class Layer(spira.ParameterInitializer):
    number = spira.Parameter(default=0, restriction=spira.RestrictRange(2, 5))
Esempio n. 16
0
class Layer(spira.ParameterInitializer):
    number = spira.Parameter(default=0, preprocess=spira.ProcessorInt())
Esempio n. 17
0
class VirtualConnect(__VirtualModel__):
    """  """

    derived_edges = spira.DictParameter(fdef_name='create_derived_edges')
    derived_contacts = spira.Parameter(fdef_name='create_derived_contacts')
    attached_contacts = spira.Parameter(fdef_name='create_attached_contacts')

    def create_derived_contacts(self):
        """  """

        mapping = {}
        for k in RDD.VIAS.keys:
            mapping[RDD.PLAYER[k].
                    CLAYER_CONTACT] = RDD.VIAS[k].LAYER_STACK['VIA_LAYER']
            mapping[
                RDD.PLAYER[k].CLAYER_M1] = RDD.VIAS[k].LAYER_STACK['BOT_LAYER']
            mapping[
                RDD.PLAYER[k].CLAYER_M2] = RDD.VIAS[k].LAYER_STACK['TOP_LAYER']

        return get_derived_elements(elements=deepcopy(self.device).elements,
                                    mapping=mapping)

    def create_derived_edges(self):
        """ Detect connecting and overlapping layer edges. Returns
        the derived merged polygons and derived intersection edges. """

        purposes = [
            RDD.PURPOSE.METAL, RDD.PURPOSE.DEVICE_METAL,
            RDD.PURPOSE.CIRCUIT_METAL
        ]
        EF = filters.EdgeShapeFilter(edge_type=constants.EDGE_TYPE_OUTSIDE,
                                     width=0.3,
                                     purposes=purposes)
        edge_elems = EF(self.device).elements

        mapping = self._derived_edges_mapping()
        derived_edges = get_derived_elements(elements=edge_elems,
                                             mapping=mapping,
                                             store_as_edge=True)

        overlap_edges = {}
        self._connect_overlap_edges(self.device, derived_edges, overlap_edges)
        self._connect_boundary_edges(self.device, derived_edges, overlap_edges)

        return overlap_edges

    def _derived_edges_mapping(self):
        """ Map the derived edge layers in the RDD to a physical layer. """
        mapping = {}
        purposes = ['METAL', 'DEVICE_METAL', 'CIRCUIT_METAL']
        for pl in RDD.get_physical_layers_by_purpose(purposes=purposes):
            key = pl.process.symbol
            if hasattr(RDD.PLAYER[key], 'EDGE_CONNECTED'):
                derived_layer = RDD.PLAYER[key].EDGE_CONNECTED
                ps_1 = derived_layer.layer1.process.symbol
                ps_2 = derived_layer.layer2.process.symbol
                if ps_1 == ps_2:
                    mapping[derived_layer] = RDD.PLAYER[
                        key].OUTSIDE_EDGE_DISABLED
                else:
                    es = "Error in RDD: Edge process \'{}\' not the same as metal process \'{}\'."
                    raise ValueError(es.format(ps_2, ps_1))
            else:
                LOG.warning(
                    'Edge detection for METAL layer {} ignored.'.format(key))
        return mapping

    def _connect_overlap_edges(self, D, derived_edges, overlap_edges):
        """ Connect edges to the overlapping polygon. """
        for j, e in enumerate(D.derived_overlap_elements):
            overlap_edges[e] = []
            for i, edge in enumerate(derived_edges):
                if len(edge.shape.intersections(e.shape)) != 0:
                    edge.external_pid = e.id_string()
                    edge.layer.purpose = RDD.PURPOSE.PORT.OUTSIDE_EDGE_ENABLED
                    overlap_edges[e].append(edge)
        return overlap_edges

    def _connect_boundary_edges(self, D, derived_edges, overlap_edges):
        """ Connect the edges that falls on a shape boudnary,
        since there is no overlapping polygon in this case. """
        for i, edge in enumerate(derived_edges):
            if edge.layer.purpose == RDD.PURPOSE.PORT.OUTSIDE_EDGE_DISABLED:
                c_edge = deepcopy(edge)
                edge.external_pid = edge.id_string()
                edge.layer.purpose = RDD.PURPOSE.PORT.OUTSIDE_EDGE_ENABLED
                overlap_edges[c_edge] = [edge]

    def view_virtual_connect(self, show_layers=False, write=False, **kwargs):
        """ View that contains all derived connections (attached contacts, derived edges). """

        elems = spira.ElementList()

        if show_layers is True:
            el = self.derived_contacts
            F = filters.PurposeFilterAllow(purposes=['JJ', 'VIA'])
            elems += F(el)
            elems += self.device.elements
        else:
            elems += self.derived_contacts

        for ply_overlap, edges in self.derived_edges.items():
            if ply_overlap.is_empty() is False:
                for e in edges:
                    EF = filters.EdgeToPolygonFilter()
                    elems += EF(e)
                if not isinstance(ply_overlap, spira.Edge):
                    elems += ply_overlap

        name = self.device.name + '_VConnect'
        D = spira.Cell(name=name,
                       elements=elems,
                       ports=self.device.ports,
                       transformation=self.device.transformation)
        D.gdsii_view()
        if write is True:
            D.gdsii_output(file_name=name)

    def view_derived_contacts(self, show_layers=False, **kwargs):

        elems = spira.ElementList()

        # if show_layers is True:
        #     elems += self.device.elements

        # el = self.derived_contacts
        # F = filters.PurposeFilterAllow(purposes=['JJ', 'VIA'])
        # elems += F(el)

        el = self.derived_contacts

        elems += el

        D = spira.Cell(name='_DERIVED_CONTACTS', elements=elems)
        D.gdsii_view()

    def view_derived_edges(self, show_layers=False, **kwargs):

        elems = spira.ElementList()

        if show_layers is True:
            elems += self.device.elements

        for ply_overlap, edges in self.derived_edges.items():
            if ply_overlap.is_empty() is False:
                for e in edges:
                    EF = filters.EdgeToPolygonFilter()
                    elems += EF(e)

        D = spira.Cell(name='_DERIVED_EDGES', elements=elems)
        D.gdsii_view()
Esempio n. 18
0
class TsvLayout(spira.Circuit):
    """ Basic 2 TSV bosch via layout. """

    width = spira.NumberParameter(default=1000)
    length = spira.NumberParameter(default=2000)

    # width = spira.NumberParameter(
    #     default=RDD.R5.MIN_SIZE,
    #     restriction=spira.RestrictRange(lower=RDD.R5.MIN_SIZE),
    #     doc='Width of the shunt resistance.')

    via = spira.CellParameter(default=BoschVia,
                              restriction=spira.RestrictType([BoschVia]),
                              doc='TSV component for connecting M0 to Al.')

    via_left = spira.Parameter(fdef_name='create_via_left')
    via_right = spira.Parameter(fdef_name='create_via_right')

    p1 = spira.Parameter(fdef_name='create_p1')
    p2 = spira.Parameter(fdef_name='create_p2')
    p1_out = spira.Parameter(fdef_name='create_p1_out')

    def validate_parameters(self):
        if self.length < self.width:
            raise ValueError('Length cannot be less than width.')
        return True

    def create_p1(self):
        return spira.Port(name='Al:T1',
                          midpoint=(-2000, 0),
                          orientation=0,
                          width=20)

    def create_p2(self):
        return spira.Port(name='Al:T2',
                          midpoint=(2000, 0),
                          orientation=180,
                          width=20)

    def create_p1_out(self):
        return spira.Port(name='M0:T4',
                          midpoint=(0, 500),
                          orientation=270,
                          width=20)

    def create_via_left(self):
        via = self.via()
        return spira.SRef(via, midpoint=(-1000, 0))

    def create_via_right(self):
        via = self.via()
        return spira.SRef(via, midpoint=(1000, 0))

    def create_elements(self, elems):
        elems += [self.via_left, self.via_right]

        d1 = spira.Port(name='Al:D1',
                        midpoint=(-1000, 0),
                        orientation=180,
                        width=20)
        d11 = spira.Port(name='M0:D3',
                         midpoint=(-1000, 0),
                         orientation=0,
                         width=20)
        d2 = spira.Port(name='Al:D2',
                        midpoint=(1000, 0),
                        orientation=0,
                        width=20)
        d12 = spira.Port(name='M0:D4',
                         midpoint=(1000, 0),
                         orientation=180,
                         width=20)
        d3 = spira.Port(name='M0:D5',
                        midpoint=(0, 0),
                        orientation=90,
                        width=20)

        # FIXME: Throughs out with a wierd angle.
        # elems += spira.RouteManhattan(
        #     ports=[self.p1, d1],
        #     width=5, layer=RDD.PLAYER.Al.METAL)

        elems += spira.RouteStraight(p1=self.p1,
                                     p2=d1,
                                     layer=RDD.PLAYER.Al.METAL)
        elems += spira.RouteStraight(p1=d11, p2=d12, layer=RDD.PLAYER.M0.METAL)
        elems += spira.RouteStraight(p1=self.p2,
                                     p2=d2,
                                     layer=RDD.PLAYER.Al.METAL)
        elems += spira.RouteStraight(p1=self.p1_out,
                                     p2=d3,
                                     layer=RDD.PLAYER.M0.METAL)

        return elems

    def create_ports(self, ports):

        return ports
class Layer(spira.ParameterInitializer):
    number = spira.Parameter(default=0,
                             restrictions=spira.INTEGER,
                             preprocess=spira.ProcessorInt(),
                             doc='Advanced parameter.')
Esempio n. 20
0
class TransformReference(spira.Cell):

    ref_point = spira.Parameter(fdef_name='create_ref_point')
    t1 = spira.Parameter(fdef_name='create_t1')
    t2 = spira.Parameter(fdef_name='create_t2')
    t3 = spira.Parameter(fdef_name='create_t3')

    def create_ref_point(self):
        ply = spira.Rectangle(p1=(-2.5, -2.5),
                              p2=(2.5, 2.5),
                              layer=spira.Layer(number=1))
        return ply

    def create_t1(self):
        cell = spira.Cell()
        cell += spira.Rectangle(p1=(0, 0),
                                p2=(10, 50),
                                layer=spira.Layer(number=2))

        S1 = spira.SRef(cell)
        S1.rotate(rotation=45)
        S1.translate(Coord(15, 15))

        S = spira.SRef(cell)
        S.rotate(rotation=45)
        S.translate(Coord(15, 15))
        S.reflect(True)

        return [S1, S]

    def create_t2(self):
        cell = spira.Cell()
        tf_1 = spira.GenericTransform(translation=(10, 10), rotation=45)
        tf_2 = spira.GenericTransform(translation=Coord(10, 10),
                                      rotation=45,
                                      reflection=True)
        cell += spira.Rectangle(p1=(0, 0),
                                p2=(10, 50),
                                layer=spira.Layer(number=3))
        S1 = spira.SRef(cell, transformation=tf_1)
        S2 = spira.SRef(cell, transformation=tf_2)
        return [S1, S2]

    def create_t3(self):
        cell = spira.Cell()
        tf_1 = spira.Translation(Coord(12.5, 2.5)) + spira.Rotation(60)
        tf_2 = spira.Translation(Coord(
            12.5, 2.5)) + spira.Rotation(60) + spira.Reflection(True)
        cell += spira.Rectangle(p1=(0, 0),
                                p2=(10, 50),
                                layer=spira.Layer(number=4))
        S1 = spira.SRef(cell, transformation=tf_1)
        S2 = spira.SRef(cell, transformation=tf_2)
        return [S1, S2]

    def create_elements(self, elems):
        elems += self.ref_point
        # elems += self.t1
        # elems += self.t2
        elems += self.t3
        return elems
Esempio n. 21
0
class __VirtualModel__(ParameterInitializer):

    device = spira.CellParameter(
        doc='The device from which a virtual model will be constructed.')
    geometry = spira.Parameter(fdef_name='create_geometry')
    process_flow = spira.VModelProcessFlowParameter()
Esempio n. 22
0
class VirtualConnect(__VirtualModel__):

    # FIXME: Add a string list restriction.
    connect_type = spira.StringParameter(default='contact_layer')
    connected_edges = spira.DictParameter(fdef_name='create_connected_edges')
    connected_elements = spira.Parameter(fdef_name='create_connected_elements')

    def __make_polygons__(self):

        elems = spira.ElementList()
        if self.connect_type == 'contact_layer':

            mapping = {}
            for k in RDD.VIAS.keys:
                mapping[RDD.PLAYER[k].
                        CLAYER_CONTACT] = RDD.VIAS[k].LAYER_STACK['VIA_LAYER']
                mapping[RDD.PLAYER[k].
                        CLAYER_M1] = RDD.VIAS[k].LAYER_STACK['BOT_LAYER']
                mapping[RDD.PLAYER[k].
                        CLAYER_M2] = RDD.VIAS[k].LAYER_STACK['TOP_LAYER']

            # print('\nMapping:')
            # for k, v in mapping.items():
            #     print(k, v)
            # print('')
            # print(self.device.elements)

            el = get_derived_elements(elements=self.device.elements,
                                      mapping=mapping)
            for e in el:
                if e.purpose == 'METAL':
                    pass
                else:
                    elems += e
        else:
            pass
            # # D = self.device.expand_flat_copy()
            # D = self.device.expand_flat_no_jjcopy()

            # elems = spira.ElementList()
            # for process in RDD.VMODEL.PROCESS_FLOW.active_processes:
            #     for layer in RDD.get_physical_layers_by_process(processes=process):
            #         LF = LayerFilterAllow(layers=[layer])
            #         el = LF(D.elements.polygons)
            #         elems += spira.PolygonGroup(elements=el, layer=layer).intersect
        return elems

    def create_connected_elements(self):
        """ Adds contact ports to each metal polygon connected by a 
        contact layer and return a list of the updated elements. """
        for e1 in self.__make_polygons__():
            for e2 in self.device.elements:
                for m in ['BOT_LAYER', 'TOP_LAYER']:
                    if e2.layer == RDD.VIAS[e1.process].LAYER_STACK[m]:
                        if e2.encloses(e1.center):
                            e2.ports += spira.Port(name=e1.process,
                                                   midpoint=e1.center,
                                                   process=e1.layer.process,
                                                   purpose=e1.layer.purpose,
                                                   port_type='contact')
        return self.device.elements

    def _map_derived_edges(self):
        mapping = {}
        for pl in RDD.get_physical_layers_by_purpose(purposes=['METAL']):
            key = pl.process.symbol
            if hasattr(RDD.PLAYER[key], 'EDGE_CONNECTED'):
                derived_layer = RDD.PLAYER[key].EDGE_CONNECTED
                ps_1 = derived_layer.layer1.process.symbol
                ps_2 = derived_layer.layer2.process.symbol
                if ps_1 == ps_2:
                    mapping[derived_layer] = RDD.PLAYER[
                        key].OUTSIDE_EDGE_DISABLED
                else:
                    es = "Error in RDD: Edge process \'{}\' not the same as metal process \'{}\'."
                    raise ValueError(es.format(ps_2, ps_1))
            else:
                LOG.warning(
                    'Edge detection for METAL layer {} ignored.'.format(key))
        return mapping

    def _connect_overlap_edges(self, D, edges, overlap_edges):
        """ Connect edges to the overlapping polygon. """
        for j, e in enumerate(D.overlap_elements):
            overlap_edges[e] = []
            for i, edge in enumerate(edges):
                if len(edge.shape.intersections(e.shape)) != 0:
                    edge.pid = '{}'.format(e.shape.hash_string)
                    edge.layer.purpose = RDD.PURPOSE.PORT.OUTSIDE_EDGE_ENABLED
                    overlap_edges[e].append(edge)
        return overlap_edges

    def _connect_boundary_edges(self, edges, overlap_edges):
        """ Connect the edges that falls on a shape boudnary,
        since there is no overlapping polygon in this case."""
        if len(edges) > 0:
            e = spira.Polygon(alias='Dummy', shape=[], layer=RDD.PLAYER.METAL)
            overlap_edges[e] = []
            for i, edge in enumerate(edges):
                if edge.layer.purpose == RDD.PURPOSE.PORT.OUTSIDE_EDGE_DISABLED:
                    edge.pid = '{}'.format(e.shape.hash_string)
                    edge.layer.purpose = RDD.PURPOSE.PORT.OUTSIDE_EDGE_ENABLED
                    overlap_edges[e].append(edge)

    def create_connected_edges(self):
        from spira.yevon.gdsii.elem_list import ElementList
        from spira.yevon.vmodel.derived import get_derived_elements

        EF = filters.EdgeFilter(edge_type=constants.EDGE_TYPE_OUTSIDE)
        el = EF(self.device).elements

        mapping = self._map_derived_edges()
        edges = get_derived_elements(el, mapping=mapping, store_as_edge=True)

        overlap_edges = {}
        self._connect_overlap_edges(self.device, edges, overlap_edges)
        self._connect_boundary_edges(edges, overlap_edges)

        return overlap_edges

    def gdsii_output_virtual_connect(self, **kwargs):

        elems = spira.ElementList()

        # for e in self.__make_polygons__():
        #     elems += e

        for ply_overlap, edges in self.connected_edges.items():
            if len(ply_overlap.points) > 0:
                elems += ply_overlap
            elems += edges

        for e in self.device.elements:
            elems += e

        D = spira.Cell(name='_VIRTUAL_CONNECT', elements=elems)
        D.gdsii_output()
class Layer(spira.ParameterInitializer):
    number = spira.Parameter()