Skip to content

Commit

Permalink
Merge pull request #21 from martinjankoehler/gdsfactory-types-fix
Browse files Browse the repository at this point in the history
Fixes for KLayout PCell library
  • Loading branch information
mole99 authored Jul 4, 2024
2 parents 23291bc + 2c982c0 commit abb5891
Show file tree
Hide file tree
Showing 27 changed files with 278 additions and 422 deletions.
55 changes: 27 additions & 28 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,42 +1,41 @@
# Skywater 130nm Technology PDK for KLayout [![License](https://img.shields.io/github/license/efabless/sky130_klayout_pdk)](LICENSE)
# Skywater 130nm Technology PDK for KLayout

<p align="center"><img src="https://avatars.githubusercontent.com/u/3238299?s=200&v=4" width="300" /></p>
<center>[![License](https://img.shields.io/github/license/efabless/sky130_klayout_pdk)](LICENSE)</center>

Efabless is excited to share with you our Skywater 130nm PDK for Klayout.
This package contains the Skywater 130nm PDK for KLayout.

## KLayout technology files for Skywater Sky130
## Contents

* sky130.lyt : technology and connections description
* sky130.lyp : layers color and shape description
* sky130.map : layer mapping of def/lef shapes
* DRC : please use the following --> <https://github.com/efabless/mpw_precheck/blob/main/checks/tech-files/sky130A_mr.drc>
* LVS : LVS script `lvs/lvs_sky130.lylvs` (In development)
* Pcells : Devices generators (In development)
* `sky130.lyt` : technology and connections description
* `sky130.lyp` : layers color and shape description
* `sky130.map` : layer mapping of def/lef shapes
* DRC : DRC deck, located at [mpw_precheck](https://github.com/efabless/mpw_precheck/blob/main/checks/tech-files/sky130A_mr.drc)
* LVS : LVS script, located at `lvs/lvs_sky130.lylvs`
* PCells : devices generators

## Installation
## Usage

To use this repo, you need to do the following:
### Installation

1. Clone the repo:
You have two options for using this package:

```bash
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.

git clone <https://github.com/mabrains/sky130_klayout_pdk.git>
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:

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

2. Go inside sky130_klayout_pdk:
### PCells

```bash
If you would like to use the PCells, you need to install `gdsfactory` in your system-wide Python package installation.
This can be as simple as running the following:

cd sky130_klayout_pdk
```console
pip install --upgrade gdsfactory
```

```

3. Open klayout using the following command:

```bash
KLAYOUT_HOME=./sky130_tech klayout -e
```
> [!IMPORTANT]
> If you are using a Linux distribution that discourages the installation of system-wide Python packages through pip, you need to pass --break-system-packages.
24 changes: 5 additions & 19 deletions sky130_tech/tech/sky130/pymacros/cells/bjt.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ def __init__(self):

# Important: initialize the super class
super(npn_bjt, self).__init__()
self.Type_handle = self.param("type", self.TypeList, "type")
self.Type_handle = self.param("type", self.TypeString, "type", default=BJT_NPN_DEV[0])

for i in BJT_NPN_DEV :
self.Type_handle.add_choice(i, i)
Expand All @@ -49,15 +49,8 @@ def produce_impl(self):

# This is the main part of the implementation: create the layout

self.percision = 1/self.layout.dbu
#self.cell.flatten(1)
npn_instance = draw_npn(layout=self.layout,device_name=self.type)
write_cells = pya.CellInstArray(npn_instance.cell_index(), pya.Trans(pya.Point(0, 0)),
pya.Vector(0, 0), pya.Vector(0, 0),1 , 1)
self.cell.flatten(1)
self.cell.insert(write_cells)
self.layout.cleanup()

npn_instance = draw_npn(cell=self.cell,device_name=self.type)

class pnp_bjt(pya.PCellDeclarationHelper):
"""
PNP BJT Generator for Skywater130
Expand All @@ -67,7 +60,7 @@ def __init__(self):

# Important: initialize the super class
super(pnp_bjt, self).__init__()
self.Type_handle = self.param("Type", self.TypeList, "Type")
self.Type_handle = self.param("Type", self.TypeString, "Type", default=BJT_PNP_DEV[0])

for i in BJT_PNP_DEV :
self.Type_handle.add_choice(i, i)
Expand All @@ -83,11 +76,4 @@ def produce_impl(self):

# This is the main part of the implementation: create the layout

self.percision = 1/self.layout.dbu
pnp_instance = draw_pnp(layout=self.layout,device_name=self.Type)
write_cells = pya.CellInstArray(pnp_instance.cell_index(), pya.Trans(pya.Point(0, 0)),
pya.Vector(0, 0), pya.Vector(0, 0),1 , 1)
self.cell.flatten(1)
self.cell.insert(write_cells)

self.layout.cleanup()
draw_pnp(cell=self.cell,device_name=self.Type)
20 changes: 7 additions & 13 deletions sky130_tech/tech/sky130/pymacros/cells/cap.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,9 +41,10 @@ def __init__(self):

#===================== PARAMETERS DECLARATIONS =====================

self.Type_handle = self.param("type", self.TypeList, "Device Type")
self.Type_handle = self.param("type", self.TypeString, "Device Type")
self.Type_handle.add_choice("sky130_fd_pr__cap_var_lvt","sky130_fd_pr__cap_var_lvt")
self.Type_handle.add_choice("sky130_fd_pr__cap_var_hvt","sky130_fd_pr__cap_var_hvt")
self.Type_handle.default = self.Type_handle.choice_values()[0]


self.param("l", self.TypeDouble, "length", default=l_min, unit="um")
Expand Down Expand Up @@ -100,11 +101,7 @@ def transformation_from_shape_impl(self):
return pya.Trans(self.shape.bbox().center())

def produce_impl(self):
instance = draw_cap_var(layout= self.layout , l=self.l, w=self.w, type=self.type,tap_con_col=self.tap_con_col, gr= self.gr , grw= self.grw, nf=self.nf)
write_cells = pya.CellInstArray(instance.cell_index(), pya.Trans(pya.Point(0, 0)),
pya.Vector(0, 0), pya.Vector(0, 0), 1, 1)
self.cell.insert(write_cells)
self.cell.flatten(1)
draw_cap_var(cell= self.cell , l=self.l, w=self.w, type=self.type,tap_con_col=self.tap_con_col, gr= self.gr , grw= self.grw, nf=self.nf)


class mim_cap(pya.PCellDeclarationHelper):
Expand All @@ -118,10 +115,11 @@ def __init__(self):

#===================== PARAMETERS DECLARATIONS =====================

self.Type_handle = self.param("type", self.TypeList, "Device Type")
self.Type_handle = self.param("type", self.TypeString, "Device Type")
self.Type_handle.add_choice("sky130_fd_pr__model__cap_mim","sky130_fd_pr__model__cap_mim")
self.Type_handle.add_choice("sky130_fd_pr__model__cap_mim_m4","sky130_fd_pr__model__cap_mim_m4")

self.Type_handle.default = self.Type_handle.choice_values()[0]


self.param("l", self.TypeDouble, "length", default=l_mim, unit="um")
self.param("w", self.TypeDouble, "width", default=l_mim, unit="um")
Expand Down Expand Up @@ -175,8 +173,4 @@ def transformation_from_shape_impl(self):
return pya.Trans(self.shape.bbox().center())

def produce_impl(self):
instance = draw_mim_cap(layout= self.layout , l=self.l, w=self.w, type=self.type)
write_cells = pya.CellInstArray(instance.cell_index(), pya.Trans(pya.Point(0, 0)),
pya.Vector(0, 0), pya.Vector(0, 0), 1, 1)
self.cell.insert(write_cells)
self.cell.flatten(1)
draw_mim_cap(cell= self.cell , l=self.l, w=self.w, type=self.type)
32 changes: 9 additions & 23 deletions sky130_tech/tech/sky130/pymacros/cells/diode.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ def __init__(self):

# Important: initialize the super class
super(photo_diode, self).__init__()
self.Type_handle = self.param("Type", self.TypeList, "Type")
self.Type_handle = self.param("Type", self.TypeString, "Type", default=PHOTO_D_DEV[0])

for i in PHOTO_D_DEV :
self.Type_handle.add_choice(i, i)
Expand All @@ -48,15 +48,7 @@ def produce_impl(self):

# This is the main part of the implementation: create the layout

self.percision = 1/self.layout.dbu
ph_d_instance = draw_photodiode(layout=self.layout,device_name=self.Type)

write_cells = pya.CellInstArray(ph_d_instance.cell_index(), pya.Trans(pya.Point(0, 0)),
pya.Vector(0, 0), pya.Vector(0, 0),1 , 1)
self.cell.flatten(1)
self.cell.insert(write_cells)

self.layout.cleanup()
draw_photodiode(cell=self.cell,device_name=self.Type)

d_min = 0.45
grw_min = 0.17
Expand All @@ -72,11 +64,12 @@ def __init__(self):

#===================== PARAMETERS DECLARATIONS =====================

self.Type_handle = self.param("type", self.TypeList, "Device Type")
self.Type_handle = self.param("type", self.TypeString, "Device Type")
self.Type_handle.add_choice("sky130_fd_pr__diode_pw2nd_05v5", "sky130_fd_pr__diode_pw2nd_05v5")
self.Type_handle.add_choice("sky130_fd_pr__diode_pw2nd_05v5_lvt", "sky130_fd_pr__diode_pw2nd_05v5_lvt")
self.Type_handle.add_choice("sky130_fd_pr__diode_pw2nd_05v5_nvt", "sky130_fd_pr__diode_pw2nd_05v5_nvt")
self.Type_handle.add_choice("sky130_fd_pr__diode_pw2nd_11v0", "sky130_fd_pr__diode_pw2nd_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")
Expand Down Expand Up @@ -125,11 +118,7 @@ def transformation_from_shape_impl(self):
return pya.Trans(self.shape.bbox().center())

def produce_impl(self):
instance = draw_diode(layout= self.layout ,d_type="n", l=self.l, w=self.w, type=self.type,cath_w=self.cath_w)
write_cells = pya.CellInstArray(instance.cell_index(), pya.Trans(pya.Point(0, 0)),
pya.Vector(0, 0), pya.Vector(0, 0), 1, 1)
self.cell.insert(write_cells)
self.cell.flatten(1)
draw_diode(cell= self.cell ,d_type="n", l=self.l, w=self.w, type=self.type,cath_w=self.cath_w)


class p_diode(pya.PCellDeclarationHelper):
Expand All @@ -143,12 +132,13 @@ def __init__(self):

#===================== PARAMETERS DECLARATIONS =====================

self.Type_handle = self.param("type", self.TypeList, "Device Type")
self.Type_handle = self.param("type", self.TypeString, "Device Type")
self.Type_handle.add_choice("sky130_fd_pr__diode_pd2nw_05v5", "sky130_fd_pr__diode_pd2nw_05v5")
self.Type_handle.add_choice("sky130_fd_pr__diode_pd2nw_05v5_lvt", "sky130_fd_pr__diode_pd2nw_05v5_lvt")
self.Type_handle.add_choice("sky130_fd_pr__diode_pd2nw_05v5_hvt", "sky130_fd_pr__diode_pd2nw_05v5_hvt")
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")
Expand Down Expand Up @@ -200,8 +190,4 @@ def transformation_from_shape_impl(self):
return pya.Trans(self.shape.bbox().center())

def produce_impl(self):
instance = draw_diode(layout= self.layout ,d_type="p", l=self.l, w=self.w, type=self.type,grw=self.grw, cath_w=self.cath_w)
write_cells = pya.CellInstArray(instance.cell_index(), pya.Trans(pya.Point(0, 0)),
pya.Vector(0, 0), pya.Vector(0, 0), 1, 1)
self.cell.insert(write_cells)
self.cell.flatten(1)
draw_diode(cell= self.cell ,d_type="p", l=self.l, w=self.w, type=self.type,grw=self.grw, cath_w=self.cath_w)
26 changes: 5 additions & 21 deletions sky130_tech/tech/sky130/pymacros/cells/draw_bjt.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,44 +21,28 @@
import os
from .globals import *
import gdsfactory as gf

from .pdk import read_component

gds_p_path = os.path.join(os.path.dirname(os.path.abspath(__file__)),"fixed_devices/bjt" )# parent file path


def draw_npn(layout, device_name):
def draw_npn(cell, device_name):

'''
drawing NPN devices
'''
gds_path = f"{gds_p_path}/npn"

if device_name in BJT_NPN_DEV :
layout.read(f"{gds_path}/{device_name}.gds")
cell_name = device_name
else :
cell_name = device_name
read_component(f"{gds_path}/{device_name}.gds", device_name, cell)



return layout.cell(cell_name)



def draw_pnp(layout, device_name):
def draw_pnp(cell, device_name):

'''
drawing PNP devices
'''
gds_path = f"{gds_p_path}/pnp"

if device_name in BJT_PNP_DEV :
layout.read(f"{gds_path}/{device_name}.gds")
cell_name = device_name
else :
cell_name = device_name
read_component(f"{gds_path}/{device_name}.gds", device_name, cell)


return layout.cell(cell_name)


32 changes: 12 additions & 20 deletions sky130_tech/tech/sky130/pymacros/cells/draw_cap.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,10 @@

from .via_generator import *
from .layers_def import *

from .pdk import open_component, take_component

def draw_cap_var(
layout,
cell,
type="sky130_fd_pr__cap_var_lvt",
l: float = 0.18,
w: float = 1,
Expand All @@ -37,7 +37,7 @@ def draw_cap_var(
Retern varactor
Args:
layout : layout object
cell : kdb.Cell cell to place layout into
l : float of gate length
w : float of gate width
tap_con_col : int of tap contacts columns
Expand All @@ -48,7 +48,7 @@ def draw_cap_var(
"""

c = gf.Component("sky_cap_var_dev")
c = open_component("sky_cap_var_dev")

c_inst = gf.Component("dev inst")

Expand Down Expand Up @@ -173,11 +173,11 @@ def draw_cap_var(
)
g_r_out.move((g_r_in.xmin - grw, g_r_in.ymin - grw))
g_r = c.add_ref(
gf.geometry.boolean(A=g_r_out, B=g_r_in, operation="A-B", layer=tap_layer)
gf.boolean(A=g_r_out, B=g_r_in, operation="A-B", layer=tap_layer)
)

g_r_li = c.add_ref(
gf.geometry.boolean(A=g_r_out, B=g_r_in, operation="A-B", layer=li_layer)
gf.boolean(A=g_r_out, B=g_r_in, operation="A-B", layer=li_layer)
)

g_psdm_in = c_temp.add_ref(
Expand All @@ -202,7 +202,7 @@ def draw_cap_var(
g_psdm_out.move((g_r_out.xmin - tap_nsdm_enc, g_r_out.ymin - tap_nsdm_enc))

g_psdm = c.add_ref(
gf.geometry.boolean(
gf.boolean(
A=g_psdm_out, B=g_psdm_in, operation="A-B", layer=psdm_layer
)
)
Expand Down Expand Up @@ -264,15 +264,11 @@ def draw_cap_var(
)
hvtp.move((poly.xmin - hv_enc, tap.ymin - hv_enc))

c.write_gds("cap_var_temp.gds")
layout.read("cap_var_temp.gds")
cell_name = "sky_cap_var_dev"

return layout.cell(cell_name)
take_component(c, cell)


def draw_mim_cap(
layout,
cell,
type="sky130_fd_pr__model__cap_mim",
l: float = 2,
w: float = 2,
Expand All @@ -282,14 +278,14 @@ def draw_mim_cap(
Retern mim cap
Args:
layout : layout object
cell : kdb.Cell cell to place layout into
l : float of capm length
w : float of capm width
"""

c = gf.Component("sky_mim_cap_dev")
c = open_component("sky_mim_cap_dev")

# used dimensions and layers

Expand Down Expand Up @@ -379,8 +375,4 @@ def draw_mim_cap(
)
c.add_ref(via_2)

c.write_gds("mim_cap_temp.gds")
layout.read("mim_cap_temp.gds")
cell_name = "sky_mim_cap_dev"

return layout.cell(cell_name)
take_component(c, cell)
Loading

0 comments on commit abb5891

Please sign in to comment.