/ pdkmaster / dispatch / primitive.py
primitive.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 Callable, Optional
  3  
  4  from ..technology import primitive as _prm
  5  from ..technology.primitive.conductors import _WaferWireIntersect, _ViaIntersect
  6  
  7  
  8  class PrimitiveDispatcher:
  9      """Dispatch to class method based on type of `_Primitive` subclasses.
 10  
 11      This dispatcher follows the common way of working in the `dispatch` module.
 12      """
 13      def __init__(self):
 14          self._parent_call: Optional[Callable] = None
 15  
 16      def __call__(self, prim: _prm.PrimitiveT, *args, **kwargs):
 17          # Reset _parent_call
 18          self._parent_call = None
 19  
 20          classname = prim.__class__.__name__.split(".")[-1]
 21          return getattr(self, classname, self._pd_unhandled)(prim, *args, **kwargs)
 22  
 23      def _pd_unhandled(self, prim, *args, **kwargs):
 24          raise RuntimeError(
 25              "Internal error: unhandled dispatcher for object of type "
 26              f"{prim.__class__.__name__}"
 27          )
 28  
 29      ### primitive._core
 30  
 31      def _Primitive(self, prim: _prm.PrimitiveT, *args, **kwargs):
 32          """Currently _PinAttribute and _BlockageAttribute are not handled by the
 33          dispatcher. It can be handled by overloading this _Primitive method and
 34          checking there oneself if the provided primitive is an instance of one
 35          of these classes.
 36          """
 37          raise NotImplementedError(
 38              f"No dispatcher implemented for object of type {prim.__class__.__name__}"
 39          )
 40  
 41      def _MaskPrimitive(self, prim: _prm.MaskPrimitiveT, *args, **kwargs):
 42          return self._Primitive(prim, *args, **kwargs)
 43  
 44      def _DesignMaskPrimitive(self,
 45          prim: _prm.DesignMaskPrimitiveT, *args, **kwargs,
 46      ):
 47          return self._MaskPrimitive(prim, *args, **kwargs)
 48  
 49      def _WidthSpacePrimitive(self, prim: _prm.WidthSpacePrimitiveT, *args, **kwargs):
 50          if isinstance(prim, _prm.DesignMaskPrimitiveT):
 51              return self._DesignMaskPrimitive(prim, *args, **kwargs)
 52          else:
 53              return self._MaskPrimitive(prim, *args, **kwargs)
 54  
 55      def _WidthSpaceDesignMaskPrimitive(self,
 56          prim: _prm.WidthSpaceDesignMaskPrimitiveT, *args, **kwargs,
 57      ):
 58          # _DesignMaskPrimitive is handled by _WidthSpacePrimitive() if needed.
 59          return self._WidthSpacePrimitive(prim, *args, **kwargs)
 60  
 61      ### primitive._derived
 62  
 63      def _DerivedPrimitive(self, prim: _prm._derived._DerivedPrimitive, *args, **kwargs):
 64          """
 65          API Notes:
 66              * No backwards compatiblity is provided for overloading this function
 67                in user land code. _DerivedPrimitive is considered for internal use only.
 68          """
 69          return self._MaskPrimitive(prim, *args, **kwargs)
 70  
 71      def _Intersect(self, prim: _prm._derived._Intersect, *args, **kwargs):
 72          """
 73          API Notes:
 74              * No backwards compatiblity is provided for overloading this function
 75                in user land code. _Intersect is considered for internal use only.
 76          """
 77          return self._DerivedPrimitive(prim, *args, **kwargs)
 78  
 79      def _Outside(self, prim: _prm._derived._Outside, * args, **kwargs):
 80          """
 81          API Notes:
 82              * No backwards compatiblity is provided for overloading this function
 83                in user land code. _Outside is considered for internal use only.
 84          """
 85          return self._DerivedPrimitive(prim, *args, **kwargs)
 86  
 87      ### primitive.layers
 88  
 89      def Base(self, prim: _prm.Base, *args, **kwargs):
 90          return self._MaskPrimitive(prim, *args, **kwargs)
 91  
 92      def Marker(self, prim: _prm.Marker, *args, **kwargs):
 93          return self._DesignMaskPrimitive(prim, *args, **kwargs)
 94  
 95      def SubstrateMarker(self, prim: _prm.Marker, *args, **kwargs):
 96          return self.Marker(prim, *args, **kwargs)
 97  
 98      def Auxiliary(self, prim: _prm.Auxiliary, *args, **kwargs):
 99          return self._DesignMaskPrimitive(prim, *args, **kwargs)
