layers.py
1 # SPDX-License-Identifier: AGPL-3.0-or-later OR GPL-2.0-or-later OR CERN-OHL-S-2.0+ OR Apache-2.0 2 from enum import Enum 3 from typing import Iterable 4 from warnings import warn 5 6 from .. import rule as _rle, wafer_ as _wfr, technology_ as _tch 7 8 from ._core import ( 9 _MaskPrimitive, _DesignMaskPrimitive, _WidthSpaceDesignMaskPrimitive, 10 ) 11 12 13 __all__ = [ 14 "Base", "BaseTypeT", "nBase", "pBase", "undopedBase", 15 "Marker", "SubstrateMarker", "Auxiliary", "ExtraProcess", "Insulator", 16 "Implant", "ImplantTypeT", "nImpl", "pImpl", "adjImpl", 17 ] 18 19 20 class Base(_MaskPrimitive): 21 class BaseType(Enum): 22 n = "n" 23 p = "p" 24 undoped = "undoped" 25 26 def __init__(self, *, type_: "BaseTypeT"): 27 super().__init__(name="base", mask=_wfr.wafer) 28 29 self._type = type_ 30 31 @property 32 def type_(self) -> "Base.BaseType": 33 return self._type 34 35 def _generate_rules(self, *, 36 tech: _tch.Technology, gen_mask: bool = True, 37 ) -> Iterable[_rle.RuleT]: 38 return super()._generate_rules(tech=tech, gen_mask=gen_mask) 39 BaseTypeT = Base.BaseType 40 nBase = Base.BaseType.n 41 pBase = Base.BaseType.p 42 undopedBase = Base.BaseType.undoped 43 44 45 class Marker(_DesignMaskPrimitive): 46 """The Marker primitive represents a layer used by other primitives for definition 47 of these primitives; typically a recognition. 48 It does not represent a processing layer and thus no physical mask is corresponding 49 with this primitive. 50 """ 51 def __init__(self, **super_args): 52 super().__init__(**super_args) 53 54 def _generate_rules(self, *, 55 tech: _tch.Technology, 56 ) -> Iterable[_rle.RuleT]: 57 return super()._generate_rules(tech=tech) 58 59 60 class SubstrateMarker(Marker): 61 """Often PDKs provide a marker layer to indicate substrate regions that have a net 62 connected different than the common ground substrate connection. This marker layer 63 is reserved for such purposes. 64 Currently no assumptions are made on how such a marker layer is to be used and thus 65 no checks on proper use are implemented. 66 """ 67 pass 68 69 70 class Auxiliary(_DesignMaskPrimitive): 71 """The Auxiliary primitive represents a layer that is defined by a foundry's 72 technology but not used in other PDKMaster primitives. 73 """ 74 def __init__(self, **super_args): 75 super().__init__(**super_args) 76 77 def _generate_rules(self, *, 78 tech: _tch.Technology, 79 ) -> Iterable[_rle.RuleT]: 80 return super()._generate_rules(tech=tech) 81 82 83 class ExtraProcess(_WidthSpaceDesignMaskPrimitive): 84 """ExtraProcess is a layer indicating an ExtraProcess step not handled 85 by other primitives. 86 87 For example non-silicidation for making active or poly resistors. 88 """ 89 def __init__(self, **super_args): 90 super().__init__(**super_args) 91 92 def _generate_rules(self, *, 93 tech: "_tch.Technology", 94 ) -> Iterable[_rle.RuleT]: 95 return super()._generate_rules(tech=tech) 96 97 98 class Insulator(_WidthSpaceDesignMaskPrimitive): 99 """Insulator is a layer representing an insulator layer. 100 101 Typical use is for thick oxide layer for higher voltage transistors. 102 """ 103 def __init__(self, **super_args): 104 super().__init__(**super_args) 105 106 def _generate_rules(self, *, 107 tech: "_tch.Technology", 108 ) -> Iterable[_rle.RuleT]: 109 return super()._generate_rules(tech=tech) 110 111 112 class Implant(_WidthSpaceDesignMaskPrimitive): 113 """Implant is a layer that represent an implantation step in the 114 semiconductor processing. 115 116 Arguments: 117 type_: type of the implant 118 an "adjust" implant layer is extra implant that can be used on 119 both n-type and p-type regions. 120 super_args: `_WidthSpacePrimitive` and `_DesignMaskPrimitive` 121 arguments 122 """ 123 class ImplantType(Enum): 124 """The type of implant. 125 Currently implemented types are: n, p, adjust. The .value of the enum 126 object is the string of the type; e.g. "n", "p", ... 127 128 These types are also made available as `nImpl`, `pImpl` and `adjImpl` 129 in the primitive module. 130 """ 131 n = "n" 132 p = "p" 133 adjust = "adjust" 134 135 def __hash__(self) -> int: 136 return super().__hash__() 137 138 def __eq__(self, __o: object) -> bool: 139 if isinstance(__o, str): 140 warn("Comparison of `ImplantType` with `str` always returns `False`") 141 return super().__eq__(__o) 142 143 # Implants are supposed to be disjoint unless they are used as combined implant 144 # MOSFET and other primitives 145 def __init__(self, *, type_: ImplantType, **super_args): 146 super().__init__(**super_args) 147 148 self._type = type_ 149 150 def _generate_rules(self, *, 151 tech: "_tch.Technology", 152 ) -> Iterable[_rle.RuleT]: 153 return super()._generate_rules(tech=tech) 154 155 @property 156 def type_(self) -> ImplantType: 157 return self._type 158 ImplantTypeT = Implant.ImplantType 159 nImpl = Implant.ImplantType.n 160 pImpl = Implant.ImplantType.p 161 adjImpl = Implant.ImplantType.adjust