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 ):
|
||||
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) ] )
|
||||
if len(datas) < 5 and len(datas) > 8:
|
||||
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_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 ):
|
||||
"""
|
||||
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