Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

PCells Improvements #23

Merged
merged 4 commits into from
Aug 13, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,12 @@ This package contains the Skywater 130nm PDK for KLayout.
You have two options for using this package:

1. Clone this repository
2. Install the complete sky130 PDK from [open_pdks](https://github.com/RTimothyEdwards/open_pdks) either manually or with [volare](https://github.com/efabless/volare). The PDK also includes this package.
2. Install the complete sky130 PDK from [open_pdks](https://github.com/RTimothyEdwards/open_pdks) either manually or with [volare](https://github.com/efabless/volare). The PDK also includes this package.

When you start KLayout, you must reference this package. This can be done by setting the environment variable `KLAYOUT_HOME`. For example, inside this repository:
When you start KLayout, you must load this package. This can be done by setting the environment variable `KLAYOUT_PATH`. For example, inside this repository:

```console
KLAYOUT_HOME=./sky130_tech klayout -e
KLAYOUT_PATH=./sky130_tech klayout -e
```

### PCells
Expand Down
10 changes: 5 additions & 5 deletions sky130_tech/tech/sky130/pymacros/cells/cap.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,12 +47,12 @@ def __init__(self):
self.Type_handle.default = self.Type_handle.choice_values()[0]


self.param("l", self.TypeDouble, "length", default=l_min, unit="um")
self.param("w", self.TypeDouble, "width", default=w_min, unit="um")
self.param("tap_con_col", self.TypeInt, "tap Contacts Columns", default=1)
self.param("l", self.TypeDouble, "Length", default=l_min, unit="um")
self.param("w", self.TypeDouble, "Width", default=w_min, unit="um")
self.param("tap_con_col", self.TypeInt, "Tap Contacts Columns", default=1)

self.param("gr", self.TypeBoolean, "Gaurd Ring", default=0)
self.param("grw", self.TypeDouble, "Gaurd Ring Width", default=grw_min, unit="um")
self.param("gr", self.TypeBoolean, "Guard Ring", default=0)
self.param("grw", self.TypeDouble, "Guard Ring Width", default=grw_min, unit="um")

self.param("nf", self.TypeDouble, "Number of Fingers", default=1)
#self.param("n", self.TypeDouble, "instance number", default=1)
Expand Down
12 changes: 6 additions & 6 deletions sky130_tech/tech/sky130/pymacros/cells/diode.py
Original file line number Diff line number Diff line change
Expand Up @@ -139,13 +139,13 @@ def __init__(self):
self.Type_handle.add_choice("sky130_fd_pr__diode_pd2nw_11v0", "sky130_fd_pr__diode_pd2nw_11v0")
self.Type_handle.default = self.Type_handle.choice_values()[0]

self.param("w", self.TypeDouble, "width", default=d_min, unit="um")
self.param("l", self.TypeDouble, "length", default=d_min, unit="um")
self.param("cath_w", self.TypeDouble, "Cathode width", default=grw_min, unit="um")
self.param("grw", self.TypeDouble, "Gaurd Ring width", default=grw_min, unit="um")
self.param("w", self.TypeDouble, "Width", default=d_min, unit="um")
self.param("l", self.TypeDouble, "Length", default=d_min, unit="um")
self.param("cath_w", self.TypeDouble, "Cathode Width", default=grw_min, unit="um")
self.param("grw", self.TypeDouble, "Guard Ring Width", default=grw_min, unit="um")

self.param("area", self.TypeDouble,"Area", readonly=True, unit="um^2")
self.param("perim", self.TypeDouble,"Perimeter", readonly=True, unit="um")
self.param("area", self.TypeDouble, "Area", readonly=True, unit="um^2")
self.param("perim", self.TypeDouble, "Perimeter", readonly=True, unit="um")

#self.param("n", self.TypeInt, "n", default=1)

Expand Down
44 changes: 23 additions & 21 deletions sky130_tech/tech/sky130/pymacros/cells/draw_fet.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ def draw_pfet(
) -> gf.Component:

'''
Retern pfet
Return pfet

Args:
cell : kdb.Cell cell to place layout into
Expand All @@ -57,7 +57,7 @@ def draw_pfet(
inter_sd_l : Float of source and drain diffusion length between fingers
nf : integer of number of fingers
M : integer of number of multipliers
grw : gaurd ring width when enabled
grw : guard ring width when enabled
type : string of the device type
bulk : String of bulk connection type (None, Bulk Tie, Guard Ring)
con_bet_fin : boolean of having contacts for diffusion between fingers
Expand Down Expand Up @@ -384,7 +384,7 @@ def draw_pfet(



elif bulk == "Gaurd Ring":
elif bulk == "guard ring":

psdm = c_inst.add_ref(gf.components.rectangle(size=(l_d+ 2*diff_psdm_enc, w+ 2*diff_psdm_enc),layer= psdm_layer))
psdm.move((-diff_psdm_enc,-diff_psdm_enc))
Expand All @@ -394,7 +394,6 @@ def draw_pfet(
rect_bulk_in = c_temp.add_ref(gf.components.rectangle(size=((c_inst.xmax - c_inst.xmin) + 2*diff_tap_spacing,
(c_inst.ymax - c_inst.ymin) + 2*poly_tap_spacing )
, layer= tap_layer))

rect_bulk_in.move((c_inst.xmin-diff_tap_spacing,c_inst.ymin - poly_tap_spacing))
rect_bulk_out = c_temp.add_ref(gf.components.rectangle(size=((rect_bulk_in.xmax - rect_bulk_in.xmin) + 2*grw,(rect_bulk_in.ymax - rect_bulk_in.ymin) + 2*grw )
, layer= tap_layer))
Expand All @@ -409,7 +408,7 @@ def draw_pfet(
nsdm_out.move((rect_bulk_out.xmin - tap_nsdm_enc, rect_bulk_out.ymin - tap_nsdm_enc))
nsdm = c.add_ref(gf.boolean(A= nsdm_out , B = nsdm_in , operation= "A-B", layer= nsdm_layer) )

# adding contacts
# generating contacts

if grw < licon_size[0] + 2*licon_t_enc :
g_con_range = (B.ymin , B.ymax )
Expand All @@ -422,20 +421,20 @@ def draw_pfet(
ring_con_up = c.add_ref(via_generator(x_range=(rect_bulk_in.xmin+0.17,rect_bulk_in.xmax-0.17),y_range=(rect_bulk_in.ymax,rect_bulk_out.ymax)
, via_enclosure=licon_dt_enc, via_layer=licon_layer,via_size=licon_size,via_spacing=licon_spacing))

ring_con_r = c.add_ref(via_generator(x_range=(rect_bulk_out.xmin,rect_bulk_in.xmin),y_range=g_con_range
ring_con_r = c.add_ref(via_generator(x_range=(rect_bulk_out.xmin,rect_bulk_in.xmin),y_range=(rect_bulk_in.ymin+0.17,rect_bulk_in.ymax-0.17)
, via_enclosure=licon_dt_enc, via_layer=licon_layer,via_size=licon_size,via_spacing=licon_spacing))

ring_con_l = c.add_ref(via_generator(x_range=(rect_bulk_in.xmax,rect_bulk_out.xmax),y_range=g_con_range
ring_con_l = c.add_ref(via_generator(x_range=(rect_bulk_in.xmax,rect_bulk_out.xmax),y_range=(rect_bulk_in.ymin+0.17,rect_bulk_in.ymax-0.17)
, via_enclosure=licon_dt_enc, via_layer=licon_layer,via_size=licon_size,via_spacing=licon_spacing))

tap_li_in = c_temp.add_ref(gf.components.rectangle(size=((l_d ) + 2*diff_tap_spacing,
tap_li_in = c_temp.add_ref(gf.components.rectangle(size=((c_inst.xmax - c_inst.xmin) + 2*diff_tap_spacing,
(c_inst.ymax - c_inst.ymin) + 2*poly_tap_spacing )
, layer= li_layer))
tap_li_in.move((-diff_tap_spacing,c_inst.ymin - poly_tap_spacing))
tap_li_in.move((c_inst.xmin - diff_tap_spacing, c_inst.ymin - poly_tap_spacing))
tap_li_out = c_temp.add_ref(gf.components.rectangle(size=((rect_bulk_in.xmax - rect_bulk_in.xmin) + 2*grw,(rect_bulk_in.ymax - rect_bulk_in.ymin) + 2*grw )
, layer= li_layer))
tap_li_out.move((rect_bulk_in.xmin - grw , rect_bulk_in.ymin -grw ))
li = c.add_ref(gf.boolean(A= rect_bulk_out , B = rect_bulk_in , operation= "A-B", layer= li_layer) )
li = c.add_ref(gf.boolean(A= tap_li_out , B = tap_li_in , operation= "A-B", layer= li_layer) )


# generating nwell
Expand All @@ -447,7 +446,7 @@ def draw_pfet(



if bulk != "Gaurd Ring":
if bulk != "guard ring":
c.add_ref(c_inst)

# nwell generation
Expand Down Expand Up @@ -496,7 +495,7 @@ def draw_nfet(
) : #-> gf.Component:

'''
Retern nfet
Return nfet

Args:
cell : kdb.Cell cell to place layout into
Expand All @@ -506,7 +505,7 @@ def draw_nfet(
inter_sd_l : Float of source and drain diffusion length between fingers
nf : integer of number of fingers
M : integer of number of multipliers
grw : gaurd ring width when enabled
grw : guard ring width when enabled
type : string of the device type
bulk : String of bulk connection type (None, Bulk Tie, Guard Ring)
con_bet_fin : boolean of having contacts for diffusion between fingers
Expand Down Expand Up @@ -840,7 +839,7 @@ def draw_nfet(



elif bulk == "Gaurd Ring":
elif bulk == "guard ring":

nsdm = c_inst.add_ref(gf.components.rectangle(size=(l_d+ 2*diff_nsdm_enc, w+ 2*diff_nsdm_enc),layer= nsdm_layer))
nsdm.move((-diff_nsdm_enc,-diff_nsdm_enc))
Expand All @@ -860,7 +859,7 @@ def draw_nfet(
, layer= psdm_layer))
psdm_in.move((rect_bulk_in.xmin + tap_psdm_enc, rect_bulk_in.ymin + tap_psdm_enc))
psdm_out = c_temp.add_ref(gf.components.rectangle(size=((rect_bulk_out.xmax - rect_bulk_out.xmin) + 2*tap_psdm_enc, (rect_bulk_out.ymax - rect_bulk_out.ymin) + 2*tap_psdm_enc )
, layer= nsdm_layer))
, layer= psdm_layer))
psdm_out.move((rect_bulk_out.xmin - tap_psdm_enc, rect_bulk_out.ymin - tap_psdm_enc))
psdm = c.add_ref(gf.boolean(A= psdm_out , B = psdm_in , operation= "A-B", layer= psdm_layer) )

Expand All @@ -881,14 +880,17 @@ def draw_nfet(
ring_con_l = c.add_ref(via_generator(x_range=(rect_bulk_in.xmax,rect_bulk_out.xmax),y_range=(rect_bulk_in.ymin+0.17,rect_bulk_in.ymax-0.17)
, via_enclosure=licon_dt_enc, via_layer=licon_layer,via_size=licon_size,via_spacing=licon_spacing))

tap_li_in = c_temp.add_ref(gf.components.rectangle(size=((l_d ) + 2*diff_tap_spacing,
(c_inst.ymax - c_inst.ymin) + 2*poly_tap_spacing )
, layer= li_layer))
tap_li_in.move((-diff_tap_spacing,c_inst.ymin - poly_tap_spacing))
tap_li_in = c_temp.add_ref(gf.components.rectangle(size=(
(c_inst.xmax - c_inst.xmin) + 2*diff_tap_spacing,
(c_inst.ymax - c_inst.ymin) + 2*poly_tap_spacing ),
layer= li_layer
)
)
tap_li_in.move((c_inst.xmin - diff_tap_spacing, c_inst.ymin - poly_tap_spacing))
tap_li_out = c_temp.add_ref(gf.components.rectangle(size=((rect_bulk_in.xmax - rect_bulk_in.xmin) + 2*grw,(rect_bulk_in.ymax - rect_bulk_in.ymin) + 2*grw )
, layer= li_layer))
tap_li_out.move((rect_bulk_in.xmin - grw , rect_bulk_in.ymin -grw ))
li = c.add_ref(gf.boolean(A= rect_bulk_out , B = rect_bulk_in , operation= "A-B", layer= li_layer) )
li = c.add_ref(gf.boolean(A= tap_li_out , B = tap_li_in , operation= "A-B", layer= li_layer) )



Expand All @@ -904,7 +906,7 @@ def draw_nfet(



if bulk != "Gaurd Ring":
if bulk != "guard ring":
c.add_ref(c_inst)


Expand Down
28 changes: 27 additions & 1 deletion sky130_tech/tech/sky130/pymacros/cells/draw_guard_ring.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,8 @@ def draw_gr (
in_l : float = 1,
in_w : float = 1,
grw : float = 0.17,
con_lev = "li"
con_lev = "li",
implant_type = "None"
) :

'''
Expand All @@ -44,16 +45,37 @@ def draw_gr (
con_spacing = (0.19, 0.19)
con_enc = (0.12, 0.12)

tap_nsdm_enc : float = 0.125
tap_psdm_enc : float = 0.125

c = open_component("sky_ring_gen")
c_temp = gf.Component("temp_store")

# Choose the implant
if implant_type == 'nsdm':
implant_layer = nsdm_layer
if implant_type == 'psdm':
implant_layer = psdm_layer

# Add the implant layer
if implant_type != 'None':
implant_in = c_temp.add_ref(gf.components.rectangle(size=(in_w - 2*tap_nsdm_enc, in_l - 2*tap_nsdm_enc), layer=implant_layer))
implant_in.move((tap_nsdm_enc, tap_nsdm_enc))
implant_out = c_temp.add_ref(gf.components.rectangle(size=(in_w + 2*grw + 2*tap_nsdm_enc, in_l + 2*grw + 2*tap_nsdm_enc), layer=implant_layer))
implant_out.move((-grw - tap_nsdm_enc, -grw - tap_nsdm_enc))
implant = c.add_ref(gf.boolean(A=implant_out, B=implant_in, operation="A-B", layer=implant_layer))

inner = c_temp.add_ref(gf.components.rectangle(size=(in_w, in_l), layer=tap_layer))
outer = c_temp.add_ref(gf.components.rectangle(size=(inner.xmax - inner.xmin + 2*grw , inner.ymax - inner.ymin + 2*grw), layer=tap_layer))
outer.move((-grw, -grw))

gr = c.add_ref(gf.boolean(A=outer, B=inner , operation="A-B", layer=tap_layer))

if con_lev == "li" or con_lev == "metal1":
inner = c_temp.add_ref(gf.components.rectangle(size=(in_w, in_l), layer=li_layer))
outer = c_temp.add_ref(gf.components.rectangle(size=(inner.xmax - inner.xmin + 2*grw , inner.ymax - inner.ymin + 2*grw), layer=li_layer))
outer.move((-grw, -grw))

li = c.add_ref(gf.boolean(A=outer, B=inner, operation="A-B", layer=li_layer))

if grw < con_size[0] + 2*con_enc[0]:
Expand All @@ -73,6 +95,10 @@ def draw_gr (


if con_lev == "metal1" :
inner = c_temp.add_ref(gf.components.rectangle(size=(in_w, in_l), layer=m1_layer))
outer = c_temp.add_ref(gf.components.rectangle(size=(inner.xmax - inner.xmin + 2*grw , inner.ymax - inner.ymin + 2*grw), layer=m1_layer))
outer.move((-grw, -grw))

m1 = c.add_ref(gf.boolean(A=outer, B=inner, operation="A-B", layer=m1_layer))

mcon_l = c.add_ref(via_generator(x_range=(outer.xmin, inner.xmin), y_range=(inner.ymin + 0.17 , inner.ymax - 0.17), via_enclosure=con_enc, via_layer=mcon_layer
Expand Down
6 changes: 3 additions & 3 deletions sky130_tech/tech/sky130/pymacros/cells/fet.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ def __init__(self):
self.Type_handle = self.param("bulk", self.TypeString, "Bulk Type")
self.Type_handle.add_choice("None", "None")
self.Type_handle.add_choice("bulk tie", "bulk tie")
self.Type_handle.add_choice("Gaurd Ring", "Gaurd Ring")
self.Type_handle.add_choice("guard ring", "guard ring")
self.Type_handle.default = self.Type_handle.choice_values()[0]

self.Type_handle = self.param("gate_con_pos", self.TypeString, "Gate Contact Position")
Expand All @@ -68,7 +68,7 @@ def __init__(self):



self.param("l", self.TypeDouble, "length", default=fet_01v8_l, unit="um")
self.param("l", self.TypeDouble, "Length", default=fet_01v8_l, unit="um")
self.param("w", self.TypeDouble, "Width", default=fet_w, unit="um")
self.param("sd_con_col", self.TypeInt, "Diffusion Contacts Columns", default=1)
self.param("inter_sd_l", self.TypeDouble, "Between Fingers Diffusion Length", default=fet_inter_ld, unit="um")
Expand Down Expand Up @@ -174,7 +174,7 @@ def __init__(self):
self.Type_handle = self.param("bulk", self.TypeString, "Bulk Type")
self.Type_handle.add_choice("None", "None")
self.Type_handle.add_choice("bulk tie", "bulk tie")
self.Type_handle.add_choice("Gaurd Ring", "Gaurd Ring")
self.Type_handle.add_choice("guard ring", "guard ring")
self.Type_handle.default = self.Type_handle.choice_values()[0]

self.Type_handle = self.param("gate_con_pos", self.TypeString, "Gate Contact Position")
Expand Down
8 changes: 7 additions & 1 deletion sky130_tech/tech/sky130/pymacros/cells/gr.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,12 @@ def __init__(self):
self.Type_handle.add_choice("li", "li")
self.Type_handle.add_choice("metal1", "metal1")
self.Type_handle.default = self.Type_handle.choice_values()[0]

self.Type_handle = self.param("implant_type", self.TypeString, "Implant Type")
self.Type_handle.add_choice("None", "None")
self.Type_handle.add_choice("psdm", "psdm")
self.Type_handle.add_choice("nsdm", "nsdm")
self.Type_handle.default = self.Type_handle.choice_values()[0]

def display_text_impl(self):
# Provide a descriptive text for the cell
Expand Down Expand Up @@ -94,5 +100,5 @@ def transformation_from_shape_impl(self):
return pya.Trans(self.shape.bbox().center())

def produce_impl(self):
draw_gr(cell=self.cell, in_l=self.in_l, in_w=self.in_w , grw= self.grw , con_lev=self.con_lev)
draw_gr(cell=self.cell, in_l=self.in_l, in_w=self.in_w , grw= self.grw , con_lev=self.con_lev, implant_type=self.implant_type)

4 changes: 4 additions & 0 deletions sky130_tech/tech/sky130/pymacros/cells/pdk.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,10 @@ def take_component(c : gf.Component, target_cell : kdb.Cell):

# TODO: have an API for this
source_cell = c._kdb_cell

# Since dbu for sky130 is 0.001nm, but the manufacturing grid is 0.005nm
# snap to 0.005nm grid to prevent offgrid DRC errors
source_cell.layout().scale_and_snap(source_cell, 5, mult=1, div=1)

cm = kdb.CellMapping()
cm.for_single_cell(target_cell, source_cell)
Expand Down
6 changes: 3 additions & 3 deletions sky130_tech/tech/sky130/pymacros/cells/res_klayout_panel.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,10 @@ def __init__(self, l_min, w_min):

self.Type_handle = self.param("type", self.TypeString, "Device Type")

self.param("len", self.TypeDouble, "length", default=l_min, unit="um")
self.param("w", self.TypeDouble, "width", default=w_min, unit="um")
self.param("len", self.TypeDouble, "Length", default=l_min, unit="um")
self.param("w", self.TypeDouble, "Width", default=w_min, unit="um")

self.param("gr", self.TypeBoolean, "Gaurd Ring", default=1)
self.param("gr", self.TypeBoolean, "Guard Ring", default=1)
self.param(
"area", self.TypeDouble, "Area", readonly=True, unit="um^2"
)
Expand Down
1 change: 1 addition & 0 deletions sky130_tech/tech/sky130/sky130.lyt
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
<original-base-path>$PDK_ROOT/$PDK/libs.tech/klayout</original-base-path>
<layer-properties_file>sky130.lyp</layer-properties_file>
<add-other-layers>true</add-other-layers>
<default-grids>0.01,0.005!</default-grids>
<reader-options>
<gds2>
<box-mode>1</box-mode>
Expand Down
Loading