Enable the heavy leaf load on the main clock.
[soclayout.git] / experiments7 / doAlu16.py
index 954a311b8ac32a521c76586c8ff6dced3e3fe217..1b8248fe3c877c75b59cf23a6edee2481897af6d 100755 (executable)
@@ -7,13 +7,18 @@ import CRL
 import Cfg
 from Hurricane import Box
 from Hurricane import Transformation
+from Hurricane import Breakpoint
+from Hurricane import Instance
 from coriolis2.settings import af
 from utils import Module, SessionManager, Config
+import Etesian
+import helpers
+from helpers.overlay import UpdateSession
 
 import symbolic.cmos  # do not remove
 
 BIT_WIDTH = 16
-
+widths = {32: 600.0, 16: 490}
 
 def coriolis_setup():
     with Config(Cfg.Parameter.Priority.UserFile) as cfg:
@@ -25,7 +30,7 @@ def coriolis_setup():
         cfg.misc_verboseLevel1 = True
         cfg.misc_verboseLevel2 = True
         cfg.etesian_effort = 2
-        cfg.etesian_spaceMargin = "20.0%"
+        cfg.etesian_spaceMargin = "10.0%"
         cfg.etesian_aspectRatio = "100.0%"
         cfg.etesian_uniformDensity = True
         cfg.anabatic_edgeLenght = 24
@@ -48,7 +53,7 @@ class AddSub(Module):
         """ Main routine. """
 
         with SessionManager():
-            self.compute_ab()
+           #self.compute_ab()
             self.create_pins()
 
         if self.editor:
@@ -65,6 +70,93 @@ class AddSub(Module):
 
 class ALU16(Module):
 
+    def place_datapath(self, datapath_insts, x_orig, y_orig, fold):
+        channel_sff1 = self.to_dbu(0)
+        with SessionManager():
+            slice_height = self.to_dbu(50.0)
+            for i in range(len(datapath_insts)):
+                if not i%fold:
+                    x = self.to_dbu(x_orig)
+                slice = i/fold
+                if slice%2:
+                    y = self.to_dbu(y_orig) + slice_height*(slice+1)
+                    orient = Transformation.Orientation.MY
+                else:
+                    y = self.to_dbu(y_orig) + slice_height*slice
+                    orient = Transformation.Orientation.ID
+
+                for (opname, inst) in datapath_insts[i]:
+                    if opname == 'sff1':
+                        x += channel_sff1
+                    inst.setTransformation(Transformation(x, y, orient))
+                    inst.setPlacementStatus(Instance.PlacementStatus.PLACED)
+                    x += inst.getAbutmentBox().getWidth()
+
+    def place(self):
+        """ALU16.place(), manual placement overload."""
+        datapath_insts = []
+        add, sub = self.submodules
+        #print (sub.ab, dir(list(sub.cell.getInstances())[0]))
+        #print (list(sub.cell.getInstances())[0].getAbutmentBox())
+        subx = widths[BIT_WIDTH] - 40 #self.from_dbu(sub.ab.getXMax())
+        addx = self.from_dbu(add.ab.getWidth()) + 5
+
+        for i in range(BIT_WIDTH):
+            dp = [['nmx2', None],
+                  ['no2', None],
+                  ['sff1', None]]
+
+            # XXX here is the computed abutment box which we want to
+            # place the auto-located cells into, using *auto* place
+            # *not* manual place.
+            y = 40.0 + i * 50
+            y1 = y + 50
+            ab = Box(self.to_dbu(addx), self.to_dbu(y),
+                     self.to_dbu(subx), self.to_dbu(y1))
+            print ("ab", addx, subx, ab, self.from_dbu(ab.getWidth()),
+                                         self.from_dbu(ab.getHeight()))
+
+            # automatically locate all non-placed cells connected to
+            # o(0)....o(15)
+            find = self.get_net_connections(['o(%d)' % i],
+                                        ['clk', 'rst', 'op'])
+            for inst in find:
+                print (inst, inst.getName(), dir(inst))
+                print ("place", ab, inst, dir(inst))
+                for column in dp:
+                    if inst.getName().find(column[0]) != -1:
+                        column[1] = inst
+                # XXX TODO: want to auto-place the instances
+                #with SessionManager():
+                    #cell.setAbutmentBox(ab)
+                    #etesian = Etesian.EtesianEngine.create(cell)
+                    #etesian.place()
+            datapath_insts.append(dp)
+
+        # place to right of add
+        add, sub = self.submodules
+        add_wid = self.from_dbu(add.ab.getWidth())
+        self.place_datapath(datapath_insts, add_wid, 40.0, 1)
+
+    def _old_place(self):
+        """ALU16.place(), manual placement overload."""
+        datapath_insts = []
+        for i in range(BIT_WIDTH):
+            datapath_insts.append([['nmx2', None],
+                                   ['no2', None],
+                                   ['sff1', None]])
+
+        for inst in self.cell.getInstances():
+            if (Module.match_instance(datapath_insts, 'nmx2', 'i0', inst) or
+                Module.match_instance(datapath_insts, 'no2', 'nq', inst) or
+                Module.match_instance(datapath_insts, 'sff1', 'i', inst)):
+                continue
+
+        # place to right of add
+        add, sub = self.submodules
+        add_wid = self.from_dbu(add.ab.getWidth())
+        self.place_datapath(datapath_insts, add_wid, 40.0, 1)
+
     def save(self):
         self.name = self.name + '_r'
         self.af.saveCell(self.cell, CRL.Catalog.State.Views)
