Ejemplo n.º 1
0
def resistance_sheet(
    width: float = 10,
    length: float = 5.0,
    layers: Layers = (LAYER.SLAB90, LAYER.NPP),
    layer_offsets: Floats = (0, 0.2),
    pad: ComponentFactory = pad_contact_slab_npp,
) -> Component:
    """Sheet resistance.
    Ensures connectivity is kept for pads and the first layer in layers

    Args:
        width:
        length:
        layers: for the middle part
        layer_offsets:
        pad: function to create a pad
    """
    c = Component()

    pad = pad()
    pad1 = c << pad
    pad2 = c << pad
    r0 = c << compass(
        size=(length + layer_offsets[0], width + layer_offsets[0]),
        layer=layers[0])

    for layer, offset in zip(layers[1:], layer_offsets[1:]):
        c << compass(size=(length + offset, width + offset), layer=layer)

    pad1.connect("e3", r0.ports["e1"])
    pad2.connect("e1", r0.ports["e3"])
    return c
Ejemplo n.º 2
0
def pad(
    size: Tuple[float, float] = (100.0, 100.0),
    layer: Layer = LAYER.M3,
    layers_cladding: Optional[Tuple[Layer, ...]] = None,
    cladding_offsets: Optional[Tuple[float, ...]] = None,
) -> Component:
    """Rectangular pad with 4 ports (1, 2, 3, 4)

    Args:
        width: pad width
        height: pad height
        layer: pad layer
        layers_cladding:
        cladding_offsets:
    """
    c = Component()
    rect = compass(size=size, layer=layer)
    c_ref = c.add_ref(rect)
    c.add_ports(c_ref.ports)
    c.info.size = (float(size[0]), float(size[1]))
    c.info.layer = layer

    if layers_cladding and cladding_offsets:
        for layer, cladding_offset in zip(layers_cladding, cladding_offsets):
            c.add_ref(
                compass(
                    size=(size[0] + 2 * cladding_offset,
                          size[1] + 2 * cladding_offset),
                    layer=layer,
                ))

    return c
Ejemplo n.º 3
0
def contact(
    size: Tuple[float, float] = (11.0, 11.0),
    layers: Tuple[Layer, ...] = (LAYER.M1, LAYER.M2, LAYER.M3),
    vias: Optional[Tuple[Optional[ComponentOrFactory], ...]] = (via1, via2),
    layer_port: Optional[Layer] = None,
) -> Component:
    """Rectangular contact

    Args:
        size: of the layers
        layers: layers on which to draw rectangles
        vias: vias to use to fill the rectangles
        layer_port: if None asumes port is on the last layer
    """

    width, height = size
    a = width / 2
    b = height / 2
    layer_port = layer_port or layers[-1]

    c = Component()
    c.height = height
    c.info.size = (float(size[0]), float(size[1]))
    c.info.layer = layer_port

    for layer in layers:
        ref = c << compass(size=(width, height), layer=layer)

        if layer == layer_port:
            c.add_ports(ref.ports)

    vias = vias or []
    for via in vias:
        if via is not None:
            via = via() if callable(via) else via

            w, h = via.info["size"]
            g = via.info["enclosure"]
            pitch_x, pitch_y = via.info["spacing"]

            nb_vias_x = (width - w - 2 * g) / pitch_x + 1
            nb_vias_y = (height - h - 2 * g) / pitch_y + 1

            nb_vias_x = int(floor(nb_vias_x)) or 1
            nb_vias_y = int(floor(nb_vias_y)) or 1
            ref = c.add_array(
                via, columns=nb_vias_x, rows=nb_vias_y, spacing=(pitch_x, pitch_y)
            )

            cw = (width - (nb_vias_x - 1) * pitch_x - w) / 2
            ch = (height - (nb_vias_y - 1) * pitch_y - h) / 2
            x0 = -a + cw + w / 2
            y0 = -b + ch + h / 2
            ref.move((x0, y0))

    return c
Ejemplo n.º 4
0
def resistance_sheet(
    width: float = 10,
    layers: Layers = (LAYER.SLAB90, LAYER.NPP),
    layer_offsets: Floats = (0, 0.2),
    pad: ComponentFactory = pad_contact_slab_npp,
    pad_pitch: float = 100.0,
    ohms_per_square: Optional[float] = None,
) -> Component:
    """Sheet resistance.
    keeps connectivity for pads and first layer in layers

    Args:
        width:
        layers: for the middle part
        layer_offsets: from edge, positive: over, negative: inclusion
        pad: function to create a pad
        pad_pitch:
        ohms_per_square: optional sheet resistance to compute info.resistance
    """
    c = Component()

    pad = pad()
    length = pad_pitch - pad.info_child.size[0]

    pad1 = c << pad
    pad2 = c << pad
    r0 = c << compass(
        size=(length + layer_offsets[0], width + layer_offsets[0]), layer=layers[0]
    )

    for layer, offset in zip(layers[1:], layer_offsets[1:]):
        c << compass(size=(length + 2 * offset, width + 2 * offset), layer=layer)

    pad1.connect("e3", r0.ports["e1"])
    pad2.connect("e1", r0.ports["e3"])

    c.info_child.resistance = (
        ohms_per_square * width * length if ohms_per_square else None
    )

    c.add_port("pad1", port_type="vertical_dc", midpoint=pad1.center)
    c.add_port("pad2", port_type="vertical_dc", midpoint=pad2.center)
    return c
