Pinmux loading is now integrated in Coriolis.
authorJean-Paul Chaput <Jean-Paul.Chaput@lip6.fr>
Wed, 27 Jan 2021 13:02:55 +0000 (14:02 +0100)
committerJean-Paul Chaput <Jean-Paul.Chaput@lip6.fr>
Wed, 27 Jan 2021 13:02:55 +0000 (14:02 +0100)
experiments9/doDesign.py

index db4f3c78703c91ebf546573f8774fe14a1941d16..890564d3d77fe3550f0b9e0d534f9dfcd8dbce98 100644 (file)
+
 from   __future__ import print_function
 
 import os
 import json
-from pprint import pprint
 import sys
 import traceback
 import CRL
 import helpers
-from   helpers.io import ErrorMessage
-from   helpers.io import WarningMessage
-from   helpers    import trace
-from   helpers    import l, u, n
+from   helpers.io import ErrorMessage, WarningMessage
+from   helpers    import trace, l, u, n
 import plugins
 from   Hurricane  import DbU
-if True: # change this to False to get errors to "go away" so that
-         # print / debug statements in generation of spec can be seen
-         # without the hard dependence of having to run via "cgt"
-    from   plugins.alpha.block.configuration import IoPin
-    from   plugins.alpha.block.block         import Block
-    from   plugins.alpha.block.configuration import GaugeConf
-    from   plugins.alpha.core2chip.niolib    import CoreToChip
-    from   plugins.alpha.chip.configuration  import ChipConf
-    from   plugins.alpha.chip.chip           import Chip
-
-
-af = CRL.AllianceFramework.get()
-
-# converts unicode strings to utf-8 because coriolis2 python code is expecting
-# str not unicode
-def _byteify(data, ignore_dicts = False):
-    # if this is a unicode string, return its string representation
-    if isinstance(data, unicode):
-        return data.encode('utf-8')
-    # if this is a list of values, return list of byteified values
-    if isinstance(data, list):
-        return [ _byteify(item, ignore_dicts=True) for item in data ]
-    # if this is a dictionary, return dictionary of byteified keys and values
-    # but only if we haven't already byteified it
-    if isinstance(data, dict) and not ignore_dicts:
-        return dict((_byteify(key, ignore_dicts=True),
-                    _byteify(value, ignore_dicts=True))
-                        for key, value in data.iteritems())
-    # if it's anything else, return it in its original form
-    return data
-
-# load JSON-formatted pad info from pinmux
-pth = os.path.abspath(__file__)
-pth = os.path.split(pth)[0]
-print ("path", pth)
-with open("%s/ls180/litex_pinpads.json" % pth) as f:
-    txt = f.read()
-chip = json.loads(txt, object_hook=_byteify)
-chip = _byteify(chip, ignore_dicts=True)
-print (chip)
-
-chip.update({ 'pads.ioPadGauge' : 'niolib',
-          # core option (big, time-consuming)
-          #'core.size'       : (l(28000), l(28000)),
-          #'chip.size'       : (l(30200), l(30200)),
-          # no-core option (test_issuer but no actual core)
-          'core.size'       : (l(13000), l(13000)),
-          'chip.size'       : (l(14400), l(14400)),
-          'pads.useCoreSize': True,
-          'chip.clockTree'  : True,
-       })
-
-# this function is the equivalent of statically-declared io pad specs.
-# it is not ok to have io declared manually, duplicated in (literally) 5
-# different places, too many mistakes can be made and changes are a
-# nightmare.
-#
-# therefore the pinmux code takes responsibility for declaring the pinouts,
-# generates a JSON file which is read (above) and *creates* the list from
-# that auto-generated file.  the core, litex peripheral code, *and* the C4M
-# JTAG Boundary Scan code do *EXACTLY* the same thing and in this way they
-# all "match".
-#
-# here we do some weirdness to convert from the ioring.py pads list format over
-# to the new niolib format.
-
-def generate_spec():
-    # convert old ioring format to ioPadsSpec
-    ioPadsSpec = []
-    sd = {'pads.east': IoPin.EAST,
-          'pads.west': IoPin.WEST,
-          'pads.south': IoPin.SOUTH,
-          'pads.north': IoPin.NORTH,
-    }
-    # create lookup dict for resolving pads.instances "side" (NSEW)
-    sides = {}
-    for side in ['pads.east', 'pads.west', 'pads.south', 'pads.north']:
-        io_pin_spec = sd[side]
-        #if side not in sides:
-        #    sides[side] = {}
-        for pinname in chip[side]:
-            sides[pinname] = io_pin_spec
-
-    # now go through pads.instances
-    pprint (sides)
-    for pad in chip['pads.instances']:
-        padname = pad[0]
-        padside = sides[padname]
-        print ("padside", padname, padside)
-
-        # format here is ['padname', 'to core', 'from core', 'direction']
-        # where direction is "+" for out, "-" for in, "*" for bi-directionaly
-        if len(pad) == 4:
-            print("4-long io", pad)
-            padspec = [padside, None, padname, pad[1], pad[2]]
-
-        # format here is:
-        # ['padname', 'something', 'to core', 'from core', 'en', 'direction']
-        elif len(pad) == 6:
-            print("6-long io", pad)
-            padspec = [padside, None, padname] + pad[1:5]
-
-        # format here is power/gnd (io)vss/vdd
-        elif len(pad) == 2:
-            print("2-long io", pad)
-            padspec = [padside, None] + pad
-        else:
-            print("? long io", pad)
-            assert False
-        print ("padspec", padspec)
-        ioPadsSpec.append(tuple(padspec))
-
-    return ioPadsSpec
+from   plugins.alpha.block.configuration import IoPin, GaugeConf
+from   plugins.alpha.block.iospecs       import IoSpecs
+from   plugins.alpha.block.block         import Block
+from   plugins.alpha.core2chip.niolib    import CoreToChip
+from   plugins.alpha.chip.configuration  import ChipConf
+from   plugins.alpha.chip.chip           import Chip
 
