/ pdkmaster / technology / primitive / _derived.py
_derived.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 typing import Optional, Tuple, Iterable
 3  
 4  from pdkmaster.technology import mask as _msk
 5  
 6  from ...typing import cast_MultiT
 7  from .. import rule as _rle, mask as _msk, technology_ as _tch
 8  
 9  from ._core import _MaskPrimitive
10  
11  
12  # _DerivedPrimitive and subclasses are considered for internal use only;
13  # not to be used in user land code. User land just sees MaskPrimitiveT
14  __all__ = []
15  
16  
17  class _DerivedPrimitive(_MaskPrimitive):
18      """A primitive that is derived from other primitives and not a
19      Primitive that can be part of the primitive list of a technology.
20      """
21      def _generate_rules(self, *, tech: _tch.Technology) -> Tuple[_rle.RuleT, ...]:
22          """As _DerivedPrimitive will not be added to the list of primitives
23          of a technology node, it does not need to generate rules.
24          """
25          raise RuntimeError("Internal error") # pragma: no cover
26  
27  
28  class _Intersect(_DerivedPrimitive):
29      """A derived primitive representing the overlap of a list of primitives
30      """
31      def __init__(self, *, prims: Iterable[_MaskPrimitive]):
32          prims2: Tuple[_MaskPrimitive, ...] = cast_MultiT(prims)
33          if len(prims2) < 2:
34              raise ValueError(f"At least two prims needed for '{self.__class__.__name__}'")
35          self.prims = prims2
36  
37          mask = _msk.Intersect(p.mask for p in prims2)
38          super().__init__(mask=mask)
39  
40  
41  class _Alias(_DerivedPrimitive):
42      """A derived primitive giving an alias to another mask primitive.
43      This is mainly used to have aliases for rules on the mask of a given
44      MaskPrimitive.
45      """
46      def __init__(self, *, prim: _MaskPrimitive, alias: str):
47          self._prim = prim
48          super().__init__(mask=prim.mask.alias(alias))
49          self.mask: _msk._MaskAlias
50  
51  class _Outside(_DerivedPrimitive):
52      """A derived primitive representing the part of another primitive
53      """
54      def __init__(self, *, prim: _MaskPrimitive, where: Tuple[_MaskPrimitive, ...]):
55          where = cast_MultiT(where)
56          if len(where) == 0:
57              raise ValueError(
58                  "At least one layer has to be given for Outside derived mask"
59              )
60          elif len(where) == 1:
61              mask = prim.mask.remove(where[0].mask)
62          else:
63              mask = prim.mask.remove(_msk.Join(w.mask for w in where))
64          super().__init__(mask=mask)