circuitsilk 0.2.0__py3-none-any.whl

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 (350) hide show
  1. circuitsilk-0.2.0.dist-info/METADATA +475 -0
  2. circuitsilk-0.2.0.dist-info/RECORD +350 -0
  3. circuitsilk-0.2.0.dist-info/WHEEL +5 -0
  4. circuitsilk-0.2.0.dist-info/licenses/LICENSE +21 -0
  5. circuitsilk-0.2.0.dist-info/top_level.txt +1 -0
  6. silk/__init__.py +206 -0
  7. silk/_json_codec.py +111 -0
  8. silk/circuit/__init__.py +43 -0
  9. silk/circuit/_behavioral_identity.py +146 -0
  10. silk/circuit/_module_base.py +570 -0
  11. silk/circuit/_module_protocol.py +115 -0
  12. silk/circuit/_results_json.py +467 -0
  13. silk/circuit/_spec_report_json.py +375 -0
  14. silk/circuit/bus_spec.py +154 -0
  15. silk/circuit/circuit_elements.py +1175 -0
  16. silk/circuit/composition.py +1124 -0
  17. silk/circuit/data/port-roles.default.yaml +18 -0
  18. silk/circuit/data/region-thresholds.default.yaml +22 -0
  19. silk/circuit/declared_indices.py +32 -0
  20. silk/circuit/device_view.py +139 -0
  21. silk/circuit/emitted_names.py +310 -0
  22. silk/circuit/ground_port.py +157 -0
  23. silk/circuit/interface_check.py +317 -0
  24. silk/circuit/junction_check.py +70 -0
  25. silk/circuit/metric_handle.py +207 -0
  26. silk/circuit/module_placement.py +337 -0
  27. silk/circuit/module_test.py +7108 -0
  28. silk/circuit/modules.py +385 -0
  29. silk/circuit/modules_db.py +785 -0
  30. silk/circuit/modules_faults.py +163 -0
  31. silk/circuit/modules_netlist.py +943 -0
  32. silk/circuit/modules_results.py +1905 -0
  33. silk/circuit/modules_sim.py +1215 -0
  34. silk/circuit/modules_spec.py +278 -0
  35. silk/circuit/modules_structure.py +1979 -0
  36. silk/circuit/modules_testbench.py +960 -0
  37. silk/circuit/monte_carlo.py +1050 -0
  38. silk/circuit/monte_carlo_draws.py +428 -0
  39. silk/circuit/monte_carlo_report.py +353 -0
  40. silk/circuit/net.py +313 -0
  41. silk/circuit/node_paths.py +303 -0
  42. silk/circuit/object_holders.py +154 -0
  43. silk/circuit/op_table.py +570 -0
  44. silk/circuit/placement_reference.py +465 -0
  45. silk/circuit/port_binding.py +41 -0
  46. silk/circuit/port_roles.py +366 -0
  47. silk/circuit/ports.py +447 -0
  48. silk/circuit/region_thresholds.py +137 -0
  49. silk/circuit/report.py +3270 -0
  50. silk/circuit/report_diff.py +1128 -0
  51. silk/circuit/rolecheck.py +19 -0
  52. silk/circuit/spec_report.py +1224 -0
  53. silk/circuit/spice_netlister.py +1688 -0
  54. silk/circuit/sweep_sources.py +64 -0
  55. silk/circuit/test_execution.py +189 -0
  56. silk/circuit/test_failure.py +243 -0
  57. silk/circuit/test_placement.py +702 -0
  58. silk/circuit/variable.py +741 -0
  59. silk/circuit/view_nodes.py +280 -0
  60. silk/circuit/voltage_domain.py +153 -0
  61. silk/circuit/wiring_consistency.py +88 -0
  62. silk/circuit/xyce_ground.py +117 -0
  63. silk/circuit/xyce_netlister.py +390 -0
  64. silk/codegen/__init__.py +18 -0
  65. silk/codegen/generator.py +2900 -0
  66. silk/codegen/source_names.py +61 -0
  67. silk/codegen/testbench_generator.py +1736 -0
  68. silk/constraints/__init__.py +63 -0
  69. silk/constraints/_module_patch.py +72 -0
  70. silk/constraints/_netlist_view.py +43 -0
  71. silk/constraints/checkers.py +120 -0
  72. silk/constraints/envelope.py +83 -0
  73. silk/constraints/serialization.py +260 -0
  74. silk/constraints/types.py +304 -0
  75. silk/db/__init__.py +86 -0
  76. silk/db/_attempts.py +87 -0
  77. silk/db/_condition_columns.py +152 -0
  78. silk/db/_deck_check.py +263 -0
  79. silk/db/_source_identity.py +138 -0
  80. silk/db/circuit_db.py +6226 -0
  81. silk/db/circuit_import.py +1020 -0
  82. silk/db/context.py +354 -0
  83. silk/db/identity.py +800 -0
  84. silk/db/migration.py +1183 -0
  85. silk/db/models.py +675 -0
  86. silk/db/schema.py +814 -0
  87. silk/db/structure_tracker.py +1196 -0
  88. silk/db/tracking.py +2585 -0
  89. silk/doctor.py +501 -0
  90. silk/elements/__init__.py +31 -0
  91. silk/elements/_catalog.py +32 -0
  92. silk/elements/analog_devices.yaml +83 -0
  93. silk/elements/base.py +484 -0
  94. silk/elements/factory.py +649 -0
  95. silk/elements/library.py +82 -0
  96. silk/elements/passives.py +284 -0
  97. silk/elements/schema.py +448 -0
  98. silk/examples/__init__.py +76 -0
  99. silk/examples/abo_th_example.py +546 -0
  100. silk/examples/amplifier_variants_example.py +155 -0
  101. silk/examples/bandgap_example.py +439 -0
  102. silk/examples/behavioral_example.py +167 -0
  103. silk/examples/bus_ports_example.py +243 -0
  104. silk/examples/charge_pump_example.py +253 -0
  105. silk/examples/circuit_report_example.py +105 -0
  106. silk/examples/circuit_tracking_example.py +258 -0
  107. silk/examples/cml_cells.py +852 -0
  108. silk/examples/cml_ffe_eye.py +110 -0
  109. silk/examples/cmos_ffe_eye.py +157 -0
  110. silk/examples/compare_outputs.py +53 -0
  111. silk/examples/composition_graph_demo.py +53 -0
  112. silk/examples/constraints_5t_ota.py +205 -0
  113. silk/examples/constraints_current_mirror.py +129 -0
  114. silk/examples/constraints_diff_pair.py +120 -0
  115. silk/examples/constraints_external_load.py +153 -0
  116. silk/examples/current_mirror_example.py +199 -0
  117. silk/examples/design_loop_walkthrough.py +773 -0
  118. silk/examples/design_loop_walkthrough_gf180mcu.py +154 -0
  119. silk/examples/design_loop_walkthrough_sg13g2.py +364 -0
  120. silk/examples/diff_pair_construction_example.py +82 -0
  121. silk/examples/differential_th_example.py +162 -0
  122. silk/examples/eye_centering.py +69 -0
  123. silk/examples/factory_api_example.py +118 -0
  124. silk/examples/fault_injection_example.py +135 -0
  125. silk/examples/flash_adc_example.py +1371 -0
  126. silk/examples/folded_cascode.py +232 -0
  127. silk/examples/gm_id_lookup.py +316 -0
  128. silk/examples/hierarchical_example.py +191 -0
  129. silk/examples/layout_intelligence_example.py +425 -0
  130. silk/examples/ldo_calibrate.py +188 -0
  131. silk/examples/ldo_design.py +174 -0
  132. silk/examples/ldo_regulator_example.py +615 -0
  133. silk/examples/lint_coverage_example.py +307 -0
  134. silk/examples/mc_diff_pair_offset.py +106 -0
  135. silk/examples/metrics/__init__.py +13 -0
  136. silk/examples/metrics/comparator_and_sampler.py +506 -0
  137. silk/examples/metrics/cs_amp_ac_noise.py +321 -0
  138. silk/examples/metrics/cs_amp_distortion.py +211 -0
  139. silk/examples/metrics/cs_amp_power_sweep.py +256 -0
  140. silk/examples/metrics/cs_amp_two_tone.py +213 -0
  141. silk/examples/metrics/diff_pair_rejection.py +323 -0
  142. silk/examples/metrics/flash_adc_codes.py +307 -0
  143. silk/examples/metrics/inverter_timing.py +219 -0
  144. silk/examples/metrics/prbs_eye.py +415 -0
  145. silk/examples/metrics/ring_osc_jitter.py +349 -0
  146. silk/examples/metrics/rlc_filter_ac.py +159 -0
  147. silk/examples/metrics/rlc_step.py +183 -0
  148. silk/examples/net_current_persistence_example.py +356 -0
  149. silk/examples/net_object_example.py +162 -0
  150. silk/examples/ota_5t_guide.py +299 -0
  151. silk/examples/output_modes_example.py +182 -0
  152. silk/examples/parameter_sweep_example.py +212 -0
  153. silk/examples/pfd_example.py +435 -0
  154. silk/examples/pll_calibrate.py +106 -0
  155. silk/examples/pll_example.py +443 -0
  156. silk/examples/pll_spec_tree_example.py +284 -0
  157. silk/examples/pll_spice_example.py +275 -0
  158. silk/examples/pll_twin_vs_spice.py +105 -0
  159. silk/examples/port_role_example.py +167 -0
  160. silk/examples/port_role_inference_example.py +129 -0
  161. silk/examples/prbs_generator_example.py +573 -0
  162. silk/examples/pwl_example.py +202 -0
  163. silk/examples/ring_calibrate.py +153 -0
  164. silk/examples/ring_oscillator_example.py +446 -0
  165. silk/examples/ring_oscillator_stage_sweep.py +112 -0
  166. silk/examples/sar_adc_example.py +288 -0
  167. silk/examples/sar_adc_spice.py +1212 -0
  168. silk/examples/sar_calibrate.py +62 -0
  169. silk/examples/sar_resolution_sweep.py +353 -0
  170. silk/examples/serdes_tx_driver_example.py +348 -0
  171. silk/examples/serdes_tx_example.py +978 -0
  172. silk/examples/serializer_example.py +552 -0
  173. silk/examples/source_examples.py +288 -0
  174. silk/examples/source_follower_calibrate.py +293 -0
  175. silk/examples/source_follower_example.py +298 -0
  176. silk/examples/source_follower_optimize.py +55 -0
  177. silk/examples/stdcells.py +982 -0
  178. silk/examples/strongarm_tb.py +874 -0
  179. silk/examples/supply_regulated_vco_example.py +286 -0
  180. silk/examples/testbench_codegen_example.py +117 -0
  181. silk/examples/two_stage_miller_ota_example.py +308 -0
  182. silk/exceptions.py +428 -0
  183. silk/faults/__init__.py +33 -0
  184. silk/faults/application.py +318 -0
  185. silk/faults/campaign.py +763 -0
  186. silk/faults/evaluation.py +299 -0
  187. silk/faults/pdk_metadata.py +125 -0
  188. silk/faults/report.py +370 -0
  189. silk/faults/runner.py +148 -0
  190. silk/faults/set.py +287 -0
  191. silk/faults/sugar.py +386 -0
  192. silk/faults/types.py +206 -0
  193. silk/layout/__init__.py +35 -0
  194. silk/layout/_types.py +39 -0
  195. silk/layout/area_model.py +248 -0
  196. silk/layout/estimator.py +610 -0
  197. silk/layout/matching.py +273 -0
  198. silk/layout/parasitics.py +242 -0
  199. silk/layout/routing_model.py +152 -0
  200. silk/layout/wirelength_model.py +66 -0
  201. silk/lint/__init__.py +84 -0
  202. silk/lint/exclusions.py +117 -0
  203. silk/lint/help.py +66 -0
  204. silk/lint/locations.py +152 -0
  205. silk/lint/registry.py +409 -0
  206. silk/lint/reports/__init__.py +12 -0
  207. silk/lint/reports/coverage_report.py +471 -0
  208. silk/lint/reports/lint_report.py +595 -0
  209. silk/lint/reports/metadata.py +118 -0
  210. silk/lint/rule.py +160 -0
  211. silk/lint/rules/__init__.py +87 -0
  212. silk/lint/rules/domain.py +224 -0
  213. silk/lint/rules/interface.py +402 -0
  214. silk/lint/rules/stress.py +483 -0
  215. silk/lint/rules/structural.py +871 -0
  216. silk/lint/severity.py +49 -0
  217. silk/lint/stress_coverage.py +159 -0
  218. silk/lint/violations.py +174 -0
  219. silk/lint/waivers.py +230 -0
  220. silk/lint_markers/__init__.py +6 -0
  221. silk/lint_markers/no_connect.py +26 -0
  222. silk/lint_markers/no_connect_port.py +55 -0
  223. silk/lint_markers/stale.py +131 -0
  224. silk/metrics/__init__.py +440 -0
  225. silk/metrics/_eye.py +137 -0
  226. silk/metrics/_guards.py +369 -0
  227. silk/metrics/ac.py +1714 -0
  228. silk/metrics/converter.py +1167 -0
  229. silk/metrics/diagnostics.py +132 -0
  230. silk/metrics/eye.py +542 -0
  231. silk/metrics/fom.py +191 -0
  232. silk/metrics/jitter.py +1121 -0
  233. silk/metrics/noise.py +1040 -0
  234. silk/metrics/power.py +258 -0
  235. silk/metrics/rf.py +1209 -0
  236. silk/metrics/spectral.py +2402 -0
  237. silk/metrics/statistics.py +666 -0
  238. silk/metrics/timing.py +2242 -0
  239. silk/metrics/waveform.py +1822 -0
  240. silk/optimize/__init__.py +5 -0
  241. silk/optimize/optimizer.py +798 -0
  242. silk/optimize/parameter_space.py +537 -0
  243. silk/pdk/__init__.py +35 -0
  244. silk/pdk/_loader.py +180 -0
  245. silk/pdk/basepdk.py +1455 -0
  246. silk/pdk/data/gf180mcu.pdk.yaml +207 -0
  247. silk/pdk/data/gf180mcu_device_details.yaml +2087 -0
  248. silk/pdk/data/sg13g2.pdk.yaml +91 -0
  249. silk/pdk/data/sg13g2_device_details.yaml +223 -0
  250. silk/pdk/data/sky130-internal-node-certificate.yaml +3118 -0
  251. silk/pdk/data/sky130.pdk.yaml +110 -0
  252. silk/pdk/data/skywater_130_device_details.yaml +1562 -0
  253. silk/pdk/registry.py +113 -0
  254. silk/pdk/statistical.py +117 -0
  255. silk/pdk/validate.py +802 -0
  256. silk/settings.py +235 -0
  257. silk/signals/__init__.py +17 -0
  258. silk/signals/analysis_kind.py +269 -0
  259. silk/signals/assemble.py +364 -0
  260. silk/signals/base.py +2212 -0
  261. silk/signals/kinds.py +555 -0
  262. silk/signals/operations.py +121 -0
  263. silk/signals/rawfile.py +987 -0
  264. silk/signals/schema.py +800 -0
  265. silk/signals/spice.py +175 -0
  266. silk/signals/view/__init__.py +28 -0
  267. silk/signals/view/__main__.py +325 -0
  268. silk/signals/view/assets/LICENSE.uPlot +21 -0
  269. silk/signals/view/assets/explorer.mjs +8367 -0
  270. silk/signals/view/assets/selectors.mjs +152 -0
  271. silk/signals/view/assets/uplot.iife.min.js +2 -0
  272. silk/signals/view/assets/uplot.min.css +1 -0
  273. silk/signals/view/assets/view.css +1358 -0
  274. silk/signals/view/assets/view.html.tmpl +26 -0
  275. silk/signals/view/assets/view.js +64 -0
  276. silk/signals/view/assets/waveform-core.mjs +732 -0
  277. silk/signals/view/emit.py +1570 -0
  278. silk/signals/view/encode.py +282 -0
  279. silk/signals/view/node_context.py +66 -0
  280. silk/signals/view/node_select.py +96 -0
  281. silk/signals/view/select.py +607 -0
  282. silk/signals/view/serialize.py +65 -0
  283. silk/signals/view/serve.py +101 -0
  284. silk/signals/view/template.py +211 -0
  285. silk/simulation/__init__.py +45 -0
  286. silk/simulation/_analysis_context.py +52 -0
  287. silk/simulation/_behavioral_elements.py +239 -0
  288. silk/simulation/_behavioral_feedback.py +109 -0
  289. silk/simulation/_behavioral_models.py +94 -0
  290. silk/simulation/_behavioral_state.py +223 -0
  291. silk/simulation/_behavioral_variation.py +168 -0
  292. silk/simulation/_behavioral_views.py +474 -0
  293. silk/simulation/_device_requests.py +80 -0
  294. silk/simulation/_failure_detail.py +105 -0
  295. silk/simulation/_frequency_grid.py +25 -0
  296. silk/simulation/_internal_nodes.py +165 -0
  297. silk/simulation/_ngspice_compat.py +175 -0
  298. silk/simulation/_ngspice_version.py +29 -0
  299. silk/simulation/_replay.py +289 -0
  300. silk/simulation/_setup_check.py +137 -0
  301. silk/simulation/_worker_pickle.py +43 -0
  302. silk/simulation/analysis.py +484 -0
  303. silk/simulation/backend.py +2071 -0
  304. silk/simulation/behavioral.py +637 -0
  305. silk/simulation/behavioral_backend.py +326 -0
  306. silk/simulation/completion.py +327 -0
  307. silk/simulation/conditions.py +1603 -0
  308. silk/simulation/convergence.py +84 -0
  309. silk/simulation/corner.py +71 -0
  310. silk/simulation/executor.py +482 -0
  311. silk/simulation/generation.py +708 -0
  312. silk/simulation/launch_fact.py +36 -0
  313. silk/simulation/mc_chunk.py +411 -0
  314. silk/simulation/provenance.py +598 -0
  315. silk/simulation/run_files.py +277 -0
  316. silk/simulation/runner.py +498 -0
  317. silk/simulation/topology.py +270 -0
  318. silk/simulation/variation.py +237 -0
  319. silk/simulation/xyce_runner.py +361 -0
  320. silk/simulators/__init__.py +8 -0
  321. silk/simulators/_loader.py +179 -0
  322. silk/simulators/behavioral.yaml +20 -0
  323. silk/simulators/ngspice.yaml +170 -0
  324. silk/simulators/xyce.yaml +61 -0
  325. silk/sources/__init__.py +101 -0
  326. silk/sources/_bits.py +88 -0
  327. silk/sources/_layout.py +112 -0
  328. silk/sources/_operating_point.py +47 -0
  329. silk/sources/_timing.py +100 -0
  330. silk/sources/classes.py +1375 -0
  331. silk/sources/library.py +168 -0
  332. silk/sources/schema.py +383 -0
  333. silk/sources/source_metadata.yaml +198 -0
  334. silk/sources/waveforms.py +1625 -0
  335. silk/specs/__init__.py +47 -0
  336. silk/specs/_calibration.py +99 -0
  337. silk/specs/aggregate.py +189 -0
  338. silk/specs/attempt.py +441 -0
  339. silk/specs/evidence.py +234 -0
  340. silk/specs/reconciler.py +246 -0
  341. silk/specs/report.py +329 -0
  342. silk/specs/resolver.py +126 -0
  343. silk/specs/spec.py +627 -0
  344. silk/spice_names.py +228 -0
  345. silk/utils/__init__.py +6 -0
  346. silk/utils/_compat.py +13 -0
  347. silk/utils/_utils.py +340 -0
  348. silk/utils/deck_text.py +93 -0
  349. silk/utils/identifiers.py +21 -0
  350. silk/vector_match.py +118 -0
