Coverage for klayout_pex/pdk_config.py: 85%
41 statements
« prev ^ index » next coverage.py v7.15.4, created at 2026-08-21 15:48 +0000
« prev ^ index » next coverage.py v7.15.4, created at 2026-08-21 15:48 +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 IHP_SG13CMOS5L = 'ihp-sg13cmos5l'
45 SKY130A = 'sky130A'
47 @classmethod
48 def from_string(cls, value: str) -> PDK:
49 return PDK(cls.legacy_aliases().get(value, value))
51 @classmethod
52 def legacy_aliases(cls) -> Dict[str, str]:
53 aliases = {
54 'ihp_sg13g2': 'ihp-sg13g2',
55 }
56 return aliases
58 @cached_property
59 def config(self) -> PDKConfig:
60 # NOTE: installation paths of resources in the distribution wheel differs from source repo
61 base_dir = os.path.dirname(os.path.realpath(__file__))
63 # NOTE: .git can be dir (standalone clone), or file (in case of submodule)
64 if os.path.exists(os.path.join(base_dir, '..', '.git')): # in source repo
65 base_dir = os.path.dirname(base_dir)
66 tech_pb_json_dir = os.path.join(base_dir, 'klayout_pex_protobuf')
67 else: # site-packages/klayout_pex -> site-packages/klayout_pex_protobuf
68 tech_pb_json_dir = os.path.join(os.path.dirname(base_dir), 'klayout_pex_protobuf')
70 match self:
71 case PDK.GF180MCUD:
72 return PDKConfig(
73 name=self,
74 pex_lvs_script_path=os.path.join(base_dir, 'pdk', self, 'libs.tech', 'kpex', 'gf180mcu.lvs'),
75 tech_pb_json_path=os.path.join(tech_pb_json_dir, f"{self}_tech.pb.json")
76 )
77 case PDK.IHP_SG13G2:
78 return PDKConfig(
79 name=self,
80 pex_lvs_script_path=os.path.join(base_dir, 'pdk', self, 'libs.tech', 'kpex', 'sg13g2.lvs'),
81 tech_pb_json_path=os.path.join(tech_pb_json_dir, f"{self}_tech.pb.json")
82 )
83 case PDK.IHP_SG13CMOS5L:
84 return PDKConfig(
85 name=self,
86 pex_lvs_script_path=os.path.join(base_dir, 'pdk', self, 'libs.tech', 'kpex', 'sg13cmos5l.lvs'),
87 tech_pb_json_path=os.path.join(tech_pb_json_dir, f"{self}_tech.pb.json")
88 )
89 case PDK.SKY130A:
90 return PDKConfig(
91 name=self,
92 pex_lvs_script_path=os.path.join(base_dir, 'pdk', self, 'libs.tech', 'kpex', 'sky130.lvs'),
93 tech_pb_json_path=os.path.join(tech_pb_json_dir, f"{self}_tech.pb.json")
94 )
95 case _:
96 raise NotImplementedError(f"Unhandled enum case {self}")