Ejemplo n.º 5
0
def _via_iterable(
    via_spacing: float,
    wire_width: float,
    layer1: Tuple[int, int],
    layer2: Tuple[int, int],
    via_layer: Tuple[int, int],
    via_width: float,
) -> Component:
    """Via"""
    c = gf.Component()
    wire1 = c.add_ref(compass(size=(via_spacing, wire_width), layer=layer1))
    wire2 = c.add_ref(compass(size=(via_spacing, wire_width), layer=layer2))
    viac = c.add_ref(compass(size=(via_width, via_width), layer=via_layer))
    via1 = c.add_ref(compass(size=(via_width, via_width), layer=via_layer))
    wire1.connect(port="e3", destination=wire2.ports["e1"], overlap=wire_width)
    viac.connect(port="e1",
                 destination=wire1.ports["e3"],
                 overlap=(wire_width + via_width) / 2)
    via1.connect(port="e1",
                 destination=wire2.ports["e3"],
                 overlap=(wire_width + via_width) / 2)
    c.add_port(name="e1", port=wire1.ports["e1"], port_type="electrical")
    c.add_port(name="e3", port=wire2.ports["e3"], port_type="electrical")
    c.add_port(
        name="e4",
        midpoint=[(1 * wire_width) + wire_width / 2, -wire_width / 2],
        width=wire_width,
        orientation=-90,
        port_type="electrical",
    )
    c.add_port(
        name="e2",
        midpoint=[(1 * wire_width) + wire_width / 2, wire_width / 2],
        width=wire_width,
        orientation=90,
        port_type="electrical",
    )

    return c
Ejemplo n.º 6
0
def rectangle(
    size: Tuple[float, float] = (4.0, 2.0),
    layer: Layer = (1, 0),
    centered: bool = False,
    port_type: str = "electrical",
) -> Component:
    """rectangle

    Args:
        size: (tuple) Width and height of rectangle.
        layer: Specific layer to put polygon geometry on.
        centered: True sets center to (0, 0), False sets south-west to (0, 0)
        port_type:

    """
    c = Component()
    ref = c << compass(size=size, layer=layer, port_type=port_type)
    if not centered:
        ref.move((size[0] / 2, size[1] / 2))
    c.add_ports(ref.ports)
    return c
Ejemplo n.º 7
0
def contact_slot(
    size: Float2 = (11.0, 11.0),
    layers: Layers = (LAYER.M1, LAYER.M2),
    layer_offsets: Optional[Floats] = (0, 1.0),
    layer_offsetsx: Optional[Floats] = None,
    layer_offsetsy: Optional[Floats] = None,
    layer_port: Optional[Layer] = None,
    via: ComponentOrFactory = via1,
    enclosure: float = 1.0,
    ysize: float = 0.5,
    yspacing: float = 2.0,
) -> Component:
    """Rectangular contact with slotted via in X direction

    Args:
        size: of the layers
        layers: layers on which to draw rectangles
        layer_offsets: cladding_offset for each layer
        layer_offsetsx: optional xoffset for layers, defaults to layer_offsets
        layer_offsetsx: optional yoffset for layers, defaults to layer_offsets
        layer_port: if None asumes port is on the last layer
        via: via to use to fill the rectangles
        enclosure: of the via by rectangle
        ysize: via height in y
        yspacing: via spacing pitch in y

    .. code::


         __________________________________________
        |                |                        |
        |                | layer_offsetsy[1]      |
        |  ______________|______________________  |
        |  |<--->                              |<>|
        |  |enclosure                          | layer_offsetsx[1]
        |  |      ______________________       |  |
        |  |     |                      |      |  |
        |  |     |     via              | ysize|  |
        |  |     |______________________|      |  |
        |  |  |                                |  |
        |  |  | yspacing                size[1]|  |
        |  |  |                                |  |
        |  |  |   ______________________       |  |
        |  |  |  |                      |      |  |
        |  |  |  |     via              | ysize|  |
        |  |  |  |______________________|      |  |
        |  |                                   |  |
        |  |                                   |  |
        |  |___________________________________|  |
        |                  size[0]                |
        |                                         |
        |_________________________________________|

    """
    if size[0] - 2 * enclosure < 0:
        raise ValueError(
            f"Contact length (size[0] = {size[0]}) < 2*enclosure ({2*enclosure}). "
        )
    if size[1] - 2 * enclosure < 0:
        raise ValueError(
            f"Contact width (size[1] = {size[1]}) < 2*enclosure ({2*enclosure}). "
        )

    layer_port = layer_port or layers[-1]

    c = Component()
    c.info.size = (float(size[0]), float(size[1]))

    layer_offsetsx = layer_offsetsx or layer_offsets
    layer_offsetsy = layer_offsetsy or layer_offsets

    layer_offsetsx = list(layer_offsetsx) + [0] * len(layers)
    layer_offsetsy = list(layer_offsetsy) + [0] * len(layers)

    for layer, offsetx, offsety in zip(layers, layer_offsetsx, layer_offsetsy):
        ref = c << compass(size=(size[0] + 2 * offsetx, size[1] + 2 * offsety),
                           layer=layer)

        if layer == layer_port:
            c.add_ports(ref.ports)

    via = via(size=(size[0] - 2 * enclosure, ysize)) if callable(via) else via

    nb_vias_y = (size[1] - 2 * enclosure) / yspacing
    nb_vias_y = int(floor(nb_vias_y)) or 1
    ref = c.add_array(via, columns=1, rows=nb_vias_y, spacing=(0, yspacing))
    dy = (size[1] - (nb_vias_y - 1) * yspacing - size[1]) / 2
    ref.move((0, dy))
    return c
