Beispiel #1
0
    class Layout(i3.LayoutView):
        """
        This section is to draw a Vernier scale
        """

        # Basic properties of the scale
        spacing = i3.PositiveNumberProperty(default=4,
                                            doc="spacing between bars")
        number_of_bars = i3.IntProperty(default=13, doc="the number of bars")
        # Detailed properties of the scale
        bar_length = i3.PositiveNumberProperty(
            default=10, doc="length of the shortest bars on the scale")
        bar_extra_length = i3.PositiveNumberProperty(
            default=10, doc="extra length of the central bar")
        bar_width = i3.PositiveNumberProperty(default=2,
                                              doc="width of a single bar")
        process = i3.ProcessProperty(
            default=i3.TECH.PPLAYER.CH2.TRENCH
        )  #i3.TECH.PROCESS.WG, doc="Process Layer on which the cross is drawn")

        # Purpose property cannot be set from outside
        purpose = i3.PurposeProperty(
            locked=True, default=i3.TECH.PPLAYER.CH2.TRENCH
        )  #i3.TECH.PURPOSE.DF.LINE, doc="Process Purpose of the cross")

        def validate_properties(self):
            # The scale is symmetric with respect to its central bar so the number of bars is an odd number
            if self.number_of_bars % 2 == 0:
                raise i3.PropertyValidationError(
                    self, "The number of bars should be an odd number",
                    {"number_of_bars": self.number_of_bars})
            return True

        def _generate_elements(self, elems):

            # Draw the central bar, which is longer than the others
            elems += i3.Rectangle(
                layer=i3.TECH.PPLAYER.CH1.
                TRENCH,  #i3.PPLayer(self.process, self.purpose),
                center=(0, (self.bar_length + self.bar_extra_length) * 0.5),
                box_size=(self.bar_width,
                          self.bar_length + self.bar_extra_length))

            # Draw the other bars
            for i in range((self.number_of_bars - 1) / 2):
                elems += i3.Rectangle(
                    layer=i3.TECH.PPLAYER.CH1.
                    TRENCH,  #i3.PPLayer(self.process, self.purpose),
                    center=(-(i + 1) * self.spacing, self.bar_length * 0.5),
                    box_size=(self.bar_width, self.bar_length))

            for j in range((self.number_of_bars - 1) / 2):
                elems += i3.Rectangle(
                    layer=i3.TECH.PPLAYER.CH1.
                    TRENCH,  #i3.PPLayer(self.process, self.purpose),
                    center=((j + 1) * self.spacing, self.bar_length * 0.5),
                    box_size=(self.bar_width, self.bar_length))

            return elems
Beispiel #2
0
    class Layout(i3.LayoutView):

        # Properties -------

        # taper to draw
        taper_prop_dict = i3.DictProperty( default = {}, doc = 'Dictionary of taper cell properties.' + \
                                           'Properties = "length", "width1", "width2", "width_etch" ' )

        # number of rows
        n_rows = i3.IntProperty(default=3, doc='number of taper clip rows')

        # number of taper pairs per row
        n_taper_pairs_per_row = i3.IntProperty(
            default=2, doc='number of taper clip pairs per row')

        # spacing between rows
        row_spacing = i3.PositiveNumberProperty(
            default=0.0, doc='spacing between rows (midpoint to midpoint)')

        # Taper pair properties
        connect_length = i3.NumberProperty(default=0.0,
                                           doc='distance between tapers')
        pair_connect_length = i3.NumberProperty(
            default=0.0, doc='distance between taper pairs')

        # input/output connection length
        bot_gc_connect_length = i3.NumberProperty(
            default=0.0, doc='distance between grating and bottom taper')
        top_gc_connect_length = i3.NumberProperty(
            default=0.0, doc='distance between grating and top taper')

        # radius of each arc
        bend_radius = i3.PositiveNumberProperty(
            default=5.0, doc='spacing between rows (midpoint to midpoint)')

        # Methods -------

        def _generate_instances(self, insts):
            # Generates taper clip

            # make my OWN custom waveguide trace template
            # wg_trace = f_MyIMECWaveguideTemplate(core_width=self.taper_prop_dict['width1'],
            #                                      cladding_width=self.taper_prop_dict['width1'] + 2.0 * self.taper_prop_dict['width_etch'])

            # make waveguide
            wg = i3.Waveguide(trace_template=StripWgTemplate(),
                              name=self.name + '_WG')
            wg_round = i3.RoundedWaveguide(trace_template=StripWgTemplate(),
                                           name=self.name + '_WG_ROUND')

            # how much to translate bends left/right
            # t_left = i3.Translation((self.bend_radius + (float(self.n_rows)/2.0) ))
            t_left = i3.Translation((-2.5 * self.bend_radius, 0.0))
            t_right = i3.Translation((2.5 * self.bend_radius, 0.0))

            # draw taper pair rows
            for ii in range(self.n_rows):

                # add rows
                tp_rows_layout = TaperPairRow(name=self.name + '_TProw' +
                                              str(ii)).get_default_view(
                                                  i3.LayoutView)
                tp_rows_layout.set(
                    taper_prop_dict=self.taper_prop_dict,
                    connect_length=self.connect_length,
                    pair_connect_length=self.pair_connect_length,
                    n_pairs=self.n_taper_pairs_per_row)

                # set translation
                t = i3.Translation((0.0, float(ii) * self.row_spacing))

                # place taper pair row
                tp_row_name = self.name + '_TP_ROW' + str(ii)
                insts += i3.SRef(name=tp_row_name,
                                 reference=tp_rows_layout,
                                 transformation=t)

                # draw connecting arcs
                if ii > 0:

                    if (ii % 2) == 1:
                        # bend on the right
                        # make shape bend
                        row_name = self.name + '_TP_ROW' + str(ii - 1)
                        shape_bend = i3.ShapeBend(start_point=insts[row_name].
                                                  ports['right'].position,
                                                  radius=self.bend_radius,
                                                  start_angle=-90.05,
                                                  end_angle=90.05,
                                                  angle_step=0.1)

                        # add 180 deg bend
                        wg_copy = i3.Waveguide(
                            trace_template=StripWgTemplate(),
                            name=self.name + '_arc_r' + str(ii))
                        arc_name = self.name + '_arc' + str(ii)
                        insts += i3.SRef(
                            name=arc_name,
                            reference=wg_copy.Layout(shape=shape_bend),
                            transformation=t_right)

                        # connect bottom wgs

                        # get coords
                        in_port_coords = insts[arc_name].ports['in'].position
                        out_port_coords = insts[row_name].ports[
                            'right'].position

                        # draw bezier curve
                        bez = BezierCurve(
                            N=100,
                            P0=(in_port_coords[0] + 0.01, in_port_coords[1]),
                            P1=(in_port_coords[0] - self.bend_radius / 2.0,
                                in_port_coords[1]),
                            P2=(out_port_coords[0] + self.bend_radius / 2.0,
                                out_port_coords[1]),
                            P3=(out_port_coords[0] - 0.01, out_port_coords[1]),
                            R=(-self.bend_radius, +self.bend_radius),
                            dy_dx=(0.0, -0.0))
                        bez_coords = bez.bezier_coords()

                        # make ipkiss shape
                        s = i3.Shape(bez_coords)

                        # add bottom wg connector
                        wg_copy = i3.Waveguide(
                            trace_template=StripWgTemplate(),
                            name=self.name + '_arc_r_con' + str(ii))
                        insts += i3.SRef(name=self.name + '_con_wg_r_b_' +
                                         str(ii),
                                         reference=wg_copy.Layout(shape=s))

                        # connect top wgs
                        next_row_name = self.name + '_TP_ROW' + str(ii)
                        in_port_coords = insts[arc_name].ports['out'].position
                        out_port_coords = insts[next_row_name].ports[
                            'right'].position

                        # draw bezier curve
                        bez = BezierCurve(
                            N=500,
                            P0=(in_port_coords[0] + 0.01, in_port_coords[1]),
                            P1=(in_port_coords[0] - self.bend_radius / 2.0,
                                in_port_coords[1]),
                            P2=(out_port_coords[0] + self.bend_radius / 2.0,
                                out_port_coords[1]),
                            P3=(out_port_coords[0] - 0.01, out_port_coords[1]),
                            R=(self.bend_radius, -self.bend_radius),
                            dy_dx=(0.0, -0.0))
                        bez_coords = bez.bezier_coords()

                        # make ipkiss shape
                        s = i3.Shape(bez_coords)

                        # add wg bend
                        wg_copy = i3.Waveguide(
                            trace_template=StripWgTemplate(),
                            name=self.name + '_bez_r' + str(ii))
                        insts += i3.SRef(name=self.name + '_con_wg_r_t_' +
                                         str(ii),
                                         reference=wg_copy.Layout(shape=s))

                    else:
                        # bend on the left
                        # make shape bend
                        row_name = self.name + '_TP_ROW' + str(ii - 1)
                        shape_bend = i3.ShapeBend(start_point=(
                            insts[row_name].ports['left'].position),
                                                  radius=self.bend_radius,
                                                  start_angle=90.05,
                                                  end_angle=-90.05,
                                                  angle_step=0.1,
                                                  clockwise=False)

                        # add 180 deg bend
                        wg_copy = i3.Waveguide(
                            trace_template=StripWgTemplate(),
                            name=self.name + '_arc_l' + str(ii))
                        arc_name = self.name + '_arc' + str(ii)
                        insts += i3.SRef(
                            name=arc_name,
                            reference=wg_copy.Layout(shape=shape_bend),
                            transformation=t_left)

                        # connect bottom wgs

                        # get coords
                        in_port_coords = insts[arc_name].ports['out'].position
                        out_port_coords = insts[row_name].ports[
                            'left'].position

                        # draw bezier curve
                        bez = BezierCurve(
                            N=100,
                            P0=(in_port_coords[0] - 0.01, in_port_coords[1]),
                            P1=(in_port_coords[0] + self.bend_radius / 2.0,
                                in_port_coords[1]),
                            P2=(out_port_coords[0] - self.bend_radius / 2.0,
                                out_port_coords[1]),
                            P3=(out_port_coords[0] + 0.01, out_port_coords[1]),
                            R=(-self.bend_radius, +self.bend_radius),
                            dy_dx=(0.0, -0.0))
                        bez_coords = bez.bezier_coords()

                        # make ipkiss shape
                        s = i3.Shape(bez_coords)

                        # add bottom wg connector
                        wg_copy = i3.Waveguide(
                            trace_template=StripWgTemplate(),
                            name=self.name + '_arc_l_con' + str(ii))
                        insts += i3.SRef(name=self.name + '_con_wg_l_b_' +
                                         str(ii),
                                         reference=wg_copy.Layout(shape=s))

                        # connect top wgs
                        next_row_name = self.name + '_TP_ROW' + str(ii)
                        in_port_coords = insts[arc_name].ports['in'].position
                        out_port_coords = insts[next_row_name].ports[
                            'left'].position

                        # draw bezier curve
                        bez = BezierCurve(
                            N=500,
                            P0=(in_port_coords[0] - 0.01, in_port_coords[1]),
                            P1=(in_port_coords[0] + self.bend_radius / 2.0,
                                in_port_coords[1]),
                            P2=(out_port_coords[0] - self.bend_radius / 2.0,
                                out_port_coords[1]),
                            P3=(out_port_coords[0] + 0.01, out_port_coords[1]),
                            R=(-self.bend_radius, +self.bend_radius),
                            dy_dx=(0.0, -0.0))
                        bez_coords = bez.bezier_coords()

                        # make ipkiss shape
                        s = i3.Shape(bez_coords)

                        # add wg bend
                        wg_copy = i3.Waveguide(
                            trace_template=StripWgTemplate(),
                            name=self.name + '_bez_l' + str(ii))
                        insts += i3.SRef(name=self.name + '_con_wg_l_t_' +
                                         str(ii),
                                         reference=wg_copy.Layout(shape=s))

                    # end if bend

                # end drawing connecting arcs

            # end for ii in range(self.rows)

            # # connect the input grating
            # # pick grating layout to return
            # grating_layout = {
            #     'FGCCTE_FC1DC_625_313':     FGCCTE_FC1DC_625_313().Layout(),
            #     'FGCCTE_FCWFC1DC_630_378':  FGCCTE_FCWFC1DC_630_378().Layout(),
            #     'FGCCTM_FC1DC_984_492':     FGCCTM_FC1DC_984_492().Layout(),
            # }[self.grating_name]
            #
            #
            #
            # # place bottom grating
            # # always assuming bottom grating starts on the left
            # bot_grating_name = self.name+'_bot_grating'
            # t = i3.vector_match_transform( grating_layout.ports['waveguide'],
            #                                insts[self.name + '_TP_ROW0'].ports['left'] ) + \
            #     i3.Translation( ( -self.bot_gc_connect_length, 0.0 ) )
            #
            # insts += i3.SRef(   name            = bot_grating_name,
            #                     reference       = grating_layout,
            #                     transformation  = t )
            #
            # # connect bottom grating to taper
            # route_wg_bot = i3.RouteManhattan( input_port  = insts[bot_grating_name].ports['waveguide'],
            #                                   output_port = insts[self.name + '_TP_ROW0'].ports['left'] )
            #
            # # add wg
            # wg_bot = i3.Waveguide( trace_template = StripWgTemplate(), name = self.name + '_WG_BOT')
            # insts += i3.SRef(name=self.name + '_connect_wg_bot', reference=wg_bot.Layout(shape=route_wg_bot))
            #
            #
            #
            # # place top grating
            # top_grating_name = self.name + '_top_grating'
            # if (self.n_rows % 2) == 1:
            #     # even # of rows, output is to the right
            #     t = i3.vector_match_transform(  grating_layout.ports['waveguide'],
            #                                     insts[self.name + '_TP_ROW' + str(self.n_rows-1)].ports['right'],
            #                                     mirrored = True ) + \
            #         i3.Translation((self.top_gc_connect_length, 0.0))
            #
            #     insts += i3.SRef( name              = top_grating_name,
            #                       reference         = grating_layout,
            #                       transformation    = t)
            #
            #     # connect top grating to taper
            #     route_wg_top = i3.RouteManhattan(   input_port  = insts[top_grating_name].ports['waveguide'],
            #                                         output_port = insts[self.name + '_TP_ROW' + str(self.n_rows-1)].ports['right'])
            #
            #     # add wg
            #     wg_top = i3.Waveguide( trace_template = StripWgTemplate(), name = self.name + '_WG_TOP')
            #     insts += i3.SRef(name=self.name + '_connect_wg_top', reference=wg_top.Layout(shape=route_wg_top))
            #
            # else:
            #     # odd # of rows, output is to the left
            #     t = i3.vector_match_transform(  grating_layout.ports['waveguide'],
            #                                     insts[self.name + '_TP_ROW' + str(self.n_rows-1)].ports['left'],
            #                                     mirrored = False ) + \
            #         i3.Translation((-self.top_gc_connect_length, 0.0))
            #
            #     insts += i3.SRef( name              = top_grating_name,
            #                       reference         = grating_layout,
            #                       transformation    = t)
            #
            #     # connect top grating to taper
            #     route_wg_top = i3.RouteManhattan(   input_port  = insts[top_grating_name].ports['waveguide'],
            #                                         output_port = insts[self.name + '_TP_ROW' + str(self.n_rows-1)].ports['left'])
            #
            #     # add wg
            #     wg_top = i3.Waveguide( trace_template = StripWgTemplate(), name = self.name + '_WG_TOP')
            #     insts += i3.SRef(name=self.name + '_connect_wg_top', reference=wg_top.Layout(shape=route_wg_top))

            return insts
