示例#1
0
class PI(i3.PCell):
    _name_prefix = "PI"

    # Center of the structure
    position = i3.Coord2Property(default=(0.0, 0.0))

    # Layer
    layer = i3.LayerProperty(default=i3.TECH.PPLAYER.HFW)
    layer_bool = i3.LayerProperty(default=i3.TECH.PPLAYER.NONE.DOC)

    # Mesa parameters
    length = i3.PositiveNumberProperty(default=7000.0)
    width = i3.PositiveNumberProperty(default=630.0)

    pocket = i3.BoolProperty(default=False)
    tilt = i3.BoolProperty(default=False)

    # Recess label
    label = i3.StringProperty(default="PI_")

    class Layout(i3.LayoutView):

        def _generate_elements(self, elems):
            # Center of the structure
            (x0, y0) = self.position

            elems += i3.Rectangle(layer=self.layer, center=(x0 + 6500, y0 + 1000 + (3000 - self.width) / 4),
                                  box_size=(self.length, (3000 - self.width) / 2))

            elems += i3.Rectangle(layer=self.layer,
                                  center=(x0 + 6500, y0 + 1000 + self.width + (3000 - self.width) * 3 / 4),
                                  box_size=(self.length, (3000 - self.width) / 2))

            elems += i3.SRef(reference=Interface(pocket=self.pocket, tilt=self.tilt))

            for i in range(7):
                elems += i3.Rectangle(layer=self.layer,
                                      center=(10000 - 725 - i * 750, 1000 + (3000 - self.width) / 2 + 185),
                                      box_size=(50, 50))
                elems += i3.Rectangle(layer=self.layer,
                                      center=(10000 - 725 - i * 750, 1000 + (3000 - self.width) / 2 + self.width - 185),
                                      box_size=(50, 50))
            if self.pocket:
                self.label += "WP"
            if self.tilt:
                self.label += "WT"
            elems += i3.PolygonText(layer=self.layer_bool,
                                    text=self.label,

                                    coordinate=(6000, 4000),
                                    # alignment=(i3.TEXT_ALIGN_LEFT, i3.TEXT_ALIGN_LEFT),
                                    font=2,
                                    height=700.0)

            generated1 = self.layer - self.layer_bool
            mapping = {generated1: self.layer}
            elems = i3.get_elements_for_generated_layers(elems, mapping)

            return elems
class Square(PlaceComponents):

	size=i3.PositiveNumberProperty(default=20.0, doc="simension of the square of aligning mark")
	separation=i3.PositiveNumberProperty(default=2.0, doc="simension of the square of aligning mark")
	square = i3.ChildCellProperty(doc="grating with pitch 1", locked=True)
        tt_square = i3.TraceTemplateProperty(doc="Wide trace template used ")
	layName = i3.StringProperty(default = 'new')
	props = i3.DictProperty()
	
	def _default_props(self):
		return AssignProcess(self.layName)
	

	def _default_tt_square(self):
		tt_w = WireWaveguideTemplate()
		tt_w.Layout(core_width=(self.size),
                    cladding_width=(self.size),
		    **self.props
                    )
		print 'ttw in Square is ', tt_w
		
		return tt_w

	def _default_square(self):
		rect=i3.Waveguide(trace_template=self.tt_square)
		layout_rect = rect.Layout(shape=[(0.0, self.size/2.0),(self.size,self.size/2.0)])
		print 'The trace template of the hline of the cross ', rect.trace_template 
		return rect
       

	def _default_child_cells(self):
		child_cells={"S1" : self.square,
                           }        

		return child_cells



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

			child_transformations={
			        "S1" : i3.Translation(translation=(-(self.size*0.5),(-self.size*0.5))),
                                   }

			return child_transformations	
class identifierText(i3.PCell):
    """A generic label
    """
    _name_prefix = "LABEL"  # a prefix aded to the unique identifier
    text = i3.StringProperty(default="Identifier Label",
                             doc="The text which will actually be displayed")
    font_size = i3.PositiveNumberProperty(default=1000.0,
                                          doc="Font size of the text")

    class Layout(i3.LayoutView):
        channel_template = microfluidics.ShortChannelTemplate()
        cInp = i3.Coord2Property(default=(0.0, 0.0))

        def _generate_elements(self, elems):
            elems += i3.PolygonText(layer=i3.TECH.PPLAYER.CH2.TRENCH,
                                    coordinate=(0., 0.),
                                    text=self.text,
                                    height=self.font_size)
            return elems
