haadic 0.6.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 (74) hide show
  1. haadic-0.6.0/PKG-INFO +131 -0
  2. haadic-0.6.0/docs/README.md +108 -0
  3. haadic-0.6.0/haadic/__init__.py +21 -0
  4. haadic-0.6.0/haadic/_config.py +5 -0
  5. haadic-0.6.0/haadic/core/__init__.py +1 -0
  6. haadic-0.6.0/haadic/core/flow.py +111 -0
  7. haadic-0.6.0/haadic/core/steps/__init__.py +1 -0
  8. haadic-0.6.0/haadic/core/steps/extraction.py +53 -0
  9. haadic-0.6.0/haadic/core/steps/layout_generation.py +59 -0
  10. haadic-0.6.0/haadic/core/steps/post_process.py +58 -0
  11. haadic-0.6.0/haadic/core/steps/spice_simulation.py +63 -0
  12. haadic-0.6.0/haadic/core/steps/step.py +226 -0
  13. haadic-0.6.0/haadic/core/techno.py +230 -0
  14. haadic-0.6.0/haadic/core/tools.py +98 -0
  15. haadic-0.6.0/haadic/data/mockup_pdk/ekv_mock.json +15 -0
  16. haadic-0.6.0/haadic/data/mockup_pdk/mock.json +153 -0
  17. haadic-0.6.0/haadic/data/mockup_pdk/mock.map +13 -0
  18. haadic-0.6.0/haadic/data/mockup_pdk/mock.proc +45 -0
  19. haadic-0.6.0/haadic/data/mockup_pdk/mock.tlef +80 -0
  20. haadic-0.6.0/haadic/data/patches/gf180mcu.json +84 -0
  21. haadic-0.6.0/haadic/data/patches/sky130.json +182 -0
  22. haadic-0.6.0/haadic/data/techno.json +38 -0
  23. haadic-0.6.0/haadic/data/template/cookiecutter.json +5 -0
  24. haadic-0.6.0/haadic/data/template/{{cookiecutter.project_name}}/bench.cir +9 -0
  25. haadic-0.6.0/haadic/data/template/{{cookiecutter.project_name}}/design.py +77 -0
  26. haadic-0.6.0/haadic/design/__init__.py +10 -0
  27. haadic-0.6.0/haadic/design/components/__init__.py +1 -0
  28. haadic-0.6.0/haadic/design/components/ekv.py +304 -0
  29. haadic-0.6.0/haadic/design/components/ekv_bench.cir +16 -0
  30. haadic-0.6.0/haadic/design/components/ekv_bench_ac.cir +12 -0
  31. haadic-0.6.0/haadic/design/layouts/__init__.py +5 -0
  32. haadic-0.6.0/haadic/design/layouts/active.py +125 -0
  33. haadic-0.6.0/haadic/design/layouts/base_cell.py +309 -0
  34. haadic-0.6.0/haadic/design/layouts/commun_source.py +32 -0
  35. haadic-0.6.0/haadic/design/layouts/general.py +109 -0
  36. haadic-0.6.0/haadic/design/layouts/inductor.py +166 -0
  37. haadic-0.6.0/haadic/design/layouts/microstrip.py +262 -0
  38. haadic-0.6.0/haadic/design/layouts/tools.py +28 -0
  39. haadic-0.6.0/haadic/design/models/__init__.py +1 -0
  40. haadic-0.6.0/haadic/design/models/constants.py +4 -0
  41. haadic-0.6.0/haadic/design/models/filter.py +87 -0
  42. haadic-0.6.0/haadic/design/models/inductor.py +33 -0
  43. haadic-0.6.0/haadic/design/models/matching.py +185 -0
  44. haadic-0.6.0/haadic/design/models/micro_strip.py +41 -0
  45. haadic-0.6.0/haadic/design/models/tools.py +74 -0
  46. haadic-0.6.0/haadic/design/post_processors/__init__.py +5 -0
  47. haadic-0.6.0/haadic/design/post_processors/ekv.py +239 -0
  48. haadic-0.6.0/haadic/design/post_processors/graphs.py +66 -0
  49. haadic-0.6.0/haadic/io/__init__.py +5 -0
  50. haadic-0.6.0/haadic/io/handlers/__init__.py +1 -0
  51. haadic-0.6.0/haadic/io/handlers/netlist.py +228 -0
  52. haadic-0.6.0/haadic/io/readers/__init__.py +1 -0
  53. haadic-0.6.0/haadic/io/readers/layermap.lark +16 -0
  54. haadic-0.6.0/haadic/io/readers/layermap.py +90 -0
  55. haadic-0.6.0/haadic/io/readers/magic_tech.py +55 -0
  56. haadic-0.6.0/haadic/io/readers/process.lark +22 -0
  57. haadic-0.6.0/haadic/io/readers/process.py +139 -0
  58. haadic-0.6.0/haadic/io/readers/raw.py +73 -0
  59. haadic-0.6.0/haadic/io/readers/tlef.lark +40 -0
  60. haadic-0.6.0/haadic/io/readers/tlef.py +205 -0
  61. haadic-0.6.0/haadic/io/readers/tools.py +16 -0
  62. haadic-0.6.0/haadic/io/wrappers/__init__.py +10 -0
  63. haadic-0.6.0/haadic/io/wrappers/em.py +141 -0
  64. haadic-0.6.0/haadic/io/wrappers/klayout.py +107 -0
  65. haadic-0.6.0/haadic/io/wrappers/magic.py +92 -0
  66. haadic-0.6.0/haadic/io/wrappers/magic_extract.tcl +22 -0
  67. haadic-0.6.0/haadic/io/wrappers/ngspice.py +70 -0
  68. haadic-0.6.0/haadic/io/wrappers/oems.py +264 -0
  69. haadic-0.6.0/haadic/io/wrappers/shell.nix +13 -0
  70. haadic-0.6.0/haadic/io/wrappers/tools.py +65 -0
  71. haadic-0.6.0/haadic/io/writers/__init__.py +1 -0
  72. haadic-0.6.0/haadic/io/writers/haadicfile.py +383 -0
  73. haadic-0.6.0/haadic/main.py +80 -0
  74. haadic-0.6.0/pyproject.toml +93 -0
