518 lines
20 KiB
Python
518 lines
20 KiB
Python
from typing import Any, Optional
|
|
import nazca as nd
|
|
import numpy as np
|
|
from .couplers import ring_bus_wg
|
|
|
|
from .taper import taper_xs2xs
|
|
|
|
from ...geometry import Racetrack,Clothoid,circle,Elipse_dual
|
|
from . import ring_bus_wg
|
|
from ...electronics import Vias
|
|
import nazca.interconnects as IC
|
|
from ...basic import __cell_arg__
|
|
|
|
class Route(IC.Interconnect):
|
|
pass
|
|
# from ...routing import *
|
|
|
|
|
|
|
|
class RacetrackResonator:
|
|
"""
|
|
RacetrackResonator primitive component.
|
|
|
|
This component builds the RacetrackResonator layout cell.
|
|
|
|
Parameters
|
|
----------
|
|
R0 : Any
|
|
Radius parameter in microns.
|
|
w0 : float
|
|
Width parameter in microns.
|
|
R1 : Any
|
|
Radius parameter in microns.
|
|
w1 : float
|
|
Width parameter in microns.
|
|
dLy : float
|
|
Value for the dLy parameter.
|
|
dLx : float
|
|
Value for the dLx parameter.
|
|
name : Optional[str], optional
|
|
Unique identifier for the device cell. Default is None.
|
|
xs : str, optional
|
|
Layer or cross-section name used by the device. Default is 'strip'.
|
|
gap1 : float, optional
|
|
Spacing or gap parameter in microns. Default is 0.2.
|
|
gap2 : float, optional
|
|
Spacing or gap parameter in microns. Default is 0.2.
|
|
w1_bus : float, optional
|
|
Value for the w1_bus parameter. Default is 0.45.
|
|
w2_bus : float, optional
|
|
Value for the w2_bus parameter. Default is 0.45.
|
|
R1_cp : Any, optional
|
|
Radius parameter in microns. Default is None.
|
|
R2_cp : Any, optional
|
|
Radius parameter in microns. Default is None.
|
|
A1_cp : int, optional
|
|
Angle parameter in degrees. Default is 0.
|
|
A2_cp : int, optional
|
|
Angle parameter in degrees. Default is 0.
|
|
w_wg : float, optional
|
|
Width parameter in microns. Default is 0.45.
|
|
R1_att : float, optional
|
|
Radius parameter in microns. Default is 20.
|
|
R2_att : float, optional
|
|
Radius parameter in microns. Default is 20.
|
|
R2_att_min : float, optional
|
|
Radius parameter in microns. Default is 10.
|
|
R1_att_min : float, optional
|
|
Radius parameter in microns. Default is 10.
|
|
A1_att : float, optional
|
|
Angle parameter in degrees. Default is 30.
|
|
A2_att : float, optional
|
|
Angle parameter in degrees. Default is 20.
|
|
Ltp_bus : int, optional
|
|
Length parameter in microns. Default is 10.
|
|
dL_p2p : Optional[float], optional
|
|
Value for the dL_p2p parameter. Default is None.
|
|
L_tilt : int, optional
|
|
Length parameter in microns. Default is 10.
|
|
sharp_patch : bool, optional
|
|
Whether to add geometry patches for sharp corners or cladding continuity. Default is True.
|
|
cell_xs_transition : Any, optional
|
|
Cell or component dependency used by this device. Default is None.
|
|
Euler_trasition : bool, optional
|
|
Value for the Euler_trasition parameter. Default is False.
|
|
res : float, optional
|
|
Value for the res parameter. Default is 0.01.
|
|
show_pins : bool, optional
|
|
Whether to draw pin markers in the generated layout. Default is False.
|
|
"""
|
|
def __init__(self,
|
|
|
|
R0: Any,
|
|
w0: float,
|
|
R1: Any,
|
|
w1: float,
|
|
dLy: float,
|
|
dLx: float,
|
|
name: Optional[str] = None,
|
|
xs: str='strip',
|
|
gap1: float = 0.2,
|
|
gap2: float = 0.2,
|
|
w1_bus: float = 0.45,
|
|
w2_bus: float = 0.45,
|
|
R1_cp: Any = None,
|
|
R2_cp: Any = None,
|
|
A1_cp: int = 0,
|
|
A2_cp: int = 0,
|
|
w_wg: float = 0.45,
|
|
R1_att: float = 20,
|
|
R2_att: float = 20,
|
|
R2_att_min: float= 10,
|
|
R1_att_min: float = 10,
|
|
A1_att: float = 30,
|
|
A2_att: float = 20,
|
|
Ltp_bus: int = 10,
|
|
dL_p2p: Optional[float] = None,
|
|
L_tilt: int = 10,
|
|
sharp_patch: bool=True,
|
|
cell_xs_transition: Any=None,
|
|
Euler_trasition: bool = False,
|
|
res: float = 0.01, ## default to 1nm accurancy
|
|
show_pins: bool=False
|
|
) -> None:
|
|
self.name = name
|
|
if (name==None):
|
|
self.instantiate = False
|
|
else:
|
|
self.instantiate = True
|
|
|
|
self.R0 = R0
|
|
self.R1 = R1
|
|
self.w0 = w0
|
|
self.w1 = w1
|
|
self.dLy = dLy
|
|
self.dLx = dLx
|
|
self.gap1 = gap1
|
|
self.gap2 = gap2
|
|
self.w1_bus = w1_bus
|
|
self.w2_bus = w2_bus
|
|
|
|
if (R1_cp==None):
|
|
self.R1_cp = self.R0+self.w0/2+self.gap1+self.w1_bus/2
|
|
else :
|
|
self.R1_cp = R1_cp
|
|
|
|
if (R2_cp==None):
|
|
self.R2_cp = self.R0+self.w0/2+self.gap2+self.w2_bus/2
|
|
else :
|
|
self.R2_cp = R2_cp
|
|
|
|
|
|
self.A1_cp = A1_cp
|
|
self.A2_cp = A2_cp
|
|
self.w_wg = w_wg
|
|
self.R1_att = R1_att
|
|
self.R2_att = R2_att
|
|
self.R2_att_min = R2_att_min
|
|
self.R1_att_min = R1_att_min
|
|
self.A1_att = A1_att
|
|
self.A2_att = A2_att
|
|
self.Ltp_bus = Ltp_bus
|
|
self.dL_p2p = dL_p2p
|
|
self.L_tilt = L_tilt
|
|
self.xs = xs
|
|
|
|
self.Euler_trasition = Euler_trasition
|
|
self.res = res
|
|
|
|
self.cell = self.generate_gds(sharp_patch=sharp_patch,show_pins=show_pins)
|
|
|
|
def generate_gds(self,sharp_patch=True,show_pins=False):
|
|
|
|
with nd.Cell(name=self.name,instantiate=self.instantiate) as C:
|
|
|
|
|
|
bend_cell = Clothoid(R=[self.R1,self.R0],A=[0,90],width_type='sine',
|
|
w=[self.w0,self.w1],
|
|
xs=self.xs,
|
|
dL_wg=self.res)
|
|
|
|
self.RCK = Racetrack(bend_cell=bend_cell,
|
|
xs=self.xs,
|
|
w=self.w1,
|
|
dLx=self.dLx,
|
|
dLy=self.dLy,
|
|
res=self.res)
|
|
|
|
RCK_INSTR = self.RCK.cell.put(0,0,0)
|
|
|
|
|
|
bus = ring_bus_wg(xs=self.xs,
|
|
R_cp=self.R1_cp,
|
|
w_bus=self.w1_bus,
|
|
dAc=self.A1_cp,
|
|
wg_Ltp=self.Ltp_bus,
|
|
dA_trans=self.A1_att,
|
|
R_max_trans=self.R1_att,
|
|
R_max_anti=self.R1_att,
|
|
R_min_anti=self.R1_att_min,
|
|
dL_p2p=self.dL_p2p,
|
|
sharp_patch=sharp_patch,
|
|
dL_trans=self.L_tilt,
|
|
euler_anti_bend=self.Euler_trasition,
|
|
euler_transistion=self.Euler_trasition)
|
|
|
|
self.cell_bus = bus.cell
|
|
bus_instr = bus.cell.put(0,-self.dLy/2-bend_cell.sz[1]-self.w0/2-self.w1_bus/2-self.gap1,0)
|
|
## revised in 2026.06.07 by Qin Yue
|
|
# legacy: bus_instr.raise_pins(['a1','b1'],['a1','b1'])
|
|
bus_instr.raise_pins(['opt_a1','opt_b1'],['opt_a1','opt_b1'])
|
|
|
|
if (self.w2_bus > 0):
|
|
bus_instr = bus.cell.put(0, self.dLy/2+bend_cell.sz[1]+self.w0/2+self.w2_bus/2+self.gap2,0,flip=1)
|
|
## revised in 2026.06.07 by Qin Yue
|
|
# legacy: bus_instr.raise_pins(['a1','b1'],['a2','b2'])
|
|
bus_instr.raise_pins(['opt_a1','opt_b1'],['opt_a2','opt_b2'])
|
|
|
|
return C
|
|
|
|
|
|
|
|
class Racetrack_STD_Allpass(RacetrackResonator):
|
|
"""
|
|
Racetrack STD Allpass primitive component.
|
|
|
|
This component builds the Racetrack STD Allpass layout cell.
|
|
|
|
Parameters
|
|
----------
|
|
r_rck : float
|
|
Radius parameter in microns.
|
|
w_rck : float
|
|
Width parameter in microns.
|
|
dLy : float
|
|
Value for the dLy parameter.
|
|
name : Optional[str], optional
|
|
Unique identifier for the device cell. Default is None.
|
|
xs : str, optional
|
|
Layer or cross-section name used by the device. Default is 'strip'.
|
|
gap : float, optional
|
|
Spacing or gap parameter in microns. Default is 0.2.
|
|
w_bus : float, optional
|
|
Width parameter in microns. Default is 0.45.
|
|
A_cp : int, optional
|
|
Angle parameter in degrees. Default is 0.
|
|
w_wg : float, optional
|
|
Width parameter in microns. Default is 0.45.
|
|
Ltp_bus : int, optional
|
|
Length parameter in microns. Default is 10.
|
|
dL_p2p : Optional[float], optional
|
|
Value for the dL_p2p parameter. Default is None.
|
|
L_tilt : int, optional
|
|
Length parameter in microns. Default is 0.
|
|
Ratt : int, optional
|
|
Radius parameter in microns. Default is 10.
|
|
w_ht : float, optional
|
|
Width parameter in microns. Default is 0.
|
|
w_mt : float, optional
|
|
Width parameter in microns. Default is 10.
|
|
via_h2m : Any, optional
|
|
Via definition used between heater and metal layers. Default is None.
|
|
xs_ht : str, optional
|
|
Layer or cross-section name used by the device. Default is 'heater'.
|
|
xs_mt : str, optional
|
|
Layer or cross-section name used by the device. Default is 'metal'.
|
|
sharp_patch : bool, optional
|
|
Whether to add geometry patches for sharp corners or cladding continuity. Default is True.
|
|
cell_xs_transition : Any, optional
|
|
Cell or component dependency used by this device. Default is None.
|
|
res : float, optional
|
|
Value for the res parameter. Default is 0.01.
|
|
show_pins : bool, optional
|
|
Whether to draw pin markers in the generated layout. Default is False.
|
|
"""
|
|
def __init__(self,
|
|
r_rck: float, w_rck: float,
|
|
dLy: float,
|
|
name: Optional[str]=None, xs: str='strip',
|
|
gap: float=0.2,
|
|
w_bus: float=0.45,
|
|
A_cp: int=0,
|
|
w_wg: float=0.45,
|
|
Ltp_bus: int=10, dL_p2p: Optional[float]=None, L_tilt: int=0,
|
|
Ratt: int = 10,
|
|
w_ht: float=0,
|
|
w_mt: float=10,
|
|
via_h2m: Any=None,
|
|
xs_ht: str = "heater",
|
|
xs_mt: str = "metal",
|
|
sharp_patch: bool=True, cell_xs_transition: Any=None, res: float=0.01, show_pins: bool=False) -> None:
|
|
if (w_ht>0):
|
|
name_pic = None
|
|
else:
|
|
name_pic = name
|
|
super().__init__(R0=r_rck, w0=w_rck,
|
|
R1=r_rck, w1=w_rck,
|
|
dLy=dLy, dLx=0,
|
|
name=name_pic, xs=xs,
|
|
gap1=gap, gap2=0,
|
|
w1_bus=w_bus, w2_bus=0,
|
|
R1_cp=None, R2_cp=None,
|
|
A1_cp=A_cp, A2_cp=0,
|
|
w_wg=w_wg,
|
|
R1_att=Ratt, R2_att=Ratt,
|
|
R2_att_min=Ratt, R1_att_min=Ratt,
|
|
A1_att=A_cp/2, A2_att=A_cp/2, Ltp_bus=Ltp_bus,
|
|
dL_p2p=dL_p2p, L_tilt=L_tilt, sharp_patch=sharp_patch,
|
|
cell_xs_transition=cell_xs_transition, Euler_trasition=False, res=res, show_pins=show_pins)
|
|
|
|
self.w_rck = w_rck
|
|
self.r_rck = r_rck
|
|
|
|
self.w_bus = w_bus
|
|
self.gap = gap
|
|
|
|
self.xs_ht = xs_ht
|
|
self.xs_mt = xs_mt
|
|
|
|
self.w_ht = w_ht
|
|
self.w_mt = w_mt
|
|
self.via_h2m = via_h2m
|
|
|
|
if (self.w_ht > 0):
|
|
self.cell_pic = self.cell
|
|
|
|
with nd.Cell(instantiate=True, name=name) as C:
|
|
INSTR = self.cell.put()
|
|
INSTR.raise_pins()
|
|
|
|
eic_cell = self.generate_eic_gds().put()
|
|
eic_cell.raise_pins(["ep1","en1"],["ep1","en1"])
|
|
|
|
self.cell = C
|
|
|
|
def generate_eic_gds(self, sharp_patch=True, show_pins=False):
|
|
with nd.Cell(instantiate=False) as C:
|
|
|
|
HT_L = nd.strt(length=self.dLy/2,width=self.w_ht,xs=self.xs_ht).put(self.RCK.sz[0]/2,0,90)
|
|
HT = nd.bend(radius=self.r_rck,width=self.w_ht,xs=self.xs_ht,angle=180).put()
|
|
HT_R = nd.strt(length=self.dLy/2,width=self.w_ht,xs=self.xs_ht).put(-self.RCK.sz[0]/2,0,90)
|
|
|
|
if (self.via_h2m is None):
|
|
self.VIA = Vias(xs=None,xs_l1=self.xs_ht,xs_l2=self.xs_mt,sz=self.w_ht,area=self.w_mt,spacing=0)
|
|
else :
|
|
self.VIA = __cell_arg__(arg=self.via_h2m,arg_name="via_h2m",func_name="Racetrack_STD_Allpass::generate_eic_gds")
|
|
|
|
HT_L = nd.strt(length=self.w_ht/2,width=self.w_ht,xs=self.xs_ht).put(self.RCK.sz[0]/2,0,-90)
|
|
HT_R = nd.strt(length=self.w_ht/2,width=self.w_ht,xs=self.xs_ht).put(-self.RCK.sz[0]/2,0,-90)
|
|
|
|
VIAL = self.VIA.put(HT_L.pin['b0'])
|
|
VIAR = self.VIA.put(HT_R.pin['b0'],flip=1)
|
|
|
|
VIAL.raise_pins(['b0'],["en1"])
|
|
VIAR.raise_pins(['b0'],["ep1"])
|
|
|
|
return C
|
|
|
|
|
|
class Racetrack_MM_Allpass(RacetrackResonator):
|
|
"""
|
|
Racetrack MM Allpass primitive component.
|
|
|
|
This component builds the Racetrack MM Allpass layout cell.
|
|
|
|
Parameters
|
|
----------
|
|
r1_rck : float
|
|
Value for the r1_rck parameter.
|
|
w1_rck : float
|
|
Value for the w1_rck parameter.
|
|
r0_rck : float
|
|
Value for the r0_rck parameter.
|
|
w0_rck : float
|
|
Value for the w0_rck parameter.
|
|
dLy : float
|
|
Value for the dLy parameter.
|
|
name : Optional[str], optional
|
|
Unique identifier for the device cell. Default is None.
|
|
xs : str, optional
|
|
Layer or cross-section name used by the device. Default is 'strip'.
|
|
gap : float, optional
|
|
Spacing or gap parameter in microns. Default is 0.2.
|
|
w_bus : float, optional
|
|
Width parameter in microns. Default is 0.45.
|
|
A_cp : int, optional
|
|
Angle parameter in degrees. Default is 0.
|
|
w_wg : float, optional
|
|
Width parameter in microns. Default is 0.45.
|
|
R_att : int, optional
|
|
Radius parameter in microns. Default is 50.
|
|
R_att_min : int, optional
|
|
Radius parameter in microns. Default is 10.
|
|
A_att : int, optional
|
|
Angle parameter in degrees. Default is 15.
|
|
Ltp_bus : int, optional
|
|
Length parameter in microns. Default is 10.
|
|
dL_p2p : Optional[float], optional
|
|
Value for the dL_p2p parameter. Default is None.
|
|
sharp_patch : bool, optional
|
|
Whether to add geometry patches for sharp corners or cladding continuity. Default is True.
|
|
cell_xs_transition : Any, optional
|
|
Cell or component dependency used by this device. Default is None.
|
|
res : float, optional
|
|
Value for the res parameter. Default is 0.01.
|
|
show_pins : bool, optional
|
|
Whether to draw pin markers in the generated layout. Default is False.
|
|
"""
|
|
def __init__(self,
|
|
r1_rck: float, w1_rck: float,
|
|
r0_rck: float, w0_rck: float,
|
|
dLy: float,
|
|
name: Optional[str]=None, xs: str='strip',
|
|
gap: float=0.2,
|
|
w_bus: float=0.45,
|
|
A_cp: int=0,
|
|
w_wg: float=0.45,
|
|
R_att: int=50,
|
|
R_att_min: int=10,
|
|
A_att: int = 15,
|
|
Ltp_bus: int=10, dL_p2p: Optional[float]=None,
|
|
sharp_patch: bool=True, cell_xs_transition: Any=None, res: float=0.01, show_pins: bool=False) -> None:
|
|
super().__init__(R0=r0_rck, w0=w0_rck,
|
|
R1=r1_rck, w1=w1_rck,
|
|
dLy=dLy, dLx=0,
|
|
name=name, xs=xs,
|
|
gap1=gap, gap2=0,
|
|
w1_bus=w_bus, w2_bus=0,
|
|
R1_cp=None, R2_cp=None,
|
|
A1_cp=A_cp, A2_cp=0,
|
|
w_wg=w_wg,
|
|
R1_att=R_att, R2_att=R_att,
|
|
R2_att_min=R_att_min, R1_att_min=R_att_min,
|
|
A1_att=A_att, A2_att=A_att,
|
|
Ltp_bus=Ltp_bus,
|
|
dL_p2p=dL_p2p, L_tilt=0, sharp_patch=sharp_patch,
|
|
cell_xs_transition=cell_xs_transition, Euler_trasition=True, res=res, show_pins=show_pins)
|
|
|
|
|
|
class Racetrack_MM_Adddrop(RacetrackResonator):
|
|
"""
|
|
Racetrack MM Adddrop primitive component.
|
|
|
|
This component builds the Racetrack MM Adddrop layout cell.
|
|
|
|
Parameters
|
|
----------
|
|
r1_rck : float
|
|
Value for the r1_rck parameter.
|
|
w1_rck : float
|
|
Value for the w1_rck parameter.
|
|
r0_rck : float
|
|
Value for the r0_rck parameter.
|
|
w0_rck : float
|
|
Value for the w0_rck parameter.
|
|
dLy : float
|
|
Value for the dLy parameter.
|
|
name : Optional[str], optional
|
|
Unique identifier for the device cell. Default is None.
|
|
xs : str, optional
|
|
Layer or cross-section name used by the device. Default is 'strip'.
|
|
gap : float, optional
|
|
Spacing or gap parameter in microns. Default is 0.2.
|
|
w_bus : float, optional
|
|
Width parameter in microns. Default is 0.45.
|
|
A_cp : int, optional
|
|
Angle parameter in degrees. Default is 0.
|
|
w_wg : float, optional
|
|
Width parameter in microns. Default is 0.45.
|
|
R_att : int, optional
|
|
Radius parameter in microns. Default is 50.
|
|
R_att_min : int, optional
|
|
Radius parameter in microns. Default is 10.
|
|
A_att : int, optional
|
|
Angle parameter in degrees. Default is 15.
|
|
Ltp_bus : int, optional
|
|
Length parameter in microns. Default is 10.
|
|
dL_p2p : Optional[float], optional
|
|
Value for the dL_p2p parameter. Default is None.
|
|
sharp_patch : bool, optional
|
|
Whether to add geometry patches for sharp corners or cladding continuity. Default is True.
|
|
cell_xs_transition : Any, optional
|
|
Cell or component dependency used by this device. Default is None.
|
|
res : float, optional
|
|
Value for the res parameter. Default is 0.01.
|
|
show_pins : bool, optional
|
|
Whether to draw pin markers in the generated layout. Default is False.
|
|
"""
|
|
def __init__(self,
|
|
r1_rck: float, w1_rck: float,
|
|
r0_rck: float, w0_rck: float,
|
|
dLy: float,
|
|
name: Optional[str]=None, xs: str='strip',
|
|
gap: float=0.2,
|
|
w_bus: float=0.45,
|
|
A_cp: int=0,
|
|
w_wg: float=0.45,
|
|
R_att: int=50,
|
|
R_att_min: int=10,
|
|
A_att: int = 15,
|
|
Ltp_bus: int=10, dL_p2p: Optional[float]=None,
|
|
sharp_patch: bool=True, cell_xs_transition: Any=None, res: float=0.01, show_pins: bool=False) -> None:
|
|
super().__init__(R0=r0_rck, w0=w0_rck,
|
|
R1=r1_rck, w1=w1_rck,
|
|
dLy=dLy, dLx=0,
|
|
name=name, xs=xs,
|
|
gap1=gap, gap2=gap,
|
|
w1_bus=w_bus, w2_bus=w_bus,
|
|
R1_cp=None, R2_cp=None,
|
|
A1_cp=A_cp, A2_cp=A_cp,
|
|
w_wg=w_wg,
|
|
R1_att=R_att, R2_att=R_att,
|
|
R2_att_min=R_att_min, R1_att_min=R_att_min,
|
|
A1_att=A_att, A2_att=A_att,
|
|
Ltp_bus=Ltp_bus,
|
|
dL_p2p=dL_p2p, L_tilt=0, sharp_patch=sharp_patch,
|
|
cell_xs_transition=cell_xs_transition, Euler_trasition=True, res=res, show_pins=show_pins)
|