示例#4
0
class AlignmentMarker(i3.PCell):
    _name_prefix = "ALIGNMENT MARKER"

    # Center of the structure
    position = i3.Coord2Property(default=(0.0, 0.0))

    # Layer
    layer = i3.LayerProperty(required=True)

    # Complement
    complement = i3.BoolProperty(default=False)

    # Protection
    protection = i3.BoolProperty(default=False)

    # Marker parameters
    cross_length = i3.PositiveNumberProperty(default=150.0)
    cross_width = i3.PositiveNumberProperty(default=16.0)
    cross_margin = i3.PositiveNumberProperty(default=4.0)

    vernier_length = i3.PositiveNumberProperty(default=30.0)
    vernier_width = i3.PositiveNumberProperty(default=8.0)
    vernier_period = i3.PositiveNumberProperty(default=20.25)
    vernier_left_center = i3.Coord2Property(default=(-121.0, 24.0))
    vernier_top_center = i3.Coord2Property(default=(-6.0, 119.0))

    vernier_complement_length = i3.PositiveNumberProperty(default=18.0)
    vernier_complement_long_length = i3.PositiveNumberProperty(default=28.0)
    vernier_complement_width = i3.PositiveNumberProperty(default=10.0)
    vernier_complement_shift = i3.PositiveNumberProperty(default=9.0)
    vernier_complement_period = i3.PositiveNumberProperty(default=20)

    protection_length = i3.PositiveNumberProperty(default=300.0)
    protection_width = i3.PositiveNumberProperty(default=320.0)

    # Layer text
    layer_text = i3.StringProperty(default="Mesa")

    class Layout(i3.LayoutView):
        def _generate_elements(self, elems):

            # Center of the structure
            (x0, y0) = self.position

            shift = 0.5 * self.cross_width + self.cross_margin
            square_length = 0.5 * self.cross_length - shift

            if (self.complement == False and self.protection == False):

                # Add cross
                elems += i3.Rectangle(layer=self.layer,
                                      center=(x0, y0),
                                      box_size=(self.cross_length,
                                                self.cross_width))
                elems += i3.Rectangle(layer=self.layer,
                                      center=(x0, y0),
                                      box_size=(self.cross_width,
                                                self.cross_length))

                # Add rectangles left VERNIER
                elems += i3.Rectangle(layer=self.layer,
                                      center=(self.vernier_left_center[0],
                                              self.vernier_left_center[1]),
                                      box_size=(self.vernier_length,
                                                self.vernier_width))
                elems += i3.Rectangle(
                    layer=self.layer,
                    center=(self.vernier_left_center[0],
                            self.vernier_left_center[1] + self.vernier_period),
                    box_size=(self.vernier_length, self.vernier_width))
                elems += i3.Rectangle(layer=self.layer,
                                      center=(self.vernier_left_center[0],
                                              self.vernier_left_center[1] +
                                              2.0 * self.vernier_period),
                                      box_size=(self.vernier_length,
                                                self.vernier_width))
                elems += i3.Rectangle(layer=self.layer,
                                      center=(self.vernier_left_center[0],
                                              self.vernier_left_center[1] +
                                              3.0 * self.vernier_period),
                                      box_size=(self.vernier_length,
                                                self.vernier_width))
                elems += i3.Rectangle(layer=self.layer,
                                      center=(self.vernier_left_center[0],
                                              self.vernier_left_center[1] +
                                              4.0 * self.vernier_period),
                                      box_size=(self.vernier_length,
                                                self.vernier_width))
                elems += i3.Rectangle(
                    layer=self.layer,
                    center=(self.vernier_left_center[0],
                            self.vernier_left_center[1] - self.vernier_period),
                    box_size=(self.vernier_length, self.vernier_width))
                elems += i3.Rectangle(layer=self.layer,
                                      center=(self.vernier_left_center[0],
                                              self.vernier_left_center[1] -
                                              2.0 * self.vernier_period),
                                      box_size=(self.vernier_length,
                                                self.vernier_width))
                elems += i3.Rectangle(layer=self.layer,
                                      center=(self.vernier_left_center[0],
                                              self.vernier_left_center[1] -
                                              3.0 * self.vernier_period),
                                      box_size=(self.vernier_length,
                                                self.vernier_width))
                elems += i3.Rectangle(layer=self.layer,
                                      center=(self.vernier_left_center[0],
                                              self.vernier_left_center[1] -
                                              4.0 * self.vernier_period),
                                      box_size=(self.vernier_length,
                                                self.vernier_width))

                # Add rectangles top VERNIER
                elems += i3.Rectangle(layer=self.layer,
                                      center=(self.vernier_top_center[0],
                                              self.vernier_top_center[1]),
                                      box_size=(self.vernier_width,
                                                self.vernier_length))
                elems += i3.Rectangle(
                    layer=self.layer,
                    center=(self.vernier_top_center[0] + self.vernier_period,
                            self.vernier_top_center[1]),
                    box_size=(self.vernier_width, self.vernier_length))
                elems += i3.Rectangle(layer=self.layer,
                                      center=(self.vernier_top_center[0] +
                                              2.0 * self.vernier_period,
                                              self.vernier_top_center[1]),
                                      box_size=(self.vernier_width,
                                                self.vernier_length))
                elems += i3.Rectangle(layer=self.layer,
                                      center=(self.vernier_top_center[0] +
                                              3.0 * self.vernier_period,
                                              self.vernier_top_center[1]),
                                      box_size=(self.vernier_width,
                                                self.vernier_length))
                elems += i3.Rectangle(layer=self.layer,
                                      center=(self.vernier_top_center[0] +
                                              4.0 * self.vernier_period,
                                              self.vernier_top_center[1]),
                                      box_size=(self.vernier_width,
                                                self.vernier_length))
                elems += i3.Rectangle(
                    layer=self.layer,
                    center=(self.vernier_top_center[0] - self.vernier_period,
                            self.vernier_top_center[1]),
                    box_size=(self.vernier_width, self.vernier_length))
                elems += i3.Rectangle(layer=self.layer,
                                      center=(self.vernier_top_center[0] -
                                              2.0 * self.vernier_period,
                                              self.vernier_top_center[1]),
                                      box_size=(self.vernier_width,
                                                self.vernier_length))
                elems += i3.Rectangle(layer=self.layer,
                                      center=(self.vernier_top_center[0] -
                                              3.0 * self.vernier_period,
                                              self.vernier_top_center[1]),
                                      box_size=(self.vernier_width,
                                                self.vernier_length))
                elems += i3.Rectangle(layer=self.layer,
                                      center=(self.vernier_top_center[0] -
                                              4.0 * self.vernier_period,
                                              self.vernier_top_center[1]),
                                      box_size=(self.vernier_width,
                                                self.vernier_length))

                # Add TEXT
                elems += i3.PolygonText(layer=self.layer,
                                        coordinate=(x0, y0 - 100.0),
                                        text=self.layer_text,
                                        height=35.0)

            elif (self.complement == True and self.protection == False):

                # Add squares
                elems += i3.Rectangle(
                    layer=self.layer,
                    center=(x0 - 0.25 * self.cross_length - 0.5 * shift,
                            y0 + 0.25 * self.cross_length + 0.5 * shift),
                    box_size=(square_length, square_length))
                elems += i3.Rectangle(
                    layer=self.layer,
                    center=(x0 + 0.25 * self.cross_length + 0.5 * shift,
                            y0 + 0.25 * self.cross_length + 0.5 * shift),
                    box_size=(square_length, square_length))
                elems += i3.Rectangle(
                    layer=self.layer,
                    center=(x0 - 0.25 * self.cross_length - 0.5 * shift,
                            y0 - 0.25 * self.cross_length - 0.5 * shift),
                    box_size=(square_length, square_length))
                elems += i3.Rectangle(
                    layer=self.layer,
                    center=(x0 + 0.25 * self.cross_length + 0.5 * shift,
                            y0 - 0.25 * self.cross_length - 0.5 * shift),
                    box_size=(square_length, square_length))

                # Add rectangles left VERNIER
                elems += i3.Rectangle(
                    layer=self.layer,
                    center=(self.vernier_left_center[0] -
                            self.vernier_complement_shift -
                            0.5 * self.vernier_complement_long_length,
                            self.vernier_left_center[1]),
                    box_size=(self.vernier_complement_long_length,
                              self.vernier_complement_width))
                elems += i3.Rectangle(
                    layer=self.layer,
                    center=(self.vernier_left_center[0] +
                            self.vernier_complement_shift +
                            0.5 * self.vernier_complement_long_length,
                            self.vernier_left_center[1]),
                    box_size=(self.vernier_complement_long_length,
                              self.vernier_complement_width))

                elems += i3.Rectangle(
                    layer=self.layer,
                    center=(self.vernier_left_center[0] -
                            self.vernier_complement_shift -
                            0.5 * self.vernier_complement_length,
                            self.vernier_left_center[1] +
                            self.vernier_complement_period),
                    box_size=(self.vernier_complement_length,
                              self.vernier_complement_width))
                elems += i3.Rectangle(
                    layer=self.layer,
                    center=(self.vernier_left_center[0] +
                            self.vernier_complement_shift +
                            0.5 * self.vernier_complement_length,
                            self.vernier_left_center[1] +
                            self.vernier_complement_period),
                    box_size=(self.vernier_complement_length,
                              self.vernier_complement_width))

                elems += i3.Rectangle(
                    layer=self.layer,
                    center=(self.vernier_left_center[0] -
                            self.vernier_complement_shift -
                            0.5 * self.vernier_complement_length,
                            self.vernier_left_center[1] +
                            2.0 * self.vernier_complement_period),
                    box_size=(self.vernier_complement_length,
                              self.vernier_complement_width))
                elems += i3.Rectangle(
                    layer=self.layer,
                    center=(self.vernier_left_center[0] +
                            self.vernier_complement_shift +
                            0.5 * self.vernier_complement_length,
                            self.vernier_left_center[1] +
                            2.0 * self.vernier_complement_period),
                    box_size=(self.vernier_complement_length,
                              self.vernier_complement_width))

                elems += i3.Rectangle(
                    layer=self.layer,
                    center=(self.vernier_left_center[0] -
                            self.vernier_complement_shift -
                            0.5 * self.vernier_complement_length,
                            self.vernier_left_center[1] +
                            3.0 * self.vernier_complement_period),
                    box_size=(self.vernier_complement_length,
                              self.vernier_complement_width))
                elems += i3.Rectangle(
                    layer=self.layer,
                    center=(self.vernier_left_center[0] +
                            self.vernier_complement_shift +
                            0.5 * self.vernier_complement_length,
                            self.vernier_left_center[1] +
                            3.0 * self.vernier_complement_period),
                    box_size=(self.vernier_complement_length,
                              self.vernier_complement_width))

                elems += i3.Rectangle(
                    layer=self.layer,
                    center=(self.vernier_left_center[0] -
                            self.vernier_complement_shift -
                            0.5 * self.vernier_complement_length,
                            self.vernier_left_center[1] +
                            4.0 * self.vernier_complement_period),
                    box_size=(self.vernier_complement_length,
                              self.vernier_complement_width))
                elems += i3.Rectangle(
                    layer=self.layer,
                    center=(self.vernier_left_center[0] +
                            self.vernier_complement_shift +
                            0.5 * self.vernier_complement_length,
                            self.vernier_left_center[1] +
                            4.0 * self.vernier_complement_period),
                    box_size=(self.vernier_complement_length,
                              self.vernier_complement_width))

                elems += i3.Rectangle(
                    layer=self.layer,
                    center=(self.vernier_left_center[0] -
                            self.vernier_complement_shift -
                            0.5 * self.vernier_complement_length,
                            self.vernier_left_center[1] -
                            self.vernier_complement_period),
                    box_size=(self.vernier_complement_length,
                              self.vernier_complement_width))
                elems += i3.Rectangle(
                    layer=self.layer,
                    center=(self.vernier_left_center[0] +
                            self.vernier_complement_shift +
                            0.5 * self.vernier_complement_length,
                            self.vernier_left_center[1] -
                            self.vernier_complement_period),
                    box_size=(self.vernier_complement_length,
                              self.vernier_complement_width))

                elems += i3.Rectangle(
                    layer=self.layer,
                    center=(self.vernier_left_center[0] -
                            self.vernier_complement_shift -
                            0.5 * self.vernier_complement_length,
                            self.vernier_left_center[1] -
                            2.0 * self.vernier_complement_period),
                    box_size=(self.vernier_complement_length,
                              self.vernier_complement_width))
                elems += i3.Rectangle(
                    layer=self.layer,
                    center=(self.vernier_left_center[0] +
                            self.vernier_complement_shift +
                            0.5 * self.vernier_complement_length,
                            self.vernier_left_center[1] -
                            2.0 * self.vernier_complement_period),
                    box_size=(self.vernier_complement_length,
                              self.vernier_complement_width))

                elems += i3.Rectangle(
                    layer=self.layer,
                    center=(self.vernier_left_center[0] -
                            self.vernier_complement_shift -
                            0.5 * self.vernier_complement_length,
                            self.vernier_left_center[1] -
                            3.0 * self.vernier_complement_period),
                    box_size=(self.vernier_complement_length,
                              self.vernier_complement_width))
                elems += i3.Rectangle(
                    layer=self.layer,
                    center=(self.vernier_left_center[0] +
                            self.vernier_complement_shift +
                            0.5 * self.vernier_complement_length,
                            self.vernier_left_center[1] -
                            3.0 * self.vernier_complement_period),
                    box_size=(self.vernier_complement_length,
                              self.vernier_complement_width))

                elems += i3.Rectangle(
                    layer=self.layer,
                    center=(self.vernier_left_center[0] -
                            self.vernier_complement_shift -
                            0.5 * self.vernier_complement_length,
                            self.vernier_left_center[1] -
                            4.0 * self.vernier_complement_period),
                    box_size=(self.vernier_complement_length,
                              self.vernier_complement_width))
                elems += i3.Rectangle(
                    layer=self.layer,
                    center=(self.vernier_left_center[0] +
                            self.vernier_complement_shift +
                            0.5 * self.vernier_complement_length,
                            self.vernier_left_center[1] -
                            4.0 * self.vernier_complement_period),
                    box_size=(self.vernier_complement_length,
                              self.vernier_complement_width))

                # Add rectangles top VERNIER
                elems += i3.Rectangle(
                    layer=self.layer,
                    center=(self.vernier_top_center[0],
                            self.vernier_top_center[1] -
                            self.vernier_complement_shift -
                            0.5 * self.vernier_complement_long_length),
                    box_size=(self.vernier_complement_width,
                              self.vernier_complement_long_length))
                elems += i3.Rectangle(
                    layer=self.layer,
                    center=(self.vernier_top_center[0],
                            self.vernier_top_center[1] +
                            self.vernier_complement_shift +
                            0.5 * self.vernier_complement_long_length),
                    box_size=(self.vernier_complement_width,
                              self.vernier_complement_long_length))

                elems += i3.Rectangle(
                    layer=self.layer,
                    center=(self.vernier_top_center[0] +
                            self.vernier_complement_period,
                            self.vernier_top_center[1] -
                            self.vernier_complement_shift -
                            0.5 * self.vernier_complement_length),
                    box_size=(self.vernier_complement_width,
                              self.vernier_complement_length))
                elems += i3.Rectangle(
                    layer=self.layer,
                    center=(self.vernier_top_center[0] +
                            self.vernier_complement_period,
                            self.vernier_top_center[1] +
                            self.vernier_complement_shift +
                            0.5 * self.vernier_complement_length),
                    box_size=(self.vernier_complement_width,
                              self.vernier_complement_length))

                elems += i3.Rectangle(
                    layer=self.layer,
                    center=(self.vernier_top_center[0] +
                            2.0 * self.vernier_complement_period,
                            self.vernier_top_center[1] -
                            self.vernier_complement_shift -
                            0.5 * self.vernier_complement_length),
                    box_size=(self.vernier_complement_width,
                              self.vernier_complement_length))
                elems += i3.Rectangle(
                    layer=self.layer,
                    center=(self.vernier_top_center[0] +
                            2.0 * self.vernier_complement_period,
                            self.vernier_top_center[1] +
                            self.vernier_complement_shift +
                            0.5 * self.vernier_complement_length),
                    box_size=(self.vernier_complement_width,
                              self.vernier_complement_length))

                elems += i3.Rectangle(
                    layer=self.layer,
                    center=(self.vernier_top_center[0] +
                            3.0 * self.vernier_complement_period,
                            self.vernier_top_center[1] -
                            self.vernier_complement_shift -
                            0.5 * self.vernier_complement_length),
                    box_size=(self.vernier_complement_width,
                              self.vernier_complement_length))
                elems += i3.Rectangle(
                    layer=self.layer,
                    center=(self.vernier_top_center[0] +
                            3.0 * self.vernier_complement_period,
                            self.vernier_top_center[1] +
                            self.vernier_complement_shift +
                            0.5 * self.vernier_complement_length),
                    box_size=(self.vernier_complement_width,
                              self.vernier_complement_length))

                elems += i3.Rectangle(
                    layer=self.layer,
                    center=(self.vernier_top_center[0] +
                            4.0 * self.vernier_complement_period,
                            self.vernier_top_center[1] -
                            self.vernier_complement_shift -
                            0.5 * self.vernier_complement_length),
                    box_size=(self.vernier_complement_width,
                              self.vernier_complement_length))
                elems += i3.Rectangle(
                    layer=self.layer,
                    center=(self.vernier_top_center[0] +
                            4.0 * self.vernier_complement_period,
                            self.vernier_top_center[1] +
                            self.vernier_complement_shift +
                            0.5 * self.vernier_complement_length),
                    box_size=(self.vernier_complement_width,
                              self.vernier_complement_length))

                elems += i3.Rectangle(
                    layer=self.layer,
                    center=(self.vernier_top_center[0] -
                            self.vernier_complement_period,
                            self.vernier_top_center[1] -
                            self.vernier_complement_shift -
                            0.5 * self.vernier_complement_length),
                    box_size=(self.vernier_complement_width,
                              self.vernier_complement_length))
                elems += i3.Rectangle(
                    layer=self.layer,
                    center=(self.vernier_top_center[0] -
                            self.vernier_complement_period,
                            self.vernier_top_center[1] +
                            self.vernier_complement_shift +
                            0.5 * self.vernier_complement_length),
                    box_size=(self.vernier_complement_width,
                              self.vernier_complement_length))

                elems += i3.Rectangle(
                    layer=self.layer,
                    center=(self.vernier_top_center[0] -
                            2.0 * self.vernier_complement_period,
                            self.vernier_top_center[1] -
                            self.vernier_complement_shift -
                            0.5 * self.vernier_complement_length),
                    box_size=(self.vernier_complement_width,
                              self.vernier_complement_length))
                elems += i3.Rectangle(
                    layer=self.layer,
                    center=(self.vernier_top_center[0] -
                            2.0 * self.vernier_complement_period,
                            self.vernier_top_center[1] +
                            self.vernier_complement_shift +
                            0.5 * self.vernier_complement_length),
                    box_size=(self.vernier_complement_width,
                              self.vernier_complement_length))

                elems += i3.Rectangle(
                    layer=self.layer,
                    center=(self.vernier_top_center[0] -
                            3.0 * self.vernier_complement_period,
                            self.vernier_top_center[1] -
                            self.vernier_complement_shift -
                            0.5 * self.vernier_complement_length),
                    box_size=(self.vernier_complement_width,
                              self.vernier_complement_length))
                elems += i3.Rectangle(
                    layer=self.layer,
                    center=(self.vernier_top_center[0] -
                            3.0 * self.vernier_complement_period,
                            self.vernier_top_center[1] +
                            self.vernier_complement_shift +
                            0.5 * self.vernier_complement_length),
                    box_size=(self.vernier_complement_width,
                              self.vernier_complement_length))

                elems += i3.Rectangle(
                    layer=self.layer,
                    center=(self.vernier_top_center[0] -
                            4.0 * self.vernier_complement_period,
                            self.vernier_top_center[1] -
                            self.vernier_complement_shift -
                            0.5 * self.vernier_complement_length),
                    box_size=(self.vernier_complement_width,
                              self.vernier_complement_length))
                elems += i3.Rectangle(
                    layer=self.layer,
                    center=(self.vernier_top_center[0] -
                            4.0 * self.vernier_complement_period,
                            self.vernier_top_center[1] +
                            self.vernier_complement_shift +
                            0.5 * self.vernier_complement_length),
                    box_size=(self.vernier_complement_width,
                              self.vernier_complement_length))

            else:
                elems += i3.Rectangle(layer=self.layer,
                                      center=(x0 - 43.5, y0 + 11.5),
                                      box_size=(self.protection_length,
                                                self.protection_width))

            return elems
