Skip to content

Commit

Permalink
Merge pull request #93 from mabrains/dev
Browse files Browse the repository at this point in the history
Updating LVS rule deck to fix some issues found based on usage feedback.
  • Loading branch information
KrzysztofHerman authored May 2, 2024
2 parents 0434369 + fa67c5e commit b5c6abe
Show file tree
Hide file tree
Showing 22 changed files with 271 additions and 66 deletions.
167 changes: 167 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,6 +1,173 @@
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class

# C extensions
*.so

# Distribution / packaging
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
share/python-wheels/
*.egg-info/
.installed.cfg
*.egg
MANIFEST

# PyInstaller
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec

# Installer logs
pip-log.txt
pip-delete-this-directory.txt

# Unit test / coverage reports
htmlcov/
.tox/
.nox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*.cover
*.py,cover
.hypothesis/
.pytest_cache/
cover/

# Translations
*.mo
*.pot

# Django stuff:
*.log
local_settings.py
db.sqlite3
db.sqlite3-journal

# Flask stuff:
instance/
.webassets-cache

# Scrapy stuff:
.scrapy

# Sphinx documentation
docs/_build/

# PyBuilder
.pybuilder/
target/

# Jupyter Notebook
.ipynb_checkpoints

# IPython
profile_default/
ipython_config.py

# pyenv
# For a library or package, you might want to ignore these files since the code is
# intended to run in multiple environments; otherwise, check them in:
# .python-version

# pipenv
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
# However, in case of collaboration, if having platform-specific dependencies or dependencies
# having no cross-platform support, pipenv may install dependencies that don't work, or not
# install all needed dependencies.
#Pipfile.lock

# poetry
# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
# This is especially recommended for binary packages to ensure reproducibility, and is more
# commonly ignored for libraries.
# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
#poetry.lock

# pdm
# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
#pdm.lock
# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
# in version control.
# https://pdm.fming.dev/#use-with-ide
.pdm.toml

# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
__pypackages__/

# Celery stuff
celerybeat-schedule
celerybeat.pid

# SageMath parsed files
*.sage.py

# Environments
.env
.venv
env/
venv/
ENV/
env.bak/
venv.bak/

# Spyder project settings
.spyderproject
.spyproject

# Rope project settings
.ropeproject

# mkdocs documentation
/site

# mypy
.mypy_cache/
.dmypy.json
dmypy.json

# Pyre type checker
.pyre/

# pytype static type analyzer
.pytype/

# Cython debug symbols
cython_debug/

# PyCharm
# JetBrains specific template is maintained in a separate JetBrains.gitignore that can
# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
# and can be added to the global gitignore or merged into this file. For a more nuclear
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
#.idea/

*.raw
*.spice
*.csv
*.osdi
.DS_Store
*.pyc

