X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=experiments7%2Futils.py;h=04f9cdea684e6051f48d7919230a4b8af616e91f;hb=53376f8c81fc606caf81913d042799fa8001db58;hp=60057f63810942bcfce160234db1c9eafe0ba5ba;hpb=81283a7462a0623cb8b5f603be5fd96117595081;p=soclayout.git diff --git a/experiments7/utils.py b/experiments7/utils.py index 60057f6..04f9cde 100644 --- a/experiments7/utils.py +++ b/experiments7/utils.py @@ -34,7 +34,8 @@ class Module(object): 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. @@ -42,7 +43,9 @@ class Module(object): :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, @@ -53,6 +56,7 @@ class Module(object): :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 @@ -80,9 +84,18 @@ class Module(object): 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): @@ -135,6 +148,28 @@ class Module(object): """ 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) @@ -190,7 +225,11 @@ class Module(object): 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 @@ -215,10 +254,14 @@ class Module(object): 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. """ @@ -278,6 +321,21 @@ class Module(object): 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. @@ -285,28 +343,47 @@ class Module(object): :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. """ @@ -317,6 +394,7 @@ class Module(object): raise NotImplementedError('You need to implement the `build` method.') + class Config: def __init__(self, priority=None):