def icon_strt(length, width, layer, bufx=None, bufy=None): length, width, bufx, bufy = calc_buf(length, width, bufx, bufy) with nd.Cell('icon', instantiate=False) as icon: rect = geom.box(length, width) nd.Polygon(points=rect, layer=layer).put(0) nd.Pin('cc').put(0.5 * length) 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 cell(width_sig=width_sig, width_gnd1=width_gnd1, width_gnd2=width_gnd2, gap1=gap1, height_tap=height_tap, gap2=gap2, length_pad=length_pad, width_pad_sig=width_pad_sig, width_pad_gnd=width_pad_gnd): """Create and return a GSG RF cell. Args: ?? Returns: Cell """ with nd.Cell(name=pdk._hash_name) as C: C.groupname = groupname C.default_pins('a0', 'a0') pdk.addBBmap(name) nd.Pin(name='a0', xs=xs['a0'], width=pinwidth['a0'], remark='electrical').put(0, 0, 180) #nd.Pin(name='b0', xs=xs['b0'], width=pinwidth['b0']).put(0, 0, 180) bb_length = length_pad+height_tap pdk.put_stub([]) pdk.cellname(C.cell_name, bb_length).put(-0.25*bb_length, 0, 180, 'a0') pdk.parameters(pdk._hash_params).put(-0.25*bb_length, 0, 180, 'a0') boundary = 10 nd.Pin(name='rc', xs=None, width=None).\ put(length_pad+height_tap+boundary, 0, 0) heightRectangle = length_pad+boundary widthRectangle = 2*width_pad_gnd+width_sig+2*gap2+2*boundary widthTaper = width_gnd1+width_gnd2+width_sig+2*gap1+2*boundary if width_gnd2 == None: width_gnd2 = width_pad_gnd # outline of the BB angle = -degrees(atan(height_tap/(0.5*(widthRectangle-widthTaper)))) outline = geom.trapezoid(length=widthTaper, height=height_tap, angle1=angle, angle2=angle, position=4) nd.Polygon(layer='bbox', points=outline).put(0, 0, -90) outline = geom.box(length=heightRectangle, width=widthRectangle) nd.Polygon(layer='bbox', points=outline).put(height_tap, 0, 0) # Ground Taper outline = geom.tetragon(length=width_gnd1, height=height_tap, dx=gap2-gap1, x=width_pad_gnd, position=4) nd.Polygon(layer=layer, points=outline).\ put(0, gap1+0.5*(width_sig+width_gnd1), -90) # Ground Pad outline = geom.rectangle(length=width_pad_gnd, height=length_pad, position=7) nd.Polygon(layer=layer, points=outline).\ put(height_tap, gap2+0.5*width_sig, -90) # Signal Line outline = geom.box(length=height_tap, width=width_sig) nd.Polygon(layer=layer, points=outline).put(0, 0, 0) # Signal Pad outline = geom.rectangle(length=width_pad_sig, height=length_pad, position=4) nd.Polygon(layer=layer, points=outline).put(height_tap, 0, -90) # Ground Taper outline = geom.tetragon(length=width_gnd2, height=height_tap, dx=-gap2-width_pad_gnd+gap1+width_gnd2, x=width_pad_gnd, position=4) nd.Polygon(layer=layer, points=outline).\ put(0, -gap1-0.5*(width_sig+width_gnd2), -90) # Ground Pad outline = geom.rectangle(length=width_pad_gnd, height=length_pad, position=1) nd.Polygon(layer=layer, points=outline).\ put(height_tap, -gap2-0.5*width_sig, -90) return C
def cell(self): """Create a Cell with DC, RF, Optical fiber postitions. Returns: Cell: package cell """ with nd.Cell(name=self.name) as C: for arr in self.pads: count = arr['count'] #Placing PAD IOs IOcountmax = round(\ (self.die_length - 2*arr['edge_sep_side']) / arr['pitch']) if count is not None and count < IOcountmax: IOcount = count else: IOcount = IOcountmax pin = arr['edge'] + arr['type'] if arr['edge'] == 'left': x0, y0, a0 = 0, 0, 90 elif arr['edge'] == 'top': x0, y0, a0 = 0, self.die_height, 0 elif arr['edge'] == 'right': x0, y0, a0 = self.die_length, self.die_height, -90 elif arr['edge'] == 'bottom': x0, y0, a0 = self.die_length, 0, 180 else: print("Edge not recognized in Package2: '{}'".format( arr['edge'])) #PAD positions for n in range(0, IOcount): pinID = pin_naming[pin].format(n) if arr['center']: if arr['edge'] in ['top', 'bottom']: dist_edge = self.die_length -\ (IOcount-1)*arr['pitch'] - 2*arr['edge_sep_side'] elif arr['edge'] in ['left', 'right']: dist_edge = self.die_height -\ (IOcount-1)*arr['pitch'] - 2*arr['edge_sep_side'] else: dist_edge = 0 #place metal io pins start = nd.Pin().put(x0, y0, a0) p = nd.Pin(pinID).put( start.move( n * arr['pitch'] + arr['edge_sep_side'] + 0.5 * dist_edge, -arr['edge_sep_front'], -90)) self.arrow.put(p) text = nd.text(pinID, layer=annotationlayer, height=textheight, align='rc') text.put(p.move(textmove)) #Fiber positions dist_edgey = self.die_height - self.cleave - self.fiberarea faa_len = self.cleave + 50 if self.show_fiberarea: farea = geom.box(width=self.fiberarea, length=faa_len) poly = nd.Polygon(layer=fiberIOlayer, points=farea) poly.put(-faa_len - 0.5 * self.cleave, 0.5 * dist_edgey + 0.5 * self.fiberarea, 0) else: print( 'Set show_fiberarea == True to see the fiber allowed area for this package.' ) return C
def cell(self): """Create a Cell with DC, RF, Optical fiber postitions. Returns: Cell: package cell """ with nd.Cell(name=self.name) as C: #Placing PAD IOs IOcountmax = round( (self.die_length - 2 * self.DCside) / self.DCpitch) if self.DCcount is not None and self.DCcount < IOcountmax: IOcount = self.DCcount else: IOcount = IOcountmax #DC PAD positions for n in range(0, IOcount): pinIDT = DCtopname.format(n) pinIDB = DCbotname.format(n) if self.DCcenter: dist_edgex = 0.5 * (self.die_length - (IOcount - 1) * self.DCpitch) else: dist_edgex = self.DCside #Top DC ports p = nd.Pin(pinIDT).put( dist_edgex + n * self.DCpitch - 0.5 * self.cleave, self.die_height - self.DCedge - 0.5 * self.cleave, -90) self.arrow.put(p) text = nd.text(pinIDT, layer=annotationlayer, height=textheight, align='rc') text.put(p.move(textmove)) #Bottom DC ports p = nd.Pin(pinIDB).put( dist_edgex + n * self.DCpitch - 0.5 * self.cleave, self.DCedge - 0.5 * self.cleave, 90) self.arrow.put(p) text = nd.text(pinIDB, layer=annotationlayer, height=textheight, align='rc') text.put(p.move(textmove)) #DC PAD positions double row if self.double_row_DC: for ndr in range(0, IOcount - 1): n = ndr + IOcountmax pinIDT = DCtopname.format(n) pinIDB = DCbotname.format(n) if self.DCcenter == True: dist_edgex = self.die_length - self.cleave -\ (IOcount-1)*self.DCpitch-2*self.DCside else: dist_edgex = 0 if self.DCx_doublerow == None: self.DCx_doublerow = 0.5 * self.DCpitch if self.DCy_doublerow == None: self.DCy_doublerow = 1.0 * self.DCpitch #Top DC ports p = nd.Pin(pinIDT).put( ndr * self.DCpitch + self.DCside + 0.5 * dist_edgex + self.DCx_doublerow, self.die_height - self.cleave - self.DCedge - self.DCy_doublerow, -90) self.arrow.put(p) text = nd.text(pinIDT, layer=annotationlayer, height=textheight, align='rc') text.put(p.move(textmove)) #Bottom DC ports p = nd.Pin(pinIDB).put( ndr * self.DCpitch + self.DCside + 0.5 * dist_edgex + self.DCx_doublerow, self.DCedge + self.DCy_doublerow, 90) self.arrow.put(p) text = nd.text(pinIDB, layer=annotationlayer, height=textheight, align='rc') text.put(p.move(textmove)) #RF PAD positions IOcountmax = round( (self.die_height - 2 * self.RFside) / self.RFpitch) if self.RFcount is not None and self.RFcount < IOcountmax: IOcount = self.RFcount else: IOcount = IOcountmax for n in range(0, IOcount): piRFn = RFname.format(n) if self.RFcenter: dist_edgey = self.die_height-self.cleave -\ (IOcount-1)*self.RFpitch-2*self.RFside else: dist_edgey = 0 p = nd.Pin(piRFn).put( self.die_length - self.cleave - self.RFedge, n * self.RFpitch + self.RFside + 0.5 * dist_edgey, 180) self.arrow.put(p) text = nd.text(piRFn, layer=annotationlayer, height=textheight, align='rc') text.put(p.move(textmove)) #RF PAD positions double row if self.double_row_RF: for ndr in range(0, IOcount - 1): n = ndr + IOcountmax piRFn = RFname.format(n) if self.RFcenter == True: dist_edgey = self.die_height-self.cleave -\ (IOcount-1)*self.RFpitch-2*self.RFside else: dist_edgey = 0 if self.RFx_doublerow == None: self.RFx_doublerow = 1.0 * self.RFpitch if self.RFy_doublerow == None: self.RFy_doublerow = 0.5 * self.RFpitch p = nd.Pin(piRFn).put(\ self.die_length-self.cleave-self.RFedge-self.RFx_doublerow, ndr*self.RFpitch+self.RFside+0.5*dist_edgey+self.RFy_doublerow, 180) self.arrow.put(p) text = nd.text(piRFn, layer=annotationlayer, height=textheight, align='rc') text.put(p.move(textmove)) #Fiber positions dist_edgey = self.die_height - self.cleave - self.fiberarea faa_len = self.cleave + 50 if self.show_fiberarea: farea = geom.box(width=self.fiberarea, length=faa_len) poly = nd.Polygon(layer=fiberIOlayer, points=farea) poly.put(-faa_len - 0.5 * self.cleave, 0.5 * dist_edgey + 0.5 * self.fiberarea, 0) else: print( 'Set show_fiberarea == True to see the fiber allowed area for this package.' ) return C
def cell(self): """Create a Cell with DC and RF postitions. Returns: Cell: cell for packaging""" # Optical positions come from foundry. l = self.length - self.cleave h = self.height - self.cleave with nd.Cell(name='{}_{}'.format(self.name, next(self.instnum))) as C: # Number of DC pads nNS = int((l - 2 * self.DCminside) / self.DCpitch) + 1 nEW = int((h - 2 * self.DCminside) / self.DCpitch) + 1 nDC = [nNS, nNS, nEW, nEW] # tuple in pins: start position of dc pins on all four sides. dc0 = ( # Bottom nd.Pin('p0B').\ put(l/2-(nNS/2-0.5)*self.DCpitch, self.DC0edge, 90), # Top nd.Pin('p0T').\ put(l/2+(nNS/2-0.5)*self.DCpitch, h-self.DC0edge, 270), # Left nd.Pin('p0L').\ put(self.DC0edge, h/2+(nEW/2-0.5)*self.DCpitch, 0), # Right nd.Pin('p0R').\ put(l-self.DC0edge, h/2-(nEW/2-0.5)*self.DCpitch, 180), ) # Number of RF pads nNS = int((l - 2 * self.RFminside) / self.RFpitch) nEW = int((h - 2 * self.RFminside) / self.RFpitch) nRF = [nNS, nNS, nEW, nEW] # tuple in pins: start position of dc pins on all four sides. rf0 = ( # Bottom nd.Pin('rfS').\ put(l/2-(nNS/2-0.5)*self.RFpitch, self.RFedge, 90), # Top nd.Pin('rfN').\ put(l/2+(nNS/2-0.5)*self.RFpitch, h-self.RFedge, 270), # Left nd.Pin('rfW').\ put(self.RFedge, h/2+(nEW/2-0.5)*self.RFpitch, 0), # Right nd.Pin('rfE').\ put(l-self.RFedge, h/2-(nEW/2-0.5)*self.RFpitch, 180), ) # Place DC0 pins for pin, n, name, arrow in zip(dc0, nDC, DC0name, self.DC0): if not arrow: continue # Don't generate the pins for i in range(0, n): loc = nd.Pin(name.format(i)).\ put(pin.move(0,-i*self.DCpitch,0)) self._put_arrow(loc, name, i) # Place DC1 pins for pin, n, name, arrow in zip(dc0, nDC, DC1name, self.DC1): if not arrow: continue # Don't generate the pins for i in range(0, n - 1): loc = nd.Pin(name.format(i)).\ put(pin.move(self.DC1edge-self.DC0edge, -(i+0.5)*self.DCpitch, 0)) self._put_arrow(loc, name, i) # Place RF pins for p, n, name, arrow in zip(rf0, nRF, RFname, self.RF): if not arrow: continue # Don't generate the pins for i in range(0, n): loc = nd.Pin(name.format(i)).\ put(p.move(0,-i*self.RFpitch,0)) self._put_arrow(loc, name, i) #Fiber positions faalen = self.cleave + 50 if self.fiberareaR: dist_edgey = self.height - self.cleave - self.fiberareaR farea = geom.box(width=self.fiberareaR, length=faalen) poly = nd.Polygon(layer=fiberIOlayer, points=farea) poly.put(self.length - 0.5 * self.cleave, 0.5 * dist_edgey + 0.5 * self.fiberareaR, 0) if self.fiberareaL: dist_edgey = self.height - self.cleave - self.fiberareaL farea = geom.box(width=self.fiberareaL, length=faalen) poly = nd.Polygon(layer=fiberIOlayer, points=farea) poly.put(-faalen - 0.5 * self.cleave, 0.5 * dist_edgey + 0.5 * self.fiberareaL, 0) return C
def put_boundingbox(pinname, length, width, raise_pins=True, outline=True, align='lc', name=True, params=True, move=(0, 0, 0)): """Create bounding box (bbox) cell inside the active cell. This function places a bbox cell and raises by default the bbox pins into the active cell. The bbox displays a bbox outline (can be switched off). By default it also adds the active cellname and parameters. Args: pin (str): pin to place bbox on (center left of bbox) length (float): length of the bbox with (float): width of the bbox raise_pins (bool): raise bbox pins into active cell (default = True) outline (bool): draw bbox outline (default = True) align (str): align the bbox on the specified bbox pin <pinname> (default = 'lc') name (bool): display the (active) cell name in the bbox. (default = True) params (bool): add parameter annotation to the bbox move (tuple): move the bbox placement by (float, float, float) Returns: None """ cell = cfg.cells[-1] _paramsname = cell.cell_paramsname _parameters = cell.parameters with nd.Cell(name='bbox', instantiate=False) as bbox: outline = geom.box(length, width) nd.Polygon(layer='bbox', points=outline).put(0) stbs = cfg.bbox_stubs and outline nd.Pin('lb', type='bbox', show=stbs).put(0, -0.5 * width, 180) nd.Pin('lc', type='bbox', show=stbs).put(0, 0, 180) nd.Pin('lt', type='bbox', show=stbs).put(0, 0.5 * width, 180) nd.Pin('tl', type='bbox', show=stbs).put(0, 0.5 * width, 90) nd.Pin('tc', type='bbox', show=stbs).put(0.5 * length, 0.5 * width, 90) nd.Pin('tr', type='bbox', show=stbs).put(length, 0.5 * width, 90) nd.Pin('rt', type='bbox', show=stbs).put(length, 0.5 * width, 0) nd.Pin('rc', type='bbox', show=stbs).put(length, 0, 0) nd.Pin('rb', type='bbox', show=stbs).put(length, -0.5 * width, 0) nd.Pin('br', type='bbox', show=stbs).put(length, -0.5 * width, -90) nd.Pin('bc', type='bbox', show=stbs).put(0.5 * length, -0.5 * width, -90) nd.Pin('bl', type='bbox', show=stbs).put(0, -0.5 * width, -90) nd.Pin('cc', type='bbox', show=cfg.bbox_stubs).put(0.5 * length, 0, 0) if stbs: nd.put_stub(['lb', 'tl', 'rt', 'br'], pinshape='arrow_righthalf', pinsize=cfg.pin_settings['bbox_pin_size'], pinlayer=cfg.pin_settings['bbox_pin_layer'], annotation_layer='bbox_pin_text') nd.put_stub(['lt', 'tr', 'rb', 'bl'], pinshape='arrow_lefthalf', pinsize=cfg.pin_settings['bbox_pin_size'], pinlayer=cfg.pin_settings['bbox_pin_layer'], annotation_layer='bbox_pin_text') nd.put_stub(['lc', 'tc', 'rc', 'bc'], pinshape='arrow_full', pinsize=cfg.pin_settings['bbox_pin_size'], pinlayer=cfg.pin_settings['bbox_pin_layer'], annotation_layer='bbox_pin_text') if name: cellname(cellname=_paramsname, length=length, width=width, align='cc').\ put(bbox.pin['cc']) if params: parameters(parameters=_parameters).put(bbox.pin['cc']) # options to align the bbox in this cell w.r.t. to its pins: align_shift = { 'lb': (0, 0.5 * width), 'lc': (0, 0), 'lt': (0, -0.5 * width), 'rb': (-length, 0.5 * width), 'rc': (-length, 0), 'rt': (-length, -0.5 * width), 'bc': (-0.5 * length, 0.5 * width), 'cc': (-0.5 * length, 0), 'tc': (-0.5 * length, -0.5 * width) } dx = align_shift[align][0] dy = align_shift[align][1] box = bbox.put(cfg.cells[-1].pin[pinname].move(dx, dy).move(*move)) cell.length = length cell.width = width if raise_pins: box.raise_pins(bbox_pinnames, show=False) return None
def _makestub(xs_guide=None, width=0, length=2.0, shape=None, pinshape=None, pinsize=None, pinlayer=None, cell=None): """Create a stub in the logical layers. A stub is the stub of a xsection shape around a pin to visualize a connection. A pincell is added to the stub to indicate the pin position inside the stub. The new stub is added to the stubs dictionary: {name: stubcell} Args: xs_guide (str): name of xsection width (float): stub width thick (float): thickness of stub into cell (length) shape (str): shape of the stub: 'box' | 'circ' (default = 'box') pinshape (string): pinshape used in the stub pinsize (float): scaling factor of the pinshape (default = 1) cell (Cell): use the provided cell as stub instead of creating a new stub cell Returns: str: name of the stub """ try: xs_logic = cfg.stubmap[xs_guide] except: # if no stub defined, use the xs as its own stub. if xs_guide is None: arrow = make_pincell(layer=pinlayer, shape=pinshape, size=pinsize) return arrow if xs_guide not in cfg.XSdict.keys(): if xs_guide not in missing_xs: missing_xs.append(xs_guide) if xs_guide != cfg.default_xs_name: print("Can not make a stub in undefined xsection '{0}'.\n"\ " Possible causes: '{0}' is misspelled or not yet defined.\n"\ " Will use xsection '{2}' instead and continue.\n" " To define a new xsection:\n"\ " add_xsection(name='{0}')\n"\ " or with layers info and adding a custom stub:\n"\ " add_xsection(name='{0}', layer=1)\n"\ " add_xsection(name='{1}', layer=2)\n"\ " add_stub(xsection='{0}', stub='{1}')".\ format(xs_guide, 'stubname', cfg.default_xs_name)) xs_guide = cfg.default_xs_name cfg.stubmap[xs_guide] = xs_guide xs_logic = xs_guide name = stubname(xs_guide, width, length, shape, pinshape, pinsize, pinlayer) if name in stubs.keys(): return name # make a new stub: stubshapes = ['box', 'circle'] arrow = make_pincell(layer=pinlayer, shape=pinshape, size=pinsize) if width is None: width = 0 with nd.Cell(name, instantiate=cfg.stub_instantiate, store_pins=False) as C: arrow.put(0) if cell is not None: cell.put() else: for lay, growx, acc in nd.layeriter(xs_logic): if shape is 'circle': outline = geom.circle(radius=0.5 * length, N=32) else: outline = geom.box(width=width + 2 * growx, length=length) if width != 0: nd.Polygon(layer=lay, points=outline).put(0, 0, 180) if shape not in stubshapes: print( "Warning: stub shape '{}' not recognized, possible options are {}." .format(shape, stubshapes)) stubs[name] = C return name #name can have change to default_xs