Skip to content

Commit

Permalink
Merge pull request #10 from mabrains/lvs_dev2
Browse files Browse the repository at this point in the history
Adding LVS testing for SG13G2-Cells
  • Loading branch information
atorkmabrains committed May 14, 2024
2 parents d446991 + 65f12c7 commit 8005ab6
Show file tree
Hide file tree
Showing 170 changed files with 5,597 additions and 197 deletions.
26 changes: 24 additions & 2 deletions .github/workflows/lvs_regression.yml
Original file line number Diff line number Diff line change
Expand Up @@ -58,9 +58,9 @@ jobs:
- name: Installing Klayout
run: |
sudo apt update -qq -y
wget https://www.klayout.org/downloads/Ubuntu-22/klayout_0.28.14-1_amd64.deb
wget https://www.klayout.org/downloads/Ubuntu-22/klayout_0.29.0-1_amd64.deb
# The dpkg command will fail complaining about missing dependencies.
sudo dpkg -i ./klayout_0.28.14-1_amd64.deb || true
sudo dpkg -i ./klayout_0.29.0-1_amd64.deb || true
# The apt install command should install the missing dependencies
# needed by KLayout above and finish the install.
sudo apt install -f -y
Expand All @@ -73,3 +73,25 @@ jobs:
- name: Testing ${{ matrix.part }} for ${{ matrix.test }}
run: |
make test-"$(python -c 'print("${{ matrix.part }}".upper())')"-${{ matrix.test }}
lvs_regression_cells:
runs-on: ubuntu-latest
steps:
- name: Installing Klayout
run: |
sudo apt update -qq -y
wget https://www.klayout.org/downloads/Ubuntu-22/klayout_0.29.0-1_amd64.deb
# The dpkg command will fail complaining about missing dependencies.
sudo dpkg -i ./klayout_0.29.0-1_amd64.deb || true
# The apt install command should install the missing dependencies
# needed by KLayout above and finish the install.
sudo apt install -f -y
# Check that KLayout was successfully installed!
klayout -v
- uses: actions/checkout@v3
with:
submodules: 'recursive'
- name: Testing LVS for SG13G2 cells
run: |
make test-LVS-cells
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -173,3 +173,4 @@ cython_debug/
unit_tests_*
lvs_run_*
*_extracted.cir
cells_tests_*
8 changes: 8 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,14 @@ test-LVS-% : env
@. $(VENV_RUN_COMMAND); echo "Running Klayout-LVS regression for $* device"
@. $(VENV_RUN_COMMAND); cd $(KLAYOUT_LVS_TESTS) && make test-LVS-$*

#=================================
# -------- test-LVS-cells --------
#=================================

test-LVS-cells: env
@. $(VENV_RUN_COMMAND); echo "Running Klayout-LVS for SG13G2 cells"
@. $(VENV_RUN_COMMAND); cd $(KLAYOUT_LVS_TESTS) && make test-LVS-cells

#=================================
# -------- test-LVS-switch -------
#=================================
Expand Down
73 changes: 11 additions & 62 deletions ihp-sg13g2/libs.tech/klayout/tech/lvs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,21 +19,23 @@ Explains how to use the SG13G2 LVS rule decks.

```text
📁 lvs
┣ 📁testing Testing environment directory for SG13G2 LVS.
┣ 📁rule_decks Holds all LVS rule decks used for SG13G2.
┣ sg13g2.lvs Main LVS runset that call all rule decks.
┣ 📜README.md This file to document LVS for SG13G2.
┗ 📜run_lvs.py Main python script used for SG13G2 LVS.
┣ 📁testing Directory for the SG13G2 LVS testing environment.
┣ 📁rule_decks Contains all LVS rule decks used for SG13G2.
📜sg13g2.lvs Main LVS runset that calls all rule decks.
┣ 📜README.md Documentation for SG13G2 LVS.
┗ 📜run_lvs.py Main Python script for SG13G2 LVS run.
```

## Prerequisites

You need the following set of tools installed to be able to run SG13G2 LVS:

At a minimum:

- Python 3.9+
- KLayout 0.28.14+
- KLayout 0.29.0+

We have tested this using the following setup:
- Python 3.9.18
- KLayout 0.29.0

## Installation

