"""Capacitor components for IHP PDK."""
import gdsfactory as gf
from gdsfactory import Component
from gdsfactory.typings import LayerSpec
from kfactory.schematic import DSchematic
from numpy import floor
from ihp import tech
from ihp.cells.passives import guard_ring
from ihp.cells.via_stacks import via_array, via_stack
from ihp.tech import CbCapCalc
_XS = "metal1_routing"
def snap_to_grid(p, grid: float = 0.005):
return round(p / grid) * grid
# TODO: snap dims to grid
def cmom_extractor(
nfingers: int = 1,
length: float = 2.0,
spacing: float = 0.26,
min_width: float = 0.2,
mom_metals: list[LayerSpec] | None = None,
**kwargs,
) -> float:
if mom_metals is None:
mom_metals = []
layer_thickness = {
"Metal1": tech.LAYER_STACK["metal1"].thickness,
"Metal2": tech.LAYER_STACK["metal2"].thickness,
"Metal3": tech.LAYER_STACK["metal3"].thickness,
"Metal4": tech.LAYER_STACK["metal4"].thickness,
"Metal5": tech.LAYER_STACK["metal5"].thickness,
}
total_cap: float = 0.0
fringe_field_factor = kwargs.get("fringe_field_factor", 0.2)
permitivity = kwargs.get("interlayer_dielectric", 3.8)
eps0 = 8.8541878188e-3 #
for metal in mom_metals:
th = layer_thickness[metal]
min_finger_width = min_width
total_cap += (
permitivity
* eps0
* (th / spacing)
* (
(nfingers * 2) * (length + spacing)
+ min_finger_width * (nfingers * 2 + 1)
)
)
return total_cap * (1 + fringe_field_factor)
[docs]
@gf.cell
def cmom(
nfingers: int = 1,
length: float = 4.0,
spacing: float = 0.26,
botmetal: LayerSpec = "Metal1",
topmetal: LayerSpec = "Metal3",
layer_metal1: LayerSpec = "Metal1drawing",
layer_metal2: LayerSpec = "Metal2drawing",
layer_metal3: LayerSpec = "Metal3drawing",
layer_metal4: LayerSpec = "Metal4drawing",
layer_metal5: LayerSpec = "Metal5drawing",
layer_metal1pin: LayerSpec = "Metal1pin",
layer_metal2pin: LayerSpec = "Metal2pin",
layer_metal3pin: LayerSpec = "Metal3pin",
layer_metal4pin: LayerSpec = "Metal4pin",
layer_metal5pin: LayerSpec = "Metal5pin",
layer_metal1label: LayerSpec = "Metal1label",
layer_metal2label: LayerSpec = "Metal2label",
layer_metal3label: LayerSpec = "Metal3label",
layer_metal4label: LayerSpec = "Metal4label",
layer_metal5label: LayerSpec = "Metal5label",
layer_metal1nofill: LayerSpec = "Metal1nofill",
layer_metal2nofill: LayerSpec = "Metal2nofill",
layer_metal3nofill: LayerSpec = "Metal3nofill",
layer_metal4nofill: LayerSpec = "Metal4nofill",
layer_metal5nofill: LayerSpec = "Metal5nofill",
layer_cap_mark: LayerSpec = "MemCapdrawing",
layer_text: LayerSpec = "TEXTdrawing",
model: str = "cmom",
**kwargs,
) -> Component:
"""Create a MOM (Metal-Over-Metal) interdigitated capacitor.
Args:
nfingers: Number of inside fingers.
length: Length of the capacitor in micrometers.
spacing: Spacing between top and bottom electrodes.
Higher spacing, lower capacitance.
botmetal: Bottom Metal layer for the capacitor stack.
topmetal: Top Metal layer for the capacitor stack.
--- Layers
layer_metal1: Metal1 drawing layer.
layer_metal2: Metal2 drawing layer.
layer_metal3: Metal3 drawing layer.
layer_metal4: Metal4 drawing layer.
layer_metal5: Metal5 drawing layer.
layer_metal1pin: Metal1 pin logic layer.
layer_metal2pin: Metal2 pin logic layer.
layer_metal3pin: Metal3 pin logic layer.
layer_metal4pin: Metal4 pin logic layer.
layer_metal5pin: Metal5 pin logic layer.
layer_metal1label: Metal1 label logic layer.
layer_metal2label: Metal2 label logic layer.
layer_metal3label: Metal3 label logic layer.
layer_metal4label: Metal4 label logic layer.
layer_metal5label: Metal5 label logic layer.
layer_metal1nofill: Metal1 nofill logic layer.
layer_metal2nofill: Metal2 nofill logic layer.
layer_metal3nofill: Metal3 nofill logic layer.
layer_metal4nofill: Metal4 nofill logic layer.
layer_metal5nofill: Metal5 nofill logic layer.
layer_cap_mark: MemCapdrawing logic layer.
layer_text: TEXT drawing layer
model: Device model name.
Returns:
Component with MOM capacitor layout.
Raises:
"""
metals = {
"Metal1": layer_metal1,
"Metal2": layer_metal2,
"Metal3": layer_metal3,
"Metal4": layer_metal4,
"Metal5": layer_metal5,
}
labels = {
"Metal1": layer_metal1label,
"Metal2": layer_metal2label,
"Metal3": layer_metal3label,
"Metal4": layer_metal4label,
"Metal5": layer_metal5label,
}
pins = {
"Metal1": layer_metal1pin,
"Metal2": layer_metal2pin,
"Metal3": layer_metal3pin,
"Metal4": layer_metal4pin,
"Metal5": layer_metal5pin,
}
nofills = {
"Metal1": layer_metal1nofill,
"Metal2": layer_metal2nofill,
"Metal3": layer_metal3nofill,
"Metal4": layer_metal4nofill,
"Metal5": layer_metal5nofill,
}
pdk_design_rules = {
"Metal1": {
"min_width": tech.TECH.metal1_width,
"min_spacing": tech.TECH.metal1_spacing,
},
"Metal2": {
"min_width": tech.TECH.metal2_width,
"min_spacing": tech.TECH.metal2_spacing,
},
"Metal3": {
"min_width": tech.TECH.metal3_width,
"min_spacing": tech.TECH.metal3_spacing,
},
"Metal4": {
"min_width": tech.TECH.metal4_width,
"min_spacing": tech.TECH.metal4_spacing,
},
"Metal5": {
"min_width": tech.TECH.metal5_width,
"min_spacing": tech.TECH.metal5_spacing,
},
}
min_width_global = min([v["min_width"] for v in pdk_design_rules.values()])
min_spacing_global = min([v["min_spacing"] for v in pdk_design_rules.values()])
min_length = 3 * min_width_global # to comply with minimum metal area DRC
assert length > min_length, (
f"Minimum Area for all metals > {min_length * min_width_global}"
)
assert spacing > min_spacing_global, (
f"Minimum metal spacing for all metals > {min_spacing_global}"
)
ordered_metals = list(metals.keys())
# ordered_vias = [lay for lay in ordered_layers if "via" in lay]
assert botmetal in ordered_metals, (
"{botmetal} not it available layers: {_ordered_metals}"
)
assert topmetal in ordered_metals, (
"{topmetal} not it available layers: {_ordered_metals}"
)
mom_metals = ordered_metals[
ordered_metals.index(botmetal) : ordered_metals.index(topmetal) + 1
]
c = gf.Component()
total_length = 0.0
top_pad_ref = None
bot_pad_ref = None
for metal_layer in mom_metals:
min_width = min_width_global
layer = metals[metal_layer]
top_finger = gf.components.rectangle(size=(min_width, length), layer=layer)
top_finger_array = c.add_ref(
top_finger,
columns=nfingers + 1,
rows=1,
column_pitch=2 * (spacing + min_width),
)
top_finger_array.ymin += spacing
bot_finger = gf.components.rectangle(size=(min_width, length), layer=layer)
bot_finger_array = c.add_ref(
bot_finger, columns=nfingers, rows=1, column_pitch=2 * (spacing + min_width)
)
bot_finger_array.xmin += min_width + spacing
total_length = (min_width + spacing) * (2 * nfingers + 1) - spacing
top_pad = gf.components.rectangle(
size=(total_length, 3 * min_width), layer=layer
)
top_pad_ref = c.add_ref(top_pad)
top_pad_ref.ymin += length + spacing
bot_pad_ref = c.add_ref(top_pad)
bot_pad_ref.ymax = 0
# add no fill and no QRC layers to the mom device region
# nofill_layer = metal_layer.capitalize()+'nofill'
nofill_layer = nofills[metal_layer.capitalize()]
c.add_ref(gf.components.bbox(c, layer=nofill_layer))
# add capacitor region marker
c.add_ref(gf.components.bbox(c, layer=layer_cap_mark))
# add ports
# pin_layer: LayerSpec = metal_layer.capitalize()+'pin'
# label_layer: LayerSpec = metal_layer.capitalize()+'label'
pin_layer = pins[metal_layer.capitalize()]
label_layer = labels[metal_layer.capitalize()]
c.add_port(
"PLUS",
center=(top_pad_ref.x, top_pad_ref.y),
width=min_width,
layer=pin_layer,
port_type="electrical",
)
c.add_port(
"MINUS",
center=(bot_pad_ref.x, bot_pad_ref.y),
width=min_width,
layer=pin_layer,
port_type="electrical",
)
c.add_label(text="PLUS", position=(top_pad_ref.x, top_pad_ref.y), layer=label_layer)
c.add_label(
text="MINUS", position=(bot_pad_ref.x, bot_pad_ref.y), layer=label_layer
)
c.add_label(text="PLUS", position=(top_pad_ref.x, top_pad_ref.y), layer=layer_text)
c.add_label(text="MINUS", position=(bot_pad_ref.x, bot_pad_ref.y), layer=layer_text)
c.add_label(text=model, position=(c.x, c.y + min_width), layer=layer_text)
# add a via array stack to the top and bottom pads
mom_via_stack = via_stack(
bottom_layer=botmetal.capitalize(),
top_layer=topmetal.capitalize(),
size=(total_length, 3 * min_width),
vn_columns=nfingers * 4,
vn_rows=1,
)
via_stack_bot = c.add_ref(mom_via_stack)
via_stack_bot.xmin = bot_pad_ref.xmin
via_stack_bot.ymax = bot_pad_ref.ymax
via_stack_top = c.add_ref(mom_via_stack)
via_stack_top.xmin = top_pad_ref.xmin
via_stack_top.ymin = top_pad_ref.ymin
# add place and route layers to define the device's bounding box
prboundary_layer = "prBoundarydrawing"
c.add_ref(gf.components.bbox(c, layer=prboundary_layer))
c.info["capacitance"] = cmom_extractor(
nfingers,
length,
spacing,
min_width=min_width_global,
mom_metals=mom_metals,
**kwargs,
)
c.add_label(
text=f"C = {c.info['capacitance']} fF",
position=(c.x, c.y - min_width),
layer=layer_text,
)
c.info["model"] = model
c.info["nfingers"] = nfingers
c.info["length"] = length
c.info["spacing"] = spacing
# return the component
return c
def cmim_schematic(
width: float = 6.0,
length: float = 6.0,
) -> DSchematic:
s = DSchematic()
s.info["tags"] = ["IHP", "capacitor", "mim"]
s.info["symbol"] = "capacitor"
s.info["ports"] = [
{"name": "MINUS", "side": "left", "type": "electric"},
{"name": "PLUS", "side": "right", "type": "electric"},
]
s.info["models"] = [
{
"language": "spice",
"name": "cap_cmim",
"spice_type": "SUBCKT",
"library": "ihp/models/ngspice/models/cornerCAP.lib",
"sections": ["cap_typ", "cap_bcs", "cap_wcs"],
"port_order": ["PLUS", "MINUS"],
"params": {"w": "width * 1e-6", "l": "length * 1e-6"},
}
]
s.create_port(name="PLUS", cross_section=_XS, x=1, y=0, orientation=0)
s.create_port(name="MINUS", cross_section=_XS, x=-1, y=0, orientation=180)
return s
[docs]
@gf.cell(schematic_function=cmim_schematic)
def cmim(
width: float = 6.0,
length: float = 6.0,
layer_metal5: LayerSpec = "Metal5drawing",
layer_mim: LayerSpec = "MIMdrawing",
layer_vmim: LayerSpec = "Vmimdrawing",
layer_topmetal1: LayerSpec = "TopMetal1drawing",
layer_cap_mark: LayerSpec = "MemCapdrawing",
layer_m4nofill: LayerSpec = "Metal4nofill",
layer_m5nofill: LayerSpec = "Metal5nofill",
layer_tm1nofill: LayerSpec = "TopMetal1nofill",
layer_tm2nofill: LayerSpec = "TopMetal2nofill",
layer_text: LayerSpec = "TEXTdrawing",
layer_metal5label: LayerSpec = "Metal5label",
layer_topmetal1label: LayerSpec = "TopMetal1label",
layer_metal5pin: LayerSpec = "Metal5pin",
layer_topmetal1pin: LayerSpec = "TopMetal1pin",
model: str = "cmim",
**kwargs,
) -> Component:
"""Create a MIM (Metal-Insulator-Metal) capacitor.
Args:
width: Width of the capacitor in micrometers.
length: Length of the capacitor in micrometers.
bot_enclosure: Bottol Metal5 layer enclosure
top_enclosure:
layer_metal5: Metal 5 drawing layer.
layer_mim: MIM device drawing layer.
layer_vmim: Vmim (MIM-TopMetal1 Via) drawing layer.
layer_topmetal1: TopMetal1 drawing layer.
layer_cap_mark: MemCap drawing layer.
layer_m4nofill: Metal4 nofill logic layer.
layer_m5nofill: Metal5 nofill logic layer.
layer_tm1nofill: TopMetal1 nofill logic layer.
layer_tm2nofill: TopMetal2 nofill logic layer.
layer_text: TEXT drawing layer.
layer_metal5label: Metal5 label logic layer.
layer_topmetal1label: TopMetal1 label logic layer.
layer_metal5pin: Metal5 pin logic layer.
layer_topmetal1pin: TopMetal1 pin logic layer.
model: Device model name.
Returns:
Component with MIM capacitor layout.
Raises:
ValueError: If width or length is outside allowed range.
"""
if width < tech.TECH.cmim_min_size or width > tech.TECH.cmim_max_size:
raise ValueError(
f"cmim width={width} out of range [{tech.TECH.cmim_min_size}, {tech.TECH.cmim_max_size}]"
)
if length < tech.TECH.cmim_min_size or length > tech.TECH.cmim_max_size:
raise ValueError(
f"cmim length={length} out of range [{tech.TECH.cmim_min_size}, {tech.TECH.cmim_max_size}]"
)
c = Component()
mim_drc = {
# capacitor
"mim_min_size": tech.TECH.mim_min_size,
"mim_cap_density": tech.TECH.mim_cap_density,
# metals
"m5_min_width": tech.TECH.metal5_width,
"m5_min_spacing": tech.TECH.metal5_spacing,
"topmetal1_width": tech.TECH.topmetal1_width,
"topmetal1_spacing": tech.TECH.topmetal1_spacing,
# vias
"vmim_size": 0.42,
"vmim_spacing": 0.52,
"vmim_enc_metal": 0.42,
"vmim_enc": 0.6, # bot_enclosure
"mim_enc": 0.36, # top_enclosure
}
bot_enclosure = mim_drc["vmim_enc"]
top_enclosure = mim_drc["mim_enc"]
# snap to grid
grid = tech.TECH.grid
width = round(width / grid) * grid
length = round(length / grid) * grid
# build capacitor stack
# Bottom plate (Metal4)
bottom_plate_width = width + 2 * bot_enclosure + 2 * top_enclosure
bottom_plate_length = length + 2 * bot_enclosure + 2 * top_enclosure
bottom_plate = gf.components.rectangle(
size=(bottom_plate_length, bottom_plate_width),
layer=layer_metal5,
centered=True,
)
bot = c.add_ref(bottom_plate)
# MIM layer
mim_layer = gf.components.rectangle(
size=(length + 2 * top_enclosure, width + 2 * top_enclosure),
layer=layer_mim,
centered=True,
)
c.add_ref(mim_layer)
# add vmim via array
vmim_min_width = mim_drc["vmim_size"] + mim_drc["vmim_spacing"]
nrows = int(floor(width / vmim_min_width))
ncols = int(floor(length / vmim_min_width))
# Top plate (TopMetal1)
top_plate = gf.components.rectangle(
size=(length, width),
layer=layer_topmetal1,
centered=True,
)
top = c.add_ref(top_plate)
vmim_array = via_array(
via_type=layer_vmim.split("drawing")[0],
via_size=mim_drc["vmim_size"],
via_spacing=mim_drc["vmim_size"] + mim_drc["vmim_spacing"],
via_enclosure=mim_drc["vmim_enc_metal"],
columns=ncols,
rows=nrows,
)
vias = c.add_ref(vmim_array)
vias.x = top.x
vias.y = top.y
# Add no fill logic layers
logic = [
layer_cap_mark,
layer_m4nofill,
layer_m5nofill,
layer_tm1nofill,
layer_tm2nofill,
]
for layer_spec in logic:
ll = gf.components.rectangle(
size=(bottom_plate_length, bottom_plate_width),
layer=layer_spec,
centered=True,
)
c.add_ref(ll)
minus = c.add_port(
name="MINUS",
center=(bot.xmin + mim_drc["m5_min_width"] / 2, bot.y),
width=mim_drc["m5_min_width"],
orientation=180,
layer=layer_metal5pin,
port_type="electrical",
)
plus = c.add_port(
name="PLUS",
center=(top.xmax - mim_drc["topmetal1_width"] / 2, top.y),
width=mim_drc["topmetal1_width"],
orientation=0,
layer=layer_topmetal1pin,
port_type="electrical",
)
pin_minus = gf.components.rectangle(
size=(mim_drc["topmetal1_width"], 2 * mim_drc["topmetal1_width"]),
layer=layer_metal5pin,
centered=True,
)
pin_minus_ref = c.add_ref(pin_minus)
pin_minus_ref.xmin = bot.xmin
pin_minus_ref.y = minus.y
pin_plus = gf.components.rectangle(
size=(mim_drc["topmetal1_width"], 2 * mim_drc["topmetal1_width"]),
layer=layer_topmetal1pin,
centered=True,
)
pin_plus_ref = c.add_ref(pin_plus)
pin_plus_ref.xmax = top.xmax
pin_plus_ref.y = plus.y
c.add_label(
text="PLUS",
position=(top.xmax - mim_drc["topmetal1_width"] / 2, top.y),
layer=layer_text,
)
c.add_label(
text="MINUS",
position=(bot.xmin + mim_drc["m5_min_width"] / 2, bot.y),
layer=layer_text,
)
c.add_label(text=model, position=(c.x, c.y + width / 2), layer=layer_text)
# fringe_factor = kwargs.get("fringe_factor", 0.355)
# capacitance = width * length * mim_drc['mim_cap_density']
# capacitance *= (1+fringe_factor)
capacitance = CbCapCalc("C", 0, length, width, model)
c.add_label(
text=f"C = {capacitance} fF", position=(c.x, c.y - width / 2), layer=layer_text
)
c.info["model"] = model
c.info["width"] = width
c.info["length"] = length
c.info["capacitance_fF"] = capacitance
c.info["area_um2"] = width * length
return c
def rfcmim_schematic(
width: float = 7.0,
length: float = 7.0,
) -> DSchematic:
s = DSchematic()
s.info["tags"] = ["IHP", "capacitor", "mim", "rf"]
s.info["symbol"] = "capacitor"
s.info["ports"] = [
{"name": "BN", "side": "bottom", "type": "electric"},
{"name": "MINUS", "side": "left", "type": "electric"},
{"name": "PLUS", "side": "right", "type": "electric"},
]
s.info["models"] = [
{
"language": "spice",
"name": "cap_rfcmim",
"spice_type": "SUBCKT",
"library": "ihp/models/ngspice/models/cornerCAP.lib",
"sections": ["cap_typ", "cap_bcs", "cap_wcs"],
"port_order": ["PLUS", "MINUS", "BN"],
"params": {"l": "length * 1e-6", "w": "width * 1e-6"},
}
]
s.create_port(name="PLUS", cross_section=_XS, x=1, y=0, orientation=0)
s.create_port(name="MINUS", cross_section=_XS, x=-1, y=0, orientation=180)
s.create_port(name="BN", cross_section=_XS, x=0, y=-1, orientation=270)
return s
[docs]
@gf.cell(schematic_function=rfcmim_schematic)
def rfcmim(
width: float = 7.0,
length: float = 7.0,
layer_pwellblock: LayerSpec = "PWellblock",
layer_metal5: LayerSpec = "Metal5drawing",
layer_mim: LayerSpec = "MIMdrawing",
layer_vmim: LayerSpec = "Vmimdrawing",
layer_topmetal1: LayerSpec = "TopMetal1drawing",
layer_cap_mark: LayerSpec = "MemCapdrawing",
layer_m4nofill: LayerSpec = "Metal4nofill",
layer_m5nofill: LayerSpec = "Metal5nofill",
layer_tm1nofill: LayerSpec = "TopMetal1nofill",
layer_tm2nofill: LayerSpec = "TopMetal2nofill",
layer_activ: LayerSpec = "Activdrawing",
layer_cont: LayerSpec = "Contdrawing",
layer_metal1: LayerSpec = "Metal1drawing",
layer_psd: LayerSpec = "pSDdrawing",
# layer_rfpad: LayerSpec = "RFPaddrawing",
layer_activnoqrc: LayerSpec = "Activnoqrc",
layer_metal1noqrc: LayerSpec = "Metal1noqrc",
layer_metal2noqrc: LayerSpec = "Metal2noqrc",
layer_metal3noqrc: LayerSpec = "Metal3noqrc",
layer_metal4noqrc: LayerSpec = "Metal4noqrc",
layer_metal5noqrc: LayerSpec = "Metal5noqrc",
layer_topmetal1noqrc: LayerSpec = "TopMetal1noqrc",
layer_text: LayerSpec = "TEXTdrawing",
layer_metal1pin: LayerSpec = "Metal1pin",
layer_metal5pin: LayerSpec = "Metal5pin",
layer_topmetal1pin: LayerSpec = "TopMetal1pin",
layer_metal5label: LayerSpec = "Metal5label",
layer_topmetal1label: LayerSpec = "TopMetal1label",
layer_metal1label: LayerSpec = "Metal1label",
model: str = "rfcmim",
) -> Component:
"""Create a MIM (Metal-Insulator-Metal) capacitor isolated by a
bulk charge-drift encapsulation P-Plus guard-ring.
Args:
width: Width of the capacitor in micrometers.
length: Length of the capacitor in micrometers.
layer_metal5: Metal 5 drawing layer.
layer_mim: MIM device drawing layer.
layer_vmim: Vmim (MIM-TopMetal1 Via) drawing layer.
layer_topmetal1: TopMetal1 drawing layer.
layer_cap_mark: MemCap drawing layer.
layer_m4nofill: Metal4 nofill logic layer.
layer_m5nofill: Metal5 nofill logic layer.
layer_tm1nofill: TopMetal1 nofill logic layer.
layer_tm2nofill: TopMetal2 nofill logic layer.
layer_text: TEXT drawing layer.
layer_metal5label: Metal5 label logic layer.
layer_topmetal1label: TopMetal1 label logic layer.
layer_metal5pin: Metal5 pin logic layer.
layer_topmetal1pin: TopMetal1 pin logic layer.
model: Device model name.
Returns:
Component with MIM capacitor layout.
Raises:
ValueError: If width or length is outside allowed range.
"""
if width < tech.TECH.rfcmim_min_size or width > tech.TECH.rfcmim_max_size:
raise ValueError(
f"rfcmim width={width} out of range [{tech.TECH.rfcmim_min_size}, {tech.TECH.rfcmim_max_size}]"
)
if length < tech.TECH.rfcmim_min_size or length > tech.TECH.rfcmim_max_size:
raise ValueError(
f"rfcmim length={length} out of range [{tech.TECH.rfcmim_min_size}, {tech.TECH.rfcmim_max_size}]"
)
c = Component()
cap = cmim(
width=width,
length=length,
layer_metal5=layer_metal5,
layer_mim=layer_mim,
layer_vmim=layer_vmim,
layer_topmetal1=layer_topmetal1,
layer_cap_mark=layer_cap_mark,
layer_m4nofill=layer_m4nofill,
layer_m5nofill=layer_m5nofill,
layer_tm1nofill=layer_tm1nofill,
layer_tm2nofill=layer_tm2nofill,
layer_text=layer_text,
layer_metal5pin=layer_metal5pin,
layer_topmetal1pin=layer_topmetal1pin,
layer_metal5label=layer_metal5label,
layer_topmetal1label=layer_topmetal1label,
model=model,
)
c.info = cap.info
c.info["model"] = "cap_rfcmim"
c.add_ref(cap)
c.ports = cap.ports
# add pwell block
size = c.bbox_np()
size = size[1] - size[0]
pwellblock_enc = 2.4
pwell = gf.components.rectangle(
size=(size[0] + 2 * pwellblock_enc, size[1] + 2 * pwellblock_enc),
layer=layer_pwellblock,
centered=True,
)
ccenter = (c.x, c.y)
pwell_ref = c.add_ref(pwell)
pwell_ref.x = ccenter[0]
pwell_ref.y = ccenter[1]
# add p guard ring
pguardring_seq = 0.6
pguardring_width = 2.0
c.add_ref(
guard_ring(
width=pguardring_width,
guardRingSpacing=pguardring_seq,
guardRingType="psub",
bbox=tuple(tuple(p) for p in c.bbox_np()),
path=None,
layer_activ=layer_activ,
layer_cont=layer_cont,
layer_metal1=layer_metal1,
layer_psd=layer_psd,
)
)
logic_layers = [
layer_activnoqrc,
layer_metal1noqrc,
layer_metal2noqrc,
layer_metal3noqrc,
layer_metal4noqrc,
layer_metal5noqrc,
layer_topmetal1noqrc,
]
size = c.bbox_np()
size = size[1] - size[0]
ccenter = (c.x, c.y)
for layer_spec in logic_layers:
ll = gf.components.rectangle(
size=(size[0], size[1]),
layer=layer_spec,
centered=True,
)
ref = c.add_ref(ll)
ref.x = ccenter[0]
ref.y = ccenter[1]
gr_drc = {
"active_min_enclose_pp": 0.14,
}
# add TIE LOW pin
tie_low = gf.components.rectangle(
size=(size[0] - 2 * gr_drc["active_min_enclose_pp"], pguardring_width),
layer=layer_metal1pin,
centered=True,
)
xmin, ymin = c.xmin, c.ymin
tie_low_ref = c.add_ref(tie_low)
tie_low_ref.xmin = xmin + gr_drc["active_min_enclose_pp"]
tie_low_ref.ymin = ymin + gr_drc["active_min_enclose_pp"]
tie = c.add_port(
name="TIE_LOW",
center=(tie_low_ref.x, tie_low_ref.y),
width=pguardring_width,
orientation=0,
layer=layer_metal1pin,
port_type="electrical",
)
c.add_label(text="TIE_LOW", position=(tie.x, tie.y), layer=layer_metal1label)
c.add_label(text="TIE_LOW", position=(tie.x, tie.y), layer=layer_text)
return c