Files
mxpic_forge/mxpic/components/primitives/pic/racetrack.py
T

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)