示例#5
0
class NP_mmi12(i3.PCell):
    _name_prefix = "NP_"

    # Center of the structure
    position = i3.Coord2Property(default=(0.0, 0.0))

    # Layer
    layer = i3.LayerProperty(default=i3.TECH.PPLAYER.HFW)
    layer_bool = i3.LayerProperty(default=i3.TECH.PPLAYER.NONE.DOC)
    layer2 = i3.LayerProperty(default=i3.TECH.PPLAYER.WG.TEXT)

    # Mesa parameters
    length = i3.PositiveNumberProperty(default=160.0)
    width = i3.PositiveNumberProperty(default=120.0)

    pillar = i3.BoolProperty(default=False)
    pocket = i3.BoolProperty(default=False)
    tilt = i3.BoolProperty(default=False)
    double = i3.BoolProperty(default=True)

    # Recess label
    label = i3.StringProperty(default="NP")

    class Layout(i3.LayoutView):
        def _generate_elements(self, elems):

            # Center of the structure
            (x0, y0) = self.position
            width2 = 450.0
            elems += i3.Rectangle(layer=self.layer,
                                  center=(x0 + 6500 + 2000 + 2000,
                                          600 + (1800 - width2) / 4),
                                  box_size=(3000, (1800 - width2) / 2))

            elems += i3.Rectangle(layer=self.layer,
                                  center=(x0 + 6500 + 2000 + 2000, y0 + 600 +
                                          width2 + (1800 - width2) * 3 / 4),
                                  box_size=(3000, (1800 - width2) / 2))

            elems += i3.SRef(
                reference=Interface_mmi12(pocket=self.pocket, tilt=self.tilt))

            if self.pillar:
                self.label = "NO"
                for i in range(4):
                    elems += i3.Rectangle(
                        layer=self.layer,
                        center=(10000 - 725 - i * 750 + 2000 + 550,
                                1275 + self.width / 2),
                        box_size=(self.length, self.width))
                    elems += i3.Rectangle(
                        layer=self.layer,
                        center=(10000 - 725 - i * 750 + 2000 + 550,
                                1725 - self.width / 2),  # change
                        box_size=(self.length, self.width))

                    if self.double:
                        elems += i3.Rectangle(
                            layer=self.layer,
                            center=(10000 - 725 - i * 750 + 2000 + 550 - 400,
                                    1275 + self.width / 2),
                            box_size=(self.length, self.width))
                        elems += i3.Rectangle(
                            layer=self.layer,
                            center=(10000 - 725 - i * 750 + 2000 + 550 - 400,
                                    1725 - self.width / 2),
                            # change
                            box_size=(self.length, self.width))

            if self.width > 120:
                self.label += "W"
            if self.pocket:
                self.label += "_WP"
            if self.tilt:
                self.label += "WT"
            elems += i3.PolygonText(
                layer=self.layer_bool,
                text=self.label,
                coordinate=(10800, 2600),
                # alignment=(i3.TEXT_ALIGN_LEFT, i3.TEXT_ALIGN_LEFT),
                font=2,
                height=400.0)

            generated1 = self.layer - self.layer_bool
            mapping = {generated1: self.layer}
            elems = i3.get_elements_for_generated_layers(elems, mapping)

            if self.pillar:
                for i in range(4):
                    elems += i3.Rectangle(
                        layer=self.layer2,
                        center=(10000 - 725 - i * 750 + 2000 + 550,
                                1275 + self.width / 2),
                        box_size=(self.length + 10, self.width + 10))
                    elems += i3.Rectangle(
                        layer=self.layer2,
                        center=(10000 - 725 - i * 750 + 2000 + 550,
                                1725 - self.width / 2),  # change
                        box_size=(self.length + 10, self.width + 10))

                    if self.double:
                        elems += i3.Rectangle(
                            layer=self.layer2,
                            center=(10000 - 725 - i * 750 + 2000 + 550 - 400,
                                    1275 + self.width / 2),
                            box_size=(self.length + 10, self.width + 10))
                        elems += i3.Rectangle(
                            layer=self.layer2,
                            center=(10000 - 725 - i * 750 + 2000 + 550 - 400,
                                    1725 - self.width / 2),
                            # change
                            box_size=(self.length + 10, self.width + 10))

            return elems
示例#6
0
    class Layout(i3.LayoutView):

        # Properties -------

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

        # grating types
        # 'one_sidewall', 'two_sidewalls', 'nitride_vertical_top', 'nitride_vertical_bottom',
        # 'nitride_one_sidewall_top', 'nitride_one_sidewall_bottom',
        grating_type = i3.StringProperty(default='',
                                         doc='flag for grating type')

        # inputs
        period = i3.DefinitionProperty(default=0.0, doc='period')
        duty_cycle = i3.DefinitionProperty(default=0.0, doc='duty cycle')
        grating_amp = i3.DefinitionProperty(default=0.0, doc='grating amp')
        grat_wg_width = i3.DefinitionProperty(default=0.0,
                                              doc='waveguide width')
        length = i3.DefinitionProperty(default=0.0, doc='length')

        # Methods -------

        def _generate_instances(self, insts):
            # Generates a long ass row of gratings

            # serp_grating_layout = SerpGratingArray().get_default_view(i3.LayoutView)
            # serp_grating_layout.set( pitch              = 0.5,
            #                          grat_wg_width      = 6.5,
            #                          flyback_wg_width   = 6.5,
            #                          grating_amp        = grating_amps[i_row][i_col],
            #                          duty_cycle         = duty_cycle,
            #                          period             = period,
            #                          numrows            = numrows_tx,
            #                          grating_type       = grating_types[i_row][i_col],
            #                          length             = 100.0 )

            # 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_mmmmffff').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)

            # Hard code the tapers into here: (I hate hardcoding stuff, but no choice here)
            taper_length = 79.0  # 79 is the best according to deniz' sims
            width_etch = 4.0
            wg_width = 0.5
            taper_swg_lay_1 = ParabolicTaper(
                name=self.name + '_TAPER_1').get_default_view(i3.LayoutView)
            taper_swg_lay_1.set(length=taper_length,
                                width1=wg_width,
                                width2=self.grat_wg_width,
                                width_etch=width_etch)
            taper_swg_name_1 = self.name + '_TAPER_1'
            t = i3.vector_match_transform(
                taper_swg_lay_1.ports['left'],
                insts[lin_taper_lay_name].ports['out'])
            insts += i3.SRef(name=taper_swg_name_1,
                             reference=taper_swg_lay_1,
                             transformation=t,
                             flatten=True)

            # add grating array
            # make grating layout
            swg_l_name = self.name + '_SWG'
            if self.grating_type == 'one_sidewall':
                # single sidewall grating
                swg_l = SidewallGratingWg(name=swg_l_name).get_default_view(
                    i3.LayoutView)
                swg_l.set(period=self.period,
                          duty_cycle=self.duty_cycle,
                          grating_amp=self.grating_amp,
                          wg_width=self.grat_wg_width,
                          length=self.length,
                          both_sides=False)

            elif self.grating_type == 'two_sidewalls':
                # double sidewall grating
                swg_l = SidewallGratingWg(name=swg_l_name).get_default_view(
                    i3.LayoutView)
                swg_l.set(period=self.period,
                          duty_cycle=self.duty_cycle,
                          grating_amp=self.grating_amp,
                          wg_width=self.grat_wg_width,
                          length=self.length,
                          both_sides=True)

            elif self.grating_type == 'nitride_vertical_top':
                # nitride vertical grating, top layer
                swg_l = NitrideGratingWg(name=swg_l_name).get_default_view(
                    i3.LayoutView)
                swg_l.set(period=self.period,
                          duty_cycle=self.duty_cycle,
                          grating_amp=self.grating_amp,
                          wg_width=self.grat_wg_width,
                          length=self.length,
                          grating_type='vertical',
                          nitride_layer='top')

            elif self.grating_type == 'nitride_vertical_bottom':
                # nitride vertical grating, top layer
                swg_l = NitrideGratingWg(name=swg_l_name).get_default_view(
                    i3.LayoutView)
                swg_l.set(period=self.period,
                          duty_cycle=self.duty_cycle,
                          grating_amp=self.grating_amp,
                          wg_width=self.grat_wg_width,
                          length=self.length,
                          grating_type='vertical',
                          nitride_layer='bottom')

            elif self.grating_type == 'nitride_one_sidewall_top':
                # nitride vertical grating, top layer
                swg_l = NitrideGratingWg(name=swg_l_name).get_default_view(
                    i3.LayoutView)
                swg_l.set(period=self.period,
                          duty_cycle=self.duty_cycle,
                          grating_amp=self.grating_amp,
                          wg_width=self.grat_wg_width,
                          length=self.length,
                          grating_type='one_sidewall',
                          nitride_layer='top')

            elif self.grating_type == 'nitride_one_sidewall_bottom':
                # nitride vertical grating, top layer
                swg_l = NitrideGratingWg(name=swg_l_name).get_default_view(
                    i3.LayoutView)
                swg_l.set(period=self.period,
                          duty_cycle=self.duty_cycle,
                          grating_amp=self.grating_amp,
                          wg_width=self.grat_wg_width,
                          length=self.length,
                          grating_type='one_sidewall',
                          nitride_layer='bottom')

            # end getting grating layout

            # add waveguide instance

            t = i3.vector_match_transform(
                swg_l.ports['in'], insts[taper_swg_name_1].ports['right'])
            insts += i3.SRef(name=swg_l_name,
                             reference=swg_l,
                             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_east = self.name + '_EDGETAPER_EAST'
            insts += i3.SRef(name=lin_taper_lay_name_east,
                             reference=lin_taper_lay,
                             transformation=t,
                             flatten=True)

            # east taper
            taper_swg_lay_2 = ParabolicTaper(
                name=self.name + '_TAPER_2').get_default_view(i3.LayoutView)
            taper_swg_lay_2.set(length=taper_length,
                                width1=wg_width,
                                width2=self.grat_wg_width,
                                width_etch=width_etch)
            taper_swg_name_2 = self.name + '_TAPER_2'
            t = i3.vector_match_transform(
                taper_swg_lay_2.ports['left'],
                insts[lin_taper_lay_name_east].ports['out'],
                mirrored=True)
            insts += i3.SRef(name=taper_swg_name_2,
                             reference=taper_swg_lay_2,
                             transformation=t,
                             flatten=True)

            # connect with fat waveguide, which is just a sidewall grating with no amp
            connect_len = insts[taper_swg_name_2].ports['right'].position[
                0] - insts[swg_l_name].ports['out'].position[0]
            fat_wg_l = SidewallGratingWg().get_default_view(i3.LayoutView)
            fat_wg_l_name = self.name + '_FAT_WG_CON'
            fat_wg_l.set(period=self.period,
                         duty_cycle=self.duty_cycle,
                         grating_amp=0.0,
                         wg_width=self.grat_wg_width,
                         length=connect_len,
                         both_sides=False)
            t = i3.vector_match_transform(fat_wg_l.ports['in'],
                                          insts[swg_l_name].ports['out'])
            insts += i3.SRef(name=fat_wg_l_name,
                             reference=fat_wg_l,
                             transformation=t,
                             flatten=True)

            return insts

        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['in'].position,
                angle=0.0)

            return ports
