def _move_probe_ref(self,cell): device_ref=cell["Device"] probe_ref=cell["Probe"] bottom_ports=ppt.find_ports(cell,'bottom',depth=0,exact=True) try: probe_port=probe_ref.ports['SigN'] except: probe_port=probe_ref.ports['SigN_1'] top_ports=ppt.find_ports(device_ref,'top') if len(top_ports)>1: probe_ref.connect( port=probe_port, destination=bottom_ports[0], overlap=-self.probe_conn_distance.y) else: probe_ref.connect( port=probe_port, destination=bottom_ports[0], overlap=-self.probe_dut_distance.y)
def _make_internal_ground_connections(self,cell): lx_ports=ppt.find_ports(cell,'GroundLX',depth=0) rx_ports=ppt.find_ports(cell,'GroundRX',depth=0) if len(lx_ports)<=1 or len(rx_ports)<=1: return else: lx_ports.remove(lx_ports[0]) rx_ports.remove(rx_ports[-1]) polyconn=pc.PolyRouting() polyconn.layer=self.plate_layer for l,r in zip(lx_ports,rx_ports): polyconn.source=l polyconn.destination=r cell.add(polyconn.draw()) cell.remove(cell.ports[l.name]) cell.remove(cell.ports[r.name])
def add_pads(cell,pad,tag='top',exact=False): ''' add pad designs to a cell, connecting it to selected ports. Parameters: ----------- cell : Device pad : pt.LayoutPart tags : str (or iterable of str) used to find ports ''' if not isinstance(tag,str): ports=[] for t in tag: ports.extend(ppt.find_ports(cell,t,depth=0,exact=exact)) else: ports=ppt.find_ports(cell,tag,depth=0,exact=exact) pad_cell=Device() for port in ports: pad.port=port pad_ref=pad_cell.add_ref(pad.draw()) pad_ref.connect('conn',destination=port) cell.add_ref(pad_cell,alias="Pad")
def _setup_probe(self,device_cell): top_ports=[pt.Point(p.midpoint) for p in ppt.find_ports(device_cell,'top',depth=0)] bottom_ports=[pt.Point(p.midpoint) for p in ppt.find_ports(device_cell,'bottom',depth=0)] top_port_midpoint=st.get_centroid(*top_ports) bottom_port_midpoint=st.get_centroid(*bottom_ports) self.probe.offset=pt.Point( (top_port_midpoint.x-bottom_port_midpoint.x), (top_port_midpoint.y-bottom_port_midpoint.y)+2*self.probe_dut_distance.y)
def _setup_ground_routing(self,cell,label): device_ref=cell["Device"] probe_ref=cell["Probe"] bbox=super()._bbox_mod(device_ref.bbox) if isinstance(self.probe,pc.GSGProbe): for index,groundroute in enumerate([self.gndlefttrace,self.gndrighttrace]): groundroute.layer=self.probe.ground_layer groundroute.clearance=bbox groundroute.overhang=None groundroute.trace_width=self.gnd_routing_width if index==0: groundroute.side='left' if label=='straight': groundroute.source=probe_ref.ports['GroundLXN'] elif label=='side': groundroute.source=(probe_ref.ports['GroundLXW'],) elif index==1: groundroute.side='right' if label=='straight': groundroute.source=(probe_ref.ports['GroundRXN'],) elif label=='side': groundroute.source=(probe_ref.ports['GroundRXE'],) dest_ports=ppt.find_ports(device_ref,'top') groundroute.destination=tuple(dest_ports) elif isinstance(self.probe,pc.GSProbe): raise ValueError("OnePortProbed with GSprobe to be implemented ") else: raise ValueError("OnePortProbed without GSG/GSprobe to be implemented ")
def _add_signal_connection(self,cell,tag): device_cell=cell["Device"] ports=ppt.find_ports(device_cell,tag,depth=0) if len(ports)>1: distance=self.probe_dut_distance.y-self.probe_conn_distance.y port_mid=st.get_centroid_ports(*ports) if distance-port_mid.width>0: sigtrace=connect_ports( device_cell, tag=tag, layer=self.probe.sig_layer, distance=distance-port_mid.width, metal_width=port_mid.width) else: sigtrace=connect_ports( device_cell, tag=tag, layer=self.probe.sig_layer, distance=0, metal_width=distance) if not self.parasitic_control: sigtrace.ports[tag].width=sigtrace.xsize paux=ppt.shift_port(sigtrace.ports[tag],self.probe_conn_distance.y/3) paux.width=self.probe.size.x sigtrace.add(pr.route_quad( sigtrace.ports[tag],paux,layer=self.probe.sig_layer)) cell.absorb(cell<<sigtrace) sigtrace.ports[tag].width=self.probe.size.x ppt.copy_ports(sigtrace,cell) else: cell.add_port(port=device_cell.ports[tag])
def _draw_ground_extensions(self,cell): device_cell=cell["Device"] output_cell=Device() lx_device_ports=[] rx_device_ports=[] gnd_ports=ppt.find_ports(device_cell,'Ground',depth=0) if not gnd_ports: return output_cell for p in gnd_ports: if "LX" in p.name: lx_device_ports.append(p) elif "RX" in p.name: rx_device_ports.append(p) for p in lx_device_ports: ext_length=abs(cell.xmin-p.midpoint[0]+self.gnd_routing_width) output_cell.add(ppt.extend_port(p, width=p.width, length=ext_length, layer=self.gndlefttrace.layer)) for p in rx_device_ports: ext_length=abs(cell.xmax-p.midpoint[0]-self.gnd_routing_width) output_cell.add(ppt.extend_port(p, width=p.width, length=ext_length, layer=self.gndlefttrace.layer)) return output_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
def _draw_device_grounds(self,device_cell,probe_cell,label): output_cell=Device() lx_device_ports=[] rx_device_ports=[] gnd_ports=ppt.find_ports(device_cell,'Ground',depth=0) if not gnd_ports: return output_cell for p in gnd_ports: p_adj=Port( name=p.name, midpoint=p.midpoint, width=probe_cell['Port1'].size[1], orientation=p.orientation) if "LX" in p.name: lx_device_ports.append(p_adj) elif "RX" in p.name: rx_device_ports.append(p_adj) r=pc.Routing() r.layer=self.gndlefttrace.layer r.clearance=pt._bbox_to_tuple(self._bbox_mod(device_cell.bbox)) r.trace_width=self.gnd_routing_width ## left connections if label=='side': r.source=tuple(ppt.find_ports(probe_cell,'GroundLXW',depth=0)) elif label=='straight': r.source=(probe_cell.ports['GroundLXN_1'],) r.destination=tuple(lx_device_ports) r.side='left' output_cell.absorb(output_cell<<r.draw()) ## right connections if label=='side': r.source=tuple(ppt.find_ports(probe_cell,'GroundRXE',depth=0)) elif label=='straight': r.source=(probe_cell.ports['GroundRXN_1'],) r.destination=tuple(rx_device_ports) r.side='right' output_cell.absorb(output_cell<<r.draw()) return output_cell