def _draw_ground_routing(self): if isinstance(self.probe,pc.GSGProbe): routing_cell=Device() routing_cell.absorb(routing_cell<<self.gndlefttrace.draw()) routing_cell.absorb(routing_cell<<self.gndrighttrace.draw()) return st.join(routing_cell) else : raise ValueError("To be implemented")
def resistivity_test_cell(): """Create cell with standard Resisistivity Test Returns ------ cell : phidl.Device """ with open(str(pathlib.Path(__file__).parent/'ResistivityTest.gds'), 'rb') as infile: cell=pg.import_gds(infile,cellname='TestCell') cell=st.join(cell) cell.name='ResistivityTest' return cell
def draw(self): device = self.device df_original = device.get_params() master_cell = Device(name=self.name) cells = [] param = self.x_param df = {} for index in range(len(param)): for name, value in zip(param.names, param.values): df[name] = value[index] device.set_params(df) if self.base_params: device.set_params(self.base_params) new_cell = st.join(device.draw()) new_cell.name = self.name + "_" + str(index + 1) if self.labels_top is not None: self.text.label = self.labels_top[index] self.text.add_to_cell(new_cell, anchor_source='s', anchor_dest='n', offset=(0, 0.02)) if self.labels_bottom is not None: self.text.label = self.labels_bottom[index] self.text.add_to_cell(new_cell, anchor_source='n', anchor_dest='s', offset=(0, -0.02)) master_cell << new_cell cells.append(new_cell) g = Group(cells) g.distribute(spacing=self.x_spacing) g.align(alignment='ymin') device.set_params(df_original) del device, cells, g return master_cell
def verniers(scale=[1, 0.5, 0.1],layers=[1,2],label='TE',text_size=20,reversed=False): """ Create a cell with vernier aligners. Parameters ---------- scale : iterable of float (default [1,0.5,0.25]) each float in list is the offset of a vernier. for each of them a vernier will be created in the X-Y axis layers : 2-len iterable of int (default [1,2]) define the two layers for the verniers. label : str (default "TE") add a label to the set of verniers. text_size : float (default) label size reversed : boolean if true, creates a negative alignment mark for the second layer Returns ------- cell : phidl.Device. """ cell=dl.Device(name="verniers") import numpy if not isinstance(scale, numpy.ndarray): scale=np.array(scale) scale=np.sort(scale) xvern=[] for dim in scale: notch_size=[dim*5, dim*25] notch_spacing=dim*10 num_notches=5 notch_offset=dim row_spacing=0 layer1=layers[0] layer2=layers[1] cal=pg.litho_calipers(\ notch_size,\ notch_spacing,\ num_notches,\ notch_offset,\ row_spacing,\ layer1,\ layer2) cal.flatten() if reversed: tobedel=cal.get_polygons(by_spec=(layer2,0)) cal=cal.remove_polygons(lambda pts, layer, datatype: layer == layer2) replica=dl.Device() replica.add(gdspy.PolygonSet(tobedel,layer=layer2)) frame=dl.Device() frame.add(pg.bbox(replica.bbox,layer=layer2)) frame_ext=dl.Device() frame_ext.add(gdspy.PolygonSet(frame.copy('tmp',scale=1.5).get_polygons(),layer=layer2)) frame_ext.flatten() frame_ext.move(origin=frame_ext.center,destination=replica.center) new_cal=pg.boolean(replica,frame_ext,'xor',layer=layer2) new_cal.rotate(angle=180,center=(cal.xmin+cal.xsize/2,cal.ymin)) new_cal.move(destination=(0,-notch_size[1])) cal<<new_cal cal.flatten() xvern.append(cal) g=dl.Group(xvern) g.distribute(direction='y',spacing=scale[-1]*20) g.align(alignment='x') xcell=dl.Device(name="x") for x in xvern: xcell<<x xcell=st.join(xcell) vern_x=cell<<xcell vern_y=cell<<xcell vern_y.rotate(angle=-90) vern_y.move(origin=(vern_y.xmin,vern_y.y),\ destination=(vern_x.x+scale[-1]*10,vern_x.ymin-scale[-1]*10)) cell.absorb(vern_x) cell.absorb(vern_y) label=pg.text(text=label,size=text_size,layer=layers[0]) label.move(destination=(cell.xmax-label.xsize/2,cell.ymax-2*label.ysize)) overlabel=pg.bbox(label.bbox,layer=layers[1]) overlabel_scaled=dl.Device().add(gdspy.PolygonSet(overlabel.copy('tmp',scale=2).get_polygons(),layer=layers[1])) overlabel_scaled.move(origin=overlabel_scaled.center,\ destination=label.center) cutlab=pg.boolean(label,overlabel_scaled,'xor',layer=layers[1]) cell<<label cell<<cutlab cell=st.join(cell) return cell
def connect_ports( cell : Device, tag : str ='top', layer : int= ld.layerTop, distance : float = 10.0, metal_width: float = None): ''' connects all the ports in the cell with name matching a tag. Parameters: ----------- cell : Device tag: str conn_dist: pt.Point offset from port location layer : tuple. Returns: ---------- cell : Device contains routings and connection port ''' import pirel.pcells as pc ports=ppt.find_ports(cell,tag,depth=0) ports.sort(key=lambda x: x.midpoint[0]) ports_centroid=st.get_centroid_ports(*ports) if len(ports)==1: raise ValueError("pm.connect_ports() : len(ports) must be >1 ") if metal_width is None: metal_width=ports_centroid.width port_mid_norm=pt.Point(ports_centroid.normal[1])-pt.Point(ports_centroid.normal[0]) midpoint_projected=Point(ports_centroid.midpoint)+port_mid_norm*(distance+metal_width) pad_side=ports_centroid.width new_port=Port( name=tag, orientation=ports_centroid.orientation, width=ports_centroid.width, midpoint=midpoint_projected.coord) output_cell=Device() for p in ports: straight_conn=output_cell<<pg.compass( layer=layer,size=(p.width,abs(midpoint_projected.y-p.midpoint[1]))) straight_conn.connect("S",p) cross_conn=output_cell<<pg.compass( layer=layer,size=(output_cell.xsize,metal_width)) cross_conn.connect('S',new_port,overlap=metal_width) output=st.join(output_cell) output.add_port(new_port) return output