.vscode/
*.lyrdb
*.lvsdb
unit_tests_*
lvs_run_*
9 changes: 6 additions & 3 deletions ihp-sg13g2/libs.tech/klayout/tech/lvs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,11 @@ Explains how to use the SG13G2 LVS rule decks.
```

## 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+

Expand Down Expand Up @@ -66,9 +69,9 @@ The following table explains the list of available SG13G2 devices we have suppor
| dpantenna |:white_check_mark:|
| schottky_nbl1 |:white_check_mark:|
| **Resistors** | |
| res_rsil |:white_check_mark:|
| res_rppd |:white_check_mark:|
| res_rhigh |:white_check_mark:|
| rsil |:white_check_mark:|
| rppd |:white_check_mark:|
| rhigh |:white_check_mark:|
| lvsres |:white_check_mark:|
| **Capacitors** | |
| SVaricap |:white_check_mark:|
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,18 @@ module DeviceCombinerMethods
series_con2 = a_net1.cluster_id == b_net2.cluster_id || a_net2.cluster_id == b_net1.cluster_id
series_con = series_con1 || series_con2
end

# Reroute terminal connections based on cluster IDs
if a_net1.cluster_id == b_net1.cluster_id
a.connect_terminal(0, b_net2)
elsif a_net2.cluster_id == b_net2.cluster_id
a.connect_terminal(1, b_net1)
elsif a_net1.cluster_id == b_net2.cluster_id
a.connect_terminal(0, b_net1)
elsif a_net2.cluster_id == b_net1.cluster_id
a.connect_terminal(1, b_net2)
end

a_net1 && b_net1 && a_net2 && b_net2 && series_con
end

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ class GeneralNTerminalExtractor < RBA::GenericDeviceExtractor
# Set up layers and register device class for extraction.
define_layers
# Register device class for extraction.
if name.downcase.start_with?('res')
if RES_DEV.any? { |res| name.downcase.start_with?(res) }
@reg_dev = DeviceCustomRes.new(name, @num)
elsif name.downcase.include?('varicap')
@reg_dev = DeviceCustomVaractor.new(name, @num)
Expand Down Expand Up @@ -133,7 +133,7 @@ class GeneralNTerminalExtractor < RBA::GenericDeviceExtractor
# Returns:
# None

if name.downcase.start_with?('res')
if RES_DEV.any? { |res| name.downcase.start_with?(res) }
width, length, poly_sp, bends = calc_res_params(dev, ports, meas_mk)
device.set_parameter('w', width * $unit)
device.set_parameter('l', length * $unit)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ class CustomReader < RBA::NetlistSpiceReaderDelegate

# Create a resistor device class.
def create_resistor(model, num_nets)
if model.downcase.start_with?('res')
if RES_DEV.any? { |res| model.downcase.start_with?(res) }
DeviceCustomRes.new(model, num_nets)
elsif num_nets == 2 && model.downcase.include?('tap')
RBA::DeviceClassDiode.new
Expand Down Expand Up @@ -172,7 +172,7 @@ class CustomReader < RBA::NetlistSpiceReaderDelegate
when 'C'
model.downcase.include?('varicap') ? gen_term_with_sub(model, nets.size) : gen_mim_terms(model)
when 'R'
if model.downcase.start_with?('res')
if RES_DEV.any? { |res| model.downcase.start_with?(res) }
gen_term_names(model, nets.size)
elsif model.downcase.include?('tap')
%w[C A]
Expand All @@ -186,7 +186,7 @@ class CustomReader < RBA::NetlistSpiceReaderDelegate
%w[C E B]
elsif model.downcase.include?('schottky')
%w[E B C]
elsif model.downcase.include?('nmoscl') || model.downcase.include?('antenna')
elsif model.downcase.include?('nmoscl')
%w[C A]
else
%w[A C]
Expand Down Expand Up @@ -268,8 +268,8 @@ class CustomReader < RBA::NetlistSpiceReaderDelegate
if model.downcase.include?('diodev') || model.downcase.include?('schottky') || model.downcase.include?('nmoscl')
device.set_parameter('m', params['M'] || 1.0)
else
device.set_parameter('A', (params['A'] || 0.0) * 1e12)
device.set_parameter('P', (params['P'] || 0.0) * 1e6)
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)
device.set_parameter('m', params['M'] || 1.0)
end
end
Expand All @@ -287,9 +287,9 @@ class CustomReader < RBA::NetlistSpiceReaderDelegate
# Map parameters for a resistor device.
def map_resistor_params(device, model, params)
if model.downcase.include?('tap')
device.set_parameter('A', (params['A'] || 0.0) * (params['M'] || 1.0) * 1e12)
device.set_parameter('P', (params['P'] || params['PERIM'] || 0.0) * (params['M'] || 1.0) * 1e6)
elsif model.downcase.start_with?('res')
device.set_parameter('A', (params['A'] || ((params['W'] || 0.0) * (params['L'] || 0.0))) * 1e12)
device.set_parameter('P', (params['P'] || params['PERIM'] || (((params['W'] || 0.0) + (params['L'] || 0.0)) * 2)) * 1e6)
elsif RES_DEV.any? { |res| model.downcase.start_with?(res) }
device.set_parameter('w', (params['W'] || 0.0) * 1e6)
device.set_parameter('l', (params['L'] || 0.0) * 1e6)
device.set_parameter('ps', (params['PS'] || 0.0) * 1e6)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,8 @@ connect(dantenna_n, cont_drw)
connect(dantenna_p, pwell)

# dantenna diode
connect(dpantenna_n, cont_drw)
connect(dpantenna_p, pwell)
connect(dpantenna_n, nwell_drw)
connect(dpantenna_p, cont_drw)

# dantenna diode
connect(schottcky_p_1x1, schottcky_p)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,25 +23,25 @@

logger.info('Starting DIODE DERIVATIONS')

diode_exclude = gatpoly_drw.join(nwell_drw).join(nsd_drw)
.join(heattrans_drw).join(trans_drw).join(emwind_drw)
.join(emwihv_drw).join(heatres_drw).join(polyres_drw)
.join(mim_drw).join(extblock_drw).join(res_drw)
.join(activ_mask).join(recog_esd).join(ind_drw)
.join(ind_pin).join(substrate_drw)
diode_exclude = gatpoly_drw.join(nsd_drw).join(heattrans_drw)
.join(trans_drw).join(emwind_drw).join(emwihv_drw)
.join(heatres_drw).join(polyres_drw).join(mim_drw)
.join(extblock_drw).join(res_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)
.join(nsd_block).join(diode_exclude)

antenna_d_mk = recog_diode.not(antenna_d_exc)

# ==== dantenna diode ====
dantenna_n = activ_drw.and(antenna_d_mk).not(psd_drw)
dantenna_n = activ_drw.and(antenna_d_mk).not(psd_drw).not(nwell_drw)
dantenna_p = pwell.and(antenna_d_mk).covering(dantenna_n)

# ==== dpantenna diode ====
dpantenna_n = pactiv.and(antenna_d_mk)
dpantenna_p = pwell.and(antenna_d_mk).covering(dpantenna_n)
dpantenna_p = pactiv.and(antenna_d_mk)
dpantenna_n = nwell_drw.covering(dpantenna_p)

# ==== schottky_nbl1 diode ====
schottky_mk = recog_diode.and(thickgateox_drw).not(diode_exclude)
Expand Down
11 changes: 8 additions & 3 deletions ihp-sg13g2/libs.tech/klayout/tech/lvs/rule_decks/globals.lvs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
# --------------- Varaibles ----------------
#===========================================

# Prefix for each device
PREFIX_MAP = {
'sg13_lv_nmos' => 'M',
'sg13_hv_nmos' => 'M',
Expand All @@ -37,9 +38,9 @@ PREFIX_MAP = {
'dantenna' => 'D',
'dpantenna' => 'D',
'schottky_nbl1' => 'D',
'res_rsil' => 'R',
'res_rppd' => 'R',
'res_rhigh' => 'R',
'rsil' => 'R',
'rppd' => 'R',
'rhigh' => 'R',
'lvsres' => 'R',
'SVaricap' => 'C',
'cap_cmim' => 'C',
Expand All @@ -60,4 +61,8 @@ PREFIX_MAP = {
'inductor3' => 'L'
}.freeze

# Prefix for devices will be customized
CUSTOM_READER = %w[M C R Q L D].freeze

# List of poly-resistors
RES_DEV = ['rsil', 'rppd', 'rhigh']
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,13 @@

logger.info('Starting RESISTOR CONNECTIONS')

# === res_rsil ===
# === rsil ===
connect(rsil_ports, cont_drw)

# === res_rppd ===
# === rppd ===
connect(rppd_ports, cont_drw)

# === res_rhigh ===
# === rhigh ===
connect(rhigh_ports, cont_drw)

# === lvsres ===
Expand Down
Loading

0 comments on commit b5c6abe

Please sign in to comment.