haadic-0.6.0/PKG-INFO ADDED
@@ -0,0 +1,131 @@
1
+ Metadata-Version: 2.3
2
+ Name: haadic
3
+ Version: 0.6.0
4
+ Summary: A package for parametric layout design.
5
+ Author: Patarimi
6
+ Author-email: Patarimi <<38954040+Patarimi@users.noreply.github.com>>
7
+ Requires-Dist: ciel>=2.5.1
8
+ Requires-Dist: cyclopts>=4.14.0
9
+ Requires-Dist: klayout>=0.30.2
10
+ Requires-Dist: lark>=1.2.2
11
+ Requires-Dist: matplotlib>=3.10.3
12
+ Requires-Dist: numpy>=2.5.0
13
+ Requires-Dist: pandas>=2.3.1
14
+ Requires-Dist: pydantic>=2.13.4
15
+ Requires-Dist: pyqt6>=6.11.0 ; sys_platform == 'linux'
16
+ Requires-Dist: python-dotenv>=1.1.1
17
+ Requires-Dist: rich>=13.9.4
18
+ Requires-Dist: scikit-rf>=1.12.0
19
+ Requires-Dist: scipy>=1.18.0
20
+ Requires-Dist: tabulate>=0.9.0
21
+ Requires-Python: >3.12, <3.14
22
+ Description-Content-Type: text/markdown
23
+
24
+ # HAADIC
25
+
26
+ **Highly-Automated Analog Designer for Integrated Circuits**
27
+
28
+ This project is a prototype. Its goal is to create a technological and
29
+ software-agnostic design flow, from device sizing to layout and implementation.
30
+
31
+ ## How to get started
32
+
33
+ This application needs nix, uv and python3. For windows, please install NixOS as shown [here](https://nixos.wiki/wiki/WSL).
34
+
35
+ Installation using [uvx](https://docs.astral.sh/uv/getting-started/installation/) is recommended.
36
+
37
+ The following command check if everything is correctly setup :
38
+
39
+ ```shell
40
+ uvx --with="git+https://github.com/Patarimi/haadic.git" haadic smoke-test
41
+ ```
42
+
43
+ ## Setting up a new Project
44
+
45
+ A directory with the required files can be generated using :
46
+
47
+ ```shell
48
+ haadic new
49
+ ```
50
+
51
+ ## GDS Generation
52
+
53
+ First update the layout fonction in the design.py file created in the previous step. Some helpfull fonctions can be found in [design:layouts](reference/haadic/design/layouts/index.md).
54
+ Then run the following command :
55
+
56
+ ```shell
57
+ uv run --script design.py
58
+ ```
59
+
60
+ The [Design flow](#design-flow) is run.
61
+
62
+ Dimensions in the layout can be changed by editing the `dim` variable.
63
+ Post-simulation computation can be done by editing the `evaluate` function.
64
+
65
+ ## Design Flow
66
+
67
+ The following flow is run using the informations given in a _design_ python file (See [Setup a new Project](#setting-up-a-new-project)). The flow has 2 entry points :
68
+
69
+ - `flow.run_from_dim` : Only requires a `dim` variables which defines the value of each parameters of the layout function.
70
+ - `flow.run_from_target` : Requires both a `target`and an `local_model` function. The `local_model` is an implementation of the design methodology which output the layout parameters value required to obtains the `target`.
71
+
72
+ ```mermaid
73
+ flowchart TD
74
+ s1{Start #2}
75
+ s2{Start #1}
76
+ app["Physical Model
77
+ (design:local_model)"]
78
+ pl["Parametric Layout
79
+ (klayout + design:layout)"]
80
+ be_ext["RC extraction
81
+ (steps.extraction + Magic-VLSI)"]
82
+ sim["Spice simulation
83
+ (steps.spice_sim + NGSpice)"]
84
+ spec["Performances Evaluation
85
+ (design:post_processors)"]
86
+
87
+ s1 -- "design:specifications" --> app
88
+ s2 -- "design:dimensions" --> pl
89
+ app --"dimensions (step.Dim)" --> pl
90
+ pl --"geometries (.gds)" --> be_ext
91
+ be_ext --"netlist (.cir)" --> sim
92
+ sim --"raw simulation (step.SimRes)" --> spec
93
+ spec --"performances (.csv)" --> st{stop}
94
+ ```
95
+
96
+ When finished, a _.gds_ file is available for further design and a _.csv_ file with the performances of the design.
97
+
98
+ ## PDKs configuration
99
+
100
+ A techno.json file can be created in the working dir or the haadic root with the following structure:
101
+
102
+ ```json
103
+ {
104
+ "techno_name": {
105
+ "base_dir": "path to the pdk directory root",
106
+ "layermap": "path to the layermap (relative to the base_dir)",
107
+ "techlef": "path to the tlef file",
108
+ "magic_rc": "path to the configuration file of magic",
109
+ "lib_spice": "path to the spice model library",
110
+ "section": "name of the section to import in the spice library typical",
111
+ "source_url": "url to be use for download (set to "ciel" for ciel installation)",
112
+ "version": "version id (only required if source_url is set to "ciel")"
113
+ }
114
+ }
115
+ ```
116
+
117
+ A techno.json file with three open source PDK and a mock PDK are already supplied.
118
+
119
+ ## For developpers
120
+
121
+ Install haadic with optional group dev :
122
+
123
+ ```shell
124
+ uv install git+https://github.com/Patarimi/haadic --with dev
125
+ ```
126
+
127
+ Then run pytest in a shell
128
+
129
+ ```shell
130
+ uvx run poe test
131
+ ```
@@ -0,0 +1,108 @@
1
+ # HAADIC
2
+
3
+ **Highly-Automated Analog Designer for Integrated Circuits**
4
+
5
+ This project is a prototype. Its goal is to create a technological and
6
+ software-agnostic design flow, from device sizing to layout and implementation.
7
+
8
+ ## How to get started
9
+
10
+ This application needs nix, uv and python3. For windows, please install NixOS as shown [here](https://nixos.wiki/wiki/WSL).
11
+
12
+ Installation using [uvx](https://docs.astral.sh/uv/getting-started/installation/) is recommended.
13
+
14
+ The following command check if everything is correctly setup :
15
+
16
+ ```shell
17
+ uvx --with="git+https://github.com/Patarimi/haadic.git" haadic smoke-test
18
+ ```
19
+
20
+ ## Setting up a new Project
21
+
22
+ A directory with the required files can be generated using :
23
+
24
+ ```shell
25
+ haadic new
26
+ ```
27
+
28
+ ## GDS Generation
29
+
30
+ First update the layout fonction in the design.py file created in the previous step. Some helpfull fonctions can be found in [design:layouts](reference/haadic/design/layouts/index.md).
31
+ Then run the following command :
32
+
33
+ ```shell
34
+ uv run --script design.py
35
+ ```
36
+
37
+ The [Design flow](#design-flow) is run.
38
+
39
+ Dimensions in the layout can be changed by editing the `dim` variable.
40
+ Post-simulation computation can be done by editing the `evaluate` function.
41
+
42
+ ## Design Flow
43
+
44
+ The following flow is run using the informations given in a _design_ python file (See [Setup a new Project](#setting-up-a-new-project)). The flow has 2 entry points :
45
+
46
+ - `flow.run_from_dim` : Only requires a `dim` variables which defines the value of each parameters of the layout function.
47
+ - `flow.run_from_target` : Requires both a `target`and an `local_model` function. The `local_model` is an implementation of the design methodology which output the layout parameters value required to obtains the `target`.
48
+
49
+ ```mermaid
50
+ flowchart TD
51
+ s1{Start #2}
52
+ s2{Start #1}
53
+ app["Physical Model
54
+ (design:local_model)"]
55
+ pl["Parametric Layout
56
+ (klayout + design:layout)"]
57
+ be_ext["RC extraction
58
+ (steps.extraction + Magic-VLSI)"]
59
+ sim["Spice simulation
60
+ (steps.spice_sim + NGSpice)"]
61
+ spec["Performances Evaluation
62
+ (design:post_processors)"]
63
+
64
+ s1 -- "design:specifications" --> app
65
+ s2 -- "design:dimensions" --> pl
66
+ app --"dimensions (step.Dim)" --> pl
67
+ pl --"geometries (.gds)" --> be_ext
68
+ be_ext --"netlist (.cir)" --> sim
69
+ sim --"raw simulation (step.SimRes)" --> spec
70
+ spec --"performances (.csv)" --> st{stop}
71
+ ```
72
+
73
+ When finished, a _.gds_ file is available for further design and a _.csv_ file with the performances of the design.
74
+
75
+ ## PDKs configuration
76
+
77
+ A techno.json file can be created in the working dir or the haadic root with the following structure:
78
+
79
+ ```json
80
+ {
81
+ "techno_name": {
82
+ "base_dir": "path to the pdk directory root",
83
+ "layermap": "path to the layermap (relative to the base_dir)",
84
+ "techlef": "path to the tlef file",
85
+ "magic_rc": "path to the configuration file of magic",
86
+ "lib_spice": "path to the spice model library",
87
+ "section": "name of the section to import in the spice library typical",
88
+ "source_url": "url to be use for download (set to "ciel" for ciel installation)",
89
+ "version": "version id (only required if source_url is set to "ciel")"
90
+ }
91
+ }
92
+ ```
93
+
94
+ A techno.json file with three open source PDK and a mock PDK are already supplied.
95
+
96
+ ## For developpers
97
+
98
+ Install haadic with optional group dev :
99
+
100
+ ```shell
101
+ uv install git+https://github.com/Patarimi/haadic --with dev
102
+ ```
103
+
104
+ Then run pytest in a shell
105
+
106
+ ```shell
107
+ uvx run poe test
108
+ ```
@@ -0,0 +1,21 @@
1
+ """
2
+ A Python framework for analog IC design automation.
3
+
4
+ # Haadic structure:
5
+
6
+ - core
7
+ - flow: for defining and running design flows
8
+ - steps: for defining the core steps in the design flow, such as layout generation, extraction, simulation, etc.
9
+ - techno: for handling technology-specific information and operations.
10
+ - io
11
+ - readers: files readers (spice, raw, etc.)
12
+ - writers: files writers (spice)
13
+ - wrappers: for external tools (e.g., magic, netgen, etc.)
14
+ - design
15
+ - layouts: for layout generation and manipulation
16
+ - models: for device and circuit modeling
17
+ - evaluators: for performance evaluation
18
+ - components: parameterized components (e.g., common sources) and design helpers (e.g., EKV model).
19
+ """
20
+
21
+ name = "haadic"
@@ -0,0 +1,5 @@
1
+ from pathlib import Path
2
+
3
+ ROOT_DIR = Path(__file__).parent
4
+ DATA_DIR = ROOT_DIR / "data"
5
+ REF_PATH = ROOT_DIR.parent / "tests" / "ref_files"
@@ -0,0 +1 @@
1
+ """Module for the haadic core functionality: run analog flow."""
@@ -0,0 +1,111 @@
1
+ """Module defining the Flow class, which composes multiple steps (layout generation, extraction, simulation, post-processing) into a complete design flow."""
2
+
3
+ import logging
4
+ from pathlib import Path
5
+ from typing import Callable, Iterable
6
+ from dataclasses import dataclass, field
7
+ from tabulate import tabulate
8
+
9
+ import haadic.core.steps.step as step
10
+ from haadic.core.steps.extraction import Extract, ConfigExtract
11
+ from haadic.core.steps.layout_generation import Layout, ConfigLayout, LayoutFunc
12
+ from haadic.core.steps.spice_simulation import BenchSim, ConfigSim
13
+ from haadic.core.steps.post_process import PostProcess, ConfigPostProc, PostProcessFunc
14
+ from haadic.core.techno import Available_PDK
15
+ from haadic.io.wrappers.magic import ExtractLevels
16
+
17
+
18
+ @dataclass
19
+ class ConfigFlow:
20
+ """
21
+ Configuration for a Flow execution.
22
+
23
+ :param techno: Selected PDK name.
24
+ :param reload: Whether to reload intermediate files when available (e.g., layout, spice netlist) or to recompute them.
25
+ :param run_dir: Base directory where results are written.
26
+ :param extract_level: Extraction level used by the Extract step.
27
+ :param sweep_folder: If True, create a separate folder per sweep value when using the run_from_* methods.
28
+ """
29
+
30
+ techno: Available_PDK = "sky130"
31
+ reload: bool = True
32
+ run_dir: Path = Path("./results")
33
+ extract_level: ExtractLevels = "RC"
34
+ sweep_folder: bool = True
35
+
36
+
37
+ @dataclass
38
+ class Flow:
39
+ """
40
+ Flow dataclass.
41
+
42
+ :param layout: function that generates the layout. It takes as argument a klayout Cell, a LayerStack and the dimensions of the layout to generate.
43
+ It should return a klayout Cell with the generated layout.
44
+ :param benches: list of bench files to run. The flow will look for these files in the current folder and run them with the extracted spice netlist.
45
+ They can be absolute or relative to the running folder.
46
+ :param postprocess: function that evaluates the performances of the circuit. It takes as argument the simulation results of the benches and the dimensions of the layout.
47
+ It should return a dictionary with the performance metrics to optimize as keys and their values as values.
48
+ :param config: flow options, such as the technology to use, whether to reload the layout if it already exists, and the folder to run the flow in.
49
+ """
50
+
51
+ layout: LayoutFunc
52
+ benches: Iterable[Path]
53
+ postprocess: Iterable[PostProcessFunc]
54
+ config: ConfigFlow = field(default_factory=ConfigFlow)
55
+
56
+ def run_from_dim(self, dimensions: step.Dim) -> step.Dim:
57
+ """
58
+ Run the composed flow starting from explicit dimensions.
59
+
60
+ Args:
61
+ dimensions: a `Dim` instance describing layout dimensions/parameters.
62
+
63
+ Returns:
64
+ A `Dim`-like object containing aggregated performance metrics produced by the postprocess steps.
65
+
66
+ """
67
+ datas = step.Dim()
68
+ d_benches = [f.resolve() for f in self.benches]
69
+ for bench, eval in zip(d_benches, self.postprocess):
70
+ start = step.init_step(
71
+ dimensions, self.config.run_dir, self.config.sweep_folder
72
+ )
73
+ flow = step.compose(
74
+ Layout(ConfigLayout(self.layout, self.config.techno)),
75
+ Extract(ConfigExtract(self.config.techno, self.config.extract_level)),
76
+ BenchSim(ConfigSim(bench, self.config.techno)),
77
+ reload=self.config.reload,
78
+ )
79
+ output_file = flow.run(start)
80
+ pp = PostProcess(ConfigPostProc(eval))
81
+ data = pp.run(output_file, dimensions)
82
+ for key in data.dct:
83
+ datas[key] = data[key]
84
+ return datas
85
+
86
+ def run_from_target(
87
+ self,
88
+ target: step.Dim,
89
+ local_model: Callable[[step.Dim], step.Dim],
90
+ ) -> step.Dim:
91
+ """
92
+ Run the flow from a target specification using a local model.
93
+
94
+ Args:
95
+ target: A `Dim` describing desired target values.
96
+ local_model: Callable that maps the `target` to actual layout `Dim` parameters.
97
+
98
+ Returns:
99
+ A `Dim`-like object containing aggregated performance metrics produced by the postprocess steps.
100
+
101
+ """
102
+ perf = self.run_from_dim(local_model(target))
103
+ res = [(key, perf.dct[key], target.dct.get(key, "N/A")) for key in perf.dct]
104
+ logging.info(
105
+ "\n" + tabulate(res, headers=["obtained", "targeted"], tablefmt="grid")
106
+ )
107
+
108
+ logging.info("compare performances to targets")
109
+ cost = step.compare_to(perf.dct, target.dct)
110
+ logging.info(f"current cost: {cost}")
111
+ return perf
@@ -0,0 +1 @@
1
+ """Module for the core steps in the design flow."""
@@ -0,0 +1,53 @@
1
+ """Module defining the Extract step, which performs layout extraction to generate a SPICE netlist from a GDSII layout."""
2
+
3
+ from haadic.core.steps.step import Step
4
+ from dataclasses import dataclass, field
5
+ from typing import Sequence
6
+ from haadic.io.wrappers.magic import ExtractLevels, extract_spice
7
+ from pathlib import Path
8
+ from haadic.core.techno import get_file, Available_PDK
9
+
10
+
11
+ @dataclass
12
+ class ConfigExtract:
13
+ """
14
+ Configuration for the Extract step.
15
+
16
+ :param techno: technology to use for extraction (e.g., "sky130", "gf180mcu").
17
+ :param level: extraction level to use (e.g., "NoPar", "RC").
18
+ """
19
+
20
+ techno: Available_PDK = "sky130"
21
+ level: ExtractLevels = "RC"
22
+
23
+
24
+ @dataclass
25
+ class Extract(Step):
26
+ """
27
+ Extract step dataclass.
28
+
29
+ :param config: configuration for the Extract step, including the technology to use and the extraction level.
30
+ :param input_suffixes: list of suffixes for the expected input file(s) (default: [".gds"]).
31
+ :param output_suffix: suffix for the output file (default: ".cir").
32
+ """
33
+
34
+ config: ConfigExtract = field(default_factory=ConfigExtract)
35
+ input_suffixes: Sequence[str] = field(default_factory=lambda: [".gds"])
36
+ output_suffix: str = ".cir"
37
+
38
+ def run(self, input_file: Path = Path("top.gds")) -> Path:
39
+ """
40
+ Extract a netlist from a given layout.
41
+
42
+ :param Path input_file: input gds file.
43
+ :return Path: extracted spice circuit.
44
+ """
45
+ output_path = self.output_file(input_file)
46
+ rc_file = get_file(self.config.techno, "magic_rc")
47
+ return extract_spice(
48
+ input_file,
49
+ rc_file,
50
+ input_file.stem,
51
+ output_path,
52
+ options=self.config.level,
53
+ )
@@ -0,0 +1,59 @@
1
+ """Module defining the Layout step for generating layouts from parametric descriptions."""
2
+
3
+ import logging
4
+ from haadic.core.techno import Available_PDK
5
+ from pathlib import Path
6
+ from typing import Callable, Sequence
7
+ from dataclasses import field, dataclass
8
+ import json
9
+
10
+ from haadic.design.layouts.base_cell import BaseCell
11
+ from haadic.core.steps.step import Dim, Step
12
+
13
+ type LayoutFunc = Callable[[BaseCell, Dim], BaseCell]
14
+
15
+
16
+ @dataclass
17
+ class ConfigLayout:
18
+ """
19
+ Configuration for the Layout step.
20
+
21
+ :param layout: function that generates the layout.
22
+ :param techno: technology to be used.
23
+ """
24
+
25
+ layout: LayoutFunc
26
+ techno: Available_PDK = "sky130"
27
+
28
+
29
+ @dataclass
30
+ class Layout(Step):
31
+ """
32
+ Step to generate a layout from a parametric description.
33
+
34
+ :param config: configuration for the layout generation step, including the layout function and the technology to use.
35
+ :param input_suffixes: list of expected suffixes for the input files. By default, it is set to [".json"].
36
+ :param output_suffix: suffix for the output file. By default, it is set to ".gds".
37
+ """
38
+
39
+ config: ConfigLayout
40
+ input_suffixes: Sequence[str] = field(default_factory=lambda: [".json"])
41
+ output_suffix: str = ".gds"
42
+
43
+ def run(self, input_file: Path) -> Path:
44
+ """
45
+ Generate a layout in the requested techologies with the given parametric layout and the given set of parameters.
46
+
47
+ :param input_file: set of parameters for the layout.
48
+ """
49
+ with input_file.open() as f:
50
+ dimensions = json.load(f)
51
+ output_file = self.output_file(input_file)
52
+ logging.info("layout generation with geometry: " + str(dimensions))
53
+
54
+ cellb = BaseCell(self.config.techno, input_file.stem)
55
+
56
+ self.config.layout(cellb, dimensions)
57
+
58
+ cellb.write(output_file)
59
+ return output_file
@@ -0,0 +1,58 @@
1
+ """Module defining the PostProcess step for post-processing simulation results and extracting performance metrics."""
2
+
3
+ from haadic.io.readers.raw import parse_out
4
+ from typing import Callable, Sequence
5
+ from dataclasses import field, dataclass
6
+ from pathlib import Path
7
+ import pandas as pd
8
+
9
+ from haadic.core.steps.step import Dim
10
+
11
+ SimRes = pd.DataFrame
12
+
13
+ type PostProcessFunc = Callable[[SimRes, Dim, Path], Dim]
14
+
15
+
16
+ @dataclass
17
+ class ConfigPostProc:
18
+ """
19
+ Configuration for the PostProcess step.
20
+
21
+ :param evaluate: function that evaluates the performances of the circuit.
22
+ It takes as argument the simulation results of the benches and the dimensions of the layout.
23
+ It should return a Dim class with the performance metrics.
24
+ """
25
+
26
+ evaluate: PostProcessFunc
27
+
28
+
29
+ @dataclass
30
+ class PostProcess:
31
+ """
32
+ Step to post-process the simulation results and extract performance metrics.
33
+
34
+ This step is meant to be run after a spice simulation step, and it takes as input the raw output file of the simulation (with suffix .raw)
35
+ and produces as output a Dim class with the performance metrics.
36
+
37
+ :param config: configuration for the post-processing step.
38
+ :param input_suffixes: list of expected suffixes for the input files. By default, it is set to [".raw"].
39
+ :param output_suffix: suffix for the output file. By default, it is set to "".
40
+ """
41
+
42
+ config: ConfigPostProc
43
+ input_suffixes: Sequence[str] = field(default_factory=lambda: [".raw"])
44
+ output_suffix: str = ""
45
+
46
+ def run(self, data_file: Path = Path("top.raw"), dimensions: Dim = Dim()) -> Dim:
47
+ """
48
+ Run the post-processing step.
49
+
50
+ This method reads the raw simulation output file, evaluates the performance metrics using the provided evaluate function, and returns a Dim class with the performance metrics.
51
+
52
+ :param data_file: path to the raw simulation output file.
53
+ :param dimensions: dimensions of the layout.
54
+ :return Dim: performance metrics.
55
+ """
56
+ data = parse_out(data_file)
57
+ base_dir = data_file.parent
58
+ return self.config.evaluate(data, dimensions, base_dir)
@@ -0,0 +1,63 @@
1
+ """Spice simulation step for the haadic design flow."""
2
+
3
+ from typing import Sequence
4
+ from dataclasses import dataclass, field
5
+ from pathlib import Path
6
+ from haadic.io.handlers.netlist import Netlist
7
+ from haadic.io.wrappers.ngspice import compute
8
+ from haadic.io.wrappers.tools import to_wsl
9
+ from haadic.core.techno import get_file, load_pdk, Available_PDK
10
+ from haadic.core.steps.step import can_skip, Step
11
+
12
+
13
+ @dataclass
14
+ class ConfigSim:
15
+ """
16
+ Configuration for the BenchSim step.
17
+
18
+ :param bench: path to the bench file to simulate, defaults to "bench.cir"."
19
+ :param techno: name of the technology to use for the simulation, defaults to "sky130".
20
+ """
21
+
22
+ bench: Path = Path("bench.cir")
23
+ techno: Available_PDK = "sky130"
24
+
25
+
26
+ @dataclass
27
+ class BenchSim(Step):
28
+ """
29
+ Step to run a spice simulation using ngspice.
30
+
31
+ :param config: configuration for the BenchSim step.
32
+ :param input_suffixes: list of accepted input file suffixes for this step, defaults to [".cir"].
33
+ :param output_suffix: suffix for the output file generated by this step, defaults to ".raw".
34
+ """
35
+
36
+ config: ConfigSim = field(default_factory=ConfigSim)
37
+ input_suffixes: Sequence[str] = field(default_factory=lambda: [".cir"])
38
+ output_suffix: str = ".raw"
39
+
40
+ def run(self, input_file: Path = Path("top.cir")) -> Path:
41
+ """
42
+ Run the given netlist using the requested technologie.
43
+
44
+ :param input_file: spice netlist bench to be simulated, defaults to "bench.cir"
45
+ :return Path: path to the output raw file generated by ngspice.
46
+ """
47
+ bench = self.config.bench
48
+ data_file = (
49
+ Path(input_file).with_name(bench.name).with_suffix(self.output_suffix)
50
+ )
51
+ if can_skip(bench, data_file) and can_skip(input_file, data_file):
52
+ return data_file
53
+ techno = self.config.techno
54
+
55
+ spice = Netlist().load(bench)
56
+ section = load_pdk(techno).get("section", "tt")
57
+ spice.add_lib(to_wsl(get_file(techno, "lib_spice")), section)
58
+
59
+ spice.add_include(input_file)
60
+ spice.write(data_file.with_name(bench.name))
61
+
62
+ compute(data_file.with_name(bench.name), data_file)
63
+ return data_file