diff --git a/silecs-codegen/src/xml/fesa/fesa_3_0_0/fesaTemplates.py b/silecs-codegen/src/xml/fesa/fesa_3_0_0/fesaTemplates.py index 916a6376f44dc5c75795b6e5e649cc9ac475c4c0..f5709632cd4ceac1c9d92e9f5b3be3d764ccbc89 100644 --- a/silecs-codegen/src/xml/fesa/fesa_3_0_0/fesaTemplates.py +++ b/silecs-codegen/src/xml/fesa/fesa_3_0_0/fesaTemplates.py @@ -14,9 +14,6 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. -import iecommon -import time - #========================================================================= # FESA .cproject file #========================================================================= diff --git a/silecs-codegen/src/xml/fesa/fesa_3_0_0/generateFesaDesign.py b/silecs-codegen/src/xml/fesa/fesa_3_0_0/generateFesaDesign.py index 685f78aa5a882b8e3185cdcf24e05050bed57c17..9f0dc32e6a44b990fdc8d160bf9f77ae786ced40 100644 --- a/silecs-codegen/src/xml/fesa/fesa_3_0_0/generateFesaDesign.py +++ b/silecs-codegen/src/xml/fesa/fesa_3_0_0/generateFesaDesign.py @@ -26,13 +26,13 @@ import datetime import socket import iecommon -import fesaGeneral import fesaTemplates import iefiles from iecommon import * from fesaGeneral import * from model.Register import DesignRegister +from model.Block import DesignBlock import libxml2 @@ -87,8 +87,7 @@ class FESADesignGenerator3_0_0(object): fillAttributes(scalarNode, {'type': register.getFesaType()}) return scalarNode - def getOrCreateType(self,fieldNode,registerNode): - register = DesignRegister(registerNode) + def getOrCreateType(self,fieldNode,register): if register.valueType == "scalar": return self.getOrCreateScalarType(fieldNode,register) elif register.valueType == "array": @@ -192,11 +191,11 @@ class FESADesignGenerator3_0_0(object): fillAttributes(getActionNode, {'implementation': implementation}) def getOrCreateFieldNode(self,parent,register): #in order to place them before any GSI-specifc fields (order matters!) - iecommon.logDebug('Generating Data-Field for register: ' + register.prop('name'), {'debuglog': True}) + iecommon.logDebug('Generating Data-Field for register: ' + register.name, {'debuglog': True}) if( hasChildren(parent) ): - return getOrCreateNamedPreviousSiblingElement(parent,getFirstChild(parent),'field',getFesaName(register)) + return getOrCreateNamedPreviousSiblingElement(parent,getFirstChild(parent),'field',register.getFesaFieldName()) else: - return getOrCreateNamedChildElement(parent,'field',getFesaName(register)) + return getOrCreateNamedChildElement(parent,'field',register.getFesaFieldName()) def getOrCreatePLCHostNameField(self,configurationNode): fieldNode = getOrCreateNamedFirstChild(configurationNode,'field','plcHostName') @@ -243,59 +242,59 @@ class FESADesignGenerator3_0_0(object): return fieldNode def getOrCreateRegisterValueItems(self,prop,block,isSetting): - for register in block.xpathEval('Register'): - if register.prop('generateFesaValueItem') == 'true': + for register in block.getDesignRegisters(): + if register.generateFesaValueItem: self.getOrCreateValueItem(prop,register,isSetting) def getOrCreateSettingProperty(self,parent,block): - iecommon.logDebug('Generating SettingProperty for Block: ' + block.prop('name'), {'debuglog': True}) + iecommon.logDebug('Generating SettingProperty for Block: ' + block.name, {'debuglog': True}) if( hasChildren(parent)): propsAfterCommand = parent.xpathEval("*[not(name()='command-property')]") - prop = getOrCreateNamedPreviousSiblingElement(parent,propsAfterCommand[0], 'setting-property',getFesaName(block)) + prop = getOrCreateNamedPreviousSiblingElement(parent,propsAfterCommand[0], 'setting-property',block.getFesaName()) else: - prop = getOrCreateNamedChildElement(parent,'setting-property',getFesaName(block)) + prop = getOrCreateNamedChildElement(parent,'setting-property',block.getFesaName()) self.getOrCreateRegisterValueItems(prop,block,True) self.getOrCreateUpdateFlagItem(prop) self.getOrCreateCyleNameItem(prop) return prop def getOrCreateAcquisitionProperty(self,parent,actionsNode,block): - iecommon.logDebug('Generating AcquisitionProperty for Block: ' + block.prop('name'), {'debuglog': True}) + iecommon.logDebug('Generating AcquisitionProperty for Block: ' + block.name, {'debuglog': True}) prop = "" if( hasChildren(parent)): - prop = getOrCreateNamedPreviousSiblingElement(parent,getFirstChild(parent), 'acquisition-property',getFesaName(block)) + prop = getOrCreateNamedPreviousSiblingElement(parent,getFirstChild(parent), 'acquisition-property',block.getFesaName()) else: - prop = getOrCreateNamedChildElement(parent,'acquisition-property',getFesaName(block)) + prop = getOrCreateNamedChildElement(parent,'acquisition-property',block.getFesaName()) fillAttributes(prop, {'visibility': 'development', 'subscribable': 'true', 'multiplexed': 'false', 'on-change': 'true'}) self.getOrCreateRegisterValueItems(prop,block,False) self.getOrCreateAcqStampItem(prop) self.getOrCreateUpdateFlagItem(prop) self.getOrCreateCyleNameItem(prop) self.getOrCreateCyleStampItem(prop) - self.getOrCreateAction(prop,'Get'+getFesaName(block),'get',actionsNode,'default') + self.getOrCreateAction(prop,'Get'+block.getFesaName(),'get',actionsNode,'default') return prop def getOrCreateGSISettingProperty(self,parent,block): - iecommon.logDebug('Generating GSISettingProperty for Block: ' + block.prop('name'), {'debuglog': True}) + iecommon.logDebug('Generating GSISettingProperty for Block: ' + block.name, {'debuglog': True}) powerProp = parent.xpathEval('GSI-Power-Property')[0] # template is used --> there has to be a power prop - prop = getOrCreateNamedPreviousSiblingElement(parent,powerProp, 'GSI-Setting-Property',getFesaName(block)) + prop = getOrCreateNamedPreviousSiblingElement(parent,powerProp, 'GSI-Setting-Property',block.getFesaName()) self.getOrCreateRegisterValueItems(prop,block,True) self.getOrCreateUpdateFlagItem(prop) self.getOrCreateCyleNameItem(prop) return prop def getOrCreateGSIAcquisitionProperty(self,parent,actionsNode,block): - iecommon.logDebug('Generating GSIAcquisitionProperty for Block: ' + block.prop('name'), {'debuglog': True}) + iecommon.logDebug('Generating GSIAcquisitionProperty for Block: ' + block.name, {'debuglog': True}) versionProp = parent.xpathEval('GSI-Version-Property')[0] # template is used --> there has to be a version prop - prop = getOrCreateNamedPreviousSiblingElement(parent,versionProp, 'GSI-Acquisition-Property',getFesaName(block)) + prop = getOrCreateNamedPreviousSiblingElement(parent,versionProp, 'GSI-Acquisition-Property',block.getFesaName()) fillAttributes(prop, {'visibility': 'development', 'subscribable': 'true', 'multiplexed': 'false', 'on-change': 'true'}) self.getOrCreateRegisterValueItems(prop,block,False) self.getOrCreateAcqStampItem(prop) self.getOrCreateUpdateFlagItem(prop) self.getOrCreateCyleNameItem(prop) self.getOrCreateCyleStampItem(prop) - self.getOrCreateAction(prop,'Get'+getFesaName(block),'get',actionsNode,'default') + self.getOrCreateAction(prop,'Get'+block.getFesaName(),'get',actionsNode,'default') self.getOrCreateAcquisitionContextItem(prop) return prop @@ -314,21 +313,21 @@ class FESADesignGenerator3_0_0(object): return self.getOrCreateAcquisitionProperty(parent,actionsNode,block) def getOrCreateValueItem(self,propertyNode,register,isSetting): - iecommon.logDebug('Generating ValueItem for Register: ' + register.prop('name'), {'debuglog': True}) - result = propertyNode.xpathEval("value-item[@name='" + getFesaName(register) + "']") + iecommon.logDebug('Generating ValueItem for Register: ' + register.name, {'debuglog': True}) + result = propertyNode.xpathEval("value-item[@name='" + register.getFesaFieldName() + "']") if len(result): return result[0] if( hasChildren(propertyNode)): result = propertyNode.xpathEval("*[not(name()='description') and not(name()='export') and not(name()='filter-item')]") # skip possible first elements to get right position - valueItemNode = getOrCreateNamedPreviousSiblingElement(propertyNode,result[0],'value-item',getFesaName(register)) + valueItemNode = getOrCreateNamedPreviousSiblingElement(propertyNode,result[0],'value-item',register.getFesaFieldName()) else: - valueItemNode = getOrCreateNamedChildElement(propertyNode,'value-item',getFesaName(register)) + valueItemNode = getOrCreateNamedChildElement(propertyNode,'value-item',register.getFesaFieldName()) if isSetting: fillAttributes(valueItemNode, {'direction': 'INOUT'}) else: fillAttributes(valueItemNode, {'direction': 'OUT'}) self.getOrCreateType(valueItemNode,register) - self.getOrCreateFieldRef(valueItemNode,getFesaName(register)) + self.getOrCreateFieldRef(valueItemNode,register.getFesaFieldName()) #------------------------------------------------------------------------- # Generates the data node of the FESA design document @@ -348,37 +347,31 @@ class FESADesignGenerator3_0_0(object): classNode = silecsRoot.xpathEval('//SILECS-Class')[0] self.getOrCreateParameterFileField(configurationNode) # parse the SILECS design document to find the blocks - for block in silecsRoot.xpathEval("//Block"): # loop over the blocks - iecommon.logDebug('Analysing block '+block.prop('name'), logTopics) - # Check that every register in the block has the same value for synchro - regList = block.xpathEval("Register") - for r in range (0, len(regList)-1): - if regList[r].prop('synchro') != regList[r+1].prop('synchro'): - # Return error and exit - iecommon.logError('ERROR: In block '+block.prop('name')+' registers have different synchronisation values.', True, logTopics) + for blockNode in silecsRoot.xpathEval("//Block"): # loop over the blocks + block = DesignBlock(blockNode) - if block.prop('mode') == 'READ-ONLY': - for reg in regList: + if block.isAcquisition(): + for reg in block.getDesignRegisters(): fieldNode = self.getOrCreateFieldNode(acquisitionNode,reg) - if reg.prop('synchro') == 'MASTER': # the value of a master register never change, consistency is not required + if reg.isAcquisition(): fillAttributes(fieldNode, {'multiplexed': 'false', 'persistent': 'false'}) - elif reg.prop('synchro') == 'NONE': + elif reg.isVolatile(): fillAttributes(fieldNode, {'multiplexed': 'false', 'persistent': 'false'}) self.getOrCreateType(fieldNode,reg) - elif block.prop('mode') == 'WRITE-ONLY': - for reg in regList: + elif block.isCommand(): + for reg in block.getDesignRegisters(): fieldNode = self.getOrCreateFieldNode(settingNode,reg) - if reg.prop('synchro') == 'SLAVE': + if reg.isSetting(): fillAttributes(fieldNode, {'multiplexed': 'false', 'persistent': 'true', 'shared': 'true'}) - elif reg.prop('synchro') == 'NONE': + elif reg.isVolatile(): fillAttributes(fieldNode, {'multiplexed': 'false', 'persistent': 'false', 'shared': 'true'}) self.getOrCreateType(fieldNode,reg) - else: # READ-WRITE block - for reg in regList: + else: # Setting Block + for reg in block.getDesignRegisters(): fieldNode = self.getOrCreateFieldNode(settingNode,reg) - if reg.prop('synchro') == 'NONE': + if reg.isVolatile(): fillAttributes(fieldNode, {'multiplexed': 'false', 'persistent': 'false'}) else: #synchro SLAVE and MASTER fillAttributes(fieldNode, {'multiplexed': 'false', 'persistent': 'true'}) @@ -407,26 +400,26 @@ class FESADesignGenerator3_0_0(object): settingNode = getOrCreateChildElement(deviceInterfaceNode,'setting') acquisitionNode = getOrCreateChildElement(deviceInterfaceNode,'acquisition') actionsNode = doc.xpathEval('/equipment-model/actions')[0] - for block in silecsRoot.xpathEval("//Block"): - - if block.prop('generateFesaProperty') == 'false': + for blockNode in silecsRoot.xpathEval("//Block"): + block = DesignBlock(blockNode) + if not block.generateFesaProperty: continue #skip this block - if block.prop('mode') in ('READ-ONLY'): + if block.mode == ('READ-ONLY'): self.getOrCreateFESAProperty(acquisitionNode,actionsNode,block) - rtAction = getOrCreateNamedChildElement(actionsNode,'rt-action','Recv'+getFesaName(block)) - notifiedProperty = getOrCreateNamedChildElement(rtAction,'notified-property',getFesaName(block),'property-name-ref') + rtAction = getOrCreateNamedChildElement(actionsNode,'rt-action','Recv'+ block.getFesaName()) + notifiedProperty = getOrCreateNamedChildElement(rtAction,'notified-property', block.getFesaName(),'property-name-ref') fillAttributes(notifiedProperty, {'automatic': 'true'}) self.genEvent(block,doc,logTopics) self.genSchedulingUnit(block,doc,logTopics) else: # setting property for both WO and RW blocks, w/get+set server action settingPropertyNode = self.getOrCreateFESAProperty(settingNode, actionsNode, block) fillAttributes(settingPropertyNode, {'visibility': 'development', 'multiplexed': 'false'}) - self.getOrCreateAction(settingPropertyNode,'Send'+getFesaName(block),'set',actionsNode,'custom') - if block.prop('mode') == 'READ-WRITE': - self.getOrCreateAction(settingPropertyNode,'Recv'+getFesaName(block),'get',actionsNode,'custom') + self.getOrCreateAction(settingPropertyNode,'Send'+block.getFesaName(),'set',actionsNode,'custom') + if block.mode == 'READ-WRITE': + self.getOrCreateAction(settingPropertyNode,'Recv'+block.getFesaName(),'get',actionsNode,'custom') else: # WRITE-ONLY - self.getOrCreateAction(settingPropertyNode,'Get'+getFesaName(block),'get',actionsNode,'default') + self.getOrCreateAction(settingPropertyNode,'Get'+block.getFesaName(),'get',actionsNode,'default') #------------------------------------------------------------------------- # Generates the logical-events node of the FESA design @@ -440,7 +433,7 @@ class FESADesignGenerator3_0_0(object): timingSourceNode = getOrCreateNamedChildElement(sourcesNode,'timing-event-source','Timing') timerSourceNode = getOrCreateNamedChildElement(sourcesNode,'timer-event-source','Timer') logicalEventsNode = getOrCreateChildElement(eventsNode,'logical-events') - logicalEventNode = getOrCreateNamedChildElement(logicalEventsNode,'logical-event','Recv'+getFesaName(block)+'Event') + logicalEventNode = getOrCreateNamedChildElement(logicalEventsNode,'logical-event','Recv'+block.getFesaName()+'Event') fillAttributes(logicalEventNode, {'type': 'timer', 'use': 'required'}) #------------------------------------------------------------------------- @@ -451,11 +444,11 @@ class FESADesignGenerator3_0_0(object): iecommon.logDebug('Generating scheduling unit', logTopics) eqpModelNode = fesaRoot.xpathEval("/equipment-model")[0] schedulingUnitsNode = getOrCreateChildElement(eqpModelNode,'scheduling-units') - schedulingUnitNode = getOrCreateNamedChildElement(schedulingUnitsNode,'scheduling-unit','Recv'+getFesaName(block)+'Unit') + schedulingUnitNode = getOrCreateNamedChildElement(schedulingUnitsNode,'scheduling-unit','Recv'+block.getFesaName()+'Unit') rtActionRefNode = getOrCreateChildElement(schedulingUnitNode,'rt-action-ref') - fillAttributes(rtActionRefNode, {'rt-action-name-ref': 'Recv'+getFesaName(block)}) + fillAttributes(rtActionRefNode, {'rt-action-name-ref': 'Recv'+block.getFesaName()}) logicalEventRefNode = getOrCreateChildElement(schedulingUnitNode,'logical-event-ref') - fillAttributes(logicalEventRefNode, {'logical-event-name-ref': 'Recv'+getFesaName(block)+'Event'}) + fillAttributes(logicalEventRefNode, {'logical-event-name-ref': 'Recv'+block.getFesaName()+'Event'}) #------------------------------------------------------------------------- # Generates the scheduling-units node of the FESA design diff --git a/silecs-codegen/src/xml/fesa/fesa_3_0_0/generateSourceCode.py b/silecs-codegen/src/xml/fesa/fesa_3_0_0/generateSourceCode.py index d79b74f1d29c00ed2da756aff3957e0f41d4edb1..f92e9cba09b132cfebe1b5f0d848dbf6bf36cb56 100644 --- a/silecs-codegen/src/xml/fesa/fesa_3_0_0/generateSourceCode.py +++ b/silecs-codegen/src/xml/fesa/fesa_3_0_0/generateSourceCode.py @@ -30,7 +30,8 @@ import iefiles from iecommon import * from fesaGeneral import * -from model.Register import * +from model.Register import DesignRegister +from model.Block import DesignBlock import libxml2 def findBlockServerSetActionName(fesaRoot, blockName): @@ -47,25 +48,28 @@ def findBlockServerSetActionName(fesaRoot, blockName): def genHSource(className, silecsRoot, fesaRoot, sourcePath,logTopics): source = fesaTemplates.genHTop(className) - for block in silecsRoot.xpathEval('//Block'): - if block.prop('mode') == 'WRITE-ONLY' or block.prop('mode') == 'READ-WRITE': - serverActionName = findBlockServerSetActionName(fesaRoot,getFesaName(block)) + for blockNode in silecsRoot.xpathEval('//Block'): + block = DesignBlock(blockNode) + if block.isWritable(): + serverActionName = findBlockServerSetActionName(fesaRoot,block.getFesaName()) source += fesaTemplates.genHTopBlock(className, serverActionName) source += fesaTemplates.genHTop2(className) - for block in silecsRoot.xpathEval('//Block'): - if block.prop('mode') == 'READ-ONLY': - source += fesaTemplates.genHBlock('RO', block.prop('name'),getFesaName(block) ) - elif block.prop('mode') == 'WRITE-ONLY': - source += fesaTemplates.genHBlock('WO', block.prop('name'),getFesaName(block)) - else: # READ-WRITE - source += fesaTemplates.genHBlock('RW', block.prop('name'),getFesaName(block)) + for blockNode in silecsRoot.xpathEval('//Block'): + block = DesignBlock(blockNode) + if block.isAcquisition(): + source += fesaTemplates.genHBlock('RO', block.name,block.getFesaName() ) + elif block.isCommand(): + source += fesaTemplates.genHBlock('WO', block.name,block.getFesaName()) + else: # Setting + source += fesaTemplates.genHBlock('RW', block.name,block.getFesaName()) source += fesaTemplates.genHBottom(className) - for block in silecsRoot.xpathEval('//Block'): - source += fesaTemplates.genHDeclBlocks(block.prop('name')) + for blockNode in silecsRoot.xpathEval('//Block'): + block = DesignBlock(blockNode) + source += fesaTemplates.genHDeclBlocks(block.name) source += fesaTemplates.genHClosing(className) @@ -92,40 +96,43 @@ def genHSource(className, silecsRoot, fesaRoot, sourcePath,logTopics): def genCppSource(className, silecsRoot, fesaRoot, sourcePath,logTopics): finalSource = fesaTemplates.genCTop(className) blockList = silecsRoot.xpathEval('//Block') - for block in blockList: - finalSource += fesaTemplates.genCGlobal(className, block.prop('name')) + for blockNode in blockList: + block = DesignBlock(blockNode) + finalSource += fesaTemplates.genCGlobal(className, block.name) finalSource += fesaTemplates.genCPart1(className) - for block in blockList: - finalSource += fesaTemplates.genCBlockConstr(block.prop('name'), className) + for blockNode in blockList: + block = DesignBlock(blockNode) + finalSource += fesaTemplates.genCBlockConstr(block.name, className) finalSource += fesaTemplates.genCPart2(className) - for block in blockList: - if (block.prop('mode') == 'WRITE-ONLY' or block.prop('mode') == 'READ-WRITE'): + for blockNode in blockList: + block = DesignBlock(blockNode) + if (block.isWritable()): # just set the fields if block is WO or RW and register synchronisation is SLAVE # WARNING: In order to have multiplexed FESA fields, the corresponding SILECS registers' synchro mode must be 'NONE' - finalSource += fesaTemplates.genCSetPLC(className, block.prop('name')) + finalSource += fesaTemplates.genCSetPLC(className, block.name) finalSource += fesaTemplates.genCPart3(className) - for block in blockList: - - if (block.prop('mode') == 'READ-ONLY' or block.prop('mode') == 'READ-WRITE'): + for blockNode in blockList: + block = DesignBlock(blockNode) + if (block.isReadable()): # just get the fields if block is RO or RW and register synchronisation is MASTER # WARNING: In order to have multiplexed FESA fields, the corresponding SILECS registers' synchro mode must be 'NONE' - finalSource += fesaTemplates.genCGetPLC(className, block.prop('name')) + finalSource += fesaTemplates.genCGetPLC(className, block.name) finalSource += fesaTemplates.genCPart4(className) - for block in blockList: - if block.prop('mode') != 'WRITE-ONLY': - finalSource += fesaTemplates.genCCommonGet(block.prop('name'),className) + for blockNode in blockList: + block = DesignBlock(blockNode) + if block.isReadable(): + finalSource += fesaTemplates.genCCommonGet(block.name,className) finalSource += '\n' finalSource += fesaTemplates.cRecv - for registerNode in block.xpathEval('Register'): - register = DesignRegister(registerNode) + for register in block.getDesignRegisters(): if register.valueType == 'string': finalSource += fesaTemplates.genCGetStringReg(register) elif register.valueType == 'stringArray': @@ -140,10 +147,9 @@ def genCppSource(className, silecsRoot, fesaRoot, sourcePath,logTopics): finalSource += fesaTemplates.genCGetArray2DReg(register) finalSource += '\n }\n' - if block.prop('mode') != 'READ-ONLY': - finalSource += fesaTemplates.genCCommonSet(block.prop('name'),className) - for registerNode in block.xpathEval('Register'): - register = DesignRegister(registerNode) + if block.isWritable(): + finalSource += fesaTemplates.genCCommonSet(block.name,className) + for register in block.getDesignRegisters(): if register.valueType == 'string': finalSource += fesaTemplates.genCSetStringReg(register) elif register.valueType == 'stringArray': @@ -158,10 +164,9 @@ def genCppSource(className, silecsRoot, fesaRoot, sourcePath,logTopics): finalSource += fesaTemplates.genCSetArray2DReg(register) finalSource += fesaTemplates.cSend finalSource += ' }\n' - finalSource += fesaTemplates.genCDatatypeSet(block.prop('name'),getFesaName(block), className) + finalSource += fesaTemplates.genCDatatypeSet(block.name,block.getFesaName(), className) - for registerNode in block.xpathEval('Register'): - register = DesignRegister(registerNode) + for register in block.getDesignRegisters(): if register.valueType == 'string': finalSource += fesaTemplates.genCSetStringRegData(register) elif register.valueType == 'stringArray': diff --git a/silecs-codegen/src/xml/genduwrapper.py b/silecs-codegen/src/xml/genduwrapper.py index 05b7501418d1ae74ebc6f28d5eeccb382f88efc4..8351988e961a7947cac80f4bcb973e0cbdcba018 100644 --- a/silecs-codegen/src/xml/genduwrapper.py +++ b/silecs-codegen/src/xml/genduwrapper.py @@ -25,32 +25,7 @@ import genduwrappertemplate from iecommon import * from model.Register import DesignRegister - -#========================================================================= -# Sub-functions -#========================================================================= - -def extractBlockList(designDOM): - blockList = [] - for blockNode in designDOM.xpathEval("//Block"): - blockList.append([blockNode.prop("name"), blockNode.prop("mode")]) - return blockList - -def getRegisterList(designFile,blockName): - '''Return the list of register included in a given block. - for each register a the following tuple is returned: [name,format,dim1,dim2] - ''' - registerList = [] - dom = libxml2.parseFile(designFile) - blockNodeList = dom.xpathEval("//Block") - for blockNode in blockNodeList: - if blockNode.prop("name")==blockName: - break #after the loop blockNode will point to the good node - - for registerNode in blockNode.xpathEval("Register"): - register = DesignRegister(registerNode) - registerList.append([register.name,register.format,register.dim1,register.dim2]) - return registerList +from model.Block import DesignBlock def genClassHeader(workspacePath, deployName, classNode, funcGetSilecsDesignFilePath, funcGetDuDesignWrapperFile, logTopics): designName = classNode.prop("silecs-design-name") @@ -59,23 +34,23 @@ def genClassHeader(workspacePath, deployName, classNode, funcGetSilecsDesignFile designDOM = libxml2.parseFile(designFile) if(not os.path.isfile(designFile)): raise Exception("File not found: " + designFile) - blockList = extractBlockList(designDOM) + blockList = designDOM.xpathEval("//Block") classDeclarations = "" #construct Block class - for [blockName,blockMode] in blockList: - registerList = getRegisterList(designFile,blockName) - registerInitializerList = genduwrappertemplate.getBlockInitializerList(registerList) - registerGetterSetter = genduwrappertemplate.getRegisterGetterSetter(blockName,blockMode,registerList) - registersDimentionsDeclaration = genduwrappertemplate.getRegistersDimetionsDeclaration(registerList) - registersDeclaration = genduwrappertemplate.getRegistersDeclaration(registerList) - classDeclarations += genduwrappertemplate.getBlockClass(blockName,registerInitializerList,registerGetterSetter,registersDimentionsDeclaration,registersDeclaration) + for blockNode in blockList: + block = DesignBlock(blockNode) + registerInitializerList = genduwrappertemplate.getBlockInitializerList(block) + registerGetterSetter = genduwrappertemplate.getRegisterGetterSetter(block) + registersDimentionsDeclaration = genduwrappertemplate.getRegistersDimetionsDeclaration(block) + registersDeclaration = genduwrappertemplate.getRegistersDeclaration(block) + classDeclarations += genduwrappertemplate.getBlockClass(block,registerInitializerList,registerGetterSetter,registersDimentionsDeclaration,registersDeclaration) blockGetters = "" sendRecvBlocks = genduwrappertemplate.getDeviceSendRecvBlocks(blockList) - for [blockName,mode] in blockList: - registerList = getRegisterList(designFile,blockName) - blockGetters += genduwrappertemplate.getDeviceBlockGetterSetter(blockName, mode, registerList) + for blockNode in blockList: + block = DesignBlock(blockNode) + blockGetters += genduwrappertemplate.getDeviceBlockGetterSetter(block) classDeclarations += genduwrappertemplate.getDeviceClass(blockGetters,sendRecvBlocks) diff --git a/silecs-codegen/src/xml/genduwrappertemplate.py b/silecs-codegen/src/xml/genduwrappertemplate.py index 8f5814902a33717a3e4fa572ce11afe9c13bfb57..af7cf950d9fd644e022ae3bef26d7ca69f0bbc44 100644 --- a/silecs-codegen/src/xml/genduwrappertemplate.py +++ b/silecs-codegen/src/xml/genduwrappertemplate.py @@ -16,6 +16,8 @@ import string import iecommon +from model.Register import DesignRegister +from model.Block import DesignBlock #================================================================= # Deploy Unit Class @@ -233,12 +235,13 @@ designSendTemplate = string.Template("""\ def getDesignSendRecvBlocks(blockList): text = "" - for [blockName,mode] in blockList: - map = {'blockName' : blockName, - 'blockNameCapitalized' : iecommon.capitalizeString(blockName)} - if mode == 'READ-ONLY' or mode == 'READ-WRITE': + for blockNode in blockList: + block = DesignBlock(blockNode) + map = {'blockName' : block.name, + 'blockNameCapitalized' : block.getNameCapitalized()} + if block.isReadable(): text += designReceiveTemplate.substitute(map) - if mode == 'WRITE-ONLY' or mode == 'READ-WRITE': + if block.isWritable(): text += designSendTemplate.substitute(map) return text @@ -336,12 +339,13 @@ controllerSendTemplate = string.Template("""\ def getControllerSendRecvBlocks(blockList): text = "" - for [blockName,mode] in blockList: - map = {'blockName' : blockName, - 'blockNameCapitalized' : iecommon.capitalizeString(blockName)} - if mode == 'READ-ONLY' or mode == 'READ-WRITE': + for blockNode in blockList: + block = DesignBlock(blockNode) + map = {'blockName' : block.name, + 'blockNameCapitalized' : block.getNameCapitalized()} + if block.isReadable(): text += controllerReceiveTemplate.substitute(map) - if mode == 'WRITE-ONLY' or mode == 'READ-WRITE': + if block.isWritable(): text += controllerSendTemplate.substitute(map) return text @@ -436,61 +440,43 @@ scalarRegisterAssignementSetter = string.Template("""\ getSilecsDevice()->getRegister("${regName}")->setVal${silecsTypeCapitalized}(block.get${regNameCapitalized}()); """) -def getDeviceBlockGetterSetter(blockName, blockMode, registerList): +def getDeviceBlockGetterSetter(block): text = "" - if blockMode == 'READ-ONLY' or blockMode == 'READ-WRITE': + if block.isReadable(): blockInitialization = "" - for [name,format,dim1,dim2] in registerList: - silecsType = iecommon.getSilecsDataType(format) - if silecsType[0] == 'u': - silecsTypeCapitalized = silecsType[:2].upper() + silecsType[2:] - else: - silecsTypeCapitalized = iecommon.capitalizeString(silecsType) - - map = {'regName' : name, - 'regNameCapitalized' : iecommon.capitalizeString(name), - 'silecsTypeCapitalized' : silecsTypeCapitalized, - 'cType' : iecommon.getCDataType(format)} - if dim2 > 1: - #matrix + for register in block.getDesignRegisters(): + map = {'regName' : register.name, + 'regNameCapitalized' : register.getNameCapitalized(), + 'silecsTypeCapitalized' : register.getSilecsTypeCapitalized(), + 'cType' : register.getCType()} + if register.isArray2D(): blockInitialization += matrixRegisterAssignementGetter.substitute(map) - elif dim1 > 1: - #array + elif register.isArray(): blockInitialization += arrayRegisterAssignementGetter.substitute(map) - else: - #scalar + else: #scalar blockInitialization += scalarRegisterAssignementGetter.substitute(map) - blockMap = {'blockName' : blockName, + blockMap = {'blockName' : block.name, 'blockInitialization' : blockInitialization, - 'blockNameCapitalized' : iecommon.capitalizeString(blockName)} + 'blockNameCapitalized' : block.getNameCapitalized()} text += blockGetterTemplate.substitute(blockMap) - if blockMode == 'WRITE-ONLY' or blockMode == 'READ-WRITE': + if block.isWritable(): blockInitialization = "" - for [name,format,dim1,dim2] in registerList: - silecsType = iecommon.getSilecsDataType(format) - if silecsType[0] == 'u': - silecsTypeCapitalized = silecsType[:2].upper() + silecsType[2:] - else: - silecsTypeCapitalized = iecommon.capitalizeString(silecsType) - - map = {'regName' : name, - 'regNameCapitalized' : iecommon.capitalizeString(name), - 'silecsTypeCapitalized' : silecsTypeCapitalized, - 'cType' : iecommon.getCDataType(format)} - if dim2 > 1: - #matrix + for register in block.getDesignRegisters(): + map = {'regName' : register.name, + 'regNameCapitalized' : register.getNameCapitalized(), + 'silecsTypeCapitalized' : register.getSilecsTypeCapitalized(), + 'cType' : register.getCType()} + if register.isArray2D(): blockInitialization += matrixRegisterAssignementSetter.substitute(map) - elif dim1 > 1: - #array + elif register.isArray(): blockInitialization += arrayRegisterAssignementSetter.substitute(map) - else: - #scalar + else: #scalar blockInitialization += scalarRegisterAssignementSetter.substitute(map) - blockMap = {'blockName' : blockName, + blockMap = {'blockName' : block.name, 'blockInitialization' : blockInitialization, - 'blockNameCapitalized' : iecommon.capitalizeString(blockName)} + 'blockNameCapitalized' : block.getNameCapitalized()} text += blockSetterTemplate.substitute(blockMap) return text @@ -518,12 +504,13 @@ deviceSendTemplate = string.Template("""\ def getDeviceSendRecvBlocks(blockList): text = "" - for [blockName,mode] in blockList: - map = {'blockName' : blockName, - 'blockNameCapitalized' : iecommon.capitalizeString(blockName)} - if mode == 'READ-ONLY' or mode == 'READ-WRITE': + for blockNode in blockList: + block = DesignBlock(blockNode) + map = {'blockName' : block.name, + 'blockNameCapitalized' : block.getNameCapitalized()} + if block.isReadable(): text += deviceReceiveTemplate.substitute(map) - if mode == 'WRITE-ONLY' or mode == 'READ-WRITE': + if block.isWritable(): text += deviceSendTemplate.substitute(map) return text @@ -553,10 +540,10 @@ ${registersDeclaration} }; """) -def getBlockClass(blockName,registerInitializerList,registerGetterSetter,registersDimentionsDeclaration,registersDeclaration): - map = {'blockName' : blockName, +def getBlockClass(block,registerInitializerList,registerGetterSetter,registersDimentionsDeclaration,registersDeclaration): + map = {'blockName' : block.name, 'registerInitializerList' : registerInitializerList, - 'blockNameCapitalized' : iecommon.capitalizeString(blockName), + 'blockNameCapitalized' : block.getNameCapitalized(), 'registerGetterSetter' : registerGetterSetter, 'registersDimentionsDeclaration' : registersDimentionsDeclaration, 'registersDeclaration' : registersDeclaration} @@ -566,11 +553,11 @@ registerInitializerListTemplate = string.Template("""\ , ${registerName}(0)""") -def getBlockInitializerList(regList): +def getBlockInitializerList(block): text = "" - for [name,format,dim1,dim2] in regList: - if format != 'string' and dim1 == 1 and dim2 == 1: - text += registerInitializerListTemplate.substitute({'registerName' : name}) + for register in block.getDesignRegisters(): + if register.isScalar(): + text += registerInitializerListTemplate.substitute({'registerName' : register.name}) return text @@ -668,26 +655,25 @@ scalarRegisterSetterTemplate = string.Template(""" } """) -def getRegisterGetterSetter(blockName,blockMode,regList): +def getRegisterGetterSetter(block): text = "" - for [name,format,dim1,dim2] in regList: - cType = iecommon.getCDataType(format) - map = {'registerName' : name, - 'registerNameCapitalized' : iecommon.capitalizeString(name), - 'cType' : iecommon.getCDataType(format)} + for register in block.getDesignRegisters(): + map = {'registerName' : register.name, + 'registerNameCapitalized' : register.getNameCapitalized(), + 'cType' : register.getCType()} - if dim2 > 1: + if register.isArray2D(): text += matrixRegisterGetterTemplate.substitute(map) text += matrixRegisterSetterTemplate.substitute(map) - elif dim1 > 1: - if format == 'string': + elif register.isArray(): + if register.isStringType(): text += stringArrayRegisterGetterTemplate.substitute(map) text += stringArrayRegisterSetterTemplate.substitute(map) else: text += arrayRegisterGetterTemplate.substitute(map) text += arrayRegisterSetterTemplate.substitute(map) else: - if format == 'string': + if register.isStringType(): map['cType'] = "const std::string&" text += scalarRegisterGetterTemplate.substitute(map) text += scalarRegisterSetterTemplate.substitute(map) @@ -697,20 +683,20 @@ registersDimetionsDeclarationTemplate = string.Template("""\ static const std::size_t ${registerName}Dim${index} = ${dimention}; """) -def getRegistersDimetionsDeclaration(regList): +def getRegistersDimetionsDeclaration(block): text = "" - for [name,format,dim1,dim2] in regList: - map = {'registerName' : name} - if dim2 > 1: + for register in block.getDesignRegisters(): + map = {'registerName' : register.name} + if register.isArray2D(): map['index'] = "2" - map['dimention'] = dim2 + map['dimention'] = register.dim2 text += registersDimetionsDeclarationTemplate.substitute(map) map['index'] = "1" - map['dimention'] = dim1 + map['dimention'] = register.dim1 text += registersDimetionsDeclarationTemplate.substitute(map) - elif dim1 > 1: + elif register.isArray(): map['index'] = "1" - map['dimention'] = dim1 + map['dimention'] = register.dim1 text += registersDimetionsDeclarationTemplate.substitute(map) return text @@ -726,14 +712,14 @@ scalarRegistersDeclarationTemplate = string.Template("""\ ${cType} ${registerName}; """) -def getRegistersDeclaration(regList): +def getRegistersDeclaration(block): text = "" - for [name,format,dim1,dim2] in regList: - map = {'registerName' : name, - 'cType' : iecommon.getCDataType(format)} - if dim2 > 1: + for register in block.getDesignRegisters(): + map = {'registerName' : register.name, + 'cType' : register.getCType()} + if register.isArray2D(): text += matrixRegistersDeclarationTemplate.substitute(map) - elif dim1 > 1: + elif register.isArray(): text += arrayRegistersDeclarationTemplate.substitute(map) else: text += scalarRegistersDeclarationTemplate.substitute(map) diff --git a/silecs-codegen/src/xml/genparam.py b/silecs-codegen/src/xml/genparam.py index 60be9d25e18c7ce933e0b8db3b1bea7173195c0d..aab232a52f5351d5cec5dfa8ba327be9c51acff8 100644 --- a/silecs-codegen/src/xml/genparam.py +++ b/silecs-codegen/src/xml/genparam.py @@ -29,6 +29,7 @@ import iefiles from iecommon import * from model.Register import * +from model.Block import * #------------------------------------------------------------------------- # Global definitions @@ -653,7 +654,7 @@ def loadSilecsDesignDOM(workspacePath, classNode, silecsVersion, funcGetSilecsDe return libxml2.parseFile(designPath) # Needed to encapsulate "genParam" in order to allow unit-testing (fake all file interactions) -def genParamBase( funcGetSilecsDesignFilePath, funcGetParameterFile, funcGetSilecsDeployFilePath, funcGetParameterFileDirectory, workspacePath, deployName, deployVersion, silecsVersion, logTopics={'errorlog': True}): +def genParamBase( funcGetSilecsDesignFilePath, funcGetParameterFile, funcGetSilecsDeployFilePath, funcGetParameterFileDirectory, workspacePath, deployName, deployVersion, silecsVersion, logTopics={'debuglog': True}): # Global variable links global plcModel, plcBrand, plcSystem, plcProtocol, plcSize, plcLast global PLCbaseAddress, checksumRef, owner, deviceMemSize, blkAddr, nbBlock, msize @@ -820,11 +821,12 @@ def genParamBase( funcGetSilecsDesignFilePath, funcGetParameterFile, funcGetSile computeBlkAddress = whichBlkAddressFunction[plcBrand + plcProtocol] # INNER LOOP TO ACCESS AT BLOCK LEVEL (LOOP-2) - for block in designDOM.xpathEval("//Block"): #LOOP-2 - element3 = libxml2.newNode("Block") - element3.setProp("name", block.prop("name")) - element3.setProp("mode", block.prop("mode")) - iecommon.logDebug("----- Processing Block "+block.prop('name')+" from design -----",logTopics) + for blockNode in designDOM.xpathEval("//Block"): #LOOP-2 + designBlock = DesignBlock(blockNode) + paramBlock = ParamBlock() + paramBlock.initWithDesignBlock(designBlock) + + iecommon.logDebug("----- Processing Block "+ designBlock.name + " from design -----",logTopics) # Initialization for inner loop local variables regAddress = 0 # memory address of the register (using byte addressing) blockSize = 0 # block size (sum of the register size) @@ -837,9 +839,8 @@ def genParamBase( funcGetSilecsDesignFilePath, funcGetParameterFile, funcGetSile # Generate section <Register></Register> #------------------------------------------------------------------------- # INNER LOOP TO ACCESS AT REGISTER LEVEL (LOOP-3) - for registerNode in block.xpathEval("Register"): - designRegister = Register(registerNode) - iecommon.logDebug("------ Processing Register "+designRegister.name+ " ------") + for designRegister in designBlock.getDesignRegisters(): + iecommon.logDebug("------ Processing Register " + designRegister.name + " ------",logTopics) # Set length attribute only for string registers if designRegister.format == 'string': if plcBrand == 'RABBIT': @@ -859,20 +860,17 @@ def genParamBase( funcGetSilecsDesignFilePath, funcGetParameterFile, funcGetSile paramRegister.initWithDesignRegister(designRegister,regSize,regAddress,msize) # Compute address for the next register regAddress = computeAnyNextRegAddress(plcBrand, regAddress, designRegister.dim1, designRegister.dim2) - # Append register - element3.addChild(paramRegister.xmlNode) + paramBlock.xmlNode.addChild(paramRegister.xmlNode) + paramRegister.xmlNode.shellPrintNode() #iterativelly compute the block size (accumulator initialized outside the loop) - blockSize = blockSize + (int(regSize) * int(designRegister.dim1) * int(designRegister.dim2)) + blockSize = blockSize + (int(regSize) * designRegister.dim1 * designRegister.dim2) # END OF INNER LOOP TO ACCESS AT REGISTER LEVEL (LOOP-3) - # Set block size - element3.setProp("size", str(blockSize)) - # Set block address - element3.setProp("address",str(computeBlkAddress(regAddress, int(classBaseAddress) , nbDevice))) - # Set block mem-size - element3.setProp("mem-size", str(blkMemSize)) + paramBlock.setSize(blockSize) + paramBlock.setAddress(computeBlkAddress(regAddress, int(classBaseAddress),nbDevice)) + paramBlock.setMemSize(blkMemSize) # Append block - paramClassNode.addChild(element3) + paramClassNode.addChild(paramBlock.xmlNode) # Count the number of devices nbBlock = nbBlock+1 # Accumulate blkMemSize to compute the total deviceMemSize diff --git a/silecs-codegen/src/xml/genplcsrc.py b/silecs-codegen/src/xml/genplcsrc.py index f1e3c2a962f1ea32d43335fd36fb2dff09ac695a..f3c98a1824004ddeef9a2b17a41dd9cdc3d20195 100644 --- a/silecs-codegen/src/xml/genplcsrc.py +++ b/silecs-codegen/src/xml/genplcsrc.py @@ -29,6 +29,7 @@ import rabbitTemplate from iecommon import * from model.Register import ParamRegister +from model.Block import ParamBlock #========================================================================= # General remarks #========================================================================= @@ -112,22 +113,22 @@ beckhoffRegInit = """ %s_%04x_%s AT %%MW%s: %s:= %s;\r\n\r\n""" # Schneider registers #------------------------------------------------------------------------- -def xsyRegister(regFormat, regDim, regDim2, regLen=1): - if regLen > 1: # register is a string or an array of strings - strLen= whichUnityFormat[regFormat]+'['+str(regLen)+']' - if regDim == 1 and regDim2 ==1: # string +def xsyRegister(register): + if register.isStringType(): + strLen = whichUnityFormat[register.format]+'['+str(register.stringLength)+']' + if register.isString(): return strLen - elif regDim > 1 and regDim2 == 1: # string array - return schneiderRegArray %(regDim-1, strLen) - else: # dim1>=1 and for whatever dim2, use double array syntax - return schneiderRegArray2d %(regDim-1, regDim2-1, strLen) + elif register.isStringArray(): + return schneiderRegArray %(register.dim1-1, strLen) + else: #2D-Array + return schneiderRegArray2d %(register.dim1-1, register.dim2-1, strLen) else: - if regDim == 1 and regDim2 ==1: # scalar - return whichUnityFormat[regFormat] - elif regDim > 1 and regDim2 == 1: # array - return schneiderRegArray %(regDim-1, whichUnityFormat[regFormat]) - else: # dim1>=1 and for whatever dim2, use double array syntax - return schneiderRegArray2d %(regDim-1, regDim2-1, whichUnityFormat[regFormat]) + if register.isScalar(): + return whichUnityFormat[register.format] + elif register.isArray(): + return schneiderRegArray %(register.dim1-1, whichUnityFormat[register.format]) + else: #2D-Array + return schneiderRegArray2d %(register.dim1-1, register.dim2-1, whichUnityFormat[register.format]) def getDateTime(): dt = time.localtime(time.time()) @@ -160,11 +161,9 @@ def generateSiemensSources(paramDOM, sourceFolderPath ,logTopics): # Generate the Blocks definition for blockIndex, blockDOM in enumerate(blockDOMList): registerList = '' - blockName = blockDOM.prop('name') - for registerDOM in blockDOM.xpathEval("Register"): - register = ParamRegister() - register.initWithParamRegisterNode(registerDOM) - + block = ParamBlock() + block.initWithParamBlockNode(blockDOM) + for register in block.getParamRegisters(): # If PLC does not supports this register format abort this generation and log the error if(register.format in ['uint64','int64','float64']): iecommon.logError('ERROR: In design %s_%s register %s, %s format not supported for current controller model.' @@ -179,8 +178,8 @@ def generateSiemensSources(paramDOM, sourceFolderPath ,logTopics): else: registerList += s7template.stlRegister(register.name, register.format, register.dim1, register.dim2, registerValue) - stlString += s7template.stlBlockUDT(deploy.owner, className, classVersion, blockName, registerList, (blockIndex == 0)) - symString += s7template.symBlockUDT(className, classVersion, blockName, UDTnumber, (blockIndex == 0)) + stlString += s7template.stlBlockUDT(deploy.owner, className, classVersion, block.name, registerList, (blockIndex == 0)) + symString += s7template.symBlockUDT(className, classVersion, block.name, UDTnumber, (blockIndex == 0)) UDTnumber += 1 if deploy.plcProtocol == 'DEVICE_MODE': @@ -188,8 +187,9 @@ def generateSiemensSources(paramDOM, sourceFolderPath ,logTopics): for deviceIndex, deviceDOM in enumerate(deviceDOMList): blockList = '' for blockDOM in blockDOMList: - blockName = blockDOM.prop('name') - blockList += s7template.stlBlock(className, blockName) + block = ParamBlock() + block.initWithParamBlockNode(blockDOM) + blockList += s7template.stlBlock(className, block.name) deviceLabel = deviceDOM.prop('label') stlString += s7template.generateBlock(deploy.owner, className, classVersion, deploy.plcSystem, DBnumber, deviceLabel, blockList, (deviceIndex == 0),deploy.plcProtocol) symString += s7template.symDeviceDB(className, classVersion, deviceLabel, DBnumber, (deviceIndex == 0)) @@ -198,15 +198,16 @@ def generateSiemensSources(paramDOM, sourceFolderPath ,logTopics): else: # BLOCK_MODE # Generate the Data-Blocks: one DB per Block of registers for blockIndex, blockDOM in enumerate(blockDOMList): - blockName = blockDOM.prop('name') + block = ParamBlock() + block.initWithParamBlockNode(blockDOM) deviceList = '' for deviceDOM in deviceDOMList: deviceLabel = deviceDOM.prop('label') - deviceList += s7template.stlDevice(deviceLabel, className, blockName) + deviceList += s7template.stlDevice(deviceLabel, className, block.name) - stlString += s7template.generateBlock(deploy.owner, className, classVersion, deploy.plcSystem, DBnumber, blockName, deviceList, (blockIndex == 0),deploy.plcProtocol) - symString += s7template.symBlockDB(className, classVersion, blockName, DBnumber, (blockIndex == 0)) + stlString += s7template.generateBlock(deploy.owner, className, classVersion, deploy.plcSystem, DBnumber, block.name, deviceList, (blockIndex == 0),deploy.plcProtocol) + symString += s7template.symBlockDB(className, classVersion, block.name, DBnumber, (blockIndex == 0)) DBnumber += 1 # write the String PLC generated code @@ -220,22 +221,17 @@ def generateSiemensSources(paramDOM, sourceFolderPath ,logTopics): #------------------------------------------------------------------------- # ---------------------------------------------------- -def generateSchneiderRegisters(xsydoc, classDOM, deviceDOM, blockDOM, deviceIndex, modeDevice, deploy, logTopics): +def generateSchneiderRegisters(xsydoc, classDOM, deviceDOM, block, deviceIndex, modeDevice, deploy, logTopics): className = classDOM.prop('name') deviceLabel = deviceDOM.prop('label') - blockName = blockDOM.prop('name') #Device and Block adresses come from the generated Paramerers file. Depends on the protocol mode: #DEVICE_MODE: relative address of the element within it parent node #BLOCK_MODE : absolute address in the entire PLC memory deviceAddress = long(deviceDOM.prop('address')) - blockAddress = long(blockDOM.prop('address')) - blockMemSize = long(blockDOM.prop('mem-size')) - for registerDOM in blockDOM.xpathEval("Register"): - register = ParamRegister() - register.initWithParamRegisterNode(registerDOM) + for register in block.getParamRegisters(): # If PLC does not supports this register format abort this generation and log the error if(register.format in ['uint64','int64','float64']): iecommon.logError('ERROR: In register '+register.name+', '+register.format+' format not supported for current controller model.', True,logTopics) @@ -243,9 +239,9 @@ def generateSchneiderRegisters(xsydoc, classDOM, deviceDOM, blockDOM, deviceInde # Compute the Register address relying on the Class Parameters file data # Attention! Schneider uses WORD addressing while Parameters data are expressed in bytes to be PLC independent if modeDevice: - totalAddress = (deviceAddress + blockAddress + register.address)/2 + totalAddress = (deviceAddress + block.address + register.address)/2 else: - totalAddress = (blockAddress + (deviceIndex * blockMemSize) + register.address)/2 + totalAddress = (block.address + (deviceIndex * block.memSize) + register.address)/2 # then insert the corresponding DOM element dataElt = xsydoc.xpathEval("//dataBlock")[0] #only one dataBlock node has been inserted so far @@ -258,13 +254,13 @@ def generateSchneiderRegisters(xsydoc, classDOM, deviceDOM, blockDOM, deviceInde regElt.setProp("name", "%s_%04x_%s" %(register.name, classNameCRC, deviceLabel)) if register.format == 'string': - regElt.setProp("typeName", "%s" %xsyRegister(register.format, register.dim1, register.dim2, register.stringLength )) + regElt.setProp("typeName", "%s" %xsyRegister(register)) else: - regElt.setProp("typeName", "%s" %xsyRegister(register.format, register.dim1, register.dim2)) + regElt.setProp("typeName", "%s" %xsyRegister(register)) regElt.setProp("topologicalAddress", "%%MW%ld" %totalAddress) - if blockName == 'hdrBlk': + if block.name == 'hdrBlk': initElt = libxml2.newNode('variableInit') if register.name == '_version': initElt.setProp("value", deploy.silecsVersion ) if register.name == '_user' : initElt.setProp("value", deploy.owner) @@ -272,7 +268,7 @@ def generateSchneiderRegisters(xsydoc, classDOM, deviceDOM, blockDOM, deviceInde if register.name == '_date' : initElt.setProp("value", getDateTime()) regElt.addChild(initElt) commElt = libxml2.newNode('comment') - commElt.setContent(className+"/"+deviceLabel+"/"+blockName) + commElt.setContent(className+"/"+deviceLabel+"/"+block.name) regElt.addChild(commElt) dataElt.addChild(regElt) @@ -294,15 +290,16 @@ def generateSchneiderSources(paramDOM,sourceFolderPath,logTopics): classNodes = paramDOM.xpathEval("/SILECS-Param/SILECS-Mapping/SILECS-Class") for classNode in classNodes: address = int(classNode.prop('address')) #address of the first register of the configuration - blockDOMList = classNode.xpathEval("Block") # get Blocks elements of that class deviceDOMList = classNode.xpathEval("Instance") # get Device instances of that class - for blockDOM in blockDOMList: + for blockDOM in classNode.xpathEval("Block"): + block = ParamBlock() + block.initWithParamBlockNode(blockDOM) for deviceIndex,deviceDOM in enumerate(deviceDOMList): if deploy.plcProtocol == 'DEVICE_MODE': #------------------- - generateSchneiderRegisters(xsyDoc, classNode, deviceDOM, blockDOM, deviceIndex, True, deploy, logTopics) + generateSchneiderRegisters(xsyDoc, classNode, deviceDOM, block, deviceIndex, True, deploy, logTopics) else: - generateSchneiderRegisters(xsyDoc, classNode, deviceDOM, blockDOM, deviceIndex, False, deploy, logTopics) + generateSchneiderRegisters(xsyDoc, classNode, deviceDOM, block, deviceIndex, False, deploy, logTopics) # Finally, write the DOM object (PLC generated code) into the XSY source file generateControllerFiles(sourceFolderPath,deploy,".xsy",rootElt.serialize(format = True),logTopics); @@ -335,13 +332,11 @@ def generateRabbitSources(paramDOM,sourceFolderPath,logTopics): deviceNumber = len(deviceDOMList) #==== Generate the Blocks definition ==== - for blockIndex, blockDOM in enumerate(blockDOMList): + for blockIndex, blockDOM in enumerate(classNode.xpathEval("Block")): registerList = '' - blockName = blockDOM.prop('name') - for registerDOM in blockDOM.xpathEval("Register"): - register = ParamRegister() - register.initWithParamRegisterNode(registerDOM) - + block = ParamBlock() + block.initWithParamBlockNode(blockDOM) + for register in block.getParamRegisters(): # If PLC does not supports this register format abort this generation and log the error if(register.format in ['float64']): iecommon.logError('ERROR: In register '+ register.name +', '+register.format+' format not supported for current controller model.', True,logTopics) @@ -351,15 +346,16 @@ def generateRabbitSources(paramDOM,sourceFolderPath,logTopics): else: registerList += rabbitTemplate.cRegister(register.name, register.format, register.dim1, register.dim2) - cTypeDefinitions += rabbitTemplate.cBlockUDT(className, classVersion, blockName, registerList, (blockIndex == 0)) + cTypeDefinitions += rabbitTemplate.cBlockUDT(className, classVersion, block.name, registerList, (blockIndex == 0)) #==== Memory allocation ==== if deploy.plcProtocol == 'DEVICE_MODE': # Generate the List of block in the class blockList ='' for blockIndex, blockDOM in enumerate(blockDOMList): - blockName = blockDOM.prop('name') - blockList += rabbitTemplate.cDeviceModeBlockInstantiation(className, blockName) + block = ParamBlock() + block.initWithParamBlockNode(blockDOM) + blockList += rabbitTemplate.cDeviceModeBlockInstantiation(className, block.name) deviceList = '' for deviceDOM in deviceDOMList: @@ -372,15 +368,15 @@ def generateRabbitSources(paramDOM,sourceFolderPath,logTopics): else: # BLOCK_MODE # Generate the List of block in the class for blockIndex, blockDOM in enumerate(blockDOMList): - # create instantation for current block - blockName = blockDOM.prop('name') + block = ParamBlock() + block.initWithParamBlockNode(blockDOM) deviceList = '' for deviceDOM in deviceDOMList: deviceLabel = deviceDOM.prop('label') - deviceList +=rabbitTemplate.cBlockModeDeviceInstantiation_deviceList(className, blockName, deviceLabel) + deviceList +=rabbitTemplate.cBlockModeDeviceInstantiation_deviceList(className, block.name, deviceLabel) - blockList += rabbitTemplate.cBlockModeBlockInstantiation(deviceList, className, blockName) + blockList += rabbitTemplate.cBlockModeBlockInstantiation(deviceList, className, block.name) # Predefine number of devices constant cDataAllocation += NBdeviceDefinitionList @@ -403,7 +399,7 @@ def generateRabbitSources(paramDOM,sourceFolderPath,logTopics): cCodeString += cInitFunction # Generate and append sample example - cCodeString += rabbitTemplate.cExample(deploy.plcProtocol,True,className, blockName, register.name, deviceLabel) + cCodeString += rabbitTemplate.cExample(deploy.plcProtocol,True,className, block.name, register.name, deviceLabel) # Finally, write the String C generated code into the temporal output file generateControllerFiles(sourceFolderPath,deploy,".h",cCodeString,logTopics); @@ -436,8 +432,7 @@ def generateVirtualS7Sources(paramDOM,sourceFolderPath,logTopics): createDeviceCodeString = '' deleteDeviceCodeString = '' designCodeString = '' - - blockDOMList = classNode.xpathEval("Block") # get Blocks elements of that class + deviceDOMList = classNode.xpathEval("Instance") # get Device instances of that class className = classNode.prop('name') @@ -450,7 +445,7 @@ def generateVirtualS7Sources(paramDOM,sourceFolderPath,logTopics): getDesign += virtualS7Template.vs7DuDesignGet(className, classVersion) #CLASSES code generation ================================ - for blockIndex, blockDOM in enumerate(blockDOMList): + for blockIndex, blockDOM in enumerate(classNode.xpathEval("Block")): getSetCodeString = '' dimsCodeString = '' dataCodeString = '' @@ -459,16 +454,13 @@ def generateVirtualS7Sources(paramDOM,sourceFolderPath,logTopics): previousRegisterMemSize = 0 #... dummyIndex = 0; - blockName = blockDOM.prop('name') - blockOffset = blockDOM.prop('address') + block = ParamBlock() + block.initWithParamBlockNode(blockDOM) - createBlockCodeString += virtualS7Template.vs7ClassCreateBlock(className, blockName) - deleteBlockCodeString += virtualS7Template.vs7ClassDeleteBlock(className, blockName) - - for registerDOM in blockDOM.xpathEval("Register"): - register = ParamRegister() - register.initWithParamRegisterNode(registerDOM) + createBlockCodeString += virtualS7Template.vs7ClassCreateBlock(className, block.name) + deleteBlockCodeString += virtualS7Template.vs7ClassDeleteBlock(className, block.name) + for register in block.getParamRegisters(): getSetCodeString += virtualS7Template.vs7ClassGetSet(register.name, register.format, register.dim1, register.dim2,register.stringLength) dimsCodeString += virtualS7Template.vs7ClassDimension(register.name, register.format, register.dim1, register.dim2,register.stringLength) @@ -483,7 +475,7 @@ def generateVirtualS7Sources(paramDOM,sourceFolderPath,logTopics): dataCodeString += virtualS7Template.vs7ClassDataRegister(register.name, register.format, register.dim1, register.dim2, register.stringLength) previousRegisterMemSize = register.memSize - blocksCodeString += virtualS7Template.vs7ClassBlock(deploy.silecsVersion, deploy.owner, deploy.checksum, className, blockName, getSetCodeString, blockOffset, dimsCodeString, dataCodeString) + blocksCodeString += virtualS7Template.vs7ClassBlock(deploy.silecsVersion, deploy.owner, deploy.checksum, className, block.name, getSetCodeString, block.address, dimsCodeString, dataCodeString) for deviceIndex, deviceDOM in enumerate(deviceDOMList): deviceLabel = deviceDOM.prop('label') @@ -511,46 +503,40 @@ def generateVirtualS7Sources(paramDOM,sourceFolderPath,logTopics): generateControllerFiles(sourceFolderPath,deploy,".cpp",mainCodeString,logTopics); # ---------------------------------------------------- -def generateBeckhoffRegisters(classDOM, deviceDOM, blockDOM, deviceIndex, deploy, logTopics): +def generateBeckhoffRegisters(classDOM, deviceDOM, block, deviceIndex, deploy, logTopics): source = '' className = classDOM.prop('name') deviceLabel = deviceDOM.prop('label') - blockName = blockDOM.prop('name') #Device and Block adresses come from the generated Paramerers file. Depends on the protocol mode: #DEVICE_MODE: relative address of the element within it parent node #BLOCK_MODE : absolute address in the entire PLC memory deviceAddress = long(deviceDOM.prop('address')) - blockAddress = long(blockDOM.prop('address')) - blockMemSize = long(blockDOM.prop('mem-size')) - - for registerDOM in blockDOM.xpathEval("Register"): - register = ParamRegister() - register.initWithParamRegisterNode(registerDOM) + for register in block.getParamRegisters(): # If PLC does not supports this register format abort this generation and log the error if(register.format in ['uint64','int64','float64']): iecommon.logError('ERROR: In register '+register.name+', '+register.format+' format not supported for current controller model.', True) return - iecommon.logDebug("Processing: %s %s %s %s" %(className, deviceLabel, blockName, register.name)) + iecommon.logDebug("Processing: %s %s %s %s" %(className, deviceLabel, block.name, register.name)) # Compute the register address relying on the Class Parameters file data # Attention! Beckhoff uses WORD addressing while Parameters data are expressed in bytes to be PLC independent if deploy.plcModel == 'BC9020': - totalAddress = (blockAddress - long(deploy.address) + (deviceIndex * blockMemSize) + register.address)/2 + totalAddress = (block.address - long(deploy.address) + (deviceIndex * block.memSize) + register.address)/2 elif deploy.plcModel == 'CX9020': - totalAddress = (blockAddress - long(deploy.address) + (deviceIndex * blockMemSize) + register.address) + totalAddress = (block.address - long(deploy.address) + (deviceIndex * block.memSize) + register.address) else: raise "PLC model not supported: " + deploy.plcModel # add comment to source to identify block - source += ' (*'+className+'/'+deviceLabel+'/'+blockName+' *)\r\n' + source += ' (*'+className+'/'+deviceLabel+'/'+block.name+' *)\r\n' # Compute the base checksum of the class name classNameCRC = zlib.crc32(className,0) & 0xffff - if blockName == 'hdrBlk': + if block.name == 'hdrBlk': if register.name == '_version': source+=beckhoffRegInit %(register.name, classNameCRC, deviceLabel, totalAddress, whichTwincatFormat[register.format]+"(16)", deploy.silecsVersion ) if register.name == '_user': @@ -599,8 +585,10 @@ def generateBeckhoffSources(paramDOM, sourceFolderPath, logTopics): # Device mode is not supported for Beckhoff PLCs - Only block mode available for blockDOM in blockDOMList: + block = ParamBlock() + block.initWithParamBlockNode(blockDOM) for deviceIndex, deviceDOM in enumerate(deviceDOMList): - source += generateBeckhoffRegisters(classNode, deviceDOM, blockDOM, deviceIndex,deploy,logTopics) + source += generateBeckhoffRegisters(classNode, deviceDOM, block, deviceIndex,deploy,logTopics) source += 'END_VAR' diff --git a/silecs-codegen/src/xml/iecommon.py b/silecs-codegen/src/xml/iecommon.py index 27f4e4dcc31e5e885237e44a12b33af48eb76a0b..720e594ecb24684dca6c6f9772a4d0ccd403a5f9 100644 --- a/silecs-codegen/src/xml/iecommon.py +++ b/silecs-codegen/src/xml/iecommon.py @@ -149,77 +149,6 @@ def fillAttributes(element, attrs): element.setProp(name, value) return element -def getCDataType(silecsDataType): - return { - 'int8' :'int8_t', - 'uint8' :'uint8_t', - 'int16' :'int16_t', - 'uint16' :'uint16_t', - 'int32' :'int32_t', - 'uint32' :'uint32_t', - 'int64' :'int64_t', - 'uint64' :'uint64_t', - 'float32' :'float', - 'float64' :'double', - 'date' :'double', - 'char' :'int8_t', - 'byte' :'int16_t', - 'word' :'int32_t', - 'dword' :'int64_t', - 'int' :'int16_t', - 'dint' :'int32_t', - 'real' :'float', - 'dt' :'double', - 'string' :'std::string' - }[silecsDataType] - -#------------------------------------------------------------------------- -# Given PLC data type, returns the corresponding -# SILECS data type -#------------------------------------------------------------------------- -def getSilecsDataType(registerFormatType): - return { - 'byte' :'uint8', - 'char' :'int8', - 'unsigned char' :'uint8', - 'short' :'int16', - 'unsigned short':'uint16', - 'long' :'int32', # conversion relies on 32-bit platform (FESA 3 does not support long type anymore) - 'unsigned long' :'uint32', - 'double' :'float64', - 'float' :'float32', - 'word' :'uint16', - 'dword' :'uint32', - 'int' :'int16', - 'dint' :'int32', - 'real' :'float32', - 'dt' :'date', - 'uint8' :'uint8', - 'int8' :'int8', - 'uint16' :'uint16', - 'int16' :'int16', - 'uint32' :'uint32', - 'int32' :'int32', - 'uint64' :'uint64', - 'int64' :'int64', - 'float32' :'float32', - 'float64' :'float64', - 'date' :'date', - 'string' : 'string' - }[registerFormatType] - -#Needed for SilecsMethodNames -def getSilecsDataTypeUpperCase(registerFormatType): - type = iecommon.getSilecsDataType(registerFormatType) - typeUpperCase = "" - if type[0] == 'u': - typeUpperCase = type[:2].upper() + type[2:] # first two characters if unsigned - elif type == 'date': - typeUpperCase = 'Date' - else: - typeUpperCase = type[:1].upper() + type[1:] # only first character if not unsigned - return typeUpperCase - def capitalizeString(text): str = "" if len(text) > 0: diff --git a/silecs-codegen/src/xml/model/Block.py b/silecs-codegen/src/xml/model/Block.py new file mode 100644 index 0000000000000000000000000000000000000000..353b4bfd711183d079e859072121b996ade4eb39 --- /dev/null +++ b/silecs-codegen/src/xml/model/Block.py @@ -0,0 +1,112 @@ +#!/usr/bin/python +# Copyright 2016 CERN and GSI +# +# 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 <http://www.gnu.org/licenses/>. + +from iecommon import * +from model.Register import * +import libxml2 + +class Block(object): + + def __init__(self, xmlNode): + self.xmlNode = xmlNode + + #xmlNode.shellPrintNode() + self.name = xmlNode.prop("name") + self.mode = xmlNode.prop("mode") + + def getNameCapitalized(self): + return iecommon.capitalizeString(self.name) + + def isReadable(self): + return self.mode == 'READ-ONLY' or self.mode == 'READ-WRITE' + + def isWritable(self): + return self.mode == 'WRITE-ONLY' or self.mode == 'READ-WRITE' + + def isAcquisition(self): + return self.mode == 'READ-ONLY' + + def isSetting(self): + return self.mode == 'READ-WRITE' + + def isCommand(self): + return self.mode == 'WRITE-ONLY' + + def getRegisterNodes(self): + return self.xmlNode.xpathEval("Register") + +#has some additionalValues +class ParamBlock(Block): + def __init__(self): + self.size = 0 + self.address = 0 + self.memSize = 0 + + + def initWithParamBlockNode(self, xmlNode): + super(ParamBlock, self).__init__(xmlNode) + self.size = long(self.xmlNode.prop("size")) + self.address = long(self.xmlNode.prop("address")) + self.memSize = long(self.xmlNode.prop("mem-size")) + + def initWithDesignBlock(self, designBlock): + newNode = libxml2.newNode(designBlock.xmlNode.get_name()) + newNode.newProp("name", designBlock.name) + newNode.newProp("mode", designBlock.mode) + super(ParamBlock, self).__init__(newNode) + newNode.newProp("size", str(self.size)) + newNode.newProp("address", str(self.address)) + newNode.newProp("mem-size", str(self.memSize)) + + def setSize(self,size): + self.xmlNode.setProp("size", str(size)) + self.size = size + + def setAddress(self,address): + self.xmlNode.setProp("address", str(address)) + self.address = address + + def setMemSize(self,memSize): + self.xmlNode.setProp("mem-size", str(memSize)) + self.memSize = memSize + + def getParamRegisters(self): + paramRegisters = [] + for registerNode in self.getRegisterNodes(): + paramRegister = ParamRegister() + paramRegister.initWithParamRegisterNode(registerNode) + paramRegisters.append(paramRegister) + return paramRegisters + + +class DesignBlock(Block): + def __init__(self, xmlNode): + super(DesignBlock, self).__init__(xmlNode) + self.fesaPropertyName = self.name + self.generateFesaProperty = False + if self.xmlNode.hasProp("fesaPropertyName"): + self.fesaPropertyName = xmlNode.prop("fesaPropertyName") + if self.xmlNode.hasProp("generateFesaProperty"): #SilecsHEader does not have this attribute + self.generateFesaProperty = xsdBooleanToBoolean(xmlNode.prop("generateFesaProperty")) + + def getFesaName(self): + return self.fesaPropertyName + + def getDesignRegisters(self): + designRegisters = [] + for registerNode in self.getRegisterNodes(): + designRegisters.append(DesignRegister(registerNode)) + return designRegisters diff --git a/silecs-codegen/src/xml/model/Register.py b/silecs-codegen/src/xml/model/Register.py index 0eb544508ab7061abb5aa2b954388bfdabdcd4ff..54abe60c49dd0dddf2ee5a43c7001fae9bfa5339 100644 --- a/silecs-codegen/src/xml/model/Register.py +++ b/silecs-codegen/src/xml/model/Register.py @@ -18,6 +18,15 @@ from iecommon import * import libxml2 class Register(object): + xmlNode = None + name = "" + synchro = "" + valueTypeNode = None + valueType = "" + dim1 = 1 + dim2 = 1 + stringLength = 1 # ... currently needs to be default because of some old convention + format = "" def __init__(self, xmlNode): self.xmlNode = xmlNode @@ -35,11 +44,7 @@ class Register(object): iecommon.logError('ERROR: The register '+ self.name +' has multiple valueTypes.', True, {'errorlog': True}) self.valueTypeNode = valueTypes[0] self.valueType = self.valueTypeNode.get_name() - - self.dim1 = 1 - self.dim2 = 1 - self.stringLength = 1 # ... currently needs to be default because of some old convention - + if self.valueTypeNode.hasProp("dim1"): self.dim1 = long(self.valueTypeNode.prop("dim1")) elif self.valueTypeNode.hasProp("dim"): @@ -53,20 +58,27 @@ class Register(object): self.format = self.valueTypeNode.prop("format") - + def getNameCapitalized(self): + return iecommon.capitalizeString(self.name) + def isUnsigned(self): - type = iecommon.getSilecsDataType(self.format) + type = self.getSilecsDataType() if type[0] == 'u': return True return False - def getCType(): - type = iecommon.getSilecsDataType(self.format) - return iecommon.getCDataType(type) - def getSilecsTypeCapitalized(self): - return iecommon.getSilecsDataTypeUpperCase(self.format) + return self.getSilecsDataTypeUpperCase() + + def isScalar(self): + return self.valueType == 'scalar' + + def isString(self): + return self.valueType == 'string' + def isStringArray(self): + return self.valueType == 'stringArray' + def isArray(self): return self.valueType == 'array' or self.valueType == 'stringArray' @@ -76,14 +88,98 @@ class Register(object): def isStringType(self): return self.valueType == 'string' or self.valueType == 'stringArray' or self.valueType == 'stringArray2D' + def isArrayType(self): + return self.isArray() or self.isArray2D() + + def isAcquisition(self): + return self.syncro == 'MASTER' + + def isSetting(self): + return self.syncro == 'SLAVE' + + def isVolatile(self): + return self.syncro == 'NONE' + + def getCType(self): + return { + 'int8' :'int8_t', + 'uint8' :'uint8_t', + 'int16' :'int16_t', + 'uint16' :'uint16_t', + 'int32' :'int32_t', + 'uint32' :'uint32_t', + 'int64' :'int64_t', + 'uint64' :'uint64_t', + 'float32' :'float', + 'float64' :'double', + 'date' :'double', + 'char' :'int8_t', + 'byte' :'int16_t', + 'word' :'int32_t', + 'dword' :'int64_t', + 'int' :'int16_t', + 'dint' :'int32_t', + 'real' :'float', + 'dt' :'double', + 'string' :'std::string' + }[self.getSilecsDataType()] + + #------------------------------------------------------------------------- + # Given PLC data type, returns the corresponding + # SILECS data type + #------------------------------------------------------------------------- + def getSilecsDataType(self): + return { + 'byte' :'uint8', + 'char' :'int8', + 'unsigned char' :'uint8', + 'short' :'int16', + 'unsigned short':'uint16', + 'long' :'int32', # conversion relies on 32-bit platform (FESA 3 does not support long type anymore) + 'unsigned long' :'uint32', + 'double' :'float64', + 'float' :'float32', + 'word' :'uint16', + 'dword' :'uint32', + 'int' :'int16', + 'dint' :'int32', + 'real' :'float32', + 'dt' :'date', + 'uint8' :'uint8', + 'int8' :'int8', + 'uint16' :'uint16', + 'int16' :'int16', + 'uint32' :'uint32', + 'int32' :'int32', + 'uint64' :'uint64', + 'int64' :'int64', + 'float32' :'float32', + 'float64' :'float64', + 'date' :'date', + 'string' : 'string' + }[self.format] + + #Needed for SilecsMethodNames + def getSilecsDataTypeUpperCase(self): + type = self.getSilecsDataType() + typeUpperCase = "" + if type[0] == 'u': + typeUpperCase = type[:2].upper() + type[2:] # first two characters if unsigned + elif type == 'date': + typeUpperCase = 'Date' + else: + typeUpperCase = type[:1].upper() + type[1:] # only first character if not unsigned + return typeUpperCase #has some additionalValues class ParamRegister(Register): - def __init__(self): - self.size = 0 - self.address = 0 - self.memSize = 0 + size = 0 + address = 0 + memSize = 0 + def __init__(self ): + size = 0 + def initWithParamRegisterNode(self, xmlNode): super(ParamRegister, self).__init__(xmlNode) self.size = long(self.xmlNode.prop("size")) @@ -96,19 +192,34 @@ class ParamRegister(Register): iecommon.logError('ERROR: Failed to copy register node: '+ designRegister.name +'.', True, {'errorlog': True}) super(ParamRegister, self).__init__(designRegister.xmlNode) self.xmlNode = newNodeTree - newNodeTree.setProp("size", size) + newNodeTree.newProp("size", size) self.size = long(size) - newNodeTree.setProp("address", str(address)) + newNodeTree.newProp("address", str(address)) + self.address = address + newNodeTree.newProp("mem-size", str(memSize)) + self.memSize = memSize + #self.xmlNode.shellPrintNode() + + def setSize(self,size): + self.xmlNode.setProp("size", str(size)) + self.size = size + + def setAddress(self,address): + self.xmlNode.setProp("address", str(address)) self.address = address - newNodeTree.setProp("mem-size", str(memSize)) + + def setMemSize(self,memSize): + self.xmlNode.setProp("mem-size", str(memSize)) self.memSize = memSize class DesignRegister(Register): + fesaFieldName = "" + generateFesaValueItem=True + def __init__(self, xmlNode): super(DesignRegister, self).__init__(xmlNode) self.fesaFieldName = self.name - self.generateFesaValueItem = True if self.xmlNode.hasProp("fesaFieldName"): self.fesaFieldName = xmlNode.prop("fesaFieldName") if self.xmlNode.hasProp("generateFesaValueItem"): #SilecsHEader does not have this attribute @@ -145,7 +256,7 @@ class DesignRegister(Register): 'real' :'float', 'dt' :'double', 'string' :'char' - }[iecommon.getSilecsDataType(self.format)] + }[self.getSilecsDataType()] def getFesaFieldNameCapitalized(self): return iecommon.capitalizeString(self.fesaFieldName)