fast-spicerack 0.1.1__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.
- fast_spicerack-0.1.1/.github/dependabot.yml +9 -0
- fast_spicerack-0.1.1/.github/workflows/docs.yaml +66 -0
- fast_spicerack-0.1.1/.github/workflows/publish.yaml +122 -0
- fast_spicerack-0.1.1/.github/workflows/tags.yaml +115 -0
- fast_spicerack-0.1.1/.github/workflows/test.yaml +36 -0
- fast_spicerack-0.1.1/.gitignore +31 -0
- fast_spicerack-0.1.1/AGENTS.md +166 -0
- fast_spicerack-0.1.1/Cargo.lock +666 -0
- fast_spicerack-0.1.1/Cargo.toml +44 -0
- fast_spicerack-0.1.1/LICENSE +21 -0
- fast_spicerack-0.1.1/PKG-INFO +81 -0
- fast_spicerack-0.1.1/README.md +69 -0
- fast_spicerack-0.1.1/SECURITY.md +4 -0
- fast_spicerack-0.1.1/dev/research/dialect-import.md +495 -0
- fast_spicerack-0.1.1/dev/research/dialect-readers.md +1043 -0
- fast_spicerack-0.1.1/dev/research/ir-gaps.md +184 -0
- fast_spicerack-0.1.1/dev/research/ponytail-audit.md +255 -0
- fast_spicerack-0.1.1/dev/research/python-api-gaps.md +181 -0
- fast_spicerack-0.1.1/docs/circuits.md +162 -0
- fast_spicerack-0.1.1/docs/index.md +76 -0
- fast_spicerack-0.1.1/docs/models.md +97 -0
- fast_spicerack-0.1.1/docs/reference.md +134 -0
- fast_spicerack-0.1.1/docs/remeasure.md +83 -0
- fast_spicerack-0.1.1/docs/simulate.md +137 -0
- fast_spicerack-0.1.1/docs/testbenches.md +165 -0
- fast_spicerack-0.1.1/docs/tools.md +42 -0
- fast_spicerack-0.1.1/examples/01_voltage_divider.py +31 -0
- fast_spicerack-0.1.1/examples/02_rc_lowpass.py +68 -0
- fast_spicerack-0.1.1/examples/03_rlc_bandpass.py +37 -0
- fast_spicerack-0.1.1/examples/04_bjt_amplifier.py +40 -0
- fast_spicerack-0.1.1/examples/05_cmos_inverter.py +43 -0
- fast_spicerack-0.1.1/examples/06_opamp_inverting.py +36 -0
- fast_spicerack-0.1.1/examples/07_diode_rectifier.py +40 -0
- fast_spicerack-0.1.1/examples/08_differential_pair.py +40 -0
- fast_spicerack-0.1.1/examples/09_controlled_sources.py +47 -0
- fast_spicerack-0.1.1/examples/10_subcircuit.py +39 -0
- fast_spicerack-0.1.1/examples/11_jfet_amplifier.py +40 -0
- fast_spicerack-0.1.1/examples/12_transmission_line.py +38 -0
- fast_spicerack-0.1.1/examples/13_switches.py +44 -0
- fast_spicerack-0.1.1/examples/14_pwl_dac.py +45 -0
- fast_spicerack-0.1.1/examples/15_linting.py +26 -0
- fast_spicerack-0.1.1/examples/16_simulator_config.py +42 -0
- fast_spicerack-0.1.1/examples/17_veriloga_inline.py +49 -0
- fast_spicerack-0.1.1/examples/18_verilog_digital.py +67 -0
- fast_spicerack-0.1.1/examples/19_backend_hotswap.py +41 -0
- fast_spicerack-0.1.1/examples/20_pdk_hotswap.py +91 -0
- fast_spicerack-0.1.1/examples/21_combined_hotswap.py +105 -0
- fast_spicerack-0.1.1/examples/22_design_testbenches.py +140 -0
- fast_spicerack-0.1.1/examples/ast_dump.rs +6 -0
- fast_spicerack-0.1.1/flake.lock +96 -0
- fast_spicerack-0.1.1/flake.nix +138 -0
- fast_spicerack-0.1.1/grammar/README.md +19 -0
- fast_spicerack-0.1.1/grammar/hspice.peg +140 -0
- fast_spicerack-0.1.1/grammar/ltspice.peg +110 -0
- fast_spicerack-0.1.1/grammar/ngspice.peg +149 -0
- fast_spicerack-0.1.1/grammar/spectre.peg +231 -0
- fast_spicerack-0.1.1/grammar/spice.peg +225 -0
- fast_spicerack-0.1.1/grammar/vacask.peg +174 -0
- fast_spicerack-0.1.1/grammar/xyce.peg +115 -0
- fast_spicerack-0.1.1/mkdocs.yml +46 -0
- fast_spicerack-0.1.1/nix/ngspice.nix +10 -0
- fast_spicerack-0.1.1/nix/openvaf.nix +72 -0
- fast_spicerack-0.1.1/nix/vacask.nix +89 -0
- fast_spicerack-0.1.1/pyproject.toml +24 -0
- fast_spicerack-0.1.1/python/spicerack/__init__.py +3 -0
- fast_spicerack-0.1.1/python/spicerack/remeasure.py +371 -0
- fast_spicerack-0.1.1/python/spicerack/testbenches/__init__.py +82 -0
- fast_spicerack-0.1.1/python/spicerack/testbenches/_common.py +42 -0
- fast_spicerack-0.1.1/python/spicerack/testbenches/_digital.py +18 -0
- fast_spicerack-0.1.1/python/spicerack/testbenches/amplifiers.py +434 -0
- fast_spicerack-0.1.1/python/spicerack/testbenches/amplifiers_2.py +440 -0
- fast_spicerack-0.1.1/python/spicerack/testbenches/analysis.py +573 -0
- fast_spicerack-0.1.1/python/spicerack/testbenches/bias.py +390 -0
- fast_spicerack-0.1.1/python/spicerack/testbenches/characterize.py +254 -0
- fast_spicerack-0.1.1/python/spicerack/testbenches/converters.py +479 -0
- fast_spicerack-0.1.1/python/spicerack/testbenches/converters_2.py +345 -0
- fast_spicerack-0.1.1/python/spicerack/testbenches/converters_3.py +230 -0
- fast_spicerack-0.1.1/python/spicerack/testbenches/design.py +787 -0
- fast_spicerack-0.1.1/python/spicerack/testbenches/power.py +493 -0
- fast_spicerack-0.1.1/python/spicerack/testbenches/timing.py +558 -0
- fast_spicerack-0.1.1/python/spicerack/testbenches/timing_2.py +435 -0
- fast_spicerack-0.1.1/schema/circuit-ir.schema.json +2269 -0
- fast_spicerack-0.1.1/schema/examples/voltage_divider.circuit.json +60 -0
- fast_spicerack-0.1.1/skills/spicerack/PDK_AND_FLOW.md +115 -0
- fast_spicerack-0.1.1/skills/spicerack/REFERENCE.md +188 -0
- fast_spicerack-0.1.1/skills/spicerack/SKILL.md +64 -0
- fast_spicerack-0.1.1/skills/spicerack/TESTBENCHES.md +321 -0
- fast_spicerack-0.1.1/src/backend/espice.rs +21 -0
- fast_spicerack-0.1.1/src/backend/ltspice.rs +70 -0
- fast_spicerack-0.1.1/src/backend/mod.rs +336 -0
- fast_spicerack-0.1.1/src/backend/ngspice.rs +249 -0
- fast_spicerack-0.1.1/src/backend/spectre.rs +67 -0
- fast_spicerack-0.1.1/src/backend/vacask.rs +82 -0
- fast_spicerack-0.1.1/src/codegen/laplace.rs +703 -0
- fast_spicerack-0.1.1/src/codegen/mod.rs +196 -0
- fast_spicerack-0.1.1/src/codegen/spectre.rs +1494 -0
- fast_spicerack-0.1.1/src/codegen/spice3.rs +1515 -0
- fast_spicerack-0.1.1/src/codegen/vacask.rs +1287 -0
- fast_spicerack-0.1.1/src/codegen/xschem.rs +1121 -0
- fast_spicerack-0.1.1/src/import/lower.rs +1288 -0
- fast_spicerack-0.1.1/src/import/mod.rs +185 -0
- fast_spicerack-0.1.1/src/import/tests.rs +154 -0
- fast_spicerack-0.1.1/src/ir/mod.rs +1057 -0
- fast_spicerack-0.1.1/src/lib.rs +21 -0
- fast_spicerack-0.1.1/src/lint.rs +195 -0
- fast_spicerack-0.1.1/src/measure_parse.rs +307 -0
- fast_spicerack-0.1.1/src/normalize.rs +209 -0
- fast_spicerack-0.1.1/src/peg.rs +489 -0
- fast_spicerack-0.1.1/src/python.rs +1932 -0
- fast_spicerack-0.1.1/src/rawfile.rs +306 -0
- fast_spicerack-0.1.1/src/result.rs +102 -0
- fast_spicerack-0.1.1/src/simulation.rs +25 -0
- fast_spicerack-0.1.1/src/unit.rs +273 -0
- fast_spicerack-0.1.1/src/veriloga.rs +280 -0
- fast_spicerack-0.1.1/tests/conftest.py +7 -0
- fast_spicerack-0.1.1/tests/fixtures/spectre_mc_scalar/README.md +10 -0
- fast_spicerack-0.1.1/tests/fixtures/spectre_mc_scalar/input.raw/tran.raw +1 -0
- fast_spicerack-0.1.1/tests/fixtures/spectre_mc_scalar/monteCarlo/mcdata +3 -0
- fast_spicerack-0.1.1/tests/fixtures/spectre_mc_scalar/monteCarlo/mcparam +2 -0
- fast_spicerack-0.1.1/tests/fixtures/spectre_mc_scalar/psf/tran.tran +1 -0
- fast_spicerack-0.1.1/tests/test_backends.rs +31 -0
- fast_spicerack-0.1.1/tests/test_bench_amplifiers.py +426 -0
- fast_spicerack-0.1.1/tests/test_bench_common.py +43 -0
- fast_spicerack-0.1.1/tests/test_bench_converters.py +536 -0
- fast_spicerack-0.1.1/tests/test_bench_metrics.py +317 -0
- fast_spicerack-0.1.1/tests/test_bench_power.py +457 -0
- fast_spicerack-0.1.1/tests/test_bench_timing.py +531 -0
- fast_spicerack-0.1.1/tests/test_bump_version.py +46 -0
- fast_spicerack-0.1.1/tests/test_characterize.py +142 -0
- fast_spicerack-0.1.1/tests/test_design_testbenches.py +279 -0
- fast_spicerack-0.1.1/tests/test_dialects.rs +273 -0
- fast_spicerack-0.1.1/tests/test_docs.py +67 -0
- fast_spicerack-0.1.1/tests/test_espice_analyses.rs +210 -0
- fast_spicerack-0.1.1/tests/test_espice_backend.py +233 -0
- fast_spicerack-0.1.1/tests/test_import_suite.rs +523 -0
- fast_spicerack-0.1.1/tests/test_laplace_ngspice.rs +371 -0
- fast_spicerack-0.1.1/tests/test_ltspice_dialect.rs +231 -0
- fast_spicerack-0.1.1/tests/test_ngspice_analyses.rs +361 -0
- fast_spicerack-0.1.1/tests/test_python_circuit.py +568 -0
- fast_spicerack-0.1.1/tests/test_python_examples.py +153 -0
- fast_spicerack-0.1.1/tests/test_python_lint.py +343 -0
- fast_spicerack-0.1.1/tests/test_python_netlist.py +911 -0
- fast_spicerack-0.1.1/tests/test_python_simulator.py +446 -0
- fast_spicerack-0.1.1/tests/test_python_subcircuit.py +1030 -0
- fast_spicerack-0.1.1/tests/test_python_units.py +175 -0
- fast_spicerack-0.1.1/tests/test_remeasure.py +265 -0
- fast_spicerack-0.1.1/tests/test_run_corners.py +90 -0
- fast_spicerack-0.1.1/tests/test_spectre_golden.rs +660 -0
- fast_spicerack-0.1.1/tests/test_unit.rs +45 -0
- fast_spicerack-0.1.1/tests/test_vacask_backend.py +155 -0
- fast_spicerack-0.1.1/tests/test_vacask_runs.rs +680 -0
- fast_spicerack-0.1.1/tools/bump_version.py +57 -0
- fast_spicerack-0.1.1/tools/spice2rack.rs +435 -0
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
name: Documentation
|
|
2
|
+
|
|
3
|
+
# Builds the site from docs/*.md with MkDocs (pinned by flake.lock through
|
|
4
|
+
# `nix develop .#docs`). Every pull request builds it in strict mode, so a
|
|
5
|
+
# broken link or anchor fails the check; a push to main also deploys it.
|
|
6
|
+
|
|
7
|
+
"on":
|
|
8
|
+
pull_request:
|
|
9
|
+
paths:
|
|
10
|
+
- "docs/**"
|
|
11
|
+
- "mkdocs.yml"
|
|
12
|
+
- "flake.nix"
|
|
13
|
+
- "flake.lock"
|
|
14
|
+
- ".github/workflows/docs.yaml"
|
|
15
|
+
push:
|
|
16
|
+
branches: [main]
|
|
17
|
+
paths:
|
|
18
|
+
- "docs/**"
|
|
19
|
+
- "mkdocs.yml"
|
|
20
|
+
- "flake.nix"
|
|
21
|
+
- "flake.lock"
|
|
22
|
+
- ".github/workflows/docs.yaml"
|
|
23
|
+
workflow_dispatch:
|
|
24
|
+
|
|
25
|
+
permissions:
|
|
26
|
+
contents: read
|
|
27
|
+
|
|
28
|
+
concurrency:
|
|
29
|
+
group: pages-${{ github.ref }}
|
|
30
|
+
cancel-in-progress: false
|
|
31
|
+
|
|
32
|
+
jobs:
|
|
33
|
+
build:
|
|
34
|
+
runs-on: ubuntu-latest
|
|
35
|
+
steps:
|
|
36
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
37
|
+
|
|
38
|
+
- name: Install Nix
|
|
39
|
+
uses: DeterminateSystems/nix-installer-action@9383ce2bf08796b65508822f5982f49151badc4e # main
|
|
40
|
+
|
|
41
|
+
- name: Build the site (strict)
|
|
42
|
+
run: nix develop .#docs --command mkdocs build --strict --site-dir site
|
|
43
|
+
|
|
44
|
+
- name: Upload artifact
|
|
45
|
+
if: github.event_name != 'pull_request'
|
|
46
|
+
uses: actions/upload-pages-artifact@fc324d3547104276b827a68afc52ff2a11cc49c9 # v5.0.0
|
|
47
|
+
with:
|
|
48
|
+
path: site
|
|
49
|
+
|
|
50
|
+
deploy:
|
|
51
|
+
if: github.event_name != 'pull_request'
|
|
52
|
+
needs: build
|
|
53
|
+
runs-on: ubuntu-latest
|
|
54
|
+
permissions:
|
|
55
|
+
pages: write
|
|
56
|
+
id-token: write
|
|
57
|
+
environment:
|
|
58
|
+
name: github-pages
|
|
59
|
+
url: ${{ steps.deployment.outputs.page_url }}
|
|
60
|
+
steps:
|
|
61
|
+
- name: Configure Pages
|
|
62
|
+
uses: actions/configure-pages@45bfe0192ca1faeb007ade9deae92b16b8254a0d # v6.0.0
|
|
63
|
+
|
|
64
|
+
- name: Deploy to GitHub Pages
|
|
65
|
+
id: deployment
|
|
66
|
+
uses: actions/deploy-pages@368f82528645a54fb793d4d04e342629a3f51346 # v5.0.1
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
name: Publish
|
|
2
|
+
|
|
3
|
+
# Releasing a version, start to finish:
|
|
4
|
+
# 1. Actions -> Publish -> Run workflow, pick the bump (patch/minor/major or
|
|
5
|
+
# an explicit X.Y.Z). This opens a pull request that moves the version in
|
|
6
|
+
# Cargo.toml, pyproject.toml and Cargo.lock; bots never push to main.
|
|
7
|
+
# 2. Merge it once the merge gate passes.
|
|
8
|
+
# 3. The merge changes pyproject.toml on main, which runs this workflow
|
|
9
|
+
# again. If that version has no tag yet, the Release workflow
|
|
10
|
+
# (tags.yaml) tests, builds the wheels and sdist, and creates the tag and
|
|
11
|
+
# the GitHub release; then the same files go to PyPI.
|
|
12
|
+
#
|
|
13
|
+
# One-time setup:
|
|
14
|
+
# - PyPI: a trusted publisher for project "fast-spicerack": owner OpenFAT,
|
|
15
|
+
# repository SpiceRack, workflow publish.yaml, environment pypi.
|
|
16
|
+
# - GitHub: an environment named "pypi", and Settings -> Actions -> General
|
|
17
|
+
# -> "Allow GitHub Actions to create and approve pull requests".
|
|
18
|
+
# - Secret RELEASE_TOKEN (fine-grained PAT, contents + pull requests write).
|
|
19
|
+
# Without it the bump pull request is opened with the default token, and
|
|
20
|
+
# GitHub starts no CI for it: close and reopen it to run the checks.
|
|
21
|
+
|
|
22
|
+
"on":
|
|
23
|
+
workflow_dispatch:
|
|
24
|
+
inputs:
|
|
25
|
+
bump:
|
|
26
|
+
description: patch, minor, major, or an explicit X.Y.Z
|
|
27
|
+
required: true
|
|
28
|
+
default: patch
|
|
29
|
+
push:
|
|
30
|
+
branches: [main]
|
|
31
|
+
paths: [pyproject.toml]
|
|
32
|
+
|
|
33
|
+
permissions: {}
|
|
34
|
+
|
|
35
|
+
concurrency:
|
|
36
|
+
group: publish
|
|
37
|
+
cancel-in-progress: false
|
|
38
|
+
|
|
39
|
+
jobs:
|
|
40
|
+
# ── Step 1: the version bump, as a pull request ──
|
|
41
|
+
bump:
|
|
42
|
+
if: github.event_name == 'workflow_dispatch'
|
|
43
|
+
runs-on: ubuntu-latest
|
|
44
|
+
permissions:
|
|
45
|
+
contents: write
|
|
46
|
+
pull-requests: write
|
|
47
|
+
steps:
|
|
48
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
49
|
+
with:
|
|
50
|
+
token: ${{ secrets.RELEASE_TOKEN || github.token }}
|
|
51
|
+
|
|
52
|
+
- name: Bump Cargo.toml, pyproject.toml and Cargo.lock
|
|
53
|
+
id: bump
|
|
54
|
+
env:
|
|
55
|
+
BUMP: ${{ inputs.bump }}
|
|
56
|
+
run: python3 tools/bump_version.py "$BUMP" >> "$GITHUB_OUTPUT"
|
|
57
|
+
|
|
58
|
+
- name: Open the release pull request
|
|
59
|
+
env:
|
|
60
|
+
GH_TOKEN: ${{ secrets.RELEASE_TOKEN || github.token }}
|
|
61
|
+
VERSION: ${{ steps.bump.outputs.version }}
|
|
62
|
+
run: |
|
|
63
|
+
branch="release/v$VERSION"
|
|
64
|
+
git config user.name "github-actions[bot]"
|
|
65
|
+
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
|
|
66
|
+
git switch -c "$branch"
|
|
67
|
+
git commit -am "release: v$VERSION"
|
|
68
|
+
git push origin "$branch"
|
|
69
|
+
gh pr create --base main --head "$branch" --title "release: v$VERSION" \
|
|
70
|
+
--body "Moves the version to $VERSION. Merging it publishes v$VERSION to PyPI and GitHub (publish.yaml)."
|
|
71
|
+
|
|
72
|
+
# ── Step 3: a merged bump becomes a release ──
|
|
73
|
+
check:
|
|
74
|
+
if: github.event_name == 'push'
|
|
75
|
+
runs-on: ubuntu-latest
|
|
76
|
+
permissions:
|
|
77
|
+
contents: read
|
|
78
|
+
outputs:
|
|
79
|
+
tag: ${{ steps.version.outputs.tag }}
|
|
80
|
+
steps:
|
|
81
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
82
|
+
- name: A version this push moved, and not yet tagged?
|
|
83
|
+
id: version
|
|
84
|
+
env:
|
|
85
|
+
BEFORE: ${{ github.event.before }}
|
|
86
|
+
run: |
|
|
87
|
+
version() { sed -n 's/^version = "\(.*\)"$/\1/p' | head -1; }
|
|
88
|
+
v=$(version < pyproject.toml)
|
|
89
|
+
git fetch -q --depth=1 origin "$BEFORE"
|
|
90
|
+
was=$(git show "$BEFORE:pyproject.toml" | version)
|
|
91
|
+
if [ "$v" = "$was" ]; then
|
|
92
|
+
echo "pyproject.toml changed but the version is still $v; nothing to publish"
|
|
93
|
+
elif git ls-remote --exit-code --tags origin "refs/tags/v$v" >/dev/null; then
|
|
94
|
+
echo "v$v is already released; nothing to publish"
|
|
95
|
+
else
|
|
96
|
+
echo "tag=v$v" >> "$GITHUB_OUTPUT"
|
|
97
|
+
fi
|
|
98
|
+
|
|
99
|
+
release:
|
|
100
|
+
needs: check
|
|
101
|
+
if: needs.check.outputs.tag != ''
|
|
102
|
+
permissions:
|
|
103
|
+
contents: write
|
|
104
|
+
uses: ./.github/workflows/tags.yaml
|
|
105
|
+
with:
|
|
106
|
+
tag: ${{ needs.check.outputs.tag }}
|
|
107
|
+
|
|
108
|
+
pypi:
|
|
109
|
+
needs: release
|
|
110
|
+
runs-on: ubuntu-latest
|
|
111
|
+
environment:
|
|
112
|
+
name: pypi
|
|
113
|
+
url: https://pypi.org/project/fast-spicerack/
|
|
114
|
+
permissions:
|
|
115
|
+
id-token: write
|
|
116
|
+
steps:
|
|
117
|
+
- uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2
|
|
118
|
+
with:
|
|
119
|
+
path: dist
|
|
120
|
+
merge-multiple: true
|
|
121
|
+
|
|
122
|
+
- uses: pypa/gh-action-pypi-publish@7245906fb61fa33a13554f9d5fb856fe61758086 # v1.14.3
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
name: Release
|
|
2
|
+
|
|
3
|
+
"on":
|
|
4
|
+
push:
|
|
5
|
+
tags:
|
|
6
|
+
- "v*"
|
|
7
|
+
workflow_dispatch:
|
|
8
|
+
# publish.yaml calls this with the tag to create once a version bump merges.
|
|
9
|
+
workflow_call:
|
|
10
|
+
inputs:
|
|
11
|
+
tag:
|
|
12
|
+
description: Tag to release, vX.Y.Z; created on the commit being built
|
|
13
|
+
type: string
|
|
14
|
+
required: true
|
|
15
|
+
|
|
16
|
+
permissions:
|
|
17
|
+
contents: write
|
|
18
|
+
|
|
19
|
+
jobs:
|
|
20
|
+
# ── Refuse a tag that disagrees with the manifests, then run the merge gate ──
|
|
21
|
+
version:
|
|
22
|
+
runs-on: ubuntu-latest
|
|
23
|
+
steps:
|
|
24
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
25
|
+
- name: Tag matches Cargo.toml and pyproject.toml
|
|
26
|
+
if: github.ref_type == 'tag' || inputs.tag != ''
|
|
27
|
+
env:
|
|
28
|
+
TAG: ${{ inputs.tag || github.ref_name }}
|
|
29
|
+
run: |
|
|
30
|
+
tag="${TAG#v}"
|
|
31
|
+
for f in Cargo.toml pyproject.toml; do
|
|
32
|
+
v=$(sed -n 's/^version = "\(.*\)"$/\1/p' "$f" | head -1)
|
|
33
|
+
[ "$v" = "$tag" ] || { echo "::error::$f is $v, tag is $tag"; exit 1; }
|
|
34
|
+
done
|
|
35
|
+
|
|
36
|
+
test:
|
|
37
|
+
needs: version
|
|
38
|
+
uses: ./.github/workflows/test.yaml
|
|
39
|
+
|
|
40
|
+
# ── Python wheels (maturin) ──
|
|
41
|
+
python:
|
|
42
|
+
needs: test
|
|
43
|
+
strategy:
|
|
44
|
+
fail-fast: false
|
|
45
|
+
matrix:
|
|
46
|
+
include:
|
|
47
|
+
- os: ubuntu-latest
|
|
48
|
+
target: x86_64
|
|
49
|
+
- os: macos-latest
|
|
50
|
+
target: aarch64
|
|
51
|
+
- os: windows-latest
|
|
52
|
+
target: x64
|
|
53
|
+
runs-on: ${{ matrix.os }}
|
|
54
|
+
steps:
|
|
55
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
56
|
+
|
|
57
|
+
- uses: actions/setup-python@6d4fd22b20465ccc0f7354476588e8df7c9ca0e0 # v7.1.0
|
|
58
|
+
with:
|
|
59
|
+
python-version: |
|
|
60
|
+
3.10
|
|
61
|
+
3.11
|
|
62
|
+
3.12
|
|
63
|
+
3.13
|
|
64
|
+
|
|
65
|
+
- name: Build wheels
|
|
66
|
+
uses: PyO3/maturin-action@e83996d129638aa358a18fbd1dfb82f0b0fb5d3b # v1
|
|
67
|
+
with:
|
|
68
|
+
target: ${{ matrix.target }}
|
|
69
|
+
# One wheel per interpreter: the extension is not abi3. 3.14 needs pyo3 >= 0.25.
|
|
70
|
+
args: --release --out dist --interpreter 3.10 3.11 3.12 3.13
|
|
71
|
+
manylinux: auto
|
|
72
|
+
|
|
73
|
+
- uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
|
|
74
|
+
with:
|
|
75
|
+
name: wheels-${{ matrix.os }}-${{ matrix.target }}
|
|
76
|
+
path: dist/*.whl
|
|
77
|
+
|
|
78
|
+
# ── Python sdist ──
|
|
79
|
+
sdist:
|
|
80
|
+
needs: test
|
|
81
|
+
runs-on: ubuntu-latest
|
|
82
|
+
steps:
|
|
83
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
84
|
+
- name: Build sdist
|
|
85
|
+
uses: PyO3/maturin-action@e83996d129638aa358a18fbd1dfb82f0b0fb5d3b # v1
|
|
86
|
+
with:
|
|
87
|
+
command: sdist
|
|
88
|
+
args: --out dist
|
|
89
|
+
- uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
|
|
90
|
+
with:
|
|
91
|
+
name: sdist
|
|
92
|
+
path: dist/*.tar.gz
|
|
93
|
+
|
|
94
|
+
# ── GitHub Release ──
|
|
95
|
+
release:
|
|
96
|
+
needs: [python, sdist]
|
|
97
|
+
runs-on: ubuntu-latest
|
|
98
|
+
steps:
|
|
99
|
+
- uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2
|
|
100
|
+
with:
|
|
101
|
+
path: artifacts
|
|
102
|
+
|
|
103
|
+
- name: Collect release assets
|
|
104
|
+
run: |
|
|
105
|
+
mkdir release
|
|
106
|
+
find artifacts -type f \( -name '*.tar.gz' -o -name '*.whl' \) -exec cp {} release/ \;
|
|
107
|
+
|
|
108
|
+
- name: Create GitHub Release
|
|
109
|
+
uses: softprops/action-gh-release@efb35369e0ad2afab669f228072c1b0d510eae64 # v3.0.3
|
|
110
|
+
with:
|
|
111
|
+
tag_name: ${{ inputs.tag || github.ref_name }}
|
|
112
|
+
target_commitish: ${{ github.sha }}
|
|
113
|
+
files: release/*
|
|
114
|
+
generate_release_notes: true
|
|
115
|
+
prerelease: ${{ contains(inputs.tag || github.ref_name, '-') }}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
name: Tests
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
pull_request:
|
|
7
|
+
workflow_call:
|
|
8
|
+
|
|
9
|
+
concurrency:
|
|
10
|
+
group: ${{ github.workflow }}-${{ github.ref }}
|
|
11
|
+
cancel-in-progress: ${{ github.event_name == 'pull_request' }}
|
|
12
|
+
|
|
13
|
+
jobs:
|
|
14
|
+
test:
|
|
15
|
+
runs-on: ubuntu-latest
|
|
16
|
+
timeout-minutes: 120
|
|
17
|
+
steps:
|
|
18
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
19
|
+
|
|
20
|
+
- name: Install Nix
|
|
21
|
+
uses: DeterminateSystems/nix-installer-action@9383ce2bf08796b65508822f5982f49151badc4e # main
|
|
22
|
+
|
|
23
|
+
- name: Setup Nix cache
|
|
24
|
+
uses: DeterminateSystems/magic-nix-cache-action@f69a2d3e148e90223fe63ab6e3f6331f2e7e33dc # main
|
|
25
|
+
|
|
26
|
+
- name: Cargo tests
|
|
27
|
+
run: nix develop .#testing --command cargo test
|
|
28
|
+
|
|
29
|
+
- name: Python tests
|
|
30
|
+
run: |
|
|
31
|
+
nix develop .#testing --command bash -c '
|
|
32
|
+
python3 -m venv .venv --system-site-packages
|
|
33
|
+
source .venv/bin/activate
|
|
34
|
+
maturin develop
|
|
35
|
+
python3 -m pytest -v
|
|
36
|
+
'
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# Build artifacts
|
|
2
|
+
/target/
|
|
3
|
+
|
|
4
|
+
# Python
|
|
5
|
+
__pycache__/
|
|
6
|
+
*.pyc
|
|
7
|
+
*.pyo
|
|
8
|
+
*.egg-info/
|
|
9
|
+
python/spicerack/_native*.so
|
|
10
|
+
dist/
|
|
11
|
+
build/
|
|
12
|
+
.venv/
|
|
13
|
+
|
|
14
|
+
# IDE
|
|
15
|
+
.idea/
|
|
16
|
+
.vscode/
|
|
17
|
+
*.swp
|
|
18
|
+
*~
|
|
19
|
+
|
|
20
|
+
# OS
|
|
21
|
+
.DS_Store
|
|
22
|
+
|
|
23
|
+
# Test/cache
|
|
24
|
+
.pytest_cache/
|
|
25
|
+
.tox/
|
|
26
|
+
|
|
27
|
+
# Nix build output
|
|
28
|
+
target_nix/
|
|
29
|
+
result
|
|
30
|
+
result-*
|
|
31
|
+
site/
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
# AGENTS.md
|
|
2
|
+
|
|
3
|
+
SpiceRack: build SPICE circuits in Python, netlist them for any simulator
|
|
4
|
+
(ngspice, HSPICE, LTspice, VACASK, Spectre, ESPice), run them and read the
|
|
5
|
+
results back. The core is a Rust crate (edition 2024) with PyO3 bindings
|
|
6
|
+
shipped as the `spicerack` Python package. `README.md` is the overview;
|
|
7
|
+
`grammar/README.md` is the dialect readers' contract.
|
|
8
|
+
|
|
9
|
+
## Skills to load first
|
|
10
|
+
|
|
11
|
+
Load each with the Skill tool (other agents: read
|
|
12
|
+
`~/.claude/skills/<name>/SKILL.md` and the companion files it names). Source:
|
|
13
|
+
https://github.com/OmarSiwy/NixOSConfig/tree/main/skills
|
|
14
|
+
|
|
15
|
+
| Skill | Use it for here |
|
|
16
|
+
|---|---|
|
|
17
|
+
| `data-oriented-design` | `CircuitIR` (`src/ir`), the import AST and result tables: the six questions, SoA, narrowest widths, handles |
|
|
18
|
+
| `codebase-clean-code` | Owners: `import` reads, `ir` holds, `codegen` writes one dialect each, `backend` runs one simulator each; one spine per direction |
|
|
19
|
+
| `api-design` | Every `pub` item and the Python API (PySpice-close, backend neutral): usage code first, caller owns memory and flow |
|
|
20
|
+
| `code-style` | File order, ≤500 code lines per file, `check_style.py` |
|
|
21
|
+
| `simd-loops` | Hot loops over raw-file columns (`src/rawfile.rs`): the plain-loop forms, or explicit SIMD with a scalar oracle |
|
|
22
|
+
| `doc-comments` | Every `pub` item |
|
|
23
|
+
| `ponytail` (ultra) | How little code; never what shape the data takes |
|
|
24
|
+
| `assertions` | Contracts, capacities, bounded loops |
|
|
25
|
+
| `test-plan`, `tdd` | The oracles below, the gates, a feature's definition of done |
|
|
26
|
+
|
|
27
|
+
Language:
|
|
28
|
+
|
|
29
|
+
| Skill | Use it for here |
|
|
30
|
+
|---|---|
|
|
31
|
+
| `rust` | Types, memory, `zero-cost.md`: an abstraction enters a hot loop only with an `asm_probe` verdict; explicit SIMD is `fearless_simd` |
|
|
32
|
+
|
|
33
|
+
Project-specific:
|
|
34
|
+
|
|
35
|
+
| Skill | Use it for here |
|
|
36
|
+
|---|---|
|
|
37
|
+
| `compiler-construction` | `grammar/*.peg`, `src/import` and `src/codegen`: one schema every dialect captures into, lowering to `CircuitIR`, coded diagnostics, goldens |
|
|
38
|
+
| `spice-engine` | Reading a simulator's result: which oracle (ngspice, VACASK, analytic) and at what tolerance |
|
|
39
|
+
|
|
40
|
+
## The method
|
|
41
|
+
|
|
42
|
+
Binding on every change, in every project.
|
|
43
|
+
|
|
44
|
+
### Code
|
|
45
|
+
|
|
46
|
+
- Five commitments: lean storage, no runtime residue, cheap change,
|
|
47
|
+
contained failure, proof by test.
|
|
48
|
+
- Answer the six data questions before writing code. Then: one array per
|
|
49
|
+
field, the narrowest width the stated range allows, typed `u32` handles
|
|
50
|
+
with a sentinel, existence tables instead of flags, hot/cold split, tables
|
|
51
|
+
sized once from a named capacity, a compile-time size assertion on every
|
|
52
|
+
hot struct.
|
|
53
|
+
- An abstraction on a hot path carries an assembly probe: FOLDED, IDENTICAL,
|
|
54
|
+
EQUIVALENT or NEGATIVE pass; RESIDUE fails the build. A "no residue" claim
|
|
55
|
+
cites the probe, a speed claim cites a benchmark. Dispatch per batch, never
|
|
56
|
+
per element.
|
|
57
|
+
- A seam names what varies and needs a second case today; it sits on the
|
|
58
|
+
cheapest rung (concrete, free function, table, closed enum with exhaustive
|
|
59
|
+
switch, comptime, request table, function-pointer table, `dyn`, plugin).
|
|
60
|
+
- Tables, transforms, one spine per pipeline (ifs up, fors down), one owner
|
|
61
|
+
writes each table and everyone else appends requests. Three likely changes
|
|
62
|
+
each have a change radius of zero; the compiler lists every other site.
|
|
63
|
+
- APIs start from the caller's code. The caller owns memory and flow:
|
|
64
|
+
requests instead of callbacks, an immediate twin for anything retained.
|
|
65
|
+
Factor at the second real instance.
|
|
66
|
+
- Branches: delete, then branchless, then vectorize along a lane axis. The
|
|
67
|
+
`W == 1` instantiation is the scalar oracle; vectorization is verified in
|
|
68
|
+
the assembly.
|
|
69
|
+
- GPU: SoA always, the roofline ceiling named with its arithmetic before
|
|
70
|
+
tuning, data kept on the device, fixed-order reductions, the dependency DAG
|
|
71
|
+
recovered before porting. "This belongs on the CPU" is a valid verdict.
|
|
72
|
+
- An operating error returns to the caller that can decide; a bug hits an
|
|
73
|
+
assertion. Two or more split, paired assertions per function, a bound on
|
|
74
|
+
every loop, input validated once at the edge, fallible work before the
|
|
75
|
+
commit.
|
|
76
|
+
- Pass order: boundary, placement, data, zero-cost proof, contracts, tests,
|
|
77
|
+
branches, lanes. Data layout beats brevity. Every pass keeps NaN gates,
|
|
78
|
+
allocation-failure paths, `errdefer`s, trust-boundary validation and
|
|
79
|
+
tolerances.
|
|
80
|
+
|
|
81
|
+
### Testing
|
|
82
|
+
|
|
83
|
+
- The oracle is named before the code and never recomputes the answer the
|
|
84
|
+
way the code does. Cheapest first: assertions, a reference
|
|
85
|
+
implementation, a round trip, a certificate, a metamorphic relation, a
|
|
86
|
+
model, a golden with recorded provenance, a spec example.
|
|
87
|
+
- The main bug class is a wrong number with no crash, which coverage and
|
|
88
|
+
fuzzing cannot see. A bug found by a person is a hole in the oracle set:
|
|
89
|
+
it lands with its regression test and the oracle or generator that would
|
|
90
|
+
have caught its class.
|
|
91
|
+
- A new test goes red on the bug before it is trusted green.
|
|
92
|
+
- Unsupported fails and never skips. A known failure is a named marker in
|
|
93
|
+
the tree; an unexpected pass fails until the marker goes. Name lists are
|
|
94
|
+
compared, never counts.
|
|
95
|
+
- A tolerance follows the oracle's own accuracy. Determinism is a test:
|
|
96
|
+
1 job and N jobs give the same bytes, and the order is fixed, not the test.
|
|
97
|
+
- A flaky test is fixed or quarantined the same day, never retried
|
|
98
|
+
silently.
|
|
99
|
+
- Tiers: pre-commit under 10 s, merge under 15 min, nightly, release. A
|
|
100
|
+
release ships on numbers a script checks. The map lives in `TESTING.md`.
|
|
101
|
+
|
|
102
|
+
### Builds
|
|
103
|
+
|
|
104
|
+
- A build is a cache keyed on its declared inputs. Every producing step has
|
|
105
|
+
an output argument, every checking step an exit-code check, every file
|
|
106
|
+
read at run time is declared (`addFileInput`) or the step says
|
|
107
|
+
`has_side_effects`. Keys hash contents, never absolute paths.
|
|
108
|
+
- Cut the artifact graph where edits land: one object per generated unit,
|
|
109
|
+
narrow imports for shared ones, kernels out of host graphs.
|
|
110
|
+
- Zig edit loop: `zig build check --watch -fincremental`, one watch per
|
|
111
|
+
artifact across all worktrees; the result that counts comes from a plain
|
|
112
|
+
build. One global cache per toolchain store path; a worktree symlinks its
|
|
113
|
+
`.zig-cache` to the main checkout's.
|
|
114
|
+
- Rust: flags live in `.cargo/config.toml`, never a one-off `RUSTFLAGS`;
|
|
115
|
+
`check`, `build`, `test` and rust-analyzer agree on features, profile and
|
|
116
|
+
target directory (rust-analyzer gets its own).
|
|
117
|
+
- Nothing collects a cache. Keep a byte budget per cache and delete old
|
|
118
|
+
entries only while no build runs (the `long-term-garbage-collection`
|
|
119
|
+
skill); a warm cache is kept, never wiped by routine.
|
|
120
|
+
- Gate on the exit code: `cmd | tail` swallows it, so use
|
|
121
|
+
`exit "${PIPESTATUS[0]}"`.
|
|
122
|
+
|
|
123
|
+
### Maintaining
|
|
124
|
+
|
|
125
|
+
- `main` is green by machine: work lands through a pull request whose merge
|
|
126
|
+
result passed the required checks. No `dev` branch; topic branches are
|
|
127
|
+
deleted after the merge.
|
|
128
|
+
- Bots never push to `main`. Generated output ships as a release asset or
|
|
129
|
+
through a gated pull request.
|
|
130
|
+
- Every dependency is pinned by commit and content hash, the toolchain by
|
|
131
|
+
`flake.lock`, actions by SHA. A third-party input you hash is mirrored
|
|
132
|
+
somewhere you control.
|
|
133
|
+
- The changelog is written by hand, one line per change citing its issue,
|
|
134
|
+
every number in it measured. A release refuses a version mismatch, builds
|
|
135
|
+
every target, checks every artifact and smokes the bundle.
|
|
136
|
+
- CI holds: the merge gate, every target compiled, docs that execute,
|
|
137
|
+
reference suites gated by name, a nightly, the downstream contracts, the
|
|
138
|
+
release job.
|
|
139
|
+
|
|
140
|
+
## Building
|
|
141
|
+
|
|
142
|
+
- Every build runs inside `nix develop -c …`; `nix develop .#testing` adds
|
|
143
|
+
ngspice, OpenVAF, VACASK and the sky130/gf180 PDKs the integration tests
|
|
144
|
+
run against. CI runs both suites in `.#testing`.
|
|
145
|
+
- Rust: `cargo test` (name one test target with `--test <file>` while
|
|
146
|
+
iterating). Python: in a venv with `--system-site-packages`,
|
|
147
|
+
`maturin develop` then `python3 -m pytest`.
|
|
148
|
+
- A change to the public Python API updates `docs/` and the user-facing
|
|
149
|
+
skill in `skills/spicerack/` in the same commit.
|
|
150
|
+
- Run one cargo process per agent, and don't build while `free -g` shows
|
|
151
|
+
under 6 GB available.
|
|
152
|
+
|
|
153
|
+
## Testing
|
|
154
|
+
|
|
155
|
+
- Every test names its oracle: the independent thing that says the output is
|
|
156
|
+
wrong. A netlist is checked by running it on the real simulator or against
|
|
157
|
+
a golden with provenance, never by re-deriving it the way codegen does.
|
|
158
|
+
- Unsupported fails and never skips: a missing simulator in `.#testing` is a
|
|
159
|
+
failure.
|
|
160
|
+
- A golden that disagrees with an independent oracle is a bug in the code
|
|
161
|
+
that wrote it. Fix the code, regenerate the golden, and say so in the commit.
|
|
162
|
+
|
|
163
|
+
## Committing
|
|
164
|
+
|
|
165
|
+
Commit at every green step: both suites passing, `cargo fmt --check` clean.
|
|
166
|
+
The message says what changed and in which owner. Never commit red to `main`.
|