def __init__(self, cell, editor, width=None, height=None, submodules=None,
pin_width=2.0, pin_height=2.0, pin_suffix='.0',
pin_layer=None, north_pins=None, east_pins=None,
- south_pins=None, west_pins=None, pads=None, **kwargs):
+ south_pins=None, west_pins=None, pads=None,
+ orientation=None, **kwargs):
"""
Creates a module.
:param editor: editor object when executing from cgt (or None),
:param width: module width,
:param height: module height,
- :param submodules: submodules (Module objects),
+ :param submodules: submodules (Module objects)
+ or tuples of (submodule, x, y), where (x, y) is a submodule's
+ placement point in lambdas,
:param pin_width: default pin width,
:param pin_height: default pin height,
:param pin_suffix: default pin suffix,
:param south_pins: ditto (for the south side),
:param west_pins: ditto (for the west side),
:param pads: dictionary of {net: list of layers} for creating pads,
+ :param orientation: when placed, should be orientated/mirrored etc.
:param kwargs: extra parameters to be implemented in derived classes.
"""
self.editor = editor
self.south_pins = south_pins or []
self.west_pins = west_pins or []
+ self.orientation = orientation or Transformation.Orientation.ID
+
self.pads = pads or {}
- self.submodules = submodules or []
+ self._submodules = []
+ if submodules is not None:
+ for submodule in submodules:
+ self._submodules.append(
+ (submodule, None, None) if isinstance(submodule, Module)
+ else submodule
+ )
+
@property
def name(self):
"""
return DbU.toLambda(dbu)
+ @property
+ def ab_x(self):
+ return self.from_dbu(self.ab.getXMin())
+
+ @property
+ def ab_y(self):
+ return self.from_dbu(self.ab.getYMin())
+
+ @property
+ def ab_width(self):
+ return self.from_dbu(self.ab.getWidth())
+
+ @property
+ def ab_height(self):
+ return self.from_dbu(self.ab.getXHeight())
+
+ def compute_ab(self):
+ """ Compute default abutment box without placement. """
+ etesian = Etesian.EtesianEngine.create(self.cell)
+ etesian.setDefaultAb()
+ etesian.destroy()
+
def place(self):
""" Places the current cell. """
etesian = Etesian.EtesianEngine.create(self.cell)
if isinstance(repeat, int):
if repeat > 1 and delta == 0.0:
- raise Warning('You are trying to place pins on each other.')
+ raise Warning(
+ '{}: you are trying to place pins on each other.'.format(
+ self.name
+ )
+ )
iterator = range(repeat)
else:
iterator = repeat
return x, y
- def init_abutment_box(self):
+ def init_ab(self):
""" Create the abutment box with object's initial values. """
-
- self.ab = Box(0, 0, self.to_dbu(self.width), self.to_dbu(self.height))
+ if self.width and self.height:
+ self.ab = Box(
+ 0, 0, self.to_dbu(self.width), self.to_dbu(self.height)
+ )
+ else:
+ raise Warning('{}: Module size is not set.'.format(self.name))
def create_pins(self):
""" Creates all pins set on Module object creation. """
for net, layers in self.pads.items():
self.create_pads_for_net(net, layers)
+ @property
+ def submodules(self):
+ """ Submodules iterator. """
+ return iter(submodule for submodule, x, y in self._submodules)
+
+ def find_submodule(self, name):
+ """
+ Returns first submodule matching `name`. Better give your submodules
+ unique names.
+
+ :param name: submodule name to match,
+ :return: `Module` object.
+ """
+ return next(s for s in self.submodules if s.name == name)
+
def build_submodules(self):
"""
Execute submodules and gather their status.
:return: True if all submodules executed successfully, False otherwise.
"""
- for submodule, x, y in self.submodules:
+ for submodule in self.submodules:
if not submodule.build():
return False
return True
- def place_submodules(self):
- """ Place submodules in the current module. """
+ def place_submodule(self, submodule, x, y):
+ """
+ Places a submodule to a given location.
- for submodule, x, y in self.submodules:
- # find instance
- instance = [
- inst for inst in self.instances if inst.getName().endswith(
- submodule.name
- )
- ][0]
+ :param submodule: `Module` object,
+ :param x: placement coordinate,
+ :param y: placement coordinate.
+ """
+
+ # find instance
+ instance = [
+ inst for inst in self.instances if inst.getName().endswith(
+ submodule.name
+ )
+ ][0]
- # place submodule
- instance.setTransformation(Transformation(
- self.to_dbu(x), self.to_dbu(y), Transformation.Orientation.ID
- ))
- instance.setPlacementStatus(Instance.PlacementStatus.FIXED)
+ # place submodule
+ instance.setTransformation(Transformation(
+ self.to_dbu(x), self.to_dbu(y), submodule.orientation,
+ ))
+ instance.setPlacementStatus(Instance.PlacementStatus.FIXED)
+
+ def place_submodules(self):
+ """
+ Places the submodules in the current module using their initial
+ placement points, if set.
+ """
+ for submodule, x, y in self._submodules:
+ if x is not None and y is not None:
+ self.place_submodule(submodule, x, y)
+ else:
+ raise Warning((
+ '{}: cannot place {}, because its '
+ 'initial placement point is not set.'
+ ).format(self.name, submodule.name))
def save(self):
""" Saves cell. """
raise NotImplementedError('You need to implement the `build` method.')
+
class Config:
def __init__(self, priority=None):