@@ -0,0 +1,475 @@
1
+ Metadata-Version: 2.4
2
+ Name: circuitsilk
3
+ Version: 0.2.0
4
+ Summary: Custom circuit design in Python, from specs to layout
5
+ Author: Levant Labs
6
+ License: MIT
7
+ Project-URL: Homepage, https://github.com/levantlabs/silk
8
+ Project-URL: Repository, https://github.com/levantlabs/silk
9
+ Project-URL: Documentation, https://github.com/levantlabs/silk/blob/main/docs/quickstart.md
10
+ Project-URL: Bug Tracker, https://github.com/levantlabs/silk/issues
11
+ Keywords: spice,analog,eda,sky130,ngspice,circuit,netlist
12
+ Classifier: Development Status :: 3 - Alpha
13
+ Classifier: Intended Audience :: Science/Research
14
+ Classifier: Intended Audience :: Developers
15
+ Classifier: License :: OSI Approved :: MIT License
16
+ Classifier: Programming Language :: Python :: 3
17
+ Classifier: Programming Language :: Python :: 3.10
18
+ Classifier: Programming Language :: Python :: 3.11
19
+ Classifier: Programming Language :: Python :: 3.12
20
+ Classifier: Programming Language :: Python :: 3.13
21
+ Classifier: Topic :: Scientific/Engineering :: Electronic Design Automation (EDA)
22
+ Classifier: Topic :: Scientific/Engineering
23
+ Requires-Python: >=3.10
24
+ Description-Content-Type: text/markdown
25
+ License-File: LICENSE
26
+ Requires-Dist: numpy>=1.26
27
+ Requires-Dist: matplotlib
28
+ Requires-Dist: pyyaml
29
+ Requires-Dist: pydantic>=2
30
+ Provides-Extra: dev
31
+ Requires-Dist: pytest; extra == "dev"
32
+ Requires-Dist: pytest-cov; extra == "dev"
33
+ Requires-Dist: build; extra == "dev"
34
+ Requires-Dist: twine; extra == "dev"
35
+ Provides-Extra: docs
36
+ Requires-Dist: sphinx<9,>=7.2; extra == "docs"
37
+ Requires-Dist: myst-parser<5,>=3; extra == "docs"
38
+ Dynamic: license-file
39
+
40
+ # circuitsilk
41
+
42
+ **Custom circuit design in Python, from specs to layout.**
43
+
44
+ circuitsilk (`import silk`) is a framework for custom IC design. A circuit is one live Python object, and that object carries the design through the whole flow: specs, sizing, simulation, verification, reports, design history and layout. Every step is code with typed, checked results, so intelligence — yours, a script's or an AI agent's — can span the entire design flow, not just the netlist.
45
+
46
+ - **Testbenches that live with the circuit.** Each block carries its own tests, metrics and specs; `run_all_tests()` measures everything and reports pass or fail.
47
+ - **Two engines, one workflow.** Iterate in seconds with the built-in behavioral engine (no simulator, no PDK), then run the same testbenches at transistor level in ngspice. Xyce is a preview backend.
48
+ - **Corners, Monte Carlo and design-space search.** PVT corners, Monte Carlo (including behavioral mismatch), sweeps, sampling, and an optimizer that reads testbench metrics directly.
49
+ - **Browser waveform viewer.** Explore signals, cursors and derived expressions in the [interactive viewer](https://github.com/levantlabs/silk/blob/main/docs/waveform-explorer.md).
50
+ - **A full metric library.** Gain, bandwidth and phase margin; SNDR, ENOB, SFDR and INL/DNL for data converters; delay, slew, settling, jitter, noise, distortion and power.
51
+ - **Results you can trust.** silk doesn't take a simulator's exit code on faith. A run that produces no data, or stops before the end of the analysis silk wrote, raises a typed error instead of returning plausible numbers.
52
+ - **Checks beyond simulation.** Analog lint rules (interfaces, voltage domains, junction overrange) and fault-injection campaigns.
53
+ - **Layout (in progress).** Estimated parasitics can be fed into simulation and optimization, and a design's simulated currents and wiring are available for layout.
54
+ - **Design history.** A local SQLite database records versions, metrics and spec results at each PVT point, so a design can be reopened, rebuilt and compared.
55
+ - **Built for AI agents.** Keyword-only APIs that fail loudly, a machine-readable schema export, and an agent guide that walks the whole flow.
56
+
57
+ The whole loop, from system intent to sizing, characterization, reports, database, rebuild and layout feedback, runs in one worked example: `python -m silk.examples.design_loop_walkthrough`.
58
+
59
+ **PDKs.** The PDK layer is pluggable: a new PDK is two data files, not code. For 0.2.0, SkyWater 130nm is the only release-validated transistor-simulation PDK; GF180MCU and SG13G2 ship as preview integrations. Install open-source PDKs with [pdksetup](https://github.com/levantlabs/pdksetup) (`pdk install sky130`).
60
+
61
+ **No PDK yet?** Create and activate a virtual environment, install silk, then
62
+ run a behavioral simulation with no PDK and no ngspice:
63
+
64
+ ```bash
65
+ python3 -m venv .venv
66
+ source .venv/bin/activate
67
+ python -m pip install "circuitsilk>=0.2"
68
+ python -m silk.examples.behavioral_example
69
+ ```
70
+
71
+ If `venv` or `ensurepip` is missing, install `python3-venv`
72
+ (`sudo apt install python3-venv`) or ask your administrator, then retry.
73
+ Continue with the [60-second start](https://github.com/levantlabs/silk/blob/main/docs/quickstart.md#1-60-second-start-no-pdk-no-ngspice).
74
+
75
+ ## A first transistor-level circuit: a CMOS inverter
76
+
77
+ This example builds a CMOS inverter on sky130, checks its delay against a spec in ngspice, and plots the waveforms. It needs the [Installation](#installation) steps first (ngspice and the sky130 PDK); the behavioral example above needs neither.
78
+
79
+ ```python
80
+ from silk import Module, Port, load_pdk, sources
81
+ from silk.elements import elements
82
+ from silk.metrics import propagation_delay
83
+ from silk.simulation import Transient
84
+
85
+ pdk = load_pdk('sky130') # finds the models through the PDK_ROOT setting
86
+
87
+ # The circuit: a CMOS inverter, as a block with typed ports
88
+ inv = Module('PDK_skywater130', 'out', 'inverter.cir', pdk_details=pdk,
89
+ module_name='inverter')
90
+ inv.define_module_ports({'VDD': Port.supply(), 'VSS': Port.ground(),
91
+ 'IN': Port.analog_input(), 'OUT': Port.analog_output()})
92
+ with inv: # devices created here join the inverter
93
+ pdk.nmos1p8('mn', d='OUT', g='IN', s='VSS', b='VSS', w=1.0, l=0.15)
94
+ pdk.pmos1p8('mp', d='OUT', g='IN', s='VDD', b='VDD', w=2.0, l=0.15)
95
+
96
+ # Its testbench: drive it, load it, probe it, and check it against a spec
97
+ tb = inv.create_test('step')
98
+ tb.add_module_under_test({'VDD': 'vdd', 'VSS': '0', 'IN': 'vin', 'OUT': 'vout'})
99
+ tb.add_source(sources.VoltageSource('vdd', positive='vdd', negative='0', dc=1.8))
100
+ tb.add_source(sources.VoltageSource('vin', positive='vin', negative='0',
101
+ pulse=sources.Pulse(v1=0, v2=1.8, td=1e-9, tr=0.5e-9,
102
+ tf=0.5e-9, pw=4e-9, per=10e-9)))
103
+ tb.add(elements.capacitor('cl', p='vout', n='0', value=10e-15))
104
+ tb.add_sim_type(Transient(step=0.01e-9, stop=10e-9))
105
+ tb.set_supply_voltage(1.8, source='vdd')
106
+
107
+ vin, vout = tb.probe('vin'), tb.probe('vout')
108
+ tb.add_metric('delay', propagation_delay, sig_in=vin, sig_out=vout,
109
+ out_edge='falling')
110
+ tb.add_spec('delay < 150 ps', 'delay', '<', 150e-12)
111
+
112
+ report = tb.run() # ngspice, typical corner
113
+ print(f"delay {report.metrics['delay'] * 1e12:.0f} ps: {'PASS' if report.passed else 'FAIL'}")
114
+ print(f'vout swings {vout.y.min():.3f} V to {vout.y.max():.3f} V')
115
+ tb.plot(vin, vout)
116
+ ```
117
+
118
+ For interactive exploration after the run, open the browser viewer:
119
+
120
+ ```python
121
+ tb.netlist.view()
122
+ ```
123
+
124
+ For a headless run, use `html_path = tb.netlist.view(open=False)` to return the
125
+ HTML path without opening a browser. By default, `view.html` is written beside
126
+ the rawfile and may have companion files. See the
127
+ [viewer guide](https://github.com/levantlabs/silk/blob/main/docs/waveform-explorer.md).
128
+ Keep `tb.plot(vin, vout)` for a static plot.
129
+
130
+ Expected output:
131
+
132
+ ```text
133
+ delay 91 ps: PASS
134
+ vout swings -0.004 V to 1.816 V
135
+ ```
136
+
137
+ Continue with [docs/quickstart.md](https://github.com/levantlabs/silk/blob/main/docs/quickstart.md) for the step-by-step workflow.
138
+
139
+ ## Installation
140
+
141
+ ```bash
142
+ # Debian/Ubuntu system pythons are externally managed (PEP 668) — work in a venv:
143
+ python3 -m venv .venv
144
+ source .venv/bin/activate
145
+
146
+ pip install "circuitsilk>=0.2"
147
+ # — or from source —
148
+ git clone https://github.com/levantlabs/silk.git
149
+ cd silk
150
+ pip install -e ".[dev]"
151
+ ```
152
+
153
+ **System requirements:**
154
+
155
+ - Python 3.10–3.13
156
+ - ngspice 42 or newer (for SPICE simulation): check `ngspice --version`.
157
+ If missing or older, install or update it with `sudo apt install ngspice`
158
+ on Debian/Ubuntu, or ask your administrator; then check again.
159
+ It is the release-validated simulator; Xyce is an optional **preview** backend
160
+ ([what is and is not validated](https://github.com/levantlabs/silk/blob/main/docs/known_issues.md#simulator-backends))
161
+ - SkyWater 130nm PDK models at `$PDK_ROOT` (for simulations using sky130 devices) —
162
+ see [docs/installing-the-pdk.md](https://github.com/levantlabs/silk/blob/main/docs/installing-the-pdk.md)
163
+
164
+ The `PDK_ROOT` setting should point to a directory that contains
165
+ `sky130A/libs.tech/ngspice/sky130.lib.spice` (the standard open_pdks layout).
166
+ [docs/installing-the-pdk.md](https://github.com/levantlabs/silk/blob/main/docs/installing-the-pdk.md) walks through getting
167
+ there with [pdksetup](https://github.com/levantlabs/pdksetup)
168
+ (`pdk install sky130`), plus Docker and open_pdks alternatives.
169
+
170
+ Tool and PDK locations (`PDK_ROOT`, `SILK_NGSPICE_BIN`, `SILK_XYCE_BIN`, …) are
171
+ silk **settings**: set them as environment variables, or once in a settings
172
+ file at `~/.config/silk/silk.env` so every shell and IDE picks them up. An
173
+ environment variable overrides the file. See
174
+ [docs/settings.md](https://github.com/levantlabs/silk/blob/main/docs/settings.md)
175
+ for the format and a copy-paste example.
176
+
177
+ `load_pdk('sky130')` loads the packaged catalog even without the model files.
178
+ SPICE circuits made only from ideal elements, sources and passives need
179
+ ngspice but no installed PDK; see the
180
+ [PDK-free RC walkthrough](https://github.com/levantlabs/silk/blob/main/docs/quickstart.md#the-middle-rung-real-spice-with-no-pdk).
181
+ Model files are checked when a simulation needs them; a missing library raises
182
+ `SimulationError` with installation advice.
183
+
184
+ Behavioral simulation needs neither ngspice nor PDK models — see the
185
+ [60-second start](https://github.com/levantlabs/silk/blob/main/docs/quickstart.md#1-60-second-start-no-pdk-no-ngspice).
186
+
187
+ To check all of the above at once — interpreter, dependencies, your silk
188
+ settings, ngspice, and the model library of every registered PDK — run the
189
+ environment doctor (exit 0 when
190
+ the setup is ready, and it prints a fix for anything that isn't):
191
+
192
+ ```bash
193
+ python -m silk.doctor # add --json for machine-readable output
194
+ ```
195
+
196
+ ## Quick start
197
+
198
+ See [docs/quickstart.md](https://github.com/levantlabs/silk/blob/main/docs/quickstart.md) for a step-by-step walkthrough.
199
+
200
+ Find answers by question in the [documentation index](https://github.com/levantlabs/silk/blob/main/docs/README.md), or browse these guides:
201
+
202
+ - [docs/examples.md](https://github.com/levantlabs/silk/blob/main/docs/examples.md) — human-facing guide to the worked
203
+ examples: a learning path plus a by-topic index
204
+ - [docs/cli.md](https://github.com/levantlabs/silk/blob/main/docs/cli.md) — every `python -m` tool (doctor, PDK validator,
205
+ schema exports, waveform explorer) and the `$SILK_NGSPICE_BIN` /
206
+ `$SILK_XYCE_BIN` simulator overrides
207
+ - [docs/database.md](https://github.com/levantlabs/silk/blob/main/docs/database.md) — design-history tracking,
208
+ characterization profiles and PVT selection, close/reopen queries and
209
+ restore, identity, promotion, migration, and JSON scope
210
+ - [docs/known_issues.md](https://github.com/levantlabs/silk/blob/main/docs/known_issues.md) — current limitations, honestly
211
+ - [docs/probes.md](https://github.com/levantlabs/silk/blob/main/docs/probes.md) — declare signals before simulation,
212
+ bind metrics without lambdas, then read or plot results across analyses and corners
213
+ - [CONTRIBUTING.md](https://github.com/levantlabs/silk/blob/main/CONTRIBUTING.md) — dev install (venv, editable, tests) and
214
+ conventions
215
+
216
+ Working examples live in `silk/examples/` and ship in the package — run any of
217
+ them as `python -m silk.examples.<name>`, no checkout needed:
218
+
219
+ | File | What it shows |
220
+ |---|---|
221
+ | `silk/examples/diff_pair_construction_example.py` | Construction-only factory and structure inspection |
222
+ | `silk/examples/factory_api_example.py` | Full factory API: devices, passives, SPICE inspection |
223
+ | `silk/examples/parameter_sweep_example.py` | Design-space sweep with `VariableSpace`/`Variable` |
224
+ | `silk/examples/ldo_design.py` | Parameterized LDO with `Module` + database tracking |
225
+ | `silk/examples/source_examples.py` | All source types: Pulse, Sine, PWL, SFFM, AM, controlled |
226
+ | `silk/examples/pwl_example.py` | PWL waveform: incremental, chaining, tuples, flat list, file |
227
+ | `silk/examples/hierarchical_example.py` | Multi-level subcircuits: inverter → buffer → testbench |
228
+
229
+ ## Core concepts
230
+
231
+ ### `Module` — the circuit object
232
+
233
+ In silk, a circuit is code. A `Module` is a live Python object holding a block's devices, nets, ports, sources and analyses. Every step of the flow reads that same object: netlisting, simulation, measurement, reports, the design database and layout estimation.
234
+
235
+ Modules are built to be reused. The usual way to write one is a factory function whose design knobs (widths, lengths, bias currents, loads) are keyword arguments, so one function produces every sizing of the block. Each block carries:
236
+ - its **ports**, with direction and role (supply, ground, analog input, output);
237
+ - its **testbenches** (`mod.create_test(...)`), each with its own sources, probes, metrics and specs, so the block knows how to test itself (`mod.run_all_tests()`);
238
+ - optionally a **behavioral model** (`set_behavioral_model`), so the block runs in the fast Python engine before its transistors exist, or stands in for them inside a larger system;
239
+ - its **specs**, which compare designed intent with measured results.
240
+
241
+ Blocks compose with `add_module`, so a system is built from blocks that each bring their own tests and models. And because it is all Python, a design can be diffed, reviewed and versioned like any other code, and read and written by an AI agent as easily as by a person.
242
+
243
+ ```python
244
+ from silk import Module
245
+ ckt = Module('PDK_skywater130', 'out_dir', 'my_circuit.cir', pdk_details=pdk)
246
+ ckt.add(device1, device2) # add pre-constructed device objects
247
+ ckt.add_source(vsource) # add a voltage or current source
248
+ ckt.add(capacitor) # ideal R, C, L are added with add() too
249
+ ckt.add_sim_type(Transient(...)) # set the simulation type
250
+ ckt.simulate(corner='tt') # generate netlist + run ngspice + load results
251
+ # optional: timeout=300 (seconds)
252
+ ckt.plot('vout', 'vin') # quick multi-panel plot
253
+ sig = ckt.load_signal('v(out)') # retrieve a waveform for custom analysis
254
+ ```
255
+
256
+ ### Factory API — device instantiation
257
+
258
+ Devices are instantiated directly from the PDK object. Pins and parameters are
259
+ keyword arguments — IDE autocomplete works on them.
260
+
261
+ ```python
262
+ mn = pdk.nmos1p8('mn', d='out', g='in', s='gnd', b='gnd', w=1.0, l=0.35, m=4)
263
+ mp = pdk.pmos1p8('mp', d='out', g='in', s='vdd', b='vdd', w=2.0, l=0.35)
264
+
265
+ # Parameters can be updated by direct attribute assignment after construction:
266
+ mn.w = 2.0
267
+ mn.d = 'new_out'
268
+ print(mn.to_spice()) # inspect the SPICE line
269
+ ```
270
+
271
+ ### PDK loading
272
+
273
+ ```python
274
+ # Option 1: load_pdk (uses the PDK_ROOT setting: env var, settings file, or ~/pdk)
275
+ from silk import load_pdk
276
+ pdk = load_pdk('sky130')
277
+
278
+ # Option 2: override the model-library path
279
+ pdk = load_pdk('sky130', library_location='/path/to/sky130.lib.spice')
280
+ ```
281
+
282
+ ### Simulation types
283
+
284
+ ```python
285
+ from silk.simulation import Transient, AC, DC, Noise, Corner
286
+
287
+ ckt.add_sim_type(Transient(step=1e-9, stop=100e-9))
288
+ ckt.add_sim_type(AC('dec', 100, 1e3, 1e9))
289
+ ckt.add_sim_type(DC(source='vin', start=0, stop=1.8, step=0.01))
290
+
291
+ # Corner is a str-subclass enum — plain strings also work
292
+ ckt.simulate(corner=Corner.TT)
293
+ ckt.simulate(corner='ff') # equivalent
294
+ ```
295
+
296
+ ### Sources
297
+
298
+ ```python
299
+ from silk import sources
300
+
301
+ vs = sources.VoltageSource('vdd', positive='vdd', negative='gnd', dc=1.8)
302
+ cs = sources.CurrentSource('ibias', positive='vdd', negative='vnbias', dc=100e-6)
303
+
304
+ # Waveforms
305
+ vs_pulse = sources.VoltageSource('vin', positive='in', negative='gnd',
306
+ pulse=sources.Pulse(v1=0, v2=1.8, td=0,
307
+ tr=100e-12, tf=100e-12,
308
+ pw=5e-9, per=10e-9))
309
+ vs_sine = sources.VoltageSource('vin', positive='in', negative='gnd',
310
+ sine=sources.Sine(voffset=0, vampl=1, freq=1e6))
311
+
312
+ # Piecewise-linear (PWL) waveform
313
+ pwl = sources.PWL().add(0, 0).add(1e-9, 0).add(2e-9, 1.8).add(10e-9, 1.8)
314
+ vs_pwl = sources.VoltageSource('vin', positive='in', negative='gnd', pwl=pwl)
315
+ # Also accepts: pwl=[(0, 0), (1e-9, 1.8)] or pwl=[0, 0, 1e-9, 1.8]
316
+ ```
317
+
318
+ ### Ideal elements (ElementLibrary)
319
+
320
+ ```python
321
+ from silk.elements import elements
322
+
323
+ r = elements.resistor('r1', p='out', n='gnd', value=10e3)
324
+ c = elements.capacitor('c1', p='out', n='gnd', value=100e-12)
325
+ l = elements.inductor('l1', p='a', n='b', value=1e-9)
326
+ ckt.add(r, c, l)
327
+ ```
328
+
329
+ Construct voltage and current sources with `silk.sources`.
330
+
331
+ ### Design-space exploration
332
+
333
+ ```python
334
+ from silk import Module, load_pdk
335
+ from silk.optimize import VariableSpace
336
+
337
+ pdk = load_pdk('sky130')
338
+ ckt = Module('PDK_skywater130', 'out', 'sweep.cir', pdk_details=pdk)
339
+
340
+ # Create variables with bounds
341
+ w_n = pdk.nmos1p8.w.variable(name='w_n', value=1.0, bounds=(0.42, 20.0))
342
+ w_p = pdk.pmos1p8.w.variable(name='w_p', value=2.0, bounds=(0.42, 20.0))
343
+ l = pdk.nmos1p8.l.variable(name='l', value=0.15, bounds=(0.15, 1.0))
344
+
345
+ # Pass Variable objects directly as device parameters
346
+ with ckt:
347
+ mn = pdk.nmos1p8('mn', d='out', g='in', s='gnd', b='gnd', w=w_n, l=l)
348
+ mp = pdk.pmos1p8('mp', d='out', g='in', s='vdd', b='vdd', w=w_p, l=l)
349
+
350
+ # Build a VariableSpace and sample it
351
+ space = VariableSpace([w_n, w_p, l])
352
+ points = space.sample(20, method='lhs') # Latin hypercube sampling
353
+ # also: method='random', 'halton', 'grid'
354
+
355
+ for pt in points:
356
+ space.apply(pt) # updates variable .value fields
357
+ ckt.generate_netlist(corner='tt') # picks up new values automatically
358
+ ```
359
+
360
+ ### Schema export APIs
361
+
362
+ ```python
363
+ from silk import export_schema, module_schema
364
+ import json
365
+
366
+ # Export all PDK devices as a machine-readable dict
367
+ schema = export_schema(pdk)
368
+ print(json.dumps(schema, indent=2))
369
+
370
+ # Export a single Module's interface
371
+ mod_schema = module_schema(my_module)
372
+ ```
373
+
374
+ ### Database / version tracking
375
+
376
+ Pass `db_path` to `Module` to enable database tracking. Python remains the
377
+ authoritative circuit/spec definition; the SQLite file preserves sealed
378
+ snapshot identity, declarations, metric/spec evidence, current sets (multiple
379
+ selected sets per corner, distinguished by characterization profile and
380
+ PVT — see [docs/database.md](https://github.com/levantlabs/silk/blob/main/docs/database.md)), lineage, and provenance.
381
+ Rebuild the same Python definition to restore live state. Unsupported or
382
+ malformed files are rejected without modification; see the database guide's
383
+ [compatibility matrix and migration guidance](https://github.com/levantlabs/silk/blob/main/docs/database.md#file-compatibility).
384
+
385
+ ```python
386
+ ckt = Module('PDK_skywater130', 'out', 'ldo.cir', pdk_details=pdk,
387
+ module_name='ldo_nmos', db_path='designs.db')
388
+
389
+ ckt.add(mn1, mp1)
390
+ ckt.declare_spec('DC gain', 'gain_dB', '>=', 40.0,
391
+ units='dB', key='gain')
392
+ version_id = ckt.create_circuit_version('Initial attempt')
393
+ ckt.store_results(
394
+ {'gain_dB': (42.5, 'dB')}, source='spice', sim_type='ac',
395
+ corner='tt', temperature=27.0, voltage=1.8,
396
+ tool_name='ngspice-44', conditions={'load_pf': 2.0},
397
+ )
398
+ ckt.close()
399
+
400
+ rebuilt = build_ldo(pdk, db_path='designs.db')
401
+ assert rebuilt.create_circuit_version() == version_id
402
+ rows = rebuilt.query_results(parameter='gain_dB', corner='tt')
403
+ rebuilt.promote('stable') # evidence remains at its origin UUID
404
+ rebuilt.close()
405
+ ```
406
+
407
+ JSON export is explicitly a lossy interoperability projection, not a database
408
+ backup or circuit archive. See the canonical [database guide](https://github.com/levantlabs/silk/blob/main/docs/database.md)
409
+ and the simulator-free `python -m silk.examples.circuit_tracking_example`.
410
+
411
+ ### Code generation
412
+
413
+ Generate runnable silk Python from a JSON-able spec dict (a circuit description):
414
+
415
+ ```python
416
+ from silk.codegen import Generator
417
+
418
+ gen = Generator() # no constructor args
419
+ code = gen.generate({
420
+ 'circuit_name': 'diff_pair',
421
+ 'pdk': 'sky130',
422
+ 'voltage_domains': {'AVDD': {'nominal': 1.8, 'tolerance': 0.1}},
423
+ 'ports': {
424
+ 'vin_p': {'dir': 'input', 'role': 'analog', 'domain': 'AVDD'},
425
+ 'vout': {'dir': 'output', 'role': 'analog', 'domain': 'AVDD'},
426
+ },
427
+ 'devices': [...],
428
+ })
429
+ print(code)
430
+ ```
431
+
432
+ Output mode depends on the payload: absent or `null` `ports` emits a standalone simulation script; `ports: {}` emits a zero-pin `Module` subcircuit; non-empty `ports` emits a reusable `Module` subcircuit with those pins and `define_module_ports`. See the [codegen contract](https://github.com/levantlabs/silk/blob/main/docs/codegen-contract.md). Optional `voltage_domains` and `bus_nets` blocks are emitted only when the spec uses them.
433
+
434
+ Full JSON shape and field reference: **[docs/codegen-contract.md](https://github.com/levantlabs/silk/blob/main/docs/codegen-contract.md)**.
435
+
436
+ ## Full API reference
437
+
438
+ See [docs/api-reference.md](https://github.com/levantlabs/silk/blob/main/docs/api-reference.md).
439
+
440
+ ## Package layout
441
+
442
+ ```
443
+ silk/
444
+ __init__.py top-level re-exports
445
+ exceptions.py CircuitError hierarchy
446
+
447
+ circuit/ Module, ModuleTestbench, schema export, port roles, composition graph
448
+ pdk/ BasePDK, load_pdk, PDK manifests + validator
449
+ elements/ ElementLibrary, passives, AnalogElement
450
+ sources/ VoltageSource, CurrentSource, waveforms
451
+ signals/ Signal, NgspiceSignal, rawfile reader, waveform metrics
452
+ simulation/ Transient, AC, DC, Noise, Corner, simulator backends
453
+ simulators/ per-simulator YAML configs (ngspice, xyce)
454
+ specs/ Spec objects, reconciliation, calibration binding
455
+ metrics/ measurement library (ADC, timing, jitter, distortion, noise, …)
456
+ lint/ design-rule framework (stress, port/domain checks, reports)
457
+ faults/ fault injection: FaultSet, FaultCampaign, reports
458
+ layout/ layout estimation, parasitics injection, EM budget
459
+ optimize/ VariableSpace, Variable, Optimizer
460
+ constraints/ constraint vocabulary
461
+ db/ Database, CircuitTracker, CircuitImporter, CircuitExporter, DesignStage
462
+ codegen/ Generator
463
+ utils/ internal helpers
464
+ examples/ runnable example scripts (see docs/agent-guide.md §7)
465
+ ```
466
+
467
+ ## Development
468
+
469
+ The test suite lives in the repository, not in the source package. Run these
470
+ commands from the root of a repository clone:
471
+
472
+ ```bash
473
+ pip install -e ".[dev]"
474
+ pytest tests/ -q
475
+ ```