@@ -72,8 +164,8 @@ class ALU16(Module):
 
     def build(self):
 
-        h_margin = 25.0
-        v_margin = 75.0
+        h_margin = 0.0
+        v_margin = 40.0
 
         if not self.build_submodules():
             return False
@@ -91,11 +183,21 @@ class ALU16(Module):
             ) + 4*h_margin
             height = self.from_dbu(max([
                 self.ab.getHeight(), add.ab.getHeight(), sub.ab.getHeight()
-            ])) + 2*v_margin
+            ])) + v_margin
+
+            # experiment, over-ride
+            width = widths[BIT_WIDTH]
+            #width = 1310
+            #height = 370
+
             self.ab = Box(0, 0, self.to_dbu(width), self.to_dbu(height))
 
-            self.place_submodule(add, h_margin, v_margin)
-            self.place_submodule(sub, width-sub.ab_width-h_margin, v_margin)
+            add_wid = self.from_dbu(add.ab.getWidth())
+            sub_ht = self.from_dbu(sub.ab.getHeight())
+            sub_wid = self.from_dbu(sub.ab.getWidth())
+
+            self.place_submodule(add, 0, v_margin)
+            self.place_submodule(sub, width-sub_wid, v_margin)
 
             # TODO: replace with some form of lazy evaluation?
             y_north = self.from_dbu(self.ab.getYMax())
@@ -104,6 +206,15 @@ class ALU16(Module):
 
             self.create_pins()
 
+        if False:
+            find = self.get_net_connections(['o(15)'],
+                                            ['clk', 'rst', 'op'])
+            print (find)
+            sys.exit(0)
+            find = self.get_net_connections(['o_next(0)'],
+                                            ['clk', 'vss', 'vdd', 'rst'])
+            print (find)
+
         if self.editor:
             self.editor.setCell(self.cell)
 
@@ -111,35 +222,41 @@ class ALU16(Module):
         # 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((width-self.ab_width)/2 - h_margin),
-            self.to_dbu(v_margin),
-            self.to_dbu((width+self.ab_width)/2 + h_margin),
-            self.to_dbu(height - v_margin)
-        )
-        self.place()
+
+        # XXX this doesn't work: box is far too big, covers the entire
+        # area (including "under" the add and sub)
+        #self.ab = Box(
+        #    self.to_dbu((width-self.ab_width)/2 - h_margin),
+        #    self.to_dbu(v_margin),
+        #    self.to_dbu((width+self.ab_width)/2 + h_margin),
+        #    self.to_dbu(height - v_margin)
+        #)
+        #self.ab = Box(self.to_dbu(475), self.to_dbu(10),
+        #              self.to_dbu(840), self.to_dbu(360))
+        self.ab = Box(0, 0, self.to_dbu(width), self.to_dbu(height))
+        self.place() # place only
 
         # 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.ab = Box(0, 0, self.to_dbu(width), self.to_dbu(height))
