Recover from awkward merge.
authorJock Tanner <tanner.of.kha@gmail.com>
Thu, 26 Mar 2020 07:24:47 +0000 (07:24 +0000)
committerJock Tanner <tanner.of.kha@gmail.com>
Thu, 26 Mar 2020 07:24:47 +0000 (07:24 +0000)
experiments7/doAlu16.py

index 7f9971ed52070b60bb958955ae5d341e75f9a192..9da6180d9ca87cc99be2b352435a92bb88b61f8c 100755 (executable)
 from __future__ import print_function
 import sys
 
-import Anabatic
 import CRL
 import Cfg
-import Etesian
-import Katana
-from Hurricane import (
-    DbU, DataBase, UpdateSession, Box, Transformation, Instance,  Pin,
-    NetExternalComponents,
-)
-from helpers import l
+from Hurricane import Box
 from plugins import RSavePlugin
 from coriolis2.settings import af
-from utils import Module
+from utils import Module, SessionManager
 
 import symbolic.cmos  # do not remove
 
 BIT_WIDTH = 16
 
 
-def get_layer(name, layer_cache={}):
-    """ Creates a new layer or returns it from cache. """
-    if name in layer_cache:
-        return layer_cache[name]
-
-    layer = DataBase.getDB().getTechnology().getLayer(name)
-    layer_cache[name] = layer
-    return layer
-
-
-def to_DbU(l):
-    """
-    Convert lambdas to database units. (See Hurricane+Python Manual 3.4.)
-    """
-    return DbU.fromLambda(l)
-
-
-def from_DbU(ph):
-    """
-    Convert database units to lambdas. (See Hurricane+Python Manual 3.4.)
-    """
-    return DbU.toLambda(ph)
-
-
-def create_pins(cell, net, name, direction,
-                status=Pin.PlacementStatus.FIXED, layer=None,
-                x=0.0, y=0.0, width=2.0, height=2.0,
-                repeat=1, delta=0.0, external=True):
-    """Creates a series of pins in a cell.
-
-    :param cell: Hurricane.Cell object to place pins onto, or object name,
-    :param net: Hurricane.Net object name or name template, taking a pin
-      enumeration parameter, i. e. pin number,
-    :param name: pin name or name template taking a pin enumeration parameter,
-    :param direction: Pin.Direction value,
-    :param status: Pin.PlacementStatus value (default is FIXED),
-    :param layer: Hurricane.Layer object or name (METAL3),
-    :param x: starting pin position (left to right, 0.0),
-    :param y: starting pin position (bottom to top, 0.0),
-    :param width: pin width (2,0),
-    :param height: pin height (2.0),
-    :param repeat: a number of pins to be placed or an iterable containing
-      pin template parameters (i. e. pin number, 1),
-    :param delta: next pin position offset (0.0),
-    :param external: mark pin as external (yes),
-    :return: tuple of next pin coordinates, or just (x, y), if delta was not
-      provided.
-    """
-    if isinstance(cell, basestring):
-        cell = af.getCell(cell, CRL.Catalog.State.Logical)
-
-    if layer is None:
-        layer = 'METAL3'
-    if isinstance(layer, basestring):
-        layer = get_layer(layer)
-
-    if isinstance(repeat, int):
-        if repeat > 1 and delta == 0.0:
-            raise Warning('You are trying to place pins on each other.')
-        iterator = range(repeat)
-    else:
-        iterator = repeat
-
-    for i in iterator:
-        pin = Pin.create(cell.getNet(net.format(i)), name.format(i),
-                         direction, status, layer,
-                         l(x), l(y), l(width), l(height))
-        if direction in (Pin.Direction.NORTH, Pin.Direction.SOUTH):
-            x += delta
-        else:
-            # EAST or WEST
-            y += delta
-
-        if external:
-            pin.getNet().setExternal(True)
-            NetExternalComponents.setExternal(pin)
-
-    return x, y
-
-
-def place_and_route(cell):
-    """
-    Places and routes.
-
-    :param cell: Hurricane.Cell object to operate on,
-    :return: True on success, False otherwise.
-    """
-    etesian = Etesian.EtesianEngine.create(cell)
-    etesian.place()
-
-    katana = Katana.KatanaEngine.create(cell)
-    katana.digitalInit()
-    katana.runGlobalRouter(Katana.Flags.NoFlags)
-    katana.loadGlobalRouting(Anabatic.EngineLoadGrByNet)
-    katana.layerAssign(Anabatic.EngineNoNetLayerAssign)
-    katana.runNegociate(Katana.Flags.NoFlags)
-    katana.finalizeLayout()
-    success = katana.isDetailedRoutingSuccess()
-    katana.destroy()
-
-    return success
-
-
 def coriolis_setup():
     Cfg.Configuration.pushDefaultPriority(Cfg.Parameter.Priority.UserFile)
