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.
- haadic-0.6.0/PKG-INFO +131 -0
- haadic-0.6.0/docs/README.md +108 -0
- haadic-0.6.0/haadic/__init__.py +21 -0
- haadic-0.6.0/haadic/_config.py +5 -0
- haadic-0.6.0/haadic/core/__init__.py +1 -0
- haadic-0.6.0/haadic/core/flow.py +111 -0
- haadic-0.6.0/haadic/core/steps/__init__.py +1 -0
- haadic-0.6.0/haadic/core/steps/extraction.py +53 -0
- haadic-0.6.0/haadic/core/steps/layout_generation.py +59 -0
- haadic-0.6.0/haadic/core/steps/post_process.py +58 -0
- haadic-0.6.0/haadic/core/steps/spice_simulation.py +63 -0
- haadic-0.6.0/haadic/core/steps/step.py +226 -0
- haadic-0.6.0/haadic/core/techno.py +230 -0
- haadic-0.6.0/haadic/core/tools.py +98 -0
- haadic-0.6.0/haadic/data/mockup_pdk/ekv_mock.json +15 -0
- haadic-0.6.0/haadic/data/mockup_pdk/mock.json +153 -0
- haadic-0.6.0/haadic/data/mockup_pdk/mock.map +13 -0
- haadic-0.6.0/haadic/data/mockup_pdk/mock.proc +45 -0
- haadic-0.6.0/haadic/data/mockup_pdk/mock.tlef +80 -0
- haadic-0.6.0/haadic/data/patches/gf180mcu.json +84 -0
- haadic-0.6.0/haadic/data/patches/sky130.json +182 -0
- haadic-0.6.0/haadic/data/techno.json +38 -0
- haadic-0.6.0/haadic/data/template/cookiecutter.json +5 -0
- haadic-0.6.0/haadic/data/template/{{cookiecutter.project_name}}/bench.cir +9 -0
- haadic-0.6.0/haadic/data/template/{{cookiecutter.project_name}}/design.py +77 -0
- haadic-0.6.0/haadic/design/__init__.py +10 -0
- haadic-0.6.0/haadic/design/components/__init__.py +1 -0
- haadic-0.6.0/haadic/design/components/ekv.py +304 -0
- haadic-0.6.0/haadic/design/components/ekv_bench.cir +16 -0
- haadic-0.6.0/haadic/design/components/ekv_bench_ac.cir +12 -0
- haadic-0.6.0/haadic/design/layouts/__init__.py +5 -0
- haadic-0.6.0/haadic/design/layouts/active.py +125 -0
- haadic-0.6.0/haadic/design/layouts/base_cell.py +309 -0
- haadic-0.6.0/haadic/design/layouts/commun_source.py +32 -0
- haadic-0.6.0/haadic/design/layouts/general.py +109 -0
- haadic-0.6.0/haadic/design/layouts/inductor.py +166 -0
- haadic-0.6.0/haadic/design/layouts/microstrip.py +262 -0
- haadic-0.6.0/haadic/design/layouts/tools.py +28 -0
- haadic-0.6.0/haadic/design/models/__init__.py +1 -0
- haadic-0.6.0/haadic/design/models/constants.py +4 -0
- haadic-0.6.0/haadic/design/models/filter.py +87 -0
- haadic-0.6.0/haadic/design/models/inductor.py +33 -0
- haadic-0.6.0/haadic/design/models/matching.py +185 -0
- haadic-0.6.0/haadic/design/models/micro_strip.py +41 -0
- haadic-0.6.0/haadic/design/models/tools.py +74 -0
- haadic-0.6.0/haadic/design/post_processors/__init__.py +5 -0
- haadic-0.6.0/haadic/design/post_processors/ekv.py +239 -0
- haadic-0.6.0/haadic/design/post_processors/graphs.py +66 -0
- haadic-0.6.0/haadic/io/__init__.py +5 -0
- haadic-0.6.0/haadic/io/handlers/__init__.py +1 -0
- haadic-0.6.0/haadic/io/handlers/netlist.py +228 -0
- haadic-0.6.0/haadic/io/readers/__init__.py +1 -0
- haadic-0.6.0/haadic/io/readers/layermap.lark +16 -0
- haadic-0.6.0/haadic/io/readers/layermap.py +90 -0
- haadic-0.6.0/haadic/io/readers/magic_tech.py +55 -0
- haadic-0.6.0/haadic/io/readers/process.lark +22 -0
- haadic-0.6.0/haadic/io/readers/process.py +139 -0
- haadic-0.6.0/haadic/io/readers/raw.py +73 -0
- haadic-0.6.0/haadic/io/readers/tlef.lark +40 -0
- haadic-0.6.0/haadic/io/readers/tlef.py +205 -0
- haadic-0.6.0/haadic/io/readers/tools.py +16 -0
- haadic-0.6.0/haadic/io/wrappers/__init__.py +10 -0
- haadic-0.6.0/haadic/io/wrappers/em.py +141 -0
- haadic-0.6.0/haadic/io/wrappers/klayout.py +107 -0
- haadic-0.6.0/haadic/io/wrappers/magic.py +92 -0
- haadic-0.6.0/haadic/io/wrappers/magic_extract.tcl +22 -0
- haadic-0.6.0/haadic/io/wrappers/ngspice.py +70 -0
- haadic-0.6.0/haadic/io/wrappers/oems.py +264 -0
- haadic-0.6.0/haadic/io/wrappers/shell.nix +13 -0
- haadic-0.6.0/haadic/io/wrappers/tools.py +65 -0
- haadic-0.6.0/haadic/io/writers/__init__.py +1 -0
- haadic-0.6.0/haadic/io/writers/haadicfile.py +383 -0
- haadic-0.6.0/haadic/main.py +80 -0
- 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 @@
|
|
|
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
|