First working version of the Flexlib + P&R flow for the ls180+SRAM.
authorJean-Paul Chaput <Jean-Paul.Chaput@lip6.fr>
Tue, 9 Mar 2021 10:01:04 +0000 (11:01 +0100)
committerJean-Paul Chaput <Jean-Paul.Chaput@lip6.fr>
Tue, 9 Mar 2021 10:01:04 +0000 (11:01 +0100)
Note: It is working in the sense that the flow complete, but is stills
      contains various errors that needs fixing.
        We discoupled from pinmux as core2chip have problems associating
      the pad instances names with the relevant core signals.
        We guessed a pad placement from pinmux, but it seems a bit odd
      to me...

experiments9/tsmc_c018/coriolis2/settings.py
experiments9/tsmc_c018/doDesign.py

index 5c1ea662331aa1ed2a50a484ac21f7a9456fd229..1142e7a8c16c37b9cb223c2c8832b00c178aab53 100644 (file)
@@ -1,79 +1,45 @@
 # -*- Mode:Python -*-
 
-import Cfg
-import CRL
-import Viewer
-from   helpers.overlay import CfgCache
-import symbolic.cmos45  # do not remove
 import os
+import socket
+import helpers
+
+NdaDirectory = None
+if os.environ.has_key('NDA_TOP'):
+    NdaDirectory = os.environ['NDA_TOP']
+if not NdaDirectory:
+    hostname = socket.gethostname()
+    if hostname.startswith('lepka'):
+        NdaDirectory = '/dsk/l1/jpc/crypted/soc/techno'
+        if not os.path.isdir(NdaDirectory):
+            print '[ERROR] You forgot to mount the NDA encrypted directory, stupid!'
+    else:
+        NdaDirectory = '/users/soft/techno/techno'
+helpers.setNdaTopDir( NdaDirectory )
 
-if os.environ.has_key('CELLS_TOP'):
-    cellsTop = os.environ['CELLS_TOP']
-else:
-    cellsTop = '../../../alliance-check-toolkit/cells'
-
-with CfgCache('', priority=Cfg.Parameter.Priority.UserFile) as cfg:
-    cfg.misc.catchCore               = False
-    cfg.misc.info                    = False
-    cfg.misc.paranoid                = False
-    cfg.misc.bug                     = False
-    cfg.misc.logMode                 = True
-    cfg.misc.verboseLevel1           = True
-    cfg.misc.verboseLevel2           = True
-    cfg.anabatic.edgeLenght          = 24
-    cfg.anabatic.edgeWidth           = 8
-    cfg.anabatic.topRoutingLayer     = 'METAL5'
-    cfg.etesian.graphics             = 3
-
-    #cfg.katana.searchHalo           = 30
-    #cfg.katana.eventsLimit          = 1000000
-    #cfg.katana.hTracksReservedLocal = 7
-
-    # Run 2 (make-cgt-2.log)
-    #cfg.etesian.effort              = 2
-    #cfg.etesian.uniformDensity      = True
-    #cfg.etesian.spaceMargin         = 0.05
-    #cfg.etesian.aspectRatio         = 1.0
-    #cfg.katana.vTracksReservedLocal = 4
-    #cfg.katana.hTracksReservedLocal = 4
-
-    # Run 3 (make-cgt-3.log)
-    #cfg.etesian.effort              = 2
-    #cfg.etesian.uniformDensity      = False
-    #cfg.etesian.spaceMargin         = 0.05
-    #cfg.etesian.aspectRatio         = 1.0
-    #cfg.katana.vTracksReservedLocal = 5
-    #cfg.katana.hTracksReservedLocal = 5
-
-    # Run 4 (make-cgt-4.log)
-    #cfg.etesian.effort              = 2
-    #cfg.etesian.uniformDensity      = True
-    #cfg.etesian.spaceMargin         = 0.05
-    #cfg.etesian.aspectRatio         = 1.0
-
-    # Run 5 (make-cgt-5.log)
-    cfg.etesian.effort               = 2
-    cfg.etesian.uniformDensity       = True
-    cfg.etesian.spaceMargin          = 0.05
-    cfg.etesian.aspectRatio          = 1.0
-    cfg.katana.useGlobalEstimate     = False
-    cfg.katana.vTracksReservedLocal  = 7
-    cfg.katana.hTracksReservedLocal  = 6
-    cfg.katana.bloatOverloadAdd      = 4
-    cfg.conductor.stopLevel          = 0
-    cfg.conductor.maxPlaceIterations = 2
-    cfg.conductor.useFixedAbHeight   = False
-
-    env = CRL.AllianceFramework.get().getEnvironment()
+import Cfg
+from   CRL     import AllianceFramework
+from   helpers import overlay, l, u, n
+from   NDA.node180.tsmc_c018 import techno, FlexLib, LibreSOCIO, LibreSOCMem
+
+techno.setup()
+FlexLib.setup()
+LibreSOCIO.setup()
+LibreSOCMem.setup()
+
+with overlay.CfgCache(priority=Cfg.Parameter.Priority.UserFile) as cfg:
+    cfg.misc.catchCore           = False
+    cfg.misc.minTraceLevel       = 14700
+    cfg.misc.maxTraceLevel       = 14800
+    cfg.misc.info                = False
+    cfg.misc.paranoid            = False
+    cfg.misc.bug                 = False
+    cfg.misc.logMode             = True
+    cfg.misc.verboseLevel1       = True
+    cfg.misc.verboseLevel2       = True
+    cfg.etesian.graphics         = 3
+    cfg.etesian.spaceMargin      = 0.10
+    cfg.katana.eventsLimit       = 4000000
+    af  = AllianceFramework.get()
+    env = af.getEnvironment()
     env.setCLOCK( '^sys_clk$|^ck|^jtag_tck$' )
