Ejemplo n.º 1
0
    def produce(self, layout, layers, parameters, cell):

        # coerce parameters (make consistent)

        self._layers = layers
        self.cell = cell
        self._param_values = parameters
        self.layout = layout

        # cell: layout cell to place the layout
        # LayerSiN: which layer to use
        # r: radius
        # w: waveguide width
        # length units in dbu

        from math import pi, cos, sin
        from SiEPIC.utils import arc_wg, arc_wg_xy
        from SiEPIC._globals import PIN_LENGTH
        from SiEPIC.utils.layout import layout_waveguide2
        from SiEPIC.extend import to_itype

        # fetch the parameters
        TECHNOLOGY = get_technology_by_name('EBeam')
        dbu = self.layout.dbu
        ly = self.layout

        LayerSiN = ly.layer(self.silayer)
        LayerSlab = ly.layer(self.slayer)
        #    LayerNN = ly.layer(self.nlayer)
        LayerNPPN = ly.layer(self.npplayer)
        LayerVCN = ly.layer(self.vclayer)
        LayerMN = ly.layer(self.mlayer)
        LayerPinRecN = ly.layer(self.pinrec)
        LayerDevRecN = ly.layer(self.devrec)
        TextLayerN = ly.layer(self.textl)

        ## define parameters for phase shifter
        overlay = to_itype(self.overlay, dbu)
        overlay_ebl = to_itype(self.overlay_ebl, dbu)

        ## define waveguide related parameters
        radius_um, adiab, bezier = 5, 1, 0.2
        w = to_itype(self.width, dbu)  #waveguide width, default 0.5 um
        l = to_itype(self.length, dbu)  #pahse shifter length, default 150 um
        npp_d = to_itype(self.npp_distance,
                         dbu)  #npp to center waveguide distance
        sw = (npp_d + w / 2) * 2  #twice of npp_d that is defined above
        in_rib = to_itype(
            self.input_rib_width, dbu
        )  #the slab width of the input/output waveguide to the phase shifter
        in_taper = to_itype(
            self.in_taper_length, dbu
        )  #the input waveguide to phase shifter dimension transfer taper length, default 15
        edge_slab_width = to_itype(
            4, dbu
        )  #width of the 90 nm slab that is outside of all the folding waveguide, default 2 * 2um
        npp_width = to_itype(self.npp_width, dbu)  #npp width, default 5 um

        ## define waveguide folding parameters
        folding_n = int(round((self.fold_number - 1) /
                              2))  # folding waveguide number on one side
        folding_w1 = w + 50  # one of the folding waveguide width
        folding_w2 = w - 50  # the other one of the folding waveguide width
        folding_gap = to_itype(2, dbu)  # the gap between two folding waveguide
        routing_step = to_itype(
            radius_um,
            dbu)  # define how large the U shape should be, default 20

        ## define node related parameters
        contact_size = to_itype(self.vc_w,
                                dbu)  # square NPP size, for VC purpose
        pin_text_size = to_itype(0.4, dbu)  # pin text size

        metal_routing_distance_to_node = to_itype(
            30, dbu)  # *** calculate from PCell parameters ***
        metal_routing_width = to_itype(self.m_w, dbu)  # width of metal
        vc_to_npp_exclusion = to_itype(
            self.overlay, dbu)  # VC boundary to NPP boundary distance

        ps_sl_w = sw + 2 * contact_size + folding_n * 2 * (
            w + folding_gap + overlay_ebl
        )  # overall pahse shifter 90nm slab width

        # measure the total length of the waveguides
        total_waveguide_length = 0

        ## define strip to slab transfer taper parameters
        N = 100
        # Number of points for the input/output slab taper
        order = 3
        # input/output slab taper curve

        pts = [Point(-l / 2, 0), Point(l / 2, 0)]
        total_waveguide_length += layout_waveguide2(TECHNOLOGY, self.layout,
                                                    self.cell, ['Si'],
                                                    [w * dbu], [0], pts,
                                                    radius_um, adiab, bezier)

        wg2 = pya.Box(-l / 2, -ps_sl_w / 2, l / 2, ps_sl_w / 2)
        wg3 = pya.Box(-l / 2, npp_d + w / 2, l / 2, npp_d + w / 2 + npp_width)
        wg4 = pya.Box(-l / 2, -npp_d - w / 2, l / 2,
                      -npp_d - w / 2 - npp_width)

        self.cell.shapes(LayerNPPN).insert(wg3)
        self.cell.shapes(LayerNPPN).insert(wg4)

        if self.io_wg_type:
            in_slab = to_itype(self.input_slab_width, dbu)
        else:
            in_slab = in_rib

        if folding_n > 0:
            ps_sl_w = contact_size * 2 + sw * 2 + (
                folding_w1 + folding_w2 +
                folding_gap * 2) * folding_n + edge_slab_width
            wg2 = pya.Box(-l / 2, -ps_sl_w / 2, l / 2, ps_sl_w / 2)
            self.cell.shapes(LayerSlab).insert(wg2)

            pts = [
                Point(-l / 2 - in_taper, -w / 2),
                Point(-l / 2, -w / 2),
                Point(-l / 2, w / 2),
                Point(-l / 2 - in_taper, w / 2)
            ]  # fix waveguide width mismatch for left center input taper
            self.cell.shapes(LayerSiN).insert(Polygon(pts))

            # add input slab taper
            pts = []
            for i in range(0, N + 1):
                pts.append(
                    Point(
                        -l / 2 - in_taper + in_taper / N * i,
                        w / 2 + ((sw / 2 + contact_size - w) /
                                 (N**order)) * (i**order)))
            for i in range(0, N + 1):
                pts.append(
                    Point(
                        -l / 2 - in_taper + in_taper / N * (N - i),
                        -w / 2 - ((sw / 2 + contact_size - w) /
                                  (N**order)) * ((N - i)**order)))
            self.cell.shapes(LayerSlab).insert(Polygon(pts))

            # add output strip taper
            pts = [
                Point(l / 2 + in_taper, -w / 2),
                Point(l / 2, -w / 2),
                Point(l / 2, w / 2),
                Point(l / 2 + in_taper, w / 2)
            ]
            #wg2 = pya.Box(-l/2,-4/2/dbu,l/2,4/2/dbu)
            self.cell.shapes(LayerSiN).insert(Polygon(pts))
            total_waveguide_length += in_taper * dbu

            # add input slab taper
            pts = []
            for i in range(0, N + 1):
                pts.append(
                    Point(l / 2 + in_taper - in_taper / N * i,
                          (w - overlay_ebl) / 2 + ((sw / 2 + contact_size -
                                                    (w - overlay_ebl)) /
                                                   (N**order)) * (i**order)))
            for i in range(0, N + 1):
                pts.append(
                    Point(
                        l / 2 + in_taper / N * i, -(w - overlay_ebl) / 2 -
                        ((sw / 2 + contact_size - (w - overlay_ebl)) /
                         (N**order)) * ((N - i)**order)))
            self.cell.shapes(LayerSlab).insert(Polygon(pts))

            for i in range(0, folding_n):
                y_coordinate = contact_size + sw + 2 * vc_to_npp_exclusion  # move up/down the position according to vc_to_npp_exclusion
                y_move = i * (folding_w1 + folding_w2 +
                              folding_gap * 2) / 2 + y_coordinate
                if i % 2:
                    folding_w = folding_w2
                else:
                    folding_w = folding_w1

                # waveguide in the heated region
                pts = [Point(-l / 2, y_move), Point(l / 2, y_move)]
                total_waveguide_length += layout_waveguide2(
                    TECHNOLOGY, self.layout, self.cell, ['Si'],
                    [folding_w * dbu], [0], pts, radius_um, adiab, bezier)
                pts = [Point(-l / 2, -y_move), Point(l / 2, -y_move)]
                total_waveguide_length += layout_waveguide2(
                    TECHNOLOGY, self.layout, self.cell, ['Si'],
                    [folding_w * dbu], [0], pts, radius_um, adiab, bezier)

                # add upper left input taper
                pts = [
                    Point(-l / 2 - in_taper, -w / 2 + y_move),
                    Point(-l / 2, -folding_w / 2 + y_move),
                    Point(-l / 2, folding_w / 2 + y_move),
                    Point(-l / 2 - in_taper, w / 2 + y_move)
                ]
                #wg2 = pya.Box(-l/2,-4/2/dbu,l/2,4/2/dbu)
                self.cell.shapes(LayerSiN).insert(Polygon(pts))
                total_waveguide_length += in_taper * dbu

                # slab cubic taper
                pts = []
                for ii in range(0, N + 1):
                    pts.append(
                        Point(-l / 2 - in_taper + in_taper / N * ii,
                              (w - overlay_ebl) / 2 +
                              ((2 / dbu - (w - overlay_ebl)) /
                               (N**order)) * (ii**order) + y_move))
                for ii in range(0, N + 1):
                    pts.append(
                        Point(
                            -l / 2 - in_taper + in_taper / N * (N - ii),
                            -(w - overlay_ebl) / 2 -
                            ((2 / dbu - (w - overlay_ebl)) /
                             (N**order)) * ((N - ii)**order) + y_move))
                self.cell.shapes(LayerSlab).insert(Polygon(pts))

                if (i != folding_n - 1):
                    # add below left taper
                    y_move = -y_move
                    pts = [
                        Point(-l / 2 - in_taper, -w / 2 + y_move),
                        Point(-l / 2, -folding_w / 2 + y_move),
                        Point(-l / 2, folding_w / 2 + y_move),
                        Point(-l / 2 - in_taper, w / 2 + y_move)
                    ]
                    #wg2 = pya.Box(-l/2,-4/2/dbu,l/2,4/2/dbu)
                    self.cell.shapes(LayerSiN).insert(Polygon(pts))
                    total_waveguide_length += in_taper * dbu

                    # slab cubic taper
                    pts = []
                    for ii in range(0, N + 1):
                        pts.append(
                            Point(-l / 2 - in_taper + in_taper / N * ii,
                                  (w - overlay_ebl) / 2 +
                                  ((2 / dbu - (w - overlay_ebl)) /
                                   (N**order)) * (ii**order) + y_move))
                    for ii in range(0, N + 1):
                        pts.append(
                            Point(
                                -l / 2 - in_taper + in_taper / N * (N - ii),
                                -(w - overlay_ebl) / 2 -
                                ((2 / dbu - (w - overlay_ebl)) /
                                 (N**order)) * ((N - ii)**order) + y_move))
                    self.cell.shapes(LayerSlab).insert(Polygon(pts))

                    # add upper right taper
                    y_move = -y_move
                    pts = [
                        Point(l / 2 + in_taper, -w / 2 + y_move),
                        Point(l / 2, -folding_w / 2 + y_move),
                        Point(l / 2, folding_w / 2 + y_move),
                        Point(l / 2 + in_taper, w / 2 + y_move)
                    ]
                    #wg2 = pya.Box(-l/2,-4/2/dbu,l/2,4/2/dbu)
                    self.cell.shapes(LayerSiN).insert(Polygon(pts))
                    total_waveguide_length += in_taper * dbu

                    # slab cubic taper
                    pts = []
                    for ii in range(0, N + 1):
                        pts.append(
                            Point(l / 2 + in_taper - in_taper / N * ii,
                                  (w - overlay_ebl) / 2 +
                                  ((2 / dbu - (w - overlay_ebl)) /
                                   (N**order)) * (ii**order) + y_move))
                    for ii in range(0, N + 1):
                        pts.append(
                            Point(
                                l / 2 + in_taper / N * ii,
                                -(w - overlay_ebl) / 2 -
                                ((2 / dbu - (w - overlay_ebl)) /
                                 (N**order)) * ((N - ii)**order) + y_move))
                    self.cell.shapes(LayerSlab).insert(Polygon(pts))

                else:
                    y_move = -y_move
                    # add input strip taper
                    pts = [
                        Point(-l / 2 - in_taper, -w / 2 + y_move),
                        Point(-l / 2, -folding_w / 2 + y_move),
                        Point(-l / 2, folding_w / 2 + y_move),
                        Point(-l / 2 - in_taper, w / 2 + y_move)
                    ]
                    #wg2 = pya.Box(-l/2,-4/2/dbu,l/2,4/2/dbu)
                    self.cell.shapes(LayerSiN).insert(Polygon(pts))
                    total_waveguide_length += in_taper * dbu

                    # add input slab taper
                    pts = []
                    for i in range(0, N + 1):
                        pts.append(
                            Point(
                                -l / 2 - in_taper + in_taper / N * i,
                                in_slab / 2 + ((edge_slab_width - in_slab) /
                                               (N**order)) * (i**order) +
                                y_move))
                    for i in range(0, N + 1):
                        pts.append(
                            Point(
                                -l / 2 - in_taper + in_taper / N * (N - i),
                                -in_slab / 2 - ((edge_slab_width - in_slab) /
                                                (N**order)) *
                                ((N - i)**order) + y_move))
                    self.cell.shapes(LayerSlab).insert(Polygon(pts))

                    # add output strip taper
                    y_move = -y_move
                    pts = [
                        Point(l / 2 + in_taper, -w / 2 + y_move),
                        Point(l / 2, -folding_w / 2 + y_move),
                        Point(l / 2, folding_w / 2 + y_move),
                        Point(l / 2 + in_taper, w / 2 + y_move)
                    ]
                    #wg2 = pya.Box(-l/2,-4/2/dbu,l/2,4/2/dbu)
                    self.cell.shapes(LayerSiN).insert(Polygon(pts))
                    total_waveguide_length += in_taper * dbu

                    # add input slab taper
                    pts = []
                    for i in range(0, N + 1):
                        pts.append(
                            Point(
                                l / 2 + in_taper - in_taper / N * i,
                                in_slab / 2 + ((edge_slab_width - in_slab) /
                                               (N**order)) * (i**order) +
                                y_move))
                    for i in range(0, N + 1):
                        pts.append(
                            Point(
                                l / 2 + in_taper / N * i, -in_slab / 2 -
                                ((edge_slab_width - in_slab) /
                                 (N**order)) * ((N - i)**order) + y_move))
                    self.cell.shapes(LayerSlab).insert(Polygon(pts))

                    # Pin on the left side:
                    wg_start = -(l / 2 + in_taper +
                                 routing_step * folding_n * 3 + w)
                    p1 = [
                        Point(wg_start + PIN_LENGTH / 2, -y_move),
                        Point(wg_start - PIN_LENGTH / 2, -y_move)
                    ]
                    p1c = Point(wg_start, -y_move)
                    self.set_p1 = p1c
                    self.p1 = p1c
                    pin = Path(p1, w)
                    self.cell.shapes(LayerPinRecN).insert(pin)
                    t = Trans(Trans.R0, wg_start, -y_move)
                    text = Text("pin1", t)
                    shape = self.cell.shapes(LayerPinRecN).insert(text)
                    shape.text_size = pin_text_size
                    # Waveguide to route to port, new in SiEPIC-Tools v0.3.64
                    pts = [
                        Point(-l / 2 - in_taper, -y_move),
                        Point(wg_start, -y_move)
                    ]
                    if self.io_wg_type:
                        waveguide_length = layout_waveguide2(
                            TECHNOLOGY, self.layout, self.cell,
                            ['Si', 'Si - 90 nm rib'], [w * dbu, in_slab * dbu],
                            [0, 0], pts, radius_um, adiab, bezier)
                    else:
                        waveguide_length = layout_waveguide2(
                            TECHNOLOGY, self.layout, self.cell, ['Si'],
                            [w * dbu], [0], pts, radius_um, adiab, bezier)

                    # Pin & Waveguide on the right side:
                    wg_end = l / 2 + in_taper + routing_step * folding_n * 3 + w
                    p2 = [
                        Point(wg_end - PIN_LENGTH / 2, y_move),
                        Point(wg_end + PIN_LENGTH / 2, y_move)
                    ]
                    p2c = Point(wg_end, y_move)
                    self.set_p2 = p2c
                    self.p2 = p2c
                    pin = Path(p2, w)
                    self.cell.shapes(LayerPinRecN).insert(pin)
                    t = Trans(Trans.R0, wg_end, y_move)
                    text = Text("pin2", t)
                    shape = self.cell.shapes(LayerPinRecN).insert(text)
                    shape.text_size = pin_text_size
                    # Waveguide to route to port, new in SiEPIC-Tools v0.3.64
                    pts = [
                        Point(l / 2 + in_taper, y_move),
                        Point(wg_end, y_move)
                    ]
                    if self.io_wg_type:
                        total_waveguide_length += layout_waveguide2(
                            TECHNOLOGY, self.layout, self.cell,
                            ['Si', 'Si - 90 nm rib'], [w * dbu, in_slab * dbu],
                            [0, 0], pts, radius_um, adiab, bezier)
                    else:
                        total_waveguide_length += layout_waveguide2(
                            TECHNOLOGY, self.layout, self.cell, ['Si'],
                            [w * dbu], [0], pts, radius_um, adiab, bezier)

                # add below right taper
                y_move = -y_move
                pts = [
                    Point(l / 2 + in_taper, -w / 2 + y_move),
                    Point(l / 2, -folding_w / 2 + y_move),
                    Point(l / 2, folding_w / 2 + y_move),
                    Point(l / 2 + in_taper, w / 2 + y_move)
                ]
                #wg2 = pya.Box(-l/2,-4/2/dbu,l/2,4/2/dbu)
                self.cell.shapes(LayerSiN).insert(Polygon(pts))
                total_waveguide_length += in_taper * dbu
                pts = []
                for ii in range(0, N + 1):
                    pts.append(
                        Point(l / 2 + in_taper - in_taper / N * ii,
                              (w - overlay_ebl) / 2 +
                              ((2 / dbu - (w - overlay_ebl)) /
                               (N**order)) * (ii**order) + y_move))
                for ii in range(0, N + 1):
                    pts.append(
                        Point(
                            l / 2 + in_taper / N * ii, -(w - overlay_ebl) / 2 -
                            ((2 / dbu - (w - overlay_ebl)) /
                             (N**order)) * ((N - ii)**order) + y_move))
                self.cell.shapes(LayerSlab).insert(Polygon(pts))

            # add metal contact and folded waveguides
            for i in range(-folding_n, folding_n):
                y_coordinate = contact_size + sw + 2 * vc_to_npp_exclusion  # move up/down the position according to vc_to_npp_exclusion
                if i < 0:
                    y_origin = (i + 1) * (folding_w1 + folding_w2 +
                                          folding_gap * 2) / 2 - y_coordinate
                if i == 0:
                    y_origin = 0
                if i > 0:
                    y_origin = (i - 1) * (folding_w1 + folding_w2 +
                                          folding_gap * 2) / 2 + y_coordinate

                if (i + 1) < 0:
                    y_end = (i + 2) * (folding_w1 + folding_w2 +
                                       folding_gap * 2) / 2 - y_coordinate
                if (i + 1) == 0:
                    y_end = 0
                if (i + 1) > 0:
                    y_end = i * (folding_w1 + folding_w2 +
                                 folding_gap * 2) / 2 + y_coordinate

                # Calculate the Folded waveguide vertices
                if (i + folding_n) % 2:
                    # Waveguides on the left side
                    if y_origin + routing_step * 2 - y_end < 2 * radius_um:
                        y_routing = max(routing_step * 2, y_end - y_origin)
                    else:
                        y_routing = y_end + routing_step * 2
                    path = Path([
                        Point(-l / 2 - in_taper, y_origin),
                        Point(
                            -l / 2 - in_taper - routing_step *
                            (1.5 * folding_n - 1.5 * i + 1.5), y_origin),
                        Point(
                            -l / 2 - in_taper - routing_step *
                            (1.5 * folding_n - 1.5 * i + 1.5), y_routing),
                        Point(
                            -l / 2 - in_taper - routing_step *
                            (1.5 * folding_n - 1.5 * i - 0.5), y_routing),
                        Point(
                            -l / 2 - in_taper - routing_step *
                            (1.5 * folding_n - 1.5 * i - 0.5), y_end),
                        Point(-l / 2 - in_taper, y_end)
                    ], 0)

                else:
                    # Waveguides on the right side
                    if y_origin - y_end + routing_step * 2 < 2 * radius_um:
                        y_routing = -max(routing_step * 2, y_end - y_origin)
                    else:
                        y_routing = y_origin - routing_step * 2
                    path = Path([
                        Point(l / 2 + in_taper, y_origin),
                        Point(
                            l / 2 + in_taper + routing_step *
                            (1.5 * folding_n + 1.5 * i + 1), y_origin),
                        Point(
                            l / 2 + in_taper + routing_step *
                            (1.5 * folding_n + 1.5 * i + 1), y_routing),
                        Point(
                            l / 2 + in_taper + routing_step *
                            (1.5 * folding_n + 1.5 * i + 3), y_routing),
                        Point(
                            l / 2 + in_taper + routing_step *
                            (1.5 * folding_n + 1.5 * i + 3), y_end),
                        Point(l / 2 + in_taper, y_end)
                    ], 0)

                # Draw the waveguide geometry, new in SiEPIC-Tools v0.3.64
                path.unique_points()
                pts = path.get_points()
                total_waveguide_length += layout_waveguide2(
                    TECHNOLOGY, self.layout, self.cell, ['Si'], [w * dbu], [0],
                    pts, radius_um, adiab, bezier)

        for i in range(0, self.segments + 1):

            wg_temp_upper = pya.Box(
                (l - contact_size) / self.segments * i - l / 2 -
                vc_to_npp_exclusion, sw / 2,
                (l - contact_size) / self.segments * i - l / 2 + contact_size +
                vc_to_npp_exclusion,
                sw / 2 + contact_size + 2 * vc_to_npp_exclusion)
            #self.cell.shapes(LayerNN).insert(wg_temp_upper)
            self.cell.shapes(LayerNPPN).insert(wg_temp_upper)
            #        self.cell.shapes(LayerNN).insert(wg_temp_upper)
            wg_temp_upper = pya.Box(
                (l - contact_size) / self.segments * i - l / 2 -
                2 * vc_to_npp_exclusion, sw / 2,
                (l - contact_size) / self.segments * i - l / 2 + contact_size +
                2 * vc_to_npp_exclusion,
                sw / 2 + contact_size + 3 * vc_to_npp_exclusion)
            self.cell.shapes(LayerSlab).insert(wg_temp_upper)

            vc_temp_upper = pya.Box(
                (l - contact_size) / self.segments * i - l / 2,
                sw / 2 + vc_to_npp_exclusion,
                (l - contact_size) / self.segments * i - l / 2 + contact_size,
                sw / 2 + contact_size + vc_to_npp_exclusion)
            self.cell.shapes(LayerVCN).insert(vc_temp_upper)

            wg_temp_lower = pya.Box(
                (l - contact_size) / self.segments * i - l / 2 -
                vc_to_npp_exclusion, -sw / 2,
                (l - contact_size) / self.segments * i - l / 2 + contact_size +
                vc_to_npp_exclusion,
                -sw / 2 - contact_size - 2 * vc_to_npp_exclusion)
            #self.cell.shapes(LayerNN).insert(wg_temp_lower)
            self.cell.shapes(LayerNPPN).insert(wg_temp_lower)
            wg_temp_lower = pya.Box(
                (l - contact_size) / self.segments * i - l / 2 -
                2 * vc_to_npp_exclusion, -sw / 2,
                (l - contact_size) / self.segments * i - l / 2 + contact_size +
                2 * vc_to_npp_exclusion,
                -sw / 2 - contact_size - 3 * vc_to_npp_exclusion)
            self.cell.shapes(LayerSlab).insert(wg_temp_lower)

            #        self.cell.shapes(LayerNN).insert(wg_temp_lower)
            vc_temp_lower = pya.Box(
                (l - contact_size) / self.segments * i - l / 2,
                -sw / 2 - vc_to_npp_exclusion,
                (l - contact_size) / self.segments * i - l / 2 + contact_size,
                -sw / 2 - contact_size - vc_to_npp_exclusion)
            self.cell.shapes(LayerVCN).insert(vc_temp_lower)

            metal_temp = pya.Box(
                (l - contact_size) / self.segments * i - l / 2 -
                vc_to_npp_exclusion,
                -sw / 2 - contact_size - metal_routing_distance_to_node *
                (i % 2) - 2 * vc_to_npp_exclusion,
                (l - contact_size) / self.segments * i - l / 2 + contact_size +
                vc_to_npp_exclusion,
                sw / 2 + contact_size + metal_routing_distance_to_node *
                ((i + 1) % 2) + 2 * vc_to_npp_exclusion)
            self.cell.shapes(LayerMN).insert(metal_temp)

        metal_routing = Path([
            Point(-l / 2,
                  -sw / 2 - metal_routing_distance_to_node - contact_size),
            Point(l / 2,
                  -sw / 2 - metal_routing_distance_to_node - contact_size)
        ], metal_routing_width)
        self.cell.shapes(LayerMN).insert(metal_routing)
        metal_routing = Path([
            Point(-l / 2,
                  sw / 2 + metal_routing_distance_to_node + contact_size),
            Point(l / 2,
                  sw / 2 + metal_routing_distance_to_node + contact_size)
        ], metal_routing_width)
        self.cell.shapes(LayerMN).insert(metal_routing)

        if folding_n > 0:
            dev = Box(
                wg_start, -sw / 2 - metal_routing_distance_to_node -
                contact_size - metal_routing_width, wg_end,
                sw / 2 + metal_routing_distance_to_node + contact_size +
                metal_routing_width)
            self.cell.shapes(LayerDevRecN).insert(dev)

        t = Trans(0, False, Point(0, 0))
        text = Text ( \
          'Waveguide Length=%.3fu' %(total_waveguide_length), t, 3*w, -1)
        shape = self.cell.shapes(LayerDevRecN).insert(text)
