monata 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (227) hide show
  1. monata-0.1.0/.gitignore +27 -0
  2. monata-0.1.0/LICENSE +21 -0
  3. monata-0.1.0/PKG-INFO +142 -0
  4. monata-0.1.0/README.md +110 -0
  5. monata-0.1.0/pyproject.toml +88 -0
  6. monata-0.1.0/src/monata/__init__.py +35 -0
  7. monata-0.1.0/src/monata/_config.py +105 -0
  8. monata-0.1.0/src/monata/_home.py +47 -0
  9. monata-0.1.0/src/monata/_json.py +57 -0
  10. monata-0.1.0/src/monata/_paths.py +73 -0
  11. monata-0.1.0/src/monata/_types.py +8 -0
  12. monata-0.1.0/src/monata/category.py +139 -0
  13. monata-0.1.0/src/monata/cell.py +179 -0
  14. monata-0.1.0/src/monata/circuits/__init__.py +29 -0
  15. monata-0.1.0/src/monata/circuits/cmos.py +102 -0
  16. monata-0.1.0/src/monata/circuits/source.py +70 -0
  17. monata-0.1.0/src/monata/corner.py +355 -0
  18. monata-0.1.0/src/monata/eda/__init__.py +35 -0
  19. monata-0.1.0/src/monata/eda/kicad.py +526 -0
  20. monata-0.1.0/src/monata/errors.py +33 -0
  21. monata-0.1.0/src/monata/examples.py +79 -0
  22. monata-0.1.0/src/monata/generation/__init__.py +6 -0
  23. monata-0.1.0/src/monata/generation/netlist.py +72 -0
  24. monata-0.1.0/src/monata/generation/symbol.py +26 -0
  25. monata-0.1.0/src/monata/library.py +323 -0
  26. monata-0.1.0/src/monata/measure/__init__.py +55 -0
  27. monata-0.1.0/src/monata/measure/calculus.py +330 -0
  28. monata-0.1.0/src/monata/measure/freq_domain.py +250 -0
  29. monata-0.1.0/src/monata/measure/result.py +107 -0
  30. monata-0.1.0/src/monata/measure/spec.py +385 -0
  31. monata-0.1.0/src/monata/measure/statistics.py +91 -0
  32. monata-0.1.0/src/monata/measure/summary.py +217 -0
  33. monata-0.1.0/src/monata/measure/time_domain.py +362 -0
  34. monata-0.1.0/src/monata/models/__init__.py +32 -0
  35. monata-0.1.0/src/monata/models/artifacts.py +104 -0
  36. monata-0.1.0/src/monata/models/cache.py +355 -0
  37. monata-0.1.0/src/monata/models/compiler.py +239 -0
  38. monata-0.1.0/src/monata/models/diagnostics.py +46 -0
  39. monata-0.1.0/src/monata/models/flow.py +243 -0
  40. monata-0.1.0/src/monata/models/manifest.py +438 -0
  41. monata-0.1.0/src/monata/models/registry.py +369 -0
  42. monata-0.1.0/src/monata/models/resolver.py +970 -0
  43. monata-0.1.0/src/monata/netlist/__init__.py +45 -0
  44. monata-0.1.0/src/monata/netlist/device_schema.py +394 -0
  45. monata-0.1.0/src/monata/netlist/ir.py +1026 -0
  46. monata-0.1.0/src/monata/netlist/mutation.py +173 -0
  47. monata-0.1.0/src/monata/netlist/ngspice.py +221 -0
  48. monata-0.1.0/src/monata/netlist/scope_api.py +1601 -0
  49. monata-0.1.0/src/monata/netlist/scope_state.py +137 -0
  50. monata-0.1.0/src/monata/netlist/topology.py +369 -0
  51. monata-0.1.0/src/monata/optim/__init__.py +13 -0
  52. monata-0.1.0/src/monata/optim/base.py +155 -0
  53. monata-0.1.0/src/monata/optim/bayesian.py +187 -0
  54. monata-0.1.0/src/monata/optim/circuit.py +166 -0
  55. monata-0.1.0/src/monata/optim/nsga2.py +272 -0
  56. monata-0.1.0/src/monata/parser/__init__.py +92 -0
  57. monata-0.1.0/src/monata/parser/analysis_import.py +1009 -0
  58. monata-0.1.0/src/monata/parser/commands.py +70 -0
  59. monata-0.1.0/src/monata/parser/deck.py +348 -0
  60. monata-0.1.0/src/monata/parser/errors.py +28 -0
  61. monata-0.1.0/src/monata/parser/expression.py +457 -0
  62. monata-0.1.0/src/monata/parser/import_plan.py +687 -0
  63. monata-0.1.0/src/monata/parser/importer.py +636 -0
  64. monata-0.1.0/src/monata/parser/source_subcircuit.py +53 -0
  65. monata-0.1.0/src/monata/physics.py +309 -0
  66. monata-0.1.0/src/monata/projection.py +238 -0
  67. monata-0.1.0/src/monata/py.typed +0 -0
  68. monata-0.1.0/src/monata/registry.py +59 -0
  69. monata-0.1.0/src/monata/sim/__init__.py +5 -0
  70. monata-0.1.0/src/monata/sim/_backend.py +28 -0
  71. monata-0.1.0/src/monata/sim/_digital_bits.py +42 -0
  72. monata-0.1.0/src/monata/sim/_frozen.py +124 -0
  73. monata-0.1.0/src/monata/sim/_vector_identity.py +93 -0
  74. monata-0.1.0/src/monata/sim/analysis_spec.py +310 -0
  75. monata-0.1.0/src/monata/sim/artifacts.py +150 -0
  76. monata-0.1.0/src/monata/sim/backends/__init__.py +41 -0
  77. monata-0.1.0/src/monata/sim/backends/base.py +335 -0
  78. monata-0.1.0/src/monata/sim/backends/ngspice.py +415 -0
  79. monata-0.1.0/src/monata/sim/backends/ngspice_common.py +550 -0
  80. monata-0.1.0/src/monata/sim/backends/ngspice_output.py +321 -0
  81. monata-0.1.0/src/monata/sim/backends/ngspice_parse.py +377 -0
  82. monata-0.1.0/src/monata/sim/backends/ngspice_plan.py +621 -0
  83. monata-0.1.0/src/monata/sim/backends/ngspice_shared.py +344 -0
  84. monata-0.1.0/src/monata/sim/backends/ngspice_shared_commands.py +65 -0
  85. monata-0.1.0/src/monata/sim/backends/ngspice_shared_ffi.py +130 -0
  86. monata-0.1.0/src/monata/sim/backends/ngspice_shared_session.py +621 -0
  87. monata-0.1.0/src/monata/sim/backends/ngspice_stdout.py +237 -0
  88. monata-0.1.0/src/monata/sim/cache.py +367 -0
  89. monata-0.1.0/src/monata/sim/capabilities.py +191 -0
  90. monata-0.1.0/src/monata/sim/core.py +77 -0
  91. monata-0.1.0/src/monata/sim/corner.py +261 -0
  92. monata-0.1.0/src/monata/sim/digital_circuits.py +199 -0
  93. monata-0.1.0/src/monata/sim/digital_claims.py +310 -0
  94. monata-0.1.0/src/monata/sim/digital_extract.py +402 -0
  95. monata-0.1.0/src/monata/sim/digital_plan.py +505 -0
  96. monata-0.1.0/src/monata/sim/digital_projection.py +111 -0
  97. monata-0.1.0/src/monata/sim/digital_results.py +186 -0
  98. monata-0.1.0/src/monata/sim/digital_spec.py +161 -0
  99. monata-0.1.0/src/monata/sim/digital_table.py +512 -0
  100. monata-0.1.0/src/monata/sim/digital_table_config.py +234 -0
  101. monata-0.1.0/src/monata/sim/digital_tasks.py +225 -0
  102. monata-0.1.0/src/monata/sim/digital_timing.py +109 -0
  103. monata-0.1.0/src/monata/sim/executor.py +100 -0
  104. monata-0.1.0/src/monata/sim/export.py +65 -0
  105. monata-0.1.0/src/monata/sim/export_hdf5.py +339 -0
  106. monata-0.1.0/src/monata/sim/export_payload.py +296 -0
  107. monata-0.1.0/src/monata/sim/montecarlo.py +251 -0
  108. monata-0.1.0/src/monata/sim/plot.py +156 -0
  109. monata-0.1.0/src/monata/sim/rawfile.py +403 -0
  110. monata-0.1.0/src/monata/sim/result_ops.py +140 -0
  111. monata-0.1.0/src/monata/sim/results.py +782 -0
  112. monata-0.1.0/src/monata/sim/session.py +382 -0
  113. monata-0.1.0/src/monata/sim/sweep.py +272 -0
  114. monata-0.1.0/src/monata/sim/task.py +152 -0
  115. monata-0.1.0/src/monata/sim/vector_names.py +203 -0
  116. monata-0.1.0/src/monata/sim/waveform.py +785 -0
  117. monata-0.1.0/src/monata/spice_library.py +775 -0
  118. monata-0.1.0/src/monata/techlib/__init__.py +5 -0
  119. monata-0.1.0/src/monata/techlib/parse.py +187 -0
  120. monata-0.1.0/src/monata/techlib/projection.py +168 -0
  121. monata-0.1.0/src/monata/techlib/registry.py +501 -0
  122. monata-0.1.0/src/monata/techlib/schema.py +130 -0
  123. monata-0.1.0/src/monata/units.py +1251 -0
  124. monata-0.1.0/src/monata/views/__init__.py +5 -0
  125. monata-0.1.0/src/monata/views/base.py +155 -0
  126. monata-0.1.0/src/monata/views/digital_truth_table.py +280 -0
  127. monata-0.1.0/src/monata/views/netlist.py +15 -0
  128. monata-0.1.0/src/monata/views/registry.py +332 -0
  129. monata-0.1.0/src/monata/views/schematic.py +10 -0
  130. monata-0.1.0/src/monata/views/simulation.py +312 -0
  131. monata-0.1.0/src/monata/views/symbol.py +64 -0
  132. monata-0.1.0/src/monata/views/testbench.py +16 -0
  133. monata-0.1.0/src/monata/workspace/__init__.py +6 -0
  134. monata-0.1.0/src/monata/workspace/experiment.py +93 -0
  135. monata-0.1.0/src/monata/workspace/project.py +230 -0
  136. monata-0.1.0/src/monata/workspace/result_store.py +177 -0
  137. monata-0.1.0/tests/conftest.py +26 -0
  138. monata-0.1.0/tests/support/README.md +26 -0
  139. monata-0.1.0/tests/support/__init__.py +1 -0
  140. monata-0.1.0/tests/support/assertions.py +15 -0
  141. monata-0.1.0/tests/support/backends.py +84 -0
  142. monata-0.1.0/tests/support/digital_cases.py +460 -0
  143. monata-0.1.0/tests/support/executors.py +60 -0
  144. monata-0.1.0/tests/support/model_cases.py +99 -0
  145. monata-0.1.0/tests/support/native_backend_cases.py +49 -0
  146. monata-0.1.0/tests/support/netlist_cases.py +14 -0
  147. monata-0.1.0/tests/support/ngspice.py +43 -0
  148. monata-0.1.0/tests/support/results.py +61 -0
  149. monata-0.1.0/tests/support/sim_results_cases.py +0 -0
  150. monata-0.1.0/tests/support/workspaces.py +20 -0
  151. monata-0.1.0/tests/test_cell.py +366 -0
  152. monata-0.1.0/tests/test_cir2py.py +167 -0
  153. monata-0.1.0/tests/test_circuit_construction.py +211 -0
  154. monata-0.1.0/tests/test_errors.py +43 -0
  155. monata-0.1.0/tests/test_examples.py +43 -0
  156. monata-0.1.0/tests/test_foundation_closed_loop.py +72 -0
  157. monata-0.1.0/tests/test_generation.py +277 -0
  158. monata-0.1.0/tests/test_integration.py +78 -0
  159. monata-0.1.0/tests/test_kicad_import.py +252 -0
  160. monata-0.1.0/tests/test_library.py +331 -0
  161. monata-0.1.0/tests/test_measure_calculus.py +195 -0
  162. monata-0.1.0/tests/test_measure_freq_domain.py +279 -0
  163. monata-0.1.0/tests/test_measure_result.py +144 -0
  164. monata-0.1.0/tests/test_measure_spec.py +370 -0
  165. monata-0.1.0/tests/test_measure_statistics.py +145 -0
  166. monata-0.1.0/tests/test_measure_summary.py +278 -0
  167. monata-0.1.0/tests/test_measure_time_domain.py +337 -0
  168. monata-0.1.0/tests/test_models_cache.py +368 -0
  169. monata-0.1.0/tests/test_models_compiler.py +241 -0
  170. monata-0.1.0/tests/test_models_external_artifacts.py +257 -0
  171. monata-0.1.0/tests/test_models_resolver.py +322 -0
  172. monata-0.1.0/tests/test_models_schema.py +259 -0
  173. monata-0.1.0/tests/test_netlist_construction.py +157 -0
  174. monata-0.1.0/tests/test_netlist_mutation.py +106 -0
  175. monata-0.1.0/tests/test_netlist_mutation_surface.py +355 -0
  176. monata-0.1.0/tests/test_netlist_rendering.py +897 -0
  177. monata-0.1.0/tests/test_netlist_roundtrip_parser.py +426 -0
  178. monata-0.1.0/tests/test_netlist_schema_topology.py +307 -0
  179. monata-0.1.0/tests/test_ngspice_rawfile.py +254 -0
  180. monata-0.1.0/tests/test_ngspice_shared.py +544 -0
  181. monata-0.1.0/tests/test_optim_base.py +98 -0
  182. monata-0.1.0/tests/test_optim_bayesian.py +118 -0
  183. monata-0.1.0/tests/test_optim_circuit.py +286 -0
  184. monata-0.1.0/tests/test_optim_nsga2.py +91 -0
  185. monata-0.1.0/tests/test_p4_workflow.py +51 -0
  186. monata-0.1.0/tests/test_paths.py +51 -0
  187. monata-0.1.0/tests/test_physics.py +142 -0
  188. monata-0.1.0/tests/test_public_api.py +756 -0
  189. monata-0.1.0/tests/test_registry.py +133 -0
  190. monata-0.1.0/tests/test_sim_analysis_spec.py +242 -0
  191. monata-0.1.0/tests/test_sim_artifacts.py +155 -0
  192. monata-0.1.0/tests/test_sim_backend_native_artifact_parsing.py +268 -0
  193. monata-0.1.0/tests/test_sim_backend_native_failure_handling.py +304 -0
  194. monata-0.1.0/tests/test_sim_backend_native_planning.py +344 -0
  195. monata-0.1.0/tests/test_sim_backend_native_subprocess.py +552 -0
  196. monata-0.1.0/tests/test_sim_backend_registry.py +312 -0
  197. monata-0.1.0/tests/test_sim_cache.py +134 -0
  198. monata-0.1.0/tests/test_sim_corner.py +539 -0
  199. monata-0.1.0/tests/test_sim_digital_result_extraction.py +205 -0
  200. monata-0.1.0/tests/test_sim_digital_task_construction.py +469 -0
  201. monata-0.1.0/tests/test_sim_digital_timing_claims.py +360 -0
  202. monata-0.1.0/tests/test_sim_digital_truth_table_spec.py +210 -0
  203. monata-0.1.0/tests/test_sim_executor.py +138 -0
  204. monata-0.1.0/tests/test_sim_export_hdf5.py +339 -0
  205. monata-0.1.0/tests/test_sim_montecarlo.py +355 -0
  206. monata-0.1.0/tests/test_sim_rawfile.py +458 -0
  207. monata-0.1.0/tests/test_sim_results_analysis.py +882 -0
  208. monata-0.1.0/tests/test_sim_results_core.py +689 -0
  209. monata-0.1.0/tests/test_sim_results_export_plot.py +563 -0
  210. monata-0.1.0/tests/test_sim_results_measurement.py +73 -0
  211. monata-0.1.0/tests/test_sim_session.py +425 -0
  212. monata-0.1.0/tests/test_sim_sweep.py +329 -0
  213. monata-0.1.0/tests/test_sim_task.py +282 -0
  214. monata-0.1.0/tests/test_sinomos_project_examples.py +181 -0
  215. monata-0.1.0/tests/test_spice_analysis_import.py +609 -0
  216. monata-0.1.0/tests/test_spice_expression.py +77 -0
  217. monata-0.1.0/tests/test_spice_import.py +694 -0
  218. monata-0.1.0/tests/test_spice_import_plan.py +278 -0
  219. monata-0.1.0/tests/test_spice_library.py +471 -0
  220. monata-0.1.0/tests/test_spice_parser.py +186 -0
  221. monata-0.1.0/tests/test_spice_roundtrip.py +92 -0
  222. monata-0.1.0/tests/test_suite_structure.py +144 -0
  223. monata-0.1.0/tests/test_techlib.py +879 -0
  224. monata-0.1.0/tests/test_units.py +829 -0
  225. monata-0.1.0/tests/test_views.py +901 -0
  226. monata-0.1.0/tests/test_workspace_experiment.py +352 -0
  227. monata-0.1.0/tests/test_workspace_project.py +486 -0