-
-    env = af.getEnvironment()
-
     Cfg.getParamBool('misc.catchCore').setBool(False)
     Cfg.getParamBool('misc.info').setBool(False)
     Cfg.getParamBool('misc.paranoid').setBool(False)
@@ -157,83 +44,73 @@ def coriolis_setup():
     Cfg.Configuration.popDefaultPriority()
 
 
-def alu16(editor=None, **kwargs):
+class AddSub(Module):
+
+    def do(self):
+        """ Main routine. """
+
+        with SessionManager():
+            self.init_abutment_box()
+            self.create_pins()
 
-    db = DataBase.getDB()
-    print(db, dir(db))
-    METAL2 = get_layer('METAL2')
+        if self.editor:
+            self.editor.setCell(self.cell)
 
-    cell = af.getCell('alu16', CRL.Catalog.State.Logical)
-    if not cell:
-        print('[ERROR] Unable to load cell "alu16.vst", aborting .')
-        return False
+        result = self.place_and_route()
 
-    width, height = 1100.0, 600.0
-    ab = Box(l(0.0), l(0.0), l(width), l(height))
+        with SessionManager():
+            self.create_pads()
 
-    UpdateSession.open()
-    cell.setAbutmentBox(ab)
+        RSavePlugin.ScriptMain(editor=self.editor, cell=self.cell)
+        return result
 
-    # get instances inside cell
-    instances = cell.getInstances()
 
-    # find adder instance
-    add_inst = [x for x in instances if x.getName().endswith('add')][0]
-    add_inst.setTransformation(Transformation(to_DbU(25.0), to_DbU(75.0),
-                               Transformation.Orientation.ID))
-    add_inst.setPlacementStatus(Instance.PlacementStatus.FIXED)
+class ALU16(Module):
 
-    # find subtractor instance
-    sub_inst = [x for x in instances if x.getName().endswith('sub')][0]
-    sub_inst.setTransformation(Transformation(to_DbU(725.0), to_DbU(75.0),
-                               Transformation.Orientation.ID))
-    sub_inst.setPlacementStatus(Instance.PlacementStatus.FIXED)
+    def do(self):
 
-    y_north = cell.getAbutmentBox().getYMax()
-    create_pins(cell, 'a({})', 'a({}).0', Pin.Direction.SOUTH,
-                x=50.0, y=0.0, delta=60.0, repeat=BIT_WIDTH)
-    create_pins(cell, 'b({})', 'b({}).0', Pin.Direction.SOUTH,
-                x=80.0, y=0.0, delta=60.0, repeat=BIT_WIDTH)
-    create_pins(cell, 'o({})', 'o({}).0', Pin.Direction.NORTH,
-                x=50.0, y=from_DbU(y_north),
-                delta=60.0, repeat=BIT_WIDTH)
-    create_pins(cell, 'rst', 'rst.0', Pin.Direction.WEST, layer=METAL2,
-                x=0.0, y=140.0)
-    UpdateSession.close()
+        if not self.do_submodules():
+            return False
 
-    if editor:
-        editor.setCell(cell)
+        with SessionManager():
+            self.init_abutment_box()
+            self.place_submodules()
 
-    print("editor", editor, dir(editor))
+            # TODO: replace with some form of lazy evaluation?
+            y_north = self.from_dbu(self.cell.getAbutmentBox().getYMax())
+            for pin_conf in self.north_pins:
+                pin_conf['y'] = y_north
 
