Merge branch 'main' into 86-cell_cross_index

This commit is contained in:
wgryncewicz 2023-05-10 10:22:34 +02:00 committed by GitHub
commit 37fb6cdb25
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
40 changed files with 1420 additions and 879 deletions

8
.github/labels.yml vendored
View File

@ -51,6 +51,10 @@
description: "Item which references a specific open task which needs finishing."
color: "57dbba" # FIXME: blueish
- name: "type-blocker"
description: "Issue which is blocking a launch."
color: "ff0000" # Very Red
##########################################################################
# Labels related to files found in the repository
#
@ -241,6 +245,10 @@
description: "Issues with using OpenROAD with the PDK."
color: "054caa"
- name: "tools-ngspice"
description: "Issues with using Ngspice with the PDK."
color: "054caa"
# Partially open or with closed source dependencies.
- name: "tools-BAG"
description: "Issues with using the Berkeley Analog Generator (BAG) with the PDK."

View File

@ -8,11 +8,11 @@ jobs:
steps:
-
name: Checkout
uses: actions/checkout@v2
uses: actions/checkout@v3
-
name: Run Labeler
if: success()
uses: crazy-max/ghaction-github-labeler@v3.1.0
uses: crazy-max/ghaction-github-labeler@v4.0.0
with:
yaml_file: .github/labels.yml
env:

124
.gitmodules vendored
View File