Expand All @@ -43,59 +45,6 @@ To install the required Python packages, execute the following command:
pip install -r ../../../../../requirements.txt
```

## Devices Status

The following table explains the list of available SG13G2 devices we have supported in our LVS runset.

| Device | Tested |
|-----------------|------------------|
| **MOSFET** | |
| sg13_lv_nmos |:white_check_mark:|
| sg13_hv_nmos |:white_check_mark:|
| sg13_lv_pmos |:white_check_mark:|
| sg13_hv_pmos |:white_check_mark:|
| **RF-MOSFET** | |
| rfnmos |:white_check_mark:|
| rfnmosHV |:white_check_mark:|
| rfpmos |:white_check_mark:|
| rfpmosHV |:white_check_mark:|
| **BJTs** | |
| npn13G2 |:white_check_mark:|
| npn13G2L |:white_check_mark:|
| npn13G2V |:white_check_mark:|
| pnpMPA |:white_check_mark:|
| **Diodes** | |
| dantenna |:white_check_mark:|
| dpantenna |:white_check_mark:|
| schottky_nbl1 |:white_check_mark:|
| **Resistors** | |
| rsil |:white_check_mark:|
| rppd |:white_check_mark:|
| rhigh |:white_check_mark:|
| lvsres |:white_check_mark:|
| **Capacitors** | |
| SVaricap |:white_check_mark:|
| cap_cmim |:white_check_mark:|
| rfcmim |:white_check_mark:|
| **ESD** | |
| diodevdd_4kv |:white_check_mark:|
| diodevdd_2kv |:white_check_mark:|
| diodevss_4kv |:white_check_mark:|
| diodevss_2kv |:white_check_mark:|
| idiodevdd_4kv |:white_check_mark:|
| idiodevdd_2kv |:white_check_mark:|
| idiodevss_4kv |:white_check_mark:|
| idiodevss_2kv |:white_check_mark:|
| nmoscl_2 |:white_check_mark:|
| nmoscl_4 |:white_check_mark:|
| **Inductors** | |
| inductor |:white_check_mark:|
| inductor3 |:white_check_mark:|
| **Taps** | |
| ptap1 |:white_check_mark:|
| ntap1 |:white_check_mark:|


## Usage

You have the option to execute the SG13G2-LVS through either a Python script via the command-line interface [CLI](#cli) or by the Klayout graphical user interface [GUI](#gui), as detailed in the subsequent usage sections.
Expand All @@ -115,7 +64,7 @@ The `run_lvs.py` script takes your gds and netlist files to run LVS rule decks w

**Options:**

- `--help -h ` Displays this help message.
- `--help -h` Displays this help message.

- `--layout=<layout_path>` Specifies the file path of the input GDS file.

Expand Down
27 changes: 12 additions & 15 deletions ihp-sg13g2/libs.tech/klayout/tech/lvs/rule_decks/custom_devices.lvs
Original file line number Diff line number Diff line change
Expand Up @@ -111,11 +111,11 @@ class DeviceCustomInd < RBA::DeviceClassInductor
add_terminals(name, num, 1)

# 5% tolerance for w,s,d:
equal_device_parameters = RBA::EqualDeviceParameters::new(parameter_id('w'), 0.0, 0.05)
equal_device_parameters += RBA::EqualDeviceParameters::new(parameter_id('s'), 0.0, 0.05)
equal_device_parameters += RBA::EqualDeviceParameters::new(parameter_id('d'), 0.0, 0.05)
equal_ind_parameters = RBA::EqualDeviceParameters::new(parameter_id('w'), 0.0, 0.05)
equal_ind_parameters += RBA::EqualDeviceParameters::new(parameter_id('s'), 0.0, 0.05)
equal_ind_parameters += RBA::EqualDeviceParameters::new(parameter_id('d'), 0.0, 0.05)
# applies the compare delegate:
self.equal_parameters = equal_device_parameters
self.equal_parameters = equal_ind_parameters

self.combiner = nil
self.supports_serial_combination=false
Expand Down Expand Up @@ -147,20 +147,17 @@ class RES2 < RBA::DeviceClassResistor
end
end

# MIMCAP device class
class MIMCap < RBA::DeviceClassCapacitor
def initialize
super
enable_parameter('C', false)
enable_parameter('A', true)
enable_parameter('P', true)
end
end

# Diode device class
class EnDiode < RBA::DeviceClassDiode
def initialize
super

# 1% tolerance for A,P:
equal_diode_parameters = RBA::EqualDeviceParameters::new(parameter_id('A'), 0.0, 0.01)
equal_diode_parameters += RBA::EqualDeviceParameters::new(parameter_id('P'), 0.0, 0.01)
# applies the compare delegate:
self.equal_parameters = equal_diode_parameters

# combiner
self.combiner = DiodeDeviceCombiner.new
self.supports_serial_combination=true
self.supports_parallel_combination=true
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,11 @@ class DeviceCustomMIM < RBA::DeviceClassCapacitor
clear_equivalent_terminal_ids

# Adding params
add_parameter(RBA::DeviceParameterDefinition.new('w', 'width', 0, true, 1e-6))
add_parameter(RBA::DeviceParameterDefinition.new('l', 'length', 0, true, 1e-6))
add_parameter(RBA::DeviceParameterDefinition.new('m', 'multiplier', 1, true, 1.0))
add_parameter(RBA::DeviceParameterDefinition.new('w', 'width', 0, false))
add_parameter(RBA::DeviceParameterDefinition.new('l', 'length', 0, false))
add_parameter(RBA::DeviceParameterDefinition.new('A', 'area', 0, true))
add_parameter(RBA::DeviceParameterDefinition.new('P', 'perimeter', 0, true))
add_parameter(RBA::DeviceParameterDefinition.new('m', 'multiplier', 1, true))

# Adding terminals
ter1 = add_terminal(RBA::DeviceTerminalDefinition.new("mim_top"))
Expand All @@ -46,7 +48,7 @@ class DeviceCustomMIM < RBA::DeviceClassCapacitor
# Adding extra param & terminal for rfcmim
return unless name.downcase.include?('rfcmim')

add_parameter(RBA::DeviceParameterDefinition.new('wfeed', 'feed width', 0, true, 1e-6))
add_parameter(RBA::DeviceParameterDefinition.new('wfeed', 'feed width', 0, true))
sub_ter = add_terminal(RBA::DeviceTerminalDefinition.new("mim_sub"))
sub_ter.name = "mim_sub"
end
Expand Down Expand Up @@ -170,6 +172,8 @@ class MIMCAPExtractor < RBA::GenericDeviceExtractor
device.set_parameter('w', width * $unit)
device.set_parameter('l', length * $unit)
end
device.set_parameter('A', width * length * $unit * $unit)
device.set_parameter('P', (width + length) * 2 * $unit)

end

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -279,6 +279,11 @@ class CustomReader < RBA::NetlistSpiceReaderDelegate
device.set_parameter('w', (params['W'] || 0.0) * 1e6)
device.set_parameter('l', (params['L'] || 0.0) * 1e6)
device.set_parameter('m', params['M'] || params['MF'] || 1.0) if model.downcase.include?('cap_cmim')

if model.downcase.include?('mim')
device.set_parameter('A', (params['A'] || ((params['W'] || 0.0) * (params['L'] || 0.0))) * 1e12)
device.set_parameter('P', (params['P'] || (((params['W'] || 0.0) + (params['L'] || 0.0)) * 2)) * 1e6)
end
return unless model.downcase.include?('rfcmim')

device.set_parameter('wfeed', (params['WFEED'] || 0.0) * 1e6)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ diode_exclude = gatpoly_drw.join(nsd_drw)
.join(activ_mask).join(recog_esd).join(ind_drw)
.join(ind_pin).join(substrate_drw)

antenna_d_exc = pwell_block.join(nbulay_drw).join(salblock_drw)
antenna_d_exc = pwell_block.join(salblock_drw)
.join(nsd_block).join(diode_exclude)

antenna_d_mk = recog_diode.not(antenna_d_exc)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ nwell_n_iso = nwell_drw.not(nbulay_drw)

# pwell
pwell_pre = pwell_drw.join(CHIP.not(nwell_drw.join(pwell_block).join(digisub_drw)))
digisub_pre = digisub_drw.sized(-1.nm)
digisub_pre = digisub_drw.sized(-1.nm).not(nwell_drw).not(pwell_block)
pwell = pwell_pre.join(digisub_pre)

# psd, nsd active & res
Expand Down Expand Up @@ -70,7 +70,7 @@ ntap = nactiv.and(nwell_n_iso).not(res_mk).not(recog_diode).not(gatpoly_drw)
ptap = pactiv.and(pwell).not(substrate_drw).not(res_mk).not(recog_diode).not(gatpoly_drw)

# Derived - Layers (Special)
nwell_holes = nwell_drw.holes
nwell_holes = nwell_drw.holes.not(nwell_drw)
ptap_holes = ptap.holes
ntap_holes = ntap.holes

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,9 @@ logger.info('Starting Inductor CONNECTIONS')
connect(ind2_ports, ind_pin)
connect(ind_pin, ind_text)
connect(ind_pin, topmetal2_con)
connect(ind2_sub, pwell_block)
connect(pwell_block, pwell)
connect(ind2_sub, pwell)

# ind3
connect(ind3_ports, ind_pin)
connect(ind_pin, topmetal1_con)
connect(ind3_sub, pwell_block)
connect(ind3_sub, pwell)
Original file line number Diff line number Diff line change
Expand Up @@ -43,10 +43,10 @@ ind_port_lc = ind_ports_.interacting(ind_text.texts("LC"))
ind2_ports = ind_port_la.join(ind_port_lb)
ind2_core = ind_core_.interacting(ind_port_la, 1).interacting(ind_port_lb, 1)
ind2_mk = ind_drw.interacting(ind2_core).interacting(ind2_ports).not_interacting(ind_port_lc)
ind2_sub = pwell_block.and(ind_drw).interacting(ind2_core)
ind2_sub = pwell_block.and(ind_drw).interacting(ind2_core).sized(1.nm)

# inductor3
ind3_ports = ind_port_la.join(ind_port_lb).join(ind_port_lc)
ind3_core = ind_core_.interacting(ind_port_la, 1).interacting(ind_port_lb, 1).interacting(ind_port_lc, 1)
ind3_mk = ind_drw.interacting(ind3_core).interacting(ind3_ports)
ind3_sub = pwell_block.and(ind_drw).interacting(ind3_core)
ind3_sub = pwell_block.and(ind_drw).interacting(ind3_core).sized(1.nm)
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,6 @@ extract_devices(GeneralNTerminalExtractor.new('inductor', 2), {
'dev_mk' => ind2_mk,
'sub_mk' => ind2_sub
})
tolerance('inductor', 'w', 0, 0.1)
tolerance('inductor', 's', 0, 0.1)
tolerance('inductor', 'd', 0, 0.1)

# ind3
logger.info('Extracting Inductor3 device')
Expand All @@ -45,6 +42,3 @@ extract_devices(GeneralNTerminalExtractor.new('inductor3', 3), {
'dev_mk' => ind3_mk,
'sub_mk' => ind3_sub
})
tolerance('inductor3', 'w', 0, 0.1)
tolerance('inductor3', 's', 0, 0.1)
tolerance('inductor3', 'd', 0, 0.1)
8 changes: 3 additions & 5 deletions ihp-sg13g2/libs.tech/klayout/tech/lvs/run_lvs.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,14 +72,12 @@ def check_klayout_version():
logging.error("Was not able to get klayout version properly.")
exit(1)
elif len(klayout_v_list) >= 2 or len(klayout_v_list) <= 3:
if klayout_v_list[1] < 28 or (
klayout_v_list[1] == 28 and klayout_v_list[2] <= 13
):
logging.error("Prerequisites at a minimum: KLayout 0.28.14")
if klayout_v_list[1] < 29:
logging.error("Prerequisites at a minimum: KLayout 0.29.0")
logging.error(
"Using this klayout version has not been assessed. Limits are unknown"
)
# exit(1)
exit(1)

logging.info(f"Your Klayout version is: {klayout_v_}")

Expand Down
14 changes: 14 additions & 0 deletions ihp-sg13g2/libs.tech/klayout/tech/lvs/testing/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,15 @@ test-LVS-%:
@echo "========== LVS-$* testing =========="
@ python3 run_regression.py --device=$*

#================================
# ------ test-LVS-stdcells ------
#================================

.ONESHELL:
test-LVS-cells:
@echo "========== SG13G2-Cells Testing =========="
@ python3 run_regression_cells.py

#=================================
# -------- test-LVS-switch -------
#=================================
Expand All @@ -49,6 +58,10 @@ test-LVS-switch:
@python3 ../run_lvs.py --layout=testcases/extraction_checking/sg13_lv_nmos.gds --netlist=testcases/extraction_checking/sg13_lv_nmos.cdl --run_mode=deep --run_dir=test_nmos_deep
@python3 ../run_lvs.py --layout=testcases/extraction_checking/sg13_lv_nmos.gds --netlist=testcases/extraction_checking/sg13_lv_nmos.cdl --run_mode=flat --run_dir=test_nmos_flat

#==============================
# -------- LIST DEVICES -------
#==============================

.ONESHELL:
list-devices:
@echo "test-LVS-MOS"
Expand All @@ -71,6 +84,7 @@ help:
@echo "... all (the default if no target is provided )"
@echo "... test-LVS (To run LVS for all devices with switching test )"
@echo "... test-LVS-main (To run LVS for all devices )"
@echo "... test-LVS-stdcells (To run LVS for all standard cells )"
@echo "... test-LVS-switch (To run simple LVS switching test )"
@echo "... test-LVS-<device> (To run LVS for specific device group )"
@echo "... list-devices (To list all available device groups )"
Loading

0 comments on commit 8005ab6

Please sign in to comment.