Ejemplo n.º 8
0
def contact(
    size: Tuple[float, float] = (11.0, 11.0),
    layers: Tuple[Layer, ...] = (LAYER.M1, LAYER.M2, LAYER.M3),
    vias: Optional[Tuple[Optional[ComponentOrFactory], ...]] = (via1, via2),
    layer_port: Optional[Layer] = None,
) -> Component:
    """Rectangular via array stack

    You can use it to connect different metal layers or metals to silicon.
    You can use the naming convention contact_layerSource_layerDestination

    Via array / stack name is more common for contacting metal while
    contact is used for contacting silicon

    http://www.vlsi-expert.com/2017/12/vias.html

    Args:
        size: of the layers
        layers: layers on which to draw rectangles
        vias: vias to use to fill the rectangles
        layer_port: if None asumes port is on the last layer
    """

    width, height = size
    a = width / 2
    b = height / 2
    layer_port = layer_port or layers[-1]

    c = Component()
    c.height = height
    c.info.size = (float(size[0]), float(size[1]))
    c.info.layer = layer_port

    for layer in layers:
        ref = c << compass(size=(width, height), layer=layer)

        if layer == layer_port:
            c.add_ports(ref.ports)

    vias = vias or []
    for via in vias:
        if via is not None:
            via = via() if callable(via) else via

            w, h = via.info["size"]
            g = via.info["enclosure"]
            pitch_x, pitch_y = via.info["spacing"]

            nb_vias_x = (width - w - 2 * g) / pitch_x + 1
            nb_vias_y = (height - h - 2 * g) / pitch_y + 1

            nb_vias_x = int(floor(nb_vias_x)) or 1
            nb_vias_y = int(floor(nb_vias_y)) or 1
            ref = c.add_array(via,
                              columns=nb_vias_x,
                              rows=nb_vias_y,
                              spacing=(pitch_x, pitch_y))

            cw = (width - (nb_vias_x - 1) * pitch_x - w) / 2
            ch = (height - (nb_vias_y - 1) * pitch_y - h) / 2
            x0 = -a + cw + w / 2
            y0 = -b + ch + h / 2
            ref.move((x0, y0))

    return c
Ejemplo n.º 9
0
def contact_slot(
    size: Tuple[float, float] = (11.0, 11.0),
    layers: Tuple[Layer, ...] = (LAYER.M1, LAYER.M2),
    layer_offsets: Tuple[float, ...] = (0, 1.0),
    layer_port: Optional[Layer] = None,
    via: ComponentOrFactory = via1,
    enclosure: float = 1.0,
    ysize: float = 0.5,
    yspacing: float = 2.0,
) -> Component:
    """Rectangular contact with slotted via in X direction

    Args:
        size: of the layers
        layers: layers on which to draw rectangles
        layer_offsets: cladding_offset for each layer
        layer_port: if None asumes port is on the last layer
        via: via to use to fill the rectangles
        enclosure: of the via by rectangle
        ysize: via height in y
        yspacing: via spacing pitch in y

    .. code::

        enclosure
        _____________________________________
        |<--->                              |
        |      ______________________       |
        |     |                      |      |
        |     |                      | ysize|
        |     |______________________|      |
        |  |                                |
        |  | yspacing                       |
        |  |                                |
        |  |   ______________________       |
        |  |  |                      |      |
        |  |  |                      | ysize|
        |  |  |______________________|      |
        |                                   |
        |___________________________________|
                        size[0]


    """

    layer_port = layer_port or layers[-1]

    c = Component()

    for layer, offset in zip(layers, list(layer_offsets) + [0] * len(layers)):
        ref = c << compass(size=(size[0] + 2 * offset, size[1] + 2 * offset),
                           layer=layer)

        if layer == layer_port:
            c.add_ports(ref.ports)

    via = via(size=(size[0] - 2 * enclosure, ysize)) if callable(via) else via

    nb_vias_y = (size[1] - 2 * enclosure) / yspacing
    nb_vias_y = int(floor(nb_vias_y)) or 1
    ref = c.add_array(via, columns=1, rows=nb_vias_y, spacing=(0, yspacing))
    dy = (size[1] - (nb_vias_y - 1) * yspacing - size[1]) / 2
    ref.move((0, dy))
    return c