-    env.addSYSTEM_LIBRARY(library=cellsTop+'/niolib',
-                           mode=CRL.Environment.Prepend )
-    env.addSYSTEM_LIBRARY(library=cellsTop+'/nsxlib',
-                          mode=CRL.Environment.Prepend )
-    env.setPOWER ('vdd')
-    env.setGROUND('vss')
-
-Viewer.Graphics.setStyle('Alliance.Classic [black]')
-
-print( '  o  Successfully run "<>/coriolis2/settings.py".' )
-print( '     - CELLS_TOP = "{}"'.format(cellsTop) )
index 76651a70bd4004def2048684f80887af634eac2a..9321f3324c8d253deb67732dd0104e26df466f27 100644 (file)
@@ -5,32 +5,189 @@ import os
 import json
 import sys
 import traceback
+import collections
 import CRL
 import helpers
-from   helpers.io import ErrorMessage, WarningMessage
-from   helpers    import trace, l, u, n
+from   helpers         import trace, l, u, n
+from   helpers.io      import ErrorMessage, WarningMessage
+from   helpers.overlay import UpdateSession
 import plugins
-from   Hurricane  import DbU
-from   plugins.alpha.block.configuration  import IoPin, GaugeConf
+from   Hurricane  import Breakpoint, DbU, Transformation, Box, Instance
+from   plugins.alpha.macro.macro          import Macro
 from   plugins.alpha.block.iospecs        import IoSpecs
 from   plugins.alpha.block.block          import Block
+from   plugins.alpha.block.configuration  import IoPin, GaugeConf
 from   plugins.alpha.core2chip.libresocio import CoreToChip
 from   plugins.alpha.chip.configuration   import ChipConf
 from   plugins.alpha.chip.chip            import Chip
 
 