-        result = self.place_and_route()
+        result = self.route()
 
         self.save()
         return result
 
 
-def ScriptMain(editor=None, **kwargs):
+def scriptMain(editor=None, **kwargs):
     coriolis_setup()
 
     add = AddSub(
         'add', editor,
-        north_pins=[
-            {'net': 'a({})', 'x': 10.0, 'delta': 10.0, 'repeat': BIT_WIDTH},
-            {'net': 'b({})', 'x': 15.0, 'delta': 10.0, 'repeat': BIT_WIDTH},
-            {'net': 'o({})', 'x': 180.0, 'delta': 10.0, 'repeat': BIT_WIDTH},
-        ],
-        south_pins=[
+        east_pins=[
+            {'net': 'a({})', 'y': 15.0, 'delta': 50.0,
+                    'repeat': BIT_WIDTH, 'layer': 'METAL2'},
+            {'net': 'b({})', 'y': 20.0, 'delta': 50.0,
+                    'repeat': BIT_WIDTH, 'layer': 'METAL2'},
+            {'net': 'o({})', 'y': 25.0, 'delta': 50.0,
+                    'repeat': BIT_WIDTH, 'layer': 'METAL2'},
         ],
         pads={
             'b({})'.format(BIT_WIDTH-1): (
@@ -148,35 +265,39 @@ def ScriptMain(editor=None, **kwargs):
         },
         orientation=Transformation.Orientation.ID,
     )
+    add.set_ab(160.0, 50.0 * BIT_WIDTH)
     sub = AddSub(
         'sub', editor,
-        north_pins=[
-            {'net': 'a({})', 'x': 180.0, 'delta': 10.0, 'repeat': BIT_WIDTH},
-            {'net': 'b({})', 'x': 185.0, 'delta': 10.0, 'repeat': BIT_WIDTH},
-            {'net': 'o({})', 'x': 10.0, 'delta': 10.0, 'repeat': BIT_WIDTH},
-        ],
-        south_pins=[
+        west_pins=[
+            {'net': 'a({})', 'y': 15.0, 'delta': 50.0,
+                    'repeat': BIT_WIDTH, 'layer': 'METAL2'},
+            {'net': 'b({})', 'y': 20.0, 'delta': 50.0,
+                    'repeat': BIT_WIDTH, 'layer': 'METAL2'},
+            {'net': 'o({})', 'y': 25.0, 'delta': 50.0,
+                    'repeat': BIT_WIDTH, 'layer': 'METAL2'},
         ],
         pads={
             'b({})'.format(BIT_WIDTH-1): (
                 'BLOCKAGE2', 'BLOCKAGE3', 'BLOCKAGE4',
             ),
         },
-        orientation=Transformation.Orientation.XR,
+        orientation=Transformation.Orientation.ID,
     )
+    sub.set_ab(165.0, 50.0 * BIT_WIDTH)
 
+    o = 00.0
     alu16 = ALU16(
         'alu16', editor, submodules=[add, sub],
         north_pins=[
-            {'net': 'o({})', 'x': 50.0, 'delta': 60.0, 'repeat': BIT_WIDTH},
+            {'net': 'o({})', 'x': 245.0+o, 'delta': 5.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},
+            {'net': 'a({})', 'x': 195.0+o, 'delta': 10.0, 'repeat': BIT_WIDTH},
+            {'net': 'b({})', 'x': 200.0+o, 'delta': 10.0, 'repeat': BIT_WIDTH},
         ],
-        west_pins=[
-            {'net': 'rst', 'y': 140.0, 'layer': 'METAL2'},
+        east_pins=[
+            {'net': 'rst', 'y': 10.0, 'layer': 'METAL2'},
         ],
     )
     return alu16.build()
@@ -184,7 +305,7 @@ def ScriptMain(editor=None, **kwargs):
 
 if __name__ == '__main__':
     kwargs = {}
-    success = ScriptMain(**kwargs)
+    success = scriptMain(**kwargs)
     shellSuccess = 0
     if not success:
         shellSuccess = 1