Coverage for klayout_pex / pdk_config.py: 87%
38 statements
« prev ^ index » next coverage.py v7.13.5, created at 2026-04-24 15:46 +0000
« prev ^ index » next coverage.py v7.13.5, created at 2026-04-24 15:46 +0000
1#
2# --------------------------------------------------------------------------------
3# SPDX-FileCopyrightText: 2024-2025 Martin Jan Köhler and Harald Pretl
4# Johannes Kepler University, Institute for Integrated Circuits.
5#
6# This file is part of KPEX
7# (see https://github.com/iic-jku/klayout-pex).
8#
9# This program is free software: you can redistribute it and/or modify
10# it under the terms of the GNU General Public License as published by
11# the Free Software Foundation, either version 3 of the License, or
12# (at your option) any later version.
13#
14# This program is distributed in the hope that it will be useful,
15# but WITHOUT ANY WARRANTY; without even the implied warranty of
16# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17# GNU General Public License for more details.
18#
19# You should have received a copy of the GNU General Public License
20# along with this program. If not, see <http://www.gnu.org/licenses/>.
21# SPDX-License-Identifier: GPL-3.0-or-later
22# --------------------------------------------------------------------------------
23#
25from __future__ import annotations
26from enum import StrEnum
27from dataclasses import dataclass
28from functools import cached_property
29import os
30from typing import *
33@dataclass
34class PDKConfig:
35 name: str
36 pex_lvs_script_path: str
37 tech_pb_json_path: str
40# TODO: this should be externally configurable
41class PDK(StrEnum):
42 GF180MCUD = 'gf180mcuD'
43 IHP_SG13G2 = 'ihp-sg13g2'
44 SKY130A = 'sky130A'
46 @classmethod
47 def from_string(cls, value: str) -> PDK:
48 return PDK(cls.legacy_aliases().get(value, value))
50 @classmethod
51 def legacy_aliases(cls) -> Dict[str, str]:
52 aliases = {
53 'ihp_sg13g2': 'ihp-sg13g2',
54 }
55 return aliases
57 @cached_property
58 def config(self) -> PDKConfig:
59 # NOTE: installation paths of resources in the distribution wheel differs from source repo
60 base_dir = os.path.dirname(os.path.realpath(__file__))
62 # NOTE: .git can be dir (standalone clone), or file (in case of submodule)
63 if os.path.exists(os.path.join(base_dir, '..', '.git')): # in source repo
64 base_dir = os.path.dirname(base_dir)
65 tech_pb_json_dir = os.path.join(base_dir, 'klayout_pex_protobuf')
66 else: # site-packages/klayout_pex -> site-packages/klayout_pex_protobuf
67 tech_pb_json_dir = os.path.join(os.path.dirname(base_dir), 'klayout_pex_protobuf')
69 match self:
70 case PDK.GF180MCUD:
71 return PDKConfig(
72 name=self,
73 pex_lvs_script_path=os.path.join(base_dir, 'pdk', self, 'libs.tech', 'kpex', 'gf180mcu.lvs'),
74 tech_pb_json_path=os.path.join(tech_pb_json_dir, f"{self}_tech.pb.json")
75 )
76 case PDK.IHP_SG13G2:
77 return PDKConfig(
78 name=self,
79 pex_lvs_script_path=os.path.join(base_dir, 'pdk', self, 'libs.tech', 'kpex', 'sg13g2.lvs'),
80 tech_pb_json_path=os.path.join(tech_pb_json_dir, f"{self}_tech.pb.json")
81 )
82 case PDK.SKY130A:
83 return PDKConfig(
84 name=self,
85 pex_lvs_script_path=os.path.join(base_dir, 'pdk', self, 'libs.tech', 'kpex', 'sky130.lvs'),
86 tech_pb_json_path=os.path.join(tech_pb_json_dir, f"{self}_tech.pb.json")
87 )
88 case _:
89 raise NotImplementedError(f"Unhandled enum case {self}")