-ioPadsSpec = generate_spec()
 
+af  = CRL.AllianceFramework.get()
 
 def scriptMain (**kw):
     """The mandatory function to be called by Coriolis CGT/Unicorn."""
     global af
     rvalue = True
-    sz = 26000 # core size
+    coreSize = 26000 
+    cwd = os.path.split( os.path.abspath(__file__) )[0]
+    ioSpecs = IoSpecs()
+    ioSpecs.loadFromPinmux( '{}/ls180/litex_pinpads.json'.format(cwd) )
     try:
-        helpers.setTraceLevel(550)
-        usePadsPosition = True
-        buildChip       = True
-        cell, editor = plugins.kwParseMain(**kw)
-        cell = af.getCell('ls180', CRL.Catalog.State.Logical)
+        #helpers.setTraceLevel( 550 )
+        cell, editor = plugins.kwParseMain( **kw )
+        cell = af.getCell( 'ls180', CRL.Catalog.State.Logical )
         if cell is None:
-            print(ErrorMessage(2, 'doDesign.scriptMain(): Unable to load '
-                                    'cell "{}".'.format('ls180')))
+            print( ErrorMessage( 2, 'doDesign.scriptMain(): Unable to load cell "{}".' \
+                                    .format('ls180') ))
             sys.exit(1)
-        if editor: editor.setCell(cell)
-        ls180Conf = ChipConf(cell, ioPads=ioPadsSpec)
+        if editor: editor.setCell( cell )
+        ls180Conf = ChipConf( cell, ioPads=ioSpecs.ioPadsSpec )
         ls180Conf.cfg.etesian.bloat = 'nsxlib'
         ls180Conf.cfg.etesian.uniformDensity = True
         ls180Conf.cfg.etesian.aspectRatio = 1.0
@@ -160,11 +52,11 @@ def scriptMain (**kw):
         ls180Conf.bRows = 2
         ls180Conf.chipConf.name = 'chip'
         ls180Conf.chipConf.ioPadGauge = 'niolib'
-        ls180Conf.coreSize = (l(sz), l(sz))
-        ls180Conf.chipSize = (l(sz+3360), l(sz+3360))
-        ls180ToChip = CoreToChip(ls180Conf)
+        ls180Conf.coreSize = (l(coreSize     ), l(coreSize     ))
+        ls180Conf.chipSize = (l(coreSize+3360), l(coreSize+3360))
+        ls180ToChip = CoreToChip( ls180Conf )
         ls180ToChip.buildChip()
-        chipBuilder = Chip(ls180Conf)
+        chipBuilder = Chip( ls180Conf )
         rvalue = chipBuilder.doPnR()
         chipBuilder.save()
     except Exception, e: