layout-canvas 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (140) hide show
  1. layout_canvas-0.1.0/.dockerignore +13 -0
  2. layout_canvas-0.1.0/.github/workflows/ci.yml +46 -0
  3. layout_canvas-0.1.0/.github/workflows/release.yml +87 -0
  4. layout_canvas-0.1.0/.gitignore +48 -0
  5. layout_canvas-0.1.0/AGENTS.md +19 -0
  6. layout_canvas-0.1.0/CONTRIBUTING.md +72 -0
  7. layout_canvas-0.1.0/LICENSE +21 -0
  8. layout_canvas-0.1.0/NOTICE +23 -0
  9. layout_canvas-0.1.0/PKG-INFO +184 -0
  10. layout_canvas-0.1.0/README.md +151 -0
  11. layout_canvas-0.1.0/deploy/Dockerfile +35 -0
  12. layout_canvas-0.1.0/deploy/cloudflare/wrangler.toml +10 -0
  13. layout_canvas-0.1.0/deploy/compose.yaml +35 -0
  14. layout_canvas-0.1.0/docs/.assetsignore +2 -0
  15. layout_canvas-0.1.0/docs/ARCH_MEMORY.md +55 -0
  16. layout_canvas-0.1.0/docs/CADENCE_INTEGRATION.md +111 -0
  17. layout_canvas-0.1.0/docs/COMMERCIAL.md +53 -0
  18. layout_canvas-0.1.0/docs/DEPLOYMENT.md +75 -0
  19. layout_canvas-0.1.0/docs/EXTERNAL_TOOLS.md +159 -0
  20. layout_canvas-0.1.0/docs/PDK_DESCRIPTORS.md +232 -0
  21. layout_canvas-0.1.0/docs/PRODUCT_PLAN_ANALOG_CANVAS.md +177 -0
  22. layout_canvas-0.1.0/docs/RELEASING.md +66 -0
  23. layout_canvas-0.1.0/docs/USAGE.md +403 -0
  24. layout_canvas-0.1.0/docs/VIRTUOSO_ACCEPTANCE.md +140 -0
  25. layout_canvas-0.1.0/docs/WORK_PLAN.md +85 -0
  26. layout_canvas-0.1.0/docs/adr/0001-transactional-edit-session.md +44 -0
  27. layout_canvas-0.1.0/docs/adr/0002-fail-closed-verification.md +30 -0
  28. layout_canvas-0.1.0/docs/adr/0003-explicit-connectivity-projection.md +34 -0
  29. layout_canvas-0.1.0/docs/adr/0004-project-file-protocol.md +28 -0
  30. layout_canvas-0.1.0/docs/adr/0005-simulation-is-fail-closed.md +33 -0
  31. layout_canvas-0.1.0/docs/adr/0006-pdk-descriptor-and-cell-abstract.md +31 -0
  32. layout_canvas-0.1.0/docs/adr/0007-hierarchical-cell-reuse.md +41 -0
  33. layout_canvas-0.1.0/docs/adr/0008-pluggable-tool-adapters.md +38 -0
  34. layout_canvas-0.1.0/docs/adr/0009-deployment-architecture.md +41 -0
  35. layout_canvas-0.1.0/docs/index.html +603 -0
  36. layout_canvas-0.1.0/examples/diffamp.json +129 -0
  37. layout_canvas-0.1.0/examples/models/illustrative_mos.lib +15 -0
  38. layout_canvas-0.1.0/examples/models/sky130/sky130_fd_pr__nfet_01v8__tt.corner.spice +1476 -0
  39. layout_canvas-0.1.0/examples/models/sky130/sky130_fd_pr__nfet_01v8__tt.pm3.spice +48274 -0
  40. layout_canvas-0.1.0/examples/models/sky130/sky130_fd_pr__parameters__invariant.spice +7342 -0
  41. layout_canvas-0.1.0/examples/models/sky130/sky130_fd_pr__parameters__lod.spice +76 -0
  42. layout_canvas-0.1.0/examples/models/sky130/sky130_fd_pr__parameters__typical.spice +3025 -0
  43. layout_canvas-0.1.0/examples/models/sky130/sky130_fd_pr__pfet_01v8__tt.corner.spice +20 -0
  44. layout_canvas-0.1.0/examples/models/sky130/sky130_fd_pr__pfet_01v8__tt.pm3.spice +29628 -0
  45. layout_canvas-0.1.0/examples/models/sky130/sky130_tt.lib +10 -0
  46. layout_canvas-0.1.0/examples/ota_lab.json +108 -0
  47. layout_canvas-0.1.0/klayout/grain.xml +9 -0
  48. layout_canvas-0.1.0/klayout/pymacros/block_canvas.lym +57 -0
  49. layout_canvas-0.1.0/klayout/python/block_canvas_plugin.py +331 -0
  50. layout_canvas-0.1.0/pyproject.toml +56 -0
  51. layout_canvas-0.1.0/skills/layout-canvas/SKILL.md +139 -0
  52. layout_canvas-0.1.0/src/layout_canvas/__init__.py +14 -0
  53. layout_canvas-0.1.0/src/layout_canvas/blocks/__init__.py +25 -0
  54. layout_canvas-0.1.0/src/layout_canvas/blocks/base.py +184 -0
  55. layout_canvas-0.1.0/src/layout_canvas/blocks/cells.py +70 -0
  56. layout_canvas-0.1.0/src/layout_canvas/blocks/gds_cell.py +222 -0
  57. layout_canvas-0.1.0/src/layout_canvas/blocks/generic.py +949 -0
  58. layout_canvas-0.1.0/src/layout_canvas/blocks/ihp_sg13g2/__init__.py +17 -0
  59. layout_canvas-0.1.0/src/layout_canvas/blocks/ihp_sg13g2/current_mirror.py +224 -0
  60. layout_canvas-0.1.0/src/layout_canvas/blocks/ihp_sg13g2/diff_pair.py +244 -0
  61. layout_canvas-0.1.0/src/layout_canvas/blocks/ihp_sg13g2/geom.py +41 -0
  62. layout_canvas-0.1.0/src/layout_canvas/blocks/ihp_sg13g2/guard_ring.py +100 -0
  63. layout_canvas-0.1.0/src/layout_canvas/blocks/ihp_sg13g2/layers.py +35 -0
  64. layout_canvas-0.1.0/src/layout_canvas/blocks/ihp_sg13g2/ota_5t.py +413 -0
  65. layout_canvas-0.1.0/src/layout_canvas/blocks/sky130/__init__.py +25 -0
  66. layout_canvas-0.1.0/src/layout_canvas/blocks/sky130/cap_array.py +137 -0
  67. layout_canvas-0.1.0/src/layout_canvas/blocks/sky130/current_mirror.py +269 -0
  68. layout_canvas-0.1.0/src/layout_canvas/blocks/sky130/diff_pair.py +306 -0
  69. layout_canvas-0.1.0/src/layout_canvas/blocks/sky130/geom.py +58 -0
  70. layout_canvas-0.1.0/src/layout_canvas/blocks/sky130/guard_ring.py +244 -0
  71. layout_canvas-0.1.0/src/layout_canvas/blocks/sky130/layers.py +41 -0
  72. layout_canvas-0.1.0/src/layout_canvas/blocks/sky130/ota_5t.py +476 -0
  73. layout_canvas-0.1.0/src/layout_canvas/blocks/sky130/strongarm.py +497 -0
  74. layout_canvas-0.1.0/src/layout_canvas/cli.py +457 -0
  75. layout_canvas-0.1.0/src/layout_canvas/compiler/__init__.py +6 -0
  76. layout_canvas-0.1.0/src/layout_canvas/compiler/compile.py +233 -0
  77. layout_canvas-0.1.0/src/layout_canvas/compiler/hierarchy.py +61 -0
  78. layout_canvas-0.1.0/src/layout_canvas/compiler/netlist.py +182 -0
  79. layout_canvas-0.1.0/src/layout_canvas/compiler/netlist_import.py +635 -0
  80. layout_canvas-0.1.0/src/layout_canvas/compiler/optimizer.py +59 -0
  81. layout_canvas-0.1.0/src/layout_canvas/compiler/ppa.py +101 -0
  82. layout_canvas-0.1.0/src/layout_canvas/compiler/render.py +120 -0
  83. layout_canvas-0.1.0/src/layout_canvas/compiler/router.py +533 -0
  84. layout_canvas-0.1.0/src/layout_canvas/compiler/virtuoso.py +297 -0
  85. layout_canvas-0.1.0/src/layout_canvas/derived/__init__.py +5 -0
  86. layout_canvas-0.1.0/src/layout_canvas/derived/connectivity.py +100 -0
  87. layout_canvas-0.1.0/src/layout_canvas/engine/__init__.py +15 -0
  88. layout_canvas-0.1.0/src/layout_canvas/engine/edits.py +281 -0
  89. layout_canvas-0.1.0/src/layout_canvas/engine/envelope.py +61 -0
  90. layout_canvas-0.1.0/src/layout_canvas/engine/optimize.py +335 -0
  91. layout_canvas-0.1.0/src/layout_canvas/engine/session.py +117 -0
  92. layout_canvas-0.1.0/src/layout_canvas/ir/__init__.py +37 -0
  93. layout_canvas-0.1.0/src/layout_canvas/ir/model.py +228 -0
  94. layout_canvas-0.1.0/src/layout_canvas/mcp/__init__.py +12 -0
  95. layout_canvas-0.1.0/src/layout_canvas/mcp/bridge.py +172 -0
  96. layout_canvas-0.1.0/src/layout_canvas/mcp/server.py +1275 -0
  97. layout_canvas-0.1.0/src/layout_canvas/pdk/__init__.py +27 -0
  98. layout_canvas-0.1.0/src/layout_canvas/pdk/descriptor.py +639 -0
  99. layout_canvas-0.1.0/src/layout_canvas/protocol/__init__.py +19 -0
  100. layout_canvas-0.1.0/src/layout_canvas/protocol/project.py +157 -0
  101. layout_canvas-0.1.0/src/layout_canvas/tools/__init__.py +6 -0
  102. layout_canvas-0.1.0/src/layout_canvas/tools/backends.py +294 -0
  103. layout_canvas-0.1.0/src/layout_canvas/tools/drc.py +290 -0
  104. layout_canvas-0.1.0/src/layout_canvas/tools/extract.py +405 -0
  105. layout_canvas-0.1.0/src/layout_canvas/tools/lvs.py +334 -0
  106. layout_canvas-0.1.0/src/layout_canvas/tools/sim.py +827 -0
  107. layout_canvas-0.1.0/src/layout_canvas/tools/testbench.py +264 -0
  108. layout_canvas-0.1.0/src/layout_canvas/tools/verify.py +53 -0
  109. layout_canvas-0.1.0/src/layout_canvas/tools/virtuoso_check.py +844 -0
  110. layout_canvas-0.1.0/src/layout_canvas/web/__init__.py +5 -0
  111. layout_canvas-0.1.0/src/layout_canvas/web/app.py +472 -0
  112. layout_canvas-0.1.0/src/layout_canvas/web/gallery.py +229 -0
  113. layout_canvas-0.1.0/src/layout_canvas/web/page.py +893 -0
  114. layout_canvas-0.1.0/tests/test_backends.py +56 -0
  115. layout_canvas-0.1.0/tests/test_blocks.py +75 -0
  116. layout_canvas-0.1.0/tests/test_compiler.py +160 -0
  117. layout_canvas-0.1.0/tests/test_e2e.py +37 -0
  118. layout_canvas-0.1.0/tests/test_engine.py +239 -0
  119. layout_canvas-0.1.0/tests/test_gallery.py +126 -0
  120. layout_canvas-0.1.0/tests/test_gds_cell.py +201 -0
  121. layout_canvas-0.1.0/tests/test_generic_blocks.py +392 -0
  122. layout_canvas-0.1.0/tests/test_guard_ring.py +31 -0
  123. layout_canvas-0.1.0/tests/test_ihp_sg13g2.py +120 -0
  124. layout_canvas-0.1.0/tests/test_ir.py +118 -0
  125. layout_canvas-0.1.0/tests/test_mcp.py +166 -0
  126. layout_canvas-0.1.0/tests/test_mcp_e2e.py +165 -0
  127. layout_canvas-0.1.0/tests/test_netlist.py +38 -0
  128. layout_canvas-0.1.0/tests/test_netlist_import.py +208 -0
  129. layout_canvas-0.1.0/tests/test_optimize_and_cells.py +353 -0
  130. layout_canvas-0.1.0/tests/test_pdk.py +25 -0
  131. layout_canvas-0.1.0/tests/test_pdk_external.py +454 -0
  132. layout_canvas-0.1.0/tests/test_protocol.py +63 -0
  133. layout_canvas-0.1.0/tests/test_pya_verification.py +133 -0
  134. layout_canvas-0.1.0/tests/test_router.py +37 -0
  135. layout_canvas-0.1.0/tests/test_sim.py +197 -0
  136. layout_canvas-0.1.0/tests/test_testbench.py +387 -0
  137. layout_canvas-0.1.0/tests/test_tools.py +29 -0
  138. layout_canvas-0.1.0/tests/test_virtuoso.py +140 -0
  139. layout_canvas-0.1.0/tests/test_virtuoso_check.py +453 -0
  140. layout_canvas-0.1.0/tests/test_web.py +211 -0
