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.
- layout_canvas-0.1.0/.dockerignore +13 -0
- layout_canvas-0.1.0/.github/workflows/ci.yml +46 -0
- layout_canvas-0.1.0/.github/workflows/release.yml +87 -0
- layout_canvas-0.1.0/.gitignore +48 -0
- layout_canvas-0.1.0/AGENTS.md +19 -0
- layout_canvas-0.1.0/CONTRIBUTING.md +72 -0
- layout_canvas-0.1.0/LICENSE +21 -0
- layout_canvas-0.1.0/NOTICE +23 -0
- layout_canvas-0.1.0/PKG-INFO +184 -0
- layout_canvas-0.1.0/README.md +151 -0
- layout_canvas-0.1.0/deploy/Dockerfile +35 -0
- layout_canvas-0.1.0/deploy/cloudflare/wrangler.toml +10 -0
- layout_canvas-0.1.0/deploy/compose.yaml +35 -0
- layout_canvas-0.1.0/docs/.assetsignore +2 -0
- layout_canvas-0.1.0/docs/ARCH_MEMORY.md +55 -0
- layout_canvas-0.1.0/docs/CADENCE_INTEGRATION.md +111 -0
- layout_canvas-0.1.0/docs/COMMERCIAL.md +53 -0
- layout_canvas-0.1.0/docs/DEPLOYMENT.md +75 -0
- layout_canvas-0.1.0/docs/EXTERNAL_TOOLS.md +159 -0
- layout_canvas-0.1.0/docs/PDK_DESCRIPTORS.md +232 -0
- layout_canvas-0.1.0/docs/PRODUCT_PLAN_ANALOG_CANVAS.md +177 -0
- layout_canvas-0.1.0/docs/RELEASING.md +66 -0
- layout_canvas-0.1.0/docs/USAGE.md +403 -0
- layout_canvas-0.1.0/docs/VIRTUOSO_ACCEPTANCE.md +140 -0
- layout_canvas-0.1.0/docs/WORK_PLAN.md +85 -0
- layout_canvas-0.1.0/docs/adr/0001-transactional-edit-session.md +44 -0
- layout_canvas-0.1.0/docs/adr/0002-fail-closed-verification.md +30 -0
- layout_canvas-0.1.0/docs/adr/0003-explicit-connectivity-projection.md +34 -0
- layout_canvas-0.1.0/docs/adr/0004-project-file-protocol.md +28 -0
- layout_canvas-0.1.0/docs/adr/0005-simulation-is-fail-closed.md +33 -0
- layout_canvas-0.1.0/docs/adr/0006-pdk-descriptor-and-cell-abstract.md +31 -0
- layout_canvas-0.1.0/docs/adr/0007-hierarchical-cell-reuse.md +41 -0
- layout_canvas-0.1.0/docs/adr/0008-pluggable-tool-adapters.md +38 -0
- layout_canvas-0.1.0/docs/adr/0009-deployment-architecture.md +41 -0
- layout_canvas-0.1.0/docs/index.html +603 -0
- layout_canvas-0.1.0/examples/diffamp.json +129 -0
- layout_canvas-0.1.0/examples/models/illustrative_mos.lib +15 -0
- layout_canvas-0.1.0/examples/models/sky130/sky130_fd_pr__nfet_01v8__tt.corner.spice +1476 -0
- layout_canvas-0.1.0/examples/models/sky130/sky130_fd_pr__nfet_01v8__tt.pm3.spice +48274 -0
- layout_canvas-0.1.0/examples/models/sky130/sky130_fd_pr__parameters__invariant.spice +7342 -0
- layout_canvas-0.1.0/examples/models/sky130/sky130_fd_pr__parameters__lod.spice +76 -0
- layout_canvas-0.1.0/examples/models/sky130/sky130_fd_pr__parameters__typical.spice +3025 -0
- layout_canvas-0.1.0/examples/models/sky130/sky130_fd_pr__pfet_01v8__tt.corner.spice +20 -0
- layout_canvas-0.1.0/examples/models/sky130/sky130_fd_pr__pfet_01v8__tt.pm3.spice +29628 -0
- layout_canvas-0.1.0/examples/models/sky130/sky130_tt.lib +10 -0
- layout_canvas-0.1.0/examples/ota_lab.json +108 -0
- layout_canvas-0.1.0/klayout/grain.xml +9 -0
- layout_canvas-0.1.0/klayout/pymacros/block_canvas.lym +57 -0
- layout_canvas-0.1.0/klayout/python/block_canvas_plugin.py +331 -0
- layout_canvas-0.1.0/pyproject.toml +56 -0
- layout_canvas-0.1.0/skills/layout-canvas/SKILL.md +139 -0
- layout_canvas-0.1.0/src/layout_canvas/__init__.py +14 -0
- layout_canvas-0.1.0/src/layout_canvas/blocks/__init__.py +25 -0
- layout_canvas-0.1.0/src/layout_canvas/blocks/base.py +184 -0
- layout_canvas-0.1.0/src/layout_canvas/blocks/cells.py +70 -0
- layout_canvas-0.1.0/src/layout_canvas/blocks/gds_cell.py +222 -0
- layout_canvas-0.1.0/src/layout_canvas/blocks/generic.py +949 -0
- layout_canvas-0.1.0/src/layout_canvas/blocks/ihp_sg13g2/__init__.py +17 -0
- layout_canvas-0.1.0/src/layout_canvas/blocks/ihp_sg13g2/current_mirror.py +224 -0
- layout_canvas-0.1.0/src/layout_canvas/blocks/ihp_sg13g2/diff_pair.py +244 -0
- layout_canvas-0.1.0/src/layout_canvas/blocks/ihp_sg13g2/geom.py +41 -0
- layout_canvas-0.1.0/src/layout_canvas/blocks/ihp_sg13g2/guard_ring.py +100 -0
- layout_canvas-0.1.0/src/layout_canvas/blocks/ihp_sg13g2/layers.py +35 -0
- layout_canvas-0.1.0/src/layout_canvas/blocks/ihp_sg13g2/ota_5t.py +413 -0
- layout_canvas-0.1.0/src/layout_canvas/blocks/sky130/__init__.py +25 -0
- layout_canvas-0.1.0/src/layout_canvas/blocks/sky130/cap_array.py +137 -0
- layout_canvas-0.1.0/src/layout_canvas/blocks/sky130/current_mirror.py +269 -0
- layout_canvas-0.1.0/src/layout_canvas/blocks/sky130/diff_pair.py +306 -0
- layout_canvas-0.1.0/src/layout_canvas/blocks/sky130/geom.py +58 -0
- layout_canvas-0.1.0/src/layout_canvas/blocks/sky130/guard_ring.py +244 -0
- layout_canvas-0.1.0/src/layout_canvas/blocks/sky130/layers.py +41 -0
- layout_canvas-0.1.0/src/layout_canvas/blocks/sky130/ota_5t.py +476 -0
- layout_canvas-0.1.0/src/layout_canvas/blocks/sky130/strongarm.py +497 -0
- layout_canvas-0.1.0/src/layout_canvas/cli.py +457 -0
- layout_canvas-0.1.0/src/layout_canvas/compiler/__init__.py +6 -0
- layout_canvas-0.1.0/src/layout_canvas/compiler/compile.py +233 -0
- layout_canvas-0.1.0/src/layout_canvas/compiler/hierarchy.py +61 -0
- layout_canvas-0.1.0/src/layout_canvas/compiler/netlist.py +182 -0
- layout_canvas-0.1.0/src/layout_canvas/compiler/netlist_import.py +635 -0
- layout_canvas-0.1.0/src/layout_canvas/compiler/optimizer.py +59 -0
- layout_canvas-0.1.0/src/layout_canvas/compiler/ppa.py +101 -0
- layout_canvas-0.1.0/src/layout_canvas/compiler/render.py +120 -0
- layout_canvas-0.1.0/src/layout_canvas/compiler/router.py +533 -0
- layout_canvas-0.1.0/src/layout_canvas/compiler/virtuoso.py +297 -0
- layout_canvas-0.1.0/src/layout_canvas/derived/__init__.py +5 -0
- layout_canvas-0.1.0/src/layout_canvas/derived/connectivity.py +100 -0
- layout_canvas-0.1.0/src/layout_canvas/engine/__init__.py +15 -0
- layout_canvas-0.1.0/src/layout_canvas/engine/edits.py +281 -0
- layout_canvas-0.1.0/src/layout_canvas/engine/envelope.py +61 -0
- layout_canvas-0.1.0/src/layout_canvas/engine/optimize.py +335 -0
- layout_canvas-0.1.0/src/layout_canvas/engine/session.py +117 -0
- layout_canvas-0.1.0/src/layout_canvas/ir/__init__.py +37 -0
- layout_canvas-0.1.0/src/layout_canvas/ir/model.py +228 -0
- layout_canvas-0.1.0/src/layout_canvas/mcp/__init__.py +12 -0
- layout_canvas-0.1.0/src/layout_canvas/mcp/bridge.py +172 -0
- layout_canvas-0.1.0/src/layout_canvas/mcp/server.py +1275 -0
- layout_canvas-0.1.0/src/layout_canvas/pdk/__init__.py +27 -0
- layout_canvas-0.1.0/src/layout_canvas/pdk/descriptor.py +639 -0
- layout_canvas-0.1.0/src/layout_canvas/protocol/__init__.py +19 -0
- layout_canvas-0.1.0/src/layout_canvas/protocol/project.py +157 -0
- layout_canvas-0.1.0/src/layout_canvas/tools/__init__.py +6 -0
- layout_canvas-0.1.0/src/layout_canvas/tools/backends.py +294 -0
- layout_canvas-0.1.0/src/layout_canvas/tools/drc.py +290 -0
- layout_canvas-0.1.0/src/layout_canvas/tools/extract.py +405 -0
- layout_canvas-0.1.0/src/layout_canvas/tools/lvs.py +334 -0
- layout_canvas-0.1.0/src/layout_canvas/tools/sim.py +827 -0
- layout_canvas-0.1.0/src/layout_canvas/tools/testbench.py +264 -0
- layout_canvas-0.1.0/src/layout_canvas/tools/verify.py +53 -0
- layout_canvas-0.1.0/src/layout_canvas/tools/virtuoso_check.py +844 -0
- layout_canvas-0.1.0/src/layout_canvas/web/__init__.py +5 -0
- layout_canvas-0.1.0/src/layout_canvas/web/app.py +472 -0
- layout_canvas-0.1.0/src/layout_canvas/web/gallery.py +229 -0
- layout_canvas-0.1.0/src/layout_canvas/web/page.py +893 -0
- layout_canvas-0.1.0/tests/test_backends.py +56 -0
- layout_canvas-0.1.0/tests/test_blocks.py +75 -0
- layout_canvas-0.1.0/tests/test_compiler.py +160 -0
- layout_canvas-0.1.0/tests/test_e2e.py +37 -0
- layout_canvas-0.1.0/tests/test_engine.py +239 -0
- layout_canvas-0.1.0/tests/test_gallery.py +126 -0
- layout_canvas-0.1.0/tests/test_gds_cell.py +201 -0
- layout_canvas-0.1.0/tests/test_generic_blocks.py +392 -0
- layout_canvas-0.1.0/tests/test_guard_ring.py +31 -0
- layout_canvas-0.1.0/tests/test_ihp_sg13g2.py +120 -0
- layout_canvas-0.1.0/tests/test_ir.py +118 -0
- layout_canvas-0.1.0/tests/test_mcp.py +166 -0
- layout_canvas-0.1.0/tests/test_mcp_e2e.py +165 -0
- layout_canvas-0.1.0/tests/test_netlist.py +38 -0
- layout_canvas-0.1.0/tests/test_netlist_import.py +208 -0
- layout_canvas-0.1.0/tests/test_optimize_and_cells.py +353 -0
- layout_canvas-0.1.0/tests/test_pdk.py +25 -0
- layout_canvas-0.1.0/tests/test_pdk_external.py +454 -0
- layout_canvas-0.1.0/tests/test_protocol.py +63 -0
- layout_canvas-0.1.0/tests/test_pya_verification.py +133 -0
- layout_canvas-0.1.0/tests/test_router.py +37 -0
- layout_canvas-0.1.0/tests/test_sim.py +197 -0
- layout_canvas-0.1.0/tests/test_testbench.py +387 -0
- layout_canvas-0.1.0/tests/test_tools.py +29 -0
- layout_canvas-0.1.0/tests/test_virtuoso.py +140 -0
- layout_canvas-0.1.0/tests/test_virtuoso_check.py +453 -0
- layout_canvas-0.1.0/tests/test_web.py +211 -0
|
@@ -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.
|