@ -5,61 +5,61 @@
# sky130_fd_pr
[submodule "libraries/sky130_fd_pr/latest"]
path = libraries/sky130_fd_pr/latest
url = https://foss-eda-tools.googlesource.com/skywater-pdk/libs/sky130_fd_pr.git
branch = master
url = https://github.com/google/skywater-pdk-libs-sky130_fd_pr.git
branch = main
shallow = true
fetchRecurseSubmodules = false
[submodule "libraries/sky130_fd_pr/v0.20.1"]
path = libraries/sky130_fd_pr/v0.20.1
url = https://foss-eda-tools.googlesource.com/skywater-pdk/libs/sky130_fd_pr.git
url = https://github.com/google/skywater-pdk-libs-sky130_fd_pr.git
branch = branch-0.20.1
shallow = true
fetchRecurseSubmodules = false
[submodule "libraries/sky130_fd_pr/v0.20.0"]
path = libraries/sky130_fd_pr/v0.20.0
url = https://foss-eda-tools.googlesource.com/skywater-pdk/libs/sky130_fd_pr.git
url = https://github.com/google/skywater-pdk-libs-sky130_fd_pr.git
branch = branch-0.20.0
shallow = true
fetchRecurseSubmodules = false
[submodule "libraries/sky130_fd_pr/v0.13.0"]
path = libraries/sky130_fd_pr/v0.13.0
url = https://foss-eda-tools.googlesource.com/skywater-pdk/libs/sky130_fd_pr.git
url = https://github.com/google/skywater-pdk-libs-sky130_fd_pr.git
branch = branch-0.13.0
shallow = true
fetchRecurseSubmodules = false
[submodule "libraries/sky130_fd_pr/v0.12.1"]
path = libraries/sky130_fd_pr/v0.12.1
url = https://foss-eda-tools.googlesource.com/skywater-pdk/libs/sky130_fd_pr.git
url = https://github.com/google/skywater-pdk-libs-sky130_fd_pr.git
branch = branch-0.12.1
shallow = true
fetchRecurseSubmodules = false
[submodule "libraries/sky130_fd_pr/v0.12.0"]
path = libraries/sky130_fd_pr/v0.12.0
url = https://foss-eda-tools.googlesource.com/skywater-pdk/libs/sky130_fd_pr.git
url = https://github.com/google/skywater-pdk-libs-sky130_fd_pr.git
branch = branch-0.12.0
shallow = true
fetchRecurseSubmodules = false
[submodule "libraries/sky130_fd_pr/v0.11.0"]
path = libraries/sky130_fd_pr/v0.11.0
url = https://foss-eda-tools.googlesource.com/skywater-pdk/libs/sky130_fd_pr.git
url = https://github.com/google/skywater-pdk-libs-sky130_fd_pr.git
branch = branch-0.11.0
shallow = true
fetchRecurseSubmodules = false
[submodule "libraries/sky130_fd_pr/v0.10.1"]
path = libraries/sky130_fd_pr/v0.10.1
url = https://foss-eda-tools.googlesource.com/skywater-pdk/libs/sky130_fd_pr.git
url = https://github.com/google/skywater-pdk-libs-sky130_fd_pr.git
branch = branch-0.10.1
shallow = true
fetchRecurseSubmodules = false
[submodule "libraries/sky130_fd_pr/v0.10.0"]
path = libraries/sky130_fd_pr/v0.10.0
url = https://foss-eda-tools.googlesource.com/skywater-pdk/libs/sky130_fd_pr.git
url = https://github.com/google/skywater-pdk-libs-sky130_fd_pr.git
branch = branch-0.10.0
shallow = true
fetchRecurseSubmodules = false
[submodule "libraries/sky130_fd_pr/v0.0.9"]
path = libraries/sky130_fd_pr/v0.0.9
url = https://foss-eda-tools.googlesource.com/skywater-pdk/libs/sky130_fd_pr.git
url = https://github.com/google/skywater-pdk-libs-sky130_fd_pr.git
branch = branch-0.0.9
shallow = true
fetchRecurseSubmodules = false
@ -67,36 +67,36 @@
# sky130_fd_sc_hd
[submodule "libraries/sky130_fd_sc_hd/latest"]
path = libraries/sky130_fd_sc_hd/latest
url = https://foss-eda-tools.googlesource.com/skywater-pdk/libs/sky130_fd_sc_hd.git
branch = master
url = https://github.com/google/skywater-pdk-libs-sky130_fd_sc_hd.git
branch = main
shallow = true
[submodule "libraries/sky130_fd_sc_hd/v0.0.2"]
path = libraries/sky130_fd_sc_hd/v0.0.2
url = https://foss-eda-tools.googlesource.com/skywater-pdk/libs/sky130_fd_sc_hd.git
url = https://github.com/google/skywater-pdk-libs-sky130_fd_sc_hd.git
branch = branch-0.0.2
shallow = true
[submodule "libraries/sky130_fd_sc_hd/v0.0.1"]
path = libraries/sky130_fd_sc_hd/v0.0.1
url = https://foss-eda-tools.googlesource.com/skywater-pdk/libs/sky130_fd_sc_hd.git
url = https://github.com/google/skywater-pdk-libs-sky130_fd_sc_hd.git
branch = branch-0.0.1
shallow = true
# sky130_fd_sc_hdll
[submodule "libraries/sky130_fd_sc_hdll/latest"]
path = libraries/sky130_fd_sc_hdll/latest
url = https://foss-eda-tools.googlesource.com/skywater-pdk/libs/sky130_fd_sc_hdll.git
branch = master
url = https://github.com/google/skywater-pdk-libs-sky130_fd_sc_hdll.git
branch = main
shallow = true
fetchRecurseSubmodules = true
[submodule "libraries/sky130_fd_sc_hdll/v0.1.1"]
path = libraries/sky130_fd_sc_hdll/v0.1.1
url = https://foss-eda-tools.googlesource.com/skywater-pdk/libs/sky130_fd_sc_hdll.git
url = https://github.com/google/skywater-pdk-libs-sky130_fd_sc_hdll.git
branch = branch-0.1.1
shallow = true
fetchRecurseSubmodules = false
[submodule "libraries/sky130_fd_sc_hdll/v0.1.0"]
path = libraries/sky130_fd_sc_hdll/v0.1.0
url = https://foss-eda-tools.googlesource.com/skywater-pdk/libs/sky130_fd_sc_hdll.git
url = https://github.com/google/skywater-pdk-libs-sky130_fd_sc_hdll.git
branch = branch-0.1.0
shallow = true
fetchRecurseSubmodules = false
@ -104,19 +104,19 @@
# sky130_fd_sc_hs
[submodule "libraries/sky130_fd_sc_hs/latest"]
path = libraries/sky130_fd_sc_hs/latest
url = https://foss-eda-tools.googlesource.com/skywater-pdk/libs/sky130_fd_sc_hs.git
branch = master
url = https://github.com/google/skywater-pdk-libs-sky130_fd_sc_hs.git
branch = main
shallow = true
fetchRecurseSubmodules = true
[submodule "libraries/sky130_fd_sc_hs/v0.0.2"]
path = libraries/sky130_fd_sc_hs/v0.0.2
url = https://foss-eda-tools.googlesource.com/skywater-pdk/libs/sky130_fd_sc_hs.git
url = https://github.com/google/skywater-pdk-libs-sky130_fd_sc_hs.git
branch = branch-0.0.2
shallow = true
fetchRecurseSubmodules = false
[submodule "libraries/sky130_fd_sc_hs/v0.0.1"]
path = libraries/sky130_fd_sc_hs/v0.0.1
url = https://foss-eda-tools.googlesource.com/skywater-pdk/libs/sky130_fd_sc_hs.git
url = https://github.com/google/skywater-pdk-libs-sky130_fd_sc_hs.git
branch = branch-0.0.1
shallow = true
fetchRecurseSubmodules = false
@ -124,19 +124,19 @@
# sky130_fd_sc_ms
[submodule "libraries/sky130_fd_sc_ms/latest"]
path = libraries/sky130_fd_sc_ms/latest
url = https://foss-eda-tools.googlesource.com/skywater-pdk/libs/sky130_fd_sc_ms.git
branch = master
url = https://github.com/google/skywater-pdk-libs-sky130_fd_sc_ms.git
branch = main
shallow = true
fetchRecurseSubmodules = true
[submodule "libraries/sky130_fd_sc_ms/v0.0.2"]
path = libraries/sky130_fd_sc_ms/v0.0.2
url = https://foss-eda-tools.googlesource.com/skywater-pdk/libs/sky130_fd_sc_ms.git
url = https://github.com/google/skywater-pdk-libs-sky130_fd_sc_ms.git
branch = branch-0.0.2
shallow = true
fetchRecurseSubmodules = false
[submodule "libraries/sky130_fd_sc_ms/v0.0.1"]
path = libraries/sky130_fd_sc_ms/v0.0.1
url = https://foss-eda-tools.googlesource.com/skywater-pdk/libs/sky130_fd_sc_ms.git
url = https://github.com/google/skywater-pdk-libs-sky130_fd_sc_ms.git
branch = branch-0.0.1
shallow = true
fetchRecurseSubmodules = false
@ -144,39 +144,38 @@
# sky130_fd_sc_ls
[submodule "libraries/sky130_fd_sc_ls/latest"]
path = libraries/sky130_fd_sc_ls/latest
url = https://foss-eda-tools.googlesource.com/skywater-pdk/libs/sky130_fd_sc_ls.git
branch = master
url = https://github.com/google/skywater-pdk-libs-sky130_fd_sc_ls.git
branch = main
shallow = true
fetchRecurseSubmodules = true
[submodule "libraries/sky130_fd_sc_ls/v0.1.1"]
path = libraries/sky130_fd_sc_ls/v0.1.1
url = https://foss-eda-tools.googlesource.com/skywater-pdk/libs/sky130_fd_sc_ls.git
url = https://github.com/google/skywater-pdk-libs-sky130_fd_sc_ls.git
branch = branch-0.1.1
shallow = true
fetchRecurseSubmodules = false
[submodule "libraries/sky130_fd_sc_ls/v0.1.0"]
path = libraries/sky130_fd_sc_ls/v0.1.0
url = https://foss-eda-tools.googlesource.com/skywater-pdk/libs/sky130_fd_sc_ls.git
url = https://github.com/google/skywater-pdk-libs-sky130_fd_sc_ls.git
branch = branch-0.1.0
shallow = true
fetchRecurseSubmodules = false
# sky130_fd_sc_lp
[submodule "libraries/sky130_fd_sc_lp/latest"]
path = libraries/sky130_fd_sc_lp/latest
url = https://foss-eda-tools.googlesource.com/skywater-pdk/libs/sky130_fd_sc_lp.git
branch = master
url = https://github.com/google/skywater-pdk-libs-sky130_fd_sc_lp.git
branch = main
shallow = true
fetchRecurseSubmodules = true
[submodule "libraries/sky130_fd_sc_lp/v0.0.2"]
path = libraries/sky130_fd_sc_lp/v0.0.2
url = https://foss-eda-tools.googlesource.com/skywater-pdk/libs/sky130_fd_sc_lp.git
url = https://github.com/google/skywater-pdk-libs-sky130_fd_sc_lp.git
branch = branch-0.0.2
shallow = true
fetchRecurseSubmodules = false
[submodule "libraries/sky130_fd_sc_lp/v0.0.1"]
path = libraries/sky130_fd_sc_lp/v0.0.1
url = https://foss-eda-tools.googlesource.com/skywater-pdk/libs/sky130_fd_sc_lp.git
url = https://github.com/google/skywater-pdk-libs-sky130_fd_sc_lp.git
branch = branch-0.0.1
shallow = true
fetchRecurseSubmodules = false
@ -184,25 +183,25 @@
# sky130_fd_sc_hvl
[submodule "libraries/sky130_fd_sc_hvl/latest"]
path = libraries/sky130_fd_sc_hvl/latest
url = https://foss-eda-tools.googlesource.com/skywater-pdk/libs/sky130_fd_sc_hvl.git
branch = master
url = https://github.com/google/skywater-pdk-libs-sky130_fd_sc_hvl.git
branch = main
shallow = true
fetchRecurseSubmodules = true
[submodule "libraries/sky130_fd_sc_hvl/v0.0.3"]
path = libraries/sky130_fd_sc_hvl/v0.0.3
url = https://foss-eda-tools.googlesource.com/skywater-pdk/libs/sky130_fd_sc_hvl.git
url = https://github.com/google/skywater-pdk-libs-sky130_fd_sc_hvl.git
branch = branch-0.0.3
shallow = true
fetchRecurseSubmodules = false
[submodule "libraries/sky130_fd_sc_hvl/v0.0.2"]
path = libraries/sky130_fd_sc_hvl/v0.0.2
url = https://foss-eda-tools.googlesource.com/skywater-pdk/libs/sky130_fd_sc_hvl.git
url = https://github.com/google/skywater-pdk-libs-sky130_fd_sc_hvl.git
branch = branch-0.0.2
shallow = true
fetchRecurseSubmodules = false
[submodule "libraries/sky130_fd_sc_hvl/v0.0.1"]
path = libraries/sky130_fd_sc_hvl/v0.0.1
url = https://foss-eda-tools.googlesource.com/skywater-pdk/libs/sky130_fd_sc_hvl.git
url = https://github.com/google/skywater-pdk-libs-sky130_fd_sc_hvl.git
branch = branch-0.0.1
shallow = true
fetchRecurseSubmodules = false
@ -210,37 +209,66 @@
# sky130_fd_io
[submodule "libraries/sky130_fd_io/latest"]
path = libraries/sky130_fd_io/latest
url = https://foss-eda-tools.googlesource.com/skywater-pdk/libs/sky130_fd_io.git
branch = master
url = https://github.com/google/skywater-pdk-libs-sky130_fd_io.git
branch = main
shallow = true
fetchRecurseSubmodules = true
[submodule "libraries/sky130_fd_io/v0.2.1"]
path = libraries/sky130_fd_io/v0.2.1
url = https://foss-eda-tools.googlesource.com/skywater-pdk/libs/sky130_fd_io.git
url = https://github.com/google/skywater-pdk-libs-sky130_fd_io.git
branch = branch-0.2.1
shallow = true
fetchRecurseSubmodules = false
[submodule "libraries/sky130_fd_io/v0.2.0"]
path = libraries/sky130_fd_io/v0.2.0
url = https://foss-eda-tools.googlesource.com/skywater-pdk/libs/sky130_fd_io.git
url = https://github.com/google/skywater-pdk-libs-sky130_fd_io.git
branch = branch-0.2.0
shallow = true
fetchRecurseSubmodules = false
[submodule "libraries/sky130_fd_io/v0.1.0"]
path = libraries/sky130_fd_io/v0.1.0
url = https://foss-eda-tools.googlesource.com/skywater-pdk/libs/sky130_fd_io.git
url = https://github.com/google/skywater-pdk-libs-sky130_fd_io.git
branch = branch-0.1.0
shallow = true
fetchRecurseSubmodules = false
[submodule "libraries/sky130_fd_io/v0.0.2"]
path = libraries/sky130_fd_io/v0.0.2
url = https://foss-eda-tools.googlesource.com/skywater-pdk/libs/sky130_fd_io.git
url = https://github.com/google/skywater-pdk-libs-sky130_fd_io.git
branch = branch-0.1.0
shallow = true
fetchRecurseSubmodules = false
[submodule "libraries/sky130_fd_io/v0.0.1"]
path = libraries/sky130_fd_io/v0.0.1
url = https://foss-eda-tools.googlesource.com/skywater-pdk/libs/sky130_fd_io.git
url = https://github.com/google/skywater-pdk-libs-sky130_fd_io.git
branch = branch-0.0.1
shallow = true
fetchRecurseSubmodules = false
#sky130_fd_pr_reram
[submodule "libraries/sky130_fd_pr_reram/v0.0.9"]
path = libraries/sky130_fd_pr_reram/v0.0.9
url = https://github.com/google/skywater-pdk-libs-sky130_fd_pr_reram.git
branch = branch-0.0.9
shallow = true
fetchRecurseSubmodules = false
[submodule "libraries/sky130_fd_pr_reram/v2.0.1"]
path = libraries/sky130_fd_pr_reram/v2.0.1
url = https://github.com/google/skywater-pdk-libs-sky130_fd_pr_reram.git
branch = branch-2.0.1
shallow = true
fetchRecurseSubmodules = false
[submodule "libraries/sky130_fd_pr_reram/v2.0.2"]
path = libraries/sky130_fd_pr_reram/v2.0.2
url = https://github.com/google/skywater-pdk-libs-sky130_fd_pr_reram.git
branch = branch-2.0.2
shallow = true
fetchRecurseSubmodules = false
[submodule "libraries/sky130_fd_pr_reram/v2.0.3"]
path = libraries/sky130_fd_pr_reram/v2.0.3
url = https://github.com/google/skywater-pdk-libs-sky130_fd_pr_reram.git
branch = branch-2.0.3
shallow = true
fetchRecurseSubmodules = false
[submodule "libraries/sky130_fd_pr_reram/latest"]
path = libraries/sky130_fd_pr_reram/latest
url = https://github.com/google/skywater-pdk-libs-sky130_fd_pr_reram.git
branch = main