class CombinedCircuit(PlaceAndAutoRoute):
	L1=i3.PositiveNumberProperty(default=100,doc="radius or curvature of circuit")

	incoupler = i3.ChildCellProperty(doc="coupler used", locked=True)
	outcoupler = i3.ChildCellProperty(doc="coupler used", locked=True)

	aligningmark=i3.ChildCellProperty(doc="aligning mark")
	lens=i3.ChildCellProperty(doc="flowcellbox")
	flowcellbox=i3.ChildCellProperty(doc="lens")
	aligningmark_h=i3.ChildCellProperty(doc="aligning mark for heater")
	coupling_l=i3.PositiveNumberProperty(default=5+2*270, doc="length of coupling WG")	
	coupling_win = i3.PositiveNumberProperty(default=15, doc="width of the coupling WG")
	coupling_wout = i3.PositiveNumberProperty(default=15, doc="width of the coupling WG")	
	chip_length=i3.PositiveNumberProperty(default=20000,doc="length of the chip")
	
	radius=i3.PositiveNumberProperty(default=100,doc="radius or curvature of circuit")

	core=i3.PositiveNumberProperty(default=3.3, doc="core width")	        
	width=i3.PositiveNumberProperty(default=3.3, doc="narrow width of heaters")
	tipo =i3.NumberProperty(default=2, doc="1=spiral, 2=wide waveguide")
	
	
	wide_wg_l = i3.NumberProperty(default=20, doc="Wide Waveguide")
	coupler_p=i3.NumberProperty(default=20, doc="position of the grating coupler with respect to the edge")
	ctipoin=i3.PositiveNumberProperty(default=2, doc="type of coupler used ctipo=1 for grating and ctipo=2 for taper")
	ctipoout=i3.PositiveNumberProperty(default=1, doc="type of coupler used ctipo=1 for grating and ctipo=2 for taper")
	transition_length_couplerin=i3.PositiveNumberProperty(default=500, doc="transition length of the coupler")
	transition_length_couplerout=i3.PositiveNumberProperty(default=500, doc="transition length of the coupler")
	aligningmark=i3.ChildCellProperty(doc="aligning mark for circuit used")
	
	increment=i3.NumberProperty(default=0, doc="core width")
	
	periodin=i3.PositiveNumberProperty(default=1.73, doc="core width")
	dutyin=i3.PositiveNumberProperty(default=0.5, doc="core width")
	nperiodsin=i3.PositiveNumberProperty(default=8, doc="core width")
	
	periodout=i3.PositiveNumberProperty(default=2.566, doc="core width")
	dutyout=i3.PositiveNumberProperty(default=0.403, doc="core width")
	nperiodsout=i3.PositiveNumberProperty(default=20, doc="core width")	
	
	Loc = i3.ListProperty(default=[]) #Non etched part, illuminated during e-beam
	Lec = i3.ListProperty(default=[]) #Etched part	
	
	
	layName_h = i3.StringProperty(default = 'standard', doc = 'options: standard, new')
	layName_h2 = i3.StringProperty(default = 'standard', doc = 'options: standard, new')
	layName_c = i3.StringProperty(default = 'standard', doc = 'options: standard, new')
	layName_f = i3.StringProperty(default = 'standard', doc = 'options: standard, new')
	separation=i3.NumberProperty(default=100.0, doc="separation between cross and gratings")
	size=i3.NumberProperty(default=250.0, doc="Size of the cross of aligning marks")
	
	print 'core width',core
	print 'heater width', width

	def _default_trace_template(self):
		return self.incoupler.inPort.trace_template
	
	
	def _default_Lec(self):
			
		#Loc=[2.175,2.122,2.07,2.016,1.963,1.908,1.854,1.798,1.743,1.687,1.63,1.573,
			    #1.515,1.457,1.398,1.339,1.279,1.219,1.158,1.096] #version A
		Loc=[2.043,1.643] #1um etch for 2um GOS
		#Loc=[1,1,1,1,1,1,1]
		Loc.reverse()
		return Loc
		
	def _default_Loc(self):
			
		#Lec=[0.242,0.301,0.361,0.421,0.482,0.543,0.605,0.667,0.73,0.794,0.858,0.922, 
		     #0.988,1.054,1.12,1.187,1.255,1.323,1.392,1.462] #version A
		Lec=[0.511,0.949] #1um etch for 2um GOS
		#Lec=[0.4,0.5,0.6,0.7,0.8,0.9,1]
		Lec.reverse()
		return Lec	

	def _default_child_cells(self):

		child_cells={
                             "incoupling1" : self.incoupler,
                             "outcoupling1" : self.outcoupler,
		             
		             
		             
                           #  "am1"     : self.aligningmark,
		           #  "am2"     : self.aligningmark,
		           #  "am3"     : self.aligningmark,
		           #  "am4"     : self.aligningmark,
		             
		           #  "inlens1" : self.lens,
		            # "outlens1" : self.lens,
		            	             
		            # "chip" : self.flowcellbox
		             	            
                     }
		return child_cells

	def _default_links(self):
		links = [( "incoupling1:InPort_in","outcoupling1:InPort_in"),
		        
                         
                         ]
	
		return links
	
	

	def _default_aligningmark(self):
		am=AligningMarks(layName='metal2', separation=self.separation, size=self.size)
		return am
	
	def _default_aligningmark_h(self):
		am=AligningMarks(layName=self.layName_h, separation=self.separation, size=self.size)
		return am	
	
	def _default_aligningmark_h2(self):
		am=AligningMarks(layName=self.layName_h2, separation=self.separation, size=self.size)
		return am


	def _default_outcoupler(self):
		print 'I am in the coupler'
		coupler = GratingCoupler1Band(coupling_l=self.coupling_l+self.increment, chirp=self.ctipoout, coupling_w=self.coupling_wout,core=self.core, 
		                              layName = self.layName_c, period=self.periodout, duty=self.dutyout, nperiods=self.nperiodsout,
						Loc=self.Loc,
		                                Lec=self.Lec,
		                                transition_length_coupler=self.transition_length_couplerout,
		                                )		
		#layout_coupler=coupler.Layout(transition_length_coupler=self.transition_length_couplerout,
		                              #)#.visualize(annotate=True)
		
		return coupler
	
	def _default_incoupler(self):
		print 'I am in the coupler'
		coupler = GratingCoupler1Band(coupling_l=self.coupling_l, chirp=self.ctipoin, coupling_w=self.coupling_win,core=self.core, 
	                                      layName = self.layName_c, period=self.periodin, duty=self.dutyin, nperiods=self.nperiodsin,
	                                        Loc=self.Loc,
	                                        Lec=self.Lec,
		                                transition_length_coupler=self.transition_length_couplerin,
	                                        )		
		##layout_coupler=coupler.Layout(transition_length_coupler=self.transition_length_couplerin,
	                                      #)#.visualize(annotate=True)
		
		return coupler	

	def _default_lens(self):
		lens=Lens()
		return lens	
	def _default_flowcellbox(self):
		fl=flowcellbox()
		return fl	


	class Layout(PlaceAndAutoRoute.Layout):
		def _default_child_transformations(self):
			
			incoupler_t =fc_t1 = i3.Rotation(rotation=00.0) #+ i3.Translation(translation=(-(self.chip_length*0.5-self.coupler_p),0.0))
			outcoupler_t = i3.Rotation(rotation=180.0) #+ i3.Translation(translation=(self.chip_length*0.5-self.coupler_p,0.0))
			
			L1=self.L1
			
			#s=270
			s=0
			#z=2500
			z=0
			#socket_length=2*self.period*int(self.nperiods)+2*10
			socket_lengthout=2*(sum(self.Lec)+sum(self.Loc))+2*self.periodout*int(self.nperiodsout)+1*10
			socket_lengthin=2*self.periodin*int(self.nperiodsin)+0*10
			xin=0.75*self.periodin*int(self.nperiodsin)
			xout=0.75*(self.periodout*int(self.nperiodsout)+sum(self.Lec)+sum(self.Loc))
			print "socket_lengthout: ", socket_lengthout
			print "socket_lengthin: ", socket_lengthin
			#print self.child_cells['incoupling1'].FGC.Layout.socket_length
			child_transformations={                                   
                                               
			                        
			                        #"incoupling1"     :   i3.Rotation(rotation=00.0) +i3.Translation(translation=(-z-socket_lengthin#-50.0#-self.transition_length_couplerin
			                                                                                                      #,-s)),
			                        #"outcoupling1"     :   i3.Rotation(rotation=180.0) +i3.Translation(translation=(L1#+50.0#+self.transition_length_couplerout+self.increment-z
			                                                                                                        #,-s)),
			                        "incoupling1"     :   i3.Rotation(rotation=00.0) +i3.Translation(translation=(-z#-socket_lengthin#-50.0#-self.transition_length_couplerin
			                                                                                                                                                              ,-s)),
			                        "outcoupling1"     :   i3.Rotation(rotation=180.0) +i3.Translation(translation=(L1+socket_lengthout-100#+50.0#+self.transition_length_couplerout+self.increment-z
			                                                                                                                                                                ,-s)),

 
			                        # "inlens1"     :   i3.Rotation(rotation=00.0) +i3.Translation(translation=(-z-self.transition_length_couplerin-socket_lengthin+xin,-s)),
			                         #"outlens1"     :   i3.Rotation(rotation=180.0) +i3.Translation(translation=(L1+self.transition_length_couplerin+self.increment-z-xin,-s)),
			                         
			                       #  "am1"     :   i3.Translation(translation=(self.chip_length*0.5-1000,0.0)),
			                       #  "am2"     :   i3.Translation(translation=(-self.chip_length*0.5+1000,0.0)),
			                       #  "am3"     :   i3.Translation(translation=(-self.chip_length*0.5+5000,0.0)),
			                       #  "am4"     :   i3.Translation(translation=(self.chip_length*0.5-5000,0.0)) ,			                       

                                    }                        


			return child_transformations
		def _generate_elements(self, elems):
		
			elems += i3.PolygonText(layer= i3.TECH.PPLAYER.WG.TEXT, text='period={}_duty={}_n={}_width={}'.format(self.periodin,
		                                                                                                      self.dutyin,
			                                                                                              self.nperiodsin,
		                                                                                                      self.core),
		                                #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)


		                                coordinate=(0.0, -20),
		                                alignment=(i3.TEXT_ALIGN_LEFT, i3.TEXT_ALIGN_LEFT),
		                                font = 2,
		                                height=20.0)                
			return elems



		def _default_bend_radius(self):
			return self.radius+self.core*0.5