@@ -0,0 +1,27 @@
1
+ __pycache__/
2
+ *.py[cod]
3
+ *$py.class
4
+ *.egg-info/
5
+ dist/
6
+ build/
7
+ .eggs/
8
+ *.egg
9
+ .pytest_cache/
10
+ .mypy_cache/
11
+ .ruff_cache/
12
+ .pyright/
13
+ .coverage
14
+ .coverage.*
15
+ htmlcov/
16
+ .tox/
17
+ .nox/
18
+ .hypothesis/
19
+ pip-wheel-metadata/
20
+ .venv/
21
+ .env
22
+ .env.*
23
+ !.env.example
24
+
25
+ # Documentation build
26
+ docs/_build/
27
+ docs/api/monata/
monata-0.1.0/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Zhangmai Li
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.
monata-0.1.0/PKG-INFO ADDED
@@ -0,0 +1,142 @@
1
+ Metadata-Version: 2.4
2
+ Name: monata
3
+ Version: 0.1.0
4
+ Summary: A lightweight EDA framework for circuit design and SPICE simulation workflows
5
+ Project-URL: Homepage, https://github.com/lizhangmai/monata
6
+ Project-URL: Repository, https://github.com/lizhangmai/monata
7
+ Project-URL: Issues, https://github.com/lizhangmai/monata/issues
8
+ Author: lizhangmai
9
+ License-Expression: MIT
10
+ License-File: LICENSE
11
+ Keywords: analog,circuit,cmos,digital,eda,simulation,spice
12
+ Classifier: Development Status :: 5 - Production/Stable
13
+ Classifier: Intended Audience :: Science/Research
14
+ Classifier: License :: OSI Approved :: MIT License
15
+ Classifier: Programming Language :: Python :: 3
16
+ Classifier: Programming Language :: Python :: 3.11
17
+ Classifier: Programming Language :: Python :: 3.12
18
+ Classifier: Topic :: Scientific/Engineering :: Electronic Design Automation (EDA)
19
+ Requires-Python: >=3.11
20
+ Requires-Dist: cffi
21
+ Requires-Dist: h5py
22
+ Requires-Dist: matplotlib
23
+ Requires-Dist: numpy
24
+ Provides-Extra: dev
25
+ Requires-Dist: build; extra == 'dev'
26
+ Requires-Dist: pyright; extra == 'dev'
27
+ Requires-Dist: pytest; extra == 'dev'
28
+ Requires-Dist: pytest-cov; extra == 'dev'
29
+ Requires-Dist: ruff; extra == 'dev'
30
+ Requires-Dist: twine; extra == 'dev'
31
+ Description-Content-Type: text/markdown
32
+
33
+ # Monata
34
+
35
+ Monata is a Python toolkit for circuit workflow automation. It provides a
36
+ typed front end for organizing circuit projects, authoring SPICE-oriented
37
+ netlists, running simulator tasks, and working with measurement and result
38
+ data.
39
+
40
+ Monata is designed as a lightweight Python package, not as a simulator
41
+ distribution. It integrates with simulator and model-toolchain programs that
42
+ users install in their own environments.
43
+
44
+ ## Features
45
+
46
+ - Library, cell, and view organization for circuit projects.
47
+ - Native circuit/netlist records with ngspice-compatible rendering.
48
+ - Backend-neutral simulation tasks, result objects, sweeps, corners, Monte
49
+ Carlo flows, and measurements.
50
+ - Built-in ngspice subprocess backend, plus a shared-library ngspice runner
51
+ for environments that provide `libngspice`.
52
+ - Plotting and HDF5 result import/export available from the default install.
53
+ - Optional technology-library packages, such as `monata-techlib`, for reusable
54
+ model metadata and redistributed model assets.
55
+
56
+ ## Installation
57
+
58
+ ```bash
59
+ python -m pip install monata
60
+ ```
61
+
62
+ Monata supports Python 3.11 and 3.12.
63
+
64
+ ## Quick Start
65
+
66
+ Create a Monata library and build a small circuit:
67
+
68
+ ```python
69
+ from monata import LibraryRegistry
70
+ from monata.netlist import Circuit
71
+
72
+ registry = LibraryRegistry()
73
+ library = registry.create_library(path="work/analog", name="analog")
74
+ cell = library.create_cell("rc_filter", description="RC low-pass filter")
75
+
76
+ circuit = Circuit("rc low-pass")
77
+ circuit.voltage("in", "vin", "0", "1")
78
+ circuit.resistor("load", "vin", "vout", "1k")
79
+ circuit.capacitor("hold", "vout", "0", "1n")
80
+
81
+ print(cell.name)
82
+ print(circuit.to_spice())
83
+ ```
84
+
85
+ Run a simulation when a supported backend is installed:
86
+
87
+ ```python
88
+ from monata.sim.core import DCSpec, LocalExecutor, SimTask
89
+
90
+ task = SimTask(
91
+ circuit=circuit,
92
+ analysis_spec=DCSpec(source="Vin", start=0, stop=1, step=0.25),
93
+ output_names=["vout"],
94
+ )
95
+
96
+ result = LocalExecutor(max_workers=1).submit(task).result()
97
+ if result.failed:
98
+ raise RuntimeError(result.error_message)
99
+
100
+ print(result.waveforms["vout"])
101
+ ```
102
+
103
+ The default backend is `ngspice-subprocess`, which runs a local `ngspice`
104
+ executable from `PATH` or `CONDA_PREFIX/bin`.
105
+
106
+ ## External Tools
107
+
108
+ The public `monata` package does not ship simulator binaries, shared simulator
109
+ libraries, XSPICE code models, OpenVAF, Xyce, foundry PDKs, PTM model cards, or
110
+ compiled OSDI binaries.
111
+
112
+ Monata can use:
113
+
114
+ - a user-installed `ngspice` executable through `ngspice-subprocess`;
115
+ - a user-provided `libngspice` shared library through `ngspice-shared`;
116
+ - separately installed technology-library packages such as `monata-techlib`.
117
+
118
+ Users and downstream packagers remain responsible for installing external tools
119
+ and complying with their upstream licenses.
120
+
121
+ ## Documentation
122
+
123
+ Long-form documentation lives outside this source package:
124
+
125
+ - Documentation repository: https://github.com/lizhangmai/monata-docs
126
+ - Getting started: https://github.com/lizhangmai/monata-docs/tree/main/docs/getting-started
127
+ - User guide: https://github.com/lizhangmai/monata-docs/tree/main/docs/user-guide
128
+ - API boundaries: https://github.com/lizhangmai/monata-docs/blob/main/docs/reference/api-boundaries.md
129
+ - Simulator and tool setup: https://github.com/lizhangmai/monata-docs/blob/main/docs/toolchain/external-tools.md
130
+ - Maintainer notes: https://github.com/lizhangmai/monata-docs/tree/main/docs/maintainers
131
+
132
+ ## Security
133
+
134
+ Monata project views can be Python source files. Loading schematic and testbench
135
+ views executes that project code in the current Python process; view loading is
136
+ not sandboxed. Open, load, generate, and simulate only trusted libraries and
137
+ project workspaces.
138
+
139
+ ## License
140
+
141
+ Monata's Python framework is licensed under the MIT License. See
142
+ [`LICENSE`](LICENSE).
monata-0.1.0/README.md ADDED
@@ -0,0 +1,110 @@
1
+ # Monata
2
+
3
+ Monata is a Python toolkit for circuit workflow automation. It provides a
4
+ typed front end for organizing circuit projects, authoring SPICE-oriented
5
+ netlists, running simulator tasks, and working with measurement and result
6
+ data.
7
+
8
+ Monata is designed as a lightweight Python package, not as a simulator
9
+ distribution. It integrates with simulator and model-toolchain programs that
10
+ users install in their own environments.
11
+
12
+ ## Features
13
+
14
+ - Library, cell, and view organization for circuit projects.
15
+ - Native circuit/netlist records with ngspice-compatible rendering.
16
+ - Backend-neutral simulation tasks, result objects, sweeps, corners, Monte
17
+ Carlo flows, and measurements.
18
+ - Built-in ngspice subprocess backend, plus a shared-library ngspice runner
19
+ for environments that provide `libngspice`.
20
+ - Plotting and HDF5 result import/export available from the default install.
21
+ - Optional technology-library packages, such as `monata-techlib`, for reusable
22
+ model metadata and redistributed model assets.
23
+
24
+ ## Installation
25
+
26
+ ```bash
27
+ python -m pip install monata
28
+ ```
29
+
30
+ Monata supports Python 3.11 and 3.12.
31
+
32
+ ## Quick Start
33
+
34
+ Create a Monata library and build a small circuit:
35
+
36
+ ```python
37
+ from monata import LibraryRegistry
38
+ from monata.netlist import Circuit
39
+
40
+ registry = LibraryRegistry()
41
+ library = registry.create_library(path="work/analog", name="analog")
42
+ cell = library.create_cell("rc_filter", description="RC low-pass filter")
43
+
44
+ circuit = Circuit("rc low-pass")
45
+ circuit.voltage("in", "vin", "0", "1")
46
+ circuit.resistor("load", "vin", "vout", "1k")
47
+ circuit.capacitor("hold", "vout", "0", "1n")
48
+
49
+ print(cell.name)
50
+ print(circuit.to_spice())
51
+ ```
52
+
53
+ Run a simulation when a supported backend is installed:
54
+
55
+ ```python
56
+ from monata.sim.core import DCSpec, LocalExecutor, SimTask
57
+
58
+ task = SimTask(
59
+ circuit=circuit,
60
+ analysis_spec=DCSpec(source="Vin", start=0, stop=1, step=0.25),
61
+ output_names=["vout"],
62
+ )
63
+
64
+ result = LocalExecutor(max_workers=1).submit(task).result()
65
+ if result.failed:
66
+ raise RuntimeError(result.error_message)
67
+
68
+ print(result.waveforms["vout"])
69
+ ```
70
+
71
+ The default backend is `ngspice-subprocess`, which runs a local `ngspice`
72
+ executable from `PATH` or `CONDA_PREFIX/bin`.
73
+
74
+ ## External Tools
75
+
76
+ The public `monata` package does not ship simulator binaries, shared simulator
77
+ libraries, XSPICE code models, OpenVAF, Xyce, foundry PDKs, PTM model cards, or
78
+ compiled OSDI binaries.
79
+
80
+ Monata can use:
81
+
82
+ - a user-installed `ngspice` executable through `ngspice-subprocess`;
83
+ - a user-provided `libngspice` shared library through `ngspice-shared`;
84
+ - separately installed technology-library packages such as `monata-techlib`.
85
+
86
+ Users and downstream packagers remain responsible for installing external tools
87
+ and complying with their upstream licenses.
88
+
89
+ ## Documentation
90
+
91
+ Long-form documentation lives outside this source package:
92
+
93
+ - Documentation repository: https://github.com/lizhangmai/monata-docs
94
+ - Getting started: https://github.com/lizhangmai/monata-docs/tree/main/docs/getting-started
95
+ - User guide: https://github.com/lizhangmai/monata-docs/tree/main/docs/user-guide
96
+ - API boundaries: https://github.com/lizhangmai/monata-docs/blob/main/docs/reference/api-boundaries.md
97
+ - Simulator and tool setup: https://github.com/lizhangmai/monata-docs/blob/main/docs/toolchain/external-tools.md
98
+ - Maintainer notes: https://github.com/lizhangmai/monata-docs/tree/main/docs/maintainers
99
+
100
+ ## Security
101
+
102
+ Monata project views can be Python source files. Loading schematic and testbench
103
+ views executes that project code in the current Python process; view loading is
104
+ not sandboxed. Open, load, generate, and simulate only trusted libraries and
105
+ project workspaces.
106
+
107
+ ## License
108
+
109
+ Monata's Python framework is licensed under the MIT License. See
110
+ [`LICENSE`](LICENSE).
@@ -0,0 +1,88 @@
1
+ [build-system]
2
+ requires = ["hatchling"]
3
+ build-backend = "hatchling.build"
4
+
5
+ [project]
6
+ name = "monata"
7
+ version = "0.1.0"
8
+ description = "A lightweight EDA framework for circuit design and SPICE simulation workflows"
9
+ readme = "README.md"
10
+ license = "MIT"
11
+ license-files = ["LICENSE"]
12
+ requires-python = ">=3.11"
13
+ authors = [
14
+ { name = "lizhangmai" },
15
+ ]
16
+ keywords = ["eda", "spice", "circuit", "simulation", "analog", "digital", "cmos"]
17
+ classifiers = [
18
+ "Development Status :: 5 - Production/Stable",
19
+ "Intended Audience :: Science/Research",
20
+ "Topic :: Scientific/Engineering :: Electronic Design Automation (EDA)",
21
+ "Programming Language :: Python :: 3",
22
+ "Programming Language :: Python :: 3.11",
23
+ "Programming Language :: Python :: 3.12",
24
+ "License :: OSI Approved :: MIT License",
25
+ ]
26
+ dependencies = [
27
+ "numpy",
28
+ "matplotlib",
29
+ "h5py",
30
+ "cffi",
31
+ ]
32
+
33
+ [project.optional-dependencies]
34
+ dev = [
35
+ "pytest",
36
+ "pytest-cov",
37
+ "ruff",
38
+ "pyright",
39
+ "build",
40
+ "twine",
41
+ ]
42
+
43
+ [project.urls]
44
+ Homepage = "https://github.com/lizhangmai/monata"
45
+ Repository = "https://github.com/lizhangmai/monata"
46
+ Issues = "https://github.com/lizhangmai/monata/issues"
47
+
48
+ [tool.hatch.build.targets.wheel]
49
+ only-packages = true
50
+ packages = ["src/monata"]
51
+
52
+ [tool.hatch.build.targets.sdist]
53
+ include = [
54
+ "src/monata/",
55
+ "tests/",
56
+ "LICENSE",
57
+ "README.md",
58
+ "pyproject.toml",
59
+ ]
60
+ exclude = [
61
+ "data/",
62
+ "examples/",
63
+ ]
64
+
65
+ [tool.pytest.ini_options]
66
+ testpaths = ["tests"]
67
+ addopts = ["--strict-markers"]
68
+ markers = [
69
+ "fast: quick unit or contract tests suitable for the default development loop",
70
+ "integration: cross-module workflows, external fixtures, or end-to-end persistence paths",
71
+ "native: tests that execute or depend on native simulator backends or external simulator binaries",
72
+ "slow: broad or computationally heavier suites kept out of the fast development loop",
73
+ ]
74
+
75
+ [tool.ruff]
76
+ line-length = 120
77
+ src = ["src", "tests"]
78
+ target-version = "py311"
79
+
80
+ [tool.pyright]
81
+ exclude = [
82
+ "**/__pycache__",
83
+ "build",
84
+ "dist",
85
+ ]
86
+ extraPaths = ["src", "tests"]
87
+ include = ["src/monata", "tests"]
88
+ pythonVersion = "3.11"
@@ -0,0 +1,35 @@
1
+ """Monata — a lightweight EDA framework for circuit design."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from monata.cell import Cell
6
+ from monata.category import Category
7
+ from monata.corner import OperatingCorner
8
+ from monata.errors import (
9
+ CellNotFoundError,
10
+ LibraryNotFoundError,
11
+ ViewAlreadyModifiedError,
12
+ ViewNotFoundError,
13
+ ViewNotGeneratedError,
14
+ )
15
+ from monata.library import Library
16
+ from monata.registry import LibraryRegistry
17
+ from monata.units import Quantity, Unit, UnitArray
18
+ from monata.views import View
19
+
20
+ __all__ = [
21
+ "Cell",
22
+ "CellNotFoundError",
23
+ "Category",
24
+ "Library",
25
+ "LibraryNotFoundError",
26
+ "LibraryRegistry",
27
+ "OperatingCorner",
28
+ "Quantity",
29
+ "Unit",
30
+ "UnitArray",
31
+ "View",
32
+ "ViewAlreadyModifiedError",
33
+ "ViewNotFoundError",
34
+ "ViewNotGeneratedError",
35
+ ]
@@ -0,0 +1,105 @@
1
+ """Internal TOML persistence helpers for Monata workspace metadata."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from collections.abc import Iterable, Mapping
6
+ from pathlib import Path
7
+ from typing import Any
8
+
9
+ try:
10
+ import tomllib
11
+ except ImportError:
12
+ import tomli as tomllib # type: ignore[no-redef]
13
+
14
+ from monata._paths import toml_string
15
+
16
+
17
+ def read_toml(path: Path) -> dict[str, Any]:
18
+ with path.open("rb") as file:
19
+ return tomllib.load(file)
20
+
21
+
22
+ def reject_unknown_fields(
23
+ data: Mapping[str, Any], allowed: frozenset[str], subject: str
24
+ ) -> None:
25
+ unknown = sorted(key for key in data if key not in allowed)
26
+ if unknown:
27
+ raise ValueError(f"{subject} has unknown fields: {', '.join(unknown)}")
28
+
29
+
30
+ def cell_config(name: str, *, description: str = "") -> dict[str, Any]:
31
+ return {"cell": {"name": name, "description": description}, "views": {}}
32
+
33
+
34
+ def category_config(name: str, *, description: str = "") -> dict[str, Any]:
35
+ return {"category": {"name": name, "description": description}}
36
+
37
+
38
+ def write_category_config(path: Path, config: Mapping[str, Any]) -> None:
39
+ category = config["category"]
40
+ lines = [f'[category]\nname = "{toml_string(category["name"])}"\n']
41
+ if "description" in category:
42
+ lines.append(f'description = "{toml_string(category["description"])}"\n')
43
+ path.write_text("".join(lines))
44
+
45
+
46
+ def write_cell_config(path: Path, config: Mapping[str, Any]) -> None:
47
+ cell = config["cell"]
48
+ lines = [f'[cell]\nname = "{toml_string(cell["name"])}"\n']
49
+ if "description" in cell:
50
+ lines.append(f'description = "{toml_string(cell["description"])}"\n')
51
+ lines.append("\n[views]\n")
52
+ for view_type, view_config in config.get("views", {}).items():
53
+ parts = ", ".join(f"{key} = {toml_value(value)}" for key, value in view_config.items())
54
+ lines.append(f"{view_type} = {{ {parts} }}\n")
55
+ path.write_text("".join(lines))
56
+
57
+
58
+ def write_library_config(
59
+ path: Path,
60
+ *,
61
+ name: str,
62
+ tech_model_paths: Iterable[Any],
63
+ description: str = "",
64
+ techlib_attachments: Iterable[str] = (),
65
+ default_corner: str | None = None,
66
+ ) -> None:
67
+ model_paths = ", ".join(toml_value(model_path) for model_path in tech_model_paths)
68
+ lines = [
69
+ f'[library]\nname = "{toml_string(name)}"\n',
70
+ f'description = "{toml_string(description)}"\n\n',
71
+ f"[technology]\nmodel_paths = [{model_paths}]\n",
72
+ ]
73
+ attachments = list(techlib_attachments)
74
+ if attachments or default_corner is not None:
75
+ techlibs = ", ".join(toml_value(attachment) for attachment in attachments)
76
+ lines.extend(["\n[attachments]\n", f"techlibs = [{techlibs}]\n"])
77
+ if default_corner is not None:
78
+ lines.append(f'default_corner = "{toml_string(default_corner)}"\n')
79
+ path.write_text("".join(lines))
80
+
81
+
82
+ def write_project_config(
83
+ path: Path,
84
+ *,
85
+ name: str,
86
+ libraries: Iterable[Mapping[str, str]] = (),
87
+ ) -> None:
88
+ lines = [f'[project]\nname = "{toml_string(name)}"\n']
89
+ for entry in libraries:
90
+ lines.extend([
91
+ "\n[[libraries]]\n",
92
+ f'name = "{toml_string(entry["name"])}"\n',
93
+ f'path = "{toml_string(entry["path"])}"\n',
94
+ ])
95
+ path.write_text("".join(lines))
96
+
97
+
98
+ def toml_value(value: Any) -> str:
99
+ if isinstance(value, bool):
100
+ return "true" if value else "false"
101
+ if isinstance(value, (int, float)):
102
+ return repr(value)
103
+ if isinstance(value, (list, tuple)):
104
+ return "[" + ", ".join(toml_value(item) for item in value) + "]"
105
+ return f'"{toml_string(value)}"'
@@ -0,0 +1,47 @@
1
+ """Monata-managed mutable state locations."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import os
6
+ from pathlib import Path
7
+
8
+
9
+ def monata_home(explicit: str | Path | None = None) -> Path | None:
10
+ """Return the configured Monata home root, if one is configured."""
11
+
12
+ if explicit is not None:
13
+ return Path(explicit)
14
+ env = os.environ.get("MONATA_HOME")
15
+ return Path(env) if env else None
16
+
17
+
18
+ def default_user_cache_root() -> Path:
19
+ """Return the platform-neutral user cache root used when MONATA_HOME is unset."""
20
+
21
+ xdg = os.environ.get("XDG_CACHE_HOME")
22
+ if xdg:
23
+ return Path(xdg)
24
+ return Path(os.path.expanduser("~/.cache"))
25
+
26
+
27
+ def monata_cache_dir(*, home: str | Path | None = None) -> Path:
28
+ """Return the generic Monata cache directory for a configured home/default."""
29
+
30
+ root = monata_home(home)
31
+ if root is not None:
32
+ return root / "cache"
33
+ return default_user_cache_root() / "monata"
34
+
35
+
36
+ def monata_registry_dir(*, home: str | Path | None = None) -> Path | None:
37
+ """Return the optional Monata registry directory when a home root exists."""
38
+
39
+ root = monata_home(home)
40
+ return root / "registry" if root is not None else None
41
+
42
+
43
+ def monata_logs_dir(*, home: str | Path | None = None) -> Path | None:
44
+ """Return the optional Monata logs directory when a home root exists."""
45
+
46
+ root = monata_home(home)
47
+ return root / "logs" if root is not None else None
@@ -0,0 +1,57 @@
1
+ """Shared JSON-safe value coercion helpers."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from collections.abc import Mapping
6
+ import json
7
+ from pathlib import Path
8
+ from typing import Any
9
+
10
+ import numpy as np
11
+
12
+
13
+ def json_safe(value: Any, *, strict: bool = False) -> Any:
14
+ """Return a recursively JSON-compatible representation of common Monata values."""
15
+
16
+ result = _json_safe(value)
17
+ if strict:
18
+ json.dumps(result)
19
+ return result
20
+
21
+
22
+ def json_safe_dict(values: Mapping[str, Any]) -> dict[str, Any]:
23
+ return {str(key): json_safe(value) for key, value in dict(values).items()}
24
+
25
+
26
+ def _json_safe(value: Any) -> Any:
27
+ if hasattr(value, "to_dict"):
28
+ return json_safe(value.to_dict())
29
+ if value is None or isinstance(value, str | int | float | bool):
30
+ return value
31
+ if isinstance(value, Path):
32
+ return str(value)
33
+ if isinstance(value, np.generic):
34
+ return json_safe(value.item())
35
+ if isinstance(value, complex):
36
+ return {"real": value.real, "imag": value.imag}
37
+ if isinstance(value, np.ndarray):
38
+ if np.iscomplexobj(value):
39
+ return {
40
+ "real": np.real(value).tolist(),
41
+ "imag": np.imag(value).tolist(),
42
+ }
43
+ return json_safe(value.tolist())
44
+ if isinstance(value, Mapping):
45
+ return json_safe_dict(value)
46
+ if isinstance(value, list | tuple):
47
+ return [json_safe(item) for item in value]
48
+ if isinstance(value, set | frozenset):
49
+ return [json_safe(item) for item in sorted(value, key=str)]
50
+ if hasattr(value, "item"):
51
+ try:
52
+ return json_safe(value.item())
53
+ except ValueError:
54
+ pass
55
+ if hasattr(value, "tolist"):
56
+ return json_safe(value.tolist())
57
+ return value