diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 27d2476f7..b2f932ee5 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,45 +1,47 @@ { - "bins/cdl2spice": "0.2.2", - "bins/spicemerge": "0.1.0", - "bins/sky130spconv": "0.1.0", - "codegen": "0.10.2", - "config": "0.4.1", + "bins/cdl2spice": "0.2.3", + "bins/spicemerge": "0.1.1", + "bins/sky130spconv": "0.1.1", + "codegen": "0.10.3", + "config": "0.4.2", "docs/snippets": "0.7.0", - "examples": "0.2.0", + "examples": "0.2.1", "examples/latest/sky130_inverter": "0.0.0", "examples/latest/spice_vdivider": "0.0.0", "examples/latest/colbuf": "0.0.0", "examples/latest/vdivider": "0.0.0", "examples/latest/via": "0.0.0", "examples/latest/substrate_api_examples": "0.0.0", - "libs/atoll": "0.1.3", - "libs/cache": "0.7.1", + "libs/atoll": "0.1.4", + "libs/cache": "0.7.2", "libs/diagnostics": "0.4.0", - "libs/enumify": "0.2.1", - "libs/enumify_macros": "0.3.1", - "libs/gds": "0.4.1", - "libs/gdsconv": "0.2.1", - "libs/geometry": "0.7.1", + "libs/enumify": "0.2.2", + "libs/enumify_macros": "0.3.2", + "libs/gds": "0.4.2", + "libs/gdsconv": "0.2.2", + "libs/geometry": "0.7.2", "libs/geometry_macros": "0.1.1", "libs/pathtree": "0.3.0", - "libs/psfparser": "0.1.4", - "libs/scir": "0.9.1", - "libs/spice": "0.9.2", - "libs/layir": "0.2.1", - "libs/lefdef": "0.2.1", + "libs/psfparser": "0.1.5", + "libs/scir": "0.9.2", + "libs/spice": "0.9.3", + "libs/layir": "0.2.2", + "libs/lefdef": "0.2.2", "libs/macrotools": "0.2.0", - "libs/nutlex": "0.4.2", + "libs/nutlex": "0.4.3", "libs/type_dispatch": "0.5.1", "libs/type_dispatch_macros": "0.4.1", - "libs/uniquify": "0.4.0", - "libs/verilog": "0.2.1", - "pdks/sky130": "0.10.2", - "substrate": "0.10.2", - "tools/magic": "0.2.1", + "libs/uniquify": "0.4.1", + "libs/verilog": "0.2.2", + "pdks/sky130": "0.10.3", + "substrate": "0.10.3", + "tools/magic": "0.2.2", "tools/netgen": "0.2.1", - "tools/ngspice": "0.5.2", + "tools/ngspice": "0.5.3", "tools/pegasus": "0.2.1", - "tools/quantus": "0.2.2", - "tools/spectre": "0.11.2", - "tools/magic_netgen": "0.1.3" + "tools/quantus": "0.2.3", + "tools/spectre": "0.11.3", + "tools/magic_netgen": "0.1.4", + "examples/latest/resistor_bank": "0.1.1", + "examples/latest/strongarm": "0.0.0" } diff --git a/Cargo.lock b/Cargo.lock index aea4b6569..145a6fa50 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -184,7 +184,7 @@ dependencies = [ [[package]] name = "atoll" -version = "0.1.3" +version = "0.1.4" dependencies = [ "arcstr", "cache", @@ -402,7 +402,7 @@ checksum = "d71b6127be86fdcfddb610f7182ac57211d4b18a3e9c82eb2d17662f2227ad6a" [[package]] name = "cache" -version = "0.7.1" +version = "0.7.2" dependencies = [ "anyhow", "backoff", @@ -446,7 +446,7 @@ dependencies = [ [[package]] name = "cdl2spice" -version = "0.2.2" +version = "0.2.3" dependencies = [ "anyhow", "arcstr", @@ -546,7 +546,7 @@ checksum = "f46ad14479a25103f283c0f10005961cf086d8dc42205bb44c46ac563475dca6" [[package]] name = "codegen" -version = "0.10.2" +version = "0.10.3" dependencies = [ "arcstr", "convert_case 0.8.0", @@ -587,7 +587,7 @@ checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990" [[package]] name = "config" -version = "0.4.1" +version = "0.4.2" dependencies = [ "anyhow", "cache", @@ -845,14 +845,14 @@ dependencies = [ [[package]] name = "enumify" -version = "0.2.1" +version = "0.2.2" dependencies = [ "enumify_macros", ] [[package]] name = "enumify_macros" -version = "0.3.1" +version = "0.3.2" dependencies = [ "convert_case 0.8.0", "darling", @@ -902,7 +902,7 @@ dependencies = [ [[package]] name = "examples" -version = "0.2.0" +version = "0.2.1" [[package]] name = "fallible-iterator" @@ -1024,7 +1024,7 @@ dependencies = [ [[package]] name = "gds" -version = "0.4.1" +version = "0.4.2" dependencies = [ "arcstr", "byteorder", @@ -1044,7 +1044,7 @@ dependencies = [ [[package]] name = "gdsconv" -version = "0.2.1" +version = "0.2.2" dependencies = [ "arcstr", "gds", @@ -1068,7 +1068,7 @@ dependencies = [ [[package]] name = "geometry" -version = "0.7.1" +version = "0.7.2" dependencies = [ "array_map", "geometry_macros", @@ -1442,7 +1442,7 @@ dependencies = [ [[package]] name = "layir" -version = "0.2.1" +version = "0.2.2" dependencies = [ "aph_disjoint_set", "arcstr", @@ -1469,7 +1469,7 @@ checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" [[package]] name = "lefdef" -version = "0.2.1" +version = "0.2.2" dependencies = [ "geometry", ] @@ -1527,7 +1527,7 @@ dependencies = [ [[package]] name = "magic" -version = "0.2.1" +version = "0.2.2" dependencies = [ "anyhow", "itertools", @@ -1540,7 +1540,7 @@ dependencies = [ [[package]] name = "magic_netgen" -version = "0.1.3" +version = "0.1.4" dependencies = [ "magic", "netgen", @@ -1616,7 +1616,7 @@ dependencies = [ [[package]] name = "ngspice" -version = "0.5.2" +version = "0.5.3" dependencies = [ "approx", "arcstr", @@ -1765,7 +1765,7 @@ dependencies = [ [[package]] name = "nutlex" -version = "0.4.2" +version = "0.4.3" dependencies = [ "approx", "enumify", @@ -2132,7 +2132,7 @@ dependencies = [ [[package]] name = "psfparser" -version = "0.1.4" +version = "0.1.5" dependencies = [ "anyhow", "approx", @@ -2165,7 +2165,7 @@ dependencies = [ [[package]] name = "quantus" -version = "0.2.2" +version = "0.2.3" dependencies = [ "anyhow", "lazy_static", @@ -2285,7 +2285,7 @@ dependencies = [ [[package]] name = "resistor_bank" -version = "0.1.0" +version = "0.1.1" dependencies = [ "approx", "arcstr", @@ -2438,7 +2438,7 @@ dependencies = [ [[package]] name = "scir" -version = "0.9.1" +version = "0.9.2" dependencies = [ "arcstr", "diagnostics", @@ -2568,7 +2568,7 @@ checksum = "56199f7ddabf13fe5074ce809e7d3f42b42ae711800501b5b16ea82ad029c39d" [[package]] name = "sky130" -version = "0.10.2" +version = "0.10.3" dependencies = [ "approx", "arcstr", @@ -2622,7 +2622,7 @@ dependencies = [ [[package]] name = "sky130spconv" -version = "0.1.0" +version = "0.1.1" dependencies = [ "anyhow", "arcstr", @@ -2693,7 +2693,7 @@ dependencies = [ [[package]] name = "spectre" -version = "0.11.2" +version = "0.11.3" dependencies = [ "approx", "arcstr", @@ -2717,7 +2717,7 @@ dependencies = [ [[package]] name = "spice" -version = "0.9.2" +version = "0.9.3" dependencies = [ "arcstr", "ena", @@ -2748,7 +2748,7 @@ dependencies = [ [[package]] name = "spicemerge" -version = "0.1.0" +version = "0.1.1" dependencies = [ "anyhow", "arcstr", @@ -2797,7 +2797,7 @@ checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" [[package]] name = "substrate" -version = "0.10.2" +version = "0.10.3" dependencies = [ "anyhow", "approx", @@ -3362,7 +3362,7 @@ checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" [[package]] name = "uniquify" -version = "0.4.0" +version = "0.4.1" dependencies = [ "arcstr", "serde", @@ -3413,7 +3413,7 @@ dependencies = [ [[package]] name = "verilog" -version = "0.2.1" +version = "0.2.2" dependencies = [ "scir", ] diff --git a/bins/cdl2spice/CHANGELOG.md b/bins/cdl2spice/CHANGELOG.md index 95270f36c..e99943d2d 100644 --- a/bins/cdl2spice/CHANGELOG.md +++ b/bins/cdl2spice/CHANGELOG.md @@ -4,6 +4,11 @@ * dependencies * spice bumped from 0.9.1 to 0.9.2 +* The following workspace dependencies were updated + * dependencies + * scir bumped from 0.9.1 to 0.9.2 + * spice bumped from 0.9.2 to 0.9.3 + ## [0.2.1](https://github.com/ucb-substrate/substrate2/compare/cdl2spice-v0.2.0...cdl2spice-v0.2.1) (2025-01-24) diff --git a/bins/cdl2spice/Cargo.toml b/bins/cdl2spice/Cargo.toml index d62632f64..d24c2716d 100644 --- a/bins/cdl2spice/Cargo.toml +++ b/bins/cdl2spice/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "cdl2spice" -version = "0.2.2" +version = "0.2.3" edition = "2021" [dependencies] @@ -8,5 +8,5 @@ anyhow = "1" clap = { version = "4", features = ["derive"] } arcstr = "1" -scir = { version = "0.9.1", registry = "substrate", path = "../../libs/scir" } -spice = { version = "0.9.2", registry = "substrate", path = "../../libs/spice" } +scir = { version = "0.9.2", registry = "substrate", path = "../../libs/scir" } +spice = { version = "0.9.3", registry = "substrate", path = "../../libs/spice" } diff --git a/bins/sky130spconv/CHANGELOG.md b/bins/sky130spconv/CHANGELOG.md index 1de82b1b0..8e24e0580 100644 --- a/bins/sky130spconv/CHANGELOG.md +++ b/bins/sky130spconv/CHANGELOG.md @@ -1,5 +1,11 @@ # Changelog +* The following workspace dependencies were updated + * dependencies + * scir bumped from 0.9.1 to 0.9.2 + * spice bumped from 0.9.2 to 0.9.3 + * sky130 bumped from 0.10.2 to 0.10.3 + ## 0.1.0 (2025-02-02) diff --git a/bins/sky130spconv/Cargo.toml b/bins/sky130spconv/Cargo.toml index ee136c5ce..2e5960bca 100644 --- a/bins/sky130spconv/Cargo.toml +++ b/bins/sky130spconv/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "sky130spconv" -version = "0.1.0" +version = "0.1.1" edition = "2021" readme = "README.md" @@ -9,7 +9,7 @@ anyhow = "1" clap = { version = "4", features = ["derive"] } arcstr = "1" -scir = { version = "0.9.1", registry = "substrate", path = "../../libs/scir" } -spice = { version = "0.9.2", registry = "substrate", path = "../../libs/spice" } -sky130 = { version = "0.10.2", registry = "substrate", path = "../../pdks/sky130" } +scir = { version = "0.9.2", registry = "substrate", path = "../../libs/scir" } +spice = { version = "0.9.3", registry = "substrate", path = "../../libs/spice" } +sky130 = { version = "0.10.3", registry = "substrate", path = "../../pdks/sky130" } thiserror = "2" diff --git a/bins/spicemerge/CHANGELOG.md b/bins/spicemerge/CHANGELOG.md index 31ef9b696..07e872726 100644 --- a/bins/spicemerge/CHANGELOG.md +++ b/bins/spicemerge/CHANGELOG.md @@ -1,5 +1,10 @@ # Changelog +* The following workspace dependencies were updated + * dependencies + * scir bumped from 0.9.1 to 0.9.2 + * spice bumped from 0.9.2 to 0.9.3 + ## 0.1.0 (2025-02-02) diff --git a/bins/spicemerge/Cargo.toml b/bins/spicemerge/Cargo.toml index 5de987efa..3a8150be6 100644 --- a/bins/spicemerge/Cargo.toml +++ b/bins/spicemerge/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "spicemerge" -version = "0.1.0" +version = "0.1.1" edition = "2021" [dependencies] @@ -8,5 +8,5 @@ anyhow = "1" clap = { version = "4", features = ["derive"] } arcstr = "1" -scir = { version = "0.9.1", registry = "substrate", path = "../../libs/scir" } -spice = { version = "0.9.2", registry = "substrate", path = "../../libs/spice" } +scir = { version = "0.9.2", registry = "substrate", path = "../../libs/scir" } +spice = { version = "0.9.3", registry = "substrate", path = "../../libs/spice" } diff --git a/codegen/CHANGELOG.md b/codegen/CHANGELOG.md index 6a7e1f0cc..f2b24a285 100644 --- a/codegen/CHANGELOG.md +++ b/codegen/CHANGELOG.md @@ -24,6 +24,24 @@ * spectre bumped from <=0.9.0 to <=0.9.1 * spice bumped from <=0.7.0 to <=0.7.1 +## [0.10.3](https://github.com/ucb-substrate/substrate2/compare/codegen-v0.10.2...codegen-v0.10.3) (2025-06-20) + + +### Bug Fixes + +* **deps:** update deps to latest versions ([#617](https://github.com/ucb-substrate/substrate2/issues/617)) ([ce3d243](https://github.com/ucb-substrate/substrate2/commit/ce3d243cbc10d64086939e44963e3cef591d6bda)) +* **schematic:** support accessing nested PEX data even upon additional nesting ([#621](https://github.com/ucb-substrate/substrate2/issues/621)) ([c1a28c3](https://github.com/ucb-substrate/substrate2/commit/c1a28c3dd9c8261218e29d3295f79b55f5eec277)) + + +### Dependencies + +* The following workspace dependencies were updated + * dev-dependencies + * substrate bumped from <=0.10.2 to <=0.10.3 + * scir bumped from <=0.9.1 to <=0.9.2 + * build-dependencies + * examples bumped from 0.2.0 to 0.2.1 + ## [0.10.2](https://github.com/ucb-substrate/substrate2/compare/codegen-v0.10.1...codegen-v0.10.2) (2025-02-02) diff --git a/codegen/Cargo.toml b/codegen/Cargo.toml index 91ce69689..5347dd58a 100644 --- a/codegen/Cargo.toml +++ b/codegen/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "codegen" -version = "0.10.2" +version = "0.10.3" edition = "2021" [dependencies] @@ -15,15 +15,15 @@ snippets = { version = "0.7.0", registry = "substrate", path = "../docs/snippets macrotools = { version = "0.2.0", registry = "substrate", path = "../libs/macrotools" } [dev-dependencies] -substrate = { version = "<=0.10.2", registry = "substrate", path = "../substrate" } -scir = { version = "<=0.9.1", registry = "substrate", path = "../libs/scir" } +substrate = { version = "<=0.10.3", registry = "substrate", path = "../substrate" } +scir = { version = "<=0.9.2", registry = "substrate", path = "../libs/scir" } arcstr = "1" rust_decimal = "1" rust_decimal_macros = "1" [build-dependencies] snippets = { version = "0.7.0", registry = "substrate", path = "../docs/snippets" } -examples = { version = "0.2.0", registry = "substrate", path = "../examples" } +examples = { version = "0.2.1", registry = "substrate", path = "../examples" } [lib] proc-macro = true diff --git a/config/CHANGELOG.md b/config/CHANGELOG.md index 0450c1e93..b2bad8fcd 100644 --- a/config/CHANGELOG.md +++ b/config/CHANGELOG.md @@ -16,6 +16,10 @@ * dependencies * cache bumped from 0.4.0 to 0.5.0 +* The following workspace dependencies were updated + * dependencies + * cache bumped from 0.7.1 to 0.7.2 + ## [0.4.1](https://github.com/ucb-substrate/substrate2/compare/config-v0.4.0...config-v0.4.1) (2025-01-24) diff --git a/config/Cargo.toml b/config/Cargo.toml index d07b9d248..641ab371c 100644 --- a/config/Cargo.toml +++ b/config/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "config" -version = "0.4.1" +version = "0.4.2" edition = "2021" [dependencies] @@ -11,7 +11,7 @@ toml_edit = "0.22" log = "0.4" toml = "0.8" -cache = { version = "0.7.1", registry = "substrate", path = "../libs/cache" } +cache = { version = "0.7.2", registry = "substrate", path = "../libs/cache" } [target.'cfg(windows)'.dependencies.windows-sys] version = "0.59" diff --git a/examples/CHANGELOG.md b/examples/CHANGELOG.md index 9d848dcaf..197b8b94c 100644 --- a/examples/CHANGELOG.md +++ b/examples/CHANGELOG.md @@ -1,5 +1,22 @@ # Changelog +## [0.2.1](https://github.com/ucb-substrate/substrate2/compare/examples-v0.2.0...examples-v0.2.1) (2025-06-20) + + +### Features + +* **atoll:** port ATOLL to Substrate 2.1 ([#639](https://github.com/ucb-substrate/substrate2/issues/639)) ([dc2d4f2](https://github.com/ucb-substrate/substrate2/commit/dc2d4f2340e1dac822beb499b6d3dbec27002ec5)) +* **atoll:** tile resizing ([#655](https://github.com/ucb-substrate/substrate2/issues/655)) ([b9b65f0](https://github.com/ucb-substrate/substrate2/commit/b9b65f0f065f11f4ceb7499f7bf7f0f088c67480)) +* **examples:** ATOLL segment folder and sky130 examples ([#648](https://github.com/ucb-substrate/substrate2/issues/648)) ([cc809ae](https://github.com/ucb-substrate/substrate2/commit/cc809ae10e1b25f224f503e5a125a38e3e202be4)) +* **strongarm:** additional strongarm parametrizations ([#663](https://github.com/ucb-substrate/substrate2/issues/663)) ([0773b4f](https://github.com/ucb-substrate/substrate2/commit/0773b4f8dd55afd1b46cb481178194822e5cfe2d)) +* **strongarm:** specify tap direction to allow PDKs to set span in other direction ([#661](https://github.com/ucb-substrate/substrate2/issues/661)) ([6917044](https://github.com/ucb-substrate/substrate2/commit/69170440e54f5848c3097b3eaee235bf440c5ce6)) + + +### Bug Fixes + +* **examples:** fix release example compilation ([#576](https://github.com/ucb-substrate/substrate2/issues/576)) ([1e3d89f](https://github.com/ucb-substrate/substrate2/commit/1e3d89f3dd8c152640ec0408fefc9e32e4d7ddba)) +* **justfile:** remove extra targets from justfile, fix formatting ([#588](https://github.com/ucb-substrate/substrate2/issues/588)) ([efc3591](https://github.com/ucb-substrate/substrate2/commit/efc35916dcfc4fe04ef59cffe9155f5069916d07)) + ## [0.2.0](https://github.com/ucb-substrate/substrate2/compare/examples-v0.1.0...examples-v0.2.0) (2025-01-23) diff --git a/examples/Cargo.toml b/examples/Cargo.toml index c6190c2f2..7d638840d 100644 --- a/examples/Cargo.toml +++ b/examples/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "examples" -version = "0.2.0" +version = "0.2.1" edition = "2021" include = [ "**/*.rs", diff --git a/examples/latest/colbuf/Cargo.toml b/examples/latest/colbuf/Cargo.toml index 55cceea73..cb62ec0d7 100644 --- a/examples/latest/colbuf/Cargo.toml +++ b/examples/latest/colbuf/Cargo.toml @@ -5,12 +5,12 @@ edition = "2021" publish = false [dependencies] -substrate = { version = "0.10.2", registry = "substrate", path = "../../../substrate" } -spice = { version = "0.9.2", registry = "substrate", path = "../../../libs/spice" } -spectre = { version = "0.11.2", registry = "substrate", path = "../../../tools/spectre" } -ngspice = { version = "0.5.2", registry = "substrate", path = "../../../tools/ngspice" } -quantus = { version = "0.2.2", registry = "substrate", path = "../../../tools/quantus" } -magic_netgen = { version = "0.1.3", registry = "substrate", path = "../../../tools/magic_netgen" } +substrate = { version = "0.10.3", registry = "substrate", path = "../../../substrate" } +spice = { version = "0.9.3", registry = "substrate", path = "../../../libs/spice" } +spectre = { version = "0.11.3", registry = "substrate", path = "../../../tools/spectre" } +ngspice = { version = "0.5.3", registry = "substrate", path = "../../../tools/ngspice" } +quantus = { version = "0.2.3", registry = "substrate", path = "../../../tools/quantus" } +magic_netgen = { version = "0.1.4", registry = "substrate", path = "../../../tools/magic_netgen" } rust_decimal = "1.37.1" rust_decimal_macros = "1.37.1" diff --git a/examples/latest/resistor_bank/Cargo.toml b/examples/latest/resistor_bank/Cargo.toml index 1459f8a61..4818a8588 100644 --- a/examples/latest/resistor_bank/Cargo.toml +++ b/examples/latest/resistor_bank/Cargo.toml @@ -1,17 +1,17 @@ [package] name = "resistor_bank" -version = "0.1.0" +version = "0.1.1" edition = "2024" [dependencies] -atoll = { version = "0.1.3", registry = "substrate", path = "../../../libs/atoll" } -substrate = { version = "0.10.2", registry = "substrate", path = "../../../substrate" } -sky130 = { version = "0.10.2", registry = "substrate", path = "../../../pdks/sky130" } -layir = { version = "0.2.1", registry = "substrate", path = "../../../libs/layir" } -gdsconv = { version = "0.2.1", registry = "substrate", path = "../../../libs/gdsconv" } -gds = { version = "0.4.1", registry = "substrate", path = "../../../libs/gds" } -scir = { version = "0.9.1", registry = "substrate", path = "../../../libs/scir" } -spice = { version = "0.9.2", registry = "substrate", path = "../../../libs/spice" } +atoll = { version = "0.1.4", registry = "substrate", path = "../../../libs/atoll" } +substrate = { version = "0.10.3", registry = "substrate", path = "../../../substrate" } +sky130 = { version = "0.10.3", registry = "substrate", path = "../../../pdks/sky130" } +layir = { version = "0.2.2", registry = "substrate", path = "../../../libs/layir" } +gdsconv = { version = "0.2.2", registry = "substrate", path = "../../../libs/gdsconv" } +gds = { version = "0.4.2", registry = "substrate", path = "../../../libs/gds" } +scir = { version = "0.9.2", registry = "substrate", path = "../../../libs/scir" } +spice = { version = "0.9.3", registry = "substrate", path = "../../../libs/spice" } arcstr = "1" rust_decimal = "1" diff --git a/examples/latest/sky130_inverter/Cargo.toml b/examples/latest/sky130_inverter/Cargo.toml index a662cd638..eed6c5343 100644 --- a/examples/latest/sky130_inverter/Cargo.toml +++ b/examples/latest/sky130_inverter/Cargo.toml @@ -6,13 +6,13 @@ publish = false # begin-code-snippet dependencies [dependencies] -substrate = { version = "0.10.2", registry = "substrate", path = "../../../substrate" } -sky130 = { version = "0.10.2", registry = "substrate", path = "../../../pdks/sky130" } -layir = { version = "0.2.1", registry = "substrate", path = "../../../libs/layir" } -gdsconv = { version = "0.2.1", registry = "substrate", path = "../../../libs/gdsconv" } -gds = { version = "0.4.1", registry = "substrate", path = "../../../libs/gds" } -scir = { version = "0.9.1", registry = "substrate", path = "../../../libs/scir" } -spice = { version = "0.9.2", registry = "substrate", path = "../../../libs/spice" } +substrate = { version = "0.10.3", registry = "substrate", path = "../../../substrate" } +sky130 = { version = "0.10.3", registry = "substrate", path = "../../../pdks/sky130" } +layir = { version = "0.2.2", registry = "substrate", path = "../../../libs/layir" } +gdsconv = { version = "0.2.2", registry = "substrate", path = "../../../libs/gdsconv" } +gds = { version = "0.4.2", registry = "substrate", path = "../../../libs/gds" } +scir = { version = "0.9.2", registry = "substrate", path = "../../../libs/scir" } +spice = { version = "0.9.3", registry = "substrate", path = "../../../libs/spice" } arcstr = "1" rust_decimal = "1" @@ -20,15 +20,15 @@ rust_decimal_macros = "1" # end-code-snippet dependencies # begin-code-snippet open-dependencies -ngspice = { version = "0.5.2", registry = "substrate", path = "../../../tools/ngspice" } -magic_netgen = { version = "0.1.3", registry = "substrate", path = "../../../tools/magic_netgen" } -magic = { version = "0.2.1", registry = "substrate", path = "../../../tools/magic" } +ngspice = { version = "0.5.3", registry = "substrate", path = "../../../tools/ngspice" } +magic_netgen = { version = "0.1.4", registry = "substrate", path = "../../../tools/magic_netgen" } +magic = { version = "0.2.2", registry = "substrate", path = "../../../tools/magic" } # end-code-snippet open-dependencies # begin-code-snippet cds-dependencies -spectre = { version = "0.11.2", registry = "substrate", path = "../../../tools/spectre" } -quantus = { version = "0.2.2", registry = "substrate", path = "../../../tools/quantus" } +spectre = { version = "0.11.3", registry = "substrate", path = "../../../tools/spectre" } +quantus = { version = "0.2.3", registry = "substrate", path = "../../../tools/quantus" } pegasus = { version = "0.2.1", registry = "substrate", path = "../../../tools/pegasus" } # end-code-snippet cds-dependencies -atoll = { version = "0.1.3", registry = "substrate", path = "../../../libs/atoll" } +atoll = { version = "0.1.4", registry = "substrate", path = "../../../libs/atoll" } diff --git a/examples/latest/spice_vdivider/Cargo.toml b/examples/latest/spice_vdivider/Cargo.toml index 3f22fd6c4..203425ecb 100644 --- a/examples/latest/spice_vdivider/Cargo.toml +++ b/examples/latest/spice_vdivider/Cargo.toml @@ -6,8 +6,8 @@ publish = false # begin-code-snippet dependencies [dependencies] -substrate = { version = "0.10.2", registry = "substrate", path = "../../../substrate" } -spice = { version = "0.9.2", registry = "substrate", path = "../../../libs/spice" } +substrate = { version = "0.10.3", registry = "substrate", path = "../../../substrate" } +spice = { version = "0.9.3", registry = "substrate", path = "../../../libs/spice" } rust_decimal = "1" rust_decimal_macros = "1" diff --git a/examples/latest/strongarm/Cargo.toml b/examples/latest/strongarm/Cargo.toml index 8c19f0f95..d6e955dc4 100644 --- a/examples/latest/strongarm/Cargo.toml +++ b/examples/latest/strongarm/Cargo.toml @@ -5,14 +5,14 @@ edition = "2021" publish = false [dependencies] -atoll = { version = "0.1.3", registry = "substrate", path = "../../../libs/atoll" } -substrate = { version = "0.10.2", registry = "substrate", path = "../../../substrate" } -sky130 = { version = "0.10.2", registry = "substrate", path = "../../../pdks/sky130" } -layir = { version = "0.2.1", registry = "substrate", path = "../../../libs/layir" } -gdsconv = { version = "0.2.1", registry = "substrate", path = "../../../libs/gdsconv" } -gds = { version = "0.4.1", registry = "substrate", path = "../../../libs/gds" } -scir = { version = "0.9.1", registry = "substrate", path = "../../../libs/scir" } -spice = { version = "0.9.2", registry = "substrate", path = "../../../libs/spice" } +atoll = { version = "0.1.4", registry = "substrate", path = "../../../libs/atoll" } +substrate = { version = "0.10.3", registry = "substrate", path = "../../../substrate" } +sky130 = { version = "0.10.3", registry = "substrate", path = "../../../pdks/sky130" } +layir = { version = "0.2.2", registry = "substrate", path = "../../../libs/layir" } +gdsconv = { version = "0.2.2", registry = "substrate", path = "../../../libs/gdsconv" } +gds = { version = "0.4.2", registry = "substrate", path = "../../../libs/gds" } +scir = { version = "0.9.2", registry = "substrate", path = "../../../libs/scir" } +spice = { version = "0.9.3", registry = "substrate", path = "../../../libs/spice" } arcstr = "1" rust_decimal = "1" @@ -21,6 +21,6 @@ derive-where = "1" approx = "0.5" itertools = "0.14" -spectre = { version = "0.11.2", registry = "substrate", path = "../../../tools/spectre" } -quantus = { version = "0.2.2", registry = "substrate", path = "../../../tools/quantus" } +spectre = { version = "0.11.3", registry = "substrate", path = "../../../tools/spectre" } +quantus = { version = "0.2.3", registry = "substrate", path = "../../../tools/quantus" } pegasus = { version = "0.2.1", registry = "substrate", path = "../../../tools/pegasus" } diff --git a/examples/latest/substrate_api_examples/Cargo.toml b/examples/latest/substrate_api_examples/Cargo.toml index ea2e4a87a..fe57b9dba 100644 --- a/examples/latest/substrate_api_examples/Cargo.toml +++ b/examples/latest/substrate_api_examples/Cargo.toml @@ -5,8 +5,8 @@ edition = "2021" publish = false [dependencies] -substrate = { version = "0.10.2", registry = "substrate", path = "../../../substrate" } -scir = { version = "0.9.1", registry = "substrate", path = "../../../libs/scir" } +substrate = { version = "0.10.3", registry = "substrate", path = "../../../substrate" } +scir = { version = "0.9.2", registry = "substrate", path = "../../../libs/scir" } arcstr = "1" rust_decimal = "1" diff --git a/examples/latest/vdivider/Cargo.toml b/examples/latest/vdivider/Cargo.toml index 580b31e5c..fab5bc5ed 100644 --- a/examples/latest/vdivider/Cargo.toml +++ b/examples/latest/vdivider/Cargo.toml @@ -9,8 +9,8 @@ arcstr = { version = "1", features = ["serde"] } rust_decimal = "1" rust_decimal_macros = "1" serde = { version = "1.0.219", features = ["derive"] } -substrate = { version = "0.10.2", registry = "substrate", path = "../../../substrate" } -spectre = { version = "0.11.2", registry = "substrate", path = "../../../tools/spectre" } +substrate = { version = "0.10.3", registry = "substrate", path = "../../../substrate" } +spectre = { version = "0.11.3", registry = "substrate", path = "../../../tools/spectre" } [dev-dependencies] approx = "0.5" diff --git a/examples/latest/via/Cargo.toml b/examples/latest/via/Cargo.toml index bfd578cc2..7f986b5ee 100644 --- a/examples/latest/via/Cargo.toml +++ b/examples/latest/via/Cargo.toml @@ -5,5 +5,5 @@ edition = "2021" publish = false [dependencies] -substrate = { version = "0.10.2", registry = "substrate", path = "../../../substrate" } -layir = { version = "0.2.1", registry = "substrate", path = "../../../libs/layir" } +substrate = { version = "0.10.3", registry = "substrate", path = "../../../substrate" } +layir = { version = "0.2.2", registry = "substrate", path = "../../../libs/layir" } diff --git a/examples/release/Cargo.toml b/examples/release/Cargo.toml index 70fce75d1..4dda1ef72 100644 --- a/examples/release/Cargo.toml +++ b/examples/release/Cargo.toml @@ -4,8 +4,10 @@ resolver = "2" members = [ "colbuf", + "resistor_bank", "sky130_inverter", "spice_vdivider", + "strongarm", "substrate_api_examples", "vdivider", "via" diff --git a/examples/release/colbuf/Cargo.toml b/examples/release/colbuf/Cargo.toml index c1b702a9e..99920320e 100644 --- a/examples/release/colbuf/Cargo.toml +++ b/examples/release/colbuf/Cargo.toml @@ -5,14 +5,14 @@ edition = "2021" publish = false [dependencies] -substrate = { version = "0.10.2", registry = "substrate" } -spice = { version = "0.9.2", registry = "substrate" } -spectre = { version = "0.11.2", registry = "substrate" } -ngspice = { version = "0.5.2", registry = "substrate" } -quantus = { version = "0.2.2", registry = "substrate" } -magic_netgen = { version = "0.1.3", registry = "substrate" } -rust_decimal = "1.36.0" -rust_decimal_macros = "1.36.0" +substrate = { version = "0.10.3", registry = "substrate" } +spice = { version = "0.9.3", registry = "substrate" } +spectre = { version = "0.11.3", registry = "substrate" } +ngspice = { version = "0.5.3", registry = "substrate" } +quantus = { version = "0.2.3", registry = "substrate" } +magic_netgen = { version = "0.1.4", registry = "substrate" } +rust_decimal = "1.37.1" +rust_decimal_macros = "1.37.1" [dev-dependencies] approx = "0.5" diff --git a/examples/release/resistor_bank/Cargo.toml b/examples/release/resistor_bank/Cargo.toml new file mode 100644 index 000000000..b4a001cbb --- /dev/null +++ b/examples/release/resistor_bank/Cargo.toml @@ -0,0 +1,21 @@ +[package] +name = "resistor_bank" +version = "0.1.1" +edition = "2024" + +[dependencies] +atoll = { version = "0.1.4", registry = "substrate" } +substrate = { version = "0.10.3", registry = "substrate" } +sky130 = { version = "0.10.3", registry = "substrate" } +layir = { version = "0.2.2", registry = "substrate" } +gdsconv = { version = "0.2.2", registry = "substrate" } +gds = { version = "0.4.2", registry = "substrate" } +scir = { version = "0.9.2", registry = "substrate" } +spice = { version = "0.9.3", registry = "substrate" } + +arcstr = "1" +rust_decimal = "1" +rust_decimal_macros = "1" +derive-where = "1" +approx = "0.5" + diff --git a/examples/release/resistor_bank/src/lib.rs b/examples/release/resistor_bank/src/lib.rs new file mode 100644 index 000000000..c9ab3fce2 --- /dev/null +++ b/examples/release/resistor_bank/src/lib.rs @@ -0,0 +1,227 @@ +use atoll::fold::Foldable; +use atoll::straps::{GreedyStrapper, LayerStrappingParams, StrappingParams}; +use atoll::{Tile, TileData, route::GreedyRouter}; +use sky130::{ + Sky130, + atoll::{NmosTile, PtapTile, Sky130ViaMaker}, + res::PrecisionResistorCell, +}; +use substrate::types::codegen::{PortGeometryBundle, View}; +use substrate::{ + block::Block, + geometry::align::AlignMode, + geometry::bbox::Bbox, + types::{FlatLen, InOut, Input, Io, Signal, layout::PortGeometryBuilder}, +}; + +#[derive(Debug, Default, Clone, Io)] +pub struct ResistorBankSliceIo { + pub din: Input, + pub en: Input, + pub vss: InOut, +} + +#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, Block)] +#[substrate(io = "ResistorBankSliceIo")] +pub struct ResistorBankSlice { + pub n: NmosTile, + pub res: PrecisionResistorCell, + pub tap: PtapTile, +} + +impl Foldable for ResistorBankSlice { + type ViaMaker = Sky130ViaMaker; + fn via_maker() -> Self::ViaMaker { + Sky130ViaMaker + } +} + +impl Tile for ResistorBankSlice { + type Schema = Sky130; + type NestedData = (); + type LayoutBundle = View>; + type LayoutData = (); + + fn tile<'a>( + &self, + io: &'a substrate::types::schematic::IoNodeBundle, + cell: &mut atoll::TileBuilder<'a, Self::Schema>, + ) -> substrate::error::Result> { + let mut din = PortGeometryBuilder::new(); + let mut en = PortGeometryBuilder::new(); + let mut vss = PortGeometryBuilder::new(); + let x = cell.signal("x", Signal); + let n = cell.generate_primitive_named(self.n, "nmos"); + for i in 0..n.io().g.len() { + cell.connect(n.io().g[i], io.en); + } + for i in 0..n.io().sd.len() { + if i % 2 == 0 { + cell.connect(n.io().sd[i], io.din); + } else { + cell.connect(n.io().sd[i], x); + } + } + cell.connect(n.io().b, io.vss); + let mut tap = cell.generate_primitive_named(self.tap, "tap"); + cell.connect(tap.io().vnb, io.vss); + let mut res = cell.generate_primitive_named(self.res, "res"); + cell.connect(res.io().p, x); + cell.connect(res.io().n, io.vss); + let nbbox = n.lcm_bounds(); + res.align_rect_mut(nbbox, AlignMode::CenterHorizontal, 0); + res.align_rect_mut(nbbox, AlignMode::Beneath, 0); + let resbbox = res.lcm_bounds(); + tap.align_rect_mut(nbbox, AlignMode::Left, 0); + tap.align_rect_mut(resbbox, AlignMode::Beneath, 0); + + let n = cell.draw(n)?; + let res = cell.draw(res)?; + let tap = cell.draw(tap)?; + + en.merge(n.layout.io().g[0].clone()); + din.merge(n.layout.io().sd[1].clone()); + vss.merge(n.layout.io().b); + vss.merge(res.layout.io().n); + vss.merge(tap.layout.io().vnb); + + cell.set_top_layer(2); + cell.set_router(GreedyRouter::new()); + cell.set_via_maker(Sky130ViaMaker); + cell.set_strapper(GreedyStrapper); + cell.set_strapping( + io.vss, + StrappingParams::new(1, vec![LayerStrappingParams::ViaDown { min_period: 30 }]), + ); + + Ok(TileData { + nested_data: (), + layout_bundle: ResistorBankSliceIoView { + din: din.build()?, + en: en.build()?, + vss: vss.build()?, + }, + layout_data: (), + outline: cell.layout.bbox_rect(), + }) + } +} + +#[cfg(test)] +mod tests { + use super::*; + + use atoll::TileWrapper; + use atoll::fold::{FoldedArray, PinConfig}; + use scir::netlist::ConvertibleNetlister; + use sky130::Sky130SrcNdaSchema; + use sky130::atoll::MosLength; + use sky130::res::{PrecisionResistor, PrecisionResistorWidth}; + use sky130::{Sky130, layout::to_gds}; + use spice::{Spice, netlist::NetlistOptions}; + use std::path::PathBuf; + use substrate::context::Context; + use substrate::geometry::dir::Dir; + use substrate::geometry::side::Side; + + pub fn sky130_src_nda_ctx() -> Context { + // Open PDK needed for standard cells. + let open_pdk_root = std::env::var("SKY130_OPEN_PDK_ROOT") + .expect("the SKY130_OPEN_PDK_ROOT environment variable must be set"); + let src_nda_pdk_root = std::env::var("SKY130_SRC_NDA_PDK_ROOT") + .expect("the SKY130_SRC_NDA_PDK_ROOT environment variable must be set"); + Context::builder() + .install(Sky130::src_nda(open_pdk_root, src_nda_pdk_root)) + .build() + } + + #[test] + fn resistor_bank_slice_lvs() { + let work_dir = PathBuf::from(concat!( + env!("CARGO_MANIFEST_DIR"), + "/build/resistor_bank_slice_lvs" + )); + let gds_path = work_dir.join("layout.gds"); + let netlist_path = work_dir.join("netlist.sp"); + let ctx = sky130_src_nda_ctx(); + + let block = TileWrapper::new(ResistorBankSlice { + tap: PtapTile::new(7, 4), + res: PrecisionResistorCell { + resistor: PrecisionResistor { + width: PrecisionResistorWidth::W285, + length: 4_000, + }, + dir: Dir::Vert, + }, + n: NmosTile::new(2_000, MosLength::L150, 6), + }); + + let scir = ctx + .export_scir(block) + .unwrap() + .scir + .convert_schema::() + .unwrap() + .convert_schema::() + .unwrap() + .build() + .unwrap(); + Spice + .write_scir_netlist_to_file(&scir, &netlist_path, NetlistOptions::default()) + .expect("failed to write netlist"); + + ctx.write_layout(block, to_gds, &gds_path) + .expect("failed to write layout"); + } + + #[test] + fn resistor_bank() { + let work_dir = PathBuf::from(concat!(env!("CARGO_MANIFEST_DIR"), "/build/resistor_bank")); + let gds_path = work_dir.join("layout.gds"); + let netlist_path = work_dir.join("netlist.sp"); + let ctx = sky130_src_nda_ctx(); + + let block = TileWrapper::new(FoldedArray { + rows: 2, + cols: 20, + pins: vec![ + PinConfig::Parallel { layer: 1 }, + PinConfig::Escape { + layer: 0, + side: Side::Top, + }, + PinConfig::Parallel { layer: 1 }, + ], + tile: ResistorBankSlice { + tap: PtapTile::new(7, 4), + res: PrecisionResistorCell { + resistor: PrecisionResistor { + width: PrecisionResistorWidth::W141, + length: 2_000, + }, + dir: Dir::Vert, + }, + n: NmosTile::new(2_000, MosLength::L150, 6), + }, + top_layer: 3, + dir: Dir::Horiz, + }); + + let scir = ctx + .export_scir(block.clone()) + .unwrap() + .scir + .convert_schema::() + .unwrap() + .convert_schema::() + .unwrap() + .build() + .unwrap(); + Spice + .write_scir_netlist_to_file(&scir, &netlist_path, NetlistOptions::default()) + .expect("failed to write netlist"); + ctx.write_layout(block, to_gds, &gds_path) + .expect("failed to write layout"); + } +} diff --git a/examples/release/sky130_inverter/Cargo.toml b/examples/release/sky130_inverter/Cargo.toml index 4f4b79f14..6b2557994 100644 --- a/examples/release/sky130_inverter/Cargo.toml +++ b/examples/release/sky130_inverter/Cargo.toml @@ -6,13 +6,13 @@ publish = false # begin-code-snippet dependencies [dependencies] -substrate = { version = "0.10.2", registry = "substrate" } -sky130 = { version = "0.10.2", registry = "substrate" } -layir = { version = "0.2.1", registry = "substrate" } -gdsconv = { version = "0.2.1", registry = "substrate" } -gds = { version = "0.4.1", registry = "substrate" } -scir = { version = "0.9.1", registry = "substrate" } -spice = { version = "0.9.2", registry = "substrate" } +substrate = { version = "0.10.3", registry = "substrate" } +sky130 = { version = "0.10.3", registry = "substrate" } +layir = { version = "0.2.2", registry = "substrate" } +gdsconv = { version = "0.2.2", registry = "substrate" } +gds = { version = "0.4.2", registry = "substrate" } +scir = { version = "0.9.2", registry = "substrate" } +spice = { version = "0.9.3", registry = "substrate" } arcstr = "1" rust_decimal = "1" @@ -20,13 +20,15 @@ rust_decimal_macros = "1" # end-code-snippet dependencies # begin-code-snippet open-dependencies -ngspice = { version = "0.5.2", registry = "substrate" } -magic_netgen = { version = "0.1.3", registry = "substrate" } -magic = { version = "0.2.1", registry = "substrate" } +ngspice = { version = "0.5.3", registry = "substrate" } +magic_netgen = { version = "0.1.4", registry = "substrate" } +magic = { version = "0.2.2", registry = "substrate" } # end-code-snippet open-dependencies # begin-code-snippet cds-dependencies -spectre = { version = "0.11.2", registry = "substrate" } -quantus = { version = "0.2.2", registry = "substrate" } +spectre = { version = "0.11.3", registry = "substrate" } +quantus = { version = "0.2.3", registry = "substrate" } pegasus = { version = "0.2.1", registry = "substrate" } # end-code-snippet cds-dependencies + +atoll = { version = "0.1.4", registry = "substrate" } diff --git a/examples/release/sky130_inverter/src/atoll/mod.rs b/examples/release/sky130_inverter/src/atoll/mod.rs new file mode 100644 index 000000000..d84b14700 --- /dev/null +++ b/examples/release/sky130_inverter/src/atoll/mod.rs @@ -0,0 +1,296 @@ +use atoll::{fold::Foldable, route::GreedyRouter, Orientation, Tile, TileData}; +use layir::Shape; +use sky130::{ + atoll::{GateDir, MosLength, NmosTile, NtapTile, PmosTile, PtapTile, Sky130ViaMaker}, + layers::Sky130Layer, + Sky130, +}; +use substrate::{ + geometry::{align::AlignMode, bbox::Bbox, rect::Rect}, + types::{ + codegen::{PortGeometryBundle, View}, + layout::PortGeometry, + }, +}; + +use crate::{Inverter, InverterIo, InverterIoView}; + +impl Tile for Inverter { + type Schema = Sky130; + type NestedData = (); + type LayoutBundle = View>; + type LayoutData = (); + + fn tile<'a>( + &self, + io: &'a substrate::types::schematic::IoNodeBundle, + cell: &mut atoll::TileBuilder<'a, Self::Schema>, + ) -> substrate::error::Result> { + let mut n = cell.generate_primitive_named( + NmosTile::new(self.nw, MosLength::L150, 1).with_gate_dir(GateDir::Left), + "nmos", + ); + let mut p = cell.generate_primitive_named( + PmosTile::new(self.pw, MosLength::L150, 1).with_gate_dir(GateDir::Left), + "pmos", + ); + let mut ptap = cell.generate_primitive(PtapTile::new(2, 2)); + let mut ntap = cell.generate_primitive(NtapTile::new(2, 2)); + n.orient_mut(Orientation::ReflectVert); + ptap.align_mut(&n, AlignMode::Beneath, 0); + ptap.align_mut(&n, AlignMode::CenterHorizontal, 0); + p.align_mut(&n, AlignMode::Above, 0); + p.align_mut(&n, AlignMode::CenterHorizontal, 0); + ntap.align_mut(&p, AlignMode::Above, 0); + ntap.align_mut(&p, AlignMode::CenterHorizontal, 0); + cell.connect(n.io().g[0], io.din); + cell.connect(p.io().g[0], io.din); + cell.connect(n.io().sd[0], io.vss); + cell.connect(p.io().sd[0], io.vdd); + cell.connect(n.io().sd[1], io.dout); + cell.connect(p.io().sd[1], io.dout); + cell.connect(ntap.io().vpb, io.vdd); + cell.connect(ptap.io().vnb, io.vss); + cell.connect(n.io().b, io.vss); + cell.connect(p.io().b, io.vdd); + + let n = cell.draw(n)?; + let p = cell.draw(p)?; + let ntap = cell.draw(ntap)?; + let ptap = cell.draw(ptap)?; + + let din = n.layout.io().g[0] + .bbox_rect() + .union(p.layout.io().g[0].bbox_rect()); + let dout = n.layout.io().sd[1] + .bbox_rect() + .union(p.layout.io().sd[1].bbox_rect()); + let m1_tracks = cell.layer_stack.tracks(1); + let mid_pin_track_idx = m1_tracks.to_track_idx( + din.center().y, + substrate::layout::tracks::RoundingMode::Nearest, + ); + let mid_pin_track = m1_tracks.get(mid_pin_track_idx); + + let m0_tracks = cell.layer_stack.tracks(0); + let left_pin_track_idx = m0_tracks.to_track_idx( + din.center().x, + substrate::layout::tracks::RoundingMode::Nearest, + ); + let left_pin_track = m0_tracks.get(left_pin_track_idx); + let right_pin_track_idx = m0_tracks.to_track_idx( + dout.center().x, + substrate::layout::tracks::RoundingMode::Nearest, + ); + let right_pin_track = m0_tracks.get(right_pin_track_idx); + let din_pin = Shape::new( + Sky130Layer::Met1, + Rect::from_spans(left_pin_track, mid_pin_track), + ); + let dout_pin = Shape::new( + Sky130Layer::Met1, + Rect::from_spans(right_pin_track, mid_pin_track), + ); + cell.layout.draw(din_pin.clone())?; + cell.layout.draw(dout_pin.clone())?; + cell.assign_grid_points( + Some(io.din), + 1, + Rect::from_xy(left_pin_track_idx, mid_pin_track_idx), + ); + cell.assign_grid_points( + Some(io.dout), + 1, + Rect::from_xy(right_pin_track_idx, mid_pin_track_idx), + ); + + cell.set_router(GreedyRouter::new()); + cell.set_top_layer(2); + cell.set_via_maker(Sky130ViaMaker); + + Ok(TileData { + nested_data: (), + layout_bundle: InverterIoView { + vdd: ntap.layout.io().vpb, + vss: ptap.layout.io().vnb, + din: PortGeometry::new(din_pin), + dout: PortGeometry::new(dout_pin), + }, + layout_data: (), + outline: cell.layout.bbox_rect(), + }) + } +} + +impl Foldable for Inverter { + type ViaMaker = Sky130ViaMaker; + + fn via_maker() -> Self::ViaMaker { + Sky130ViaMaker + } +} + +#[cfg(test)] +mod tests { + use crate::sky130_cds_ctx; + + use super::*; + + use atoll::fold::{FoldedArray, PinConfig}; + use atoll::TileWrapper; + use pegasus::drc::{run_drc, DrcParams}; + use pegasus::lvs::{LvsParams, LvsStatus}; + use pegasus::RuleCheck; + use scir::netlist::ConvertibleNetlister; + + use sky130::layout::to_gds; + use sky130::{ + Sky130CdsSchema, SKY130_DRC, SKY130_DRC_RULES_PATH, SKY130_LVS, SKY130_LVS_RULES_PATH, + }; + use spice::{netlist::NetlistOptions, Spice}; + use std::path::PathBuf; + use substrate::block::Block; + + use substrate::geometry::dir::Dir; + + use substrate::schematic::ConvertSchema; + + fn test_check_filter(check: &RuleCheck) -> bool { + !["licon.12", "hvnwell.8"].contains(&check.name.as_ref()) + } + + #[test] + fn inverter_layout_atoll() { + let work_dir = PathBuf::from(concat!( + env!("CARGO_MANIFEST_DIR"), + "/build/inverter_layout_atoll" + )); + let layout_path = work_dir.join("layout.gds"); + let ctx = sky130_cds_ctx(); + + let block = TileWrapper::new(Inverter { + nw: 1_200, + pw: 2_400, + }); + + ctx.write_layout(block, to_gds, &layout_path).unwrap(); + + // Run DRC. + let drc_dir = work_dir.join("drc"); + let data = run_drc(&DrcParams { + work_dir: &drc_dir, + layout_path: &layout_path, + cell_name: &block.name(), + rules_dir: &PathBuf::from(SKY130_DRC), + rules_path: &PathBuf::from(SKY130_DRC_RULES_PATH), + }) + .expect("failed to run drc"); + + assert_eq!( + data.rule_checks + .into_iter() + .filter(test_check_filter) + .count(), + 0, + "layout was not DRC clean" + ); + + // Run LVS. + let lvs_dir = work_dir.join("lvs"); + let source_path = work_dir.join("schematic.spice"); + let rawlib = ctx + .export_scir(ConvertSchema::<_, Spice>::new(ConvertSchema::< + _, + Sky130CdsSchema, + >::new(block))) + .unwrap(); + + Spice + .write_scir_netlist_to_file(&rawlib.scir, &source_path, NetlistOptions::default()) + .expect("failed to write netlist"); + let output = pegasus::lvs::run_lvs(&LvsParams { + work_dir: &lvs_dir, + layout_path: &layout_path, + layout_cell_name: &block.name(), + source_paths: &[source_path], + source_cell_name: &block.name(), + rules_dir: &PathBuf::from(SKY130_LVS), + rules_path: &PathBuf::from(SKY130_LVS_RULES_PATH), + }) + .expect("failed to run lvs"); + + assert_eq!( + output.status, + LvsStatus::Correct, + "layout does not match netlist" + ); + } + + #[test] + fn inverter_chain_layout_atoll() { + let work_dir = PathBuf::from(concat!( + env!("CARGO_MANIFEST_DIR"), + "/build/inverter_chain_layout_atoll" + )); + let layout_path = work_dir.join("layout.gds"); + let ctx = sky130_cds_ctx(); + + let block = TileWrapper::new(FoldedArray { + tile: Inverter { + nw: 1_200, + pw: 2_400, + }, + rows: 5, + cols: 5, + pins: vec![ + PinConfig::Ignore, + PinConfig::Ignore, + PinConfig::Ignore, + PinConfig::Series { + partner: 2, + layer: 1, + }, + ], + top_layer: 2, + dir: Dir::Horiz, + }); + + ctx.write_layout(block.clone(), to_gds, &layout_path) + .unwrap(); + + // Run DRC. + let drc_dir = work_dir.join("drc"); + let data = run_drc(&DrcParams { + work_dir: &drc_dir, + layout_path: &layout_path, + cell_name: &block.name(), + rules_dir: &PathBuf::from(SKY130_DRC), + rules_path: &PathBuf::from(SKY130_DRC_RULES_PATH), + }) + .expect("failed to run drc"); + + assert_eq!( + data.rule_checks + .into_iter() + .filter(test_check_filter) + .count(), + 0, + "layout was not DRC clean" + ); + + // Write netlist. + let source_path = work_dir.join("schematic.spice"); + let rawlib = ctx + .export_scir(ConvertSchema::<_, Spice>::new(ConvertSchema::< + _, + Sky130CdsSchema, + >::new( + block.clone() + ))) + .unwrap(); + + Spice + .write_scir_netlist_to_file(&rawlib.scir, &source_path, NetlistOptions::default()) + .expect("failed to write netlist"); + } +} diff --git a/examples/release/sky130_inverter/src/lib.rs b/examples/release/sky130_inverter/src/lib.rs index 039cdf8dc..ea0876506 100644 --- a/examples/release/sky130_inverter/src/lib.rs +++ b/examples/release/sky130_inverter/src/lib.rs @@ -9,6 +9,7 @@ use substrate::types::schematic::IoNodeBundle; use substrate::types::{InOut, Input, Io, Output, Signal}; // end-code-snippet imports +pub mod atoll; pub mod layout; pub mod tb; diff --git a/examples/release/spice_vdivider/Cargo.toml b/examples/release/spice_vdivider/Cargo.toml index f5ddd4e96..85e5babbf 100644 --- a/examples/release/spice_vdivider/Cargo.toml +++ b/examples/release/spice_vdivider/Cargo.toml @@ -6,8 +6,8 @@ publish = false # begin-code-snippet dependencies [dependencies] -substrate = { version = "0.10.2", registry = "substrate" } -spice = { version = "0.9.2", registry = "substrate" } +substrate = { version = "0.10.3", registry = "substrate" } +spice = { version = "0.9.3", registry = "substrate" } rust_decimal = "1" rust_decimal_macros = "1" diff --git a/examples/release/strongarm/Cargo.toml b/examples/release/strongarm/Cargo.toml new file mode 100644 index 000000000..529a40538 --- /dev/null +++ b/examples/release/strongarm/Cargo.toml @@ -0,0 +1,26 @@ +[package] +name = "strongarm" +version = "0.0.0" +edition = "2021" +publish = false + +[dependencies] +atoll = { version = "0.1.4", registry = "substrate" } +substrate = { version = "0.10.3", registry = "substrate" } +sky130 = { version = "0.10.3", registry = "substrate" } +layir = { version = "0.2.2", registry = "substrate" } +gdsconv = { version = "0.2.2", registry = "substrate" } +gds = { version = "0.4.2", registry = "substrate" } +scir = { version = "0.9.2", registry = "substrate" } +spice = { version = "0.9.3", registry = "substrate" } + +arcstr = "1" +rust_decimal = "1" +rust_decimal_macros = "1" +derive-where = "1" +approx = "0.5" +itertools = "0.14" + +spectre = { version = "0.11.3", registry = "substrate" } +quantus = { version = "0.2.3", registry = "substrate" } +pegasus = { version = "0.2.1", registry = "substrate" } diff --git a/examples/release/strongarm/src/lib.rs b/examples/release/strongarm/src/lib.rs new file mode 100644 index 000000000..7c47203f8 --- /dev/null +++ b/examples/release/strongarm/src/lib.rs @@ -0,0 +1,758 @@ +//! StrongARM latch layout generators. + +use crate::tiles::{MosKind, MosTileParams, TapIo, TapTileParams, TileKind}; +use atoll::grid::AtollLayer; +use atoll::resizing::{ResizableGrid, ResizableInstance}; +use atoll::route::{GreedyRouter, ViaMaker}; +use atoll::straps::{GreedyStrapper, LayerStrappingParams, StrappingParams}; +use atoll::{Orientation, Tile, TileBuilder, TileData}; +use itertools::Itertools; +use std::any::Any; +use std::marker::PhantomData; +use substrate::arcstr::ArcStr; +use substrate::block::Block; +use substrate::error::Result; +use substrate::geometry::align::AlignMode; +use substrate::geometry::bbox::Bbox; +use substrate::geometry::dir::Dir; +use substrate::types::codegen::{PortGeometryBundle, View}; +use substrate::types::layout::PortGeometryBuilder; +use substrate::types::schematic::NodeBundle; +use substrate::types::{DiffPair, DiffPairView, InOut, Input, Io, MosIo, Output, Signal}; +use substrate::{layout, schematic}; + +pub mod tb; +pub mod tech; +pub mod tiles; + +/// The interface to a clocked differential comparator. +#[derive(Debug, Default, Clone, Io)] +pub struct ClockedDiffComparatorIo { + /// The input differential pair. + pub input: Input, + /// The output differential pair. + pub output: Output, + /// The clock signal. + pub clock: Input, + /// The VDD rail. + pub vdd: InOut, + /// The VSS rail. + pub vss: InOut, +} + +/// The input pair device kind of the comparator. +#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq)] +pub enum InputKind { + /// A comparator with an NMOS input pair. + N, + /// A comparator with a PMOS input pair. + P, +} + +impl InputKind { + /// Returns true if the input kind is NMOS. + pub fn is_n(&self) -> bool { + matches!(self, InputKind::N) + } + + /// Returns true if the input kind is PMOS. + pub fn is_p(&self) -> bool { + matches!(self, InputKind::P) + } +} + +/// The parameters of the [`StrongArm`] layout generator. +#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq)] +pub struct StrongArmParams { + /// The NMOS device flavor. + pub nmos_kind: MosKind, + /// The PMOS device flavor. + pub pmos_kind: MosKind, + /// The width of one half of the tail MOS device. + pub half_tail_w: i64, + /// The width of an input pair MOS device. + pub input_pair_w: i64, + /// The width of the inverter MOS devices connected to the input pair. + pub inv_input_w: i64, + /// The width of the inverter MOS devices connected to the precharge devices. + pub inv_precharge_w: i64, + /// The width of the precharge MOS devices. + pub precharge_w: i64, + /// The kind of the input pair MOS devices. + pub input_kind: InputKind, + /// The maximum height of the StrongARM in direction `self.dir`. + pub h_max: i64, + /// The direction of the StrongARM. + pub dir: Dir, +} + +/// A StrongARM latch implementation. +pub trait StrongArmImpl: Any { + const TAP_FREQ: i64; + type Schema: layout::schema::Schema + schematic::schema::Schema; + /// The MOS tile. + type MosTile: ResizableInstance< + Tile: Tile< + Schema = Self::Schema, + LayoutBundle = View>, + > + Block + + Clone, + >; + /// The tap tile. + type TapTile: Tile>> + + Block + + Clone; + /// A PDK-specific via maker. + type ViaMaker: ViaMaker<::Layer>; + + /// Creates an instance of the MOS tile. + fn mos(params: MosTileParams) -> Self::MosTile; + /// Creates an instance of the tap tile. + fn tap(params: TapTileParams) -> Self::TapTile; + /// Creates a PDK-specific via maker. + fn via_maker() -> Self::ViaMaker; + /// Additional layout hooks to run after the strongARM layout is complete. + fn post_layout_hooks(_cell: &mut TileBuilder<'_, Self::Schema>) -> Result<()> { + Ok(()) + } +} + +#[derive(Debug, Default, Clone, Io)] +struct StrongArmHalfIo { + /// Ports that are exposed at the top level of a StrongARM. + top_io: InOut, + /// Drains of input pair. + input_d: InOut, + /// Drain of tail. + tail_d: InOut, +} + +#[derive_where::derive_where(Copy, Clone, Debug, Hash, PartialEq, Eq)] +struct StrongArmHalf(StrongArmParams, PhantomData T>); + +impl StrongArmHalf { + fn new(params: StrongArmParams) -> Self { + Self(params, PhantomData) + } +} + +impl Block for StrongArmHalf { + type Io = StrongArmHalfIo; + + // todo: include parameters in name + fn name(&self) -> ArcStr { + substrate::arcstr::literal!("strong_arm_half") + } + + fn io(&self) -> Self::Io { + Default::default() + } +} + +impl Tile for StrongArmHalf { + type Schema = ::Schema; + type NestedData = (); + type LayoutBundle = View>; + type LayoutData = (); + + fn tile<'a>( + &self, + io: &'a substrate::types::schematic::IoNodeBundle, + cell: &mut TileBuilder<'a, Self::Schema>, + ) -> substrate::error::Result> { + let ( + input_kind, + precharge_kind, + input_flavor, + precharge_flavor, + input_rail, + precharge_rail, + ) = match self.0.input_kind { + InputKind::N => ( + TileKind::N, + TileKind::P, + self.0.nmos_kind, + self.0.pmos_kind, + io.top_io.vss, + io.top_io.vdd, + ), + InputKind::P => ( + TileKind::P, + TileKind::N, + self.0.pmos_kind, + self.0.nmos_kind, + io.top_io.vdd, + io.top_io.vss, + ), + }; + let half_tail_params = MosTileParams::new(input_flavor, input_kind, self.0.half_tail_w); + let input_pair_params = MosTileParams::new(input_flavor, input_kind, self.0.input_pair_w); + let inv_input_params = MosTileParams::new(input_flavor, input_kind, self.0.inv_input_w); + let inv_precharge_params = + MosTileParams::new(precharge_flavor, precharge_kind, self.0.inv_precharge_w); + let precharge_params = + MosTileParams::new(precharge_flavor, precharge_kind, self.0.precharge_w); + + let tail = io.tail_d; + let intn = io.input_d.n; + let intp = cell.signal("intp", Signal); + + let mut grid = ResizableGrid::new(); + if self.0.dir == Dir::Vert { + grid.transpose(); + } + let half_tail = (0..3) + .map(|_| grid.push_tile(T::mos(half_tail_params))) + .collect_vec(); + grid.end_column(); + let input_pair = (0..3) + .map(|_| grid.push_tile(T::mos(input_pair_params))) + .collect_vec(); + grid.end_column(); + let inv_input = (0..3) + .map(|_| grid.push_tile(T::mos(inv_input_params))) + .collect_vec(); + grid.end_column(); + let inv_precharge = (0..3) + .map(|_| grid.push_tile(T::mos(inv_precharge_params))) + .collect_vec(); + grid.end_column(); + let precharge_a = (0..3) + .map(|_| grid.push_tile(T::mos(precharge_params))) + .collect_vec(); + grid.end_column(); + let precharge_b = (0..3) + .map(|_| grid.push_tile(T::mos(precharge_params))) + .collect_vec(); + let grid = grid.size(self.0.h_max); + + let half_tail_params = half_tail + .into_iter() + .map(|key| grid.get_tile(key)) + .collect_vec(); + let input_pair_params = input_pair + .into_iter() + .map(|key| grid.get_tile(key)) + .collect_vec(); + let inv_input_params = inv_input + .into_iter() + .map(|key| grid.get_tile(key)) + .collect_vec(); + let inv_precharge_params = inv_precharge + .into_iter() + .map(|key| grid.get_tile(key)) + .collect_vec(); + let precharge_a_params = precharge_a + .into_iter() + .map(|key| grid.get_tile(key)) + .collect_vec(); + let precharge_b_params = precharge_b + .into_iter() + .map(|key| grid.get_tile(key)) + .collect_vec(); + + let mut tail_dummy = cell.generate_connected( + half_tail_params[0].0.clone(), + NodeBundle:: { + d: input_rail, + g: input_rail, + s: input_rail, + b: input_rail, + }, + ); + let mut tail_pair = (0..2) + .map(|i| { + cell.generate_connected( + half_tail_params[i + 1].0.clone(), + NodeBundle:: { + d: tail, + g: io.top_io.clock, + s: input_rail, + b: input_rail, + }, + ) + }) + .collect::>(); + + let max_hspan = [ + &half_tail_params, + &input_pair_params, + &inv_input_params, + &inv_precharge_params, + &precharge_a_params, + &precharge_b_params, + ] + .iter() + .map(|params| { + params + .iter() + .map(|(_, rect)| { + rect.span(!self.0.dir).length() + / match self.0.dir { + Dir::Horiz => cell.layer_stack.layer(1).pitch(), + Dir::Vert => cell.layer_stack.layer(0).pitch(), + } + }) + .reduce(|a, b| a + b) + .unwrap() + }) + .max() + .unwrap(); + let span = match self.0.dir { + Dir::Horiz => max_hspan + 8, + Dir::Vert => max_hspan, + }; + let ptap_params = T::tap(TapTileParams::new(TileKind::P, !self.0.dir, span)); + let ntap_params = T::tap(TapTileParams::new(TileKind::N, !self.0.dir, span)); + let mut ptap = cell.generate(ptap_params.clone()); + let ntap = cell.generate(ntap_params.clone()); + cell.connect(ptap.io().x, io.top_io.vss); + cell.connect(ntap.io().x, io.top_io.vdd); + + let mut input_pair = (0..2) + .map(|i| { + cell.generate_connected( + input_pair_params[i + 1].0.clone(), + NodeBundle:: { + d: if i == 0 { intn } else { intp }, + g: if i == 0 { + io.top_io.input.p + } else { + io.top_io.input.n + }, + s: tail, + b: input_rail, + }, + ) + }) + .collect::>(); + let mut input_dummy = cell.generate_connected( + input_pair_params[0].0.clone(), + NodeBundle:: { + d: input_rail, + g: input_rail, + s: input_rail, + b: input_rail, + }, + ); + let mut inv_input_pair = (0..2) + .map(|i| { + cell.generate_connected( + inv_input_params[i + 1].0.clone(), + if i == 0 { + NodeBundle:: { + d: io.top_io.output.n, + g: io.top_io.output.p, + s: intn, + b: input_rail, + } + } else { + NodeBundle:: { + d: io.top_io.output.p, + g: io.top_io.output.n, + s: intp, + b: input_rail, + } + }, + ) + }) + .collect::>(); + let mut inv_input_dummy = cell.generate_connected( + inv_input_params[0].0.clone(), + NodeBundle:: { + d: input_rail, + g: input_rail, + s: input_rail, + b: input_rail, + }, + ); + let mut inv_precharge_pair = (0..2) + .map(|i| { + cell.generate_connected( + inv_precharge_params[i + 1].0.clone(), + NodeBundle:: { + d: if i == 0 { + io.top_io.output.n + } else { + io.top_io.output.p + }, + g: if i == 0 { + io.top_io.output.p + } else { + io.top_io.output.n + }, + s: precharge_rail, + b: precharge_rail, + }, + ) + }) + .collect::>(); + let mut inv_precharge_dummy = cell.generate_connected( + inv_precharge_params[0].0.clone(), + NodeBundle:: { + d: precharge_rail, + g: precharge_rail, + s: precharge_rail, + b: precharge_rail, + }, + ); + let mut precharge_pair_a = (0..2) + .map(|i| { + cell.generate_connected( + precharge_a_params[i + 1].0.clone(), + NodeBundle:: { + d: if i == 0 { + io.top_io.output.n + } else { + io.top_io.output.p + }, + g: io.top_io.clock, + s: precharge_rail, + b: precharge_rail, + }, + ) + }) + .collect::>(); + let mut precharge_pair_a_dummy = cell.generate_connected( + precharge_a_params[0].0.clone(), + NodeBundle:: { + d: precharge_rail, + g: precharge_rail, + s: precharge_rail, + b: precharge_rail, + }, + ); + let mut precharge_pair_b = (0..2) + .map(|i| { + cell.generate_connected( + precharge_b_params[i + 1].0.clone(), + NodeBundle:: { + d: if i == 0 { intn } else { intp }, + g: io.top_io.clock, + s: precharge_rail, + b: precharge_rail, + }, + ) + }) + .collect::>(); + let mut precharge_pair_b_dummy = cell.generate_connected( + precharge_b_params[0].0.clone(), + NodeBundle:: { + d: precharge_rail, + g: precharge_rail, + s: precharge_rail, + b: precharge_rail, + }, + ); + + let mut prev = ntap.lcm_bounds(); + + let mut rows = [ + (&mut precharge_pair_a_dummy, &mut precharge_pair_a), + (&mut precharge_pair_b_dummy, &mut precharge_pair_b), + (&mut inv_precharge_dummy, &mut inv_precharge_pair), + (&mut inv_input_dummy, &mut inv_input_pair), + (&mut input_dummy, &mut input_pair), + (&mut tail_dummy, &mut tail_pair), + ]; + + if self.0.input_kind == InputKind::P { + rows.reverse(); + } + + let (align_row_a, align_row_b, align_next_a, align_next_b) = match self.0.dir { + Dir::Vert => ( + AlignMode::Bottom, + AlignMode::ToTheLeft, + AlignMode::Right, + AlignMode::Beneath, + ), + Dir::Horiz => ( + AlignMode::Left, + AlignMode::Beneath, + AlignMode::Top, + AlignMode::ToTheLeft, + ), + }; + let mut height = 0; + for (dummy, mos_pair) in &mut rows[0..3] { + let curr_height = cell + .layer_stack + .slice(0..2) + .lcm_to_physical_rect(mos_pair[1].lcm_bounds()) + .span(self.0.dir) + .length(); + if height > T::TAP_FREQ || height + curr_height > 2 * T::TAP_FREQ { + let mut tap = cell.generate(ntap_params.clone()); + tap.align_rect_mut(prev, align_next_a, 0); + tap.align_rect_mut(prev, align_next_b, 0); + prev = tap.lcm_bounds(); + cell.connect(tap.io().x, io.top_io.vdd); + cell.draw(tap)?; + height = 0; + } + height += curr_height; + mos_pair[1].align_rect_mut(prev, align_next_a, 0); + mos_pair[1].align_rect_mut(prev, align_next_b, 0); + prev = mos_pair[1].lcm_bounds(); + mos_pair[0].align_rect_mut(prev, align_row_a, 0); + mos_pair[0].align_rect_mut(prev, align_row_b, 0); + let left_rect = mos_pair[0].lcm_bounds(); + dummy.align_rect_mut(left_rect, align_row_a, 0); + dummy.align_rect_mut(left_rect, align_row_b, 0); + } + if height > T::TAP_FREQ { + let mut tap = cell.generate(ntap_params.clone()); + tap.align_rect_mut(prev, align_next_a, 0); + tap.align_rect_mut(prev, align_next_b, 0); + prev = tap.lcm_bounds(); + cell.connect(tap.io().x, io.top_io.vdd); + cell.draw(tap)?; + } + + ptap.align_rect_mut(prev, align_next_a, 0); + ptap.align_rect_mut(prev, align_next_b, 0); + prev = ptap.lcm_bounds(); + + height = 0; + for (dummy, mos_pair) in &mut rows[3..6] { + let curr_height = cell + .layer_stack + .slice(0..2) + .lcm_to_physical_rect(mos_pair[1].lcm_bounds()) + .span(self.0.dir) + .length(); + if height > T::TAP_FREQ || height + curr_height > 2 * T::TAP_FREQ { + let mut tap = cell.generate(ptap_params.clone()); + tap.align_rect_mut(prev, align_next_a, 0); + tap.align_rect_mut(prev, align_next_b, 0); + prev = tap.lcm_bounds(); + cell.connect(tap.io().x, io.top_io.vss); + cell.draw(tap)?; + height = 0; + } + height += curr_height; + mos_pair[1].align_rect_mut(prev, align_next_a, 0); + mos_pair[1].align_rect_mut(prev, align_next_b, 0); + prev = mos_pair[1].lcm_bounds(); + mos_pair[0].align_rect_mut(prev, align_row_a, 0); + mos_pair[0].align_rect_mut(prev, align_row_b, 0); + let left_rect = mos_pair[0].lcm_bounds(); + dummy.align_rect_mut(left_rect, align_row_a, 0); + dummy.align_rect_mut(left_rect, align_row_b, 0); + } + if height > T::TAP_FREQ { + let mut tap = cell.generate(ptap_params.clone()); + tap.align_rect_mut(prev, align_next_a, 0); + tap.align_rect_mut(prev, align_next_b, 0); + cell.connect(tap.io().x, io.top_io.vss); + cell.draw(tap)?; + } + + let ptap = cell.draw(ptap)?; + let ntap = cell.draw(ntap)?; + let tail_pair = tail_pair + .into_iter() + .map(|inst| cell.draw(inst)) + .collect::>>()?; + let _tail_dummy = cell.draw(tail_dummy)?; + let input_pair = input_pair + .into_iter() + .map(|inst| cell.draw(inst)) + .collect::>>()?; + let _input_dummy = cell.draw(input_dummy)?; + let inv_nmos_pair = inv_input_pair + .into_iter() + .map(|inst| cell.draw(inst)) + .collect::>>()?; + let _inv_nmos_dummy = cell.draw(inv_input_dummy)?; + let _inv_pmos_pair = inv_precharge_pair + .into_iter() + .map(|inst| cell.draw(inst)) + .collect::>>()?; + let _inv_pmos_dummy = cell.draw(inv_precharge_dummy)?; + let _precharge_pair_a = precharge_pair_a + .into_iter() + .map(|inst| cell.draw(inst)) + .collect::>>()?; + let _precharge_pair_a_dummy = cell.draw(precharge_pair_a_dummy)?; + let _precharge_pair_b = precharge_pair_b + .into_iter() + .map(|inst| cell.draw(inst)) + .collect::>>()?; + let _precharge_pair_b_dummy = cell.draw(precharge_pair_b_dummy)?; + + cell.set_top_layer(2); + cell.set_router(GreedyRouter::new()); + cell.set_via_maker(T::via_maker()); + + Ok(TileData { + nested_data: (), + layout_bundle: StrongArmHalfIoView { + top_io: ClockedDiffComparatorIoView { + vdd: ntap.layout.io().x, + vss: ptap.layout.io().x, + clock: tail_pair[0].layout.io().g, + input: DiffPairView { + p: input_pair[0].layout.io().g, + n: input_pair[1].layout.io().g, + }, + output: DiffPairView { + p: inv_nmos_pair[1].layout.io().d, + n: inv_nmos_pair[0].layout.io().d, + }, + }, + input_d: DiffPairView { + p: input_pair[1].layout.io().d, + n: input_pair[0].layout.io().d, + }, + tail_d: tail_pair[0].layout.io().d, + }, + layout_data: (), + outline: cell.layout.bbox_rect(), + }) + } +} + +/// A StrongARM latch. +// Layout assumes that PDK layer stack has a vertical layer 0. +#[derive_where::derive_where(Copy, Clone, Debug, Hash, PartialEq, Eq)] +pub struct StrongArm(StrongArmParams, PhantomData T>); + +impl StrongArm { + /// Creates a new [`StrongArm`]. + pub const fn new(params: StrongArmParams) -> Self { + Self(params, PhantomData) + } +} + +impl Block for StrongArm { + type Io = ClockedDiffComparatorIo; + + // todo: include parameters in name + fn name(&self) -> ArcStr { + substrate::arcstr::literal!("strong_arm") + } + + fn io(&self) -> Self::Io { + Default::default() + } +} + +impl Tile for StrongArm { + type Schema = ::Schema; + type NestedData = (); + type LayoutBundle = View>; + type LayoutData = (); + + fn tile<'a>( + &self, + io: &'a substrate::types::schematic::IoNodeBundle, + cell: &mut TileBuilder<'a, Self::Schema>, + ) -> substrate::error::Result> { + let tail_d = cell.signal("tail_d", Signal::new()); + let input_d = cell.signal("input_d", DiffPair::default()); + let mut vdd = PortGeometryBuilder::new(); + let mut vss = PortGeometryBuilder::new(); + let mut clock = PortGeometryBuilder::new(); + let mut input_p = PortGeometryBuilder::new(); + let mut input_n = PortGeometryBuilder::new(); + let mut output_p = PortGeometryBuilder::new(); + let mut output_n = PortGeometryBuilder::new(); + + let conn = NodeBundle:: { + top_io: io.clone(), + input_d, + tail_d, + }; + let left_half = cell.generate_connected(StrongArmHalf::::new(self.0), conn.clone()); + + let right_half = cell + .generate_connected(StrongArmHalf::::new(self.0), conn) + .orient(match self.0.dir { + Dir::Horiz => Orientation::ReflectVert, + Dir::Vert => Orientation::ReflectHoriz, + }) + .align( + &left_half, + match self.0.dir { + Dir::Horiz => AlignMode::Above, + Dir::Vert => AlignMode::ToTheRight, + }, + 0, + ); + + let left_half = cell.draw(left_half)?; + let right_half = cell.draw(right_half)?; + + cell.set_top_layer(2); + cell.set_router(GreedyRouter::new()); + cell.set_via_maker(T::via_maker()); + + vdd.merge(left_half.layout.io().top_io.vdd); + vdd.merge(right_half.layout.io().top_io.vdd); + vss.merge(left_half.layout.io().top_io.vss); + vss.merge(right_half.layout.io().top_io.vss); + clock.merge(left_half.layout.io().top_io.clock); + clock.merge(right_half.layout.io().top_io.clock); + + input_p.merge(left_half.layout.io().top_io.input.p); + input_p.merge(right_half.layout.io().top_io.input.p); + input_n.merge(left_half.layout.io().top_io.input.n); + input_n.merge(right_half.layout.io().top_io.input.n); + output_p.merge(left_half.layout.io().top_io.output.p); + output_p.merge(right_half.layout.io().top_io.output.p); + output_n.merge(left_half.layout.io().top_io.output.n); + output_n.merge(right_half.layout.io().top_io.output.n); + + cell.set_strapping( + io.vss, + StrappingParams::new( + 1, + vec![ + LayerStrappingParams::ViaDown { min_period: 2 }, + LayerStrappingParams::OffsetPeriod { + offset: 0, + period: 4, + }, + ], + ), + ); + cell.set_strapping( + io.vdd, + StrappingParams::new( + 1, + vec![ + LayerStrappingParams::ViaDown { min_period: 2 }, + LayerStrappingParams::OffsetPeriod { + offset: 1, + period: 4, + }, + ], + ), + ); + + cell.set_strapper(GreedyStrapper); + + T::post_layout_hooks(cell)?; + + Ok(TileData { + nested_data: (), + layout_bundle: ClockedDiffComparatorIoView { + input: DiffPairView { + p: input_p.build()?, + n: input_n.build()?, + }, + output: DiffPairView { + p: output_p.build()?, + n: output_n.build()?, + }, + clock: clock.build()?, + vdd: vdd.build()?, + vss: vss.build()?, + }, + layout_data: (), + outline: cell.layout.bbox_rect(), + }) + } +} diff --git a/examples/release/strongarm/src/tb/mod.rs b/examples/release/strongarm/src/tb/mod.rs new file mode 100644 index 000000000..26a72f217 --- /dev/null +++ b/examples/release/strongarm/src/tb/mod.rs @@ -0,0 +1,471 @@ +//! StrongARM testbenches. + +use approx::abs_diff_eq; +use rust_decimal::prelude::ToPrimitive; +use rust_decimal::Decimal; +use rust_decimal_macros::dec; +use spectre::analysis::tran::Tran; +use spectre::blocks::{Pulse, Vsource}; +use spectre::{ErrPreset, Spectre}; +use std::any::Any; +use std::fmt::{Debug, Display, Formatter}; +use std::hash::Hash; +use std::marker::PhantomData; +use substrate::arcstr; +use substrate::arcstr::ArcStr; +use substrate::block::Block; +use substrate::schematic::schema::Schema; +use substrate::schematic::{CellBuilder, NestedData, Schematic}; +use substrate::simulation::options::{SimOption, Temperature}; +use substrate::simulation::waveform::{EdgeDir, TimeWaveform}; +use substrate::simulation::{Pvt, SimController}; +use substrate::types::schematic::{Node, NodeBundle}; +use substrate::types::{DiffPair, Signal, TestbenchIo}; + +use crate::ClockedDiffComparatorIo; + +/// A transient testbench that provides a differential input voltage and +/// measures the output waveform. +#[derive_where::derive_where(Copy, Clone, Debug, Hash, PartialEq, Eq; T, C)] +pub struct StrongArmTranTb { + /// The device-under-test. + pub dut: T, + + /// The positive input voltage. + pub vinp: Decimal, + + /// The negative input voltage. + pub vinn: Decimal, + + /// Whether to pass an inverted clock to the DUT. + /// + /// If set to true, the clock will be held high when idle. + /// The DUT should perform a comparison in response to a falling clock edge, + /// rather than a rising clock edge. + pub inverted_clk: bool, + + /// The PVT corner. + pub pvt: Pvt, + + phantom: PhantomData PDK>, +} + +impl StrongArmTranTb { + /// Creates a new [`StrongArmTranTb`]. + pub fn new(dut: T, vinp: Decimal, vinn: Decimal, inverted_clk: bool, pvt: Pvt) -> Self { + Self { + dut, + vinp, + vinn, + pvt, + inverted_clk, + phantom: PhantomData, + } + } +} + +impl Block + for StrongArmTranTb +{ + type Io = TestbenchIo; + + fn name(&self) -> ArcStr { + arcstr::literal!("strong_arm_tran_tb") + } + + fn io(&self) -> Self::Io { + Default::default() + } +} + +/// Nodes measured by [`StrongArmTranTb`]. +#[derive(Clone, Debug, Hash, PartialEq, Eq, NestedData)] +pub struct StrongArmTranTbNodes { + vop: Node, + von: Node, + vinn: Node, + vinp: Node, + clk: Node, +} + +impl Schematic for StrongArmTranTb +where + Spectre: scir::schema::FromSchema, + S: Schema, + StrongArmTranTb: Block, + T: Block + Schematic + Clone, +{ + type Schema = Spectre; + type NestedData = StrongArmTranTbNodes; + fn schematic( + &self, + io: &substrate::types::schematic::IoNodeBundle, + cell: &mut CellBuilder<::Schema>, + ) -> substrate::error::Result { + let dut = cell.sub_builder::().instantiate(self.dut.clone()); + + let vinp = cell.signal("vinp", Signal); + let vinn = cell.signal("vinn", Signal); + let vdd = cell.signal("vdd", Signal); + let clk = cell.signal("clk", Signal); + + let vvinp = cell.instantiate(Vsource::dc(self.vinp)); + let vvinn = cell.instantiate(Vsource::dc(self.vinn)); + let vvdd = cell.instantiate(Vsource::dc(self.pvt.voltage)); + let (val0, val1) = if self.inverted_clk { + (self.pvt.voltage, dec!(0)) + } else { + (dec!(0), self.pvt.voltage) + }; + let vclk = cell.instantiate(Vsource::pulse(Pulse { + val0, + val1, + period: Some(dec!(1000)), + width: Some(dec!(100)), + delay: Some(dec!(10e-9)), + rise: Some(dec!(100e-12)), + fall: Some(dec!(100e-12)), + })); + + cell.connect(io.vss, vvinp.io().n); + cell.connect(io.vss, vvinn.io().n); + cell.connect(io.vss, vvdd.io().n); + cell.connect(io.vss, vclk.io().n); + cell.connect(vinp, vvinp.io().p); + cell.connect(vinn, vvinn.io().p); + cell.connect(vdd, vvdd.io().p); + cell.connect(clk, vclk.io().p); + + let output = cell.signal("output", DiffPair::default()); + + cell.connect( + NodeBundle:: { + input: NodeBundle:: { p: vinp, n: vinn }, + output: output.clone(), + clock: clk, + vdd, + vss: io.vss, + }, + dut.io(), + ); + + Ok(StrongArmTranTbNodes { + vop: output.p, + von: output.n, + vinn, + vinp, + clk, + }) + } +} + +/// The decision made by a comparator. +#[derive(Copy, Clone, Hash, Eq, PartialEq, Ord, PartialOrd, Debug)] +pub enum ComparatorDecision { + /// Negative. + /// + /// The negative input was larger than the positive input. + Neg, + /// Positive. + /// + /// The positive input was larger than the negative input. + Pos, +} + +impl + Copy> StrongArmTranTb +where + StrongArmTranTb: + Block + Schematic, +{ + pub fn run(&self, sim: SimController) -> Option { + let mut opts = spectre::Options::default(); + sim.set_option(self.pvt.corner, &mut opts); + sim.set_option(Temperature::from(self.pvt.temp), &mut opts); + let wav = sim + .simulate( + opts, + Tran { + stop: dec!(30e-9), + start: None, + errpreset: Some(ErrPreset::Conservative), + ..Default::default() + }, + ) + .expect("failed to run simulation"); + + let von = wav.von.last().unwrap().x(); + let vop = wav.vop.last().unwrap().x(); + + let vdd = self.pvt.voltage.to_f64().unwrap(); + let epsilon = vdd * 0.05; + if abs_diff_eq!(von, 0.0, epsilon = epsilon) && abs_diff_eq!(vop, vdd, epsilon = epsilon) { + Some(ComparatorDecision::Pos) + } else if abs_diff_eq!(von, vdd, epsilon = epsilon) + && abs_diff_eq!(vop, 0.0, epsilon = epsilon) + { + Some(ComparatorDecision::Neg) + } else { + None + } + } +} + +/// Parameters for [`StrongArmHighSpeedTb`]. +#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)] +pub struct StrongArmHighSpeedTbParams { + /// The device-under-test. + pub dut: T, + + /// The p and n voltages giving a 0. + pub v0: (Decimal, Decimal), + + /// The p and n voltages giving a 1. + pub v1: (Decimal, Decimal), + + /// The clock period. + pub period: Decimal, + + /// The number of cycles to test. + pub cycles: usize, + + /// Threshold for valid voltage levels at comparator outputs, as a percent of VDD. + /// + /// For example, a threshold of 0.8 indicates that the comparator must output + /// vop >= 0.8*VDD and von <= 0.2*VDD for the output to be considered a 1. + pub thresh: Decimal, + + /// Rise time. + pub tr: Decimal, + + /// Fall time. + pub tf: Decimal, + + /// Whether to pass an inverted clock to the DUT. + /// + /// If set to true, the clock will be held high when idle. + /// The DUT should perform a comparison in response to a falling clock edge, + /// rather than a rising clock edge. + pub inverted_clk: bool, + + /// The PVT corner. + pub pvt: Pvt, +} + +/// A high speed StrongARM testbench. +/// +/// Applies an alternating sequence of 0s and 1s, +/// and checks that the output rails correctly. +#[derive_where::derive_where(Copy, Clone, Debug, Hash, PartialEq, Eq; T, C)] +pub struct StrongArmHighSpeedTb { + params: StrongArmHighSpeedTbParams, + phantom: PhantomData PDK>, +} + +impl StrongArmHighSpeedTb { + /// Creates a new [`StrongArmHighSpeedTb`]. + pub fn new(params: StrongArmHighSpeedTbParams) -> Self { + Self { + params, + phantom: PhantomData, + } + } +} + +impl Block + for StrongArmHighSpeedTb +{ + type Io = TestbenchIo; + + fn name(&self) -> ArcStr { + arcstr::literal!("strong_arm_high_speed_tb") + } + + fn io(&self) -> Self::Io { + Default::default() + } +} + +impl + Schematic + Clone, S: Schema, C> Schematic + for StrongArmHighSpeedTb +where + Spectre: scir::schema::FromSchema, + StrongArmHighSpeedTb: Block, +{ + type Schema = Spectre; + type NestedData = StrongArmTranTbNodes; + + fn schematic( + &self, + io: &substrate::types::schematic::IoNodeBundle, + cell: &mut CellBuilder<::Schema>, + ) -> substrate::error::Result { + let dut = cell.sub_builder::().instantiate(self.params.dut.clone()); + + let vinp = cell.signal("vinp", Signal); + let vinn = cell.signal("vinn", Signal); + let vdd = cell.signal("vdd", Signal); + let clk = cell.signal("clk", Signal); + + let vvinp = cell.instantiate(Vsource::pulse(Pulse { + val0: self.params.v0.0, + val1: self.params.v1.0, + period: Some(self.params.period * dec!(2)), + rise: Some(self.params.tr), + fall: Some(self.params.tf), + width: None, + delay: None, + })); + let vvinn = cell.instantiate(Vsource::pulse(Pulse { + val0: self.params.v0.1, + val1: self.params.v1.1, + period: Some(self.params.period * dec!(2)), + rise: Some(self.params.tr), + fall: Some(self.params.tf), + width: None, + delay: None, + })); + + let vvdd = cell.instantiate(Vsource::dc(self.params.pvt.voltage)); + let (val0, val1) = if self.params.inverted_clk { + (self.params.pvt.voltage, dec!(0)) + } else { + (dec!(0), self.params.pvt.voltage) + }; + let vclk = cell.instantiate(Vsource::pulse(Pulse { + val0, + val1, + period: Some(self.params.period), + width: None, + delay: Some(self.params.period / dec!(2)), + rise: Some(self.params.tr), + fall: Some(self.params.tf), + })); + + cell.connect(io.vss, vvinp.io().n); + cell.connect(io.vss, vvinn.io().n); + cell.connect(io.vss, vvdd.io().n); + cell.connect(io.vss, vclk.io().n); + cell.connect(vinp, vvinp.io().p); + cell.connect(vinn, vvinn.io().p); + cell.connect(vdd, vvdd.io().p); + cell.connect(clk, vclk.io().p); + + let output = cell.signal("output", DiffPair::default()); + + cell.connect( + NodeBundle:: { + input: NodeBundle:: { p: vinp, n: vinn }, + output: output.clone(), + clock: clk, + vdd, + vss: io.vss, + }, + dut.io(), + ); + + Ok(StrongArmTranTbNodes { + vop: output.p, + von: output.n, + vinn, + vinp, + clk, + }) + } +} + +/// The output of the [`StrongArmHighSpeedTb`]. +#[derive(Clone, Eq, PartialEq, Debug)] +pub struct StrongArmHighSpeedTbOutput { + /// Whether the testbench used an inverted clock. + inverted_clk: bool, + /// The sequence of decisions made by the comparator. + pub decisions: Vec>, +} + +impl + Copy> StrongArmHighSpeedTb +where + StrongArmHighSpeedTb: + Block + Schematic, +{ + pub fn run(&self, sim: SimController) -> StrongArmHighSpeedTbOutput { + let mut opts = spectre::Options::default(); + sim.set_option(self.params.pvt.corner, &mut opts); + let wav = sim + .simulate( + opts, + Tran { + stop: self.params.period * Decimal::from(self.params.cycles + 2), + start: None, + errpreset: Some(ErrPreset::Conservative), + ..Default::default() + }, + ) + .expect("failed to run simulation"); + + let von = wav.von.as_ref(); + let vop = wav.vop.as_ref(); + let clk = wav.clk.as_ref(); + let vdd = self.params.pvt.voltage.to_f64().unwrap(); + let (clk_thresh, edge_dir) = if self.params.inverted_clk { + (0.2, EdgeDir::Rising) + } else { + (0.8, EdgeDir::Falling) + }; + let decisions = clk + .edges(clk_thresh * vdd) + .filter(|e| e.dir() == edge_dir) + .map(|edge| { + let t = edge.t(); + let von = von.sample_at(t); + let vop = vop.sample_at(t); + let thresh = self.params.thresh.to_f64().unwrap(); + if von >= thresh * vdd && vop <= (1. - thresh) * vdd { + Some(ComparatorDecision::Neg) + } else if von <= (1. - thresh) * vdd && vop >= thresh * vdd { + Some(ComparatorDecision::Pos) + } else { + None + } + }) + .collect::>(); + + StrongArmHighSpeedTbOutput { + inverted_clk: self.params.inverted_clk, + decisions, + } + } +} + +impl StrongArmHighSpeedTbOutput { + /// Returns true if the testbench output was correct. + pub fn is_correct(&self) -> bool { + for (i, item) in self.decisions.iter().enumerate() { + if let Some(item) = *item { + if (i % 2 == 0 && item != ComparatorDecision::Pos) + || (i % 2 != 0 && item != ComparatorDecision::Neg) + { + return false; + } + } else { + return false; + } + } + true + } +} + +impl Display for StrongArmHighSpeedTbOutput { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + write!(f, "[")?; + for decision in self.decisions.iter() { + let s = match *decision { + None => "X", + Some(ComparatorDecision::Neg) => "0", + Some(ComparatorDecision::Pos) => "1", + }; + write!(f, "{}", s)?; + } + write!(f, "]")?; + Ok(()) + } +} diff --git a/examples/release/strongarm/src/tech/mod.rs b/examples/release/strongarm/src/tech/mod.rs new file mode 100644 index 000000000..28e7915db --- /dev/null +++ b/examples/release/strongarm/src/tech/mod.rs @@ -0,0 +1 @@ +pub mod sky130; diff --git a/examples/release/strongarm/src/tech/sky130.rs b/examples/release/strongarm/src/tech/sky130.rs new file mode 100644 index 000000000..6a1ba4ee8 --- /dev/null +++ b/examples/release/strongarm/src/tech/sky130.rs @@ -0,0 +1,713 @@ +//! SKY130-specific implementations. + +use crate::tiles::{MosKind, MosTileParams, TapIo, TapIoView, TapTileParams, TileKind}; +use crate::StrongArmImpl; +use atoll::resizing::ResizableInstance; +use atoll::route::GreedyRouter; +use atoll::{Tile, TileBuilder, TileData}; +use sky130::atoll::{MosLength, NmosTile, PmosTile, Sky130ViaMaker}; +use sky130::Sky130; +use substrate::arcstr; +use substrate::arcstr::ArcStr; +use substrate::block::Block; +use substrate::geometry::bbox::Bbox; +use substrate::geometry::dims::Dims; +use substrate::geometry::dir::Dir; +use substrate::types::codegen::{PortGeometryBundle, View}; +use substrate::types::layout::PortGeometryBuilder; +use substrate::types::{FlatLen, MosIo, MosIoView}; + +/// A SKY130 implementation. +pub struct Sky130Impl; + +impl StrongArmImpl for Sky130Impl { + const TAP_FREQ: i64 = 6_000; + type Schema = Sky130; + type MosTile = ResizeableMosTile; + type TapTile = TapTile; + type ViaMaker = Sky130ViaMaker; + + fn mos(params: MosTileParams) -> Self::MosTile { + match params.mos_kind { + MosKind::Nom => {} + _ => unimplemented!(), + } + ResizeableMosTile::new(params.w, MosLength::L150, params.tile_kind) + } + fn tap(params: TapTileParams) -> Self::TapTile { + TapTile::new(params) + } + fn via_maker() -> Self::ViaMaker { + Sky130ViaMaker + } +} + +pub struct ResizeableMosTile { + wxnf: i64, + l: MosLength, + kind: TileKind, +} + +fn max_nf(w_max: i64) -> i64 { + (w_max - 860) / 430 +} + +#[allow(dead_code)] +fn max_w(h_max: i64) -> i64 { + (h_max / 540 - 1) * 540 - 20 +} + +impl ResizeableMosTile { + fn new(wxnf: i64, l: MosLength, kind: TileKind) -> Self { + Self { wxnf, l, kind } + } + fn max_nf(&self, w_max: i64) -> Option { + let mut nf = max_nf(w_max); + if nf > 0 { + loop { + if self.wxnf % nf == 0 { + break Some(nf); + } + nf -= 1; + } + } else { + None + } + } +} + +impl ResizableInstance for ResizeableMosTile { + type Tile = MosTile; + + fn wh_increments(&self) -> substrate::geometry::prelude::Dims { + Dims::new(430, 540) + } + + fn tile(&self, dims: substrate::geometry::prelude::Dims) -> Self::Tile { + let nf = self.max_nf(dims.w()).unwrap(); + let w = self.wxnf / nf; + MosTile::new(w, nf, self.l, self.kind) + } + + fn max_min_width(&self) -> i64 { + (self.wxnf / 420 + 1) * 430 + 860 + } + + fn min_height(&self, w_max: i64) -> Option { + let mut nf = max_nf(w_max); + if nf > 0 { + let nf = loop { + if self.wxnf % nf == 0 { + break nf; + } + nf -= 1; + }; + let w = self.wxnf / nf; + Some(((w + 20 - 1) / 540 + 2) * 540) + } else { + None + } + } +} + +/// A MOS tile. +#[derive(Block, Copy, Clone, Debug, Hash, PartialEq, Eq)] +#[substrate(io = "MosIo")] +pub struct MosTile { + w: i64, + nf: i64, + l: MosLength, + kind: TileKind, +} + +impl MosTile { + /// Creates a new [`MosTile`]. + pub fn new(w: i64, nf: i64, l: MosLength, kind: TileKind) -> Self { + Self { w, nf, l, kind } + } +} + +impl Tile for MosTile { + type Schema = Sky130; + type NestedData = (); + type LayoutBundle = View>; + type LayoutData = (); + + fn tile<'a>( + &self, + io: &'a substrate::types::schematic::IoNodeBundle, + cell: &mut TileBuilder<'a, Self::Schema>, + ) -> substrate::error::Result> { + cell.flatten(); + let (d, g, s, b) = match self.kind { + TileKind::P => { + let pmos = cell.generate_primitive(PmosTile::new(self.w, self.l, self.nf)); + let pmos = cell.draw(pmos)?; + cell.connect(pmos.schematic.io().b, io.b); + let mut d = PortGeometryBuilder::new(); + let mut g = PortGeometryBuilder::new(); + let mut s = PortGeometryBuilder::new(); + for i in 0..pmos.schematic.io().g.len() { + cell.connect(pmos.schematic.io().g[i], io.g); + g.merge(pmos.layout.io().g[i].clone()); + } + for i in 0..pmos.schematic.io().sd.len() { + cell.connect( + pmos.schematic.io().sd[i], + if i % 2 == 0 { io.s } else { io.d }, + ); + if i % 2 == 0 { + s.merge(pmos.layout.io().sd[i].clone()); + } else { + d.merge(pmos.layout.io().sd[i].clone()); + } + } + (d.build()?, g.build()?, s.build()?, pmos.layout.io().b) + } + TileKind::N => { + let nmos = cell.generate_primitive(NmosTile::new(self.w, self.l, self.nf)); + let nmos = cell.draw(nmos)?; + cell.connect(nmos.schematic.io().b, io.b); + let mut d = PortGeometryBuilder::new(); + let mut g = PortGeometryBuilder::new(); + let mut s = PortGeometryBuilder::new(); + for i in 0..nmos.schematic.io().g.len() { + cell.connect(nmos.schematic.io().g[i], io.g); + g.merge(nmos.layout.io().g[i].clone()); + } + for i in 0..nmos.schematic.io().sd.len() { + cell.connect( + nmos.schematic.io().sd[i], + if i % 2 == 0 { io.s } else { io.d }, + ); + if i % 2 == 0 { + s.merge(nmos.layout.io().sd[i].clone()); + } else { + d.merge(nmos.layout.io().sd[i].clone()); + } + } + (d.build()?, g.build()?, s.build()?, nmos.layout.io().b) + } + }; + + cell.set_top_layer(1); + cell.set_router(GreedyRouter::new()); + cell.set_via_maker(Sky130ViaMaker); + + Ok(TileData { + nested_data: (), + layout_bundle: MosIoView { d, g, s, b }, + layout_data: (), + outline: cell.layout.bbox_rect(), + }) + } +} + +/// A tile containing a N/P tap for biasing an N-well or P-substrate. +/// These can be used to connect to the body terminals of MOS devices. +#[derive(Debug, Clone, Copy, Hash, Eq, PartialEq)] +pub struct TapTile(TapTileParams); + +impl TapTile { + /// Creates a new [`TapTile`]. + pub fn new(params: TapTileParams) -> Self { + Self(params) + } +} + +impl Block for TapTile { + type Io = TapIo; + + fn name(&self) -> ArcStr { + arcstr::format!( + "{}tap_tile", + match self.0.kind { + TileKind::N => "n", + TileKind::P => "p", + } + ) + } + + fn io(&self) -> Self::Io { + Default::default() + } +} + +impl Tile for TapTile { + type Schema = Sky130; + type NestedData = (); + type LayoutBundle = View>; + type LayoutData = (); + + fn tile<'a>( + &self, + io: &'a substrate::types::schematic::IoNodeBundle, + cell: &mut TileBuilder<'a, Self::Schema>, + ) -> substrate::error::Result> { + cell.flatten(); + let (hspan, vspan) = match self.0.dir { + Dir::Horiz => (self.0.span, 2), + Dir::Vert => (2, self.0.span), + }; + let x = match self.0.kind { + TileKind::N => { + let inst = cell.generate_primitive(sky130::atoll::NtapTile::new(hspan - 1, vspan)); + cell.connect(io.x, inst.io().vpb); + let inst = cell.draw(inst)?; + inst.layout.io().vpb + } + TileKind::P => { + let inst = cell.generate_primitive(sky130::atoll::PtapTile::new(hspan - 1, vspan)); + cell.connect(io.x, inst.io().vnb); + let inst = cell.draw(inst)?; + inst.layout.io().vnb + } + }; + cell.set_router(GreedyRouter::new()); + Ok(TileData { + nested_data: (), + layout_bundle: TapIoView { x }, + layout_data: (), + outline: cell.layout.bbox_rect(), + }) + } +} + +#[cfg(test)] +mod tests { + use crate::tb::{ComparatorDecision, StrongArmTranTb}; + use crate::tech::sky130::Sky130Impl; + use crate::tiles::MosKind; + use crate::{InputKind, StrongArm, StrongArmParams}; + use atoll::TileWrapper; + use pegasus::lvs::LvsParams; + use pegasus::{ + drc::{run_drc, DrcParams}, + lvs::LvsStatus, + RuleCheck, + }; + use quantus::pex::Pex; + use rust_decimal::Decimal; + use rust_decimal_macros::dec; + use scir::netlist::ConvertibleNetlister; + use sky130::corner::Sky130Corner; + use sky130::{layout::to_gds, Sky130, Sky130CdsSchema}; + use spice::{netlist::NetlistOptions, Spice}; + use std::path::{Path, PathBuf}; + use std::sync::Arc; + use substrate::context::Context; + use substrate::geometry::dir::Dir; + use substrate::simulation::Pvt; + use substrate::{block::Block, schematic::ConvertSchema}; + + pub const SKY130_DRC: &str = concat!(env!("SKY130_CDS_PDK_ROOT"), "/Sky130_DRC"); + pub const SKY130_DRC_RULES_PATH: &str = concat!( + env!("SKY130_CDS_PDK_ROOT"), + "/Sky130_DRC/sky130_rev_0.0_1.0.drc.pvl", + ); + pub const SKY130_LVS: &str = concat!(env!("SKY130_CDS_PDK_ROOT"), "/Sky130_LVS"); + pub const SKY130_LVS_RULES_PATH: &str = + concat!(env!("SKY130_CDS_PDK_ROOT"), "/Sky130_LVS/sky130.lvs.pvl",); + pub const SKY130_TECHNOLOGY_DIR: &str = + concat!(env!("SKY130_CDS_PDK_ROOT"), "/quantus/extraction/typical",); + + pub const STRONGARM_PARAMS: StrongArmParams = StrongArmParams { + nmos_kind: MosKind::Nom, + pmos_kind: MosKind::Nom, + half_tail_w: 1_000, + input_pair_w: 1_000, + inv_input_w: 500, + inv_precharge_w: 500, + precharge_w: 500, + input_kind: InputKind::P, + h_max: 10_000, + dir: Dir::Vert, + }; + + pub const STRONGARM_PARAMS_1: StrongArmParams = StrongArmParams { + nmos_kind: MosKind::Nom, + pmos_kind: MosKind::Nom, + half_tail_w: 8_192, + input_pair_w: 2_048, + inv_input_w: 8_192, + inv_precharge_w: 4096, + precharge_w: 2_048, + input_kind: InputKind::P, + h_max: 40_000, + dir: Dir::Vert, + }; + + pub const STRONGARM_PARAMS_2: StrongArmParams = StrongArmParams { + nmos_kind: MosKind::Nom, + pmos_kind: MosKind::Nom, + half_tail_w: 8_192, + input_pair_w: 2_048, + inv_input_w: 8_192, + inv_precharge_w: 4096, + precharge_w: 2_048, + input_kind: InputKind::P, + h_max: 20_000, + dir: Dir::Vert, + }; + + pub const STRONGARM_PARAMS_3: StrongArmParams = StrongArmParams { + nmos_kind: MosKind::Nom, + pmos_kind: MosKind::Nom, + half_tail_w: 8_192, + input_pair_w: 2_048, + inv_input_w: 8_192, + inv_precharge_w: 4096, + precharge_w: 2_048, + input_kind: InputKind::P, + h_max: 15_000, + dir: Dir::Vert, + }; + + pub const STRONGARM_PARAMS_4: StrongArmParams = StrongArmParams { + nmos_kind: MosKind::Nom, + pmos_kind: MosKind::Nom, + half_tail_w: 8_192, + input_pair_w: 2_048, + inv_input_w: 8_192, + inv_precharge_w: 4096, + precharge_w: 2_048, + input_kind: InputKind::P, + h_max: 15_000, + dir: Dir::Horiz, + }; + + pub const STRONGARM_PARAMS_5: StrongArmParams = StrongArmParams { + nmos_kind: MosKind::Nom, + pmos_kind: MosKind::Nom, + half_tail_w: 8_192, + input_pair_w: 2_048, + inv_input_w: 8_192, + inv_precharge_w: 4096, + precharge_w: 2_048, + input_kind: InputKind::P, + h_max: 40_000, + dir: Dir::Horiz, + }; + + pub const STRONGARM_PARAMS_6: StrongArmParams = StrongArmParams { + nmos_kind: MosKind::Nom, + pmos_kind: MosKind::Nom, + half_tail_w: 8_192, + input_pair_w: 8_192, + inv_input_w: 8_192, + inv_precharge_w: 8_192, + precharge_w: 8_192, + input_kind: InputKind::N, + h_max: 8_000, + dir: Dir::Vert, + }; + + pub const STRONGARM_PARAMS_7: StrongArmParams = StrongArmParams { + nmos_kind: MosKind::Nom, + pmos_kind: MosKind::Nom, + half_tail_w: 8_192, + input_pair_w: 8_192, + inv_input_w: 8_192, + inv_precharge_w: 2_048, + precharge_w: 2_048, + input_kind: InputKind::N, + h_max: 40_000, + dir: Dir::Vert, + }; + + pub const STRONGARM_PARAMS_8: StrongArmParams = StrongArmParams { + nmos_kind: MosKind::Nom, + pmos_kind: MosKind::Nom, + half_tail_w: 8_192, + input_pair_w: 8_192, + inv_input_w: 8_192, + inv_precharge_w: 2_048, + precharge_w: 2_048, + input_kind: InputKind::N, + h_max: 20_000, + dir: Dir::Vert, + }; + + pub const STRONGARM_PARAMS_9: StrongArmParams = StrongArmParams { + nmos_kind: MosKind::Nom, + pmos_kind: MosKind::Nom, + half_tail_w: 8_192, + input_pair_w: 8_192, + inv_input_w: 8_192, + inv_precharge_w: 2_048, + precharge_w: 2_048, + input_kind: InputKind::N, + h_max: 15_000, + dir: Dir::Vert, + }; + + pub const STRONGARM_PARAMS_10: StrongArmParams = StrongArmParams { + nmos_kind: MosKind::Nom, + pmos_kind: MosKind::Nom, + half_tail_w: 8_192, + input_pair_w: 8_192, + inv_input_w: 8_192, + inv_precharge_w: 2_048, + precharge_w: 2_048, + input_kind: InputKind::N, + h_max: 15_000, + dir: Dir::Horiz, + }; + + pub const STRONGARM_PARAMS_11: StrongArmParams = StrongArmParams { + nmos_kind: MosKind::Nom, + pmos_kind: MosKind::Nom, + half_tail_w: 8_192, + input_pair_w: 8_192, + inv_input_w: 8_192, + inv_precharge_w: 2_048, + precharge_w: 2_048, + input_kind: InputKind::N, + h_max: 40_000, + dir: Dir::Horiz, + }; + + pub fn sky130_cds_ctx() -> Context { + let pdk_root = std::env::var("SKY130_CDS_PDK_ROOT") + .expect("the SKY130_CDS_PDK_ROOT environment variable must be set"); + Context::builder() + .install(spectre::Spectre::default()) + .install(Sky130::cds_only(pdk_root)) + .build() + } + + fn test_check_filter(check: &RuleCheck) -> bool { + !["licon.12", "hvnwell.8"].contains(&check.name.as_ref()) + } + + fn test_strongarm(work_dir: impl AsRef, extracted: bool) { + let work_dir = work_dir.as_ref(); + let input_kind = InputKind::P; + let dut = TileWrapper::new(StrongArm::::new(STRONGARM_PARAMS)); + let pvt = Pvt { + corner: Sky130Corner::Tt, + voltage: dec!(1.8), + temp: dec!(25.0), + }; + let ctx = sky130_cds_ctx(); + + for i in 0..=10 { + for j in [dec!(-0.1), dec!(-0.05), dec!(0.05), dec!(0.1)] { + let vinn = dec!(0.18) * Decimal::from(i); + let vinp = vinn + j; + + if vinp < dec!(0) || vinp > dec!(1.8) { + continue; + } + + match input_kind { + InputKind::P => { + if (vinp + vinn) / dec!(2) > dec!(1.2) { + continue; + } + } + InputKind::N => { + if (vinp + vinn) / dec!(2) < dec!(0.6) { + continue; + } + } + } + let work_dir = work_dir.join(format!("ofs_{i}_{j}")); + let decision = if extracted { + let layout_path = work_dir.join("layout.gds"); + ctx.write_layout(dut, to_gds, &layout_path) + .expect("failed to write layout"); + let tb = StrongArmTranTb::new( + Pex { + schematic: Arc::new(ConvertSchema::new(ConvertSchema::< + _, + Sky130CdsSchema, + >::new( + dut + ))), + gds_path: work_dir.join("layout.gds"), + layout_cell_name: dut.name(), + work_dir: work_dir.clone(), + lvs_rules_dir: PathBuf::from(SKY130_LVS), + lvs_rules_path: PathBuf::from(SKY130_LVS_RULES_PATH), + technology_dir: PathBuf::from(SKY130_TECHNOLOGY_DIR), + }, + vinp, + vinn, + input_kind.is_p(), + pvt, + ); + let sim = ctx + .get_sim_controller(tb.clone(), work_dir) + .expect("failed to get sim controller"); + tb.run(sim).expect("comparator output did not rail") + } else { + let tb = StrongArmTranTb::new( + ConvertSchema::<_, Sky130CdsSchema>::new(dut), + vinp, + vinn, + input_kind.is_p(), + pvt, + ); + let sim = ctx + .get_sim_controller(tb.clone(), work_dir) + .expect("failed to get sim controller"); + tb.run(sim).expect("comparator output did not rail") + }; + assert_eq!( + decision, + if j > dec!(0) { + ComparatorDecision::Pos + } else { + ComparatorDecision::Neg + }, + "comparator produced incorrect decision" + ); + } + } + } + + #[test] + fn sky130_strongarm_schematic_sim() { + let work_dir = concat!( + env!("CARGO_MANIFEST_DIR"), + "/build/sky130_strongarm_schematic_sim" + ); + test_strongarm(work_dir, false); + } + + #[test] + #[ignore = "long"] + fn sky130_strongarm_extracted_sim() { + let work_dir = concat!( + env!("CARGO_MANIFEST_DIR"), + "/build/sky130_strongarm_extracted_sim" + ); + test_strongarm(work_dir, true); + } + + fn test_sky130_strongarm_lvs(test_name: &'static str, params: StrongArmParams) { + let work_dir = PathBuf::from(concat!(env!("CARGO_MANIFEST_DIR"), "/build")).join(test_name); + let gds_path = work_dir.join("layout.gds"); + let netlist_path = work_dir.join("netlist.sp"); + let ctx = sky130_cds_ctx(); + + let block = TileWrapper::new(StrongArm::::new(params)); + let scir = ctx + .export_scir(block) + .unwrap() + .scir + .convert_schema::() + .unwrap() + .convert_schema::() + .unwrap() + .build() + .unwrap(); + Spice + .write_scir_netlist_to_file(&scir, &netlist_path, NetlistOptions::default()) + .expect("failed to write netlist"); + + ctx.write_layout(block, to_gds, &gds_path) + .expect("failed to write layout"); + + // Run DRC. + let drc_dir = work_dir.join("drc"); + let data = run_drc(&DrcParams { + work_dir: &drc_dir, + layout_path: &gds_path, + cell_name: &block.name(), + rules_dir: &PathBuf::from(SKY130_DRC), + rules_path: &PathBuf::from(SKY130_DRC_RULES_PATH), + }) + .expect("failed to run drc"); + + assert_eq!( + data.rule_checks + .into_iter() + .filter(test_check_filter) + .count(), + 0, + "layout was not DRC clean" + ); + + // Run LVS. + let lvs_dir = work_dir.join("lvs"); + let output = pegasus::lvs::run_lvs(&LvsParams { + work_dir: &lvs_dir, + layout_path: &gds_path, + layout_cell_name: &block.name(), + source_paths: &[netlist_path], + source_cell_name: &block.name(), + rules_dir: &PathBuf::from(SKY130_LVS), + rules_path: &PathBuf::from(SKY130_LVS_RULES_PATH), + }) + .expect("failed to run lvs"); + + assert_eq!( + output.status, + LvsStatus::Correct, + "layout does not match netlist" + ); + } + + #[test] + fn sky130_strongarm_lvs() { + test_sky130_strongarm_lvs("sky130_strongarm_lvs", STRONGARM_PARAMS); + } + + #[ignore] + #[test] + fn sky130_strongarm_lvs_resizing_1() { + test_sky130_strongarm_lvs("sky130_strongarm_lvs_1", STRONGARM_PARAMS_1); + } + #[ignore] + #[test] + fn sky130_strongarm_lvs_resizing_2() { + test_sky130_strongarm_lvs("sky130_strongarm_lvs_2", STRONGARM_PARAMS_2); + } + #[ignore] + #[test] + fn sky130_strongarm_lvs_resizing_3() { + test_sky130_strongarm_lvs("sky130_strongarm_lvs_3", STRONGARM_PARAMS_3); + } + #[ignore] + #[test] + fn sky130_strongarm_lvs_resizing_4() { + test_sky130_strongarm_lvs("sky130_strongarm_lvs_4", STRONGARM_PARAMS_4); + } + #[ignore] + #[test] + fn sky130_strongarm_lvs_resizing_5() { + test_sky130_strongarm_lvs("sky130_strongarm_lvs_5", STRONGARM_PARAMS_5); + } + #[ignore] + #[test] + fn sky130_strongarm_lvs_resizing_6() { + test_sky130_strongarm_lvs("sky130_strongarm_lvs_6", STRONGARM_PARAMS_6); + } + #[ignore] + #[test] + fn sky130_strongarm_lvs_resizing_7() { + test_sky130_strongarm_lvs("sky130_strongarm_lvs_7", STRONGARM_PARAMS_7); + } + #[ignore] + #[test] + fn sky130_strongarm_lvs_resizing_8() { + test_sky130_strongarm_lvs("sky130_strongarm_lvs_8", STRONGARM_PARAMS_8); + } + #[ignore] + #[test] + fn sky130_strongarm_lvs_resizing_9() { + test_sky130_strongarm_lvs("sky130_strongarm_lvs_9", STRONGARM_PARAMS_9); + } + #[ignore] + #[test] + fn sky130_strongarm_lvs_resizing_10() { + test_sky130_strongarm_lvs("sky130_strongarm_lvs_10", STRONGARM_PARAMS_10); + } + #[ignore] + #[test] + fn sky130_strongarm_lvs_resizing_11() { + test_sky130_strongarm_lvs("sky130_strongarm_lvs_11", STRONGARM_PARAMS_11); + } +} diff --git a/examples/release/strongarm/src/tiles.rs b/examples/release/strongarm/src/tiles.rs new file mode 100644 index 000000000..f2bcc6e53 --- /dev/null +++ b/examples/release/strongarm/src/tiles.rs @@ -0,0 +1,107 @@ +//! Tile definitions. + +use substrate::{ + geometry::dir::Dir, + types::{InOut, Io, Signal}, +}; + +/// MOS device kind. +#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq)] +pub enum MosKind { + /// Nominal Vt. + Nom, + /// Low Vt. + Lvt, + /// Ultra low Vt. + Ulvt, +} + +/// The IO of a tap. +#[derive(Default, Debug, Clone, Copy, Io)] +pub struct TapIo { + /// The tap contact. + pub x: InOut, +} + +/// The kind of tile. +#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq)] +pub enum TileKind { + /// An n-type tile. + N, + /// A p-type tile. + P, +} + +/// MOS tile parameters. +#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq)] +pub struct MosTileParams { + /// The flavor of MOS device. + pub mos_kind: MosKind, + /// Whether MOS is n-channel or p-channel. + pub tile_kind: TileKind, + /// The MOS device width. + pub w: i64, +} + +impl MosTileParams { + /// Creates a new [`MosTileParams`]. + pub fn new(mos_kind: MosKind, tile_kind: TileKind, w: i64) -> Self { + Self { + mos_kind, + tile_kind, + w, + } + } +} + +/// Tap tile parameters. +#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq)] +pub struct TapTileParams { + /// The kind of tap. + pub kind: TileKind, + /// The direction in which this tap extends. + pub dir: Dir, + /// Number of layer 0/1 tracks this horizontal/vertical tap must span. + pub span: i64, +} + +impl TapTileParams { + /// Creates a new [`TapTileParams`]. + pub fn new(kind: TileKind, dir: Dir, span: i64) -> Self { + Self { kind, dir, span } + } +} + +/// The IO of a resistor. +#[derive(Default, Debug, Clone, Copy, Io)] +pub struct ResistorIo { + /// The positive terminal. + pub p: InOut, + /// The negative terminal. + pub n: InOut, + /// The body terminal. + pub b: InOut, +} + +/// Resistor tile parameters. +#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq)] +pub struct ResistorTileParams { + /// Resistor length. + pub l: i64, +} + +impl ResistorTileParams { + /// Creates a new [`ResistorTileParams`]. + pub fn new(l: i64) -> Self { + Self { l } + } +} + +/// Resistor connection configurations. +#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq)] +pub enum ResistorConn { + /// Series. + Series, + /// Parallel. + Parallel, +} diff --git a/examples/release/substrate_api_examples/Cargo.toml b/examples/release/substrate_api_examples/Cargo.toml index 3119c82a3..c560f9731 100644 --- a/examples/release/substrate_api_examples/Cargo.toml +++ b/examples/release/substrate_api_examples/Cargo.toml @@ -5,8 +5,8 @@ edition = "2021" publish = false [dependencies] -substrate = { version = "0.10.2", registry = "substrate" } -scir = { version = "0.9.1", registry = "substrate" } +substrate = { version = "0.10.3", registry = "substrate" } +scir = { version = "0.9.2", registry = "substrate" } arcstr = "1" rust_decimal = "1" diff --git a/examples/release/vdivider/Cargo.toml b/examples/release/vdivider/Cargo.toml index 21a7da99f..c5a1b72d4 100644 --- a/examples/release/vdivider/Cargo.toml +++ b/examples/release/vdivider/Cargo.toml @@ -8,9 +8,9 @@ publish = false arcstr = { version = "1", features = ["serde"] } rust_decimal = "1" rust_decimal_macros = "1" -serde = { version = "1.0.217", features = ["derive"] } -substrate = { version = "0.10.2", registry = "substrate" } -spectre = { version = "0.11.2", registry = "substrate" } +serde = { version = "1.0.219", features = ["derive"] } +substrate = { version = "0.10.3", registry = "substrate" } +spectre = { version = "0.11.3", registry = "substrate" } [dev-dependencies] approx = "0.5" diff --git a/examples/release/via/Cargo.toml b/examples/release/via/Cargo.toml index 746673a76..12d735fbe 100644 --- a/examples/release/via/Cargo.toml +++ b/examples/release/via/Cargo.toml @@ -5,5 +5,5 @@ edition = "2021" publish = false [dependencies] -substrate = { version = "0.10.2", registry = "substrate" } -layir = { version = "0.2.1", registry = "substrate" } +substrate = { version = "0.10.3", registry = "substrate" } +layir = { version = "0.2.2", registry = "substrate" } diff --git a/libs/atoll/CHANGELOG.md b/libs/atoll/CHANGELOG.md index 9c2872215..5f346a223 100644 --- a/libs/atoll/CHANGELOG.md +++ b/libs/atoll/CHANGELOG.md @@ -12,6 +12,31 @@ * dependencies * substrate bumped from 0.8.0 to 0.8.1 +## [0.1.4](https://github.com/ucb-substrate/substrate2/compare/atoll-v0.1.3...atoll-v0.1.4) (2025-06-20) + + +### Features + +* **atoll:** port ATOLL to Substrate 2.1 ([#639](https://github.com/ucb-substrate/substrate2/issues/639)) ([dc2d4f2](https://github.com/ucb-substrate/substrate2/commit/dc2d4f2340e1dac822beb499b6d3dbec27002ec5)) +* **atoll:** tile resizing ([#655](https://github.com/ucb-substrate/substrate2/issues/655)) ([b9b65f0](https://github.com/ucb-substrate/substrate2/commit/b9b65f0f065f11f4ceb7499f7bf7f0f088c67480)) +* **examples:** ATOLL segment folder and sky130 examples ([#648](https://github.com/ucb-substrate/substrate2/issues/648)) ([cc809ae](https://github.com/ucb-substrate/substrate2/commit/cc809ae10e1b25f224f503e5a125a38e3e202be4)) +* **folding:** use Hopcroft-Karp algorithm for track matching ([#668](https://github.com/ucb-substrate/substrate2/issues/668)) ([d97a217](https://github.com/ucb-substrate/substrate2/commit/d97a217609f8d19b482e470592f51bee2fe1d927)) + + +### Bug Fixes + +* **deps:** update rust crate grid to 0.16.0 ([#649](https://github.com/ucb-substrate/substrate2/issues/649)) ([3875ea7](https://github.com/ucb-substrate/substrate2/commit/3875ea750229196998a8b7505971c36b5be64f62)) + + +### Dependencies + +* The following workspace dependencies were updated + * dependencies + * substrate bumped from 0.10.2 to 0.10.3 + * layir bumped from 0.2.1 to 0.2.2 + * enumify bumped from 0.2.1 to 0.2.2 + * cache bumped from 0.7.1 to 0.7.2 + ## 0.1.0 (2023-11-02) diff --git a/libs/atoll/Cargo.toml b/libs/atoll/Cargo.toml index f3246ad45..8b0acbc1d 100644 --- a/libs/atoll/Cargo.toml +++ b/libs/atoll/Cargo.toml @@ -1,14 +1,14 @@ [package] name = "atoll" -version = "0.1.3" +version = "0.1.4" edition = "2021" description = "Automatic transformation of logical layout" license = "BSD-3-Clause" [dependencies] -substrate = { version = "0.10.2", registry = "substrate", path = "../../substrate" } -layir = { version = "0.2.1", registry = "substrate", path = "../layir" } -enumify = { version = "0.2.1", registry = "substrate", path = "../enumify" } +substrate = { version = "0.10.3", registry = "substrate", path = "../../substrate" } +layir = { version = "0.2.2", registry = "substrate", path = "../layir" } +enumify = { version = "0.2.2", registry = "substrate", path = "../enumify" } grid = { version = "0.16.0", features = ["serde"] } ena = "0.14" tracing = "0.1" @@ -18,7 +18,7 @@ serde = { version = "1.0.192", features = ["derive"] } pathfinding = "4.8.0" indexmap = "2" rustc-hash = "1" -cache = { version = "0.7.1", registry = "substrate", path = "../cache" } +cache = { version = "0.7.2", registry = "substrate", path = "../cache" } arcstr = { version = "1.2.0", features = ["serde"] } itertools = "0.14.0" downcast-rs = "2" diff --git a/libs/cache/CHANGELOG.md b/libs/cache/CHANGELOG.md index afb532529..531a32845 100644 --- a/libs/cache/CHANGELOG.md +++ b/libs/cache/CHANGELOG.md @@ -1,5 +1,12 @@ # Changelog +## [0.7.2](https://github.com/ucb-substrate/substrate2/compare/cache-v0.7.1...cache-v0.7.2) (2025-06-20) + + +### Bug Fixes + +* **deps:** update tonic monorepo to 0.13 ([#642](https://github.com/ucb-substrate/substrate2/issues/642)) ([2b34382](https://github.com/ucb-substrate/substrate2/commit/2b34382d065141ef05f0c8998cd8de39bc4c6154)) + ## [0.7.1](https://github.com/ucb-substrate/substrate2/compare/cache-v0.7.0...cache-v0.7.1) (2025-01-24) diff --git a/libs/cache/Cargo.toml b/libs/cache/Cargo.toml index e434acf05..1a96a767d 100644 --- a/libs/cache/Cargo.toml +++ b/libs/cache/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "cache" -version = "0.7.1" +version = "0.7.2" edition = "2021" description = "A general purpose cache with possibly multiple remote servers for storing and retrieving data." license = "BSD-3-Clause" diff --git a/libs/enumify/CHANGELOG.md b/libs/enumify/CHANGELOG.md index 2887871c1..c96d336cb 100644 --- a/libs/enumify/CHANGELOG.md +++ b/libs/enumify/CHANGELOG.md @@ -8,6 +8,10 @@ * dependencies * enumify_macros bumped from 0.3.0 to 0.3.1 +* The following workspace dependencies were updated + * dependencies + * enumify_macros bumped from 0.3.1 to 0.3.2 + ## [0.2.0](https://github.com/ucb-substrate/substrate2/compare/enumify-v0.1.1...enumify-v0.2.0) (2025-01-23) diff --git a/libs/enumify/Cargo.toml b/libs/enumify/Cargo.toml index f23e488aa..46f2e5d47 100644 --- a/libs/enumify/Cargo.toml +++ b/libs/enumify/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "enumify" -version = "0.2.1" +version = "0.2.2" edition = "2021" [dependencies] -enumify_macros = { version = "0.3.1", registry = "substrate", path = "../enumify_macros" } +enumify_macros = { version = "0.3.2", registry = "substrate", path = "../enumify_macros" } diff --git a/libs/enumify_macros/CHANGELOG.md b/libs/enumify_macros/CHANGELOG.md index fe4b58716..10e0d000a 100644 --- a/libs/enumify_macros/CHANGELOG.md +++ b/libs/enumify_macros/CHANGELOG.md @@ -1,5 +1,12 @@ # Changelog +## [0.3.2](https://github.com/ucb-substrate/substrate2/compare/enumify_macros-v0.3.1...enumify_macros-v0.3.2) (2025-06-20) + + +### Bug Fixes + +* **deps:** update deps to latest versions ([#617](https://github.com/ucb-substrate/substrate2/issues/617)) ([ce3d243](https://github.com/ucb-substrate/substrate2/commit/ce3d243cbc10d64086939e44963e3cef591d6bda)) + ## [0.3.1](https://github.com/ucb-substrate/substrate2/compare/enumify_macros-v0.3.0...enumify_macros-v0.3.1) (2025-01-24) diff --git a/libs/enumify_macros/Cargo.toml b/libs/enumify_macros/Cargo.toml index 39d71e0e7..71179da8e 100644 --- a/libs/enumify_macros/Cargo.toml +++ b/libs/enumify_macros/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "enumify_macros" -version = "0.3.1" +version = "0.3.2" edition = "2021" description = "Macros for the enumify crate" license = "BSD-3-Clause" diff --git a/libs/gds/CHANGELOG.md b/libs/gds/CHANGELOG.md index 99d1932af..84da41af7 100644 --- a/libs/gds/CHANGELOG.md +++ b/libs/gds/CHANGELOG.md @@ -1,5 +1,18 @@ # Changelog +## [0.4.2](https://github.com/ucb-substrate/substrate2/compare/gds-v0.4.1...gds-v0.4.2) (2025-06-20) + + +### Features + +* **gds:** support importing GDS libraries into sky130 ([#583](https://github.com/ucb-substrate/substrate2/issues/583)) ([5e3181b](https://github.com/ucb-substrate/substrate2/commit/5e3181b1307e32a017126028fc15a13255129195)) +* **scir:** driver analysis handles opaque SCIR primitives correctly ([#636](https://github.com/ucb-substrate/substrate2/issues/636)) ([7dccba4](https://github.com/ucb-substrate/substrate2/commit/7dccba4da427b4b07b93b92d13ad9ecb1aef8512)) + + +### Bug Fixes + +* **deps:** update rust crate derive_more to v2 ([#573](https://github.com/ucb-substrate/substrate2/issues/573)) ([46be12c](https://github.com/ucb-substrate/substrate2/commit/46be12cd68038469f7986c10db6a2ad1beab3b05)) + ## [0.4.1](https://github.com/ucb-substrate/substrate2/compare/gds-v0.4.0...gds-v0.4.1) (2025-01-24) diff --git a/libs/gds/Cargo.toml b/libs/gds/Cargo.toml index bed0be9f3..d6705d9ea 100644 --- a/libs/gds/Cargo.toml +++ b/libs/gds/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "gds" -version = "0.4.1" +version = "0.4.2" edition = "2021" [dependencies] diff --git a/libs/gdsconv/CHANGELOG.md b/libs/gdsconv/CHANGELOG.md index 1c477245c..06baa5e11 100644 --- a/libs/gdsconv/CHANGELOG.md +++ b/libs/gdsconv/CHANGELOG.md @@ -1,5 +1,26 @@ # Changelog +## [0.2.2](https://github.com/ucb-substrate/substrate2/compare/gdsconv-v0.2.1...gdsconv-v0.2.2) (2025-06-20) + + +### Features + +* **gds:** convert GDS to generic layer type via FromGds trait ([#590](https://github.com/ucb-substrate/substrate2/issues/590)) ([1b98f28](https://github.com/ucb-substrate/substrate2/commit/1b98f289b4cd5b94f4248691b35bad8ec73b83c5)) + + +### Bug Fixes + +* **gds:** do not throw error on ports with missing labels ([#595](https://github.com/ucb-substrate/substrate2/issues/595)) ([014ef80](https://github.com/ucb-substrate/substrate2/commit/014ef80536c3e5a217da02344d44b3f524132105)) + + +### Dependencies + +* The following workspace dependencies were updated + * dependencies + * layir bumped from 0.2.1 to 0.2.2 + * gds bumped from 0.4.1 to 0.4.2 + * geometry bumped from 0.7.1 to 0.7.2 + ## [0.2.1](https://github.com/ucb-substrate/substrate2/compare/gdsconv-v0.2.0...gdsconv-v0.2.1) (2025-01-24) diff --git a/libs/gdsconv/Cargo.toml b/libs/gdsconv/Cargo.toml index f2841fc79..21a5bb966 100644 --- a/libs/gdsconv/Cargo.toml +++ b/libs/gdsconv/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "gdsconv" -version = "0.2.1" +version = "0.2.2" edition = "2021" [dependencies] @@ -10,6 +10,6 @@ slotmap = "1" serde = { version = "1", features = ["derive"] } thiserror = "2" -layir = { version = "0.2.1", registry = "substrate", path = "../layir" } -gds = { version = "0.4.1", registry = "substrate", path = "../gds" } -geometry = { version = "0.7.1", registry = "substrate", path = "../geometry" } +layir = { version = "0.2.2", registry = "substrate", path = "../layir" } +gds = { version = "0.4.2", registry = "substrate", path = "../gds" } +geometry = { version = "0.7.2", registry = "substrate", path = "../geometry" } diff --git a/libs/geometry/CHANGELOG.md b/libs/geometry/CHANGELOG.md index 138013084..a6737d17a 100644 --- a/libs/geometry/CHANGELOG.md +++ b/libs/geometry/CHANGELOG.md @@ -1,5 +1,12 @@ # Changelog +## [0.7.2](https://github.com/ucb-substrate/substrate2/compare/geometry-v0.7.1...geometry-v0.7.2) (2025-06-20) + + +### Bug Fixes + +* **polygon:** fix implementation of `Contains<Point>` for `Polygon` ([#592](https://github.com/ucb-substrate/substrate2/issues/592)) ([585f4e3](https://github.com/ucb-substrate/substrate2/commit/585f4e37a35d18e30348b86da598cb31710de19e)) + ## [0.7.1](https://github.com/ucb-substrate/substrate2/compare/geometry-v0.7.0...geometry-v0.7.1) (2025-01-24) diff --git a/libs/geometry/Cargo.toml b/libs/geometry/Cargo.toml index 324c31726..c6411451c 100644 --- a/libs/geometry/Cargo.toml +++ b/libs/geometry/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "geometry" -version = "0.7.1" +version = "0.7.2" edition = "2021" [dependencies] diff --git a/libs/layir/CHANGELOG.md b/libs/layir/CHANGELOG.md index 723c6865b..e7713c674 100644 --- a/libs/layir/CHANGELOG.md +++ b/libs/layir/CHANGELOG.md @@ -1,5 +1,24 @@ # Changelog +## [0.2.2](https://github.com/ucb-substrate/substrate2/compare/layir-v0.2.1...layir-v0.2.2) (2025-06-20) + + +### Features + +* **connectivity:** implement connectivity analysis for LayIR libraries ([#679](https://github.com/ucb-substrate/substrate2/issues/679)) ([7a55f75](https://github.com/ucb-substrate/substrate2/commit/7a55f753c14efd0d973d8ebca147991ed8b2030c)) +* **gds:** convert GDS to generic layer type via FromGds trait ([#590](https://github.com/ucb-substrate/substrate2/issues/590)) ([1b98f28](https://github.com/ucb-substrate/substrate2/commit/1b98f289b4cd5b94f4248691b35bad8ec73b83c5)) +* **gds:** support importing GDS libraries into sky130 ([#583](https://github.com/ucb-substrate/substrate2/issues/583)) ([5e3181b](https://github.com/ucb-substrate/substrate2/commit/5e3181b1307e32a017126028fc15a13255129195)) +* **stdcells:** implement layout for sky130 stdcells ([#586](https://github.com/ucb-substrate/substrate2/issues/586)) ([6e438ec](https://github.com/ucb-substrate/substrate2/commit/6e438ecde6b092231b4f9b6f17e3004663c17f74)) + + +### Dependencies + +* The following workspace dependencies were updated + * dependencies + * enumify bumped from 0.2.1 to 0.2.2 + * uniquify bumped from 0.4.0 to 0.4.1 + * geometry bumped from 0.7.1 to 0.7.2 + ## [0.2.1](https://github.com/ucb-substrate/substrate2/compare/layir-v0.2.0...layir-v0.2.1) (2025-01-24) diff --git a/libs/layir/Cargo.toml b/libs/layir/Cargo.toml index 764b1ad34..6895478a1 100644 --- a/libs/layir/Cargo.toml +++ b/libs/layir/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "layir" -version = "0.2.1" +version = "0.2.2" edition = "2021" [dependencies] @@ -10,8 +10,8 @@ serde = "1" indexmap = { version = "2", features = ["serde"] } thiserror = "2" -enumify = { version = "0.2.1", registry = "substrate", path = "../enumify" } -uniquify = { version = "0.4.0", registry = "substrate", path = "../uniquify" } -geometry = { version = "0.7.1", registry = "substrate", path = "../geometry" } +enumify = { version = "0.2.2", registry = "substrate", path = "../enumify" } +uniquify = { version = "0.4.1", registry = "substrate", path = "../uniquify" } +geometry = { version = "0.7.2", registry = "substrate", path = "../geometry" } aph_disjoint_set = "0.1.0" diff --git a/libs/lefdef/CHANGELOG.md b/libs/lefdef/CHANGELOG.md index 4c98c0e5c..2713f2cc9 100644 --- a/libs/lefdef/CHANGELOG.md +++ b/libs/lefdef/CHANGELOG.md @@ -4,6 +4,10 @@ * dependencies * geometry bumped from 0.7.0 to 0.7.1 +* The following workspace dependencies were updated + * dependencies + * geometry bumped from 0.7.1 to 0.7.2 + ## [0.2.0](https://github.com/ucb-substrate/substrate2/compare/lefdef-v0.1.0...lefdef-v0.2.0) (2025-01-23) diff --git a/libs/lefdef/Cargo.toml b/libs/lefdef/Cargo.toml index 93dbc8011..853e6469e 100644 --- a/libs/lefdef/Cargo.toml +++ b/libs/lefdef/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "lefdef" -version = "0.2.1" +version = "0.2.2" edition = "2021" [dependencies] -geometry = { version = "0.7.1", registry = "substrate", path = "../geometry" } +geometry = { version = "0.7.2", registry = "substrate", path = "../geometry" } diff --git a/libs/nutlex/CHANGELOG.md b/libs/nutlex/CHANGELOG.md index 17324959b..c89536dcc 100644 --- a/libs/nutlex/CHANGELOG.md +++ b/libs/nutlex/CHANGELOG.md @@ -1,5 +1,9 @@ # Changelog +* The following workspace dependencies were updated + * dependencies + * enumify bumped from 0.2.1 to 0.2.2 + ## [0.4.2](https://github.com/ucb-substrate/substrate2/compare/nutlex-v0.4.1...nutlex-v0.4.2) (2025-02-02) diff --git a/libs/nutlex/Cargo.toml b/libs/nutlex/Cargo.toml index cfef12e34..4376ec3d9 100644 --- a/libs/nutlex/Cargo.toml +++ b/libs/nutlex/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "nutlex" -version = "0.4.2" +version = "0.4.3" edition = "2021" description = "Parses SPICE nutmeg files (aka rawfiles)" @@ -9,7 +9,7 @@ nom = "8" serde = { version = "1", features = ["derive"] } thiserror = "2" -enumify = { version = "0.2.1", path = "../enumify", registry = "substrate" } +enumify = { version = "0.2.2", path = "../enumify", registry = "substrate" } [dev-dependencies] approx = "0.5" diff --git a/libs/psfparser/CHANGELOG.md b/libs/psfparser/CHANGELOG.md index c568bcf98..de9bddb9a 100644 --- a/libs/psfparser/CHANGELOG.md +++ b/libs/psfparser/CHANGELOG.md @@ -1,5 +1,24 @@ # Changelog +## [0.1.5](https://github.com/ucb-substrate/substrate2/compare/psfparser-v0.1.4...psfparser-v0.1.5) (2025-06-20) + + +### Features + +* **psf:** support parsing PSF files with sparse signal values ([#677](https://github.com/ucb-substrate/substrate2/issues/677)) ([d4718d3](https://github.com/ucb-substrate/substrate2/commit/d4718d38debdf70a253dd8437c66b3b7778d3681)) + + +### Bug Fixes + +* **psfparser:** read signal IDs in sweep value section ([#647](https://github.com/ucb-substrate/substrate2/issues/647)) ([3cc0c54](https://github.com/ucb-substrate/substrate2/commit/3cc0c540788c4e96999261c8c1f27acca5a031c9)) + + +### Dependencies + +* The following workspace dependencies were updated + * dependencies + * enumify bumped from 0.2.1 to 0.2.2 + ## [0.1.4](https://github.com/ucb-substrate/substrate2/compare/psfparser-v0.1.3...psfparser-v0.1.4) (2025-02-02) diff --git a/libs/psfparser/Cargo.toml b/libs/psfparser/Cargo.toml index fb556d9a6..bfe0e5d95 100644 --- a/libs/psfparser/Cargo.toml +++ b/libs/psfparser/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "psfparser" -version = "0.1.4" +version = "0.1.5" edition = "2021" description = "A PSF reader written in Rust" readme = "README.md" @@ -8,7 +8,7 @@ license = "BSD-3-Clause" exclude = ["/examples"] [dependencies] -enumify = { version = "0.2.1", path = "../enumify", registry = "substrate" } +enumify = { version = "0.2.2", path = "../enumify", registry = "substrate" } anyhow = "1" pest = "2" diff --git a/libs/scir/CHANGELOG.md b/libs/scir/CHANGELOG.md index a67860199..ddc46f790 100644 --- a/libs/scir/CHANGELOG.md +++ b/libs/scir/CHANGELOG.md @@ -1,5 +1,22 @@ # Changelog +## [0.9.2](https://github.com/ucb-substrate/substrate2/compare/scir-v0.9.1...scir-v0.9.2) (2025-06-20) + + +### Features + +* **scir:** driver analysis handles opaque SCIR primitives correctly ([#636](https://github.com/ucb-substrate/substrate2/issues/636)) ([7dccba4](https://github.com/ucb-substrate/substrate2/commit/7dccba4da427b4b07b93b92d13ad9ecb1aef8512)) +* **scir:** remove unused primitives when pruning SCIR libraries ([#658](https://github.com/ucb-substrate/substrate2/issues/658)) ([7536255](https://github.com/ucb-substrate/substrate2/commit/753625570bb6edce9e7637ca30d2d7f0225a7d21)) +* **scir:** support removing cells from `LibraryBuilder` ([#657](https://github.com/ucb-substrate/substrate2/issues/657)) ([eb57369](https://github.com/ucb-substrate/substrate2/commit/eb573691672c6109c41942811a9cdd1ffe75087b)) + + +### Dependencies + +* The following workspace dependencies were updated + * dependencies + * uniquify bumped from 0.4.0 to 0.4.1 + * enumify bumped from 0.2.1 to 0.2.2 + ## [0.9.1](https://github.com/ucb-substrate/substrate2/compare/scir-v0.9.0...scir-v0.9.1) (2025-01-24) diff --git a/libs/scir/Cargo.toml b/libs/scir/Cargo.toml index 9a37ad063..c43e4c7cb 100644 --- a/libs/scir/Cargo.toml +++ b/libs/scir/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "scir" -version = "0.9.1" +version = "0.9.2" edition = "2021" [dependencies] @@ -12,8 +12,8 @@ indexmap = { version = "2", features = ["serde"] } thiserror = "2" diagnostics = { version = "0.4.0", path = "../diagnostics", registry = "substrate" } -uniquify = { version = "0.4.0", path = "../uniquify", registry = "substrate" } -enumify = { version = "0.2.1", path = "../enumify", registry = "substrate" } +uniquify = { version = "0.4.1", path = "../uniquify", registry = "substrate" } +enumify = { version = "0.2.2", path = "../enumify", registry = "substrate" } [dev-dependencies] tracing-subscriber = { version = "0.3", features = ["env-filter", "fmt"] } diff --git a/libs/spice/CHANGELOG.md b/libs/spice/CHANGELOG.md index 9bbfbc5a3..bedccc227 100644 --- a/libs/spice/CHANGELOG.md +++ b/libs/spice/CHANGELOG.md @@ -4,6 +4,22 @@ * dependencies * substrate bumped from 0.8.0 to 0.8.1 +## [0.9.3](https://github.com/ucb-substrate/substrate2/compare/spice-v0.9.2...spice-v0.9.3) (2025-06-20) + + +### Features + +* **scir:** support removing cells from `LibraryBuilder` ([#657](https://github.com/ucb-substrate/substrate2/issues/657)) ([eb57369](https://github.com/ucb-substrate/substrate2/commit/eb573691672c6109c41942811a9cdd1ffe75087b)) + + +### Dependencies + +* The following workspace dependencies were updated + * dependencies + * scir bumped from 0.9.1 to 0.9.2 + * substrate bumped from 0.10.2 to 0.10.3 + * enumify bumped from 0.2.1 to 0.2.2 + ## [0.9.2](https://github.com/ucb-substrate/substrate2/compare/spice-v0.9.1...spice-v0.9.2) (2025-02-02) diff --git a/libs/spice/Cargo.toml b/libs/spice/Cargo.toml index 214a409d5..53c4419d1 100644 --- a/libs/spice/Cargo.toml +++ b/libs/spice/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "spice" -version = "0.9.2" +version = "0.9.3" edition = "2021" [dependencies] @@ -17,6 +17,6 @@ regex = "1" lazy_static = "1" num-traits = "0.2" -scir = { version = "0.9.1", registry = "substrate", path = "../scir" } -substrate = { version = "0.10.2", registry = "substrate", path = "../../substrate" } -enumify = { version = "0.2.1", registry = "substrate", path = "../enumify" } +scir = { version = "0.9.2", registry = "substrate", path = "../scir" } +substrate = { version = "0.10.3", registry = "substrate", path = "../../substrate" } +enumify = { version = "0.2.2", registry = "substrate", path = "../enumify" } diff --git a/libs/uniquify/CHANGELOG.md b/libs/uniquify/CHANGELOG.md index 2f779d1a8..af881f23d 100644 --- a/libs/uniquify/CHANGELOG.md +++ b/libs/uniquify/CHANGELOG.md @@ -1,5 +1,12 @@ # Changelog +## [0.4.1](https://github.com/ucb-substrate/substrate2/compare/uniquify-v0.4.0...uniquify-v0.4.1) (2025-06-20) + + +### Features + +* **scir:** support removing cells from `LibraryBuilder` ([#657](https://github.com/ucb-substrate/substrate2/issues/657)) ([eb57369](https://github.com/ucb-substrate/substrate2/commit/eb573691672c6109c41942811a9cdd1ffe75087b)) + ## [0.4.0](https://github.com/ucb-substrate/substrate2/compare/uniquify-v0.3.0...uniquify-v0.4.0) (2025-01-23) diff --git a/libs/uniquify/Cargo.toml b/libs/uniquify/Cargo.toml index 6070cc64b..ee885e6aa 100644 --- a/libs/uniquify/Cargo.toml +++ b/libs/uniquify/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "uniquify" -version = "0.4.0" +version = "0.4.1" edition = "2021" description = "A library for assigning unique names." license = "BSD-3-Clause" diff --git a/libs/verilog/CHANGELOG.md b/libs/verilog/CHANGELOG.md index 6535c02eb..86adab5bb 100644 --- a/libs/verilog/CHANGELOG.md +++ b/libs/verilog/CHANGELOG.md @@ -4,6 +4,10 @@ * dependencies * scir bumped from 0.9.0 to 0.9.1 +* The following workspace dependencies were updated + * dependencies + * scir bumped from 0.9.1 to 0.9.2 + ## [0.2.0](https://github.com/ucb-substrate/substrate2/compare/verilog-v0.1.0...verilog-v0.2.0) (2025-01-23) diff --git a/libs/verilog/Cargo.toml b/libs/verilog/Cargo.toml index d152fd39d..35201bc77 100644 --- a/libs/verilog/Cargo.toml +++ b/libs/verilog/Cargo.toml @@ -1,9 +1,9 @@ [package] name = "verilog" -version = "0.2.1" +version = "0.2.2" edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -scir = { version = "0.9.1", registry = "substrate", path = "../scir" } +scir = { version = "0.9.2", registry = "substrate", path = "../scir" } diff --git a/pdks/sky130/CHANGELOG.md b/pdks/sky130/CHANGELOG.md index 84d0dc5e8..707024df0 100644 --- a/pdks/sky130/CHANGELOG.md +++ b/pdks/sky130/CHANGELOG.md @@ -25,6 +25,35 @@ * ngspice bumped from 0.3.0 to 0.3.1 * spice bumped from 0.7.0 to 0.7.1 +## [0.10.3](https://github.com/ucb-substrate/substrate2/compare/sky130-v0.10.2...sky130-v0.10.3) (2025-06-20) + + +### Features + +* **atoll:** port ATOLL to Substrate 2.1 ([#639](https://github.com/ucb-substrate/substrate2/issues/639)) ([dc2d4f2](https://github.com/ucb-substrate/substrate2/commit/dc2d4f2340e1dac822beb499b6d3dbec27002ec5)) +* **atoll:** tile resizing ([#655](https://github.com/ucb-substrate/substrate2/issues/655)) ([b9b65f0](https://github.com/ucb-substrate/substrate2/commit/b9b65f0f065f11f4ceb7499f7bf7f0f088c67480)) +* **examples:** ATOLL segment folder and sky130 examples ([#648](https://github.com/ucb-substrate/substrate2/issues/648)) ([cc809ae](https://github.com/ucb-substrate/substrate2/commit/cc809ae10e1b25f224f503e5a125a38e3e202be4)) +* **gds:** convert GDS to generic layer type via FromGds trait ([#590](https://github.com/ucb-substrate/substrate2/issues/590)) ([1b98f28](https://github.com/ucb-substrate/substrate2/commit/1b98f289b4cd5b94f4248691b35bad8ec73b83c5)) +* **gds:** support importing GDS libraries into sky130 ([#583](https://github.com/ucb-substrate/substrate2/issues/583)) ([5e3181b](https://github.com/ucb-substrate/substrate2/commit/5e3181b1307e32a017126028fc15a13255129195)) +* **stdcells:** implement layout for sky130 stdcells ([#586](https://github.com/ucb-substrate/substrate2/issues/586)) ([6e438ec](https://github.com/ucb-substrate/substrate2/commit/6e438ecde6b092231b4f9b6f17e3004663c17f74)) + + +### Dependencies + +* The following workspace dependencies were updated + * dependencies + * atoll bumped from 0.1.3 to 0.1.4 + * substrate bumped from 0.10.2 to 0.10.3 + * scir bumped from 0.9.1 to 0.9.2 + * layir bumped from 0.2.1 to 0.2.2 + * gdsconv bumped from 0.2.1 to 0.2.2 + * gds bumped from 0.4.1 to 0.4.2 + * spectre bumped from 0.11.2 to 0.11.3 + * ngspice bumped from 0.5.2 to 0.5.3 + * quantus bumped from 0.2.2 to 0.2.3 + * spice bumped from 0.9.2 to 0.9.3 + * geometry bumped from 0.7.1 to 0.7.2 + ## [0.10.2](https://github.com/ucb-substrate/substrate2/compare/sky130-v0.10.1...sky130-v0.10.2) (2025-02-02) diff --git a/pdks/sky130/Cargo.toml b/pdks/sky130/Cargo.toml index f72e3c81c..186eebf8e 100644 --- a/pdks/sky130/Cargo.toml +++ b/pdks/sky130/Cargo.toml @@ -1,22 +1,22 @@ [package] name = "sky130" -version = "0.10.2" +version = "0.10.3" edition = "2021" [dependencies] -atoll = { version = "0.1.3", registry = "substrate", path = "../../libs/atoll" } -substrate = { version = "0.10.2", registry = "substrate", path = "../../substrate" } -scir = { version = "0.9.1", registry = "substrate", path = "../../libs/scir" } -layir = { version = "0.2.1", registry = "substrate", path = "../../libs/layir" } -gdsconv = { version = "0.2.1", registry = "substrate", path = "../../libs/gdsconv" } -gds = { version = "0.4.1", registry = "substrate", path = "../../libs/gds" } -spectre = { version = "0.11.2", registry = "substrate", path = "../../tools/spectre" } -ngspice = { version = "0.5.2", registry = "substrate", path = "../../tools/ngspice" } +atoll = { version = "0.1.4", registry = "substrate", path = "../../libs/atoll" } +substrate = { version = "0.10.3", registry = "substrate", path = "../../substrate" } +scir = { version = "0.9.2", registry = "substrate", path = "../../libs/scir" } +layir = { version = "0.2.2", registry = "substrate", path = "../../libs/layir" } +gdsconv = { version = "0.2.2", registry = "substrate", path = "../../libs/gdsconv" } +gds = { version = "0.4.2", registry = "substrate", path = "../../libs/gds" } +spectre = { version = "0.11.3", registry = "substrate", path = "../../tools/spectre" } +ngspice = { version = "0.5.3", registry = "substrate", path = "../../tools/ngspice" } pegasus = { version = "0.2.1", registry = "substrate", path = "../../tools/pegasus" } -quantus = { version = "0.2.2", registry = "substrate", path = "../../tools/quantus" } -spice = { version = "0.9.2", registry = "substrate", path = "../../libs/spice" } +quantus = { version = "0.2.3", registry = "substrate", path = "../../tools/quantus" } +spice = { version = "0.9.3", registry = "substrate", path = "../../libs/spice" } geometry_macros = { version = "0.1.1", registry = "substrate", path = "../../libs/geometry_macros" } -geometry = { version = "0.7.1", registry = "substrate", path = "../../libs/geometry" } +geometry = { version = "0.7.2", registry = "substrate", path = "../../libs/geometry" } rust_decimal = "1" rust_decimal_macros = "1" diff --git a/substrate/CHANGELOG.md b/substrate/CHANGELOG.md index 681adf1f9..7f49212de 100644 --- a/substrate/CHANGELOG.md +++ b/substrate/CHANGELOG.md @@ -28,6 +28,42 @@ * dependencies * codegen bumped from 0.10.1 to 0.10.2 +## [0.10.3](https://github.com/ucb-substrate/substrate2/compare/substrate-v0.10.2...substrate-v0.10.3) (2025-06-20) + + +### Features + +* **atoll:** port ATOLL to Substrate 2.1 ([#639](https://github.com/ucb-substrate/substrate2/issues/639)) ([dc2d4f2](https://github.com/ucb-substrate/substrate2/commit/dc2d4f2340e1dac822beb499b6d3dbec27002ec5)) +* **examples:** ATOLL segment folder and sky130 examples ([#648](https://github.com/ucb-substrate/substrate2/issues/648)) ([cc809ae](https://github.com/ucb-substrate/substrate2/commit/cc809ae10e1b25f224f503e5a125a38e3e202be4)) +* **simulation:** blanket implementation for saving ArrayBundles ([#607](https://github.com/ucb-substrate/substrate2/issues/607)) ([41f67ee](https://github.com/ucb-substrate/substrate2/commit/41f67ee509c6f1c21796835398c057edaffe2009)) +* **stdcells:** implement layout for sky130 stdcells ([#586](https://github.com/ucb-substrate/substrate2/issues/586)) ([6e438ec](https://github.com/ucb-substrate/substrate2/commit/6e438ecde6b092231b4f9b6f17e3004663c17f74)) +* **tiling:** expose raw tiles and allow tiling ArrayTilers ([#604](https://github.com/ucb-substrate/substrate2/issues/604)) ([4769a77](https://github.com/ucb-substrate/substrate2/commit/4769a77310606dc4a62b408556cea094da1cd531)) +* **waveform:** add offset parameter to `DigitalWaveformParams` ([#628](https://github.com/ucb-substrate/substrate2/issues/628)) ([3b590ca](https://github.com/ucb-substrate/substrate2/commit/3b590ca33936198b6729cbd4ba154ef766c6149a)) + + +### Bug Fixes + +* **schematic:** fix bug in direction wrapper type flattening ([#637](https://github.com/ucb-substrate/substrate2/issues/637)) ([04b373e](https://github.com/ucb-substrate/substrate2/commit/04b373e7acae179f9a77aad880df8b44b7d23a68)) +* **schematic:** support accessing nested PEX data even upon additional nesting ([#621](https://github.com/ucb-substrate/substrate2/issues/621)) ([c1a28c3](https://github.com/ucb-substrate/substrate2/commit/c1a28c3dd9c8261218e29d3295f79b55f5eec277)) + + +### Dependencies + +* The following workspace dependencies were updated + * dependencies + * config bumped from 0.4.1 to 0.4.2 + * cache bumped from 0.7.1 to 0.7.2 + * codegen bumped from 0.10.2 to 0.10.3 + * layir bumped from 0.2.1 to 0.2.2 + * geometry bumped from 0.7.1 to 0.7.2 + * gds bumped from 0.4.1 to 0.4.2 + * gdsconv bumped from 0.2.1 to 0.2.2 + * enumify bumped from 0.2.1 to 0.2.2 + * scir bumped from 0.9.1 to 0.9.2 + * uniquify bumped from 0.4.0 to 0.4.1 + * build-dependencies + * examples bumped from 0.2.0 to 0.2.1 + ## [0.10.1](https://github.com/ucb-substrate/substrate2/compare/substrate-v0.10.0...substrate-v0.10.1) (2025-01-24) diff --git a/substrate/Cargo.toml b/substrate/Cargo.toml index 085645ff9..17ae52e77 100644 --- a/substrate/Cargo.toml +++ b/substrate/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "substrate" -version = "0.10.2" +version = "0.10.3" edition = "2021" [dependencies] @@ -24,19 +24,19 @@ num = { version = "0.4", features = ["serde"] } splines = { version = "4", features = ["serde"] } derive-where = "1" -config = { version = "0.4.1", registry = "substrate", path = "../config" } +config = { version = "0.4.2", registry = "substrate", path = "../config" } snippets = { version = "0.7.0", registry = "substrate", path = "../docs/snippets" } -cache = { version = "0.7.1", registry = "substrate", path = "../libs/cache" } -codegen = { version = "0.10.2", registry = "substrate", path = "../codegen" } -layir = { version = "0.2.1", registry = "substrate", path = "../libs/layir" } -geometry = { version = "0.7.1", registry = "substrate", path = "../libs/geometry" } -gds = { version = "0.4.1", registry = "substrate", path = "../libs/gds" } -gdsconv = { version = "0.2.1", registry = "substrate", path = "../libs/gdsconv" } -enumify = { version = "0.2.1", registry = "substrate", path = "../libs/enumify" } -scir = { version = "0.9.1", registry = "substrate", path = "../libs/scir" } +cache = { version = "0.7.2", registry = "substrate", path = "../libs/cache" } +codegen = { version = "0.10.3", registry = "substrate", path = "../codegen" } +layir = { version = "0.2.2", registry = "substrate", path = "../libs/layir" } +geometry = { version = "0.7.2", registry = "substrate", path = "../libs/geometry" } +gds = { version = "0.4.2", registry = "substrate", path = "../libs/gds" } +gdsconv = { version = "0.2.2", registry = "substrate", path = "../libs/gdsconv" } +enumify = { version = "0.2.2", registry = "substrate", path = "../libs/enumify" } +scir = { version = "0.9.2", registry = "substrate", path = "../libs/scir" } pathtree = { version = "0.3.0", registry = "substrate", path = "../libs/pathtree" } type_dispatch = { version = "0.5.1", registry = "substrate", path = "../libs/type_dispatch" } -uniquify = { version = "0.4.0", registry = "substrate", path = "../libs/uniquify" } +uniquify = { version = "0.4.1", registry = "substrate", path = "../libs/uniquify" } [dev-dependencies] approx = "0.5" @@ -44,4 +44,4 @@ lazy_static = "1" [build-dependencies] snippets = { version = "0.7.0", registry = "substrate", path = "../docs/snippets" } -examples = { version = "0.2.0", registry = "substrate", path = "../examples" } +examples = { version = "0.2.1", registry = "substrate", path = "../examples" } diff --git a/tools/magic/CHANGELOG.md b/tools/magic/CHANGELOG.md index c9485e6dc..e70df69ee 100644 --- a/tools/magic/CHANGELOG.md +++ b/tools/magic/CHANGELOG.md @@ -1,5 +1,12 @@ # Changelog +## [0.2.2](https://github.com/ucb-substrate/substrate2/compare/magic-v0.2.1...magic-v0.2.2) (2025-06-20) + + +### Bug Fixes + +* **schematic:** fix bug in direction wrapper type flattening ([#637](https://github.com/ucb-substrate/substrate2/issues/637)) ([04b373e](https://github.com/ucb-substrate/substrate2/commit/04b373e7acae179f9a77aad880df8b44b7d23a68)) + ## [0.2.1](https://github.com/ucb-substrate/substrate2/compare/magic-v0.2.0...magic-v0.2.1) (2025-01-24) diff --git a/tools/magic/Cargo.toml b/tools/magic/Cargo.toml index e82d3e9cc..395db05a9 100644 --- a/tools/magic/Cargo.toml +++ b/tools/magic/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "magic" -version = "0.2.1" +version = "0.2.2" edition = "2021" [dependencies] diff --git a/tools/magic_netgen/CHANGELOG.md b/tools/magic_netgen/CHANGELOG.md index 8ece20134..fcf6f0acb 100644 --- a/tools/magic_netgen/CHANGELOG.md +++ b/tools/magic_netgen/CHANGELOG.md @@ -13,6 +13,23 @@ * spice bumped from 0.9.1 to 0.9.2 * netgen bumped from 0.2.0 to 0.2.1 +## [0.1.4](https://github.com/ucb-substrate/substrate2/compare/magic_netgen-v0.1.3...magic_netgen-v0.1.4) (2025-06-20) + + +### Bug Fixes + +* **schematic:** support accessing nested PEX data even upon additional nesting ([#621](https://github.com/ucb-substrate/substrate2/issues/621)) ([c1a28c3](https://github.com/ucb-substrate/substrate2/commit/c1a28c3dd9c8261218e29d3295f79b55f5eec277)) + + +### Dependencies + +* The following workspace dependencies were updated + * dependencies + * substrate bumped from 0.10.2 to 0.10.3 + * scir bumped from 0.9.1 to 0.9.2 + * spice bumped from 0.9.2 to 0.9.3 + * magic bumped from 0.2.1 to 0.2.2 + ## [0.1.1](https://github.com/ucb-substrate/substrate2/compare/magic_netgen-v0.1.0...magic_netgen-v0.1.1) (2025-01-23) diff --git a/tools/magic_netgen/Cargo.toml b/tools/magic_netgen/Cargo.toml index 3d4072c09..9f204e88e 100644 --- a/tools/magic_netgen/Cargo.toml +++ b/tools/magic_netgen/Cargo.toml @@ -1,11 +1,11 @@ [package] name = "magic_netgen" -version = "0.1.3" +version = "0.1.4" edition = "2021" [dependencies] -substrate = { version = "0.10.2", registry = "substrate", path = "../../substrate" } -scir = { version = "0.9.1", registry = "substrate", path = "../../libs/scir" } -spice = { version = "0.9.2", registry = "substrate", path = "../../libs/spice" } -magic = { version = "0.2.1", registry = "substrate", path = "../magic" } +substrate = { version = "0.10.3", registry = "substrate", path = "../../substrate" } +scir = { version = "0.9.2", registry = "substrate", path = "../../libs/scir" } +spice = { version = "0.9.3", registry = "substrate", path = "../../libs/spice" } +magic = { version = "0.2.2", registry = "substrate", path = "../magic" } netgen = { version = "0.2.1", registry = "substrate", path = "../netgen" } diff --git a/tools/ngspice/CHANGELOG.md b/tools/ngspice/CHANGELOG.md index 092668831..0156935f8 100644 --- a/tools/ngspice/CHANGELOG.md +++ b/tools/ngspice/CHANGELOG.md @@ -6,6 +6,24 @@ * nutlex bumped from 0.4.1 to 0.4.2 * spice bumped from 0.9.1 to 0.9.2 +## [0.5.3](https://github.com/ucb-substrate/substrate2/compare/ngspice-v0.5.2...ngspice-v0.5.3) (2025-06-20) + + +### Features + +* **ngspice:** save stdout and stderr to file ngspice.out ([#616](https://github.com/ucb-substrate/substrate2/issues/616)) ([dc8a6fd](https://github.com/ucb-substrate/substrate2/commit/dc8a6fd6234efa6c9bbb6ee735aa15b35d484300)) + + +### Dependencies + +* The following workspace dependencies were updated + * dependencies + * cache bumped from 0.7.1 to 0.7.2 + * scir bumped from 0.9.1 to 0.9.2 + * substrate bumped from 0.10.2 to 0.10.3 + * nutlex bumped from 0.4.2 to 0.4.3 + * spice bumped from 0.9.2 to 0.9.3 + ## [0.5.1](https://github.com/ucb-substrate/substrate2/compare/ngspice-v0.5.0...ngspice-v0.5.1) (2025-01-24) diff --git a/tools/ngspice/Cargo.toml b/tools/ngspice/Cargo.toml index 423a2e862..7385d0c3d 100644 --- a/tools/ngspice/Cargo.toml +++ b/tools/ngspice/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "ngspice" -version = "0.5.2" +version = "0.5.3" edition = "2021" [dependencies] @@ -15,11 +15,11 @@ tracing = "0.1" indexmap = { version = "2", features = ["serde"] } unicase = "2" -cache = { version = "0.7.1", registry = "substrate", path = "../../libs/cache" } -scir = { version = "0.9.1", registry = "substrate", path = "../../libs/scir" } -substrate = { version = "0.10.2", registry = "substrate", path = "../../substrate" } -nutlex = { version = "0.4.2", registry = "substrate", path = "../../libs/nutlex" } -spice = { version = "0.9.2", registry = "substrate", path = "../../libs/spice" } +cache = { version = "0.7.2", registry = "substrate", path = "../../libs/cache" } +scir = { version = "0.9.2", registry = "substrate", path = "../../libs/scir" } +substrate = { version = "0.10.3", registry = "substrate", path = "../../substrate" } +nutlex = { version = "0.4.3", registry = "substrate", path = "../../libs/nutlex" } +spice = { version = "0.9.3", registry = "substrate", path = "../../libs/spice" } [dev-dependencies] approx = "0.5" diff --git a/tools/quantus/CHANGELOG.md b/tools/quantus/CHANGELOG.md index 5b8676c45..1ce93c9c3 100644 --- a/tools/quantus/CHANGELOG.md +++ b/tools/quantus/CHANGELOG.md @@ -1,5 +1,21 @@ # Changelog +## [0.2.3](https://github.com/ucb-substrate/substrate2/compare/quantus-v0.2.2...quantus-v0.2.3) (2025-06-20) + + +### Bug Fixes + +* **schematic:** support accessing nested PEX data even upon additional nesting ([#621](https://github.com/ucb-substrate/substrate2/issues/621)) ([c1a28c3](https://github.com/ucb-substrate/substrate2/commit/c1a28c3dd9c8261218e29d3295f79b55f5eec277)) + + +### Dependencies + +* The following workspace dependencies were updated + * dependencies + * substrate bumped from 0.10.2 to 0.10.3 + * scir bumped from 0.9.1 to 0.9.2 + * spice bumped from 0.9.2 to 0.9.3 + ## [0.2.2](https://github.com/ucb-substrate/substrate2/compare/quantus-v0.2.1...quantus-v0.2.2) (2025-02-02) diff --git a/tools/quantus/Cargo.toml b/tools/quantus/Cargo.toml index 9dcc15d5f..aa8e149c8 100644 --- a/tools/quantus/Cargo.toml +++ b/tools/quantus/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "quantus" -version = "0.2.2" +version = "0.2.3" edition = "2021" [dependencies] @@ -10,9 +10,9 @@ serde = { version = "1", features = ["derive"] } anyhow = "1" regex = "1" -substrate = { version = "0.10.2", registry = "substrate", path = "../../substrate" } -scir = { version = "0.9.1", registry = "substrate", path = "../../libs/scir" } -spice = { version = "0.9.2", registry = "substrate", path = "../../libs/spice" } +substrate = { version = "0.10.3", registry = "substrate", path = "../../substrate" } +scir = { version = "0.9.2", registry = "substrate", path = "../../libs/scir" } +spice = { version = "0.9.3", registry = "substrate", path = "../../libs/spice" } pegasus = { version = "0.2.1", registry = "substrate", path = "../pegasus" } [dev-dependencies] diff --git a/tools/spectre/CHANGELOG.md b/tools/spectre/CHANGELOG.md index e21620de8..4ccd21e54 100644 --- a/tools/spectre/CHANGELOG.md +++ b/tools/spectre/CHANGELOG.md @@ -8,6 +8,29 @@ * dependencies * substrate bumped from 0.6.0 to 0.6.1 +## [0.11.3](https://github.com/ucb-substrate/substrate2/compare/spectre-v0.11.2...spectre-v0.11.3) (2025-06-20) + + +### Features + +* **spectre:** add support for IBIS model includes ([#591](https://github.com/ucb-substrate/substrate2/issues/591)) ([8ec582f](https://github.com/ucb-substrate/substrate2/commit/8ec582f7088c3c863fba1db2ed899dd1a25bab54)) + + +### Bug Fixes + +* **spectre:** save spectre stdin and stderr to spectre.out ([#615](https://github.com/ucb-substrate/substrate2/issues/615)) ([9ca3cf9](https://github.com/ucb-substrate/substrate2/commit/9ca3cf9975e170f20645d2e6a9de47cc7f19b37e)) + + +### Dependencies + +* The following workspace dependencies were updated + * dependencies + * cache bumped from 0.7.1 to 0.7.2 + * psfparser bumped from 0.1.4 to 0.1.5 + * scir bumped from 0.9.1 to 0.9.2 + * substrate bumped from 0.10.2 to 0.10.3 + * spice bumped from 0.9.2 to 0.9.3 + ## [0.11.2](https://github.com/ucb-substrate/substrate2/compare/spectre-v0.11.1...spectre-v0.11.2) (2025-02-02) diff --git a/tools/spectre/Cargo.toml b/tools/spectre/Cargo.toml index 8c8038951..e0f0a2b50 100644 --- a/tools/spectre/Cargo.toml +++ b/tools/spectre/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "spectre" -version = "0.11.2" +version = "0.11.3" edition = "2021" [dependencies] @@ -16,11 +16,11 @@ itertools = "0.14" regex = "1" num = { version = "0.4", features = ["serde"] } -cache = { version = "0.7.1", registry = "substrate", path = "../../libs/cache" } -psfparser = { version = "0.1.4", registry = "substrate", path = "../../libs/psfparser" } -scir = { version = "0.9.1", registry = "substrate", path = "../../libs/scir" } -substrate = { version = "0.10.2", registry = "substrate", path = "../../substrate" } -spice = { version = "0.9.2", registry = "substrate", path = "../../libs/spice" } +cache = { version = "0.7.2", registry = "substrate", path = "../../libs/cache" } +psfparser = { version = "0.1.5", registry = "substrate", path = "../../libs/psfparser" } +scir = { version = "0.9.2", registry = "substrate", path = "../../libs/scir" } +substrate = { version = "0.10.3", registry = "substrate", path = "../../substrate" } +spice = { version = "0.9.3", registry = "substrate", path = "../../libs/spice" } type_dispatch = { version = "0.5.1", registry = "substrate", path = "../../libs/type_dispatch" } [dev-dependencies]