class GratingCoupler1Band(PlaceComponents):
	core=i3.PositiveNumberProperty(default=3.3, doc="core width")
	period=i3.PositiveNumberProperty(default=2.566, doc="core width")
	duty=i3.PositiveNumberProperty(default=0.403, doc="core width")
	nperiods=i3.PositiveNumberProperty(default=7, doc="core width")
	wg_coupler= i3.TraceTemplateProperty(doc="Wide trace template used")
	#FGC= i3.ChildCellProperty(doc="grating used")
	ctipo=i3.PositiveNumberProperty(default=1, doc="type of coupler used ctipo=1 for grating and ctipo=2 for taper")	
	coupling_l=i3.PositiveNumberProperty(default=5000, doc="length of coupling WG")	
	coupler_template= i3.TraceTemplateProperty(doc="Wide trace template used for coupler tipo2")
	waveguide_template= i3.TraceTemplateProperty(doc="Wide trace template used on routing")
	coupling_w = i3.PositiveNumberProperty(default=20, doc="width of the coupling WG")
	transition_length_coupler=i3.PositiveNumberProperty(default=300, doc="transition length of the coupler")
	Grating_list = i3.ChildCellListProperty(doc="List containing the non etched parts of gratings")
	inPort = i3.ChildCellProperty( doc="Used for ports")
	outPort = i3.ChildCellProperty( doc="Used for ports")
	incouplingWG = i3.ChildCellProperty( doc="Used for ports")
	outcouplingWG = i3.ChildCellProperty( doc="Used for ports")
	chirp=i3.NumberProperty(default=1, doc="1=chirped")
	socket_length=i3.PositiveNumberProperty(default=2.2, doc="length of coupling WG")

	layName = i3.StringProperty(default = 'waveguide')
	layNameg = i3.StringProperty(default = 'metal')
	print 'the name of the layer is', layName
	props = i3.DictProperty()	
	
	def _default_props(self):
		return AssignProcess(self.layName)

	propsg = i3.DictProperty()	
		
	def _default_propsg(self):
		return AssignProcess(self.layNameg)	 
		
	
	Lo = i3.ListProperty(default=[]) #Non etched part, illuminated during e-beam
	Le = i3.ListProperty(default=[]) #Etched part
	Loc = i3.ListProperty(default=[]) #Non etched part, illuminated during e-beam
	Lec = i3.ListProperty(default=[]) #Etched part	

	
	#def _default_transition_length(self):
		#return self.transition_length_coupler
	
	def _default_socket_length(self):
		a=sum(self.Lo)+sum(self.Le)
		#if self.chirp==1:
			#A=a=self.period * int(self.nperiods)+sum(self.Loc))
		return a
	def _default_Loc(self):
		
		#Loc=[2.175,2.122,2.07,2.016,1.963,1.908,1.854,1.798,1.743,1.687,1.63,1.573,
			    #1.515,1.457,1.398,1.339,1.279,1.219,1.158,1.096]
		Loc=self.Loc
		Loc.reverse()
		return Loc
	
	def _default_Lec(self):
			
		#Lec=[0.242,0.301,0.361,0.421,0.482,0.543,0.605,0.667,0.73,0.794,0.858,0.922, 
	             #0.988,1.054,1.12,1.187,1.255,1.323,1.392,1.462]
		Lec=self.Lec
		Lec.reverse()
		return Lec	
	
	def _default_Lo(self):
		A=[None] * int(self.nperiods)
		if self.chirp==1:
			A=[None] * int(self.nperiods+len(self.Loc))
		
		for x in range(0,int(self.nperiods)):
			A[x]=self.period*self.duty
			if self.chirp==1:
				for x in range(0,int(len(self.Loc))):
					print x
					print len(self.Loc)
					A[int(self.nperiods)+x]=self.Loc[x]
			
			print 'Lo: ',A
			
		return A	
	
	
	def _default_Le(self):
		Le=[None] * int(self.nperiods)
		if self.chirp==1:
			Le=[None] * int(self.nperiods+len(self.Loc))		
		for x in range(0,int(self.nperiods)):
			Le[x]=self.period*(1-self.duty)
			if self.chirp==1:
				for x in range(0,int(len(self.Loc))):
					Le[int(self.nperiods)+x]=self.Lec[x]			
			print 'Le: ',Le
			
		return Le	
	
	def _default_Grating_list(self):
		Grating_list = [] 
		for x in range(0,int(len(self.Lo))):
			#rect=i3.Waveguide(trace_template=self.wg_coupler)
			rect=i3.Waveguide(trace_template=self.coupler_template)
			
			#layout_rect = rect.Layout(shape=[(0.0, 0.0),(self.Lo[x],0.0)])#.visualize(annotate=True)
			layout_rect = rect.Layout(shape=[(0.0, 0.0),(self.Lo[x],0.0)])#.visualize(annotate=True)
			                          
		 		
			Grating_list.append(rect)
		return Grating_list
	
	def _default_incouplingWG(self):
		rect=i3.Waveguide(trace_template=self.wg_coupler)
		layout_rect = rect.Layout(shape=[(0.0, 0.0),(self.coupling_l,0.0)]
			                  )
		return rect	

	def _default_outcouplingWG(self):
		rect=i3.Waveguide(trace_template=self.wg_coupler)
		layout_rect = rect.Layout(shape=[(0.0, 0.0),(50+self.socket_length,0.0)]
	                                  )
		return rect	
	
	def _default_inPort(self):
		Port=AutoTransitionPorts(contents=self.incouplingWG,
			                 port_labels=["in"],
			                     trace_template=self.waveguide_template)
		layout_Port = Port.Layout(transition_length=self.transition_length_coupler)#.visualize(annotate=True)
		return Port
	
	def _default_outPort(self):
		Port=AutoTransitionPorts(contents=self.outcouplingWG,
	                                 port_labels=["in"],
	                                     trace_template=self.wg_coupler)
		layout_Port = Port.Layout(transition_length=10)#.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, pillar  in enumerate(self.Grating_list):
			child_cells['pillar{}'.format(counter)] = pillar
			
			print pillar
			print 'name of pillar:', pillar.name
			
		child_cells['InPort'] = self.inPort
		child_cells['OutPort']= self.outPort
		print 'child_cells:', child_cells
		return child_cells	
	
	def _default_props(self):
		return AssignProcess(self.layName)	

	def _default_wg_coupler(self):
		wg_coupler = WireWaveguideTemplate()
		wg_coupler.Layout(core_width=self.coupling_w, cladding_width=self.coupling_w+2*8, **self.props)
		return wg_coupler
	
	def _default_waveguide_template(self):
		wg_t = WireWaveguideTemplate()
		wg_t_layout=wg_t.Layout(core_width=self.core, cladding_width=self.core+2*8, **self.props)
				
		return wg_t

	def _default_coupler_template(self):
		wg_t = WireWaveguideTemplate()
		wg_t_layout=wg_t.Layout(core_width=self.coupling_w, cladding_width=self.coupling_w, **self.propsg)

		return wg_t	

	def _default_trace_template(self):
		return self.waveguide_template  	


	def _default_contents(self):
		return self.FGC

	def _default_port_labels(self):
		return ["out"]

	


	class Layout(PlaceComponents.Layout):

		#def _default_transition_length(self):
			#return self.transition_length_coupler
		
		def _default_child_transformations(self):
			d={}
			position=0
			for counter, child  in enumerate(self.Grating_list):
				
				d['pillar{}'.format(counter)] = i3.Translation(translation=(position, 0.0))
				position=position+self.Lo[counter]+self.Le[counter]
				print 'pillar position: ', position
				print 'counter= ', counter
				print 'Lo: ', self.Lo[counter]
				print 'Le: ', self.Le[counter]
				
			#d['InPort'] = i3.HMirror()+ i3.Translation(translation=(position+10,0))
			d['InPort'] = i3.HMirror()+ i3.Translation(translation=(self.coupling_l+self.socket_length,0))
			d['OutPort'] = i3.Translation(translation=(-50,0.0))
												   
			return d			
class AligningMarks(PlaceComponents):

	tt_cross = i3.TraceTemplateProperty(doc="Wide trace template used for the contact pads")
	hline = i3.ChildCellProperty(doc="Horizontal line", locked=True)
	vline = i3.ChildCellProperty(doc="Vertical", locked=True)
	square = i3.ChildCellProperty(doc="Vertical", locked=True)
	size=i3.PositiveNumberProperty(default=250.0, doc="bigger dimension of aligning mark")
	width=i3.PositiveNumberProperty(default=20.0, doc="smaller dimension of aligning mark")
	#Pitch1=i3.PositiveNumberProperty(default=2.0, doc="pitch grating 1")	
	separation=i3.NumberProperty(default=100.0, doc="separation between cross and gratings")

	#dc=i3.PositiveNumberProperty(default=0.47, doc="duty cycle") 
	
	layName = i3.StringProperty(default = 'metal2')
	props = i3.DictProperty()	
			
		
	def _default_props(self):
		return AssignProcess(self.layName)		

	def _default_tt_cross(self):
		tt_w = WireWaveguideTemplate()
		tt_w.Layout(core_width=(self.width),
                    cladding_width=(self.width),
		    **self.props
                        )

		return tt_w

	def _default_hline(self):
		rect=i3.Waveguide(trace_template=self.tt_cross)
		layout_rect = rect.Layout(shape=[(0.0, self.size/2.0),(self.size,self.size/2.0)])
		print 'The trace template of the hline of the cross ', rect.trace_template 
		return rect  

	def _default_vline(self):
		rect=i3.Waveguide(trace_template=self.tt_cross)
		layout_rect = rect.Layout(shape=[(self.size/2.0, 0.0),(self.size/2.0,self.size)])
		print 'The trace template of the vline of the cross ', rect.trace_template 
		                          
			
		return rect  

	def _default_square(self):
		#square=Square(size=self.width, layName=self.layName)
		square=Square(size=self.width, layName='metal')
		#square.Layout().visualize()
		return square

	def _default_child_cells(self):
		child_cells={"S1" : self.square,
                     "S2" : self.square,
                     "S3" : self.square,
                     "S4" : self.square,
                     "V"  : self.vline,
                     "H"  : self.hline
                     }        

		return child_cells    

	class Layout(PlaceComponents.Layout):

		def _default_child_transformations(self):

			child_transformations={"S1" : i3.Translation(translation=(-(self.width+5.0),(self.width+5.0))),
			                       "S2" : i3.Translation(translation=((self.width+5.0),(self.width+5.0))),
			                       "S3" : i3.Translation(translation=(-(self.width+5.0),-(self.width+5.0))), 
			                       "S4" : i3.Translation(translation=((self.width+5.0),-(self.width+5.0))), 
			                       "V"  : i3.Translation(translation=(0.0, 0.0))+ i3.Translation(translation=(-(self.size)/2.0,-(self.size)/2.0)),
			                       "H"  : i3.Translation(translation=(0.0, 0.0))+ i3.Translation(translation=(-(self.size)/2.0,-(self.size)/2.0))				           
                                 }   


			return child_transformations
