def cell(length=length, angle=angle): anglerad = radians(angle) """Create a trapezoidal IO cell. Returns: Cell """ with nd.Cell(hashme=True, instantiate=False) as C: """When instantiate is True, cell put in (0, 0, 0)""" nd.Pin(name='a0', xs=xs['a0'], width=pinwidth['a0']).put(0, 0, 180) nd.Pin(name='b0', xs=xs['b0'], width=pinwidth['b0']).\ put(0.5*length*(1.0+1.0/cos(anglerad))) pdk.put_stub(['a0', 'b0']) pdk.cellname(length=0.5 * length).put(C.pin['a0'].rot(180)) temp_a = tan(anglerad) + 0.5 * width * tan(anglerad) temp_b = length / cos(anglerad) + length for lay, grow, acc in nd.layeriter(xs['a0']): outline = [(0, 0.5 * width + grow), (0.5 * temp_b - (width + grow) * temp_a, 0.5 * width + grow), (0.5 * temp_b + grow * temp_a, -0.5 * width - grow), (0, -0.5 * width - grow)] nd.Polygon(layer=lay, points=outline).put(0) cfg.cp = C.pin['b0'] C.groupname = groupname return C
def cell(length=length, angle=angle): anglerad = radians(angle) """Create a trapezoidal IO cell. Returns: Cell """ with nd.Cell(hashme=True, instantiate=False) as C: #When instantiate is True, cell put in (0,0,0) nd.Pin(name='a0', xs=xs['a0'], width=pinwidth['a0']).put(0, 0, 180) nd.Pin(name='b0', xs=xs['b0'], width=pinwidth['b0']).\ put(length/cos(anglerad)-0.5*width*tan(abs(anglerad))) pdk.put_stub(['b0']) pdk.cellname(length=0.5 * length).put(-0.1 * length, 0, 180, 'a0') for lay, grow, acc in nd.layeriter(xs['a0']): outline = nd.geom.trapezoid(length=length / cos(anglerad) + grow * tan(abs(anglerad)), height=width + 2 * grow, angle1=90 + angle, angle2=90, position=2) nd.Polygon(layer=lay, points=outline).put(0) cfg.cp = C.pin['b0'] C.groupname = groupname return C
def icon_ssc(length=100, width=20, bufx=None, bufy=None): """Create an icon for a grating. Args: length (float): length of the grating icon width (float): width of the grating icon Returns: Cell: grating icon """ length, width, bufx, bufy = calc_buf(length, width, bufx, bufy) N = 20 dx = length / N wout = width win = 0.1 * wout wi = 0.5 * win wo = 0.5 * (wout - win) x, y1, y2 = [], [], [] for i in range(N): x.append(i * dx) dy = wi + (wo / (N - 1)) * i * i / (N - 1) y1.append(dy) y2.append(-dy) X = x + x[::-1] Y = y1 + y2[::-1] outline = list(zip(X, Y)) with nd.Cell('icon', instantiate=False) as icon: nd.Polygon(points=outline, layer=layer).put(0) nd.Pin('cc').put(0.5 * length) nd.Pin('a0').put(0, 0, 180) nd.Pin('b0').put(length, 0, 0) return icon
def cell(length=length, pads=pads): """Create a SOA cell. Args: length (float): SOA length in um Returns: Cell; SOA element """ nonlocal width with nd.Cell(hashme=True) as C: C.groupname = groupname pdk.addBBmap(name, params=(length)) nd.Pin(name='a0', xs=xs['a0'], width=pinwidth['a0']).put(0, dy_io, 180) nd.Pin(name='b0', xs=xs['b0'], width=pinwidth['b0']).put(length, dy_io, 0) nd.Pin(name='c0', xs=xs['c0'], width=pinwidth['c0']).put(length / 2, dy_io, 90) if pads: bb_width = padwidth else: bb_width = width pdk.put_stub(['a0', 'b0', 'c0']) pdk.put_boundingbox('org', length, bb_width, align='lb') if icon: icon(length, bb_width).put(0, 0, 180, 'lc') cfg.cp = C.pin['b0'] return C
def getcell(self): with nd.Cell(name=self.name) as dha_cell: inpin = nd.Pin(name='a0').put(self.start[0], self.start[1], self.start[2]) nd.Pin(name='b0').put(self.end[0], self.end[1], self.end[2]) a, b = self.outline() if self.return_path == True: nd.Polygon(nd.util.polyline2polygon(xy=self.points, width=self.ww), layer=self.layer).put() nd.Polyline(width=self.owidth, points=a, layer=self.olayer).put(inpin.rotate(180)) nd.Polyline(width=self.owidth, points=b, layer=self.olayer).put(inpin.rotate(180)) else: nd.Polygon(nd.util.polyline2polygon(xy=self.points, width=self.ww), layer=self.layer).put() nd.Polygon(nd.util.polyline2polygon(xy=a, width=self.owidth), layer=self.olayer).put(inpin.rotate(180)) nd.Polygon(nd.util.polyline2polygon(xy=b, width=self.owidth), layer=self.olayer).put(inpin.rotate(180)) return dha_cell
def cell(length=length, width_sig=width_sig, width_gnd=width_gnd, gap=gap): """Create a GSG RF line cell. Returns: Cell """ with nd.Cell(name=pdk._hash_name, instantiate=False) as C: C.groupname = groupname pdk.addBBmap(name) #bb_width = width_sig + 2*width_gnd + 2*gap width = width_sig sig = nd.strt(length=length, width=width, xs=xs['a0']).put(0) nd.Pin(name='a0', xs=xs['a0'], width=pinwidth['a0'], remark='electrical').put(sig.pin['a0']) nd.Pin(name='b0', xs=xs['b0'], width=pinwidth['b0'], remark='electrical').put(sig.pin['b0']) pdk.put_stub(['a0', 'b0']) #pdk.put_boundingbox('org', length, bb_width) #pdk.parameters(pdk._hash_params).put(0) #pdk.cellname(C.cell_name, length, align='rc').put(-0.25*length, 'b0') width = width_gnd #nd.strt(length=length, width=width+2*width_gnd+2*gap+2*wext_bg, layer='bbox').put(0) nd.strt(length=length, width=width, xs=xs['a0']).put(0, -gap-0.5*(width_sig+width_gnd)) nd.strt(length=length, width=width, xs=xs['a0']).put(0, +gap+0.5*(width_sig+width_gnd)) if xs_bg is not None: nd.strt(length=length, width=xs_bg_width, xs=xs_bg).put(0) cfg.cp = C.pin['b0'] return C
def cell(length=length): """Create a photodetector RF cell. Returns: Cell """ cshift = 0 with nd.Cell(hashme=True) as C: C.default_pins('a0', 'a0') C.groupname = groupname C.foundry_spt = [] pdk.addBBmap(name) nd.Pin(name='a0', xs=xs['a0'], width=pinwidth['a0'], remark='optical').\ put(0, 0, 180) nd.Pin(name='c0', xs=xs['c0'], width=pinwidth['c0'], remark='gnd').\ put(length, cshift-spaceGS-pinwidth['c0']) nd.Pin(name='c1', xs=xs['c1'], width=pinwidth['c1'], remark='signal').\ put(length, cshift) nd.Pin(name='c2', xs=xs['c2'], width=pinwidth['c2'], remark='gnd').\ put(length, cshift+spaceGS+pinwidth['c2']) pdk.put_stub(['a0']) pdk.put_boundingbox('org', length, width) if icon: icon(length, width).put(0) pdk.put_stub(['c0', 'c1', 'c2']) return C
def cell(length=length, pitch=pitch, metal=metal): """Create a DBR cell. Args: length (float): pitch (float): Returns: Cell """ duty_cycle = 0.5 if metal: contact = 1 else: contact = 0 with nd.Cell(hashme=True) as C: C.groupname = groupname pdk.addBBmap(name, params=(length, pitch, duty_cycle, contact)) nd.Pin(name='a0', xs=xs['a0'], width=pinwidth['a0']).put(0, 0, 180) nd.Pin(name='b0', xs=xs['b0'], width=pinwidth['b0']).put(length) nd.Pin(name='c0', xs=xs['c0'], width=pinwidth['c0']).put(0.5*length, 0, 90) pdk.put_stub(['a0', 'b0', 'c0']) pdk.put_boundingbox('org', length, width) if icon: icon(length, width).put(0) return C
def abb_eopm_dc(length=750, contacts=2): """Create an electro-optic phase modulator cell. Args: length (float): length of the modulator section in um Returns: Cell: eopm element """ width = 60 with nd.Cell(hashme=True) as C: nd.Pin(name='a0', xs='Deep', width=wdeep).put(0, 0, 180) nd.Pin(name='b0', xs='Deep', width=wdeep).put(length, 0, 0) # x-positions of pads: L = 0.5*(length - wmetdc) xpos = [] if contacts > 1: for n in range(contacts): xpos.append(0.5*wmetdc + L*2*n/(contacts-1)) elif contacts == 1: xpos = [0.5*length] elif contacts == 0: pass for n, x in enumerate(xpos): pinname = 'c'+str(n) p1 = nd.Pin(name=pinname, xs='MetalDC', width=wmetdc).put(x, 0, 90) nd.put_stub(pinname) #nd.Pin(name='c0', xs='MetalDC', width=wmetdc).put(0.5*length, 5.0, 90) pdk.put_stub(['a0', 'b0', 'c0']) pdk.put_boundingbox('org', length, width, align='lc') icons.icon_strt(length, width, bufx=0, bufy=10, layer='MetalDCIcon').put('cc', 0, 'cc') icons.icon_strt(length, width, bufx=10, bufy=-8, layer='DeepIcon').put('cc', 0, 'cc') return C
def cell(length=length, pitch=pitch, duty_cycle=duty_cycle): """Create a DBR cell. Args: length (float): length of DBR section in um pitch (float): pitch (full period) of dbr in um duty_cycle (float): duty cycle of grating (default = 0.5) Returns: Cell: dbr element """ with nd.Cell(hashme=True) as C: C.groupname = groupname C.foundry_spt = [] pdk.addBBmap(name, params=(length, pitch, duty_cycle)) nd.Pin(name='a0', xs=xs['a0'], width=pinwidth['a0']).put(0, 0, 180) nd.Pin(name='b0', xs=xs['b0'], width=pinwidth['b0']).put(length) nd.Pin(name='c0', xs=xs['c0'], width=pinwidth['c0']).put(length/2, 5.0, 90) pdk.put_stub(['a0', 'b0', 'c0']) pdk.put_boundingbox('org', length, width) if icon: icon(length, width).put(0) return C
def yjunction(radius=20, angle=45): with nd.Cell('y_junction') as yj: b1 = ic1.bend(angle=angle, radius=radius, xs='xs1').put(0, 0, 0) b2 = ic1.bend(angle=-angle, radius=radius, xs='xs1').put(0, 0, 0) nd.Pin(name='a0').put(b1.pin['a0']) nd.Pin(name='b0').put(b1.pin['b0']) nd.Pin(name='b1').put(b2.pin['b0']) return yj
def icon_gsg(pitch=100, height=None): """Create an icon with a gsg diode symbol. The icon scales with the pitch and the height. Args: pitch (float): pitch beteween ground and signal height (float): height of the icon Returns: Cell: diode gsg icon """ if height is None: height = 2 * pitch ratio = 0.3 w_line = 0.1 * ratio * height radius = 0.15 * ratio * height height = height - 2 * radius - 2 * w_line with nd.Cell('icon_gsg', instantiate=False) as icon: # define shapes outline = [(-0.5 * ratio * height, 0.5 * ratio * height), (0.5 * ratio * height, 0.5 * ratio * height), (0, -0.5 * ratio * height)] diode_triangle = nd.Polygon(points=outline, layer=layer) outline = geom.rectangle(ratio * height, w_line, position=5) diode_base = nd.Polygon(points=outline, layer=layer) outline = geom.ring(radius=radius, width=w_line, N=20) ring = nd.Polygon(points=outline, layer=layer) outline = geom.rectangle(w_line, height, position=5) pole = nd.Polygon(points=outline, layer=layer) outline = geom.rectangle(2 * pitch, w_line, position=5) gnd = nd.Polygon(points=outline, layer=layer) # put shapes gnd.put(0, -0.5 * (height - w_line)) diode_triangle.put(0) diode_base.put(0, -0.5 * ratio * (height - w_line)) pole.put(0) pole.put(pitch - 0.5 * w_line) pole.put(-pitch + 0.5 * w_line) ringpos = 0.5 * (height + radius + w_line) ring.put(0, ringpos) ring.put(pitch - 0.5 * w_line, ringpos) ring.put(-pitch + 0.5 * w_line, ringpos) # add pins nd.Pin('cc').put(0) nd.Pin('top').put(0, ringpos + radius + w_line, -90) return icon
def marker2(layera=1, layerb=None, layerc=None): """TU/e-Smart alignment marker 2. This is the second (marker2) of two matching markers. Args: layera (int | str | tuple): layer (or list of layers) in which marker pattern is written. Default 1. layerb (int | str | tuple): layer (or list of layers) in which the background is defined. Default None. layerc (int | str | tuple): layer (or list of layers) in which an extra box around the marker is drawn for visibility in dark field masks. Default None. Returns: function: function generating a cell with this specific marker. Example: Place marker centered at (0,0) in layer 5 with darkfield box:: import nazca as nd m2 = nd.marker2(layera=5, layerc=5) m2.put() nd.export_plt() """ with nd.Cell(name='marker2_'+nd.md5((layera,layerb,layerc))) as C: poly = (((-55,-75), (-55,-55), (-75,-55), (-75,55), (-55,55), (-55,75), (-5,75), (-5,55), (-40,55), (-40,40), (-55,40), (-55,30), (-40,30), (-40,15), (-30,15), (-30,30), (-15,30), (-15,40), (-30,40), (-30,55), (-5,55), (-5,-16), (-39,-16), (-39,-31), (-54,-31), (-54,-39), (-39,-39), (-39,-54), (-31,-54), (-31,-39), (-16,-39), (-16,-31), (-31,-31), (-31,-16), (-5,-16), (-5,-75),), ((30,15), (30,30), (15,30), (15,40), (30,40), (30,55), (40,55), (40,40), (55,40), (55,30), (40,30), (40,15),), ((31,-54), (31,-39), (16,-39), (16,-31), (31,-31), (31,-16), (39,-16), (39,-31), (54,-31), (54,-39), (39,-39), (39,-54),), ((55,-75), (55,-55), (75,-55), (75,-75),), ((55,55), (55,75), (75,75), (75,55),)) nd.Pin(name='a0', xs=None).put(0,0,180) nd.Pin(name='b0', xs=None).put(0,0,0) for p in poly: for lay in nd.make_iter(layera): nd.Polygon(layer=lay, points=p).put() for lay in nd.make_iter(layerb): nd.Polygon(layer=lay, points=geom.rectangle(180, 180, position=5)).put() for lay in nd.make_iter(layerc): nd.Polygon(layer=lay, points=geom.frame(60, 240,240)).put(-90,-90) return C
def cell(length=length, width1=width1, width2=width2, xs=xs, layer=layer, name=name): """ Create a taper element. Args: length (float): length of taper width1 (float): start width of taper width2 (float): end width of taper xs (str): xsection of taper layer (int | str): layer number or layername Returns: Cell: taper element """ #nonlocal name if name is None: name = 'taper' # Cellname with md5 hash #h = md5('{}{}{}{}'.format(length, width1, width2, xs)) #fullname = name="{}_{}".format(name, h) #if fullname in cfg.cellnames.keys(): # return cfg.cellnames[fullname] with Cell(name=name, cnt=True) as taper: taper.instantiate = False if abs(length) < gridsize / 2: return taper # Empty taper if width1 > width2: pin = ['b0', 'a0'] width1, width2 = width2, width1 else: pin = ['a0', 'b0'] nd.Pin(name=pin[0], width=width1, xs=xs, show=True).put(0, 0, 180) nd.Pin(name=pin[1], width=width2, xs=xs, show=True).put(length, 0, 0) taper.length_geo = length for lay, growx, growy, acc in layeriter(xs, layer, dogrowy=True): # Set widths for this layer twidth1 = width1 + 2 * growx twidth2 = width2 + 2 * growx outline = [(0 - growy, twidth1 / 2), (length + growy, twidth2 / 2), (length + growy, -twidth2 / 2), (0 - growy, -twidth1 / 2)] nd.Polygon(layer=lay, points=outline).put() return taper
def cell(length=length, contacts=contacts): """Create an electro-optical phase modulator (EOPM) cell. Their can be from 0 up to <contacts> contac points. They will be equidistantly spaced along the modulator. Args: length (float): length of the EOPM. contacts (int): number of contact pads (bool): draw pads Returns: Cell: eopm """ with nd.Cell(hashme=True) as C: C.groupname = groupname pdk.addBBmap(name, params=(length)) # modulator section: nd.Pin(name='a0', xs=xs['a0'], width=pinwidth['a0'], remark='optical').put(0, 0, 180) nd.Pin(name='b0', xs=xs['b0'], width=pinwidth['b0'], remark='optical').put(length) # x-positions of pads: L = 0.5 * (length - pinwidth['c0']) xpos = [] if contacts > 1: for n in range(contacts): xpos.append(0.5 * pinwidth['c0'] + L * 2 * n / (contacts - 1)) elif contacts == 1: xpos = [0.5 * length] elif contacts == 0: pass for n, x in enumerate(xpos): pinname = 'c' + str(n) p1 = nd.Pin(name=pinname, xs=xs['c0'], width=pinwidth['c0']).\ put(x, 0, 90) nd.put_stub(pinname) pdk.put_stub(['a0', 'b0']) pdk.put_boundingbox('org', length, width) if icon: icon(length, width).put(0) cfg.cp = C.pin['b0'] return C
def example_cell(): """Create a Nazca example cell. Returns: cell """ with nd.Cell('example_cell') as example: s = nd.strt(length=20).put(0) b = nd.bend(angle=45).put() nd.Pin('a0', pin=s.pin['a0']).put() nd.Pin('b0', pin=b.pin['b0']).put() return example
def marker1(layera=1, layerb=None): """TU/e-Smart alignment marker 1. This is the first (marker1) of two matching markers. Args: layera (int | str | tuple): layer (or list of layers) in which marker pattern is written. layerb (int | str | tuple): layer (or list of layers) in which the background is defined. Returns: function: marker cell. Example: Place marker centered at (0,0) in layer 1 with background layer 12:: import nazca as nd m1 = nd.marker1(layera=1, layerb=12) m1.put() nd.export_plt() """ with nd.Cell(name='marker1_'+nd.md5((layera,layerb))) as C: poly = (((-75,55), (-75,75), (75,75), (75,55), (65,55), (65,65), (-65,65), (-65,55),), ((-37.5,17.5), (-37.5,32.5), (-52.5,32.5), (-52.5,37.5), (-37.5,37.5), (-37.5,52.5), (-32.5,52.5), (-32.5,37.5), (-17.5,37.5), (-17.5,32.5), (-32.5,32.5), (-32.5,17.5),), ((32.5,17.5), (32.5,32.5), (17.5,32.5), (17.5,37.5), (32.5,37.5), (32.5,52.5), (37.5,52.5), (37.5,37.5), (52.5,37.5), (52.5,32.5), (37.5,32.5), (37.5,17.5),), ((-38.5,-53.5), (-38.5,-38.5), (-53.5,-38.5), (-53.5,-31.5), (-38.5,-31.5), (-38.5,-16.5), (-31.5,-16.5), (-31.5,-31.5), (-16.5,-31.5), (-16.5,-38.5), (-31.5,-38.5), (-31.5,-53.5),), ((31.5,-53.5), (31.5,-38.5), (16.5,-38.5), (16.5,-31.5), (31.5,-31.5), (31.5,-16.5), (38.5,-16.5), (38.5,-31.5), (53.5,-31.5), (53.5,-38.5), (38.5,-38.5), (38.5,-53.5),), ((-75,-75), (-75,-55), (-65,-55), (-65,-65), (65,-65), (65,-55), (75,-55), (75,-75),)) nd.Pin(name='a0', xs=None).put(0,0,180) nd.Pin(name='b0', xs=None).put(0,0,0) for p in poly: for lay in nd.make_iter(layera): nd.Polygon(layer=lay, points=p).put() for lay in nd.make_iter(layerb): nd.Polygon(layer=lay, points=geom.rectangle(180, 180, position=5)).put() return C
def crossing(angle, w_cross, L): with nd.Cell('y_junction') as crossing: s1 = ic1.strt(width=w_cross, length=L/2,xs='xs1').put() s2 = ic1.strt(width=w_cross, length=L/2,xs='xs1').put() a1 = ic1.strt(width=w_cross, length=100,xs='xs1').put(s2.pin['a0'].move(0,0,angle)) a2 = ic1.strt(width=w_cross, length=100,xs='xs1').put(s2.pin['a0'].move(0,0,angle), flop=True) nd.Pin(name='a0').put(s1.pin['a0']) nd.Pin(name='a1').put(a1.pin['a0']) nd.Pin(name='b0').put(s2.pin['b0']) nd.Pin(name='b1').put(a2.pin['b0']) return crossing
def split1_2_4_8(taper_in = True): with nd.Cell(name='Yjunction_taper_in') as yj: a = dha(name='y_junction_taper_input',layer=layer_inner_path, olayer=layer_outer_path,width=W_t_out, owidth=w_trench, return_path=True) b = dha(name='y_junction_connector',layer=layer_inner_path, olayer=layer_outer_path,width=W_t_out, owidth=w_trench, return_path=True) c = dha(name='y_junction_connector',layer=layer_inner_path, olayer=layer_outer_path,width=W_t_out, owidth=w_trench, return_path=True) if taper_in == True: a.strt(1000) a.taper(width2=w_SM) a.strt(700) a.taper(width2=W_out, length=10) a.strt(length=10) a.getcell().put(0,0) else: a = dha(name='y_junction_taper_input',layer=layer_inner_path, olayer=layer_outer_path,width=W_t_out, owidth=w_trench, return_path=False) a.strt(1710) a.taper(width2=W_out, length=10) a.strt(length=10) a.getcell().put(0,0) b.strt() b.taper(width2=w_SM,length=10) b.strt(375) b.taper(width2=W_t_out) b.strt() b = b.getcell() c.strt(100) c = c.getcell() y0 = y_junction(layer=layer_inner_poly, olayer=layer_outer_poly, height=100).put(nd.cp.move(-5)) s0_0 = b.put(y0.pin['b0'].move(-5)) s0_1 = b.put(y0.pin['b1'].move(-5)) y1_0 = y_junction(layer=layer_inner_poly, olayer=layer_outer_poly,height=50).put(s0_0.pin['b0'].move(-5)) y1_1 = y_junction(layer=layer_inner_poly, olayer=layer_outer_poly,height=50).put(s0_1.pin['b0'].move(-5)) s1_0 = b.put(y1_0.pin['b0'].move(-5)) s1_1 = b.put(y1_0.pin['b1'].move(-5)) s1_2 = b.put(y1_1.pin['b0'].move(-5)) s1_3 = b.put(y1_1.pin['b1'].move(-5)) y=[] y.append(y_junction(layer=layer_inner_poly, olayer=layer_outer_poly,height=25).put(s1_0.pin['b0'].move(-5))) y.append(y_junction(layer=layer_inner_poly, olayer=layer_outer_poly,height=25).put(s1_1.pin['b0'].move(-5))) y.append(y_junction(layer=layer_inner_poly, olayer=layer_outer_poly,height=25).put(s1_2.pin['b0'].move(-5))) y.append(y_junction(layer=layer_inner_poly, olayer=layer_outer_poly,height=25).put(s1_3.pin['b0'].move(-5))) for i in range(len(y)): nd.Pin(name='b'+str(2*i)).put(y[i].pin['b0'].move(-5)) nd.Pin(name='b'+str(2*i+1)).put(y[i].pin['b1'].move(-5)) return yj
def mzi(length=1000, sep=50): with nd.Cell(hashme=True) as mziBB: eopm = eopm_dc(length=length, pads=True, sep=40) mmi_left = mmi2x2_dp().put('lc') deep.sbend(offset=sep).put(mmi_left.pin['b0']) eopm_top = eopm.put() deep.sbend(offset=-sep).put() mmi_right = mmi2x2_dp().put() deep.sbend(offset=-sep).put(mmi_left.pin['b1']) eopm_bot = eopm.put(flip=True) deep.sbend(offset=sep).put() nd.Pin('a0', pin=mmi_left.pin['a0']).put() nd.Pin('a1', pin=mmi_left.pin['a1']).put() nd.Pin('b0', pin=mmi_right.pin['b0']).put() nd.Pin('b1', pin=mmi_right.pin['b1']).put() nd.Pin('c0', pin=eopm_top.pin['c0']).put() nd.Pin('c1', pin=eopm_top.pin['c1']).put() nd.Pin('d0', pin=eopm_bot.pin['c0']).put() nd.Pin('d1', pin=eopm_bot.pin['c1']).put() pdk.put_stub() bb_length, y, a = nd.diff(mziBB.pin['a0'], mziBB.pin['b0']) pdk.put_boundingbox('org', length=abs(bb_length), width=2*sep+428) return mziBB
def cell(length=length, width=width, xs=xs, layer=layer, edge1=edge1, edge2=edge2, name=name): """Create a straight waveguide element. Args: length (float): length of waveguide width (float): width of waveguide xs (str): xsection of waveguide layer (int | str): layer number or layername edge1 (function): optional function F(t) describing edge1 of the waveguide edge2 (function): optional function G(t) describing edge2 of the waveguide Returns: Cell: straight element """ if name is None: name = 'straight' #assert width is not None if width is None: width = 0.0 with Cell(name=name, cnt=True) as guide: guide.instantiate = False nd.Pin(name='a0', width=width, xs=xs, show=True).put(0, 0, 180) nd.Pin(name='b0', width=width, xs=xs, show=True).put(length, 0, 0) guide.length_geo = length for lay, growx, growy, acc in layeriter(xs, layer, dogrowy=True): if edge1 is None: outline = [(0 - growy, 0.5 * width + growx), (length + growy, 0.5 * width + growx), (length + growy, -0.5 * width - growx), (0 - growy, -0.5 * width - growx)] else: if edge2 is None: edge2 = edge1 Fp1 = [] Fp2 = [] for t in np.linspace(0, 1, 20): Fp1.append((length * t, edge1(t) + growx)) Fp2.append((length * t, -edge2(t) - growx)) outline = Fp1 + list(reversed(Fp2)) if abs(length) > min_length: nd.Polygon(layer=lay, points=outline).put(0) return guide
def cell(length=length, height=height, cleave=cleave, pitch=pitch): """Create a cell boundary. Returns: Cell """ with nd.Cell(hashme=True) as C: pdk.parameters('hashme').put(0) #TODO: No foundry specific stuff here: remove. for lay, grow, acc in nd.layeriter(xs): frame = geom.frame(sizew=cleave, sizel=length, sizeh=height, grow=grow) nd.Polygon(layer=lay, points=frame).put(0) #Placing IOs amount_ios = round((height - cleave - pitch) / pitch) #IOs positions lay = 'AnnotationIO' for no in range(0, amount_ios): pinID = 'ioL{:03d}'.format(no) angle = 0 p = nd.Pin(name=pinID).put(-cleave, pitch + no * pitch, angle) p = nd.Pin(name='ioL' + str(no)).put(-cleave, pitch + no * pitch, angle) pdk.arrow.put(p) nd.text(pinID, layer=lay, height=0.15, align='rc').put(p.move(-0.1)) for no in range(0, amount_ios): mo = amount_ios + no pinID = 'ioR{:03d}'.format(no) angle = 0 p = nd.Pin(name=pinID).put(length, pitch + no * pitch, 180 + angle) p = nd.Pin(name='ioR' + str(no)).put(length, pitch + no * pitch, 180 + angle) pdk.arrow.put(p) nd.text(pinID, layer=lay, height=0.15, align='lc').\ put(p.move(-0.1, 0, 180)) C.groupname = groupname return C
def cell(length=length): """Create an Isolation cell. Returns: Cell """ with nd.Cell(hashme=True) as C: pdk.addBBmap(name, params=(length)) nd.Pin(name='a0', xs=xs['a0'], width=pinwidth['a0']).put(0, 0, 180) nd.Pin(name='b0', xs=xs['b0'], width=pinwidth['b0']).put(length) pdk.put_stub(['a0', 'b0']) pdk.put_boundingbox('org', length, width) C.groupname = groupname return C
def cell(diameter=diameter): """Create a DCpad cell. Args: diameter (float): diameter of circular debt Returns: Cell """ with nd.Cell(hashme=True) as C: C.groupname = groupname pdk.addBBmap(name) bb_width = diameter + 2*buf_width bb_length = diameter + 2*buf_length C.default_pins('c0', 'c0') nd.Pin(name='c0', xs=xs['c0'], width=pinwidth['c0'], remark='electrical').\ put(0.5*bb_length, 0, 180) pdk.put_stub('c0', length=pinwidth['c0'], shape='circle') pdk.put_boundingbox('org', bb_length, bb_width) for lay, grow, acc in nd.layeriter(xs['c0']): pad = nd.geom.circle(radius=0.5*diameter, N=100) nd.Polygon(layer=lay, points=pad).\ put('cc') return C
def cell(length=length): """Create and return a DCpad cell. Args: length (float): pad length in um width (float): pad width in um Returns: Cell: pad element """ with nd.Cell(hashme=True) as C: C.groupname = groupname C.foundry_spt = [] bb_length = length + 2*buf_length pdk.addBBmap(name, params=(length, tab_width, "RoundedRectangle"), trans=(0.5*(length-100), 0, 0)) C.default_pins('c0','c0') nd.Pin(name='c0', xs=xs['c0'], width=pinwidth['c0'], remark='electrical').\ put(0.5*bb_length, 0, 180) pdk.put_stub('c0', length=pinwidth['c0'], shape='circle') pdk.put_boundingbox('org', bb_length, bb_length) if icon: icon(bb_length, bb_length).put(0, 'cc') return C
def cell(length=length, width=width): """Create a DCpad_lw cell. Args: length (float): length of the pad in um width (float): width of the pad in um Returns: Cell: dcpad element """ with nd.Cell(hashme=True) as C: C.groupname = groupname C.default_pins('c0','c0') buf = 10 bb_width = width + buf bb_length = length + buf nd.Pin(name='c0', xs=xs['c0'], width=pinwidth['c0'], remark='electrical').\ put(0.5*bb_length, 0, 180) pdk.put_stub('c0', length=pinwidth['c0'], shape='circle') pdk.put_boundingbox('org', bb_length, bb_width) for lay, grow, acc in nd.layeriter(xs['c0']): pad = nd.geom.rounded_rect( length=length+grow, height=width, position=5) nd.Polygon(layer=lay, points=pad).\ put(C.pin['c0']) return C
def icon_pad(length, width, bufx=bufx, bufy=bufy): length, width, bufx, bufy = calc_buf(length, width, bufx, bufy) with nd.Cell('icon', instantiate=False) as icon: pad = geom.rounded_rect(length=length, height=width, position=5) nd.Polygon(layer=layer, points=pad).put(0) nd.Pin('cc').put(0) return icon
def xsection_transition(length, width, layer1, layer2): with nd.Cell('icon', instantiate=False) as icon: rect = geom.box(0.25 * length, 0.50 * width) nd.Polygon(points=rect, layer=layer1).put(0.25 * length) nd.Polygon(points=rect, layer=layer2).put(0.50 * length) nd.Pin('cc').put(0.5 * length) return icon
def icon_mmi(length=None, width=None, bufx=None, bufy=None): length, width, bufx, bufy = calc_buf(length, width, bufx, bufy) Nin0 = 0.5 * (Nin - 1) Nout0 = 0.5 * (Nout - 1) w_mmi = scale_width * width w_in = w_mmi / (2.0 * max(Nin + 0.5, Nout + 0.5)) w_pitch = 2 * w_in l_in = w_in p = [] # list of points (x, y) p.append((bufx + l_in, -0.5 * w_mmi)) #bottom left for i in range(Nin): p.append((bufx + l_in, (-Nin0 + i) * w_pitch - 0.5 * w_in)) p.append((bufx, (-Nin0 + i) * w_pitch - 0.5 * w_in)) p.append((bufx, (-Nin0 + i) * w_pitch + 0.5 * w_in)) p.append((bufx + l_in, (-Nin0 + i) * w_pitch + 0.5 * w_in)) p.append((bufx + l_in, +0.5 * w_mmi)) p.append((bufx + length - l_in, +0.5 * w_mmi)) for i in range(Nout - 1, -1, -1): p.append( (bufx + length - l_in, (-Nout0 + i) * w_pitch + 0.5 * w_in)) p.append((bufx + length, (-Nout0 + i) * w_pitch + 0.5 * w_in)) p.append((bufx + length, (-Nout0 + i) * w_pitch - 0.5 * w_in)) p.append( (bufx + length - l_in, (-Nout0 + i) * w_pitch - 0.5 * w_in)) p.append((bufx + length - l_in, -0.5 * w_mmi)) with nd.Cell('icon', instantiate=False) as icon: nd.Polygon(points=p, layer=layer).put(0) nd.Pin('cc').put(0.5 * length) return icon
def icon_grating(length=100, width=20, bufx=None, bufy=None): """Create an icon for a grating. Args: length (float): length of the grating icon width (float): width of the grating icon Returns: Cell: grating icon """ length, width, bufx, bufy = calc_buf(length, width, bufx, bufy) Nmin = 3 h = width w = 0.4 * width if length < 2 * Nmin * w: w = length / 6 N = 3 else: N = int(length / (2 * w)) with nd.Cell('icon', instantiate=False) as icon: t, u, v = w / 4, w / 2, h / 2 cross = [(u, t), (u, v), (-u, v), (-u, t), (-w, t), (-w, -t), (-u, -t), (-u, -v), (u, -v), (u, -t), (w, -t), (w, t)] for i in range(N): nd.Polygon(points=cross, layer=layer).put(0 + i * w * 2) nd.Pin('cc').put((N - 1) * w) return icon