255 lines
11 KiB
Python
255 lines
11 KiB
Python
|
|
from ..gds_devices import gds_lib_load
|
|
import nazca as nd
|
|
from ..routing import Route
|
|
|
|
from ..electronics import PADs
|
|
|
|
CUMEC_LAYER_MAP = {
|
|
|
|
(31,1): 'STRIP_COR',
|
|
(31,2): 'STRIP_CLD',
|
|
(31,3): 'STRIP_TRE',
|
|
(31,4): 'STRIP_HOL',
|
|
|
|
(32,1): 'SRIB_COR',
|
|
(32,2): 'SRIB_CLD',
|
|
(32,3): 'SRIB_TRE',
|
|
(32,4): 'SRIB_HOL',
|
|
|
|
(33,1): 'RIB_COR',
|
|
(33,2): 'RIB_CLD',
|
|
(33,3): 'RIB_TRE',
|
|
(33,4): 'RIB_HOL',
|
|
|
|
(11,1): 'METAL',
|
|
(12,1): 'METAL_2',
|
|
(51,1): 'VIA_H2M',
|
|
(60,0): 'PASS1',
|
|
(63,0): 'PASS2',
|
|
(20,0): 'PAD',
|
|
|
|
(61,0): 'GC_OPEN',
|
|
|
|
}
|
|
|
|
|
|
class PAD_60_80(gds_lib_load) :
|
|
def __init__(self,pdk_path: str="CUMEC_SiP130Cu_PDK") -> None:
|
|
lib_path = pdk_path + "\\bondpads"
|
|
lib_name = "BP_60_80"
|
|
cellname = "Fixed_BP_60_80"
|
|
super().__init__(lib_path=lib_path, lib_name=lib_name, cell_name=cellname, rename=cellname+"_WithPin", instantiate=False)
|
|
self.add_pin(pin_name='p1',xya=(0,0,-90))
|
|
|
|
class GPD_1550(gds_lib_load):
|
|
def __init__(self,pdk_path: str="CUMEC_SiP130Cu_PDK") -> None:
|
|
lib_path = pdk_path + "\\photodetector"
|
|
lib_name = "GPD_1550_unit"
|
|
cell_name = "Fixed_GPD_1550_unit"
|
|
super().__init__(lib_path=lib_path, lib_name=lib_name, cell_name=cell_name, rename=cell_name+"_WithPin", instantiate=False,
|
|
cellsreused=["Fixed_GPD_1550_unit"],layermap=CUMEC_LAYER_MAP)
|
|
self.w_wg = 0.45
|
|
self.length = 110.4
|
|
self.add_pin(pin_name='ep1', xya=(55.2, 3.325, 90), width=1) ## anode
|
|
self.add_pin(pin_name='en1', xya=(55.2,-3.325,-90), width=1) ## cathod
|
|
self.add_pin(pin_name='a1', xya=(0,0,180), width=0.45)
|
|
self.add_pin(pin_name='b1', xya=(110.4,0,0), width=self.w_wg)
|
|
|
|
|
|
class EC_1550(gds_lib_load):
|
|
'''
|
|
CUMEC TE Grating Coupler at 1550nm.
|
|
'''
|
|
def __init__(self,pdk_path: str="CUMEC_SiP130Cu_PDK") -> None:
|
|
lib_path = pdk_path + "\\edge_couplers"
|
|
lib_name = "EC_1550"
|
|
cell_name = "Fixed_EC_1550"
|
|
super().__init__(lib_path=lib_path, lib_name=lib_name, cell_name=cell_name, rename=cell_name+"_WithPin", instantiate=False,
|
|
cellsreused=["Fixed_EC_1550"],layermap=CUMEC_LAYER_MAP)
|
|
self.w_wg = 0.45
|
|
self.length = 689.9
|
|
self.add_pin(pin_name='g1', xya=(0,0,0), width=self.w_wg)
|
|
self.add_pin(pin_name='b0', xya=(-673.9,0,180))
|
|
self.add_pin(pin_name='a0',xya=(-673.9,0,0))
|
|
|
|
class GC_TE_1550(gds_lib_load):
|
|
'''
|
|
CUMEC TE Grating Coupler at 1550nm.
|
|
'''
|
|
def __init__(self,pdk_path: str="CUMEC_SiP130Cu_PDK") -> None:
|
|
lib_path = pdk_path + "\\grating_couplers"
|
|
lib_name = "GC_TE_1550"
|
|
cell_name = "Fixed_GC_TE_1550"
|
|
super().__init__(lib_path=lib_path, lib_name=lib_name, cell_name=cell_name, rename=cell_name+"_WithPin", instantiate=False,cellsreused=["Fixed_GC_TE_1550"],layermap=CUMEC_LAYER_MAP)
|
|
self.w_wg = 0.45
|
|
self.add_pin(pin_name='g1', xya=(0,0,0), width=self.w_wg)
|
|
|
|
def generate_test_gds(self,gc2gc_dX=300):
|
|
with nd.Cell(name=self.cell.cell_name+"_test",instantiate=False) as C:
|
|
gc_input = self.cell.put('g1',-gc2gc_dX/2,0,180)
|
|
gc_output = self.cell.put('g1',gc2gc_dX/2,0,0)
|
|
stripe=Route(radius=5, width=self.w_wg, xs="strip")
|
|
stripe.strt_p2p(pin1=gc_input.pin['g1'],pin2=gc_output.pin['g1'],arrow=False).put()
|
|
return C
|
|
|
|
class GC_TM_1550(gds_lib_load):
|
|
'''
|
|
CUMEC TE Grating Coupler at 1550nm.
|
|
'''
|
|
def __init__(self,pdk_path: str="CUMEC_SiP130Cu_PDK") -> None:
|
|
lib_path = pdk_path + "\\grating_couplers"
|
|
lib_name = "GC_TM_1550"
|
|
cell_name = "Fixed_GC_TM_1550"
|
|
super().__init__(lib_path=lib_path, lib_name=lib_name, cell_name=cell_name, rename=cell_name+"_WithPin", instantiate=False,cellsreused=["Fixed_GC_TM_1550"],layermap=CUMEC_LAYER_MAP)
|
|
self.w_wg = 0.5
|
|
self.add_pin(pin_name='g1', xya=(0,0,0), width=self.w_wg)
|
|
|
|
def generate_test_gds(self,gc2gc_dX=300):
|
|
with nd.Cell(name=self.cell.cell_name+"_test",instantiate=False) as C:
|
|
gc_input = self.cell.put('g1',-gc2gc_dX/2,0,180)
|
|
gc_output = self.cell.put('g1',gc2gc_dX/2,0,0)
|
|
stripe=Route(radius=5, width=self.w_wg, xs="strip")
|
|
stripe.strt_p2p(pin1=gc_input.pin['g1'],pin2=gc_output.pin['g1'],arrow=False).put()
|
|
return C
|
|
|
|
class GC_TE_1310(gds_lib_load):
|
|
'''
|
|
CUMEC TE Grating Coupler at 1310nm.
|
|
'''
|
|
def __init__(self,pdk_path: str="CUMEC_SiP130Cu_PDK") -> None:
|
|
lib_path = pdk_path + "\\grating_couplers"
|
|
lib_name = "GC_TE_1310"
|
|
cell_name = "Fixed_GC_TE_1310"
|
|
super().__init__(lib_path=lib_path, lib_name=lib_name, cell_name=cell_name, rename=cell_name+"_WithPin", instantiate=False,cellsreused=["Fixed_GC_TE_1310"],layermap=CUMEC_LAYER_MAP)
|
|
self.w_wg = 0.38
|
|
self.add_pin(pin_name='g1', xya=(0,0,0), width=self.w_wg)
|
|
|
|
|
|
class MMI_1x2_TE_1550(gds_lib_load):
|
|
'''
|
|
CUMEC TE 1by 2 MMI at 1550nm.
|
|
'''
|
|
def __init__(self,pdk_path: str="CUMEC_SiP130Cu_PDK",sharp_patch: bool=True) -> None:
|
|
lib_path = pdk_path + "\\mmis"
|
|
lib_name = "M1X2_TE_1550"
|
|
cellname = "Fixed_M1X2_TE_1550"
|
|
super().__init__(lib_path=lib_path, lib_name=lib_name, cell_name=cellname, rename=cellname+"_WithPin", instantiate=False,cellsreused=["Fixed_M1X2_TE_1550"],layermap=CUMEC_LAYER_MAP)
|
|
self.length = 12
|
|
self.width = 1.55
|
|
self.w_wg = 0.45
|
|
|
|
self.add_pin(pin_name='a1', xya=(0,0,180), width=self.w_wg)
|
|
self.add_pin(pin_name='b1', xya=(self.length,self.width/2,0), width=self.w_wg)
|
|
self.add_pin(pin_name='b2', xya=(self.length,-self.width/2,0), width=self.w_wg)
|
|
|
|
def generate_test_gds(self,gc,gc2gc_length=300):
|
|
with nd.Cell(name=self.cell.cell_name+"_test", instantiate=False) as C:
|
|
gc_input = gc.cell.put('g1',0,0,180)
|
|
gc_output_1 = gc.cell.put('g1',gc2gc_length, 20,0)
|
|
gc_output_2 = gc.cell.put('g1',gc2gc_length,-20,0)
|
|
# Put DC
|
|
dc = self.cell.put('a1',gc_input.pin['g1'].move((gc2gc_length-self.length)/2,0,0))
|
|
# Connect all the ports
|
|
stripe=Route(radius=5, width=self.w_wg, xs="strip")
|
|
stripe.sbend_route_p2p(pin1=gc_input.pin['g1'],pin2=dc.pin['a1'],arrow=False).put()
|
|
stripe.sbend_route_p2p(pin1=gc_output_1.pin['g1'],pin2=dc.pin['b1'],arrow=False).put()
|
|
stripe.sbend_route_p2p(pin1=gc_output_2.pin['g1'],pin2=dc.pin['b2'],arrow=False).put()
|
|
return C
|
|
|
|
class MMI_1x2_TE_1310(gds_lib_load):
|
|
'''
|
|
CUMEC TE 1by 2 MMI at 1310nm.
|
|
'''
|
|
def __init__(self,pdk_path: str="CUMEC_SiP130Cu_PDK",sharp_patch: bool=True) -> None:
|
|
lib_path = pdk_path + "\\mmis"
|
|
lib_name = "M1X2_TE_1310"
|
|
cellname = "Fixed_M1X2_TE_1310"
|
|
super().__init__(lib_path=lib_path, lib_name=lib_name, cell_name=cellname, rename=cellname+"_WithPin", instantiate=False,cellsreused=["Fixed_M1X2_TE_1310"],layermap=CUMEC_LAYER_MAP)
|
|
self.length = 15
|
|
self.width = 1.45
|
|
self.w_wg = 0.38
|
|
self.add_pin(pin_name='a1', xya=(0,0,180), width=self.w_wg)
|
|
self.add_pin(pin_name='b1', xya=(self.length,self.width/2,0), width=self.w_wg)
|
|
self.add_pin(pin_name='b2', xya=(self.length,-self.width/2,0), width=self.w_wg)
|
|
|
|
class MMI_2x2_TE_1550(gds_lib_load):
|
|
'''
|
|
CUMEC TE 1by 2 MMI at 1310nm.
|
|
'''
|
|
def __init__(self,pdk_path: str="CUMEC_SiP130Cu_PDK") -> None:
|
|
lib_path = pdk_path + "\\mmis"
|
|
lib_name = "M2X2_TE_1550"
|
|
cellname = "Fixed_M2X2_TE_1550"
|
|
super().__init__(lib_path=lib_path, lib_name=lib_name, cell_name=cellname, rename=cellname+"_WithPin", instantiate=False,cellsreused=["Fixed_M2X2_TE_1550"],layermap=CUMEC_LAYER_MAP)
|
|
self.length = 125.4
|
|
self.width = 3
|
|
self.w_wg = 0.45
|
|
self.add_pin(pin_name='a1', xya=(0,self.width/2,180), width=self.w_wg)
|
|
self.add_pin(pin_name='a2', xya=(0,-self.width/2,180), width=self.w_wg)
|
|
self.add_pin(pin_name='b1', xya=(self.length,self.width/2,0), width=self.w_wg)
|
|
self.add_pin(pin_name='b2', xya=(self.length,-self.width/2,0), width=self.w_wg)
|
|
|
|
class CRX_TE_1550(gds_lib_load):
|
|
def __init__(self,pdk_path: str="CUMEC_SiP130Cu_PDK") -> None:
|
|
lib_path = pdk_path + "\\crossings"
|
|
lib_name = "X_TE_1550"
|
|
cellname = "Fixed_X_TE_1550"
|
|
super().__init__(lib_path=lib_path, lib_name=lib_name, cell_name=cellname, rename=cellname+"_WithPin", instantiate=False,cellsreused=["Fixed_X_TE_1550"],layermap=CUMEC_LAYER_MAP)
|
|
self.length = 5
|
|
self.width = 5
|
|
self.w_wg = 0.45
|
|
self.xs = 'strip'
|
|
self.L_arm = 5
|
|
self.add_pin(pin_name='a1',xya=(-5,0,180),width=self.w_wg)
|
|
self.add_pin(pin_name='b1',xya=( 5,0,0),width=self.w_wg)
|
|
self.add_pin(pin_name='a2',xya=( 0,5,90),width=self.w_wg)
|
|
self.add_pin(pin_name='b2',xya=( 0,-5,-90),width=self.w_wg)
|
|
|
|
def generate_test_gds(self,gc,num=5,dX_gc2gc=400,w_end=0.2,L_end=10):
|
|
with nd.Cell(instantiate=False) as C:
|
|
|
|
if (isinstance(gc,nd.Cell)):
|
|
gc_cell = gc
|
|
elif (hasattr(gc,'cell')):
|
|
gc_cell = gc.cell
|
|
else :
|
|
raise Exception("ERROR: In <mxpiv::passive::cross::generate_test_gds>, <gc> is not recongized")
|
|
|
|
dL = self.L_arm*2
|
|
|
|
dX = dL*1.75
|
|
|
|
pic_strip = Route(radius=10,width=self.w_wg,xs=self.xs)
|
|
|
|
gc_In = gc_cell.put('g1',-dX_gc2gc/2,0,180)
|
|
pin_pre = gc_In.pin['g1']
|
|
for _idx_ in range(0,num):
|
|
inst = self.cell.put('a0',_idx_*dX - (num/2 - 1/2)*dX)
|
|
pic_strip.strt_p2p(pin1=pin_pre,pin2=inst.pin['a1'],arrow=False).put()
|
|
pin_pre = inst.pin['b1']
|
|
|
|
nd.taper(length=L_end/2,width1=self.w_wg,width2=w_end,xs=self.xs).put(inst.pin['b2'])
|
|
nd.strt(length=L_end/2,width=w_end,xs=self.xs).put()
|
|
nd.taper(length=L_end/2,width1=self.w_wg,width2=w_end,xs=self.xs).put(inst.pin['a2'])
|
|
nd.strt(length=L_end/2,width=w_end,xs=self.xs).put()
|
|
|
|
gc_Out = gc_cell.put('g1', dX_gc2gc/2,0,0)
|
|
pic_strip.strt_p2p(pin1=pin_pre,pin2=gc_Out.pin['g1'],arrow=False).put()
|
|
return C
|
|
|
|
class PBS_1550(gds_lib_load):
|
|
def __init__(self,pdk_path: str="CUMEC_SiP130Cu_PDK") -> None:
|
|
lib_path = pdk_path + "\\polarization_beam_splitter"
|
|
lib_name = "PBS_1550"
|
|
cellname = "Fixed_PBS_1550"
|
|
super().__init__(lib_path=lib_path, lib_name=lib_name, cell_name=cellname, rename=cellname+"_WithPin", instantiate=False,cellsreused=cellname,layermap=CUMEC_LAYER_MAP)
|
|
self.length = 5
|
|
self.width = 5
|
|
self.w_wg = 0.45
|
|
self.xs = 'strip'
|
|
self.add_pin(pin_name='a1',xya=(-0,0,180),width=self.w_wg)
|
|
self.add_pin(pin_name='b1',xya=( 87.2,0,0),width=self.w_wg)
|
|
self.add_pin(pin_name='b2',xya=( 87.2,-20,0),width=self.w_wg)
|
|
|