-af  = CRL.AllianceFramework.get()
+af         = CRL.AllianceFramework.get()
+powerCount = 0
+
+
+def isiterable ( pyobj ):
+    if isinstance(pyobj,collections.Iterable): return True
+    return False
+
+
+def doIoPowerCap ( flags ):
+    global powerCount
+    side = flags & IoPin.SIDE_MASK
+    if flags & IoPin.A_BEGIN:
+        ioPadPower = [ (side , None,    'power_{}'.format(powerCount),   'vdd' )
+                     , (side , None,   'ground_{}'.format(powerCount),   'vss' )
+                     , (side , None, 'ioground_{}'.format(powerCount), 'iovss' )
+                     , (side , None,  'iopower_{}'.format(powerCount), 'iovdd' )
+                     ]
+    else:
+        ioPadPower = [ (side , None,  'iopower_{}'.format(powerCount), 'iovdd' )
+                     , (side , None, 'ioground_{}'.format(powerCount), 'iovss' )
+                     , (side , None,   'ground_{}'.format(powerCount),   'vss' )
+                     , (side , None,    'power_{}'.format(powerCount),   'vdd' )
+                     ]
+    powerCount += 1
+    return ioPadPower
+
+
+def doIoPinVector ( ioSpec, bits ):
+    v = []
+    if not isiterable(bits): bits = range(bits)
+    if not bits:
+        raise ErrorMessage( 1, [ 'doIoPinVector(): Argument "bits" is neither a width nor an iterable.'
+                               , '(bits={})'.format(bits)
+                               ] )
+    if len(ioSpec) == 5:
+        for bit in bits:
+            v.append(( ioSpec[0]
+                     , ioSpec[1]
+                     , ioSpec[2].format(bit)
+                     , ioSpec[3].format(bit)
+                     , ioSpec[4].format(bit) ))
+    elif len(ioSpec) == 6:
+        for bit in bits:
+            v.append(( ioSpec[0]
+                     , ioSpec[1]
+                     , ioSpec[2].format(bit)
+                     , ioSpec[3].format(bit)
+                     , ioSpec[4].format(bit)
+                     , ioSpec[5].format(bit) ))
+    elif len(ioSpec) == 7:
+        for bit in bits:
+            v.append(( ioSpec[0]
+                     , ioSpec[1]
+                     , ioSpec[2].format(bit)
+                     , ioSpec[3].format(bit)
+                     , ioSpec[4].format(bit)
+                     , ioSpec[5].format(bit)
+                     , ioSpec[6].format(bit) ))
+    else:
+        raise ErrorMessage( 1, [ 'doIoPinVector(): Argument "ioSpec" must have between 5 and 7 fields ({})'.format(len(ioSpec))
+                               , '(ioSpec={})'.format(ioSpec)
+                               ] )
+    return v
+
+
+def rgetInstance ( cell, path ):
+    """
+    Get the instance designated by path (recursively). The path argument can be
+    either a string of instance names separated by dots or directly a list of
+    instances names.
+    """
+    if isinstance(path,str):
+        path = path.split( '.' )
+    elif not isinstance(path,list):
+        raise ErrorMessage( 1, 'rgetInstance(): "path" argument is neither a string or a list ({})"' \
+                               .format(path) )
+    instance = cell.getInstance( path[0] )
+    if instance is None:
+        raise ErrorMessage( 1, 'rgetInstance(): no instance "{}" in cell "{}"' \
+                               .format(path[0],cell.getName()) )
+    if len(path) == 1:
+        return instance
+    return rgetInstance( instance.getMasterCell(), path[1:] )
+
+
+def rsetAbutmentBox ( cell, ab ):
+    for occurrence in cell.getNonTerminalNetlistInstanceOccurrences():
+        masterCell = occurrence.getEntity().getMasterCell()
+        masterCell.setAbutmentBox( ab )
+
 
 def scriptMain (**kw):
     """The mandatory function to be called by Coriolis CGT/Unicorn."""
     global af
-    rvalue = True
-    coreSize = 5200.0 
-    chipBorder = 2*214.0 + 10*13.0
-    ioSpecs = IoSpecs()
-    ioSpecs.loadFromPinmux( './non_generated/litex_pinpads.json' )
+   #helpers.setTraceLevel( 550 )
+    rvalue     = True
+    coreSize   = u(5850.0)
+    chipBorder = u(2*214.0 + 10*13.0)
+    ioSpecs    = IoSpecs()
+   #pinmuxFile = './non_generated/litex_pinpads.json'
+   #pinmuxFile = './coriolis2/ls180/litex_pinpads.json'
+   #ioSpecs.loadFromPinmux( pinmuxFile )
+   # I/O pads, East side.
+    ioPadsSpec  = []
+    ioPadsSpec += doIoPowerCap( IoPin.EAST|IoPin.A_BEGIN )
+    ioPadsSpec += doIoPinVector( (IoPin.EAST , None, 'sdram_a_{}', 'sdram_a({})', 'sdram_a({})'), 13 )
+    ioPadsSpec += doIoPinVector( (IoPin.EAST , None,    'gpio_{}',    'gpio({})',  'gpio_i({})',  'gpio_oe({})',  'gpio_o({})'), range(8,16) )
+    ioPadsSpec += [ (IoPin.EAST , None, 'jtag_tms', 'jtag_tms', 'jtag_tms' )
+                  , (IoPin.EAST , None, 'jtag_tdi', 'jtag_tdi', 'jtag_tdi' )
+                  , (IoPin.EAST , None, 'jtag_tdo', 'jtag_tdo', 'jtag_tdo' )
+                  , (IoPin.EAST , None, 'jtag_tck', 'jtag_tck', 'jtag_tck' )
+                  ]
+    ioPadsSpec += doIoPinVector( (IoPin.EAST , None, 'nc_{}', 'nc({})', 'nc({})'), range(4) )
+    ioPadsSpec += doIoPowerCap( IoPin.EAST|IoPin.A_END )
+   # I/O pads, West side.
+    ioPadsSpec += doIoPowerCap( IoPin.WEST|IoPin.A_BEGIN )
+    ioPadsSpec += [ (IoPin.WEST, None, 'pwm_1', 'pwm(1)', 'pwm(1)' ) ]
+    ioPadsSpec += doIoPinVector( (IoPin.WEST , None, 'eint_{}', 'eint({})', 'eint({})'),  3 )
+    ioPadsSpec += [ (IoPin.WEST , None, 'spimaster_clk' , 'spimaster_clk' , 'spimaster_clk' )
+                  , (IoPin.WEST , None, 'spimaster_cs_n', 'spimaster_cs_n', 'spimaster_cs_n' )
+                  , (IoPin.WEST , None, 'spimaster_mosi', 'spimaster_mosi', 'spimaster_mosi' )
+                  , (IoPin.WEST , None, 'spimaster_miso', 'spimaster_miso', 'spimaster_miso' )
+                  , (IoPin.WEST , None, 'sdcard_cmd'    , 'sdcard_cmd'    , 'sdcard_cmd_i', 'sdcard_cmd_oe', 'sdcard_cmd_o' )
+                  , (IoPin.WEST , None, 'sdcard_clk'    , 'sdcard_clk'    , 'sdcard_clk' )
+                  ]
+    ioPadsSpec += doIoPinVector( (IoPin.WEST , None, 'sdcard_data_{}', 'sdcard_data({})', 'sdcard_data_i({})', 'sdcard_data_oe', 'sdcard_data_o({})'),  4 )
+    ioPadsSpec += doIoPinVector( (IoPin.WEST , None, 'nc_{}', 'nc({})', 'nc({})'), range(4,16) )
+    ioPadsSpec += doIoPowerCap( IoPin.WEST|IoPin.A_END )
+   # I/O pads, North side.
+    ioPadsSpec += doIoPowerCap( IoPin.NORTH|IoPin.A_BEGIN )
+    ioPadsSpec += doIoPinVector( (IoPin.NORTH, None, 'sdram_dm_{}', 'sdram_dm({})', 'sdram_dm({})'),  2 )
+    ioPadsSpec += doIoPinVector( (IoPin.NORTH, None, 'sdram_dq_{}', 'sdram_dq({})', 'sdram_dq_i({})', 'sdram_dq_oe', 'sdram_dq_o({})'), range(0,16) )
+    ioPadsSpec += doIoPinVector( (IoPin.NORTH, None, 'sdram_ba_{}', 'sdram_ba({})', 'sdram_ba({})'), 2 )
+    ioPadsSpec += [ (IoPin.NORTH, None, 'sdram_clock'   , 'sdram_clock'   , 'sdram_clock' )
+                  , (IoPin.NORTH, None, 'sdram_cke'     , 'sdram_cke'     , 'sdram_cke' )
+                  , (IoPin.NORTH, None, 'sdram_ras_n'   , 'sdram_ras_n'   , 'sdram_ras_n' )
+                  , (IoPin.NORTH, None, 'sdram_cas_n'   , 'sdram_cas_n'   , 'sdram_cas_n' )
+                  , (IoPin.NORTH, None, 'sdram_we_n'    , 'sdram_we_n'    , 'sdram_we_n' )
+                  , (IoPin.NORTH, None, 'sdram_cs_n'    , 'sdram_cs_n'    , 'sdram_cs_n' )
+                  ]
+    ioPadsSpec += doIoPinVector( (IoPin.NORTH, None, 'nc_{}', 'nc({})', 'nc({})'), range(16,18) )
+    ioPadsSpec += doIoPowerCap( IoPin.NORTH|IoPin.A_END )
+   # I/O pads, South side.
+    ioPadsSpec += doIoPowerCap( IoPin.SOUTH|IoPin.A_BEGIN )
+    ioPadsSpec += [ (IoPin.SOUTH, None, 'i2c_sda_i'     , 'i2c_sda_i'     , 'i2c_sda_i' ) ]
+    ioPadsSpec += doIoPinVector( (IoPin.SOUTH, None, 'nc_{}', 'nc({})', 'nc({})'), range(18,22) )
+    ioPadsSpec += [ (IoPin.SOUTH, None, 'spisdcard_clk' , 'spisdcard_clk' , 'spisdcard_clk' )
+                  , (IoPin.SOUTH, None, 'spisdcard_cs_n', 'spisdcard_cs_n', 'spisdcard_cs_n' )
+                  , (IoPin.SOUTH, None, 'spisdcard_mosi', 'spisdcard_mosi', 'spisdcard_mosi' )
+                  , (IoPin.SOUTH, None, 'spisdcard_miso', 'spisdcard_miso', 'spisdcard_miso' )
+                  ]
+    ioPadsSpec += doIoPinVector( (IoPin.SOUTH, None, 'nc_{}', 'nc({})', 'nc({})'), range(22,23) )
+    ioPadsSpec += [ (IoPin.SOUTH, None, 'uart_tx', 'uart_tx', 'uart_tx' )
+                  , (IoPin.SOUTH, None, 'uart_rx', 'uart_rx', 'uart_rx' )
+                  ]
+    ioPadsSpec += doIoPinVector( (IoPin.SOUTH, None, 'gpio_{}', 'gpio({})', 'gpio_i({})', 'gpio_oe({})',  'gpio_o({})'), range(0,8) )
+    ioPadsSpec += [ (IoPin.SOUTH, None, 'sys_clk', 'sys_clk', 'sys_clk' )
+                  , (IoPin.SOUTH, None, 'sys_rst', 'sys_rst', 'sys_rst' )
+                  ]
+    ioPadsSpec += doIoPinVector( (IoPin.SOUTH, None, 'nc_{}', 'nc({})', 'nc({})'), range(23,24) )
+    ioPadsSpec += [ (IoPin.SOUTH, None, 'sys_pll_18_o'  , 'sys_pll_18_o'  , 'sys_pll_18_o' ) ]
+    ioPadsSpec += doIoPinVector( (IoPin.SOUTH, None,   'sys_clksel_i{}',  'sys_clksel_i({})',  'sys_clksel_i({})'),  2 )
+    ioPadsSpec += [ (IoPin.SOUTH, None, 'sys_pll_lck_o' , 'sys_pll_lck_o' , 'sys_pll_lck_o' ) ]
+    ioPadsSpec += doIoPowerCap( IoPin.SOUTH|IoPin.A_END )
     try:
-        #helpers.setTraceLevel( 550 )
         cell, editor = plugins.kwParseMain( **kw )
         cell = af.getCell( 'ls180', CRL.Catalog.State.Logical )
         if cell is None:
@@ -38,7 +195,8 @@ def scriptMain (**kw):
                                     .format('ls180') ))
             sys.exit(1)
         if editor: editor.setCell( cell )
-        ls180Conf = ChipConf( cell, ioPads=ioSpecs.ioPadsSpec )
+       #ls180Conf = ChipConf( cell, ioPads=ioSpecs.ioPadsSpec )
+        ls180Conf = ChipConf( cell, ioPads=ioPadsSpec )
         ls180Conf.cfg.etesian.bloat = 'nsxlib'
         ls180Conf.cfg.etesian.uniformDensity = True
         ls180Conf.cfg.etesian.aspectRatio = 1.0
@@ -50,7 +208,7 @@ def scriptMain (**kw):
         ls180Conf.cfg.katana.vTracksReservedLocal = 3
         ls180Conf.cfg.katana.hTracksReservedMin = 3
         ls180Conf.cfg.katana.vTracksReservedMin = 1
-        ls180Conf.cfg.block.spareSide = u(200)
+        ls180Conf.cfg.block.spareSide = u(156)
         ls180Conf.cfg.chip.supplyRailWidth = u(35)
         ls180Conf.cfg.chip.supplyRailPitch = u(90)
         ls180Conf.editor = editor