示例#10
0
class SerpGratingArray(i3.PCell):
    """Sidewall Grating Waveguide: Waveguide with rectangular sidewall gratings
    """

    _name_prefix = "SerpGrating"

    wg_temp = i3.WaveguideTemplateProperty(
        doc=
        "Waveguide template to use for flyback waveguides, bends, and tapers")
    bend_type = i3.StringProperty(
        default="manual",
        doc=
        "String denoting type of bend to use for connecting arcs (options: 'default', 'manual')"
    )
    taper_type = i3.StringProperty(
        default="default",
        doc=
        "String denoting type of taper to use for connecting tapers (options: 'default', 'manual')"
    )
    bend = i3.ChildCellProperty(
        doc="Bend cell to use for connecting arc waveguides")
    taper_swg = i3.ChildCellProperty(
        doc=
        "Taper cell to use for taper connectors between sidewall grating waveguides and bends"
    )
    taper_flyback = i3.ChildCellProperty(
        doc=
        "Taper cell to use for taper connectors between flyback waveguides and bends"
    )
    swg = i3.ChildCellProperty(doc="Sidewall grating waveguide cell")
    flyback = i3.ChildCellProperty(doc="Flyback waveguide cell")

    def _default_wg_temp(self):
        wg_temp = StripWgTemplate(name=self.name + "_WgTemplate")
        return wg_temp

    def _default_bend(self):
        if self.bend_type is "default":
            bend = i3.Waveguide(name=self.name + "_Bend",
                                trace_template=self.wg_temp)
        else:
            from Custom_Waveguide import CustomWaveguide
            bend = CustomWaveguide(name=self.name + "_Bend")
        return bend

    def _default_taper_swg(self):
        if self.taper_type is "default":
            from Linear_Taper import LinearTaper
            taper = LinearTaper(name=self.name + "_SwgTaper")
        else:
            from Custom_Waveguide import CustomWaveguide
            taper = CustomWaveguide(name=self.name + "_SwgTaper")
        return taper

    def _default_taper_flyback(self):
        if self.taper_type is "default":
            from Linear_Taper import LinearTaper
            taper = LinearTaper(name=self.name + "_FlybackTaper")
        else:
            from Custom_Waveguide import CustomWaveguide
            taper = CustomWaveguide(name=self.name + "_FlybackTaper")
        return taper

    def _default_swg(self):
        swg = SidewallGratingWg(name=self.name + "_SidewallGratingWg")
        return swg

    def _default_flyback(self):
        flyback = i3.Waveguide(name=self.name + "_FlybackWg",
                               trace_template=self.wg_temp)
        return flyback

    class Layout(i3.LayoutView):

        from ipkiss.technology import get_technology
        TECH = get_technology()

        # Sidewall grating waveguide properties
        period = i3.PositiveNumberProperty(default=.3,
                                           doc="Period of sidewall grating")
        duty_cycle = i3.PositiveNumberProperty(
            default=.1,
            doc="Length of grating teeth (along periodic direction)")
        grating_amp = i3.PositiveNumberProperty(
            default=.01,
            doc=
            "Width/amplitude of grating teeth (normal to periodic direction)")
        grat_wg_width = i3.PositiveNumberProperty(
            default=1.0,
            doc=
            "Width of sidewall grating waveguide core (if grating_amp=0 width of waveguide)"
        )

        # Flyback waveguide properites
        flyback_wg_width = i3.PositiveNumberProperty(
            default=0.4, doc="Width of flyback waveguide core")

        # Grating array properties
        pitch = i3.PositiveNumberProperty(
            default=16.0,
            doc=
            "Sidewall grating pitch (center-to-center distance of sidewall grating waveguides)"
        )
        spacing = i3.PositiveNumberProperty(
            doc="Gap between sidewall grating waveguides and flyback waveguides"
        )

        def _default_spacing(self):
            spacing = (self.pitch - self.grat_wg_width -
                       self.flyback_wg_width) / 2
            return spacing

        length = i3.PositiveNumberProperty(
            default=800.0,
            doc="Length of straight (untapered) waveguide sections")
        numrows = i3.PositiveIntProperty(
            default=32,
            doc=
            "Number of sidewall grating/flyback waveguide pairs in the array")

        # Taper properties
        # Properties used for taper_type = "default"
        taper_length = i3.PositiveNumberProperty(default=10.0,
                                                 doc="Taper length")
        # Properties used for taper_type = "manual"
        taper_path_flyback = i3.NumpyArrayProperty(
            doc=
            "List of coordinates denoting the center path of the taper (bend to flyback waveguide)"
        )
        taper_width_flyback = i3.NumpyArrayProperty(
            doc=
            "List of taper widths normal to each point on the path (bend to flyback waveguide)"
        )
        taper_path_swg = i3.NumpyArrayProperty(
            doc=
            "List of coordinates denoting the center path of the taper (bend to sidewall grating waveguide)"
        )
        taper_width_swg = i3.NumpyArrayProperty(
            doc=
            "List of taper widths normal to each point on the path (bend to sidewall grating waveguide)"
        )

        def _default_taper_path_flyback(self):
            #Default is a straight linear taper
            path = np.array([[0.0, 0.0], [self.taper_length, 0.0]], np.float_)
            return path

        def _default_taper_width_flyback(self):
            # Default is a straight linear taper
            widths = np.array([self.bend_width, self.flyback_wg_width],
                              np.float_)
            return widths

        def _default_taper_path_swg(self):
            #Default is a straight linear taper
            path = np.array([[0.0, 0.0], [self.taper_length, 0.0]], np.float_)
            return path

        def _default_taper_width_swg(self):
            # Default is a straight linear taper
            widths = np.array([self.bend_width, self.grat_wg_width], np.float_)
            return widths

        # Bend properties
        # Properties used for bend_type = "default"
        bend_width = i3.PositiveNumberProperty(
            default=TECH.WG.CORE_WIDTH,
            doc="Width of waveguides in bend sections")
        # Properties used for bend_type = "manual"
        arc_path = i3.NumpyArrayProperty(
            doc=
            "List of coordinates denoting the center path of the arc connectors (going from sidewall grating waveguide to flyback waveguide"
        )
        arc_width = i3.NumpyArrayProperty(
            doc=
            "List of arc widths normal to each point on the path (going from sidewall grating waveguide to flyback waveguide"
        )

        def _default_arc_path(self):
            if self.pitch == 16.0:
                #Use pregenerated adiabatic bends (TX)
                pathwidth = np.loadtxt("./bend_data/txbend.txt", np.float_)
                arc_path = pathwidth[:, :2]
            elif self.pitch == 16.516:
                # Use pregenerated adiabatic bends (RX)
                pathwidth = np.loadtxt("./bend_data/rxbend.txt", np.float_)
                arc_path = pathwidth[:, :2]
            else:
                # Default is 180 arc
                arc_path = np.zeros([181, 2], np.float_)
                bend_rad = (self.grat_wg_width / 2 + self.spacing +
                            self.flyback_wg_width / 2) / 2
                for ii in range(181):
                    angle = np.pi / 180.0 * ii
                    arc_path[ii, :] = bend_rad * np.array(
                        [-np.sin(angle), np.cos(angle)], np.float_)

            return arc_path

        def _default_arc_width(self):
            if self.pitch == 16.0:
                #Use pregenerated adiabatic bends (TX)
                pathwidth = np.loadtxt("./bend_data/txbend.txt", np.float_)
                arc_width = pathwidth[:, 2]
            elif self.pitch == 16.516:
                #Use pregenerated adiabatic bends (RX)
                pathwidth = np.loadtxt("./bend_data/rxbend.txt", np.float_)
                arc_width = pathwidth[:, 2]
            else:
                #Default is uniform width with default core_width
                arc_width = np.ones([181], np.float_)
                arc_width = arc_width * self.bend_width
            return arc_width

        def validate_properties(self):
            """Check whether the combination of properties is valid."""
            if (self.grat_wg_width + self.flyback_wg_width +
                    2 * self.spacing) != self.pitch:
                raise i3.PropertyValidationError(
                    self,
                    "Array incorrectly overspecified (pitch=/=wg_widths+spacing",
                    {"pitch": self.pitch})
            return True

        @i3.cache()
        def _get_components(self):
            # Make waveguides
            swg_l = self.cell.swg.get_default_view(i3.LayoutView)
            swg_l.set(period=self.period,
                      duty_cycle=self.duty_cycle,
                      grating_amp=self.grating_amp,
                      wg_width=self.grat_wg_width,
                      length=self.length)
            flyback_l = self.cell.flyback.get_default_view(i3.LayoutView)
            flyback_path = [(0.0, 0.0), (self.length, 0.0)]
            wg_temp_flyback = self.cell.wg_temp.get_default_view(i3.LayoutView)
            wg_temp_flyback.set(core_width=self.flyback_wg_width)
            flyback_l.set(trace_template=wg_temp_flyback, shape=flyback_path)

            # Center-to-center distance between sidewall grating waveguide and flyback waveguide
            flyback_offset = self.grat_wg_width / 2 + self.spacing + self.flyback_wg_width / 2

            # Make bends
            bend_l = self.cell.bend.get_default_view(i3.LayoutView)
            if self.cell.bend_type is "default":
                # Default waveguide 180 arc
                bend_rad = flyback_offset / 2
                arc = i3.ShapeArc(center=(0.0, 0.0),
                                  radius=bend_rad,
                                  start_angle=89.0,
                                  end_angle=270.0)
                wg_temp_bend = self.cell.wg_temp.get_default_view(
                    i3.LayoutView)
                wg_temp_bend.set(core_width=self.bend_width)
                bend_l.set(trace_template=wg_temp_bend, shape=arc)
            else:
                # Custom bend pcell
                bend_l.set(wg_path=self.arc_path,
                           wg_width=self.arc_width,
                           start_angle=180.0,
                           end_angle=0.0)

            # Make tapers
            taper_flyback_l = self.cell.taper_flyback.get_default_view(
                i3.LayoutView)
            taper_swg_l = self.cell.taper_swg.get_default_view(i3.LayoutView)
            if self.cell.taper_type is "default":
                # Linear taper pcell
                if self.cell.bend_type is "default":
                    flyback_bend_width = self.bend_width
                    swg_bend_width = self.bend_width
                else:
                    arcsize = self.arc_width.shape
                    arclength = arcsize[0]
                    flyback_bend_width = self.arc_width[arclength - 1]
                    swg_bend_width = self.arc_width[0]

                taper_flyback_l.set(length=self.taper_length,
                                    wg_width_in=flyback_bend_width,
                                    wg_width_out=self.flyback_wg_width)
                taper_swg_l.set(length=self.taper_length,
                                wg_width_in=swg_bend_width,
                                wg_width_out=self.grat_wg_width)
            else:
                # Custom taper pcell
                taper_flyback_l.set(wg_path=self.taper_path_flyback,
                                    wg_width=self.taper_width_flyback,
                                    start_angle=0.0,
                                    end_angle=0.0)
                taper_swg_l.set(wg_path=self.taper_path_swg,
                                wg_width=self.taper_width_swg,
                                start_angle=0.0,
                                end_angle=0.0)

            return swg_l, flyback_l, bend_l, taper_swg_l, taper_flyback_l

        def _generate_instances(self, insts):
            swg_l, flyback_l, bend_l, taper_swg_l, taper_flyback_l = self._get_components(
            )

            for ii in range(self.numrows):
                # Find component translations (for all numrows)
                t_swg = i3.Translation((0.0, ii * self.pitch))
                t_taper_swg_w = vector_match_transform(
                    taper_swg_l.ports["out"], swg_l.ports['in']) + t_swg
                t_taper_swg_e = vector_match_transform(
                    taper_swg_l.ports["out"],
                    swg_l.ports['out'],
                    mirrored=True) + t_swg
                # Add instances (for all numrows)
                insts += i3.SRef(reference=swg_l,
                                 name="SidewallGratWg" + str(ii),
                                 transformation=t_swg)
                insts += i3.SRef(reference=taper_swg_l,
                                 name="SwgTaper_West" + str(ii),
                                 transformation=t_taper_swg_w)
                insts += i3.SRef(reference=taper_swg_l,
                                 name="SwgTaper_East" + str(ii),
                                 transformation=t_taper_swg_e)
                if ii < (self.numrows - 1):
                    # Find component translations (for numrows-1)
                    flyback_offset = self.grat_wg_width / 2 + self.spacing + self.flyback_wg_width / 2
                    t_flyback = i3.Translation(
                        (0.0, ii * self.pitch + flyback_offset))
                    t_taper_flyback_w = vector_match_transform(
                        taper_flyback_l.ports["out"],
                        flyback_l.ports['in']) + t_flyback
                    t_taper_flyback_e = vector_match_transform(
                        taper_flyback_l.ports["out"],
                        flyback_l.ports['out'],
                        mirrored=True) + t_flyback
                    t_bend_e = i3.VMirror() + vector_match_transform(
                        bend_l.ports['in'],
                        taper_swg_l.ports["in"],
                        mirrored=True) + t_taper_swg_e
                    t_bend_w = i3.VMirror() + vector_match_transform(
                        bend_l.ports['out'], taper_flyback_l.ports["in"]
                    ) + t_taper_flyback_w + i3.Translation((0.0, self.pitch))
                    # Add instances (for numrows-1)
                    insts += i3.SRef(reference=flyback_l,
                                     name="FlybackWg" + str(ii),
                                     transformation=t_flyback)
                    insts += i3.SRef(reference=taper_flyback_l,
                                     name="FlybackTaper_West" + str(ii),
                                     transformation=t_taper_flyback_w)
                    insts += i3.SRef(reference=taper_flyback_l,
                                     name="FlybackTaper_East" + str(ii),
                                     transformation=t_taper_flyback_e)
                    insts += i3.SRef(reference=bend_l,
                                     name="Bend_West" + str(ii),
                                     transformation=t_bend_w)
                    insts += i3.SRef(reference=bend_l,
                                     name="Bend_East" + str(ii),
                                     transformation=t_bend_e)

            return insts

        def _generate_ports(self, ports):
            ports += self.instances["SidewallGratWg0"].ports["in"]
            ports += self.instances["SidewallGratWg" +
                                    str(self.numrows - 1)].ports["out"]
            return ports
    class Layout(i3.LayoutView):

        from ipkiss.technology import get_technology
        TECH = get_technology()

        period = i3.PositiveNumberProperty(default=.3,
                                           doc="Period of sidewall grating")
        duty_cycle = i3.PositiveNumberProperty(
            default=.1,
            doc="Length of grating teeth (along periodic direction)")
        grating_amp = i3.PositiveNumberProperty(
            default=.01,
            doc=
            "Width/amplitude of grating teeth (normal to periodic direction)")
        wg_width = i3.PositiveNumberProperty(
            default=TECH.WG.CORE_WIDTH,
            doc="Width of waveguide core (if grating_amp=0 width of waveguide)"
        )
        length = i3.PositiveNumberProperty(default=100.0,
                                           doc="Length of waveguide")

        # Flag to determine grating type
        # 'vertical' for vertical (along entire width) grating
        # 'one_sidewall' for single sidewall grating
        # 'two_sidewalls' for double sidewall grating
        grating_type = i3.StringProperty(
            default='',
            doc=
            'determines grating type. Set to "vertical", "one_sidewall", or "two_sidewalls"'
        )

        # flag to determine nitride top or bottom ('top' or 'bottom')
        nitride_layer = i3.StringProperty(
            default='',
            doc=
            'determines which nitride layer to draw. Set to "top" or "bottom"')

        def validate_properties(self):
            """Check whether the combination of properties is valid."""
            if self.duty_cycle >= self.period:
                raise i3.PropertyValidationError(
                    self,
                    "Duty cycle is larger than/equal to the grating period",
                    {"duty_cyle": self.duty_cycle})

            return True

        def _generate_elements(self, elems):
            # Waveguide path
            wg_path = [(0.0, 0.0), (self.length, 0.0)]

            # Grating tooth path
            gt_path = [(0.0, 0.0), (self.duty_cycle, 0.0)]

            gap_cycle = self.period - self.duty_cycle
            numperiod = int(np.floor(self.length / self.period))

            # determine which layer to use
            my_layer = {
                'top': i3.TECH.PPLAYER.AIM.SNAM,
                'bottom': i3.TECH.PPLAYER.AIM.FNAM,
            }[self.nitride_layer]

            # Add waveguide core
            elems += i3.Path(layer=i3.TECH.PPLAYER.WG.COR,
                             shape=wg_path,
                             line_width=self.wg_width)
            if self.grating_type != 'vertical':
                elems += i3.Path(layer=my_layer,
                                 shape=wg_path,
                                 line_width=self.wg_width)

            # Add grating teeth
            ytrans = i3.Translation(
                (0.0, self.wg_width / 2 + self.grating_amp / 2))
            for ii in range(numperiod):
                #Start with gap rather than tooth

                if self.grating_type == 'vertical':
                    # Draw vertically etched tooth
                    xtrans = i3.Translation(
                        ((gap_cycle + ii * self.period), 0.0))
                    elems += i3.Path(layer=my_layer,
                                     shape=gt_path,
                                     line_width=self.wg_width,
                                     transformation=(xtrans))

                elif self.grating_type == 'one_sidewall':
                    # Draw single sided sidewall grating
                    xtrans = i3.Translation(
                        ((gap_cycle + ii * self.period), 0.0))
                    elems += i3.Path(layer=my_layer,
                                     shape=gt_path,
                                     line_width=self.grating_amp,
                                     transformation=(xtrans + ytrans))

                elif self.grating_type == 'two_sidewalls':
                    # Draw double sided sidewall grating
                    xtrans = i3.Translation(
                        ((gap_cycle + ii * self.period), 0.0))
                    elems += i3.Path(layer=my_layer,
                                     shape=gt_path,
                                     line_width=self.grating_amp,
                                     transformation=(xtrans + ytrans))
                    elems += i3.Path(layer=my_layer,
                                     shape=gt_path,
                                     line_width=self.grating_amp,
                                     transformation=(xtrans - ytrans))

                # # draw bottom grating if desired
                # if self.both_sides == True:
                #     elems += i3.Path(layer=i3.TECH.PPLAYER.WG.COR, shape=gt_path, line_width=self.grating_amp,
                #                      transformation=(xtrans - ytrans))

            # Add block layers
            import block_layers as bl
            block_layers = bl.layers
            block_widths = bl.widths
            for ii in range(len(block_layers)):
                elems += i3.Path(layer=block_layers[ii],
                                 shape=wg_path,
                                 line_width=self.wg_width +
                                 2 * self.grating_amp + 2 * block_widths[ii])

            return elems

        def _generate_ports(self, ports):
            # ports += i3.OpticalPort(name="in", position=(0.0, 0.0), angle=180.0,
            #                         trace_template=StripWgTemplate().Layout(core_width=self.wg_width))
            # ports += i3.OpticalPort(name="out", position=(self.length, 0.0), angle=0.0,
            #                         trace_template=StripWgTemplate().Layout(core_width=self.wg_width))

            ports += i3.OpticalPort(name="in",
                                    position=(0.0, 0.0),
                                    angle=180.0)
            ports += i3.OpticalPort(name="out",
                                    position=(self.length, 0.0),
                                    angle=0.0)
            return ports