Beispiel #3
0
class Spirals(PlaceAndAutoRoute):

    _name_prefix = 'LSpiral'

    tipo = i3.PositiveNumberProperty(doc="Number loops", default=1)

    waveguide_template = i3.DefinitionProperty(doc="Trace template used")
    R = i3.PositiveNumberProperty(default=200, doc="Radius of curvature")
    spacing = i3.PositiveNumberProperty(default=100, doc="Radius of curvature")
    n_loops = i3.IntProperty(doc="Number loops", default=2)
    n_loops_vec = i3.ListProperty(default=[4, 8])
    s_length_vec = i3.ListProperty(default=[0.0])
    Spiral_list = i3.ChildCellListProperty(
        doc="List containing the 90 degree angle child cells")
    #chip_length = i3.PositiveNumberProperty(default=2500.0, doc="Radius of curvature")
    chip_length = i3.PositiveNumberProperty(default=3000.0,
                                            doc="Radius of curvature")
    Port = i3.ChildCellProperty(doc="Used for ports")
    Port2 = i3.ChildCellProperty(doc="Used for ports")
    tlport = i3.PositiveNumberProperty(default=1000.0,
                                       doc="Transition legth to ports")
    couplingWG = i3.ChildCellProperty(doc="", locked=True)
    couplingWG_l = i3.PositiveNumberProperty(default=5000.0,
                                             doc="Length of the coupling WG ")
    tt_port = i3.TraceTemplateProperty(
        doc="Wide trace template used for the contacts")
    tt_port2 = i3.TraceTemplateProperty(
        doc="Wide trace template used for the contacts")

    #width_vec = i3.ListProperty(default=[1])
    n = i3.PositiveNumberProperty(default=1, doc="")
    width = i3.PositiveNumberProperty(default=1, doc="")
    lengths = i3.PositiveNumberProperty(default=1, doc="")

    def _default_lengths(self):
        for counter, cell in enumerate(self.s_length_vec):
            numero = counter + 1
        return numero

    #template for Autorute
    def _default_trace_template(self):
        return self.waveguide_template

    def _default_tt(self):
        return self.waveguide_template

    def _default_tt_port(self):
        tt_port = WireWaveguideTemplate()
        tt_port_layout = tt_port.Layout(core_width=10.0, cladding_width=10.0)
        return tt_port

    def _default_tt_port2(self):
        tt_port = WireWaveguideTemplate()
        tt_port_layout = tt_port.Layout(core_width=10.0, cladding_width=10.0)
        return tt_port

    def _default_Spiral_list(self):
        Spiral_list = []  # empty list
        print ' I am in _Spiral_list'
        for l, length in enumerate(self.s_length_vec):
            loops = 1
            print length

            cell = FixedLengthSpiralRounded(
                trace_template=self.waveguide_template,
                #total_length=length-self.chip_length,
                total_length=length,
                n_o_loops=loops,
                name=self.name + '_Spiral_' + str(l))

            cell.Layout(
                incoupling_length=0,
                bend_radius=self.R,
                spacing=self.spacing,
                stub_direction="H",
                growth_direction="H",
            )  #.visualize(annotate=True)
            print 'The legth of the spiral is: ', cell.total_length
            print 'Cell: ', cell.name

            Spiral_list.append(cell)

        return Spiral_list

    def _default_couplingWG(self):
        rect = i3.Waveguide(trace_template=self.tt_port)
        layout_rect = rect.Layout(shape=[(0.0, 0.0), (self.couplingWG_l, 0.0)])
        return rect

    def _default_Port(self):
        Port = AutoTransitionPorts(contents=self.couplingWG,
                                   port_labels=["in"],
                                   trace_template=self.waveguide_template)
        layout_Port = Port.Layout(
            transition_length=self.tlport)  #.visualize(annotate=True)
        return Port

    def _default_Port2(self):
        Port = AutoTransitionPorts(contents=self.couplingWG,
                                   port_labels=["in"],
                                   trace_template=self.waveguide_template)
        layout_Port = Port.Layout(
            transition_length=self.tlport)  #.visualize(annotate=True)
        return Port

    def _default_child_cells(self):
        child_cells = {
        }  # First we define the property "child_cells" as  an empty dictionary

        for counter, spiral in enumerate(
                self.Spiral_list
        ):  # the iteration starts in the first element of the list and follows element by element to the last element.

            child_cells['Spiral{}'.format(counter)] = spiral
            print spiral
            print 'name of spiral:', spiral.name
            child_cells['InPort' + str(counter)] = self.Port
            child_cells['OutPort' + str(counter)] = self.Port

            print 'child_cells:', child_cells
        return child_cells

    def _default_links(self):
        links = []
        for counter, spiral in enumerate(self.Spiral_list):
            print counter
            in_port = "Spiral{}:in".format(counter)
            out_port = "InPort{}:in".format(counter)
            links.append((in_port, out_port))
            in_port = "Spiral{}:out".format(counter)
            out_port = "OutPort{}:in".format(counter)
            links.append((in_port, out_port))

        return links

    class Layout(PlaceAndAutoRoute.Layout):
        #tipo=1

        def _default_bend_radius(self):
            return self.R

        def _default_child_transformations(self):
            d = {}
            for counter, child in enumerate(self.Spiral_list):
                ip = child.ports["in"].position
                #print self.child_cells['InPort' + str(counter)].ports["out"].position
                #print self.child_cells['OutPort' + str(counter)].ports.position
                print '----------------'
                print 'spiral length:', child.total_length
                print 'counter: ', counter
                #print ip
                op = child.ports["out"].position
                #print op

                print 'The lateral size of the spiral is', op[0] - ip[0]
                print 'The type of mask is: ', self.tipo
                print 'The number of widths is: ', self.n
                print 'The number of lengths is: ', self.lengths
                print 'The width number is: ', self.width
                print '----------------'
                iz = child.inner_size
                sx = iz[1] + 200
                #sx=1200
                if self.tipo == 1:

                    d['Spiral' + str(counter)] = i3.Translation(
                        translation=(-(op[0] - ip[0]) / 2,
                                     self.n * counter * sx))
                    d['InPort' + str(counter)] = i3.HMirror() + i3.Translation(
                        translation=(-self.chip_length / 2.0 -
                                     self.couplingWG_l, self.n * counter * sx))
                    d['OutPort' + str(counter)] = i3.Translation(
                        translation=(self.chip_length / 2.0 +
                                     self.couplingWG_l, self.n * counter * sx))
                if self.tipo == 2:
                    d['Spiral' + str(counter)] = i3.Translation(
                        translation=(-(op[0] - ip[0]) / 2,
                                     -(self.n + 0.5) * counter * sx))
                    #d['InPort' + str(counter)] = i3.HMirror()+ i3.Translation(translation=(-self.chip_length*(3/4)-self.couplingWG_l, -(self.n+0.5)*counter*sx))
                    #d['OutPort' + str(counter)] = i3.Rotation(rotation=90) + i3.Translation(translation=((op[0]-ip[0])/2+2*self.R+(((self.n+0.5)*counter+self.width)*sx/4), self.chip_length*(3/4)+(self.width+counter-(((counter+1)-1.0)%self.lengths))*sx))
                    d['InPort' + str(counter)] = i3.HMirror() + i3.Translation(
                        translation=(-self.chip_length * (1 / 2) - 2000,
                                     -(self.n + 0.5) * counter * sx))
                    d['OutPort' + str(counter)] = i3.Rotation(
                        rotation=90) + i3.Translation(translation=(
                            (op[0] - ip[0]) / 2 + 2 * self.R +
                            (((self.n + 0.5) * counter + self.width) * sx / 4),
                            3000 + self.chip_length * (3 / 4) +
                            (self.width + counter -
                             (((counter + 1) - 1.0) % self.lengths)) * sx))
                #For awg's
                #if self.tipo==2:
                #d['Spiral' + str(counter)] = i3.Translation(translation=(-(op[0]-ip[0])/2, -(self.n+0.5)*counter*sx))
                #d['InPort' + str(counter)] = i3.HMirror()+ i3.Translation(translation=(-self.chip_length*(3/4.0), -(self.n+0.5)*counter*sx))
                #d['OutPort' + str(counter)] = i3.Rotation(rotation=90) + i3.Translation(translation=((op[0]-ip[0])/2+2*self.R
                #+(((self.n+0.5)*counter+self.width)*sx/100.0)
                #, self.chip_length*(2/4.0)+
                #(self.width+counter-(((counter+1)-1.0)%self.lengths))*sx))
            return d

        # Fabio's addition
        def _generate_elements(self, elems):
            # We calculate the lengths of the 2 spirals in this pcell.
            # Note that we assume that there are exactly 2 spirals in this list.
            #assert len(self.Spiral_list) == 2
            lengths = get_lengths(self)
            iz = self.Spiral_list[0].inner_size
            sx = iz[1] + 200
            for counter, (child,
                          length) in enumerate(zip(self.Spiral_list, lengths)):
                ip = child.ports["in"].position
                op = child.ports["out"].position
                width = child.ports["in"].trace_template.core_width
                #print 'child.ports["in"].trace_template.core_width: ', child.ports["in"].trace_template.core_width

                #i3.TECH.PPLAYER.NONE.LOGOTXT   when using isipp50g
                if self.tipo == 2:
                    elems += i3.PolygonText(
                        layer=i3.TECH.PPLAYER.WG.TEXT,
                        text='Width={}_Length={}_R={}'.format(
                            width, length, self.R),
                        coordinate=((op[0] - ip[0]) / 2 - 1000.0,
                                    (self.n + 0.5) * counter * sx - 50.0),
                        alignment=(i3.TEXT_ALIGN_LEFT, i3.TEXT_ALIGN_LEFT),
                        font=2,
                        height=20.0)
                if self.tipo == 1:
                    elems += i3.PolygonText(
                        layer=i3.TECH.PPLAYER.WG.TEXT,
                        text='Width={}_Length={}_R={}'.format(
                            width, length, self.R),
                        coordinate=(-(op[0] - ip[0]) / 2 - 1000.0,
                                    -(self.n + 0.5) * counter * sx - 50.0),
                        alignment=(i3.TEXT_ALIGN_LEFT, i3.TEXT_ALIGN_LEFT),
                        font=2,
                        height=20.0)
            return elems
    class Layout(i3.LayoutView):
        # specified parameters used for layout, lengths of various waveguides
        # using some default values if standard ring shape is used
        bend_radius_ring = i3.PositiveNumberProperty(default=10.,
                                                     doc="bend radius of ring")
        ring_x_straight = i3.PositiveNumberProperty(
            default=15., doc="straight between bends in x ring")
        ring_y_straight = i3.PositiveNumberProperty(
            default=25., doc="straight between bends in y ring")
        external_straights = i3.PositiveNumberProperty(
            default=10., doc="extra straight for outside structure")
        external_gap = i3.PositiveNumberProperty(
            default=1., doc="gap between outside waveguides and resonator")
        # external_radius = i3.PositiveNumberProperty(default=bend_radius_ring, doc="radius of outside coupler")
        rounding_algorithm = i3.DefinitionProperty(
            default=SplineRoundingAlgorithm(),
            doc="secondary rounding algorithm")

        # extra layouting for the CROW
        num_rings = i3.IntProperty(default=3, doc="number of rings")
        ring_gap = i3.PositiveNumberProperty(default=0.5,
                                             doc="gap between internal rings")

        use_gap_list = i3.BoolProperty(default=False,
                                       doc="use non default bending algorithm")
        ring_gap_list = i3.ListProperty(
            default=[], doc="list of gaps for manual swapping, default empty!")

        # define the layout of the internal coupler which we SRef below
        def _default_resonator(self):
            res_layout = self.cell.resonator.get_default_view(
                i3.LayoutView)  # Retrieve layout view following example

            # make the shape of the layout from the previous values. Assume (0, 0) is bottom middle!)
            # will do each corner for clarity
            # bottom_left = (-self.bend_radius_ring - self.ring_x_straight/2., 0.)
            # top_left = (-self.bend_radius_ring - self.ring_x_straight/2.,
            #             self.bend_radius_ring*2. + self.ring_y_straight)
            # top_right = (self.bend_radius_ring + self.ring_x_straight/2.,
            #              self.bend_radius_ring*2. + self.ring_y_straight)
            # bottom_right = (self.bend_radius_ring + self.ring_x_straight/2., 0.)
            # ring_shape = [bottom_left, top_left, top_right, bottom_right, bottom_left]
            # print ring_shape

            # tried to use generic round ring, but failed :P. Using ring rect instead
            # set the layout of the resonator. Stuck a bool for non default rounding algorithm

            res_layout.set(bend_radius=self.bend_radius_ring,
                           straights=(self.ring_x_straight,
                                      self.ring_y_straight),
                           rounding_algorithm=self.rounding_algorithm)

            return res_layout

        def _dummy_resonator(self):
            dummy_res = i3.SRef(name="just_a_dummy", reference=self.resonator)
            return dummy_res

        # make a function for determining the distance between core size and

        def _resonator_size_core_to_core(self):
            # calls the get components function and then does math on the pulled in layout
            resonator = self._dummy_resonator()
            wg_ring_template = self.wg_ring_template

            # grabbing the position of the resonator to layout the rest of the coupler properly
            resonator_west_side = resonator.size_info().west
            resonator_east_side = resonator.size_info().east

            resonator_core_width = wg_ring_template.core_width
            resonator_clad_width = wg_ring_template.cladding_width

            resonator_x_dim = (resonator_east_side -
                               resonator_west_side) - resonator_clad_width
            return resonator_x_dim

        # setting the output shape of the access waveguides using a shape defined by ports from MMI (hopefully..)
        def _default_wgs(self):
            # bring in parts from rest of PCell Layout, used dummy resonator to grab positions
            resonator = self._dummy_resonator()
            wg_in_cell, wg_pass_cell = self.cell.wgs
            wg_template = self.wg_coupler_template
            wg_ring_template = self.wg_ring_template

            # using the ring radius for the external radius
            external_rad = self.bend_radius_ring
            external_str = self.external_straights

            # grabbing the position of the resonator to layout the rest of the coupler properly
            resonator_west_side = resonator.size_info().west
            resonator_south_side = resonator.size_info().south

            resonator_core_width = wg_ring_template.core_width
            resonator_clad_width = wg_ring_template.cladding_width
            coupler_core_width = wg_template.core_width

            # calculate the x position for center of input coupling waveguide when coupling, and make shape
            x_coup_spot = resonator_west_side + resonator_clad_width/2. - resonator_core_width/2. - self.external_gap \
                - coupler_core_width/2.

            # get bottom using the south and cladding information again
            bottom_left = (x_coup_spot - external_str - external_rad,
                           resonator_south_side + resonator_clad_width / 2.)
            bottom_right = (x_coup_spot,
                            resonator_south_side + resonator_clad_width / 2.)
            top_right = (x_coup_spot, bottom_right[1] + 2. * external_rad +
                         self.ring_y_straight)
            top_left = (bottom_left[0], top_right[1])

            wg_shape = [bottom_left, bottom_right, top_right, top_left]

            # now make the instance using this shape info
            wg_in_layout = wg_in_cell.get_default_view(i3.LayoutView)

            wg_in_layout.set(trace_template=wg_template,
                             shape=wg_shape,
                             bend_radius=external_rad,
                             rounding_algorithm=self.rounding_algorithm)

            # other waveguide for reference, can put in shape or mirror later
            wg_pass_layout = wg_pass_cell.get_default_view(i3.LayoutView)
            # wg_in_layout.set()
            return wg_in_layout, wg_pass_layout  # wg_ring_layout

        # A few functions for grabbing waveguide parameters to determine lengths for FSR checking
        # def wg_lengths(self):
        #     # grab the lengths of internal waveguides to use for calculations later
        #     wg_in_layout, wg_pass_layout, wg_ring_layout = self.wgs
        #
        #     straights_and_bends = wg_ring_layout.trace_length()
        #     return straights_and_bends

        # now we take the resonator and perform multiple translations for the CROW
        def _get_components(self):
            res_x_dim = self._resonator_size_core_to_core()
            ring_gap = self.ring_gap
            ring_core_width = self.wg_ring_template.core_width
            ring_gap_list = self.ring_gap_list

            shifting_list = [0.] + ring_gap_list
            all_components = []
            # and now crank an SRef for each Ring in a loop
            for ring in range(self.num_rings):
                # will translate the original ring over to the correct position, and iterate for number of rings
                # use an if statement for external gap list or not. Need an error
                if self.use_gap_list is False:
                    this_transform = i3.Translation(
                        ((res_x_dim + ring_gap + ring_core_width) * ring, 0.))
                    this_resonator = i3.SRef(name="R_" + str(ring),
                                             reference=self.resonator,
                                             transformation=this_transform)
                    all_components.append(this_resonator)
                else:
                    # sum previous elements of the shifting list for correct relative translation
                    total_shift = sum(shifting_list[:(ring + 1)])

                    this_transform = i3.Translation(
                        ((res_x_dim + ring_core_width) * ring + total_shift,
                         0.))
                    this_resonator = i3.SRef(name="R_" + str(ring),
                                             reference=self.resonator,
                                             transformation=this_transform)
                    all_components.append(this_resonator)

            return all_components

        def _generate_instances(self, insts):
            # includes the get components and the waveguides
            the_rings = self._get_components()
            insts += the_rings
            wg_in_layout, wg_pass_layout = self.wgs  #  wg_pass_layout, wg_ring_layout
            insts += i3.SRef(reference=wg_in_layout, name="wg_in")

            # ok so now I grab the last ring from the rings and use it to determine its position
            last_ring = the_rings[-1]
            east_side_ring = last_ring.size_info().east

            # and I get the waveguide properties for ring and coupler, to give correct outside gap
            ring_core_width = self.wg_ring_template.core_width
            ring_clad_width = self.wg_ring_template.cladding_width

            bus_wg_core_width = self.wg_coupler_template.core_width
            bus_wg_clad_width = self.wg_coupler_template.cladding_width

            final_x_spot = (east_side_ring - ring_clad_width/2.) + ring_core_width/2. \
                           + self.external_gap + bus_wg_core_width/2.

            # rather than making a new waveguide we can mirror the previous structure into the final position
            # thus we need to determine the difference in the core position of the original structure
            # with the *negative* position of the final x position, and then the mirror will flip it around
            bus_core_pos = wg_in_layout.size_info(
            ).east - bus_wg_clad_width / 2.

            # now we translate the original structure to the desired negative position, and horizontally mirror around 0
            output_transformation = i3.HMirror() + i3.Translation(
                (-1. * (-final_x_spot - bus_core_pos), 0.))

            # finally we perform the SRef on the previous layout and transform it with a new name
            insts += i3.SRef(reference=wg_in_layout,
                             name="wg_out",
                             transformation=output_transformation)

            return insts

        def _generate_ports(self, prts):
            # try to reuse the output waveguides following the example and change the names, looks good
            instances = self.instances
            prts += instances["wg_in"].ports["in"].modified_copy(name="in1")
            prts += instances["wg_in"].ports["out"].modified_copy(name="in2")
            prts += instances["wg_out"].ports["in"].modified_copy(name="out1")
            prts += instances["wg_out"].ports["out"].modified_copy(name="out2")
            return prts