@@ -61,8 +219,39 @@ def scriptMain (**kw):
         ls180Conf.bRows = 2
         ls180Conf.chipConf.name = 'chip'
         ls180Conf.chipConf.ioPadGauge = 'LibreSOCIO'
-        ls180Conf.coreSize = (u(coreSize), u(coreSize))
-        ls180Conf.chipSize = (u(coreSize + chipBorder), u(coreSize + chipBorder))
+        ls180Conf.coreSize = (coreSize, coreSize)
+        ls180Conf.chipSize = (coreSize + chipBorder, coreSize + chipBorder)
+
+        with UpdateSession():
+            sliceHeight = ls180Conf.sliceHeight
+            coreAb      = Box( 0, 0, coreSize, coreSize )
+            rsetAbutmentBox( cell, coreAb )
+            tiPath = 'subckt_38695_test_issuer.subckt_1_ti.'
+            sramPaths = [ tiPath+'subckt_3695_sram4k_0.subckt_144_SPBlock_512W64B8W'
+                        , tiPath+'subckt_3696_sram4k_1.subckt_144_SPBlock_512W64B8W'
+                        , tiPath+'subckt_3697_sram4k_2.subckt_144_SPBlock_512W64B8W'
+                        , tiPath+'subckt_3698_sram4k_3.subckt_144_SPBlock_512W64B8W'
+                        ]
+            sramAb    = None
+            for i in range(4):
+                sram = rgetInstance( cell, sramPaths[i] )
+                if not sram:
+                    raise ErrorMessage( 1, 'SRAM instance "{}" not found.'.format(sramPaths[i]) )
+                if i == 0:
+                    Macro.wrap( sram.getMasterCell(), 'FlexLib', 3, 2 )
+                sramAb = sram.getMasterCell().getAbutmentBox()
+                Macro.place( sram
+                           , Transformation( coreAb.getXMin() + sramAb.getWidth ()*i
+                                           , coreAb.getYMax() - sramAb.getHeight()
+                                           , Transformation.Orientation.ID )
+                           , Instance.PlacementStatus.FIXED )
+            ls180Conf.placeArea = Box( coreAb.getXMin()
+                                     , coreAb.getYMin()
+                                     , coreAb.getXMax()
+                                     , coreAb.getYMax() - sramAb.getHeight()
+                                     )
+        Breakpoint.stop( 99, 'After core placement.' )
+
         ls180ToChip = CoreToChip( ls180Conf )
         ls180ToChip.buildChip()
         chipBuilder = Chip( ls180Conf )