New forge coding added
This commit is contained in:
@@ -0,0 +1,7 @@
|
||||
|
||||
from .dev_ps import Heater_NDoped,PS_PIN
|
||||
|
||||
from .pin_wg import waveguide_PIN,WGDoped
|
||||
|
||||
from .rings import STD_Ring_PIN,AED_Ring_PIN,PIN_MRR_STD_Allpass,PIN_MRR_MM_Allpass,PIN_MRR_MM_Adddrop
|
||||
|
||||
@@ -0,0 +1,445 @@
|
||||
|
||||
import nazca as nd
|
||||
import numpy as np
|
||||
from ..pic import taper_xs2xs
|
||||
|
||||
import nazca.interconnects as IC
|
||||
class Route(IC.Interconnect):
|
||||
pass
|
||||
|
||||
# from ...routing import Route
|
||||
from ...electronics import Vias
|
||||
|
||||
|
||||
class Heater_NDoped():
|
||||
'''
|
||||
This is the class for N-doped heater as a phase shifter.
|
||||
'''
|
||||
def __init__(
|
||||
self,
|
||||
w_wg: float=0.45,
|
||||
slab_width: float=1.1,
|
||||
heater_length: int=100,
|
||||
heater_width: int=1,
|
||||
if_open: bool=True,
|
||||
show_pins: bool=False
|
||||
) -> None:
|
||||
'''
|
||||
__Summary__: Initilization of N Doped Heater.
|
||||
|
||||
Args:
|
||||
1. w_wg [um] Width of input waveguide
|
||||
2. slab_width [um] Distance betwee wg edge and N doped region edge
|
||||
3. heater_length[um] Length of heater
|
||||
4. heater_width [um] Width of heater
|
||||
5. if_open [Bool] If add an open region to decrease the thickness of cladding
|
||||
'''
|
||||
self.w_wg = w_wg
|
||||
self.slab_width = slab_width
|
||||
self.heater_length = heater_length
|
||||
self.heater_width = heater_width
|
||||
self.pitch = self.heater_width + self.w_wg + self.slab_width*2
|
||||
self.if_open = if_open
|
||||
self.show_pins = show_pins
|
||||
self.cell = self.generate_gds()
|
||||
|
||||
def generate_gds(self):
|
||||
with nd.Cell(name="Heater_NDoped", instantiate=False) as C:
|
||||
nd.add_xsection(name="rib_narrow")
|
||||
nd.add_layer2xsection(xsection="rib_narrow", layer="RIB_COR")
|
||||
nd.add_layer2xsection(xsection="rib_narrow", layer="RIB_CLD", leftedge=(0.5, self.slab_width), rightedge=(-0.5, -self.slab_width))
|
||||
nd.add_layer2xsection(xsection="rib_narrow", layer="STRIP_COR", leftedge=(0.5, self.slab_width), rightedge=(-0.5, -self.slab_width))
|
||||
nd.add_layer2xsection(xsection="rib_narrow", layer="STRIP_CLD", leftedge=(0.5, 2), rightedge=(-0.5, -2))
|
||||
layer_cld = nd.get_layer("STRIP_CLD")
|
||||
if layer_cld=="dump" :
|
||||
nd.text(text="==This device is not compatible with this foundry==",height=5,layer=(1005)).put(3,-20)
|
||||
print("==Active::dev_ps::Heater_NDoped is not compatible with this tapeout.")
|
||||
L_taper = 10
|
||||
taper = taper_xs2xs(
|
||||
xs_1='rib_narrow',
|
||||
xs_2='strip',
|
||||
L_taper=L_taper,
|
||||
w_1=self.w_wg,
|
||||
w_2=self.w_wg,
|
||||
L_port=0
|
||||
).cell
|
||||
taper_l1 = taper.put('b0', 0, 0)
|
||||
bend_radius_stripe = 5
|
||||
stripe = Route(xs='strip', width=self.w_wg, radius=bend_radius_stripe)
|
||||
rib = Route(xs='rib_narrow', width=self.w_wg)
|
||||
|
||||
## Build waveguide first
|
||||
rib_strt_up = rib.strt(length=self.heater_length, arrow=False).put(taper_l1.pin['a0'])
|
||||
taper_r1 = taper.put('a0', rib_strt_up.pin['b0'])
|
||||
stripe.bend(angle=90, arrow=False).put(taper_r1.pin['b0'])
|
||||
stripe.bend(angle=-180, arrow=False).put()
|
||||
stripe.strt(length=self.pitch, arrow=False).put()
|
||||
bend_out = stripe.bend(angle=-90, arrow=False).put()
|
||||
stripe.strt_p2p(pin1=bend_out.pin['b0'], pin2=(taper_r1.pin['b0'].x, taper_r1.pin['b0'].y-self.pitch, taper_r1.pin['b0'].a+180), arrow=False).put()
|
||||
taper_r2 = taper.put('b0')
|
||||
|
||||
rib_strt_mid = rib.strt(length=self.heater_length, arrow=False).put(taper_r2.pin['a0'])
|
||||
taper_l2 = taper.put('a0', rib_strt_mid.pin['b0'])
|
||||
stripe.strt(length=bend_radius_stripe*2, arrow=False).put(taper_l2.pin['b0'])
|
||||
stripe.bend(angle=90, arrow=False).put()
|
||||
stripe.strt(length=self.pitch, arrow=False).put()
|
||||
stripe.bend(angle=180, arrow=False).put()
|
||||
stripe.bend(angle=-90, arrow=False).put()
|
||||
taper_l3 = taper.put('b0')
|
||||
|
||||
rib_strt_low = rib.strt(length=self.heater_length, arrow=False).put(taper_l3.pin['a0'])
|
||||
taper_r3 = taper.put('a0', rib_strt_low.pin['b0'])
|
||||
# Add input and output waveguide
|
||||
length_wg = bend_radius_stripe*3+2+self.w_wg/2
|
||||
wg_input = stripe.strt(length=length_wg, arrow=False).put(taper_l1.pin['b0'])
|
||||
wg_output =stripe.strt(length=length_wg, arrow=False).put(taper_r3.pin['b0'])
|
||||
|
||||
## Add N-doped heater region
|
||||
heater_strip_cor = nd.strt(length=self.heater_length, width=self.heater_width, layer='STRIP_COR')
|
||||
heater_Ndoped = nd.strt(length=self.heater_length, width=self.heater_width, layer='NP')
|
||||
heater_strip_cor.put(rib_strt_up.pin['a0'].x, (rib_strt_up.pin['a0'].y+rib_strt_mid.pin['b0'].y)/2, 0)
|
||||
heater_strip_cor.put(rib_strt_up.pin['a0'].x, (rib_strt_low.pin['a0'].y+rib_strt_mid.pin['b0'].y)/2, 0)
|
||||
heater_Ndoped.put(rib_strt_up.pin['a0'].x, (rib_strt_up.pin['a0'].y+rib_strt_mid.pin['b0'].y)/2, 0)
|
||||
heater_Ndoped.put(rib_strt_up.pin['a0'].x, (rib_strt_low.pin['a0'].y+rib_strt_mid.pin['b0'].y)/2, 0)
|
||||
|
||||
vias_width = 6
|
||||
vias = Vias(xs='via_s2m', area=[vias_width, self.heater_width-0.2*2], sz=[0.25, 0.25], spacing=[0.35, 0.35], xs_l1='sa', xs_l2='metal').cell
|
||||
vias_l1 = vias.put(rib_strt_up.pin['a0'].x+0.2+vias_width/2, (rib_strt_up.pin['a0'].y+rib_strt_mid.pin['b0'].y)/2, 0)
|
||||
vias_l2 = vias.put(rib_strt_up.pin['a0'].x+0.2+vias_width/2, (rib_strt_low.pin['a0'].y+rib_strt_mid.pin['b0'].y)/2, 0)
|
||||
vias_r1 = vias.put(rib_strt_up.pin['b0'].x-0.2-vias_width/2, (rib_strt_up.pin['a0'].y+rib_strt_mid.pin['b0'].y)/2, 0)
|
||||
vias_r2 = vias.put(rib_strt_up.pin['b0'].x-0.2-vias_width/2, (rib_strt_low.pin['a0'].y+rib_strt_mid.pin['b0'].y)/2, 0)
|
||||
metal1 = Route(xs='metal', radius=0)
|
||||
metal_l=metal1.strt_p2p(pin1=vias_l1.pin['a0'], pin2=vias_l2.pin['b0'], width=vias_width, arrow=False).put()
|
||||
metal_r=metal1.strt_p2p(pin1=vias_r1.pin['a0'], pin2=vias_r2.pin['b0'], width=vias_width, arrow=False).put()
|
||||
## Add open region to decrease the thickness of cladding
|
||||
if self.if_open:
|
||||
length_open = self.heater_length - 0.4 - vias_width*2 - 6*2
|
||||
nd.strt(length=length_open, width=20, layer='GC_OPEN').put(
|
||||
rib_strt_up.pin['a0'].x+0.2+vias_width+6,
|
||||
(metal_r.pin['a0'].y+metal_r.pin['b0'].y)/2,
|
||||
|
||||
0
|
||||
)
|
||||
## Add dummy to avoid sharp angle
|
||||
poly = [
|
||||
(0, 0),
|
||||
(0, self.pitch+self.w_wg+4+bend_radius_stripe*2),
|
||||
(bend_radius_stripe*3+self.w_wg/2+2, self.pitch+self.w_wg+4+bend_radius_stripe*2),
|
||||
(bend_radius_stripe*3+self.w_wg/2+2, 0)
|
||||
]
|
||||
nd.Polygon(points=poly, layer="STRIP_CLD").put(
|
||||
taper_l1.pin['b0'].x, taper_l1.pin['b0'].y-self.pitch+self.w_wg/2+2, flip=True, flop=True
|
||||
)
|
||||
nd.Polygon(points=poly, layer="STRIP_CLD").put(
|
||||
taper_r1.pin['b0'].x, taper_r2.pin['b0'].y-self.w_wg/2-2
|
||||
)
|
||||
## Add pin
|
||||
nd.Pin(name='a0').put(wg_input.pin['b0'])
|
||||
nd.Pin(name='a1', width=self.w_wg).put(wg_input.pin['b0'])
|
||||
nd.Pin(name='b1', width=self.w_wg).put(wg_output.pin['b0'])
|
||||
nd.Pin(name='ep1', width=abs(metal_l.pin['a0'].y-metal_l.pin['b0'].y)).put(
|
||||
metal_l.pin['a0'].x, (metal_l.pin['a0'].y+metal_l.pin['b0'].y)/2, 180
|
||||
)
|
||||
nd.Pin(name='en1', width=abs(metal_r.pin['a0'].y-metal_r.pin['b0'].y)).put(
|
||||
metal_r.pin['a0'].x, (metal_r.pin['a0'].y+metal_r.pin['b0'].y)/2, 0
|
||||
)
|
||||
if self.show_pins:
|
||||
nd.put_stub()
|
||||
return C
|
||||
|
||||
def generate_test_gds(self, gc, mmi, mzi_offset=60, ct_pitch=20, gc2gc_length=500, cell_name=None, gc_offset=0):
|
||||
if cell_name==None:
|
||||
cell_name = self.cell.cell_name + "_test"
|
||||
with nd.Cell(name=cell_name, instantiate=False) as C:
|
||||
stripe = Route(radius=5, width=gc.w_wg, xs='strip')
|
||||
gc_input = gc.cell.put('g1',0,gc_offset,180)
|
||||
gc_output = gc.cell.put('g1',gc2gc_length,gc_offset,0)
|
||||
mmi_input = mmi.cell.put('a1',20,0,0)
|
||||
mmi_output = mmi.cell.put('a1', gc_output.pin['g1'].x-20,0, 180)
|
||||
stripe.sbend_p2p(
|
||||
pin1=gc_input.pin['g1'],
|
||||
pin2=mmi_input.pin['a1'],
|
||||
Lstart=5,
|
||||
arrow=False
|
||||
).put()
|
||||
stripe.sbend_p2p(
|
||||
pin1=gc_output.pin['g1'],
|
||||
pin2=mmi_output.pin['a1'],
|
||||
Lstart=5,
|
||||
arrow=False
|
||||
).put()
|
||||
# Connect upper arm
|
||||
ps = self.cell.put('a1',mmi_input.pin['b1'].x+40,mzi_offset)
|
||||
stripe.sbend_route_p2p(
|
||||
pin1=mmi_input.pin['b1'],
|
||||
pin2=ps.pin['a1'],
|
||||
arrow=False
|
||||
).put()
|
||||
stripe.sbend_route_p2p(
|
||||
pin1=mmi_output.pin['b2'],
|
||||
pin2=ps.pin['b1'],
|
||||
arrow=False
|
||||
).put()
|
||||
# Connect lower arm
|
||||
stripe.strt_p2p(
|
||||
pin1=mmi_input.pin['b2'],
|
||||
pin2=mmi_output.pin['b1'],
|
||||
arrow=False
|
||||
).put()
|
||||
## Put CT heater
|
||||
ps_ct = self.cell.put('a1',ps.pin['a1'].x,ps.pin['a1'].y+ct_pitch,0)
|
||||
## Put pins
|
||||
nd.Pin(name="ep1", pin=ps.pin['ep1']).put()
|
||||
nd.Pin(name="en1", pin=ps.pin['en1']).put()
|
||||
nd.Pin(name="ep2", pin=ps_ct.pin['ep1']).put()
|
||||
nd.Pin(name="en2", pin=ps_ct.pin['en1']).put()
|
||||
return C
|
||||
|
||||
class PS_PIN() :
|
||||
|
||||
'''
|
||||
PIN junction for a high-speed phase shift.
|
||||
'''
|
||||
def __init__(
|
||||
self,
|
||||
w_wg: float=0.45,
|
||||
w_wg_slab: float=0.5,
|
||||
w_slab: float=1,
|
||||
l_wg: float=800,
|
||||
d2wg_list: list = [0.2, 1],
|
||||
p_layer_list: list = ['PW', 'PP'],
|
||||
n_layer_list: list = ['NW', 'NP'],
|
||||
w_plus_max: float = 5.1,
|
||||
show_pins: bool=False,
|
||||
# # Parameters to be abandoned
|
||||
# d2wg=0.4,
|
||||
# layer_pld='PLD_2',
|
||||
# layer_nld='NLD_2'
|
||||
) -> None:
|
||||
'''
|
||||
Initilization of PS_PIN.
|
||||
|
||||
Args:
|
||||
- w_wg [um] Width of the input waveguide.
|
||||
- w_wg_slab [um] Width of the slab waveguide.
|
||||
- w_slab [um] Width of the slab region of slab waveguides.
|
||||
- l_wg [um] Length of the PIN phase shifter.
|
||||
- d2wg_list [list[um]] Distance to the waveguide edge of corresponding doping regions.
|
||||
- p_layer_list [list[strt]] Layer names of P doped regions, with same length as 'd2wg_list'.
|
||||
- n_layer_list [list[strt]] Layer names of N doped regions, with same length as 'd2wg_list'.
|
||||
- w_plus_max[um] Maximum distance of doping regions to the center.
|
||||
- show_pins [bool] If show connecting pins, with a1, b1, ep1, en1.
|
||||
'''
|
||||
self.w_wg = w_wg
|
||||
self.w_wg_slab = w_wg_slab
|
||||
self.w_slab = w_slab
|
||||
self.l_wg = l_wg
|
||||
self.d2wg_list = d2wg_list
|
||||
self.p_layer_list = p_layer_list
|
||||
self.n_layer_list = n_layer_list
|
||||
self.w_plus_max = w_plus_max
|
||||
if len(self.d2wg_list) != len(self.p_layer_list) :
|
||||
print("==Warning==PIN:: len(d2wg_list) != len(self.p_layer_list). ")
|
||||
if len(self.d2wg_list) != len(self.n_layer_list) :
|
||||
print("==Warning==PIN:: len(d2wg_list) != len(self.n_layer_list). ")
|
||||
self.show_pins = show_pins
|
||||
self.cell = self.generate_gds()
|
||||
''' Parameters to be abandoned '''
|
||||
# self.d2wg = d2wg
|
||||
# self.layer_pld = layer_pld
|
||||
# self.layer_nld = layer_nld
|
||||
|
||||
def generate_gds(self) :
|
||||
cell_name = "ps_pin"
|
||||
for _index_ in range(len(self.d2wg_list)) :
|
||||
cell_name = cell_name + "_" + self.p_layer_list[_index_] + str(int(self.d2wg_list[_index_]*1000)) + "nm"
|
||||
self.cell_name = cell_name
|
||||
with nd.Cell(name=self.cell_name, instantiate=True) as ICell :
|
||||
''' Add The Waveguide '''
|
||||
strip = Route(radius=10,width=self.w_wg,xs='strip')
|
||||
|
||||
nd.add_xsection(name='slab_pin')
|
||||
nd.add_layer2xsection(xsection='slab_pin', layer='RIB_COR', leftedge=(0.5,0), rightedge=(-0.5,0), overwrite=True)
|
||||
nd.add_layer2xsection(xsection='slab_pin', layer='RIB_CLD', leftedge=(0.5,self.w_slab), rightedge=(-0.5,-self.w_slab), overwrite=True)
|
||||
slab = Route(radius=10,width=self.w_wg_slab,xs='slab_pin')
|
||||
|
||||
nd.add_xsection(name='slab2strip_pin')
|
||||
nd.add_layer2xsection(xsection='slab2strip_pin', layer='RIB_COR', leftedge=(0.5,0), rightedge=(-0.5,0), overwrite=True)
|
||||
nd.add_layer2xsection(xsection='slab2strip_pin', layer='RIB_CLD', leftedge=(0.5,self.w_slab), rightedge=(-0.5,-self.w_slab), overwrite=True)
|
||||
nd.add_layer2xsection(xsection='slab2strip_pin', layer='STRIP_COR', leftedge=(0.5,self.w_slab), rightedge=(-0.5,-self.w_slab), overwrite=True)
|
||||
nd.add_layer2xsection(xsection='slab2strip_pin', layer='STRIP_CLD', leftedge=(0.5,self.w_slab*2), rightedge=(-0.5,-self.w_slab*2), overwrite=True)
|
||||
taper_strip2slab = taper_xs2xs(xs_1='strip',xs_2='slab2strip_pin',L_taper=10,w_1=self.w_wg,w_2=self.w_wg_slab, L_port=0.2)
|
||||
taper_slab2strip = taper_xs2xs(xs_1='slab2strip_pin',xs_2='strip',L_taper=10,w_1=self.w_wg_slab, w_2=self.w_wg,L_port=0.2)
|
||||
taper_input = taper_strip2slab.cell.put('a1',0,0,0)
|
||||
wg_ps = slab.strt(length=self.l_wg,arrow=False).put(taper_input.pin['b1'])
|
||||
taper_output = taper_slab2strip.cell.put('a1',wg_ps.pin['b0'])
|
||||
|
||||
''' Add doping area near the waveguide '''
|
||||
l_edge = 1
|
||||
for _index_ in range(len(self.d2wg_list)) :
|
||||
d2wg_temp = self.d2wg_list[_index_]
|
||||
p_layer_temp = self.p_layer_list[_index_]
|
||||
n_layer_temp = self.n_layer_list[_index_]
|
||||
doping_polygon = [
|
||||
(taper_input.pin['b1'].x+l_edge, self.w_wg_slab/2+d2wg_temp),
|
||||
(taper_output.pin['a1'].x-l_edge, self.w_wg_slab/2+d2wg_temp),
|
||||
(taper_output.pin['a1'].x-l_edge, self.w_plus_max),
|
||||
(taper_input.pin['b1'].x+l_edge, self.w_plus_max)
|
||||
]
|
||||
nd.Polygon(points=doping_polygon, layer=p_layer_temp).put(0,0)
|
||||
nd.Polygon(points=doping_polygon, layer=n_layer_temp).put(0,0,flop=True)
|
||||
|
||||
''' Add Vias '''
|
||||
vias = Vias(
|
||||
xs='via_s2m', area=[self.l_wg-l_edge*2-0.2*2, self.w_plus_max-(self.d2wg_list[-1]+self.w_wg_slab/2)-0.2*2],
|
||||
sz=[0.25, 0.25], spacing=[0.35, 0.35],
|
||||
xs_l1="sa", xs_l2="metal", show_pins=False
|
||||
)
|
||||
vias_p = vias.cell.put(
|
||||
taper_input.pin['b1'].x+self.l_wg/2, (self.w_plus_max+self.d2wg_list[-1]+self.w_wg_slab/2)/2
|
||||
)
|
||||
vias_n = vias.cell.put(
|
||||
taper_input.pin['b1'].x+self.l_wg/2, -(self.w_plus_max+self.d2wg_list[-1]+self.w_wg_slab/2)/2
|
||||
)
|
||||
|
||||
''' Add Pins '''
|
||||
nd.Pin(name='a1',width=self.w_wg).put(taper_input.pin['a1'])
|
||||
nd.Pin(name='b1',width=self.w_wg).put(taper_output.pin['b1'])
|
||||
nd.Pin(name="ep1", width=self.w_plus_max-(self.d2wg_list[-1]+self.w_wg_slab/2)-0.2*2).put(vias_p.pin['a0'])
|
||||
nd.Pin(name="en1", width=self.w_plus_max-(self.d2wg_list[-1]+self.w_wg_slab/2)-0.2*2).put(vias_n.pin['a0'])
|
||||
# nd.put_stub()
|
||||
return ICell
|
||||
|
||||
def generate_mzi_gds(self, gc, mmi, pad) :
|
||||
'''
|
||||
Generating a Mach-Zehnder Interferometer for testing the PIN phase shifter.
|
||||
'''
|
||||
with nd.Cell(name=self.cell_name+"_MZI", instantiate=False) as ICell :
|
||||
mmi_input = mmi.cell.put('a1',0,0,0)
|
||||
pin2test = self.cell.put('a1', mmi_input.pin['b1'].move(60,100,0))
|
||||
mmi_bottom = mmi.cell.put('a1', pin2test.pin['b1'].x+10, mmi_input.pin['b2'].y, 0)
|
||||
mmi_up = mmi.cell.put('a1', pin2test.pin['b1'].move(10,0,0))
|
||||
mmi_middle = mmi.cell.put(
|
||||
'a1',
|
||||
mmi_bottom.pin['b1'].x+mmi.length+25,
|
||||
mmi_up.pin['b2'].y/2+mmi_bottom.pin['b1'].y/2,
|
||||
180
|
||||
)
|
||||
''' Wg routing '''
|
||||
strip = Route(radius=10, width=self.w_wg, xs='strip')
|
||||
strip.strt_p2p(pin1=mmi_input.pin['b2'],pin2=mmi_bottom.pin['a1'],arrow=False).put()
|
||||
# strip.sbend_p2p(pin1=mmi_input.pin['b1'],pin2=pin2test.pin['a1'],Lstart=1,arrow=False).put()
|
||||
strip.sbend_p2p(
|
||||
pin1=mmi_input.pin['b1'],pin2=nd.Pin().put(mmi_input.pin['b1'].x+11,pin2test.pin['a1'].y,180),
|
||||
radius=5, Lstart=0.5, arrow=False
|
||||
).put()
|
||||
strip.sbend_p2p(
|
||||
pin1=nd.Pin().put(),pin2=nd.Pin().put(mmi_input.pin['b1'].x+22,mmi_input.pin['b1'].y+1,180),
|
||||
radius=5, Lstart=0.5, arrow=False
|
||||
).put()
|
||||
strip.sbend_p2p(
|
||||
pin1=nd.Pin().put(),pin2=nd.Pin().put(mmi_input.pin['b1'].x+33,pin2test.pin['a1'].y,180),
|
||||
radius=5, Lstart=0.5, arrow=False
|
||||
).put()
|
||||
strip.sbend_p2p(
|
||||
pin1=nd.Pin().put(),pin2=nd.Pin().put(mmi_input.pin['b1'].x+44,mmi_input.pin['b1'].y+1,180),
|
||||
radius=5, Lstart=0.5, arrow=False
|
||||
).put()
|
||||
strip.sbend_p2p(
|
||||
pin1=nd.Pin().put(),pin2=nd.Pin().put(mmi_input.pin['b1'].x+55,pin2test.pin['a1'].y,180),
|
||||
radius=5, Lstart=0.5, arrow=False
|
||||
).put()
|
||||
strip.strt_p2p(pin1=nd.Pin().put(),pin2=pin2test.pin['a1'],arrow=False).put()
|
||||
# strip.sbend(radius=5,offset=-abs(pin2test.pin['a1'].y-mmi_input.pin['b1'].y),arrow=False).put()
|
||||
strip.strt_p2p(pin1=mmi_up.pin['a1'],pin2=pin2test.pin['b1'],arrow=False).put()
|
||||
strip.sbend_p2p(pin1=mmi_up.pin['b2'],pin2=mmi_middle.pin['b2'],Lstart=0.5,radius=10,arrow=False).put()
|
||||
strip.sbend_p2p(pin1=mmi_bottom.pin['b1'],pin2=mmi_middle.pin['b1'],Lstart=2.5,radius=10,arrow=False).put()
|
||||
|
||||
''' Add pads '''
|
||||
pad_ground = pad.cell.put(
|
||||
mmi_input.pin['b1'].x+40+30+50,mmi_input.pin['b1'].y+5+40-4,0
|
||||
)
|
||||
pad_signal = pad.cell.put(
|
||||
mmi_input.pin['b1'].x+40+30+100+50,mmi_input.pin['b1'].y+5+40-4,0
|
||||
)
|
||||
|
||||
''' Metal Connecting '''
|
||||
metal = Route(radius=5,width=10,xs='metal')
|
||||
metal_2 = Route(radius=5,width=10,xs='metal_2')
|
||||
vias_m2m = Vias(
|
||||
xs='via_m2m', area=[self.l_wg+0.4, 10], sz=[0.6, 0.6], spacing=[0.6, 0.6],
|
||||
xs_l1='metal', xs_l2='metal_2', instantiate=True, show_pins=False
|
||||
)
|
||||
metal.strt_p2p(
|
||||
pin1=pad_ground.pin['p1'],
|
||||
pin2=nd.Pin().put(pad_ground.pin['p1'].x,pin2test.pin['en1'].y),
|
||||
arrow=False
|
||||
).put()
|
||||
vias = vias_m2m.cell.put(
|
||||
pin2test.pin['ep1'].move(
|
||||
0,-5+(self.w_plus_max-self.d2wg_list[-1]-self.w_wg_slab/2)/2,0
|
||||
)
|
||||
)
|
||||
metal_2.strt_p2p(
|
||||
pin1=pad_signal.pin['p1'],
|
||||
pin2=nd.Pin().put(pad_signal.pin['p1'].x,vias.pin['a0'].y),
|
||||
arrow=False
|
||||
).put()
|
||||
metal.strt(length=self.l_wg+0.4,width=10,arrow=False).put(
|
||||
pin2test.pin['en1'].move(
|
||||
-self.l_wg/2-0.2,5-(self.w_plus_max-self.d2wg_list[-1]-self.w_wg_slab/2)/2,0
|
||||
)
|
||||
)
|
||||
''' Put output gratings '''
|
||||
strip.strt(length=60,arrow=False).put(mmi_input.pin['a1'])
|
||||
gc.cell.put('g1')
|
||||
strip.strt(length=60,arrow=False).put(mmi_up.pin['b1'])
|
||||
gc.cell.put('g1')
|
||||
strip.strt(length=100,arrow=False).put(mmi_middle.pin['a1'])
|
||||
gc.cell.put('g1')
|
||||
strip.strt(length=60,arrow=False).put(mmi_bottom.pin['b2'])
|
||||
gc.cell.put('g1')
|
||||
return ICell
|
||||
|
||||
# class N_Doped_strt() :
|
||||
# '''
|
||||
# Class for a strt N doped region
|
||||
# '''
|
||||
# def __init__(self, tapeout, width=2.5, length=100, sa_length=6):
|
||||
# self.tapeout = tapeout
|
||||
# self.width = width
|
||||
# self.length = length
|
||||
# self.sa_length = sa_length
|
||||
# self.generate_gds()
|
||||
|
||||
# def generate_gds(self):
|
||||
# with nd.Cell(name="N_Doped_strt", instantiate=False) as C:
|
||||
# nd.strt(length=self.length, width=self.width, layer="STRIP_COR").put(0,0)
|
||||
# nd.strt(length=self.length, width=self.width, layer="NP").put(0,0)
|
||||
# nd.strt(length=self.length, width=self.width, layer="STRIP_COR").put(0,0)
|
||||
# nd.strt(length=self.length+4, width=self.width+4, layer="STRIP_CLD").put(-2,0)
|
||||
# sa_ep1 = nd.strt(length=self.sa_length, width=self.width-0.4, xs="sa").put(0.2,0)
|
||||
# sa_ep2 = nd.strt(length=self.sa_length, width=self.width-0.4, xs="sa").put(self.length-0.2,0,180)
|
||||
# sa_en1 = nd.strt(length=self.sa_length, width=self.width-0.4, xs="sa").put(self.length/2-self.sa_length/2,0)
|
||||
# # vias = Vias(
|
||||
# # xs="via_h2m",
|
||||
# # area=[self.sa_length, self.width-0.4],
|
||||
# # sz=[0.6, 0.6],
|
||||
# # spacing=[0.6, 0.6],
|
||||
# # xs="ct",
|
||||
# # area=[self.sa_length, self.width-0.4],
|
||||
# # sz=[0.25, 0.25],
|
||||
# # spacing=[0.35, 0.35],
|
||||
# # xs_l1='sa',
|
||||
# # xs_l2='metal_1'
|
||||
# # )
|
||||
# # vias_ep1 = vias.cell.put(sa_ep1.pin['a0'].move(-self.sa_length/2,0))
|
||||
# # vias_ep2 = vias.cell.put(sa_ep2.pin['a0'].move(-self.sa_length/2,0))
|
||||
# # vias_en1 = vias.cell.put(sa_en1.pin['a0'].move(-self.sa_length/2,0))
|
||||
|
||||
# # nd.Pin(name="ep1", pin=vias_ep1.pin['b0']).put()
|
||||
# # nd.Pin(name="ep2", pin=vias_ep2.pin['a0']).put()
|
||||
# # nd.Pin(name="en1", pin=vias_en1.pin['b0'].move(0,0,90)).put()
|
||||
# # nd.put_stub(pinname=["ep1", "ep2", "en1"])
|
||||
# self.cell = C
|
||||
# return C
|
||||
@@ -0,0 +1,401 @@
|
||||
from typing import Any, Optional
|
||||
import nazca as nd
|
||||
import numpy as np
|
||||
from ..pic import taper_xs2xs
|
||||
|
||||
from ...electronics import Vias
|
||||
|
||||
import nazca.interconnects as IC
|
||||
|
||||
from ...basic import __list_convert__,__array_convert__
|
||||
|
||||
class waveguide_PIN:
|
||||
def __init__(self,
|
||||
xs: str="rib", ## note, this xsection cannot directly mixed iwth 'rib'
|
||||
L_wg: float = 100,
|
||||
w_wg: float = 1.2,
|
||||
|
||||
xs_pn_ct: str = 'strip_cor',
|
||||
w_itr : float = 2.0,
|
||||
w_p : float = 4.0,
|
||||
w_n : float = 4.0,
|
||||
w_p_ct : float = 4.0,
|
||||
w_n_ct : float = 4.0,
|
||||
|
||||
xs_heater: str = 'heater',
|
||||
xs_via_h2m: str = 'via_h2m',
|
||||
|
||||
w_metal_pn: float = 8,
|
||||
|
||||
sz_via_i2m: float = 0.25,
|
||||
sp_via_i2m: float = 0.35,
|
||||
sp_sc: float = 1,
|
||||
xs_p : str = 'pw',
|
||||
xs_n : str = 'nw',
|
||||
xs_pcont : str = 'pp',
|
||||
xs_ncont : str = 'np',
|
||||
xs_sa : str = 'sa',
|
||||
xs_via_s2m: str = 'via_s2m',
|
||||
xs_metal: str = 'metal',
|
||||
|
||||
rib_taper: bool = True,
|
||||
L_taper: float = 30,
|
||||
xs_port: str = 'strip',
|
||||
|
||||
show_pins: bool = True,
|
||||
) -> None:
|
||||
|
||||
self.xs = xs
|
||||
self.L_wg = L_wg
|
||||
self.w_wg = w_wg
|
||||
self.w_itr = w_itr
|
||||
|
||||
self.xs_p = __list_convert__(xs_p,'xs_p','mxpic::active::rings')
|
||||
self.xs_n = __list_convert__(xs_n,'xs_n','mxpic::active::rings')
|
||||
|
||||
self.w_p = __array_convert__(w_p,'w_p','mxpic::active::rings')
|
||||
self.w_n = __array_convert__(w_n,'w_n','mxpic::active::rings')
|
||||
|
||||
# self.w_p = w_p
|
||||
# self.w_n = w_n
|
||||
# self.xs_n = xs_n
|
||||
# self.xs_p = xs_p
|
||||
self.w_p_ct = w_p_ct
|
||||
self.w_n_ct = w_n_ct
|
||||
|
||||
self.xs_pn_ct = xs_pn_ct
|
||||
|
||||
|
||||
self.xs_heater = xs_heater
|
||||
self.xs_via_h2m = xs_via_h2m
|
||||
|
||||
if (w_metal_pn==None or w_metal_pn>min([w_n_ct,w_p_ct])-2*sp_sc):
|
||||
w_metal_pn = min([w_n_ct,w_p_ct])-2*sp_sc
|
||||
w_metal_pn = max([0,w_metal_pn])
|
||||
self.w_metal_pn = w_metal_pn ## w_metal_pn <= w_p_ct - 2*sp_ct
|
||||
|
||||
self.sz_via_i2m = sz_via_i2m
|
||||
self.sp_via_i2m = sp_via_i2m
|
||||
|
||||
self.xs_p = xs_p
|
||||
self.xs_n = xs_n
|
||||
self.xs_pcont = xs_pcont
|
||||
self.xs_ncont = xs_ncont
|
||||
self.xs_sa = xs_sa
|
||||
self.sp_sc = sp_sc
|
||||
self.xs_via_s2m = xs_via_s2m
|
||||
self.xs_metal = xs_metal
|
||||
|
||||
self.rib_taper = rib_taper
|
||||
self.L_taper = L_taper
|
||||
self.xs_port = xs_port
|
||||
|
||||
|
||||
self.cell = self.generate_gds(show_pins)
|
||||
|
||||
def generate_gds(self,show_pins=False):
|
||||
with nd.Cell(instantiate=False) as C:
|
||||
|
||||
nd.add_xsection(name='temp')
|
||||
for layers,growx,growy,acc in nd.layeriter(xs=self.xs):
|
||||
(a1,b1), (a2,b2),c1,c2 = growx
|
||||
if (b1==0 and b2==0 and layers.find("COR")!=-1): ## this is the core of the waveguide
|
||||
w_total = self.w_wg
|
||||
core = nd.strt(length=self.L_wg,width=self.w_wg,layer=layers).put(0,0,0)
|
||||
elif (layers.find("COR")!=-1): ## this is the core of the slab area
|
||||
## revised in 2023.1.4, w_n chaned into list or array
|
||||
w_total = self.w_itr + sum(self.w_n) + sum(self.w_p) + self.w_n_ct + self.w_p_ct
|
||||
# w_total = self.w_itr + self.w_n + self.w_p + self.w_n_ct + self.w_p_ct
|
||||
y_center = (-(sum(self.w_n) + self.w_n_ct) + sum(self.w_p) + self.w_p_ct)/2
|
||||
|
||||
nd.strt(length=self.L_wg,width=w_total,layer=layers).put(0,y_center,0)
|
||||
|
||||
else :
|
||||
w_total = (self.w_itr + sum(self.w_n) + sum(self.w_p) + self.w_n_ct + self.w_p_ct)*(a1-a2)+(b1-b2)
|
||||
# w_total = (self.w_itr + self.w_n + self.w_p + self.w_n_ct + self.w_p_ct)*(a1-a2)+(b1-b2)
|
||||
y_center = (-(sum(self.w_n) + self.w_n_ct) + sum(self.w_p) + self.w_p_ct)/2
|
||||
nd.strt(length=self.L_wg,width=w_total,layer=layers).put(0,y_center,0)
|
||||
|
||||
nd.add_layer2xsection(xsection='temp',layer=layers,leftedge=(a1,(w_total-self.w_wg)/2),rightedge=(a2,-(w_total-self.w_wg)/2))
|
||||
|
||||
if (self.rib_taper):
|
||||
tp_L = taper_xs2xs(xs_1='temp',xs_2=self.xs_port,L_taper=self.L_taper,w_1=self.w_wg,w_2=self.w_wg).cell.put(core.pin['a0'])
|
||||
tp_R = taper_xs2xs(xs_1='temp',xs_2=self.xs_port,L_taper=self.L_taper,w_1=self.w_wg,w_2=self.w_wg).cell.put(core.pin['b0'])
|
||||
nd.Pin(name='a1',pin=tp_L.pin['b0']).put()
|
||||
nd.Pin(name='b1',pin=tp_R.pin['b0']).put()
|
||||
else:
|
||||
nd.Pin(name='a1',pin=core.pin['a0']).put()
|
||||
nd.Pin(name='b1',pin=core.pin['b0']).put()
|
||||
|
||||
## adding p doping area
|
||||
_y_ = self.w_itr/2
|
||||
for itn in range(0,len(self.w_p)):
|
||||
_y_ = _y_ + self.w_p[itn]/2
|
||||
nd.strt(length=self.L_wg,width=self.w_p[itn],xs=self.xs_p[itn]).put(0,_y_,0)
|
||||
_y_ = _y_ + self.w_p[itn]/2
|
||||
|
||||
|
||||
if (self.xs_pn_ct!=None):
|
||||
nd.strt(length=self.L_wg,width=self.w_p_ct,xs=self.xs_pn_ct).put(0, _y_+self.w_p_ct/2,0)
|
||||
|
||||
|
||||
_y_ = -self.w_itr/2
|
||||
for itn in range(0,len(self.w_n)):
|
||||
_y_ = _y_ - self.w_n[itn]/2
|
||||
nd.strt(length=self.L_wg,width=self.w_n[itn],xs=self.xs_n[itn]).put(0,_y_,0)
|
||||
_y_ = _y_ - self.w_n[itn]/2
|
||||
|
||||
if (self.xs_pn_ct!=None):
|
||||
nd.strt(length=self.L_wg,width=self.w_n_ct,xs=self.xs_pn_ct).put(0, _y_-self.w_p_ct/2,0)
|
||||
|
||||
|
||||
# nd.strt(length=self.L_wg,width=self.w_p_ct,xs=self.xs_pcont).put(0, self.w_itr/2+self.w_p+self.w_p_ct/2,0)
|
||||
|
||||
# if (self.xs_pn_ct!=None):
|
||||
# nd.strt(length=self.L_wg,width=self.w_p_ct,xs=self.xs_pn_ct).put(0, self.w_itr/2+self.w_p+self.w_p_ct/2,0)
|
||||
|
||||
|
||||
# y_ct = self.w_itr/2+self.w_p+self.w_p_ct - self.w_metal_pn/2-self.sp_sc
|
||||
|
||||
# via_p_ct = Vias(xs=self.xs_via_s2m,sz=self.sz_via_i2m,spacing=self.sp_via_i2m,area=[self.L_wg-self.sp_sc*2,self.w_metal_pn],
|
||||
# xs_l1=self.xs_sa,xs_l2=self.xs_metal).cell.put(self.L_wg/2,y_ct,0)
|
||||
|
||||
# nd.Pin(name='ep1',pin=via_p_ct.pin['a0']).put()
|
||||
|
||||
# ## adding n doping area
|
||||
# nd.strt(length=self.L_wg,width=self.w_n,xs=self.xs_n).put(0,-self.w_itr/2-self.w_n/2,0)
|
||||
# nd.strt(length=self.L_wg,width=self.w_n_ct,xs=self.xs_ncont).put(0,-self.w_itr/2-self.w_n-self.w_n_ct/2,0)
|
||||
# if (self.xs_pn_ct!=None):
|
||||
# nd.strt(length=self.L_wg,width=self.w_p_ct,xs=self.xs_pn_ct).put(0, -self.w_itr/2-self.w_n-self.w_n_ct/2,0)
|
||||
|
||||
# y_ct = -self.w_itr/2-self.w_n-self.w_n_ct + self.w_metal_pn/2+self.sp_sc
|
||||
|
||||
# via_n_ct = Vias(xs=self.xs_via_s2m,sz=self.sz_via_i2m,spacing=self.sp_via_i2m,area=[self.L_wg-self.sp_sc*2,self.w_metal_pn],
|
||||
# xs_l1=self.xs_sa,xs_l2=self.xs_metal).cell.put(self.L_wg/2,y_ct,0)
|
||||
|
||||
# nd.Pin(name='en1',pin=via_n_ct.pin['a0']).put()
|
||||
|
||||
if (show_pins):
|
||||
nd.put_stub()
|
||||
return C
|
||||
|
||||
|
||||
|
||||
|
||||
class WGDoped():
|
||||
def __init__(self,
|
||||
name: Optional[str]=None,
|
||||
w_wg: float = 0.5,
|
||||
w_port: float = 0.5,
|
||||
Ltp_port: int = 10,
|
||||
L_wg: int = 200,
|
||||
xs_wg: str = "rib",
|
||||
xs_n: list = ['nld','np'],
|
||||
xs_p: list = ['pld','pp'],
|
||||
w_n: list = [0.5,1],
|
||||
w_p: list = [0.5,1],
|
||||
w_ht: float = 0,
|
||||
L_ht: Any = None,
|
||||
xs_ht: str = "heater",
|
||||
w_mt: Optional[float] = None,
|
||||
xs_mt: str = "metal",
|
||||
xs_cont_wg: Optional[str] = None,
|
||||
w_i: Optional[float] = None,
|
||||
dope_offset: int = 0,
|
||||
via_s2m: Any = None,
|
||||
via_h2m: Any = None,
|
||||
|
||||
dope_ovlp: float = 0.2,
|
||||
cell_xs_transition: Any = None,
|
||||
) -> None:
|
||||
"""_summary_
|
||||
|
||||
Args:
|
||||
w_wg (float, optional): Core width of the waveguide. Defaults to 0.5.
|
||||
xs_wg (str, optional): cross-section definition of the waveguide. Defaults to "rib".
|
||||
xs_n (list, optional): _description_. Defaults to ['nld','np'].
|
||||
xs_p (list, optional): _description_. Defaults to ['pld','pp'].
|
||||
w_n (list, optional): _description_. Defaults to [0.5,1].
|
||||
w_p (list, optional): _description_. Defaults to [0.5,1].
|
||||
w_i (_type_, optional): _description_. Defaults to None.
|
||||
dope_offset (int, optional): Offset value of the PN junction center to waveguide center. Defaults to 0.
|
||||
via_i2m (_type_, optional): _description_. Defaults to None.
|
||||
via_h2m (_type_, optional): _description_. Defaults to None.
|
||||
"""
|
||||
self.name = name
|
||||
if (name is None):
|
||||
self.instantiate = False
|
||||
else:
|
||||
self.instantiate = True
|
||||
|
||||
""" Input value quality check """
|
||||
if (len(xs_p)!=len(w_p)):
|
||||
raise Exception("In <WGDoped>, input parameter doesn't have same length (w_p & xs_p)")
|
||||
|
||||
if (len(xs_n)!=len(w_n)):
|
||||
raise Exception("In <WGDoped>, input parameter doesn't have same length (w_n & xs_n)")
|
||||
|
||||
self.w_wg = w_wg
|
||||
self.xs_wg = xs_wg
|
||||
self.xs_n = xs_n
|
||||
self.xs_p = xs_p
|
||||
self.w_n = w_n
|
||||
self.w_p = w_p
|
||||
self.xs_cont_wg = xs_cont_wg
|
||||
self.L_wg = L_wg
|
||||
self.w_mt = w_mt
|
||||
self.xs_mt = xs_mt
|
||||
self.w_ht = w_ht
|
||||
self.xs_ht = xs_ht
|
||||
self.L_ht = L_ht
|
||||
self.w_port = w_port
|
||||
self.Ltp_port = Ltp_port
|
||||
|
||||
if (w_i is None):
|
||||
self.w_i = w_wg
|
||||
else :
|
||||
self.w_i = w_i
|
||||
|
||||
self.dope_ovlp = dope_ovlp
|
||||
self.dope_offset = dope_offset
|
||||
self.via_s2m = via_s2m
|
||||
self.via_h2m = via_h2m
|
||||
self.cell_xs_transition = cell_xs_transition
|
||||
self.cell = self.generate_gds()
|
||||
|
||||
def generate_gds(self):
|
||||
""" Generation of GDS pattern
|
||||
|
||||
Returns:
|
||||
_type_: _description_
|
||||
"""
|
||||
with nd.Cell(name=self.name,instantiate=self.instantiate) as C:
|
||||
|
||||
Lstrt = self.L_wg - self.Ltp_port
|
||||
|
||||
w_n_cont = self.w_n[-1]
|
||||
w_p_cont = self.w_p[-1]
|
||||
""" Placing Doping areas UPPER """
|
||||
_y_ = self.w_i/2 + self.dope_offset
|
||||
for _idx_dop_ in range(len(self.w_n)):
|
||||
_y_ = _y_ + self.w_n[_idx_dop_]/2
|
||||
nd.strt(xs=self.xs_n[_idx_dop_],width=self.w_n[_idx_dop_]+int(_idx_dop_>0)*int(_idx_dop_<len(self.w_n)-1)*self.dope_ovlp,length=self.L_wg).put(0,_y_)
|
||||
_y_ = _y_ + self.w_n[_idx_dop_]/2
|
||||
yContN = _y_ - self.w_n[-1]/2
|
||||
|
||||
""" Placing Doping areas LOWER """
|
||||
_y_ =-self.w_i/2 + self.dope_offset
|
||||
for _idx_dop_ in range(len(self.w_p)):
|
||||
_y_ = _y_ - self.w_p[_idx_dop_]/2
|
||||
nd.strt(xs=self.xs_p[_idx_dop_],width=self.w_p[_idx_dop_]+int(_idx_dop_>0)*int(_idx_dop_<len(self.w_p)-1)*self.dope_ovlp,length=self.L_wg).put(0,_y_)
|
||||
_y_ = _y_ - self.w_p[_idx_dop_]/2
|
||||
yContP = _y_ + self.w_p[-1]/2
|
||||
|
||||
""" Adding contact waveguide """
|
||||
if (self.xs_cont_wg is not None):
|
||||
nd.strt(xs=self.xs_cont_wg,width=w_n_cont,length=self.L_wg).put(0,yContN,0)
|
||||
nd.strt(xs=self.xs_cont_wg,width=w_p_cont,length=self.L_wg).put(0,yContP,0)
|
||||
|
||||
""" Adding central waveguide """
|
||||
w_slab_max = 2*np.max([np.sum(self.w_n)+self.dope_offset,np.sum(self.w_p)-self.dope_offset]) + self.w_i
|
||||
for layers,growx,growy,acc in nd.layeriter(xs=self.xs_wg):
|
||||
(a1,b1), (a2,b2),c1,c2 = growx
|
||||
print(growy)
|
||||
if (b1==0 and b2==0 and layers.find("COR")!=-1): ## this is the core of the waveguide
|
||||
coreIN = nd.taper(length=self.Ltp_port,width1=self.w_port,width2=self.w_wg,layer=layers).put(0,0,0)
|
||||
core = nd.strt(length=self.L_wg - self.Ltp_port*2,width=self.w_wg,layer=layers).put()
|
||||
coreOUT = nd.taper(length=self.Ltp_port,width2=self.w_port,width1=self.w_wg,layer=layers).put()
|
||||
elif (layers.find("COR")!=-1): ## this is the core of the slab area
|
||||
clad = nd.strt(length=self.L_wg,width=np.max([w_slab_max+b1-b2,self.w_wg+b1-b2]),layer=layers).put(0,0,0)
|
||||
|
||||
""" Adding Heaters """
|
||||
if (self.w_ht>0 and self.xs_ht is not None):
|
||||
if (self.L_ht is None):
|
||||
L_ht = self.L_wg
|
||||
else:
|
||||
L_ht = self.L_ht
|
||||
|
||||
ht = nd.strt(xs=self.xs_ht,width=self.w_ht,length=L_ht).put(self.L_wg/2-L_ht/2,0,0)
|
||||
|
||||
if (isinstance(self.via_h2m,nd.Cell)):
|
||||
viaHT=self.via_h2m
|
||||
elif(hasattr(self.via_h2m,"cell")):
|
||||
viaHT=self.via_h2m.cell
|
||||
|
||||
VL=viaHT.put(ht.pin['a0'])
|
||||
VR=viaHT.put(ht.pin['b0'])
|
||||
|
||||
VL.raise_pins(['b0'],['ep3'])
|
||||
VR.raise_pins(['b0'],['en3'])
|
||||
|
||||
|
||||
""" Adding vias """
|
||||
if (self.via_s2m is not None):
|
||||
via_s2m_N = Vias(xs=self.via_s2m.xs,sz=self.via_s2m.sz,spacing=self.via_s2m.spacing,sp_via_xs=self.via_s2m.sp_via_xs,xs_l1=self.via_s2m.xs_l1,
|
||||
area=[self.L_wg,w_n_cont]).cell.put(self.L_wg/2,yContN,0)
|
||||
|
||||
via_s2m_P = Vias(xs=self.via_s2m.xs,sz=self.via_s2m.sz,spacing=self.via_s2m.spacing,sp_via_xs=self.via_s2m.sp_via_xs,xs_l1=self.via_s2m.xs_l1,
|
||||
area=[self.L_wg,w_p_cont]).cell.put(self.L_wg/2,yContP,0)
|
||||
yPvia = yContP
|
||||
yNvia = yContN
|
||||
|
||||
wPvia = self.w_p[-1]-self.via_s2m.sp_via_xs*2
|
||||
wNvia = self.w_n[-1]-self.via_s2m.sp_via_xs*2
|
||||
|
||||
""" Adding metals """
|
||||
if (self.w_mt is not None):
|
||||
nd.strt(xs=self.xs_mt,length=self.w_mt,width=self.L_wg+0.2).put(self.L_wg/2,yContN-w_n_cont/2,90)
|
||||
nd.strt(xs=self.xs_mt,length=self.w_mt,width=self.L_wg+0.2).put(self.L_wg/2,yContP+w_p_cont/2,-90)
|
||||
|
||||
yPvia = yContP+w_p_cont/2-self.w_mt/2
|
||||
yNvia = yContN-w_n_cont/2+self.w_mt/2
|
||||
|
||||
wPvia = self.w_mt
|
||||
wNvia = self.w_mt
|
||||
|
||||
nd.Pin(name="ep1",width=wPvia).put(0,yPvia,180)
|
||||
nd.Pin(name="ep2",width=wPvia).put(self.L_wg,yPvia,0)
|
||||
|
||||
nd.Pin(name="en1",width=wNvia).put(0,yNvia,180)
|
||||
nd.Pin(name="en2",width=wNvia).put(self.L_wg,yNvia,0)
|
||||
|
||||
|
||||
if (self.cell_xs_transition is not None):
|
||||
xs1 = self.cell_xs_transition.put('a0',coreOUT.pin['b0'])
|
||||
xs2 = self.cell_xs_transition.put('a0',coreIN.pin['a0'])
|
||||
|
||||
xs1.raise_pins(['b0'],['a1'])
|
||||
xs2.raise_pins(['b0'],['b1'])
|
||||
else:
|
||||
|
||||
coreIN.raise_pins(['a0'],['b1'])
|
||||
coreOUT.raise_pins(['b0'],['a1'])
|
||||
|
||||
# nd.put_stub()
|
||||
return C
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user