Beispiel #5
0
    class Layout(i3.LayoutView):

        # Properties -------

        # taper to draw
        # taper_prop_dict = i3.DictProperty( default = {}, doc = 'Dictionary of taper cell properties.' + \
        #                                    'Properties = "length", "width1", "width2", "width_etch" ' )

        # connecting length between tapers
        # connect_length = i3.NumberProperty( default=0.0, doc='distance between tapers' )

        # connecting length between taper PAIRS
        # pair_connect_length = i3.NumberProperty( default=0.0, doc='distance between taper pairs' )

        # number of taper pairs
        n_pairs = i3.IntProperty(default=1, doc='number of taper pairs')

        # Methods -------

        def _generate_instances(self, insts):
            # Generates taper pairs

            tp_name_list = []

            # temporary? pick taper properties
            taper_prop_dict = {
                'length': 79.0,
                'width1': 0.50,
                'width2': 6.50,
                'width_etch': 2.0
            }

            # generate a huge taper row
            tp_rows_layout = TaperPairRow().Layout(
                taper_prop_dict=taper_prop_dict,
                connect_length=0.0,
                pair_connect_length=10.0,
                n_pairs=self.n_pairs)

            # load the aim gds just to get its positions and stuff
            # main chip GDS
            fname = os.path.dirname(
                os.path.realpath(__file__)) + '/gds/ap_suny_v20a_chipframe.gds'
            main_chip_gds_cell = i3.GDSCell(filename=fname)

            # grab layout size info
            main_chip_gds_lay = main_chip_gds_cell.Layout()
            main_chip_gds_lay_size_info = main_chip_gds_lay.size_info()

            # grab relevant positions
            chip_edge_east = main_chip_gds_lay_size_info.east
            chip_edge_west = main_chip_gds_lay_size_info.west

            # make edge coupler and add to layout
            # edge coupler
            edge_coupler_gds_lay = EdgeCoupler(name=self.name +
                                               'edge_coupler_si').Layout()

            # add and route input/west edgecoupler
            # position edge coupler on west side of chip
            chip_port_west = i3.OpticalPort(position=(chip_edge_west, 0.0),
                                            angle_deg=0.0)
            edge_coupler_west_port = edge_coupler_gds_lay.ports['out']
            t = i3.vector_match_transform(edge_coupler_west_port,
                                          chip_port_west)
            edge_coupler_west_name = self.name + '_EDGE_COUPLER_WEST'
            west_edge_coupler = i3.SRef(name=edge_coupler_west_name,
                                        reference=edge_coupler_gds_lay,
                                        transformation=t,
                                        flatten=False)

            # add a small linear taper to go from 0.4 to 0.5um wg
            lin_taper_lay = LinearTaper().get_default_view(i3.LayoutView)
            lin_taper_lay.set(wg_width_in=0.4, wg_width_out=0.5, length=10.0)
            t = i3.vector_match_transform(lin_taper_lay.ports['in'],
                                          west_edge_coupler.ports['in'])
            lin_taper_lay_name = self.name + '_EDGETAPER_WEST'
            insts += i3.SRef(name=lin_taper_lay_name,
                             reference=lin_taper_lay,
                             transformation=t,
                             flatten=True)

            # add taper rows
            taper_row_name = self.name + '_TAPERSSSSSSSS'
            t = i3.vector_match_transform(
                tp_rows_layout.ports['left'],
                insts[lin_taper_lay_name].ports['out'])
            insts += i3.SRef(name=taper_row_name,
                             reference=tp_rows_layout,
                             transformation=t,
                             flatten=True)

            # add east coupler
            chip_port_east = i3.OpticalPort(position=(chip_edge_east, 0.0),
                                            angle_deg=180.0)
            edge_coupler_east_port = edge_coupler_gds_lay.ports['out']
            t = i3.vector_match_transform(edge_coupler_east_port,
                                          chip_port_east,
                                          mirrored=True)
            edge_coupler_east_name = self.name + '_EDGE_COUPLER_EAST'
            east_edge_coupler = i3.SRef(name=edge_coupler_east_name,
                                        reference=edge_coupler_gds_lay,
                                        transformation=t,
                                        flatten=False)

            # add a small linear taper to go from 0.4 to 0.5um wg
            lin_taper_lay = LinearTaper().get_default_view(i3.LayoutView)
            lin_taper_lay.set(wg_width_in=0.4, wg_width_out=0.5, length=10.0)
            t = i3.vector_match_transform(lin_taper_lay.ports['in'],
                                          east_edge_coupler.ports['in'],
                                          mirrored=True)
            lin_taper_lay_name = self.name + '_EDGETAPER_EAST'
            insts += i3.SRef(name=lin_taper_lay_name,
                             reference=lin_taper_lay,
                             transformation=t,
                             flatten=True)

            # route the east coupler to the east edge of the taper pairs
            route_wg_row_taper = i3.Shape([
                insts[taper_row_name].ports['right'].position,
                insts[lin_taper_lay_name].ports['out'].position
            ])
            wg_name = self.name + '_WG'
            wg_lay = i3.Waveguide(trace_template=StripWgTemplate(),
                                  name=wg_name).get_default_view(i3.LayoutView)
            wg_lay.set(shape=route_wg_row_taper)
            insts += i3.SRef(name=wg_name, reference=wg_lay, flatten=True)

            return insts

        # end _generate_instances()

        def _generate_ports(self, ports):
            # add ports 'left' and 'right'

            # left port
            ports += i3.OpticalPort(
                name='left',
                position=self.instances[
                    self.name + '_EDGETAPER_WEST'].ports['in'].position,
                angle=180.0)

            # right port
            ports += i3.OpticalPort(
                name='right',
                position=self.instances[
                    self.name + '_EDGETAPER_EAST'].ports['out'].position,
                angle=0.0)

            return ports
