PK
hO$I registerMap/VERSION0.6.0
PK hO] registerMap/__init__.py#
# Copyright 2016 Russell Smiley
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
#
"""
A Python 3 framework for creating and maintaining register maps for integrated circuit design and embedded
software development.
"""
import os.path
here = os.path.abspath( os.path.dirname( __file__ ) )
versionFilePath = os.path.abspath( os.path.join( here, 'VERSION' ) )
with open( versionFilePath ) as version_file :
version = version_file.read().strip()
__version__ = version
from .exceptions import \
ConfigurationError, \
ParseError
from .registerMap import \
RegisterMap, \
load, \
save
PK hOn, , registerMap/exceptions.py#
# Copyright 2016 Russell Smiley
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
#
class ConfigurationError( Exception ) :
pass
class ConstraintError( Exception ) :
pass
class ParseError( Exception ) :
pass
PK hOh5 registerMap/exporter.py#
# Copyright 2018 Russell Smiley
#
# This file is part of registerMap.
#
# registerMap is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# registerMap is distributed in the hope that it will be useful
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with registerMap. If not, see .
#
import logging
import sys
import yaml
from .registerMap import RegisterMap
from .export import parseArguments
log = logging.getLogger( __name__ )
def acquireLicenseText( licenseTextFile ) :
if licenseTextFile is not None :
with open( licenseTextFile, 'r' ) as fileObject :
licenseTextLines = fileObject.readlines()
else :
licenseTextLines = list()
return licenseTextLines
def acquireRegisterMap( registerMapFile ) :
with open( registerMapFile, 'r' ) as fileObject :
yamlData = yaml.safe_load( fileObject )
if yamlData is None :
# Register map file was empty
registerMap = None
else :
registerMap = RegisterMap.from_yamlData( yamlData )
return registerMap
def main( commandLineArguments ) :
exporterOptions = parseArguments( commandLineArguments )
licenseText = acquireLicenseText( exporterOptions.licenseFile )
registerMap = acquireRegisterMap( exporterOptions.registerMapFile )
if registerMap is None :
log.warning( 'Empty register map exports no code, {0}'.format( exporterOptions.registerMapFile ) )
else :
thisGenerator = exporterOptions.languageOptions.generator( exporterOptions.languageOptions,
licenseTextLines = licenseText )
thisGenerator.generate( registerMap, exporterOptions.registerMapName )
def entry() :
main( sys.argv[ 1 : ] )
if __name__ == '__main__' :
main( sys.argv[ 1 : ] )
PK hO:2Q Q registerMap/registerMap.py"""
Definition of RegisterMap
"""
#
# Copyright 2016 Russell Smiley
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
#
import logging
from .base.parameters import \
ElementsParameter, \
ModulesParameter
from .structure.elements.base.parameter import Parameter
from .structure.elements.module import Module
from .exceptions import \
ConfigurationError, \
ParseError
from .structure.set import SetCollection
from .structure.memory.element import AddressableMemoryElement
from .structure.memory.configuration import MemoryConfiguration
from .utility.observer import AddressChangeObserver
from .export.io.yaml.stream import \
load as load_yaml_data, \
save as save_yaml_data
log = logging.getLogger( __name__ )
class RegisterMap :
__yamlName = 'registerMap'
def __init__( self ) :
self.__addressObserver = AddressChangeObserver( self )
self.setCollection = SetCollection()
self.__initializeMemorySpace()
self.__initializeElement()
self.__data = {
'description' : Parameter( 'description', '' ),
'element' : ElementsParameter( self ),
'modules' : ModulesParameter( self ),
'summary' : Parameter( 'summary', '' )
}
self.__sizeObserver = self.__data[ 'modules' ].sizeObserver
self.__memorySpace.sizeChangeNotifier.addObserver( self.__sizeObserver )
def __initializeElement( self ) :
self.__element = AddressableMemoryElement( self.__memorySpace )
self.__element.startAddress = self.__memorySpace.baseAddress
self.__element.sizeMemoryUnits = None
def __initializeMemorySpace( self ) :
self.__memorySpace = MemoryConfiguration()
self.__memorySpace.addressChangeNotifier.addObserver( self.__addressObserver )
@property
def assignedMemoryUnits( self ) :
"""
:return: Total number of memory units assigned a definition via a register.
"""
totalSize = 0
for thisModule in self.__data[ 'modules' ].value.values() :
totalSize += thisModule.assignedMemoryUnits
return totalSize
@property
def memory( self ) :
return self.__memorySpace
@property
def spanMemoryUnits( self ) :
return self.__element.sizeMemoryUnits
@property
def startAddress( self ) :
return self.__element.startAddress
def addModule( self, name ) :
"""
Create a module with the specified name.
:param name: Name of the new module.
:return: The created module.
"""
thisModule = Module( self.__memorySpace, self.setCollection )
self.setCollection.moduleSet.add( thisModule )
thisModule[ 'name' ] = name
self.__validateAddedModule( thisModule )
self.__data[ 'modules' ].value[ thisModule[ 'name' ] ] = thisModule
log.debug( 'Notifying on module change in register map' )
self.reviewSizeChange()
return thisModule
def __validateAddedModule( self, module ) :
foundModules = [ x[ 'name' ] for x in self.__data[ 'modules' ].value.values() if
x[ 'name' ] == module[ 'name' ] ]
if len( foundModules ) != 0 :
raise ConfigurationError(
'Created module names must be unique within a register map, ' + repr( module[ 'name' ] ) )
def reviewAddressChange( self ) :
"""
Propagate a memory space base address change.
"""
if self.__data[ 'modules' ].firstElement is not None :
self.__data[ 'modules' ].firstElement.endAddress = self.__memorySpace.baseAddress - 1
def reviewSizeChange( self ) :
startAddress = self.__memorySpace.baseAddress
# Assume the map has size 0
endAddress = startAddress - 1
for thisModule in self.__data[ 'modules' ].value.values() :
if thisModule.endAddress > endAddress :
endAddress = thisModule.endAddress
self.__element.sizeMemoryUnits = endAddress - startAddress + 1
def __getitem__( self, item ) :
return self.__data[ item ].value
def __setitem__( self, key, value ) :
self.__data[ key ].value = value
@classmethod
def from_yamlData( cls, yamlData,
optional = False ) :
def acquireMemorySpace( thisData ) :
nonlocal thisMap
thisMap.__memorySpace = MemoryConfiguration.from_yamlData( thisData )
thisMap.__memorySpace.sizeChangeNotifier.addObserver( thisMap.__sizeObserver )
thisMap.__memorySpace.addressChangeNotifier.addObserver( thisMap.__addressObserver )
def acquireDescription( thisData ) :
nonlocal thisMap
thisMap.__data[ 'description' ] = Parameter.from_yamlData( thisData, 'description',
optional = True )
def acquireModules( thisData ) :
nonlocal thisMap
thisMap.__data[ 'modules' ] = ModulesParameter.from_yamlData(
thisData, thisMap, thisMap.__memorySpace, thisMap.setCollection,
optional = True )
def acquireSummary( thisData ) :
nonlocal thisMap
thisMap.__data[ 'summary' ] = Parameter.from_yamlData( thisData, 'summary',
optional = True )
thisMap = cls()
if (not optional) and (cls.__yamlName not in yamlData.keys()) :
raise ParseError( 'RegisterMap is not defined in yaml data' )
elif cls.__yamlName in yamlData.keys() :
# Memory space acquisition must occur first because it is used by module acquisition
acquireMemorySpace( yamlData[ cls.__yamlName ] )
acquireDescription( yamlData[ cls.__yamlName ] )
acquireSummary( yamlData[ cls.__yamlName ] )
acquireModules( yamlData[ cls.__yamlName ] )
thisMap.reviewAddressChange()
thisMap.reviewSizeChange()
return thisMap
def to_yamlData( self ) :
yamlData = { self.__yamlName : { } }
parameters = list()
for parameterData in self.__data.values() :
parameterYamlData = parameterData.to_yamlData()
if parameterYamlData is not None :
parameters.append( parameterYamlData )
yamlData[ self.__yamlName ].update( self.__memorySpace.to_yamlData() )
for thisParameter in parameters :
yamlData[ self.__yamlName ].update( thisParameter )
return yamlData
def __len__( self ) :
thisLength = len( self.setCollection.moduleSet ) \
+ len( self.setCollection.registerSet ) \
+ len( self.setCollection.fieldSet )
return thisLength
def load(file_name:str)->RegisterMap:
yaml_data = load_yaml_data(file_name)
this_map = RegisterMap.from_yamlData(yaml_data)
return this_map
def save(file_name:str, register_map:RegisterMap):
yaml_data = register_map.to_yamlData()
save_yaml_data(file_name, yaml_data)PK hO registerMap/base/__init__.py#
# Copyright 2017 Russell Smiley
#
# This file is part of registerMap.
#
# registerMap is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# registerMap is distributed in the hope that it will be useful
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with registerMap. If not, see .
#
PK hOF~K registerMap/base/parameters.py#
# Copyright 2017 Russell Smiley
#
# This file is part of registerMap.
#
# registerMap is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# registerMap is distributed in the hope that it will be useful
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with registerMap. If not, see .
#
from ..structure.elements.base import ElementList
from ..structure.elements.module import Module
from ..structure.elements.base.parameter import Parameter
from ..exceptions import ParseError
from ..utility.observer import \
Observable, \
SizeChangeObserver
class ElementsParameter( Parameter ) :
def __init__( self, setCollection ) :
self.__setCollection = setCollection
def __getitem__( self, item ) :
fields = [ x for x in self.__setCollection.fieldSet if x.canonicalId == item ]
if len( fields ) == 0 :
registers = [ x for x in self.__setCollection.registerSet if x.canonicalId == item ]
if len( registers ) == 0 :
modules = [ x for x in self.__setCollection.moduleSet if x.canonicalId == item ]
if len( modules ) == 0 :
foundItem = None
else :
assert len( modules ) == 1
foundItem = modules[ 0 ]
else :
assert len( registers ) == 1
foundItem = registers[ 0 ]
else :
# Canonical ID is supposed to be unique so there should be only one result.
assert len( fields ) == 1
foundItem = fields[ 0 ]
return foundItem
def to_yamlData( self ) :
# ElementParameter should not be stored in YAML. It should be built in situ when acquired from YAML.
return None
class ModulesParameter( Parameter ) :
__parameterName = 'modules'
class FirstModule :
def __init__( self,
endAddress = None ) :
self.addressChangeNotifier = Observable()
self.sizeChangeNotifier = Observable()
self.__endAddress = endAddress
@property
def endAddress( self ) :
return self.__endAddress
@endAddress.setter
def endAddress( self, value ) :
self.__endAddress = value
self.sizeChangeNotifier.notifyObservers()
def __init__( self, owner ) :
super().__init__( self.__parameterName, ElementList( self ) )
self.__owner = owner
self.firstElement = None
self.sizeObserver = SizeChangeObserver( self.__owner )
self.__createFirstModulePrevious()
def __createFirstModulePrevious( self ) :
assert self.__owner.memory.baseAddress >= 0
firstModule = ModulesParameter.FirstModule( endAddress = (self.__owner.memory.baseAddress - 1) )
self.firstElement = firstModule
@classmethod
def from_yamlData( cls, yamlData, owner, memorySpace, bitFieldSet,
optional = False ) :
parameter = cls( owner )
if (not optional) and (cls.__parameterName not in yamlData.keys()) :
raise ParseError( 'Modules not defined in yaml data' )
elif cls.__parameterName in yamlData.keys() :
for moduleYamlData in yamlData[ cls.__parameterName ] :
module = Module.from_yamlData( moduleYamlData, memorySpace, bitFieldSet )
parameter.value[ module[ 'name' ] ] = module
return parameter
def to_yamlData( self ) :
yamlData = { self.__parameterName : list() }
for register in self.value.values() :
yamlData[ self.__parameterName ].append( register.to_yamlData() )
return yamlData
PK hO " registerMap/base/tests/__init__.py#
# Copyright 2017 Russell Smiley
#
# This file is part of registerMap.
#
# registerMap is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# registerMap is distributed in the hope that it will be useful
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with registerMap. If not, see .
#
PK hO+q q / registerMap/base/tests/testElementsParameter.py#
# Copyright 2017 Russell Smiley
#
# This file is part of registerMap.
#
# registerMap is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# registerMap is distributed in the hope that it will be useful
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with registerMap. If not, see .
#
import unittest
from registerMap.structure.elements.module import Module
from registerMap.structure.set import SetCollection
from registerMap.structure.memory.configuration import MemoryConfiguration
from ..parameters import ElementsParameter
class TestElementsParameter( unittest.TestCase ) :
def setUp( self ) :
def setupSetCollection() :
m = self.createModule( 'module' )
r = m.addRegister( 'register' )
lf = r.addField( 'local-field', [ 0, 3 ] )
self.assertEqual( 'module.register.local-field', lf.canonicalId )
gf = r.addField( 'global-field', [ 5, 6 ],
isGlobal = True )
self.assertEqual( 'global-field', gf.canonicalId )
self.memorySpace = MemoryConfiguration()
self.setCollection = SetCollection()
setupSetCollection()
self.testElements = ElementsParameter( self.setCollection )
def createModule( self, name ) :
thisModule = Module( self.memorySpace, self.setCollection )
thisModule[ 'name' ] = name
self.setCollection.moduleSet.add( thisModule )
return thisModule
def testGlobalFieldFound( self ) :
actualElement = self.testElements[ 'global-field' ]
self.assertIsNotNone( actualElement )
self.assertEqual( actualElement[ 'name' ], 'global-field' )
def testLocalFieldFound( self ) :
actualElement = self.testElements[ 'module.register.local-field' ]
self.assertIsNotNone( actualElement )
self.assertEqual( actualElement[ 'name' ], 'local-field' )
def testRegisterFound( self ) :
actualElement = self.testElements[ 'module.register' ]
self.assertIsNotNone( actualElement )
self.assertEqual( actualElement[ 'name' ], 'register' )
def testModuleFound( self ) :
actualElement = self.testElements[ 'module' ]
self.assertIsNotNone( actualElement )
self.assertEqual( actualElement[ 'name' ], 'module' )
def testElementNotFound( self ) :
actualElement = self.testElements[ 'not-an-element' ]
self.assertIsNone( actualElement )
if __name__ == '__main__' :
unittest.main()
PK hO7͘ . registerMap/base/tests/testModulesParameter.py#
# Copyright 2017 Russell Smiley
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
#
import unittest
import registerMap.structure.elements.base as rmbs
import registerMap.registerMap as rm
import registerMap.structure.memory.configuration as rmm
from registerMap.structure.set import SetCollection
class TestModulesParameter( unittest.TestCase ) :
def setUp( self ) :
self.sourceFieldSet = SetCollection()
self.testMemory = rmm.MemoryConfiguration()
self.registerMap = rm.RegisterMap()
self.acquiredFieldSet = SetCollection()
def testInitialization( self ) :
p = rm.ModulesParameter( self.registerMap )
self.assertEqual( p.name, 'modules' )
self.assertTrue( isinstance( p.value, rmbs.ElementList ) )
def testEmptyYamlLoadSave( self ) :
p = rm.ModulesParameter( self.registerMap )
generatedYamlData = p.to_yamlData()
decodedModules = rm.ModulesParameter.from_yamlData(
generatedYamlData, self.registerMap, self.testMemory, self.acquiredFieldSet )
self.assertEqual( len( decodedModules.value ), 0 )
def testSingleModuleYamlLoadSave( self ) :
module = self.createSampleModule( 'm1' )
p = rm.ModulesParameter( self.registerMap )
p.value[ module[ 'name' ] ] = module
generatedYamlData = p.to_yamlData()
decodedModules = rm.ModulesParameter.from_yamlData(
generatedYamlData, self.registerMap, self.testMemory, self.acquiredFieldSet )
self.assertEqual( decodedModules.value[ 'm1' ][ 'description' ], p.value[ 'm1' ][ 'description' ] )
self.assertEqual( decodedModules.value[ 'm1' ][ 'name' ], p.value[ 'm1' ][ 'name' ] )
self.assertEqual( decodedModules.value[ 'm1' ][ 'summary' ], p.value[ 'm1' ][ 'summary' ] )
def createSampleModule( self, name ) :
module = rm.Module( self.testMemory, self.sourceFieldSet )
module[ 'name' ] = name
register = module.addRegister( 'r1' )
register.addField( 'f1', [ 3, 5 ], (3, 5) )
register.addField( 'f2', [ 7, 7 ], (7, 7) )
return module
def testFromOptionalYamlData( self ) :
yamlData = { 'mode' : 'ro' }
decodedModules = rm.ModulesParameter.from_yamlData(
yamlData, self.registerMap, self.testMemory, self.acquiredFieldSet,
optional = True )
self.assertEqual( len( decodedModules.value ), 0 )
if __name__ == '__main__' :
unittest.main()
PK hOr r # registerMap/constraints/__init__.py#
# Copyright 2017 Russell Smiley
#
# This file is part of registerMap.
#
# registerMap is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# registerMap is distributed in the hope that it will be useful
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with registerMap. If not, see .
#
from .constraints import \
AlignmentMemoryUnits, \
FixedAddress, \
FixedSizeMemoryUnits
from .constraintTable import \
ConstraintError, \
ConstraintTable
PK hOeo`k * registerMap/constraints/constraintTable.py#
# Copyright 2017 Russell Smiley
#
# This file is part of registerMap.
#
# registerMap is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# registerMap is distributed in the hope that it will be useful
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with registerMap. If not, see .
#
import collections
import logging
import registerMap.export.io.yaml.parameters.parse as ryp
import registerMap.utility.observer as rmo
from registerMap.export.io import yaml
from registerMap.exceptions import ConstraintError, ParseError
from .constraints import \
AbstractConstraint, \
AlignmentMemoryUnits, \
FixedAddress, \
FixedSizeMemoryUnits, \
validatePositive, \
validatePositiveNonZero
log = logging.getLogger( __name__ )
class ConstraintTable( yaml.Import, yaml.Export ) :
"""
Express constraints to be applied to RegisterMap, Module, Register or BitField.
The constraint table notifies registered observers about changes to address or size. The notifications are triggered
by user modification of a constraint in the table.
"""
VALID_CONSTRAINTS = collections.OrderedDict( [ ('fixedAddress', FixedAddress),
('alignmentMemoryUnits', AlignmentMemoryUnits),
('fixedSizeMemoryUnits', FixedSizeMemoryUnits) ] )
def __init__( self, memory,
validConstraints = None ) :
super().__init__()
self.addressChangeNotifier = rmo.Observable()
self.sizeChangeNotifier = rmo.Observable()
self.__memory = memory
self.__constraints = collections.OrderedDict()
self.__notifiers = {
'alignmentMemoryUnits' : self.addressChangeNotifier.notifyObservers,
'fixedAddress' : self.addressChangeNotifier.notifyObservers,
'fixedSizeMemoryUnits' : self.sizeChangeNotifier.notifyObservers
}
if validConstraints is None :
self.currentlyValidConstraints = self.VALID_CONSTRAINTS.keys()
else :
assert all( { x in self.VALID_CONSTRAINTS for x in validConstraints } ), \
'Constraints must be in the master constraint list, {0}'.format( validConstraints )
self.currentlyValidConstraints = validConstraints
@property
def isEmpty( self ) :
return len( self.__constraints ) == 0
def __delitem__( self, key ) :
log.debug( 'Deleting constraint, ' + repr( key ) )
self.__validateGetItem( key )
del self.__constraints[ key ]
self.__notifiers[ key ]( self )
def __getitem__( self, item ) :
self.__validateGetItem( item )
return self.__constraints[ item ].value
def __validateGetItem( self, item ) :
self.__validateConstraintName( item )
try :
self.__constraints[ item ]
except KeyError as e :
raise ConstraintError( 'Constraint not applied, {0}'.format( repr( item ) ) ) from e
def __len__( self ) :
return len( self.__constraints )
def __setitem__( self, key, value ) :
log.debug( 'Setting constraint value, ' + repr( key ) + ', ' + repr( value ) )
self.__validateConstraintName( key )
self.__constraints[ key ] = self.VALID_CONSTRAINTS[ key ]( self.__memory, value )
self.__validateAddressConstraintConsistency()
self.__notifiers[ key ]( key )
def __validateConstraintName( self, name ) :
if name not in self.VALID_CONSTRAINTS.keys() :
raise ConstraintError( 'Not a valid constraint, {0}'.format( name ) )
if name not in self.currentlyValidConstraints :
raise ConstraintError( 'Constraint has been excluded from this ConstraintTable, {0}'.format( name ) )
def __validateAddressConstraintConsistency( self ) :
if FixedAddress.name in self.__constraints.keys() :
testAddress = self.__constraints[ FixedAddress.name ].value
else :
testAddress = 0
collectedAddresses = [ ]
for constraint in self.__constraints.values() :
if constraint.type == AbstractConstraint.constraintTypes[ 'address' ] :
collectedAddresses.append( constraint.calculate( testAddress ) )
if not all( collectedAddresses[ 0 ] == x for x in collectedAddresses ) :
raise ConstraintError( 'Address constraints conflict' )
def applyAddressConstraints( self, addressValue ) :
newAddress = addressValue
for constraint in self.__constraints.values() :
if constraint.type == AbstractConstraint.constraintTypes[ 'address' ] :
newAddress = constraint.calculate( addressValue )
addressValue = newAddress
return newAddress
def applySizeConstraints( self, sizeValue ) :
newSize = sizeValue
for constraint in self.__constraints.values() :
if constraint.type == AbstractConstraint.constraintTypes[ 'size' ] :
newSize = constraint.calculate( sizeValue )
sizeValue = newSize
return newSize
@classmethod
def from_yamlData( cls, yamlData, memorySpace,
optional = False ) :
thisConstraints = cls( memorySpace )
goodResult = thisConstraints.__decodeConstraintTable( yamlData, memorySpace,
optional = optional )
if (not goodResult) and (not optional) :
raise ParseError( 'Processing constraint data failed. Check log for details. ' + repr( yamlData ) )
return thisConstraints
def __decodeConstraintTable( self, yamlData, memorySpace,
optional = False ) :
def recordConstraint( name, value ) :
nonlocal self
self[ name ] = value
def getParameters( thisData ) :
nonlocal self, memorySpace
# All constraints are optional
# Expecting a list of constraints
for constraintClass in self.VALID_CONSTRAINTS.values() :
constraint = constraintClass.from_yamlData( thisData, memorySpace,
optional = True )
if constraint is not None :
self.__constraints[ constraint.name ] = constraint
return True
keyName = 'constraints'
return ryp.complexParameter( yamlData, keyName, getParameters,
optional = optional )
def to_yamlData( self ) :
parameters = list()
for constraint in self.__constraints.values() :
parameters.append( constraint.to_yamlData() )
keyName = 'constraints'
yamlData = { keyName : { } }
for thisParameter in parameters :
yamlData[ keyName ].update( thisParameter )
return yamlData
PK hO2'eD) D) &