100  
101      def ExtraProcess(self, prim: _prm.ExtraProcess, *args, **kwargs):
102          return self._WidthSpaceDesignMaskPrimitive(prim, *args, **kwargs)
103  
104      def Insulator(self, prim: _prm.Insulator, *args, **kwargs):
105          return self._WidthSpaceDesignMaskPrimitive(prim, *args, **kwargs)
106  
107      def Implant(self, prim: _prm.Implant, *args, **kwargs):
108          if self._parent_call is None:
109              call = self._WidthSpaceDesignMaskPrimitive
110          else:
111              call = self._parent_call
112              self._parent_call = None
113          return call(prim, *args, **kwargs)
114  
115      ### primitive.conductors
116  
117      def _Conductor(self,
118          prim: _prm.ConductorT, *args, **kwargs,
119      ):
120          if isinstance(prim, _prm.WidthSpacePrimitiveT):
121              return self._WidthSpacePrimitive(prim, *args, **kwargs)
122          else:
123              return self._DesignMaskPrimitive(prim, *args, **kwargs)
124  
125      def _WidthSpaceConductor(self,
126          prim: _prm.WidthSpaceConductorT, *args, **kwargs,
127      ):
128          return self._Conductor(prim, *args, **kwargs)
129  
130      def Well(self, prim: _prm.Well, *args, **kwargs):
131          self._parent_call = self._WidthSpaceConductor
132          return self.Implant(prim=prim, *args, **kwargs)
133  
134      def DeepWell(self, prim: _prm.DeepWell, *args, **kwargs):
135          self._parent_call = self._WidthSpaceConductor
136          return self.Implant(prim=prim, *args, **kwargs)
137  
138      def WaferWire(self, prim: _prm.WaferWire, *args, **kwargs):
139          return self._WidthSpaceConductor(prim, *args, **kwargs)
140  
141      def _WaferWireIntersect(self, prim: _WaferWireIntersect, *args, **kwargs):
142          return self._Intersect(prim, *args, **kwargs)
143  
144      def GateWire(self, prim: _prm.GateWire, *args, **kwargs):
145          return self._WidthSpaceConductor(prim, *args, **kwargs)
146  
147      def MetalWire(self, prim: _prm.MetalWire, *args, **kwargs):
148          return self._WidthSpaceConductor(prim, *args, **kwargs)
149  
150      def MIMTop(self, prim: _prm.MIMTop, *args, **kwargs):
151          return self.MetalWire(prim, *args, **kwargs)
152  
153      def TopMetalWire(self, prim: _prm.TopMetalWire, *args, **kwargs):
154          return self.MetalWire(prim, *args, **kwargs)
155  
156      def Via(self, prim, *args: _prm.Via, **kwargs):
157          return self._Conductor(prim, *args, **kwargs)
158  
159      def _ViaIntersect(self, prim: _ViaIntersect, *args, **kwargs):
160          return self._Intersect(prim, *args, **kwargs)
161  
162      def PadOpening(self, prim: _prm.PadOpening, *args, **kwargs):
163          return self._WidthSpaceConductor(prim, *args, **kwargs)
164  
165      ### primitive.devices
166  
167      def _DevicePrimitive(self, prim: _prm.DevicePrimitiveT, *args, **kwargs):
168          if isinstance(prim, _prm.MaskPrimitiveT):
169              return self._MaskPrimitive(prim=prim, *args, **kwargs)
170          else:
171              return self._Primitive(prim=prim, *args, **kwargs)
172  
173      def Resistor(self, prim: _prm.Resistor, *args, **kwargs):
174          return self._DevicePrimitive(prim, *args, **kwargs)
175  
176      def _Capacitor(self, prim: _prm.CapacitorT, *args, **kwargs):
177          return self._DevicePrimitive(prim, *args, **kwargs)
178  
179      def MIMCapacitor(self, prim: _prm.MIMCapacitor, *args, **kwargs):
180          return self._Capacitor(prim, *args, **kwargs)
181  
182      def Diode(self, prim: _prm.Diode, *args, **kwargs):
183          return self._DevicePrimitive(prim, *args, **kwargs)
184  
185      def MOSFETGate(self, prim: _prm.MOSFETGate, *args, **kwargs):
186          return self._WidthSpacePrimitive(prim, *args, **kwargs)
187  
188      def MOSFET(self, prim: _prm.MOSFET, *args, **kwargs):
189          return self._DevicePrimitive(prim, *args, **kwargs)
190  
191      def Bipolar(self, prim: _prm.Bipolar, *args, **kwargs):
192          return self._DevicePrimitive(prim, *args, **kwargs)
193  
194      ### primitive.rules
195  
196      def _RulePrimitive(self, prim: _prm.RulePrimitiveT, *args, **kwargs):
197          return self._Primitive(prim, *args, **kwargs)
198  
199      def MinWidth(self, prim: _prm.MinWidth, *args, **kwargs):
200          return self._RulePrimitive(prim, *args, **kwargs)
201  
202      def Spacing(self, prim: _prm.Spacing, *args, **kwargs):
203          return self._RulePrimitive(prim, *args, **kwargs)
204  
205      def Enclosure(self, prim: _prm.Enclosure, *args, **kwargs):
206          return self._RulePrimitive(prim, *args, **kwargs)
207  
208      def NoOverlap(self, prim: _prm.NoOverlap, *args, **kwargs):
209          return self._RulePrimitive(prim, *args, **kwargs)