def _make_internal_ground_connections(self, cell): lx_ports = pt._find_ports(cell, 'GroundLX', depth=0) rx_ports = pt._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 _move_probe_ref(self, cell): device_ref = cell["Device"] probe_ref = cell["Probe"] bottom_ports = pt._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 = pt._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 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(pt._find_ports(cell, t, depth=0, exact=exact)) else: ports = pt._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 pt._find_ports(device_cell, 'top', depth=0) ] bottom_ports = [ pt.Point(p.midpoint) for p in pt._find_ports(device_cell, 'bottom', depth=0) ] top_port_midpoint = pt._get_centroid(*top_ports) bottom_port_midpoint = pt._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 _add_signal_connection(self, cell, tag): device_cell = cell["Device"] ports = pt._find_ports(device_cell, tag, depth=0) if len(ports) > 1: distance = self.probe_dut_distance.y - self.probe_conn_distance.y port_mid = pt._get_centroid_ports(ports) if distance - port_mid.width > 0: sigtrace = connect_ports(device_cell, tag=tag, layers=self.probe.sig_layer, distance=distance - port_mid.width, metal_width=port_mid.width) else: sigtrace = connect_ports(device_cell, tag=tag, layers=self.probe.sig_layer, distance=0, metal_width=distance) _add_default_ground_vias(self, sigtrace) cell.absorb(cell << sigtrace) sigtrace.ports[tag].width = self.probe.size.x pt._copy_ports(sigtrace, cell) else: cell.add_port(port=device_cell.ports[tag])
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.set_auto_overhang(True) 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 = pt._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 connect_ports(cell: Device, tag: str = 'top', layers: tuple = (LayoutDefault.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 = pt._find_ports(cell, tag, depth=0) ports.sort(key=lambda x: x.midpoint[0]) ports_centroid = pt._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 << pt._draw_multilayer( 'compass', layers, size=(p.width, abs(midpoint_projected.y - p.midpoint[1]))) straight_conn.connect("S", p) cross_conn = output_cell << pt._draw_multilayer( 'compass', layers, size=(output_cell.xsize, metal_width)) cross_conn.connect('S', new_port, overlap=metal_width) output = pt.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 = pt._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.MultiRouting() 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( pt._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( pt._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