Beispiel #6
0
    class Layout(i3.LayoutView):

        # Properties -------

        # taper to draw
        taper_prop_dict = i3.DictProperty( default = {}, doc = 'Dictionary of taper cell properties.' + \
                                           'Properties = "length", "width1", "width2", "width_etch" ' )

        # connecting length between tapers
        connect_length = i3.NumberProperty(default=0.0,
                                           doc='distance between tapers')

        # connecting length between taper PAIRS
        pair_connect_length = i3.NumberProperty(
            default=0.0, doc='distance between taper pairs')

        # number of taper pairs
        n_pairs = i3.IntProperty(default=1, doc='number of taper pairs')

        # Methods -------

        def _generate_instances(self, insts):
            # Generates taper pairs

            tp_name_list = []

            for ii in range(self.n_pairs):
                # for each pair

                # draw taper pair layout
                tp_lay = TaperPair(name=self.name + '_tp' +
                                   str(ii)).get_default_view(i3.LayoutView)
                tp_lay.set(taper_prop_dict=self.taper_prop_dict,
                           connect_length=self.connect_length)

                # set name
                tp_name = 'tp' + str(ii)
                tp_name_list.append(tp_name)

                # set transformation
                if ii > 0:

                    # set transform
                    t = i3.vector_match_transform(  tp_lay.ports['left'],
                                                    insts[ tp_name_list[ii - 1] ].ports['right']) \
                                                    + i3.Translation( ( self.pair_connect_length, 0.0 ) )

                    # print t

                    # draw next taper pair
                    insts += i3.SRef(name=tp_name,
                                     reference=tp_lay,
                                     transformation=t)

                    # route wg
                    route_wg = i3.RouteManhattan(
                        input_port=insts[tp_name_list[ii - 1]].ports['right'],
                        output_port=insts[tp_name_list[ii]].ports['left'])

                    # # make my OWN custom waveguide trace template
                    # wg_trace = f_MyIMECWaveguideTemplate( core_width = self.taper_prop_dict['width1'],
                    #                                       cladding_width = self.taper_prop_dict['width1'] + 2.0*self.taper_prop_dict['width_etch'] )

                    # make waveguide
                    wg = i3.Waveguide(trace_template=StripWgTemplate(),
                                      name=self.name + '_WG' + str(ii))

                    # add wg
                    insts += i3.SRef(name=self.name + 'connect_wg' + str(ii),
                                     reference=wg.Layout(shape=route_wg))

                else:
                    # draw first taper pair
                    insts += i3.SRef(name=tp_name, reference=tp_lay)

                    # DEBUG
                    # print insts

                # end if else

            return insts

        # end _generate_instances()

        def _generate_ports(self, ports):
            # add ports 'left' and 'right'

            # left port
            ports += i3.OpticalPort(
                name='left',
                position=self.instances['tp0'].ports['left'].position,
                angle=180.0)

            # right port
            ports += i3.OpticalPort(
                name='right',
                position=self.instances['tp' + str(self.n_pairs -
                                                   1)].ports['right'].position,
                angle=0.0)

            return ports
Beispiel #7
0
class Spirals(PlaceAndAutoRoute):

    _name_prefix = 'LSpiral'

    tipo = i3.PositiveNumberProperty(doc="Number loops", default=1)

    waveguide_template = i3.DefinitionProperty(doc="Trace template used")
    R = i3.PositiveNumberProperty(default=500, doc="Radius of curvature")
    spacing = i3.PositiveNumberProperty(default=100, doc="Radius of curvature")
    n_loops = i3.IntProperty(doc="Number loops", default=2)
    n_loops_vec = i3.ListProperty(default=[4, 8])
    s_length_vec = i3.ListProperty(default=[0.0])
    #Spiral_list = i3.ChildCellListProperty(doc="List containing the 90 degree angle child cells")
    #chip_length = i3.PositiveNumberProperty(default=12000.0, doc="")
    chip_length = i3.PositiveNumberProperty(default=13000.0, doc="")
    Port = i3.ChildCellProperty(doc="Used for ports")
    tlport = i3.PositiveNumberProperty(default=2000.0,
                                       doc="Transition legth to ports")
    couplingWG = i3.ChildCellProperty(doc="", locked=True)
    couplingWG_l = i3.PositiveNumberProperty(default=5000.0,
                                             doc="Length of the coupling WG ")
    tt_port = i3.TraceTemplateProperty(
        doc="Wide trace template used for the contacts")

    #width_vec = i3.ListProperty(default=[1])
    n = i3.PositiveNumberProperty(default=1, doc="")
    width = i3.PositiveNumberProperty(default=1, doc="")
    lengths = i3.PositiveNumberProperty(default=1, doc="")

    def _default_lengths(self):
        for counter, cell in enumerate(self.s_length_vec):
            numero = counter + 1
        return numero

    #template for Autorute
    def _default_trace_template(self):
        return self.waveguide_template

    def _default_tt(self):
        return self.waveguide_template

    def _default_tt_port(self):
        tt_port = WireWaveguideTemplate()
        tt_port_layout = tt_port.Layout(core_width=15.0,
                                        cladding_width=15.0 + 2 * 8.0)
        return tt_port

    def _default_couplingWG(self):
        rect = i3.Waveguide(trace_template=self.tt_port)
        layout_rect = rect.Layout(shape=[(0.0, 0.0), (self.couplingWG_l, 0.0)])
        return rect

    def _default_Port(self):
        Port = AutoTransitionPorts(contents=self.couplingWG,
                                   port_labels=["in"],
                                   trace_template=self.waveguide_template)
        layout_Port = Port.Layout(
            transition_length=self.tlport)  #.visualize(annotate=True)
        return Port

    def _default_child_cells(self):
        child_cells = {
        }  # First we define the property "child_cells" as  an empty dictionary

        for counter, length in enumerate(
                self.s_length_vec
        ):  # the iteration starts in the first element of the list and follows element by element to the last element.

            #child_cells['Spiral{}'.format(counter)] = spiral
            #print spiral
            #print 'name of spiral:', spiral.name
            child_cells['InPort' + str(counter)] = self.Port
            child_cells['OutPort' + str(counter)] = self.Port

            print 'child_cells:', child_cells
        return child_cells

    def _default_links(self):
        links = []
        for counter, spiral in enumerate(self.s_length_vec):
            print counter
            #in_port = "Spiral{}:in".format(counter)
            in_port = "InPort{}:in".format(counter)
            #links.append((in_port, out_port))
            #in_port = "Spiral{}:out".format(counter)
            out_port = "OutPort{}:in".format(counter)
            links.append((in_port, out_port))

        return links

    class Layout(PlaceAndAutoRoute.Layout):
        #tipo=1

        def _default_bend_radius(self):
            return self.R

        def _default_child_transformations(self):
            d = {}
            for counter, child in enumerate(self.s_length_vec):
                #ip= child.ports["in"].position
                #print self.child_cells['InPort' + str(counter)].ports["out"].position
                #print self.child_cells['OutPort' + str(counter)].ports.position
                print '----------------'

                #print 'spiral length:', child.total_length
                print 'counter: ', counter
                print 'self.n = ', self.n
                print 'self.width: ', self.width
                #print 'sx: ', sx

                if self.tipo == 1:
                    sx = 70
                    a = 0.5
                    print 2 * (22362 * 0.5 - self.couplingWG_l)
                    print 'tipo = ', self.tipo

                    #d['Spiral' + str(counter)] = i3.Translation(translation=(-(op[0]-ip[0])/2, self.n*counter*sx))
                    #d['InPort' + str(counter)] = i3.HMirror()+ i3.Translation(translation=(-self.chip_length*0.5, (self.n+a)*counter*sx))
                    #d['OutPort' + str(counter)] = i3.Translation(translation=(self.chip_length*0.5, (self.n+a)*counter*sx))

                    d['InPort' + str(counter)] = i3.HMirror() + i3.Translation(
                        translation=(-22362 * 0.5 + self.couplingWG_l,
                                     (self.n + a) * counter * sx))
                    d['OutPort' + str(counter)] = i3.Translation(
                        translation=(22362 * 0.5 - self.couplingWG_l,
                                     (self.n + a) * counter * sx))

                #if self.tipo==2:
                #d['Spiral' + str(counter)] = i3.Translation(translation=(-(op[0]-ip[0])/2, -(self.n+0.5)*counter*sx))
                #d['InPort' + str(counter)] = i3.HMirror()+ i3.Translation(translation=(-self.chip_length*(3/4)-self.couplingWG_l, -(self.n+0.5)*counter*sx))
                #d['OutPort' + str(counter)] = i3.Rotation(rotation=90) + i3.Translation(translation=((op[0]-ip[0])/2+2*self.R+(((self.n+0.5)*counter+self.width)*sx/4), self.chip_length*(3/4)+(self.width+counter-(((counter+1)-1.0)%self.lengths))*sx))
                if self.tipo == 2:
                    sx = 100
                    #d['Spiral' + str(counter)] = i3.Translation(translation=(-(op[0]-ip[0])/2, -(self.n+1)*counter*sx))
                    a = 7.0
                    print 'increment of length between waveguides of same width: ', (
                        self.n + a) * 1 * sx + ((self.n + a) * 1 + 0) * sx
                    print 'increment of length between waveguides of same length group: ', (
                        self.n + a) * 0 * sx + (
                            (self.n + a) * 0 + self.width) * sx

                    d['InPort' + str(counter)] = i3.HMirror() + i3.Translation(
                        translation=(0.0 - self.chip_length * 0.5,
                                     -(self.n + a) * counter * sx))
                    d['OutPort' + str(counter)] = i3.Rotation(
                        rotation=90) + i3.Translation(translation=(
                            (((self.n + a) * counter + self.width) * sx),
                            self.chip_length * 0.5 +
                            (self.width + counter -
                             (((counter + 1) - 1.0) % self.lengths)) * sx))

            return d

        # Fabio's addition
        def _generate_elements(self, elems):
            # We calculate the lengths of the 2 spirals in this pcell.
            # Note that we assume that there are exactly 2 spirals in this list.
            #assert len(self.Spiral_list) == 2
            lengths = get_lengths(self)[0]
            print lengths
            Link = get_lengths(self)[1]
            print Link
            if self.tipo == 1:

                sx = 70
                for counter, (child, length) in enumerate(
                        zip(self.s_length_vec, lengths)):
                    #ip= child.ports["in"].position
                    #op= child.ports["out"].position

                    width = Link.trace_template.core_width
                    #print 'child.ports["in"].trace_template.core_width: ', child.ports["in"].trace_template.core_width
                    a = 0.5
                    #i3.TECH.PPLAYER.NONE.LOGOTXT   when using isipp50g
                    elems += i3.PolygonText(
                        layer=i3.TECH.PPLAYER.WG.TEXT,
                        text='Width={}'.format(width, ),
                        coordinate=(-self.chip_length * 0.5 + 2 * self.tlport,
                                    (self.n + a) * counter * sx - 15.0),
                        alignment=(i3.TEXT_ALIGN_LEFT, i3.TEXT_ALIGN_LEFT),
                        font=2,
                        height=20.0)

                    elems += i3.PolygonText(
                        layer=i3.TECH.PPLAYER.WG.TEXT,
                        text='Width={}'.format(width, ),
                        coordinate=(0.0, (self.n + a) * counter * sx - 15.0),
                        alignment=(i3.TEXT_ALIGN_LEFT, i3.TEXT_ALIGN_LEFT),
                        font=2,
                        height=20.0)

                    elems += i3.PolygonText(
                        layer=i3.TECH.PPLAYER.WG.TEXT,
                        text='Width={}'.format(width, ),
                        coordinate=(self.chip_length * 0.5 - 2 * self.tlport,
                                    (self.n + a) * counter * sx - 15.0),
                        alignment=(i3.TEXT_ALIGN_LEFT, i3.TEXT_ALIGN_LEFT),
                        font=2,
                        height=20.0)

            if self.tipo == 2:
                sx = 100
                for counter, (child, length) in enumerate(
                        zip(self.s_length_vec, lengths)):
                    #ip= child.ports["in"].position
                    #op= child.ports["out"].position

                    width = Link.trace_template.core_width
                    #print 'child.ports["in"].trace_template.core_width: ', child.ports["in"].trace_template.core_width
                    a = 7.0
                    #i3.TECH.PPLAYER.NONE.LOGOTXT   when using isipp50g
                    elems += i3.PolygonText(
                        layer=i3.TECH.PPLAYER.WG.TEXT,
                        text='Width={}_Length={}_R={}'.format(
                            width, length, self.R),
                        coordinate=(-1500,
                                    -(self.n + a) * counter * sx - 55.0),
                        alignment=(i3.TEXT_ALIGN_LEFT, i3.TEXT_ALIGN_LEFT),
                        font=2,
                        height=20.0)
            return elems
