Added support for JSON pinmux reading from LibreSOC.
* New: In cumulus/plugins.blocks.iospecs.IoSpecs, new class to manage I/O pads placement. Support for reading the JSON pinmux format (courtesy of LKCL & StackOverflow).
This commit is contained in:
parent
13726d648b
commit
85d943a3e4
|
@ -533,7 +533,7 @@ class IoPadConf ( object ):
|
||||||
|
|
||||||
def __init__ ( self, datas ):
|
def __init__ ( self, datas ):
|
||||||
if not isinstance(datas,tuple):
|
if not isinstance(datas,tuple):
|
||||||
raise ErrorMessage( 1, [ 'IoPadConf.__init__(): The "datas" parameter is not a list.'
|
raise ErrorMessage( 1, [ 'IoPadConf.__init__(): The "datas" parameter is not a tuple.'
|
||||||
, str(datas) ] )
|
, str(datas) ] )
|
||||||
if len(datas) < 5 and len(datas) > 8:
|
if len(datas) < 5 and len(datas) > 8:
|
||||||
raise ErrorMessage( 1, [ 'IoPadConf.__init__(): The "datas" list must have between 5 to 7 elements.'
|
raise ErrorMessage( 1, [ 'IoPadConf.__init__(): The "datas" list must have between 5 to 7 elements.'
|
||||||
|
@ -886,6 +886,20 @@ class IoPin ( object ):
|
||||||
A_END = 0x0020
|
A_END = 0x0020
|
||||||
A_MASK = A_BEGIN|A_END
|
A_MASK = A_BEGIN|A_END
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def toStr ( value ):
|
||||||
|
s = ''
|
||||||
|
for constant, name in ( (IoPin.SOUTH , 'SOUTH' )
|
||||||
|
, (IoPin.NORTH , 'NORTH' )
|
||||||
|
, (IoPin.EAST , 'EAST' )
|
||||||
|
, (IoPin.WEST , 'WEST' )
|
||||||
|
, (IoPin.A_BEGIN, 'A_BEGIN')
|
||||||
|
, (IoPin.A_END , 'A_END' ) ):
|
||||||
|
if value & constant:
|
||||||
|
if len(s): s += '|'
|
||||||
|
s += 'IoPin.'+name
|
||||||
|
return s
|
||||||
|
|
||||||
def __init__ ( self, flags, stem, upos, ustep=0, count=1 ):
|
def __init__ ( self, flags, stem, upos, ustep=0, count=1 ):
|
||||||
"""
|
"""
|
||||||
Create an I/O Pin(s) on the abutment box of a block. Could be for one
|
Create an I/O Pin(s) on the abutment box of a block. Could be for one
|
||||||
|
|
|
@ -0,0 +1,149 @@
|
||||||
|
#
|
||||||
|
# This file is part of the Coriolis Software.
|
||||||
|
# Copyright (c) SU 2020-2020, All Rights Reserved
|
||||||
|
#
|
||||||
|
# +-----------------------------------------------------------------+
|
||||||
|
# | C O R I O L I S |
|
||||||
|
# | C u m u l u s - P y t h o n T o o l s |
|
||||||
|
# | |
|
||||||
|
# | Author : Jean-Paul CHAPUT |
|
||||||
|
# | E-mail : Jean-Paul.Chaput@lip6.fr |
|
||||||
|
# | =============================================================== |
|
||||||
|
# | Python : "./plugins/block/iospecs.py" |
|
||||||
|
# +-----------------------------------------------------------------+
|
||||||
|
|
||||||
|
from __future__ import print_function
|
||||||
|
import sys
|
||||||
|
import re
|
||||||
|
import os.path
|
||||||
|
import json
|
||||||
|
from operator import itemgetter
|
||||||
|
import Cfg
|
||||||
|
from Hurricane import Breakpoint, DbU, Box, Transformation
|
||||||
|
import CRL
|
||||||
|
from helpers import trace, l, u, n
|
||||||
|
from helpers.utils import classdecorator
|
||||||
|
from helpers.io import ErrorMessage, WarningMessage, catch
|
||||||
|
from helpers.overlay import CfgCache
|
||||||
|
from plugins.alpha.block.configuration import IoPin
|
||||||
|
|
||||||
|
__all__ = [ 'IoSpecs' ]
|
||||||
|
|
||||||
|
|
||||||
|
# ----------------------------------------------------------------------------
|
||||||
|
# Function : "iospecs.utf8toStr".
|
||||||
|
def utf8toStr ( data, ignoreDicts=False ):
|
||||||
|
"""
|
||||||
|
Translate UTF-8 strings into basic str ones in dict & list datas.
|
||||||
|
Based on _byteify() by Mirec Miskuf on Stackoverflow.
|
||||||
|
|
||||||
|
reference: https://stackoverflow.com/questions/956867/
|
||||||
|
how-to-get-string-objects-instead-of-unicode-from-json/
|
||||||
|
33571117#33571117
|
||||||
|
"""
|
||||||
|
if isinstance(data,unicode):
|
||||||
|
return data.encode('utf-8')
|
||||||
|
if isinstance(data,list):
|
||||||
|
return [ utf8toStr( item, ignoreDicts=True ) for item in data ]
|
||||||
|
if isinstance(data,dict) and not ignoreDicts:
|
||||||
|
return dict( ( utf8toStr(key , ignoreDicts=True )
|
||||||
|
, utf8toStr(value, ignoreDicts=True ))
|
||||||
|
for key, value in data.iteritems() )
|
||||||
|
return data
|
||||||
|
|
||||||
|
|
||||||
|
# ----------------------------------------------------------------------------
|
||||||
|
# Class : "iospecs.IoPadSpec".
|
||||||
|
|
||||||
|
class IoPadSpec ( object ):
|
||||||
|
|
||||||
|
id = 0
|
||||||
|
|
||||||
|
def __init__ ( self, instance, side, position=None, nets=[] ):
|
||||||
|
self.instance = instance
|
||||||
|
self.side = side
|
||||||
|
self.position = position
|
||||||
|
self.nets = list(nets)
|
||||||
|
self._id = IoPadSpec.id
|
||||||
|
IoPadSpec.id += 1
|
||||||
|
|
||||||
|
def addNets ( self, nets ):
|
||||||
|
self.nets += nets
|
||||||
|
|
||||||
|
def asList ( self ):
|
||||||
|
return tuple( [ self.side, self.position, self.instance ] + self.nets )
|
||||||
|
|
||||||
|
def __str__ ( self ):
|
||||||
|
s = '({:<11}'.format( IoPin.toStr(self.side) )
|
||||||
|
s += ', {}'.format( self.position )
|
||||||
|
s += ', "{}"'.format( self.instance )
|
||||||
|
for net in self.nets:
|
||||||
|
s += ', "{}"'.format(net)
|
||||||
|
s += ')'
|
||||||
|
return s
|
||||||
|
|
||||||
|
|
||||||
|
# ----------------------------------------------------------------------------
|
||||||
|
# Class : "iospecs.IoSpecs".
|
||||||
|
|
||||||
|
class IoSpecs ( object ):
|
||||||
|
"""
|
||||||
|
Load and generate IoPadsSpec from a variety of sources.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__ ( self ):
|
||||||
|
self._ioPadsLUT = {}
|
||||||
|
self._ioPadsSpec = []
|
||||||
|
|
||||||
|
def addIoPadSpec ( self, instance, side ):
|
||||||
|
if self._ioPadsLUT.has_key(instance):
|
||||||
|
print( ErrorMessage( 2, 'IoSpecs.addIoPadSpec(): Duplicate pad specification for "{}" (ignored).' \
|
||||||
|
.format(instance) ) )
|
||||||
|
return self._ioPadsLUT[ instance ]
|
||||||
|
spec = IoPadSpec( instance, side )
|
||||||
|
self._ioPadsLUT[ instance ] = spec
|
||||||
|
self._ioPadsSpec.append( spec )
|
||||||
|
return spec
|
||||||
|
|
||||||
|
def loadFromPinmux ( self, fileName ):
|
||||||
|
"""
|
||||||
|
Load ioPadsSpec from a LibreSOC generated pinmux file in JSON format.
|
||||||
|
"""
|
||||||
|
if not os.path.isfile(fileName):
|
||||||
|
raise ErrorMessage( 2, [ 'IoSpecs.loadFromPinmux(): JSON pinmux file not found.'
|
||||||
|
, '("{}")'.format(fileName) ] )
|
||||||
|
with open(fileName) as fd:
|
||||||
|
datas = utf8toStr( json.loads( fd.read(), object_hook=utf8toStr )
|
||||||
|
, ignoreDicts=True )
|
||||||
|
for padName in datas['pads.east' ]: self.addIoPadSpec( padName, IoPin.EAST )
|
||||||
|
for padName in datas['pads.west' ]: self.addIoPadSpec( padName, IoPin.WEST )
|
||||||
|
for padName in datas['pads.north']: self.addIoPadSpec( padName, IoPin.NORTH )
|
||||||
|
for padName in datas['pads.south']: self.addIoPadSpec( padName, IoPin.SOUTH )
|
||||||
|
for padDatas in datas['pads.instances']:
|
||||||
|
padName = padDatas[0]
|
||||||
|
if not self._ioPadsLUT.has_key(padName):
|
||||||
|
print( WarningMessage('IoSpecs.loadFromPinmux(): Pad "{}" is not on any side, ignored.' \
|
||||||
|
.format(padName) ))
|
||||||
|
continue
|
||||||
|
end = None
|
||||||
|
if padDatas[-1] in '+-*': end = -1
|
||||||
|
self._ioPadsLUT[padName].addNets( padDatas[1:end] )
|
||||||
|
|
||||||
|
@property
|
||||||
|
def ioPadsSpec ( self ):
|
||||||
|
specs = []
|
||||||
|
for spec in self._ioPadsSpec:
|
||||||
|
specs.append( spec.asList() )
|
||||||
|
return specs
|
||||||
|
|
||||||
|
def __str__ ( self ):
|
||||||
|
if len(self._ioPadsSpec):
|
||||||
|
s = 'ioPadsSpec = [ '
|
||||||
|
for spec in self._ioPadsSpec:
|
||||||
|
if len(s) > 15: s += '\n , '
|
||||||
|
s += '{}'.format( spec )
|
||||||
|
s += ')'
|
||||||
|
s += ' ]'
|
||||||
|
return s
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue