diff --git a/.github/workflows/asic.yaml b/.github/workflows/asic.yaml
new file mode 100644
index 000000000..0206800d4
--- /dev/null
+++ b/.github/workflows/asic.yaml
@@ -0,0 +1,79 @@
+name: "Torii-HDL Tests - ASIC"
+on:
+ push:
+ branches:
+ - '**/**asic**'
+
+jobs:
+ test-torii-asic-openlane:
+ name: Torii OpenLANE Test
+ runs-on: ubuntu-latest
+ env:
+ OPENLANE_IMAGE_NAME: efabless/openlane:latest
+ OPENLANE_ROOT: /home/runner/work/torii-hdl/torii-hdl/openlane
+ PDK_ROOT: /home/runner/work/torii-hdl/torii-hdl/pdk
+ PDK_TAG: 3df14f84ab167baf757134739bb1d2c5c044849c
+ TORII_OPENLANE_ROOT: ${OPENLANE_ROOT}
+ TORII_PDK_ROOT: ${PDK_ROOT}
+
+ steps:
+ - name: Setup Python
+ uses: actions/setup-python@v5
+ with:
+ python-version: 3.11
+
+ - name: Initialize Env
+ shell: bash
+ env:
+ WORKSPACE: ${{ github.workspace }}
+ run: |
+ echo "$HOME/.local/bin:$PATH" >> $GITHUB_PATH
+ echo "GITHUB_WORKSPACE=\"`pwd`\"" >> $GITHUB_ENV
+
+ - name: Checkout
+ uses: actions/checkout@v4
+
+ - name: Setup OSS CAD Suite
+ uses: YosysHQ/setup-oss-cad-suite@v3
+ with:
+ github-token: ${{ secrets.GITHUB_TOKEN }}
+
+ - name: Install magic + klayout
+ run: |
+ sudo apt-get update
+ sudo apt-get install klayout magic
+
+ - name: Setup
+ shell: bash
+ run: |
+ python -m pip install --user --upgrade pip setuptools wheel setuptools_scm nox volare
+
+ - name: Checkout OpenLANE
+ uses: actions/checkout@v3
+ with:
+ repository: 'The-OpenROAD-Project/OpenLane'
+ ref: '2023.06.22'
+ path: 'openlane'
+ fetch-depth: 1
+
+ - name: Setup PDK / OpenLane
+ shell: bash
+ run: |
+ volare enable --pdk sky130 ${PDK_TAG}
+ pushd ${OPENLANE_ROOT}
+ make
+ make test
+ popd
+
+
+ - name: Run ASIC Tests
+ shell: bash
+ run: |
+ nox -s test -- --asic --coverage
+
+ - name: Codecov Upload
+ uses: codecov/codecov-action@v4
+ with:
+ verbose: true
+ files: ./build/tests/coverage.xml
+ token: ${{ secrets.CODECOV_TOKEN }}
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 560ca7f8c..df07f7554 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -22,6 +22,7 @@ Unreleased template stuff
### Added
- Added new `torii.platform.formal.FormalPlatform` for formal verification of Torii designs.
+ - Added `torii.vendor.asic` OpenLANE ASIC flow support
### Changed
@@ -92,20 +93,6 @@ Unreleased template stuff
### Fixed
- - Fixed `ToriiTestCase.settle` to handle "0" count settles.
- - Fixed `torii.hdl.dsl.Module`'s constructor to properly use `super()` rather than a parent class name call.
- - Load of typing annotation fixes.
- - Cleaned up a load of blank `asserts`, they should now have more clear error diagnostics.
- - Fixed a handful of typos throughout the library and documentation.
- - Fixed tracer calls for Python 3.13
- - Fixed `Array` not being indexable by a `ValueCastable`.
- - Fixed `ValueCastable` not being accepted as a simulation coroutine command.
- - Fixed handling of redundant `Case` branches.
- - Fixed `Value.shift_right` and `Value.as_signed` edge cases.
- - Fixed using 0-width `Switch`'s with integer keys.
- - Trying to use the Python `in` operator on a `Value` now raises a sensible error.
- - When indexing or slicing a Value with another Value, it now raises an error and suggests to use `Value.bit_select` or `Value.word_select` instead.
- - Fixed simulation look when process catches an injected exception.
## [0.5.0]
diff --git a/README.md b/README.md
index f06b19b60..d54ec507c 100644
--- a/README.md
+++ b/README.md
@@ -85,6 +85,40 @@ Torii can be used to target any FPGA or ASIC process that accepts behavioral Ver
+> **Warning** ASIC Flow targets are super experimental
+> and unstable at the moment.
+> Please don't use these for production in any capacity.
+
+
+
+
+ ASIC |
+ Toolchain |
+
+
+
+ FOSS |
+ Proprietary |
+
+
+
+
+ sky130 |
+ OpenLANE |
+ |
+
+
+
+ sky90 |
+
+
+
+ gf180mcu |
+
+
+
+
+
## License
Torii is released under the [BSD-2-Clause](https://spdx.org/licenses/BSD-2-Clause.html), the full text of which can be found in the [LICENSE](LICENSE) file.
diff --git a/docs/platforms/asic/index.md b/docs/platforms/asic/index.md
new file mode 100644
index 000000000..962fcae62
--- /dev/null
+++ b/docs/platforms/asic/index.md
@@ -0,0 +1,5 @@
+# Torii ASIC Platforms
+
+```{warning}
+ASIC Support in Torii is not stable, use at your own risk
+```
diff --git a/examples/asic/alu.py b/examples/asic/alu.py
new file mode 100644
index 000000000..a03809067
--- /dev/null
+++ b/examples/asic/alu.py
@@ -0,0 +1,37 @@
+# SPDX-License-Identifier: BSD-2-Clause
+
+from torii import Elaboratable, Module, Signal, Cat
+from torii.platform.asic.sky130 import Sky130BHighDensityPlatform
+
+class ALU(Elaboratable):
+ def __init__(self, width: int):
+ self.sel = Signal(2)
+ self.a = Signal(width)
+ self.b = Signal(width)
+ self.o = Signal(width)
+ self.co = Signal()
+
+ def elaborate(self, platform) -> Module:
+ m = Module()
+ with m.If(self.sel == 0b00):
+ m.d.comb += self.o.eq(self.a | self.b)
+ with m.Elif(self.sel == 0b01):
+ m.d.comb += self.o.eq(self.a & self.b)
+ with m.Elif(self.sel == 0b10):
+ m.d.comb += self.o.eq(self.a ^ self.b)
+ with m.Else():
+ m.d.comb += Cat(self.o, self.co).eq(self.a - self.b)
+ return m
+
+class ExampleFlow(Sky130BHighDensityPlatform):
+ flow_settings = {
+ 'DESIGN_IS_CORE': 0,
+ }
+ connectors = ()
+ resources = ()
+
+if __name__ == '__main__':
+ alu = ALU(width = 16)
+ flow = ExampleFlow()
+
+ flow.build(alu, name = 'alu', ports = [alu.sel, alu.a, alu.b, alu.o, alu.co])
diff --git a/examples/asic/counter.py b/examples/asic/counter.py
new file mode 100644
index 000000000..e1cd98bbd
--- /dev/null
+++ b/examples/asic/counter.py
@@ -0,0 +1,38 @@
+# SPDX-License-Identifier: BSD-2-Clause
+
+from torii import Elaboratable, Signal, Module
+from torii.build import Resource, Clock, Pins
+from torii.platform.asic.sky130 import Sky130BHighDensityPlatform
+
+class Counter(Elaboratable):
+ def __init__(self, width: int):
+ self.v = Signal(width, reset = 2**width-1)
+ self.o = Signal()
+
+ def elaborate(self, platform) -> Module:
+ m = Module()
+ m.d.sync += self.v.eq(self.v + 1)
+ m.d.comb += self.o.eq(self.v[-1])
+ return m
+
+class ExampleFlow(Sky130BHighDensityPlatform):
+ default_clk = 'clk'
+
+ flow_settings = {
+ 'FP_CORE_UTIL': 1,
+ 'DESIGN_IS_CORE': 0,
+ }
+
+ connectors = ()
+ resources = (
+ Resource('clk', 0,
+ Pins('C', dir = 'i'),
+ Clock(1e6)
+ ),
+ )
+
+if __name__ == '__main__':
+ ctr = Counter(width = 16)
+ flow = ExampleFlow()
+
+ flow.build(ctr, name = 'ctr', ports = [ctr.o])
diff --git a/examples/asic/fsm.py b/examples/asic/fsm.py
new file mode 100644
index 000000000..3926cac24
--- /dev/null
+++ b/examples/asic/fsm.py
@@ -0,0 +1,85 @@
+# SPDX-License-Identifier: BSD-2-Clause
+
+from torii import Elaboratable, Module, Signal, Cat
+from torii.build import Resource, Clock, Pins
+from torii.platform.asic.sky130 import Sky130BHighDensityPlatform
+
+
+class UARTReceiver(Elaboratable):
+ def __init__(self, divisor: int):
+ self.divisor = divisor
+
+ self.i = Signal()
+ self.data = Signal(8)
+ self.rdy = Signal()
+ self.ack = Signal()
+ self.err = Signal()
+
+ def elaborate(self, platform) -> Module:
+ m = Module()
+
+ ctr = Signal(range(self.divisor))
+ stb = Signal()
+ with m.If(ctr == 0):
+ m.d.sync += ctr.eq(self.divisor - 1)
+ m.d.comb += stb.eq(1)
+ with m.Else():
+ m.d.sync += ctr.eq(ctr - 1)
+
+ bit = Signal(3)
+ with m.FSM() as fsm:
+ with m.State('START'):
+ with m.If(~self.i):
+ m.next = 'DATA'
+ m.d.sync += [
+ ctr.eq(self.divisor // 2),
+ bit.eq(7),
+ ]
+ with m.State('DATA'):
+ with m.If(stb):
+ m.d.sync += [
+ bit.eq(bit - 1),
+ self.data.eq(Cat(self.i, self.data))
+ ]
+ with m.If(bit == 0):
+ m.next = 'STOP'
+ with m.State('STOP'):
+ with m.If(stb):
+ with m.If(self.i):
+ m.next = 'DONE'
+ with m.Else():
+ m.next = 'ERROR'
+
+ with m.State('DONE'):
+ m.d.comb += self.rdy.eq(1)
+ with m.If(self.ack):
+ m.next = 'START'
+
+ m.d.comb += self.err.eq(fsm.ongoing('ERROR'))
+ with m.State('ERROR'):
+ pass
+
+ return m
+
+
+class ExampleFlow(Sky130BHighDensityPlatform):
+ default_clk = 'clk'
+
+ flow_settings = {
+ 'FP_CORE_UTIL': 50,
+ 'DESIGN_IS_CORE': 0,
+ }
+
+ connectors = ()
+ resources = (
+ Resource('clk', 0,
+ Pins('C', dir = 'i'),
+ Clock(1e6)
+ ),
+ )
+
+if __name__ == '__main__':
+ rx = UARTReceiver(10)
+ flow = ExampleFlow()
+
+ flow.build(rx, name = 'fsm', ports = [rx.i, rx.data, rx.rdy, rx.ack, rx.err])
diff --git a/noxfile.py b/noxfile.py
index 01ba4f19a..2652d9027 100644
--- a/noxfile.py
+++ b/noxfile.py
@@ -44,6 +44,7 @@ def test(session: Session) -> None:
out_dir.mkdir(parents = True, exist_ok = True)
coverage = '--coverage' in session.posargs
formal = '--formal' in session.posargs
+ asic = '--asic' in session.posargs
unitest_args = ('-m', 'unittest', 'discover', '-s', str(ROOT_DIR))
@@ -70,11 +71,18 @@ def test(session: Session) -> None:
session.run(
'python', *coverage_args, example
)
- else:
- session.log('Running standard test suite')
+ elif asic:
+ ASIC_EXAMPLES = ROOT_DIR / 'examples' / 'asic'
+
+ session.log('Running ASIC tests')
session.run(
- 'python', *coverage_args, *unitest_args
+ 'python', *coverage_args, f'{ASIC_EXAMPLES / "alu.py"}'
)
+ else:
+ session.log('Running standard tests')
+ session.run(
+ 'python', *coverage_args, *unitest_args
+ )
if coverage:
session.run(
'python', '-m', 'coverage', 'xml',
diff --git a/torii/platform/asic/__init__.py b/torii/platform/asic/__init__.py
new file mode 100644
index 000000000..3ff4dc2a3
--- /dev/null
+++ b/torii/platform/asic/__init__.py
@@ -0,0 +1,18 @@
+# SPDX-License-Identifier: BSD-3-Clause
+
+from .sky130 import (
+ Sky130BHighDensityPlatform,
+ Sky130BHighSpeedPlatform,
+ Sky130BMediumSpeedPlatform,
+ Sky130BLowSpeedPlatform,
+ Sky130BHighDensityLowLeakagePlatform,
+)
+
+
+__all__ = (
+ 'Sky130BHighDensityPlatform',
+ 'Sky130BHighSpeedPlatform',
+ 'Sky130BMediumSpeedPlatform',
+ 'Sky130BLowSpeedPlatform',
+ 'Sky130BHighDensityLowLeakagePlatform',
+)
diff --git a/torii/platform/asic/efabless_caravel.py b/torii/platform/asic/efabless_caravel.py
new file mode 100644
index 000000000..5d9b11d03
--- /dev/null
+++ b/torii/platform/asic/efabless_caravel.py
@@ -0,0 +1,13 @@
+# SPDX-License-Identifier: BSD-2-Clause
+
+from .openlane import OpenLANEPlatform
+
+
+__all__ = (
+ 'OpenLANEPlatform',
+)
+
+class EfablessCaravel(OpenLANEPlatform):
+
+ def __init__(self) -> None:
+ super().__init__()
diff --git a/torii/platform/asic/gf180mcu.py b/torii/platform/asic/gf180mcu.py
new file mode 100644
index 000000000..73959e760
--- /dev/null
+++ b/torii/platform/asic/gf180mcu.py
@@ -0,0 +1,3 @@
+# SPDX-License-Identifier: BSD-3-Clause
+
+from .openlane import OpenLANEPlatform # noqa: F401
diff --git a/torii/platform/asic/openlane.py b/torii/platform/asic/openlane.py
new file mode 100644
index 000000000..209c0f849
--- /dev/null
+++ b/torii/platform/asic/openlane.py
@@ -0,0 +1,223 @@
+# SPDX-License-Identifier: BSD-2-Clause
+
+from abc import abstractmethod
+from typing import Union, Optional
+from pathlib import Path
+
+from ...build.plat import TemplatedPlatform
+from ...build.run import BuildPlan
+from ...hdl.ir import Fragment
+
+__all__ = (
+ 'OpenLANEPlatform',
+)
+
+class OpenLANEPlatform(TemplatedPlatform):
+ '''
+ .. note::
+
+ See https://github.com/The-OpenROAD-Project/OpenLane#setting-up-openlane for instructions on
+ setting up OpenLANE and the various PDKs.
+
+ .. note::
+
+ See https://openlane.readthedocs.io/en/latest/configuration/README.html#variables-information for
+ more detailed information on the various ``flow_settings`` available.
+
+ Required tools:
+ * ``OpenLANE``
+ * ``docker``
+
+ Build products:
+ * ``config.tcl``: OpenLANE Flow configuration
+ * ``{{name}}.sdc``: Timing and clock constraints
+ * ``{{name}}.v``: Design Verilog
+ * ``{{name}}.debug.v``: Design debug verilog
+ * ``runs/*``: OpenLANE flow output
+
+ '''
+
+ openlane_root : Optional[Path] = None
+ pdk_root : Optional[Path] = None
+ toolchain = 'openlane'
+
+ @property
+ @abstractmethod
+ def pdk(self) -> str:
+ raise NotImplementedError('Platform must implement this property')
+
+ @property
+ @abstractmethod
+ def cell_library(self) -> str:
+ raise NotImplementedError('Platform must implement this property')
+
+ @property
+ @abstractmethod
+ def flow_settings(self) -> dict[str, Union[str, int, float]]:
+ raise NotImplementedError('Platform must implement this property')
+
+ _openlane_required_tools = (
+ 'docker',
+ )
+
+ _openlane_file_templates = {
+ 'build_{{name}}.sh': '''
+ # {{autogenerated}}
+ set -e{{verbose("x")}}
+ [ -n "${{platform._toolchain_env_var}}" ] && . "${{platform._toolchain_env_var}}"
+ {{emit_commands("sh")}}
+ ''',
+ '{{name}}.v': r'''
+ /* {{autogenerated}} */
+ {{emit_verilog()}}
+ ''',
+ '{{name}}.debug.v': r'''
+ /* {{autogenerated}} */
+ {{emit_debug_verilog()}}
+ ''',
+ 'config.tcl': r'''
+ # {{autogenerated}}
+ # Design Information
+ set ::env(DESIGN_NAME) "{{name}}"
+ set ::env(VERILOG_FILES) "/design_{{name}}/{{name}}.v"
+ set ::env(SDC_FILE) "/design_{{name}}/{{name}}.sdc"
+ {% if platform.default_clk %}
+ # Clocking Settings
+ # TODO: We assume the clock is in MHz here,
+ set ::env(CLOCK_PERIOD) {{(platform.default_clk_constraint.period / 1e-9)|round}}
+ set ::env(CLOCK_PORT) "{{platform._default_clk_name}}"
+ set ::env(CLOCK_NET) $::env(CLOCK_PORT)
+ {% else %}
+ # No Clock
+ set ::env(RUN_CTS) 0
+ set ::env(CLOCK_PORT) ""
+ {% endif %}
+ # PDK Settings
+ set ::env(PDK) "{{platform.pdk}}"
+ set ::env(STD_CELL_LIBRARY) "{{platform.cell_library}}"
+ # Design "{{name}}" Specific flow settings
+ {% for e, v in platform.flow_settings.items() %}
+ set ::env({{e}}) {{v}}
+ {% endfor %}
+ # Pull in {{platform.pdk}} settings
+ set pdk_config $::env(DESIGN_DIR)/$::env(PDK)_$::env(STD_CELL_LIBRARY)_config.tcl
+ if { [file exists $pdk_config] == 1 } {
+ source $pdk_config
+ }
+ ''',
+ '{{name}}.sdc': r'''
+ # {{autogenerated}}
+ set_units -time ns
+ {% for net_sig, port_sig, frq in platform.iter_clock_constraints() -%}
+ {% if port_sig is not none -%}
+ create_clock -name {{port_sig.name|tcl_escape}} -period {{frq}} [get_ports {{port_sig.name|tcl_escape}}]
+ {% else -%}
+ create_clock -name {{net_sig.name|tcl_escape}} -period {{frq}} [get_nets {{net_sig.name|hierarchy("/")|tcl_escape}}]
+ {% endif -%}
+ {% endfor %}
+ {{get_override("add_constraints")|default("# (add_constraints placeholder)")}}
+ ''', # noqa: E501
+ 'run_flow_{{name}}.sh': r'''
+ ./flow.tcl {{verbose("-verbose 2")}} \
+ -design /design_{{name}} \
+ -config_file /design_{{name}}/config.tcl {{get_override("flow_opts")|options}}
+ '''
+ }
+
+ _openlane_command_templates = (
+ r'''
+ {{invoke_tool("docker")}}
+ rm "torii-openlane-{{name}}" &> /dev/null || true
+ ''',
+ r'''
+ {{invoke_tool("docker")}}
+ run
+ {% if get_override_flag("openlane_interactive") %}
+ -it
+ {% endif %}
+ {% if not get_override_flag("docker_networked") %}
+ --network none
+ {% endif %}
+ --rm
+ --name "torii-openlane-{{name}}"
+ -v {{get_override("OPENLANE_ROOT")|default(platform.openlane_root)}}:/openLANE_flow
+ -v {{get_override("PDK_ROOT")|default(platform.pdk_root)}}:/PDK
+ -v {{platform._build_dir}}:/design_{{name}}
+ -e PDK_ROOT=/PDK
+ -u $(id -u):$(id -g)
+ efabless/openlane:{{get_override("OPENLANE_TAG")|default("latest")}}
+ sh /design_{{name}}/run_flow_{{name}}.sh
+ ''',
+ )
+
+ _build_dir : Optional[Path] = None
+
+ def __init__(
+ self, *,
+ PDK_root: Optional[Union[str, Path]] = None, OpenLANE_root: Optional[Union[str, Path]] = None
+ ) -> None:
+ '''
+
+ Parameters
+ ----------
+ PDK_root: Optional[Union[str, Path]]
+ The path to the root where the PDK is located
+ ( default: /opt/PDK )
+
+ OpenLANE_root: Optional[Union[str, Path]]
+ The path to the local install of OpenLANE
+ ( default: /opt/OpenLANE )
+
+ '''
+
+ super().__init__()
+
+ if PDK_root is not None:
+ self.pdk_root = PDK_root
+ else:
+ self.pdk_root = '/opt/PDK'
+
+ if OpenLANE_root is not None:
+ self.openlane_root = OpenLANE_root
+ else:
+ self.openlane_root = '/opt/OpenLANE'
+
+
+ @property
+ def required_tools(self) -> tuple[str]:
+ return self._openlane_required_tools
+
+ @property
+ def file_templates(self) -> dict[str, str]:
+ return self._openlane_file_templates
+
+ @property
+ def command_templates(self) -> list[str]:
+ return self._openlane_command_templates
+
+ @property
+ def _default_clk_name(self) -> str:
+ if self.default_clk is None:
+ raise AttributeError(f'Platform \'{type(self).__name__}\' does not define a default clock')
+
+ res = self.lookup(self.default_clk)
+
+ for resource, pin, _, _ in self._ports:
+ if resource == res:
+ return pin.i.name if res.ios[0].dir == 'i' else pin.o.name
+
+
+ raise ValueError(f'Platform \'{type(self).__name__}\' defined a default clock but has no matching resource')
+
+ def build(self, *args, **kwargs):
+ self._build_dir = Path(kwargs.get('build_dir', 'build')).resolve()
+ return super().build(*args, **kwargs)
+
+ def toolchain_prepare(self, fragment: Fragment, name: str, **kwargs) -> BuildPlan:
+
+ # Propagate module ports for io placement
+ a_ports = kwargs.get('ports', None)
+ if a_ports is not None:
+ fragment._propagate_ports(ports = a_ports, all_undef_as_ports = False)
+
+ return super().toolchain_prepare(fragment, name, **kwargs)
diff --git a/torii/platform/asic/sky130.py b/torii/platform/asic/sky130.py
new file mode 100644
index 000000000..be0fee9e3
--- /dev/null
+++ b/torii/platform/asic/sky130.py
@@ -0,0 +1,220 @@
+# SPDX-License-Identifier: BSD-3-Clause
+
+from .openlane import OpenLANEPlatform
+
+__all__ = (
+ 'SKY130_PLATFORMS',
+
+ 'SKY130A_PLATFORMS',
+ 'Sky130APlatform',
+ 'Sky130AHighDensityPlatform',
+ 'Sky130AHighSpeedPlatform',
+ 'Sky130AMediumSpeedPlatform',
+ 'Sky130ALowSpeedPlatform',
+ 'Sky130AHighDensityLowLeakagePlatform',
+
+ 'SKY130B_PLATFORMS',
+ 'Sky130BPlatform',
+ 'Sky130BHighDensityPlatform',
+ 'Sky130BHighSpeedPlatform',
+ 'Sky130BMediumSpeedPlatform',
+ 'Sky130BLowSpeedPlatform',
+ 'Sky130BHighDensityLowLeakagePlatform',
+
+)
+
+# PDK Key:
+# * FD - Foundry
+# * SC - Standard Cell
+# * HD - High Density
+# * HDLL - High Density Low Leakage
+# * LS/MS/HS - Low/Medium/High Speed
+
+class Sky130APlatform(OpenLANEPlatform):
+ '''OpenLANE - Sky130A PDK Platform
+
+ .. warning::
+
+ **DO NOT** use any of the sky130A platforms unless you absolutely are sure
+ you know what you're doing, use the sky130B platforms instead!
+
+ This is the base platform the specifies the the sky130A PDK.
+
+ Don't use this platform directly unless you plan to override behavior, use one
+ of the specialized platforms instead:
+
+ * :py:class:`Sky130AHighDensityPlatform`
+ * :py:class:`Sky130AHighSpeedPlatform`
+ * :py:class:`Sky130AMediumSpeedPlatform`
+ * :py:class:`Sky130ALowSpeedPlatform`
+ * :py:class:`Sky130AHighDensityLowLeakagePlatform`
+
+ ''' # noqa: E101
+
+ pdk = 'sky130A'
+
+class Sky130AHighDensityPlatform(Sky130APlatform):
+ '''OpenLANE - Sky130A High Density
+
+ .. warning::
+
+ **DO NOT** use any of the sky130A platforms unless you absolutely are sure
+ you know what you're doing, use the sky130B platforms instead!
+
+ This platform is a specialization of the :py:class:`Sky130APlatform` that sets
+ the cell library to ``sky130_fd_sc_hd`` for the high-density standard cells.
+
+ '''
+ cell_library = 'sky130_fd_sc_hd'
+
+class Sky130AHighSpeedPlatform(Sky130APlatform):
+ '''OpenLANE - Sky130A High Speed
+
+ .. warning::
+
+ **DO NOT** use any of the sky130A platforms unless you absolutely are sure
+ you know what you're doing, use the sky130B platforms instead!
+
+ This platform is a specialization of the :py:class:`Sky130APlatform` that sets
+ the cell library to ``sky130_fd_sc_hs`` for the high speed standard cells.
+
+ '''
+
+ cell_library = 'sky130_fd_sc_hs'
+
+class Sky130AMediumSpeedPlatform(Sky130APlatform):
+ '''OpenLANE - Sky130A Medium Speed
+
+ .. warning::
+
+ **DO NOT** use any of the sky130A platforms unless you absolutely are sure
+ you know what you're doing, use the sky130B platforms instead!
+
+ This platform is a specialization of the :py:class:`Sky130APlatform` that sets
+ the cell library to ``sky130_fd_sc_ms`` for the medium speed standard cells.
+
+ '''
+
+ cell_library = 'sky130_fd_sc_ms'
+
+class Sky130ALowSpeedPlatform(Sky130APlatform):
+ '''OpenLANE - Sky130A Low Speed
+
+ .. warning::
+
+ **DO NOT** use any of the sky130A platforms unless you absolutely are sure
+ you know what you're doing, use the sky130B platforms instead!
+
+ This platform is a specialization of the :py:class:`Sky130APlatform` that sets
+ the cell library to ``sky130_fd_sc_ls`` for the low speed standard cells.
+
+ '''
+
+ cell_library = 'sky130_fd_sc_ls'
+
+class Sky130AHighDensityLowLeakagePlatform(Sky130APlatform):
+ '''OpenLANE - Sky130A High Density Low Leakage
+
+ .. warning::
+
+ **DO NOT** use any of the sky130A platforms unless you absolutely are sure
+ you know what you're doing, use the sky130B platforms instead!
+
+ This platform is a specialization of the :py:class:`Sky130APlatform` that sets
+ the cell library to ``sky130_fd_sc_hdll`` for the high-density low-leakage standard cells.
+
+ '''
+
+ cell_library = 'sky130_fd_sc_hdll'
+
+class Sky130BPlatform(OpenLANEPlatform):
+ '''OpenLANE - Sky130B PDK Platform
+
+ This is the base platform the specifies the the sky130A PDK.
+
+ Don't use this platform directly unless you plan to override behavior, use one
+ of the specialized platforms instead:
+
+ * :py:class:`Sky130BHighDensityPlatform`
+ * :py:class:`Sky130BHighSpeedPlatform`
+ * :py:class:`Sky130BMediumSpeedPlatform`
+ * :py:class:`Sky130BLowSpeedPlatform`
+ * :py:class:`Sky130BHighDensityLowLeakagePlatform`
+
+ ''' # noqa: E101
+
+ pdk = 'sky130B'
+
+class Sky130BHighDensityPlatform(Sky130BPlatform):
+ '''OpenLANE - Sky130B High Density
+
+ This platform is a specialization of the :py:class:`Sky130BPlatform` that sets
+ the cell library to ``sky130_fd_sc_hd`` for the high-density standard cells.
+
+ '''
+
+ cell_library = 'sky130_fd_sc_hd'
+
+class Sky130BHighSpeedPlatform(Sky130BPlatform):
+ '''OpenLANE - Sky130B High Speed
+
+
+ This platform is a specialization of the :py:class:`Sky130BPlatform` that sets
+ the cell library to ``sky130_fd_sc_hs`` for the high speed standard cells.
+
+ '''
+
+ cell_library = 'sky130_fd_sc_hs'
+
+class Sky130BMediumSpeedPlatform(Sky130BPlatform):
+ '''OpenLANE - Sky130B Medium Speed
+
+
+ This platform is a specialization of the :py:class:`Sky130BPlatform` that sets
+ the cell library to ``sky130_fd_sc_ms`` for the medium speed standard cells.
+
+ '''
+
+ cell_library = 'sky130_fd_sc_ms'
+
+class Sky130BLowSpeedPlatform(Sky130BPlatform):
+ '''OpenLANE - Sky130B Low Speed
+
+
+ This platform is a specialization of the :py:class:`Sky130BPlatform` that sets
+ the cell library to ``sky130_fd_sc_ls`` for the low speed standard cells.
+
+ '''
+
+ cell_library = 'sky130_fd_sc_ls'
+
+class Sky130BHighDensityLowLeakagePlatform(Sky130BPlatform):
+ '''OpenLANE - Sky130B High Density Low Leakage
+
+ This platform is a specialization of the :py:class:`Sky130BPlatform` that sets
+ the cell library to ``sky130_fd_sc_hdll`` for the high-density low-leakage standard cells.
+
+ '''
+
+ cell_library = 'sky130_fd_sc_hdll'
+
+SKY130A_PLATFORMS = {
+ 'sky130_fd_sc_hd' : Sky130AHighDensityPlatform,
+ 'sky130_fd_sc_hs' : Sky130AHighSpeedPlatform,
+ 'sky130_fd_sc_ms' : Sky130AMediumSpeedPlatform,
+ 'sky130_fd_sc_ls' : Sky130ALowSpeedPlatform,
+ 'sky130_fd_sc_hdll': Sky130AHighDensityLowLeakagePlatform,
+}
+
+SKY130B_PLATFORMS = {
+ 'sky130_fd_sc_hd' : Sky130BHighDensityPlatform,
+ 'sky130_fd_sc_hs' : Sky130BHighSpeedPlatform,
+ 'sky130_fd_sc_ms' : Sky130BMediumSpeedPlatform,
+ 'sky130_fd_sc_ls' : Sky130BLowSpeedPlatform,
+ 'sky130_fd_sc_hdll': Sky130BHighDensityLowLeakagePlatform,
+}
+
+SKY130_PLATFORMS = {
+ 'sky130A': SKY130A_PLATFORMS,
+ 'sky130B': SKY130B_PLATFORMS,
+}
diff --git a/torii/platform/asic/sky90.py b/torii/platform/asic/sky90.py
new file mode 100644
index 000000000..6464f4800
--- /dev/null
+++ b/torii/platform/asic/sky90.py
@@ -0,0 +1,3 @@
+# SPDX-License-Identifier: BSD-3-Clause
+
+from .openlane import OpenLANEPlatform # noqa: F401