Beispiel #8
0
    class Layout(i3.LayoutView):

        # Properties -------

        # number of bend pairs
        n_pairs = i3.IntProperty(default=1, doc='number of bend pairs')

        # Methods -------

        def _generate_instances(self, insts):
            # Generates bend pairs

            tp_name_list = []

            # arc path
            fname = '../nathan/bend_data/txbend.txt'
            path_width = np.loadtxt(fname, np.float_)
            arc_path = path_width[:, :2]

            # make a bend woo
            bend_wg_lay = i3.Waveguide(
                name=self.name + "_Bend",
                trace_template=StripWgTemplate()).get_default_view(
                    i3.LayoutView)
            bend_wg_lay.set(shape=arc_path)

            # add to insts
            insts += i3.SRef(name=self.name + '_BEND', reference=bend_wg_lay)

            # list of bend names
            bend_name_A_list = []
            bend_name_B_list = []

            # draw a bunch of bends
            for ii in range(self.n_pairs):

                # make bend A
                if ii == 0:
                    # place first bend pair

                    # make a bend woo
                    bend_name_A = self.name + '_BEND_A' + str(ii)
                    bend_wg_lay_A = i3.Waveguide(
                        trace_template=StripWgTemplate()).get_default_view(
                            i3.LayoutView)
                    bend_wg_lay_A.set(shape=arc_path)

                    # add to insts
                    insts += i3.SRef(name=bend_name_A,
                                     reference=bend_wg_lay_A,
                                     flatten=True)

                else:

                    # make a bend woo
                    bend_name_A = self.name + '_BEND_A' + str(ii)
                    bend_wg_lay_A = i3.Waveguide(
                        trace_template=StripWgTemplate()).get_default_view(
                            i3.LayoutView)
                    bend_wg_lay_A.set(shape=arc_path)

                    # add to insts
                    t = i3.vector_match_transform(
                        bend_wg_lay_A.ports['in'],
                        insts[bend_name_B_list[ii - 1]].ports['out'],
                        mirrored=False)
                    insts += i3.SRef(name=bend_name_A,
                                     reference=bend_wg_lay_A,
                                     transformation=t,
                                     flatten=True)

                # make another bend woo
                bend_name_B = self.name + '_BEND_B' + str(ii)
                bend_wg_lay_B = i3.Waveguide(
                    trace_template=StripWgTemplate()).get_default_view(
                        i3.LayoutView)
                bend_wg_lay_B.set(shape=arc_path)

                # add to insts
                t = i3.vector_match_transform(bend_wg_lay_B.ports['in'],
                                              insts[bend_name_A].ports['out'],
                                              mirrored=True)
                insts += i3.SRef(name=bend_name_B,
                                 reference=bend_wg_lay_B,
                                 transformation=t,
                                 flatten=True)

                # end if else

                # append bend names
                bend_name_A_list.append(bend_name_A)
                bend_name_B_list.append(bend_name_B)

            # end for loop

            return insts

        # end _generate_instances()

        def _generate_ports(self, ports):
            # add ports 'left' and 'right'

            # left port
            ports += i3.OpticalPort(
                name='in',
                position=self.instances[self.name +
                                        '_BEND_A0'].ports['in'].position,
                angle=0.0)

            # right port
            ports += i3.OpticalPort(
                name='out',
                position=self.instances[self.name + '_BEND_B' +
                                        str(self.n_pairs -
                                            1)].ports['out'].position,
                angle=180.0)

            return ports