示例#12
0
class SerpGratingArray(i3.PCell):
    """Sidewall Grating Waveguide: Waveguide with rectangular sidewall gratings
    """

    _name_prefix = "SerpGrating"

    wg_temp = i3.WaveguideTemplateProperty(
        doc=
        "Waveguide template to use for flyback waveguides, bends, and tapers")
    bend_type = i3.StringProperty(
        default="manual",
        doc=
        "String denoting type of bend to use for connecting arcs (options: 'default', 'manual')"
    )
    taper_type = i3.StringProperty(
        default="default",
        doc=
        "String denoting type of taper to use for connecting tapers (options: 'default', 'manual')"
    )
    bend = i3.ChildCellProperty(
        doc="Bend cell to use for connecting arc waveguides")
    taper_swg = i3.ChildCellProperty(
        doc=
        "Taper cell to use for taper connectors between sidewall grating waveguides and bends"
    )
    taper_flyback = i3.ChildCellProperty(
        doc=
        "Taper cell to use for taper connectors between flyback waveguides and bends"
    )
    swg = i3.ChildCellProperty(doc="Sidewall grating waveguide cell")
    flyback = i3.ChildCellProperty(doc="Flyback waveguide cell")

    def _default_wg_temp(self):
        wg_temp = StripWgTemplate(name=self.name + "_WgTemplate")
        return wg_temp

    def _default_bend(self):
        if self.bend_type is "default":
            bend = i3.Waveguide(name=self.name + "_Bend",
                                trace_template=self.wg_temp)
        else:
            from Custom_Waveguide import CustomWaveguide
            bend = CustomWaveguide(name=self.name + "_Bend")
        return bend

    def _default_taper_swg(self):
        if self.taper_type is "default":
            from Linear_Taper import LinearTaper
            taper = LinearTaper(name=self.name + "_SwgTaper")
        else:
            from Custom_Waveguide import CustomWaveguide
            taper = CustomWaveguide(name=self.name + "_SwgTaper")
        return taper

    def _default_taper_flyback(self):
        if self.taper_type is "default":
            from Linear_Taper import LinearTaper
            taper = LinearTaper(name=self.name + "_FlybackTaper")
        else:
            from Custom_Waveguide import CustomWaveguide
            taper = CustomWaveguide(name=self.name + "_FlybackTaper")
        return taper

    def _default_swg(self):
        swg = SidewallGratingWg(name=self.name + "_SidewallGratingWg")
        return swg

    def _default_flyback(self):
        flyback = i3.Waveguide(name=self.name + "_FlybackWg",
                               trace_template=self.wg_temp)
        return flyback

    # --------------------------
    # Layout
    # --------------------------
    class Layout(i3.LayoutView):
        """
        List of properties:
        period
        duty_cycle
            absolute length of the grating section, not percentage
        grating_amp
        grat_wg_width
        flyback_wg_width
        pitch
        spacing
        length
        numrows
        taper_length
        taper_path_flyback
        taper_width_flyback
        taper_path_swg
        taper_width_swg
        bend_width
        arc_path
        arc_width

        TO GENERATE CUSTOM BENDS:
            set pitch to either 16.0 or 16.516

        """

        from ipkiss.technology import get_technology
        TECH = get_technology()

        # -----------
        # Properties

        # Sidewall grating waveguide properties
        period = i3.PositiveNumberProperty(default=.3,
                                           doc="Period of sidewall grating")
        duty_cycle = i3.PositiveNumberProperty(
            default=.1,
            doc="Length of grating teeth (along periodic direction)")
        grating_amp = i3.NumberProperty(
            default=.01,
            doc=
            "Width/amplitude of grating teeth (normal to periodic direction)")
        grat_wg_width = i3.PositiveNumberProperty(
            default=1.0,
            doc=
            "Width of sidewall grating waveguide core (if grating_amp=0 width of waveguide)"
        )

        # Flyback waveguide properites
        flyback_wg_width = i3.PositiveNumberProperty(
            default=0.4, doc="Width of flyback waveguide core")

        # Grating array properties
        pitch = i3.PositiveNumberProperty(
            default=16.0,
            doc=
            "Sidewall grating pitch (center-to-center distance of sidewall grating waveguides)"
        )
        spacing = i3.PositiveNumberProperty(
            doc="Gap between sidewall grating waveguides and flyback waveguides"
        )

        def _default_spacing(self):
            spacing = (self.pitch - self.grat_wg_width -
                       self.flyback_wg_width) / 2
            return spacing

        length = i3.PositiveNumberProperty(
            default=800.0,
            doc="Length of straight (untapered) waveguide sections")
        numrows = i3.PositiveIntProperty(
            default=32,
            doc=
            "Number of sidewall grating/flyback waveguide pairs in the array")

        # Taper properties
        # Properties used for taper_type = "default"
        taper_length = i3.PositiveNumberProperty(default=10.0,
                                                 doc="Taper length")
        # Properties used for taper_type = "manual"
        taper_path_flyback = i3.NumpyArrayProperty(
            doc=
            "List of coordinates denoting the center path of the taper (bend to flyback waveguide)"
        )
        taper_width_flyback = i3.NumpyArrayProperty(
            doc=
            "List of taper widths normal to each point on the path (bend to flyback waveguide)"
        )
        taper_path_swg = i3.NumpyArrayProperty(
            doc=
            "List of coordinates denoting the center path of the taper (bend to sidewall grating waveguide)"
        )
        taper_width_swg = i3.NumpyArrayProperty(
            doc=
            "List of taper widths normal to each point on the path (bend to sidewall grating waveguide)"
        )

        # REDEFINING TAPER HERE
        # taper_swg       = i3.ViewProperty( default='', doc='Taper layout that connects grating waveguide to the bends')
        # taper_flyback   = i3.ViewProperty( default='', doc='Taper layout that connects flyback waveguide to the bends')

        # Pick grating type:
        # 'one_sidewall', 'two_sidewalls', 'nitride_vertical_top', 'nitride_vertical_bottom',
        # 'nitride_one_sidewall_top', 'nitride_one_sidewall_bottom',
        grating_type = i3.StringProperty(default='',
                                         doc='Grating type to draw')

        def _default_taper_path_flyback(self):
            #Default is a straight linear taper
            path = np.array([[0.0, 0.0], [self.taper_length, 0.0]], np.float_)
            return path

        def _default_taper_width_flyback(self):
            # Default is a straight linear taper
            widths = np.array([self.bend_width, self.flyback_wg_width],
                              np.float_)
            return widths

        def _default_taper_path_swg(self):
            #Default is a straight linear taper
            path = np.array([[0.0, 0.0], [self.taper_length, 0.0]], np.float_)
            return path

        def _default_taper_width_swg(self):
            # Default is a straight linear taper
            widths = np.array([self.bend_width, self.grat_wg_width], np.float_)
            return widths

        # Bend properties
        # Properties used for bend_type = "default"
        bend_width = i3.PositiveNumberProperty(
            default=TECH.WG.CORE_WIDTH,
            doc="Width of waveguides in bend sections")
        # Properties used for bend_type = "manual"
        arc_path = i3.NumpyArrayProperty(
            doc=
            "List of coordinates denoting the center path of the arc connectors (going from sidewall grating waveguide to flyback waveguide"
        )
        arc_width = i3.NumpyArrayProperty(
            doc=
            "List of arc widths normal to each point on the path (going from sidewall grating waveguide to flyback waveguide"
        )

        def _default_arc_path(self):
            if self.pitch == 16.0:
                #Use pregenerated adiabatic bends (TX)
                pathwidth = np.loadtxt("../nathan/bend_data/txbend.txt",
                                       np.float_)
                arc_path = pathwidth[:, :2]
            elif self.pitch == 16.516:
                # Use pregenerated adiabatic bends (RX)
                pathwidth = np.loadtxt("../nathan/bend_data/rxbend.txt",
                                       np.float_)
                arc_path = pathwidth[:, :2]
            else:
                # Default is 180 arc
                arc_path = np.zeros([181, 2], np.float_)
                bend_rad = (self.grat_wg_width / 2 + self.spacing +
                            self.flyback_wg_width / 2) / 2
                for ii in range(181):
                    angle = np.pi / 180.0 * ii
                    arc_path[ii, :] = bend_rad * np.array(
                        [-np.sin(angle), np.cos(angle)], np.float_)

            return arc_path

        def _default_arc_width(self):
            if self.pitch == 16.0:
                #Use pregenerated adiabatic bends (TX)
                pathwidth = np.loadtxt("../nathan/bend_data/txbend.txt",
                                       np.float_)
                arc_width = pathwidth[:, 2]
            elif self.pitch == 16.516:
                #Use pregenerated adiabatic bends (RX)
                pathwidth = np.loadtxt("../nathan/bend_data/rxbend.txt",
                                       np.float_)
                arc_width = pathwidth[:, 2]
            else:
                #Default is uniform width with default core_width
                arc_width = np.ones([181], np.float_)
                arc_width = arc_width * self.bend_width
            return arc_width

        def validate_properties(self):
            """Check whether the combination of properties is valid."""
            if (self.grat_wg_width + self.flyback_wg_width +
                    2 * self.spacing) != self.pitch:
                raise i3.PropertyValidationError(
                    self,
                    "Array incorrectly overspecified (pitch=/=wg_widths+spacing",
                    {"pitch": self.pitch})
            return True

        @i3.cache()
        def _get_components(self):
            # Make waveguides

            # Pick grating type:
            # 'one_sidewall', 'two_sidewalls', 'nitride_vertical_top', 'nitride_vertical_bottom',
            # 'nitride_one_sidewall_top', 'nitride_one_sidewall_bottom',

            if self.grating_type == 'one_sidewall':
                # single sidewall grating
                swg_l = self.cell.swg.get_default_view(i3.LayoutView)
                swg_l.set(period=self.period,
                          duty_cycle=self.duty_cycle,
                          grating_amp=self.grating_amp,
                          wg_width=self.grat_wg_width,
                          length=self.length,
                          both_sides=False)

            elif self.grating_type == 'two_sidewalls':
                # double sidewall grating
                swg_l = self.cell.swg.get_default_view(i3.LayoutView)
                swg_l.set(period=self.period,
                          duty_cycle=self.duty_cycle,
                          grating_amp=self.grating_amp,
                          wg_width=self.grat_wg_width,
                          length=self.length,
                          both_sides=True)

            elif self.grating_type == 'nitride_vertical_top':
                # nitride vertical grating, top layer
                swg_l = NitrideGratingWg().get_default_view(i3.LayoutView)
                swg_l.set(period=self.period,
                          duty_cycle=self.duty_cycle,
                          grating_amp=self.grating_amp,
                          wg_width=self.grat_wg_width,
                          length=self.length,
                          grating_type='vertical',
                          nitride_layer='top')

            elif self.grating_type == 'nitride_vertical_bottom':
                # nitride vertical grating, top layer
                swg_l = NitrideGratingWg().get_default_view(i3.LayoutView)
                swg_l.set(period=self.period,
                          duty_cycle=self.duty_cycle,
                          grating_amp=self.grating_amp,
                          wg_width=self.grat_wg_width,
                          length=self.length,
                          grating_type='vertical',
                          nitride_layer='bottom')

            elif self.grating_type == 'nitride_one_sidewall_top':
                # nitride vertical grating, top layer
                swg_l = NitrideGratingWg().get_default_view(i3.LayoutView)
                swg_l.set(period=self.period,
                          duty_cycle=self.duty_cycle,
                          grating_amp=self.grating_amp,
                          wg_width=self.grat_wg_width,
                          length=self.length,
                          grating_type='one_sidewall',
                          nitride_layer='top')

            elif self.grating_type == 'nitride_one_sidewall_bottom':
                # nitride vertical grating, top layer
                swg_l = NitrideGratingWg().get_default_view(i3.LayoutView)
                swg_l.set(period=self.period,
                          duty_cycle=self.duty_cycle,
                          grating_amp=self.grating_amp,
                          wg_width=self.grat_wg_width,
                          length=self.length,
                          grating_type='one_sidewall',
                          nitride_layer='bottom')

            # end making grating if statement

            # flyback and stuff
            flyback_l = self.cell.flyback.get_default_view(i3.LayoutView)
            flyback_path = [(0.0, 0.0), (self.length, 0.0)]
            wg_temp_flyback = self.cell.wg_temp.get_default_view(i3.LayoutView)
            wg_temp_flyback.set(core_width=self.flyback_wg_width)
            flyback_l.set(trace_template=wg_temp_flyback, shape=flyback_path)

            # Center-to-center distance between sidewall grating waveguide and flyback waveguide
            flyback_offset = self.grat_wg_width / 2 + self.spacing + self.flyback_wg_width / 2

            # Make bends
            bend_l = self.cell.bend.get_default_view(i3.LayoutView)
            if self.cell.bend_type is "default":
                # Default waveguide 180 arc
                bend_rad = flyback_offset / 2
                arc = i3.ShapeArc(center=(0.0, 0.0),
                                  radius=bend_rad,
                                  start_angle=89.0,
                                  end_angle=270.0)
                wg_temp_bend = self.cell.wg_temp.get_default_view(
                    i3.LayoutView)
                wg_temp_bend.set(core_width=self.bend_width)
                bend_l.set(trace_template=wg_temp_bend, shape=arc)
            else:
                # Custom bend pcell
                bend_l.set(wg_path=self.arc_path,
                           wg_width=self.arc_width,
                           start_angle=180.0,
                           end_angle=0.0)

            # Make tapers
            taper_flyback_l = self.cell.taper_flyback.get_default_view(
                i3.LayoutView)
            taper_swg_l = self.cell.taper_swg.get_default_view(i3.LayoutView)

            if self.cell.taper_type is "default":
                # Linear taper pcell
                if self.cell.bend_type is "default":
                    flyback_bend_width = self.bend_width
                    swg_bend_width = self.bend_width
                else:
                    arcsize = self.arc_width.shape
                    arclength = arcsize[0]
                    flyback_bend_width = self.arc_width[arclength - 1]
                    swg_bend_width = self.arc_width[0]

                taper_flyback_l.set(length=self.taper_length,
                                    wg_width_in=flyback_bend_width,
                                    wg_width_out=self.flyback_wg_width)
                taper_swg_l.set(length=self.taper_length,
                                wg_width_in=swg_bend_width,
                                wg_width_out=self.grat_wg_width)
            else:
                # Custom taper pcell
                taper_flyback_l.set(wg_path=self.taper_path_flyback,
                                    wg_width=self.taper_width_flyback,
                                    start_angle=0.0,
                                    end_angle=0.0)
                taper_swg_l.set(wg_path=self.taper_path_swg,
                                wg_width=self.taper_width_swg,
                                start_angle=0.0,
                                end_angle=0.0)

            return swg_l, flyback_l, bend_l, taper_swg_l, taper_flyback_l

        def _generate_instances(self, insts):
            swg_l, flyback_l, bend_l, taper_swg_l, taper_flyback_l = self._get_components(
            )

            # Hard code the tapers into here: (I hate hardcoding stuff, but no choice here)
            taper_length = 79.0  # 79 is the best according to deniz' sims
            width_etch = 4.0
            wg_width = 0.5
            taper_swg = ParabolicTaper(
                name=self.name + '_TAPER').get_default_view(i3.LayoutView)
            taper_swg.set(length=taper_length,
                          width1=wg_width,
                          width2=self.grat_wg_width,
                          width_etch=width_etch)

            taper_flyback = ParabolicTaper(
                name=self.name + '_OTHERTAPER').get_default_view(i3.LayoutView)
            taper_flyback.set(length=taper_length,
                              width1=wg_width,
                              width2=self.flyback_wg_width,
                              width_etch=width_etch)

            for ii in range(self.numrows):

                # Find component translations (for all numrows)
                t_swg = i3.Translation((0.0, ii * self.pitch))
                # t_taper_swg_w   = vector_match_transform(taper_swg_l.ports["out"], swg_l.ports['in']) + t_swg
                # t_taper_swg_e   = vector_match_transform(taper_swg_l.ports["out"], swg_l.ports['out'], mirrored=True) + t_swg
                t_taper_swg_w = vector_match_transform(
                    taper_swg.ports["right"], swg_l.ports['in']) + t_swg
                t_taper_swg_e = vector_match_transform(
                    taper_swg.ports["right"],
                    swg_l.ports['out'],
                    mirrored=True) + t_swg

                # Add grating rows + grating row tapers
                insts += i3.SRef(reference=swg_l,
                                 name="SidewallGratWg" + str(ii),
                                 transformation=t_swg)
                # insts += i3.SRef(reference=taper_swg_l, name="SwgTaper_West" + str(ii), transformation=t_taper_swg_w)
                # insts += i3.SRef(reference=taper_swg_l, name="SwgTaper_East" + str(ii), transformation=t_taper_swg_e)
                insts += i3.SRef(reference=taper_swg,
                                 name="SwgTaper_West" + str(ii),
                                 transformation=t_taper_swg_w)
                insts += i3.SRef(reference=taper_swg,
                                 name="SwgTaper_East" + str(ii),
                                 transformation=t_taper_swg_e)

                if ii < (self.numrows - 1):

                    # Find component translations (for numrows-1)
                    flyback_offset = self.grat_wg_width / 2 + self.spacing + self.flyback_wg_width / 2
                    t_flyback = i3.Translation(
                        (0.0, ii * self.pitch + flyback_offset))
                    # t_taper_flyback_w   = vector_match_transform(taper_flyback_l.ports["out"], flyback_l.ports['in']) + t_flyback
                    # t_taper_flyback_e   = vector_match_transform(taper_flyback_l.ports["out"], flyback_l.ports['out'],
                    #                                        mirrored=True) + t_flyback
                    t_taper_flyback_w   = vector_match_transform( taper_flyback.ports["right"],
                                                                  flyback_l.ports['in'] ) \
                                          + t_flyback
                    t_taper_flyback_e   = vector_match_transform( taper_flyback.ports["right"],
                                                                  flyback_l.ports['out'],
                                                                  mirrored = True ) \
                                          + t_flyback

                    # t_bend_e = i3.VMirror() + vector_match_transform(bend_l.ports['in'], taper_swg_l.ports["in"],mirrored=True) + t_taper_swg_e
                    t_bend_e = i3.VMirror() \
                               + vector_match_transform( bend_l.ports['in'],
                                                       taper_swg.ports["left"],
                                                       mirrored = True ) \
                               + t_taper_swg_e
                    t_bend_w = i3.VMirror() \
                               + vector_match_transform( bend_l.ports['out'],
                                                         taper_flyback.ports["left"] ) \
                               + t_taper_flyback_w \
                               + i3.Translation( (0.0, self.pitch) )

                    # Add instances (for numrows-1)

                    # flyback waveguide
                    insts += i3.SRef(reference=flyback_l,
                                     name="FlybackWg" + str(ii),
                                     transformation=t_flyback)

                    # flyback tapers
                    # insts += i3.SRef(   reference       = taper_flyback_l,
                    #                     name            = "FlybackTaper_West" + str(ii),
                    #                     transformation  = t_taper_flyback_w )
                    # insts += i3.SRef(   reference       = taper_flyback_l,
                    #                     name            = "FlybackTaper_East" + str(ii),
                    #                     transformation  = t_taper_flyback_e )
                    insts += i3.SRef(reference=taper_flyback,
                                     name="FlybackTaper_West" + str(ii),
                                     transformation=t_taper_flyback_w)
                    insts += i3.SRef(reference=taper_flyback,
                                     name="FlybackTaper_East" + str(ii),
                                     transformation=t_taper_flyback_e)

                    # bends
                    insts += i3.SRef(reference=bend_l,
                                     name="Bend_West" + str(ii),
                                     transformation=t_bend_w)
                    insts += i3.SRef(reference=bend_l,
                                     name="Bend_East" + str(ii),
                                     transformation=t_bend_e)

                # end if
            # end for loop

            return insts

        def _generate_ports(self, ports):
            """
            THIS NEEDS TO BE UPDATED TO REFLECT INPUT OUTPUT TAPERS
            """
            # ports += self.instances["SidewallGratWg0"].ports["in"]
            # ports += self.instances["SidewallGratWg"+str(self.numrows-1)].ports["out"]

            ports += i3.OpticalPort(name='in',
                                    position=self.instances["SwgTaper_West0"].
                                    ports["left"].position,
                                    angle=180.0)
            ports += i3.OpticalPort(
                name='out',
                position=self.instances["SwgTaper_East" +
                                        str(self.numrows -
                                            1)].ports["left"].position,
                angle=0.0)

            return ports