-    # place first (in middle, between two)
-    # this puts all the remaining cells (little ones)
-    # into this (small) space so that they do not go
-    # "all over the place" around the add and sub
-    ab2 = Box(l(400.0), l(50.0), l(700.0), l(500.0))
+            self.create_pins()
 
-    cell.setAbutmentBox(ab2)
-    etesian = Etesian.EtesianEngine.create(cell)
-    etesian.place()
+        if self.editor:
+            self.editor.setCell(self.cell)
 
-    # then route (globally)
-    # this connects up not just in the remaining (little) cells,
-    # it connects *to add and sub and the outside world as well*
-    cell.setAbutmentBox(ab)
+        # place first (in middle, between two)
+        # this puts all the remaining cells (little ones)
+        # into this (small) space so that they do not go
+        # "all over the place" around the add and sub
+        self.ab = Box(self.to_dbu(400.0), self.to_dbu(50.0),
+                      self.to_dbu(700.0), self.to_dbu(500.0))
+        self.place()
 
-    result = place_and_route(cell)
+        # then route (globally)
+        # this connects up not just in the remaining (little) cells,
+        # it connects *to add and sub and the outside world as well*
+        self.init_abutment_box()
+        result = self.place_and_route()
 
-    cell.setName(cell.getName()+'_r')
-    af.saveCell(cell, CRL.Catalog.State.Views)
-    RSavePlugin.ScriptMain(editor=editor, cell=cell, **kwargs)
+        self.name = self.name + '_r'
+        self.af.saveCell(self.cell, CRL.Catalog.State.Views)
+        RSavePlugin.ScriptMain(editor=self.editor, cell=self.cell)
 
-    return result
+        return result
 
 
 def ScriptMain(editor=None, **kwargs):
     coriolis_setup()
 
-    add = Module(
+    add = AddSub(
         'add', editor, width=350.0, height=400.0,
         north_pins=[
             {'net': 'a({})', 'x': 10.0, 'delta': 20.0, 'repeat': BIT_WIDTH},
@@ -242,10 +119,13 @@ def ScriptMain(editor=None, **kwargs):
         south_pins=[
             {'net': 'o({})', 'x': 100.0, 'delta': 10.0, 'repeat': BIT_WIDTH},
         ],
-        pads={'b(15)': ('BLOCKAGE2', 'BLOCKAGE3', 'BLOCKAGE4')},
+        pads={
+            'b({})'.format(BIT_WIDTH-1): (
+                'BLOCKAGE2', 'BLOCKAGE3', 'BLOCKAGE4',
+            ),
+        },
     )
-
-    sub = Module(
+    sub = AddSub(
         'sub', editor, width=350.0, height=400.0,
         north_pins=[
             {'net': 'a({})', 'x': 10.0, 'delta': 20.0, 'repeat': BIT_WIDTH},
@@ -254,12 +134,29 @@ def ScriptMain(editor=None, **kwargs):
         south_pins=[
             {'net': 'o({})', 'x': 100.0, 'delta': 10.0, 'repeat': BIT_WIDTH},
         ],
-        pads={'b(15)': ('BLOCKAGE2', 'BLOCKAGE3', 'BLOCKAGE4')},
+        pads={
+            'b({})'.format(BIT_WIDTH-1): (
+                'BLOCKAGE2', 'BLOCKAGE3', 'BLOCKAGE4',
+            ),
+        },
     )
 
-    add.do()
-    sub.do()
-    return alu16(editor, **kwargs)
+    alu16 = ALU16(
+        'alu16', editor, width=1100.0, height=600.0,
+        submodules=[(add, 25.0, 75.0), (sub, 725.0, 75.0)],
+        north_pins=[
+            {'net': 'o({})', 'x': 50.0, 'delta': 60.0, 'repeat': BIT_WIDTH},
+            {'net': 'op'},
+        ],
+        south_pins=[
+            {'net': 'a({})', 'x': 50.0, 'delta': 60.0, 'repeat': BIT_WIDTH},
+            {'net': 'b({})', 'x': 80.0, 'delta': 60.0, 'repeat': BIT_WIDTH},
+        ],
+        west_pins=[
+            {'net': 'rst', 'y': 140.0, 'layer': 'METAL2'},
+        ],
+    )
+    return alu16.do()
 
 
 if __name__ == '__main__':