class SpiralWgLossEbeam(PlaceAndAutoRoute):
    ## generate segmented FBMS line
    spiral = i3.ChildCellProperty()
    taper = i3.ChildCellProperty()
    wg = i3.ChildCellProperty()
    wg_right = i3.ChildCellProperty()
    expanded_wg = i3.ChildCellProperty()
    trace_template = i3.WaveguideTemplateProperty()
    expanded_wg_template = i3.WaveguideTemplateProperty()

    wg_width = i3.PositiveNumberProperty(default=2.0)
    trench_width = i3.PositiveNumberProperty(default=3.0)
    _wg_width_indesign = i3.PositiveNumberProperty()
    expanded_wg_width = i3.PositiveNumberProperty(default=3.0)
    _expanded_wg_width_indesign = i3.PositiveNumberProperty()
    spiral_length = i3.PositiveNumberProperty(default=10000.0)
    n_o_loops = i3.IntProperty(default=2)

    def _default__wg_width_indesign(self):
        return self.wg_width

    def _default__expanded_wg_width_indesign(self):
        return self.expanded_wg_width

    def _default_trace_template(self):
        wstart1 = PathTraceWindow(layer=i3.TECH.PPLAYER.WG.CORE,
                                  start_offset=-self.wg_width * 0.5,
                                  end_offset=self.wg_width * 0.5)
        wstart2 = PathTraceWindow(
            layer=i3.TECH.PPLAYER.WG.CLADDING,
            start_offset=-(self.wg_width + self.trench_width) * 0.5,
            end_offset=-(self.wg_width + self.trench_width) * 0.5,
            line_width=0)
        wstart3 = PathTraceWindow(
            layer=i3.TECH.PPLAYER.WG.CLADDING,
            start_offset=(self.wg_width + self.trench_width) * 0.5,
            end_offset=(self.wg_width + self.trench_width) * 0.5,
            line_width=0)
        wg_t = i3.WindowWaveguideTemplate()
        wg_t.Layout(windows=[wstart1, wstart2, wstart3])
        return wg_t

    def _default_expanded_wg_template(self):
        wstart1 = PathTraceWindow(layer=i3.TECH.PPLAYER.WG.CORE,
                                  start_offset=-self.expanded_wg_width * 0.5,
                                  end_offset=self.expanded_wg_width * 0.5)
        wstart2 = PathTraceWindow(
            layer=i3.TECH.PPLAYER.WG.CLADDING,
            start_offset=-(self.expanded_wg_width + self.trench_width) * 0.5,
            end_offset=-(self.expanded_wg_width + self.trench_width) * 0.5,
            line_width=0)
        wstart3 = PathTraceWindow(
            layer=i3.TECH.PPLAYER.WG.CLADDING,
            start_offset=(self.expanded_wg_width + self.trench_width) * 0.5,
            end_offset=(self.expanded_wg_width + self.trench_width) * 0.5,
            line_width=0)
        expanded_wg_template = i3.WindowWaveguideTemplate()
        expanded_wg_template.Layout(windows=[wstart1, wstart2, wstart3])
        return expanded_wg_template

    def _default_wg(self):
        wg = i3.RoundedWaveguide(trace_template=self.trace_template)
        return wg

    def _default_wg_right(self):
        wg_right = i3.RoundedWaveguide(trace_template=self.trace_template)
        return wg_right

    def _default_spiral(self):
        spiral = FixedLengthSpiralRounded(total_length=self.spiral_length,
                                          n_o_loops=self.n_o_loops,
                                          trace_template=self.trace_template)
        return spiral

    def _default_expanded_wg(self):
        expanded_wg = i3.RoundedWaveguide(
            trace_template=self.expanded_wg_template)
        return expanded_wg

    def _default_taper(self):
        taper = LinearWindowWaveguideTransition(
            start_trace_template=self.trace_template,
            end_trace_template=self.expanded_wg_template)
        return taper

    def _default_child_cells(self):
        child_cells = dict()
        child_cells["spiral"] = self.spiral
        child_cells["taper_left"] = self.taper
        child_cells["taper_right"] = self.taper
        child_cells["wg_left"] = self.wg
        child_cells["wg_right"] = self.wg_right
        child_cells["expanded_wg_left"] = self.expanded_wg
        child_cells["expanded_wg_right"] = self.expanded_wg
        return child_cells

    def _default_external_port_names(self):
        ports = dict()
        ports["expanded_wg_right:out"] = "in"
        ports["expanded_wg_left:out"] = "out"
        return ports

    class Layout(PlaceAndAutoRoute.Layout):
        spiral_width = i3.PositiveNumberProperty(
            doc="total width of spiral structure", default=6000.0)
        right_wg_length = i3.PositiveNumberProperty(
            doc="length of narrow wg on the right side of spiral",
            default=500.0)
        expanded_wg_length = i3.PositiveNumberProperty(default=5000.0)
        taper_length = i3.PositiveNumberProperty(default=300.0)
        bend_radius = i3.PositiveNumberProperty(default=100.0)
        gap = i3.PositiveNumberProperty(doc="distance between two trenches",
                                        default=3.0)
        _spacing_indesign = i3.PositiveNumberProperty()

        def _default__spacing_indesign(self):
            return self.gap + self.trench_width * 2 + self.wg_width

        def _default_spiral(self):
            spiral_lo = self.cell.spiral.get_default_view(i3.LayoutView)
            spiral_lo.set(incoupling_length=0,
                          bend_radius=self.bend_radius,
                          spacing=self._spacing_indesign,
                          growth_direction="H",
                          stub_direction="H")
            return spiral_lo

        def _default_wg(self):
            wg_lo = self.cell.wg.get_default_view(i3.LayoutView)
            wg_lo.set(shape=[(
                0.0,
                0.0), (self.spiral_width - self._spiral_in_out_distance(), 0)])
            return wg_lo

        def _spiral_in_out_distance(self):
            return self.spiral.ports["out"].position.x - self.spiral.ports[
                "in"].position.x

        def _default_wg_right(self):
            wg_right_lo = self.cell.wg_right.get_default_view(i3.LayoutView)
            wg_right_lo.set(shape=[(0.0, 0.0), (self.right_wg_length, 0)])
            return wg_right_lo

        def _default_taper(self):
            taper_lo = self.cell.taper.get_default_view(i3.LayoutView)
            taper_lo.set(start_position=(0.0, 0.0),
                         end_position=(self.taper_length, 0.0))
            return taper_lo

        def _default_expanded_wg(self):
            expanded_wg_lo = self.cell.expanded_wg.get_default_view(
                i3.LayoutView)
            expanded_wg_lo.set(shape=[(0.0, 0.0), (self.expanded_wg_length,
                                                   0.0)])
            return expanded_wg_lo

        def _default_child_transformations(self):
            trans = dict()
            trans["spiral"] = (-self._spiral_in_out_distance(), 0.0)
            trans["wg_right"] = (0.0, 0.0)
            trans["taper_right"] = i3.Translation((self.right_wg_length, 0))
            trans["expanded_wg_right"] = i3.Translation(
                (self.right_wg_length + self.taper_length, 0))
            trans["wg_left"] = i3.HMirror(mirror_plane_x=0.0) + i3.Translation(
                (-self._spiral_in_out_distance(), 0))
            trans["taper_left"] = i3.HMirror(
                mirror_plane_x=0.0) + i3.Translation((-self.spiral_width, 0))
            trans["expanded_wg_left"] = i3.HMirror(
                mirror_plane_x=0.0) + i3.Translation(
                    (-self.spiral_width - self.taper_length, 0))
            return trans

        def get_true_length(self):
            return self.spiral_width - self._spiral_in_out_distance(
            ) + self.right_wg_length + self.spiral_length
    class Layout(i3.LayoutView):

        # Properties -------

        # number of taper pairs
        n_pairs = i3.IntProperty(default=1, doc='number of taper pairs')

        # Methods -------

        def _generate_instances(self, insts):
            # Generates taper pairs w edge couplers

            # load the aim gds just to get its positions and stuff
            # main chip GDS
            fname = '../PDK_Library_Layout_GDS/ap_suny_v20a_chipframe.gds'
            main_chip_gds_cell = i3.GDSCell(filename=fname)

            # grab layout size info
            main_chip_gds_lay = main_chip_gds_cell.Layout()
            main_chip_gds_lay_size_info = main_chip_gds_lay.size_info()

            # grab relevant positions
            chip_edge_east = main_chip_gds_lay_size_info.east
            chip_edge_west = main_chip_gds_lay_size_info.west

            # make edge coupler
            edge_coupler_gds_lay = EdgeCoupler(name=self.name +
                                               'edge_coupler_sffdfi').Layout()

            # add and route input/west edgecoupler
            # position edge coupler on west side of chip
            chip_port_west = i3.OpticalPort(position=(chip_edge_west, 0.0),
                                            angle_deg=0.0)
            edge_coupler_west_port = edge_coupler_gds_lay.ports['out']
            t = i3.vector_match_transform(edge_coupler_west_port,
                                          chip_port_west)
            edge_coupler_west_name = self.name + '_EDGE_COUPLER_WEST'
            west_edge_coupler = i3.SRef(name=edge_coupler_west_name,
                                        reference=edge_coupler_gds_lay,
                                        transformation=t,
                                        flatten=False)

            # add a small linear taper to go from 0.4 to 0.5um wg
            lin_taper_lay = LinearTaper().get_default_view(i3.LayoutView)
            lin_taper_lay.set(wg_width_in=0.4, wg_width_out=0.5, length=10.0)
            t = i3.vector_match_transform(lin_taper_lay.ports['in'],
                                          west_edge_coupler.ports['in'])
            lin_taper_lay_name = self.name + '_EDGETAPER_WEST'
            insts += i3.SRef(name=lin_taper_lay_name,
                             reference=lin_taper_lay,
                             transformation=t,
                             flatten=True)

            # route wg to wg with arc
            bend_radius = 10.0
            arc_center_1 = (
                insts[lin_taper_lay_name].ports['out'].position[0],
                insts[lin_taper_lay_name].ports['out'].position[1] +
                bend_radius)
            route_wg_shape_arc1 = i3.ShapeArc(radius=bend_radius,
                                              angle_step=1.0,
                                              center=arc_center_1,
                                              start_angle=269.5,
                                              end_angle=0.5,
                                              closed=False,
                                              clockwise=False)
            wg_name_arc1 = self.name + '_ARC1'
            wg_lay_arc1 = i3.Waveguide(trace_template=StripWgTemplate(),
                                       name=wg_name_arc1).get_default_view(
                                           i3.LayoutView)
            wg_lay_arc1.set(shape=route_wg_shape_arc1)
            insts += i3.SRef(name=wg_name_arc1,
                             reference=wg_lay_arc1,
                             flatten=True)

            # add the bends
            bend_clip_lay = BendClip(
                name=self.name + '_BEND_CLIP').get_default_view(i3.LayoutView)
            bend_clip_lay.set(n_pairs=self.n_pairs)

            # add to insts
            bend_clip_lay_name = self.name + '_BEND_CLIP'
            t = i3.vector_match_transform(bend_clip_lay.ports['in'],
                                          insts[wg_name_arc1].ports['out'])
            insts += i3.SRef(name=bend_clip_lay_name,
                             reference=bend_clip_lay,
                             transformation=t,
                             flatten=True)

            # add output bend
            arc_center_2 = (
                insts[bend_clip_lay_name].ports['out'].position[0] +
                bend_radius,
                insts[bend_clip_lay_name].ports['out'].position[1])
            route_wg_shape_arc2 = i3.ShapeArc(radius=bend_radius,
                                              angle_step=1.0,
                                              center=arc_center_2,
                                              start_angle=180.5,
                                              end_angle=89.5,
                                              closed=False,
                                              clockwise=True)
            wg_name_arc2 = self.name + '_ARC2'
            wg_lay_arc2 = i3.Waveguide(trace_template=StripWgTemplate(),
                                       name=wg_name_arc2).get_default_view(
                                           i3.LayoutView)
            wg_lay_arc2.set(shape=route_wg_shape_arc2)
            insts += i3.SRef(name=wg_name_arc2,
                             reference=wg_lay_arc2,
                             flatten=True)

            # add east coupler
            chip_port_east = i3.OpticalPort(
                position=(chip_edge_east,
                          insts[wg_name_arc2].ports['out'].position[1]),
                angle_deg=180.0)
            edge_coupler_east_port = edge_coupler_gds_lay.ports['out']
            t = i3.vector_match_transform(edge_coupler_east_port,
                                          chip_port_east,
                                          mirrored=True)
            edge_coupler_east_name = self.name + '_EDGE_COUPLER_EAST'
            east_edge_coupler = i3.SRef(name=edge_coupler_east_name,
                                        reference=edge_coupler_gds_lay,
                                        transformation=t,
                                        flatten=False)

            # add a small linear taper to go from 0.4 to 0.5um wg
            lin_taper_lay = LinearTaper().get_default_view(i3.LayoutView)
            lin_taper_lay.set(wg_width_in=0.4, wg_width_out=0.5, length=10.0)
            t = i3.vector_match_transform(lin_taper_lay.ports['in'],
                                          east_edge_coupler.ports['in'],
                                          mirrored=True)
            lin_taper_lay_name = self.name + '_EDGETAPER_EAST'
            insts += i3.SRef(name=lin_taper_lay_name,
                             reference=lin_taper_lay,
                             transformation=t,
                             flatten=True)

            # route arc to arc with straight section
            route_wg_shape_out = i3.Shape([
                insts[wg_name_arc2].ports['out'].position,
                insts[lin_taper_lay_name].ports['out'].position
            ])
            wg_name_out = self.name + '_WG_CON_OUT'
            wg_lay_out = i3.Waveguide(trace_template=StripWgTemplate(),
                                      name=wg_name_out).get_default_view(
                                          i3.LayoutView)
            wg_lay_out.set(shape=route_wg_shape_out)
            insts += i3.SRef(name=wg_name_out,
                             reference=wg_lay_out,
                             flatten=True)

            return insts

        # end _generate_instances()

        def _generate_ports(self, ports):
            # add ports 'left' and 'right'

            # left port
            ports += i3.OpticalPort(
                name='in',
                position=self.instances[
                    self.name + '_EDGETAPER_WEST'].ports['in'].position,
                angle=180.0)

            # right port
            ports += i3.OpticalPort(
                name='out',
                position=self.instances[
                    self.name + '_EDGETAPER_EAST'].ports['out'].position,
                angle=0.0)

            return ports
    class Layout(i3.LayoutView):
        """
        Alignment mark layout view.
        """

        # Specify two layers on which markers are drawn
        process1 = i3.ProcessProperty(default=i3.TECH.PPLAYER.CH2.TRENCH)#i3.TECH.PROCESS.CHANNEL_1, doc="Process Layer 1")  #was i3.TECH.PROCESS.WG
        process2 = i3.ProcessProperty(default=i3.TECH.PPLAYER.CH1.TRENCH)#i3.TECH.PROCESS.CHANNEL_2, doc="Process Layer 2")

        # Properties of crosses
        dark_cross_bar_width = i3.PositiveNumberProperty(default=30, doc="width of the dark cross")
        open_cross_bar_width = i3.PositiveNumberProperty(default=40, doc="width of the open cross")
        cross_boundary_width = i3.PositiveNumberProperty(default=150, doc="width of the cross boundary box")
    
        # Basic properties of Vernier scales
        vern_spacing_short = i3.PositiveNumberProperty(default=18, doc="spacing between bars of shorter vernier scale")
        vern_spacing_long = i3.PositiveNumberProperty(default=18.5, doc="spacing between bars of longer vernier scale")
        vern_number_of_bar = i3.IntProperty(default=13, doc="the number of vernier bars")
    
        # Detailed properties of Vernier scales
        vern_bar_length = i3.PositiveNumberProperty(default=30, doc="length of the shortest bars on the scale")
        vern_bar_extra_length = i3.PositiveNumberProperty(default=10, doc="extra length of the central bar")
        vern_bar_width = i3.PositiveNumberProperty(default=5, doc="width of a single bar")

        # Separation between Vernier scales and Crosses section
        vern_cross_spacing = i3.PositiveNumberProperty(default=30,
                                      doc="Distance between cross box and closest edge of scales")

        # Separation between 2 scales of 2 layers
        vern_layer_gap = i3.NonNegativeNumberProperty(default=0.0, doc="gap between 2 scales of 2 layers on alignment")

        def _default_verniers(self):
            vern_1 = self.cell.verniers[0].Layout(spacing=self.vern_spacing_long,
                                                number_of_bars=self.vern_number_of_bar,
                                                bar_length=self.vern_bar_length,
                                                bar_extra_length=self.vern_bar_extra_length,
                                                bar_width=self.vern_bar_width)#,
                                                #process=self.process1)
                                                
            vern_2 = self.cell.verniers[1].Layout(spacing=self.vern_spacing_short,
                                                number_of_bars=self.vern_number_of_bar,
                                                bar_length=self.vern_bar_length,
                                                bar_extra_length=self.vern_bar_extra_length,
                                                bar_width=self.vern_bar_width)#,
                                                #process=self.process2)

            return [vern_1, vern_2]

    
        def _default_cross_marks(self):
            # Dark Cross on layer 1
            dark_cross = self.cell.cross_marks[0].Layout(inversion=False, 
                                                         cross_bar_width=self.dark_cross_bar_width,
                                                         cross_boundary_width=self.cross_boundary_width)#,
                                                         #process=self.process1)

            open_cross = self.cell.cross_marks[1].Layout(inversion=True, 
                                                         cross_bar_width=self.open_cross_bar_width,
                                                         cross_boundary_width=self.cross_boundary_width)#,
                                                         #process=self.process2)
            return [dark_cross, open_cross]

        def _generate_instances(self, insts):
            insts += i3.SRef(reference=self.cross_marks[0])
            insts += i3.SRef(reference=self.cross_marks[1])
            
            vern_1_horz_trans = i3.VMirror() + \
                                i3.Translation((0, -self.cross_boundary_width * 0.5 - self.vern_cross_spacing -
                                                (self.vern_bar_length + self.vern_bar_extra_length) - self.vern_layer_gap))            
            
            insts += i3.SRef(reference=self.verniers[0], transformation=vern_1_horz_trans)           
            
            vern_2_horz_trans = i3.Translation((0, -self.cross_boundary_width * 0.5 - self.vern_cross_spacing -
                                                (self.vern_bar_length + self.vern_bar_extra_length)))        
            
            insts += i3.SRef(reference=self.verniers[1], transformation=vern_2_horz_trans) 

            vern_1_vert_trans = i3.Rotation(rotation=90) + \
                                i3.Translation((-self.cross_boundary_width*0.5 - 
                                                self.vern_cross_spacing -
                                                (self.vern_bar_length + self.vern_bar_extra_length) -
                                                self.vern_layer_gap,
                                                0))
                                
            insts += i3.SRef(reference=self.verniers[0], transformation=vern_1_vert_trans)  
            
            vern_2_vert_trans = i3.Rotation(rotation=270) + \
                                i3.Translation((-self.cross_boundary_width*0.5 -
                                                (self.vern_bar_length + self.vern_bar_extra_length) -
                                                self.vern_cross_spacing, 0))                    
            insts += i3.SRef(reference=self.verniers[1], transformation=vern_2_vert_trans)  
            
            return insts