View File

@ -37,3 +37,6 @@ submodules:
- libraries/sky130_fd_sc_ls/latest
- libraries/sky130_fd_sc_ms/latest
recursive: false
formats:
- pdf

View File

@ -79,9 +79,9 @@ all: README.rst
@true
LIBRARIES = $(sort $(notdir $(wildcard libraries/sky130_*_sc_*)))
SC_LIBS = $(sort $(notdir $(wildcard libraries/sky130_*_sc_*)))
$(LIBRARIES): | $(CONDA_ENV_PYTHON)
$(SC_LIBS): | $(CONDA_ENV_PYTHON)
@$(IN_CONDA_ENV) for V in libraries/$@/*; do \
if [ -d "$$V/cells" ]; then \
python -m skywater_pdk.liberty $$V; \
@ -99,7 +99,7 @@ sky130_fd_sc_ms-leakage: | $(CONDA_ENV_PYTHON)
sky130_fd_sc_ms: sky130_fd_sc_ms-leakage
timing: $(LIBRARIES) | $(CONDA_ENV_PYTHON)
timing: $(SC_LIBS) | $(CONDA_ENV_PYTHON)
@true

BIN
docs/_static/skywater-pdk-logo-top.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

13
docs/_templates/relbar.html vendored Normal file
View File

@ -0,0 +1,13 @@
{% extends '!relbar.html' %}
{%- block extralinks -%}
{{ super() }}
<li class="md-tabs__item"><a href="https://www.skywatertechnology.com/" class="md-tabs__link"><i class="md-icon">business</i> SkyWater</a></li>
<li class="md-tabs__item"><a href="https://efabless.com/open_shuttle_program" class="md-tabs__link"><i class="md-icon">precision_manufacturing</i> Shuttle Program</a></li>
<li class="md-tabs__item"><a href="https://join.skywater.tools/" class="md-tabs__link"><i class="md-icon">chat_bubble</i> Chat</a></li>
<li class="md-tabs__item"><a href="https://groups.google.com/g/skywater-pdk-announce" class="md-tabs__link"><i class="md-icon">campaign</i>Announcements</a></li>
<li class="md-tabs__item"><a href="https://groups.google.com/g/skywater-pdk-users" class="md-tabs__link"><i class="md-icon">mail</i> Mailing List</a></li>
{%- endblock -%}

View File

@ -61,14 +61,19 @@ extensions = [
'sphinx.ext.autosectionlabel',
'sphinx.ext.githubpages',
'sphinx.ext.ifconfig',
'sphinx.ext.imgconverter',
'sphinx.ext.mathjax',
'sphinx.ext.napoleon',
'sphinx.ext.todo',
'sphinxcontrib_hdl_diagrams',
'sphinxcontrib.bibtex',
'skywater_pdk.cells.cross_index',
'skywater_pdk.cells.generate.readme',
]
bibtex_default_style = 'plain'
bibtex_bibfiles = ['refs.bib']
# Add any paths that contain templates here, relative to this directory.
templates_path = ['_templates']
@ -88,8 +93,8 @@ if not on_rtd:
"display_github": True, # Integrate GitHub
"github_user": "google", # Username
"github_repo": "skywater-pdk", # Repo name
"github_version": "master", # Version
"conf_py_path": "/doc/",
"github_version": "main", # Version
"conf_py_path": "/docs/",
}
else:
docs_dir = os.path.abspath(os.path.dirname(__file__))
@ -126,6 +131,9 @@ exclude_patterns = [
'code-of-conduct.rst',
'rules/periphery-rules.rst',
'rules/device-details/*/index.rst',
'rules/summary/*-key.rst',
'rules/layers/*-key.rst',
'rules/hv/*-key.rst',
]
# The name of the Pygments (syntax highlighting) style to use.
@ -148,56 +156,24 @@ pygments_style = None
#
html_theme = "sphinx_symbiflow_theme"
html_logo = "_static/skywater-pdk-logo-top.png"
# Theme options are theme-specific and customize the look and feel of a theme
# further. For a list of options available for each theme, see the
# documentation.
#
# https://sphinx-symbiflow-theme.readthedocs.io/en/latest/customization.html
html_theme_options = {
# Specify a list of menu in Header.
# Tuples forms:
# ('Name', 'external url or path of pages in the document', boolean, 'icon name')
#
# Third argument:
# True indicates an external link.
# False indicates path of pages in the document.
#
# Fourth argument:
# Specify the icon name.
# For details see link.
# https://material.io/icons/
'header_links': [
('Home', 'index', False, 'home'),
("GitHub", "https://github.com/google/skywater-pdk", True, 'code'),
("SkyWater", "https://www.skywatertechnology.com/", True, 'link'),
],
'nav_title': 'SkyWater SKY130 PDK',
# Customize css colors.
# For details see link.
# https://getmdl.io/customize/index.html
#
# Values: amber, blue, brown, cyan deep_orange, deep_purple, green, grey, indigo, light_blue,
# light_green, lime, orange, pink, purple, red, teal, yellow(Default: indigo)
'primary_color': 'light_green',
# Values: Same as primary_color. (Default: pink)
'accent_color': 'teal',
'color_primary': 'light-green',
'color_accent': 'teal',
# Customize layout.
# For details see link.
# https://getmdl.io/components/index.html#layout-section
'fixed_drawer': True,
'fixed_header': True,
'header_waterfall': True,
'header_scroll': False,
# Set the repo location to get a badge with stats
'github_url': 'https://github.com/google/skywater-pdk',
'repo_name': 'google/skywater-pdk',
# Render title in header.
# Values: True, False (Default: False)
'show_header_title': False,
# Render title in drawer.
# Values: True, False (Default: True)
'show_drawer_title': True,
# Render footer.
# Values: True, False (Default: True)
'show_footer': True,
'globaltoc_depth': 4,
'globaltoc_collapse': False,
# Hide the symbiflow links
'hide_symbiflow_links': True,
@ -322,6 +298,23 @@ numfig = True
# If true, `todo` and `todoList` produce output, else they produce nothing.
todo_include_todos = True
latex_elements = {
'preamble': r'\DeclareUnicodeCharacter{03A9}{\ensuremath{\Omega}}' +
r'\DeclareUnicodeCharacter{03BC}{\ensuremath{\mu}}' +
r'\DeclareUnicodeCharacter{2184}{\ensuremath{\supset}}' +
r'\DeclareUnicodeCharacter{2295}{\ensuremath{\oplus}}' +
r'\DeclareUnicodeCharacter{2228}{\ensuremath{\vee}}' +
r'\DeclareUnicodeCharacter{22BB}{\ensuremath{\veebar}}' +
r'\DeclareUnicodeCharacter{01C1}{\ensuremath{\parallel}}' +
r'\DeclareUnicodeCharacter{2220}{\ensuremath{\angle}}' +
r'\DeclareUnicodeCharacter{2227}{\ensuremath{\wedge}}' +
r'\DeclareUnicodeCharacter{25A1}{\ensuremath{\Box}}' +
r'\DeclareUnicodeCharacter{F06D}{\ensuremath{\mu}}' +
r'\DeclareUnicodeCharacter{03B2}{\ensuremath{\beta}}' +
r'\DeclareUnicodeCharacter{2264}{\ensuremath{\leq}}' +
r'\usepackage{pmboxdraw}' +
r'\DeclareUnicodeCharacter{2534}{\textSFvii}'
}
import re
from docutils.parsers.rst import directives, roles, nodes

View File

@ -34,7 +34,7 @@ All sections are **lower case** and separated by an **underscore**. The sections
+--------------------------------+---------------------------------------+
| Digital Standard Cells | :lib_type:`sc` |
+--------------------------------+---------------------------------------+
| Build Space (Flash, SRAM, etc) | :lib_type:`sp` |
| Build Space (Flash, SRAM, etc) | :lib_type:`bd` |
+--------------------------------+---------------------------------------+
| IO and Periphery | :lib_type:`io` |
+--------------------------------+---------------------------------------+

View File

@ -16,13 +16,12 @@
name: skywater-pdk-docs
channels:
- symbiflow
- conda-forge
- defaults
dependencies:
- python=3.8
- pip
- yosys
- netlistsvg
# Packages installed from PyPI
- pip:
- -r file:requirements.txt
- -r requirements.txt
- ../scripts/python-skywater-pdk

View File

@ -24,7 +24,7 @@
contributing
partners
references
Welcome to SkyWater SKY130 PDK's documentation!

View File

@ -29,13 +29,9 @@ This section should also help people who have previously had access (under NDA)
process. It stood for the "8th generation" of the SONOS technology
developed originally by Cypress.
:lib_process:`s8phrc`
:lib_process:`s180`
The name for using 180nm technology on the 130nm process.
:lib_process:`s8phirs`
:lib_process:`s8pfhd`
The base process. 5 metal layer backend stack, 16V devices, deep
nwell.

8
docs/references.rst Normal file
View File

@ -0,0 +1,8 @@
.. _References:
References
##########
.. bibliography::
:notcited:
:labelprefix: R

6
docs/refs.bib Normal file
View File

@ -0,0 +1,6 @@
@Online{SkyWaterPDKIntro_Edwards21,
author = {Edwards, Tim},
title = {{Introduction to the SkyWater PDK: The New Age of Open Source Silicon}},
url = {https://isn.ucsd.edu/courses/beng207/lectures/Tim_Edwards_2021_slides.pdf},
year = {2021},
}

View File

@ -1,8 +1,9 @@
git+https://github.com/SymbiFlow/sphinx_materialdesign_theme.git#egg=sphinx-symbiflow-theme
git+https://github.com/SymbiFlow/sphinx_symbiflow_theme.git#egg=sphinx-symbiflow-theme
docutils
sphinx
sphinx-autobuild
sphinxcontrib-bibtex
# Verilog domain
sphinx-verilog-domain
@ -10,7 +11,7 @@ sphinx-verilog-domain
sphinxcontrib-hdl-diagrams
# Module diagrams
git+https://github.com/SymbiFlow/symbolator.git#egg=symbolator
#git+https://github.com/SymbiFlow/symbolator.git#egg=symbolator
# pycairo
# vext.gi

View File

@ -2,28 +2,66 @@
import re
import os
import sys
from pathlib import Path
from pprint import pformat
RE_IMAGE = re.compile('.. (.*) image:: (.*)')
RE_INCLUDE = re.compile('.. include:: (.*)')
device_list = [
# 1.8V MOS
"nfet_01v8",
"nfet_01v8_lvt",
"pfet_01v8",
"pfet_01v8_lvt",
"pfet_01v8_hvt",
"cap_var",
# 3.3V MOS
"nfet_03v3_nvt",
# 5V MOS
"nfet_05v0_nvt",
"nfet_g5v0d10v5",
"pfet_g5v0d10v5",
"pfet_g5v0d16v0",
# 11V MOS
"nfet_g11v0d16v0",
# 20V MOS
"nfet_20v0",
"nfet_20v0_nvt",
"nfet_20v0_zvt",
"nfet_20v0_iso",
"pfet_20v0",
# ESD MOS
"esd_nfet",
# Diodes/Bipolar
"diodes",
"npn_05v0",
"pnp_05v0",
# Special active devices
"special_sram",
"special_sonosfet",
# Well/Diffusion/Poly/Metal Resistors
"res_generic",
"res_high",
"res_xhigh",
# Metal Capacitors
"cap_mim",
"cap_vpp",
]
print('Device Details')
print('==============')
print()
def r(m):
n = m.group(0)
while len(n) < 10:
n = '0'+n
return n
def k(s):
return re.sub('([0-9.V/]*)', r, str(s))
for fname in sorted(Path('.').rglob('index.rst'), key=k):
for device_name in device_list:
fname = os.path.join("device-details", device_name, "index.rst")
with open(fname) as f:
data = f.read()
@ -33,4 +71,3 @@ for fname in sorted(Path('.').rglob('index.rst'), key=k):
data = RE_IMAGE.sub(r'.. \1 image:: {}/\2'.format(dirname), data)
data = RE_INCLUDE.sub(r'.. include:: {}/\1'.format(dirname), data)
print(data)

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,5 @@
MiM Capacitor
-------------
MiM capacitors
--------------
Spice Model Information
~~~~~~~~~~~~~~~~~~~~~~~

View File

@ -1,5 +1,5 @@
Varactors
---------
1.8V accumulation-mode MOS varactors
------------------------------------
Spice Model Information
~~~~~~~~~~~~~~~~~~~~~~~

View File

@ -1,4 +1,4 @@
NMOS ESD FET
ESD NMOS FET
------------
Spice Model Information

View File

@ -4,7 +4,7 @@
Spice Model Information
~~~~~~~~~~~~~~~~~~~~~~~
- Cell Name: :cell:`sky130_fd_pr__nfet_01v8`
- Cell Name: :cell:`sky130_fd_pr__nfet_05v0_nvt`
- Model Name: :model:`sky130_fd_pr__nfet_05v0_nvt`
Operating Voltages where SPICE models are valid for :model:`sky130_fd_pr__nfet_05v0_nvt`

View File

@ -1,4 +1,4 @@
20V NMOS zero-VT FET
20V zero-VT NMOS FET
--------------------
Spice Model Information

View File

@ -1,5 +1,5 @@
Bipolar (NPN)
-------------
Bipolar NPN transistor
----------------------
Spice Model Information
~~~~~~~~~~~~~~~~~~~~~~~

View File

@ -1,5 +1,5 @@
Bipolar (PNP)
-------------
Bipolar PNP transistor
----------------------
Spice Model Information
~~~~~~~~~~~~~~~~~~~~~~~

View File

@ -1,4 +1,4 @@
Generic Resistors
Generic resistors
-----------------
Generic resistors are supported in the PDK but are not recommended for analog applications. Resistor values will be extracted from the layout as long as the resistor layer is utilized, for LVS against schematic elements.

View File

@ -1,4 +1,5 @@
Explanation of symbols:
* ``-`` = Layer illegal for the device
* ``+`` = Layer allowed to overlap
* ``D`` = DRAWN indicates that a layer is drawn by Design.

View File

@ -1,4 +1,5 @@
Explanation of symbols:
* ``-`` = Layer not created for the device
* ``+`` = Layer allowed to overlap
* ``C`` = CREATED

View File

@ -1,5 +1,5 @@
Summry of Key Periphery Rules
=============================
Summary of Key Periphery Rules
==============================
.. csv-table:: Table F3a: Front end layers (Low Voltage Devices)
:file: summary/table-f3a-font-end-low-voltage.csv

View File

@ -20,6 +20,9 @@ channels:
dependencies:
- python=3.8
- pip
- yosys
- netlistsvg
- iverilog
# Packages installed from PyPI
- pip:
- -r file:requirements.txt
- -r requirements.txt

@ -0,0 +1 @@
Subproject commit 48c8310e464157d797c78cb2e6d6b5a21d710c20

@ -0,0 +1 @@
Subproject commit 1ed57501be4b8b7816942b7eac6f864910025799

@ -0,0 +1 @@
Subproject commit 21212f530de3b071e4737a7622ce3c7dce1527bb

@ -0,0 +1 @@
Subproject commit ef3ec3edd3d30a35ff04011fd3afc8f2cdd1d06f

@ -0,0 +1 @@
Subproject commit d3c4505de8ec4c52fe70c276b351929297ffcd6e

View File

@ -1,4 +1,5 @@
flake8
wavedrom
# rst_include tool as GitHub doesn't support `.. include::` when rendering
# previews.

View File

@ -21,19 +21,24 @@ ifeq (,$(FULL_VERSION))
$(error "Version value could not be determined. Make sure you fetch the tags.")
endif
submodules: libraries/sky130_fd_sc_hd/$(SUBMODULE_VERSION)/.git libraries/sky130_fd_sc_hdll/$(SUBMODULE_VERSION)/.git libraries/sky130_fd_sc_hs/$(SUBMODULE_VERSION)/.git libraries/sky130_fd_sc_ms/$(SUBMODULE_VERSION)/.git libraries/sky130_fd_sc_ls/$(SUBMODULE_VERSION)/.git
LIBRARIES = $(sort $(notdir $(wildcard libraries/sky130_*)))
libraries/sky130_fd_sc_hd/%/.git: .gitmodules
git submodule update --init $(@D)
LIBS_DOT_GIT = $(addsuffix /$(SUBMODULE_VERSION)/.git,$(addprefix libraries/,$(LIBRARIES)))
libraries/sky130_fd_sc_hdll/%/.git: .gitmodules
git submodule update --init $(@D)
libraries-info:
@echo "The following libraries exist:"
@for L in $(LIBRARIES); do \
LD=libraries/$$L/$(SUBMODULE_VERSION); \
echo " * $$L"; \
echo " $$(git submodule status $$LD)"; \
done
@echo $(LIBS_DOT_GIT)
libraries/sky130_fd_sc_hs/%/.git: .gitmodules
git submodule update --init $(@D)
submodules: $(LIBS_DOT_GIT)
libraries/sky130_fd_sc_ms/%/.git: .gitmodules
git submodule update --init $(@D)
define LIB_template
libraries/$(1)/%/.git: .gitmodules
git submodule update --init $$(@D)
endef
libraries/sky130_fd_sc_ls/%/.git: .gitmodules
git submodule update --init $(@D)
$(foreach lib,$(LIBRARIES), $(eval $(call LIB_template,$(lib))))

View File

@ -0,0 +1,263 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
#
# Copyright 2020 The SkyWater PDK Authors.
#
# Use of this source code is governed by the Apache 2.0
# license that can be found in the LICENSE file or at
# https://www.apache.org/licenses/LICENSE-2.0
#
# SPDX-License-Identifier: Apache-2.0
''' VCD waveform to wawedrom script/SVG conversion script.
'''
from __future__ import print_function
import os
import sys
import argparse
import pathlib
import wavedrom
import re
from contextlib import contextmanager
wavedrom_template ="""\
{{ signal: [
{signals}
]}}"""
signal_template = " {{ name: \"{name}\", {fill}wave: '{wave}' }}"
def eprint(*args, **kwargs):
''' Print to stderr '''
print(*args, file=sys.stderr, **kwargs)
@contextmanager
def file_or_stdout(file):
''' Open file or stdout if file is None
'''
if file is None:
yield sys.stdout
else:
with file.open('w') as out_file:
yield out_file
def readVCD (file):
''' Parses VCD file.
Args:
file - path to a VCD file [pathlib.Path]
Returns:
vcd - dictionary containing vcd sections [dict]
'''
eprint()
eprint(file.name)
assert file.is_file(), file
vcd = {}
with file.open('r') as f:
currtag = 'body'
for line in f:
# regular line
if not line.startswith('$'):
vcd[currtag] = vcd.setdefault(currtag, '') + line
continue
# tag, other than end
if not line.startswith('$end'):
currtag = line.partition(' ')[0].lstrip('$').rstrip()
vcd[currtag] = vcd.setdefault(currtag, '') + line.partition(' ')[2].rpartition('$')[0]
# line ends with end tag
if not vcd[currtag].endswith('\n'):
vcd[currtag] += '\n'
if line.split()[-1]=='$end':
currtag = 'body'
vcd[currtag] = ''
if 'var' not in vcd:
raise SyntaxError("No variables recorded in VCD file")
if 'dumpvars' not in vcd:
print ("Warning: intial variable states undefined")
var['dumpvars'] = ''
return vcd
def reduce_clock_sequences (wave) :
''' Remove clock seqnces longer than 2 cycles
not accompanied by other signals changes
Parameters:
wave - dictionary 'signal'->['list of states'] [dict]
'''
for v in wave:
sig = wave[v] # analized signal
other = [wave[i] for i in wave if i!=v] # list of other signals
other = [''.join(s) for s in zip(*other)] # list of concatenated states
other = [len(s.replace('.','')) for s in other] # list of state changes count
sig = [s if o==0 else ' ' for s,o in zip(sig,other)] # keep only when no changes in other
sig = "".join(sig)
cuts = []
for m in re.finditer("(10){2,}",sig):
cuts.append( (m.start()+1, m.end()-1) ) # area to be reduced, leave 1..0
cuts.reverse()
for cut in cuts:
for v,w in wave.items(): # reduce cuts from all signals
wave[v] = w[ :cut[0]] + w[cut[1]: ]
return wave
def parsetowavedrom (file, savetofile = False, reduce_clock = False):
''' Reads and simplifies VCD waveform
Generates wavedrom notation.
Args:
file - path to a VCD file [pathlib.Path]
'''
varsubst = {} # var substitution
reg = [] # list of signals
wire = [] # list of signals (wire class)
wave = {} # waveform
event = [] # event timings
vcd = readVCD (file)
# parse vars
for line in vcd['var'].split('\n'):
line = line.strip().split()
if len(line)<4:
if len(line):
print (f"Warning: malformed var definition {' '.join(line)}")
continue
if line[1]!='1':
print (f"Warning: bus in vars (unsupported) {' '.join(line)}")
if line[0]=='reg':
reg.append(line[3])
varsubst[line[2]] = line[3]
if line[0]=='wire':
wire.append(line[3])
varsubst[line[2]] = line[3]
# set initial states
event.append(0)
#default
for v in reg+wire:
wave[v] = ['x']
#defined
for line in vcd['dumpvars'].split('\n'):
if len(line)>=2:
wave[ varsubst[line[1]] ] = [line[0]]
# parse wave body
for line in vcd['body'].split('\n'):
#timestamp line
if line.startswith('#'):
line = line.strip().lstrip('#')
if not line.isnumeric():
raise SyntaxError("Invalid VCD timestamp")
event.append(int(line))
for v in wave.keys():
wave[v].append('.')
# state change line
else :
if len(line)>=2:
wave [ varsubst[line[1]] ][-1] = line[0]
if reduce_clock:
wave = reduce_clock_sequences(wave)
signals = []
for v in wave.keys():
fill = ' ' * (max( [len(s) for s in wave.keys()] ) - len(v))
wavestr = ''.join(wave[v])
signals.append( signal_template.format( name = v, wave = wavestr, fill = fill ) )
signals = ',\n'.join(signals)
wavedrom = wavedrom_template.format ( signals = signals )
outfile = file.with_suffix(".wdr.json") if savetofile else None
with file_or_stdout(outfile) as f:
f.write(wavedrom)
return wavedrom
def quoted_strings_wavedrom (wdr) :
''' Convert wavedrom script to more restrictive
version of JSON with quoted keywords
Parameters:
wdr - wavedrom script [str]
'''
wdr = wdr.replace(' signal:',' "signal":')
wdr = wdr.replace(' name:',' "name":')
wdr = wdr.replace(' wave:',' "wave":')
wdr = wdr.replace("'",'"')
return wdr
def main():
''' Converts VCD waveform to wavedrom format'''
output_txt = 'output:\n stdout or [vcdname].wdr.json file and/or [vcdname].svg file'
allcellpath = '../../../libraries/*/latest/cells/*/*.vcd'
parser = argparse.ArgumentParser(
description = main.__doc__,
epilog = output_txt,
formatter_class=argparse.RawDescriptionHelpFormatter)
parser.add_argument(
"--all_libs",
help="process all in "+allcellpath,
action="store_true")
parser.add_argument(
"-w",
"--wavedrom",
help="generate wavedrom .wdr.json file",
action="store_true")
parser.add_argument(
"-s",
"--savesvg",
help="generate .svg image",
action="store_true")
parser.add_argument(
"-r",
"--reduceclk",
help="reduce clock sequences",
action="store_true")
parser.add_argument(
"infile",
help="VCD waveform file",
type=pathlib.Path,
nargs="*")
args = parser.parse_args()
if args.all_libs:
path = pathlib.Path(allcellpath).expanduser()
parts = path.parts[1:] if path.is_absolute() else path.parts
paths = pathlib.Path(path.root).glob(str(pathlib.Path("").joinpath(*parts)))
args.infile = list(paths)
infile = [d.resolve() for d in args.infile if d.is_file()]
errors = 0
for f in infile:
try:
wdr = parsetowavedrom(f, args.wavedrom, args.reduceclk)
if args.savesvg:
svg = wavedrom.render( quoted_strings_wavedrom(wdr) )
outfile = f.with_suffix(".svg")
svg.saveas(outfile)
except KeyboardInterrupt:
sys.exit(1)
except (SyntaxError, AssertionError, FileNotFoundError, ChildProcessError) as ex:
eprint (f'{type(ex).__name__}: {", ".join(ex.args)}')
errors +=1
eprint (f'\n{len(infile)} files processed, {errors} errors.')
return 0 if errors else 1
if __name__ == "__main__":
sys.exit(main())

View File

@ -0,0 +1,169 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
#
# Copyright 2020 The SkyWater PDK Authors.
#
# Use of this source code is governed by the Apache 2.0
# license that can be found in the LICENSE file or at
# https://www.apache.org/licenses/LICENSE-2.0
#
# SPDX-License-Identifier: Apache-2.0
''' This is a cell VCD waveform generation script.
'''
import csv
import json
import os
import sys
import argparse
import pathlib
import glob
import subprocess
import textwrap
import re
def write_vcd (cellpath, define_data, use_power_pins=False):
''' Generates vcd for a given cell.
Args:
cellpath - path to a cell [str of pathlib.Path]
define_data - cell data from json [dic]
use_power_pins - include power pins toggling in simulation [bool]
'''
# collect power port names
pp = []
for p in define_data['ports']:
if len(p)>2 and p[0]=='power':
pp.append(p[1])
# define output file(s)
ppsuffix = '.pp' if use_power_pins else ''
outfile = os.path.join(cellpath, define_data['file_prefix'] + ppsuffix + '.vcd')
vppfile = os.path.join(cellpath, define_data['file_prefix'] + '.vpp.tmp')
tmptestbed = os.path.join(cellpath, define_data['file_prefix'] + '.tb.v.tmp')
# find and patch Verilog testbed file
testbedfile = os.path.join(cellpath, define_data['file_prefix'] + '.tb.v')
assert os.path.exists(testbedfile), testbedfile
insertppdefine = use_power_pins
insertdumpvars = True
insertfinish = True
prvline=''
with open(tmptestbed,'w') as ttb:
with open(testbedfile,'r') as tbf:
for line in tbf:
# add use_power_pins define
if insertppdefine and line.startswith('`include'):
line = '`define USE_POWER_PINS\n' + line
insertppdefine = False
# add dumpfile define
if insertdumpvars and prvline.strip(' \n\r')=='begin':
line = line[:-len(line.lstrip())] + \
'$dumpfile("' + outfile + '");\n' + \
line[:-len(line.lstrip())] + \
'$dumpvars(1,top);\n' + \
line
insertdumpvars = False
# add finish command, to stop paraller threads
if insertfinish and line.strip(' \n\r')=='end' and not '$finish' in prvline:
line = prvline[:-len(prvline.lstrip())] + '$finish;\n' + line
insertfinish = False
# remove power pins from reg - optinal, but makes output more readable
if not use_power_pins:
for p in pp:
if re.search( 'reg\s+'+p, line ) is not None or \
re.search( p+'\s+\=', line ) is not None :
line=''
break
# remove power pins from dut
if not use_power_pins and define_data['file_prefix']+' dut' in line:
for p in pp:
line = line.replace(f'.{p}({p}),','')
line = line.replace(f'.{p}({p}))',')')
prvline = line
ttb.write(line)
# generate vpp code and vcd recording
if subprocess.call(['iverilog', '-o', vppfile, tmptestbed], cwd=cellpath):
raise ChildProcessError("Icarus Verilog compilation failed")
if subprocess.call(['vvp', vppfile], cwd=cellpath):
raise ChildProcessError("Icarus Verilog runtime failed")
# remove temporary files
os.remove(tmptestbed)
os.remove(vppfile)
def process(cellpath):
''' Processes cell indicated by path.
Opens cell definiton and calls further processing
Args:
cellpath - path to a cell [str of pathlib.Path]
'''
print()
print(cellpath)
define_json = os.path.join(cellpath, 'definition.json')
if not os.path.exists(define_json):
print("No definition.json in", cellpath)
assert os.path.exists(define_json), define_json
define_data = json.load(open(define_json))
if define_data['type'] == 'cell':
write_vcd(cellpath, define_data, use_power_pins = False)
write_vcd(cellpath, define_data, use_power_pins = True)
return
def main():
''' Generates VCD waveform for cell.'''
prereq_txt = ''
output_txt = 'output:\n generates [fullcellname].vcd'
allcellpath = '../../../libraries/*/latest/cells/*'
parser = argparse.ArgumentParser(
description = main.__doc__,
epilog = prereq_txt +'\n\n'+ output_txt,
formatter_class=argparse.RawDescriptionHelpFormatter)
parser.add_argument(
"--all_libs",
help="process all cells in "+allcellpath,
action="store_true")
parser.add_argument(
"cell_dir",
help="path to the cell directory",
type=pathlib.Path,
nargs="*")
args = parser.parse_args()
if args.all_libs:
path = pathlib.Path(allcellpath).expanduser()
parts = path.parts[1:] if path.is_absolute() else path.parts
paths = pathlib.Path(path.root).glob(str(pathlib.Path("").joinpath(*parts)))
args.cell_dir = list(paths)
cell_dirs = [d.resolve() for d in args.cell_dir if d.is_dir()]
errors = 0
for d in cell_dirs:
try:
process(d)
except KeyboardInterrupt:
sys.exit(1)
except (AssertionError, FileNotFoundError, ChildProcessError) as ex:
print (f'Error: {type(ex).__name__}')
print (f'{ex.args}')
errors +=1
print (f'\n{len(cell_dirs)} files processed, {errors} errors.')
return 0 if errors else 1
if __name__ == "__main__":
sys.exit(main())

View File

@ -31,12 +31,15 @@ from collections import defaultdict
from typing import Tuple, List, Dict
from math import frexp, log2
from . import sizes
from .utils import sortable_extracted_numbers
debug = False
LOG2_10 = log2(10)
class TimingType(enum.IntFlag):
"""
@ -766,6 +769,15 @@ def liberty_float(f):
>>> liberty_float(1)
'1.0000000000'
>>> liberty_float(1e9)
'1000000000.0'
>>> liberty_float(1e10)
'1.000000e+10'
>>> liberty_float(1e15)
'1.000000e+15'
>>> liberty_float(True)
Traceback (most recent call last):
...
@ -792,36 +804,25 @@ def liberty_float(f):
"""
try:
f2 = float(f)
r = float(f)
except (ValueError, TypeError):
f2 = None
r = None
if isinstance(f, bool):
f2 = None
r = None
if f is None or f2 != f:
if f is None or r != f:
raise ValueError("%r is not a float" % f)
WIDTH = len(str(0.0083333333))
width = 11
s = json.dumps(f)
if 'e' in s:
a, b = s.split('e')
if '.' not in a:
a += '.'
while len(a)+len(b)+1 < WIDTH:
a += '0'
s = "%se%s" % (a, b)
elif '.' in s:
while len(s) < WIDTH:
s += '0'
mag = int(frexp(r)[1]/LOG2_10)
if mag > 9:
return f'%{width}e' % r
if mag < 0:
return f"%{width+1}.{width-1}f" % r
else:
if len(s) < WIDTH:
s += '.'
while len(s) < WIDTH:
s += '0'
return s
return f"%{width+1}.{width-mag-1}f" % r
LIBERTY_ATTRIBUTE_TYPES = {
'boolean': liberty_bool,

@ -1 +1 @@
Subproject commit 9b07ad2bb62fbf8af789c9e4669715c974b4912d
Subproject commit 33b80bd32c30fb8affd0fd5cda544d1bca075593