Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • silecs/opensilecs
  • k.fugiel/opensilecs
  • s.kupiecki/opensilecs
3 results
Show changes
Showing
with 1759 additions and 1705 deletions
#!/bin/sh
set -e
CPU="x86_64"
SCRIPT=$(readlink -f "$0")
SCRIPTPATH=$(dirname "$SCRIPT") # path where this script is located in
#SNAP7_PATH=${SCRIPTPATH}/../../../git/snap7/snap7-full/build/bin/${CPU}-linux #local
SNAP7_PATH=${SCRIPTPATH}/../../../snap7/2.0.0/bin/${CPU}-linux
#BINARY="${SCRIPTPATH}/../build/bin/${CPU}/silecs-cli-client" #local
BINARY="${SCRIPTPATH}/../bin/${CPU}/silecs-cli-client"
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$SNAP7_PATH
echo "##### LD_LIBRARY_PATH: ###################################################################################"
echo "$LD_LIBRARY_PATH"
echo "##########################################################################################################"
echo ""
PARAM_FILE=/common/home/bel/schwinn/lnx/workspace-silecs-neon/SiemensTestDU/generated/client/tsts7001.silecsparam
REGISTER=DQ_Anlog00
DEVICE=MyDevice1
......
#!/bin/sh
set -e
CPU="x86_64"
SCRIPT=$(readlink -f "$0")
SCRIPTPATH=$(dirname "$SCRIPT") # path where this script is located in
#SNAP7_PATH=${SCRIPTPATH}/../../../git/snap7/snap7-full/build/bin/${CPU}-linux #local
SNAP7_PATH=${SCRIPTPATH}/../../../snap7/2.0.0/bin/${CPU}-linux
#BINARY="${SCRIPTPATH}/../build/bin/${CPU}/silecs-cli-client" #local
BINARY="${SCRIPTPATH}/../bin/${CPU}/silecs-cli-client"
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$SNAP7_PATH
echo "##### LD_LIBRARY_PATH: ###################################################################################"
echo "$LD_LIBRARY_PATH"
echo "##########################################################################################################"
echo ""
PARAM_FILE=/common/home/bel/schwinn/lnx/workspace-silecs-neon/SiemensTestDU/generated/client/tsts7001.silecsparam
# config for SiemensTestDU
......
#!/bin/sh
set -e
INSTALL_DIR=$1
SCRIPT=$(readlink -f "$0")
SCRIPTPATH=$(dirname "$SCRIPT") # path where this script is located in
mkdir -p ${INSTALL_DIR}
cp -r ${SCRIPTPATH}/build/bin ${INSTALL_DIR}
cp -r ${SCRIPTPATH}/examples ${INSTALL_DIR}
\ No newline at end of file
**/*.pyc
**/*__pycache__
\ No newline at end of file
cmake_minimum_required(VERSION 3.20.2)
project(silecs-codegen)
find_package(Python COMPONENTS Interpreter)
add_test (NAME codegen-tests
COMMAND ${Python_EXECUTABLE} -m unittest
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}/src/xml/
)
install (
DIRECTORY ${PROJECT_SOURCE_DIR}/src/xml
DESTINATION ${CMAKE_PROJECT_VERSION}/${PROJECT_NAME}
FILES_MATCHING PATTERN "*.py*")
This diff is collapsed.
# silecs-codegen
This component of the SILECS PLC-framework generates FESA and stand-alone C++ code from an existing silecs-project in order to ease the usage of the package silecs-communication-cpp
This component of the opensilecs PLC-framework generates FESA and stand-alone C++ code from an existing silecs-project in order to ease the usage of the package silecs-communication-cpp
## Getting Started
## Tests
Please check the lab-specific SILECS-Wikis for more information:
In [test](src/xml/test/) directory there are files with {test_name} which contain unit tests written using `unittest` framework. Tests conserning the migration tools are in their own corresponding folders inside [migration](src/xml/migration/).
[CERN SILECS Wiki Page][CERN_Wiki]
[GSI SILECS Wiki Page][GSI_Wiki]
## License
Licensed under the GNU GENERAL PUBLIC LICENSE Version 3. See the [LICENSE file][license] for details.
[license]: LICENSE
[CERN_Wiki]: https://wikis.cern.ch/display/SIL/SILECs+Home
[GSI_Wiki]: https://www-acc.gsi.de/wiki/Frontend/SILECS
All tests can be run together using following command from inside [src/xml](src/xml/):
```
python3 -m unittest
```
#!/bin/sh
set -e
INSTALL_DIR=$1
SCRIPT=$(readlink -f "$0")
SCRIPTPATH=$(dirname "$SCRIPT") # path where this script is located in
mkdir -p ${INSTALL_DIR}
cp -r ${SCRIPTPATH}/src/xml ${INSTALL_DIR}
\ No newline at end of file
#!/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/>.
global MEM_TYPE
global DI_TYPE
global DO_TYPE
global AI_TYPE
global AO_TYPE
global mappin2String
MEM_TYPE = 0
DI_TYPE = 1
DO_TYPE = 2
AI_TYPE = 3
AO_TYPE = 4
mappingType2String = { MEM_TYPE: "MEM", DI_TYPE: "DI", DO_TYPE: "DO", AI_TYPE: "AI", AO_TYPE: "AO" }
class Mapping(object):
def __init__(self,controllerAddress, type):
self.classBaseAddress = controllerAddress # start-address of the data per area type (MEM, DI,DO, AI,AO) for the given class
self.nbBlock = 0 # number of block per area type (MEM, DI,DO, AI,AO)
self.deviceDataSize = 0 # global size of one class instance (sum of block size per area type)
self.usedData = "" # data size summary per class and per area type#
self.instanceAddress = -1 # start-address of the device data
self.isDefined = False # True if the object related base-address has been defined
self.type = type # mapping-type (MEM, DI, DO,AI,AO )
self.blockDataSize = 0
self.blockAddress = 0
if controllerAddress != -1:
self.instanceAddress = 0
self.isDefined = True
def clearInstanceAddressIfDefined(self):
if self.isDefined:
self.instanceAddress = 0
\ No newline at end of file
......@@ -33,9 +33,9 @@ from iecommon import *
# Generates two Makefile.specific, one for the class design
# and another for the deploy unit
#-------------------------------------------------------------------------
def genMakefileClass(projectPath, centralMakefilePath, logTopics={'errorlog': True} ):
def genMakefileClass(projectPath, logTopics={'errorlog': True} ):
# Generate makefile for class design
source = fesaTemplates.genMakeDesign(centralMakefilePath)
source = fesaTemplates.genMakeDesign()
makefile = projectPath + "/" + "Makefile.specific"
if os.path.isfile(makefile): #dont overwrite
return
......@@ -44,9 +44,9 @@ def genMakefileClass(projectPath, centralMakefilePath, logTopics={'errorlog': Tr
fdesc.write(source)
fdesc.close()
def genMakefileDU(projectPath, silecsBasePath, snap7BasePath, logTopics={'errorlog': True}):
def genMakefileDU(projectPath, logTopics={'errorlog': True}):
# Generate makefile for class design
source = fesaTemplates.genMakeDeploy(silecsBasePath,snap7BasePath)
source = fesaTemplates.genMakeDeploy()
# Write file and save
makefile = projectPath + "/" + "Makefile.specific"
if os.path.isfile(makefile): #dont overwrite
......
......@@ -26,7 +26,7 @@ import datetime
import socket
import iecommon
import fesaTemplates
import fesa.fesa_3_0_0.fesaTemplates
import iefiles
from iecommon import *
......@@ -87,8 +87,29 @@ class FESADesignGenerator3_0_0(object):
fillAttributes(scalarNode, {'type': register.getFesaType()})
return scalarNode
def getOrCreateType(self,fieldNode,register):
if register.valueType == "scalar":
def getOrCreateCustomScalarType(self, fieldNode, register):
scalarNode = getOrCreateChildElement(fieldNode,'custom-type-scalar')
fillAttributes(scalarNode, {'data-type-name-ref': register.custom_type_name})
return scalarNode
def getOrCreateCustomArrayType(self,fieldNode,register):
arrayNode = getOrCreateChildElement(fieldNode,'custom-type-array')
fillAttributes(arrayNode, {'data-type-name-ref': register.custom_type_name})
dimNode = getOrCreateChildElement(arrayNode,'dim')
dimNode.setContent(str(register.dim1))
return arrayNode
def getOrCreateCustom2DArrayType(self,fieldNode,register):
array2DNode = getOrCreateChildElement(fieldNode,'custom-type-array2D')
fillAttributes(array2DNode, {'data-type-name-ref': register.custom_type_name})
dim1Node = getOrCreateChildElement(array2DNode,'dim1')
dim2Node = getOrCreateChildElement(array2DNode,'dim2')
dim1Node.setContent(str(register.dim1))
dim2Node.setContent(str(register.dim2))
return array2DNode
def getOrCreateType(self,fieldNode, register):
if register.valueType == "scalar":
return self.getOrCreateScalarType(fieldNode,register)
elif register.valueType == "array":
return self.getOrCreateArrayType(fieldNode,register)
......@@ -100,6 +121,12 @@ class FESADesignGenerator3_0_0(object):
return self.getOrCreateStringArrayType(fieldNode,register)
elif register.valueType == "stringArray2D":
iecommon.logError('ERROR: In register '+register.name+' - 2D array of strings not supported in FESA.', True, {'errorlog': True})
elif register.valueType == "custom-type-scalar":
return self.getOrCreateCustomScalarType(fieldNode, register)
elif register.valueType == "custom-type-array":
return self.getOrCreateCustomArrayType(fieldNode, register)
elif register.valueType == "custom-type-array2D":
return self.getOrCreateCustom2DArrayType(fieldNode, register)
else:
iecommon.logError('ERROR: Unknown data-type:' + register.valueType, True, {'errorlog': True})
return None
......@@ -197,6 +224,10 @@ class FESADesignGenerator3_0_0(object):
else:
return getOrCreateNamedChildElement(parent,'field',register.getFesaFieldName())
def addDefaultNode(self, fieldNode, defaultValue):
defaultNode = getOrCreateChildElement(fieldNode,'default')
defaultNode.setContent(defaultValue)
def getOrCreatePLCHostNameField(self,configurationNode):
fieldNode = getOrCreateNamedFirstChild(configurationNode,'field','plcHostName')
descriptionNode = getOrCreateChildElement(fieldNode,'description')
......@@ -224,15 +255,14 @@ class FESADesignGenerator3_0_0(object):
array = getOrCreateChildElement(fieldNode,'array')
fillAttributes(array, {'type': 'char'})
dim = getOrCreateChildElement(array,'dim')
defaultNode = getOrCreateChildElement(fieldNode,'default')
defaultNode.setContent(plcClassVersion)
dim.setContent(str(len(defaultNode.getContent())))
self.addDefaultNode(fieldNode, plcClassVersion)
dim.setContent(str(len(plcClassVersion)))
return fieldNode
def getOrCreateRegisterValueItems(self,prop,block,isSetting):
def getOrCreateRegisterValueItems(self,prop,block,direction):
for register in block.getDesignRegisters():
if register.generateFesaValueItem:
self.getOrCreateValueItem(prop,register,isSetting)
self.getOrCreateValueItem(prop,register,direction)
def getOrCreateSettingProperty(self,parent,actionsNode,block):
iecommon.logDebug('Generating SettingProperty for Block: ' + block.name, {'debuglog': True})
......@@ -242,12 +272,23 @@ class FESADesignGenerator3_0_0(object):
else:
prop = getOrCreateNamedChildElement(parent,'setting-property',block.getFesaName())
fillAttributes(prop, {'visibility': 'development', 'multiplexed': 'false'})
self.getOrCreateRegisterValueItems(prop,block,True)
self.getOrCreateRegisterValueItems(prop,block,"INOUT")
self.getOrCreateUpdateFlagItem(prop)
self.getOrCreateCyleNameItem(prop)
self.getOrCreateAction(prop,block.fesaSetServerActionName,'set',actionsNode,'custom')
self.getOrCreateAction(prop,block.fesaGetServerActionName,'get',actionsNode,'custom')
return prop
def getOrCreateCommandProperty(self,parent,actionsNode,block):
iecommon.logDebug('Generating CommandProperty for Block: ' + block.name, {'debuglog': True})
if( hasChildren(parent)):
prop = getOrCreateNamedPreviousSiblingElement(parent,getFirstChild(parent), 'command-property',block.getFesaName())
else:
prop = getOrCreateNamedChildElement(parent,'command-property',block.getFesaName())
fillAttributes(prop, {'visibility': 'development', 'multiplexed': 'false'})
self.getOrCreateRegisterValueItems(prop,block,"IN")
self.getOrCreateAction(prop,block.fesaSetServerActionName,'set',actionsNode,'custom')
return prop
def getOrCreateAcquisitionProperty(self,parent,actionsNode,block):
iecommon.logDebug('Generating AcquisitionProperty for Block: ' + block.name, {'debuglog': True})
......@@ -257,7 +298,7 @@ class FESADesignGenerator3_0_0(object):
else:
prop = getOrCreateNamedChildElement(parent,'acquisition-property',block.getFesaName())
fillAttributes(prop, {'visibility': 'development', 'subscribable': 'true', 'multiplexed': 'false', 'on-change': 'true'})
self.getOrCreateRegisterValueItems(prop,block,False)
self.getOrCreateRegisterValueItems(prop,block,"OUT")
self.getOrCreateAcqStampItem(prop)
self.getOrCreateUpdateFlagItem(prop)
self.getOrCreateCyleNameItem(prop)
......@@ -265,13 +306,15 @@ class FESADesignGenerator3_0_0(object):
self.getOrCreateAction(prop,block.fesaGetServerActionName,'get',actionsNode,'custom')
return prop
def getOrCreateGSISettingProperty(self,parent,actionsNode,block):
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
powerProps = parent.xpathEval('GSI-Power-Property')
if len(powerProps) == 0:
raise Exception("Error: A GSI-Power-Property needs to be available to generate a GSISettingProperty")
powerProp = powerProps[0] # template is used --> there has to be a power prop
prop = getOrCreateNamedPreviousSiblingElement(parent,powerProp, 'GSI-Setting-Property',block.getFesaName())
fillAttributes(prop, {'visibility': 'development', 'multiplexed': 'false'})
self.getOrCreateRegisterValueItems(prop,block,True)
self.getOrCreateRegisterValueItems(prop,block,"INOUT")
self.getOrCreateUpdateFlagItem(prop)
self.getOrCreateCyleNameItem(prop)
self.getOrCreateAction(prop,block.fesaSetServerActionName,'set',actionsNode,'custom')
......@@ -280,10 +323,12 @@ class FESADesignGenerator3_0_0(object):
def getOrCreateGSIAcquisitionProperty(self,parent,actionsNode,block):
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',block.getFesaName())
versionProps = parent.xpathEval('GSI-Version-Property')
if len(versionProps) == 0:
raise Exception("Error: A GSI-Version-Property needs to be available to generate a GSIAcquisitionProperty")
prop = getOrCreateNamedPreviousSiblingElement(parent,versionProps[0], 'GSI-Acquisition-Property',block.getFesaName())
fillAttributes(prop, {'visibility': 'development', 'subscribable': 'true', 'multiplexed': 'false', 'on-change': 'true'})
self.getOrCreateRegisterValueItems(prop,block,False)
self.getOrCreateRegisterValueItems(prop,block,"OUT")
self.getOrCreateAcqStampItem(prop)
self.getOrCreateUpdateFlagItem(prop)
self.getOrCreateCyleNameItem(prop)
......@@ -295,17 +340,44 @@ class FESADesignGenerator3_0_0(object):
# propertyType only used during creation ! If named property already exists, it is just returned, no matter which type
def getOrCreateFESAProperty(self,parent,actionsNode,block):
if self.isGSITemplate(parent):
if parent.get_name() == 'setting':
return self.getOrCreateGSISettingProperty(parent,actionsNode,block)
if block.isSetting():
if block.getFesaName() == 'Power':
raise Exception("Error: Please use '@generateFesaProperty=false' for the GSI-Power-Property and connect silecs-fields manually")
else:
return self.getOrCreateGSISettingProperty(parent,actionsNode,block)
elif block.isCommand():
if block.getFesaName() == 'Init':
raise Exception("Error: Please use '@generateFesaProperty=false' for the GSI-Init-Property and connect silecs-fields manually")
elif block.getFesaName() == 'Reset':
raise Exception("Error: Please use '@generateFesaProperty=false' for the GSI-Reset-Property and connect silecs-fields manually")
else:
return self.getOrCreateCommandProperty(parent,actionsNode,block)
elif block.isAcquisition():
if block.getFesaName() == 'Status':
raise Exception("Error: Please use '@generateFesaProperty=false' for the GSI-Status-Property and connect silecs-fields manually")
elif block.getFesaName() == 'ModuleStatus':
raise Exception("Error: Please use '@generateFesaProperty=false' for the GSI-ModuleStatus-Property and connect silecs-fields manually")
elif block.getFesaName() == 'Version':
raise Exception("Error: Please use '@generateFesaProperty=false' for the GSI-Version-Property and connect silecs-fields manually")
else:
return self.getOrCreateGSIAcquisitionProperty(parent,actionsNode,block)
elif block.isConfiguration():
return self.getOrCreateGSIAcquisitionProperty(parent,actionsNode,block);
else:
return self.getOrCreateGSIAcquisitionProperty(parent,actionsNode,block)
raise Exception( "Cannot identify FESA GSI Property-type to use for block:" + block.name )
else:
if parent.get_name() == 'setting':
if block.isSetting():
return self.getOrCreateSettingProperty(parent,actionsNode,block)
else:
elif block.isCommand():
return self.getOrCreateCommandProperty(parent,actionsNode,block)
elif block.isAcquisition():
return self.getOrCreateAcquisitionProperty(parent,actionsNode,block)
elif block.isConfiguration():
return self.getOrCreateAcquisitionProperty(parent,actionsNode,block);
else:
raise Exception( "Cannot identify FESA Property-type to use for block:" + block.name )
def getOrCreateValueItem(self,propertyNode,register,isSetting):
def getOrCreateValueItem(self,propertyNode,register,direction):
iecommon.logDebug('Generating ValueItem for Register: ' + register.name, {'debuglog': True})
result = propertyNode.xpathEval("value-item[@name='" + register.getFesaFieldName() + "']")
if len(result):
......@@ -315,10 +387,7 @@ class FESADesignGenerator3_0_0(object):
valueItemNode = getOrCreateNamedPreviousSiblingElement(propertyNode,result[0],'value-item',register.getFesaFieldName())
else:
valueItemNode = getOrCreateNamedChildElement(propertyNode,'value-item',register.getFesaFieldName())
if isSetting:
fillAttributes(valueItemNode, {'direction': 'INOUT'})
else:
fillAttributes(valueItemNode, {'direction': 'OUT'})
fillAttributes(valueItemNode, {'direction': direction})
self.getOrCreateType(valueItemNode,register)
self.getOrCreateFieldRef(valueItemNode,register.getFesaFieldName())
......@@ -346,9 +415,10 @@ class FESADesignGenerator3_0_0(object):
elif reg.isAcquisition():
fieldNode = self.getOrCreateFieldNode(acquisitionNode,reg)
fillAttributes(fieldNode, {'multiplexed': 'false', 'persistent': 'false'})
else: #volatile#
fieldNode = self.getOrCreateFieldNode(settingNode,reg)
fillAttributes(fieldNode, {'multiplexed': 'false', 'persistent': 'false'})
elif reg.isConfiguration():
fieldNode = self.getOrCreateFieldNode(configurationNode,reg)
else:
raise Exception( "Cannot identify register-type to use for register:" + reg.name )
self.getOrCreateType(fieldNode,reg)
globalDataNode = getOrCreateChildElement(dataNode,'global-data')
......@@ -377,32 +447,11 @@ class FESADesignGenerator3_0_0(object):
for block in designClass.getDesignBlocks():
if not block.generateFesaProperty:
continue #skip this block
if block.isWritable():
if block.isSetting() or block.isCommand():
propertyNode = self.getOrCreateFESAProperty(settingNode, actionsNode, block)
else:
propertyNode = self.getOrCreateFESAProperty(acquisitionNode,actionsNode,block)
#-------------------------------------------------------------------------
# Generates the scheduling-units node of the FESA design
# document parsing the SILECS class document
#-------------------------------------------------------------------------
def addDesignFileId(self,fesaDesignFile,logTopics):
nodeRequiringId = ['setting-property','acquisition-property','diagnostic-property',
'value-item','update-flag-item','cycle-name-item', 'acq-stamp-item',
'cycle-stamp-item','mode-item','host-item','port-item','config-item',
'state-item','fwk-topic-item','custom-topic-item','device-trace-item',
'bypass-action-item','diag-custom-topic','field','timing-event-source',
'timer-event-source','logical-event']
counter = 0
now = datetime.datetime.today()
id = '_' + now.strftime('%y%m%d%H%M%S') + '_%s'
for nodeName in nodeRequiringId:
for node in fesaDesignFile.xpathEval("//" + nodeName):
if node.hasProp("id"):
node.setProp("id", id%counter)
counter = counter +1
def fillXML(self,fesaVersion, className, fesaRoot, silecsRoot,logTopics={'errorlog': True}):
......@@ -428,7 +477,6 @@ class FESADesignGenerator3_0_0(object):
# Generate properties, Actions, Events, Scheduling Units
self.genDeviceInterface(designClass, fesaRoot,logTopics)
self.addDesignFileId(fesaRoot,logTopics)
return fesaRoot
#-------------------------------------------------------------------------
......
......@@ -24,7 +24,7 @@ import datetime
import socket
import iecommon
import fesaTemplates
import fesa.fesa_3_0_0.fesaTemplates as fesaTemplates
import iefiles
from iecommon import *
......@@ -47,25 +47,19 @@ def findBlockServerSetActionName(fesaRoot, propName):
def genHSource(className, silecsRoot, fesaRoot, sourcePath,logTopics):
designClass = DesignClass.getDesignClassFromRootNode(silecsRoot)
source = fesaTemplates.genHTop(className)
for block in designClass.getDesignBlocks():
if block.isWritable():
serverActionName = findBlockServerSetActionName(fesaRoot,block.getFesaName())
source += fesaTemplates.genHTopBlock(className, serverActionName)
source += fesaTemplates.genHTop2(className)
for block in designClass.getDesignBlocks():
for block in designClass.getDesignFesaBlocks():
if block.isAcquisition():
source += fesaTemplates.genHBlock('RO', block.name,block.getFesaName() )
elif block.isCommand():
source += fesaTemplates.genHBlock('WO', block.name,block.getFesaName())
source += fesaTemplates.genHReadBlock(className, block.name)
elif block.isCommand() or block.isConfiguration():
source += fesaTemplates.genHWriteBlock(className, block.name, block.getFesaName())
else: # Setting
source += fesaTemplates.genHBlock('RW', block.name,block.getFesaName())
source += fesaTemplates.genHReadWriteBlock(className, block.name, block.getFesaName())
source += fesaTemplates.genHBottom(className)
for block in designClass.getDesignBlocks():
for block in designClass.getDesignFesaBlocks():
source += fesaTemplates.genHDeclBlocks(block.name)
source += fesaTemplates.genHClosing(className)
......@@ -93,7 +87,8 @@ def genHSource(className, silecsRoot, fesaRoot, sourcePath,logTopics):
def genCppSource(className, silecsRoot, fesaRoot, sourcePath,logTopics):
designClass = DesignClass.getDesignClassFromRootNode(silecsRoot)
finalSource = fesaTemplates.genCTop(className)
blockList = designClass.getDesignBlocks()
blockList = designClass.getDesignFesaBlocks()
for block in blockList:
finalSource += fesaTemplates.genCGlobal(className, block.name)
......@@ -103,24 +98,15 @@ def genCppSource(className, silecsRoot, fesaRoot, sourcePath,logTopics):
finalSource += fesaTemplates.genCBlockConstr(block.name, className)
finalSource += fesaTemplates.genCPart2(className)
for block in blockList:
if (block.isWritable()):
# WARNING: In order to have multiplexed FESA fields, the corresponding SILECS registers' synchro mode must be 'NONE'
finalSource += fesaTemplates.genCSetPLC(className, block.name)
finalSource += fesaTemplates.genCPart3(className)
for block in blockList:
if (block.isReadable()):
# WARNING: In order to have multiplexed FESA fields, the corresponding SILECS registers' synchro mode must be 'NONE'
finalSource += fesaTemplates.genCGetPLC(className, block.name)
finalSource += fesaTemplates.updatePLCRegisters(className, blockList)
finalSource += fesaTemplates.updateFesaFields(className, blockList)
finalSource += fesaTemplates.genCPart4(className)
for block in blockList:
if block.isReadable():
finalSource += fesaTemplates.genCCommonGet(block.name,className)
if block.isSetting() or block.isAcquisition(): #configuration-fields in fesa are not writable, so no setter to generate for them !
finalSource += fesaTemplates.genCCommonGet(block.name, className)
finalSource += '\n'
finalSource += fesaTemplates.cRecv
for register in block.getDesignRegisters():
......@@ -136,10 +122,43 @@ def genCppSource(className, silecsRoot, fesaRoot, sourcePath,logTopics):
finalSource += fesaTemplates.genCGetArrayReg(register)
elif register.valueType == 'array2D':
finalSource += fesaTemplates.genCGetArray2DReg(register)
elif register.valueType == 'custom-type-scalar':
finalSource += fesaTemplates.genCGetCustomScalarReg(register)
elif register.valueType == 'custom-type-array':
finalSource += fesaTemplates.genCGetCustomArrayReg(register)
elif register.valueType == 'custom-type-array2D':
finalSource += fesaTemplates.genCGetCustomArray2DReg(register)
finalSource += '\n }\n'
if block.isSetting():
finalSource += fesaTemplates.genCDatatypeGet(block.name, block.getFesaName(), className)
finalSource += '\n'
finalSource += fesaTemplates.cRecv
for register in block.getDesignRegisters():
if register.valueType == 'string':
finalSource += fesaTemplates.genCGetStringRegData(register)
elif register.valueType == 'stringArray':
finalSource += fesaTemplates.genCGetStringArrayRegData(register)
elif register.valueType == 'stringArray2D':
iecommon.logError('ERROR: In register '+register.name+' - 2D array of strings not supported in FESA.', True, {'errorlog': True})
elif register.valueType == 'scalar':
finalSource += fesaTemplates.genCGetScalarRegData(register)
elif register.valueType == 'array':
finalSource += fesaTemplates.genCGetArrayRegData(register)
elif register.valueType == 'array2D':
finalSource += fesaTemplates.genCGetArray2DRegData(register)
elif register.valueType == 'custom-type-scalar':
finalSource += fesaTemplates.genCGetCustomScalarRegData(register)
elif register.valueType == 'custom-type-array':
finalSource += fesaTemplates.genCGetCustomArrayRegData(register)
elif register.valueType == 'custom-type-array2D':
finalSource += fesaTemplates.genCGetCustomArray2DRegData(register)
finalSource += '\n }\n'
if block.isWritable():
finalSource += fesaTemplates.genCCommonSet(block.name,className)
finalSource += fesaTemplates.genCCommonSet(block.name, className)
for register in block.getDesignRegisters():
if register.valueType == 'string':
finalSource += fesaTemplates.genCSetStringReg(register)
......@@ -153,6 +172,12 @@ def genCppSource(className, silecsRoot, fesaRoot, sourcePath,logTopics):
finalSource += fesaTemplates.genCSetArrayReg(register)
elif register.valueType == 'array2D':
finalSource += fesaTemplates.genCSetArray2DReg(register)
elif register.valueType == 'custom-type-scalar':
finalSource += fesaTemplates.genCSetScalarReg(register)
elif register.valueType == 'custom-type-array':
finalSource += fesaTemplates.genCSetCustomArrayReg(register)
elif register.valueType == 'custom-type-array2D':
finalSource += fesaTemplates.genCSetCustomArray2DReg(register)
finalSource += fesaTemplates.cSend
finalSource += ' }\n'
finalSource += fesaTemplates.genCDatatypeSet(block.name,block.getFesaName(), className)
......@@ -170,6 +195,12 @@ def genCppSource(className, silecsRoot, fesaRoot, sourcePath,logTopics):
finalSource += fesaTemplates.genCSetArrayRegData(register)
elif register.valueType == 'scalar':
finalSource += fesaTemplates.genCSetScalarRegData(register)
elif register.valueType == 'custom-type-scalar':
finalSource += fesaTemplates.genCSetScalarRegData(register)
elif register.valueType == 'custom-type-array':
finalSource += fesaTemplates.genCSetCustomArrayRegData(register)
elif register.valueType == 'custom-type-array2D':
finalSource += fesaTemplates.genCSetCustomArray2DRegData(register)
finalSource += fesaTemplates.cSend
finalSource += '\n }\n' # closing bracket for block
......
......@@ -16,11 +16,11 @@
import fesa.fesa_3_0_0.generateBuildEnvironment
def genMakefileClass(projectPath, centralMakefilePath, logTopics={'errorlog': True} ):
return fesa.fesa_3_0_0.generateBuildEnvironment.genMakefileClass(projectPath, centralMakefilePath, logTopics )
def genMakefileClass(projectPath, logTopics={'errorlog': True} ):
return fesa.fesa_3_0_0.generateBuildEnvironment.genMakefileClass(projectPath, logTopics )
def genMakefileDU(projectPath, silecsBasePath, snap7BasePath, logTopics={'errorlog': True}):
return fesa.fesa_3_0_0.generateBuildEnvironment.genMakefileDU(projectPath, silecsBasePath, snap7BasePath, logTopics )
def genMakefileDU(projectPath, logTopics={'errorlog': True}):
return fesa.fesa_3_0_0.generateBuildEnvironment.genMakefileDU(projectPath, logTopics )
def genCProjectFile(projectPath, logTopics={'errorlog': True}):
return fesa.fesa_3_0_0.generateBuildEnvironment.genCProjectFile(projectPath, logTopics )
#!/usr/bin/python
# Copyright 2016 CERN and GSI
#
# This program is free software: you can redistribute it and/or modify
......@@ -13,19 +14,10 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
PROJECT = silecs
PRODUCT = cli-client
VERSION = 0.0.0
import fesa.fillFesaDeployUnitBase
import fesa.fesa_3_0_0.fillFESADeployUnit
SKIP_MANIFEST = TRUE
#local
#COMMON_MAKE_PATH ?= /common/home/bel/schwinn/lnx/workspace-silecs-neon/generic-makefiles
#global
COMMON_MAKE_PATH ?= /opt/cern/buildsystem/generic/2.9.0
def fillDeployUnit(fesaVersion, className, workspacePath,fesaDesignXSDPath,logTopics={'errorlog': True}):
generator = fesa.fesa_3_0_0.fillFESADeployUnit.FESADeployUnitGenerator3_0_0() # identical with FESA 3.0.0
fesa.fillFesaDeployUnitBase.fillFesaDeployUnitBase(generator,fesaVersion, className, workspacePath,fesaDesignXSDPath,logTopics)
# product configuration
BIN_NAME = $(PROJECT)-$(PRODUCT)
DBG = false
# Include the generic make file
include $(COMMON_MAKE_PATH)/Make.generic
\ No newline at end of file
#!/usr/bin/python
# Copyright 2016 CERN and GSI
#
# This program is free software: you can redistribute it and/or modify
......@@ -13,28 +14,13 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
PROJECT = silecs
PRODUCT = communication
VERSION = 0.0.0
import fesa.fesa_3_1_0.generateBuildEnvironment
SKIP_MANIFEST = TRUE
#local
#COMMON_MAKE_PATH ?= /common/home/bel/schwinn/lnx/workspace-silecs-neon/generic-makefiles
#global
COMMON_MAKE_PATH ?= /opt/cern/buildsystem/generic/2.9.0
def genMakefileClass(projectPath, logTopics={'errorlog': True} ):
return fesa.fesa_3_1_0.generateBuildEnvironment.genMakefileClass(projectPath, logTopics )
# product configuration
LIB_NAME = comm
DBG = true
def genMakefileDU(projectPath, logTopics={'errorlog': True}):
return fesa.fesa_3_1_0.generateBuildEnvironment.genMakefileDU(projectPath, logTopics )
#COMPILER_FLAGS = -Os -fno-strict-aliasing -fexceptions -DLINUX -DARM_FIX -DDAVE_LITTLE_ENDIAN -D_GNU_SOURCE -DMAJOR=$(MAJOR) -DMINOR=$(MINOR) -DPATCH=$(PATCH)
COMPILER_FLAGS = -DMAJOR=$(MAJOR) -DMINOR=$(MINOR) -DPATCH=$(PATCH)
# Comment IN/Out to enable NI-Support
#COMPILER_FLAGS += -DNI_SUPPORT_ENABLED=TRUE
# Comment IN/Out to enable Modbus-Support
#COMPILER_FLAGS += -DMODBUS_SUPPORT_ENABLED=TRUE
# Include the generic make file
include $(COMMON_MAKE_PATH)/Make.generic
\ No newline at end of file
def genCProjectFile(projectPath, logTopics={'errorlog': True}):
return fesa.fesa_3_1_0.generateBuildEnvironment.genCProjectFile(projectPath, logTopics )
#!/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/>.
import fesa.fillFesaDesignBase
import fesa.fesa_3_1_0.generateFesaDesign
from iecommon import *
def fillDesignFile(fesaVersion, className, workspacePath,fesaDesignXSDPath,logTopics={'errorlog': True}):
generator = FESADesignGenerator7_3_0()
fesa.fillFesaDesignBase.fillDesignFileBase(generator,fesaVersion, className, workspacePath,fesaDesignXSDPath,logTopics)
class FESADesignGenerator7_3_0(fesa.fesa_3_1_0.generateFesaDesign.FESADesignGenerator3_1_0):
#overwrite 3_0_0 version (multiplexed --> cycle-bound)
def getOrCreateAcquisitionProperty(self,parent,actionsNode,block):
iecommon.logDebug('Generating AcquisitionProperty for Block: ' + block.name, {'debuglog': True})
prop = ""
if( hasChildren(parent)):
prop = getOrCreateNamedPreviousSiblingElement(parent,getFirstChild(parent), 'acquisition-property',block.getFesaName())
else:
prop = getOrCreateNamedChildElement(parent,'acquisition-property',block.getFesaName())
fillAttributes(prop, {'visibility': 'development', 'subscribable': 'true', 'cycle-bound': 'false', 'on-change': 'true'})
self.getOrCreateRegisterValueItems(prop,block,"OUT")
self.getOrCreateAcqStampItem(prop)
self.getOrCreateUpdateFlagItem(prop)
self.getOrCreateCyleNameItem(prop)
self.getOrCreateCyleStampItem(prop)
self.getOrCreateAction(prop,block.fesaGetServerActionName,'get',actionsNode,'custom')
return prop
#overwrite 3_0_0 version (multiplexed --> cycle-bound)
def getOrCreateGSIAcquisitionProperty(self,parent,actionsNode,block):
iecommon.logDebug('Generating GSIAcquisitionProperty for Block: ' + block.name, {'debuglog': True})
versionProps = parent.xpathEval('GSI-Version-Property')
if len(versionProps) == 0:
raise Exception("Error: A GSI-Version-Property needs to be available to generate a GSIAcquisitionProperty")
prop = getOrCreateNamedPreviousSiblingElement(parent,versionProps[0], 'GSI-Acquisition-Property',block.getFesaName())
fillAttributes(prop, {'visibility': 'development', 'subscribable': 'true', 'cycle-bound': 'false', 'on-change': 'true'})
self.getOrCreateRegisterValueItems(prop,block,"OUT")
self.getOrCreateAcqStampItem(prop)
self.getOrCreateUpdateFlagItem(prop)
self.getOrCreateCyleNameItem(prop)
self.getOrCreateCyleStampItem(prop)
self.getOrCreateAction(prop,block.fesaGetServerActionName,'get',actionsNode,'custom')
self.getOrCreateAcquisitionContextItem(prop)
return prop
#overwrite 3_0_0 version (multiplexed --> cycle-bound for acquisition fileds)
def genData(self,designClass, doc,logTopics):
iecommon.logDebug("Creating data fields", logTopics)
dataNode = doc.xpathEval('/equipment-model/data')[0]
iecommon.logError("len(dataNode)" + dataNode.get_name(), logTopics)
deviceDataNode = getOrCreateChildElement(dataNode,'device-data')
configurationNode = getOrCreateChildElement(deviceDataNode,'configuration')
settingNode = getOrCreateChildElement(deviceDataNode,'setting')
acquisitionNode = getOrCreateChildElement(deviceDataNode,'acquisition')
self.getOrCreatePLCHostNameField(configurationNode)
self.getOrCreatePLCDeviceLabelField(configurationNode)
for block in designClass.getDesignBlocks():
for reg in block.getDesignRegisters():
if reg.isSetting():
fieldNode = self.getOrCreateFieldNode(settingNode,reg)
fillAttributes(fieldNode, {'multiplexed': 'false', 'persistent': 'true'})
elif reg.isAcquisition():
fieldNode = self.getOrCreateFieldNode(acquisitionNode,reg)
fillAttributes(fieldNode, {'cycle-bound': 'false', 'persistent': 'false'})
elif reg.isConfiguration():
fieldNode = self.getOrCreateFieldNode(configurationNode,reg)
else:
raise Exception( "Cannot identify register-type to use for register:" + reg.name )
self.getOrCreateType(fieldNode,reg)
globalDataNode = getOrCreateChildElement(dataNode,'global-data')
globalConfigurationNode = ""
if len(globalDataNode.xpathEval("configuration")) == 0:
if len( globalDataNode.xpathEval("*")) == 0:
globalConfigurationNode = getOrCreateChildElement(globalDataNode,'configuration')
else:
globalConfigurationNode = getOrCreatePreviousSiblingElement(getFirstChild(globalDataNode),'configuration')
else:
globalConfigurationNode = globalDataNode.xpathEval("configuration")[0]
self.getOrCreatePLCClassVersionField(globalConfigurationNode,designClass.version)
# Fill custom-types with enums.
enums = designClass.getEnums()
customTypesNode = doc.xpathEval('/equipment-model/custom-types')[0]
for enum in enums:
enumElement = getOrCreateNamedChildElement(customTypesNode, "enum", enum.name)
existing_items = enumElement.xpathEval("item")
to_add = []
to_edit = []
# Loop through all new enums and check which should be added and which edited.
for item in enum.items:
if item.symbol in [item.prop("symbol") for item in existing_items]:
to_edit.append(item)
else:
to_add.append(item)
# Loop though all existing enums and remove any which are not in new enums.
to_add_edit = to_add + to_edit
for existing in existing_items:
if existing.prop("symbol") not in [item.symbol for item in to_add_edit]:
existing.unlinkNode()
existing.freeNode()
# Edit existing items.
for item in to_edit:
for existing in existing_items:
if existing.prop("symbol") != item.symbol:
continue
existing.setProp("access", item.access)
existing.setProp("value", item.value)
# Add missing items.
for item in to_add:
itemElement = libxml2.newNode("item")
enumElement.addChild(itemElement)
itemElement.setProp("access", item.access)
itemElement.setProp("value", item.value)
itemElement.setProp("symbol", item.symbol)