Beispiel #12
0
class SplitterTree(APAC):
    splitter = i3.ChildCellProperty(doc="splitter used")
    levels = i3.IntProperty(default=3, doc="Number of levels")
    spacing_x = i3.PositiveNumberProperty(default=100.0)
    spacing_y = i3.PositiveNumberProperty(default=50.0)
    bend_radius = i3.PositiveNumberProperty()

    def _default_bend_radius(self):
        return 20.0

    def _default_splitter(self):
        return MMI_12(name=self.name + "_MMI")

    def _default_child_cells(self):

        childs = dict()
        for l in range(self.levels):
            for sp in range(int(2**l)):
                childs["sp_{}_{}".format(l, sp)] = self.splitter

        return childs

    def _default_connectors(self):
        conn = []
        for l in range(1, self.levels):
            for sp in range(int(2**l)):
                if sp % 2 == 0:
                    in_port = "sp_{}_{}:out1".format(l - 1, int(sp / 2.0))
                else:
                    in_port = "sp_{}_{}:out2".format(l - 1, int(sp / 2.0))

                out_port = "sp_{}_{}:in1".format(l, sp)

                conn.append((in_port, out_port, sbend, {
                    "bend_radius": self.bend_radius
                }))

        return conn

    def _default_external_port_names(self):
        epn = dict()
        cnt = 1
        l = self.levels - 1
        for sp in range(int(2**l)):
            epn["sp_{}_{}:out1".format(l, sp)] = "out{}".format(cnt)
            cnt = cnt + 1
            epn["sp_{}_{}:out2".format(l, sp)] = "out{}".format(cnt)
            cnt = cnt + 1

        epn["sp_{}_{}:in1".format(0, 0)] = "in"
        return epn

    class Layout(APAC.Layout):
        def _default_child_transformations(self):

            trans = dict()
            for l in range(self.levels):
                for sp in range(int(2**l)):
                    sp_y = self.spacing_y * 2**(self.levels - l - 1)
                    trans["sp_{}_{}".format(l, sp)] = i3.Translation(
                        translation=(l * self.spacing_x,
                                     -0.5 * (2**l - 1) * sp_y + sp * sp_y))

            return trans