@@ -0,0 +1,13 @@
1
+ .git
2
+ .venv
3
+ venv
4
+ __pycache__
5
+ *.pyc
6
+ .tmp_*
7
+ tests/
8
+ docs/
9
+ klayout/
10
+ *.gds
11
+ *.oas
12
+ .claude
13
+ .codeium
@@ -0,0 +1,46 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ pull_request:
7
+ branches: [main]
8
+
9
+ jobs:
10
+ test:
11
+ runs-on: ubuntu-latest
12
+ strategy:
13
+ matrix:
14
+ python-version: ["3.11", "3.12"]
15
+
16
+ steps:
17
+ - uses: actions/checkout@v4
18
+
19
+ - name: Set up Python ${{ matrix.python-version }}
20
+ uses: actions/setup-python@v5
21
+ with:
22
+ python-version: ${{ matrix.python-version }}
23
+ cache: "pip"
24
+
25
+ - name: Install dependencies
26
+ run: |
27
+ python -m pip install --upgrade pip
28
+ pip install -e ".[dev]"
29
+
30
+ - name: Lint with ruff
31
+ run: |
32
+ ruff check src tests
33
+
34
+ - name: Validate Block IR JSON Schema
35
+ run: |
36
+ layout-canvas schema > block_ir_schema.json
37
+ python -c "import json, jsonschema; schema=json.load(open('block_ir_schema.json')); doc=json.load(open('examples/diffamp.json')); jsonschema.validate(doc, schema); print('Schema validation passed!')"
38
+
39
+ - name: Test Block compilation and export
40
+ run: |
41
+ layout-canvas list-blocks
42
+ layout-canvas compile examples/diffamp.json --out diffamp.gds
43
+
44
+ - name: Run test suite
45
+ run: |
46
+ pytest -v --tb=short
@@ -0,0 +1,87 @@
1
+ # Release pipeline: tag v* → build → verify → PyPI (OIDC trusted
2
+ # publishing, no stored secrets) + GitHub Release with the wheel attached.
3
+ #
4
+ # One-time setup (documented in docs/RELEASING.md):
5
+ # 1. PyPI → Account → Publishing → "add a new pending publisher":
6
+ # owner=Kairos2425 repo=layout-canvas workflow=release.yml
7
+ # environment=pypi
8
+ # 2. GitHub repo → Settings → Environments → new environment "pypi"
9
+ # (optional: require a reviewer before publish runs)
10
+ #
11
+ # Manual `workflow_dispatch` runs build+check only — the publish and
12
+ # github-release jobs are gated on refs/tags/v*.
13
+
14
+ name: release
15
+
16
+ on:
17
+ push:
18
+ tags: ["v*"]
19
+ workflow_dispatch:
20
+
21
+ permissions:
22
+ contents: read
23
+
24
+ jobs:
25
+ build:
26
+ name: Build + verify artifacts
27
+ runs-on: ubuntu-latest
28
+ steps:
29
+ - uses: actions/checkout@v4
30
+
31
+ - uses: actions/setup-python@v5
32
+ with:
33
+ python-version: "3.12"
34
+
35
+ - name: Build sdist + wheel
36
+ run: |
37
+ pip install build twine
38
+ python -m build
39
+ twine check dist/*
40
+
41
+ - name: Smoke-test the wheel (fresh install + CLI entry point)
42
+ run: |
43
+ pip install dist/*.whl
44
+ layout-canvas schema | head -5
45
+
46
+ - uses: actions/upload-artifact@v4
47
+ with:
48
+ name: dist
49
+ path: dist/
50
+ retention-days: 30
51
+
52
+ publish:
53
+ name: Publish to PyPI
54
+ needs: build
55
+ runs-on: ubuntu-latest
56
+ if: startsWith(github.ref, 'refs/tags/v')
57
+ environment:
58
+ name: pypi
59
+ url: https://pypi.org/p/layout-canvas
60
+ permissions:
61
+ id-token: write # OIDC trusted publishing — no API token in secrets
62
+ steps:
63
+ - uses: actions/download-artifact@v4
64
+ with:
65
+ name: dist
66
+ path: dist/
67
+ - uses: pypa/gh-action-pypi-publish@release/v1
68
+ # To stage on TestPyPI first, set on the step:
69
+ # with:
70
+ # repository-url: https://test.pypi.org/legacy/
71
+
72
+ github-release:
73
+ name: GitHub Release with dist artifacts
74
+ needs: build
75
+ runs-on: ubuntu-latest
76
+ if: startsWith(github.ref, 'refs/tags/v')
77
+ permissions:
78
+ contents: write
79
+ steps:
80
+ - uses: actions/download-artifact@v4
81
+ with:
82
+ name: dist
83
+ path: dist/
84
+ - uses: softprops/action-gh-release@v2
85
+ with:
86
+ files: dist/*
87
+ generate_release_notes: true
@@ -0,0 +1,48 @@
1
+ .git/
2
+ __pycache__/
3
+ *.py[cod]
4
+ *$py.class
5
+ *.so
6
+ .Python
7
+ build/
8
+ develop-eggs/
9
+ dist/
10
+ downloads/
11
+ eggs/
12
+ .eggs/
13
+ lib/
14
+ lib64/
15
+ parts/
16
+ sdist/
17
+ var/
18
+ wheels/
19
+ *.egg-info/
20
+ .installed.cfg
21
+ *.egg
22
+ *.gds
23
+ *.oas
24
+ *.drc.txt
25
+ *.lvs.out
26
+ .pytest_cache/
27
+ .ruff_cache/
28
+ .venv/
29
+ venv/
30
+ ENV/
31
+ .idea/
32
+ .vscode/
33
+ *.swp
34
+ *.swo
35
+ *~
36
+ uv.lock
37
+
38
+ .tmp_*
39
+ waves.dat
40
+ # private PDK descriptors never enter git (docs/PDK_DESCRIPTORS.md)
41
+ *.pdk.json
42
+
43
+ # investor/fundraising docs stay local — never committed or pushed
44
+ INVESTOR_*.md
45
+
46
+
47
+
48
+ .wrangler/
@@ -0,0 +1,19 @@
1
+ # Agent entry
2
+
3
+ **If you are an AI agent**, read `skills/layout-canvas/SKILL.md` first — it is
4
+ the operating manual for driving this repository's layout compiler through MCP
5
+ (`layout-canvas mcp`), including the 8-step design loop, the typed edit ops,
6
+ and how to read fail-closed results.
7
+
8
+ Working in this repository as a contributor:
9
+
10
+ - Follow `CONTRIBUTING.md`; commits use `feat:` / `fix:` / `docs:` / `test:` /
11
+ `chore:` prefixes.
12
+ - Verification is fail-closed by contract (ADR 0002, 0005): never make a DRC,
13
+ LVS or simulation path report a pass when a tool, model or signal is
14
+ missing, and never loosen a rule value to make a check green.
15
+ - Machine-specific paths go through environment variables
16
+ (`docs/EXTERNAL_TOOLS.md`); private PDKs and run products never enter git.
17
+ - Run `.venv\Scripts\python.exe -m pytest tests -q` before committing; set
18
+ `LAYOUT_CANVAS_NGSPICE` to a console ngspice to exercise the simulation
19
+ tests instead of skipping them.
@@ -0,0 +1,72 @@
1
+ # Contributing to Layout Canvas
2
+
3
+ ## Development Setup
4
+
5
+ ```bash
6
+ git clone https://github.com/Kairos2425/layout-canvas.git
7
+ cd layout-canvas
8
+ python -m venv .venv
9
+ source .venv/bin/activate # Windows: .venv\Scripts\activate
10
+ pip install -e ".[dev]"
11
+ ```
12
+
13
+ ## Running Tests
14
+
15
+ ```bash
16
+ pytest
17
+ ruff check src tests
18
+ ```
19
+
20
+ ## Adding a New Block
21
+
22
+ 1. Create `src/layout_canvas/blocks/{pdk}/{block_name}.py`
23
+ 2. Define `BlockSpec` with params, ports, constraints
24
+ 3. Implement build function (returns `gf.Component`)
25
+ 4. Optionally implement netlist emitter
26
+ 5. Register with `@register(spec, netlist=...)`
27
+ 6. Import in `src/layout_canvas/blocks/{pdk}/__init__.py`
28
+
29
+ Example:
30
+
31
+ ```python
32
+ from layout_canvas.blocks.base import register
33
+ from layout_canvas.ir.model import BlockSpec, ParamSpec, PortSpec
34
+
35
+ spec = BlockSpec(
36
+ name="sky130.my_block",
37
+ pdk="sky130",
38
+ level="L1",
39
+ summary="My parametric block",
40
+ params=[
41
+ ParamSpec(name="width", type="float", default=1.0, unit="um", min=0.5, max=10.0),
42
+ ],
43
+ ports=[
44
+ PortSpec(name="in", layer="met1", direction="input"),
45
+ ],
46
+ )
47
+
48
+ @register(spec)
49
+ def _build(width: float) -> gf.Component:
50
+ c = gf.Component()
51
+ # ... add geometry
52
+ return c
53
+ ```
54
+
55
+ ## Code Style
56
+
57
+ - Line length: 100
58
+ - Imports: sorted with `ruff`
59
+ - Type hints: required for public APIs
60
+ - Docstrings: Google style for public functions
61
+
62
+ ## License
63
+
64
+ All contributions are licensed under MIT — see `LICENSE`. Bundled Sky130 model
65
+ files under `examples/models/sky130/` remain Apache-2.0 (upstream SkyWater),
66
+ and `NOTICE` reserves the "Layout Canvas" name.
67
+
68
+ By contributing you certify the [Developer Certificate of Origin](https://developercertificate.org/)
69
+ (DCO 1.1): you wrote the change or have the right to submit it under MIT, and
70
+ you understand it becomes part of the open core. If you can, add
71
+ `Signed-off-by: Name <email>` to the commit; either way, opening a PR
72
+ constitutes the certification.
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 layout-canvas contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,23 @@
1
+ layout-canvas
2
+ Copyright (c) 2026 layout-canvas contributors
3
+
4
+ This product includes software developed by the layout-canvas project.
5
+
6
+ Third-party attribution
7
+ -----------------------
8
+ Files under `examples/models/sky130/` are verbatim from
9
+ google/skywater-pdk-libs-sky130_fd_pr and remain licensed under the
10
+ Apache License, Version 2.0 (copyright SkyWater / Google contributors).
11
+
12
+ Trademark
13
+ ---------
14
+ "Layout Canvas" and the layout-canvas name are trademarks of the project
15
+ authors. The MIT license covers the software only — it does not grant
16
+ permission to use the project name or marks for derivative products or
17
+ services. Forks should be renamed.
18
+
19
+ Commercial use
20
+ --------------
21
+ The core is MIT-licensed and free for commercial use. The authors also
22
+ offer commercial arrangements (private PDK enablement, enterprise support,
23
+ hosted gallery/registry services) — see `docs/COMMERCIAL.md`.
@@ -0,0 +1,184 @@
1
+ Metadata-Version: 2.5
2
+ Name: layout-canvas
3
+ Version: 0.1.0
4
+ Summary: Block-level, AI-native analog layout canvas: Block IR + parametric blocks + DRC/LVS/PEX verification + Virtuoso export.
5
+ Project-URL: Repository, https://github.com/Kairos2425/layout-canvas
6
+ Project-URL: Issues, https://github.com/Kairos2425/layout-canvas/issues
7
+ Project-URL: Documentation, https://github.com/Kairos2425/layout-canvas/tree/main/docs
8
+ Project-URL: Gallery, https://github.com/Kairos2425/layout-canvas-gallery
9
+ Author: layout-canvas contributors
10
+ License-Expression: MIT
11
+ License-File: LICENSE
12
+ License-File: NOTICE
13
+ Keywords: analog,drc,eda,gds,layout,llm-agent,lvs,mcp,pdk,spectre,virtuoso
14
+ Classifier: Development Status :: 3 - Alpha
15
+ Classifier: Environment :: Console
16
+ Classifier: Intended Audience :: Developers
17
+ Classifier: Intended Audience :: Science/Research
18
+ Classifier: Operating System :: OS Independent
19
+ Classifier: Programming Language :: Python :: 3
20
+ Classifier: Programming Language :: Python :: 3.11
21
+ Classifier: Programming Language :: Python :: 3.12
22
+ Classifier: Topic :: Scientific/Engineering :: Electronic Design Automation (EDA)
23
+ Requires-Python: >=3.11
24
+ Requires-Dist: gdsfactory>=8.0
25
+ Requires-Dist: pydantic>=2.5
26
+ Provides-Extra: dev
27
+ Requires-Dist: build>=1.2; extra == 'dev'
28
+ Requires-Dist: jsonschema>=4; extra == 'dev'
29
+ Requires-Dist: pytest>=8; extra == 'dev'
30
+ Requires-Dist: ruff>=0.5; extra == 'dev'
31
+ Requires-Dist: twine>=5; extra == 'dev'
32
+ Description-Content-Type: text/markdown
33
+
34
+ # Layout Canvas
35
+
36
+ **Block-level, AI-native analog layout canvas** — parametric block library, typed
37
+ Block IR, deterministic layout compiler, in-process DRC/LVS/PEX verification, and
38
+ a local-first web canvas that AI agents can drive through MCP.
39
+
40
+ **Live demo → https://kairos2425.github.io/layout-canvas/**
41
+
42
+ ```
43
+ Block IR (JSON) ── compile ──▶ gdsfactory ──▶ GDS
44
+ │ │
45
+ │ └──▶ SPICE netlist ──▶ LVS vs extracted netlist
46
+ │ └──▶ KLayout pya ──▶ DRC subset + extraction
47
+ │ └──▶ ngspice ──▶ schematic & post-layout sim
48
+ │
49
+ └── constraints · ports · metadata ──▶ MCP tools for AI agents
50
+ ```
51
+
52
+ ## What it does
53
+
54
+ | Stage | Capability |
55
+ |---|---|
56
+ | **IR** | Pydantic-typed Block IR: instances, params, placements, nets, ports |
57
+ | **Blocks** | Sky130: diff_pair · current_mirror · ota_5t · strongarm · cap_array · guard_ring — IHP SG13G2: diff_pair · current_mirror · ota_5t · guard_ring |
58
+ | **Compile** | Design → hierarchical GDS + SPICE; top-level router with keep-outs, risers, via stacks |
59
+ | **DRC** | In-process KLayout engine: real width / spacing / via-enclosure subset with violation bboxes drawn back on the canvas (RVE-style) |
60
+ | **LVS** | `LayoutToNetlist` extraction + `NetlistComparer` topology match; passive blocks get connectivity-semantics comparison; mismatched nets are localized and highlighted |
61
+ | **PEX sim** | Extracted netlist → BSIM4/PSP foundry models via ngspice; internal-node probes (`xd1.tail`), custom testbenches |
62
+ | **External PDKs** | `*.pdk.json` descriptors via `LAYOUT_CANVAS_PDK_DIR`/`LAYOUT_CANVAS_PDKS` — layer map + extract recipe + DRC subset + model prelude + generic `gen_diff_pair`/`gen_current_mirror`/`gen_guard_ring` generators, no code (`docs/PDK_DESCRIPTORS.md`) |
63
+ | **Testbenches** | Named sim setups on the IR (schematic/extracted, op/tran/ac/dc, probes) + per-spec pass/fail/unavailable with reasons — `final/min/max/mean/pp/db/bw_3db` plus transient `settling`/`slew`/`overshoot` (with `tol`); CLI exit codes, session run history |
64
+ | **Export** | Virtuoso SKILL (shapes/instances, tech-lib attach, mirror/mag transforms) + Spectre netlist, GDS/OASIS, SPICE — plus `virtuoso-accept`: static SKILL/.scs checks anywhere, real Virtuoso/spectre acceptance over SSH on an EDA host (`docs/VIRTUOSO_ACCEPTANCE.md`; 30-min bring-up: `docs/CADENCE_INTEGRATION.md`) |
65
+ | **Import** | `import-netlist`: upstream SPICE/Spectre subckt netlists → Block IR draft (blocks matched by name + port signature; unmapped instances named, never guessed) — the upstream-pipeline on-ramp |
66
+ | **Interfaces** | CLI · local web canvas · MCP stdio server (35 tools) |
67
+
68
+ ## Install
69
+
70
+ ```bash
71
+ pip install layout-canvas # PyPI — or: pip install git+https://github.com/Kairos2425/layout-canvas
72
+ pip install klayout # in-process DRC/LVS/extraction engine
73
+ pytest # 245 tests; tool-dependent tests auto-skip
74
+ ```
75
+
76
+ Optional tools (probed adapters — absent tools report `unavailable`, never fake results):
77
+
78
+ - **ngspice** — schematic & post-layout simulation (`LAYOUT_CANVAS_NGSPICE=<path>`)
79
+ - **KLayout app / netgen / magic** — full foundry decks (`LAYOUT_CANVAS_KLAYOUT`, …)
80
+ - **IHP SG13G2 models** — `LAYOUT_CANVAS_IHP_MODELS`, `LAYOUT_CANVAS_OSDI_DIR`
81
+ (see `docs/EXTERNAL_TOOLS.md`)
82
+ - **Remote Virtuoso/spectre host** — `LAYOUT_CANVAS_VIRTUOSO_HOST`,
83
+ `LAYOUT_CANVAS_VIRTUOSO_DIR`, `LAYOUT_CANVAS_SPECTRE_MODELS`
84
+ (SSH key auth; see `docs/VIRTUOSO_ACCEPTANCE.md`)
85
+
86
+ ## Quick start
87
+
88
+ ### CLI
89
+
90
+ ```bash
91
+ layout-canvas compile examples/diffamp.json -o diffamp.gds # IR → GDS
92
+ layout-canvas netlist examples/diffamp.json -o diffamp.sp # IR → SPICE
93
+ layout-canvas schema # Block IR JSON schema
94
+ layout-canvas web --port 8080 # local canvas UI
95
+ layout-canvas mcp # MCP stdio server
96
+ ```
97
+
98
+ ### Web canvas
99
+
100
+ `layout-canvas web` opens the editor at `http://127.0.0.1:8080`: place blocks,
101
+ edit params, wire nets, then **Verify** (extract → DRC → LVS, violations painted
102
+ on the layout) and **PEX** (post-layout ngspice on extracted netlist with
103
+ waveform sparklines). Projects save/load as JSON — local-first, nothing leaves
104
+ the machine.
105
+
106
+ ### Python API
107
+
108
+ ```python
109
+ from layout_canvas.ir.model import Design
110
+ from layout_canvas.tools.verify import verify_design
111
+ import layout_canvas.blocks # registers all block generators
112
+
113
+ d = Design.model_validate({
114
+ "name": "diffamp", "pdk": "sky130",
115
+ "instances": [{"id": "U1", "block": "sky130.diff_pair",
116
+ "params": {"fingers": 4, "width": 2.0},
117
+ "placement": {"x": 0, "y": 0}}],
118
+ "nets": [], "ports": [{"name": "inp", "pin": "U1.inp"}],
119
+ })
120
+ r = verify_design(d) # extract → DRC → LVS in one call
121
+ r["passed"], r["drc"]["total_violations"], r["lvs"]["match"]
122
+ ```
123
+
124
+ Post-layout simulation on the extracted netlist:
125
+
126
+ ```python
127
+ from layout_canvas.tools.sim import simulate_extracted
128
+ res = simulate_extracted(d, probes=["out", "tail"], vdd=1.8)
129
+ # res["status"], res["waves"] → per-probe waveform vectors
130
+ ```
131
+
132
+ ### MCP (AI agents)
133
+
134
+ Point any MCP client at `layout-canvas mcp` (stdio). Agents get the full loop:
135
+ `open_design` → `insert_block_into_layout` / `transact` → `verify_design` →
136
+ `run_simulation(source="extracted", probes=[...])` → `export_virtuoso` /
137
+ `save_project`. `probe_environment` reports which EDA tools are live.
138
+
139
+ ## Repository layout
140
+
141
+ ```
142
+ src/layout_canvas/
143
+ ir/ Block IR schema (Pydantic)
144
+ blocks/ parametric generators (sky130/, ihp_sg13g2/)
145
+ compiler/ GDS/SPICE/Skill compile, router, Virtuoso export, PPA
146
+ engine/ transactional edit session (snapshot/undo)
147
+ tools/ drc, extract, lvs, sim, verify, backends
148
+ web/ local canvas app + gallery
149
+ mcp/ stdio MCP server
150
+ tests/ 245 tests incl. real-ngspice / real-PDK smokes
151
+ docs/ architecture, ADRs 0001-0009, external-tool setup
152
+ deploy/ Dockerfile + compose for the web app
153
+ ```
154
+
155
+ ## Security & privacy
156
+
157
+ - **Local-first by design.** The web app binds `127.0.0.1`; project files,
158
+ GDS output and simulation decks stay on your machine. No telemetry, no
159
+ cloud calls, no analytics.
160
+ - **No secrets in-repo.** PDK model paths, tool binaries and simulator paths
161
+ are supplied via `LAYOUT_CANVAS_*` environment variables — see
162
+ `docs/EXTERNAL_TOOLS.md`. Proprietary PDKs are never shipped or required.
163
+ - **Fail-closed verification.** DRC/LVS/sim report real tool results;
164
+ missing tools return `unavailable`/`refused`, never fabricated green.
165
+ - **Process isolation.** GPL tools (KLayout app, netgen) run as external
166
+ processes or the pip `klayout` module — no GPL code is linked in.
167
+ - Report vulnerabilities by opening a GitHub issue marked `security`, or
168
+ contact the maintainer directly. Please do not include proprietary PDK
169
+ material or NDA'd data in public reports.
170
+
171
+ ## License
172
+
173
+ MIT — see `LICENSE`. The "Layout Canvas" name is reserved (see `NOTICE`);
174
+ bundled Sky130 model files under `examples/models/sky130/` are upstream
175
+ SkyWater files and remain Apache-2.0. Commercial arrangements (private PDK
176
+ enablement, enterprise deployment, support): `docs/COMMERCIAL.md`.
177
+
178
+ ## Prior art & references
179
+
180
+ Independently implemented; product-direction inspiration from Analog Canvas
181
+ (github.com/cascode-ai/analog-canvas). Built on
182
+ [gdsfactory](https://github.com/gdsfactory/gdsfactory),
183
+ [KLayout](https://www.klayout.de/), ngspice, and the Sky130 / IHP SG13G2
184
+ open PDKs. Related: Glayout (OpenFASOC), ALIGN, Layout21, BAG, VLSIR.
@@ -0,0 +1,151 @@
1
+ # Layout Canvas
2
+
3
+ **Block-level, AI-native analog layout canvas** — parametric block library, typed
4
+ Block IR, deterministic layout compiler, in-process DRC/LVS/PEX verification, and
5
+ a local-first web canvas that AI agents can drive through MCP.
6
+
7
+ **Live demo → https://kairos2425.github.io/layout-canvas/**
8
+
9
+ ```
10
+ Block IR (JSON) ── compile ──▶ gdsfactory ──▶ GDS
11
+ │ │
12
+ │ └──▶ SPICE netlist ──▶ LVS vs extracted netlist
13
+ │ └──▶ KLayout pya ──▶ DRC subset + extraction
14
+ │ └──▶ ngspice ──▶ schematic & post-layout sim
15
+ │
16
+ └── constraints · ports · metadata ──▶ MCP tools for AI agents
17
+ ```
18
+
19
+ ## What it does
20
+
21
+ | Stage | Capability |
22
+ |---|---|
23
+ | **IR** | Pydantic-typed Block IR: instances, params, placements, nets, ports |
24
+ | **Blocks** | Sky130: diff_pair · current_mirror · ota_5t · strongarm · cap_array · guard_ring — IHP SG13G2: diff_pair · current_mirror · ota_5t · guard_ring |
25
+ | **Compile** | Design → hierarchical GDS + SPICE; top-level router with keep-outs, risers, via stacks |
26
+ | **DRC** | In-process KLayout engine: real width / spacing / via-enclosure subset with violation bboxes drawn back on the canvas (RVE-style) |
27
+ | **LVS** | `LayoutToNetlist` extraction + `NetlistComparer` topology match; passive blocks get connectivity-semantics comparison; mismatched nets are localized and highlighted |
28
+ | **PEX sim** | Extracted netlist → BSIM4/PSP foundry models via ngspice; internal-node probes (`xd1.tail`), custom testbenches |
29
+ | **External PDKs** | `*.pdk.json` descriptors via `LAYOUT_CANVAS_PDK_DIR`/`LAYOUT_CANVAS_PDKS` — layer map + extract recipe + DRC subset + model prelude + generic `gen_diff_pair`/`gen_current_mirror`/`gen_guard_ring` generators, no code (`docs/PDK_DESCRIPTORS.md`) |
30
+ | **Testbenches** | Named sim setups on the IR (schematic/extracted, op/tran/ac/dc, probes) + per-spec pass/fail/unavailable with reasons — `final/min/max/mean/pp/db/bw_3db` plus transient `settling`/`slew`/`overshoot` (with `tol`); CLI exit codes, session run history |
31
+ | **Export** | Virtuoso SKILL (shapes/instances, tech-lib attach, mirror/mag transforms) + Spectre netlist, GDS/OASIS, SPICE — plus `virtuoso-accept`: static SKILL/.scs checks anywhere, real Virtuoso/spectre acceptance over SSH on an EDA host (`docs/VIRTUOSO_ACCEPTANCE.md`; 30-min bring-up: `docs/CADENCE_INTEGRATION.md`) |
32
+ | **Import** | `import-netlist`: upstream SPICE/Spectre subckt netlists → Block IR draft (blocks matched by name + port signature; unmapped instances named, never guessed) — the upstream-pipeline on-ramp |
33
+ | **Interfaces** | CLI · local web canvas · MCP stdio server (35 tools) |
34
+
35
+ ## Install
36
+
37
+ ```bash
38
+ pip install layout-canvas # PyPI — or: pip install git+https://github.com/Kairos2425/layout-canvas
39
+ pip install klayout # in-process DRC/LVS/extraction engine
40
+ pytest # 245 tests; tool-dependent tests auto-skip
41
+ ```
42
+
43
+ Optional tools (probed adapters — absent tools report `unavailable`, never fake results):
44
+
45
+ - **ngspice** — schematic & post-layout simulation (`LAYOUT_CANVAS_NGSPICE=<path>`)
46
+ - **KLayout app / netgen / magic** — full foundry decks (`LAYOUT_CANVAS_KLAYOUT`, …)
47
+ - **IHP SG13G2 models** — `LAYOUT_CANVAS_IHP_MODELS`, `LAYOUT_CANVAS_OSDI_DIR`
48
+ (see `docs/EXTERNAL_TOOLS.md`)
49
+ - **Remote Virtuoso/spectre host** — `LAYOUT_CANVAS_VIRTUOSO_HOST`,
50
+ `LAYOUT_CANVAS_VIRTUOSO_DIR`, `LAYOUT_CANVAS_SPECTRE_MODELS`
51
+ (SSH key auth; see `docs/VIRTUOSO_ACCEPTANCE.md`)
52
+
53
+ ## Quick start
54
+
55
+ ### CLI
56
+
57
+ ```bash
58
+ layout-canvas compile examples/diffamp.json -o diffamp.gds # IR → GDS
59
+ layout-canvas netlist examples/diffamp.json -o diffamp.sp # IR → SPICE
60
+ layout-canvas schema # Block IR JSON schema
61
+ layout-canvas web --port 8080 # local canvas UI
62
+ layout-canvas mcp # MCP stdio server
63
+ ```
64
+
65
+ ### Web canvas
66
+
67
+ `layout-canvas web` opens the editor at `http://127.0.0.1:8080`: place blocks,
68
+ edit params, wire nets, then **Verify** (extract → DRC → LVS, violations painted
69
+ on the layout) and **PEX** (post-layout ngspice on extracted netlist with
70
+ waveform sparklines). Projects save/load as JSON — local-first, nothing leaves
71
+ the machine.
72
+
73
+ ### Python API
74
+
75
+ ```python
76
+ from layout_canvas.ir.model import Design
77
+ from layout_canvas.tools.verify import verify_design
78
+ import layout_canvas.blocks # registers all block generators
79
+
80
+ d = Design.model_validate({
81
+ "name": "diffamp", "pdk": "sky130",
82
+ "instances": [{"id": "U1", "block": "sky130.diff_pair",
83
+ "params": {"fingers": 4, "width": 2.0},
84
+ "placement": {"x": 0, "y": 0}}],
85
+ "nets": [], "ports": [{"name": "inp", "pin": "U1.inp"}],
86
+ })
87
+ r = verify_design(d) # extract → DRC → LVS in one call
88
+ r["passed"], r["drc"]["total_violations"], r["lvs"]["match"]
89
+ ```
90
+
91
+ Post-layout simulation on the extracted netlist:
92
+
93
+ ```python
94
+ from layout_canvas.tools.sim import simulate_extracted
95
+ res = simulate_extracted(d, probes=["out", "tail"], vdd=1.8)
96
+ # res["status"], res["waves"] → per-probe waveform vectors
97
+ ```
98
+
99
+ ### MCP (AI agents)
100
+
101
+ Point any MCP client at `layout-canvas mcp` (stdio). Agents get the full loop:
102
+ `open_design` → `insert_block_into_layout` / `transact` → `verify_design` →
103
+ `run_simulation(source="extracted", probes=[...])` → `export_virtuoso` /
104
+ `save_project`. `probe_environment` reports which EDA tools are live.
105
+
106
+ ## Repository layout
107
+
108
+ ```
109
+ src/layout_canvas/
110
+ ir/ Block IR schema (Pydantic)
111
+ blocks/ parametric generators (sky130/, ihp_sg13g2/)
112
+ compiler/ GDS/SPICE/Skill compile, router, Virtuoso export, PPA
113
+ engine/ transactional edit session (snapshot/undo)
114
+ tools/ drc, extract, lvs, sim, verify, backends
115
+ web/ local canvas app + gallery
116
+ mcp/ stdio MCP server
117
+ tests/ 245 tests incl. real-ngspice / real-PDK smokes
118
+ docs/ architecture, ADRs 0001-0009, external-tool setup
119
+ deploy/ Dockerfile + compose for the web app
120
+ ```
121
+
122
+ ## Security & privacy
123
+
124
+ - **Local-first by design.** The web app binds `127.0.0.1`; project files,
125
+ GDS output and simulation decks stay on your machine. No telemetry, no
126
+ cloud calls, no analytics.
127
+ - **No secrets in-repo.** PDK model paths, tool binaries and simulator paths
128
+ are supplied via `LAYOUT_CANVAS_*` environment variables — see
129
+ `docs/EXTERNAL_TOOLS.md`. Proprietary PDKs are never shipped or required.
130
+ - **Fail-closed verification.** DRC/LVS/sim report real tool results;
131
+ missing tools return `unavailable`/`refused`, never fabricated green.
132
+ - **Process isolation.** GPL tools (KLayout app, netgen) run as external
133
+ processes or the pip `klayout` module — no GPL code is linked in.
134
+ - Report vulnerabilities by opening a GitHub issue marked `security`, or
135
+ contact the maintainer directly. Please do not include proprietary PDK
136
+ material or NDA'd data in public reports.
137
+
138
+ ## License
139
+
140
+ MIT — see `LICENSE`. The "Layout Canvas" name is reserved (see `NOTICE`);
141
+ bundled Sky130 model files under `examples/models/sky130/` are upstream
142
+ SkyWater files and remain Apache-2.0. Commercial arrangements (private PDK
143
+ enablement, enterprise deployment, support): `docs/COMMERCIAL.md`.
144
+
145
+ ## Prior art & references
146
+
147
+ Independently implemented; product-direction inspiration from Analog Canvas
148
+ (github.com/cascode-ai/analog-canvas). Built on
149
+ [gdsfactory](https://github.com/gdsfactory/gdsfactory),
150
+ [KLayout](https://www.klayout.de/), ngspice, and the Sky130 / IHP SG13G2
151
+ open PDKs. Related: Glayout (OpenFASOC), ALIGN, Layout21, BAG, VLSIR.