Ejemplo n.º 2
0
    def produce_impl(self):

        from SiEPIC.utils.layout import layout_waveguide2
        from SiEPIC.utils import angle_vector
        from math import cos, sin, pi, sqrt
        import pya
        from SiEPIC.extend import to_itype

        TECHNOLOGY = get_technology_by_name('GSiP')

        dbu = self.layout.dbu
        wg_width = to_itype(self.width, dbu)
        path = self.path.to_itype(dbu)

        if not (len(self.layers) == len(self.widths)
                and len(self.layers) == len(self.offsets)
                and len(self.offsets) == len(self.widths)):
            raise Exception(
                "There must be an equal number of layers, widths and offsets")
        path.unique_points()
        pts = path.get_points()

        # Draw the waveguide geometry, new in SiEPIC-Tools v0.3.64
        waveguide_length = layout_waveguide2(TECHNOLOGY, self.layout,
                                             self.cell, self.layers,
                                             self.widths, self.offsets, pts,
                                             self.radius, self.adiab,
                                             self.bezier)

        pts = path.get_points()
        LayerPinRecN = self.layout.layer(TECHNOLOGY['PinRec'])

        t1 = Trans(angle_vector(pts[0] - pts[1]) / 90, False, pts[0])
        self.cell.shapes(LayerPinRecN).insert(
            Path([Point(-50, 0), Point(50, 0)], wg_width).transformed(t1))
        self.cell.shapes(LayerPinRecN).insert(Text("pin1", t1, 0.3 / dbu, -1))

        t = Trans(angle_vector(pts[-1] - pts[-2]) / 90, False, pts[-1])
        self.cell.shapes(LayerPinRecN).insert(
            Path([Point(-50, 0), Point(50, 0)], wg_width).transformed(t))
        self.cell.shapes(LayerPinRecN).insert(Text("pin2", t, 0.3 / dbu, -1))

        LayerDevRecN = self.layout.layer(TECHNOLOGY['DevRec'])

        # Compact model information
        angle_vec = angle_vector(pts[0] - pts[1]) / 90
        halign = 0  # left
        angle = 0
        if angle_vec == 0:  # horizontal
            halign = 2  # right
            angle = 0
            dpt = Point(0, 0.2 * wg_width)
        if angle_vec == 2:  # horizontal
            halign = 0  # left
            angle = 0
            dpt = Point(0, 0.2 * wg_width)
        if angle_vec == 1:  # vertical
            halign = 2  # right
            angle = 1
            dpt = Point(0.2 * wg_width, 0)
        if angle_vec == -1:  # vertical
            halign = 0  # left
            angle = 1
            dpt = Point(0.2 * wg_width, 0)
        pt2 = pts[0] + dpt
        pt3 = pts[0] - dpt
        pt4 = pts[0] - 2 * dpt
        pt5 = pts[0] + 2 * dpt

        t = Trans(angle, False, pt5)
        text = Text('cellName=%s' % self.cellName, t, 0.1 * wg_width, -1)
        text.halign = halign
        shape = self.cell.shapes(LayerDevRecN).insert(text)
        t = Trans(angle, False, pt3)
        text = Text('Lumerical_INTERCONNECT_library=Design kits/%s' % self.CML,
                    t, 0.1 * wg_width, -1)
        text.halign = halign
        shape = self.cell.shapes(LayerDevRecN).insert(text)
        t = Trans(angle, False, pt2)
        text = Text('Component=%s' % self.model, t, 0.1 * wg_width, -1)
        text.halign = halign
        shape = self.cell.shapes(LayerDevRecN).insert(text)
        t = Trans(angle, False, pts[0])
        pts_txt = str(
            [[round(p.to_dtype(dbu).x, 3),
              round(p.to_dtype(dbu).y, 3)] for p in pts]).replace(', ', ',')
        text = Text ( \
          'Spice_param:wg_length=%.3fu wg_width=%.3fu points="%s" radius=%s' %\
            (waveguide_length, self.width, pts_txt,self.radius ), t, 0.1*wg_width, -1  )
        text.halign = halign
        shape = self.cell.shapes(LayerDevRecN).insert(text)
        t = Trans(angle, False, pt4)
        text = Text ( \
          'Length=%.3fu' %(waveguide_length), t, 0.5*wg_width, -1  )
        text.halign = halign
        shape = self.cell.shapes(LayerDevRecN).insert(text)